python-netgear-switch-library 0.0.post349__tar.gz → 0.0.post351__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 (390) hide show
  1. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/PKG-INFO +1 -1
  2. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/_version.py +2 -2
  3. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli_write.py +11 -0
  4. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/http_read.py +79 -0
  5. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/http_write.py +44 -6
  6. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/models.py +11 -0
  7. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/nsdp_read.py +75 -1
  8. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/nsdp_write.py +32 -0
  9. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/cli/parse.py +35 -3
  10. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/snmp_read.py +70 -0
  11. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/.github/workflows/ci.yml +0 -0
  12. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/.github/workflows/deb.yml +0 -0
  13. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/.github/workflows/publish-pypi.yml +0 -0
  14. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/.gitignore +0 -0
  15. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/.readthedocs.yaml +0 -0
  16. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/CLAUDE.md +0 -0
  17. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/LICENSE +0 -0
  18. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/README.md +0 -0
  19. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/RELEASING.md +0 -0
  20. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/debian/changelog +0 -0
  21. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/debian/control +0 -0
  22. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/debian/copyright +0 -0
  23. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/debian/rules +0 -0
  24. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/debian/source/format +0 -0
  25. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/Makefile +0 -0
  26. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_ext/filelinks.py +0 -0
  27. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_ext/support_tables.py +0 -0
  28. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gs105pe.png +0 -0
  29. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gs110emx.png +0 -0
  30. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gs305ep.png +0 -0
  31. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gs728tpp.png +0 -0
  32. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gsm7228ps.jpg +0 -0
  33. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gsm7252ps.jpg +0 -0
  34. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/m4300-16x.png +0 -0
  35. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/m4300-24x.png +0 -0
  36. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/ngsw.css +0 -0
  37. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/cli.rst +0 -0
  38. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/core.rst +0 -0
  39. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/facades.rst +0 -0
  40. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/index.rst +0 -0
  41. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/mcp.rst +0 -0
  42. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/operations.rst +0 -0
  43. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/protocols.rst +0 -0
  44. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/transport.rst +0 -0
  45. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/virtual.rst +0 -0
  46. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/cli.rst +0 -0
  47. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/conf.py +0 -0
  48. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/development.rst +0 -0
  49. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/fake/index.rst +0 -0
  50. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/fake/internals.rst +0 -0
  51. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/fake/serving.rst +0 -0
  52. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/fake/testing.rst +0 -0
  53. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/concepts.rst +0 -0
  54. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/configuration.rst +0 -0
  55. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/installation.rst +0 -0
  56. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/principles.rst +0 -0
  57. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/quickstart.rst +0 -0
  58. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/reading.rst +0 -0
  59. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/writing.rst +0 -0
  60. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/index.rst +0 -0
  61. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/mcp.rst +0 -0
  62. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gs105pe.rst +0 -0
  63. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gs110emx.rst +0 -0
  64. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gs305ep.rst +0 -0
  65. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gs728tpp.rst +0 -0
  66. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gsm7228ps.rst +0 -0
  67. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gsm7252ps.rst +0 -0
  68. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/index.rst +0 -0
  69. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/m4300-16x.rst +0 -0
  70. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/m4300-24x.rst +0 -0
  71. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/support.rst +0 -0
  72. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/cli.rst +0 -0
  73. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http/cheetah-form.rst +0 -0
  74. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http/cheetah-v1.rst +0 -0
  75. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http/gambit.rst +0 -0
  76. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http/merge-hash-cgi.rst +0 -0
  77. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http/xml-api.rst +0 -0
  78. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http.rst +0 -0
  79. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/index.rst +0 -0
  80. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/nsdp.rst +0 -0
  81. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/snmp.rst +0 -0
  82. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/plans/2026-07-15-foundation.md +0 -0
  83. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/plans/2026-07-17-slice-02-snmp-read-core.md +0 -0
  84. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/plans/2026-07-17-slice-03-read-apis.md +0 -0
  85. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/plans/2026-07-18-slice-04-snmp-write.md +0 -0
  86. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/plans/2026-07-18-slice-05-nsdp.md +0 -0
  87. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/plans/2026-07-18-slice-06-http.md +0 -0
  88. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/plans/2026-07-18-slice-07-cli.md +0 -0
  89. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/plans/2026-07-18-slice-08-packaging-ci.md +0 -0
  90. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/plans/2026-07-23-gsm7252ps-http-xe-dialect.md +0 -0
  91. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/specs/2026-07-15-netgear-control-library-design.md +0 -0
  92. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/specs/2026-07-23-gsm7252ps-http-xe-dialect-design.md +0 -0
  93. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/specs/2026-08-02-snmp-surface-findings.md +0 -0
  94. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/packaging/apt-index.html +0 -0
  95. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/packaging/ci-build.sh +0 -0
  96. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/packaging/deb-version.py +0 -0
  97. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/pyproject.toml +0 -0
  98. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/__init__.py +0 -0
  99. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/_dispatch.py +0 -0
  100. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/aio_api.py +0 -0
  101. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/capabilities.py +0 -0
  102. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/__init__.py +0 -0
  103. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/capture.py +0 -0
  104. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/context.py +0 -0
  105. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/format.py +0 -0
  106. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/main.py +0 -0
  107. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/resolve.py +0 -0
  108. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/safety.py +0 -0
  109. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli_read.py +0 -0
  110. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/config.py +0 -0
  111. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/errors.py +0 -0
  112. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/mcp/__init__.py +0 -0
  113. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/mcp/server.py +0 -0
  114. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/__init__.py +0 -0
  115. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/cli/__init__.py +0 -0
  116. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/cli/commands.py +0 -0
  117. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/__init__.py +0 -0
  118. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/crypt.py +0 -0
  119. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/endpoints.py +0 -0
  120. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/forms.py +0 -0
  121. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/parse.py +0 -0
  122. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/session.py +0 -0
  123. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/types.py +0 -0
  124. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/__init__.py +0 -0
  125. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/auth.py +0 -0
  126. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/client.py +0 -0
  127. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/parsers.py +0 -0
  128. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/protocol.py +0 -0
  129. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/types.py +0 -0
  130. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/write.py +0 -0
  131. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/snmp/__init__.py +0 -0
  132. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/snmp/client.py +0 -0
  133. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/snmp/oids.py +0 -0
  134. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/snmp/parse.py +0 -0
  135. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/snmp/write.py +0 -0
  136. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/py.typed +0 -0
  137. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/registry.py +0 -0
  138. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/snmp_write.py +0 -0
  139. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/sync_api.py +0 -0
  140. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/__init__.py +0 -0
  141. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/aio/__init__.py +0 -0
  142. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/aio/nsdp_udp.py +0 -0
  143. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/aio/snmp_pysnmp.py +0 -0
  144. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/cli/__init__.py +0 -0
  145. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/cli/console.py +0 -0
  146. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/cli/session.py +0 -0
  147. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/cli/ssh.py +0 -0
  148. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/cli/telnet.py +0 -0
  149. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/http/__init__.py +0 -0
  150. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/http/client.py +0 -0
  151. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/sync/__init__.py +0 -0
  152. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/sync/nsdp_udp.py +0 -0
  153. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/sync/snmp_netsnmp_cli.py +0 -0
  154. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/__init__.py +0 -0
  155. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/cli_fastpath.py +0 -0
  156. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/__init__.py +0 -0
  157. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/cli.py +0 -0
  158. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/http.py +0 -0
  159. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/mibview.py +0 -0
  160. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/nsdp.py +0 -0
  161. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/snmp.py +0 -0
  162. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/seed.py +0 -0
  163. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/server.py +0 -0
  164. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/state.py +0 -0
  165. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web.py +0 -0
  166. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_fastpath_vlan.py +0 -0
  167. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_fastpath_xui.py +0 -0
  168. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gs105pe.py +0 -0
  169. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gs110emx.py +0 -0
  170. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gs110emx_templates.py +0 -0
  171. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gs728tpp.py +0 -0
  172. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gsm7228ps.py +0 -0
  173. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gsm7252ps.py +0 -0
  174. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_m4300.py +0 -0
  175. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/capture_parity.py +0 -0
  176. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_capture.py +0 -0
  177. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_cli_integration.py +0 -0
  178. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_control_poe_port.py +0 -0
  179. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_control_vlan_ip.py +0 -0
  180. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_format.py +0 -0
  181. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_main_framework.py +0 -0
  182. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_new_commands.py +0 -0
  183. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_op_coverage.py +0 -0
  184. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_prompt_wiring.py +0 -0
  185. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_read_commands.py +0 -0
  186. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_resolve.py +0 -0
  187. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_safety.py +0 -0
  188. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_serve.py +0 -0
  189. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/conftest.py +0 -0
  190. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/equivalence.py +0 -0
  191. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/captures/gsm7228ps.json +0 -0
  192. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/captures/gsm7252ps.json +0 -0
  193. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/captures/m4300-16x.json +0 -0
  194. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/captures/m4300-24x.json +0 -0
  195. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_environment.txt +0 -0
  196. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_lldp.txt +0 -0
  197. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_mac_table.txt +0 -0
  198. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_network.txt +0 -0
  199. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_poe.txt +0 -0
  200. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_port_all.txt +0 -0
  201. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_show_version.txt +0 -0
  202. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_vlan.txt +0 -0
  203. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_vlan_brief.txt +0 -0
  204. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_vlan_port_all.txt +0 -0
  205. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_environment.txt +0 -0
  206. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_interface_ethernet_1_0_1.txt +0 -0
  207. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_lldp_remote_device_all.txt +0 -0
  208. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_mac_addr_table.txt +0 -0
  209. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_network.txt +0 -0
  210. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_poe_port_info_all.txt +0 -0
  211. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_port_all.txt +0 -0
  212. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_version.txt +0 -0
  213. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_vlan_90.txt +0 -0
  214. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_vlan_brief.txt +0 -0
  215. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_vlan_port_all.txt +0 -0
  216. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_environment.txt +0 -0
  217. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_interface_ethernet_1_0_1.txt +0 -0
  218. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_ip_management.txt +0 -0
  219. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_lldp_remote_device_all.txt +0 -0
  220. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_mac_addr_table.txt +0 -0
  221. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_poe_port_info_all.txt +0 -0
  222. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_port_all.txt +0 -0
  223. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_version.txt +0 -0
  224. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_vlan.txt +0 -0
  225. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_vlan_1.txt +0 -0
  226. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_vlan_4.txt +0 -0
  227. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_vlan_5.txt +0 -0
  228. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_vlan_port_all.txt +0 -0
  229. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_environment.txt +0 -0
  230. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_interface_ethernet_1_0_1.txt +0 -0
  231. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_ip_management.txt +0 -0
  232. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_lldp_remote_device_all.txt +0 -0
  233. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_mac_addr_table.txt +0 -0
  234. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_port_all.txt +0 -0
  235. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_version.txt +0 -0
  236. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_vlan.txt +0 -0
  237. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_vlan_5.txt +0 -0
  238. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_vlan_90.txt +0 -0
  239. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_vlan_port_all.txt +0 -0
  240. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_membership.html +0 -0
  241. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_portstats.html +0 -0
  242. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_pvid.html +0 -0
  243. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_status.html +0 -0
  244. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_switch_info.html +0 -0
  245. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_vlancfg.html +0 -0
  246. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_cf8021q.html +0 -0
  247. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_interface_stats.html +0 -0
  248. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_login.html +0 -0
  249. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_port_settings.html +0 -0
  250. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_pvid.html +0 -0
  251. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_redirect.html +0 -0
  252. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_sysinfo.html +0 -0
  253. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_vlanmembership.html +0 -0
  254. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_dashboard.html +0 -0
  255. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_login.html +0 -0
  256. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_membership.html +0 -0
  257. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_poestatus.html +0 -0
  258. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_portstats.html +0 -0
  259. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_pvid.html +0 -0
  260. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_vlancfg.html +0 -0
  261. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_device_info_and_sensors.xml +0 -0
  262. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_lldp.xml +0 -0
  263. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_macs.xml +0 -0
  264. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_mgmt_ip.xml +0 -0
  265. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_poe.xml +0 -0
  266. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_ports.xml +0 -0
  267. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_pvids_membership.xml +0 -0
  268. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_vlan_membership_per_vlan.xml +0 -0
  269. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_vlans.xml +0 -0
  270. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_basicAddressTable.html +0 -0
  271. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_ipConfiguration.html +0 -0
  272. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_lldpRemoteInventory.html +0 -0
  273. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_poeInterfaceConfiguration.html +0 -0
  274. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_portPvidConfiguration.html +0 -0
  275. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_portStatistics.html +0 -0
  276. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_portsConfiguration.html +0 -0
  277. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_sysInfo.html +0 -0
  278. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_vlanPortCfg_vlan5.html +0 -0
  279. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_vlanStatus.html +0 -0
  280. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_basicAddressTable.html +0 -0
  281. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_ipConfiguration.html +0 -0
  282. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_lldpRemoteInventory.html +0 -0
  283. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_login.html +0 -0
  284. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_poeInterfaceConfiguration.html +0 -0
  285. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_portPvidConfiguration.html +0 -0
  286. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_portStatistics.html +0 -0
  287. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_portsConfiguration.html +0 -0
  288. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_sysInfo.html +0 -0
  289. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan1.html +0 -0
  290. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan141.html +0 -0
  291. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_vlanStatus.html +0 -0
  292. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_16x_lldpRemoteInventory.html +0 -0
  293. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_16x_mgmtVlanIpv4Configuration.html +0 -0
  294. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_16x_poeInterfaceConfiguration.html +0 -0
  295. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_16x_portsConfiguration.html +0 -0
  296. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_16x_vlanportcfg_vlan4.html +0 -0
  297. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_24x_poeInterfaceConfiguration.html +0 -0
  298. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_addresstable.html +0 -0
  299. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_lldpRemoteInventory.html +0 -0
  300. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_mgmtVlanIpv4Configuration.html +0 -0
  301. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_ports.html +0 -0
  302. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_portstats.html +0 -0
  303. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_pvid.html +0 -0
  304. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_sysinfo.html +0 -0
  305. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_vlanportcfg_vlan1.html +0 -0
  306. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_vlanstatus.html +0 -0
  307. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/snmp/gsm7252ps_fans.txt +0 -0
  308. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/snmp/gsm7252ps_ifhighspeed.txt +0 -0
  309. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/snmp/gsm7252ps_ifoperstatus.txt +0 -0
  310. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/snmp/gsm7252ps_psu.txt +0 -0
  311. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/http_specs.py +0 -0
  312. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/cli/test_cli_parse.py +0 -0
  313. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/http/test_crypt.py +0 -0
  314. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/http/test_endpoints.py +0 -0
  315. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/http/test_forms.py +0 -0
  316. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/http/test_parse.py +0 -0
  317. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/nsdp/test_auth.py +0 -0
  318. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/nsdp/test_parsers.py +0 -0
  319. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/nsdp/test_protocol.py +0 -0
  320. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/nsdp/test_write_frame.py +0 -0
  321. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_client.py +0 -0
  322. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_oids.py +0 -0
  323. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_lldp_macs.py +0 -0
  324. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_mgmt_ip.py +0 -0
  325. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_poe_sensors.py +0 -0
  326. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_ports.py +0 -0
  327. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_system_info.py +0 -0
  328. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_vlans.py +0 -0
  329. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_write_encode.py +0 -0
  330. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_aio_api.py +0 -0
  331. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_capabilities.py +0 -0
  332. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_cli_read.py +0 -0
  333. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_cli_vlan_write.py +0 -0
  334. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_cli_write.py +0 -0
  335. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_config.py +0 -0
  336. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_cross_backend_equivalence.py +0 -0
  337. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_deb_version.py +0 -0
  338. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_dispatch.py +0 -0
  339. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_docs_coverage.py +0 -0
  340. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_errors.py +0 -0
  341. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_facade_equivalence.py +0 -0
  342. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_dispatch.py +0 -0
  343. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_equivalence.py +0 -0
  344. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_read.py +0 -0
  345. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_vlan_membership.py +0 -0
  346. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_write.py +0 -0
  347. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_xui_writes.py +0 -0
  348. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_import.py +0 -0
  349. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_mcp_server.py +0 -0
  350. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_models.py +0 -0
  351. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_models_snmp_read.py +0 -0
  352. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_nsdp_integration.py +0 -0
  353. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_nsdp_read.py +0 -0
  354. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_nsdp_write.py +0 -0
  355. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_public_api.py +0 -0
  356. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_quality_gates.py +0 -0
  357. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_registry.py +0 -0
  358. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_snmp_integration.py +0 -0
  359. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_snmp_read.py +0 -0
  360. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_snmp_write.py +0 -0
  361. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_sync_api.py +0 -0
  362. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_version.py +0 -0
  363. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_write_equivalence.py +0 -0
  364. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/_fastpath_fake.py +0 -0
  365. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_cli_console.py +0 -0
  366. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_cli_scp_cert.py +0 -0
  367. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_cli_telnet.py +0 -0
  368. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_http_client.py +0 -0
  369. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_nsdp_udp_sync.py +0 -0
  370. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_set_transport.py +0 -0
  371. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_snmp_netsnmp_cli.py +0 -0
  372. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_snmp_pysnmp.py +0 -0
  373. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_value_parity.py +0 -0
  374. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_cli_cross_backend.py +0 -0
  375. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_cli_gsm7228ps_parity.py +0 -0
  376. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_gsm7228ps_seed.py +0 -0
  377. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_hostname.py +0 -0
  378. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_m4300_seeds.py +0 -0
  379. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_mibview.py +0 -0
  380. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_mutable_state.py +0 -0
  381. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_nsdp_state.py +0 -0
  382. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_serve_daemon.py +0 -0
  383. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_snmp_write_face.py +0 -0
  384. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_state_seed.py +0 -0
  385. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_switchport_vlan_write.py +0 -0
  386. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_virtual_http_face.py +0 -0
  387. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_virtual_nsdp_face.py +0 -0
  388. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_virtual_snmp_face.py +0 -0
  389. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_web_projection.py +0 -0
  390. {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/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.post349
3
+ Version: 0.0.post351
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
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.0.post349'
22
- __version_tuple__ = version_tuple = (0, 0, 'post349')
21
+ __version__ = version = '0.0.post351'
22
+ __version_tuple__ = version_tuple = (0, 0, 'post351')
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -712,3 +712,14 @@ class CliWriter:
712
712
  except CliTransportError:
713
713
  # Expected: the switch tore the session down while rebooting.
714
714
  return
715
+
716
+ def set_syslog_enabled(self, enabled: bool, *, force: bool = False) -> None:
717
+ """This backend does not serve a remote-logging toggle.
718
+
719
+ Refused by name rather than returned empty: an empty answer here
720
+ would be indistinguishable from a switch that genuinely has none.
721
+ """
722
+ raise UnsupportedCapabilityError(
723
+ f"model {self.model.key!r}: this backend does not expose "
724
+ "a remote-logging toggle"
725
+ )
@@ -45,6 +45,9 @@ if TYPE_CHECKING:
45
45
  PortStats,
46
46
  PortStatus,
47
47
  Sensor,
48
+ ServiceStatus,
49
+ SwitchUser,
50
+ SyslogConfig,
48
51
  )
