Configure ruff in pyproject.toml and apply its fixes: modern annotations
(X | None, builtin generics, collections.abc), sorted imports, explicit
stacklevel in test warnings.
Read the output as it arrives, split on newlines and carriage returns,
instead of all at once with communicate(). This is needed for the
progress bar. Invalid UTF-8 in the output is replaced instead of raising.
Use a fake SSH client that runs commands locally to test remote path resolution, removing old backups, finding the last backup and the rsync arguments, plus the login paths with a fake paramiko client and real keys made by ssh-keygen.