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.
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/PKG-INFO +1 -1
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/_version.py +2 -2
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli_write.py +11 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/http_read.py +79 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/http_write.py +44 -6
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/models.py +11 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/nsdp_read.py +75 -1
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/nsdp_write.py +32 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/cli/parse.py +35 -3
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/snmp_read.py +70 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/.github/workflows/ci.yml +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/.github/workflows/deb.yml +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/.github/workflows/publish-pypi.yml +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/.gitignore +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/.readthedocs.yaml +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/CLAUDE.md +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/LICENSE +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/README.md +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/RELEASING.md +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/debian/changelog +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/debian/control +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/debian/copyright +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/debian/rules +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/debian/source/format +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/Makefile +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_ext/filelinks.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_ext/support_tables.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gs105pe.png +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gs110emx.png +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gs305ep.png +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gs728tpp.png +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gsm7228ps.jpg +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/gsm7252ps.jpg +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/m4300-16x.png +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/models/m4300-24x.png +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/_static/ngsw.css +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/cli.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/core.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/facades.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/index.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/mcp.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/operations.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/protocols.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/transport.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/api/virtual.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/cli.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/conf.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/development.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/fake/index.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/fake/internals.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/fake/serving.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/fake/testing.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/concepts.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/configuration.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/installation.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/principles.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/quickstart.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/reading.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/guide/writing.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/index.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/mcp.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gs105pe.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gs110emx.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gs305ep.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gs728tpp.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gsm7228ps.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/gsm7252ps.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/index.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/m4300-16x.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/m4300-24x.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/models/support.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/cli.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http/cheetah-form.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http/cheetah-v1.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http/gambit.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http/merge-hash-cgi.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http/xml-api.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/http.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/index.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/nsdp.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/protocols/snmp.rst +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/superpowers/plans/2026-07-15-foundation.md +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/packaging/apt-index.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/packaging/ci-build.sh +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/packaging/deb-version.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/pyproject.toml +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/_dispatch.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/aio_api.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/capabilities.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/capture.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/context.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/format.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/main.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/resolve.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli/safety.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/cli_read.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/config.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/errors.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/mcp/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/mcp/server.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/cli/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/cli/commands.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/crypt.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/endpoints.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/forms.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/parse.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/session.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/http/types.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/auth.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/client.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/parsers.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/protocol.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/types.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/nsdp/write.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/snmp/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/snmp/client.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/snmp/oids.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/snmp/parse.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/protocols/snmp/write.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/py.typed +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/registry.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/snmp_write.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/sync_api.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/aio/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/aio/nsdp_udp.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/aio/snmp_pysnmp.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/cli/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/cli/console.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/cli/session.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/cli/ssh.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/cli/telnet.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/http/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/http/client.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/sync/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/transport/sync/nsdp_udp.py +0 -0
- {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
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/cli_fastpath.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/cli.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/http.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/mibview.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/nsdp.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/faces/snmp.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/seed.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/server.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/state.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_fastpath_vlan.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_fastpath_xui.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gs105pe.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gs110emx.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gs110emx_templates.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gs728tpp.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gsm7228ps.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_gsm7252ps.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/src/netgear_switch/virtual/web_m4300.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/capture_parity.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_capture.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_cli_integration.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_control_poe_port.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_control_vlan_ip.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_format.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_main_framework.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_new_commands.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_op_coverage.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_prompt_wiring.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_read_commands.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_resolve.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_safety.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/cli/test_serve.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/conftest.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/captures/gsm7228ps.json +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/captures/gsm7252ps.json +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/captures/m4300-16x.json +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/captures/m4300-24x.json +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_environment.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_lldp.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_mac_table.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_network.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_poe.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_vlan.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_vlan_brief.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7228ps_vlan_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_environment.txt +0 -0
- {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
- {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
- {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
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_network.txt +0 -0
- {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
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_vlan_90.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/gsm7252ps_show_vlan_brief.txt +0 -0
- {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
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_environment.txt +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_16x_show_vlan.txt +0 -0
- {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
- {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
- {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
- {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
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_environment.txt +0 -0
- {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
- {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
- {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
- {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
- {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
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/cli/m4300_24x_show_vlan.txt +0 -0
- {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
- {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
- {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
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_membership.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_portstats.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_status.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_switch_info.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs105pe_vlancfg.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_cf8021q.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_interface_stats.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_login.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_port_settings.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_redirect.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_sysinfo.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs110emx_vlanmembership.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_dashboard.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_login.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_membership.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_poestatus.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_portstats.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs305ep_vlancfg.html +0 -0
- {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
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_lldp.xml +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_macs.xml +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_mgmt_ip.xml +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_poe.xml +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_ports.xml +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_pvids_membership.xml +0 -0
- {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
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gs728tpp_vlans.xml +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_basicAddressTable.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_ipConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_portPvidConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_portStatistics.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_portsConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_sysInfo.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_vlanPortCfg_vlan5.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7228ps_vlanStatus.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_basicAddressTable.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_ipConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_login.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_portPvidConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_portStatistics.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_portsConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_sysInfo.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan1.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan141.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/gsm7252ps_vlanStatus.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_16x_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_16x_mgmtVlanIpv4Configuration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_16x_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_16x_portsConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_16x_vlanportcfg_vlan4.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_24x_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_addresstable.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_mgmtVlanIpv4Configuration.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_ports.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_portstats.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_sysinfo.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_vlanportcfg_vlan1.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/http/m4300_vlanstatus.html +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/snmp/gsm7252ps_fans.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/snmp/gsm7252ps_ifhighspeed.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/snmp/gsm7252ps_ifoperstatus.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/fixtures/snmp/gsm7252ps_psu.txt +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/http_specs.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/cli/test_cli_parse.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/http/test_crypt.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/http/test_endpoints.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/http/test_forms.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/http/test_parse.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/nsdp/test_auth.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/nsdp/test_parsers.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/nsdp/test_protocol.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/nsdp/test_write_frame.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_client.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_oids.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_lldp_macs.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_mgmt_ip.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_poe_sensors.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_ports.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_system_info.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_parse_vlans.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/protocols/snmp/test_write_encode.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_aio_api.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_capabilities.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_cli_read.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_cli_vlan_write.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_cli_write.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_config.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_cross_backend_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_deb_version.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_dispatch.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_docs_coverage.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_errors.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_facade_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_dispatch.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_read.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_vlan_membership.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_write.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_http_xui_writes.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_import.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_mcp_server.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_models.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_models_snmp_read.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_nsdp_integration.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_nsdp_read.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_nsdp_write.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_public_api.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_quality_gates.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_registry.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_snmp_integration.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_snmp_read.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_snmp_write.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_sync_api.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_version.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/test_write_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/_fastpath_fake.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_cli_console.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_cli_scp_cert.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_cli_telnet.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_http_client.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_nsdp_udp_sync.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_set_transport.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_snmp_netsnmp_cli.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_snmp_pysnmp.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/transport/test_value_parity.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_cli_cross_backend.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_cli_gsm7228ps_parity.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_gsm7228ps_seed.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_hostname.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_m4300_seeds.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_mibview.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_mutable_state.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_nsdp_state.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_serve_daemon.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_snmp_write_face.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_state_seed.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_switchport_vlan_write.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_virtual_http_face.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_virtual_nsdp_face.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_virtual_snmp_face.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/tests/virtual/test_web_projection.py +0 -0
- {python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/uv.lock +0 -0
{python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/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.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.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 0, '
|
|
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
|
|
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
|
|
269
|
-
|
|
270
|
-
|
|
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
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/.gitignore
RENAMED
|
File without changes
|
|
File without changes
|
{python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/CLAUDE.md
RENAMED
|
File without changes
|
{python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/LICENSE
RENAMED
|
File without changes
|
{python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/README.md
RENAMED
|
File without changes
|
{python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/RELEASING.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/debian/rules
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/cli.rst
RENAMED
|
File without changes
|
{python_netgear_switch_library-0.0.post349 → python_netgear_switch_library-0.0.post351}/docs/conf.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|