nbforager 0.2.6__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nbforager-0.2.6 → nbforager-0.5.0}/PKG-INFO +17 -4
- {nbforager-0.2.6 → nbforager-0.5.0}/README.rst +13 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/__init__.py +0 -13
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/base_c.py +13 -8
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/circuits.py +1 -1
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/connector.py +14 -12
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/extended_get.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/ipam.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/circuits.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/core.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/dcim.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/extras.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/forager.py +65 -43
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/ipam.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/ipv4.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/joiner.py +68 -72
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/tenancy.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/users.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/virtualization.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/wireless.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/helpers.py +212 -27
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/log.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/messages.py +1 -1
- nbforager-0.5.0/nbforager/nb_api.py +421 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/nb_forager.py +24 -9
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/nb_tree.py +37 -2
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/parser/nb_custom.py +2 -1
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/parser/nb_parser.py +8 -13
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/parser/nb_value.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/py_tree.py +1 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/types_.py +5 -2
- {nbforager-0.2.6 → nbforager-0.5.0}/pyproject.toml +18 -14
- nbforager-0.2.6/nbforager/models/__init__.py +0 -1
- nbforager-0.2.6/nbforager/models/dcim/__init__.py +0 -1
- nbforager-0.2.6/nbforager/models/dcim/interfaces/__init__.py +0 -1
- nbforager-0.2.6/nbforager/models/dcim/interfaces/interface_nb.py +0 -13
- nbforager-0.2.6/nbforager/nb_api.py +0 -187
- /nbforager-0.2.6/LICENCE.txt → /nbforager-0.5.0/LICENSE.txt +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/__init__.py +0 -0
- /nbforager-0.2.6/nbforager/api/base_ca.py → /nbforager-0.5.0/nbforager/api/base_ac.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/core.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/dcim.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/extras.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/ip_addresses.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/plugins_ca.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/status.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/tenancy.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/users.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/virtualization.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/api/wireless.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/exceptions.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/__init__.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/foragers/base_fa.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/nb_cache.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/parser/__init__.py +0 -0
- {nbforager-0.2.6 → nbforager-0.5.0}/nbforager/py.typed +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: nbforager
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.0
|
4
4
|
Summary: Python package designed to assist in working with the Netbox REST API. The filter parameters are identical to those in the Web UI filter form. It replaces brief data with full information, and Netbox objects are represented as a recursive multidimensional dictionary.
|
5
5
|
Home-page: https://github.com/vladimirs-git/nbforager
|
6
6
|
License: Apache-2.0
|
@@ -20,18 +20,25 @@ Classifier: Programming Language :: Python :: 3.11
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.12
|
21
21
|
Provides-Extra: test
|
22
22
|
Requires-Dist: ciscoconfparse (>=1.9,<2.0)
|
23
|
-
Requires-Dist: netports (>=0.
|
23
|
+
Requires-Dist: netports (>=0.14,<1.0.0)
|
24
24
|
Requires-Dist: pydantic (>=2,<3)
|
25
25
|
Requires-Dist: pynetbox (>=7.3.3,<8.0.0)
|
26
26
|
Requires-Dist: requests (>=2,<3)
|
27
27
|
Requires-Dist: tabulate (>=0.9.0,<0.10.0)
|
28
28
|
Requires-Dist: tomli (==2.0.1)
|
29
|
-
Requires-Dist: vhelpers (>=0.
|
29
|
+
Requires-Dist: vhelpers (>=0.3,<1.0.0)
|
30
30
|
Project-URL: Bug Tracker, https://github.com/vladimirs-git/nbforager/issues
|
31
|
-
Project-URL: Download URL, https://github.com/vladimirs-git/nbforager/archive/refs/tags/0.
|
31
|
+
Project-URL: Download URL, https://github.com/vladimirs-git/nbforager/archive/refs/tags/0.5.0.tar.gz
|
32
32
|
Project-URL: Repository, https://github.com/vladimirs-git/nbforager
|
33
33
|
Description-Content-Type: text/x-rst
|
34
34
|
|
35
|
+
|
36
|
+
.. image:: https://img.shields.io/pypi/v/netports.svg
|
37
|
+
:target: https://pypi.python.org/pypi/netports
|
38
|
+
.. image:: https://img.shields.io/badge/Python-3.8%20%7C%203.9%20%7C%203.10%20%7C%203.11-blue.svg
|
39
|
+
:target: https://pypi.python.org/pypi/logger-color
|
40
|
+
|
41
|
+
|
35
42
|
nbforager
|
36
43
|
=========
|
37
44
|
|
@@ -51,6 +58,12 @@ Fully documented on `Read the Docs`_.
|
|
51
58
|
|
52
59
|
----------------------------------------------------------------------------------------
|
53
60
|
|
61
|
+
Requirements
|
62
|
+
============
|
63
|
+
|
64
|
+
Python >=3.8,<3.12
|
65
|
+
|
66
|
+
|
54
67
|
Quickstart
|
55
68
|
==========
|
56
69
|
|
@@ -1,3 +1,10 @@
|
|
1
|
+
|
2
|
+
.. image:: https://img.shields.io/pypi/v/netports.svg
|
3
|
+
:target: https://pypi.python.org/pypi/netports
|
4
|
+
.. image:: https://img.shields.io/badge/Python-3.8%20%7C%203.9%20%7C%203.10%20%7C%203.11-blue.svg
|
5
|
+
:target: https://pypi.python.org/pypi/logger-color
|
6
|
+
|
7
|
+
|
1
8
|
nbforager
|
2
9
|
=========
|
3
10
|
|
@@ -17,6 +24,12 @@ Fully documented on `Read the Docs`_.
|
|
17
24
|
|
18
25
|
----------------------------------------------------------------------------------------
|
19
26
|
|
27
|
+
Requirements
|
28
|
+
============
|
29
|
+
|
30
|
+
Python >=3.8,<3.12
|
31
|
+
|
32
|
+
|
20
33
|
Quickstart
|
21
34
|
==========
|
22
35
|
|
@@ -157,9 +157,10 @@ class BaseC:
|
|
157
157
|
session timeout reached. Default is `10`.
|
158
158
|
|
159
159
|
:param bool strict: When querying objects by tag, if there are no tags present,
|
160
|
-
the Netbox API response returns a status_code=400.
|
161
|
-
raised when status_code=400.
|
162
|
-
empty list is returned with status_code=200.
|
160
|
+
the Netbox API response returns a status_code=400.
|
161
|
+
True - ConnectionError is raised when status_code=400.
|
162
|
+
False - WARNING message is logged and an empty list is returned with status_code=200.
|
163
|
+
Default is `False`.
|
163
164
|
|
164
165
|
:param bool extended_get: True - Extend filtering parameters in GET request,
|
165
166
|
``{parameter}`` can be used instead of ``{parameter}_id``. Default is `True`.
|
@@ -180,9 +181,9 @@ class BaseC:
|
|
180
181
|
self.threads: int = _init_threads(**kwargs)
|
181
182
|
self.interval: float = float(kwargs.get("interval") or 0.0)
|
182
183
|
# Errors processing
|
183
|
-
self.timeout:
|
184
|
+
self.timeout: int = int(kwargs.get("timeout") or 60)
|
184
185
|
self.max_retries: int = int(kwargs.get("max_retries") or 0)
|
185
|
-
self.sleep:
|
186
|
+
self.sleep: int = int(kwargs.get("sleep") or 10)
|
186
187
|
self.strict: bool = bool(kwargs.get("strict"))
|
187
188
|
# Settings
|
188
189
|
self.extended_get: bool = bool(kwargs.get("extended_get"))
|
@@ -316,6 +317,9 @@ class BaseC:
|
|
316
317
|
:return: Netbox objects. Update self _results.
|
317
318
|
"""
|
318
319
|
offset = 0
|
320
|
+
if offsets := params_d.get("offset"):
|
321
|
+
offset = int(offsets[0])
|
322
|
+
|
319
323
|
max_limit: int = self._set_limit(params_d)
|
320
324
|
params_l: LParam = vparam.from_dict(params_d)
|
321
325
|
|
@@ -351,12 +355,12 @@ class BaseC:
|
|
351
355
|
:return: Max limit value, update params_d["limit"] value
|
352
356
|
"""
|
353
357
|
limit = 0
|
354
|
-
if limit_ := vdict.pop("limit"
|
358
|
+
if limit_ := vdict.pop(params_d, key="limit") or []:
|
355
359
|
limit = int(limit_[0])
|
356
360
|
if not limit:
|
357
361
|
limit = self.limit
|
358
362
|
max_limit = 0
|
359
|
-
if max_limit_ := vdict.pop("max_limit"
|
363
|
+
if max_limit_ := vdict.pop(params_d, key="max_limit") or []:
|
360
364
|
max_limit = int(max_limit_[0])
|
361
365
|
if max_limit and max_limit < limit:
|
362
366
|
limit = max_limit
|
@@ -485,7 +489,7 @@ class BaseC:
|
|
485
489
|
url=url,
|
486
490
|
headers=self._headers(),
|
487
491
|
verify=self.verify,
|
488
|
-
timeout=self.timeout,
|
492
|
+
timeout=float(self.timeout),
|
489
493
|
)
|
490
494
|
except ReadTimeout:
|
491
495
|
attempts = f"{counter} of {self.max_retries}"
|
@@ -501,6 +505,7 @@ class BaseC:
|
|
501
505
|
|
502
506
|
if response.ok:
|
503
507
|
return response
|
508
|
+
|
504
509
|
msg = self._msg_status_code(response)
|
505
510
|
if self._is_status_code_5xx(response):
|
506
511
|
raise ConnectionError(f"Netbox server error: {msg}.")
|
@@ -23,9 +23,9 @@ class Connector(BaseC):
|
|
23
23
|
# ============================= methods ==============================
|
24
24
|
|
25
25
|
def create(self, **kwargs) -> Response:
|
26
|
-
"""Create object in Netbox.
|
26
|
+
"""Create an object in Netbox.
|
27
27
|
|
28
|
-
:param kwargs: Parameters
|
28
|
+
:param kwargs: Parameters for creating a new object.
|
29
29
|
|
30
30
|
:return: Session response.
|
31
31
|
|
@@ -43,11 +43,11 @@ class Connector(BaseC):
|
|
43
43
|
return response
|
44
44
|
|
45
45
|
def create_d(self, **kwargs) -> DAny:
|
46
|
-
"""Create object in Netbox.
|
46
|
+
"""Create an object in Netbox.
|
47
47
|
|
48
|
-
:param kwargs:
|
48
|
+
:param kwargs: Parameters for creating a new object.
|
49
49
|
|
50
|
-
:return: Data of newly
|
50
|
+
:return: Data of newly created object.
|
51
51
|
:rtype: dict
|
52
52
|
"""
|
53
53
|
response: Response = self.create(**kwargs)
|
@@ -59,7 +59,7 @@ class Connector(BaseC):
|
|
59
59
|
|
60
60
|
# noinspection PyShadowingBuiltins
|
61
61
|
def delete(self, id: int) -> Response: # pylint: disable=redefined-builtin
|
62
|
-
"""Delete object in Netbox.
|
62
|
+
"""Delete an object in Netbox.
|
63
63
|
|
64
64
|
:param id: Object ID.
|
65
65
|
:type id: int
|
@@ -70,6 +70,8 @@ class Connector(BaseC):
|
|
70
70
|
- <Response [404]> Object not found.
|
71
71
|
:rtype: Response
|
72
72
|
"""
|
73
|
+
if not id:
|
74
|
+
raise ValueError("id is required.")
|
73
75
|
response: Response = self._session.delete(
|
74
76
|
url=f"{self.url}{id}",
|
75
77
|
headers=self._headers(),
|
@@ -123,12 +125,12 @@ class Connector(BaseC):
|
|
123
125
|
|
124
126
|
# noinspection PyIncorrectDocstring
|
125
127
|
def update(self, **kwargs) -> Response:
|
126
|
-
"""Update object in Netbox.
|
128
|
+
"""Update an object in Netbox.
|
127
129
|
|
128
130
|
:param id: Netbox object id to update.
|
129
131
|
:type id: int
|
130
132
|
|
131
|
-
:param kwargs: Parameters to update object in Netbox.
|
133
|
+
:param kwargs: Parameters to update an object in Netbox.
|
132
134
|
|
133
135
|
:return: Session response.
|
134
136
|
|
@@ -136,9 +138,9 @@ class Connector(BaseC):
|
|
136
138
|
- <Response [400]> Invalid data.
|
137
139
|
:rtype: Response
|
138
140
|
"""
|
139
|
-
id_ = vdict.pop("id"
|
141
|
+
id_ = vdict.pop(kwargs, key="id")
|
140
142
|
if not id_:
|
141
|
-
raise ValueError("id
|
143
|
+
raise ValueError("id is required in the data.")
|
142
144
|
|
143
145
|
response: Response = self._session.patch(
|
144
146
|
url=f"{self.url}{id_}/",
|
@@ -151,12 +153,12 @@ class Connector(BaseC):
|
|
151
153
|
|
152
154
|
# noinspection PyIncorrectDocstring
|
153
155
|
def update_d(self, **kwargs) -> DAny:
|
154
|
-
"""Update object in Netbox.
|
156
|
+
"""Update an object in Netbox.
|
155
157
|
|
156
158
|
:param id: Netbox object id to update.
|
157
159
|
:type id: int
|
158
160
|
|
159
|
-
:param kwargs: Parameters to update object in Netbox.
|
161
|
+
:param kwargs: Parameters to update an object in Netbox.
|
160
162
|
|
161
163
|
:return: Data of updated object.
|
162
164
|
:rtype: dict
|
@@ -4,7 +4,6 @@
|
|
4
4
|
|
5
5
|
from __future__ import annotations
|
6
6
|
|
7
|
-
import logging
|
8
7
|
import time
|
9
8
|
from queue import Queue
|
10
9
|
from threading import Thread
|
@@ -13,11 +12,12 @@ from urllib.parse import urlparse, parse_qs
|
|
13
12
|
from vhelpers import vstr
|
14
13
|
|
15
14
|
from nbforager import helpers as h
|
15
|
+
from nbforager import nb_tree
|
16
16
|
from nbforager.nb_api import NbApi
|
17
|
-
from nbforager.nb_tree import NbTree
|
18
|
-
from nbforager.parser
|
17
|
+
from nbforager.nb_tree import NbTree
|
18
|
+
from nbforager.parser import nb_parser
|
19
19
|
from nbforager.py_tree import PyTree
|
20
|
-
from nbforager.types_ import LDAny, DiDAny, LStr, LT2StrDAny, DList, LDList, DiAny
|
20
|
+
from nbforager.types_ import LDAny, DiDAny, LStr, LT2StrDAny, DList, LDList, DiAny, SInt, DAny
|
21
21
|
|
22
22
|
|
23
23
|
class Forager:
|
@@ -86,7 +86,10 @@ class Forager:
|
|
86
86
|
:return: None. Update self object.
|
87
87
|
"""
|
88
88
|
# Query main data
|
89
|
-
|
89
|
+
kwargs_: DAny = self._delete_existing_nested_ids(**kwargs)
|
90
|
+
if kwargs and not kwargs_:
|
91
|
+
return
|
92
|
+
nb_objects: LDAny = self._get_root_data_from_netbox(nested=nested, **kwargs_)
|
90
93
|
if not nested:
|
91
94
|
return
|
92
95
|
urls: LStr = self._collect_nested_urls(nb_objects)
|
@@ -104,7 +107,7 @@ class Forager:
|
|
104
107
|
# loop
|
105
108
|
else:
|
106
109
|
for url in urls:
|
107
|
-
app, model, _ = h.
|
110
|
+
app, model, _ = h.url_to_ami_items(url)
|
108
111
|
path = f"{app}/{model}/"
|
109
112
|
connector = self._get_connector(path)
|
110
113
|
params_d: DList = parse_qs(urlparse(url).query)
|
@@ -134,7 +137,7 @@ class Forager:
|
|
134
137
|
|
135
138
|
:return: Filtered Netbox objects.
|
136
139
|
"""
|
137
|
-
return find_objects(objects=list(self.root_d.values()), **kwargs)
|
140
|
+
return nb_parser.find_objects(objects=list(self.root_d.values()), **kwargs)
|
138
141
|
|
139
142
|
def find_rse(self, role: str = "", site: str = "", env: str = "", **kwargs) -> LDAny:
|
140
143
|
"""Find Netbox objects in NbForager.tree by Role-Sile-Env finding parameters.
|
@@ -155,7 +158,7 @@ class Forager:
|
|
155
158
|
}
|
156
159
|
params = {k: v for k, v in params.items() if v}
|
157
160
|
kwargs.update(params)
|
158
|
-
return find_objects(objects=list(self.tree_d.values()), **kwargs)
|
161
|
+
return nb_parser.find_objects(objects=list(self.tree_d.values()), **kwargs)
|
159
162
|
|
160
163
|
def find_tree(self, **kwargs) -> LDAny:
|
161
164
|
"""Find Netbox objects in NbForager.tree by extended finding parameters.
|
@@ -167,48 +170,50 @@ class Forager:
|
|
167
170
|
|
168
171
|
:return: Filtered Netbox objects.
|
169
172
|
"""
|
170
|
-
return find_objects(objects=list(self.tree_d.values()), **kwargs)
|
173
|
+
return nb_parser.find_objects(objects=list(self.tree_d.values()), **kwargs)
|
171
174
|
|
172
175
|
# ============================= helpers ==============================
|
173
176
|
|
174
|
-
def
|
177
|
+
def _delete_existing_nested_ids(self, **kwargs) -> DAny:
|
178
|
+
"""Delete the IDs of objects that are already present in the tree and nested=True.
|
179
|
+
|
180
|
+
Delete only if kwargs["id"] is a list, ignore other data types.
|
181
|
+
|
182
|
+
:param kwargs: Filtering parameters.
|
183
|
+
|
184
|
+
:return: None. Update IDs in kwargs.
|
185
|
+
"""
|
186
|
+
if list(kwargs) != ["id"]:
|
187
|
+
return kwargs
|
188
|
+
if not isinstance(kwargs["id"], list):
|
189
|
+
return kwargs
|
190
|
+
ids: SInt = set(kwargs["id"])
|
191
|
+
existing_ids: SInt = {d["id"] for d in self.find_root(_nested=True, **kwargs)}
|
192
|
+
if new_ids := sorted(set(ids).difference(existing_ids)):
|
193
|
+
return {"id": new_ids}
|
194
|
+
return {}
|
195
|
+
|
196
|
+
def _get_root_data_from_netbox(self, nested: bool = False, **kwargs) -> LDAny:
|
175
197
|
"""Retrieve data from the Netbox.
|
176
198
|
|
177
199
|
Request data based on the kwargs filter parameters and
|
178
200
|
save the received objects to the NbForager.root.
|
201
|
+
Set extra `_nested` value in Netbox object.
|
179
202
|
|
180
|
-
:param
|
203
|
+
:param bool nested: `True` - Request base and nested objects,
|
204
|
+
`False` - Request only base objects. Default id `False`
|
205
|
+
|
206
|
+
:param kwargs: Filtering parameters.
|
181
207
|
|
182
208
|
:return: List of Netbox objects. Update NbForager.root object.
|
183
209
|
"""
|
184
210
|
nb_objects: LDAny = self.connector.get(**kwargs)
|
185
|
-
nb_objects = self._validate_ids(nb_objects)
|
186
211
|
for nb_object in nb_objects:
|
187
|
-
|
212
|
+
nb_object["_nested"] = nested
|
213
|
+
idx = int(nb_object["id"])
|
214
|
+
self.root_d[idx] = nb_object
|
188
215
|
return nb_objects
|
189
216
|
|
190
|
-
@staticmethod
|
191
|
-
def _validate_ids(nb_objects: LDAny) -> LDAny:
|
192
|
-
"""Check the IDs in the items. The ID should be a unique integer.
|
193
|
-
|
194
|
-
:param nb_objects: List of dictionaries containing Netbox objects.
|
195
|
-
|
196
|
-
:return: None. Logging an error if the ID does not match the conditions.
|
197
|
-
"""
|
198
|
-
nb_objects_: LDAny = []
|
199
|
-
for nb_object in nb_objects:
|
200
|
-
id_ = nb_object.get("id")
|
201
|
-
if not isinstance(id_, int):
|
202
|
-
msg = f"TypeError: {id_=} {int} expected in {nb_object=}."
|
203
|
-
logging.error(msg)
|
204
|
-
continue
|
205
|
-
if id_ in nb_objects:
|
206
|
-
msg = f"ValueError: Duplicate {id_=} in nb_objects_ and {nb_object=}."
|
207
|
-
logging.error(msg)
|
208
|
-
continue
|
209
|
-
nb_objects_.append(nb_object)
|
210
|
-
return nb_objects_
|
211
|
-
|
212
217
|
def _collect_nested_urls(self, nb_objects: LDAny) -> LStr:
|
213
218
|
"""Collect nested urls.
|
214
219
|
|
@@ -217,10 +222,20 @@ class Forager:
|
|
217
222
|
:return: Nested URLs.
|
218
223
|
"""
|
219
224
|
urls: LStr = h.nested_urls(nb_objects)
|
220
|
-
urls = missed_urls(urls=urls, tree=self.root)
|
225
|
+
urls = nb_tree.missed_urls(urls=urls, tree=self.root)
|
221
226
|
urls = h.join_urls(urls)
|
222
|
-
urls = [s for s in urls if h.
|
223
|
-
|
227
|
+
urls = [s for s in urls if h.url_to_ami_items(s)[0]]
|
228
|
+
|
229
|
+
urls_: LStr = []
|
230
|
+
|
231
|
+
for url in urls:
|
232
|
+
app, model, _ = h.url_to_ami_items(url)
|
233
|
+
path = f"{app}/{model}/"
|
234
|
+
connector = self._get_connector(path)
|
235
|
+
urls_sliced = h.slice_url(url, max_len=connector.url_length)
|
236
|
+
urls_.extend(urls_sliced)
|
237
|
+
|
238
|
+
return urls_
|
224
239
|
|
225
240
|
# noinspection PyProtectedMember
|
226
241
|
def _get_path_params(self, urls: LStr) -> LT2StrDAny:
|
@@ -232,7 +247,7 @@ class Forager:
|
|
232
247
|
"""
|
233
248
|
path_params: LT2StrDAny = []
|
234
249
|
for url in urls:
|
235
|
-
app, model, _ = h.
|
250
|
+
app, model, _ = h.url_to_ami_items(url)
|
236
251
|
path = f"{app}/{model}/"
|
237
252
|
connector = self._get_connector(path)
|
238
253
|
params_d = parse_qs(urlparse(url).query)
|
@@ -310,13 +325,20 @@ class Forager:
|
|
310
325
|
connector = getattr(getattr(self.api, app), model)
|
311
326
|
return connector
|
312
327
|
|
313
|
-
def _save_results(self, results):
|
314
|
-
|
328
|
+
def _save_results(self, results: LDAny) -> None:
|
329
|
+
"""Save Netbox objects to root NbTree object.
|
330
|
+
|
331
|
+
:param results: Data to be saved.
|
332
|
+
:return: None. root NbTree object.
|
333
|
+
"""
|
315
334
|
for data in results:
|
316
|
-
app, model,
|
335
|
+
app, model, idx_ = h.url_to_ami_items(data["url"])
|
336
|
+
idx = int(idx_)
|
317
337
|
path = f"{app}/{model}"
|
318
338
|
model_d: DiDAny = self._get_root_data(path)
|
319
|
-
|
339
|
+
if idx not in model_d:
|
340
|
+
data["_nested"] = False
|
341
|
+
model_d[idx] = data
|
320
342
|
|
321
343
|
def _get_pynb_data(self, path: str) -> DiAny:
|
322
344
|
"""Get data in self pynb by app/model path.
|