python-netgear-switch-library 0.0.post290__tar.gz → 0.0.post321__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.
Files changed (380) hide show
  1. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/.github/workflows/ci.yml +28 -0
  2. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/.gitignore +4 -0
  3. python_netgear_switch_library-0.0.post321/.readthedocs.yaml +32 -0
  4. python_netgear_switch_library-0.0.post321/CLAUDE.md +203 -0
  5. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/PKG-INFO +28 -1
  6. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/README.md +17 -0
  7. python_netgear_switch_library-0.0.post321/docs/Makefile +30 -0
  8. python_netgear_switch_library-0.0.post321/docs/_ext/filelinks.py +275 -0
  9. python_netgear_switch_library-0.0.post321/docs/_ext/support_tables.py +291 -0
  10. python_netgear_switch_library-0.0.post321/docs/_static/ngsw.css +27 -0
  11. python_netgear_switch_library-0.0.post321/docs/api/cli.rst +39 -0
  12. python_netgear_switch_library-0.0.post321/docs/api/core.rst +31 -0
  13. python_netgear_switch_library-0.0.post321/docs/api/facades.rst +25 -0
  14. python_netgear_switch_library-0.0.post321/docs/api/index.rst +53 -0
  15. python_netgear_switch_library-0.0.post321/docs/api/mcp.rst +10 -0
  16. python_netgear_switch_library-0.0.post321/docs/api/operations.rst +35 -0
  17. python_netgear_switch_library-0.0.post321/docs/api/protocols.rst +67 -0
  18. python_netgear_switch_library-0.0.post321/docs/api/transport.rst +53 -0
  19. python_netgear_switch_library-0.0.post321/docs/api/virtual.rst +60 -0
  20. python_netgear_switch_library-0.0.post321/docs/cli.rst +127 -0
  21. python_netgear_switch_library-0.0.post321/docs/conf.py +137 -0
  22. python_netgear_switch_library-0.0.post321/docs/development.rst +129 -0
  23. python_netgear_switch_library-0.0.post321/docs/fake/index.rst +120 -0
  24. python_netgear_switch_library-0.0.post321/docs/fake/internals.rst +197 -0
  25. python_netgear_switch_library-0.0.post321/docs/fake/serving.rst +180 -0
  26. python_netgear_switch_library-0.0.post321/docs/fake/testing.rst +383 -0
  27. python_netgear_switch_library-0.0.post321/docs/guide/concepts.rst +180 -0
  28. python_netgear_switch_library-0.0.post321/docs/guide/configuration.rst +173 -0
  29. python_netgear_switch_library-0.0.post321/docs/guide/installation.rst +126 -0
  30. python_netgear_switch_library-0.0.post321/docs/guide/principles.rst +148 -0
  31. python_netgear_switch_library-0.0.post321/docs/guide/quickstart.rst +173 -0
  32. python_netgear_switch_library-0.0.post321/docs/guide/reading.rst +178 -0
  33. python_netgear_switch_library-0.0.post321/docs/guide/writing.rst +195 -0
  34. python_netgear_switch_library-0.0.post321/docs/index.rst +112 -0
  35. python_netgear_switch_library-0.0.post321/docs/mcp.rst +140 -0
  36. python_netgear_switch_library-0.0.post321/docs/models/index.rst +175 -0
  37. python_netgear_switch_library-0.0.post321/docs/models/support.rst +109 -0
  38. python_netgear_switch_library-0.0.post321/docs/protocols/cli.rst +143 -0
  39. python_netgear_switch_library-0.0.post321/docs/protocols/http.rst +112 -0
  40. python_netgear_switch_library-0.0.post321/docs/protocols/index.rst +75 -0
  41. python_netgear_switch_library-0.0.post321/docs/protocols/nsdp.rst +126 -0
  42. python_netgear_switch_library-0.0.post321/docs/protocols/snmp.rst +171 -0
  43. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/pyproject.toml +17 -0
  44. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/__init__.py +43 -1
  45. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/_dispatch.py +56 -0
  46. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/_version.py +2 -2
  47. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/aio_api.py +174 -104
  48. python_netgear_switch_library-0.0.post321/src/netgear_switch/capabilities.py +414 -0
  49. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/cli/main.py +11 -1
  50. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/cli/resolve.py +14 -0
  51. python_netgear_switch_library-0.0.post321/src/netgear_switch/cli_write.py +666 -0
  52. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/errors.py +14 -0
  53. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/http_read.py +250 -33
  54. python_netgear_switch_library-0.0.post321/src/netgear_switch/http_write.py +1348 -0
  55. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/mcp/server.py +93 -13
  56. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/nsdp_read.py +65 -11
  57. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/nsdp_write.py +148 -38
  58. python_netgear_switch_library-0.0.post321/src/netgear_switch/protocols/cli/commands.py +440 -0
  59. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/cli/parse.py +15 -10
  60. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/http/endpoints.py +328 -21
  61. python_netgear_switch_library-0.0.post321/src/netgear_switch/protocols/http/forms.py +273 -0
  62. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/http/parse.py +650 -9
  63. python_netgear_switch_library-0.0.post321/src/netgear_switch/protocols/http/types.py +202 -0
  64. python_netgear_switch_library-0.0.post321/src/netgear_switch/protocols/nsdp/auth.py +111 -0
  65. python_netgear_switch_library-0.0.post321/src/netgear_switch/protocols/nsdp/client.py +131 -0
  66. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/nsdp/parsers.py +26 -1
  67. python_netgear_switch_library-0.0.post321/src/netgear_switch/protocols/nsdp/protocol.py +301 -0
  68. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/nsdp/types.py +37 -4
  69. python_netgear_switch_library-0.0.post321/src/netgear_switch/protocols/nsdp/write.py +169 -0
  70. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/snmp/oids.py +30 -0
  71. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/registry.py +69 -0
  72. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/snmp_write.py +449 -27
  73. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/sync_api.py +244 -134
  74. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/aio/nsdp_udp.py +48 -7
  75. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/http/client.py +13 -2
  76. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/sync/nsdp_udp.py +47 -7
  77. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/sync/snmp_netsnmp_cli.py +18 -1
  78. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/cli_fastpath.py +45 -2
  79. python_netgear_switch_library-0.0.post321/src/netgear_switch/virtual/faces/cli.py +421 -0
  80. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/faces/http.py +150 -8
  81. python_netgear_switch_library-0.0.post321/src/netgear_switch/virtual/faces/nsdp.py +237 -0
  82. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/faces/snmp.py +15 -0
  83. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/seed.py +274 -2
  84. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/server.py +2 -1
  85. python_netgear_switch_library-0.0.post321/src/netgear_switch/virtual/state.py +1446 -0
  86. python_netgear_switch_library-0.0.post321/src/netgear_switch/virtual/web_fastpath_vlan.py +421 -0
  87. python_netgear_switch_library-0.0.post321/src/netgear_switch/virtual/web_fastpath_xui.py +287 -0
  88. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/web_gs110emx.py +34 -0
  89. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/web_gs110emx_templates.py +6 -1
  90. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/web_gsm7228ps.py +41 -2
  91. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/web_gsm7252ps.py +182 -19
  92. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/web_m4300.py +77 -11
  93. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/capture_parity.py +8 -2
  94. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_op_coverage.py +4 -0
  95. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/equivalence.py +15 -8
  96. python_netgear_switch_library-0.0.post321/tests/fixtures/http/gsm7228ps_ipConfiguration.html +236 -0
  97. python_netgear_switch_library-0.0.post321/tests/fixtures/http/gsm7228ps_vlanPortCfg_vlan5.html +769 -0
  98. python_netgear_switch_library-0.0.post321/tests/fixtures/http/gsm7252ps_ipConfiguration.html +200 -0
  99. python_netgear_switch_library-0.0.post321/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan1.html +792 -0
  100. python_netgear_switch_library-0.0.post321/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan141.html +791 -0
  101. python_netgear_switch_library-0.0.post321/tests/fixtures/http/m4300_16x_lldpRemoteInventory.html +402 -0
  102. python_netgear_switch_library-0.0.post321/tests/fixtures/http/m4300_16x_mgmtVlanIpv4Configuration.html +514 -0
  103. python_netgear_switch_library-0.0.post321/tests/fixtures/http/m4300_16x_poeInterfaceConfiguration.html +1046 -0
  104. python_netgear_switch_library-0.0.post321/tests/fixtures/http/m4300_16x_portsConfiguration.html +1277 -0
  105. python_netgear_switch_library-0.0.post321/tests/fixtures/http/m4300_16x_vlanportcfg_vlan4.html +643 -0
  106. python_netgear_switch_library-0.0.post321/tests/fixtures/http/m4300_24x_poeInterfaceConfiguration.html +612 -0
  107. python_netgear_switch_library-0.0.post321/tests/fixtures/http/m4300_lldpRemoteInventory.html +365 -0
  108. python_netgear_switch_library-0.0.post321/tests/fixtures/http/m4300_mgmtVlanIpv4Configuration.html +512 -0
  109. python_netgear_switch_library-0.0.post321/tests/fixtures/http/m4300_vlanportcfg_vlan1.html +663 -0
  110. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/http/test_endpoints.py +12 -1
  111. python_netgear_switch_library-0.0.post321/tests/protocols/nsdp/test_auth.py +67 -0
  112. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/nsdp/test_parsers.py +12 -2
  113. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_aio_api.py +58 -25
  114. python_netgear_switch_library-0.0.post321/tests/test_capabilities.py +338 -0
  115. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_cli_read.py +9 -7
  116. python_netgear_switch_library-0.0.post321/tests/test_cli_vlan_write.py +836 -0
  117. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_cross_backend_equivalence.py +32 -1
  118. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_http_equivalence.py +7 -2
  119. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_http_read.py +174 -26
  120. python_netgear_switch_library-0.0.post321/tests/test_http_vlan_membership.py +551 -0
  121. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_http_write.py +20 -8
  122. python_netgear_switch_library-0.0.post321/tests/test_http_xui_writes.py +644 -0
  123. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_mcp_server.py +56 -7
  124. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_nsdp_read.py +69 -1
  125. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_nsdp_write.py +81 -2
  126. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_snmp_write.py +99 -0
  127. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_sync_api.py +119 -23
  128. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/transport/test_nsdp_udp_sync.py +17 -4
  129. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/transport/test_snmp_netsnmp_cli.py +35 -0
  130. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_cli_cross_backend.py +21 -1
  131. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_state_seed.py +48 -0
  132. python_netgear_switch_library-0.0.post321/tests/virtual/test_switchport_vlan_write.py +947 -0
  133. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_virtual_http_face.py +19 -6
  134. python_netgear_switch_library-0.0.post321/tests/virtual/test_virtual_nsdp_face.py +294 -0
  135. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_virtual_snmp_face.py +12 -3
  136. python_netgear_switch_library-0.0.post290/src/netgear_switch/cli_write.py +0 -89
  137. python_netgear_switch_library-0.0.post290/src/netgear_switch/http_write.py +0 -682
  138. python_netgear_switch_library-0.0.post290/src/netgear_switch/protocols/cli/commands.py +0 -237
  139. python_netgear_switch_library-0.0.post290/src/netgear_switch/protocols/http/forms.py +0 -76
  140. python_netgear_switch_library-0.0.post290/src/netgear_switch/protocols/http/types.py +0 -48
  141. python_netgear_switch_library-0.0.post290/src/netgear_switch/protocols/nsdp/auth.py +0 -34
  142. python_netgear_switch_library-0.0.post290/src/netgear_switch/protocols/nsdp/client.py +0 -67
  143. python_netgear_switch_library-0.0.post290/src/netgear_switch/protocols/nsdp/protocol.py +0 -208
  144. python_netgear_switch_library-0.0.post290/src/netgear_switch/protocols/nsdp/write.py +0 -99
  145. python_netgear_switch_library-0.0.post290/src/netgear_switch/virtual/faces/cli.py +0 -114
  146. python_netgear_switch_library-0.0.post290/src/netgear_switch/virtual/faces/nsdp.py +0 -129
  147. python_netgear_switch_library-0.0.post290/src/netgear_switch/virtual/state.py +0 -795
  148. python_netgear_switch_library-0.0.post290/tests/protocols/nsdp/test_auth.py +0 -24
  149. python_netgear_switch_library-0.0.post290/tests/virtual/test_virtual_nsdp_face.py +0 -57
  150. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/.github/workflows/deb.yml +0 -0
  151. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/.github/workflows/publish-pypi.yml +0 -0
  152. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/LICENSE +0 -0
  153. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/RELEASING.md +0 -0
  154. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/debian/changelog +0 -0
  155. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/debian/control +0 -0
  156. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/debian/copyright +0 -0
  157. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/debian/rules +0 -0
  158. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/debian/source/format +0 -0
  159. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/docs/superpowers/plans/2026-07-15-foundation.md +0 -0
  160. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/docs/superpowers/plans/2026-07-17-slice-02-snmp-read-core.md +0 -0
  161. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/docs/superpowers/plans/2026-07-17-slice-03-read-apis.md +0 -0
  162. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/docs/superpowers/plans/2026-07-18-slice-04-snmp-write.md +0 -0
  163. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/docs/superpowers/plans/2026-07-18-slice-05-nsdp.md +0 -0
  164. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/docs/superpowers/plans/2026-07-18-slice-06-http.md +0 -0
  165. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/docs/superpowers/plans/2026-07-18-slice-07-cli.md +0 -0
  166. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/docs/superpowers/plans/2026-07-18-slice-08-packaging-ci.md +0 -0
  167. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/docs/superpowers/plans/2026-07-23-gsm7252ps-http-xe-dialect.md +0 -0
  168. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/docs/superpowers/specs/2026-07-15-netgear-control-library-design.md +0 -0
  169. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/docs/superpowers/specs/2026-07-23-gsm7252ps-http-xe-dialect-design.md +0 -0
  170. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/packaging/apt-index.html +0 -0
  171. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/packaging/ci-build.sh +0 -0
  172. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/packaging/deb-version.py +0 -0
  173. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/cli/__init__.py +0 -0
  174. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/cli/capture.py +0 -0
  175. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/cli/context.py +0 -0
  176. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/cli/format.py +0 -0
  177. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/cli/safety.py +0 -0
  178. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/cli_read.py +0 -0
  179. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/config.py +0 -0
  180. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/mcp/__init__.py +0 -0
  181. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/models.py +0 -0
  182. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/__init__.py +0 -0
  183. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/cli/__init__.py +0 -0
  184. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/http/__init__.py +0 -0
  185. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/http/crypt.py +0 -0
  186. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/http/session.py +0 -0
  187. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/nsdp/__init__.py +0 -0
  188. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/snmp/__init__.py +0 -0
  189. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/snmp/client.py +0 -0
  190. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/snmp/parse.py +0 -0
  191. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/protocols/snmp/write.py +0 -0
  192. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/py.typed +0 -0
  193. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/snmp_read.py +0 -0
  194. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/__init__.py +0 -0
  195. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/aio/__init__.py +0 -0
  196. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/aio/snmp_pysnmp.py +0 -0
  197. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/cli/__init__.py +0 -0
  198. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/cli/console.py +0 -0
  199. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/cli/session.py +0 -0
  200. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/cli/ssh.py +0 -0
  201. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/cli/telnet.py +0 -0
  202. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/http/__init__.py +0 -0
  203. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/transport/sync/__init__.py +0 -0
  204. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/__init__.py +0 -0
  205. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/faces/__init__.py +0 -0
  206. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/faces/mibview.py +0 -0
  207. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/web.py +0 -0
  208. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/web_gs105pe.py +0 -0
  209. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/src/netgear_switch/virtual/web_gs728tpp.py +0 -0
  210. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_capture.py +0 -0
  211. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_cli_integration.py +0 -0
  212. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_control_poe_port.py +0 -0
  213. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_control_vlan_ip.py +0 -0
  214. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_format.py +0 -0
  215. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_main_framework.py +0 -0
  216. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_new_commands.py +0 -0
  217. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_prompt_wiring.py +0 -0
  218. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_read_commands.py +0 -0
  219. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_resolve.py +0 -0
  220. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_safety.py +0 -0
  221. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/cli/test_serve.py +0 -0
  222. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/conftest.py +0 -0
  223. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/captures/gsm7228ps.json +0 -0
  224. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/captures/gsm7252ps.json +0 -0
  225. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/captures/m4300-16x.json +0 -0
  226. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/captures/m4300-24x.json +0 -0
  227. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7228ps_environment.txt +0 -0
  228. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7228ps_lldp.txt +0 -0
  229. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7228ps_mac_table.txt +0 -0
  230. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7228ps_network.txt +0 -0
  231. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7228ps_poe.txt +0 -0
  232. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7228ps_port_all.txt +0 -0
  233. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7228ps_show_version.txt +0 -0
  234. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7228ps_vlan.txt +0 -0
  235. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7228ps_vlan_brief.txt +0 -0
  236. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7228ps_vlan_port_all.txt +0 -0
  237. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7252ps_show_environment.txt +0 -0
  238. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7252ps_show_interface_ethernet_1_0_1.txt +0 -0
  239. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7252ps_show_lldp_remote_device_all.txt +0 -0
  240. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7252ps_show_mac_addr_table.txt +0 -0
  241. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7252ps_show_network.txt +0 -0
  242. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7252ps_show_poe_port_info_all.txt +0 -0
  243. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7252ps_show_port_all.txt +0 -0
  244. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7252ps_show_version.txt +0 -0
  245. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7252ps_show_vlan_90.txt +0 -0
  246. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7252ps_show_vlan_brief.txt +0 -0
  247. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/gsm7252ps_show_vlan_port_all.txt +0 -0
  248. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_environment.txt +0 -0
  249. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_interface_ethernet_1_0_1.txt +0 -0
  250. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_ip_management.txt +0 -0
  251. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_lldp_remote_device_all.txt +0 -0
  252. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_mac_addr_table.txt +0 -0
  253. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_poe_port_info_all.txt +0 -0
  254. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_port_all.txt +0 -0
  255. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_version.txt +0 -0
  256. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_vlan.txt +0 -0
  257. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_vlan_1.txt +0 -0
  258. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_vlan_4.txt +0 -0
  259. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_vlan_5.txt +0 -0
  260. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_16x_show_vlan_port_all.txt +0 -0
  261. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_24x_show_environment.txt +0 -0
  262. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_24x_show_interface_ethernet_1_0_1.txt +0 -0
  263. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_24x_show_ip_management.txt +0 -0
  264. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_24x_show_lldp_remote_device_all.txt +0 -0
  265. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_24x_show_mac_addr_table.txt +0 -0
  266. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_24x_show_port_all.txt +0 -0
  267. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_24x_show_version.txt +0 -0
  268. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_24x_show_vlan.txt +0 -0
  269. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_24x_show_vlan_5.txt +0 -0
  270. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_24x_show_vlan_90.txt +0 -0
  271. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/cli/m4300_24x_show_vlan_port_all.txt +0 -0
  272. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs105pe_membership.html +0 -0
  273. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs105pe_portstats.html +0 -0
  274. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs105pe_pvid.html +0 -0
  275. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs105pe_status.html +0 -0
  276. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs105pe_switch_info.html +0 -0
  277. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs105pe_vlancfg.html +0 -0
  278. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs110emx_cf8021q.html +0 -0
  279. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs110emx_interface_stats.html +0 -0
  280. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs110emx_login.html +0 -0
  281. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs110emx_port_settings.html +0 -0
  282. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs110emx_pvid.html +0 -0
  283. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs110emx_redirect.html +0 -0
  284. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs110emx_sysinfo.html +0 -0
  285. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs110emx_vlanmembership.html +0 -0
  286. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs305ep_dashboard.html +0 -0
  287. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs305ep_login.html +0 -0
  288. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs305ep_membership.html +0 -0
  289. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs305ep_poestatus.html +0 -0
  290. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs305ep_portstats.html +0 -0
  291. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs305ep_pvid.html +0 -0
  292. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs305ep_vlancfg.html +0 -0
  293. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs728tpp_device_info_and_sensors.xml +0 -0
  294. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs728tpp_lldp.xml +0 -0
  295. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs728tpp_macs.xml +0 -0
  296. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs728tpp_mgmt_ip.xml +0 -0
  297. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs728tpp_poe.xml +0 -0
  298. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs728tpp_ports.xml +0 -0
  299. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs728tpp_pvids_membership.xml +0 -0
  300. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs728tpp_vlan_membership_per_vlan.xml +0 -0
  301. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gs728tpp_vlans.xml +0 -0
  302. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7228ps_basicAddressTable.html +0 -0
  303. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7228ps_lldpRemoteInventory.html +0 -0
  304. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7228ps_poeInterfaceConfiguration.html +0 -0
  305. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7228ps_portPvidConfiguration.html +0 -0
  306. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7228ps_portStatistics.html +0 -0
  307. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7228ps_portsConfiguration.html +0 -0
  308. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7228ps_sysInfo.html +0 -0
  309. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7228ps_vlanStatus.html +0 -0
  310. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7252ps_basicAddressTable.html +0 -0
  311. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7252ps_lldpRemoteInventory.html +0 -0
  312. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7252ps_login.html +0 -0
  313. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7252ps_poeInterfaceConfiguration.html +0 -0
  314. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7252ps_portPvidConfiguration.html +0 -0
  315. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7252ps_portStatistics.html +0 -0
  316. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7252ps_portsConfiguration.html +0 -0
  317. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7252ps_sysInfo.html +0 -0
  318. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/gsm7252ps_vlanStatus.html +0 -0
  319. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/m4300_addresstable.html +0 -0
  320. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/m4300_ports.html +0 -0
  321. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/m4300_portstats.html +0 -0
  322. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/m4300_pvid.html +0 -0
  323. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/m4300_sysinfo.html +0 -0
  324. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/http/m4300_vlanstatus.html +0 -0
  325. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/snmp/gsm7252ps_fans.txt +0 -0
  326. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/snmp/gsm7252ps_ifhighspeed.txt +0 -0
  327. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/snmp/gsm7252ps_ifoperstatus.txt +0 -0
  328. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/fixtures/snmp/gsm7252ps_psu.txt +0 -0
  329. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/http_specs.py +0 -0
  330. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/cli/test_cli_parse.py +0 -0
  331. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/http/test_crypt.py +0 -0
  332. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/http/test_forms.py +0 -0
  333. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/http/test_parse.py +0 -0
  334. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/nsdp/test_protocol.py +0 -0
  335. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/nsdp/test_write_frame.py +0 -0
  336. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/snmp/test_client.py +0 -0
  337. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/snmp/test_oids.py +0 -0
  338. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/snmp/test_parse_lldp_macs.py +0 -0
  339. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/snmp/test_parse_mgmt_ip.py +0 -0
  340. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/snmp/test_parse_poe_sensors.py +0 -0
  341. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/snmp/test_parse_ports.py +0 -0
  342. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/snmp/test_parse_system_info.py +0 -0
  343. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/snmp/test_parse_vlans.py +0 -0
  344. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/protocols/snmp/test_write_encode.py +0 -0
  345. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_cli_write.py +0 -0
  346. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_config.py +0 -0
  347. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_deb_version.py +0 -0
  348. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_dispatch.py +0 -0
  349. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_errors.py +0 -0
  350. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_facade_equivalence.py +0 -0
  351. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_http_dispatch.py +0 -0
  352. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_import.py +0 -0
  353. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_models.py +0 -0
  354. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_models_snmp_read.py +0 -0
  355. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_nsdp_integration.py +0 -0
  356. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_public_api.py +0 -0
  357. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_quality_gates.py +0 -0
  358. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_registry.py +0 -0
  359. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_snmp_integration.py +0 -0
  360. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_snmp_read.py +0 -0
  361. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_version.py +0 -0
  362. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/test_write_equivalence.py +0 -0
  363. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/transport/_fastpath_fake.py +0 -0
  364. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/transport/test_cli_console.py +0 -0
  365. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/transport/test_cli_scp_cert.py +0 -0
  366. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/transport/test_cli_telnet.py +0 -0
  367. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/transport/test_http_client.py +0 -0
  368. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/transport/test_set_transport.py +0 -0
  369. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/transport/test_snmp_pysnmp.py +0 -0
  370. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/transport/test_value_parity.py +0 -0
  371. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_cli_gsm7228ps_parity.py +0 -0
  372. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_gsm7228ps_seed.py +0 -0
  373. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_m4300_seeds.py +0 -0
  374. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_mibview.py +0 -0
  375. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_mutable_state.py +0 -0
  376. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_nsdp_state.py +0 -0
  377. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_serve_daemon.py +0 -0
  378. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_snmp_write_face.py +0 -0
  379. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/tests/virtual/test_web_projection.py +0 -0
  380. {python_netgear_switch_library-0.0.post290 → python_netgear_switch_library-0.0.post321}/uv.lock +0 -0
