python-netgear-switch-library 0.0.post360__tar.gz → 0.0.post404__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 (430) hide show
  1. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/PKG-INFO +2 -2
  2. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/api/protocols.rst +2 -0
  3. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/fake/index.rst +2 -2
  4. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/fake/internals.rst +4 -2
  5. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/fake/testing.rst +4 -3
  6. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/guide/concepts.rst +11 -4
  7. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/guide/quickstart.rst +7 -3
  8. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/guide/reading.rst +31 -3
  9. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/guide/writing.rst +66 -0
  10. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/index.rst +7 -6
  11. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/models/gs305ep.rst +16 -0
  12. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/models/index.rst +7 -2
  13. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/models/m4300-16x.rst +19 -14
  14. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/models/support.rst +12 -0
  15. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/protocols/nsdp.rst +3 -1
  16. python_netgear_switch_library-0.0.post404/docs/superpowers/specs/2026-08-02-gs728tpp-poe-vlan-live.md +344 -0
  17. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/specs/2026-08-02-snmp-surface-findings.md +28 -0
  18. python_netgear_switch_library-0.0.post404/docs/superpowers/specs/2026-08-03-snmp-vendor-oid-sweep.md +144 -0
  19. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/__init__.py +2 -0
  20. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/_version.py +2 -2
  21. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/aio_api.py +85 -3
  22. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/capabilities.py +291 -31
  23. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/cli/format.py +48 -0
  24. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/cli/main.py +265 -1
  25. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/cli_write.py +267 -9
  26. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/http_read.py +91 -48
  27. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/http_write.py +971 -7
  28. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/mcp/server.py +225 -4
  29. python_netgear_switch_library-0.0.post404/src/netgear_switch/models.py +499 -0
  30. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/nsdp_read.py +15 -6
  31. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/nsdp_write.py +191 -1
  32. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/cli/commands.py +156 -0
  33. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/cli/parse.py +121 -48
  34. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/http/endpoints.py +126 -19
  35. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/http/forms.py +131 -1
  36. python_netgear_switch_library-0.0.post404/src/netgear_switch/protocols/http/goahead.py +341 -0
  37. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/http/parse.py +403 -21
  38. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/http/types.py +12 -0
  39. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/snmp/oids.py +38 -0
  40. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/snmp/parse.py +106 -7
  41. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/registry.py +30 -0
  42. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/snmp_read.py +33 -2
  43. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/snmp_write.py +326 -15
  44. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/sync_api.py +97 -0
  45. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/http/client.py +69 -5
  46. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/sync/snmp_netsnmp_cli.py +17 -5
  47. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/cli_fastpath.py +120 -2
  48. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/faces/cli.py +139 -5
  49. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/faces/http.py +72 -44
  50. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/faces/snmp.py +11 -0
  51. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/seed.py +128 -12
  52. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/state.py +245 -11
  53. python_netgear_switch_library-0.0.post404/src/netgear_switch/virtual/web_fastpath_xui.py +601 -0
  54. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/web_gs728tpp.py +204 -7
  55. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_op_coverage.py +11 -0
  56. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/equivalence.py +17 -2
  57. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs110emx_interface_stats.html +1 -1
  58. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs110emx_redirect.html +1 -1
  59. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs110emx_sysinfo.html +1 -1
  60. python_netgear_switch_library-0.0.post404/tests/fixtures/http/gsm7228ps_http_configuration.html +169 -0
  61. python_netgear_switch_library-0.0.post404/tests/fixtures/http/gsm7228ps_syslog_configuration.html +306 -0
  62. python_netgear_switch_library-0.0.post404/tests/fixtures/http/gsm7252ps_https_configuration.html +194 -0
  63. python_netgear_switch_library-0.0.post404/tests/fixtures/http/gsm7252ps_ssh_configuration.html +196 -0
  64. python_netgear_switch_library-0.0.post404/tests/fixtures/http/gsm7252ps_telnet.html +327 -0
  65. python_netgear_switch_library-0.0.post404/tests/fixtures/http/gsm7252ps_user_management.html +208 -0
  66. python_netgear_switch_library-0.0.post404/tests/fixtures/http/m4300_16x_syslog_configuration.html +528 -0
  67. python_netgear_switch_library-0.0.post404/tests/fixtures/http/m4300_24x_http_configuration.html +122 -0
  68. python_netgear_switch_library-0.0.post404/tests/fixtures/http/m4300_24x_https_configuration.html +127 -0
  69. python_netgear_switch_library-0.0.post404/tests/fixtures/http/m4300_24x_ssh_configuration.html +331 -0
  70. python_netgear_switch_library-0.0.post404/tests/fixtures/http/m4300_24x_syslog_configuration.html +526 -0
  71. python_netgear_switch_library-0.0.post404/tests/fixtures/http/m4300_24x_telnet.html +444 -0
  72. python_netgear_switch_library-0.0.post404/tests/fixtures/http/m4300_24x_user_management.html +481 -0
  73. python_netgear_switch_library-0.0.post404/tests/protocols/http/test_goahead_write.py +132 -0
  74. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/http/test_parse.py +11 -11
  75. python_netgear_switch_library-0.0.post404/tests/protocols/snmp/test_parse_vlans.py +196 -0
  76. python_netgear_switch_library-0.0.post404/tests/snmp_fakes.py +40 -0
  77. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_aio_api.py +11 -3
  78. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_capabilities.py +68 -1
  79. python_netgear_switch_library-0.0.post404/tests/test_flow_control.py +264 -0
  80. python_netgear_switch_library-0.0.post404/tests/test_http_hostname_emx.py +129 -0
  81. python_netgear_switch_library-0.0.post404/tests/test_http_services.py +144 -0
  82. python_netgear_switch_library-0.0.post404/tests/test_http_syslog.py +116 -0
  83. python_netgear_switch_library-0.0.post404/tests/test_http_users.py +96 -0
  84. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_http_write.py +22 -1
  85. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_nsdp_read.py +16 -7
  86. python_netgear_switch_library-0.0.post404/tests/test_port_speed.py +351 -0
  87. python_netgear_switch_library-0.0.post404/tests/test_port_speed_http.py +276 -0
  88. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_snmp_read.py +4 -3
  89. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_snmp_write.py +83 -6
  90. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_sync_api.py +14 -4
  91. python_netgear_switch_library-0.0.post404/tests/test_syslog_collectors.py +481 -0
  92. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/transport/test_snmp_netsnmp_cli.py +37 -0
  93. python_netgear_switch_library-0.0.post404/tests/virtual/test_gs728tpp_vlan_fidelity.py +294 -0
  94. python_netgear_switch_library-0.0.post404/tests/virtual/test_port_description_outcomes.py +112 -0
  95. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_syslog_fidelity.py +21 -1
  96. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_virtual_http_face.py +127 -11
  97. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/uv.lock +491 -3
  98. python_netgear_switch_library-0.0.post360/src/netgear_switch/models.py +0 -246
  99. python_netgear_switch_library-0.0.post360/src/netgear_switch/virtual/web_fastpath_xui.py +0 -287
  100. python_netgear_switch_library-0.0.post360/tests/protocols/snmp/test_parse_vlans.py +0 -80
  101. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/.github/workflows/ci.yml +0 -0
  102. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/.github/workflows/deb.yml +0 -0
  103. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/.github/workflows/publish-pypi.yml +0 -0
  104. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/.gitignore +0 -0
  105. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/.readthedocs.yaml +0 -0
  106. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/CLAUDE.md +0 -0
  107. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/LICENSE +0 -0
  108. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/README.md +0 -0
  109. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/RELEASING.md +0 -0
  110. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/debian/changelog +0 -0
  111. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/debian/control +0 -0
  112. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/debian/copyright +0 -0
  113. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/debian/rules +0 -0
  114. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/debian/source/format +0 -0
  115. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/Makefile +0 -0
  116. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/_ext/filelinks.py +0 -0
  117. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/_ext/support_tables.py +0 -0
  118. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/_static/models/gs105pe.png +0 -0
  119. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/_static/models/gs110emx.png +0 -0
  120. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/_static/models/gs305ep.png +0 -0
  121. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/_static/models/gs728tpp.png +0 -0
  122. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/_static/models/gsm7228ps.jpg +0 -0
  123. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/_static/models/gsm7252ps.jpg +0 -0
  124. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/_static/models/m4300-16x.png +0 -0
  125. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/_static/models/m4300-24x.png +0 -0
  126. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/_static/ngsw.css +0 -0
  127. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/api/cli.rst +0 -0
  128. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/api/core.rst +0 -0
  129. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/api/facades.rst +0 -0
  130. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/api/index.rst +0 -0
  131. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/api/mcp.rst +0 -0
  132. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/api/operations.rst +0 -0
  133. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/api/transport.rst +0 -0
  134. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/api/virtual.rst +0 -0
  135. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/cli.rst +0 -0
  136. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/conf.py +0 -0
  137. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/development.rst +0 -0
  138. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/fake/serving.rst +0 -0
  139. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/guide/configuration.rst +0 -0
  140. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/guide/installation.rst +0 -0
  141. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/guide/principles.rst +0 -0
  142. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/mcp.rst +0 -0
  143. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/models/gs105pe.rst +0 -0
  144. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/models/gs110emx.rst +0 -0
  145. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/models/gs728tpp.rst +0 -0
  146. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/models/gsm7228ps.rst +0 -0
  147. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/models/gsm7252ps.rst +0 -0
  148. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/models/m4300-24x.rst +0 -0
  149. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/protocols/cli.rst +0 -0
  150. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/protocols/http/cheetah-form.rst +0 -0
  151. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/protocols/http/cheetah-v1.rst +0 -0
  152. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/protocols/http/gambit.rst +0 -0
  153. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/protocols/http/merge-hash-cgi.rst +0 -0
  154. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/protocols/http/xml-api.rst +0 -0
  155. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/protocols/http.rst +0 -0
  156. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/protocols/index.rst +0 -0
  157. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/protocols/snmp.rst +0 -0
  158. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/plans/2026-07-15-foundation.md +0 -0
  159. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/plans/2026-07-17-slice-02-snmp-read-core.md +0 -0
  160. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/plans/2026-07-17-slice-03-read-apis.md +0 -0
  161. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/plans/2026-07-18-slice-04-snmp-write.md +0 -0
  162. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/plans/2026-07-18-slice-05-nsdp.md +0 -0
  163. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/plans/2026-07-18-slice-06-http.md +0 -0
  164. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/plans/2026-07-18-slice-07-cli.md +0 -0
  165. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/plans/2026-07-18-slice-08-packaging-ci.md +0 -0
  166. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/plans/2026-07-23-gsm7252ps-http-xe-dialect.md +0 -0
  167. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/specs/2026-07-15-netgear-control-library-design.md +0 -0
  168. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/docs/superpowers/specs/2026-07-23-gsm7252ps-http-xe-dialect-design.md +0 -0
  169. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/packaging/apt-index.html +0 -0
  170. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/packaging/ci-build.sh +0 -0
  171. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/packaging/deb-version.py +0 -0
  172. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/pyproject.toml +0 -0
  173. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/_dispatch.py +0 -0
  174. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/cli/__init__.py +0 -0
  175. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/cli/capture.py +0 -0
  176. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/cli/context.py +0 -0
  177. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/cli/resolve.py +0 -0
  178. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/cli/safety.py +0 -0
  179. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/cli_read.py +0 -0
  180. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/config.py +0 -0
  181. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/errors.py +0 -0
  182. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/mcp/__init__.py +0 -0
  183. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/__init__.py +0 -0
  184. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/cli/__init__.py +0 -0
  185. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/http/__init__.py +0 -0
  186. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/http/crypt.py +0 -0
  187. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/http/session.py +0 -0
  188. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/nsdp/__init__.py +0 -0
  189. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/nsdp/auth.py +0 -0
  190. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/nsdp/client.py +0 -0
  191. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/nsdp/parsers.py +0 -0
  192. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/nsdp/protocol.py +0 -0
  193. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/nsdp/types.py +0 -0
  194. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/nsdp/write.py +0 -0
  195. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/snmp/__init__.py +0 -0
  196. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/snmp/client.py +0 -0
  197. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/protocols/snmp/write.py +0 -0
  198. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/py.typed +0 -0
  199. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/__init__.py +0 -0
  200. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/aio/__init__.py +0 -0
  201. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/aio/nsdp_udp.py +0 -0
  202. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/aio/snmp_pysnmp.py +0 -0
  203. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/cli/__init__.py +0 -0
  204. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/cli/console.py +0 -0
  205. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/cli/session.py +0 -0
  206. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/cli/ssh.py +0 -0
  207. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/cli/telnet.py +0 -0
  208. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/http/__init__.py +0 -0
  209. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/sync/__init__.py +0 -0
  210. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/transport/sync/nsdp_udp.py +0 -0
  211. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/__init__.py +0 -0
  212. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/faces/__init__.py +0 -0
  213. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/faces/mibview.py +0 -0
  214. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/faces/nsdp.py +0 -0
  215. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/server.py +0 -0
  216. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/web.py +0 -0
  217. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/web_fastpath_vlan.py +0 -0
  218. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/web_gs105pe.py +0 -0
  219. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/web_gs110emx.py +0 -0
  220. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/web_gs110emx_templates.py +0 -0
  221. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/web_gsm7228ps.py +0 -0
  222. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/web_gsm7252ps.py +0 -0
  223. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/src/netgear_switch/virtual/web_m4300.py +0 -0
  224. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/capture_parity.py +0 -0
  225. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_capture.py +0 -0
  226. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_cli_integration.py +0 -0
  227. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_control_poe_port.py +0 -0
  228. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_control_vlan_ip.py +0 -0
  229. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_format.py +0 -0
  230. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_main_framework.py +0 -0
  231. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_new_commands.py +0 -0
  232. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_prompt_wiring.py +0 -0
  233. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_read_commands.py +0 -0
  234. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_resolve.py +0 -0
  235. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_safety.py +0 -0
  236. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/cli/test_serve.py +0 -0
  237. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/conftest.py +0 -0
  238. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/captures/gsm7228ps.json +0 -0
  239. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/captures/gsm7252ps.json +0 -0
  240. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/captures/m4300-16x.json +0 -0
  241. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/captures/m4300-24x.json +0 -0
  242. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7228ps_environment.txt +0 -0
  243. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7228ps_lldp.txt +0 -0
  244. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7228ps_mac_table.txt +0 -0
  245. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7228ps_network.txt +0 -0
  246. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7228ps_poe.txt +0 -0
  247. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7228ps_port_all.txt +0 -0
  248. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7228ps_show_version.txt +0 -0
  249. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7228ps_vlan.txt +0 -0
  250. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7228ps_vlan_brief.txt +0 -0
  251. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7228ps_vlan_port_all.txt +0 -0
  252. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7252ps_show_environment.txt +0 -0
  253. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7252ps_show_interface_ethernet_1_0_1.txt +0 -0
  254. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7252ps_show_lldp_remote_device_all.txt +0 -0
  255. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7252ps_show_mac_addr_table.txt +0 -0
  256. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7252ps_show_network.txt +0 -0
  257. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7252ps_show_poe_port_info_all.txt +0 -0
  258. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7252ps_show_port_all.txt +0 -0
  259. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7252ps_show_version.txt +0 -0
  260. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7252ps_show_vlan_90.txt +0 -0
  261. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7252ps_show_vlan_brief.txt +0 -0
  262. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/gsm7252ps_show_vlan_port_all.txt +0 -0
  263. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_environment.txt +0 -0
  264. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_interface_ethernet_1_0_1.txt +0 -0
  265. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_ip_management.txt +0 -0
  266. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_lldp_remote_device_all.txt +0 -0
  267. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_mac_addr_table.txt +0 -0
  268. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_poe_port_info_all.txt +0 -0
  269. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_port_all.txt +0 -0
  270. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_version.txt +0 -0
  271. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_vlan.txt +0 -0
  272. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_vlan_1.txt +0 -0
  273. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_vlan_4.txt +0 -0
  274. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_vlan_5.txt +0 -0
  275. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_16x_show_vlan_port_all.txt +0 -0
  276. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_24x_show_environment.txt +0 -0
  277. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_24x_show_interface_ethernet_1_0_1.txt +0 -0
  278. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_24x_show_ip_management.txt +0 -0
  279. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_24x_show_lldp_remote_device_all.txt +0 -0
  280. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_24x_show_mac_addr_table.txt +0 -0
  281. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_24x_show_port_all.txt +0 -0
  282. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_24x_show_version.txt +0 -0
  283. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_24x_show_vlan.txt +0 -0
  284. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_24x_show_vlan_5.txt +0 -0
  285. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_24x_show_vlan_90.txt +0 -0
  286. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/cli/m4300_24x_show_vlan_port_all.txt +0 -0
  287. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs105pe_membership.html +0 -0
  288. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs105pe_portstats.html +0 -0
  289. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs105pe_pvid.html +0 -0
  290. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs105pe_status.html +0 -0
  291. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs105pe_switch_info.html +0 -0
  292. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs105pe_vlancfg.html +0 -0
  293. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs110emx_cf8021q.html +0 -0
  294. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs110emx_login.html +0 -0
  295. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs110emx_port_settings.html +0 -0
  296. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs110emx_pvid.html +0 -0
  297. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs110emx_vlanmembership.html +0 -0
  298. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs305ep_dashboard.html +0 -0
  299. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs305ep_login.html +0 -0
  300. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs305ep_membership.html +0 -0
  301. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs305ep_poestatus.html +0 -0
  302. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs305ep_portstats.html +0 -0
  303. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs305ep_pvid.html +0 -0
  304. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs305ep_vlancfg.html +0 -0
  305. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs728tpp_device_info_and_sensors.xml +0 -0
  306. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs728tpp_lldp.xml +0 -0
  307. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs728tpp_macs.xml +0 -0
  308. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs728tpp_mgmt_ip.xml +0 -0
  309. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs728tpp_poe.xml +0 -0
  310. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs728tpp_ports.xml +0 -0
  311. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs728tpp_pvids_membership.xml +0 -0
  312. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs728tpp_vlan_membership_per_vlan.xml +0 -0
  313. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gs728tpp_vlans.xml +0 -0
  314. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7228ps_basicAddressTable.html +0 -0
  315. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7228ps_ipConfiguration.html +0 -0
  316. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7228ps_lldpRemoteInventory.html +0 -0
  317. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7228ps_poeInterfaceConfiguration.html +0 -0
  318. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7228ps_portPvidConfiguration.html +0 -0
  319. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7228ps_portStatistics.html +0 -0
  320. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7228ps_portsConfiguration.html +0 -0
  321. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7228ps_sysInfo.html +0 -0
  322. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7228ps_vlanPortCfg_vlan5.html +0 -0
  323. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7228ps_vlanStatus.html +0 -0
  324. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_basicAddressTable.html +0 -0
  325. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_http_configuration.html +0 -0
  326. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_ipConfiguration.html +0 -0
  327. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_lldpRemoteInventory.html +0 -0
  328. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_login.html +0 -0
  329. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_poeInterfaceConfiguration.html +0 -0
  330. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_portPvidConfiguration.html +0 -0
  331. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_portStatistics.html +0 -0
  332. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_portsConfiguration.html +0 -0
  333. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_sysInfo.html +0 -0
  334. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_syslog_configuration.html +0 -0
  335. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_user_configuration.html +0 -0
  336. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan1.html +0 -0
  337. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan141.html +0 -0
  338. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_vlanStatus.html +0 -0
  339. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_vlan_add_form.html +0 -0
  340. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_vlan_configuration.js +0 -0
  341. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_vlan_configuration_live.html +0 -0
  342. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/gsm7252ps_vlan_status_live.html +0 -0
  343. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_16x_lldpRemoteInventory.html +0 -0
  344. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_16x_mgmtVlanIpv4Configuration.html +0 -0
  345. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_16x_poeInterfaceConfiguration.html +0 -0
  346. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_16x_portsConfiguration.html +0 -0
  347. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_16x_vlanportcfg_vlan4.html +0 -0
  348. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_24x_poeInterfaceConfiguration.html +0 -0
  349. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_addresstable.html +0 -0
  350. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_lldpRemoteInventory.html +0 -0
  351. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_mgmtVlanIpv4Configuration.html +0 -0
  352. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_ports.html +0 -0
  353. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_portstats.html +0 -0
  354. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_pvid.html +0 -0
  355. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_sysinfo.html +0 -0
  356. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_vlanportcfg_vlan1.html +0 -0
  357. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/http/m4300_vlanstatus.html +0 -0
  358. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/snmp/gsm7252ps_fans.txt +0 -0
  359. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/snmp/gsm7252ps_ifhighspeed.txt +0 -0
  360. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/snmp/gsm7252ps_ifoperstatus.txt +0 -0
  361. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/fixtures/snmp/gsm7252ps_psu.txt +0 -0
  362. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/http_specs.py +0 -0
  363. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/cli/test_cli_parse.py +0 -0
  364. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/http/test_crypt.py +0 -0
  365. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/http/test_endpoints.py +0 -0
  366. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/http/test_forms.py +0 -0
  367. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/nsdp/test_auth.py +0 -0
  368. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/nsdp/test_parsers.py +0 -0
  369. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/nsdp/test_protocol.py +0 -0
  370. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/nsdp/test_write_frame.py +0 -0
  371. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/snmp/test_client.py +0 -0
  372. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/snmp/test_oids.py +0 -0
  373. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/snmp/test_parse_lldp_macs.py +0 -0
  374. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/snmp/test_parse_mgmt_ip.py +0 -0
  375. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/snmp/test_parse_poe_sensors.py +0 -0
  376. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/snmp/test_parse_ports.py +0 -0
  377. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/snmp/test_parse_system_info.py +0 -0
  378. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/protocols/snmp/test_write_encode.py +0 -0
  379. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_cli_read.py +0 -0
  380. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_cli_vlan_write.py +0 -0
  381. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_cli_write.py +0 -0
  382. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_config.py +0 -0
  383. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_cross_backend_equivalence.py +0 -0
  384. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_deb_version.py +0 -0
  385. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_dispatch.py +0 -0
  386. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_docs_coverage.py +0 -0
  387. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_errors.py +0 -0
  388. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_facade_equivalence.py +0 -0
  389. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_http_dispatch.py +0 -0
  390. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_http_equivalence.py +0 -0
  391. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_http_read.py +0 -0
  392. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_http_vlan_membership.py +0 -0
  393. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_http_xui_writes.py +0 -0
  394. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_import.py +0 -0
  395. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_mcp_server.py +0 -0
  396. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_models.py +0 -0
  397. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_models_snmp_read.py +0 -0
  398. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_nsdp_integration.py +0 -0
  399. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_nsdp_write.py +0 -0
  400. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_public_api.py +0 -0
  401. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_quality_gates.py +0 -0
  402. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_registry.py +0 -0
  403. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_snmp_integration.py +0 -0
  404. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_version.py +0 -0
  405. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/test_write_equivalence.py +0 -0
  406. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/transport/_fastpath_fake.py +0 -0
  407. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/transport/test_cli_console.py +0 -0
  408. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/transport/test_cli_scp_cert.py +0 -0
  409. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/transport/test_cli_telnet.py +0 -0
  410. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/transport/test_http_client.py +0 -0
  411. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/transport/test_nsdp_udp_sync.py +0 -0
  412. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/transport/test_set_transport.py +0 -0
  413. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/transport/test_snmp_pysnmp.py +0 -0
  414. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/transport/test_value_parity.py +0 -0
  415. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_cli_cross_backend.py +0 -0
  416. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_cli_gsm7228ps_parity.py +0 -0
  417. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_gsm7228ps_seed.py +0 -0
  418. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_hostname.py +0 -0
  419. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_m4300_seeds.py +0 -0
  420. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_mibview.py +0 -0
  421. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_mutable_state.py +0 -0
  422. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_nsdp_state.py +0 -0
  423. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_serve_daemon.py +0 -0
  424. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_snmp_write_face.py +0 -0
  425. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_state_seed.py +0 -0
  426. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_switchport_vlan_write.py +0 -0
  427. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_virtual_nsdp_face.py +0 -0
  428. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_virtual_snmp_face.py +0 -0
  429. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_web_projection.py +0 -0
  430. {python_netgear_switch_library-0.0.post360 → python_netgear_switch_library-0.0.post404}/tests/virtual/test_write_outcomes.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: python-netgear-switch-library
