4d1c33dbcf39bc3bd630c9ef7ec83611bf76b74b
[mdis.git] / src / mdis / walker.py
1 __all__ = [
2 "Walker",
3 "WalkerMeta",
4 ]
5
6 import enum
7 import dataclasses
8
9 from . import dispatcher
10
11
12 class WalkerMeta(dispatcher.DispatcherMeta):
13 pass
14
15
16 class PartId(enum.Enum):
17 Index = enum.auto()
18 Attribute = enum.auto()
19 Hash = enum.auto()
20
21 def __call__(self, part):
22 return {
23 PartId.Index: "[{part}]",
24 PartId.Attribute: ".{part}",
25 PartId.Hash: "{{{part}}}",
26 }[self].format(part=part)
27
28
29 class Walker(dispatcher.Dispatcher, metaclass=WalkerMeta):
30 @dispatcher.Hook(tuple, list)
31 def dispatch_ordered_sequence(self, instance):
32 for (index, item) in enumerate(instance):
33 yield (item, instance, index, PartId.Index)
34 yield from self(item)
35
36 @dispatcher.Hook(set, frozenset)
37 def dispatch_unordered_sequence(self, instance):
38 for item in instance:
39 yield (item, instance, item, PartId.Hash)
40 yield from self(item)
41
42 @dispatcher.Hook(dataclasses.is_dataclass)
43 def dispatch_dataclass(self, instance):
44 for field in dataclasses.fields(instance):
45 key = field.name
46 value = getattr(instance, key)
47 yield (value, instance, key, PartId.Attribute)
48 yield from self(value)
49
50 @dispatcher.Hook(dict)
51 def dispatch_mapping(self, instance):
52 for (key, value) in instance.items():
53 yield (key, instance, key, PartId.Hash)
54 yield from self(key)
55 yield (value, instance, key, PartId.Index)
56 yield from self(value)
57
58 @dispatcher.Hook(object)
59 def dispatch_object(self, instance, path=()):
60 yield from ()