@@ -46,3 +46,31 @@ jobs:
46
46
 
47
47
  - name: Tests + coverage gate (>= 90)
48
48
  run: uv run pytest
49
+
50
+ docs:
51
+ # The published documentation generates its model/backend support tables
52
+ # from the library itself and links every file reference to the file, so a
53
+ # stale table or a renamed file is a build failure rather than a page that
54
+ # quietly misleads. Warnings are errors here exactly as they are on Read
55
+ # the Docs (see .readthedocs.yaml's fail_on_warning).
56
+ runs-on: ubuntu-latest
57
+ timeout-minutes: 15
58
+ steps:
59
+ - uses: actions/checkout@v5
60
+ with:
61
+ fetch-depth: 0 # full history so hatch-vcs can derive the version
62
+
63
+ - uses: astral-sh/setup-uv@v7
64
+
65
+ - name: Sync the docs extra
66
+ run: uv sync --extra docs
67
+
68
+ - name: Build the documentation (warnings are errors)
69
+ run: uv run sphinx-build -W --keep-going -b html docs docs/_build/html
70
+
71
+ - name: Upload the built documentation
72
+ uses: actions/upload-artifact@v4
73
+ with:
74
+ name: docs-html
75
+ path: docs/_build/html
76
+ retention-days: 7
@@ -23,6 +23,10 @@ htmlcov/
23
23
  # hatch-vcs writes this at build/editable-install time; it is derived from git.
