testprotocols 0.1.0__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.
Files changed (119) hide show
  1. testprotocols/__init__.py +217 -0
  2. testprotocols/aftr_gateway.py +22 -0
  3. testprotocols/appliance_nat.py +52 -0
  4. testprotocols/appliance_uplinks.py +32 -0
  5. testprotocols/appliance_vlans.py +50 -0
  6. testprotocols/arp_client.py +26 -0
  7. testprotocols/bgp.py +55 -0
  8. testprotocols/conntrack.py +147 -0
  9. testprotocols/content_filtering.py +47 -0
  10. testprotocols/device_lifecycle.py +49 -0
  11. testprotocols/device_management.py +50 -0
  12. testprotocols/devices/__init__.py +46 -0
  13. testprotocols/devices/base.py +40 -0
  14. testprotocols/devices/client.py +133 -0
  15. testprotocols/devices/cpe.py +66 -0
  16. testprotocols/devices/infra.py +62 -0
  17. testprotocols/devices/sdwan.py +97 -0
  18. testprotocols/devices/switch.py +115 -0
  19. testprotocols/devices/traffic.py +53 -0
  20. testprotocols/devices/voice.py +69 -0
  21. testprotocols/devices/wan.py +60 -0
  22. testprotocols/dhcp_client.py +30 -0
  23. testprotocols/dhcp_server.py +23 -0
  24. testprotocols/discovery.py +20 -0
  25. testprotocols/dns_client.py +23 -0
  26. testprotocols/file_transfer.py +22 -0
  27. testprotocols/firewall.py +121 -0
  28. testprotocols/firewall_zones.py +133 -0
  29. testprotocols/first_hop_security.py +52 -0
  30. testprotocols/gateway_redundancy.py +29 -0
  31. testprotocols/http_client.py +36 -0
  32. testprotocols/http_server.py +22 -0
  33. testprotocols/hw_console.py +48 -0
  34. testprotocols/infra_controller.py +28 -0
  35. testprotocols/interface_dhcp.py +30 -0
  36. testprotocols/ip_interface.py +62 -0
  37. testprotocols/ip_routing.py +57 -0
  38. testprotocols/iperf_client.py +47 -0
  39. testprotocols/iperf_generator.py +42 -0
  40. testprotocols/iperf_server.py +41 -0
  41. testprotocols/l3_firewall.py +74 -0
  42. testprotocols/l7_firewall.py +32 -0
  43. testprotocols/link_aggregation.py +24 -0
  44. testprotocols/mac_table.py +20 -0
  45. testprotocols/models/__init__.py +304 -0
  46. testprotocols/models/dhcp.py +28 -0
  47. testprotocols/models/firewall.py +197 -0
  48. testprotocols/models/impairment.py +18 -0
  49. testprotocols/models/l2_common.py +53 -0
  50. testprotocols/models/multicast.py +22 -0
  51. testprotocols/models/networking.py +50 -0
  52. testprotocols/models/packets.py +21 -0
  53. testprotocols/models/qoe.py +31 -0
  54. testprotocols/models/radius.py +63 -0
  55. testprotocols/models/sdwan_appliance.py +637 -0
  56. testprotocols/models/switch.py +297 -0
  57. testprotocols/models/switch_routing.py +122 -0
  58. testprotocols/models/tr069.py +35 -0
  59. testprotocols/models/traffic.py +29 -0
  60. testprotocols/models/wan_edge.py +116 -0
  61. testprotocols/models/wifi.py +183 -0
  62. testprotocols/multicast_client.py +20 -0
  63. testprotocols/nat.py +87 -0
  64. testprotocols/netem_controller.py +42 -0
  65. testprotocols/network_endpoint.py +32 -0
  66. testprotocols/network_probe.py +27 -0
  67. testprotocols/nmap_scanner.py +27 -0
  68. testprotocols/ntp_client.py +26 -0
  69. testprotocols/ntp_config.py +25 -0
  70. testprotocols/ospf.py +24 -0
  71. testprotocols/packet_filter.py +144 -0
  72. testprotocols/pcap_capture.py +39 -0
  73. testprotocols/pdu_controller.py +26 -0
  74. testprotocols/port_poe.py +25 -0
  75. testprotocols/port_security.py +25 -0
  76. testprotocols/port_status.py +23 -0
  77. testprotocols/py.typed +0 -0
  78. testprotocols/qoe_browser.py +62 -0
  79. testprotocols/radius_client.py +78 -0
  80. testprotocols/radius_server.py +130 -0
  81. testprotocols/routed_interfaces.py +29 -0
  82. testprotocols/router.py +53 -0
  83. testprotocols/routing_read.py +22 -0
  84. testprotocols/sdwan_policy_manager.py +64 -0
  85. testprotocols/sip_phone.py +230 -0
  86. testprotocols/sip_server.py +205 -0
  87. testprotocols/site_to_site_vpn.py +61 -0
  88. testprotocols/snmp_client.py +17 -0
  89. testprotocols/spanning_tree.py +37 -0
  90. testprotocols/static_routes.py +47 -0
  91. testprotocols/storm_control.py +24 -0
  92. testprotocols/streaming_server.py +32 -0
  93. testprotocols/switch_acl.py +29 -0
  94. testprotocols/switch_ports.py +28 -0
  95. testprotocols/switch_qos.py +33 -0
  96. testprotocols/switch_vlans.py +34 -0
  97. testprotocols/syslog_config.py +31 -0
  98. testprotocols/tftp_server.py +22 -0
  99. testprotocols/threat_prevention.py +60 -0
  100. testprotocols/tr069_client.py +47 -0
  101. testprotocols/tr069_server.py +151 -0
  102. testprotocols/traffic_shaping.py +54 -0
  103. testprotocols/upnp_client.py +37 -0
  104. testprotocols/vlan_client.py +22 -0
  105. testprotocols/wan_link_admin.py +34 -0
  106. testprotocols/wifi_bss.py +197 -0
  107. testprotocols/wifi_client.py +72 -0
  108. testprotocols/wifi_mesh.py +259 -0
  109. testprotocols/wifi_onboarding.py +105 -0
  110. testprotocols/wifi_radio.py +153 -0
  111. testprotocols/wifi_rf.py +78 -0
  112. testprotocols/wifi_stations.py +59 -0
  113. testprotocols/wifi_transitions.py +112 -0
  114. testprotocols-0.1.0.dist-info/METADATA +29 -0
  115. testprotocols-0.1.0.dist-info/RECORD +119 -0
  116. testprotocols-0.1.0.dist-info/WHEEL +5 -0
  117. testprotocols-0.1.0.dist-info/licenses/LICENSE +201 -0
  118. testprotocols-0.1.0.dist-info/licenses/NOTICE +11 -0
  119. testprotocols-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,153 @@