3
- Version: 0.0.post360
3
+ Version: 0.0.post404
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
@@ -51,6 +51,8 @@ HTTP web UI
51
51
 
52
52
  .. automodule:: netgear_switch.protocols.http.forms
53
53
 
54
+ .. automodule:: netgear_switch.protocols.http.goahead
55
+
54
56
  .. automodule:: netgear_switch.protocols.http.crypt
55
57
 
56
58
  .. automodule:: netgear_switch.protocols.http.session
@@ -60,8 +60,8 @@ with a comment naming the host and firmware version it was observed on. A
60
60
  finding that lives only in a report gets regressed by the next change.
61
61
 
62
62
  Tools that know nothing about this library have cross-checked it too. The
63
- third-party ProSafeLinux NSDP implementation decodes both mock switches
64
- completely, every value matching the seed; the C tool ``ngadmin`` validated the
63
+ third-party ProSafeLinux NSDP implementation decodes the GS110EMX and GS105PE
64
+ mocks completely, every value matching the seed; the C tool ``ngadmin`` validated the
65
65
  packet header — and surfaced a real four-byte sequence-number bug in the
66
66
  process, since fixed. A mock validated only by the client that talks to it
67
67
  proves nothing.
@@ -140,8 +140,10 @@ A mock validated only by the client that talks to it proves nothing, so the NSDP
140
140
  face has been driven by third-party implementations that know nothing about this