49
52
  from .protocols.http.endpoints import HttpModelSpec
50
53
  from .protocols.http.session import AsyncHttpSession, HttpSession
@@ -681,6 +684,39 @@ class HttpReader:
681
684
  )
682
685
  return cfg
683
686
 
687
+ def get_users(self) -> list[SwitchUser]:
688
+ """This backend does not serve local user accounts.
689
+
690
+ Refused by name rather than returned empty: an empty answer here
691
+ would be indistinguishable from a switch that genuinely has none.
692
+ """
693
+ raise UnsupportedCapabilityError(
694
+ f"model {self.model.key!r}: this backend does not expose "
695
+ "local user accounts (no such tag/page/table on this backend)"
696
+ )
697
+
698
+ def get_services(self) -> list[ServiceStatus]:
699
+ """This backend does not serve management-service state.
700
+
701
+ Refused by name rather than returned empty: an empty answer here
702
+ would be indistinguishable from a switch that genuinely has none.
703
+ """
704
+ raise UnsupportedCapabilityError(
705
+ f"model {self.model.key!r}: this backend does not expose "
706
+ "management-service state (http/https/telnet/ssh)"
707
+ )
708
+
709
+ def get_syslog(self) -> SyslogConfig:
710
+ """This backend does not serve remote-logging configuration.
711
+
712
+ Refused by name rather than returned empty: an empty answer here
713
+ would be indistinguishable from a switch that genuinely has none.
714
+ """
715
+ raise UnsupportedCapabilityError(
716
+ f"model {self.model.key!r}: this backend does not expose "
717
+ "remote-logging configuration"
718
+ )
719
+
684
720
 
