python-netgear-switch-library 0.0.post325__tar.gz → 0.0.post326__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 (374) hide show
  1. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/PKG-INFO +1 -1
  2. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/_ext/support_tables.py +6 -1
  3. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/api/cli.rst +1 -1
  4. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/api/facades.rst +1 -1
  5. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/api/index.rst +1 -1
  6. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/conf.py +43 -2
  7. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/development.rst +2 -2
  8. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/fake/internals.rst +7 -5
  9. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/fake/serving.rst +1 -1
  10. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/fake/testing.rst +105 -41
  11. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/guide/concepts.rst +21 -20
  12. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/guide/configuration.rst +8 -8
  13. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/guide/installation.rst +1 -1
  14. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/guide/quickstart.rst +4 -4
  15. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/guide/reading.rst +17 -17
  16. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/guide/writing.rst +15 -15
  17. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/mcp.rst +1 -1
  18. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/models/gs110emx.rst +1 -1
  19. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/models/gsm7228ps.rst +3 -3
  20. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/models/index.rst +3 -3
  21. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/models/m4300-16x.rst +1 -1
  22. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/models/m4300-24x.rst +5 -5
  23. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/models/support.rst +4 -4
  24. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/protocols/cli.rst +7 -7
  25. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/protocols/http.rst +3 -3
  26. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/protocols/nsdp.rst +4 -4
  27. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/protocols/snmp.rst +3 -3
  28. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/_version.py +2 -2
  29. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/aio_api.py +12 -6
  30. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/.github/workflows/ci.yml +0 -0
  31. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/.github/workflows/deb.yml +0 -0
  32. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/.github/workflows/publish-pypi.yml +0 -0
  33. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/.gitignore +0 -0
  34. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/.readthedocs.yaml +0 -0
  35. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/CLAUDE.md +0 -0
  36. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/LICENSE +0 -0
  37. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/README.md +0 -0
  38. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/RELEASING.md +0 -0
  39. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/debian/changelog +0 -0
  40. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/debian/control +0 -0
  41. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/debian/copyright +0 -0
  42. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/debian/rules +0 -0
  43. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/debian/source/format +0 -0
  44. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/Makefile +0 -0
  45. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/_ext/filelinks.py +0 -0
  46. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/_static/ngsw.css +0 -0
  47. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/api/core.rst +0 -0
  48. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/api/mcp.rst +0 -0
  49. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/api/operations.rst +0 -0
  50. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/api/protocols.rst +0 -0
  51. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/api/transport.rst +0 -0
  52. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/api/virtual.rst +0 -0
  53. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/cli.rst +0 -0
  54. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/fake/index.rst +0 -0
  55. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/guide/principles.rst +0 -0
  56. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/index.rst +0 -0
  57. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/models/gs105pe.rst +0 -0
  58. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/models/gs305ep.rst +0 -0
  59. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/models/gs728tpp.rst +0 -0
  60. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/models/gsm7252ps.rst +0 -0
  61. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/protocols/index.rst +0 -0
  62. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/superpowers/plans/2026-07-15-foundation.md +0 -0
  63. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/superpowers/plans/2026-07-17-slice-02-snmp-read-core.md +0 -0
  64. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/superpowers/plans/2026-07-17-slice-03-read-apis.md +0 -0
  65. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/superpowers/plans/2026-07-18-slice-04-snmp-write.md +0 -0
  66. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/superpowers/plans/2026-07-18-slice-05-nsdp.md +0 -0
  67. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/superpowers/plans/2026-07-18-slice-06-http.md +0 -0
  68. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/superpowers/plans/2026-07-18-slice-07-cli.md +0 -0
  69. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/superpowers/plans/2026-07-18-slice-08-packaging-ci.md +0 -0
  70. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/superpowers/plans/2026-07-23-gsm7252ps-http-xe-dialect.md +0 -0
  71. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/superpowers/specs/2026-07-15-netgear-control-library-design.md +0 -0
  72. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/docs/superpowers/specs/2026-07-23-gsm7252ps-http-xe-dialect-design.md +0 -0
  73. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/packaging/apt-index.html +0 -0
  74. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/packaging/ci-build.sh +0 -0
  75. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/packaging/deb-version.py +0 -0
  76. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/pyproject.toml +0 -0
  77. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/__init__.py +0 -0
  78. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/_dispatch.py +0 -0
  79. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/capabilities.py +0 -0
  80. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/cli/__init__.py +0 -0
  81. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/cli/capture.py +0 -0
  82. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/cli/context.py +0 -0
  83. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/cli/format.py +0 -0
  84. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/cli/main.py +0 -0
  85. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/cli/resolve.py +0 -0
  86. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/cli/safety.py +0 -0
  87. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/cli_read.py +0 -0
  88. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/cli_write.py +0 -0
  89. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/config.py +0 -0
  90. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/errors.py +0 -0
  91. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/http_read.py +0 -0
  92. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/http_write.py +0 -0
  93. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/mcp/__init__.py +0 -0
  94. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/mcp/server.py +0 -0
  95. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/models.py +0 -0
  96. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/nsdp_read.py +0 -0
  97. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/nsdp_write.py +0 -0
  98. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/__init__.py +0 -0
  99. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/cli/__init__.py +0 -0
  100. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/cli/commands.py +0 -0
  101. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/cli/parse.py +0 -0
  102. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/http/__init__.py +0 -0
  103. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/http/crypt.py +0 -0
  104. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/http/endpoints.py +0 -0
  105. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/http/forms.py +0 -0
  106. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/http/parse.py +0 -0
  107. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/http/session.py +0 -0
  108. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/http/types.py +0 -0
  109. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/nsdp/__init__.py +0 -0
  110. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/nsdp/auth.py +0 -0
  111. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/nsdp/client.py +0 -0
  112. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/nsdp/parsers.py +0 -0
  113. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/nsdp/protocol.py +0 -0
  114. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/nsdp/types.py +0 -0
  115. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/nsdp/write.py +0 -0
  116. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/snmp/__init__.py +0 -0
  117. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/snmp/client.py +0 -0
  118. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/snmp/oids.py +0 -0
  119. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/snmp/parse.py +0 -0
  120. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/protocols/snmp/write.py +0 -0
  121. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/py.typed +0 -0
  122. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/registry.py +0 -0
  123. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/snmp_read.py +0 -0
  124. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/snmp_write.py +0 -0
  125. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/sync_api.py +0 -0
  126. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/__init__.py +0 -0
  127. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/aio/__init__.py +0 -0
  128. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/aio/nsdp_udp.py +0 -0
  129. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/aio/snmp_pysnmp.py +0 -0
  130. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/cli/__init__.py +0 -0
  131. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/cli/console.py +0 -0
  132. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/cli/session.py +0 -0
  133. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/cli/ssh.py +0 -0
  134. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/cli/telnet.py +0 -0
  135. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/http/__init__.py +0 -0
  136. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/http/client.py +0 -0
  137. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/sync/__init__.py +0 -0
  138. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/sync/nsdp_udp.py +0 -0
  139. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/transport/sync/snmp_netsnmp_cli.py +0 -0
  140. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/__init__.py +0 -0
  141. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/cli_fastpath.py +0 -0
  142. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/faces/__init__.py +0 -0
  143. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/faces/cli.py +0 -0
  144. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/faces/http.py +0 -0
  145. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/faces/mibview.py +0 -0
  146. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/faces/nsdp.py +0 -0
  147. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/faces/snmp.py +0 -0
  148. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/seed.py +0 -0
  149. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/server.py +0 -0
  150. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/state.py +0 -0
  151. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/web.py +0 -0
  152. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/web_fastpath_vlan.py +0 -0
  153. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/web_fastpath_xui.py +0 -0
  154. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/web_gs105pe.py +0 -0
  155. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/web_gs110emx.py +0 -0
  156. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/web_gs110emx_templates.py +0 -0
  157. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/web_gs728tpp.py +0 -0
  158. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/web_gsm7228ps.py +0 -0
  159. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/web_gsm7252ps.py +0 -0
  160. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/src/netgear_switch/virtual/web_m4300.py +0 -0
  161. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/capture_parity.py +0 -0
  162. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_capture.py +0 -0
  163. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_cli_integration.py +0 -0
  164. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_control_poe_port.py +0 -0
  165. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_control_vlan_ip.py +0 -0
  166. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_format.py +0 -0
  167. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_main_framework.py +0 -0
  168. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_new_commands.py +0 -0
  169. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_op_coverage.py +0 -0
  170. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_prompt_wiring.py +0 -0
  171. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_read_commands.py +0 -0
  172. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_resolve.py +0 -0
  173. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_safety.py +0 -0
  174. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/cli/test_serve.py +0 -0
  175. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/conftest.py +0 -0
  176. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/equivalence.py +0 -0
  177. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/captures/gsm7228ps.json +0 -0
  178. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/captures/gsm7252ps.json +0 -0
  179. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/captures/m4300-16x.json +0 -0
  180. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/captures/m4300-24x.json +0 -0
  181. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7228ps_environment.txt +0 -0
  182. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7228ps_lldp.txt +0 -0
  183. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7228ps_mac_table.txt +0 -0
  184. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7228ps_network.txt +0 -0
  185. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7228ps_poe.txt +0 -0
  186. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7228ps_port_all.txt +0 -0
  187. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7228ps_show_version.txt +0 -0
  188. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7228ps_vlan.txt +0 -0
  189. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7228ps_vlan_brief.txt +0 -0
  190. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7228ps_vlan_port_all.txt +0 -0
  191. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7252ps_show_environment.txt +0 -0
  192. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7252ps_show_interface_ethernet_1_0_1.txt +0 -0
  193. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7252ps_show_lldp_remote_device_all.txt +0 -0
  194. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7252ps_show_mac_addr_table.txt +0 -0
  195. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7252ps_show_network.txt +0 -0
  196. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7252ps_show_poe_port_info_all.txt +0 -0
  197. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7252ps_show_port_all.txt +0 -0
  198. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7252ps_show_version.txt +0 -0
  199. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7252ps_show_vlan_90.txt +0 -0
  200. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7252ps_show_vlan_brief.txt +0 -0
  201. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/gsm7252ps_show_vlan_port_all.txt +0 -0
  202. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_environment.txt +0 -0
  203. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_interface_ethernet_1_0_1.txt +0 -0
  204. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_ip_management.txt +0 -0
  205. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_lldp_remote_device_all.txt +0 -0
  206. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_mac_addr_table.txt +0 -0
  207. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_poe_port_info_all.txt +0 -0
  208. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_port_all.txt +0 -0
  209. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_version.txt +0 -0
  210. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_vlan.txt +0 -0
  211. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_vlan_1.txt +0 -0
  212. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_vlan_4.txt +0 -0
  213. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_vlan_5.txt +0 -0
  214. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_16x_show_vlan_port_all.txt +0 -0
  215. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_24x_show_environment.txt +0 -0
  216. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_24x_show_interface_ethernet_1_0_1.txt +0 -0
  217. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_24x_show_ip_management.txt +0 -0
  218. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_24x_show_lldp_remote_device_all.txt +0 -0
  219. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_24x_show_mac_addr_table.txt +0 -0
  220. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_24x_show_port_all.txt +0 -0
  221. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_24x_show_version.txt +0 -0
  222. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_24x_show_vlan.txt +0 -0
  223. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_24x_show_vlan_5.txt +0 -0
  224. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_24x_show_vlan_90.txt +0 -0
  225. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/cli/m4300_24x_show_vlan_port_all.txt +0 -0
  226. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs105pe_membership.html +0 -0
  227. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs105pe_portstats.html +0 -0
  228. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs105pe_pvid.html +0 -0
  229. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs105pe_status.html +0 -0
  230. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs105pe_switch_info.html +0 -0
  231. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs105pe_vlancfg.html +0 -0
  232. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs110emx_cf8021q.html +0 -0
  233. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs110emx_interface_stats.html +0 -0
  234. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs110emx_login.html +0 -0
  235. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs110emx_port_settings.html +0 -0
  236. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs110emx_pvid.html +0 -0
  237. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs110emx_redirect.html +0 -0
  238. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs110emx_sysinfo.html +0 -0
  239. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs110emx_vlanmembership.html +0 -0
  240. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs305ep_dashboard.html +0 -0
  241. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs305ep_login.html +0 -0
  242. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs305ep_membership.html +0 -0
  243. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs305ep_poestatus.html +0 -0
  244. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs305ep_portstats.html +0 -0
  245. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs305ep_pvid.html +0 -0
  246. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs305ep_vlancfg.html +0 -0
  247. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs728tpp_device_info_and_sensors.xml +0 -0
  248. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs728tpp_lldp.xml +0 -0
  249. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs728tpp_macs.xml +0 -0
  250. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs728tpp_mgmt_ip.xml +0 -0
  251. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs728tpp_poe.xml +0 -0
  252. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs728tpp_ports.xml +0 -0
  253. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs728tpp_pvids_membership.xml +0 -0
  254. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs728tpp_vlan_membership_per_vlan.xml +0 -0
  255. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gs728tpp_vlans.xml +0 -0
  256. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7228ps_basicAddressTable.html +0 -0
  257. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7228ps_ipConfiguration.html +0 -0
  258. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7228ps_lldpRemoteInventory.html +0 -0
  259. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7228ps_poeInterfaceConfiguration.html +0 -0
  260. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7228ps_portPvidConfiguration.html +0 -0
  261. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7228ps_portStatistics.html +0 -0
  262. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7228ps_portsConfiguration.html +0 -0
  263. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7228ps_sysInfo.html +0 -0
  264. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7228ps_vlanPortCfg_vlan5.html +0 -0
  265. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7228ps_vlanStatus.html +0 -0
  266. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_basicAddressTable.html +0 -0
  267. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_ipConfiguration.html +0 -0
  268. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_lldpRemoteInventory.html +0 -0
  269. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_login.html +0 -0
  270. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_poeInterfaceConfiguration.html +0 -0
  271. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_portPvidConfiguration.html +0 -0
  272. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_portStatistics.html +0 -0
  273. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_portsConfiguration.html +0 -0
  274. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_sysInfo.html +0 -0
  275. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan1.html +0 -0
  276. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan141.html +0 -0
  277. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/gsm7252ps_vlanStatus.html +0 -0
  278. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_16x_lldpRemoteInventory.html +0 -0
  279. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_16x_mgmtVlanIpv4Configuration.html +0 -0
  280. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_16x_poeInterfaceConfiguration.html +0 -0
  281. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_16x_portsConfiguration.html +0 -0
  282. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_16x_vlanportcfg_vlan4.html +0 -0
  283. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_24x_poeInterfaceConfiguration.html +0 -0
  284. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_addresstable.html +0 -0
  285. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_lldpRemoteInventory.html +0 -0
  286. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_mgmtVlanIpv4Configuration.html +0 -0
  287. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_ports.html +0 -0
  288. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_portstats.html +0 -0
  289. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_pvid.html +0 -0
  290. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_sysinfo.html +0 -0
  291. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_vlanportcfg_vlan1.html +0 -0
  292. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/http/m4300_vlanstatus.html +0 -0
  293. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/snmp/gsm7252ps_fans.txt +0 -0
  294. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/snmp/gsm7252ps_ifhighspeed.txt +0 -0
  295. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/snmp/gsm7252ps_ifoperstatus.txt +0 -0
  296. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/fixtures/snmp/gsm7252ps_psu.txt +0 -0
  297. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/http_specs.py +0 -0
  298. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/cli/test_cli_parse.py +0 -0
  299. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/http/test_crypt.py +0 -0
  300. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/http/test_endpoints.py +0 -0
  301. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/http/test_forms.py +0 -0
  302. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/http/test_parse.py +0 -0
  303. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/nsdp/test_auth.py +0 -0
  304. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/nsdp/test_parsers.py +0 -0
  305. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/nsdp/test_protocol.py +0 -0
  306. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/nsdp/test_write_frame.py +0 -0
  307. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/snmp/test_client.py +0 -0
  308. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/snmp/test_oids.py +0 -0
  309. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/snmp/test_parse_lldp_macs.py +0 -0
  310. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/snmp/test_parse_mgmt_ip.py +0 -0
  311. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/snmp/test_parse_poe_sensors.py +0 -0
  312. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/snmp/test_parse_ports.py +0 -0
  313. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/snmp/test_parse_system_info.py +0 -0
  314. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/snmp/test_parse_vlans.py +0 -0
  315. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/protocols/snmp/test_write_encode.py +0 -0
  316. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_aio_api.py +0 -0
  317. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_capabilities.py +0 -0
  318. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_cli_read.py +0 -0
  319. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_cli_vlan_write.py +0 -0
  320. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_cli_write.py +0 -0
  321. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_config.py +0 -0
  322. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_cross_backend_equivalence.py +0 -0
  323. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_deb_version.py +0 -0
  324. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_dispatch.py +0 -0
  325. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_errors.py +0 -0
  326. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_facade_equivalence.py +0 -0
  327. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_http_dispatch.py +0 -0
  328. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_http_equivalence.py +0 -0
  329. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_http_read.py +0 -0
  330. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_http_vlan_membership.py +0 -0
  331. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_http_write.py +0 -0
  332. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_http_xui_writes.py +0 -0
  333. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_import.py +0 -0
  334. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_mcp_server.py +0 -0
  335. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_models.py +0 -0
  336. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_models_snmp_read.py +0 -0
  337. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_nsdp_integration.py +0 -0
  338. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_nsdp_read.py +0 -0
  339. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_nsdp_write.py +0 -0
  340. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_public_api.py +0 -0
  341. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_quality_gates.py +0 -0
  342. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_registry.py +0 -0
  343. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_snmp_integration.py +0 -0
  344. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_snmp_read.py +0 -0
  345. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_snmp_write.py +0 -0
  346. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_sync_api.py +0 -0
  347. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_version.py +0 -0
  348. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/test_write_equivalence.py +0 -0
  349. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/transport/_fastpath_fake.py +0 -0
  350. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/transport/test_cli_console.py +0 -0
  351. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/transport/test_cli_scp_cert.py +0 -0
  352. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/transport/test_cli_telnet.py +0 -0
  353. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/transport/test_http_client.py +0 -0
  354. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/transport/test_nsdp_udp_sync.py +0 -0
  355. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/transport/test_set_transport.py +0 -0
  356. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/transport/test_snmp_netsnmp_cli.py +0 -0
  357. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/transport/test_snmp_pysnmp.py +0 -0
  358. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/transport/test_value_parity.py +0 -0
  359. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_cli_cross_backend.py +0 -0
  360. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_cli_gsm7228ps_parity.py +0 -0
  361. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_gsm7228ps_seed.py +0 -0
  362. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_m4300_seeds.py +0 -0
  363. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_mibview.py +0 -0
  364. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_mutable_state.py +0 -0
  365. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_nsdp_state.py +0 -0
  366. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_serve_daemon.py +0 -0
  367. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_snmp_write_face.py +0 -0
  368. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_state_seed.py +0 -0
  369. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_switchport_vlan_write.py +0 -0
  370. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_virtual_http_face.py +0 -0
  371. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_virtual_nsdp_face.py +0 -0
  372. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_virtual_snmp_face.py +0 -0
  373. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/tests/virtual/test_web_projection.py +0 -0
  374. {python_netgear_switch_library-0.0.post325 → python_netgear_switch_library-0.0.post326}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-netgear-switch-library
