The default `mdis.Walker` already incorporates the logic to walk over some builtin Python objects.
The example below shows how to override the way the dicts are traversed so that keys and values are swapped.
- import mdis.core
+ import mdis.dispatcher
import mdis.walker
class CustomWalker(mdis.walker.Walker):
- @mdis.core.hook(dict)
+ @mdis.dispatcher.hook(dict)
def dispatch_dict(self, instance):
for (key, value) in instance.items():
yield (value, key)
import contextlib
- import mdis.core
+ import mdis.dispatcher
import mdis.visitor
class CustomVisitor(mdis.visitor.Visitor):
- @mdis.core.hook(int)
+ @mdis.dispatcher.hook(int)
@contextlib.contextmanager
def dispatch_int(self, instance):
print("entering int")
yield (instance + 42)
print("leaving int")
- @mdis.core.hook(str)
+ @mdis.dispatcher.hook(str)
@contextlib.contextmanager
def dispatch_str(self, instance):
print("entering str")
yield f"!!!{instance}!!!"
print("leaving str")
- @mdis.core.hook(object)
+ @mdis.dispatcher.hook(object)
@contextlib.contextmanager
def dispatch_object(self, instance):
print("entering object")
+++ /dev/null
-class Hook(object):
- def __init__(self, *typeids):
- for typeid in typeids:
- if not isinstance(typeid, type):
- raise ValueError(typeid)
- self.__typeids = typeids
- return super().__init__()
-
- def __iter__(self):
- yield from self.__typeids
-
- def __repr__(self):
- names = []
- for typeid in self.__typeids:
- name = typeid.__qualname__
- module = typeid.__module__
- if module not in ("builtins",):
- name = f"{module}.{name}"
- names.append(name)
- return f"<{', '.join(names)}>"
-
- def __call__(self, call):
- class ConcreteHook(Hook):
- def __call__(self, dispatcher, instance):
- return call(self=dispatcher, instance=instance)
-
- return ConcreteHook(*tuple(self))
-
-
-def hook(*typeids):
- return Hook(*typeids)
import inspect as _inspect
import types as _types
-from . import core as _core
+
+class Hook(object):
+ def __init__(self, *typeids):
+ for typeid in typeids:
+ if not isinstance(typeid, type):
+ raise ValueError(typeid)
+ self.__typeids = typeids
+ return super().__init__()
+
+ def __iter__(self):
+ yield from self.__typeids
+
+ def __repr__(self):
+ names = []
+ for typeid in self.__typeids:
+ name = typeid.__qualname__
+ module = typeid.__module__
+ if module not in ("builtins",):
+ name = f"{module}.{name}"
+ names.append(name)
+ return f"<{', '.join(names)}>"
+
+ def __call__(self, call):
+ class ConcreteHook(Hook):
+ def __call__(self, dispatcher, instance):
+ return call(self=dispatcher, instance=instance)
+
+ return ConcreteHook(*tuple(self))
class DispatcherMeta(type):
def __new__(metacls, name, bases, ns):
hooks = {}
- ishook = lambda member: isinstance(member, _core.Hook)
+ ishook = lambda member: isinstance(member, Hook)
for basecls in reversed(bases):
members = _inspect.getmembers(basecls, predicate=ishook)
hook = self.__class__.dispatch()
return hook(dispatcher=self, instance=instance)
- @_core.hook(object)
+ @Hook(object)
def dispatch_object(self, instance):
raise NotImplementedError()
import contextlib as _contextlib
-from . import core as _core
from . import dispatcher as _dispatcher
class Visitor(_dispatcher.Dispatcher, metaclass=VisitorMeta):
+ @_dispatcher.Hook(object)
@_contextlib.contextmanager
- @_core.hook(object)
def dispatch_object(self, instance):
yield instance
-from . import core as _core
from . import dispatcher as _dispatcher
class Walker(_dispatcher.Dispatcher, metaclass=WalkerMeta):
- @_core.hook(tuple, list, set, frozenset)
+ @_dispatcher.Hook(tuple, list, set, frozenset)
def dispatch_sequence(self, instance):
for item in instance:
yield item
yield from self(item)
- @_core.hook(dict)
+ @_dispatcher.Hook(dict)
def dispatch_mapping(self, instance):
for (key, value) in instance.items():
yield (key, value)
yield from self((key, value))
- @_core.hook(object)
+ @_dispatcher.Hook(object)
def dispatch_object(self, instance):
yield from ()