Repository navigation
Conversation
Passing ssl= into Server.start/run used to raise TypeError because it was forwarded to asyncio.start_server alongside ssl=self.ssl. Pop it from kwargs so both the constructor and start() keyword work. The getting-started server snippet also referenced undefined names; use the default Server() shown in the tutorial. Fixes aio-libs#204 Fixes aio-libs#203
|
| if "ssl" in kwargs: | ||
| self.ssl = kwargs.pop("ssl") |
There was a problem hiding this comment.
If a server is reused after start(ssl=...), this assignment leaves the override in self.ssl. Neither close() nor a failed start restores the constructor setting. A later start() without ssl= therefore gives control and passive listeners an unexpected TLS configuration, disrupting clients that rely on the original setting. Restore the intended setting before merging.
Knowledge Base Used: Asynchronous FTP server
Artifacts
- This authored script runs the pre-PR or PR server source through real control, passive, close, failure, and restart checks; it defines the shared test.
Lifecycle output capture command
- This authored command wrapper records each executed command, working directory, exit code, and process output; it produces the two comparable logs.
Pre-PR FTP TLS lifecycle output
- The executed pre-PR source rejected `start(ssl=...)` and served plaintext control and passive connections on later starts; no override persisted.
PR-head FTP TLS lifecycle output
- The executed PR source served TLS control and passive connections after restart without `ssl`, including after a failed bind; the override persisted.
|
|
||
| async def main(): | ||
| server = aioftp.Server([user], path_io_factory=path_io_factory) | ||
| server = aioftp.Server() |
There was a problem hiding this comment.
Example exposes writable files
If someone runs this now-working example on a network-reachable machine, it serves the process’s current directory with anonymous read and write access; run() does not restrict the bind to loopback. Clients could read or change those files. The same example appears in docs/index.rst. Restrict the directory and bind, or clearly warn readers about these defaults, before merging.
How this was verified: An anonymous connection read and uploaded files, and the example requested the unrestricted default host.
Knowledge Base Used: Server users and permissions
Artifacts
Isolated README server example probe
- The authored harness extracts and executes each README example in a temporary directory, intercepts wildcard binds, and uses a loopback FTP client to test access; it avoids exposing the repository or a network listener.
Original README example fails before starting
- The command executed the parent-commit example and captured its exit code and `NameError`; the original example never started a service.
Changed README example accepts anonymous reads and writes
- The command executed the changed example and captured its default bind request plus successful anonymous RETR and STOR over a loopback-only connection; the unsafe default permissions are reproducible.
| kwargs = start_server.call_args.kwargs | ||
| assert kwargs["ssl"] is ssl_context | ||
| assert start_server.call_args.args[2] == 0 |
There was a problem hiding this comment.
This test checks only the control listener’s ssl argument. It still passes when passive listeners receive no TLS context, although a client then cannot complete a passive data-connection TLS handshake. Cover a passive connection started with ssl= so a future regression does not break TLS transfers unnoticed. This test gap does not itself block merging.
Knowledge Base Used: Server data connections and transfers
Artifacts
Source for the targeted test and passive TLS probe
- This isolated script runs the PR test and a real FTP exchange, optionally suppressing TLS only during passive-listener creation; it shows exactly what was executed.
Unmodified server: targeted test passes and passive TLS works
- The captured baseline command exits 0, reports the full FTP responses, and completes a passive TLS handshake; the unmodified path works.
Passive TLS suppressed: targeted test still passes
- The captured perturbed command exits 0 and reports the FTP responses, but the passive TLS handshake times out; the targeted test misses the failure.
Comments Outside DiffThese findings sit on lines the diff does not cover, so they could not be posted inline. Each one leaves this list once its file changes.
|
Summary
Server.start/Server.runaccept**kwargstyped asAsyncIOStartServerKwargs, which includesssl. Those kwargs were forwarded toasyncio.start_servertogether withssl=self.ssl, so:raised
TypeError: got multiple values for keyword argument 'ssl'.sslis now taken from kwargs when provided (and still used for PASV listeners viaself.ssl).The getting-started server snippet also used undefined
userandpath_io_factorynames. It now matches the tutorial default (aioftp.Server()).Fixes #204
Fixes #203
Test plan
test_start_ssl_kwarg_does_not_conflictpython -m pytest tests/test_connection.py tests/test_tls.py— 57 passed