1
+ """WiFi / WifiRadio template.
2
+
3
+ Defines the abstract contract for per-radio PHY control on a WiFi-capable
4
+ device (2.4 / 5 / 6 GHz radios). Covers admin state, channel / bandwidth /
5
+ tx power / mode configuration, regulatory-domain control, and DFS-state
6
+ read.
7
+
8
+ The template is per-device with band-keyed methods (matching the
9
+ existing palco pattern in IpInterface and WifiClient). A device with
10
+ multiple radios on the same band (e.g. dual-5GHz) is not modelled in
11
+ this release; band-string keying assumes one radio per band per device.
12
+
13
+ White-box extensions (radar-event injection, raw PHY dump) live on the
14
+ ``WifiRadioWhiteBox`` extension Protocol below — see LEVELS.md for the
15
+ mandatory-vs-white-box rationale.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ from typing import Protocol, runtime_checkable
21
+
22
+ from testprotocols.models.wifi import WifiDfsState
23
+
24
+
25
+ @runtime_checkable
26
+ class WifiRadio(Protocol):
27
+ """Abstract contract for per-radio WiFi PHY control."""
28
+
29
+ # --- Discovery ---
30
+
31
+ def list_radios(self) -> list[str]:
32
+ """Return the bands present on this device (e.g. ``["2.4GHz", "5GHz", "6GHz"]``)."""
33
+ ...
34
+
35
+ # --- Admin state ---
36
+
37
+ def set_enabled(self, band: str, enabled: bool) -> None:
38
+ """Enable or disable the radio on *band*. Disabling shuts down the PHY entirely."""
39
+ ...
40
+
41
+ def get_enabled(self, band: str) -> bool:
42
+ """Return True if the radio on *band* is administratively enabled."""
43
+ ...
44
+
45
+ # --- Channel / bandwidth / power / mode ---
46
+
47
+ def set_channel(self, band: str, channel: int) -> None:
48
+ """Set the operating channel on *band* to a specific channel number.
49
+
50
+ Auto-channel selection is not modelled in this release — pass an explicit
51
+ channel. Raises ValueError if *channel* is not in
52
+ ``list_supported_channels(band)``.
53
+ """
54
+ ...
55
+
56
+ def get_channel(self, band: str) -> int:
57
+ """Return the channel currently in use on *band*."""
58
+ ...
59
+
60
+ def list_supported_channels(self, band: str) -> list[int]:
61
+ """Return the channels the radio can operate on under the current regulatory domain."""
62
+ ...
63
+
64
+ def set_bandwidth(self, band: str, bandwidth_mhz: int) -> None:
65
+ """Set channel bandwidth on *band*: one of 20, 40, 80, 160, 320.
66
+
67
+ Raises ValueError if the radio does not support *bandwidth_mhz*
68
+ (e.g. 320 on a non-Wi-Fi-7 radio).
69
+ """
70
+ ...
71
+
72
+ def get_bandwidth(self, band: str) -> int:
73
+ """Return the channel bandwidth currently in use on *band* (MHz)."""
74
+ ...
75
+
76
+ def set_tx_power(self, band: str, power_dbm: int) -> None:
77
+ """Set the transmit power on *band* in dBm.
78
+
79
+ Drivers translate to vendor units (percentage / index) internally.
80
+ Raises ValueError if *power_dbm* is outside the radio's supported range.
81
+ """
82
+ ...
83
+
84
+ def get_tx_power(self, band: str) -> int:
85
+ """Return the transmit power currently in use on *band* (dBm)."""
86
+ ...
87
+
88
+ def set_mode(self, band: str, mode: str) -> None:
89
+ """Set the 802.11 PHY mode on *band*.
90
+
91
+ Values: ``"a"``, ``"b"``, ``"g"``, ``"n"``, ``"ac"``, ``"ax"``, ``"be"``.
92
+ Drivers may accept compound forms (``"n/ac/ax"``) at their discretion.
93
+ Raises ValueError if the radio does not support *mode*.
94
+ """
95
+ ...
96
+
97
+ def get_mode(self, band: str) -> str:
98
+ """Return the 802.11 PHY mode currently in use on *band*."""
99
+ ...
100
+
101
+ # --- Regulatory domain (device-wide) ---
102
+
103
+ def set_country(self, country_code: str) -> None:
104
+ """Set the regulatory domain. *country_code* is ISO 3166-1 alpha-2 (``"US"``, ``"NL"``)."""
105
+ ...
106
+
107
+ def get_country(self) -> str:
108
+ """Return the configured regulatory domain as an ISO 3166-1 alpha-2 country code."""
109
+ ...
110
+
111
+ # --- DFS ---
112
+
113
+ def get_dfs_state(self, band: str) -> WifiDfsState:
114
+ """Return the current DFS state of the radio on *band*.
115
+
116
+ Includes Channel-Availability-Check status, time remaining, and
117
+ the Non-Occupancy List of channels currently locked out by prior
118
+ radar detection.
119
+ """
120
+ ...
121
+
122
+
123
+ @runtime_checkable
124
+ class WifiRadioWhiteBox(WifiRadio, Protocol):
125
+ """White-box extension of WifiRadio for deep PHY introspection and event injection.
126
+
127
+ Drivers backed by ``mac80211_hwsim`` (OpenWrt with the simulator radio),
128
+ vendor PHY-test stacks, or simulated environments satisfy this extension.
129
+ Real APs typically satisfy only the base ``WifiRadio`` Protocol; tests
130
+ that need radar-event injection or raw PHY introspection should pin
131
+ against ``WifiRadioWhiteBox`` and accept that they collection-skip on
132
+ drivers that don't satisfy it (per the ``@white_box`` scenario tag rule).
133
+ """
134
+
135
+ def inject_radar_event(self, band: str, channel: int | None = None) -> None:
136
+ """Inject a synthetic radar detection event on *band*.
137
+
138
+ Test hook for DFS automation testing. *channel* defaults to the
139
+ radio's current channel. The OpenWrt + ``mac80211_hwsim`` driver
140
+ is the canonical implementer; drivers without hardware/simulation
141
+ support do not satisfy ``WifiRadioWhiteBox`` at all (rather than
142
+ raising at call time).
143
+ """
144
+ ...
145
+
146
+ def get_raw_phy_dump(self) -> str:
147
+ """Dump raw nl80211 / vendor PHY state.
148
+
149
+ Returns the underlying driver's PHY description verbatim (e.g.
150
+ ``iw phy`` output on Linux). Caller parses; format is driver-dependent
151
+ and intended for diagnostics, not for steady-state contract checks.
152
+ """
153
+ ...
@@ -0,0 +1,78 @@
1
+ """WiFi / WifiRf template.
2
+
3
+ Defines the abstract contract for per-radio RF observability:
4
+ on-demand scan triggering, neighbor BSS enumeration, channel utilization,
5
+ noise floor, and cumulative per-radio TX/RX/retry counters.
6
+
7
+ Read-only telemetry only — PHY configuration (channel, bandwidth, tx
8
+ power, mode, country, DFS state) lives in WifiRadio. Per-frame 802.11
9
+ spectrum analysis (FFT, CleanAir, spectral_scan) is deferred to a future
10
+ WifiSpectrum template, given the low cross-vendor uniformity.
11
+
12
+ Per-radio identity is band-keyed, matching WifiRadio.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from typing import Protocol, runtime_checkable
18
+
19
+ from testprotocols.models.wifi import (
20
+ WifiChannelUtilization,
21
+ WifiNeighbor,
22
+ WifiRadioStats,
23
+ )
24
+
25
+
26
+ @runtime_checkable
27
+ class WifiRf(Protocol):
28
+ """Abstract contract for per-radio WiFi RF telemetry."""
29
+
30
+ # --- Scan ---
31
+
32
+ def scan(self, band: str, timeout: float = 30.0) -> list[WifiNeighbor]:
33
+ """Trigger an off-channel scan on *band* and return the neighbour BSSes found.
34
+
35
+ Blocks until scan results are available or *timeout* seconds elapse.
36
+ Hides vendor divergence:
37
+ - Vendors that return immediately with a job handle: the driver polls
38
+ the job until it completes.
39
+ - Vendors that return inline: the driver returns directly.
40
+ - Vendors that post results to a separate diagnostic resource: the
41
+ driver polls that resource.
42
+
43
+ Raises TimeoutError if results are not available within *timeout*.
44
+ """
45
+ ...
46
+
47
+ def get_neighbors(self, band: str) -> list[WifiNeighbor]:
48
+ """Return the most recent neighbour-BSS list for *band* without triggering a new scan.
49
+
50
+ Returns whatever the driver has cached from prior background scans
51
+ or the most recent ``scan()`` call. Empty list if no scan has run.
52
+ """
53
+ ...
54
+
55
+ # --- Channel telemetry ---
56
+
57
+ def get_channel_utilization(self, band: str) -> WifiChannelUtilization:
58
+ """Return current channel utilization breakdown for *band*.
59
+
60
+ All percentages are 0-100. Drivers that don't separate TX/RX/interference
61
+ components return only ``busy_pct`` populated; the others are None.
62
+ """
63
+ ...
64
+
65
+ def get_noise_floor(self, band: str) -> int:
66
+ """Return the current noise floor on *band* in dBm (typically negative, e.g. -95)."""
67
+ ...
68
+
69
+ # --- Cumulative per-radio counters ---
70
+
71
+ def get_radio_stats(self, band: str) -> WifiRadioStats:
72
+ """Return cumulative per-radio TX/RX/retry counters for *band*.
73
+
74
+ Counters are since the radio came up (typically boot or last
75
+ ``WifiRadio.set_enabled(band, True)``). Drivers reset them on
76
+ radio disable/enable cycles.
77
+ """
78
+ ...
@@ -0,0 +1,59 @@
1
+ """WiFi / WifiStations template.
2
+
3
+ Defines the abstract contract for the AP-side view of associated stations:
4
+ enumeration, per-station stats and capability inspection, and admin-driven
5
+ disconnect.
6
+
7
+ Stations are identified by MAC address. The MAC argument format is
8
+ free-form on input (drivers normalize); the canonical form returned in
9
+ read methods is lowercase colon-separated (e.g. "aa:bb:cc:dd:ee:ff").
10
+
11
+ Per-frame 802.11v BTM and 802.11k Neighbor-Report-Request operations
12
+ live on the WifiTransitions template, not here. This template only
13
+ covers admin-state operations on the AP's view of its stations.
14
+
15
+ Per-BSS MAC ACL administration (set_acl_mode, add_acl_entry, etc.)
16
+ lives on the WifiBss template — see SPLITS.md for the rationale.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from typing import Protocol, runtime_checkable
22
+
23
+ from testprotocols.models.wifi import WifiStation
24
+
25
+
26
+ @runtime_checkable
27
+ class WifiStations(Protocol):
28
+ """Abstract contract for AP-side WiFi station inspection and admin."""
29
+
30
+ # --- Inspection ---
31
+
32
+ def list_associated_stations(self, bss_name: str | None = None) -> list[WifiStation]:
33
+ """Return all currently associated stations, optionally filtered to *bss_name*.
34
+
35
+ With *bss_name* None, returns stations across all BSSes on the device.
36
+ Raises KeyError if *bss_name* is provided and not registered in WifiBss.
37
+ """
38
+ ...
39
+
40
+ def get_station(self, mac: str) -> WifiStation:
41
+ """Return the full record for the associated station identified by *mac*.
42
+
43
+ Raises KeyError if no station with that MAC is currently associated.
44
+ """
45
+ ...
46
+
47
+ # --- Admin disconnect ---
48
+
49
+ def disconnect_station(self, mac: str, reason_code: int | None = None) -> None:
50
+ """Administratively disconnect the station identified by *mac*.
51
+
52
+ *reason_code* is an optional IEEE 802.11 reason code (e.g. 1
53
+ "unspecified", 4 "disassociated due to inactivity"). When None the
54
+ driver picks a sensible default. This is admin-state disconnect —
55
+ for an explicit deauth frame use ``WifiTransitions.send_deauth``.
56
+
57
+ Raises KeyError if no station with that MAC is currently associated.
58
+ """
59
+ ...
@@ -0,0 +1,112 @@
1
+ """WiFi / WifiTransitions template.
2
+
3
+ Defines the abstract contract for IEEE 802.11k/v/r transition primitives
4
+ on a WiFi-capable device:
5
+
6
+ - Per-BSS admin enable for 802.11k (Radio Resource Management),
7
+ 802.11v (BSS Transition Management), and 802.11r (Fast Transition).
8
+ - Per-client triggered frames: BTM Request (802.11v), Neighbor Report
9
+ Request (802.11k), explicit deauth.
10
+
11
+ 802.11w (PMF) is set as a security parameter on WifiBss; reading it is
12
+ also done via WifiBss (no convenience-bleed snapshot here).
13
+
14
+ Per-client triggers may legitimately raise NotImplementedError on drivers
15
+ whose underlying stack only exposes coarse-grained "client steering"
16
+ features without raw frame-send (typical of controller-managed enterprise
17
+ stacks).
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ from typing import Protocol, runtime_checkable
23
+
24
+ from testprotocols.models.wifi import WifiTransitionConfig
25
+
26
+
27
+ @runtime_checkable
28
+ class WifiTransitions(Protocol):
29
+ """Abstract contract for 802.11 k/v/r admin and per-client transition primitives."""
30
+
31
+ # --- Per-BSS enables ---
32
+
33
+ def set_rrm_enabled(self, bss_name: str, enabled: bool) -> None:
34
+ """Enable or disable 802.11k Radio Resource Management on *bss_name*.
35
+
36
+ Raises KeyError if *bss_name* is not registered.
37
+ """
38
+ ...
39
+
40
+ def set_btm_enabled(self, bss_name: str, enabled: bool) -> None:
41
+ """Enable or disable 802.11v BSS Transition Management on *bss_name*.
42
+
43
+ Raises KeyError if *bss_name* is not registered.
44
+ """
45
+ ...
46
+
47
+ def set_ft_enabled(self, bss_name: str, enabled: bool, *, over_ds: bool = False) -> None:
48
+ """Enable or disable 802.11r Fast Transition on *bss_name*.
49
+
50
+ *over_ds* controls FT-over-the-DS (True) vs FT-over-the-air (False).
51
+ Ignored when *enabled* is False.
52
+ Raises KeyError if *bss_name* is not registered.
53
+ """
54
+ ...
55
+
56
+ def get_transition_config(self, bss_name: str) -> WifiTransitionConfig:
57
+ """Return the k/v/r configuration of *bss_name* (single read).
58
+
59
+ Raises KeyError if *bss_name* is not registered.
60
+ """
61
+ ...
62
+
63
+ # --- Per-client triggers ---
64
+
65
+ def send_btm_request(
66
+ self,
67
+ mac: str,
68
+ candidate_bssids: list[str] | None = None,
69
+ *,
70
+ disassoc_imminent: bool = False,
71
+ ) -> None:
72
+ """Send an 802.11v BSS Transition Management Request to the station *mac*.
73
+
74
+ *candidate_bssids* is an optional list of preferred candidate BSSIDs
75
+ for the client to consider roaming to (canonical lowercase
76
+ colon-separated). When None, the AP includes its default candidate set.
77
+
78
+ *disassoc_imminent* sets the "disassociation imminent" bit in the
79
+ request, prompting the client to roam faster on penalty of being
80
+ disassociated.
81
+
82
+ Raises KeyError if no station with that MAC is currently associated.
83
+ Drivers without raw BTM-frame support raise NotImplementedError.
84
+ """
85
+ ...
86
+
87
+ def send_neighbor_report_request(self, mac: str) -> None:
88
+ """Send an 802.11k Neighbor Report Request to the station *mac*.
89
+
90
+ The client's response (a Neighbor Report containing BSSes it can see)
91
+ is consumed by the driver's internal neighbour table. Tests that
92
+ need the AP-side view of neighbours read it via
93
+ ``WifiRf.get_neighbors``; the per-client client-side neighbour
94
+ report is not modelled in this release.
95
+
96
+ Raises KeyError if no station with that MAC is currently associated.
97
+ Drivers without raw 802.11k-NRR support raise NotImplementedError.
98
+ """
99
+ ...
100
+
101
+ def send_deauth(self, mac: str, reason_code: int = 2) -> None:
102
+ """Send an explicit IEEE 802.11 Deauthentication frame to the station *mac*.
103
+
104
+ *reason_code* is an IEEE 802.11 reason code (default 2 — "previous
105
+ authentication no longer valid"). This is a raw-frame primitive,
106
+ distinct from ``WifiStations.disconnect_station`` which is admin-state
107
+ disconnect.
108
+
109
+ Raises KeyError if no station with that MAC is currently associated.
110
+ Drivers without raw deauth-frame support raise NotImplementedError.
111
+ """
112
+ ...
@@ -0,0 +1,29 @@
1
+ Metadata-Version: 2.4
2
+ Name: testprotocols
3
+ Version: 0.1.0
4
+ Summary: Common Test Resource Layer — capability and device protocols for telco testing.
5
+ Author-email: Alottabits <rjvisser@alottabits.com>
6
+ Maintainer-email: Alottabits <rjvisser@alottabits.com>
7
+ License-Expression: Apache-2.0
8
+ Project-URL: Homepage, https://github.com/alottabits/testprotocols
9
+ Project-URL: Repository, https://github.com/alottabits/testprotocols
10
+ Project-URL: Issues, https://github.com/alottabits/testprotocols/issues
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Telecommunications Industry
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Software Development :: Testing
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.12
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ License-File: NOTICE
23
+ Dynamic: license-file
24
+
25
+ # testprotocols
26
+
27
+ Capability and device contracts as `typing.Protocol`s, plus their dataclass models. Pure stdlib, framework-neutral.
28
+
29
+ See the [monorepo README](../../README.md) for the full architecture.
@@ -0,0 +1,119 @@
1
+ testprotocols/__init__.py,sha256=lvF273gI4zv0uwudzrxxybmeM63-jSYACvEfkwCdHAg,7256
2
+ testprotocols/aftr_gateway.py,sha256=Zw70eyHTfeVjt3Y5D7-R71w3SB5RC86SESvWnjRhYLY,568
3
+ testprotocols/appliance_nat.py,sha256=lPtecOcM86-E5MFyq7ZhDC0X6Pn1B2NU0tMZZr3TPMI,1719
4
+ testprotocols/appliance_uplinks.py,sha256=x37O0ayGhuMSFr-J0LWPh9vgAUStWB1S0U0m_XOatMo,1072
5
+ testprotocols/appliance_vlans.py,sha256=oc7dNrMpuCdsA2T4lJ5dxmNzkqsBy3GBZc9_EPbEbbM,1811
6
+ testprotocols/arp_client.py,sha256=h5WEWqHj7TgTjUoz02GeudELmksHGKy76Ijid9_POyY,682
7
+ testprotocols/bgp.py,sha256=AvYL5Pck1MbzB5wplGEQb4MjC0VKQ6OhRy6Sg_fBFU0,2021
8
+ testprotocols/conntrack.py,sha256=HGyHoN6D7uDITQvG5e4U_juNThWtQgi35fdwc_eNnjw,4650
9
+ testprotocols/content_filtering.py,sha256=O-k5ln_PIukLHXSGs9z7tF_7cIKmdhUTUBF0kNV6V-k,1746
10
+ testprotocols/device_lifecycle.py,sha256=J97hSIJrqwAjmFCY99gI21WwhZwqvJRrCG5UIqpDVNA,1823
11
+ testprotocols/device_management.py,sha256=zPH8QSsst-2elfIqQtOO5HOuniSG5mftFVzi7mL0sws,1638
12
+ testprotocols/dhcp_client.py,sha256=IuvfPpHeu2x8uo0B5hme0OY7eOaWH8Js6xwwTMEzHVo,860
13
+ testprotocols/dhcp_server.py,sha256=0nX0Yx1Fi4g4Da_RnjBIFFYpHzC9dP1_UotEAxZ8iLw,557
14
+ testprotocols/discovery.py,sha256=CqvbmwyvCMnUBdPkEHNf5Sgo8k_0BOcKtoY_5xBjzf4,609
15
+ testprotocols/dns_client.py,sha256=1RqQSt_rT6osi-OIw-4ymb8nQFJSrWVNE3-MPuN1blI,550
16
+ testprotocols/file_transfer.py,sha256=YXkwRGaUz3Y_rVENZ9mLAteAo4mXDftKAQbRKq733UM,602
17
+ testprotocols/firewall.py,sha256=W9h6v7qbXs4FvzTiza9CGn-qRwMhd2y9owggSg3z-0U,4452
18
+ testprotocols/firewall_zones.py,sha256=2N1uca9zBQYIm0FK9gOarxldUQ5sNZDBpZ6H-69D5Lc,4355
19
+ testprotocols/first_hop_security.py,sha256=ai0Exebbr-Ttyc2FWaGkeO0QGYalGwvrkFaWqXZCIkU,2049
20
+ testprotocols/gateway_redundancy.py,sha256=iSMzUaSmB7STibsNYT5jcD-1pqpPO8LaY1uzgmCmVVg,908
21
+ testprotocols/http_client.py,sha256=us940z0C2OfG2gUp7EzCzTtfn_JG24_yNBTZoyRGlSY,854
22
+ testprotocols/http_server.py,sha256=dT-ook0zYrcnFCRVNhaF-YDjgpCjjLrVFrDW_aiXrUY,595
23
+ testprotocols/hw_console.py,sha256=a8A8cyIehni2Qn-lSNOm2NfytamO2Op4LAahkCa9qgU,1448
24
+ testprotocols/infra_controller.py,sha256=BYn_mO9KPOs-sO6IeZVK4n1AL7owJFmHkGrZZ8EWx1I,1016
25
+ testprotocols/interface_dhcp.py,sha256=94n3xYgzO44o8mLtOJ2H1r0cQujykcLg7G511wLpDjE,1095
26
+ testprotocols/ip_interface.py,sha256=cM5RNuz0iUpln6hK0k_zQhRJM7Vy2dO3wpr0Rj3R93Y,1959
27
+ testprotocols/ip_routing.py,sha256=MeA9OgkPA5lWwrN9ntShKUSBB1HVRsCEa_Zo1XDfJwo,1685
28
+ testprotocols/iperf_client.py,sha256=woPTHapGzfXWft2lwzOXk2hdmKrfhCjswhMs9ivm5Lg,1305
29
+ testprotocols/iperf_generator.py,sha256=x_DPhz8LO7ckCJNbLxE8OrqBlITJDDxo0WQKQyrK2-o,1296
30
+ testprotocols/iperf_server.py,sha256=HDr1yHVECSuVhL5rXpXJ0fw97yKUNUKR_rGY8TS7Chw,1107
31
+ testprotocols/l3_firewall.py,sha256=QYXYLko0Ul_lwB-Mwrou8ShZhCoxYM3NPeEDIgcGY00,2982
32
+ testprotocols/l7_firewall.py,sha256=V8H0kwjHceQw69f3nG5GUovLbI49RLvXsp4n9QOhCn8,1124
33
+ testprotocols/link_aggregation.py,sha256=91R4knkpBFMvRBdWd1F2eWeBwLE_x28vGe393AIqSVY,666
34
+ testprotocols/mac_table.py,sha256=hBy99JHxcmrCaAtqLZcwKktI3aanPVHeFRpdysQPSwk,613
35
+ testprotocols/multicast_client.py,sha256=oyP2T3L7jccDXlGuUPxCWekM-0kEsaX74mA0rgLsM3M,599
36
+ testprotocols/nat.py,sha256=yVqn7pK4QDhPyLkiYEXVE1ZdMbi7LOYzsPRzkRtCNLA,2924
37
+ testprotocols/netem_controller.py,sha256=7voR_knZoZuawTW43z_7kzb7gKTxkXNrOQFUv3-ZAT8,1454
38
+ testprotocols/network_endpoint.py,sha256=cyMgOqaamH1-YuLtNl2sHuyuQVA-6UMLg7dP5ZVEYgc,1202
39
+ testprotocols/network_probe.py,sha256=8Xcwtg_wqXAGn1GEaasaQzrukyyMV6Xbd69opMyOUBo,1058
40
+ testprotocols/nmap_scanner.py,sha256=R8e1rDpYYuJiiTd47v9gYVWkWNl7Dz0_Ux6ZQ53c6aQ,713
41
+ testprotocols/ntp_client.py,sha256=yXDxdLW69vR0KWFqdeEQ3UoagPL6AxG6glPF2Ct3q7I,751
42
+ testprotocols/ntp_config.py,sha256=zCsTgDNc3ov7H01FlzOtVbXlTPiiQVNNX-K15j1hiG0,757
43
+ testprotocols/ospf.py,sha256=1Tf9ZhWG8WQAgKXR1SYkyJ05MpFXYsRhPbhoWLBXFH4,633
44
+ testprotocols/packet_filter.py,sha256=T-2RGmmjNdZeIIyP-B-13vtgGedw7QMlF1h7ZqxjGZE,5154
45
+ testprotocols/pcap_capture.py,sha256=b3P3NTnuQDY8VDKqDbFPRKkcY6-1-ZFmQk1Qe6IEOHU,1063
46
+ testprotocols/pdu_controller.py,sha256=uW4lfaJmodhe3nh5HBL35AM_49gHhOlA9X1p3O53Zrg,664
47
+ testprotocols/port_poe.py,sha256=H8UHnkaboep7Iube2Ccigmebq256fqnfp9GMXMKQBXI,732
48
+ testprotocols/port_security.py,sha256=tayNi3hTkFICyUSQqZtaw9ya2RHQU4EgfT7A1Nx8GDk,742
49
+ testprotocols/port_status.py,sha256=2TcVSZxqpOHJV4vbkMxVnd-kWF9L7ga2bg7pVvv65rI,646
50
+ testprotocols/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
+ testprotocols/qoe_browser.py,sha256=Gp4J0BIzg5JEu1WoPM1uFVZs2GCaaO9c0Zxg5wtkrf4,1678
52
+ testprotocols/radius_client.py,sha256=HT6EiXzJQTPMHncHJDgeuibwzcQx386Z9chPZRyvbUo,2548
53
+ testprotocols/radius_server.py,sha256=potttcKVsy8Ju41jnZcpdzHvA5sH5cGMRbusv_hl-Nc,4474
54
+ testprotocols/routed_interfaces.py,sha256=hf75kNrYGoC37nlczk2CeJ4PkpPHyS_NhcGhNcK1kV0,942
55
+ testprotocols/router.py,sha256=qWWwMwNMQhNtBpGHcAbnVgprofYVpIfjkN6gXpV-uQk,1972
56
+ testprotocols/routing_read.py,sha256=uPSwrIF7sbABIldIbeK0_3jxHFtQHr5rz-DtA04sfEk,766
57
+ testprotocols/sdwan_policy_manager.py,sha256=7zbBedGTYZ3EJaFLoIO2X500w8HQUd66jLDcuqQREOg,2436
58
+ testprotocols/sip_phone.py,sha256=6qLankVypItcnYtyHQ2CEt9KP5p3-26ZxY9njBYNkPc,7155
59
+ testprotocols/sip_server.py,sha256=4Ww4iBUY5A9-QKJRv3eoRI15UAA0BxSomwrBd6knimw,7224
60
+ testprotocols/site_to_site_vpn.py,sha256=EfTq4nOZyaV3hyApkG53i_OLi4Zoe_RPJm5y5LtUJYw,2630
61
+ testprotocols/snmp_client.py,sha256=mutMvm4-oTZa_ZOI8oBmELQGpKTpU8kW85oVUI7NJP8,441
62
+ testprotocols/spanning_tree.py,sha256=SO57rydMW3KZOpZqvkNPd7UeXQU9xKusn-xhnocR3Lo,1222
63
+ testprotocols/static_routes.py,sha256=K4-wmClBPuRuIB_Y2W9qZCjkK56R0XjEjqu2seYbdxk,1646
64
+ testprotocols/storm_control.py,sha256=aukzvk5io18Yfl27BCBB9FcDfslCwa84LN1YL3PfPsg,714
65
+ testprotocols/streaming_server.py,sha256=_LBGejTCiVD6pX6QOzh_B1JvXml-szotXzSAa30cfy0,1105
66
+ testprotocols/switch_acl.py,sha256=rBVxkkny--m3ahoJu6H3x-UoD0IUxrp3UmvS6mWfevM,1044
67
+ testprotocols/switch_ports.py,sha256=J8Gn1gbsHbCX4aThnEgsOKyz5S3GmSxdPpx0_8OtOYU,851
68
+ testprotocols/switch_qos.py,sha256=Y4wThfzjQBfv5-wj94tYvgYA51uIfwNMhTVeLtLkv80,974
69
+ testprotocols/switch_vlans.py,sha256=Yeca82V7aT0cMJI8pExMyEwHWkUuhAJ5-38SgWy-1fQ,1068
70
+ testprotocols/syslog_config.py,sha256=1EY4BQjePbBBOORovmEncv2o9yQvyWtxWa3UletP-LE,1119
71
+ testprotocols/tftp_server.py,sha256=8tS65johIZ6kSOLWanyoE0cSMeNvGOVItRtzzB0RoCc,603
72
+ testprotocols/threat_prevention.py,sha256=tWxulxIxRE6w3MXnPjxzMIf4zG8G4k4p7Ilk2T86FaA,2011
73
+ testprotocols/tr069_client.py,sha256=FsTqefxFFcIIWgqscjqSAL4yDykSOTq_iVTn2VJZeHk,1771
74
+ testprotocols/tr069_server.py,sha256=sHe6dEigPVobOW-Txh2TI72CZatm8ef0yU1SDmSQBGs,4036
75
+ testprotocols/traffic_shaping.py,sha256=BXKUd4pQt4zsOUqCT3Cg22koVbT3r3EFjaTDqvykXyc,2162
76
+ testprotocols/upnp_client.py,sha256=X6LUBQ63Yfugo9qmPFwTImKrnW5rabUO_PkgOwz54SM,860
77
+ testprotocols/vlan_client.py,sha256=3fgjMLbBRkObODo1FD9BkJA-_ApKDQrzfc7HdAVE3Ew,578
78
+ testprotocols/wan_link_admin.py,sha256=w-jSBJYXAIPBjkbGt63si1sC3-3qd8AwM03zKNYnra4,1398
79
+ testprotocols/wifi_bss.py,sha256=d4Zo1LgULf44dRLgWcbUMFrg4YiDXxFPLMGKWr7YCs0,6368
80
+ testprotocols/wifi_client.py,sha256=xw5N-2t5PoRHxaWjnXYIE9W_tQWRFij1RqtiI38ZZ_o,2089
81
+ testprotocols/wifi_mesh.py,sha256=qWk-eSXfcfEKeCnCVF5f-7z7G8Kc306r9VCfbkx_6d4,10380
82
+ testprotocols/wifi_onboarding.py,sha256=oZ309o205A5g5fxvcJv-I1gEDY9Yol7_1a6TXskkJrw,4022
83
+ testprotocols/wifi_radio.py,sha256=gzxke_kFX5SuBnRegZzi5hDf9kIbM0IGeszO3IN8gxI,5614
84
+ testprotocols/wifi_rf.py,sha256=OjDGlSqkgjaWONIYxXc9l-dROkqvqgogJivTUrYt4OU,2779
85
+ testprotocols/wifi_stations.py,sha256=E9FEi8Q4OqC-GJNF15BlubBWVhSrT-NT0Q0WFgoWOAk,2219
86
+ testprotocols/wifi_transitions.py,sha256=5sFrtmoussmMYXCywmLoVcYdWoOWf_npCZIA-ltZWVk,4200
87
+ testprotocols/devices/__init__.py,sha256=_AYiKlz-esIIwqz9pgj_EpBxraKwhGy39jDmsmOYDKA,1531
88
+ testprotocols/devices/base.py,sha256=tQyKUmSsnSk_qUWlCEz3iyHklTOdLek1iTy0xYh5EZo,1799
89
+ testprotocols/devices/client.py,sha256=7Mh-gS-8ERqBmD0A5fNpuZ6VL5WHZkT6dPD7I6AcfDQ,5191
90
+ testprotocols/devices/cpe.py,sha256=csfTdnHcrlS9DRNrnsrYpEmXJ9irqYgmGZlVZKeX5_k,2486
91
+ testprotocols/devices/infra.py,sha256=fvNC6sh5mcS_ae19_V15IoVOe6c0PzuZui2POZqeaQw,2127
92
+ testprotocols/devices/sdwan.py,sha256=h_-4gGcp7OS8nlDpXRIcudfYBJ3Y6jSWhGmwsTOmxmU,4062
93
+ testprotocols/devices/switch.py,sha256=il9FGNYSlHfBzHt6voHK4HccPsU6rBNemUyQ5rvBiUw,4527
94
+ testprotocols/devices/traffic.py,sha256=n3s3STJruOJ2Z_o7ROiqrHLfEEXeXTvRebR0ftPBIOA,2027
95
+ testprotocols/devices/voice.py,sha256=iGwYqgPQugKgBShIKoTO7EAQg5mfDCcCCcFNd3cpVoE,2732
96
+ testprotocols/devices/wan.py,sha256=v0X7eVwnMfopY99EO8pA1Y_eWcY900T1h0m_d89jHIY,2272
97
+ testprotocols/models/__init__.py,sha256=bCgJy2XhVbf0Dwo8smKr80ywAa_kTeM_z6jvAx23NKw,6255
98
+ testprotocols/models/dhcp.py,sha256=Q-02veO0kRriYXETSDS0Pn20sJZox3dTm7PQB5hpsEE,685
99
+ testprotocols/models/firewall.py,sha256=Na-gduCszIUGE8PM2uw7QmFhF-zUxNhUMtgWiKeLBUs,6375
100
+ testprotocols/models/impairment.py,sha256=-jQTa2kgXf7-5y3wyTsQVF8q_J9s51apbtEdDw46adw,462
101
+ testprotocols/models/l2_common.py,sha256=HAbiL7jTt2DJgp6qt3yre55ROguyxKlOmz0se2HcWh0,1395
102
+ testprotocols/models/multicast.py,sha256=4nOhMmDcR1jcLNwJMk39xCZqM2EmSy1b-sw2JyF0zNU,597
103
+ testprotocols/models/networking.py,sha256=5gnTaPSATiDmBDJRLayuHn01D7TiNbfmh25FqTh0eAM,1600
104
+ testprotocols/models/packets.py,sha256=3t6QShpj5GpszTYn8JgkmbpPluWkjoLUrh7GmCNufhE,533
105
+ testprotocols/models/qoe.py,sha256=9FdMT_N9qOOXBvpHrlySKoAvtFR9z1mzmGiSUT7CUgQ,854
106
+ testprotocols/models/radius.py,sha256=vfXOa6bgJ776NSEfqSbtCDvAhuiPTd76g6FEp60Y38Q,1939
107
+ testprotocols/models/sdwan_appliance.py,sha256=dx-V1Z5FWGYPYoNiJpyGCtvWCkLwM1Tgguq6BlhfPFw,17056
108
+ testprotocols/models/switch.py,sha256=Ayp0WwksfErDqcWOAGSD0ex7VU6KRl1ZlP18WbC5sTY,7223
109
+ testprotocols/models/switch_routing.py,sha256=va-F2GUqcEAo9AmiHM_BVOHvAWfpVkylmtKnBuwVc2s,3205
110
+ testprotocols/models/tr069.py,sha256=DrN1tgU5JX2YebwXVe2PF_FkTXrJmv74C4t7nOhzWqM,1301
111
+ testprotocols/models/traffic.py,sha256=js2OPKkrUAmyXwJJ4fucZcWtW0amb1mtAn_KU--63ko,688
112
+ testprotocols/models/wan_edge.py,sha256=cQJ6JQg7l5boale6hTeR-Ej2-xaSLFG5KgItGv1Dga0,2667
113
+ testprotocols/models/wifi.py,sha256=n5-Hq1BkQ-eKvnt-rL1RPSZr00MEgwoFRK755ybaLF8,5520
114
+ testprotocols-0.1.0.dist-info/licenses/LICENSE,sha256=No8aJnn7SvNkXpcvHTMrPDGhtZo-usV9AitDA3bEI2s,11340
115
+ testprotocols-0.1.0.dist-info/licenses/NOTICE,sha256=l1ggTluhhtKw7DStHRkOpLGibFJw2CjbJXdd2W0Lbuk,404
116
+ testprotocols-0.1.0.dist-info/METADATA,sha256=5ruEpGBNWZE3wr_iWHzvSzA4WjD62hLoBB3p73gmdzY,1203
117
+ testprotocols-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
118
+ testprotocols-0.1.0.dist-info/top_level.txt,sha256=v_BBlzjS0Tnd8erFI6K7yel5vGoC3Snamh0V51wjs_c,14
119
+ testprotocols-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+