Mechanical: ruff format, and ruff check --fix with the rule set every NAPALM
driver uses (E, F, I, UP, B at line length 100). typing.List/Dict/Optional
become builtin generics and X | None, imports are sorted, the coding cookies
are gone. Two tests that read the source text follow the new spelling.
What ruff cannot fix comes in the next commit.
Squashes three changes:
## chore: support Python 3.13 and make mypy --strict pass in CI
Add 3.13 to the CI matrix and classifiers, run mypy in CI, fix the
14 strict errors it reported, and correct the README's minimum Python.
## fix: eight bugs found in a full review, each with a regression test
- channel: run_on_transport lost output sshd sent after the exit status;
it now reads stdout and stderr to EOF before returning.
- ssh_server: a failed way back (restore or reload) raised out of
harden_ssh_server after the host was touched; it is now reported in
the result, with rolled_back False.
- host_status: a newer RPM kernel (RHEL, Fedora) was never seen, because
its release, not its arch, followed the last "-".
- package_updates: an apt line wrapped at a blank lost the blank, and
with it the package.
- kernel: an empty payload (gzip or base64 missing) read as a report.
- listening: "[fe80::1]%eth0:546", as ss prints it, kept its brackets.
- ping_sweep: a reply whose "success" was not a dict aborted the sweep.
- lag: a member of unknown speed (-1) lowered the LAG's speed.
## docs: bring the README and docstrings in line with the code
The firewall worked example showed the runtime stubs the README forbids;
the class table missed PhoneDriver and MediaDriver; ConfigLifecycleMixin
is mixed in by drivers, not by a role base; services, mac_acl and
packages named a class, a key and an exception that do not exist.
netOrk reached a host's shell through napalm-linux's private `_send`: an
interactive PTY with stdout and stderr merged and no exit code. For Docker
it went further and opened its own paramiko connections around the driver.
This adds the access layer only, no container model (NetOrk/netork#765):
- `channel.py`: `CommandChannelMixin` declares `run_command()` (stdout,
stderr, exit code) and `open_stream()` (a `ByteStream` to a running
command). Declared under TYPE_CHECKING, so hasattr stays truthful.
`run_on_transport()` and `open_stream_on_transport()` implement both on
a paramiko exec channel for any SSH driver; `ParamikoExecStream` drains
stderr on every read so the shared window never stalls.
- `container_engine.py`: `ContainerEngineMixin` with `container_engines()`
and `open_container_engine()`. The returned `ContainerEngineConnection`
opens the engine API over `<binary> system dial-stdio` and runs the CLI
with caller-chosen arguments. The driver decides the binary through
`_container_engine_binary()`; callers never see the path.
- README: why the container model lives in netOrk and not here.
Additive; the Docker*Dict declarations stay until netOrk no longer reads
them. Version 2.6.0.
Refs #17