141
141
  library:
142
142
 
143
- * **ProSafeLinux** decodes both mock switches completely, and every value it
144
- reports matches the seed.
143
+ * **ProSafeLinux** decodes the GS110EMX and GS105PE mocks completely, and every
144
+ value it reports matches the seed. Those two, not all three NSDP models: the
145
+ GS305EP seed is hand-invented, so decoding it would only confirm this
146
+ library's own invention.
145
147
  * **ngadmin** (a C implementation) validated the packet header — and surfaced a
146
148
  real four-byte sequence-number bug in the process, which was fixed.
147
149
 
@@ -130,10 +130,11 @@ Every backend takes an injected client:
130
130
  transports block, so :py:class:`~netgear_switch.aio_api.AsyncSwitch` has no CLI
131
131
  backend and takes no ``cli_client``.
132
132
 
133
- All four at once
134
- ----------------
133
+ All three at once
134
+ -----------------
135
135
 
136
- One mock, one facade, three protocols — what makes cross-backend behaviour
136
+ One mock, one facade, three protocols — SNMP, the web UI and the FASTPATH CLI
137
+ answering the same question. This is what makes cross-backend behaviour
137
138
  testable without hardware:
138
139
 
139
140
  .. tab-set::
@@ -57,10 +57,17 @@ A backend is *the protocol an operation travels over*:
57
57
  transports; ``CONSOLE`` is a serial line rather than a network backend,
