unifi-network-maps 1.4.1__py3-none-any.whl → 1.4.3__py3-none-any.whl

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.
@@ -29,6 +29,18 @@ def _coerce_color(value: object, default: str) -> str:
29
29
  return value if isinstance(value, str) else default
30
30
 
31
31
 
32
+ def _coerce_optional_color(value: object, default: str | None) -> str | None:
33
+ return value if isinstance(value, str) else default
34
+
35
+
36
+ def _coerce_optional_int(value: object, default: int | None) -> int | None:
37
+ if isinstance(value, int):
38
+ return value
39
+ if isinstance(value, float):
40
+ return int(value)
41
+ return default
42
+
43
+
32
44
  def _mermaid_theme_from_dict(data: dict, base: MermaidTheme) -> MermaidTheme:
33
45
  nodes = data.get("nodes", {}) if isinstance(data.get("nodes"), dict) else {}
34
46
 
@@ -52,6 +64,13 @@ def _mermaid_theme_from_dict(data: dict, base: MermaidTheme) -> MermaidTheme:
52
64
  standard_link_arrow=_coerce_color(
53
65
  data.get("standard_link_arrow"), base.standard_link_arrow
54
66
  ),
67
+ node_text=_coerce_optional_color(data.get("node_text"), base.node_text),
68
+ edge_label_border=_coerce_optional_color(
69
+ data.get("edge_label_border"), base.edge_label_border
70
+ ),
71
+ edge_label_border_width=_coerce_optional_int(
72
+ data.get("edge_label_border_width"), base.edge_label_border_width
73
+ ),
55
74
  )
56
75
 
57
76
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unifi-network-maps
3
- Version: 1.4.1
3
+ Version: 1.4.3
4
4
  Summary: Dynamic UniFi -> network maps in mermaid or svg
5
5
  Author: Merlijn
6
6
  License-Expression: MIT
@@ -25,31 +25,38 @@ Requires-Dist: python-dotenv==1.2.1
25
25
  Requires-Dist: PyYAML==6.0.3
26
26
  Provides-Extra: dev
27
27
  Requires-Dist: Faker==40.1.0; extra == "dev"
28
+ Requires-Dist: behave==1.3.3; extra == "dev"
28
29
  Requires-Dist: pre-commit==4.5.1; extra == "dev"
29
30
  Requires-Dist: pytest==9.0.2; extra == "dev"
30
31
  Requires-Dist: pytest-cov==7.0.0; extra == "dev"
31
- Requires-Dist: ruff==0.14.10; extra == "dev"
32
+ Requires-Dist: pyright==1.1.408; extra == "dev"
33
+ Requires-Dist: ruff==0.14.11; extra == "dev"
32
34
  Dynamic: license-file
33
35
 
34
36
  # unifi-network-maps
35
37
 
