unifi-network-maps 1.4.10__py3-none-any.whl → 1.4.12__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.
@@ -1 +1 @@
1
- __version__ = "1.4.10"
1
+ __version__ = "1.4.12"
@@ -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(devices, clients, client_mode=args.client_scope),
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(devices, clients, client_mode=args.client_scope),
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(devices, clients, client_mode=args.client_scope),
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
@@ -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(devices, clients, client_mode=args.client_scope)
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
@@ -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
- for key in ("name", "hostname", "mac"):
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()
@@ -482,20 +488,31 @@ def _client_uplink_mac(client: object) -> str | None:
482
488
 
483
489
 
484
490
  def _client_uplink_port(client: object) -> int | None:
485
- for key in ("uplink_remote_port", "sw_port", "ap_port"):
486
- value = _client_field(client, key)
487
- if isinstance(value, int):
488
- return value
489
- if isinstance(value, str) and value.isdigit():
490
- return int(value)
491
+ for value in _client_port_values(client):
492
+ parsed = _parse_port_value(value)
493
+ if parsed is not None:
494
+ return parsed
495
+ return None
496
+
497
+
498
+ def _client_port_values(client: object) -> Iterable[object | None]:
499
+ for key in ("uplink_remote_port", "sw_port", "ap_port", "port_idx"):
500
+ yield _client_field(client, key)
491
501
  for key in ("uplink", "last_uplink"):
492
502
  nested = _client_field(client, key)
493
503
  if isinstance(nested, dict):
494
- value = nested.get("uplink_remote_port")
495
- if isinstance(value, int):
496
- return value
497
- if isinstance(value, str) and value.isdigit():
498
- return int(value)
504
+ for nested_key in ("uplink_remote_port", "port_idx"):
505
+ yield nested.get(nested_key)
506
+
507
+
508
+ def _parse_port_value(value: object | None) -> int | None:
509
+ if isinstance(value, int):
510
+ return value
511
+ if isinstance(value, str):
512
+ stripped = value.strip()
513
+ if stripped.isdigit():
514
+ return int(stripped)
515
+ return extract_port_number(stripped)
499
516
  return None
500
517
 
501
518
 
@@ -503,6 +520,73 @@ def _client_is_wired(client: object) -> bool:
503
520
  return bool(_client_field(client, "is_wired"))
504
521
 
505
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
+
506
590
  def _client_channel(client: object) -> int | None:
507
591
  for key in ("channel", "radio_channel", "wifi_channel"):
508
592
  value = _client_field(client, key)
@@ -522,17 +606,26 @@ def _client_matches_mode(client: object, mode: str) -> bool:
522
606
  return wired
523
607
 
524
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
+
525
617
  def build_client_edges(
526
618
  clients: Iterable[object],
527
619
  device_index: dict[str, str],
528
620
  *,
529
621
  include_ports: bool = False,
530
622
  client_mode: str = "wired",
623
+ only_unifi: bool = False,
531
624
  ) -> list[Edge]:
532
625
  edges: list[Edge] = []
533
626
  seen: set[tuple[str, str]] = set()
534
627
  for client in clients:
535
- if not _client_matches_mode(client, client_mode):
628
+ if not _client_matches_filters(client, client_mode=client_mode, only_unifi=only_unifi):
536
629
  continue
537
630
  name = _client_display_name(client)
538
631
  uplink_mac = _client_uplink_mac(client)
@@ -569,13 +662,14 @@ def build_node_type_map(
569
662
  clients: Iterable[object] | None = None,
570
663
  *,
571
664
  client_mode: str = "wired",
665
+ only_unifi: bool = False,
572
666
  ) -> dict[str, str]:
573
667
  node_types: dict[str, str] = {}
574
668
  for device in devices:
575
669
  node_types[device.name] = classify_device_type(device)
576
670
  if clients:
577
671
  for client in clients:
578
- if not _client_matches_mode(client, client_mode):
672
+ if not _client_matches_filters(client, client_mode=client_mode, only_unifi=only_unifi):
579
673
  continue
580
674
  name = _client_display_name(client)
581
675
  if name:
@@ -672,11 +766,12 @@ def build_client_port_map(
672
766
  clients: Iterable[object],
673
767
  *,
674
768
  client_mode: str,
769
+ only_unifi: bool = False,
675
770
  ) -> ClientPortMap:
