7
7
from .common import without_keys
8
8
from typing import Self , Iterator , TypeVar , NoReturn
9
9
10
+ def findSubclasses (cls ):
11
+ return set (cls .__subclasses__ ()).union (
12
+ [s for c in cls .__subclasses__ () for s in findSubclasses (c )])
10
13
11
14
T = TypeVar ('T' , bound = "AbstractNetboxType" )
12
15
class AbstractNetboxType (abc .ABC , Iterable ):
@@ -16,7 +19,7 @@ def __init__(self, *args, **kwargs):
16
19
self ._store .update (** kwargs )
17
20
for k , v in without_keys (self ._store , "__parent" ).items ():
18
21
self [k ] = self .convert (v )
19
-
22
+
20
23
def __getitem__ (self , key ):
21
24
return self ._store [key ]
22
25
@@ -30,15 +33,20 @@ def __len__(self):
30
33
return len (self ._store )
31
34
32
35
def __iter__ (self ) -> Iterator [Self | str | int | bool | None ]:
36
+ # I bet, we cannot to this before AbstractClass and all of it's inherited childs are constructed, so we need to do this in here.
37
+ iterableSubclasses = findSubclasses (AbstractNetboxType )
38
+
33
39
yield self
34
40
for k , v in without_keys (self ._store , ["__parent" , "__typename" ]).items ():
35
41
if isinstance (v , dict ):
36
42
yield from iter (v )
37
- if isinstance (v , list ):
43
+ elif isinstance (v , list ):
38
44
for e in v :
39
45
yield from e
40
- else :
41
- yield v
46
+ elif next ((cs for cs in iterableSubclasses if isinstance (v , cs )), None ):
47
+ yield from iter (v )
48
+
49
+ # Note: We can omit the emit of scalars, because we do not use them.
42
50
43
51
def __hash__ (self ):
44
52
non_recursive_clone = without_keys (self ._store , "__parent" )
@@ -74,7 +82,12 @@ def get(self, *args, **kwargs):
74
82
def convert (self , item ):
75
83
if isinstance (item , dict ):
76
84
if "__typename" in item .keys ():
77
- c = {k : v for k , v in [c .register () for c in AbstractNetboxType .__subclasses__ ()]}[item ["__typename" ]]
85
+
86
+ # Taken from https://stackoverflow.com/questions/3862310/how-to-find-all-the-subclasses-of-a-class-given-its-name
87
+ availableSubclasses = findSubclasses (AbstractNetboxType )
88
+ availableClassesForTypeNames = {k : v for k , v in [c .register () for c in availableSubclasses ]}
89
+
90
+ c = availableClassesForTypeNames [item ["__typename" ]]
78
91
o = c ()
79
92
o ._store .update (
80
93
{k : o .convert (v ) for k , v in without_keys (item , "__parent" ).items ()} | {"__parent" : self }
0 commit comments