58
58
  so it is never registered on a model.
59
59
 
60
- Every read and every write is implemented on every backend a model has. That is
61
- deliberate: if SNMP writes are locked down on your network, or the web UI is the
62
- only port through a firewall, you can pick a different protocol and get the same
63
- answer. :doc:`../models/support` lists the gaps that remain.
60
+ Backend parity is the design aim: an operation should work on every backend a
61
+ model has, so that if SNMP writes are locked down on your network, or the web UI
62
+ is the only port through a firewall, you can pick a different protocol and get
63
+ the same answer.
64
+
65
+ Where that does not hold, the reason is recorded rather than glossed over. Some
66
+ are limits proven against the hardware — the GS728TPP's SNMP agent refuses every
67
+ documented way of creating a VLAN, while its own web UI creates one without
68
+ complaint — and others are pages or commands nobody has built yet.
69
+ :doc:`../models/support` marks each one. Either way the library refuses by name;
70
+ it never substitutes a protocol you did not ask for.
64
71
 
65
72
  Dispatch: exactly one backend, every time
66
73
  -----------------------------------------
@@ -185,9 +185,13 @@ back to another protocol — see :doc:`concepts`.
185
185
  # has no SSH/telnet/console backend. Use SyncSwitch, or:
186
186
  # await asyncio.to_thread(sync_switch.get_vlans, backend=Backend.SSH)