36
- Dynamic UniFi -> Mermaid network maps generated from LLDP topology.
38
+ [![CI](https://github.com/merlijntishauser/unifi-network-maps/actions/workflows/ci.yml/badge.svg)](https://github.com/merlijntishauser/unifi-network-maps/actions/workflows/ci.yml)
39
+ [![CodeQL](https://github.com/merlijntishauser/unifi-network-maps/actions/workflows/codeql.yml/badge.svg)](https://github.com/merlijntishauser/unifi-network-maps/actions/workflows/codeql.yml)
40
+ [![Publish](https://github.com/merlijntishauser/unifi-network-maps/actions/workflows/publish.yml/badge.svg)](https://github.com/merlijntishauser/unifi-network-maps/actions/workflows/publish.yml)
41
+ [![PyPI](https://img.shields.io/pypi/v/unifi-network-maps.svg)](https://pypi.org/project/unifi-network-maps/)
37
42
 
38
- ## Setup
43
+ Dynamic UniFi network maps generated from LLDP topology. Output can be a range of options including Markdown,
44
+ Mermaid, SVG (including an Isometric view), and MkDocs.
39
45
 
40
- - Python >= 3.13
41
- - Virtualenv required
46
+ ## Installation
47
+
48
+ PyPI:
42
49
 
43
50
  ```bash
44
- python -m venv .venv
45
- source .venv/bin/activate
46
- pip install -r requirements-build.txt
47
- pip install -e . -c constraints.txt
51
+ pip install unifi-network-maps
48
52
  ```
49
53
 
50
- Local install (non-editable):
54
+ From source:
51
55
 
52
56
  ```bash
57
+ python -m venv .venv
58
+ source .venv/bin/activate
59
+ pip install -r requirements-build.txt
53
60
  pip install .
54
61
  ```
55
62
 
@@ -63,6 +70,7 @@ export UNIFI_SITE=default
63
70
  export UNIFI_USER=local_admin
64
71
  export UNIFI_PASS=********
65
72
  export UNIFI_VERIFY_SSL=false
73
+ export UNIFI_REQUEST_TIMEOUT_SECONDS=10
66
74
  ```
67
75
 
68
76
  Use a custom env file:
@@ -71,7 +79,7 @@ Use a custom env file:
71
79
  unifi-network-maps --env-file ./site.env --stdout
72
80
  ```
73
81
 
74
- ## Usage
82
+ ## Quickstart
75
83
 
76
84
  Basic map (tree layout by LLDP hops):
77
85
 
@@ -85,6 +93,8 @@ Write Markdown for notes tools:
85
93
  unifi-network-maps --markdown --output ./network.md
86
94
  ```
87
95
 
96
+ ## Usage
97
+
88
98
  Show ports + clients:
89
99
 
90
100
  ```bash
@@ -101,23 +111,29 @@ Isometric SVG output:
101
111
 
102
112
  ```bash
103
113
  unifi-network-maps --format svg-iso --output ./network.svg
114
+ ```
104
115
 
105
- # Single-page MkDocs output (ports included, no clients)
106
- unifi-network-maps --format mkdocs --output ./docs/unifi-network.md
116
+ MkDocs output (ports included, no clients):
107
117
 
108
- # MkDocs output (map + legend + gateway/switch port tables)
118
+ ```bash
109
119
  unifi-network-maps --format mkdocs --output ./docs/unifi-network.md
120
+ ```
110
121
 
111
- # Include wired clients in the port tables
122
+ MkDocs output with clients:
123
+
124
+ ```bash
112
125
  unifi-network-maps --format mkdocs --include-clients --output ./docs/unifi-network.md
113
126
  ```
114
127
 
115
- SVG size overrides:
128
+ MkDocs output with dual Mermaid blocks for Material theme switching:
116
129
 
117
130
  ```bash
118
- unifi-network-maps --format svg --svg-width 1400 --svg-height 900 --output ./network.svg
131
+ unifi-network-maps --format mkdocs --mkdocs-dual-theme --output ./docs/unifi-network.md
132
+ ```
119
133
 
120
- # LLDP tables for troubleshooting
134
+ LLDP tables for troubleshooting:
135
+
136
+ ```bash
121
137
  unifi-network-maps --format lldp-md --output ./lldp.md
122
138
  ```
123
139
 
@@ -142,9 +158,7 @@ unifi-network-maps --generate-mock examples/mock_data.json --mock-seed 1337
142
158
  Generate the isometric SVG:
143
159
 
144
160
  ```bash
145
- unifi-network-maps --mock-data examples/mock_data.json \
146
- --include-ports --include-clients --format svg-iso \
147
- --output examples/output/network_ports_clients_iso.svg
161
+ unifi-network-maps --mock-data examples/mock_data.json --include-ports --include-clients --format svg-iso --output examples/output/network_ports_clients_iso.svg
148
162
  ```
149
163
 
150
164
  ![Isometric network example](examples/output/network_ports_clients_iso.svg)
@@ -170,50 +184,14 @@ graph TB
170
184
  linkStyle 1 stroke:#1e88e5,stroke-width:2px,arrowhead:none;
171
185
  ```
172
186
 
173
- ## Local install check
174
-
175
- ```bash
176
- pip install .
177
- ```
178
-
179
- ## Dev
180
-
181
- ```bash
182
- pip install -r requirements-dev.txt -c constraints.txt
183
- ```
184
-
185
- ## Release
186
-
187
- Build and upload to PyPI:
188
-
189
- ```bash
190
- python -m pip install build twine
191
- python -m build
192
- twine upload dist/*
193
- ```
194
-
195
- Tagging is recommended before release:
196
-
197
- ```bash
198
- git tag -a vX.Y.Z -m "vX.Y.Z"
199
- git push origin vX.Y.Z
200
- ```
201
-
202
- See `LICENSES.md` for third-party license info.
203
-
204
- ## Installation
205
-
206
- PyPI: https://pypi.org/project/unifi-network-maps/
187
+ ## MkDocs Material example
207
188
 
208
- ```bash
209
- pip install unifi-network-maps
210
- ```
189
+ See `examples/mkdocs/` for a ready-to-use setup that renders Mermaid diagrams
190
+ with Material for MkDocs, including a sample `unifi-network` page and legend.
211
191
 
212
- Then run:
192
+ The built-in themes live at `src/unifi_network_maps/assets/themes/default.yaml` and
193
+ `src/unifi_network_maps/assets/themes/dark.yaml`.
213
194
 
214
- ```bash
215
- unifi-network-maps --help
216
- ```
217
195
 
218
196
  ## Options
219
197
 
@@ -223,6 +201,7 @@ Source:
223
201
  - `--site`: override `UNIFI_SITE`.
224
202
  - `--env-file`: load environment variables from a specific `.env` file.
225
203
  - `--mock-data`: use mock data JSON instead of the UniFi API.
204
+
226
205
  Mock:
227
206
  - `--generate-mock`: write mock data JSON and exit.
228
207
  - `--mock-seed`: seed for deterministic mock generation.
@@ -236,6 +215,7 @@ Functional:
236
215
  - `--include-clients`: add active wired clients as leaf nodes.
237
216
  - `--client-scope wired|wireless|all`: which client types to include (default wired).
238
217
  - `--only-unifi`: only include neighbors that are UniFi devices.
218
+ - `--no-cache`: disable UniFi API cache reads and writes.
239
219
 
240
220
  Mermaid:
241
221
  - `--direction LR|TB`: diagram direction for Mermaid (default TB).
@@ -253,25 +233,13 @@ Output:
253
233
  - `--stdout`: write output to stdout.
254
234
  - `--markdown`: wrap Mermaid output in a code fence.
255
235
  - `--mkdocs-sidebar-legend`: write assets to place the compact legend in the MkDocs right sidebar.
236
+ - `--mkdocs-dual-theme`: render light/dark Mermaid blocks for Material theme switching.
237
+ - `--mkdocs-timestamp-zone`: timezone for mkdocs timestamp (`Europe/Amsterdam` default; use `off` to disable).
256
238
 
257
239
  Debug:
258
240
  - `--debug-dump`: dump gateway + sample devices to stderr for debugging.
259
241
  - `--debug-sample N`: number of non-gateway devices in debug dump (default 2).
260
242
 
261
- ## Notes
262
-
263
- - Default output is top-to-bottom (TB) and rendered as a hop-based tree from the gateway(s).
264
- - Nodes are color-coded by type (gateway/switch/AP/client) with a sensible default palette.
265
- - PoE links are highlighted in blue and annotated with a power icon when detected from `port_table`.
266
- - Wireless client links render as dashed lines to indicate the last-known upstream.
267
- - SVG output uses vendored device glyphs from `src/unifi_network_maps/assets/icons`.
268
- - Isometric SVG output uses MIT-licensed icons from `markmanx/isopacks`.
269
- - SVG port labels render inside child nodes for readability.
270
-
271
- ## AI Disclosure
272
-
273
- This project used OpenAI Codex as a coding assistant for portions of the implementation and documentation.
274
-
275
243
  ## Theme file
276
244
 
277
245
  Example theme YAML (override only the values you want):
@@ -297,10 +265,17 @@ svg:
297
265
  to: "#b6dcff"
298
266
  ```
299
267
 
300
- ## MkDocs Material example
268
+ ## Notes
301
269
 
302
- See `examples/mkdocs/` for a ready-to-use setup that renders Mermaid diagrams
303
- with Material for MkDocs, including a sample `unifi-network` page and legend.
270
+ - Default output is top-to-bottom (TB) and rendered as a hop-based tree from the gateway(s).
271
+ - Nodes are color-coded by type (gateway/switch/AP/client) with a sensible default palette.
272
+ - PoE links are highlighted in blue and annotated with a power icon when detected from `port_table`.
273
+ - Wireless client links render as dashed lines to indicate the last-known upstream.
274
+ - SVG output uses vendored device glyphs from `src/unifi_network_maps/assets/icons`.
275
+ - Isometric SVG output uses MIT-licensed icons from `markmanx/isopacks`.
276
+ - SVG port labels render inside child nodes for readability.
304
277
 
305
- The built-in themes live at `src/unifi_network_maps/assets/themes/default.yaml` and
306
- `src/unifi_network_maps/assets/themes/dark.yaml`.
278
+
279
+ ## AI Disclosure
280
+
281
+ This project used OpenAI Codex as a coding assistant for portions of the implementation and documentation.
@@ -1,8 +1,8 @@
1
- unifi_network_maps/__init__.py,sha256=BqOI5y46o1G1RWC9bF1DPL-YM68lGYPmZt1pn6FZFZs,22
1
+ unifi_network_maps/__init__.py,sha256=rxvQUWSe6nvSADkIyuziyi8Irk70s2DZSxOB9c8cpAQ,22
2
2
  unifi_network_maps/__main__.py,sha256=XsOjaqslAVgyVlOTokjVddZ2iT8apZXpJ_OB-9WEEe4,179
3
3
  unifi_network_maps/adapters/__init__.py,sha256=nzx1KsiYalL_YuXKE6acW8Dj5flmMg0-i4gyYO0gV54,22
4
4
  unifi_network_maps/adapters/config.py,sha256=Bx9JDZxxY7Gjxyb8FDT0dxiKfgXt_TmzTDbgvpwB53s,1548
5
- unifi_network_maps/adapters/unifi.py,sha256=H-yANmXaXoQjItVKZaAP44ATREZ2LtPrz_M48wAcTqI,7020
5
+ unifi_network_maps/adapters/unifi.py,sha256=olrs-K7EWK7Uhib8pjtPnkZg3LhnnSz-lcGuHG8RsOI,15140
6
6
  unifi_network_maps/assets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  unifi_network_maps/assets/icons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  unifi_network_maps/assets/icons/access-point.svg,sha256=RJOgO2s9Ino5lWRrh4V7q8Jdwffros5bQq3UeDuQYF4,742
@@ -48,32 +48,32 @@ unifi_network_maps/assets/icons/isometric/truck-2.svg,sha256=I7MFGbXW2fmr9WdD29N
48
48
  unifi_network_maps/assets/icons/isometric/truck.svg,sha256=BrpBr9Qf8hplQIrBpfhN2USxUlPvGCKahlV5e-G13r0,7195
49
49
  unifi_network_maps/assets/icons/isometric/user.svg,sha256=bYpr0t8rETJ1M7RDTWaNkK-nfF3kq9eMxmxYCthNmE0,23026
50
50
  unifi_network_maps/assets/icons/isometric/vm.svg,sha256=in6x9cdS6JgQVJl0KAbA79rap4X140dfIBCuxmgQI7s,3694
51
- unifi_network_maps/assets/themes/dark.yaml,sha256=F86A25kd0VSCCpN4jcMZxPWWtqNC5ftJHUEvUvESTQQ,849
51
+ unifi_network_maps/assets/themes/dark.yaml,sha256=SxK6QnnvrljQxg82NFbU052vlqTVTVp9jiYGu9b0bxI,932
52
52
  unifi_network_maps/assets/themes/default.yaml,sha256=F2Jj18NmdaJ_zyERvGAn8NEWBwapjtozrtZUxayd5AU,849
53
53
  unifi_network_maps/cli/__init__.py,sha256=2FdmLMpYFh_7P0ew2LnieLANf6ni43Ht9FKzYUDiNis,770
54
54
  unifi_network_maps/cli/__main__.py,sha256=nK_jh78VW3h3DRvSpjzpcf64zkCqniP2k82xUR9Hw2I,147
55
- unifi_network_maps/cli/main.py,sha256=xAPFmzxjNbpwrR_lyLv66m0EqrUy7KFYZ20Dt8Q2NhE,19896
55
+ unifi_network_maps/cli/main.py,sha256=y053K-EbnAvxZ073-AEHhAGYWSvc4-UcoDTKpaBsvZY,27319
56
56
  unifi_network_maps/io/__init__.py,sha256=nzx1KsiYalL_YuXKE6acW8Dj5flmMg0-i4gyYO0gV54,22
57
- unifi_network_maps/io/debug.py,sha256=wTSGMARfVh_U2R5vD-n9DjwQHdhMpypmVvoXRUdy68k,1461
58
- unifi_network_maps/io/export.py,sha256=v3x6mSXmbO3dWtNQv4nGNGVqMCIE0mvTBGTKsNJBg6o,352
57
+ unifi_network_maps/io/debug.py,sha256=eUVs6GLfs6VqI6ma8ra7NLhC3q4ek2K8OSRLnpQDF9s,1745
58
+ unifi_network_maps/io/export.py,sha256=2vURunQDja-_fKKMb-gQG-n34aeM8GFprNJqcGaP4qg,843
59
59
  unifi_network_maps/io/mock_data.py,sha256=uiQ8Ta8oxs5D1MUA1ONWmp09sxH0-FNlz3SJBXMeezo,714
60
60
  unifi_network_maps/io/mock_generate.py,sha256=xKaPRj-STtI154SMTPP9iCl0s7AVZekX4uPb-bMxRvA,8508
61
61
  unifi_network_maps/model/__init__.py,sha256=nzx1KsiYalL_YuXKE6acW8Dj5flmMg0-i4gyYO0gV54,22
62
62
  unifi_network_maps/model/labels.py,sha256=m_k8mbzWtOSDOjjHhLUqwIw93pg98HAtGtHkiERXmek,1135
63
63
  unifi_network_maps/model/lldp.py,sha256=SrPW5XC2lfJgaGeVx-KnSFNltyok7gIWWQNg1SkOaj4,3300
64
64
  unifi_network_maps/model/ports.py,sha256=o3NBlXcC5VV5iPWJsO4Ll1mRKJZC0f8zTHdlkkE34GU,609
65
- unifi_network_maps/model/topology.py,sha256=TxHWR4JmAcvD9yOaiq87qwnTukstCaAxziJMyOmtnak,25424
65
+ unifi_network_maps/model/topology.py,sha256=JfpY6Pam_pgqnnmsBmzy3oDv4OCi4Ezc8msxvp5Z5NQ,26784
66
66
  unifi_network_maps/render/__init__.py,sha256=nzx1KsiYalL_YuXKE6acW8Dj5flmMg0-i4gyYO0gV54,22
67
- unifi_network_maps/render/device_ports_md.py,sha256=JP2Sjvq-O9h20RPygr7WEMp2R1XhLe_iw3gfgoD-SDM,15151
68
- unifi_network_maps/render/lldp_md.py,sha256=0CwFz1KPeU8gpu_wslPsvR3j6yunC4XX1uRETrctveI,9595
69
- unifi_network_maps/render/mermaid.py,sha256=zXSPkjHxFuQk4s5ENtqSobiXiMur4Tiq1aYVa7aUrhk,8158
70
- unifi_network_maps/render/mermaid_theme.py,sha256=QReSBFoYSIz7vgAwyHx-9f4ucbSgMTGvo1Ffa2ZfzDQ,1527
71
- unifi_network_maps/render/svg.py,sha256=9TIuo63EJCoHO6Mwm26dLLcfsvTpOZaZkUegDIxv6ts,33018
67
+ unifi_network_maps/render/device_ports_md.py,sha256=QoRiuP9l2CH8BYRHXRaWM5wyucAURz-zByzwMetnND4,15473
68
+ unifi_network_maps/render/lldp_md.py,sha256=Eg5c5SWEwTfEn6AN0fOfD3f41GlsqwZQRO8AzIXFQf4,10753
69
+ unifi_network_maps/render/mermaid.py,sha256=GVn7VN0xdmweDnjk-0Q8nuivqOZ3YFBQ_iTonNydy28,9675
70
+ unifi_network_maps/render/mermaid_theme.py,sha256=7nqLlvhaUA4z0YOs0ByEx_yHWcQD_hJJjhDtRcbSpg4,1781
71
+ unifi_network_maps/render/svg.py,sha256=RHmSmlKxrS8m3-zYsTJu-GZugsZt8X8TDsPpK7DA6tg,38807
72
72
  unifi_network_maps/render/svg_theme.py,sha256=Si1ArM3v_-wAvHZyLFPiOZ0ohQRd6ezIckwC3_b-WIw,2684
73
- unifi_network_maps/render/theme.py,sha256=-cPvj9dfmOpBD3Ohpye_yTBWxXtsE0-g73mekqoh5kA,3606
74
- unifi_network_maps-1.4.1.dist-info/licenses/LICENSE,sha256=mYo1siIIfIwyfdOuK2-Zt0ij2xBTii2hnpeTu79nD80,1074
75
- unifi_network_maps-1.4.1.dist-info/METADATA,sha256=z4KBMpd033ok2Thpcfvik6qi2PMCOR2ctQBu6E791PY,9035
76
- unifi_network_maps-1.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
77
- unifi_network_maps-1.4.1.dist-info/entry_points.txt,sha256=cdJ7jsBgNgHxSflYUOqgz5BbvuM0Nnh-x8_Hbyh_LFg,67
78
- unifi_network_maps-1.4.1.dist-info/top_level.txt,sha256=G0rUX1PNfVCn1u-KtB6QjFQHopCOVLnPMczvPOoraHg,19
79
- unifi_network_maps-1.4.1.dist-info/RECORD,,
73
+ unifi_network_maps/render/theme.py,sha256=vKYdPhcGEOV1o_irwqzJlIXPgRvZqQEzYYV2_TxZn4E,4301
74
+ unifi_network_maps-1.4.3.dist-info/licenses/LICENSE,sha256=mYo1siIIfIwyfdOuK2-Zt0ij2xBTii2hnpeTu79nD80,1074
75
+ unifi_network_maps-1.4.3.dist-info/METADATA,sha256=DbY9aCDyMocST84Fsr9Ukx2uSKxta0f3SM4TVHrrKbM,9529
76
+ unifi_network_maps-1.4.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
77
+ unifi_network_maps-1.4.3.dist-info/entry_points.txt,sha256=cdJ7jsBgNgHxSflYUOqgz5BbvuM0Nnh-x8_Hbyh_LFg,67
78
+ unifi_network_maps-1.4.3.dist-info/top_level.txt,sha256=G0rUX1PNfVCn1u-KtB6QjFQHopCOVLnPMczvPOoraHg,19
79
+ unifi_network_maps-1.4.3.dist-info/RECORD,,