685
721
  class AsyncHttpReader:
686
722
  """Asynchronous web-UI read facade (mirror of ``HttpReader``)."""
@@ -820,3 +856,46 @@ class AsyncHttpReader:
820
856
  ),
821
857
  )
822
858
  return cfg
859
+
860
+ async def get_users(self) -> list[SwitchUser]:
861
+ """This backend does not serve local user accounts.
862
+
863
+ Refused by name rather than returned empty: an empty answer here
864
+ would be indistinguishable from a switch that genuinely has none.
865
+ """
866
+ raise UnsupportedCapabilityError(
867
+ f"model {self.model.key!r}: this backend does not expose "
868
+ "local user accounts (no such tag/page/table on this backend)"
869
+ )
870
+
871
+ async def get_services(self) -> list[ServiceStatus]:
872
+ """This backend does not serve management-service state.
873
+
874
+ Refused by name rather than returned empty: an empty answer here
875
+ would be indistinguishable from a switch that genuinely has none.
876
+ """
877
+ raise UnsupportedCapabilityError(
878
+ f"model {self.model.key!r}: this backend does not expose "
879
+ "management-service state (http/https/telnet/ssh)"
880
+ )
881
+
882
+ async def get_syslog(self) -> SyslogConfig:
883
+ """This backend does not serve remote-logging configuration.
884
+
885
+ Refused by name rather than returned empty: an empty answer here
886
+ would be indistinguishable from a switch that genuinely has none.
887
+ """
888
+ raise UnsupportedCapabilityError(
889
+ f"model {self.model.key!r}: this backend does not expose "
890
+ "remote-logging configuration"
891
+ )
892
+
893
+ async def get_hostname(self) -> str:
894
+ """This backend does not serve a host name field.
895
+
896
+ Refused by name rather than returned empty: an empty answer here
897
+ would be indistinguishable from a switch that genuinely has none.
898
+ """
899
+ raise UnsupportedCapabilityError(
900
+ f"model {self.model.key!r}: this backend does not expose a host name field"
901
+ )
@@ -742,9 +742,7 @@ class HttpWriter:
742
742
  if page.vlan_id == vlan:
