1 import inspect
as _inspect
2 import operator
as _operator
4 from . import core
as _core
7 class DispatcherMeta(type):
8 def __new__(metacls
, name
, bases
, ns
):
11 for (key
, value
) in tuple(ns
.items()):
12 if not isinstance(value
, _core
.CallHook
):
15 for typeid
in hook
.typeids
:
17 raise ValueError(f
"conflicting hook: {typeid!r}")
19 site
= hook
.call
.__name
__
22 return super().__new
__(metacls
, name
, bases
, ns
)
24 def __init__(cls
, name
, bases
, ns
):
26 for hook
in map(_operator
.itemgetter(1), _inspect
.getmembers(cls
,
27 predicate
=lambda member
: isinstance(member
, _core
.CallHook
))):
28 for typeid
in hook
.typeids
:
31 return super().__init
__(name
, bases
, ns
)
33 def dispatch(cls
, typeid
=object):
34 return cls
.__hooks
.get(typeid
)
37 class Dispatcher(metaclass
=DispatcherMeta
):
38 def __call__(self
, instance
):
39 for typeid
in instance
.__class
__.__mro
__:
40 hook
= self
.__class
__.dispatch(typeid
=typeid
)
44 hook
= self
.__class
__.dispatch()
45 return hook(dispatcher
=self
, instance
=instance
)
48 def dispatch_object(self
, instance
):
49 raise NotImplementedError()