55093556a1eacff5c18ebca0850cdcb94d0c4713
[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 GenericPath:
17 def __init__(self, path):
18 self.__path = path
19 return super().__init__()
20
21 def __str__(self):
22 return self.__path.__str__()
23
24 def __repr__(self):
25 return f"{self.__class__.__name__}({str(self)})"
26
27 @property
28 def path(self):
29 return self.__path
30
31
32 class IndexPath(GenericPath):
33 def __str__(self):
34 return f"[{self.path}]"
35
36
37 class AttributePath(GenericPath):
38 def __str__(self):
39 return f".{self.path}]"
40
41
42 class HashPath(GenericPath):
43 def __str__(self):
44 return f"{{{self.path}}}"
45
46
47 class Walker(dispatcher.Dispatcher, metaclass=WalkerMeta):
48 @dispatcher.Hook(tuple, list)
49 def dispatch_ordered_sequence(self, instance):
50 for (index, item) in enumerate(instance):
51 yield (item, instance, index, IndexPath)
52 yield from self(item)
53
54 @dispatcher.Hook(set, frozenset)
55 def dispatch_unordered_sequence(self, instance):
56 for item in instance:
57 yield (item, instance, item, HashPath)
58 yield from self(item)
59
60 @dispatcher.Hook(dataclasses.is_dataclass)
61 def dispatch_dataclass(self, instance):
62 for field in dataclasses.fields(instance):
63 key = field.name
64 value = getattr(instance, key)
65 yield (value, instance, key, AttributePath)
66 yield from self(value)
67
68 @dispatcher.Hook(dict)
69 def dispatch_mapping(self, instance):
70 for (key, value) in instance.items():
71 yield (key, instance, key, HashPath)
72 yield from self(key)
73 yield (value, instance, key, IndexPath)
74 yield from self(value)
75
76 @dispatcher.Hook(object)
77 def dispatch_object(self, instance, path=()):
78 yield from ()