Repository navigation
Releases: jose-pr/sftppath
Release list
v0.1.3
Added
AsyncSSHBackend.over_connection(connection, loop, *, host=None, max_concurrency=None, sftp_version=4, timeout=60.0)builds a backend
that runs SFTP over anasyncssh.SSHClientConnectionyour program already
opened and authenticated, on the event loop that connection is bound to,
instead of connecting and logging in a second time. Paths and thesftp:
scheme work on it unchanged. The connection stays yours:close()closes
only the backend's SFTP channel, and once the connection is closed every
request raisesConnectionResetError. Keeplooprunning while the
backend is used (a request on a stopped loop raisesRuntimeError), and
build a new backend afterfork(). Such a backend cannot be pickled.
Full Changelog: v0.1.2...v0.1.3
v0.1.2
Changed
sftppathrequirespathapi>=0.1.2,<0.2(it allowed>=0.1.0): 0.1.2
providesAsyncPath, whichAsyncSFTPPathbuilds on. Upgradingsftppathupgrades
pathapiwith it.
Added
AsyncSFTPPath, apathapi.AsyncPathfor an SFTP server whose requests are
made on the caller's event loop with asyncssh, not on a worker thread:stat(),
lstat(),exists(),is_dir(),is_file(),iterdir(),walk(),open(),
read_*(),write_*(),mkdir(),unlink(),rmdir(),rename(), and the
recursivecopy()andrm()of a directory on one server. The other methods,
glob()among them, run on worker threads asAsyncPathruns them. It is
built likeSFTPPathor from one, opens its connection on first use, and
closes it onaclose()orasync with. It needs theasyncsshextra and a
pathapithat providesAsyncPath(pathapi>=0.1.2); without them
import sftppathstill works and naming the class raises anImportError
that says what is missing.rm()andcopy()takemax_workers, the keyword ofpathapi's recursive
rm()andcopy()(a class runs serially unless it declares_threadsafe,
which these classes do not). The generic walks pass it on; the asyncssh native
walks ignore it and stay bounded bymax_concurrency. Nothing changes for a
call that does not give it, and it works with thepathapirelease that
lacks it as long as it is not given.
Full Changelog: v0.1.1...v0.1.2
v0.1.1
Changed
- Reading a directory as a file (
read_bytes(),read_text(), a read of
open("rb")) raisesIsADirectoryError(EISDIR, with the remote path as
filename) against servers that open a directory for reading, as OpenSSH
does, on both backends. Against OpenSSH for Windows an unsized read returned
b""(""in text mode); against OpenSSH on Linux, and for a sized read on
Windows, it raised anOSError("Failure")with noerrno.open()itself
still succeeds on those servers. Code that caught the bareOSErrorstill
catches it; code that read a directory and got empty content now gets the
error.
Full Changelog: v0.1.0...v0.1.1
v0.1.0
The first release of sftppath: the SFTP support of pathlib-next 0.9.14
(pathlib_next.uri.schemes.sftp) as a distribution of its own, with a path that
needs no URI. It needs Python 3.9 or newer and pathapi>=0.1.0,<0.2.
Neither SSH library is required to import it: the extras paramiko
(paramiko>=5.0,<6) and asyncssh (asyncssh>=2.20.0, below 3) add one, and
uri (pathapi-uri>=0.1.0,<0.2) adds the sftp: scheme. With neither SSH library a
path can still be built, joined and compared, and its first request raises an
ImportError that names both extras; naming SFTPBackend or AsyncSSHBackend
without its library raises one that names its extra. Under Changed, the
migration from pathlib_next.uri.schemes.sftp comes in this order: the table of
names, the table of extras, then every change of behaviour with what to do about
it.
It is built on pathapi, which was published as pathlib-next up to 0.10.0 (import
name pathlib_next); the old names below are the ones before the move.
Added
SFTPPath, apathapi.Pathfor a directory tree on an SFTP server, built
from keywords:SFTPPath("/srv/x", host="h", port=2222, user="u", password="p").
Nothing connects until the first request.backend=shares one connection
between paths built separately; a path joined from another keeps its backend.SFTPBackend(paramiko),AsyncSSHBackend(asyncssh),BaseSFTPBackendand
CheckFileSFTPBackend, each the connections to one server and account. Every
backend is a context manager,close()returns when the connections are
closed, and may be called twice.SFTPEndpoint,DEFAULT_PORTand
DEFAULT_SSH_CONFIGare exported too.sftppath.exceptions:SFTPPathError, apathapi.PathError, with
SFTPAuthenticationError(alsoPermissionError) andSFTPHostKeyError
(alsoConnectionError).sftppath.uri:SFTPURIPath, thesftp:scheme ofuripath, found by
uripaththrough the entry pointsftpof the groupuripath.schemes, and
SFTPURIBackend, which builds the backend of each server a URI names. Importing
sftppath.uriwithouturipathraises anImportErrorthat names
pip install "sftppath[uri]";import sftppathnever importsuripath.SFTPPath.is_local(): true for a loopback address,localhostand a backend
with no host, soPathSyncer(quick_check=True)applies to a real server.sftppath.__version__, read from the installed metadata.
Changed
-
The names.
pathlib_next.uri.schemes.sftpis gone with no alias.Was Now SftpPath(aUriPath)sftppath.SFTPPathfor a path built from keywords;sftppath.uri.SFTPURIPathforURIPath("sftp://...")SftpBackendsftppath.SFTPBackendAsyncsshSftpBackendsftppath.AsyncSSHBackendBaseSftpBackendsftppath.BaseSFTPBackendCheckFileSftpBackendsftppath.CheckFileSFTPBackendSftpAuthenticationError,SftpHostKeyErrorsftppath.SFTPAuthenticationError,sftppath.SFTPHostKeyError(insftppath.exceptions)_DEFAULT_SSH_CONFIGsftppath.DEFAULT_SSH_CONFIGPATHLIB_NEXT_SFTP_BACKENDSFTPPATH_BACKEND; the old variable is not readthe logger pathlib_next.sftpthe logger sftppaththe entry-point group pathlib_next.schemes, entrysftpthe group uripath.schemes, entrysftp = "sftppath.uri:SFTPURIPath" -
What to install where
pathlib-nexthad an extra.pathlib-next0.10 has no
sftporsftp-asyncextra.Was Install now pathlib-next[sftp]sftppath[paramiko]pathlib-next[sftp-async]sftppath[asyncssh]either, for UriPath("sftp://...")add sftppath[uri](or installuripathbeside it) -
A backend is the connections to one server and account. Was: one backend
served every host a path named, andclient(source),opts(source)and
transport(source)took theSourceof the URI; a backend was built with its
options only (SftpBackend(connect_opts, hostkeypolicy, ...)). Now the host,
port, user and password are arguments of the backend
(SFTPBackend("h", 2222, user="u", password="p", connect_opts=...),
AsyncSSHBackend("h", ...)), andclient(),opts()andtransport()take
nothing. ABaseSFTPBackendsubclass overridesclient(self). For URI paths,
givebackend=anSFTPURIBackend(SFTPBackend, connect_opts=...)(the
options of the backend class; the user, password and port come from the URI)
or aBaseSFTPBackendfor the one server.BaseSftpBackend.default()and the
default(ssh_config=)classmethods are removed. -
A relative or empty path is read from the server root. Was:
sftp://host(no
path) listed the home directory of the account. Now it is/, and
SFTPPath("x", host=h)is/x. Name the directory you mean
(/home/user). -
SFTPPath.readlink()returns a path on the same backend, so dot segments of
the target collapse as they do forpathlib. TheSFTPURIPathkeeps the text
verbatim in.path. -
SFTPPath.iterdir()yields children without the attributes the listing
carried, sois_dir()on each costs a request;walk(),glob()and
rm(recursive=True)still use the listing. The children anSFTPURIPath
yields carry them, as before. -
An error that has a file name and no second one prints only the first; it
printed-> Noneafter it.
Full Changelog: https://github.com/jose-pr/sftppath/commits/v0.1.0