94067636b5faf11e798aa6b70869a8c96eae9ce2
1 import collections
as _collections
2 import inspect
as _inspect
5 from . import core
as _core
8 class DispatcherMeta(type):
9 def __new__(metacls
, name
, bases
, ns
):
11 ishook
= lambda member
: isinstance(member
, _core
.CallHook
)
13 for basecls
in reversed(bases
):
14 members
= _inspect
.getmembers(basecls
, predicate
=ishook
)
15 for (_
, hook
) in members
:
16 hooks
.update(dict.fromkeys(hook
, hook
))
18 conflicts
= _collections
.defaultdict(list)
19 for (key
, value
) in tuple(ns
.items()):
25 conflicts
[typeid
].append(key
)
28 for (typeid
, keys
) in conflicts
.items():
30 raise ValueError(f
"dispatch conflict: {keys!r}")
32 ns
["__hooks__"] = _types
.MappingProxyType(hooks
)
34 return super().__new
__(metacls
, name
, bases
, ns
)
36 def dispatch(cls
, typeid
=object):
37 return cls
.__hooks
__.get(typeid
)
40 class Dispatcher(metaclass
=DispatcherMeta
):
41 def __call__(self
, instance
):
42 for typeid
in instance
.__class
__.__mro
__:
43 hook
= self
.__class
__.dispatch(typeid
=typeid
)
47 hook
= self
.__class
__.dispatch()
48 return hook(dispatcher
=self
, instance
=instance
)
51 def dispatch_object(self
, instance
):
52 raise NotImplementedError()