sftp-helper 2.2.3__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,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, Warith HARCHAOUI
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. 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
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,258 @@
1
+ Metadata-Version: 2.4
2
+ Name: sftp-helper
3
+ Version: 2.2.3
4
+ Summary: SFTP Helper โ€” utility functions for working with SFTP servers via paramiko, exposed as library, argparse CLI, click CLI, FastAPI HTTP surface and MCP tools. Strict host-key verification, credentials loader, upload / download / list / remove / exists / remote_tempfile context manager.
5
+ Author-email: Warith HARCHAOUI <warithmetics@deraison.ai>
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/warith-harchaoui/sftp-helper
8
+ Project-URL: Issues, https://github.com/warith-harchaoui/sftp-helper/issues
9
+ Keywords: sftp,paramiko,ssh,file-transfer,secure
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: BSD License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Internet :: File Transfer Protocol (FTP)
20
+ Classifier: Topic :: System :: Networking
21
+ Requires-Python: <3.14,>=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: os-helper>=1.5.0
25
+ Requires-Dist: paramiko<4,>=3.0
26
+ Provides-Extra: cli
27
+ Requires-Dist: click<9,>=8.1; extra == "cli"
28
+ Provides-Extra: api
29
+ Requires-Dist: fastapi<1,>=0.111; extra == "api"
30
+ Requires-Dist: uvicorn<1,>=0.30; extra == "api"
31
+ Requires-Dist: python-multipart<1,>=0.0.9; extra == "api"
32
+ Provides-Extra: mcp
33
+ Requires-Dist: fastapi-mcp<1,>=0.3; extra == "mcp"
34
+ Requires-Dist: fastapi<1,>=0.111; extra == "mcp"
35
+ Requires-Dist: uvicorn<1,>=0.30; extra == "mcp"
36
+ Requires-Dist: python-multipart<1,>=0.0.9; extra == "mcp"
37
+ Provides-Extra: dev
38
+ Requires-Dist: pytest>=8; extra == "dev"
39
+ Requires-Dist: pyyaml>=6; extra == "dev"
40
+ Requires-Dist: httpx>=0.27; extra == "dev"
41
+ Requires-Dist: click<9,>=8.1; extra == "dev"
42
+ Requires-Dist: fastapi<1,>=0.111; extra == "dev"
43
+ Requires-Dist: python-multipart<1,>=0.0.9; extra == "dev"
44
+ Requires-Dist: fastapi-mcp<1,>=0.3; extra == "dev"
45
+ Dynamic: license-file
46
+
47
+ # SFTP Helper
48
+
49
+ [๐Ÿ‡ซ๐Ÿ‡ท](https://github.com/warith-harchaoui/sftp-helper/blob/main/LISEZMOI.md) ยท [๐Ÿ‡ฌ๐Ÿ‡ง](https://github.com/warith-harchaoui/sftp-helper/blob/main/README.md)
50
+
51
+ [![CI](https://github.com/warith-harchaoui/sftp-helper/actions/workflows/ci.yml/badge.svg)](https://github.com/warith-harchaoui/sftp-helper/actions/workflows/ci.yml) [![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](LICENSE) [![Python](https://img.shields.io/badge/python-3.10%E2%80%933.13-blue.svg)](#)
52
+
53
+ `SFTP Helper` belongs to a collection of libraries called `AI Helpers` developped for building Artificial Intelligence
54
+
55
+ This toolbox requires:
56
+ - a `config.json` for the sftp parameters (or YAML or environment variables or .env)
57
+ - that you previously added you SSH key of your local machine in the SFTP server
58
+
59
+ [๐ŸŒ AI Helpers](https://harchaoui.org/warith/ai-helpers)
60
+
61
+ [![logo](https://raw.githubusercontent.com/warith-harchaoui/sftp-helper/main/assets/logo.png)](https://harchaoui.org/warith/ai-helpers)
62
+
63
+ SFTP Helper is a Python library that provides utility functions for working with SFTP servers via [paramiko](https://www.paramiko.org/). Host key verification is on by default โ€” `~/.ssh/known_hosts` is loaded and unknown hosts are rejected.
64
+
65
+ # Installation
66
+
67
+ **Prerequisites** โ€” **Python 3.10โ€“3.13** and **git**, cross-platform:
68
+
69
+ - ๐ŸŽ **macOS** ([Homebrew](https://brew.sh)): `brew install python git`
70
+ - ๐Ÿง **Ubuntu/Debian**: `sudo apt update && sudo apt install -y python3 python3-pip git`
71
+ - ๐ŸชŸ **Windows** (PowerShell): `winget install Python.Python.3.12 Git.Git`
72
+
73
+ Then install the package:
74
+
75
+
76
+ ## Install Package
77
+
78
+ We can recommand python environments. Check this link if you don't know how
79
+
80
+ [๐Ÿฅธ Tech tips](https://harchaoui.org/warith/4ml/#install)
81
+
82
+ ```bash
83
+ pip install --force-reinstall --no-cache-dir git+https://github.com/warith-harchaoui/sftp-helper.git@v2.2.2
84
+ ```
85
+
86
+ Or, from a checkout:
87
+
88
+ ```bash
89
+ pip install -r requirements.txt
90
+ pip install -e .
91
+ ```
92
+
93
+ ## Write your own configuration file
94
+
95
+ A ready-to-fill template is committed at [`sftp_config.json.example`](https://github.com/warith-harchaoui/sftp-helper/blob/main/sftp_config.json.example). A heavily-commented YAML variant is also provided at [`sftp_config.yaml.example`](https://github.com/warith-harchaoui/sftp-helper/blob/main/sftp_config.yaml.example) โ€” YAML supports inline comments explaining every key and how to obtain its value. Copy either one and edit in place โ€” real `*config.json` / `*config.yaml` files are gitignored so you cannot accidentally commit secrets:
96
+
97
+ ```bash
98
+ cp sftp_config.json.example sftp_config.json
99
+ # then edit sftp_config.json with your credentials
100
+ ```
101
+
102
+ You may also provide a YAML version (`sftp_config.yaml`), environment variables, or an `.env` file โ€” `sftp-helper` falls back in that order via `os_helper.get_config`:
103
+
104
+ _JSON_
105
+ ```json
106
+ {
107
+ "sftp_host": "<sftp_host>",
108
+ "sftp_login": "<sftp_login>",
109
+ "sftp_passwd": "<sftp_passwd>",
110
+ "sftp_https": "<sftp_https>",
111
+ "sftp_destination_path": "<sftp_destination_path>",
112
+ }
113
+ ```
114
+ or
115
+
116
+ _YAML_
117
+ ```yaml
118
+ sftp_host: "<sftp_host>"
119
+ sftp_login: "<sftp_login>"
120
+ sftp_passwd: "<sftp_passwd>"
121
+ sftp_https: "<sftp_https>"
122
+ sftp_destination_path: "<sftp_destination_path>"
123
+ ```
124
+ or
125
+
126
+ _ENVIRONMENT VARIABLES_
127
+ ```bash
128
+ SFTP_HOST="<sftp_host>" \
129
+ SFTP_LOGIN="<sftp_login>" \
130
+ SFTP_PASSWD="<sftp_passwd>" \
131
+ SFTP_HTTPS="<sftp_https>" \
132
+ SFTP_DESTINATION_PATH="<sftp_destination_path>" \
133
+ python <your_python_script>
134
+ ```
135
+ or
136
+
137
+ _.env_
138
+ ```
139
+ SFTP_HOST = <sftp_host>
140
+ SFTP_LOGIN = <sftp_login>
141
+ SFTP_PASSWD = <sftp_passwd>
142
+ SFTP_HTTPS = <sftp_https>
143
+ SFTP_DESTINATION_PATH = <sftp_destination_path>
144
+ ```
145
+
146
+ In which you can find these information in your favorite FTP tool (mine is FileZilla):
147
+ + `<sftp_host>` is the server path `sftp.` ...
148
+ + `<sftp_login>` and `<sftp_passwd>` that you use in FileZilla
149
+ + `<sftp_destination_path>` is the remote folder path
150
+ + `<sftp_https>` corresponds to the web URL of `<sftp_destination_path>`
151
+ + <your_python_script> is your python script :)
152
+
153
+ ## Usage
154
+
155
+ For the full catalog of recipes (uploads, downloads, existence checks, recursive directory creation, temporary remote files with auto-cleanup, strict host-key verification), see [๐Ÿ“‹ EXAMPLES.md](https://github.com/warith-harchaoui/sftp-helper/blob/main/EXAMPLES.md).
156
+
157
+ Here's an example of how to use SFTP helper (**won't work without a valid `path/to/sftp_config.json`**):
158
+
159
+ ```python
160
+ import sftp_helper as sftph
161
+ import os_helper as osh
162
+
163
+ # Write a small text file
164
+ local_file = "example.txt"
165
+ with open(local_file, "wt") as f:
166
+ f.write("A small example of text")
167
+
168
+ # Load creds from JSON / YAML file, or fall back to .env / environment vars.
169
+ cred = sftph.credentials("path/to/sftp_config.json")
170
+
171
+ remote_file = cred["sftp_destination_path"] + "/" + local_file
172
+ url = cred["sftp_https"] + "/" + local_file
173
+
174
+ # upload() raises on failure and returns the destination URL on success.
175
+ sftph.upload(local_file, cred, remote_file)
176
+ print(f"Uploaded {local_file} to {remote_file}")
177
+ # Uploaded example.txt to /remote/base/path/example.txt
178
+
179
+ assert osh.is_working_url(url), f"URL not reachable: {url}"
180
+ print(f"URL is live: {url}")
181
+ # URL is live: https://files.example.com/example.txt
182
+ ```
183
+
184
+ ## Temporary remote files
185
+
186
+ If you need a unique remote path that gets cleaned up automatically, use the
187
+ `remote_tempfile` context manager:
188
+
189
+ ```python
190
+ import sftp_helper as sftph
191
+ import os_helper as osh
192
+
193
+ credentials = sftph.credentials("path/to/sftp_config.json")
194
+
195
+ with sftph.remote_tempfile(credentials, ext="txt") as (sftp_address, url):
196
+ sftph.upload("local.txt", credentials, sftp_address)
197
+ assert osh.is_working_url(url)
198
+ # On exit, the remote file is deleted.
199
+ ```
200
+
201
+ ## Host key verification
202
+
203
+ `sftp_helper` never disables host key verification. The default policy is
204
+ `paramiko.RejectPolicy()` and `~/.ssh/known_hosts` is loaded automatically. To
205
+ trust a server in a non-default location, point at an extra known_hosts file
206
+ via the optional `sftp_known_hosts` credential.
207
+
208
+ # Multi-surface exposure
209
+
210
+ `sftp-helper` is not just a library โ€” the same functions are exposed
211
+ as a CLI, a FastAPI HTTP surface, and an MCP tool set:
212
+
213
+ ```bash
214
+ # Python library (default)
215
+ import sftp_helper as sftph
216
+
217
+ # argparse-based CLI (installed automatically)
218
+ sftp-helper upload --config sftp_config.json --input local.txt --remote /uploads/local.txt
219
+ sftp-helper download --config sftp_config.json --remote /uploads/local.txt --output out.txt
220
+ sftp-helper exists --config sftp_config.json --remote /uploads/local.txt
221
+ sftp-helper mkdir --config sftp_config.json --remote /uploads/a/b/c
222
+
223
+ # click-based CLI twin (needs the [cli] extra)
224
+ pip install 'sftp-helper[cli] @ git+https://github.com/warith-harchaoui/sftp-helper.git@v2.2.2'
225
+ sftp-helper-click upload --config sftp_config.json --input local.txt --remote /uploads/local.txt
226
+
227
+ # FastAPI HTTP surface (needs the [api] extra)
228
+ pip install 'sftp-helper[api] @ git+https://github.com/warith-harchaoui/sftp-helper.git@v2.2.2'
229
+ SFTP_HELPER_CONFIG=./sftp_config.json uvicorn sftp_helper.api:app --port 8000
230
+ # โ†’ OpenAPI docs at http://localhost:8000/docs
231
+
232
+ # MCP tools over FastAPI (needs the [api,mcp] extras)
233
+ pip install 'sftp-helper[api,mcp] @ git+https://github.com/warith-harchaoui/sftp-helper.git@v2.2.2'
234
+ sftp-helper-mcp # serves FastAPI + MCP on port 8000
235
+ ```
236
+
237
+ Docker image (HTTP + MCP on port 8000):
238
+
239
+ ```bash
240
+ docker build -t sftp-helper .
241
+ docker run --rm -p 8000:8000 \
242
+ -v $PWD/sftp_config.json:/app/sftp_config.json:ro \
243
+ -e SFTP_HELPER_CONFIG=/app/sftp_config.json \
244
+ sftp-helper
245
+ ```
246
+
247
+ An innovative GUI plan (pipeline dashboard, storage health panel,
248
+ live transfer feed) lives in [GUI.md](https://github.com/warith-harchaoui/sftp-helper/blob/main/GUI.md).
249
+
250
+ The competitive landscape (paramiko, pysftp, asyncssh, Fabric,
251
+ smart-open, PyFilesystem2, lftp, Rclone, โ€ฆ) is analysed in
252
+ [LANDSCAPE.md](https://github.com/warith-harchaoui/sftp-helper/blob/main/LANDSCAPE.md).
253
+
254
+ # Author
255
+ - [Warith HARCHAOUI](https://linkedin.com/in/warith-harchaoui)
256
+
257
+ # Acknowledgements
258
+ Special thanks to [Mohamed Chelali](https://mchelali.github.io) and [Bachir Zerroug](https://www.linkedin.com/in/bachirzerroug) for fruitful discussions.
@@ -0,0 +1,212 @@
1
+ # SFTP Helper
2
+
3
+ [๐Ÿ‡ซ๐Ÿ‡ท](https://github.com/warith-harchaoui/sftp-helper/blob/main/LISEZMOI.md) ยท [๐Ÿ‡ฌ๐Ÿ‡ง](https://github.com/warith-harchaoui/sftp-helper/blob/main/README.md)
4
+
5
+ [![CI](https://github.com/warith-harchaoui/sftp-helper/actions/workflows/ci.yml/badge.svg)](https://github.com/warith-harchaoui/sftp-helper/actions/workflows/ci.yml) [![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](LICENSE) [![Python](https://img.shields.io/badge/python-3.10%E2%80%933.13-blue.svg)](#)
6
+
7
+ `SFTP Helper` belongs to a collection of libraries called `AI Helpers` developped for building Artificial Intelligence
8
+
9
+ This toolbox requires:
10
+ - a `config.json` for the sftp parameters (or YAML or environment variables or .env)
11
+ - that you previously added you SSH key of your local machine in the SFTP server
12
+
13
+ [๐ŸŒ AI Helpers](https://harchaoui.org/warith/ai-helpers)
14
+
15
+ [![logo](https://raw.githubusercontent.com/warith-harchaoui/sftp-helper/main/assets/logo.png)](https://harchaoui.org/warith/ai-helpers)
16
+
17
+ SFTP Helper is a Python library that provides utility functions for working with SFTP servers via [paramiko](https://www.paramiko.org/). Host key verification is on by default โ€” `~/.ssh/known_hosts` is loaded and unknown hosts are rejected.
18
+
19
+ # Installation
20
+
21
+ **Prerequisites** โ€” **Python 3.10โ€“3.13** and **git**, cross-platform:
22
+
23
+ - ๐ŸŽ **macOS** ([Homebrew](https://brew.sh)): `brew install python git`
24
+ - ๐Ÿง **Ubuntu/Debian**: `sudo apt update && sudo apt install -y python3 python3-pip git`
25
+ - ๐ŸชŸ **Windows** (PowerShell): `winget install Python.Python.3.12 Git.Git`
26
+
27
+ Then install the package:
28
+
29
+
30
+ ## Install Package
31
+
32
+ We can recommand python environments. Check this link if you don't know how
33
+
34
+ [๐Ÿฅธ Tech tips](https://harchaoui.org/warith/4ml/#install)
35
+
36
+ ```bash
37
+ pip install --force-reinstall --no-cache-dir git+https://github.com/warith-harchaoui/sftp-helper.git@v2.2.2
38
+ ```
39
+
40
+ Or, from a checkout:
41
+
42
+ ```bash
43
+ pip install -r requirements.txt
44
+ pip install -e .
45
+ ```
46
+
47
+ ## Write your own configuration file
48
+
49
+ A ready-to-fill template is committed at [`sftp_config.json.example`](https://github.com/warith-harchaoui/sftp-helper/blob/main/sftp_config.json.example). A heavily-commented YAML variant is also provided at [`sftp_config.yaml.example`](https://github.com/warith-harchaoui/sftp-helper/blob/main/sftp_config.yaml.example) โ€” YAML supports inline comments explaining every key and how to obtain its value. Copy either one and edit in place โ€” real `*config.json` / `*config.yaml` files are gitignored so you cannot accidentally commit secrets:
50
+
51
+ ```bash
52
+ cp sftp_config.json.example sftp_config.json
53
+ # then edit sftp_config.json with your credentials
54
+ ```
55
+
56
+ You may also provide a YAML version (`sftp_config.yaml`), environment variables, or an `.env` file โ€” `sftp-helper` falls back in that order via `os_helper.get_config`:
57
+
58
+ _JSON_
59
+ ```json
60
+ {
61
+ "sftp_host": "<sftp_host>",
62
+ "sftp_login": "<sftp_login>",
63
+ "sftp_passwd": "<sftp_passwd>",
64
+ "sftp_https": "<sftp_https>",
65
+ "sftp_destination_path": "<sftp_destination_path>",
66
+ }
67
+ ```
68
+ or
69
+
70
+ _YAML_
71
+ ```yaml
72
+ sftp_host: "<sftp_host>"
73
+ sftp_login: "<sftp_login>"
74
+ sftp_passwd: "<sftp_passwd>"
75
+ sftp_https: "<sftp_https>"
76
+ sftp_destination_path: "<sftp_destination_path>"
77
+ ```
78
+ or
79
+
80
+ _ENVIRONMENT VARIABLES_
81
+ ```bash
82
+ SFTP_HOST="<sftp_host>" \
83
+ SFTP_LOGIN="<sftp_login>" \
84
+ SFTP_PASSWD="<sftp_passwd>" \
85
+ SFTP_HTTPS="<sftp_https>" \
86
+ SFTP_DESTINATION_PATH="<sftp_destination_path>" \
87
+ python <your_python_script>
88
+ ```
89
+ or
90
+
91
+ _.env_
92
+ ```
93
+ SFTP_HOST = <sftp_host>
94
+ SFTP_LOGIN = <sftp_login>
95
+ SFTP_PASSWD = <sftp_passwd>
96
+ SFTP_HTTPS = <sftp_https>
97
+ SFTP_DESTINATION_PATH = <sftp_destination_path>
98
+ ```
99
+
100
+ In which you can find these information in your favorite FTP tool (mine is FileZilla):
101
+ + `<sftp_host>` is the server path `sftp.` ...
102
+ + `<sftp_login>` and `<sftp_passwd>` that you use in FileZilla
103
+ + `<sftp_destination_path>` is the remote folder path
104
+ + `<sftp_https>` corresponds to the web URL of `<sftp_destination_path>`
105
+ + <your_python_script> is your python script :)
106
+
107
+ ## Usage
108
+
109
+ For the full catalog of recipes (uploads, downloads, existence checks, recursive directory creation, temporary remote files with auto-cleanup, strict host-key verification), see [๐Ÿ“‹ EXAMPLES.md](https://github.com/warith-harchaoui/sftp-helper/blob/main/EXAMPLES.md).
110
+
111
+ Here's an example of how to use SFTP helper (**won't work without a valid `path/to/sftp_config.json`**):
112
+
113
+ ```python
114
+ import sftp_helper as sftph
115
+ import os_helper as osh
116
+
117
+ # Write a small text file
118
+ local_file = "example.txt"
119
+ with open(local_file, "wt") as f:
120
+ f.write("A small example of text")
121
+
122
+ # Load creds from JSON / YAML file, or fall back to .env / environment vars.
123
+ cred = sftph.credentials("path/to/sftp_config.json")
124
+
125
+ remote_file = cred["sftp_destination_path"] + "/" + local_file
126
+ url = cred["sftp_https"] + "/" + local_file
127
+
128
+ # upload() raises on failure and returns the destination URL on success.
129
+ sftph.upload(local_file, cred, remote_file)
130
+ print(f"Uploaded {local_file} to {remote_file}")
131
+ # Uploaded example.txt to /remote/base/path/example.txt
132
+
133
+ assert osh.is_working_url(url), f"URL not reachable: {url}"
134
+ print(f"URL is live: {url}")
135
+ # URL is live: https://files.example.com/example.txt
136
+ ```
137
+
138
+ ## Temporary remote files
139
+
140
+ If you need a unique remote path that gets cleaned up automatically, use the
141
+ `remote_tempfile` context manager:
142
+
143
+ ```python
144
+ import sftp_helper as sftph
145
+ import os_helper as osh
146
+
147
+ credentials = sftph.credentials("path/to/sftp_config.json")
148
+
149
+ with sftph.remote_tempfile(credentials, ext="txt") as (sftp_address, url):
150
+ sftph.upload("local.txt", credentials, sftp_address)
151
+ assert osh.is_working_url(url)
152
+ # On exit, the remote file is deleted.
153
+ ```
154
+
155
+ ## Host key verification
156
+
157
+ `sftp_helper` never disables host key verification. The default policy is
158
+ `paramiko.RejectPolicy()` and `~/.ssh/known_hosts` is loaded automatically. To
159
+ trust a server in a non-default location, point at an extra known_hosts file
160
+ via the optional `sftp_known_hosts` credential.
161
+
162
+ # Multi-surface exposure
163
+
164
+ `sftp-helper` is not just a library โ€” the same functions are exposed
165
+ as a CLI, a FastAPI HTTP surface, and an MCP tool set:
166
+
167
+ ```bash
168
+ # Python library (default)
169
+ import sftp_helper as sftph
170
+
171
+ # argparse-based CLI (installed automatically)
172
+ sftp-helper upload --config sftp_config.json --input local.txt --remote /uploads/local.txt
173
+ sftp-helper download --config sftp_config.json --remote /uploads/local.txt --output out.txt
174
+ sftp-helper exists --config sftp_config.json --remote /uploads/local.txt
175
+ sftp-helper mkdir --config sftp_config.json --remote /uploads/a/b/c
176
+
177
+ # click-based CLI twin (needs the [cli] extra)
178
+ pip install 'sftp-helper[cli] @ git+https://github.com/warith-harchaoui/sftp-helper.git@v2.2.2'
179
+ sftp-helper-click upload --config sftp_config.json --input local.txt --remote /uploads/local.txt
180
+
181
+ # FastAPI HTTP surface (needs the [api] extra)
182
+ pip install 'sftp-helper[api] @ git+https://github.com/warith-harchaoui/sftp-helper.git@v2.2.2'
183
+ SFTP_HELPER_CONFIG=./sftp_config.json uvicorn sftp_helper.api:app --port 8000
184
+ # โ†’ OpenAPI docs at http://localhost:8000/docs
185
+
186
+ # MCP tools over FastAPI (needs the [api,mcp] extras)
187
+ pip install 'sftp-helper[api,mcp] @ git+https://github.com/warith-harchaoui/sftp-helper.git@v2.2.2'
188
+ sftp-helper-mcp # serves FastAPI + MCP on port 8000
189
+ ```
190
+
191
+ Docker image (HTTP + MCP on port 8000):
192
+
193
+ ```bash
194
+ docker build -t sftp-helper .
195
+ docker run --rm -p 8000:8000 \
196
+ -v $PWD/sftp_config.json:/app/sftp_config.json:ro \
197
+ -e SFTP_HELPER_CONFIG=/app/sftp_config.json \
198
+ sftp-helper
199
+ ```
200
+
201
+ An innovative GUI plan (pipeline dashboard, storage health panel,
202
+ live transfer feed) lives in [GUI.md](https://github.com/warith-harchaoui/sftp-helper/blob/main/GUI.md).
203
+
204
+ The competitive landscape (paramiko, pysftp, asyncssh, Fabric,
205
+ smart-open, PyFilesystem2, lftp, Rclone, โ€ฆ) is analysed in
206
+ [LANDSCAPE.md](https://github.com/warith-harchaoui/sftp-helper/blob/main/LANDSCAPE.md).
207
+
208
+ # Author
209
+ - [Warith HARCHAOUI](https://linkedin.com/in/warith-harchaoui)
210
+
211
+ # Acknowledgements
212
+ Special thanks to [Mohamed Chelali](https://mchelali.github.io) and [Bachir Zerroug](https://www.linkedin.com/in/bachirzerroug) for fruitful discussions.
@@ -0,0 +1,105 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sftp-helper"
7
+ version = "2.2.3"
8
+ description = "SFTP Helper โ€” utility functions for working with SFTP servers via paramiko, exposed as library, argparse CLI, click CLI, FastAPI HTTP surface and MCP tools. Strict host-key verification, credentials loader, upload / download / list / remove / exists / remote_tempfile context manager."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10,<3.14"
11
+ license = {text = "BSD-3-Clause"}
12
+ authors = [
13
+ {name = "Warith HARCHAOUI", email = "warithmetics@deraison.ai"},
14
+ ]
15
+ keywords = ["sftp", "paramiko", "ssh", "file-transfer", "secure"]
16
+ classifiers = [
17
+ "Development Status :: 5 - Production/Stable",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: BSD License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Topic :: Internet :: File Transfer Protocol (FTP)",
27
+ "Topic :: System :: Networking",
28
+ ]
29
+ dependencies = [
30
+ "os-helper>=1.5.0",
31
+ "paramiko>=3.0,<4",
32
+ ]
33
+
34
+ [project.optional-dependencies]
35
+ # CLI-only-with-click extra. argparse variant needs no runtime dep and
36
+ # is always available.
37
+ cli = ["click>=8.1,<9"]
38
+ # FastAPI HTTP surface (sftp_helper.api). uvicorn + python-multipart
39
+ # so multipart file uploads work out of the box.
40
+ api = [
41
+ "fastapi>=0.111,<1",
42
+ "uvicorn>=0.30,<1",
43
+ "python-multipart>=0.0.9,<1",
44
+ ]
45
+ # MCP surface (sftp_helper.mcp). Depends on the `api` extra
46
+ # โ€” fastapi-mcp wraps the FastAPI app.
47
+ mcp = [
48
+ "fastapi-mcp>=0.3,<1",
49
+ "fastapi>=0.111,<1",
50
+ "uvicorn>=0.30,<1",
51
+ "python-multipart>=0.0.9,<1",
52
+ ]
53
+ # `dev` keeps the bar low for CI โ€” pytest + httpx (for FastAPI TestClient)
54
+ # + click (so the click CLI import always resolves in tests) + pyyaml
55
+ # (used by the credentials tests to write YAML configs).
56
+ dev = [
57
+ "pytest>=8",
58
+ "pyyaml>=6",
59
+ "httpx>=0.27",
60
+ "click>=8.1,<9",
61
+ "fastapi>=0.111,<1",
62
+ "python-multipart>=0.0.9,<1",
63
+ "fastapi-mcp>=0.3,<1",
64
+ ]
65
+
66
+ [project.scripts]
67
+ # argparse-based CLI โ€” no runtime dep beyond stdlib + core package.
68
+ sftp-helper = "sftp_helper.cli_argparse:main"
69
+ # click-based twin โ€” install with [cli] extra.
70
+ sftp-helper-click = "sftp_helper.cli_click:cli"
71
+ # MCP server (over FastAPI) โ€” install with [api,mcp] extras.
72
+ sftp-helper-mcp = "sftp_helper.mcp:main"
73
+
74
+ [project.urls]
75
+ Homepage = "https://github.com/warith-harchaoui/sftp-helper"
76
+ Issues = "https://github.com/warith-harchaoui/sftp-helper/issues"
77
+
78
+ [tool.setuptools.packages.find]
79
+ include = ["sftp_helper*"]
80
+ exclude = ["tests*", "assets*"]
81
+
82
+ [tool.pytest.ini_options]
83
+ markers = [
84
+ "integration: tests that hit a real SFTP server (skipped by default)",
85
+ ]
86
+ addopts = "-m 'not integration'"
87
+
88
+ [tool.ruff]
89
+ line-length = 100
90
+ target-version = "py310"
91
+ extend-exclude = ["assets", "tests"]
92
+
93
+ [tool.ruff.lint]
94
+ # Conservative starter set: pyflakes (F), pycodestyle errors (E), warnings (W),
95
+ # isort (I), bugbear (B), comprehensions (C4), pyupgrade (UP), simplify (SIM).
96
+ # Easy to tighten later; this is the baseline.
97
+ select = ["E", "F", "W", "I", "B", "C4", "UP", "SIM"]
98
+ ignore = [
99
+ "E501", # line-too-long โ€” handled by formatter / context-dependent
100
+ "B008", # function call in argument default โ€” too noisy for our style
101
+ "SIM108", # ternary preferred over if/else โ€” sometimes hurts readability
102
+ ]
103
+
104
+ [tool.ruff.lint.per-file-ignores]
105
+ "tests/*" = ["B011"] # assert False in pytest is fine
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,57 @@
1
+ """
2
+ SFTP Helper โ€” public API surface.
3
+
4
+ Re-exports the utility functions from :mod:`sftp_helper.main` so that
5
+ downstream code can simply write ``import sftp_helper as sftph`` and reach
6
+ every supported operation (credentials loading, connection context manager,
7
+ upload, download, exists, delete, mkdir -p, remote temp file with
8
+ auto-cleanup) without knowing about the module layout.
9
+
10
+ Backed by paramiko with strict host-key verification. See the module docs
11
+ for the full policy โ€” there is no flag to disable verification.
12
+
13
+ Usage Example
14
+ -------------
15
+ >>> import sftp_helper as sftph
16
+ >>> cred = sftph.credentials("sftp_config.json")
17
+ >>> sftph.upload("local.txt", cred, "/remote/base/local.txt")
18
+ >>> assert sftph.remote_file_exists("/remote/base/local.txt", cred)
19
+ >>> sftph.download("/remote/base/local.txt", cred, "roundtrip.txt")
20
+ >>> sftph.delete("/remote/base/local.txt", cred)
21
+
22
+ Author
23
+ ------
24
+ Warith Harchaoui, Ph.D. โ€” https://linkedin.com/in/warith-harchaoui/
25
+ """
26
+
27
+ __author__ = "Warith Harchaoui, Ph.D."
28
+ __email__ = "warithmetics@deraison.ai"
29
+
30
+ # Specify the public API of this module using __all__
31
+ __all__ = [
32
+ "credentials",
33
+ "get_client_sftp",
34
+ "normalize_path",
35
+ "strip_sftp_path",
36
+ "remote_file_exists",
37
+ "delete",
38
+ "upload",
39
+ "download",
40
+ "remote_dir_exist",
41
+ "make_remote_directory",
42
+ "remote_tempfile",
43
+ ]
44
+
45
+ from .main import (
46
+ credentials,
47
+ delete,
48
+ download,
49
+ get_client_sftp,
50
+ make_remote_directory,
51
+ normalize_path,
52
+ remote_dir_exist,
53
+ remote_file_exists,
54
+ remote_tempfile,
55
+ strip_sftp_path,
56
+ upload,
57
+ )