743
743
  return page
744
744
  body = forms.fastpath_membership_form(page, vlan=vlan)
745
- shown = parse.parse_fastpath_membership(
746
- self.session.post_form(post_path, body)
747
- )
745
+ shown = parse.parse_fastpath_membership(self.session.post_form(post_path, body))
748
746
  _require_fastpath_membership_for(shown, vlan, post_path)
749
747
  return shown
750
748
 
@@ -985,6 +983,27 @@ class HttpWriter:
985
983
  return r.admin_enabled
986
984
  return False
987
985
 
986
+ def set_hostname(self, name: str, *, force: bool = False) -> None:
987
+ """This backend does not serve a host-name write.
988
+
989
+ Refused by name rather than returned empty: an empty answer here
990
+ would be indistinguishable from a switch that genuinely has none.
991
+ """
992
+ raise UnsupportedCapabilityError(
993
+ f"model {self.model.key!r}: this backend does not expose a host-name write"
994
+ )
995
+
996
+ def set_syslog_enabled(self, enabled: bool, *, force: bool = False) -> None:
997
+ """This backend does not serve a remote-logging toggle.
998
+
999
+ Refused by name rather than returned empty: an empty answer here
1000
+ would be indistinguishable from a switch that genuinely has none.
1001
+ """
1002
+ raise UnsupportedCapabilityError(
1003
+ f"model {self.model.key!r}: this backend does not expose "
1004
+ "a remote-logging toggle"
1005
+ )
1006
+
988
1007
 
