rapcsv 0.0.2__cp38-cp38-manylinux_2_28_x86_64.whl
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.
- rapcsv/__init__.py +16 -0
- rapcsv/_rapcsv.cpython-38-x86_64-linux-gnu.so +0 -0
- rapcsv/_rapcsv.pyi +11 -0
- rapcsv/py.typed +0 -0
- rapcsv-0.0.2.dist-info/METADATA +226 -0
- rapcsv-0.0.2.dist-info/RECORD +7 -0
- rapcsv-0.0.2.dist-info/WHEEL +4 -0
rapcsv/__init__.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Streaming async CSV — no fake async, no GIL stalls."""
|
|
2
|
+
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
from _rapcsv import Reader, Writer # type: ignore[import-not-found]
|
|
7
|
+
except ImportError:
|
|
8
|
+
try:
|
|
9
|
+
from rapcsv._rapcsv import Reader, Writer
|
|
10
|
+
except ImportError:
|
|
11
|
+
raise ImportError(
|
|
12
|
+
"Could not import _rapcsv. Make sure rapcsv is built with maturin."
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__version__: str = "0.0.2"
|
|
16
|
+
__all__: List[str] = ["Reader", "Writer"]
|
|
Binary file
|
rapcsv/_rapcsv.pyi
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Type stubs for _rapcsv Rust extension module."""
|
|
2
|
+
|
|
3
|
+
from typing import Coroutine, Any, List
|
|
4
|
+
|
|
5
|
+
class Reader:
|
|
6
|
+
def __init__(self, path: str) -> None: ...
|
|
7
|
+
def read_row(self) -> Coroutine[Any, Any, List[str]]: ...
|
|
8
|
+
|
|
9
|
+
class Writer:
|
|
10
|
+
def __init__(self, path: str) -> None: ...
|
|
11
|
+
def write_row(self, row: List[str]) -> Coroutine[Any, Any, None]: ...
|
rapcsv/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rapcsv
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Summary: Streaming async CSV — no fake async, no GIL stalls.
|
|
14
|
+
Keywords: async,csv,streaming,async-io
|
|
15
|
+
Author: RAP Project
|
|
16
|
+
License: MIT
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
19
|
+
|
|
20
|
+
# rapcsv
|
|
21
|
+
|
|
22
|
+
**Streaming async CSV — no fake async, no GIL stalls.**
|
|
23
|
+
|
|
24
|
+
[](https://pypi.org/project/rapcsv/)
|
|
25
|
+
[](https://pepy.tech/project/rapcsv)
|
|
26
|
+
[](https://www.python.org/downloads/)
|
|
27
|
+
[](https://opensource.org/licenses/MIT)
|
|
28
|
+
|
|
29
|
+
## Overview
|
|
30
|
+
|
|
31
|
+
`rapcsv` provides true async CSV reading and writing for Python, backed by Rust and Tokio. Unlike libraries that wrap blocking I/O in `async` syntax, `rapcsv` guarantees that all CSV operations execute **outside the Python GIL**, ensuring event loops never stall under load, even when processing large files.
|
|
32
|
+
|
|
33
|
+
**Roadmap Goal**: Achieve drop-in replacement compatibility with `aiocsv`, enabling seamless migration with true async performance. See [ROADMAP.md](https://github.com/eddiethedean/rapcsv/blob/main/ROADMAP.md) for details.
|
|
34
|
+
|
|
35
|
+
## Why `rap*`?
|
|
36
|
+
|
|
37
|
+
Packages prefixed with **`rap`** stand for **Real Async Python**. Unlike many libraries that merely wrap blocking I/O in `async` syntax, `rap*` packages guarantee that all I/O work is executed **outside the Python GIL** using native runtimes (primarily Rust). This means event loops are never stalled by hidden thread pools, blocking syscalls, or cooperative yielding tricks. If a `rap*` API is `async`, it is *structurally non-blocking by design*, not by convention. The `rap` prefix is a contract: measurable concurrency, real parallelism, and verifiable async behavior under load.
|
|
38
|
+
|
|
39
|
+
See the [rap-manifesto](https://github.com/eddiethedean/rap-manifesto) for philosophy and guarantees.
|
|
40
|
+
|
|
41
|
+
## Features
|
|
42
|
+
|
|
43
|
+
- ✅ **True async** CSV reading and writing
|
|
44
|
+
- ✅ **Streaming support** for large files
|
|
45
|
+
- ✅ **Native Rust-backed** execution (Tokio)
|
|
46
|
+
- ✅ **Zero Python thread pools**
|
|
47
|
+
- ✅ **Event-loop-safe** concurrency under load
|
|
48
|
+
- ✅ **GIL-independent** I/O operations
|
|
49
|
+
- ✅ **Verified** by Fake Async Detector
|
|
50
|
+
|
|
51
|
+
## Requirements
|
|
52
|
+
|
|
53
|
+
- Python 3.8+
|
|
54
|
+
- Rust 1.70+ (for building from source)
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install rapcsv
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Building from Source
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
git clone https://github.com/eddiethedean/rapcsv.git
|
|
66
|
+
cd rapcsv
|
|
67
|
+
pip install maturin
|
|
68
|
+
maturin develop
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Usage
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import asyncio
|
|
77
|
+
from rapcsv import Reader, Writer
|
|
78
|
+
|
|
79
|
+
async def main():
|
|
80
|
+
# Write CSV file (one row per Writer instance for MVP)
|
|
81
|
+
writer = Writer("output.csv")
|
|
82
|
+
await writer.write_row(["name", "age", "city"])
|
|
83
|
+
|
|
84
|
+
# Read CSV file (reads first row)
|
|
85
|
+
reader = Reader("output.csv")
|
|
86
|
+
row = await reader.read_row()
|
|
87
|
+
print(row) # Output: ['name', 'age', 'city']
|
|
88
|
+
|
|
89
|
+
asyncio.run(main())
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Writing Multiple Rows
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
import asyncio
|
|
96
|
+
from rapcsv import Writer
|
|
97
|
+
|
|
98
|
+
async def main():
|
|
99
|
+
# Write multiple rows with a single Writer instance (file handle reused)
|
|
100
|
+
writer = Writer("output.csv")
|
|
101
|
+
rows = [
|
|
102
|
+
["name", "age", "city"],
|
|
103
|
+
["Alice", "30", "New York"],
|
|
104
|
+
["Bob", "25", "London"],
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
for row in rows:
|
|
108
|
+
await writer.write_row(row)
|
|
109
|
+
|
|
110
|
+
# Verify file contents
|
|
111
|
+
with open("output.csv") as f:
|
|
112
|
+
print(f.read())
|
|
113
|
+
|
|
114
|
+
asyncio.run(main())
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Note**: The Writer reuses the file handle across multiple `write_row()` calls for efficient writing. The Reader maintains position state across `read_row()` calls.
|
|
118
|
+
|
|
119
|
+
## API Reference
|
|
120
|
+
|
|
121
|
+
### `Reader(path: str)`
|
|
122
|
+
|
|
123
|
+
Create a new async CSV reader.
|
|
124
|
+
|
|
125
|
+
**Parameters:**
|
|
126
|
+
- `path` (str): Path to the CSV file to read
|
|
127
|
+
|
|
128
|
+
**Example:**
|
|
129
|
+
```python
|
|
130
|
+
reader = Reader("data.csv")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `Reader.read_row() -> List[str]`
|
|
134
|
+
|
|
135
|
+
Read the next row from the CSV file.
|
|
136
|
+
|
|
137
|
+
**Returns:**
|
|
138
|
+
- `List[str]`: A list of string values for the row, or an empty list if EOF
|
|
139
|
+
|
|
140
|
+
**Raises:**
|
|
141
|
+
- `IOError`: If the file cannot be read or parsed
|
|
142
|
+
|
|
143
|
+
**Note**: The Reader maintains position state across `read_row()` calls, reading sequentially through the file.
|
|
144
|
+
|
|
145
|
+
### `Writer(path: str)`
|
|
146
|
+
|
|
147
|
+
Create a new async CSV writer.
|
|
148
|
+
|
|
149
|
+
**Parameters:**
|
|
150
|
+
- `path` (str): Path to the CSV file to write
|
|
151
|
+
|
|
152
|
+
**Example:**
|
|
153
|
+
```python
|
|
154
|
+
writer = Writer("output.csv")
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### `Writer.write_row(row: List[str]) -> None`
|
|
158
|
+
|
|
159
|
+
Write a row to the CSV file.
|
|
160
|
+
|
|
161
|
+
**Parameters:**
|
|
162
|
+
- `row` (List[str]): A list of string values to write as a CSV row
|
|
163
|
+
|
|
164
|
+
**Raises:**
|
|
165
|
+
- `IOError`: If the file cannot be written
|
|
166
|
+
|
|
167
|
+
**Note**: The Writer reuses the file handle across multiple `write_row()` calls for efficient writing. Proper RFC 4180 compliant CSV escaping and quoting is applied automatically.
|
|
168
|
+
|
|
169
|
+
## Benchmarks
|
|
170
|
+
|
|
171
|
+
This package passes the [Fake Async Detector](https://github.com/eddiethedean/rap-bench). Benchmarks are available in the [rap-bench](https://github.com/eddiethedean/rap-bench) repository.
|
|
172
|
+
|
|
173
|
+
Run the detector yourself:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
pip install rap-bench
|
|
177
|
+
rap-bench detect rapcsv
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Roadmap
|
|
181
|
+
|
|
182
|
+
See [ROADMAP.md](https://github.com/eddiethedean/rapcsv/blob/main/ROADMAP.md) for detailed development plans. Key goals include:
|
|
183
|
+
- Drop-in replacement for `aiocsv` (Phase 1)
|
|
184
|
+
- Full streaming support for large files
|
|
185
|
+
- Comprehensive CSV dialect support
|
|
186
|
+
- Zero-copy optimizations
|
|
187
|
+
|
|
188
|
+
## Related Projects
|
|
189
|
+
|
|
190
|
+
- [rap-manifesto](https://github.com/eddiethedean/rap-manifesto) - Philosophy and guarantees
|
|
191
|
+
- [rap-bench](https://github.com/eddiethedean/rap-bench) - Fake Async Detector CLI
|
|
192
|
+
- [rapfiles](https://github.com/eddiethedean/rapfiles) - True async filesystem I/O
|
|
193
|
+
- [rapsqlite](https://github.com/eddiethedean/rapsqlite) - True async SQLite
|
|
194
|
+
|
|
195
|
+
## Limitations (v0.0.2)
|
|
196
|
+
|
|
197
|
+
**Current limitations:**
|
|
198
|
+
- Reader still reads entire file into memory on each call (streaming improvements planned)
|
|
199
|
+
- No advanced CSV dialect support (delimiters, quote characters, line terminators)
|
|
200
|
+
- No header detection or manipulation
|
|
201
|
+
- Not yet a drop-in replacement for `aiocsv` (goal for Phase 1)
|
|
202
|
+
- Not designed for synchronous use cases
|
|
203
|
+
|
|
204
|
+
**Recent improvements (v0.0.2):**
|
|
205
|
+
- ✅ Security fixes: Upgraded dependencies (pyo3 0.27, pyo3-async-runtimes 0.27), fixed CSV injection vulnerability
|
|
206
|
+
- ✅ Position tracking: Reader now maintains position state across `read_row()` calls
|
|
207
|
+
- ✅ File handle reuse: Writer reuses file handle across multiple `write_row()` calls
|
|
208
|
+
- ✅ CSV escaping: Implemented RFC 4180 compliant CSV escaping and quoting
|
|
209
|
+
- ✅ Input validation: Added path validation (non-empty, no null bytes)
|
|
210
|
+
- ✅ Improved error handling: Enhanced error messages with file path context
|
|
211
|
+
- ✅ Type stubs: Added `.pyi` type stubs for better IDE support and type checking
|
|
212
|
+
|
|
213
|
+
**Roadmap**: See [ROADMAP.md](https://github.com/eddiethedean/rapcsv/blob/main/ROADMAP.md) for planned improvements. Our goal is to achieve drop-in replacement compatibility with `aiocsv` while providing true async performance with GIL-independent I/O.
|
|
214
|
+
|
|
215
|
+
## Contributing
|
|
216
|
+
|
|
217
|
+
Contributions are welcome! Please see our [contributing guidelines](https://github.com/eddiethedean/rapcsv/blob/main/CONTRIBUTING.md) (coming soon).
|
|
218
|
+
|
|
219
|
+
## License
|
|
220
|
+
|
|
221
|
+
MIT
|
|
222
|
+
|
|
223
|
+
## Changelog
|
|
224
|
+
|
|
225
|
+
See [CHANGELOG.md](https://github.com/eddiethedean/rapcsv/blob/main/CHANGELOG.md) (coming soon) for version history.
|
|
226
|
+
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
rapcsv/__init__.py,sha256=sMhUUCdC2oVTKMic67GXxx2bs2nyKAvy5jp41aXlKEE,454
|
|
2
|
+
rapcsv/_rapcsv.cpython-38-x86_64-linux-gnu.so,sha256=OXkIqEexG4kGesbeMO8o61S-8as-NEGoOY5bglF10ac,1086888
|
|
3
|
+
rapcsv/_rapcsv.pyi,sha256=kHxUy6naJjUfEBGrM6p6FuOLIyTlJ0Fm2W8IlcYQsF0,353
|
|
4
|
+
rapcsv/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
rapcsv-0.0.2.dist-info/METADATA,sha256=gc2lMrQADF-WHhZJptugq70WcKhYb0s4U_iqmLhX6lg,7726
|
|
6
|
+
rapcsv-0.0.2.dist-info/WHEEL,sha256=3N5EpdPBJMYIW1be1E4XQax3kkFUj46lEw0Ks8eIJi4,107
|
|
7
|
+
rapcsv-0.0.2.dist-info/RECORD,,
|