walker: support path parts formatting
authorDmitry Selyutin <ghostmansd@gmail.com>
Tue, 20 Jun 2023 18:17:16 +0000 (21:17 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Tue, 20 Jun 2023 18:17:16 +0000 (21:17 +0300)
src/mdis/walker.py

index a5762fadd096a8a57f55af2f00b63366ef830634..578284e4c9b9667ceb44f759e200fd9f92a25834 100644 (file)
@@ -3,6 +3,7 @@ __all__ = [
     "WalkerMeta",
 ]
 
+import enum
 import dataclasses
 
 from . import dispatcher
@@ -12,27 +13,54 @@ class WalkerMeta(dispatcher.DispatcherMeta):
     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 ()