pysftp-ng 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .eggs/
5
+ build/
6
+ dist/
7
+ .venv/
8
+ venv/
9
+ .nox/
10
+ # A library: CI tests dependency ranges, so no lock file is kept
11
+ uv.lock
12
+ .pytest_cache/
13
+ .ruff_cache/
14
+ .mypy_cache/
15
+ .coverage
16
+ .coverage.*
17
+ coverage.xml
18
+ htmlcov/
19
+ .DS_Store
20
+ .idea/
21
+ .vscode/
@@ -0,0 +1,63 @@
1
+ # Changelog
2
+
3
+ All notable changes are listed here. pysftp-ng follows [Semantic Versioning](https://semver.org/).
4
+ Until 1.0, minor releases may deprecate things but won't remove anything from the pysftp 0.2.9
5
+ API.
6
+
7
+ ## 0.3.0 (unreleased)
8
+
9
+ First release of pysftp-ng, forked from pysftp 0.2.9 (released 2016-07-04).
10
+
11
+ ### Fixed
12
+
13
+ - `import pysftp` no longer fails on paramiko 4.0 and later, which removed `DSSKey`.
14
+ - Ed25519 and ECDSA private key files now load, encrypted or not, in OpenSSH or PEM format.
15
+ Any `paramiko.PKey` object, not only `RSAKey` or `AgentKey`, can be passed as `private_key`.
16
+ - With no password or key given, the default keys `~/.ssh/id_rsa`, `id_ecdsa` and `id_ed25519`
17
+ (and `id_dsa` on paramiko < 4) are each tried, and the first one the server accepts is used.
18
+ - known_hosts entries in OpenSSH's `[host]:port` form, plain or hashed, are now found for servers
19
+ on non-standard ports. Bare hostname entries still work.
20
+ - Host key verification now negotiates only key types listed in known_hosts and accepts any
21
+ matching key, instead of pinning the first key found. This fixes "Incompatible ssh peer
22
+ (no acceptable host key)" when a retired key type or an old `ssh-dss` line came first.
23
+ - A connection that fails part-way no longer raises
24
+ `AttributeError: 'Connection' object has no attribute '_sftp_live'` from `__del__`, and its
25
+ transport is closed instead of left running.
26
+ - `close()` removes only the log handler the connection added and restores the logger's level.
27
+ It used to delete every handler on the `paramiko` logger.
28
+ - `put_r` and `put_d` join remote paths with `/` on every OS instead of `os.path.join`, which sent
29
+ backslashes from Windows. They no longer `chdir` the whole process.
30
+ - `get_r` builds local paths correctly on Windows, creates missing local directories, and
31
+ reports broken symlinks to the unknown-type callback instead of crashing.
32
+ - `walktree` uses one `listdir_attr` call per directory instead of a `stat` per entry.
33
+ - `get_r`, `get_d` and `walktree` skip, with a `RuntimeWarning`, file names from the server that
34
+ would escape the target directory (for example `../x`).
35
+ - `execute()` closes its channel.
36
+ - `makedirs` splits remote paths with `posixpath`.
37
+ - The missing-known_hosts warning reads "disable HostKey checking" (it said "disableHostKey").
38
+ - `path_advance` and `path_retreat` handle an empty path.
39
+
40
+ ### Added
41
+
42
+ - `CnOpts.timeout`: limit, in seconds, for the TCP connection, SSH banner, key exchange and
43
+ authentication.
44
+ - `CnOpts.get_hostkey(host, port=22)` takes an optional port.
45
+ - `BadHostKeyException` and `PasswordRequiredException` are re-exported from `pysftp`.
46
+ - Type hints and a `py.typed` marker.
47
+ - An in-process SFTP server and a test suite covering the API across Python and paramiko
48
+ versions.
49
+
50
+ ### Changed
51
+
52
+ - Requires Python 3.9+ and paramiko 3.4+. paramiko 3.4 is the first release with the fix for the
53
+ Terrapin attack (CVE-2023-48795).
54
+ - A server key that doesn't match known_hosts raises `paramiko.BadHostKeyException`. It is a
55
+ subclass of `SSHException`, so existing `except SSHException` blocks still catch it.
56
+ - Connection refused or unreachable still raises `SSHException("Unable to connect to ...")`, but
57
+ pysftp-ng now opens the socket itself, so a failed connect no longer leaks it.
58
+ - `str(ConnectionException)` is now the human-readable message. `.args` is unchanged.
59
+ - The deprecated `log` and `ciphers` arguments to `Connection` are no longer scheduled for removal
60
+ in 0.3.0. They will be removed no earlier than 1.0.
61
+ - If no username is given and `LOGNAME` isn't set, the current OS user is used (`getpass.getuser()`).
62
+
63
+ For changes before the fork, see the pysftp 0.2.9 changelog.
@@ -0,0 +1,70 @@
1
+ # Contributing
2
+
3
+ Thanks for helping. pysftp-ng exists so that code written against pysftp 0.2.9 keeps working, so
4
+ compatibility comes first.
5
+
6
+ ## Ground rules
7
+
8
+ - **Don't break the 0.2.9 API.** Keep public names, arguments, defaults and return values as they
9
+ are. New behaviour should be opt-in, normally through `CnOpts`.
10
+ - **Every bug fix comes with a test.** If the bug exists in pysftp 0.2.9, mark the test
11
+ `@pytest.mark.regression`.
12
+ - **Security-sensitive changes need extra care.** That covers host keys, authentication and path
13
+ handling. Explain the threat model in the pull request.
14
+ - **Small pull requests.** One fix or feature per pull request is much easier to review.
15
+ - **Understand what you submit.** Tools are fine, but you should be able to explain and defend
16
+ every line in review.
17
+
18
+ ## Development setup
19
+
20
+ You need Python 3.9 or newer. With [uv](https://docs.astral.sh/uv/):
21
+
22
+ ```bash
23
+ uv venv
24
+ uv pip install -e . --group dev
25
+ uv run pytest
26
+ ```
27
+
28
+ Or with pip:
29
+
30
+ ```bash
31
+ python -m venv .venv
32
+ source .venv/bin/activate # .venv\Scripts\activate on Windows
33
+ pip install -e . pytest pytest-cov ruff
34
+ pytest
35
+ ```
36
+
37
+ The tests start a small SFTP server inside the test process (`tests/sftp_server.py`), so you don't
38
+ need Docker or a real server.
39
+
40
+ To test against a specific paramiko version:
41
+
42
+ ```bash
43
+ uv run --with "paramiko==3.4.1" pytest
44
+ ```
45
+
46
+ Don't install the version with `uv pip install` first: `uv run` resets the environment to match
47
+ `uv.lock` before it starts, so the tests would run against the paramiko version in `uv.lock`
48
+ instead. The pytest header shows which paramiko version was used.
49
+
50
+ To run the full matrix (every supported Python with paramiko 3.4.1 and the newest release), plus
51
+ lint and a build check, use [nox](https://nox.thea.codes/). It downloads any Python you don't have:
52
+
53
+ ```bash
54
+ uvx nox # everything
55
+ uvx nox -s lint # one session; `uvx nox -l` lists them
56
+ ```
57
+
58
+ ## Style
59
+
60
+ [ruff](https://docs.astral.sh/ruff/) handles linting and formatting:
61
+
62
+ ```bash
63
+ ruff check .
64
+ ruff format .
65
+ ```
66
+
67
+ ## Releases
68
+
69
+ Maintainers cut releases from GitHub. The release workflow builds the package and publishes it to
70
+ PyPI through trusted publishing, so no API tokens are stored in the repository.
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2014, Dundee Media & Technology, Inc
4
+ Copyright (c) 2026, Abdul Hakim Aremeyaw and pysftp-ng contributors
5
+ All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without modification,
8
+ are permitted provided that the following conditions are met:
9
+
10
+ * Redistributions of source code must retain the above copyright notice,
11
+ this list of conditions and the following disclaimer.
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+ * Neither the name of the Dundee Media & Technology, Inc nor the names of
16
+ its contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,144 @@
1
+ Metadata-Version: 2.5
2
+ Name: pysftp-ng
3
+ Version: 0.3.0
4
+ Summary: A friendly face on SFTP. Maintained, drop-in fork of pysftp for paramiko 4/5 and current Python.
5
+ Project-URL: Homepage, https://github.com/Vitalik-Hakim/pysftp-ng
6
+ Project-URL: Source, https://github.com/Vitalik-Hakim/pysftp-ng
7
+ Project-URL: Issues, https://github.com/Vitalik-Hakim/pysftp-ng/issues
8
+ Project-URL: Changelog, https://github.com/Vitalik-Hakim/pysftp-ng/blob/main/CHANGELOG.md
9
+ Author: Jeff Hinrichs, Abdul Hakim Aremeyaw
10
+ Maintainer: Abdul Hakim Aremeyaw
11
+ License-Expression: BSD-3-Clause
12
+ License-File: LICENSE
13
+ Keywords: file transfer,ftp,paramiko,pysftp,sftp,ssh
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: System Administrators
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
26
+ Classifier: Programming Language :: Python :: Implementation :: CPython
27
+ Classifier: Topic :: Internet :: File Transfer Protocol (FTP)
28
+ Classifier: Topic :: System :: Networking
29
+ Classifier: Typing :: Typed
30
+ Requires-Python: >=3.9
31
+ Requires-Dist: paramiko>=3.4
32
+ Description-Content-Type: text/markdown
33
+
34
+ # pysftp-ng
35
+
36
+ [![CI](https://github.com/Vitalik-Hakim/pysftp-ng/actions/workflows/ci.yml/badge.svg)](https://github.com/Vitalik-Hakim/pysftp-ng/actions/workflows/ci.yml)
37
+ [![PyPI](https://img.shields.io/pypi/v/pysftp-ng.svg)](https://pypi.org/project/pysftp-ng/)
38
+ [![Python](https://img.shields.io/pypi/pyversions/pysftp-ng.svg)](https://pypi.org/project/pysftp-ng/)
39
+
40
+ A maintained, drop-in fork of [pysftp](https://pypi.org/project/pysftp/). Your code still says
41
+ `import pysftp` and uses the same API, but it now works with current paramiko (3.4 through 5.x)
42
+ and Python 3.9 through 3.14.
43
+
44
+ ## Why this exists
45
+
46
+ pysftp 0.2.9 came out in July 2016 and is still installed around 11.8 million times a month.
47
+ It no longer works with current dependencies. paramiko 4.0 removed DSA keys, so a fresh
48
+ `pip install pysftp` now fails the moment you import it:
49
+
50
+ ```
51
+ ImportError: cannot import name 'DSSKey' from 'paramiko'
52
+ ```
53
+
54
+ There has been no upstream release since 2016. pysftp-ng fixes that break and a set of
55
+ long-standing bugs, and keeps the API stable so existing code keeps running.
56
+
57
+ ## Switching over
58
+
59
+ ```bash
60
+ pip uninstall -y pysftp
61
+ pip install pysftp-ng
62
+ ```
63
+
64
+ No code changes are needed. In `requirements.txt` or `pyproject.toml`, replace `pysftp` with
65
+ `pysftp-ng`. Don't install both packages, because they provide the same `pysftp` module.
66
+
67
+ ## Usage
68
+
69
+ ```python
70
+ import pysftp
71
+
72
+ with pysftp.Connection("sftp.example.com", username="me", private_key="~/.ssh/id_ed25519") as sftp:
73
+ sftp.put("report.csv", "/upload/report.csv")
74
+ with sftp.cd("/download"):
75
+ sftp.get_r(".", "local-copy")
76
+ ```
77
+
78
+ Extra connection options go on a `CnOpts` object:
79
+
80
+ ```python
81
+ cnopts = pysftp.CnOpts() # loads ~/.ssh/known_hosts
82
+ cnopts.timeout = 10 # new: limit for connecting, the handshake and logging in
83
+
84
+ with pysftp.Connection(
85
+ "sftp.example.com", port=2222, username="me", password="...", cnopts=cnopts
86
+ ) as sftp:
87
+ print(sftp.listdir())
88
+ ```
89
+
90
+ ## What's fixed compared with pysftp 0.2.9
91
+
92
+ Each item below has a test in `tests/`. Tests marked `regression` reproduce bugs in pysftp 0.2.9.
93
+
94
+ - **paramiko 4 and 5.** Imports and runs without DSA. On paramiko < 4, DSA keys still work.
95
+ - **Modern keys.** Ed25519 and ECDSA key files work, encrypted or not, in OpenSSH or PEM format.
96
+ You can also pass any paramiko key object, such as `Ed25519Key` or `AgentKey`, as `private_key`.
97
+ - **Default keys.** With no password or key given, pysftp-ng tries `~/.ssh/id_rsa`, `id_ecdsa` and
98
+ `id_ed25519` in OpenSSH's order and uses the first one the server accepts. 0.2.9 only looked
99
+ for `id_rsa` and `id_dsa`.
100
+ - **known_hosts on non-standard ports.** OpenSSH stores these as `[host]:port`, including in hashed
101
+ form. pysftp-ng finds them; 0.2.9 failed with "No hostkey for host ... found".
102
+ - **Hosts with several known keys.** pysftp-ng only negotiates key types that are in known_hosts
103
+ and accepts any key that matches. 0.2.9 pinned whichever key was listed first. If the server had
104
+ retired that key type, or the first line was an old `ssh-dss` key, the connection failed with
105
+ "Incompatible ssh peer".
106
+ - **Cleaner failures.** No more `AttributeError: 'Connection' object has no attribute '_sftp_live'`
107
+ hiding the real error. A failed connection closes its transport.
108
+ - **Logging.** `close()` removes only the log handler it added. 0.2.9 removed every handler on the
109
+ `paramiko` logger, including your application's.
110
+ - **Windows paths.** `put_r` and `put_d` build remote paths with `/` on every OS (0.2.9 sent
111
+ backslashes from Windows), and they no longer change the process's working directory.
112
+ - **`get_r`.** Works on Windows clients, creates missing local directories, and no longer crashes
113
+ on a broken symlink.
114
+ - **Speed.** `walktree` sends one listing request per directory instead of one `stat` per entry.
115
+ - **Path traversal.** If a server returns a file name that would land outside the target
116
+ directory, such as `../../.bashrc`, `get_r`, `get_d` and `walktree` skip it with a warning.
117
+ - **Smaller fixes.** New `CnOpts.timeout` option. The username falls back to the OS user when
118
+ `LOGNAME` isn't set, as on Windows. `ConnectionException` has a readable message.
119
+
120
+ ## Compatibility
121
+
122
+ - The public API of pysftp 0.2.9 is kept: same names, arguments and return values. The deprecated
123
+ `log` and `ciphers` arguments still work and emit a `DeprecationWarning`.
124
+ - Behaviour changes are limited to the fixes above. The [changelog](CHANGELOG.md) lists every one.
125
+ - The test suite runs against Python 3.9–3.14 and paramiko 3.4, 3.5, 4.0 and 5.1. It uses an
126
+ in-process SFTP server, so no external server is needed.
127
+
128
+ ## Security
129
+
130
+ Host key checking is on by default and verifies the server before any password or key is sent.
131
+ Setting `cnopts.hostkeys = None` turns verification off and exposes you to man-in-the-middle
132
+ attacks, so don't do it outside a test environment.
133
+
134
+ To report a vulnerability, see [SECURITY.md](SECURITY.md).
135
+
136
+ ## Credits
137
+
138
+ pysftp was written by Jeff Hinrichs (Dundee Media & Technology), with contributions from Don
139
+ Reilly, James Kruth and Nick Robinson-Wall. pysftp-ng is forked from the 0.2.9 release and keeps
140
+ its BSD 3-Clause license.
141
+
142
+ ## Contributing
143
+
144
+ Bug reports and pull requests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).
@@ -0,0 +1,111 @@
1
+ # pysftp-ng
2
+
3
+ [![CI](https://github.com/Vitalik-Hakim/pysftp-ng/actions/workflows/ci.yml/badge.svg)](https://github.com/Vitalik-Hakim/pysftp-ng/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/pysftp-ng.svg)](https://pypi.org/project/pysftp-ng/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/pysftp-ng.svg)](https://pypi.org/project/pysftp-ng/)
6
+
7
+ A maintained, drop-in fork of [pysftp](https://pypi.org/project/pysftp/). Your code still says
8
+ `import pysftp` and uses the same API, but it now works with current paramiko (3.4 through 5.x)
9
+ and Python 3.9 through 3.14.
10
+
11
+ ## Why this exists
12
+
13
+ pysftp 0.2.9 came out in July 2016 and is still installed around 11.8 million times a month.
14
+ It no longer works with current dependencies. paramiko 4.0 removed DSA keys, so a fresh
15
+ `pip install pysftp` now fails the moment you import it:
16
+
17
+ ```
18
+ ImportError: cannot import name 'DSSKey' from 'paramiko'
19
+ ```
20
+
21
+ There has been no upstream release since 2016. pysftp-ng fixes that break and a set of
22
+ long-standing bugs, and keeps the API stable so existing code keeps running.
23
+
24
+ ## Switching over
25
+
26
+ ```bash
27
+ pip uninstall -y pysftp
28
+ pip install pysftp-ng
29
+ ```
30
+
31
+ No code changes are needed. In `requirements.txt` or `pyproject.toml`, replace `pysftp` with
32
+ `pysftp-ng`. Don't install both packages, because they provide the same `pysftp` module.
33
+
34
+ ## Usage
35
+
36
+ ```python
37
+ import pysftp
38
+
39
+ with pysftp.Connection("sftp.example.com", username="me", private_key="~/.ssh/id_ed25519") as sftp:
40
+ sftp.put("report.csv", "/upload/report.csv")
41
+ with sftp.cd("/download"):
42
+ sftp.get_r(".", "local-copy")
43
+ ```
44
+
45
+ Extra connection options go on a `CnOpts` object:
46
+
47
+ ```python
48
+ cnopts = pysftp.CnOpts() # loads ~/.ssh/known_hosts
49
+ cnopts.timeout = 10 # new: limit for connecting, the handshake and logging in
50
+
51
+ with pysftp.Connection(
52
+ "sftp.example.com", port=2222, username="me", password="...", cnopts=cnopts
53
+ ) as sftp:
54
+ print(sftp.listdir())
55
+ ```
56
+
57
+ ## What's fixed compared with pysftp 0.2.9
58
+
59
+ Each item below has a test in `tests/`. Tests marked `regression` reproduce bugs in pysftp 0.2.9.
60
+
61
+ - **paramiko 4 and 5.** Imports and runs without DSA. On paramiko < 4, DSA keys still work.
62
+ - **Modern keys.** Ed25519 and ECDSA key files work, encrypted or not, in OpenSSH or PEM format.
63
+ You can also pass any paramiko key object, such as `Ed25519Key` or `AgentKey`, as `private_key`.
64
+ - **Default keys.** With no password or key given, pysftp-ng tries `~/.ssh/id_rsa`, `id_ecdsa` and
65
+ `id_ed25519` in OpenSSH's order and uses the first one the server accepts. 0.2.9 only looked
66
+ for `id_rsa` and `id_dsa`.
67
+ - **known_hosts on non-standard ports.** OpenSSH stores these as `[host]:port`, including in hashed
68
+ form. pysftp-ng finds them; 0.2.9 failed with "No hostkey for host ... found".
69
+ - **Hosts with several known keys.** pysftp-ng only negotiates key types that are in known_hosts
70
+ and accepts any key that matches. 0.2.9 pinned whichever key was listed first. If the server had
71
+ retired that key type, or the first line was an old `ssh-dss` key, the connection failed with
72
+ "Incompatible ssh peer".
73
+ - **Cleaner failures.** No more `AttributeError: 'Connection' object has no attribute '_sftp_live'`
74
+ hiding the real error. A failed connection closes its transport.
75
+ - **Logging.** `close()` removes only the log handler it added. 0.2.9 removed every handler on the
76
+ `paramiko` logger, including your application's.
77
+ - **Windows paths.** `put_r` and `put_d` build remote paths with `/` on every OS (0.2.9 sent
78
+ backslashes from Windows), and they no longer change the process's working directory.
79
+ - **`get_r`.** Works on Windows clients, creates missing local directories, and no longer crashes
80
+ on a broken symlink.
81
+ - **Speed.** `walktree` sends one listing request per directory instead of one `stat` per entry.
82
+ - **Path traversal.** If a server returns a file name that would land outside the target
83
+ directory, such as `../../.bashrc`, `get_r`, `get_d` and `walktree` skip it with a warning.
84
+ - **Smaller fixes.** New `CnOpts.timeout` option. The username falls back to the OS user when
85
+ `LOGNAME` isn't set, as on Windows. `ConnectionException` has a readable message.
86
+
87
+ ## Compatibility
88
+
89
+ - The public API of pysftp 0.2.9 is kept: same names, arguments and return values. The deprecated
90
+ `log` and `ciphers` arguments still work and emit a `DeprecationWarning`.
91
+ - Behaviour changes are limited to the fixes above. The [changelog](CHANGELOG.md) lists every one.
92
+ - The test suite runs against Python 3.9–3.14 and paramiko 3.4, 3.5, 4.0 and 5.1. It uses an
93
+ in-process SFTP server, so no external server is needed.
94
+
95
+ ## Security
96
+
97
+ Host key checking is on by default and verifies the server before any password or key is sent.
98
+ Setting `cnopts.hostkeys = None` turns verification off and exposes you to man-in-the-middle
99
+ attacks, so don't do it outside a test environment.
100
+
101
+ To report a vulnerability, see [SECURITY.md](SECURITY.md).
102
+
103
+ ## Credits
104
+
105
+ pysftp was written by Jeff Hinrichs (Dundee Media & Technology), with contributions from Don
106
+ Reilly, James Kruth and Nick Robinson-Wall. pysftp-ng is forked from the 0.2.9 release and keeps
107
+ its BSD 3-Clause license.
108
+
109
+ ## Contributing
110
+
111
+ Bug reports and pull requests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).
@@ -0,0 +1,26 @@
1
+ # Security policy
2
+
3
+ ## Supported versions
4
+
5
+ Security fixes go into the latest release. pysftp-ng is a drop-in replacement for pysftp 0.2.9,
6
+ which gets no further fixes, so upgrading to pysftp-ng is the fix for issues in the original.
7
+
8
+ ## Reporting a vulnerability
9
+
10
+ Please don't open a public issue for security problems. Report them privately through GitHub:
11
+ open the repository's **Security** tab and choose **Report a vulnerability**.
12
+
13
+ Include what you found, how to reproduce it, and which versions of pysftp-ng, paramiko and
14
+ Python you used. You'll get an acknowledgement within 72 hours and a plan for a fix within a
15
+ week. You'll be credited in the release notes unless you'd rather not be.
16
+
17
+ ## What counts
18
+
19
+ Anything that weakens what pysftp-ng promises is in scope. Examples:
20
+
21
+ - host key verification being skipped or bypassed
22
+ - credentials being sent before the server is verified
23
+ - files written outside the directory a transfer was aimed at
24
+ - private key material leaking into logs or exceptions
25
+
26
+ Bugs in paramiko itself should go to the [paramiko project](https://github.com/paramiko/paramiko).
@@ -0,0 +1,100 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.26"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "pysftp-ng"
7
+ dynamic = ["version"]
8
+ description = "A friendly face on SFTP. Maintained, drop-in fork of pysftp for paramiko 4/5 and current Python."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "BSD-3-Clause"
12
+ license-files = ["LICENSE"]
13
+ authors = [
14
+ { name = "Jeff Hinrichs" },
15
+ { name = "Abdul Hakim Aremeyaw" },
16
+ ]
17
+ maintainers = [{ name = "Abdul Hakim Aremeyaw" }]
18
+ keywords = ["sftp", "ssh", "ftp", "paramiko", "pysftp", "file transfer"]
19
+ classifiers = [
20
+ "Development Status :: 4 - Beta",
21
+ "Intended Audience :: Developers",
22
+ "Intended Audience :: System Administrators",
23
+ "Operating System :: OS Independent",
24
+ "Programming Language :: Python :: 3",
25
+ "Programming Language :: Python :: 3 :: Only",
26
+ "Programming Language :: Python :: 3.9",
27
+ "Programming Language :: Python :: 3.10",
28
+ "Programming Language :: Python :: 3.11",
29
+ "Programming Language :: Python :: 3.12",
30
+ "Programming Language :: Python :: 3.13",
31
+ "Programming Language :: Python :: 3.14",
32
+ "Programming Language :: Python :: Implementation :: CPython",
33
+ "Topic :: Internet :: File Transfer Protocol (FTP)",
34
+ "Topic :: System :: Networking",
35
+ "Typing :: Typed",
36
+ ]
37
+ dependencies = ["paramiko>=3.4"]
38
+
39
+ [project.urls]
40
+ Homepage = "https://github.com/Vitalik-Hakim/pysftp-ng"
41
+ Source = "https://github.com/Vitalik-Hakim/pysftp-ng"
42
+ Issues = "https://github.com/Vitalik-Hakim/pysftp-ng/issues"
43
+ Changelog = "https://github.com/Vitalik-Hakim/pysftp-ng/blob/main/CHANGELOG.md"
44
+
45
+ [dependency-groups]
46
+ dev = [
47
+ "pytest>=8",
48
+ "pytest-cov>=5",
49
+ "ruff>=0.8",
50
+ ]
51
+
52
+ [tool.hatch.version]
53
+ path = "src/pysftp/__init__.py"
54
+
55
+ [tool.hatch.build.targets.wheel]
56
+ packages = ["src/pysftp"]
57
+
58
+ [tool.hatch.build.targets.sdist]
59
+ include = [
60
+ "src/pysftp",
61
+ "tests",
62
+ "README.md",
63
+ "CHANGELOG.md",
64
+ "LICENSE",
65
+ "SECURITY.md",
66
+ "CONTRIBUTING.md",
67
+ ]
68
+
69
+ [tool.pytest.ini_options]
70
+ testpaths = ["tests"]
71
+ addopts = ["-ra", "--strict-markers"]
72
+ markers = [
73
+ "regression: reproduces a bug present in pysftp 0.2.9",
74
+ ]
75
+ filterwarnings = [
76
+ "error",
77
+ # paramiko itself still imports ciphers that cryptography has deprecated
78
+ "ignore::DeprecationWarning:paramiko.*",
79
+ "ignore:.*TripleDES.*",
80
+ "ignore:.*Blowfish.*",
81
+ ]
82
+
83
+ [tool.coverage.run]
84
+ source = ["pysftp"]
85
+ branch = true
86
+
87
+ [tool.ruff]
88
+ line-length = 100
89
+ target-version = "py39"
90
+ src = ["src", "tests"]
91
+
92
+ [tool.ruff.lint]
93
+ select = ["E", "F", "W", "I", "B", "UP", "S", "PT", "RUF"]
94
+ ignore = [
95
+ "UP007", # keep Union[...] spelling where it is evaluated at runtime on 3.9
96
+ "RUF022", # __all__ is grouped by hand
97
+ ]
98
+
99
+ [tool.ruff.lint.per-file-ignores]
100
+ "tests/**" = ["S101", "S105", "S106", "S107", "S108", "S505", "S603", "S607"]