unifi-network-maps 1.4.11__tar.gz → 1.4.12__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.
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/CHANGELOG.md +10 -2
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/PKG-INFO +2 -2
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/README.md +1 -1
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/pyproject.toml +1 -1
- unifi_network_maps-1.4.12/src/unifi_network_maps/__init__.py +1 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/cli/render.py +19 -3
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/cli/runtime.py +7 -1
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/topology.py +88 -4
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/lldp_md.py +100 -4
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps.egg-info/PKG-INFO +2 -2
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_clients.py +65 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_lldp_md.py +55 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_topology.py +32 -0
- unifi_network_maps-1.4.11/src/unifi_network_maps/__init__.py +0 -1
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/CONTRIBUTING.md +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/LICENSE +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/LICENSES.md +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/MANIFEST.in +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/RELEASING.md +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/SECURITY.md +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/setup.cfg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/__main__.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/adapters/__init__.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/adapters/config.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/adapters/unifi.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/__init__.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/__init__.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/access-point.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/ISOPACKS_LICENSE +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/block.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/cache.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/cardterminal.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/cloud.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/cronjob.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/cube.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/desktop.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/diamond.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/dns.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/document.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/firewall.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/function-module.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/image.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/laptop.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/loadbalancer.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/lock.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/mail.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/mailmultiple.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/mobiledevice.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/office.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/package-module.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/paymentcard.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/plane.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/printer.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/pyramid.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/queue.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/router.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/server.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/speech.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/sphere.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/storage.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/switch-module.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/tower.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/truck-2.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/truck.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/user.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/isometric/vm.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/laptop.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/router-network.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/server-network.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/icons/server.svg +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/themes/dark.yaml +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/themes/default.yaml +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/cli/__init__.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/cli/__main__.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/cli/args.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/cli/main.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/io/__init__.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/io/debug.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/io/export.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/io/mkdocs_assets.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/io/mock_data.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/io/mock_generate.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/__init__.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/labels.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/lldp.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/mock.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/ports.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/__init__.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/device_ports_md.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/legend.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/markdown_tables.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/mermaid.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/mermaid_theme.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/mkdocs.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/svg.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/svg_theme.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templates/device_port_block.md.j2 +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templates/legend_compact.html.j2 +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templates/lldp_device_section.md.j2 +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templates/markdown_section.md.j2 +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templates/mermaid_legend.mmd.j2 +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templates/mkdocs_document.md.j2 +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templates/mkdocs_dual_theme_style.html.j2 +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templates/mkdocs_html_block.html.j2 +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templates/mkdocs_legend.css.j2 +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templates/mkdocs_legend.js.j2 +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templates/mkdocs_mermaid_block.md.j2 +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templating.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/theme.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps.egg-info/SOURCES.txt +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps.egg-info/dependency_links.txt +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps.egg-info/entry_points.txt +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps.egg-info/requires.txt +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps.egg-info/top_level.txt +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_cli.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_config.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_contract_unifi.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_contract_unifi_live.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_debug.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_device_ports_md.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_export.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_groups.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_labels.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_lldp.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_mermaid.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_mock_generate.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_svg.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_svg_iso.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_theme.py +0 -0
- {unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/tests/test_unifi.py +0 -0
|
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.4.12] - 2026-01-21
|
|
9
|
+
### Added
|
|
10
|
+
- Filter UniFi clients with --only-unifi, and not only neighbors
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- inconsistencies in --only-unifi
|
|
14
|
+
|
|
8
15
|
## [1.4.11] - 2026-01-19
|
|
9
16
|
### Added
|
|
10
17
|
- Add data-edge-left/right attributes to SVG paths
|
|
@@ -176,8 +183,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
176
183
|
- Introduced SVG renderer and tree layout fixes.
|
|
177
184
|
- Increased test coverage and added coverage tooling.
|
|
178
185
|
|
|
179
|
-
[Unreleased]: https://github.com/merlijntishauser/unifi-network-maps/compare/v1.4.
|
|
180
|
-
[1.4.
|
|
186
|
+
[Unreleased]: https://github.com/merlijntishauser/unifi-network-maps/compare/v1.4.12...HEAD
|
|
187
|
+
[1.4.12]:https://github.com/merlijntishauser/unifi-network-maps/compare/v1.4.11...v1.4.12
|
|
188
|
+
[1.4.11]:https://github.com/merlijntishauser/unifi-network-maps/compare/v1.4.10...v1.4.11
|
|
181
189
|
[1.4.10]:https://github.com/merlijntishauser/unifi-network-maps/compare/v1.4.9...v1.4.10
|
|
182
190
|
[1.4.9]: https://github.com/merlijntishauser/unifi-network-maps/compare/v1.4.8...v1.4.9
|
|
183
191
|
[1.4.8]: https://github.com/merlijntishauser/unifi-network-maps/compare/v1.4.7...v1.4.8
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unifi-network-maps
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.12
|
|
4
4
|
Summary: Dynamic UniFi -> network maps in mermaid or svg
|
|
5
5
|
Author: Merlijn
|
|
6
6
|
License-Expression: MIT
|
|
@@ -223,7 +223,7 @@ Functional:
|
|
|
223
223
|
- `--include-ports`: show port labels (Mermaid shows both ends; SVG shows compact labels).
|
|
224
224
|
- `--include-clients`: add active wired clients as leaf nodes.
|
|
225
225
|
- `--client-scope wired|wireless|all`: which client types to include (default wired).
|
|
226
|
-
- `--only-unifi`: only include neighbors that are UniFi devices.
|
|
226
|
+
- `--only-unifi`: only include neighbors that are UniFi devices; when clients are included, filters to UniFi-managed clients (by explicit UniFi flags or vendor/OUI).
|
|
227
227
|
- `--no-cache`: disable UniFi API cache reads and writes.
|
|
228
228
|
|
|
229
229
|
Mermaid:
|
|
@@ -186,7 +186,7 @@ Functional:
|
|
|
186
186
|
- `--include-ports`: show port labels (Mermaid shows both ends; SVG shows compact labels).
|
|
187
187
|
- `--include-clients`: add active wired clients as leaf nodes.
|
|
188
188
|
- `--client-scope wired|wireless|all`: which client types to include (default wired).
|
|
189
|
-
- `--only-unifi`: only include neighbors that are UniFi devices.
|
|
189
|
+
- `--only-unifi`: only include neighbors that are UniFi devices; when clients are included, filters to UniFi-managed clients (by explicit UniFi flags or vendor/OUI).
|
|
190
190
|
- `--no-cache`: disable UniFi API cache reads and writes.
|
|
191
191
|
|
|
192
192
|
Mermaid:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.4.12"
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/cli/render.py
RENAMED
|
@@ -62,7 +62,12 @@ def render_mermaid_output(
|
|
|
62
62
|
direction=args.direction,
|
|
63
63
|
groups=groups,
|
|
64
64
|
group_order=group_order,
|
|
65
|
-
node_types=build_node_type_map(
|
|
65
|
+
node_types=build_node_type_map(
|
|
66
|
+
devices,
|
|
67
|
+
clients,
|
|
68
|
+
client_mode=args.client_scope,
|
|
69
|
+
only_unifi=args.only_unifi,
|
|
70
|
+
),
|
|
66
71
|
theme=mermaid_theme,
|
|
67
72
|
)
|
|
68
73
|
if args.markdown:
|
|
@@ -97,13 +102,23 @@ def render_svg_output(
|
|
|
97
102
|
|
|
98
103
|
return render_svg_isometric(
|
|
99
104
|
edges,
|
|
100
|
-
node_types=build_node_type_map(
|
|
105
|
+
node_types=build_node_type_map(
|
|
106
|
+
devices,
|
|
107
|
+
clients,
|
|
108
|
+
client_mode=args.client_scope,
|
|
109
|
+
only_unifi=args.only_unifi,
|
|
110
|
+
),
|
|
101
111
|
options=options,
|
|
102
112
|
theme=svg_theme,
|
|
103
113
|
)
|
|
104
114
|
return render_svg(
|
|
105
115
|
edges,
|
|
106
|
-
node_types=build_node_type_map(
|
|
116
|
+
node_types=build_node_type_map(
|
|
117
|
+
devices,
|
|
118
|
+
clients,
|
|
119
|
+
client_mode=args.client_scope,
|
|
120
|
+
only_unifi=args.only_unifi,
|
|
121
|
+
),
|
|
107
122
|
options=options,
|
|
108
123
|
theme=svg_theme,
|
|
109
124
|
)
|
|
@@ -190,6 +205,7 @@ def render_lldp_format(
|
|
|
190
205
|
include_ports=args.include_ports,
|
|
191
206
|
show_clients=args.include_clients,
|
|
192
207
|
client_mode=args.client_scope,
|
|
208
|
+
only_unifi=args.only_unifi,
|
|
193
209
|
)
|
|
194
210
|
write_output(content, output_path=args.output, stdout=args.stdout)
|
|
195
211
|
return 0
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/cli/runtime.py
RENAMED
|
@@ -95,6 +95,7 @@ def build_edges_with_clients(
|
|
|
95
95
|
device_index,
|
|
96
96
|
include_ports=args.include_ports,
|
|
97
97
|
client_mode=args.client_scope,
|
|
98
|
+
only_unifi=args.only_unifi,
|
|
98
99
|
)
|
|
99
100
|
return edges, clients
|
|
100
101
|
|
|
@@ -153,5 +154,10 @@ def resolve_mkdocs_client_ports(
|
|
|
153
154
|
clients = list(fetch_clients(config, site=site))
|
|
154
155
|
else:
|
|
155
156
|
clients = mock_clients
|
|
156
|
-
client_ports = build_client_port_map(
|
|
157
|
+
client_ports = build_client_port_map(
|
|
158
|
+
devices,
|
|
159
|
+
clients,
|
|
160
|
+
client_mode=args.client_scope,
|
|
161
|
+
only_unifi=args.only_unifi,
|
|
162
|
+
)
|
|
157
163
|
return client_ports, None
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/topology.py
RENAMED
|
@@ -460,7 +460,13 @@ def _client_field(client: object, name: str) -> object | None:
|
|
|
460
460
|
|
|
461
461
|
|
|
462
462
|
def _client_display_name(client: object) -> str | None:
|
|
463
|
-
|
|
463
|
+
raw_name = _client_field(client, "name")
|
|
464
|
+
if isinstance(raw_name, str) and raw_name.strip():
|
|
465
|
+
return raw_name.strip()
|
|
466
|
+
preferred = _client_ucore_display_name(client)
|
|
467
|
+
if preferred:
|
|
468
|
+
return preferred
|
|
469
|
+
for key in ("hostname", "mac"):
|
|
464
470
|
value = _client_field(client, key)
|
|
465
471
|
if isinstance(value, str) and value.strip():
|
|
466
472
|
return value.strip()
|
|
@@ -514,6 +520,73 @@ def _client_is_wired(client: object) -> bool:
|
|
|
514
520
|
return bool(_client_field(client, "is_wired"))
|
|
515
521
|
|
|
516
522
|
|
|
523
|
+
def _client_unifi_flag(client: object) -> bool | None:
|
|
524
|
+
for key in ("is_unifi", "is_unifi_device", "is_ubnt", "is_uap", "is_managed"):
|
|
525
|
+
value = _client_field(client, key)
|
|
526
|
+
if isinstance(value, bool):
|
|
527
|
+
return value
|
|
528
|
+
if isinstance(value, int):
|
|
529
|
+
return value != 0
|
|
530
|
+
return None
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
def _client_vendor(client: object) -> str | None:
|
|
534
|
+
for key in ("oui", "vendor", "vendor_name", "manufacturer", "manufacturer_name"):
|
|
535
|
+
value = _client_field(client, key)
|
|
536
|
+
if isinstance(value, str) and value.strip():
|
|
537
|
+
return value.strip()
|
|
538
|
+
return None
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
def _client_ucore_info(client: object) -> dict[str, object] | None:
|
|
542
|
+
info = _client_field(client, "unifi_device_info_from_ucore")
|
|
543
|
+
if isinstance(info, dict):
|
|
544
|
+
return info
|
|
545
|
+
return None
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
def _client_ucore_display_name(client: object) -> str | None:
|
|
549
|
+
ucore = _client_ucore_info(client)
|
|
550
|
+
if not ucore:
|
|
551
|
+
return None
|
|
552
|
+
for key in ("name", "computed_model", "product_model", "product_shortname"):
|
|
553
|
+
value = ucore.get(key)
|
|
554
|
+
if isinstance(value, str) and value.strip():
|
|
555
|
+
return value.strip()
|
|
556
|
+
return None
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
def _client_hostname_source(client: object) -> str | None:
|
|
560
|
+
value = _client_field(client, "hostname_source")
|
|
561
|
+
if isinstance(value, str) and value.strip():
|
|
562
|
+
return value.strip()
|
|
563
|
+
return None
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
def _client_is_unifi(client: object) -> bool:
|
|
567
|
+
flag = _client_unifi_flag(client)
|
|
568
|
+
if flag is not None:
|
|
569
|
+
return flag
|
|
570
|
+
ucore = _client_ucore_info(client)
|
|
571
|
+
if ucore:
|
|
572
|
+
managed = ucore.get("managed")
|
|
573
|
+
if isinstance(managed, bool) and managed:
|
|
574
|
+
return True
|
|
575
|
+
if isinstance(ucore.get("product_line"), str) and ucore.get("product_line"):
|
|
576
|
+
return True
|
|
577
|
+
if isinstance(ucore.get("product_shortname"), str) and ucore.get("product_shortname"):
|
|
578
|
+
return True
|
|
579
|
+
for key in ("name", "computed_model", "product_model"):
|
|
580
|
+
value = ucore.get(key)
|
|
581
|
+
if isinstance(value, str) and value.strip():
|
|
582
|
+
return True
|
|
583
|
+
vendor = _client_vendor(client)
|
|
584
|
+
if not vendor:
|
|
585
|
+
return False
|
|
586
|
+
normalized = vendor.lower()
|
|
587
|
+
return "ubiquiti" in normalized or "unifi" in normalized
|
|
588
|
+
|
|
589
|
+
|
|
517
590
|
def _client_channel(client: object) -> int | None:
|
|
518
591
|
for key in ("channel", "radio_channel", "wifi_channel"):
|
|
519
592
|
value = _client_field(client, key)
|
|
@@ -533,17 +606,26 @@ def _client_matches_mode(client: object, mode: str) -> bool:
|
|
|
533
606
|
return wired
|
|
534
607
|
|
|
535
608
|
|
|
609
|
+
def _client_matches_filters(client: object, *, client_mode: str, only_unifi: bool) -> bool:
|
|
610
|
+
if not _client_matches_mode(client, client_mode):
|
|
611
|
+
return False
|
|
612
|
+
if only_unifi and not _client_is_unifi(client):
|
|
613
|
+
return False
|
|
614
|
+
return True
|
|
615
|
+
|
|
616
|
+
|
|
536
617
|
def build_client_edges(
|
|
537
618
|
clients: Iterable[object],
|
|
538
619
|
device_index: dict[str, str],
|
|
539
620
|
*,
|
|
540
621
|
include_ports: bool = False,
|
|
541
622
|
client_mode: str = "wired",
|
|
623
|
+
only_unifi: bool = False,
|
|
542
624
|
) -> list[Edge]:
|
|
543
625
|
edges: list[Edge] = []
|
|
544
626
|
seen: set[tuple[str, str]] = set()
|
|
545
627
|
for client in clients:
|
|
546
|
-
if not
|
|
628
|
+
if not _client_matches_filters(client, client_mode=client_mode, only_unifi=only_unifi):
|
|
547
629
|
continue
|
|
548
630
|
name = _client_display_name(client)
|
|
549
631
|
uplink_mac = _client_uplink_mac(client)
|
|
@@ -580,13 +662,14 @@ def build_node_type_map(
|
|
|
580
662
|
clients: Iterable[object] | None = None,
|
|
581
663
|
*,
|
|
582
664
|
client_mode: str = "wired",
|
|
665
|
+
only_unifi: bool = False,
|
|
583
666
|
) -> dict[str, str]:
|
|
584
667
|
node_types: dict[str, str] = {}
|
|
585
668
|
for device in devices:
|
|
586
669
|
node_types[device.name] = classify_device_type(device)
|
|
587
670
|
if clients:
|
|
588
671
|
for client in clients:
|
|
589
|
-
if not
|
|
672
|
+
if not _client_matches_filters(client, client_mode=client_mode, only_unifi=only_unifi):
|
|
590
673
|
continue
|
|
591
674
|
name = _client_display_name(client)
|
|
592
675
|
if name:
|
|
@@ -683,11 +766,12 @@ def build_client_port_map(
|
|
|
683
766
|
clients: Iterable[object],
|
|
684
767
|
*,
|
|
685
768
|
client_mode: str,
|
|
769
|
+
only_unifi: bool = False,
|
|
686
770
|
) -> ClientPortMap:
|
|
687
771
|
device_index = build_device_index(devices)
|
|
688
772
|
port_map: ClientPortMap = {}
|
|
689
773
|
for client in clients:
|
|
690
|
-
if not
|
|
774
|
+
if not _client_matches_filters(client, client_mode=client_mode, only_unifi=only_unifi):
|
|
691
775
|
continue
|
|
692
776
|
name = _client_display_name(client)
|
|
693
777
|
uplink_mac = _client_uplink_mac(client)
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/lldp_md.py
RENAMED
|
@@ -23,7 +23,13 @@ def _client_field(client: object, name: str) -> object | None:
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def _client_display_name(client: object) -> str | None:
|
|
26
|
-
|
|
26
|
+
raw_name = _client_field(client, "name")
|
|
27
|
+
if isinstance(raw_name, str) and raw_name.strip():
|
|
28
|
+
return raw_name.strip()
|
|
29
|
+
preferred = _client_ucore_display_name(client)
|
|
30
|
+
if preferred:
|
|
31
|
+
return preferred
|
|
32
|
+
for key in ("hostname", "mac"):
|
|
27
33
|
value = _client_field(client, key)
|
|
28
34
|
if isinstance(value, str) and value.strip():
|
|
29
35
|
return value.strip()
|
|
@@ -77,6 +83,73 @@ def _client_is_wired(client: object) -> bool:
|
|
|
77
83
|
return bool(_client_field(client, "is_wired"))
|
|
78
84
|
|
|
79
85
|
|
|
86
|
+
def _client_unifi_flag(client: object) -> bool | None:
|
|
87
|
+
for key in ("is_unifi", "is_unifi_device", "is_ubnt", "is_uap", "is_managed"):
|
|
88
|
+
value = _client_field(client, key)
|
|
89
|
+
if isinstance(value, bool):
|
|
90
|
+
return value
|
|
91
|
+
if isinstance(value, int):
|
|
92
|
+
return value != 0
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _client_vendor(client: object) -> str | None:
|
|
97
|
+
for key in ("oui", "vendor", "vendor_name", "manufacturer", "manufacturer_name"):
|
|
98
|
+
value = _client_field(client, key)
|
|
99
|
+
if isinstance(value, str) and value.strip():
|
|
100
|
+
return value.strip()
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _client_ucore_info(client: object) -> dict[str, object] | None:
|
|
105
|
+
info = _client_field(client, "unifi_device_info_from_ucore")
|
|
106
|
+
if isinstance(info, dict):
|
|
107
|
+
return info
|
|
108
|
+
return None
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _client_ucore_display_name(client: object) -> str | None:
|
|
112
|
+
ucore = _client_ucore_info(client)
|
|
113
|
+
if not ucore:
|
|
114
|
+
return None
|
|
115
|
+
for key in ("name", "computed_model", "product_model", "product_shortname"):
|
|
116
|
+
value = ucore.get(key)
|
|
117
|
+
if isinstance(value, str) and value.strip():
|
|
118
|
+
return value.strip()
|
|
119
|
+
return None
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _client_hostname_source(client: object) -> str | None:
|
|
123
|
+
value = _client_field(client, "hostname_source")
|
|
124
|
+
if isinstance(value, str) and value.strip():
|
|
125
|
+
return value.strip()
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _client_is_unifi(client: object) -> bool:
|
|
130
|
+
flag = _client_unifi_flag(client)
|
|
131
|
+
if flag is not None:
|
|
132
|
+
return flag
|
|
133
|
+
ucore = _client_ucore_info(client)
|
|
134
|
+
if ucore:
|
|
135
|
+
managed = ucore.get("managed")
|
|
136
|
+
if isinstance(managed, bool) and managed:
|
|
137
|
+
return True
|
|
138
|
+
if isinstance(ucore.get("product_line"), str) and ucore.get("product_line"):
|
|
139
|
+
return True
|
|
140
|
+
if isinstance(ucore.get("product_shortname"), str) and ucore.get("product_shortname"):
|
|
141
|
+
return True
|
|
142
|
+
for key in ("name", "computed_model", "product_model"):
|
|
143
|
+
value = ucore.get(key)
|
|
144
|
+
if isinstance(value, str) and value.strip():
|
|
145
|
+
return True
|
|
146
|
+
vendor = _client_vendor(client)
|
|
147
|
+
if not vendor:
|
|
148
|
+
return False
|
|
149
|
+
normalized = vendor.lower()
|
|
150
|
+
return "ubiquiti" in normalized or "unifi" in normalized
|
|
151
|
+
|
|
152
|
+
|
|
80
153
|
def _client_matches_mode(client: object, mode: str) -> bool:
|
|
81
154
|
wired = _client_is_wired(client)
|
|
82
155
|
if mode == "all":
|
|
@@ -86,6 +159,14 @@ def _client_matches_mode(client: object, mode: str) -> bool:
|
|
|
86
159
|
return wired
|
|
87
160
|
|
|
88
161
|
|
|
162
|
+
def _client_matches_filters(client: object, *, client_mode: str, only_unifi: bool) -> bool:
|
|
163
|
+
if not _client_matches_mode(client, client_mode):
|
|
164
|
+
return False
|
|
165
|
+
if only_unifi and not _client_is_unifi(client):
|
|
166
|
+
return False
|
|
167
|
+
return True
|
|
168
|
+
|
|
169
|
+
|
|
89
170
|
def _lldp_sort_key(entry: LLDPEntry) -> tuple[int, str, str]:
|
|
90
171
|
port_label = local_port_label(entry) or ""
|
|
91
172
|
port_number = "".join(ch for ch in port_label if ch.isdigit())
|
|
@@ -199,10 +280,11 @@ def _client_rows(
|
|
|
199
280
|
*,
|
|
200
281
|
include_ports: bool,
|
|
201
282
|
client_mode: str,
|
|
283
|
+
only_unifi: bool,
|
|
202
284
|
) -> dict[str, list[tuple[str, str | None]]]:
|
|
203
285
|
rows_by_device: dict[str, list[tuple[str, str | None]]] = {}
|
|
204
286
|
for client in clients:
|
|
205
|
-
if not
|
|
287
|
+
if not _client_matches_filters(client, client_mode=client_mode, only_unifi=only_unifi):
|
|
206
288
|
continue
|
|
207
289
|
name = _client_display_name(client)
|
|
208
290
|
uplink_mac = _client_uplink_mac(client)
|
|
@@ -227,6 +309,7 @@ def _prepare_lldp_maps(
|
|
|
227
309
|
include_ports: bool,
|
|
228
310
|
show_clients: bool,
|
|
229
311
|
client_mode: str,
|
|
312
|
+
only_unifi: bool,
|
|
230
313
|
) -> tuple[
|
|
231
314
|
dict[tuple[str, str], str],
|
|
232
315
|
dict[str, list[tuple[int, str]]] | None,
|
|
@@ -234,7 +317,13 @@ def _prepare_lldp_maps(
|
|
|
234
317
|
]:
|
|
235
318
|
device_index = build_device_index(devices)
|
|
236
319
|
client_rows = (
|
|
237
|
-
_client_rows(
|
|
320
|
+
_client_rows(
|
|
321
|
+
clients,
|
|
322
|
+
device_index,
|
|
323
|
+
include_ports=include_ports,
|
|
324
|
+
client_mode=client_mode,
|
|
325
|
+
only_unifi=only_unifi,
|
|
326
|
+
)
|
|
238
327
|
if clients
|
|
239
328
|
else {}
|
|
240
329
|
)
|
|
@@ -243,7 +332,12 @@ def _prepare_lldp_maps(
|
|
|
243
332
|
if include_ports:
|
|
244
333
|
port_map = build_port_map(devices, only_unifi=False)
|
|
245
334
|
if clients and show_clients:
|
|
246
|
-
client_port_map = build_client_port_map(
|
|
335
|
+
client_port_map = build_client_port_map(
|
|
336
|
+
devices,
|
|
337
|
+
clients,
|
|
338
|
+
client_mode=client_mode,
|
|
339
|
+
only_unifi=only_unifi,
|
|
340
|
+
)
|
|
247
341
|
return port_map, client_port_map, client_rows
|
|
248
342
|
|
|
249
343
|
|
|
@@ -318,6 +412,7 @@ def render_lldp_md(
|
|
|
318
412
|
include_ports: bool = False,
|
|
319
413
|
show_clients: bool = False,
|
|
320
414
|
client_mode: str = "wired",
|
|
415
|
+
only_unifi: bool = False,
|
|
321
416
|
) -> str:
|
|
322
417
|
device_index = build_device_index(devices)
|
|
323
418
|
port_map, client_port_map, client_rows = _prepare_lldp_maps(
|
|
@@ -326,6 +421,7 @@ def render_lldp_md(
|
|
|
326
421
|
include_ports=include_ports,
|
|
327
422
|
show_clients=show_clients,
|
|
328
423
|
client_mode=client_mode,
|
|
424
|
+
only_unifi=only_unifi,
|
|
329
425
|
)
|
|
330
426
|
sections: list[str] = []
|
|
331
427
|
for device in sorted(devices, key=lambda item: item.name.lower()):
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps.egg-info/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unifi-network-maps
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.12
|
|
4
4
|
Summary: Dynamic UniFi -> network maps in mermaid or svg
|
|
5
5
|
Author: Merlijn
|
|
6
6
|
License-Expression: MIT
|
|
@@ -223,7 +223,7 @@ Functional:
|
|
|
223
223
|
- `--include-ports`: show port labels (Mermaid shows both ends; SVG shows compact labels).
|
|
224
224
|
- `--include-clients`: add active wired clients as leaf nodes.
|
|
225
225
|
- `--client-scope wired|wireless|all`: which client types to include (default wired).
|
|
226
|
-
- `--only-unifi`: only include neighbors that are UniFi devices.
|
|
226
|
+
- `--only-unifi`: only include neighbors that are UniFi devices; when clients are included, filters to UniFi-managed clients (by explicit UniFi flags or vendor/OUI).
|
|
227
227
|
- `--no-cache`: disable UniFi API cache reads and writes.
|
|
228
228
|
|
|
229
229
|
Mermaid:
|
|
@@ -57,6 +57,58 @@ def test_build_client_edges_includes_uplink_port_label():
|
|
|
57
57
|
assert edges[0].label == "Switch A: Port 3 <-> Laptop"
|
|
58
58
|
|
|
59
59
|
|
|
60
|
+
def test_build_client_edges_only_unifi_filters_non_unifi():
|
|
61
|
+
device_index = {"aa:bb:cc:dd:ee:ff": "Switch A"}
|
|
62
|
+
clients = [
|
|
63
|
+
{"name": "Desk PC", "is_wired": True, "sw_mac": "aa:bb:cc:dd:ee:ff", "is_unifi": False},
|
|
64
|
+
{"name": "Protect Cam", "is_wired": True, "sw_mac": "aa:bb:cc:dd:ee:ff", "is_unifi": True},
|
|
65
|
+
]
|
|
66
|
+
edges = build_client_edges(clients, device_index, only_unifi=True)
|
|
67
|
+
assert [edge.right for edge in edges] == ["Protect Cam"]
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_build_client_edges_only_unifi_vendor_fallback():
|
|
71
|
+
device_index = {"aa:bb:cc:dd:ee:ff": "Switch A"}
|
|
72
|
+
clients = [
|
|
73
|
+
{
|
|
74
|
+
"name": "UniFi Sensor",
|
|
75
|
+
"is_wired": True,
|
|
76
|
+
"sw_mac": "aa:bb:cc:dd:ee:ff",
|
|
77
|
+
"oui": "Ubiquiti Inc.",
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
edges = build_client_edges(clients, device_index, only_unifi=True)
|
|
81
|
+
assert edges[0].right == "UniFi Sensor"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_build_client_edges_only_unifi_ucore_managed():
|
|
85
|
+
device_index = {"aa:bb:cc:dd:ee:ff": "Switch A"}
|
|
86
|
+
clients = [
|
|
87
|
+
{
|
|
88
|
+
"name": "Doorbell Lite",
|
|
89
|
+
"is_wired": True,
|
|
90
|
+
"sw_mac": "aa:bb:cc:dd:ee:ff",
|
|
91
|
+
"unifi_device_info_from_ucore": {"managed": True},
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
edges = build_client_edges(clients, device_index, only_unifi=True)
|
|
95
|
+
assert edges[0].right == "Doorbell Lite"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_build_client_edges_prefers_ucore_name_over_hostname():
|
|
99
|
+
device_index = {"aa:bb:cc:dd:ee:ff": "Switch A"}
|
|
100
|
+
clients = [
|
|
101
|
+
{
|
|
102
|
+
"hostname": "espressif",
|
|
103
|
+
"is_wired": True,
|
|
104
|
+
"sw_mac": "aa:bb:cc:dd:ee:ff",
|
|
105
|
+
"unifi_device_info_from_ucore": {"name": "Smart PoE Chime"},
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
edges = build_client_edges(clients, device_index, only_unifi=True)
|
|
109
|
+
assert edges[0].right == "Smart PoE Chime"
|
|
110
|
+
|
|
111
|
+
|
|
60
112
|
def test_build_node_type_map_skips_wireless_clients():
|
|
61
113
|
devices = [
|
|
62
114
|
Device(name="Gateway", model_name="", model="", mac="aa", ip="", type="udm", lldp_info=[])
|
|
@@ -64,3 +116,16 @@ def test_build_node_type_map_skips_wireless_clients():
|
|
|
64
116
|
clients = [{"name": "Phone", "is_wired": False}]
|
|
65
117
|
node_types = build_node_type_map(devices, clients)
|
|
66
118
|
assert "Phone" not in node_types
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def test_build_node_type_map_only_unifi_filters_clients():
|
|
122
|
+
devices = [
|
|
123
|
+
Device(name="Gateway", model_name="", model="", mac="aa", ip="", type="udm", lldp_info=[])
|
|
124
|
+
]
|
|
125
|
+
clients = [
|
|
126
|
+
{"name": "Desk PC", "is_wired": True, "is_unifi": False},
|
|
127
|
+
{"name": "Protect Cam", "is_wired": True, "is_unifi": True},
|
|
128
|
+
]
|
|
129
|
+
node_types = build_node_type_map(devices, clients, only_unifi=True)
|
|
130
|
+
assert "Protect Cam" in node_types
|
|
131
|
+
assert "Desk PC" not in node_types
|
|
@@ -67,6 +67,61 @@ def test_render_lldp_md_includes_clients_when_requested():
|
|
|
67
67
|
assert "| TV | Port 3 |" in output
|
|
68
68
|
|
|
69
69
|
|
|
70
|
+
def test_render_lldp_md_only_unifi_filters_clients():
|
|
71
|
+
devices = [
|
|
72
|
+
Device(
|
|
73
|
+
name="Switch A", model_name="", model="", mac="aa:bb", ip="", type="usw", lldp_info=[]
|
|
74
|
+
)
|
|
75
|
+
]
|
|
76
|
+
clients = [
|
|
77
|
+
{"name": "Desk PC", "is_wired": True, "sw_mac": "aa:bb", "sw_port": 1},
|
|
78
|
+
{
|
|
79
|
+
"name": "Protect Cam",
|
|
80
|
+
"is_wired": True,
|
|
81
|
+
"sw_mac": "aa:bb",
|
|
82
|
+
"sw_port": 2,
|
|
83
|
+
"is_unifi": True,
|
|
84
|
+
},
|
|
85
|
+
]
|
|
86
|
+
output = render_lldp_md(
|
|
87
|
+
devices,
|
|
88
|
+
clients=clients,
|
|
89
|
+
include_ports=True,
|
|
90
|
+
show_clients=True,
|
|
91
|
+
client_mode="wired",
|
|
92
|
+
only_unifi=True,
|
|
93
|
+
)
|
|
94
|
+
assert "| Protect Cam | Port 2 |" in output
|
|
95
|
+
assert "Desk PC" not in output
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_render_lldp_md_uses_ucore_name_for_clients():
|
|
99
|
+
devices = [
|
|
100
|
+
Device(
|
|
101
|
+
name="Switch A", model_name="", model="", mac="aa:bb", ip="", type="usw", lldp_info=[]
|
|
102
|
+
)
|
|
103
|
+
]
|
|
104
|
+
clients = [
|
|
105
|
+
{
|
|
106
|
+
"hostname": "espressif",
|
|
107
|
+
"is_wired": True,
|
|
108
|
+
"sw_mac": "aa:bb",
|
|
109
|
+
"sw_port": 4,
|
|
110
|
+
"unifi_device_info_from_ucore": {"name": "Smart PoE Chime"},
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
output = render_lldp_md(
|
|
114
|
+
devices,
|
|
115
|
+
clients=clients,
|
|
116
|
+
include_ports=True,
|
|
117
|
+
show_clients=True,
|
|
118
|
+
client_mode="wired",
|
|
119
|
+
only_unifi=True,
|
|
120
|
+
)
|
|
121
|
+
assert "| Smart PoE Chime | Port 4 |" in output
|
|
122
|
+
assert "espressif" not in output
|
|
123
|
+
|
|
124
|
+
|
|
70
125
|
def test_render_lldp_md_includes_ports_only_when_enabled():
|
|
71
126
|
devices = [
|
|
72
127
|
Device(
|
|
@@ -422,6 +422,38 @@ def test_build_edges_only_unifi_false_uses_chassis_id():
|
|
|
422
422
|
assert edges[0].right == "bb"
|
|
423
423
|
|
|
424
424
|
|
|
425
|
+
def test_build_edges_only_unifi_skips_unknown_uplink():
|
|
426
|
+
device = SimpleNamespace(
|
|
427
|
+
name="Switch",
|
|
428
|
+
model_name="",
|
|
429
|
+
model="",
|
|
430
|
+
mac="aa",
|
|
431
|
+
ip="",
|
|
432
|
+
type="switch",
|
|
433
|
+
lldp_info=[],
|
|
434
|
+
port_table=[],
|
|
435
|
+
uplink_mac="cc",
|
|
436
|
+
)
|
|
437
|
+
edges = build_edges([coerce_device(device)], only_unifi=True)
|
|
438
|
+
assert edges == []
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
def test_build_edges_only_unifi_false_includes_unknown_uplink():
|
|
442
|
+
device = SimpleNamespace(
|
|
443
|
+
name="Switch",
|
|
444
|
+
model_name="",
|
|
445
|
+
model="",
|
|
446
|
+
mac="aa",
|
|
447
|
+
ip="",
|
|
448
|
+
type="switch",
|
|
449
|
+
lldp_info=[],
|
|
450
|
+
port_table=[],
|
|
451
|
+
uplink_mac="cc",
|
|
452
|
+
)
|
|
453
|
+
edges = build_edges([coerce_device(device)], only_unifi=False)
|
|
454
|
+
assert (edges[0].left, edges[0].right) == ("cc", "Switch")
|
|
455
|
+
|
|
456
|
+
|
|
425
457
|
def test_build_edges_resolves_port_idx_from_ifname():
|
|
426
458
|
lldp = SimpleNamespace(
|
|
427
459
|
chassis_id="bb",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.4.11"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/adapters/__init__.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/adapters/config.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/adapters/unifi.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/assets/__init__.py
RENAMED
|
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
|
|
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
|
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/cli/__init__.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/cli/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/io/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/io/mkdocs_assets.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/io/mock_data.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/io/mock_generate.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/__init__.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/labels.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/lldp.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/mock.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/model/ports.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/legend.py
RENAMED
|
File without changes
|
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/mermaid.py
RENAMED
|
File without changes
|
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/mkdocs.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/svg.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/svg_theme.py
RENAMED
|
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
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/templating.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps/render/theme.py
RENAMED
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{unifi_network_maps-1.4.11 → unifi_network_maps-1.4.12}/src/unifi_network_maps.egg-info/requires.txt
RENAMED
|
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
|