0
# aioftp
1
2
A comprehensive asynchronous FTP client and server implementation for Python's asyncio framework. aioftp provides both client and server functionality with support for modern FTP commands including MLSD/MLST for machine-readable directory listings, passive mode transfers, resumable downloads/uploads, SSL/TLS encryption, and customizable path I/O abstractions.
3
4
## Package Information
5
6
- **Package Name**: aioftp
7
- **Language**: Python
8
- **Installation**: `pip install aioftp`
9
- **Optional Dependencies**: `pip install aioftp[socks]` for SOCKS proxy support
10
11
## Core Imports
12
13
```python
14
import aioftp
15
```
16
17
Common patterns for specific functionality:
18
19
```python
20
# Client operations
21
from aioftp import Client
22
23
# Server operations
24
from aioftp import Server, User, Permission
25
26
# Errors and exceptions
27
from aioftp import AIOFTPException, StatusCodeError
28
29
# Path I/O abstractions
30
from aioftp import PathIO, AsyncPathIO, MemoryPathIO
31
32
# Throttling and utilities
33
from aioftp import Throttle, StreamThrottle
34
35
# Type imports (for type annotations)
36
from pathlib import Path, PurePosixPath
37
from typing import Union, Optional, Dict, List, Tuple, AsyncIterator, AsyncIterable, Generator
38
```
39
40
## Basic Usage
41
42
### FTP Client
43
44
```python
45
import aioftp
46
import asyncio
47
48
async def client_example():
49
# Using context manager (recommended)
50
async with aioftp.Client.context("ftp.example.com") as client:
51
# Upload a file
52
await client.upload("local_file.txt", "remote_file.txt")
53
54
# Download a file
55
await client.download("remote_file.txt", "downloaded_file.txt")
56
57
# List directory contents
58
async for path, info in client.list():
59
print(f"{path}: {info['type']} ({info.get('size', 'unknown')} bytes)")
60
61
# Directory operations
62
await client.make_directory("new_folder")
63
await client.change_directory("new_folder")
64
current_dir = await client.get_current_directory()
65
print(f"Current directory: {current_dir}")
66
67
asyncio.run(client_example())
68
```
69
70
### FTP Server
71
72
```python
73
import aioftp
74
import asyncio
75
from pathlib import Path
76
77
async def server_example():
78
# Create users with permissions
79
users = [
80
aioftp.User(
81
login="admin",
82
password="secret",
83
base_path=Path("/srv/ftp"),
84
permissions=[
85
aioftp.Permission("/", readable=True, writable=True),
86
]
87
),
88
aioftp.User( # Anonymous user
89
base_path=Path("/srv/ftp/public"),
90
permissions=[
91
aioftp.Permission("/", readable=True, writable=False),
92
]
93
)
94
]
95
96
# Create and run server
97
server = aioftp.Server(users=users)
98
await server.run(host="localhost", port=2121)
99
100
asyncio.run(server_example())
101
```
102
103
## Architecture
104
105
aioftp follows a modular design with distinct layers:
106
107
- **Client Layer**: BaseClient provides protocol implementation, Client adds high-level operations
108
- **Server Layer**: Server handles protocol, User/Permission system manages access control
109
- **Transport Layer**: StreamIO and ThrottleStreamIO provide connection abstractions with speed limiting
110
- **Path I/O Layer**: AbstractPathIO enables filesystem abstraction (local, async, in-memory)
111
- **Protocol Layer**: Code class and command handlers implement FTP protocol semantics
112
113
The library supports both traditional blocking I/O (PathIO) and fully asynchronous I/O (AsyncPathIO), with a memory-based implementation (MemoryPathIO) for testing. Connection throttling and SSL/TLS are supported throughout.
114
115
## Capabilities
116
117
### FTP Client Operations
118
119
High-level FTP client functionality including connection management, authentication, file transfers, directory operations, and listing. Supports context managers, streaming operations, and various connection options.
120
121
```python { .api }
122
class Client(BaseClient):
123
@classmethod
124
async def context(host: str, port: int = 21, user: str = "anonymous",
125
password: str = "anon@", account: str = "",
126
upgrade_to_tls: bool = False, **kwargs) -> AsyncGenerator[Client]:
127
"""Async context manager for FTP client connections."""
128
129
async def connect(host: str, port: int = 21) -> list[str]:
130
"""Connect to FTP server and return greeting."""
131
132
async def login(user: str = "anonymous", password: str = "anon@",
133
account: str = "") -> None:
134
"""Authenticate with the FTP server."""
135
136
async def upload(source, destination: str = "", write_into: bool = False,
137
block_size: int = 8192) -> None:
138
"""Upload a file to the server."""
139
140
async def download(source, destination: str = "", write_into: bool = False,
141
block_size: int = 8192) -> None:
142
"""Download a file from the server."""
143
144
def list(path: str = "", recursive: bool = False,
145
raw_command: str = None) -> AbstractAsyncLister:
146
"""List directory contents."""
147
```
148
149
[FTP Client](./client.md)
150
151
### FTP Server Implementation
152
153
Complete FTP server with user management, permission system, connection limiting, and protocol command handlers. Supports SSL/TLS, custom path I/O backends, and extensive configuration options.
154
155
```python { .api }
156
class Server:
157
def __init__(users=None, block_size: int = 8192, socket_timeout=None,
158
idle_timeout=None, wait_future_timeout: int = 1, path_timeout=None,
159
path_io_factory=PathIO, maximum_connections=None,
160
read_speed_limit=None, write_speed_limit=None, **kwargs):
161
"""Initialize FTP server with configuration."""
162
163
async def start(host: str = None, port: int = 0, **kwargs) -> None:
164
"""Start the FTP server."""
165
166
async def run(host: str = None, port: int = 0, **kwargs) -> None:
167
"""Start server and run forever."""
168
169
async def close() -> None:
170
"""Close the server and all connections."""
171
172
class User:
173
def __init__(login: str = None, password: str = None,
174
base_path: Path = Path("."), home_path: PurePosixPath = PurePosixPath("/"),
175
permissions: list[Permission] = None, maximum_connections: int = None,
176
read_speed_limit: int = None, write_speed_limit: int = None):
177
"""User account with credentials and permissions."""
178
179
class Permission:
180
def __init__(path: str = "/", readable: bool = True, writable: bool = True):
181
"""Path permission specification."""
182
```
183
184
[FTP Server](./server.md)
185
186
### Error Handling
187
188
Exception hierarchy for FTP operations including protocol errors, path validation, and I/O errors. All exceptions inherit from AIOFTPException for consistent error handling.
189
190
```python { .api }
191
class AIOFTPException(Exception):
192
"""Base exception for all aioftp errors."""
193
194
class StatusCodeError(AIOFTPException):
195
"""Raised when FTP server returns unexpected status code."""
196
expected_codes: tuple[Code, ...]
197
received_codes: tuple[Code, ...]
198
info: Union[list[str], str]
199
200
class PathIsNotAbsolute(AIOFTPException):
201
"""Raised when path is not absolute but should be."""
202
203
class PathIOError(AIOFTPException):
204
"""Universal exception for path I/O operations."""
205
reason: Union[tuple, None] # Original exception info
206
207
class NoAvailablePort(AIOFTPException, OSError):
208
"""Raised when no data ports are available."""
209
```
210
211
[Error Handling](./errors.md)
212
213
### Stream and Throttling
214
215
Stream wrappers with timeout and throttling support for controlling data transfer rates. Includes both simple streams and throttled streams with configurable read/write limits.
216
217
```python { .api }
218
class StreamIO:
219
def __init__(reader: asyncio.StreamReader, writer: asyncio.StreamWriter,
220
timeout: float = None, read_timeout: float = None,
221
write_timeout: float = None):
222
"""Basic stream wrapper with timeout support."""
223
224
async def read(count: int = -1) -> bytes:
225
"""Read data from stream."""
226
227
async def write(data: bytes) -> None:
228
"""Write data to stream."""
229
230
class Throttle:
231
def __init__(limit: int = None, reset_rate: int = 10):
232
"""Speed throttling mechanism."""
233
234
async def wait() -> None:
235
"""Wait if throttling is needed."""
236
237
class ThrottleStreamIO(StreamIO):
238
def __init__(reader: asyncio.StreamReader, writer: asyncio.StreamWriter,
239
throttles: dict[str, StreamThrottle] = {}, **kwargs):
240
"""Stream with throttling support."""
241
```
242
243
[Streaming and Throttling](./streaming.md)
244
245
### Path I/O Abstractions
246
247
Filesystem abstraction layer supporting synchronous, asynchronous, and in-memory implementations. Enables custom backends and testing with memory-based filesystems.
248
249
```python { .api }
250
class AbstractPathIO(Generic[PathType]):
251
"""Abstract base class for filesystem operations."""
252
253
async def exists(path: PathType) -> bool:
254
"""Check if path exists."""
255
256
async def is_file(path: PathType) -> bool:
257
"""Check if path is a file."""
258
259
async def is_dir(path: PathType) -> bool:
260
"""Check if path is a directory."""
261
262
def open(path: PathType, mode: str = "rb") -> AsyncPathIOContext:
263
"""Open file for reading/writing."""
264
265
class PathIO(AbstractPathIO[Path]):
266
"""Synchronous filesystem operations using pathlib.Path."""
267
268
class AsyncPathIO(AbstractPathIO[Path]):
269
"""Asynchronous filesystem operations via executor."""
270
271
class MemoryPathIO(AbstractPathIO[PurePosixPath]):
272
"""In-memory filesystem for testing."""
273
```
274
275
[Path I/O](./pathio.md)
276
277
### Common Utilities
278
279
Core utility functions, decorators, and classes for FTP operations including status code handling, timeouts, locale management, and async context management.
280
281
```python { .api }
282
class Code(str):
283
"""Representation of server status code with template matching."""
284
def matches(self, mask: str) -> bool:
285
"""Template comparison for status codes (e.g., '2xx', '4xx')."""
286
287
class Connection(defaultdict[str, asyncio.Future]):
288
"""Connection state container for async coordination between components."""
289
290
class SSLSessionBoundContext:
291
"""SSL context bound to existing session for connection reuse."""
292
293
def with_timeout(func, timeout: float = None):
294
"""Decorator adding timeout to async methods."""
295
296
def async_enterable(func):
297
"""Decorator to bring coroutine result up for async context usage."""
298
299
def setlocale(name: str) -> Generator[str, None, None]:
300
"""Thread-safe locale context manager for system locale changes."""
301
302
def wrap_with_container() -> Callable:
303
"""Utility function for container wrapping operations."""
304
305
def wrap_into_codes() -> Callable:
306
"""Utility to wrap iterables into Code tuples for status handling."""
307
```
308
309
## Constants and Utilities
310
311
```python { .api }
312
# Default values
313
DEFAULT_PORT: int = 21
314
DEFAULT_USER: str = "anonymous"
315
DEFAULT_PASSWORD: str = "anon@"
316
DEFAULT_ACCOUNT: str = ""
317
DEFAULT_BLOCK_SIZE: int = 8192
318
END_OF_LINE: str = "\\r\\n"
319
320
# Version information
321
__version__: str # Package version string
322
version: tuple[int, ...] # Version as tuple of integers
323
```