24
24
  /src/netgear_switch/_version.py
25
25
 
26
+ # Sphinx build output (docs/Makefile's BUILDDIR). Read the Docs builds from a
27
+ # clean checkout; a local `make -C docs html` writes here.
28
+ /docs/_build/
29
+
26
30
  # Debian build byproducts (dpkg-buildpackage writes to the parent dir; local
27
31
  # builds may drop these in-tree).
28
32
  /built-debs/
@@ -0,0 +1,32 @@
1
+ # Read the Docs build configuration.
2
+ # https://docs.readthedocs.io/en/stable/config-file/v2.html
3
+ version: 2
4
+
5
+ build:
6
+ os: ubuntu-24.04
7
+ tools:
8
+ python: "3.12"
9
+ jobs:
10
+ post_checkout:
11
+ # This project's version is derived from git by hatch-vcs (see
12
+ # pyproject.toml's [tool.hatch.version]). Read the Docs makes a SHALLOW
13
+ # clone with no tags, which makes that derivation fail the build. Fetch
14
+ # the full history + tags so the version the docs display is the real
15
+ # one. `|| true` keeps a build working if the clone is already complete.
16
+ - git fetch --unshallow || true
17
+ - git fetch --tags || true
18
+
19
+ sphinx:
20
+ configuration: docs/conf.py
21
+ # A warning here means a broken cross-reference, a missing document, or a
22
+ # documented file path that no longer exists (see docs/_ext/filelinks.py).
23
+ # All three are documentation bugs, so they fail the build rather than
24
+ # shipping a page that quietly lies.
25
+ fail_on_warning: true
26
+
27
+ python:
28
+ install:
29
+ - method: pip
30
+ path: .
31
+ extra_requirements:
32
+ - docs
@@ -0,0 +1,203 @@
1
+ # python-netgear-switch-library — working agreement
2
+
3
+ These are **non-negotiable design principles** for this library. They override
4
+ convenience, they override "it works on my switch", and they override any
5
+ temptation to declare something unsupported. Each one is written here because it
6
+ was violated in practice — the concrete example is included so the rule is not
7
+ abstract.
8
+
9
+ Anything that contradicts a principle below needs an explicit, recorded decision
10
+ from the repository owner. "I couldn't get it working" is not such a decision.
11
+
12
+ ---
13
+
14
+ ## 1. Fail fast and loud. Never paper over a problem.
15
+
16
+ If an operation cannot be performed as asked, **raise** — immediately, with the
17
+ detail needed to debug it (which backend, which OID/URL/command, what the device
18
+ answered). Never substitute a different behaviour to make a call appear to
19
+ succeed.
20
+
21
+ **Specifically forbidden: switching protocol/backend mid-operation.** A caller
22
+ who asks for SNMP gets SNMP or an error. Silently retrying over HTTP is not
23
+ robustness, it is data loss disguised as success.
24
+
25
+ *Why this exists:* `SyncSwitch._read`/`_write` used to loop over
26
+ `SNMP > NSDP > HTTP` and silently return the next backend's answer when one
27
+ raised `UnsupportedCapabilityError`. That fallback concealed a real defect for
28
+ months — `HttpReader.get_vlans()` returns no untagged ports at all on the managed
29
+ switches, and nobody saw it because SNMP quietly answered in its place. Worse,
30
+ every past "HTTP verified" claim became untrustworthy, because the HTTP path may
31
+ never have run. On a write it is worse still: an operator who deliberately
32
+ restricts SNMP write access could have their change pushed over another protocol
33
+ without being told.
34
+
35
+ Corollaries:
36
+ - Verification must drive one backend **directly**. A cross-backend comparison is
37
+ only evidence if each backend answered on its own merits.
38
+ - A degraded or partial result is a failure. Do not return `[]`, `None` or a
39
+ silently-truncated value where the caller asked a question you could not answer.
40
+ - Errors must name the thing that failed. `commitFailed` on which OID, with which
41
+ value, for which model.
42
+
43
+ ## 2. Backends must have feature parity.
44
+
45
+ Every backend a model supports (SNMP / NSDP / HTTP / CLI) must offer the **same
46
+ functionality**. The point of having several is that the *caller* chooses — for
47
+ example when SNMP writes are locked down, or when the web UI is the only thing
48
+ reachable through a firewall. That choice only exists if the backends are
49
+ equivalent.
50
+
51
+ A backend missing an operation is a **missing implementation**, to be built. It
52
+ is not a device limitation until proven otherwise (see principle 4). Only the
53
+ repository owner may exempt a specific backend/operation, and the exemption must
54
+ be recorded in the code with the reason.
55
+
56
+ *Why this exists:* `vlan_membership_path=None # vlanStatus carries the egress
57
+ list inline` was left on every managed switch, so HTTP could neither report
58
+ tagged/untagged membership nor write membership at all — while the same file
59
+ already had the working `/iss/specific/vlanMembership.html` path for a sibling
60
+ model. Likewise there was no CLI write backend whatsoever, even though the
61
+ FASTPATH command sequences work (they were driven by hand on an M4300 to prove
62
+ it).
63
+
64
+ ## 3. Every switch model, not just the one in front of you.
65
+
66
+ A feature is not done when it works on one switch. It is done when it works on
67
+ **every** registered model, verified against every reachable one. All models have
68
+ feature parity unless the repository owner explicitly exempts one, with the reason
69
+ recorded in the registry entry.
70
+
71
+ When you implement or fix something, enumerate the models it applies to and check
72
+ each. Firmware differs between SKUs of the *same* family — do not extrapolate.
73
+
74
+ *Why this exists:* the M4300-16X was marked `snmp_vlan_write="fastpath_switchport"`
75
+ purely by inference from the M4300-24X ("same firmware family"). It runs different
76
+ firmware (12.0.19.15 vs 12.0.13.8) and **accepts** Q-BRIDGE writes the -24X
77
+ refuses, so the inference could not be trusted even though it happened to reach the
78
+ right answer.
79
+
80
+ Measuring it (2026-07-30) replaced both the inference *and* the counter-example
81
+ with the actual rule: `dot1qVlanStaticEgressPorts` is writable only while **no
82
+ interface on the switch is in access mode** — switch-wide, not per-VLAN, and the
83
+ same on both firmwares. An A/B/A on -16X port 1/0/1, issuing byte-identical writes
84
+ while flipping only that one port's mode, gave general→noError, access→**commitFailed**,
85
+ general→noError, trunk→noError, access→**commitFailed**, general→noError. The -24X
86
+ looks different only because 21 of its 24 ports are access-mode, so the column is
87
+ never writable there. And because an UNTAGGED membership write is *expressed as*
88
+ access mode, the qbridge dialect would disable itself on first use — the -16X
89
+ belongs on the switchport dialect after all, now for a reason instead of a guess.
90
+ The lesson stands unchanged: the extrapolation was invalid, and only measurement
91
+ told us what the devices actually do.
92
+
93
+ ## 4. A failure is something you did wrong.
94
+
95
+ Not flaky hardware. Not "the switch is slow". Not a timeout that will pass. Before
96
+ you even consider blaming the device, answer all of these:
97
+
98
+ - **Have you actually debugged it,** or just observed it fail? What does the device
99
+ say when you ask it directly (its CLI, its web UI, its own config dump)?
100
+ - **Is another setting required first?** Some writes are gated by other state.
101
+ - **Are you sending the wrong details?** Wrong community, username, password,
102
+ port, value type, encoding, field width, or **ordering** of operations.
103
+ - **Did you try every mechanism the device exposes,** or only the first one you
104
+ thought of?
105
+
106
+ Only after that, and only with captured device output quoted as proof, may a
107
+ limitation be recorded — and it must name the firmware version it applies to.
108
+
109
+ *Why this exists,* three times over in one session:
110
+ - "The S3300's SNMP agent is dead / timing out." It was not. The switch has no
111
+ `private` community (`show snmpcommunity` lists `pib` and `public`, both
112
+ Read/Write). An agent **silently drops** an unauthorized request, so a wrong
113
+ write community looks exactly like an unreachable host. Reads worked the whole
114
+ time. Wrong credential, blamed on hardware.
115
+ - "The M4300 refuses VLAN writes." It does not. One OID was tried; the switch's
116
+ own vendor switchport table accepts membership writes. Never enumerating what
117
+ the device published, blamed on firmware.
118
+ - "The S3300 forces untagged membership." It does not. Setting the egress bit
119
+ auto-untags the port, and that side effect beats an untagged varbind in the
120
+ **same PDU**; two PDUs, egress first, work perfectly. Wrong ordering, blamed on
121
+ firmware.
122
+
123
+ ## 5. The fake must behave like the real hardware. When it differs, fix the fake.
124
+
125
+ The virtual switch (`src/netgear_switch/virtual/`) exists so this library can be
126
+ tested honestly without hardware. That only works if it is a **faithful** model of
127
+ the real devices — including their refusals, their quirks and their ordering
128
+ requirements, not just their happy paths.
129
+
130
+ Therefore:
131
+ - When live hardware behaves differently from the mock, **the mock is wrong** and
132
+ must be corrected to match the device. Never adjust a test's expectation to
133
+ match a mock you already know is unfaithful, and never "fix" a divergence by
134
+ making the real-hardware path lenient.
135
+ - The mock must reproduce **rejections** as faithfully as successes: the right SMI
136
+ error-status (`commitFailed` vs `notWritable` vs `wrongValue`), the same
137
+ preconditions, the same side effects, the same ordering sensitivity.
138
+ - The mock must be an **independent** source of truth. If it derives a value using
139
+ the same formula as the code under test, it can only ever agree with that code
140
+ and proves nothing. Seed measured device values instead of computing them.
141
+ - Every behaviour learned from hardware gets encoded in the mock **and** pinned by
142
+ a test in the same change, with a comment naming the host and firmware it was
143
+ observed on. A finding that is not in the mock will be regressed later.
144
+
145
+ *Why this exists:* the VLAN PortList-width defect went unnoticed because the mock
146
+ emitted the bitmap using `vlan_bitmap_width(model)` — the exact same wrong formula
147
+ the buggy writer used — so mock and code agreed with each other while both
148
+ disagreed with every real switch (whose widths are 79 / 131 / 45 bytes, none of
149
+ them derivable from the port count). The round trip was green and meaningless.
150
+
151
+ ---
152
+
153
+ ## Practical rules that follow
154
+
155
+ - **Ground everything in real devices.** Fixtures come from captured
156
+ traffic/pages, never from imagination or from a MIB's ideal semantics.
157
+ - **Diff the device, don't guess the MIB.** To learn how something is configured:
158
+ capture a full walk to a file, change the setting through the switch's own
159
+ UI/CLI, walk again, diff. That is how the vendor switchport table was found with
160
+ no MIB file available.
161
+ - **Never leave a device changed.** Record the exact prior state, use throwaway
162
+ VLAN ids and ports that are link-down and undescribed, restore, and prove the
163
+ restore by re-reading. Never persist config (`write memory`) during testing.
164
+ - **Say what you actually verified.** Distinguish "live-verified on host X,
165
+ firmware Y" from "assumed". Never round an inference up to a fact.
166
+
167
+ ---
168
+
169
+ ## If you are a dispatched subagent
170
+
171
+ The five principles above bind you exactly as they bind the main session. In
172
+ particular:
173
+
174
+ - **Never declare an operation unsupported to finish your task.** If you cannot
175
+ implement something, say so plainly in your report — naming the model, backend
176
+ and operation — and leave no `raise UnsupportedCapabilityError` behind that
177
+ lacks captured device output as proof. An honest "not done, here's why" is
178
+ wanted; a false "the hardware can't" is not.
179
+ - **Implement across all backends and all models,** or state precisely which
180
+ combinations remain. Do not extrapolate one SKU's behaviour to its siblings.
181
+ - **Verify by driving one backend directly**, never through a facade that might
182
+ substitute another — otherwise your PASS may be a different protocol answering.
183
+ - **Encode what you learn from hardware into the virtual switch, plus a test**,
184
+ naming the host and firmware version in a comment. A finding that lives only in
185
+ your report will be regressed by the next change.
186
+
187
+ ### Live-hardware rules (absolute)
188
+
189
+ - Credentials come from `sudo -n .venv/bin/gdoc2netcfg password --type password -q
190
+ <host>` run from `/opt/gdoc2netcfg`. **Never print a credential.**
191
+ - Use throwaway VLAN ids in the 4001-4008 range, coordinated so concurrent agents
192
+ do not collide.
193
+ - Touch only a port that is **link-down** AND whose description is empty or
194
+ `'empty'`. Never a described production port.
195
+ - **Record the exact prior state, restore it, and prove the restore by
196
+ re-reading.** Never `write memory` / save configuration.
197
+
198
+ ### Running things on this machine
199
+
200
+ It OOMs easily: `PYTHONPATH=src .venv/bin/python -m pytest <specific file> -q
201
+ --no-cov`, one pytest process at a time, never the full suite. `uv run ruff check
202
+ src/ tests/` and `uv run mypy` must both be clean. Never use `2>/dev/null` (a hook
203
+ blocks it). Prefer Python over involved shell.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-netgear-switch-library
3
- Version: 0.0.post290
3
+ Version: 0.0.post321
4
4
  Summary: Python library and CLI to query and control Netgear switches over SNMP, NSDP and HTTP.