187
187
 
188
- That the three agree is asserted, not assumed
189
- ``tests/test_cross_backend_equivalence.py`` compares them for every model with
190
- more than one backend. They agree on the *physical* ports; SNMP also reports
188
+ That they agree is asserted, not assumed, and by two suites rather than one:
189
+ ``tests/test_cross_backend_equivalence.py`` compares HTTP against NSDP or SNMP,
190
+ while ``tests/virtual/test_cli_cross_backend.py`` and
191
+ ``tests/virtual/test_cli_gsm7228ps_parity.py`` bring the FASTPATH CLI into the
192
+ same comparison — the CLI is deliberately absent from the first file, so citing
193
+ it alone would overstate what is checked. They agree on the *physical* ports;
194
+ SNMP also reports
191
195
  internal and link-aggregation interfaces that a web UI's port table does not
192
196
  list, and one model has a VLAN where SNMP shows configured members and the
193
197
  web UI shows current ones. Both are real properties of the interfaces, and the
@@ -19,7 +19,11 @@ The operations
19
19
  - ``list[PortStatus]``
20
20
  - Port number, ``ifName``, admin state, link state, speed in Mbit/s, and
21
21
  the operator-set description (``ifAlias``) where the backend can read
22
- one.
22
+ one. ``speed_config`` carries the port's **configured** speed/duplex,
23
+ which is a different question from the negotiated ``speed_mbps`` —
24
+ see :ref:`speed-vs-negotiated`. The CLI and the GoAhead web UI both
25
+ report it; SNMP and NSDP leave it ``None``, because ``ifSpeed`` and
26
+ NSDP's port record are both the negotiated rate.
23
27
  * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.get_stats`
24
28
  - ``list[PortStats]``
25
29
  - RX/TX bytes, packets and errors. Any counter a backend cannot read is
@@ -48,6 +52,25 @@ The operations
48
52
  - :py:obj:`~netgear_switch.models.MgmtIpConfig`
49
53
  - Address, netmask, gateway, DHCP-or-static mode, and the switch's base
50
54
  MAC.
55
+ * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.get_hostname`
56
+ - ``str``
57
+ - The switch's configured host name.
58
+ * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.get_users`
59
+ - ``list[SwitchUser]``
60
+ - Local login accounts. ``access_mode`` is the switch's own wording for
61
+ the account, kept verbatim because it differs by *face*, not just by
62
+ firmware: asked over the CLI the same admin account reads
63
+ ``Privilege-15`` on one image and ``Read/Write`` on another, while both
64
+ switches' web UIs call it ``Super User``. The normalised ``privileged``
65
+ flag beside it agrees across all three.
66
+ * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.get_services`
67
+ - ``list[ServiceStatus]``
68
+ - Whether http, https, telnet and ssh are enabled, and on which port
69
+ where the firmware reports one.
70
+ * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.get_syslog`
71
+ - :py:obj:`~netgear_switch.models.SyslogConfig`
72
+ - Whether remote logging is on, the local source port, and the configured
73
+ collectors.
51
74
 
52
75
  Not every model serves every one of these on every backend.
53
76
  :doc:`../models/support` has the complete grid, and
@@ -58,8 +81,13 @@ Absent data is ``None``, never a substitute
58
81
 
59
82
  A field a backend genuinely cannot read stays ``None``:
60
83
 
61
- * ``PortStatus.description`` is ``None`` on NSDP and HTTP backends, which have
62
- no ``ifAlias`` equivalent — not ``""``.
84
+ * ``PortStatus.description`` is ``None`` where the backend has no ``ifAlias``
85
+ equivalent — not ``""``. NSDP is **not** such a backend: tag 0xB000 carries
86
+ the operator's label and was cross-checked byte-for-byte against three real
87
+ GS110EMX units' own "Port Description" column, so it fills this field like
88
+ SNMP's ifAlias does. ``PortStatus.name`` is the opposite way round there:
89
+ NSDP reports a port NUMBER and no interface identifier, so ``name`` is None
90
+ over NSDP while SNMP gives ``1/0/1`` and the web UI ``g1``.
63
91
  * ``PoEStatus.power_mw`` is ``None`` on a switch with no vendor power column
64
92
  (the GS728TPP serves everything from standard MIBs and has no such column) —
65
93
  not ``0``.
@@ -23,6 +23,16 @@ The operations
23
23
  wait for it to deliver again.
24
24
  * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.clear_poe_fault`