989
1008
  class AsyncHttpWriter:
990
1009
  def __init__(
@@ -1302,9 +1321,7 @@ class AsyncHttpWriter:
1302
1321
  ),
1303
1322
  )
1304
1323
  _raise_on_fastpath_err_flag(applied, f"management IP -> {address}/{netmask}")
1305
- after = parse.parse_xui_form_page(
1306
- await self.session.get_page(path), page=path
1307
- )
1324
+ after = parse.parse_xui_form_page(await self.session.get_page(path), page=path)
1308
1325
  got = (
1309
1326
  after.fields.get(fields.address),
1310
1327
  after.fields.get(fields.netmask),
@@ -1346,3 +1363,24 @@ class AsyncHttpWriter:
1346
1363
  _check_multipart_cert_response(
1347
1364
  await self.session.post_multipart(path, fields, payload)
1348
1365
  )
1366
+
1367
+ async def set_hostname(self, name: str, *, force: bool = False) -> None:
1368
+ """This backend does not serve a host-name write.
1369
+
1370
+ Refused by name rather than returned empty: an empty answer here
1371
+ would be indistinguishable from a switch that genuinely has none.
1372
+ """
1373
+ raise UnsupportedCapabilityError(
1374
+ f"model {self.model.key!r}: this backend does not expose a host-name write"
1375
+ )
1376
+
1377
+ async def set_syslog_enabled(self, enabled: bool, *, force: bool = False) -> None:
1378
+ """This backend does not serve a remote-logging toggle.
1379
+
1380
+ Refused by name rather than returned empty: an empty answer here
1381
+ would be indistinguishable from a switch that genuinely has none.
1382
+ """
1383
+ raise UnsupportedCapabilityError(
1384
+ f"model {self.model.key!r}: this backend does not expose "
1385
+ "a remote-logging toggle"
1386
+ )
@@ -38,6 +38,17 @@ class PortStatus:
38
38
  # older tests) keep constructing without it; a backend that cannot read
39
39
  # ifAlias (NSDP, HTTP) leaves it honestly None rather than fabricating "".
40
40
  description: str | None = None
41
+ #: Whether the link negotiated FULL duplex. ``None`` when the backend cannot
42
+ #: tell -- a down port has no negotiated duplex, and not every backend
43
+ #: reports it at all. Measured 2026-08-02: the M4300's EtherLike-MIB dot3
44
+ #: table exposes only error counters, NOT dot3StatsDuplexStatus (column 19
45
+ #: is absent), so SNMP cannot answer this and leaves it None. The FASTPATH
46
+ #: CLI does: `show port all` reports "1000 Full" in its Physical Status
47
+ #: column, carrying speed and duplex together.
48
+ full_duplex: bool | None = None
49
+ #: Whether IEEE 802.3x flow control is enabled on the port ("Flow Mode" in
50
+ #: `show port all`). ``None`` where the backend does not report it.
51
+ flow_control: bool | None = None
41
52
 
42
53
 
43
54
  @dataclass(frozen=True)
@@ -21,7 +21,15 @@ from .protocols.nsdp.types import LinkSpeed
21
21
  from .registry import Backend
22
22
 
23
23
  if TYPE_CHECKING:
24
- from .models import LLDPNeighbor, MacEntry, PoEStatus, Sensor
24
+ from .models import (
25
+ LLDPNeighbor,
26
+ MacEntry,
27
+ PoEStatus,
28
+ Sensor,
29
+ ServiceStatus,
30
+ SwitchUser,
31
+ SyslogConfig,
32
+ )
25
33
  from .protocols.nsdp.client import AsyncNsdpClient, NsdpClient
26
34
  from .protocols.nsdp.types import NsdpDevice
27
35
  from .registry import SwitchModel
@@ -255,6 +263,39 @@ class NsdpReader:
255
263
  def get_poe(self) -> list[PoEStatus]:
256
264
  raise UnsupportedCapabilityError(_NO_POE)
257
265
 
266
+ def get_users(self) -> list[SwitchUser]:
267
+ """This backend does not serve local user accounts.
268
+
269
+ Refused by name rather than returned empty: an empty answer here
270
+ would be indistinguishable from a switch that genuinely has none.
271
+ """
272
+ raise UnsupportedCapabilityError(
273
+ f"model {self.model.key!r}: this backend does not expose "
274
+ "local user accounts (no such tag/page/table on this backend)"
275
+ )
276
+
277
+ def get_services(self) -> list[ServiceStatus]:
278
+ """This backend does not serve management-service state.
279
+
280
+ Refused by name rather than returned empty: an empty answer here
281
+ would be indistinguishable from a switch that genuinely has none.
282
+ """
283
+ raise UnsupportedCapabilityError(
284
+ f"model {self.model.key!r}: this backend does not expose "
285
+ "management-service state (http/https/telnet/ssh)"
286
+ )
287
+
288
+ def get_syslog(self) -> SyslogConfig:
289
+ """This backend does not serve remote-logging configuration.
290
+
291
+ Refused by name rather than returned empty: an empty answer here
292
+ would be indistinguishable from a switch that genuinely has none.
293
+ """
294
+ raise UnsupportedCapabilityError(
295
+ f"model {self.model.key!r}: this backend does not expose "
296
+ "remote-logging configuration"
297
+ )
298
+
258
299
 
259
300
  class AsyncNsdpReader:
260
301
  """Asynchronous NSDP read facade (mirror of NsdpReader)."""
@@ -308,3 +349,36 @@ class AsyncNsdpReader:
308
349
 
309
350
  async def get_poe(self) -> list[PoEStatus]:
310
351
  raise UnsupportedCapabilityError(_NO_POE)
352
+
353
+ async def get_users(self) -> list[SwitchUser]:
354
+ """This backend does not serve local user accounts.
355
+
356
+ Refused by name rather than returned empty: an empty answer here
357
+ would be indistinguishable from a switch that genuinely has none.
358
+ """
359
+ raise UnsupportedCapabilityError(
360
+ f"model {self.model.key!r}: this backend does not expose "
361
+ "local user accounts (no such tag/page/table on this backend)"
362
+ )
363
+
364
+ async def get_services(self) -> list[ServiceStatus]:
365
+ """This backend does not serve management-service state.
366
+
367
+ Refused by name rather than returned empty: an empty answer here
368
+ would be indistinguishable from a switch that genuinely has none.
369
+ """
370
+ raise UnsupportedCapabilityError(
371
+ f"model {self.model.key!r}: this backend does not expose "
372
+ "management-service state (http/https/telnet/ssh)"
373
+ )
374
+
375
+ async def get_syslog(self) -> SyslogConfig:
376
+ """This backend does not serve remote-logging configuration.
377
+
378
+ Refused by name rather than returned empty: an empty answer here
379
+ would be indistinguishable from a switch that genuinely has none.
380
+ """
381
+ raise UnsupportedCapabilityError(
382
+ f"model {self.model.key!r}: this backend does not expose "
383
+ "remote-logging configuration"
384
+ )
@@ -305,6 +305,17 @@ class NsdpWriter:
305
305
  after=after,
306
306
  )