5
5
  Author-email: Tim Ansell <me@mith.ro>
6
6
  License-Expression: Apache-2.0
@@ -9,6 +9,16 @@ Requires-Python: >=3.11
9
9
  Requires-Dist: cryptography>=41
10
10
  Provides-Extra: async
11
11
  Requires-Dist: pysnmp>=7.0; extra == 'async'
12
+ Provides-Extra: docs
13
+ Requires-Dist: furo>=2024.8.6; extra == 'docs'
14
+ Requires-Dist: httpx>=0.27; extra == 'docs'
15
+ Requires-Dist: mcp>=1.2; extra == 'docs'
16
+ Requires-Dist: paramiko<3,>=2.12; extra == 'docs'
17
+ Requires-Dist: pyserial>=3.5; extra == 'docs'
18
+ Requires-Dist: pysnmp>=7.0; extra == 'docs'
19
+ Requires-Dist: sphinx-argparse>=0.5; extra == 'docs'
20
+ Requires-Dist: sphinx-copybutton>=0.5.2; extra == 'docs'
21
+ Requires-Dist: sphinx>=8.1; extra == 'docs'
12
22
  Provides-Extra: http
13
23
  Requires-Dist: httpx>=0.27; extra == 'http'
14
24
  Provides-Extra: mcp
