Show More
@@ -1,139 +1,99 | |||
|
1 | """This is version 0.7 of Philip J. Eby's simplegeneric module | |
|
2 | (http://pypi.python.org/pypi/simplegeneric) | |
|
3 | """ | |
|
4 | ||
|
1 | 5 | #Name: simplegeneric |
|
2 |
#Version: 0. |
|
|
6 | #Version: 0.7 | |
|
3 | 7 | #Summary: Simple generic functions (similar to Python's own len(), pickle.dump(), etc.) |
|
4 |
#Home-page: http:// |
|
|
8 | #Home-page: http://pypi.python.org/pypi/simplegeneric | |
|
5 | 9 | #Author: Phillip J. Eby |
|
6 | 10 | #Author-email: peak@eby-sarna.com |
|
7 | 11 | #License: PSF or ZPL |
|
8 | 12 | |
|
9 | # This is version 0.6 of Philip J. Eby's simplegeneric module | |
|
10 | # (http://cheeseshop.python.org/pypi/simplegeneric) patched to work | |
|
11 | # with Python 2.3 (which doesn't support assigning to __name__) | |
|
12 | ||
|
13 | 13 | __all__ = ["generic"] |
|
14 | 14 | |
|
15 | ||
|
16 | 15 | from types import ClassType, InstanceType |
|
17 | 16 | classtypes = type, ClassType |
|
18 | 17 | |
|
19 | 18 | def generic(func): |
|
20 | 19 | """Create a simple generic function""" |
|
21 | 20 | |
|
22 | 21 | _sentinel = object() |
|
23 | 22 | |
|
24 | 23 | def _by_class(*args, **kw): |
|
25 | 24 | cls = args[0].__class__ |
|
26 | 25 | for t in type(cls.__name__, (cls,object), {}).__mro__: |
|
27 | 26 | f = _gbt(t, _sentinel) |
|
28 | 27 | if f is not _sentinel: |
|
29 | 28 | return f(*args, **kw) |
|
30 | 29 | else: |
|
31 | 30 | return func(*args, **kw) |
|
32 | 31 | |
|
33 | 32 | _by_type = {object: func, InstanceType: _by_class} |
|
34 | 33 | _gbt = _by_type.get |
|
35 | 34 | |
|
36 | def when_type(t): | |
|
37 |
"""Decorator to add a method that will be called for t |
|
|
38 |
|
|
|
39 | raise TypeError( | |
|
40 | "%r is not a type or class" % (t,) | |
|
41 | ) | |
|
42 | def decorate(f): | |
|
43 | if _by_type.setdefault(t,f) is not f: | |
|
35 | def when_type(*types): | |
|
36 | """Decorator to add a method that will be called for the given types""" | |
|
37 | for t in types: | |
|
38 | if not isinstance(t, classtypes): | |
|
44 | 39 | raise TypeError( |
|
45 |
"%r |
|
|
40 | "%r is not a type or class" % (t,) | |
|
46 | 41 | ) |
|
42 | def decorate(f): | |
|
43 | for t in types: | |
|
44 | if _by_type.setdefault(t,f) is not f: | |
|
45 | raise TypeError( | |
|
46 | "%r already has method for type %r" % (func, t) | |
|
47 | ) | |
|
47 | 48 | return f |
|
48 | 49 | return decorate |
|
49 | 50 | |
|
50 | 51 | |
|
51 | 52 | |
|
52 | 53 | |
|
53 | ||
|
54 | ||
|
55 | 54 | _by_object = {} |
|
56 | 55 | _gbo = _by_object.get |
|
57 | 56 | |
|
58 | def when_object(o): | |
|
59 |
"""Decorator to add a method t |
|
|
57 | def when_object(*obs): | |
|
58 | """Decorator to add a method to be called for the given object(s)""" | |
|
60 | 59 | def decorate(f): |
|
61 | if _by_object.setdefault(id(o), (o,f))[1] is not f: | |
|
62 | raise TypeError( | |
|
63 | "%r already has method for object %r" % (func, o) | |
|
64 | ) | |
|
60 | for o in obs: | |
|
61 | if _by_object.setdefault(id(o), (o,f))[1] is not f: | |
|
62 | raise TypeError( | |
|
63 | "%r already has method for object %r" % (func, o) | |
|
64 | ) | |
|
65 | 65 | return f |
|
66 | 66 | return decorate |
|
67 | 67 | |
|
68 | 68 | |
|
69 | 69 | def dispatch(*args, **kw): |
|
70 | 70 | f = _gbo(id(args[0]), _sentinel) |
|
71 | 71 | if f is _sentinel: |
|
72 | 72 | for t in type(args[0]).__mro__: |
|
73 | 73 | f = _gbt(t, _sentinel) |
|
74 | 74 | if f is not _sentinel: |
|
75 | 75 | return f(*args, **kw) |
|
76 | 76 | else: |
|
77 | 77 | return func(*args, **kw) |
|
78 | 78 | else: |
|
79 | 79 | return f[1](*args, **kw) |
|
80 | 80 | |
|
81 | try: | |
|
82 | dispatch.__name__ = func.__name__ | |
|
83 | except TypeError: | |
|
84 | pass | |
|
81 | dispatch.__name__ = func.__name__ | |
|
85 | 82 | dispatch.__dict__ = func.__dict__.copy() |
|
86 | 83 | dispatch.__doc__ = func.__doc__ |
|
87 | 84 | dispatch.__module__ = func.__module__ |
|
88 | 85 | |
|
89 | 86 | dispatch.when_type = when_type |
|
90 | 87 | dispatch.when_object = when_object |
|
91 | 88 | dispatch.default = func |
|
92 | 89 | dispatch.has_object = lambda o: id(o) in _by_object |
|
93 | 90 | dispatch.has_type = lambda t: t in _by_type |
|
94 | 91 | return dispatch |
|
95 | 92 | |
|
96 | 93 | |
|
97 | ||
|
98 | ||
|
99 | 94 | def test_suite(): |
|
100 | 95 | import doctest |
|
101 | 96 | return doctest.DocFileSuite( |
|
102 | 97 | 'README.txt', |
|
103 | 98 | optionflags=doctest.ELLIPSIS|doctest.REPORT_ONLY_FIRST_FAILURE, |
|
104 | 99 | ) |
|
105 | ||
|
106 | ||
|
107 | ||
|
108 | ||
|
109 | ||
|
110 | ||
|
111 | ||
|
112 | ||
|
113 | ||
|
114 | ||
|
115 | ||
|
116 | ||
|
117 | ||
|
118 | ||
|
119 | ||
|
120 | ||
|
121 | ||
|
122 | ||
|
123 | ||
|
124 | ||
|
125 | ||
|
126 | ||
|
127 | ||
|
128 | ||
|
129 | ||
|
130 | ||
|
131 | ||
|
132 | ||
|
133 | ||
|
134 | ||
|
135 | ||
|
136 | ||
|
137 | ||
|
138 | ||
|
139 |
General Comments 0
You need to be logged in to leave comments.
Login now