3
- Version: 0.0.post325
3
+ Version: 0.0.post326
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
@@ -399,7 +399,12 @@ class BackendOperationTable(_GeneratedTable):
399
399
  seen[reason] = index
400
400
  notes.append(reason)
401
401
  cells.append(f"{_NO} [{label}-{index}]_")
402
- rows.append([f":py:meth:`~netgear_switch.SyncSwitch.{op.name}`", *cells])
402
+ # The facade class is documented under its defining module, so a
403
+ # `netgear_switch.SyncSwitch.x` target does not resolve and would
404
+ # render as plain text rather than a link.
405
+ rows.append(
406
+ [f":py:meth:`~netgear_switch.sync_api.SyncSwitch.{op.name}`", *cells]
407
+ )
403
408
  table = _list_table("", ["Operation", *keys], rows)
404
409
  if not notes:
405
410
  return table
@@ -17,7 +17,7 @@ Switch and credential resolution
17
17
  --------------------------------
18
18
 
19
19
  The shared path the CLI *and* the MCP server both use to turn arguments,
20
- environment variables and an inventory into a ready `SyncSwitch`.
20
+ environment variables and an inventory into a ready :py:obj:`~netgear_switch.sync_api.SyncSwitch`.
21
21
 
22
22
  .. automodule:: netgear_switch.cli.resolve
