"WalkerMeta",
]
+import enum
import dataclasses
from . import dispatcher
pass
+class PartId(enum.Enum):
+ Index = enum.auto()
+ Attribute = enum.auto()
+ Hash = enum.auto()
+
+ def __call__(self, part):
+ return {
+ PartId.Index: "[{part}]",
+ PartId.Attribute: ".{part}",
+ PartId.Hash: "{{{part}}}",
+ }[self].format(part=part)
+
+
class Walker(dispatcher.Dispatcher, metaclass=WalkerMeta):
- @dispatcher.Hook(tuple, list, set, frozenset)
- def dispatch_sequence(self, instance):
- for item in instance:
- yield item
- yield from self(item)
+ @dispatcher.Hook(tuple, list)
+ def dispatch_ordered_sequence(self, instance, path=()):
+ for (index, item) in enumerate(instance):
+ part = (PartId.Index, index)
+ parts = (path + (part,))
+ yield (item, parts)
+ yield from self(item, path=parts)
- @dispatcher.Hook(dict)
- def dispatch_mapping(self, instance):
- for (key, value) in instance.items():
- yield (key, value)
- yield from self((key, value))
+ @dispatcher.Hook(set, frozenset)
+ def dispatch_unordered_sequence(self, instance, path=[]):
+ for item in instance:
+ part = (PartId.Hash, item)
+ parts = (path + (part,))
+ yield (item, parts)
+ yield from self(item, path=parts)
@dispatcher.Hook(dataclasses.is_dataclass)
- def dispatch_dataclass(self, instance):
+ def dispatch_dataclass(self, instance, path=[]):
for field in dataclasses.fields(instance):
key = field.name
value = getattr(instance, key)
- yield (key, value)
- yield from self((key, value))
+ part = (PartId.Attribute, key)
+ parts = (path + (part,))
+ yield (value, parts)
+ yield from self(value, path=parts)
+
+ @dispatcher.Hook(dict)
+ def dispatch_mapping(self, instance, path=[]):
+ for (key, value) in instance.items():
+ part = (PartId.Index, key)
+ parts = (path + (part,))
+ yield (value, parts)
+ yield from self(value, path=parts)
@dispatcher.Hook(object)
- def dispatch_object(self, instance):
+ def dispatch_object(self, instance, path=()):
yield from ()