summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre-Yves David <pierre-yves.david@logilab.fr>2008-06-24 11:59:16 +0200
committerPierre-Yves David <pierre-yves.david@logilab.fr>2008-06-24 11:59:16 +0200
commit6af087a3c32ac501f742d6dd1a74848175188d79 (patch)
tree370773b886753eaff75b1d28b820a6c432e955be
parent156df98848bcc383fd126d7649d45410f975ecca (diff)
downloadlogilab-common-6af087a3c32ac501f742d6dd1a74848175188d79.tar.gz
compat: adds a max function taking 'key' as keyword argument
-rw-r--r--ChangeLog1
-rw-r--r--compat.py40
-rw-r--r--test/unittest_compat.py38
3 files changed, 78 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 9343b55..272840a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,6 +10,7 @@ ChangeLog for logilab.common
- added assertUnorderedIterableEquals
* umessage.date() return unparsage string as is instead of None
+ * compat: adds a max function taking 'key' as keyword argument
2008-09-08 -- 0.32.0
* textutils: add the apply_unit fonction
* testlib:
diff --git a/compat.py b/compat.py
index 7e98330..fc2b231 100644
--- a/compat.py
+++ b/compat.py
@@ -22,6 +22,8 @@ from __future__ import generators
from warnings import warn
+import __builtin__
+
from logilab.common.deprecation import class_renamed
try:
@@ -188,6 +190,44 @@ except NameError:
l2.reverse()
return l2
+try: #
+ max = max
+ max(("ab","cde"),key=len)
+except TypeError:
+ def max( *args, **kargs):
+ if len(args) == 0:
+ raise TypeError("max expected at least 1 arguments, got 0")
+ key= kargs.pop("key", None)
+ #default implementation
+ if key is None:
+ return __builtin__.max(*args,**kargs)
+
+ for karg in kargs:
+ raise TypeError("unexpected keyword argument %s for function max") % karg
+
+ if len(args) == 1:
+ items = iter(args[0])
+ else:
+ items = iter(args)
+
+ try:
+ best_item = items.next()
+ best_value = key(best_item)
+ except StopIteration:
+ raise ValueError("max() arg is an empty sequence")
+
+ for item in items:
+ value = key(item)
+ if value > best_value:
+ best_item = item
+ best_value = value
+
+ return best_item
+
+
+
+
+
# Python2.5 builtins
try:
any = any
diff --git a/test/unittest_compat.py b/test/unittest_compat.py
index b9c7cd0..eaa769b 100644
--- a/test/unittest_compat.py
+++ b/test/unittest_compat.py
@@ -9,11 +9,13 @@ import pprint
class CompatTCMixIn:
MODNAMES = {}
BUILTINS = []
+ ALTERED_BUILTINS = {}
def setUp(self):
self.builtins_backup = {}
self.modules_backup = {}
self.remove_builtins()
+ self.alter_builtins()
self.remove_modules()
def tearDown(self):
@@ -36,6 +38,13 @@ class CompatTCMixIn:
self.builtins_backup[builtin] = func
delattr(__builtin__, builtin)
# setattr(__builtin__, 'builtin_%s' % builtin, func)
+ def alter_builtins(self):
+ for builtin, func in self.ALTERED_BUILTINS.iteritems():
+ old_func = getattr(__builtin__, builtin, None)
+ if func is not None:
+ self.builtins_backup[builtin] = old_func
+ setattr(__builtin__, builtin, func)
+ # setattr(__builtin__, 'builtin_%s' % builtin, func)
def remove_modules(self):
for modname in self.MODNAMES:
@@ -147,9 +156,18 @@ class Py24CompatTC(CompatTCMixIn, TestCase):
+class _MaxFaker(object):
+ def __init__(self, func):
+ self.func = func
+ def fake(self,*args,**kargs):
+ if kargs:
+ raise TypeError("max() takes no keyword argument")
+ return self.func(*args)
+
class Py25CompatTC(CompatTCMixIn, TestCase):
BUILTINS = ('any', 'all',)
+ ALTERED_BUILTINS = {'max': _MaxFaker(max).fake}
def test_any(self):
from logilab.common.compat import any
@@ -180,7 +198,25 @@ class Py25CompatTC(CompatTCMixIn, TestCase):
self.assertEquals(all(irange), False)
self.assertEquals(irange.next(), 1)
-
+ def test_max(self):
+ from logilab.common.compat import max
+
+ # old apy
+ self.assertEquals(max("fdjkmhsgmdfhsg"),'s')
+ self.assertEquals(max(1,43,12,45,1337,34,2), 1337)
+ self.assertRaises(TypeError,max)
+ self.assertRaises(TypeError,max,1)
+ self.assertRaises(ValueError,max,[])
+ self.assertRaises(TypeError,max,bob=None)
+
+ # new apy
+ self.assertEquals(max("shorter","longer",key=len),"shorter")
+ self.assertEquals(max(((1,1),(2,3,5),(8,13,21)),key=len),(2,3,5))
+ self.assertEquals(max(((1,1),(42,),(2,3,5),(8,13,21)),key=max),(42,))
+ self.assertRaises(TypeError,max,key=None)
+ self.assertRaises(TypeError,max,1,key=len)
+ self.assertRaises(ValueError,max,[],key=max)
+ self.assertRaises(TypeError,max,"shorter","longer",key=len,kathy=None)
if __name__ == '__main__':
unittest_main()