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