676
771
  device_index = build_device_index(devices)
677
772
  port_map: ClientPortMap = {}
678
773
  for client in clients:
679
- if not _client_matches_mode(client, client_mode):
774
+ if not _client_matches_filters(client, client_mode=client_mode, only_unifi=only_unifi):
680
775
  continue
681
776
  name = _client_display_name(client)
682
777
  uplink_mac = _client_uplink_mac(client)
@@ -5,6 +5,7 @@ from __future__ import annotations
5
5
  from collections.abc import Iterable
6
6
 
7
7
  from ..model.lldp import LLDPEntry, local_port_label
8
+ from ..model.ports import extract_port_number
8
9
  from ..model.topology import Device, build_client_port_map, build_device_index, build_port_map
9
10
  from .device_ports_md import render_device_port_details
10
11
  from .markdown_tables import markdown_table_lines
@@ -22,7 +23,13 @@ def _client_field(client: object, name: str) -> object | None:
22
23
 
23
24
 
24
25
  def _client_display_name(client: object) -> str | None:
25
- for key in ("name", "hostname", "mac"):
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"):
26
33
  value = _client_field(client, key)
27
34
  if isinstance(value, str) and value.strip():
28
35
  return value.strip()
@@ -44,20 +51,31 @@ def _client_uplink_mac(client: object) -> str | None:
44
51
 
45
52
 
46
53
  def _client_uplink_port(client: object) -> int | None:
47
- for key in ("uplink_remote_port", "sw_port", "ap_port"):
48
- value = _client_field(client, key)
49
- if isinstance(value, int):
50
- return value
51
- if isinstance(value, str) and value.isdigit():
52
- return int(value)
54
+ for value in _client_port_values(client):
55
+ parsed = _parse_port_value(value)
56
+ if parsed is not None:
57
+ return parsed
58
+ return None
59
+
60
+
61
+ def _client_port_values(client: object) -> Iterable[object | None]:
62
+ for key in ("uplink_remote_port", "sw_port", "ap_port", "port_idx"):
63
+ yield _client_field(client, key)
53
64
  for key in ("uplink", "last_uplink"):
54
65
  nested = _client_field(client, key)
55
66
  if isinstance(nested, dict):
56
- value = nested.get("uplink_remote_port")
57
- if isinstance(value, int):
58
- return value
59
- if isinstance(value, str) and value.isdigit():
60
- return int(value)
67
+ for nested_key in ("uplink_remote_port", "port_idx"):
68
+ yield nested.get(nested_key)
69
+
70
+
71
+ def _parse_port_value(value: object | None) -> int | None:
72
+ if isinstance(value, int):
73
+ return value
74
+ if isinstance(value, str):
75
+ stripped = value.strip()
76
+ if stripped.isdigit():
77
+ return int(stripped)
78
+ return extract_port_number(stripped)
61
79
  return None
62
80
 
63
81
 
@@ -65,6 +83,73 @@ def _client_is_wired(client: object) -> bool:
65
83
  return bool(_client_field(client, "is_wired"))
66
84
 
67
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
+
68
153
  def _client_matches_mode(client: object, mode: str) -> bool:
69
154
  wired = _client_is_wired(client)
70
155
  if mode == "all":
@@ -74,6 +159,14 @@ def _client_matches_mode(client: object, mode: str) -> bool:
74
159
  return wired
75
160
 
76
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
+
77
170
  def _lldp_sort_key(entry: LLDPEntry) -> tuple[int, str, str]:
78
171
  port_label = local_port_label(entry) or ""
79
172
  port_number = "".join(ch for ch in port_label if ch.isdigit())
@@ -187,10 +280,11 @@ def _client_rows(
187
280
  *,
188
281
  include_ports: bool,
189
282
  client_mode: str,
283
+ only_unifi: bool,
190
284
  ) -> dict[str, list[tuple[str, str | None]]]:
191
285
  rows_by_device: dict[str, list[tuple[str, str | None]]] = {}
192
286
  for client in clients:
193
- if not _client_matches_mode(client, client_mode):
287
+ if not _client_matches_filters(client, client_mode=client_mode, only_unifi=only_unifi):
194
288
  continue