23
23
 
@@ -1,7 +1,7 @@
1
1
  Facades
2
2
  =======
3
3
 
4
- `SyncSwitch` and `AsyncSwitch` are the public entry points. They expose the same
4
+ :py:obj:`~netgear_switch.sync_api.SyncSwitch` and :py:obj:`~netgear_switch.aio_api.AsyncSwitch` are the public entry points. They expose the same
5
5
  operations with the same arguments, and both resolve exactly one backend per
6
6
  call — see :doc:`../guide/concepts`.
7
7
 
@@ -5,7 +5,7 @@ Complete reference for every module in the ``netgear_switch`` package,
5
5
  generated from the source.
6
6
 
7
7
  Most callers need only :doc:`core` (the data model, the registry, the
8
- capability oracle) and :doc:`facades` (`SyncSwitch` and `AsyncSwitch`).
8
+ capability oracle) and :doc:`facades` (:py:obj:`~netgear_switch.sync_api.SyncSwitch` and :py:obj:`~netgear_switch.aio_api.AsyncSwitch`).
9
9
  The rest is there for anyone reading the source, extending a backend, or
10
10
  building on the protocol layer directly.
11
11
 
@@ -75,8 +75,49 @@ exclude_patterns = [
75
75
 
76
76
  # Single backticks mean "a Python object", which is what most inline references
77
77
  # in this project are.
78
- default_role = "py:obj"
79
- nitpicky = False
78
+ # Single backticks mean "literal", not "cross-reference". The library's
79
+ # docstrings use them loosely for prose and shell fragments (`snmpget`,
80
+ # `apt-get install -y snmp`, `type: ignore`), which a py:obj default role turns
81
+ # into a flood of unresolvable references under nitpicky mode. Cross-references
82
+ # in this documentation are always written with an explicit role, so nothing is
83
+ # lost -- and filelinks still turns any literal naming a repository file into a
84
+ # link to that file.
85
+ default_role = "literal"
86
+
87
+ # Every cross-reference must resolve, or the build fails. This is what keeps the
88
+ # documentation actually hyperlinked: an unresolved `py:obj` renders as plain
89
+ # text, so without this a whole page of API names can silently stop being links
90
+ # -- which is exactly what happened when references were written as
91
+ # `netgear_switch.SyncSwitch` (autodoc documents the class under its DEFINING
92
+ # module, netgear_switch.sync_api, so the short path never resolved).
93
+ nitpicky = True
94
+ nitpick_ignore = [
95
+ # Base classes autodoc emits for our enums. They resolve through
96
+ # intersphinx, so these only matter for an offline build.
97
+ ("py:class", "enum.Enum"),
98
+ ("py:class", "enum.IntEnum"),
99
+ ]
100
+
101
+ # Napoleon splits a docstring "Returns:"/"Attributes:" type on its first comma,
102
+ # so a generic like ``tuple[NsdpPortStatus, ...]`` arrives as the fragment
103
+ # ``'tuple[NsdpPortStatus``. These are mis-parses of a real annotation, not
104
+ # broken links; the signatures autodoc renders from the actual type hints are
105
+ # correct. Ignored by shape so a genuinely missing class still fails the build.
106
+ nitpick_ignore_regex = [
107
+ ("py:class", r"^'?(?:tuple|list|dict|Mapping|Sequence|frozenset)\[.*"),
108
+ # A prose Attributes: entry whose type slot holds a sentence.
109
+ ("py:class", r"^The [A-Z].*"),
110
+ ]
111
+
112
+ if os.environ.get("NGSW_DOCS_OFFLINE"):
113
+ # Standard-library targets that only resolve when intersphinx can fetch its
114
+ # inventory. Online (CI and Read the Docs) they link properly and stay
115
+ # strict; offline they would be noise.
116
+ nitpick_ignore += [
117
+ ("py:class", "argparse.ArgumentParser"),
118
+ ("py:func", "asyncio.to_thread"),
119
+ ("py:func", "importlib.import_module"),
120
+ ]
80
121
  maximum_signature_line_length = 88
81
122
 
82
123
  # -- Autodoc ------------------------------------------------------------------
@@ -33,7 +33,7 @@ hardware, no network. Coverage is enforced at 90%.
33
33
  - That every backend of a model reports the same thing — the parity
34
34
  guarantee, checked rather than asserted in prose.
35
35
  * - ``tests/test_facade_equivalence.py``
36
- - That `SyncSwitch` and `AsyncSwitch` stay in step.
36
+ - That :py:obj:`~netgear_switch.sync_api.SyncSwitch` and :py:obj:`~netgear_switch.aio_api.AsyncSwitch` stay in step.
37
37
  * - ``tests/test_capabilities.py``
38
38
  - That the support tables in these docs match what the code actually does,
39
39
  by driving every operation for real.
@@ -96,7 +96,7 @@ The rules
96
96
 
97
97
  * **Never declare something unsupported to finish a task.** If you cannot
98
98
  implement it, say so plainly — naming the model, backend and operation — and
99
- leave behind no `UnsupportedCapabilityError` that lacks captured device output
99
+ leave behind no :py:obj:`~netgear_switch.errors.UnsupportedCapabilityError` that lacks captured device output
100
100
  as proof. An honest "not done, here's why" is wanted; a false "the hardware
101
101
  can't" is not.
102
102
  * **Implement across all backends and all models,** or state precisely which
@@ -65,7 +65,7 @@ The faces
65
65
  * - ``faces/cli.py``
66
66
  - nothing
67
67
  - In-process: implements the ``CliSession`` protocol directly, so no SSH
68
- or telnet server is needed. Reached via `VirtualSwitch.cli_session`.
68
+ or telnet server is needed. Reached via :py:obj:`~netgear_switch.virtual.server.VirtualSwitch.cli_session`.
69
69
 
70
70
  ``faces/mibview.py`` deserves a note. It builds a **sorted** OID view from the
71
71
  state so GETNEXT and GETBULK have real lexicographic-ordering semantics rather
@@ -93,8 +93,8 @@ From a real switch to a seed
93
93
 
94
94
  ngsw --switch core capture tmp/core.json
95
95
 
96
- `ngsw capture <cli.capture>` records the switch's full state via
97
- `SyncSwitch.snapshot`, and — given live access and a raw-walk callable — the
96
+ :doc:`ngsw capture <../cli>` records the switch's full state via
97
+ :py:obj:`~netgear_switch.sync_api.SyncSwitch.snapshot`, and — given live access and a raw-walk callable — the
98
98
  reference ``snmpbulkwalk`` output alongside it. The result is a JSON file used
99
99
  **for reference** when hand-authoring a seed. It is deliberately not loaded
100
100
  directly by the mock.
@@ -186,7 +186,8 @@ Where things live
186
186
  * - ``src/netgear_switch/virtual/seed.py``
187
187
  - One seed builder per model.
188
188
  * - ``src/netgear_switch/virtual/server.py``
189
- - ``VirtualSwitch``, the seed map, and ``serve_forever``.
189
+ - :py:class:`~netgear_switch.virtual.server.VirtualSwitch`, the seed map,
190
+ and :py:func:`~netgear_switch.virtual.server.serve_forever`.
190
191
  * - ``src/netgear_switch/virtual/faces/``
191
192
  - The protocol faces.
192
193
  * - ``tests/fixtures/captures/``
@@ -194,4 +195,5 @@ Where things live
194
195
  * - ``tests/virtual/``
195
196
  - Tests of the mock itself.
196
197
  * - ``tests/conftest.py``
197
- - The per-model ``VirtualSwitch`` fixtures this project uses.
198
+ - The per-model :py:class:`~netgear_switch.virtual.server.VirtualSwitch`
199
+ fixtures this project uses.
@@ -141,7 +141,7 @@ The FASTPATH CLI
141
141
  The CLI face is deliberately **in-process**: it implements the ``CliSession``
142
142
  protocol rather than binding an SSH or telnet listener, so there is no key
143
143
  exchange or terminal emulation to fight. It is reached through
144
- `VirtualSwitch.cli_session`, not over a socket, and so is not exposed by
144
+ :py:obj:`~netgear_switch.virtual.server.VirtualSwitch.cli_session`, not over a socket, and so is not exposed by
145
145
  ``ngsw serve``. See :doc:`testing`.
146
146
 
147
147
  This library against a mock
@@ -37,7 +37,7 @@ A pytest fixture
37
37
  finally:
38
38
  mock.stop()
39
39
 
40
- `VirtualSwitch` is also a context manager, which is usually enough:
40
+ :py:obj:`~netgear_switch.virtual.server.VirtualSwitch` is also a context manager, which is usually enough:
41
41
 
42
42
  .. code-block:: python
43
43
 
@@ -127,7 +127,7 @@ Every backend takes an injected client:
127
127
  async: the same arguments to ``AsyncHttpClient``.
128
128
  * - CLI
129
129
  - ``cli_client=mock.cli_session()`` — **synchronous only**. The CLI
130
- transports block, so :py:class:`~netgear_switch.AsyncSwitch` has no CLI
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
133
  All four at once
@@ -136,31 +136,66 @@ All four at once
136
136
  One mock, one facade, three protocols — which is what makes cross-backend
137
137
  behaviour testable without hardware:
138
138
 
139
- .. code-block:: python
139
+ .. tab-set::
140
140
 
141
- from netgear_switch import Backend, SyncSwitch, get_model
142
- from netgear_switch.protocols.http.endpoints import http_spec
143
- from netgear_switch.transport.http.client import HttpClient
144
- from netgear_switch.transport.sync.snmp_netsnmp_cli import NetsnmpCliClient
145
- from netgear_switch.virtual.server import VirtualSwitch
141
+ .. tab-item:: Sync
142
+ :sync: sync
146
143
 
147
- model = get_model("gsm7252ps")
148
- with VirtualSwitch(model="gsm7252ps") as mock:
149
- switch = SyncSwitch(
150
- model,
151
- host=mock.host,
152
- snmp_client=NetsnmpCliClient(f"{mock.host}:{mock.port}", "public"),
153
- http_client=HttpClient(
154
- f"{mock.host}:{mock.http_port}", "password", http_spec(model)
155
- ),
156
- cli_client=mock.cli_session(),
157
- )
158
- snmp = switch.get_vlans(backend=Backend.SNMP)
159
- http = switch.get_vlans(backend=Backend.HTTP)
160
- cli = switch.get_vlans(backend=Backend.SSH)
144
+ .. code-block:: python
145
+
146
+ from netgear_switch import Backend, SyncSwitch, get_model
147
+ from netgear_switch.protocols.http.endpoints import http_spec
148
+ from netgear_switch.transport.http.client import HttpClient
149
+ from netgear_switch.transport.sync.snmp_netsnmp_cli import NetsnmpCliClient
150
+ from netgear_switch.virtual.server import VirtualSwitch
151
+
152
+ model = get_model("gsm7252ps")
153
+ with VirtualSwitch(model="gsm7252ps") as mock:
154
+ switch = SyncSwitch(
155
+ model,
156
+ host=mock.host,
157
+ snmp_client=NetsnmpCliClient(f"{mock.host}:{mock.port}", "public"),
158
+ http_client=HttpClient(
159
+ f"{mock.host}:{mock.http_port}", "password", http_spec(model)
160
+ ),
161
+ cli_client=mock.cli_session(),
162
+ )
163
+ snmp = switch.get_vlans(backend=Backend.SNMP)
164
+ http = switch.get_vlans(backend=Backend.HTTP)
165
+ cli = switch.get_vlans(backend=Backend.SSH)
166
+
167
+ assert {v.vlan_id for v in snmp} == {v.vlan_id for v in http} \
168
+ == {v.vlan_id for v in cli}
169
+
170
+ .. tab-item:: Async
171
+ :sync: async
172
+
173
+ .. code-block:: python
174
+
175
+ from netgear_switch import AsyncSwitch, Backend, get_model
176
+ from netgear_switch.protocols.http.endpoints import http_spec
177
+ from netgear_switch.transport.aio.snmp_pysnmp import PysnmpClient
178
+ from netgear_switch.transport.http.client import AsyncHttpClient
179
+ from netgear_switch.virtual.server import VirtualSwitch
161
180
 
162
- assert {v.vlan_id for v in snmp} == {v.vlan_id for v in http} \
163
- == {v.vlan_id for v in cli}
181
+ model = get_model("gsm7252ps")
182
+ with VirtualSwitch(model="gsm7252ps") as mock:
183
+ switch = AsyncSwitch(
184
+ model,
185
+ host=mock.host,
186
+ snmp_client=PysnmpClient(mock.host, "public", port=mock.port),
187
+ http_client=AsyncHttpClient(
188
+ f"{mock.host}:{mock.http_port}", "password", http_spec(model)
189
+ ),
190
+ # No cli_client: the async facade has no CLI backend.
191
+ )
192
+ try:
193
+ snmp = await switch.get_vlans(backend=Backend.SNMP)
194
+ http = await switch.get_vlans(backend=Backend.HTTP)
195
+
196
+ assert {v.vlan_id for v in snmp} == {v.vlan_id for v in http}
197
+ finally:
198
+ await switch.aclose()
164
199
 
165
200
  .. code-block:: text
166
201
 
@@ -197,24 +232,53 @@ Testing that your code handles refusals
197
232
  The most valuable thing a faithful mock gives you is the *failure* paths. The
198
233
  mock refuses exactly what the hardware refuses, with the same message:
199
234
 
200
- .. code-block:: python
235
+ .. tab-set::
201
236
 
202
- from netgear_switch import SyncSwitch, UnsupportedCapabilityError, get_model
203
- from netgear_switch.transport.sync.nsdp_udp import UdpNsdpClient
204
- from netgear_switch.virtual.server import VirtualSwitch
237
+ .. tab-item:: Sync
238
+ :sync: sync
205
239
 
206
- with VirtualSwitch(model="gs110emx") as mock:
207
- switch = SyncSwitch(
208
- get_model("gs110emx"),
209
- host=mock.host,
210
- nsdp_client=UdpNsdpClient(
211
- mock.host, client_port=0, server_port=mock.port, timeout=2.0
212
- ),
213
- )
214
- try:
215
- switch.get_poe()
216
- except UnsupportedCapabilityError as exc:
217
- print(exc)
240
+ .. code-block:: python
241
+
242
+ from netgear_switch import SyncSwitch, UnsupportedCapabilityError, get_model
243
+ from netgear_switch.transport.sync.nsdp_udp import UdpNsdpClient
244
+ from netgear_switch.virtual.server import VirtualSwitch
245
+
246
+ with VirtualSwitch(model="gs110emx") as mock:
247
+ switch = SyncSwitch(
248
+ get_model("gs110emx"),
249
+ host=mock.host,
250
+ nsdp_client=UdpNsdpClient(
251
+ mock.host, client_port=0, server_port=mock.port, timeout=2.0
252
+ ),
253
+ )
254
+ try:
255
+ switch.get_poe()
256
+ except UnsupportedCapabilityError as exc:
257
+ print(exc)
258
+
259
+ .. tab-item:: Async
260
+ :sync: async
261
+
262
+ .. code-block:: python
263
+
264
+ from netgear_switch import AsyncSwitch, UnsupportedCapabilityError, get_model
265
+ from netgear_switch.transport.aio.nsdp_udp import AsyncUdpNsdpClient
266
+ from netgear_switch.virtual.server import VirtualSwitch
267
+
268
+ with VirtualSwitch(model="gs110emx") as mock:
269
+ switch = AsyncSwitch(
270
+ get_model("gs110emx"),
271
+ host=mock.host,
272
+ nsdp_client=AsyncUdpNsdpClient(
273
+ mock.host, client_port=0, server_port=mock.port, timeout=2.0
274
+ ),
275
+ )
276
+ try:
277
+ await switch.get_poe()
278
+ except UnsupportedCapabilityError as exc:
279
+ print(exc)
280
+ finally:
281
+ await switch.aclose()
218
282
 
219
283
  .. code-block:: text
220
284
 
@@ -272,7 +336,7 @@ configuration:
272
336
  Crafting a scenario
273
337
  -------------------
274
338
 
275
- `VirtualSwitch.state` is an ordinary mutable dataclass. Edit it to produce the
339
+ ``VirtualSwitch.state`` is an ordinary mutable dataclass. Edit it to produce the
276
340
  condition you want to test — a dead link, a PoE fault, a full MAC table:
277
341
 
278
342
  .. code-block:: python
@@ -10,7 +10,7 @@ Models
10
10
  A switch model is a frozen `netgear_switch.registry.SwitchModel` record: its
11
11
  key, display name, class, port and PoE-port counts, the backends it exposes, its
12
12
  SNMP vendor OID subtree, and a few per-model protocol dialect flags. The whole
13
- registry lives in ``src/netgear_switch/registry.py``, and `get_model` resolves a
13
+ registry lives in ``src/netgear_switch/registry.py``, and :py:obj:`~netgear_switch.registry.get_model` resolves a
14
14
  key (or an alias, such as ``s3300`` for ``gsm7228ps``) to the record.
15
15
 
16
16
  Models fall into three classes, which is what decides the protocols available:
@@ -83,11 +83,11 @@ Dispatch: exactly one backend, every time
83
83
  await switch.get_vlans(backend=Backend.HTTP) # exactly HTTP, or an error
84
84
 
85
85
  When you **name** a backend, that backend runs. If the model does not have it,
86
- you get `UnsupportedCapabilityError` immediately. If it has it but cannot serve
87
- that operation, you get `UnsupportedCapabilityError` naming the backend you
86
+ you get :py:obj:`~netgear_switch.errors.UnsupportedCapabilityError` immediately. If it has it but cannot serve
87
+ that operation, you get :py:obj:`~netgear_switch.errors.UnsupportedCapabilityError` naming the backend you
88
88
  asked for.
89
89
 
90
- When you **do not** name one, `SyncSwitch.resolve_backend` picks the first
90
+ When you **do not** name one, :py:obj:`~netgear_switch.sync_api.SyncSwitch.resolve_backend` picks the first
91
91
  backend the model declares, in the fixed order **SNMP → NSDP → HTTP → SSH →
92
92
  TELNET → CONSOLE**. The choice depends only on the model, never on the
93
93
  operation: the facade does not probe one backend, catch its refusal, and try
@@ -105,7 +105,8 @@ names the other backends you could pass:
105
105
 
106
106
  **The library will never answer over a protocol you did not get.** This was
107
107
  not always true, and the cost of the old behaviour is why the rule is
108
- absolute. ``SyncSwitch`` used to loop over SNMP → NSDP → HTTP, silently
108
+ absolute. :py:class:`~netgear_switch.sync_api.SyncSwitch` used to loop over
109
+ SNMP → NSDP → HTTP, silently
109
110
  returning the next backend's answer when one raised. That hid a real defect
110
111
  for months — ``HttpReader.get_vlans`` returned no untagged ports at all on
111
112
  the managed switches, and nobody noticed because SNMP quietly answered
@@ -149,7 +150,7 @@ Verification status
149
150
  This project distinguishes what has been *measured* from what has been
150
151
  *assumed*, and the distinction is visible in the API.
151
152
 
152
- `SwitchModel.verified`
153
+ :py:attr:`~netgear_switch.registry.SwitchModel.verified`
153
154
  ``False`` marks a model registered from a specification sheet, with no
154
155
  device of that kind ever reachable from this project. Such a model is
155
156
  **excluded from every support table** — see :doc:`../models/index` —
@@ -167,7 +168,7 @@ This project distinguishes what has been *measured* from what has been
167
168
  Errors
168
169
  ------
169
170
 
170
- All errors derive from `NetgearSwitchError`. The distinctions that matter:
171
+ All errors derive from :py:obj:`~netgear_switch.errors.NetgearSwitchError`. The distinctions that matter:
171
172
 
172
173
  .. list-table::
173
174
  :header-rows: 1
@@ -175,36 +176,36 @@ All errors derive from `NetgearSwitchError`. The distinctions that matter:
175
176
 
176
177
  * - Error
177
178
  - Means
178
- * - `UnsupportedCapabilityError`
179
+ * - :py:obj:`~netgear_switch.errors.UnsupportedCapabilityError`
179
180
  - This backend genuinely cannot do this, for this model. Never "not
180
181
  implemented yet" — a missing implementation is a bug to fix, not a
181
182
  device limitation to document.
182
- * - `CredentialError`
183
+ * - :py:obj:`~netgear_switch.errors.CredentialError`
183
184
  - A credential is missing or wrong. Note that an SNMP agent **silently
184
185
  drops** an unauthorised request, so a wrong write community looks exactly
185
186
  like an unreachable host.
186
- * - `WriteVerificationError`
187
+ * - :py:obj:`~netgear_switch.errors.WriteVerificationError`
187
188
  - The write was sent and accepted, but reading back did not show the
188
189
  intended value.
189
- * - `ProtectedPortError`
190
+ * - :py:obj:`~netgear_switch.errors.ProtectedPortError`
190
191
  - The port is in this switch's ``protected_ports`` set. Pass ``force=True``
191
192
  to override.
192
- * - `HttpAuthError`, `HttpUnexpectedPageError`
193
+ * - :py:obj:`~netgear_switch.errors.HttpAuthError`, :py:obj:`~netgear_switch.errors.HttpUnexpectedPageError`
193
194
  - Web-UI login failed, or a page did not look like what the model's dialect
194
195
  expects (usually a session that expired).
195
- * - `CliCommandError`
196
+ * - :py:obj:`~netgear_switch.errors.CliCommandError`
196
197
  - The switch's CLI rejected a command; the message carries what it said.
197
198
 
198
199
  `NotImplementedError` appears in exactly one place — certificate upload on a
199
200
  model whose real mechanism is known but not wired to that backend. It is
200
- deliberately *not* `UnsupportedCapabilityError`, because the hardware can do it;
201
+ deliberately *not* :py:obj:`~netgear_switch.errors.UnsupportedCapabilityError`, because the hardware can do it;
201
202
  see :doc:`../models/support`.
202
203
 
203
204
  Synchronous and asynchronous
204
205
  ----------------------------
205
206
 
206
- :py:class:`~netgear_switch.SyncSwitch` and
207
- :py:class:`~netgear_switch.AsyncSwitch` expose the same operations with the same
207
+ :py:class:`~netgear_switch.sync_api.SyncSwitch` and
208
+ :py:class:`~netgear_switch.aio_api.AsyncSwitch` expose the same operations with the same
208
209
  arguments and the same semantics. They share the model registry, the parsers and
209
210
  the backend-resolution seam in ``src/netgear_switch/_dispatch.py``; only the
210
211
  transports differ. ``tests/test_facade_equivalence.py`` asserts they stay in
@@ -214,18 +215,18 @@ step.
214
215
 
215
216
  **One backend is synchronous-only: the CLI.** All three CLI transports —
216
217
  SSH, telnet and the serial console — are blocking, and none has an async
217
- twin, so :py:class:`~netgear_switch.AsyncSwitch` has no CLI backend at all.
218
+ twin, so :py:class:`~netgear_switch.aio_api.AsyncSwitch` has no CLI backend at all.
218
219
  Asking for one raises rather than quietly blocking the event loop::
219
220
 
220
221
  UnsupportedCapabilityError: model 'gsm7252ps' CLI reads are not available
221
222
  via the async facade (CLI is synchronous ...)
222
223
 
223
224
  That also rules out
224
- :py:meth:`~netgear_switch.SyncSwitch.upload_certificate_scp` on the async
225
+ :py:meth:`~netgear_switch.sync_api.SyncSwitch.upload_certificate_scp` on the async
225
226
  facade, since the operation is CLI-based by nature. Use
226
- :py:class:`~netgear_switch.SyncSwitch` for those, or wrap the call in
227
+ :py:class:`~netgear_switch.sync_api.SyncSwitch` for those, or wrap the call in
227
228
  :py:func:`asyncio.to_thread`.
228
229
 
229
230
  **The support tables in** :doc:`../models/support` **describe the
230
231
  synchronous facade.** Every SNMP, NSDP and HTTP entry holds for both; the CLI
231
- columns apply to :py:class:`~netgear_switch.SyncSwitch` only.
232
+ columns apply to :py:class:`~netgear_switch.sync_api.SyncSwitch` only.
@@ -2,7 +2,7 @@ Inventories and credentials
2
2
  ===========================
3
3
 
4
4
  Hosts, models and credentials belong in an inventory file, not in your code or
5
- your shell history. `load_inventory` reads a TOML file into
5
+ your shell history. :py:obj:`~netgear_switch.config.load_inventory` reads a TOML file into
6
6
  ``{name: SwitchConfig}``; the ``ngsw`` CLI and the MCP server both use it, via
7
7
  the same resolver.
8
8
 
@@ -70,7 +70,7 @@ Per switch:
70
70
  Secret specs
71
71
  ------------
72
72
 
73
- Any value marked "secret spec" above is resolved by `resolve_secret`, which
73
+ Any value marked "secret spec" above is resolved by :py:obj:`~netgear_switch.config.resolve_secret`, which
74
74
  accepts three forms:
75
75
 
76
76
  .. list-table::
@@ -80,16 +80,16 @@ accepts three forms:
80
80
  * - Form
81
81
  - Behaviour
82
82
  * - ``${NAME}``
83
- - Read environment variable ``NAME``. `CredentialError` if unset.
83
+ - Read environment variable ``NAME``. :py:obj:`~netgear_switch.errors.CredentialError` if unset.
84
84
  * - ``!command args``
85
85
  - Run the command (split with ``shlex``, no shell) and take its stdout,
86
- stripped. A 10-second timeout; a non-zero exit raises `CredentialError`
86
+ stripped. A 10-second timeout; a non-zero exit raises :py:obj:`~netgear_switch.errors.CredentialError`
87
87
  with the command's stderr.
88
88
  * - anything else
89
89
  - The literal secret.
90
90
 
91
91
  Prefer the first two. **If any secret in the file is a literal, the file's
92
- permissions are checked** and `load_inventory` raises `ConfigError` unless the
92
+ permissions are checked** and :py:obj:`~netgear_switch.config.load_inventory` raises :py:obj:`~netgear_switch.errors.ConfigError` unless the
93
93
  file is unreadable by group and other:
94
94
 
95
95
  .. code-block:: text
@@ -97,7 +97,7 @@ file is unreadable by group and other:
97
97
  ConfigError: inventory.toml has insecure permissions 0o644; chmod 600 it
98
98
  (contains a literal secret)
99
99
 
100
- That check is `ensure_secure_file`, and it only fires when a literal is present
100
+ That check is :py:obj:`~netgear_switch.config.ensure_secure_file`, and it only fires when a literal is present
101
101
  — a file containing only ``${VAR}`` and ``!command`` specs needs no special
102
102
  mode.
103
103
 
@@ -136,7 +136,7 @@ Using an inventory
136
136
  finally:
137
137
  await switch.aclose()
138
138
 
139
- `SwitchConfig.snmp_write_community` and `SwitchConfig.http_password` resolve
139
+ :py:attr:`~netgear_switch.config.SwitchConfig.snmp_write_community` and :py:attr:`~netgear_switch.config.SwitchConfig.http_password` resolve
140
140
  their specs on demand and take an explicit ``env=`` mapping, which makes them
141
141
  straightforward to test.
142
142
 
@@ -177,7 +177,7 @@ Protected ports
177
177
  ---------------
178
178
 
179
179
  ``protected_ports`` is enforced by the library, not just the CLI. Every write
180
- that names a port checks it and raises `ProtectedPortError` unless
180
+ that names a port checks it and raises :py:obj:`~netgear_switch.errors.ProtectedPortError` unless
181
181
  ``force=True``:
182
182
 
183
183
  .. tab-set::
@@ -32,7 +32,7 @@ in an HTTP stack, and vice versa.
32
32
  - Needed for
33
33
  * - ``[async]``
34
34
  - :pypi:`pysnmp`
35
- - The asynchronous SNMP transport used by `AsyncSwitch`.
35
+ - The asynchronous SNMP transport used by :py:obj:`~netgear_switch.aio_api.AsyncSwitch`.
36
36
  * - ``[http]``
37
37
  - :pypi:`httpx`
38
38
  - Every web-UI backend, synchronous and asynchronous.
@@ -9,8 +9,8 @@ faithful mock switches, and the example points at one.
9
9
  Every example below appears in **synchronous** and **asynchronous** form.
10
10
  Choosing one switches every example on the page, and the choice is
11
11
  remembered as you move around the site.
12
- :py:class:`~netgear_switch.SyncSwitch` and
13
- :py:class:`~netgear_switch.AsyncSwitch` expose the same operations with the
12
+ :py:class:`~netgear_switch.sync_api.SyncSwitch` and
13
+ :py:class:`~netgear_switch.aio_api.AsyncSwitch` expose the same operations with the
14
14
  same arguments; only the transports differ.
15
15
 
16
16
  Talk to a mock in-process
@@ -88,8 +88,8 @@ the switch at 10.1.5.22, not from invented values. See :doc:`../fake/index`.
88
88
  Talk to a real switch
89
89
  ---------------------
90
90
 
91
- The first argument is a :py:class:`~netgear_switch.SwitchModel`, which
92
- :py:func:`~netgear_switch.get_model` resolves from a registry key (``ngsw
91
+ The first argument is a :py:class:`~netgear_switch.registry.SwitchModel`, which
92
+ :py:func:`~netgear_switch.registry.get_model` resolves from a registry key (``ngsw
93
93
  models`` lists them all).
94
94
 
95
95
  .. tab-set::