pathlib_next
A robust, extensible pathlib-like base for any resource addressable as a
path or URI. Same method names, signatures, semantics, and exception types as
pathlib.Path wherever a pathlib.Path equivalent exists -- write code
against Path/UriPath once, and it works against your local disk, an
in-memory tree, an HTTP index, or an SFTP server.
Every intentional divergence from pathlib's behavior is documented, not
silent -- see Divergences from pathlib.
Installation
pip install pathlib_next
| Extra | Adds | Needed for |
|---|---|---|
uri |
uritools |
Uri/UriPath parsing (any URI scheme) |
http |
requests |
http(s):// and dav(s):// (WebDAV) paths |
sftp |
paramiko |
sftp:// paths (sync backend) |
sftp-async |
asyncssh |
sftp:// paths via the asyncssh backend instead |
s3 |
boto3 |
s3://bucket/key paths |
import pathlib_next and pathlib_next.LocalPath/MemPath work with no
extras installed; data:, ftp(s):, and zip:/tar: archive paths only
need the uri extra (they're stdlib-based otherwise).
30-second tour
Local filesystem -- drop-in pathlib.Path:
from pathlib_next import Path
p = Path("./data") / "report.txt"
p.write_text("hello")
print(p.read_text())
In-memory -- a virtual filesystem for tests/mocks, no disk I/O:
from pathlib_next.mempath import MemPath
p = MemPath("/config/settings.json")
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text('{"debug": true}')
HTTP -- read files and list Apache/nginx-style directory indexes:
from pathlib_next.uri import UriPath
p = UriPath("http://example.com/data/")
for child in p.iterdir():
if child.is_file():
print(child.name, child.stat().st_size)
SFTP -- same interface, over SSH:
from pathlib_next.uri import UriPath
p = UriPath("sftp://user@host/var/log/app.log")
print(p.read_text())
Archives -- a member inside a zip/tar, itself addressed by any URI:
from pathlib_next.uri import UriPath
member = UriPath("zip:file:./backup.zip!/etc/config.ini")
print(member.read_text())
Also built in: data: (RFC 2397 inline payloads), ftp(s): (stdlib
ftplib), dav(s): (WebDAV, full read/write), and s3: (boto3).
All of these are the same Path contract -- exists(), is_dir(),
iterdir(), glob(), read_text()/write_text(), copy()/move(),
rm(), all behave the same way regardless of backend (capability
differences, e.g. http: being read-only, are listed in
Schemes).
Where to go next
- Divergences from pathlib -- every deliberate
behavioral difference from
pathlib.Path, with rationale. - Schemes -- capability matrix (read/write/list/ stat/mkdir/delete/rename) per scheme.
- Extending -- add your own path type, two ways:
subclass
Pathdirectly, or subclassUriPathfor a new URI scheme. - API Reference -- generated from docstrings.
- Changelog.