3825b9efc5be94c3097daf8142465f48053f9e78
13 def __init__(self
, *typeids
):
14 for typeid
in typeids
:
15 if not callable(typeid
):
16 raise ValueError(typeid
)
17 self
.__typeids
= typeids
18 return super().__init
__()
21 yield from self
.__typeids
25 for typeid
in self
.__typeids
:
26 name
= typeid
.__qualname
__
27 module
= typeid
.__module
__
28 if module
not in ("builtins",):
29 name
= f
"{module}.{name}"
31 return f
"<{', '.join(names)}>"
33 def __call__(self
, call
):
34 class ConcreteHook(Hook
):
35 def __call__(self
, dispatcher
, instance
):
36 return call(self
=dispatcher
, instance
=instance
)
38 return ConcreteHook(*tuple(self
))
41 class DispatcherMeta(type):
44 def __new__(metacls
, name
, bases
, ns
):
46 ishook
= lambda member
: isinstance(member
, Hook
)
48 for basecls
in reversed(bases
):
49 members
= inspect
.getmembers(basecls
, predicate
=ishook
)
50 for (_
, hook
) in members
:
51 hooks
.update(dict.fromkeys(hook
, hook
))
53 conflicts
= collections
.defaultdict(list)
54 for (key
, value
) in tuple(ns
.items()):
60 conflicts
[typeid
].append(key
)
63 for (typeid
, keys
) in conflicts
.items():
65 raise ValueError(f
"dispatch conflict: {keys!r}")
67 ns
["__hooks__"] = types
.MappingProxyType(hooks
)
69 return super().__new
__(metacls
, name
, bases
, ns
)
71 def dispatch(cls
, typeid
=object):
72 hook
= cls
.__hooks
__.get(typeid
)
75 for (checker
, hook
) in cls
.__hooks
__.items():
76 if not isinstance(checker
, type) and checker(typeid
):
81 class Dispatcher(metaclass
=DispatcherMeta
):
82 def __call__(self
, instance
):
83 for typeid
in instance
.__class
__.__mro
__:
84 hook
= self
.__class
__.dispatch(typeid
=typeid
)
88 hook
= self
.__class
__.dispatch()
89 return hook(dispatcher
=self
, instance
=instance
)
92 def dispatch_object(self
, instance
):
93 raise NotImplementedError()