python-netgear-switch-library 0.0.post323__tar.gz → 0.0.post325__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.
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/PKG-INFO +15 -1
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/README.md +13 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/_ext/support_tables.py +258 -4
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/conf.py +11 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/fake/testing.rst +55 -18
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/guide/concepts.rst +65 -14
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/guide/configuration.rst +49 -12
- python_netgear_switch_library-0.0.post325/docs/guide/quickstart.rst +311 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/guide/reading.rst +128 -39
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/guide/writing.rst +58 -16
- python_netgear_switch_library-0.0.post325/docs/index.rst +170 -0
- python_netgear_switch_library-0.0.post325/docs/models/gs105pe.rst +43 -0
- python_netgear_switch_library-0.0.post325/docs/models/gs110emx.rst +52 -0
- python_netgear_switch_library-0.0.post325/docs/models/gs305ep.rst +63 -0
- python_netgear_switch_library-0.0.post325/docs/models/gs728tpp.rst +52 -0
- python_netgear_switch_library-0.0.post325/docs/models/gsm7228ps.rst +66 -0
- python_netgear_switch_library-0.0.post325/docs/models/gsm7252ps.rst +54 -0
- python_netgear_switch_library-0.0.post325/docs/models/index.rst +76 -0
- python_netgear_switch_library-0.0.post325/docs/models/m4300-16x.rst +60 -0
- python_netgear_switch_library-0.0.post325/docs/models/m4300-24x.rst +55 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/models/support.rst +8 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/protocols/cli.rst +76 -16
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/protocols/http.rst +14 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/protocols/nsdp.rst +10 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/protocols/snmp.rst +10 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/pyproject.toml +1 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/__init__.py +10 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/_version.py +2 -2
- python_netgear_switch_library-0.0.post323/docs/guide/quickstart.rst +0 -173
- python_netgear_switch_library-0.0.post323/docs/index.rst +0 -112
- python_netgear_switch_library-0.0.post323/docs/models/index.rst +0 -175
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/.github/workflows/ci.yml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/.github/workflows/deb.yml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/.github/workflows/publish-pypi.yml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/.gitignore +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/.readthedocs.yaml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/CLAUDE.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/LICENSE +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/RELEASING.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/debian/changelog +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/debian/control +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/debian/copyright +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/debian/rules +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/debian/source/format +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/Makefile +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/_ext/filelinks.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/_static/ngsw.css +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/api/cli.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/api/core.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/api/facades.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/api/index.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/api/mcp.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/api/operations.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/api/protocols.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/api/transport.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/api/virtual.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/cli.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/development.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/fake/index.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/fake/internals.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/fake/serving.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/guide/installation.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/guide/principles.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/mcp.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/protocols/index.rst +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/superpowers/plans/2026-07-15-foundation.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/superpowers/plans/2026-07-17-slice-02-snmp-read-core.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/superpowers/plans/2026-07-17-slice-03-read-apis.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/superpowers/plans/2026-07-18-slice-04-snmp-write.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/superpowers/plans/2026-07-18-slice-05-nsdp.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/superpowers/plans/2026-07-18-slice-06-http.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/superpowers/plans/2026-07-18-slice-07-cli.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/superpowers/plans/2026-07-18-slice-08-packaging-ci.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/superpowers/plans/2026-07-23-gsm7252ps-http-xe-dialect.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/superpowers/specs/2026-07-15-netgear-control-library-design.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/superpowers/specs/2026-07-23-gsm7252ps-http-xe-dialect-design.md +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/packaging/apt-index.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/packaging/ci-build.sh +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/packaging/deb-version.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/_dispatch.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/aio_api.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/capabilities.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/cli/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/cli/capture.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/cli/context.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/cli/format.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/cli/main.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/cli/resolve.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/cli/safety.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/cli_read.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/cli_write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/config.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/errors.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/http_read.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/http_write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/mcp/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/mcp/server.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/models.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/nsdp_read.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/nsdp_write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/cli/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/cli/commands.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/cli/parse.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/http/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/http/crypt.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/http/endpoints.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/http/forms.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/http/parse.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/http/session.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/http/types.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/nsdp/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/nsdp/auth.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/nsdp/client.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/nsdp/parsers.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/nsdp/protocol.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/nsdp/types.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/nsdp/write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/snmp/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/snmp/client.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/snmp/oids.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/snmp/parse.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/protocols/snmp/write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/py.typed +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/registry.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/snmp_read.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/snmp_write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/sync_api.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/aio/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/aio/nsdp_udp.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/aio/snmp_pysnmp.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/cli/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/cli/console.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/cli/session.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/cli/ssh.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/cli/telnet.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/http/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/http/client.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/sync/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/sync/nsdp_udp.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/transport/sync/snmp_netsnmp_cli.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/cli_fastpath.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/faces/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/faces/cli.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/faces/http.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/faces/mibview.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/faces/nsdp.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/faces/snmp.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/seed.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/server.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/state.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/web.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/web_fastpath_vlan.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/web_fastpath_xui.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/web_gs105pe.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/web_gs110emx.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/web_gs110emx_templates.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/web_gs728tpp.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/web_gsm7228ps.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/web_gsm7252ps.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/src/netgear_switch/virtual/web_m4300.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/capture_parity.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_capture.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_cli_integration.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_control_poe_port.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_control_vlan_ip.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_format.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_main_framework.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_new_commands.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_op_coverage.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_prompt_wiring.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_read_commands.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_resolve.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_safety.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/cli/test_serve.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/conftest.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/captures/gsm7228ps.json +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/captures/gsm7252ps.json +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/captures/m4300-16x.json +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/captures/m4300-24x.json +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7228ps_environment.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7228ps_lldp.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7228ps_mac_table.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7228ps_network.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7228ps_poe.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7228ps_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7228ps_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7228ps_vlan.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7228ps_vlan_brief.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7228ps_vlan_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7252ps_show_environment.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7252ps_show_interface_ethernet_1_0_1.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7252ps_show_lldp_remote_device_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7252ps_show_mac_addr_table.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7252ps_show_network.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7252ps_show_poe_port_info_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7252ps_show_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7252ps_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7252ps_show_vlan_90.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7252ps_show_vlan_brief.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/gsm7252ps_show_vlan_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_environment.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_interface_ethernet_1_0_1.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_ip_management.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_lldp_remote_device_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_mac_addr_table.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_poe_port_info_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_vlan.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_vlan_1.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_vlan_4.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_vlan_5.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_16x_show_vlan_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_24x_show_environment.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_24x_show_interface_ethernet_1_0_1.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_24x_show_ip_management.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_24x_show_lldp_remote_device_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_24x_show_mac_addr_table.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_24x_show_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_24x_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_24x_show_vlan.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_24x_show_vlan_5.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_24x_show_vlan_90.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/cli/m4300_24x_show_vlan_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs105pe_membership.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs105pe_portstats.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs105pe_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs105pe_status.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs105pe_switch_info.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs105pe_vlancfg.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs110emx_cf8021q.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs110emx_interface_stats.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs110emx_login.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs110emx_port_settings.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs110emx_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs110emx_redirect.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs110emx_sysinfo.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs110emx_vlanmembership.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs305ep_dashboard.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs305ep_login.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs305ep_membership.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs305ep_poestatus.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs305ep_portstats.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs305ep_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs305ep_vlancfg.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs728tpp_device_info_and_sensors.xml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs728tpp_lldp.xml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs728tpp_macs.xml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs728tpp_mgmt_ip.xml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs728tpp_poe.xml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs728tpp_ports.xml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs728tpp_pvids_membership.xml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs728tpp_vlan_membership_per_vlan.xml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gs728tpp_vlans.xml +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7228ps_basicAddressTable.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7228ps_ipConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7228ps_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7228ps_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7228ps_portPvidConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7228ps_portStatistics.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7228ps_portsConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7228ps_sysInfo.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7228ps_vlanPortCfg_vlan5.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7228ps_vlanStatus.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_basicAddressTable.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_ipConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_login.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_portPvidConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_portStatistics.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_portsConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_sysInfo.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan1.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan141.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/gsm7252ps_vlanStatus.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_16x_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_16x_mgmtVlanIpv4Configuration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_16x_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_16x_portsConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_16x_vlanportcfg_vlan4.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_24x_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_addresstable.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_mgmtVlanIpv4Configuration.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_ports.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_portstats.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_sysinfo.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_vlanportcfg_vlan1.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/http/m4300_vlanstatus.html +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/snmp/gsm7252ps_fans.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/snmp/gsm7252ps_ifhighspeed.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/snmp/gsm7252ps_ifoperstatus.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/fixtures/snmp/gsm7252ps_psu.txt +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/http_specs.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/cli/test_cli_parse.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/http/test_crypt.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/http/test_endpoints.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/http/test_forms.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/http/test_parse.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/nsdp/test_auth.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/nsdp/test_parsers.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/nsdp/test_protocol.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/nsdp/test_write_frame.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/snmp/test_client.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/snmp/test_oids.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/snmp/test_parse_lldp_macs.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/snmp/test_parse_mgmt_ip.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/snmp/test_parse_poe_sensors.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/snmp/test_parse_ports.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/snmp/test_parse_system_info.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/snmp/test_parse_vlans.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/protocols/snmp/test_write_encode.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_aio_api.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_capabilities.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_cli_read.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_cli_vlan_write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_cli_write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_config.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_cross_backend_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_deb_version.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_dispatch.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_errors.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_facade_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_http_dispatch.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_http_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_http_read.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_http_vlan_membership.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_http_write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_http_xui_writes.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_import.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_mcp_server.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_models.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_models_snmp_read.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_nsdp_integration.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_nsdp_read.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_nsdp_write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_public_api.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_quality_gates.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_registry.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_snmp_integration.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_snmp_read.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_snmp_write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_sync_api.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_version.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/test_write_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/transport/_fastpath_fake.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/transport/test_cli_console.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/transport/test_cli_scp_cert.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/transport/test_cli_telnet.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/transport/test_http_client.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/transport/test_nsdp_udp_sync.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/transport/test_set_transport.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/transport/test_snmp_netsnmp_cli.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/transport/test_snmp_pysnmp.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/transport/test_value_parity.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_cli_cross_backend.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_cli_gsm7228ps_parity.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_gsm7228ps_seed.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_m4300_seeds.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_mibview.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_mutable_state.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_nsdp_state.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_serve_daemon.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_snmp_write_face.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_state_seed.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_switchport_vlan_write.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_virtual_http_face.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_virtual_nsdp_face.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_virtual_snmp_face.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/tests/virtual/test_web_projection.py +0 -0
- {python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/uv.lock +0 -0
{python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-netgear-switch-library
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.post325
|
|
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,6 +18,7 @@ Requires-Dist: pyserial>=3.5; extra == 'docs'
|
|
|
18
18
|
Requires-Dist: pysnmp>=7.0; extra == 'docs'
|
|
19
19
|
Requires-Dist: sphinx-argparse>=0.5; extra == 'docs'
|
|
20
20
|
Requires-Dist: sphinx-copybutton>=0.5.2; extra == 'docs'
|
|
21
|
+
Requires-Dist: sphinx-design>=0.6; extra == 'docs'
|
|
21
22
|
Requires-Dist: sphinx>=8.1; extra == 'docs'
|
|
22
23
|
Provides-Extra: http
|
|
23
24
|
Requires-Dist: httpx>=0.27; extra == 'http'
|
|
@@ -37,6 +38,19 @@ Description-Content-Type: text/markdown
|
|
|
37
38
|
Query and control all your Netgear switches — SNMP (managed), NSDP and HTTP
|
|
38
39
|
web-UI (Plus) — behind one model-driven Python API and the `ngsw` CLI.
|
|
39
40
|
|
|
41
|
+
> [!WARNING]
|
|
42
|
+
> **This library and its documentation were written by an AI.** Every line of
|
|
43
|
+
> code, every test and every documentation page was generated by a language
|
|
44
|
+
> model, with a human directing and reviewing the work.
|
|
45
|
+
>
|
|
46
|
+
> The device behaviour in it is *measured* — protocol details and firmware
|
|
47
|
+
> quirks come from captured traffic and live runs against the real switches,
|
|
48
|
+
> recorded with the host and firmware they were seen on — and the support tables
|
|
49
|
+
> are generated from the code rather than written by hand. But an AI is
|
|
50
|
+
> perfectly capable of confident, fluent error, and nothing here has had
|
|
51
|
+
> independent human review at scale. Verify anything that matters to you against
|
|
52
|
+
> the source or your own hardware, and please report what you find.
|
|
53
|
+
|
|
40
54
|
**Documentation: <https://python-netgear-switch-library.readthedocs.io/>** — API
|
|
41
55
|
reference, the complete `ngsw` CLI reference, the virtual-switch guide (how to
|
|
42
56
|
test your own tools against a mock), and generated
|
{python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/README.md
RENAMED
|
@@ -3,6 +3,19 @@
|
|
|
3
3
|
Query and control all your Netgear switches — SNMP (managed), NSDP and HTTP
|
|
4
4
|
web-UI (Plus) — behind one model-driven Python API and the `ngsw` CLI.
|
|
5
5
|
|
|
6
|
+
> [!WARNING]
|
|
7
|
+
> **This library and its documentation were written by an AI.** Every line of
|
|
8
|
+
> code, every test and every documentation page was generated by a language
|
|
9
|
+
> model, with a human directing and reviewing the work.
|
|
10
|
+
>
|
|
11
|
+
> The device behaviour in it is *measured* — protocol details and firmware
|
|
12
|
+
> quirks come from captured traffic and live runs against the real switches,
|
|
13
|
+
> recorded with the host and firmware they were seen on — and the support tables
|
|
14
|
+
> are generated from the code rather than written by hand. But an AI is
|
|
15
|
+
> perfectly capable of confident, fluent error, and nothing here has had
|
|
16
|
+
> independent human review at scale. Verify anything that matters to you against
|
|
17
|
+
> the source or your own hardware, and please report what you find.
|
|
18
|
+
|
|
6
19
|
**Documentation: <https://python-netgear-switch-library.readthedocs.io/>** — API
|
|
7
20
|
reference, the complete `ngsw` CLI reference, the virtual-switch guide (how to
|
|
8
21
|
test your own tools against a mock), and generated
|
|
@@ -29,9 +29,11 @@ Directives
|
|
|
29
29
|
|
|
30
30
|
from __future__ import annotations
|
|
31
31
|
|
|
32
|
+
from pathlib import Path
|
|
32
33
|
from typing import TYPE_CHECKING, Any, ClassVar
|
|
33
34
|
|
|
34
35
|
from docutils.parsers.rst import directives
|
|
36
|
+
from sphinx.util import logging
|
|
35
37
|
from sphinx.util.docutils import SphinxDirective
|
|
36
38
|
|
|
37
39
|
from netgear_switch.capabilities import (
|
|
@@ -49,6 +51,8 @@ if TYPE_CHECKING:
|
|
|
49
51
|
from docutils import nodes
|
|
50
52
|
from sphinx.application import Sphinx
|
|
51
53
|
|
|
54
|
+
logger = logging.getLogger(__name__)
|
|
55
|
+
|
|
52
56
|
#: Compact per-backend labels used inside grid cells. The CLI backends share a
|
|
53
57
|
#: label because they are one command surface reached over three transports
|
|
54
58
|
#: (see ``src/netgear_switch/registry.py``'s ``Backend``).
|
|
@@ -65,6 +69,24 @@ _YES = "✓" # check mark
|
|
|
65
69
|
_NO = "—" # em dash
|
|
66
70
|
|
|
67
71
|
|
|
72
|
+
def matrix_models() -> tuple[str, ...]:
|
|
73
|
+
"""The models the generated tables cover.
|
|
74
|
+
|
|
75
|
+
A model registered from a specification sheet with **no device access**
|
|
76
|
+
(``SwitchModel.verified is False``) is deliberately excluded. Listing one in
|
|
77
|
+
a support matrix would assert per-model, per-backend behaviour that nobody
|
|
78
|
+
has ever observed on that hardware -- the exact difference between a
|
|
79
|
+
measurement and an inference this project refuses to blur. They are named in
|
|
80
|
+
prose instead, so their existence is not hidden either.
|
|
81
|
+
"""
|
|
82
|
+
return tuple(key for key, model in MODELS.items() if model.verified)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def unverified_models() -> tuple[str, ...]:
|
|
86
|
+
"""Registered models with no capture behind them, excluded from the tables."""
|
|
87
|
+
return tuple(key for key, model in MODELS.items() if not model.verified)
|
|
88
|
+
|
|
89
|
+
|
|
68
90
|
def _rst_escape(text: str) -> str:
|
|
69
91
|
"""Neutralise inline reST markup in generated cell text."""
|
|
70
92
|
for char in ("\\", "*", "`", "|", "_"):
|
|
@@ -114,7 +136,8 @@ class ModelTable(_GeneratedTable):
|
|
|
114
136
|
for alias, canonical in MODEL_ALIASES.items():
|
|
115
137
|
aliases.setdefault(canonical, []).append(alias)
|
|
116
138
|
rows = []
|
|
117
|
-
for key
|
|
139
|
+
for key in matrix_models():
|
|
140
|
+
model = MODELS[key]
|
|
118
141
|
also = aliases.get(key)
|
|
119
142
|
name = f"``{key}``"
|
|
120
143
|
if also:
|
|
@@ -159,7 +182,8 @@ class ProtocolTable(_GeneratedTable):
|
|
|
159
182
|
|
|
160
183
|
def body(self) -> str:
|
|
161
184
|
rows = []
|
|
162
|
-
for key
|
|
185
|
+
for key in matrix_models():
|
|
186
|
+
model = MODELS[key]
|
|
163
187
|
cells = [_YES if b in model.backends else _NO for b in self._COLUMNS]
|
|
164
188
|
rows.append([f"``{key}``", *cells])
|
|
165
189
|
return _list_table(
|
|
@@ -185,7 +209,7 @@ class OperationTable(_GeneratedTable):
|
|
|
185
209
|
raise self.error(f"ngsw-operation-table: unknown kind {kind!r}")
|
|
186
210
|
|
|
187
211
|
def body(self) -> str:
|
|
188
|
-
keys = list(
|
|
212
|
+
keys = list(matrix_models())
|
|
189
213
|
rows = []
|
|
190
214
|
for op in self._operations():
|
|
191
215
|
cells = []
|
|
@@ -251,7 +275,7 @@ class SupportGaps(_GeneratedTable):
|
|
|
251
275
|
|
|
252
276
|
def body(self) -> str:
|
|
253
277
|
rows = []
|
|
254
|
-
for key in
|
|
278
|
+
for key in matrix_models():
|
|
255
279
|
backends = backends_for(key)
|
|
256
280
|
if len(backends) < 2:
|
|
257
281
|
continue
|
|
@@ -282,10 +306,240 @@ class SupportGaps(_GeneratedTable):
|
|
|
282
306
|
)
|
|
283
307
|
|
|
284
308
|
|
|
309
|
+
_BACKEND_BY_NAME = {b.name: b for b in Backend}
|
|
310
|
+
|
|
311
|
+
#: CLI is one command surface over three transports, so a "CLI" column means
|
|
312
|
+
#: whichever of SSH/TELNET/CONSOLE a model actually registers.
|
|
313
|
+
_CLI = (Backend.SSH, Backend.TELNET, Backend.CONSOLE)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def _named_backends(name: str) -> tuple[Backend, ...]:
|
|
317
|
+
key = name.strip().upper()
|
|
318
|
+
if key == "CLI":
|
|
319
|
+
return _CLI
|
|
320
|
+
try:
|
|
321
|
+
return (_BACKEND_BY_NAME[key],)
|
|
322
|
+
except KeyError:
|
|
323
|
+
raise ValueError(f"unknown backend: {name!r}") from None
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def _models_with(backends: tuple[Backend, ...]) -> tuple[str, ...]:
|
|
327
|
+
return tuple(
|
|
328
|
+
key
|
|
329
|
+
for key in matrix_models()
|
|
330
|
+
if any(b in MODELS[key].backends for b in backends)
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
class BackendModelTable(_GeneratedTable):
|
|
335
|
+
"""Which models expose one backend, and how they are reached."""
|
|
336
|
+
|
|
337
|
+
required_arguments = 1
|
|
338
|
+
|
|
339
|
+
def body(self) -> str:
|
|
340
|
+
backends = _named_backends(self.arguments[0])
|
|
341
|
+
rows = []
|
|
342
|
+
for key in _models_with(backends):
|
|
343
|
+
model = MODELS[key]
|
|
344
|
+
reached = ", ".join(
|
|
345
|
+
b.name for b in backends_for(model) if b in backends
|
|
346
|
+
)
|
|
347
|
+
rows.append(
|
|
348
|
+
[
|
|
349
|
+
# Absolute doc path: this table is included from
|
|
350
|
+
# docs/protocols/, so a relative target would resolve there.
|
|
351
|
+
f":doc:`{key} </models/{key}>`",
|
|
352
|
+
_rst_escape(model.display_name),
|
|
353
|
+
model.switch_class.value.replace("_", " "),
|
|
354
|
+
str(model.port_count),
|
|
355
|
+
reached,
|
|
356
|
+
]
|
|
357
|
+
)
|
|
358
|
+
if not rows:
|
|
359
|
+
return "No registered model exposes this backend.\n"
|
|
360
|
+
return _list_table(
|
|
361
|
+
"",
|
|
362
|
+
["Model", "Product", "Class", "Ports", "Reached over"],
|
|
363
|
+
rows,
|
|
364
|
+
widths="16 24 18 10 32",
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
class BackendOperationTable(_GeneratedTable):
|
|
369
|
+
"""Operation x model grid for ONE backend: what it can do, where."""
|
|
370
|
+
|
|
371
|
+
required_arguments = 1
|
|
372
|
+
|
|
373
|
+
def body(self) -> str:
|
|
374
|
+
backends = _named_backends(self.arguments[0])
|
|
375
|
+
keys = _models_with(backends)
|
|
376
|
+
if not keys:
|
|
377
|
+
return "No registered model exposes this backend.\n"
|
|
378
|
+
rows = []
|
|
379
|
+
notes: list[str] = []
|
|
380
|
+
seen: dict[str, int] = {}
|
|
381
|
+
label = self.arguments[0].strip().upper()
|
|
382
|
+
for op in (*READ_OPERATIONS, *WRITE_OPERATIONS):
|
|
383
|
+
cells = []
|
|
384
|
+
for key in keys:
|
|
385
|
+
backend = next(
|
|
386
|
+
(b for b in backends_for(key) if b in backends), None
|
|
387
|
+
)
|
|
388
|
+
if backend is None: # pragma: no cover - filtered by _models_with
|
|
389
|
+
cells.append(_NO)
|
|
390
|
+
continue
|
|
391
|
+
cap = support(key, backend, op)
|
|
392
|
+
if cap.supported:
|
|
393
|
+
cells.append(_YES)
|
|
394
|
+
continue
|
|
395
|
+
reason = _rst_escape(cap.reason)
|
|
396
|
+
index = seen.get(reason)
|
|
397
|
+
if index is None:
|
|
398
|
+
index = len(notes) + 1
|
|
399
|
+
seen[reason] = index
|
|
400
|
+
notes.append(reason)
|
|
401
|
+
cells.append(f"{_NO} [{label}-{index}]_")
|
|
402
|
+
rows.append([f":py:meth:`~netgear_switch.SyncSwitch.{op.name}`", *cells])
|
|
403
|
+
table = _list_table("", ["Operation", *keys], rows)
|
|
404
|
+
if not notes:
|
|
405
|
+
return table
|
|
406
|
+
citations = "\n".join(
|
|
407
|
+
f".. [{label}-{i}] {text}" for i, text in enumerate(notes, 1)
|
|
408
|
+
)
|
|
409
|
+
return f"{table}\n{citations}\n"
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
class ModelFacts(_GeneratedTable):
|
|
413
|
+
"""The registry record for one model, as a field list."""
|
|
414
|
+
|
|
415
|
+
required_arguments = 1
|
|
416
|
+
|
|
417
|
+
def body(self) -> str:
|
|
418
|
+
model = get_model(self.arguments[0])
|
|
419
|
+
aliases = sorted(k for k, v in MODEL_ALIASES.items() if v == model.key)
|
|
420
|
+
vendor = model.snmp_vendor_base or "none (standard MIBs only)"
|
|
421
|
+
dialect = {
|
|
422
|
+
"qbridge": "Q-BRIDGE static PortLists (read-modify-write)",
|
|
423
|
+
"fastpath_switchport": "FASTPATH vendor switchport table",
|
|
424
|
+
}.get(model.snmp_vlan_write, model.snmp_vlan_write)
|
|
425
|
+
rows = [
|
|
426
|
+
["Registry key", f"``{model.key}``"],
|
|
427
|
+
["Product name", _rst_escape(model.display_name)],
|
|
428
|
+
["Class", model.switch_class.value.replace("_", " ")],
|
|
429
|
+
["Ports", str(model.port_count)],
|
|
430
|
+
["PoE (PSE) ports", str(model.poe_port_count)],
|
|
431
|
+
[
|
|
432
|
+
"Backends",
|
|
433
|
+
", ".join(f"``{b.name}``" for b in backends_for(model)),
|
|
434
|
+
],
|
|
435
|
+
["SNMP vendor subtree", f"``{vendor}``"],
|
|
436
|
+
]
|
|
437
|
+
if Backend.SNMP in model.backends:
|
|
438
|
+
rows.append(["VLAN write dialect", dialect])
|
|
439
|
+
if model.snmp_vlan_split_membership_writes:
|
|
440
|
+
rows.append(
|
|
441
|
+
[
|
|
442
|
+
"VLAN write quirk",
|
|
443
|
+
"egress and untagged PortLists must travel in "
|
|
444
|
+
"SEPARATE PDUs, egress first",
|
|
445
|
+
]
|
|
446
|
+
)
|
|
447
|
+
if aliases:
|
|
448
|
+
rows.append(
|
|
449
|
+
["Aliases", ", ".join(f"``{a}``" for a in aliases)]
|
|
450
|
+
)
|
|
451
|
+
rows.append(
|
|
452
|
+
[
|
|
453
|
+
"MAC/FDB table",
|
|
454
|
+
"yes" if model.has_mac_table else "no",
|
|
455
|
+
]
|
|
456
|
+
)
|
|
457
|
+
return _list_table("", ["Field", "Value"], rows, widths="30 70")
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
class ModelPhoto(_GeneratedTable):
|
|
461
|
+
"""Render a photo of the switch, if one has been added to the repository.
|
|
462
|
+
|
|
463
|
+
Photos live at ``docs/_static/models/<key>.<ext>``. Nothing is emitted when
|
|
464
|
+
the file is absent -- a missing photo must not render as a broken image --
|
|
465
|
+
and every gap is reported once at the end of the build.
|
|
466
|
+
"""
|
|
467
|
+
|
|
468
|
+
required_arguments = 1
|
|
469
|
+
option_spec: ClassVar[dict[str, Any]] = {"alt": directives.unchanged}
|
|
470
|
+
|
|
471
|
+
_EXTENSIONS = (".jpg", ".jpeg", ".png", ".webp")
|
|
472
|
+
|
|
473
|
+
def body(self) -> str:
|
|
474
|
+
key = self.arguments[0]
|
|
475
|
+
model = get_model(key)
|
|
476
|
+
static = Path(str(self.env.srcdir)) / "_static" / "models"
|
|
477
|
+
for ext in self._EXTENSIONS:
|
|
478
|
+
if (static / f"{key}{ext}").is_file():
|
|
479
|
+
alt = self.options.get("alt", f"{model.display_name} switch")
|
|
480
|
+
return (
|
|
481
|
+
f".. figure:: /_static/models/{key}{ext}\n"
|
|
482
|
+
f" :alt: {alt}\n"
|
|
483
|
+
" :align: center\n"
|
|
484
|
+
" :class: ngsw-model-photo\n\n"
|
|
485
|
+
f" {_rst_escape(model.display_name)}\n"
|
|
486
|
+
)
|
|
487
|
+
MISSING_PHOTOS.add(key)
|
|
488
|
+
return ""
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
#: Models whose photo slot was empty during this build; reported at the end.
|
|
492
|
+
MISSING_PHOTOS: set[str] = set()
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
class UnverifiedNote(_GeneratedTable):
|
|
496
|
+
"""Name the models the tables leave out, and say why."""
|
|
497
|
+
|
|
498
|
+
def body(self) -> str:
|
|
499
|
+
keys = unverified_models()
|
|
500
|
+
if not keys:
|
|
501
|
+
return ""
|
|
502
|
+
listed = ", ".join(f"``{k}`` ({MODELS[k].display_name})" for k in keys)
|
|
503
|
+
return (
|
|
504
|
+
".. note::\n\n"
|
|
505
|
+
f" The registry also carries {listed}, which the tables above "
|
|
506
|
+
"deliberately leave out.\n"
|
|
507
|
+
" No device of either kind has ever been reachable from this "
|
|
508
|
+
"project, so there is no\n"
|
|
509
|
+
" capture, no live run, and nothing measured to report. They are "
|
|
510
|
+
"registered only so a\n"
|
|
511
|
+
" caller can construct a facade for them; treat every one of "
|
|
512
|
+
"their fields as a\n"
|
|
513
|
+
" specification-sheet guess until a real capture exists.\n"
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
def _report_missing_photos(app: Sphinx, exception: Exception | None) -> None:
|
|
518
|
+
"""Say which model pages have no photo yet, rather than failing the build.
|
|
519
|
+
|
|
520
|
+
A photo is content the repository may simply not have; the build must not
|
|
521
|
+
break over it, but the gap should be visible instead of silently invisible.
|
|
522
|
+
"""
|
|
523
|
+
if exception is not None or not MISSING_PHOTOS:
|
|
524
|
+
return
|
|
525
|
+
logger.info(
|
|
526
|
+
"ngsw: no photo for %d model(s): %s "
|
|
527
|
+
"(add docs/_static/models/<key>.jpg to fill the slot)",
|
|
528
|
+
len(MISSING_PHOTOS),
|
|
529
|
+
", ".join(sorted(MISSING_PHOTOS)),
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
|
|
285
533
|
def setup(app: Sphinx) -> dict[str, Any]:
|
|
534
|
+
app.add_directive("ngsw-unverified-note", UnverifiedNote)
|
|
286
535
|
app.add_directive("ngsw-model-table", ModelTable)
|
|
287
536
|
app.add_directive("ngsw-protocol-table", ProtocolTable)
|
|
288
537
|
app.add_directive("ngsw-operation-table", OperationTable)
|
|
289
538
|
app.add_directive("ngsw-model-support", ModelSupportTable)
|
|
539
|
+
app.add_directive("ngsw-model-facts", ModelFacts)
|
|
540
|
+
app.add_directive("ngsw-model-photo", ModelPhoto)
|
|
541
|
+
app.add_directive("ngsw-backend-models", BackendModelTable)
|
|
542
|
+
app.add_directive("ngsw-backend-operations", BackendOperationTable)
|
|
290
543
|
app.add_directive("ngsw-support-gaps", SupportGaps)
|
|
544
|
+
app.connect("build-finished", _report_missing_photos)
|
|
291
545
|
return {"version": "1.0", "parallel_read_safe": True, "parallel_write_safe": True}
|
{python_netgear_switch_library-0.0.post323 → python_netgear_switch_library-0.0.post325}/docs/conf.py
RENAMED
|
@@ -54,6 +54,9 @@ extensions = [
|
|
|
54
54
|
"sphinx.ext.intersphinx",
|
|
55
55
|
"sphinx.ext.extlinks",
|
|
56
56
|
"sphinx_copybutton",
|
|
57
|
+
# Synchronised tab sets: every API example is shown in both synchronous and
|
|
58
|
+
# asynchronous form, and picking one switches every example on the page.
|
|
59
|
+
"sphinx_design",
|
|
57
60
|
"sphinxarg.ext",
|
|
58
61
|
# Local: see docs/_ext/.
|
|
59
62
|
"filelinks",
|
|
@@ -135,6 +138,14 @@ html_theme_options = {
|
|
|
135
138
|
"source_repository": f"{GITHUB_REPO}/",
|
|
136
139
|
"source_branch": filelinks_ref,
|
|
137
140
|
"source_directory": "docs/",
|
|
141
|
+
# Shown at the top of EVERY page. This library and this documentation were
|
|
142
|
+
# written by an AI; a reader deserves to know that before they trust a
|
|
143
|
+
# sentence of it, not only if they happen to land on the front page.
|
|
144
|
+
"announcement": (
|
|
145
|
+
"This library and its documentation were written by an AI. "
|
|
146
|
+
'<a href="/en/latest/#ai-generated">What that means, and what was '
|
|
147
|
+
"actually verified against hardware</a>."
|
|
148
|
+
),
|
|
138
149
|
}
|
|
139
150
|
|
|
140
151
|
copybutton_prompt_text = r"\$ |>>> |\.\.\. "
|
|
@@ -54,21 +54,53 @@ Testing code that uses this library
|
|
|
54
54
|
Inject a client pointed at the mock. Everything above the transport — dispatch,
|
|
55
55
|
parsing, model rules — is the same code that runs against hardware.
|
|
56
56
|
|
|
57
|
-
..
|
|
57
|
+
.. tab-set::
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
.. tab-item:: Sync
|
|
60
|
+
:sync: sync
|
|
61
|
+
|
|
62
|
+
.. code-block:: python
|
|
63
|
+
|
|
64
|
+
from netgear_switch import SyncSwitch, get_model
|
|
65
|
+
from netgear_switch.transport.sync.snmp_netsnmp_cli import NetsnmpCliClient
|
|
66
|
+
from netgear_switch.virtual.server import VirtualSwitch
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_reports_link_state() -> None:
|
|
70
|
+
with VirtualSwitch(model="gsm7252ps") as mock:
|
|
71
|
+
switch = SyncSwitch(
|
|
72
|
+
get_model("gsm7252ps"),
|
|
73
|
+
host=mock.host,
|
|
74
|
+
snmp_client=NetsnmpCliClient(
|
|
75
|
+
f"{mock.host}:{mock.port}", "public"
|
|
76
|
+
),
|
|
77
|
+
)
|
|
78
|
+
assert switch.get_ports()[0].link_up
|
|
79
|
+
|
|
80
|
+
.. tab-item:: Async
|
|
81
|
+
:sync: async
|
|
82
|
+
|
|
83
|
+
.. code-block:: python
|
|
84
|
+
|
|
85
|
+
import pytest
|
|
86
|
+
|
|
87
|
+
from netgear_switch import AsyncSwitch, get_model
|
|
88
|
+
from netgear_switch.transport.aio.snmp_pysnmp import PysnmpClient
|
|
89
|
+
from netgear_switch.virtual.server import VirtualSwitch
|
|
62
90
|
|
|
63
91
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
92
|
+
@pytest.mark.asyncio
|
|
93
|
+
async def test_reports_link_state() -> None:
|
|
94
|
+
with VirtualSwitch(model="gsm7252ps") as mock:
|
|
95
|
+
switch = AsyncSwitch(
|
|
96
|
+
get_model("gsm7252ps"),
|
|
97
|
+
host=mock.host,
|
|
98
|
+
snmp_client=PysnmpClient(mock.host, "public", port=mock.port),
|
|
99
|
+
)
|
|
100
|
+
try:
|
|
101
|
+
assert (await switch.get_ports())[0].link_up
|
|
102
|
+
finally:
|
|
103
|
+
await switch.aclose()
|
|
72
104
|
|
|
73
105
|
.. code-block:: text
|
|
74
106
|
|
|
@@ -84,14 +116,19 @@ Every backend takes an injected client:
|
|
|
84
116
|
* - Backend
|
|
85
117
|
- Constructor argument
|
|
86
118
|
* - SNMP
|
|
87
|
-
- ``snmp_client=NetsnmpCliClient(f"{host}:{port}", community)
|
|
88
|
-
``
|
|
119
|
+
- sync: ``snmp_client=NetsnmpCliClient(f"{host}:{port}", community)``;
|
|
120
|
+
async: ``snmp_client=PysnmpClient(host, community, port=mock.port)``.
|
|
121
|
+
Add ``snmp_write_client=`` for writes.
|
|
89
122
|
* - NSDP
|
|
90
|
-
- ``nsdp_client=UdpNsdpClient(host, client_port=0, server_port=mock.port)
|
|
123
|
+
- sync: ``nsdp_client=UdpNsdpClient(host, client_port=0, server_port=mock.port)``;
|
|
124
|
+
async: the same arguments to ``AsyncUdpNsdpClient``.
|
|
91
125
|
* - HTTP
|
|
92
|
-
- ``http_client=HttpClient(f"{host}:{http_port}", password, http_spec(model))
|
|
126
|
+
- sync: ``http_client=HttpClient(f"{host}:{http_port}", password, http_spec(model))``;
|
|
127
|
+
async: the same arguments to ``AsyncHttpClient``.
|
|
93
128
|
* - CLI
|
|
94
|
-
- ``cli_client=mock.cli_session()``
|
|
129
|
+
- ``cli_client=mock.cli_session()`` — **synchronous only**. The CLI
|
|
130
|
+
transports block, so :py:class:`~netgear_switch.AsyncSwitch` has no CLI
|
|
131
|
+
backend and takes no ``cli_client``.
|
|
95
132
|
|
|
96
133
|
All four at once
|
|
97
134
|
----------------
|
|
@@ -274,7 +311,7 @@ with the wrong model:
|
|
|
274
311
|
host=mock.host,
|
|
275
312
|
snmp_client=NetsnmpCliClient(f"{mock.host}:{mock.port}", "public"),
|
|
276
313
|
)
|
|
277
|
-
print(switch.identify())
|
|
314
|
+
print(switch.identify()) # await switch.identify() on AsyncSwitch
|
|
278
315
|
|
|
279
316
|
.. code-block:: text
|
|
280
317
|
|
|
@@ -64,10 +64,23 @@ gaps that remain.
|
|
|
64
64
|
Dispatch: exactly one backend, every time
|
|
65
65
|
-----------------------------------------
|
|
66
66
|
|
|
67
|
-
..
|
|
67
|
+
.. tab-set::
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
.. tab-item:: Sync
|
|
70
|
+
:sync: sync
|
|
71
|
+
|
|
72
|
+
.. code-block:: python
|
|
73
|
+
|
|
74
|
+
switch.get_vlans() # the model's default backend
|
|
75
|
+
switch.get_vlans(backend=Backend.HTTP) # exactly HTTP, or an error
|
|
76
|
+
|
|
77
|
+
.. tab-item:: Async
|
|
78
|
+
:sync: async
|
|
79
|
+
|
|
80
|
+
.. code-block:: python
|
|
81
|
+
|
|
82
|
+
await switch.get_vlans() # the model's default backend
|
|
83
|
+
await switch.get_vlans(backend=Backend.HTTP) # exactly HTTP, or an error
|
|
71
84
|
|
|
72
85
|
When you **name** a backend, that backend runs. If the model does not have it,
|
|
73
86
|
you get `UnsupportedCapabilityError` immediately. If it has it but cannot serve
|
|
@@ -106,12 +119,27 @@ Choosing a default per facade
|
|
|
106
119
|
|
|
107
120
|
Pass ``backend=`` to the constructor to change the default for every call:
|
|
108
121
|
|
|
109
|
-
..
|
|
122
|
+
.. tab-set::
|
|
123
|
+
|
|
124
|
+
.. tab-item:: Sync
|
|
125
|
+
:sync: sync
|
|
126
|
+
|
|
127
|
+
.. code-block:: python
|
|
128
|
+
|
|
129
|
+
web_only = SyncSwitch(
|
|
130
|
+
get_model("gsm7252ps"), host="10.1.5.22",
|
|
131
|
+
http_password="...", backend=Backend.HTTP,
|
|
132
|
+
)
|
|
110
133
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
134
|
+
.. tab-item:: Async
|
|
135
|
+
:sync: async
|
|
136
|
+
|
|
137
|
+
.. code-block:: python
|
|
138
|
+
|
|
139
|
+
web_only = AsyncSwitch(
|
|
140
|
+
get_model("gsm7252ps"), host="10.1.5.22",
|
|
141
|
+
http_password="...", backend=Backend.HTTP,
|
|
142
|
+
)
|
|
115
143
|
|
|
116
144
|
Per-call ``backend=`` still overrides it.
|
|
117
145
|
|
|
@@ -121,11 +149,13 @@ Verification status
|
|
|
121
149
|
This project distinguishes what has been *measured* from what has been
|
|
122
150
|
*assumed*, and the distinction is visible in the API.
|
|
123
151
|
|
|
124
|
-
|
|
125
|
-
``False`` marks a model registered from a specification sheet with no
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
in
|
|
152
|
+
`SwitchModel.verified`
|
|
153
|
+
``False`` marks a model registered from a specification sheet, with no
|
|
154
|
+
device of that kind ever reachable from this project. Such a model is
|
|
155
|
+
**excluded from every support table** — see :doc:`../models/index` —
|
|
156
|
+
because putting it in a matrix would assert per-backend behaviour nobody has
|
|
157
|
+
observed. It stays in the registry only so a caller can construct a facade
|
|
158
|
+
for it, and nothing here treats it as evidence of anything.
|
|
129
159
|
|
|
130
160
|
``HttpModelSpec.reads_verified``, ``CliModelSpec.reads_verified`` / ``writes_verified``
|
|
131
161
|
Per-model, per-backend flags recording whether that backend's output has
|
|
@@ -173,8 +203,29 @@ see :doc:`../models/support`.
|
|
|
173
203
|
Synchronous and asynchronous
|
|
174
204
|
----------------------------
|
|
175
205
|
|
|
176
|
-
|
|
206
|
+
:py:class:`~netgear_switch.SyncSwitch` and
|
|
207
|
+
:py:class:`~netgear_switch.AsyncSwitch` expose the same operations with the same
|
|
177
208
|
arguments and the same semantics. They share the model registry, the parsers and
|
|
178
209
|
the backend-resolution seam in ``src/netgear_switch/_dispatch.py``; only the
|
|
179
210
|
transports differ. ``tests/test_facade_equivalence.py`` asserts they stay in
|
|
180
211
|
step.
|
|
212
|
+
|
|
213
|
+
.. important::
|
|
214
|
+
|
|
215
|
+
**One backend is synchronous-only: the CLI.** All three CLI transports —
|
|
216
|
+
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
|
+
Asking for one raises rather than quietly blocking the event loop::
|
|
219
|
+
|
|
220
|
+
UnsupportedCapabilityError: model 'gsm7252ps' CLI reads are not available
|
|
221
|
+
via the async facade (CLI is synchronous ...)
|
|
222
|
+
|
|
223
|
+
That also rules out
|
|
224
|
+
:py:meth:`~netgear_switch.SyncSwitch.upload_certificate_scp` on the async
|
|
225
|
+
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:func:`asyncio.to_thread`.
|
|
228
|
+
|
|
229
|
+
**The support tables in** :doc:`../models/support` **describe the
|
|
230
|
+
synchronous facade.** Every SNMP, NSDP and HTTP entry holds for both; the CLI
|
|
231
|
+
columns apply to :py:class:`~netgear_switch.SyncSwitch` only.
|