Summary
Expose real-time transfer progress to Python by adding an optional callback parameter to SFTP and SCP read/write methods, enabling integration with progress-bar libraries such as tqdm or rich.
Motivation
For large file transfers there is currently no way to observe progress. Users are left guessing whether the operation is still running, making hussh difficult to use in interactive scripts and deployment tools.
Proposed API
from tqdm import tqdm
with Connection("myserver.example.com", username="deploy", password="...") as conn:
with tqdm(unit="B", unit_scale=True, desc="upload") as bar:
def on_progress(transferred: int, total: int) -> None:
bar.total = total
bar.update(transferred - bar.n)
conn.sftp_write("/local/large_file.tar.gz", "/remote/large_file.tar.gz",
callback=on_progress)
The callback signature is:
Callable[[int, int], None] # (bytes_transferred, total_bytes)
The same callback parameter should be available on:
| Method |
Direction |
sftp_write / sftp_write_file |
local → remote |
sftp_read |
remote → local |
scp_write |
local → remote |
scp_read |
remote → local |
put_dir / get_dir (see #84) |
aggregate bytes across all files |
Implementation Notes
- On the Rust side, buffer SFTP/SCP reads and writes in chunks (e.g. 32 KiB). After each chunk, invoke a cached Python callable via PyO3's
call1 / call_bound with (transferred, total).
- For SCP, the total size is known from the SCP protocol header before data transfer begins. For SFTP, stat the file first to obtain size.
- The callback must release the GIL between chunks (
Python::allow_threads) to avoid blocking Rust I/O while Python executes the callback.
callback=None (the default) should have zero overhead—skip the PyO3 call entirely.
- For async transfers, invoke the callback as a coroutine if it is a coroutine function, otherwise call it synchronously.
Acceptance Criteria
Summary
Expose real-time transfer progress to Python by adding an optional
callbackparameter to SFTP and SCP read/write methods, enabling integration with progress-bar libraries such astqdmorrich.Motivation
For large file transfers there is currently no way to observe progress. Users are left guessing whether the operation is still running, making hussh difficult to use in interactive scripts and deployment tools.
Proposed API
The callback signature is:
The same
callbackparameter should be available on:sftp_write/sftp_write_filesftp_readscp_writescp_readput_dir/get_dir(see #84)Implementation Notes
call1/call_boundwith(transferred, total).Python::allow_threads) to avoid blocking Rust I/O while Python executes the callback.callback=None(the default) should have zero overhead—skip the PyO3 call entirely.Acceptance Criteria
callbackparameter on all four SFTP and SCP read/write methods(transferred_bytes: int, total_bytes: int)callback=Noneintroduces no measurable overheadtqdmintegration example