@@ -27,6 +37,11 @@ Description-Content-Type: text/markdown
27
37
  Query and control all your Netgear switches — SNMP (managed), NSDP and HTTP
28
38
  web-UI (Plus) — behind one model-driven Python API and the `ngsw` CLI.
29
39
 
40
+ **Documentation: <https://python-netgear-switch-library.readthedocs.io/>** — API
41
+ reference, the complete `ngsw` CLI reference, the virtual-switch guide (how to
42
+ test your own tools against a mock), and generated
43
+ [model × protocol and model × functionality support tables](https://python-netgear-switch-library.readthedocs.io/en/latest/models/support.html).
44
+
30
45
  Status: **early development.** See `docs/superpowers/specs/` for the design and
31
46
  `docs/superpowers/plans/` for the implementation plans.
32
47
 
@@ -128,12 +143,24 @@ Options:
128
143
  listener, these are only allowed when serving exactly one model; otherwise
129
144
  leave them unset and read the printed ephemeral ports.
130
145
 
146
+ Full details, including worked examples of testing an external tool against a
147
+ mock, are in the [virtual switch
148
+ guide](https://python-netgear-switch-library.readthedocs.io/en/latest/fake/).
149
+
131
150
  ## Development
132
151
 
133
152
  ```sh
134
153
  uv sync --all-extras
135
154
  uv run pytest
136
155
  uv run ruff check
156
+ uv run mypy
157
+ ```
158
+
159
+ Build the documentation (warnings are errors, as on Read the Docs):
160
+
161
+ ```sh
162
+ uv sync --extra docs
163
+ make -C docs html
137
164
  ```
138
165
 
139
166
  ## License
@@ -3,6 +3,11 @@
3
3
  Query and control all your Netgear switches — SNMP (managed), NSDP and HTTP
4
4
  web-UI (Plus) — behind one model-driven Python API and the `ngsw` CLI.
5
5
 
6
+ **Documentation: <https://python-netgear-switch-library.readthedocs.io/>** — API
7
+ reference, the complete `ngsw` CLI reference, the virtual-switch guide (how to
8
+ test your own tools against a mock), and generated
9
+ [model × protocol and model × functionality support tables](https://python-netgear-switch-library.readthedocs.io/en/latest/models/support.html).
10
+
6
11
  Status: **early development.** See `docs/superpowers/specs/` for the design and
7
12
  `docs/superpowers/plans/` for the implementation plans.
8
13
 
@@ -104,12 +109,24 @@ Options:
104
109
  listener, these are only allowed when serving exactly one model; otherwise
105
110
  leave them unset and read the printed ephemeral ports.
106
111
 
112
+ Full details, including worked examples of testing an external tool against a
113
+ mock, are in the [virtual switch
114
+ guide](https://python-netgear-switch-library.readthedocs.io/en/latest/fake/).
115
+
107
116
  ## Development
108
117
 
109
118
  ```sh
110
119
  uv sync --all-extras
111
120
  uv run pytest
112
121
  uv run ruff check
122
+ uv run mypy
123
+ ```
124
+
125
+ Build the documentation (warnings are errors, as on Read the Docs):
126
+
127
+ ```sh
128
+ uv sync --extra docs
129
+ make -C docs html
113
130
  ```
114
131
 
115
132
  ## License
@@ -0,0 +1,30 @@
1
+ # Documentation build. `make html` mirrors what Read the Docs runs
2
+ # (see .readthedocs.yaml), including warnings-as-errors.
3
+ #
4
+ # `make offline` additionally skips the intersphinx inventory fetch, for
5
+ # building without network access.
6
+
7
+ SPHINXOPTS ?= -W --keep-going
8
+ SPHINXBUILD ?= sphinx-build
9
+ SOURCEDIR = .
10
+ BUILDDIR = _build
11
+
12
+ .PHONY: help html offline linkcheck clean Makefile
13
+
14
+ help:
15
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
16
+
17
+ html:
18
+ @$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
19
+
20
+ offline:
21
+ @NGSW_DOCS_OFFLINE=1 $(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
22
+
23
+ linkcheck:
24
+ @$(SPHINXBUILD) -M linkcheck "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
25
+
26
+ clean:
27
+ @$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
28
+
29
+ %: Makefile
30
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)