python-netgear-switch-library 0.0.post354__tar.gz → 0.0.post355__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.post354 → python_netgear_switch_library-0.0.post355}/PKG-INFO +1 -1
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/_version.py +2 -2
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/capabilities.py +17 -1
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/http_write.py +23 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/http/endpoints.py +21 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/web.py +2 -2
- python_netgear_switch_library-0.0.post355/tests/virtual/test_write_outcomes.py +136 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/.github/workflows/ci.yml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/.github/workflows/deb.yml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/.github/workflows/publish-pypi.yml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/.gitignore +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/.readthedocs.yaml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/CLAUDE.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/LICENSE +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/README.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/RELEASING.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/debian/changelog +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/debian/control +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/debian/copyright +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/debian/rules +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/debian/source/format +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/Makefile +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/_ext/filelinks.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/_ext/support_tables.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/_static/models/gs105pe.png +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/_static/models/gs110emx.png +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/_static/models/gs305ep.png +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/_static/models/gs728tpp.png +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/_static/models/gsm7228ps.jpg +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/_static/models/gsm7252ps.jpg +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/_static/models/m4300-16x.png +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/_static/models/m4300-24x.png +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/_static/ngsw.css +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/api/cli.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/api/core.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/api/facades.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/api/index.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/api/mcp.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/api/operations.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/api/protocols.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/api/transport.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/api/virtual.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/cli.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/conf.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/development.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/fake/index.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/fake/internals.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/fake/serving.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/fake/testing.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/guide/concepts.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/guide/configuration.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/guide/installation.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/guide/principles.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/guide/quickstart.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/guide/reading.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/guide/writing.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/index.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/mcp.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/models/gs105pe.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/models/gs110emx.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/models/gs305ep.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/models/gs728tpp.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/models/gsm7228ps.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/models/gsm7252ps.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/models/index.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/models/m4300-16x.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/models/m4300-24x.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/models/support.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/protocols/cli.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/protocols/http/cheetah-form.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/protocols/http/cheetah-v1.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/protocols/http/gambit.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/protocols/http/merge-hash-cgi.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/protocols/http/xml-api.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/protocols/http.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/protocols/index.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/protocols/nsdp.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/protocols/snmp.rst +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/plans/2026-07-15-foundation.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/plans/2026-07-17-slice-02-snmp-read-core.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/plans/2026-07-17-slice-03-read-apis.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/plans/2026-07-18-slice-04-snmp-write.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/plans/2026-07-18-slice-05-nsdp.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/plans/2026-07-18-slice-06-http.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/plans/2026-07-18-slice-07-cli.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/plans/2026-07-18-slice-08-packaging-ci.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/plans/2026-07-23-gsm7252ps-http-xe-dialect.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/specs/2026-07-15-netgear-control-library-design.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/specs/2026-07-23-gsm7252ps-http-xe-dialect-design.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/superpowers/specs/2026-08-02-snmp-surface-findings.md +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/packaging/apt-index.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/packaging/ci-build.sh +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/packaging/deb-version.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/pyproject.toml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/_dispatch.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/aio_api.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/cli/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/cli/capture.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/cli/context.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/cli/format.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/cli/main.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/cli/resolve.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/cli/safety.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/cli_read.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/cli_write.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/config.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/errors.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/http_read.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/mcp/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/mcp/server.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/models.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/nsdp_read.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/nsdp_write.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/cli/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/cli/commands.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/cli/parse.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/http/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/http/crypt.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/http/forms.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/http/parse.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/http/session.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/http/types.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/nsdp/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/nsdp/auth.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/nsdp/client.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/nsdp/parsers.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/nsdp/protocol.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/nsdp/types.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/nsdp/write.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/snmp/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/snmp/client.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/snmp/oids.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/snmp/parse.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/protocols/snmp/write.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/py.typed +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/registry.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/snmp_read.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/snmp_write.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/sync_api.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/aio/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/aio/nsdp_udp.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/aio/snmp_pysnmp.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/cli/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/cli/console.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/cli/session.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/cli/ssh.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/cli/telnet.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/http/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/http/client.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/sync/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/sync/nsdp_udp.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/transport/sync/snmp_netsnmp_cli.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/cli_fastpath.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/faces/__init__.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/faces/cli.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/faces/http.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/faces/mibview.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/faces/nsdp.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/faces/snmp.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/seed.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/server.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/state.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/web_fastpath_vlan.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/web_fastpath_xui.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/web_gs105pe.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/web_gs110emx.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/web_gs110emx_templates.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/web_gs728tpp.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/web_gsm7228ps.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/web_gsm7252ps.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/src/netgear_switch/virtual/web_m4300.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/capture_parity.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_capture.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_cli_integration.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_control_poe_port.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_control_vlan_ip.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_format.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_main_framework.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_new_commands.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_op_coverage.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_prompt_wiring.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_read_commands.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_resolve.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_safety.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/cli/test_serve.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/conftest.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/captures/gsm7228ps.json +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/captures/gsm7252ps.json +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/captures/m4300-16x.json +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/captures/m4300-24x.json +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7228ps_environment.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7228ps_lldp.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7228ps_mac_table.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7228ps_network.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7228ps_poe.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7228ps_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7228ps_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7228ps_vlan.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7228ps_vlan_brief.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7228ps_vlan_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7252ps_show_environment.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7252ps_show_interface_ethernet_1_0_1.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7252ps_show_lldp_remote_device_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7252ps_show_mac_addr_table.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7252ps_show_network.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7252ps_show_poe_port_info_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7252ps_show_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7252ps_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7252ps_show_vlan_90.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7252ps_show_vlan_brief.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/gsm7252ps_show_vlan_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_environment.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_interface_ethernet_1_0_1.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_ip_management.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_lldp_remote_device_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_mac_addr_table.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_poe_port_info_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_vlan.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_vlan_1.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_vlan_4.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_vlan_5.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_16x_show_vlan_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_24x_show_environment.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_24x_show_interface_ethernet_1_0_1.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_24x_show_ip_management.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_24x_show_lldp_remote_device_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_24x_show_mac_addr_table.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_24x_show_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_24x_show_version.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_24x_show_vlan.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_24x_show_vlan_5.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_24x_show_vlan_90.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/cli/m4300_24x_show_vlan_port_all.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs105pe_membership.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs105pe_portstats.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs105pe_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs105pe_status.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs105pe_switch_info.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs105pe_vlancfg.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs110emx_cf8021q.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs110emx_interface_stats.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs110emx_login.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs110emx_port_settings.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs110emx_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs110emx_redirect.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs110emx_sysinfo.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs110emx_vlanmembership.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs305ep_dashboard.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs305ep_login.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs305ep_membership.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs305ep_poestatus.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs305ep_portstats.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs305ep_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs305ep_vlancfg.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs728tpp_device_info_and_sensors.xml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs728tpp_lldp.xml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs728tpp_macs.xml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs728tpp_mgmt_ip.xml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs728tpp_poe.xml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs728tpp_ports.xml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs728tpp_pvids_membership.xml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs728tpp_vlan_membership_per_vlan.xml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gs728tpp_vlans.xml +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7228ps_basicAddressTable.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7228ps_ipConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7228ps_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7228ps_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7228ps_portPvidConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7228ps_portStatistics.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7228ps_portsConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7228ps_sysInfo.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7228ps_vlanPortCfg_vlan5.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7228ps_vlanStatus.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_basicAddressTable.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_http_configuration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_ipConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_login.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_portPvidConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_portStatistics.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_portsConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_sysInfo.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_syslog_configuration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_user_configuration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan1.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_vlanPortCfg_vlan141.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_vlanStatus.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/gsm7252ps_vlan_status_live.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_16x_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_16x_mgmtVlanIpv4Configuration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_16x_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_16x_portsConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_16x_vlanportcfg_vlan4.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_24x_poeInterfaceConfiguration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_addresstable.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_lldpRemoteInventory.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_mgmtVlanIpv4Configuration.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_ports.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_portstats.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_pvid.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_sysinfo.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_vlanportcfg_vlan1.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/http/m4300_vlanstatus.html +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/snmp/gsm7252ps_fans.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/snmp/gsm7252ps_ifhighspeed.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/snmp/gsm7252ps_ifoperstatus.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/fixtures/snmp/gsm7252ps_psu.txt +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/http_specs.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/cli/test_cli_parse.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/http/test_crypt.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/http/test_endpoints.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/http/test_forms.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/http/test_parse.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/nsdp/test_auth.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/nsdp/test_parsers.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/nsdp/test_protocol.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/nsdp/test_write_frame.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/snmp/test_client.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/snmp/test_oids.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/snmp/test_parse_lldp_macs.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/snmp/test_parse_mgmt_ip.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/snmp/test_parse_poe_sensors.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/snmp/test_parse_ports.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/snmp/test_parse_system_info.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/snmp/test_parse_vlans.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/protocols/snmp/test_write_encode.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_aio_api.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_capabilities.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_cli_read.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_cli_vlan_write.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_cli_write.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_config.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_cross_backend_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_deb_version.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_dispatch.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_docs_coverage.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_errors.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_facade_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_http_dispatch.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_http_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_http_read.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_http_vlan_membership.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_http_write.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_http_xui_writes.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_import.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_mcp_server.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_models.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_models_snmp_read.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_nsdp_integration.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_nsdp_read.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_nsdp_write.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_public_api.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_quality_gates.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_registry.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_snmp_integration.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_snmp_read.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_snmp_write.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_sync_api.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_version.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/test_write_equivalence.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/transport/_fastpath_fake.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/transport/test_cli_console.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/transport/test_cli_scp_cert.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/transport/test_cli_telnet.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/transport/test_http_client.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/transport/test_nsdp_udp_sync.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/transport/test_set_transport.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/transport/test_snmp_netsnmp_cli.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/transport/test_snmp_pysnmp.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/transport/test_value_parity.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_cli_cross_backend.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_cli_gsm7228ps_parity.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_gsm7228ps_seed.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_hostname.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_m4300_seeds.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_mibview.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_mutable_state.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_nsdp_state.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_serve_daemon.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_snmp_write_face.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_state_seed.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_switchport_vlan_write.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_syslog_fidelity.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_virtual_http_face.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_virtual_nsdp_face.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_virtual_snmp_face.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/tests/virtual/test_web_projection.py +0 -0
- {python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/uv.lock +0 -0
{python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/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.post355
|
|
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.post355'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 0, 'post355')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -101,6 +101,11 @@ class Operation:
|
|
|
101
101
|
|
|
102
102
|
_CLI_BACKENDS = frozenset({Backend.SSH, Backend.TELNET, Backend.CONSOLE})
|
|
103
103
|
|
|
104
|
+
#: HTTP writes implemented by scraping the Plus dialect's CSRF token. A dialect
|
|
105
|
+
#: without that token cannot serve any of them -- see
|
|
106
|
+
#: ``endpoints.dialect_has_csrf_hash`` for the measurement.
|
|
107
|
+
_CSRF_HTTP_WRITES = frozenset({"create_vlan", "delete_vlan"})
|
|
108
|
+
|
|
104
109
|
READ_OPERATIONS: tuple[Operation, ...] = (
|
|
105
110
|
Operation("get_ports", OperationKind.READ, "Per-port link/admin status"),
|
|
106
111
|
Operation("get_stats", OperationKind.READ, "Per-port octet/packet counters"),
|
|
@@ -351,7 +356,7 @@ def _http_path_for(spec: HttpModelSpec, op: Operation) -> str | None:
|
|
|
351
356
|
|
|
352
357
|
def _http_support(model: SwitchModel, op: Operation) -> tuple[Support, str]:
|
|
353
358
|
from .http_write import CERT_UPLOAD_KNOWN_UNIMPLEMENTED
|
|
354
|
-
from .protocols.http.endpoints import http_spec
|
|
359
|
+
from .protocols.http.endpoints import dialect_has_csrf_hash, http_spec
|
|
355
360
|
|
|
356
361
|
spec = http_spec(model)
|
|
357
362
|
if not spec.reads_verified:
|
|
@@ -374,6 +379,17 @@ def _http_support(model: SwitchModel, op: Operation) -> tuple[Support, str]:
|
|
|
374
379
|
f"this model takes a certificate by {mechanism}, not over the "
|
|
375
380
|
"web UI -- use upload_certificate_scp",
|
|
376
381
|
)
|
|
382
|
+
if op.name in _CSRF_HTTP_WRITES and not dialect_has_csrf_hash(spec.html_dialect):
|
|
383
|
+
# These writers scrape an <input name="hash"> before posting, and this
|
|
384
|
+
# dialect's pages do not carry one -- MEASURED on gsm7252ps and
|
|
385
|
+
# gs110emx, see endpoints.dialect_has_csrf_hash. Driving them raises
|
|
386
|
+
# HttpUnexpectedPageError on real hardware, so claiming support here
|
|
387
|
+
# would publish a support table that contradicts the device.
|
|
388
|
+
return (
|
|
389
|
+
Support.UNSUPPORTED,
|
|
390
|
+
f"model {model.key!r} web UI carries no CSRF 'hash' token, which "
|
|
391
|
+
f"the HTTP {op.name} writer requires",
|
|
392
|
+
)
|
|
377
393
|
path = _http_path_for(spec, op)
|
|
378
394
|
if path is None:
|
|
379
395
|
return (
|
|
@@ -268,6 +268,25 @@ def _check_goahead_upload_response(text: str) -> None:
|
|
|
268
268
|
)
|
|
269
269
|
|
|
270
270
|
|
|
271
|
+
def _require_csrf_dialect(spec: HttpModelSpec, model_key: str, op: str) -> None:
|
|
272
|
+
"""Refuse a hash-scraping write on a dialect whose pages carry no token.
|
|
273
|
+
|
|
274
|
+
This is a CAPABILITY refusal, not a surprise, so it raises
|
|
275
|
+
UnsupportedCapabilityError rather than HttpUnexpectedPageError: the writer
|
|
276
|
+
is built on the Plus form, and MEASURED probes of gsm7252ps and gs110emx
|
|
277
|
+
found no ``<input name="hash">`` anywhere in their write pages. Saying so by
|
|
278
|
+
type is what lets the facade, the capability table and the caller agree --
|
|
279
|
+
and what stops a bare "unexpected page" from reading like a transient fault.
|
|
280
|
+
"""
|
|
281
|
+
from .protocols.http.endpoints import dialect_has_csrf_hash
|
|
282
|
+
|
|
283
|
+
if not dialect_has_csrf_hash(spec.html_dialect):
|
|
284
|
+
raise UnsupportedCapabilityError(
|
|
285
|
+
f"model {model_key!r} web UI carries no CSRF 'hash' token, which "
|
|
286
|
+
f"the HTTP {op} writer requires"
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
|
|
271
290
|
def _csrf(html: str) -> str:
|
|
272
291
|
token = parse.parse_csrf_hash(html)
|
|
273
292
|
if token is None:
|
|
@@ -747,6 +766,7 @@ class HttpWriter:
|
|
|
747
766
|
return shown
|
|
748
767
|
|
|
749
768
|
def create_vlan(self, vlan: int, name: str, *, force: bool = False) -> None:
|
|
769
|
+
_require_csrf_dialect(self._spec, self.model.key, "create_vlan")
|
|
750
770
|
del name, force # web UI 8021qCf.cgi has no VLAN-name field (GROUNDED).
|
|
751
771
|
path = _require_path(self.model.key, self._spec.vlan_config_path, "VLAN config")
|
|
752
772
|
page = self.session.get_page(path)
|
|
@@ -760,6 +780,7 @@ class HttpWriter:
|
|
|
760
780
|
)
|
|
761
781
|
|
|
762
782
|
def delete_vlan(self, vlan: int, *, force: bool = False) -> None:
|
|
783
|
+
_require_csrf_dialect(self._spec, self.model.key, "delete_vlan")
|
|
763
784
|
del force # VLAN delete disruptiveness is guarded per-member elsewhere.
|
|
764
785
|
path = _require_path(self.model.key, self._spec.vlan_config_path, "VLAN config")
|
|
765
786
|
page = self.session.get_page(path)
|
|
@@ -1215,6 +1236,7 @@ class AsyncHttpWriter:
|
|
|
1215
1236
|
return shown
|
|
1216
1237
|
|
|
1217
1238
|
async def create_vlan(self, vlan: int, name: str, *, force: bool = False) -> None:
|
|
1239
|
+
_require_csrf_dialect(self._spec, self.model.key, "create_vlan")
|
|
1218
1240
|
del name, force
|
|
1219
1241
|
path = _require_path(self.model.key, self._spec.vlan_config_path, "VLAN config")
|
|
1220
1242
|
page = await self.session.get_page(path)
|
|
@@ -1228,6 +1250,7 @@ class AsyncHttpWriter:
|
|
|
1228
1250
|
)
|
|
1229
1251
|
|
|
1230
1252
|
async def delete_vlan(self, vlan: int, *, force: bool = False) -> None:
|
|
1253
|
+
_require_csrf_dialect(self._spec, self.model.key, "delete_vlan")
|
|
1231
1254
|
del force
|
|
1232
1255
|
path = _require_path(self.model.key, self._spec.vlan_config_path, "VLAN config")
|
|
1233
1256
|
page = await self.session.get_page(path)
|
|
@@ -140,6 +140,27 @@ class HtmlDialect(enum.Enum):
|
|
|
140
140
|
GOAHEAD_XML = "goahead_xml"
|
|
141
141
|
|
|
142
142
|
|
|
143
|
+
def dialect_has_csrf_hash(dialect: HtmlDialect) -> bool:
|
|
144
|
+
"""Whether this dialect's pages carry an ``<input name="hash">`` CSRF token.
|
|
145
|
+
|
|
146
|
+
``http_write`` scrapes that token before every form post, so a dialect
|
|
147
|
+
without one cannot be driven by those writers at all.
|
|
148
|
+
|
|
149
|
+
MEASURED 2026-08-02, not inferred. Live probes found NO hash on any write
|
|
150
|
+
page of gsm7252ps (10.1.5.22: vlanStatus, poeInterfaceConfiguration,
|
|
151
|
+
portPvidConfiguration, vlan_port_cfg, portsConfiguration) nor of gs110emx
|
|
152
|
+
(10.1.5.25: Cf8021q, vlan_pvidsetting). Only the Plus ``.cgi`` pages have
|
|
153
|
+
it -- the surface ``HttpWriter`` was originally written against.
|
|
154
|
+
|
|
155
|
+
ONE definition, read by the capability oracle AND by the virtual switch, so
|
|
156
|
+
the mock can never emit a token the hardware lacks. That divergence is
|
|
157
|
+
exactly how HTTP ``create_vlan`` passed the entire test suite while failing
|
|
158
|
+
on all four FASTPATH switches.
|
|
159
|
+
"""
|
|
160
|
+
return dialect in {HtmlDialect.STANDARD, HtmlDialect.GS105PE}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
143
164
|
@dataclass(frozen=True)
|
|
144
165
|
class XuiMgmtIpFields:
|
|
145
166
|
"""Which fields of a FASTPATH XUI management-IP page carry what.
|
|
@@ -57,9 +57,9 @@ def _has_csrf_hash(spec: HttpModelSpec) -> bool:
|
|
|
57
57
|
where the hardware does makes the mock refuse the same write the switch
|
|
58
58
|
refuses.
|
|
59
59
|
"""
|
|
60
|
-
from ..protocols.http.endpoints import
|
|
60
|
+
from ..protocols.http.endpoints import dialect_has_csrf_hash
|
|
61
61
|
|
|
62
|
-
return spec.html_dialect
|
|
62
|
+
return dialect_has_csrf_hash(spec.html_dialect)
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
def render_page(
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# tests/virtual/test_write_outcomes.py
|
|
2
|
+
"""Writes must CHANGE STATE, not merely reach a backend.
|
|
3
|
+
|
|
4
|
+
``tests/test_capabilities.py`` deliberately asserts something weaker: that the
|
|
5
|
+
facade dispatches an operation to the backend the table names. Its ``_refused``
|
|
6
|
+
counts only ``UnsupportedCapabilityError``/``NotImplementedError`` as a refusal,
|
|
7
|
+
so any other exception means "the backend accepted the op and tried" -- which is
|
|
8
|
+
exactly what ``Support.SUPPORTED`` claims there.
|
|
9
|
+
|
|
10
|
+
That is a reasonable contract, and it is why a write which reaches the right
|
|
11
|
+
backend and then FAILS there is invisible to it. HTTP ``create_vlan`` did that
|
|
12
|
+
on four FASTPATH models for as long as the operation has existed: the writer
|
|
13
|
+
scrapes an ``<input name="hash">`` CSRF token those pages do not carry, and the
|
|
14
|
+
mock hid it by emitting one anyway. 27 green capability tests coexisted with a
|
|
15
|
+
write that had never worked on real hardware.
|
|
16
|
+
|
|
17
|
+
This module closes that gap for the VLAN lifecycle: for every (model, backend)
|
|
18
|
+
the capability table claims is SUPPORTED, create a VLAN and assert it is
|
|
19
|
+
actually there afterwards, then delete it and assert it is actually gone.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from typing import TYPE_CHECKING, Any
|
|
25
|
+
|
|
26
|
+
import pytest
|
|
27
|
+
|
|
28
|
+
from netgear_switch.capabilities import backends_for, operation, support
|
|
29
|
+
from netgear_switch.protocols.cli.commands import CLI_BACKENDS
|
|
30
|
+
from netgear_switch.protocols.http.endpoints import http_spec
|
|
31
|
+
from netgear_switch.registry import Backend, get_model
|
|
32
|
+
from netgear_switch.sync_api import SyncSwitch
|
|
33
|
+
from netgear_switch.transport.http.client import HttpClient
|
|
34
|
+
from netgear_switch.transport.sync.nsdp_udp import UdpNsdpClient
|
|
35
|
+
from netgear_switch.transport.sync.snmp_netsnmp_cli import NetsnmpCliClient
|
|
36
|
+
from netgear_switch.virtual.server import VirtualSwitch
|
|
37
|
+
|
|
38
|
+
if TYPE_CHECKING:
|
|
39
|
+
from netgear_switch.registry import SwitchModel
|
|
40
|
+
|
|
41
|
+
#: gs105pe is expected to FAIL: its HTTP create_vlan reports
|
|
42
|
+
#: WriteVerificationError("VLAN 4007 was not created") against the mock. That is
|
|
43
|
+
#: a REAL defect this module exposed, not a test artefact -- an earlier ad-hoc
|
|
44
|
+
#: probe called it working only because it never deleted between backends, so
|
|
45
|
+
#: the HTTP check saw the VLAN NSDP had already created. Marked xfail(strict) so
|
|
46
|
+
#: the suite stays honest AND tells us the moment it starts passing.
|
|
47
|
+
XFAIL_MODELS = {"gs105pe"}
|
|
48
|
+
|
|
49
|
+
SEEDED_MODELS = (
|
|
50
|
+
"gsm7252ps",
|
|
51
|
+
"gsm7228ps",
|
|
52
|
+
"m4300-24x",
|
|
53
|
+
"m4300-16x",
|
|
54
|
+
"gs110emx",
|
|
55
|
+
"gs305ep",
|
|
56
|
+
"gs105pe",
|
|
57
|
+
"gs728tpp",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
#: A throwaway id from the range this project reserves for testing (4001-4008).
|
|
61
|
+
TEST_VLAN = 4007
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _facade(mock: VirtualSwitch, model: SwitchModel) -> SyncSwitch:
|
|
65
|
+
"""A facade wired to every face this mock bound, so no op reaches a network."""
|
|
66
|
+
kwargs: dict[str, Any] = {}
|
|
67
|
+
if Backend.SNMP in model.backends:
|
|
68
|
+
snmp = NetsnmpCliClient(f"{mock.host}:{mock.port}", mock.community)
|
|
69
|
+
kwargs["snmp_client"] = snmp
|
|
70
|
+
kwargs["snmp_write_client"] = snmp
|
|
71
|
+
if Backend.NSDP in model.backends:
|
|
72
|
+
nsdp = UdpNsdpClient(
|
|
73
|
+
mock.host, client_port=0, server_port=mock.port, timeout=2.0
|
|
74
|
+
)
|
|
75
|
+
kwargs["nsdp_client"] = nsdp
|
|
76
|
+
kwargs["nsdp_write_client"] = nsdp
|
|
77
|
+
kwargs["nsdp_password"] = mock.nsdp_password
|
|
78
|
+
if Backend.HTTP in model.backends:
|
|
79
|
+
kwargs["http_client"] = HttpClient(
|
|
80
|
+
f"{mock.host}:{mock.http_port}", mock.http_password, http_spec(model)
|
|
81
|
+
)
|
|
82
|
+
if CLI_BACKENDS & model.backends:
|
|
83
|
+
kwargs["cli_client"] = mock.cli_session()
|
|
84
|
+
return SyncSwitch(model, host=mock.host, **kwargs)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@pytest.mark.parametrize(
|
|
88
|
+
"key",
|
|
89
|
+
[
|
|
90
|
+
pytest.param(
|
|
91
|
+
k,
|
|
92
|
+
marks=pytest.mark.xfail(
|
|
93
|
+
strict=True,
|
|
94
|
+
reason="HTTP create_vlan does not apply on this dialect; see "
|
|
95
|
+
"XFAIL_MODELS",
|
|
96
|
+
),
|
|
97
|
+
)
|
|
98
|
+
if k in XFAIL_MODELS
|
|
99
|
+
else k
|
|
100
|
+
for k in SEEDED_MODELS
|
|
101
|
+
],
|
|
102
|
+
)
|
|
103
|
+
def test_claimed_vlan_writes_actually_change_state(key: str) -> None:
|
|
104
|
+
model = get_model(key)
|
|
105
|
+
create, delete = operation("create_vlan"), operation("delete_vlan")
|
|
106
|
+
with VirtualSwitch(model=key) as mock:
|
|
107
|
+
switch = _facade(mock, model)
|
|
108
|
+
for backend in backends_for(model):
|
|
109
|
+
if not support(model, backend, create).supported:
|
|
110
|
+
continue
|
|
111
|
+
|
|
112
|
+
def vlans(b: Backend = backend) -> set[int]:
|
|
113
|
+
return {v.vlan_id for v in switch.get_vlans(backend=b)}
|
|
114
|
+
|
|
115
|
+
before = vlans()
|
|
116
|
+
assert TEST_VLAN not in before, f"{key}/{backend.name}: seed uses the id"
|
|
117
|
+
|
|
118
|
+
switch.create_vlan(TEST_VLAN, "outcome", backend=backend)
|
|
119
|
+
assert TEST_VLAN in vlans(), (
|
|
120
|
+
f"{key}/{backend.name}: capabilities says create_vlan is "
|
|
121
|
+
"supported, and the call returned, but the VLAN is not there"
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
if support(model, backend, delete).supported:
|
|
125
|
+
# force=True: NSDP force-gates delete_vlan because it drops every
|
|
126
|
+
# member port. The gate is a deliberate safety feature, not the
|
|
127
|
+
# thing under test here.
|
|
128
|
+
switch.delete_vlan(TEST_VLAN, force=True, backend=backend)
|
|
129
|
+
assert TEST_VLAN not in vlans(), (
|
|
130
|
+
f"{key}/{backend.name}: delete_vlan returned but the VLAN "
|
|
131
|
+
"is still present"
|
|
132
|
+
)
|
|
133
|
+
assert vlans() == before, (
|
|
134
|
+
f"{key}/{backend.name}: VLAN set not restored after the "
|
|
135
|
+
"create/delete round trip"
|
|
136
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/.gitignore
RENAMED
|
File without changes
|
|
File without changes
|
{python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/CLAUDE.md
RENAMED
|
File without changes
|
{python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/LICENSE
RENAMED
|
File without changes
|
{python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/README.md
RENAMED
|
File without changes
|
{python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/RELEASING.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/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.post354 → python_netgear_switch_library-0.0.post355}/docs/cli.rst
RENAMED
|
File without changes
|
{python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/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
|
{python_netgear_switch_library-0.0.post354 → python_netgear_switch_library-0.0.post355}/docs/mcp.rst
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
|
|
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
|
|
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
|
|
File without changes
|