25
25
  - Clear a latched PoE fault on a port.
26
+ * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.set_port_description`
27
+ - Set or clear a port's label. Pass ``""`` to clear it.
28
+ * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.set_port_speed`
29
+ - Force a port's speed and duplex, or restore auto-negotiation. See
30
+ :ref:`speed-vs-negotiated` — the field this write verifies against is
31
+ *not* ``PortStatus.speed_mbps``.
32
+ * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.set_flow_control`
33
+ - Turn IEEE 802.3x flow control on or off for a port. CLI only — no web
34
+ UI captured so far carries a control for it, including the one whose
35
+ ports page *reports* the field.
26
36
  * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.set_pvid`
27
37
  - Set a port's PVID (native VLAN).
28
38
  * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.set_vlan_membership`
@@ -33,6 +43,10 @@ The operations
33
43
  - Delete a VLAN.
34
44
  * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.set_mgmt_ip`
35
45
  - Set the management address, netmask and gateway.
46
+ * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.set_hostname`
47
+ - Set the switch's host name.
48
+ * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.set_syslog_enabled`
49
+ - Turn remote logging on or off. Does not change the collector list.
36
50
  * - :py:obj:`~netgear_switch.sync_api.SyncSwitch.upload_certificate` / :py:obj:`~netgear_switch.sync_api.SyncSwitch.upload_certificate_scp`
37
51
  - Install an HTTPS server certificate — over the web UI, or by FASTPATH
38
52
  ``copy scp://``.
@@ -118,6 +132,58 @@ is here because it explains why the same call can behave differently across two
118
132
  switches from the same family, and why this project refuses to extrapolate