307
307
 
308
+ def set_syslog_enabled(self, enabled: bool, *, force: bool = False) -> None:
309
+ """This backend does not serve a remote-logging toggle.
310
+
311
+ Refused by name rather than returned empty: an empty answer here
312
+ would be indistinguishable from a switch that genuinely has none.
313
+ """
314
+ raise UnsupportedCapabilityError(
315
+ f"model {self.model.key!r}: this backend does not expose "
316
+ "a remote-logging toggle"
317
+ )
318
+
308
319
 
309
320
  class AsyncNsdpWriter:
310
321
  """Asynchronous NSDP write facade (mirror of NsdpWriter)."""
@@ -465,3 +476,24 @@ class AsyncNsdpWriter:
465
476
  before=before,
466
477
  after=after,
467
478
  )
479
+
480
+ async def set_hostname(self, name: str, *, force: bool = False) -> None:
481
+ """This backend does not serve a host-name write.
482
+
483
+ Refused by name rather than returned empty: an empty answer here
484
+ would be indistinguishable from a switch that genuinely has none.
485
+ """
486
+ raise UnsupportedCapabilityError(
487
+ f"model {self.model.key!r}: this backend does not expose a host-name write"
488
+ )
489
+
490
+ async def set_syslog_enabled(self, enabled: bool, *, force: bool = False) -> None:
491
+ """This backend does not serve a remote-logging toggle.
492
+
493
+ Refused by name rather than returned empty: an empty answer here
494
+ would be indistinguishable from a switch that genuinely has none.
495
+ """
496
+ raise UnsupportedCapabilityError(
497
+ f"model {self.model.key!r}: this backend does not expose "
498
+ "a remote-logging toggle"
499
+ )
@@ -244,6 +244,11 @@ def parse_version(text: str, models: Mapping[str, SwitchModel]) -> DetectedModel
244
244
  # Link Status | Link Trap | LACP Mode | Flow Mode
