forked from cool-RR/python_toolbox
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcomparison_tools.py
More file actions
76 lines (64 loc) · 3.06 KB
/
comparison_tools.py
File metadata and controls
76 lines (64 loc) · 3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# Copyright 2009-2014 Ram Rachum.
# This program is distributed under the MIT license.
'''Defines various tools for comparisons.'''
import sys
def underscore_hating_key(string):
'''Key function for sorting that treats `_` as last character.'''
assert isinstance(string, basestring)
return unicode(string).replace('_', unichr(sys.maxunicode))
def total_ordering(cls):
'''
Add full arsenal of ordering methods to a class based on existing subset.
'''
convert = {
'__lt__': [('__gt__', lambda self, other:
not (self < other or self == other)),
('__le__', lambda self, other:
self < other or self == other),
('__ge__', lambda self, other:
not self < other)],
'__le__': [('__ge__', lambda self, other:
not self <= other or self == other),
('__lt__', lambda self, other:
self <= other and not self == other),
('__gt__', lambda self, other:
not self <= other)],
'__gt__': [('__lt__', lambda self, other:
not (self > other or self == other)),
('__ge__', lambda self, other:
self > other or self == other),
('__le__', lambda self, other:
not self > other)],
'__ge__': [('__le__', lambda self, other:
(not self >= other) or self == other),
('__gt__', lambda self, other:
self >= other and not self == other),
('__lt__', lambda self, other:
not self >= other)]
}
roots = set(dir(cls)) & set(convert)
if not roots:
raise ValueError('Must define at least one ordering operation: `<`, '
'`>`, `<=`, or `>=`.')
root = max(roots) # We prefer __lt__ to __le__ to __gt__ to __ge__
for opname, opfunc in convert[root]:
if opname not in roots:
opfunc.__name__ = opname
opfunc.__doc__ = getattr(float, opname).__doc__
setattr(cls, opname, opfunc)
return cls
def process_key_function_or_attribute_name(key_function_or_attribute_name):
'''
Make a key function given either a key function or an attribute name.
Some functions let you sort stuff by entering a key function or an
attribute name by which the elements will be sorted. This function tells
whether we were given a key function or an attribute name, and generates a
key function out of it if needed.
'''
if key_function_or_attribute_name is None:
return None
elif callable(key_function_or_attribute_name):
return key_function_or_attribute_name
else:
assert isinstance(key_function_or_attribute_name, basestring)
return lambda key: getattr(key, key_function_or_attribute_name)