sftppath
pathlib for SFTP servers. SFTPPath("/srv/data/report.txt", host="files.example.org")
has the method names, signatures and exception types of pathlib.Path, over
paramiko or asyncssh, and needs no URI. It builds on
pathapi alone; with
uripath installed it also provides the
sftp: scheme. It is documented at https://jose-pr.github.io/sftppath/.
Features
- A
pathlibpath on a server:open,read_text,iterdir,glob,stat,mkdir,rename,replace,chmod,symlink_to,readlinkand the rest, pluswalk,copy,move,rmandPathSyncerfrompathapi. Nothing connects until the first request. - Two backends, one behaviour:
SFTPBackend(paramiko) andAsyncSSHBackend(asyncssh) raise the same exceptions for the same server answers; the choice is a keyword, a subclass attribute orSFTPPATH_BACKEND. - Native tree operations: on asyncssh a recursive
copy()andrm()run as concurrent requests on one connection, bounded bymax_concurrency. - ssh_config:
HostName,Port,User,IdentityFile,ProxyCommandandIncludeapply to the host you name; host keys are verified. - Server-side checksums:
checksum()uses thecheck-file-handleextension where the server has it, andPathSyncerfalls back to streaming where it does not. - No SSH library at import:
import sftppathloads neither library noruripath. Errors areOSErrorsubclasses,SFTPAuthenticationErrorandSFTPHostKeyError; no library exception crosses the API. - The
sftp:scheme foruripath:URIPath("sftp://user@host/dir")is anSFTPURIPaththat delegates to anSFTPPath.
Installation
pip install "sftppath[paramiko]"
Requires pathapi, which pip installs with it, and Python 3.9 or newer.
| Install | Adds |
|---|---|
pip install sftppath |
the path and the backend contract; no SSH library |
pip install "sftppath[paramiko]" |
the paramiko backend (paramiko>=5.0,<6) |
pip install "sftppath[asyncssh]" |
the asyncssh backend and the native tree operations (asyncssh>=2.20) |
pip install "sftppath[uri]" |
uripath and with it the sftp: scheme |
pip install "sftppath[all]" |
the three above |
Quick start
A path on a server: the endpoint goes in as keywords; the user, password and
port may come from your ~/.ssh/config instead:
from sftppath import SFTPPath
report = SFTPPath("/srv/data/report.txt", host="files.example.org", user="deploy")
print(report.read_text())
for child in report.parent.iterdir():
print(child.name, child.stat().st_size)
Share a connection: a backend is the connections to one server and account, and a context manager:
from sftppath import SFTPBackend, SFTPPath
with SFTPBackend("files.example.org", user="deploy", timeout=10) as backend:
root = SFTPPath("/srv/data", backend=backend)
(root / "out").mkdir(exist_ok=True)
(root / "out" / "n.txt").write_text("1")
root.copy(SFTPPath("/srv/backup", backend=backend), recursive=True)
Mirror a tree with PathSyncer, onto a local directory:
from pathapi import LocalPath
from pathapi.sync import PathSyncer
from sftppath import SFTPPath
remote = SFTPPath("/var/log", host="files.example.org", user="deploy")
PathSyncer(remove_missing=True).sync(remote, LocalPath("mirror"))
The scheme, with uripath installed:
from uripath import URIPath
print(URIPath("sftp://deploy@files.example.org/srv/data/report.txt").read_text())
API overview
| Module | Purpose |
|---|---|
sftppath |
SFTPPath, the backends SFTPBackend, AsyncSSHBackend, BaseSFTPBackend and CheckFileSFTPBackend, SFTPEndpoint, DEFAULT_PORT, DEFAULT_SSH_CONFIG, the errors and __version__ |
sftppath.exceptions |
SFTPPathError, SFTPAuthenticationError and SFTPHostKeyError |
sftppath.uri |
SFTPURIPath and SFTPURIBackend, the sftp: scheme of uripath (needs the uri extra) |
The full reference is on the documentation site;
an agent-oriented API summary ships inside the package as sftppath/AGENTS.md.
Development
pip install -e ".[dev,all]"
python -m pytest -q -rs
The tests start SSH servers of their own on the loopback interface with
throwaway keys; they never reach another host. A test for a library or an extra
that is not installed is skipped, so check the skip list (-rs). Contributor
notes (virtual environments, formatting, CI, releases) are in the repository's
AGENTS.md. To
preview the documentation: pip install -e ".[all,docs]" then mkdocs serve.
Changes are recorded in the changelog.
Releasing
This project follows Semantic Versioning and keeps a
CHANGELOG.md. Pushing a tag matching v* triggers the release
workflow: test gate → build (checking the tag names the version built) → a strict
docs build as a gate → GitHub release → publish. The release workflow never deploys
the docs site itself: for a final release its last job dispatches the docs workflow
at the tag, which owns every Pages deploy.
License
MIT — see LICENSE.
Metadata
Release files for sftppath 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sftppath-0.1.1.tar.gz | 185.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sftppath-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 264.2 kB
Release files / sftppath-0.1.1.tar.gz
| Download URL | sftppath-0.1.1.tar.gz |
|---|---|
| Size | 185.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a134b48e35c69dc726beb65b580637ef9c26bbb423c6edbaa345c9e6e546f19a
|
|
BLAKE2b-256 checksum How to use checksums |
39cfd7db028a3309eef3279b7c32a39c95f711cd819d104a77adb17495423441
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency logRelease files / sftppath-0.1.1-py3-none-any.whl
| Download URL | sftppath-0.1.1-py3-none-any.whl |
|---|---|
| Size | 79.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5f7a8791c9503ec43b07fa821690a92f5a9af55d11638abb7b446f1510458717
|
|
BLAKE2b-256 checksum How to use checksums |
838c14fc42625101abc87c67a5f6a8e69dc81790cb780c72afecb432f77a4e25
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.
Transparency log