245
245
  _PORT_INTF, _PORT_TYPE, _PORT_ADMIN = 0, 1, 2
246
246
  _PORT_PHYS_MODE, _PORT_PHYS_STATUS, _PORT_LINK = 3, 4, 5
247
+ # Flow Mode is the LAST column of `show port all` (Intf, Type, Admin Mode,
248
+ # Physical Mode, Physical Status, Link Status, Link Trap, LACP Mode, Flow
249
+ # Mode). Indexed from the end so a firmware that omits an intermediate
250
+ # column cannot silently shift it.
251
+ _PORT_FLOW = -1
247
252
 
248
253
  _SPEED_RE = re.compile(r"(\d+)\s*([GgMm]?)")
249
254
 
@@ -261,13 +266,30 @@ def _speed_mbps(phys_status: str) -> int | None:
261
266
  return value * 1000 if m.group(2).upper() == "G" else value
262
267
 
263
268
 
269
+ def _duplex(phys_status: str) -> bool | None:
270
+ """FULL/HALF from the Physical Status cell, e.g. "1000 Full" -> True.
271
+
272
+ Blank on a down port, which has no negotiated duplex -- honestly None rather
273
+ than a fabricated False.
274
+ """
275
+ text = phys_status.strip().lower()
276
+ if "full" in text:
277
+ return True
278
+ if "half" in text:
279
+ return False
280
+ return None
281
+
282
+
264
283
  def parse_port_status(text: str) -> list[PortStatus]:
265
284
  """``show port all`` -> per physical-port ``PortStatus``.
266
285
 
267
286
  ``admin_enabled`` = Admin Mode == "Enable"; ``link_up`` = Link Status ==
268
- "Up"; ``speed_mbps`` from Physical Status (None when blank/down). ``lag N``
269
- aggregation rows are skipped (not physical ports). ``description`` is
270
- honestly ``None``: this command carries no ifAlias column.
287
+ "Up"; ``speed_mbps`` and ``full_duplex`` both from Physical Status, which
288
+ carries them together ("1000 Full"); ``flow_control`` from the Flow Mode
289
+ column. All three are ``None`` on a down port, which has negotiated nothing.
290
+ ``lag N`` aggregation rows are skipped (not physical ports).
291
+ ``description`` is honestly ``None``: this command carries no ifAlias
292
+ column.
271
293
  """
