nbforager 0.4.1__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.4.1 → nbforager-0.5.0}/PKG-INFO +2 -2
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/__init__.py +0 -13
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/circuits.py +1 -1
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/extended_get.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/ipam.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/circuits.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/core.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/dcim.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/extras.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/ipam.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/ipv4.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/joiner.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/tenancy.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/users.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/virtualization.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/wireless.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/helpers.py +6 -3
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/log.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/messages.py +1 -1
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/nb_api.py +81 -27
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/nb_forager.py +1 -1
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/nb_tree.py +1 -9
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/parser/nb_custom.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/parser/nb_parser.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/parser/nb_value.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/py_tree.py +1 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/types_.py +3 -3
- {nbforager-0.4.1 → nbforager-0.5.0}/pyproject.toml +6 -6
- {nbforager-0.4.1 → nbforager-0.5.0}/LICENSE.txt +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/README.rst +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/__init__.py +0 -0
- /nbforager-0.4.1/nbforager/api/base_ca.py → /nbforager-0.5.0/nbforager/api/base_ac.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/base_c.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/connector.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/core.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/dcim.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/extras.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/ip_addresses.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/plugins_ca.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/status.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/tenancy.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/users.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/virtualization.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/api/wireless.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/exceptions.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/__init__.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/base_fa.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/foragers/forager.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/nb_cache.py +0 -0
- {nbforager-0.4.1 → nbforager-0.5.0}/nbforager/parser/__init__.py +0 -0
- {nbforager-0.4.1 → 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
|
@@ -28,7 +28,7 @@ Requires-Dist: tabulate (>=0.9.0,<0.10.0)
|
|
28
28
|
Requires-Dist: tomli (==2.0.1)
|
29
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
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"""Helper functions."""
|
2
|
+
|
2
3
|
import itertools
|
3
|
-
import re
|
4
4
|
import urllib
|
5
5
|
from typing import Any
|
6
6
|
from urllib.parse import ParseResult, urlencode, urlparse, parse_qs
|
@@ -14,6 +14,7 @@ from nbforager.types_ import LTInt2, DAny, SeqStr, SStr, TValues, TLists, T2Str,
|
|
14
14
|
|
15
15
|
# =========================== app model id ===========================
|
16
16
|
|
17
|
+
|
17
18
|
def am_to_object_type(app: str, model: str) -> str:
|
18
19
|
"""Convert application and model to object_type.
|
19
20
|
|
@@ -30,6 +31,7 @@ def am_to_object_type(app: str, model: str) -> str:
|
|
30
31
|
model_singular = f"vm{model_singular}"
|
31
32
|
return f"{app}.{model_singular}"
|
32
33
|
|
34
|
+
|
33
35
|
def attr_name(obj: Any) -> str:
|
34
36
|
"""Transform the class name to the attribute name, lowercase without postfix.
|
35
37
|
|
@@ -170,6 +172,7 @@ def path_to_attrs(path: str) -> T2Str:
|
|
170
172
|
model = model_to_attr(model)
|
171
173
|
return app, model
|
172
174
|
|
175
|
+
|
173
176
|
def plural_to_singular(plural: str) -> str:
|
174
177
|
"""Convert a plural model name to a singular model name.
|
175
178
|
|
@@ -189,6 +192,7 @@ def plural_to_singular(plural: str) -> str:
|
|
189
192
|
singular = singular[:-1] # types -> type
|
190
193
|
return singular
|
191
194
|
|
195
|
+
|
192
196
|
def replace_upper(word: str) -> str:
|
193
197
|
"""Replace upper character with underscore and lower.
|
194
198
|
|
@@ -339,7 +343,7 @@ def url_to_object_type(url: str) -> str:
|
|
339
343
|
:example:
|
340
344
|
url_to_object_type("/api/ipam/ip-addresses/1/") -> "ipam.ipaddress"
|
341
345
|
"""
|
342
|
-
app, model,
|
346
|
+
app, model, _ = url_to_ami(url)
|
343
347
|
object_type = am_to_object_type(app, model)
|
344
348
|
return object_type
|
345
349
|
|
@@ -361,7 +365,6 @@ def url_to_ui_url(url: str) -> str:
|
|
361
365
|
return ui_url
|
362
366
|
|
363
367
|
|
364
|
-
|
365
368
|
# ============================== params ==============================
|
366
369
|
|
367
370
|
|
@@ -20,9 +20,21 @@ from nbforager.api.tenancy import TenancyAC
|
|
20
20
|
from nbforager.api.users import UsersAC
|
21
21
|
from nbforager.api.virtualization import VirtualizationAC
|
22
22
|
from nbforager.api.wireless import WirelessAC
|
23
|
-
from nbforager.nb_tree import NbTree
|
24
23
|
from nbforager.parser.nb_parser import NbParser
|
25
|
-
from nbforager.types_ import ODLStr, ODDAny, DAny, LDAny
|
24
|
+
from nbforager.types_ import ODLStr, ODDAny, DAny, LDAny, LStr, LT2Str
|
25
|
+
|
26
|
+
APPS = (
|
27
|
+
"circuits",
|
28
|
+
"core",
|
29
|
+
"dcim",
|
30
|
+
"extras",
|
31
|
+
"ipam",
|
32
|
+
"plugins",
|
33
|
+
"tenancy",
|
34
|
+
"users",
|
35
|
+
"virtualization",
|
36
|
+
"wireless",
|
37
|
+
)
|
26
38
|
|
27
39
|
|
28
40
|
class NbApi:
|
@@ -48,27 +60,27 @@ class NbApi:
|
|
48
60
|
"""
|
49
61
|
|
50
62
|
def __init__(
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
63
|
+
self,
|
64
|
+
host: str,
|
65
|
+
token: str = "",
|
66
|
+
scheme: str = "https",
|
67
|
+
port: int = 0,
|
68
|
+
verify: bool = True,
|
69
|
+
limit: int = 1000,
|
70
|
+
url_length: int = 2047,
|
71
|
+
# Multithreading
|
72
|
+
threads: int = 1,
|
73
|
+
interval: float = 0.0,
|
74
|
+
# Errors processing
|
75
|
+
timeout: int = 60,
|
76
|
+
max_retries: int = 0,
|
77
|
+
sleep: int = 10,
|
78
|
+
strict: bool = False,
|
79
|
+
# Settings
|
80
|
+
extended_get: bool = True,
|
81
|
+
default_get: ODDAny = None,
|
82
|
+
loners: ODLStr = None,
|
83
|
+
**kwargs,
|
72
84
|
):
|
73
85
|
"""Init NbApi.
|
74
86
|
|
@@ -199,6 +211,8 @@ class NbApi:
|
|
199
211
|
loners=connector.loners,
|
200
212
|
)
|
201
213
|
|
214
|
+
# ============================= property =============================
|
215
|
+
|
202
216
|
@property
|
203
217
|
def host(self) -> str:
|
204
218
|
"""Netbox host name."""
|
@@ -222,12 +236,52 @@ class NbApi:
|
|
222
236
|
|
223
237
|
:return: None. Update threads in all connectors.
|
224
238
|
"""
|
225
|
-
|
226
|
-
|
227
|
-
for model in
|
239
|
+
for app in self.apps():
|
240
|
+
models: LStr = [s for s in dir(getattr(self, app)) if s[0].islower()]
|
241
|
+
for model in models:
|
228
242
|
connector = getattr(getattr(self, app), model)
|
229
243
|
setattr(connector, "threads", threads)
|
230
244
|
|
245
|
+
# ============================= methods ==============================
|
246
|
+
|
247
|
+
@staticmethod
|
248
|
+
def apps() -> LStr:
|
249
|
+
"""Get list of application names.
|
250
|
+
|
251
|
+
:return: Applications.
|
252
|
+
:rtype: List[str]
|
253
|
+
"""
|
254
|
+
return list(APPS)
|
255
|
+
|
256
|
+
def app_models(self) -> LT2Str:
|
257
|
+
"""Get list of application model names.
|
258
|
+
|
259
|
+
:return: Application model names.
|
260
|
+
:rtype: List[Tuple[str, str]]
|
261
|
+
"""
|
262
|
+
app_models: LT2Str = []
|
263
|
+
for app in self.apps():
|
264
|
+
models: LStr = [s for s in dir(getattr(self, app)) if s[0].islower()]
|
265
|
+
for model in models:
|
266
|
+
app_models.append((app, model))
|
267
|
+
return app_models
|
268
|
+
|
269
|
+
def app_paths(self) -> LStr:
|
270
|
+
"""Get list of application/model paths.
|
271
|
+
|
272
|
+
:return: Application/model paths.
|
273
|
+
:rtype: List[str]
|
274
|
+
"""
|
275
|
+
app_paths: LStr = []
|
276
|
+
for app in self.apps():
|
277
|
+
models: LStr = [s for s in dir(getattr(self, app)) if s[0].islower()]
|
278
|
+
for model in models:
|
279
|
+
connector = getattr(getattr(self, app), model)
|
280
|
+
path = getattr(connector, "path")
|
281
|
+
path = path.rstrip("/")
|
282
|
+
app_paths.append(path)
|
283
|
+
return app_paths
|
284
|
+
|
231
285
|
def copy(self, **kwargs) -> NbApi:
|
232
286
|
"""Create a duplicate of the object.
|
233
287
|
|
@@ -317,7 +371,7 @@ class NbApi:
|
|
317
371
|
url = str(kwargs.get("url") or "")
|
318
372
|
app, model, _ = h.url_to_ami(url)
|
319
373
|
data: DAny = {k: v for k, v in kwargs.items() if k not in ["url", "id"]}
|
320
|
-
method: Callable = getattr(getattr(getattr(self, app), model), "
|
374
|
+
method: Callable = getattr(getattr(getattr(self, app), model), "create_d")
|
321
375
|
return method(**data)
|
322
376
|
|
323
377
|
def delete(self, **kwargs) -> Response:
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""Tree of Netbox model objects."""
|
2
|
+
|
2
3
|
import logging
|
3
4
|
from copy import deepcopy
|
4
5
|
from typing import Optional
|
@@ -240,9 +241,6 @@ class NbTree(BaseModel):
|
|
240
241
|
ONbTree = Optional[NbTree]
|
241
242
|
|
242
243
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
244
|
def insert_tree(src: NbTree, dst: NbTree) -> None:
|
247
245
|
"""Insert the data from the source NbTree object into the destination NbTree object.
|
248
246
|
|
@@ -313,7 +311,6 @@ def missed_urls(urls: LStr, tree: NbTree) -> LStr:
|
|
313
311
|
return urls_
|
314
312
|
|
315
313
|
|
316
|
-
|
317
314
|
def object_type_to_am(object_type: str, path: bool = False) -> T2Str:
|
318
315
|
"""Convert object_type value (used in extras/changelog) to app/model values.
|
319
316
|
|
@@ -348,9 +345,6 @@ def object_type_to_am(object_type: str, path: bool = False) -> T2Str:
|
|
348
345
|
raise ValueError(f"{object_type=} is not defined.")
|
349
346
|
|
350
347
|
|
351
|
-
|
352
|
-
|
353
|
-
|
354
348
|
# ============================= helpers ==============================
|
355
349
|
|
356
350
|
|
@@ -378,5 +372,3 @@ def _get_child(child: DAny, tree: NbTree) -> DAny:
|
|
378
372
|
return {}
|
379
373
|
|
380
374
|
return {}
|
381
|
-
|
382
|
-
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""Typing."""
|
2
|
+
|
2
3
|
from datetime import datetime
|
3
4
|
from pathlib import Path
|
4
5
|
from typing import Any, Dict, List, Optional, Set, Tuple, Union, Sequence, TypeVar
|
@@ -32,7 +33,6 @@ TValues = (str, int, float)
|
|
32
33
|
Value = Union[str, int, float]
|
33
34
|
|
34
35
|
# 2 level
|
35
|
-
SeqUIntStr = Sequence[IntStr]
|
36
36
|
DDAny = Dict[str, DAny]
|
37
37
|
DDStr = Dict[str, DStr]
|
38
38
|
DLInt = Dict[str, LInt]
|
@@ -46,14 +46,15 @@ LDAny = List[DAny]
|
|
46
46
|
LDStr = List[DStr]
|
47
47
|
LParam = List[Param]
|
48
48
|
LT = List[T]
|
49
|
+
LT2Str = List[T2Str]
|
49
50
|
LT2StrDAny = List[Tuple[str, DAny]]
|
50
|
-
LTup2 = List[T2Str]
|
51
51
|
LValue = List[Value]
|
52
52
|
ODAny = Optional[DAny]
|
53
53
|
OSeqStr = Optional[SeqStr]
|
54
54
|
SParam = Set[Param]
|
55
55
|
SeqDAny = Sequence[DAny]
|
56
56
|
SeqT = Sequence[T]
|
57
|
+
SeqUIntStr = Sequence[IntStr]
|
57
58
|
T3SStr = Tuple[SStr, SStr, SStr]
|
58
59
|
TParam = Tuple[Param, ...]
|
59
60
|
UStr = Union[str, SeqStr]
|
@@ -76,4 +77,3 @@ UParam = Union[LParam, SParam, TParam]
|
|
76
77
|
|
77
78
|
# 5 level
|
78
79
|
OUParam = Optional[UParam]
|
79
|
-
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "nbforager"
|
3
|
-
version = "0.
|
3
|
+
version = "0.5.0"
|
4
4
|
description = "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
|
authors = ["Vladimirs Prusakovs <vladimir.prusakovs@gmail.com>"]
|
6
6
|
readme = "README.rst"
|
@@ -29,17 +29,17 @@ vhelpers = ">=0.3,<1.0.0"
|
|
29
29
|
|
30
30
|
[tool.poetry.group.dev.dependencies]
|
31
31
|
dictdiffer = "0.9.0"
|
32
|
-
mypy = "^1.
|
32
|
+
mypy = "^1.14.1"
|
33
33
|
poetry = "^1.8.3"
|
34
34
|
pygments = "^2.16.1"
|
35
|
-
pylint = "^3.2.
|
36
|
-
pytest = "^8.3.
|
35
|
+
pylint = "^3.2.7"
|
36
|
+
pytest = "^8.3.4"
|
37
37
|
pytest-cov = "^5.0.0"
|
38
38
|
pytest-mock = "^3.14.0"
|
39
39
|
readthedocs-sphinx-search = "^0.3.1"
|
40
40
|
requests-mock = "^1.12.1"
|
41
41
|
restructuredtext-lint = "^1.4.0"
|
42
|
-
ruff = "^0.
|
42
|
+
ruff = "^0.9.9"
|
43
43
|
sphinx = "7.1.2"
|
44
44
|
sphinx-rtd-theme = "^1.3.0"
|
45
45
|
sphinxnotes-strike = "^1.2"
|
@@ -57,7 +57,7 @@ test = ["pytest"]
|
|
57
57
|
|
58
58
|
[tool.poetry.urls]
|
59
59
|
"Bug Tracker" = "https://github.com/vladimirs-git/nbforager/issues"
|
60
|
-
"Download URL" = "https://github.com/vladimirs-git/nbforager/archive/refs/tags/0.
|
60
|
+
"Download URL" = "https://github.com/vladimirs-git/nbforager/archive/refs/tags/0.5.0.tar.gz"
|
61
61
|
|
62
62
|
[tool.pylint]
|
63
63
|
disable = "fixme"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|