195
289
  name = _client_display_name(client)
196
290
  uplink_mac = _client_uplink_mac(client)
@@ -215,6 +309,7 @@ def _prepare_lldp_maps(
215
309
  include_ports: bool,
216
310
  show_clients: bool,
217
311
  client_mode: str,
312
+ only_unifi: bool,
218
313
  ) -> tuple[
219
314
  dict[tuple[str, str], str],
220
315
  dict[str, list[tuple[int, str]]] | None,
@@ -222,7 +317,13 @@ def _prepare_lldp_maps(
222
317
  ]:
223
318
  device_index = build_device_index(devices)
224
319
  client_rows = (
225
- _client_rows(clients, device_index, include_ports=include_ports, client_mode=client_mode)
320
+ _client_rows(
321
+ clients,
322
+ device_index,
323
+ include_ports=include_ports,
324
+ client_mode=client_mode,
325
+ only_unifi=only_unifi,
326
+ )
226
327
  if clients
227
328
  else {}
228
329
  )
@@ -231,7 +332,12 @@ def _prepare_lldp_maps(
231
332
  if include_ports:
232
333
  port_map = build_port_map(devices, only_unifi=False)
233
334
  if clients and show_clients:
234
- client_port_map = build_client_port_map(devices, clients, client_mode=client_mode)
335
+ client_port_map = build_client_port_map(
336
+ devices,
337
+ clients,
338
+ client_mode=client_mode,
339
+ only_unifi=only_unifi,
340
+ )
235
341
  return port_map, client_port_map, client_rows
236
342
 
237
343
 
@@ -306,6 +412,7 @@ def render_lldp_md(
306
412
  include_ports: bool = False,
307
413
  show_clients: bool = False,
308
414
  client_mode: str = "wired",
415
+ only_unifi: bool = False,
309
416
  ) -> str:
310
417
  device_index = build_device_index(devices)
311
418
  port_map, client_port_map, client_rows = _prepare_lldp_maps(
@@ -314,6 +421,7 @@ def render_lldp_md(
314
421
  include_ports=include_ports,
315
422
  show_clients=show_clients,
316
423
  client_mode=client_mode,
424
+ only_unifi=only_unifi,
317
425
  )
318
426
  sections: list[str] = []
319
427
  for device in sorted(devices, key=lambda item: item.name.lower()):
@@ -547,8 +547,11 @@ def _render_svg_edges(
547
547
  f"L {dst_cx} {mid_y} L {dst_cx} {dst_top}"
548
548
  )
549
549
  dash = ' stroke-dasharray="6 4"' if edge.wireless else ""
550
+ left_attr = _escape_attr(edge.left, quote=True)
551
+ right_attr = _escape_attr(edge.right, quote=True)
550
552
  lines.append(
551
- f'<path d="{path}" stroke="{color}" stroke-width="{width_px}" fill="none"{dash}/>'
553
+ f'<path d="{path}" stroke="{color}" stroke-width="{width_px}" fill="none"{dash} '
554
+ f'data-edge-left="{left_attr}" data-edge-right="{right_attr}"/>'
552
555
  )
553
556
  if edge.poe:
554
557
  icon_x = dst_cx
@@ -834,9 +837,12 @@ def _render_iso_edges(
834
837
  dst_cy,
835
838
  )
836
839
  dash = ' stroke-dasharray="8 6"' if edge.wireless else ""
840
+ left_attr = _escape_attr(edge.left, quote=True)
841
+ right_attr = _escape_attr(edge.right, quote=True)
837
842
  lines.append(
838
843
  f'<path d="{" ".join(path_cmds)}" stroke="{color}" stroke-width="{width_px}" '
839
- f'fill="none" stroke-linecap="round" stroke-linejoin="round"{dash}/>'
844
+ f'fill="none" stroke-linecap="round" stroke-linejoin="round"{dash} '
845
+ f'data-edge-left="{left_attr}" data-edge-right="{right_attr}"/>'
840
846
  )
841
847
  if edge.poe:
842
848
  icon_x = dst_cx
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unifi-network-maps
3
- Version: 1.4.10
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:
@@ -1,4 +1,4 @@
1
- unifi_network_maps/__init__.py,sha256=WCR-6aXXvi4kHlaMAYnHT-VzLSifo-1Btos9idb9SM8,23
1
+ unifi_network_maps/__init__.py,sha256=nGraM_ujqcNJ-Dyz-qi99_8ynLwzQU2N68yOSnVykOs,23
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
@@ -54,8 +54,8 @@ unifi_network_maps/cli/__init__.py,sha256=cds9GvFNZmYAR22Ab3TSzfriSAW--kf9jvC5U-
54
54
  unifi_network_maps/cli/__main__.py,sha256=nK_jh78VW3h3DRvSpjzpcf64zkCqniP2k82xUR9Hw2I,147
55
55
  unifi_network_maps/cli/args.py,sha256=lIgQDeob_SIhjXg76hJsnpgNOKupSjSYum_MqarWOkE,5552
56
56
  unifi_network_maps/cli/main.py,sha256=jQXesuHJLTQl4lBk1DD6em67Wj9oEjBmH9X-X1zA6MI,4150
57
- unifi_network_maps/cli/render.py,sha256=sUyDWm_I_zbEcKuNEpKUXDxhe1XptgOYsmdMP9BJ3Eg,7040
58
- unifi_network_maps/cli/runtime.py,sha256=Hln4LMpuTrEsy6gIBmqkOrUpMb4nTeZ-AH72KyxpZwA,4723
57
+ unifi_network_maps/cli/render.py,sha256=hT4RS3Y5F2TVDe85xpaOckgz9b5c8igY5Q77Uoh8nmk,7357
58
+ unifi_network_maps/cli/runtime.py,sha256=cMtIShERup2z2_uCcEGcaJFJptvdI0L3FDWqKFwSevY,4830
59
59
  unifi_network_maps/io/__init__.py,sha256=nzx1KsiYalL_YuXKE6acW8Dj5flmMg0-i4gyYO0gV54,22
60
60
  unifi_network_maps/io/debug.py,sha256=eUVs6GLfs6VqI6ma8ra7NLhC3q4ek2K8OSRLnpQDF9s,1745
61
61
  unifi_network_maps/io/export.py,sha256=2vURunQDja-_fKKMb-gQG-n34aeM8GFprNJqcGaP4qg,843
@@ -67,16 +67,16 @@ unifi_network_maps/model/labels.py,sha256=m_k8mbzWtOSDOjjHhLUqwIw93pg98HAtGtHkiE
67
67
  unifi_network_maps/model/lldp.py,sha256=SrPW5XC2lfJgaGeVx-KnSFNltyok7gIWWQNg1SkOaj4,3300
68
68
  unifi_network_maps/model/mock.py,sha256=kd1MSiIn-7KKu_nMVmheYPfTyAN5DHt4dzRrBifF_lI,8706
69
69
  unifi_network_maps/model/ports.py,sha256=o3NBlXcC5VV5iPWJsO4Ll1mRKJZC0f8zTHdlkkE34GU,609
70
- unifi_network_maps/model/topology.py,sha256=Rq69wcJ5toXz4ZZPHahc2Jiuw-3CXiOiIrZp1fupaUU,28262
70
+ unifi_network_maps/model/topology.py,sha256=l26yHsRGuD-D1x4-qsaMBRTeA8SBU_xhRCi9ZwyG7w8,31472
71
71
  unifi_network_maps/render/__init__.py,sha256=nzx1KsiYalL_YuXKE6acW8Dj5flmMg0-i4gyYO0gV54,22
72
72
  unifi_network_maps/render/device_ports_md.py,sha256=vt5kGFSIAabMbcSxIuVVLSzdb_i58NHGi4hJM2ZLZR4,15975
73
73
  unifi_network_maps/render/legend.py,sha256=TmZsxgCVOM2CZImI9zgRVyzrcg01HZFDj9F715d4CGo,772
74
- unifi_network_maps/render/lldp_md.py,sha256=K6qTaI8HPsU7Cn0rNCJxn-Gvzkol1-m4kt0atI2NAXA,11347
74
+ unifi_network_maps/render/lldp_md.py,sha256=wHMMoxcRicF3NirNh0L62PQFNQYOp6XFxNOTwFm7x0Y,14738
75
75
  unifi_network_maps/render/markdown_tables.py,sha256=VvM0fSnSmpeeDPcD5pXaL_j_PTF0STrMCaqnr2BVHn4,547
76
76
  unifi_network_maps/render/mermaid.py,sha256=xsC57Xg-nKhmlVATzEbwLkMM2BOeDYlBjZuxBIPhHeI,8324
77
77
  unifi_network_maps/render/mermaid_theme.py,sha256=7nqLlvhaUA4z0YOs0ByEx_yHWcQD_hJJjhDtRcbSpg4,1781
78
78
  unifi_network_maps/render/mkdocs.py,sha256=EOST9_eP1ZoZQax-p-2fjlelrl3AKEJ9Gn-KXW8TI-o,5389
79
- unifi_network_maps/render/svg.py,sha256=W0tiuCkicTxbHTJbeRbnWzFfaO9yawL7e6EJiP7TLnU,40791
79
+ unifi_network_maps/render/svg.py,sha256=Zd6TFaBhqa92O2Z7G_k3LnRXIbuaOAj-dYu2qzEwWvI,41171
80
80
  unifi_network_maps/render/svg_theme.py,sha256=Si1ArM3v_-wAvHZyLFPiOZ0ohQRd6ezIckwC3_b-WIw,2684
81
81
  unifi_network_maps/render/templating.py,sha256=VJbXzZFBPjL8LFFPcLf_EU5Eu53GN9_vpten2Mf9A-k,576
82
82
  unifi_network_maps/render/theme.py,sha256=vKYdPhcGEOV1o_irwqzJlIXPgRvZqQEzYYV2_TxZn4E,4301
@@ -91,9 +91,9 @@ unifi_network_maps/render/templates/mkdocs_html_block.html.j2,sha256=5l5-BbNujOc
91
91
  unifi_network_maps/render/templates/mkdocs_legend.css.j2,sha256=tkTI-RagBSgdjUygVenlTsQFenU09ePbXOfDt_Q7YRM,612
92
92
  unifi_network_maps/render/templates/mkdocs_legend.js.j2,sha256=qMYyCKsJ84uXf1wGgzbc7Bc49RU4oyuaGK9KrgQDQEI,685
93
93
  unifi_network_maps/render/templates/mkdocs_mermaid_block.md.j2,sha256=9IncllWQpoI8BN3A7b2zOQ5cksj97ddsjHJ-aBhpw7o,66
94
- unifi_network_maps-1.4.10.dist-info/licenses/LICENSE,sha256=mYo1siIIfIwyfdOuK2-Zt0ij2xBTii2hnpeTu79nD80,1074
95
- unifi_network_maps-1.4.10.dist-info/METADATA,sha256=hLv77auAYEJIxkk_vslu8qvQnI975Oud_AqsC3THRoE,9851
96
- unifi_network_maps-1.4.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
97
- unifi_network_maps-1.4.10.dist-info/entry_points.txt,sha256=cdJ7jsBgNgHxSflYUOqgz5BbvuM0Nnh-x8_Hbyh_LFg,67
98
- unifi_network_maps-1.4.10.dist-info/top_level.txt,sha256=G0rUX1PNfVCn1u-KtB6QjFQHopCOVLnPMczvPOoraHg,19
99
- unifi_network_maps-1.4.10.dist-info/RECORD,,
94
+ unifi_network_maps-1.4.12.dist-info/licenses/LICENSE,sha256=mYo1siIIfIwyfdOuK2-Zt0ij2xBTii2hnpeTu79nD80,1074
95
+ unifi_network_maps-1.4.12.dist-info/METADATA,sha256=ob7P4a7jb8JTC_OWLX4Ej0jPf8SrYNXWyhCCodGmyRM,9952
96
+ unifi_network_maps-1.4.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
97
+ unifi_network_maps-1.4.12.dist-info/entry_points.txt,sha256=cdJ7jsBgNgHxSflYUOqgz5BbvuM0Nnh-x8_Hbyh_LFg,67
98
+ unifi_network_maps-1.4.12.dist-info/top_level.txt,sha256=G0rUX1PNfVCn1u-KtB6QjFQHopCOVLnPMczvPOoraHg,19
99
+ unifi_network_maps-1.4.12.dist-info/RECORD,,