119
133
  between SKUs.
120
134
 
135
+ .. _speed-vs-negotiated:
136
+
137
+ Configured speed is not negotiated speed
138
+ ----------------------------------------
139
+
140
+ ``set_port_speed`` writes the port's *configuration*; :py:obj:`~netgear_switch.models.PortStatus`
141
+ reports both that and the result, in two separate fields:
142
+
143
+ * ``speed_config`` — a :py:obj:`~netgear_switch.models.PortSpeed`: what the port is **set** to
144
+ (``show port``'s "Physical Mode" column). Answers even while the link is down.
145
+ * ``speed_mbps`` / ``full_duplex`` — what the link actually **negotiated**
146
+ ("Physical Status"). ``None`` while the link is down, because a down port has
147
+ negotiated nothing.
148
+
149
+ They are separate because they genuinely disagree, and disagree hardest exactly
150
+ where this library operates. A port forced to 100 Mbit/s with no cable in it
151
+ reports ``speed_config=PortSpeed.forced(100, full_duplex=True)`` and
152
+ ``speed_mbps=None``. ``set_port_speed`` verifies itself against the first;
153
+ verifying against the second would mean a write to any link-down port could
154
+ never be confirmed.
155
+
156
+ .. code-block:: python
157
+
158
+ from netgear_switch import PortSpeed
159
+
160
+ switch.set_port_speed(8, PortSpeed.forced(100, full_duplex=True), force=True)
161
+ switch.set_port_speed(8, PortSpeed.auto(), force=True) # and back
162
+
163
+ **The two backends disagree about a forced 1000, and both are right.**
164
+
165
+ *Over the CLI*, asking for one raises :py:obj:`~netgear_switch.errors.CliCommandError` before
166
+ anything is sent. 1000BASE-T requires auto-negotiation, and the FASTPATH
167
+ grammar encodes that by leaving 1000 out of its forced ``speed`` command
168
+ entirely while keeping it among ``speed auto``'s advertised rates.
169
+
170
+ *Over the GoAhead web UI* (GS728TPP) it is accepted, because that page's own
171
+ Speed control offers "1000M Full Duplex" — and the live switch really does run
172
+ its four SFP uplinks that way. Fibre 1000BASE-X carries no such requirement.
173
+ Harmonising the two into a single rule would have made one of them wrong about
174
+ real hardware, so each backend answers for its own device.
175
+
176
+ Which *other* rates are available differs the same way, and for the same
177
+ reason — the PHY, not the firmware:
178
+
179
+ * **CLI**: no rate table is kept at all. A 1G copper port offered 10/100/10G
180
+ while a 10GBASE-T port on another model offered 100/10G, so the library sends
181
+ what you ask for and surfaces the switch's own ``% Invalid input`` as
182
+ ``CliCommandError``.
183
+ * **HTTP**: the page publishes its choices as a dropdown, so the library
184
+ validates against that captured list (10/100 half or full, 1000 full, Auto)
185
+ and refuses anything else with :py:obj:`~netgear_switch.errors.UnsupportedCapabilityError`.
186
+
121
187
  Certificates
122
188
  ------------
123
189
 
@@ -75,12 +75,13 @@ follows.
75
75
  What this library gives you
76
76
  ---------------------------
77
77
 
78
- **The same operations on every protocol a switch speaks.** Every read and every
79
- write is implemented across SNMP, NSDP, the web UI and the FASTPATH CLI, so the
80
- *caller* picks — useful when SNMP writes are locked down, or when the web port
81
- is all a firewall allows. Reading VLANs over SNMP, HTTP and SSH returns the same
82
- values, and the tests assert it. Where a gap remains, it is listed in
83
- :doc:`models/support`, with the reason.
78
+ **One set of operations, on as many of a switch's protocols as it can serve.**
79
+ The same API drives SNMP, NSDP, the web UI and the FASTPATH CLI, so the *caller*
80
+ picks — useful when SNMP writes are locked down, or when the web port is all a
81
+ firewall allows. Reading VLANs over SNMP, HTTP and SSH returns the same values,
82
+ and the tests assert it. Where a backend cannot serve an operation, the library
83
+ refuses by name instead of quietly answering over a different protocol, and
84
+ :doc:`models/support` records which combinations those are and why.
84
85
 
85
86
  **Plus switches, not only managed ones.** The GS110EMX, GS305EP and GS105PE have
86
87
  no SNMP agent at all; they are driven over NSDP, an undocumented UDP protocol
@@ -13,6 +13,22 @@ At a glance
13
13
 
14
14
  .. ngsw-model-facts:: gs305ep
15
15
 
16
+ **Not captured from hardware.** This is the one model here with no device
17
+ capture and no live run: every unit in this fleet (10.1.5.28-.30) was powered
18
+ off when the attempt was made. What it *is* grounded in is two independent
19
+ implementations that drive these switches — ``py_netgear_plus`` for the
20
+ merge-hash login and the PoE/VLAN CGI paths, and ``netgear-smp-vlan`` for the
21
+ ``8021qCf.cgi``/``8021qMembe.cgi``/``portPVID.cgi`` field shapes and the
22
+ 1=untagged/2=tagged/3=excluded wire codes, observed on a GS105PE.
23
+
24
+ So the page shapes are grounded, but the *values* are not: the mock seed is
25
+ hand-invented (:py:func:`~netgear_switch.virtual.seed.seed_gs305ep` says so) and
26
+ the web-UI fixtures under ``tests/fixtures/http/gs305ep_*.html`` each carry an
27
+ ``UNVERIFIED-pending-capture: synthetic`` marker. Treat behaviour recorded here
28
+ as the documented shape, not as observed values — and see
29
+ :doc:`gs105pe`, whose read paths turned out NOT to be shareable with this model
30
+ even though the two do share a login scheme.
31
+
16
32
  Seed: :py:func:`~netgear_switch.virtual.seed.seed_gs305ep`.
17
33
 
18
34
  What works, over which protocol
@@ -7,8 +7,13 @@ that registry at documentation build time, so it cannot drift from the code.
7
7
 
8
8
  .. ngsw-model-table::
9
9
 
10
- Every model listed above is backed by a real device capture or a live run
11
- against the hardware. :py:func:`~netgear_switch.registry.get_model` resolves a key or
10
+ Every model listed above is backed by evidence, and each model's own page says
11
+ which kind. All but one are a device capture or a live run against the
12
+ hardware. The **GS305EP is the exception**: its support is grounded in two
13
+ independent implementations that drive these switches — ``py_netgear_plus``
14
+ and ``netgear-smp-vlan``, the latter observed against a GS105PE — and no
15
+ GS305EP has been captured, so its mock seed and web-UI fixtures are marked
16
+ synthetic in the source. :py:func:`~netgear_switch.registry.get_model` resolves a key — or
12
17
  an alias, such as ``s3300`` — to the record; ``ngsw models`` prints the whole
13
18
  registry, including the entries these tables leave out, named below.
14
19
 
@@ -32,15 +32,17 @@ the port and the TLS flag, so :py:meth:`~netgear_switch.sync_api.SyncSwitch.get_
32
32
  with ``backend=Backend.HTTP`` reaches it with no special handling from the
33
33
  caller.
34
34
 
35
- **Its firmware requires a ``Referer`` header on every POST.** The same body
36
- returns 403 without one and 200 with it a difference isolated live, then
37
- reproduced by the mock's HTTP face so the requirement cannot regress.
38
-
39
- **The VLAN-write dialect was settled by measurement, not by family.** This
40
- firmware *does* accept some Q-BRIDGE egress writes that the -24X refuses, so the
41
- inference from its sibling could not be trusted even though it happened to land
42
- on the right answer. An A/B/A on port 1/0/1, issuing byte-identical writes while
43
- flipping only that one port's mode, gave:
35
+ **Its firmware requires an ``Origin`` header alongside the ``Referer`` on every
36
+ POST.** A ``Referer`` alone is not enough: the same body returns 403 with only
37
+ the Referer and 200 once Origin accompanies it, on pages whose ``GET`` returns
38
+ 200 — isolated live, then reproduced by the mock's HTTP face so the requirement
39
+ cannot regress.
40
+
41
+ **The VLAN-write dialect was settled by measurement, not by family.** The
42
+ tempting reading that this firmware simply accepts Q-BRIDGE egress writes the
43
+ -24X refuses is not what is happening, and the measurement says so. An A/B/A
44
+ on port 1/0/1, issuing byte-identical writes while flipping only that one port's
45
+ mode, gave:
44
46
 
45
47
  .. code-block:: text
46
48
 
@@ -49,11 +51,14 @@ flipping only that one port's mode, gave:
49
51
  access → commitFailed general → noError
50
52
 
51
53
  ``dot1qVlanStaticEgressPorts`` is writable only while **no interface on the
52
- switch** is in access mode — switch-wide, not per-VLAN. Since an untagged
53
- membership write is expressed *as* access mode, the standard dialect would
54
- disable itself on first use. So this SKU belongs on ``fastpath_switchport``
55
- after all now for a reason rather than a guess. The full account is in
56
- :doc:`../guide/principles`.
54
+ switch** is in access mode — switch-wide, not per-VLAN, and that rule is the
55
+ same on both firmwares. The -24X looks different only because 21 of its 24 ports
56
+ are in access mode, so its column is never writable; nothing about the two
57
+ images differs here. Since an untagged membership write is expressed *as* access
58
+ mode, the standard dialect would disable itself on first use, so this SKU
59
+ belongs on ``fastpath_switchport`` after all — now for a reason rather than a
60
+ guess, and for a reason that is a precondition rather than a firmware quirk. The
61
+ full account is in :doc:`../guide/principles`.
57
62
 
58
63
  Protocols
59
64
  ---------
@@ -93,6 +93,18 @@ restating them. A refusal falls into one of three kinds:
93
93
  most likely to move, because a page that exists but has not been found yet
94
94
  looks exactly the same from here.
95
95
 
96
+ **The device's agent does not implement that operation.**
97
+ The protocol defines it, the hardware has it, and the switch still refuses.
98
+ The GS728TPP's SNMP agent will not create a VLAN: every documented RowStatus
99
+ mechanism — ``createAndGo`` alone, ``createAndGo`` carrying
100
+ ``dot1qVlanStaticName`` in one PDU, ``createAndWait`` → name → ``active``,
101
+ setting the name column alone, and ``createAndGo`` with an egress PortList —
102
+ is answered ``inconsistentValue``. That it is the agent and not the table is
103
+ shown by what the same firmware *does* accept: an existing VLAN's membership
104
+ columns, ``dot1qPvid``, and ``destroy(6)``, while its web UI creates a VLAN
105
+ without complaint. So VLAN creation on that model is an HTTP operation, and
106
+ the refusal names the backend that does work.
107
+
96
108
  What is *not* on this list is "not implemented yet". A backend that could serve
97
109
  an operation but does not is a bug in this library, and is fixed rather than
98
110
  documented.
@@ -104,7 +104,9 @@ Cross-checked against other implementations
104
104
 
105
105
  The v2 fold reproduces ``go-nsdp``'s own test vector byte for byte, and two
106
106
  independent third-party tools decoded the mock's packets. ProSafeLinux decodes
107
- both mock switches completely, with every value matching the seed; the C
107
+ the GS110EMX and GS105PE mocks completely, with every value matching the seed
108
+ (the third NSDP model, the GS305EP, is seeded from invention rather than a
109
+ capture, so decoding it would prove nothing); the C
108
110
  implementation ``ngadmin`` validated the header and surfaced a real four-byte
109
111
  sequence-number bug, since fixed.
110
112