From 1133cac2ac7af483656270a7e6403014a4f3de74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Flagothier?= <29896153+srfwx@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:10:35 +0100 Subject: [PATCH 1/2] Adds generic list object --- pynetbox/core/response.py | 51 ++++++++++++++++++++++++++++++++------- pynetbox/models/mapper.py | 2 ++ 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/pynetbox/core/response.py b/pynetbox/core/response.py index fd8cfae..160792e 100644 --- a/pynetbox/core/response.py +++ b/pynetbox/core/response.py @@ -313,7 +313,7 @@ def __iter__(self): if isinstance(cur_attr, Record): yield i, dict(cur_attr) elif isinstance(cur_attr, list) and all( - isinstance(i, Record) for i in cur_attr + isinstance(i, (Record, GenericListObject)) for i in cur_attr ): yield i, [dict(x) for x in cur_attr] else: @@ -373,10 +373,9 @@ def generic_list_parser(key_name, list_item): and "object" in list_item ): lookup = list_item["object_type"] - model = None - model = CONTENT_TYPE_MAPPER.get(lookup) - if model: - return model(list_item["object"], self.api, self.endpoint) + if model := CONTENT_TYPE_MAPPER.get(lookup, None): + record = model(list_item["object"], self.api, self.endpoint) + return GenericListObject(record) return list_item @@ -412,7 +411,7 @@ def list_parser(key_name, list_item): # check if GFK if len(v) and isinstance(v[0], dict) and "object_type" in v[0]: v = [generic_list_parser(k, i) for i in v] - to_cache = list(v) + to_cache = [i.serialize() for i in v] elif k == "constraints": # Permissions constraints can be either dict or list to_cache = copy.deepcopy(v) @@ -470,6 +469,7 @@ def serialize(self, nested=False, init=False): If an attribute's value is a ``Record`` type it's replaced with the ``id`` field of that object. + .. note:: Using this to get a dictionary representation of the record @@ -485,6 +485,7 @@ def serialize(self, nested=False, init=False): init_vals = dict(self._init_cache) ret = {} + for i in dict(self): current_val = getattr(self, i) if not init else init_vals.get(i) if i == "custom_fields": @@ -494,15 +495,21 @@ def serialize(self, nested=False, init=False): current_val = getattr(current_val, "serialize")(nested=True) if isinstance(current_val, list): - current_val = [ - v.id if isinstance(v, Record) else v for v in current_val - ] + serialized_list = [] + for v in current_val: + if isinstance(v, GenericListObject): + v = v.serialize() + elif isinstance(v, Record): + v = v.id + serialized_list.append(v) + current_val = serialized_list if i in LIST_AS_SET and ( all([isinstance(v, str) for v in current_val]) or all([isinstance(v, int) for v in current_val]) ): current_val = list(OrderedDict.fromkeys(current_val)) ret[i] = current_val + return ret def _diff(self): @@ -615,3 +622,29 @@ def delete(self): http_session=self.api.http_session, ) return True if req.delete() else False + + +class GenericListObject: + def __init__(self, record): + from pynetbox.models.mapper import TYPE_CONTENT_MAPPER + + self.object = record + self.object_id = record.id + self.object_type = TYPE_CONTENT_MAPPER.get(record.__class__) + + def __repr__(self): + return str(self.object) + + def serialize(self): + ret = {k: getattr(self, k) for k in ["object_id", "object_type"]} + return ret + + def __getattr__(self, k): + return getattr(self.object, k) + + def __iter__(self): + for i in dir(self): + cur_attr = getattr(self, i) + if isinstance(cur_attr, Record): + cur_attr = dict(cur_attr) + yield i, cur_attr diff --git a/pynetbox/models/mapper.py b/pynetbox/models/mapper.py index 1dcfc99..9a468ee 100644 --- a/pynetbox/models/mapper.py +++ b/pynetbox/models/mapper.py @@ -109,3 +109,5 @@ "wireless.WirelessLANGroup": None, "wireless.wirelesslink": None, } + +TYPE_CONTENT_MAPPER = {v: k for k, v in CONTENT_TYPE_MAPPER.items() if v is not None} From 108a080c927d55471ee490ed11511934eccc53fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Flagothier?= <29896153+srfwx@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:52:42 +0100 Subject: [PATCH 2/2] Fix iteration on GenericListObject --- pynetbox/core/response.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pynetbox/core/response.py b/pynetbox/core/response.py index 160792e..68f65a1 100644 --- a/pynetbox/core/response.py +++ b/pynetbox/core/response.py @@ -643,7 +643,7 @@ def __getattr__(self, k): return getattr(self.object, k) def __iter__(self): - for i in dir(self): + for i in ["object_id", "object_type", "object"]: cur_attr = getattr(self, i) if isinstance(cur_attr, Record): cur_attr = dict(cur_attr)