272
294
  out: list[PortStatus] = []
273
295
  for cells in iter_table_rows(text):
@@ -288,6 +310,16 @@ def parse_port_status(text: str) -> list[PortStatus]:
288
310
  else None
289
311
  ),
290
312
  description=None,
313
+ full_duplex=(
314
+ _duplex(cells[_PORT_PHYS_STATUS])
315
+ if cells[_PORT_LINK].strip().lower() == "up"
316
+ else None
317
+ ),
318
+ flow_control=(
319
+ cells[_PORT_FLOW].strip().lower() == "enable"
320
+ if len(cells) > _PORT_LINK + 1
321
+ else None
322
+ ),
291
323
  )
292
324
  )
293
325
  return out
@@ -23,6 +23,8 @@ if TYPE_CHECKING:
23
23
  PortStats,
24
24
  PortStatus,
25
25
  Sensor,
26
+ ServiceStatus,
27
+ SwitchUser,
26
28
  SyslogConfig,
27
29
  VLANInfo,
28
30
  )
@@ -243,6 +245,28 @@ class SnmpReader:
243
245
  """
244
246
  return read_system_info(self.client)
245
247
 
248
+ def get_users(self) -> list[SwitchUser]:
249
+ """This backend does not serve local user accounts.
250
+
251
+ Refused by name rather than returned empty: an empty answer here
252
+ would be indistinguishable from a switch that genuinely has none.
253
+ """
254
+ raise UnsupportedCapabilityError(
255
+ f"model {self.model.key!r}: this backend does not expose "
256
+ "local user accounts (no such tag/page/table on this backend)"
257
+ )
258
+
259
+ def get_services(self) -> list[ServiceStatus]:
260
+ """This backend does not serve management-service state.
261
+
262
+ Refused by name rather than returned empty: an empty answer here
263
+ would be indistinguishable from a switch that genuinely has none.
264
+ """
265
+ raise UnsupportedCapabilityError(
266
+ f"model {self.model.key!r}: this backend does not expose "
267
+ "management-service state (http/https/telnet/ssh)"
268
+ )
269
+
246
270
 
247
271
  class AsyncSnmpReader:
248
272
  def __init__(self, client: AsyncSnmpClient, model: SwitchModel) -> None:
@@ -359,6 +383,30 @@ class AsyncSnmpReader:
359
383
  await w(oids.IP_ADDRESS_IFINDEX), # RFC-4293 fallback (M4300)
360
384
  )
361
385
 
386
+ async def get_syslog(self) -> SyslogConfig:
387
+ """Async twin of ``SnmpReader.get_syslog`` -- see there."""
388
+ if not oids.has_vendor_oids(self.model):
389
+ raise UnsupportedCapabilityError(
390
+ f"model {self.model.key!r} registers no Netgear vendor OID "
391
+ "subtree, and the logging columns are vendor-only; an empty "
392
+ "result here would be indistinguishable from a switch with no "
393
+ "syslog collectors configured"
394
+ )
395
+ vo = oids.vendor_oids(self.model)
396
+ w = self.client.walk
397
+ return parse.parse_syslog(
398
+ await self.client.get([vo.syslog_admin_mode]),
399
+ await self.client.get([vo.syslog_local_port]),
400
+ await w(vo.syslog_host_addr),
401
+ await w(vo.syslog_host_port),
402
+ await w(vo.syslog_host_severity),
403
+ await w(vo.syslog_host_status),
404
+ addr_base=vo.syslog_host_addr,
405
+ port_base=vo.syslog_host_port,
406
+ severity_base=vo.syslog_host_severity,
407
+ status_base=vo.syslog_host_status,
408
+ )
409
+
362
410
  async def get_hostname(self) -> str:
363
411
  """Async twin of ``SnmpReader.get_hostname`` -- see there."""
364
412
  return parse.parse_hostname(await self.client.get([oids.SYS_NAME]))
@@ -366,3 +414,25 @@ class AsyncSnmpReader:
366
414
  async def get_system_info(self) -> DetectedModel:
367
415
  """Async twin of ``SnmpReader.get_system_info`` -- see there."""
368
416
  return await async_read_system_info(self.client)
417
+
418
+ async def get_users(self) -> list[SwitchUser]:
419
+ """This backend does not serve local user accounts.
420
+
421
+ Refused by name rather than returned empty: an empty answer here
422
+ would be indistinguishable from a switch that genuinely has none.
423
+ """
424
+ raise UnsupportedCapabilityError(
425
+ f"model {self.model.key!r}: this backend does not expose "
426
+ "local user accounts (no such tag/page/table on this backend)"
427
+ )
428
+
429
+ async def get_services(self) -> list[ServiceStatus]:
430
+ """This backend does not serve management-service state.
431
+
432
+ Refused by name rather than returned empty: an empty answer here
433
+ would be indistinguishable from a switch that genuinely has none.
434
+ """
435
+ raise UnsupportedCapabilityError(
436
+ f"model {self.model.key!r}: this backend does not expose "
437
+ "management-service state (http/https/telnet/ssh)"
438
+ )