pybcsv 1.5.7__tar.gz → 1.5.10.dev0__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.
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/PKG-INFO +39 -1
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/README.md +38 -0
- pybcsv-1.5.10.dev0/VERSION.txt +1 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/pybcsv/__init__.py +72 -15
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/pybcsv/__init__.pyi +7 -5
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/pybcsv/_bcsv.pyi +44 -124
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/pybcsv/_version.py +3 -3
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/pybcsv/bindings.cpp +524 -463
- pybcsv-1.5.10.dev0/pybcsv/parquet_utils.py +1248 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/pyproject.toml +4 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_cycle4_python_hardening.py +51 -29
- pybcsv-1.5.10.dev0/tests/test_parquet_conversion.py +518 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_performance_edge_cases.py +173 -122
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_pybcsv_arrow.py +68 -56
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_pybcsv_core.py +76 -20
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_pybcsv_pandas.py +138 -96
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_pybcsv_performance.py +34 -23
- pybcsv-1.5.10.dev0/tests/test_streaming_bindings.py +499 -0
- pybcsv-1.5.7/VERSION.txt +0 -1
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/BUILD_NOTES.md +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/CMakeLists.txt +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/LICENSE +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/MANIFEST.in +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/benchmarks/README.md +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/benchmarks/run_pybcsv_benchmarks.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/examples/README.md +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/examples/advanced_usage.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/examples/basic_usage.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/examples/pandas_integration.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/examples/performance_benchmark.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/bcsv.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/bcsv.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/bcsv_c_api.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/bitset.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/bitset.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/byte_buffer.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/checksum.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_file/file_codec_concept.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_file/file_codec_dispatch.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_file/file_codec_packet001.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_file/file_codec_packet_lz4_001.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_file/file_codec_packet_lz4_batch001.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_file/file_codec_stream001.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_file/file_codec_stream_lz4_001.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_row/row_codec_delta002.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_row/row_codec_delta002.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_row/row_codec_dispatch.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_row/row_codec_flat001.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_row/row_codec_flat001.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_row/row_codec_zoh001.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/codec_row/row_codec_zoh001.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/column_name_index.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/column_name_index.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/csv_reader.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/csv_reader.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/csv_writer.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/csv_writer.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/definitions.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/file_footer.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/file_header.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/file_header.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/layout.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/layout.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/layout_guard.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/lz4_block.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/lz4_stream.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/packet_header.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/reader.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/reader.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/reader_concept.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/row.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/row.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/row_visitors.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/sampler/sampler.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/sampler/sampler.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/sampler/sampler_ast.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/sampler/sampler_compiler.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/sampler/sampler_parser.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/sampler/sampler_tokenizer.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/sampler/sampler_types.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/sampler/sampler_vm.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/sampler/sampler_vm.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/sampler/sampler_window.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/std_charconv_compat.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/vle.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/writer.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/writer.hpp +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/bcsv/writer_concept.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/lz4-1.10.0/lz4.c +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/lz4-1.10.0/lz4.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/lz4-1.10.0/lz4file.c +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/lz4-1.10.0/lz4file.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/lz4-1.10.0/lz4frame.c +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/lz4-1.10.0/lz4frame.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/lz4-1.10.0/lz4frame_static.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/lz4-1.10.0/lz4hc.c +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/lz4-1.10.0/lz4hc.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/lz4-1.10.0/xxhash.c +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/lz4-1.10.0/xxhash.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/xxHash-0.8.3/xxhash.c +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/include/xxHash-0.8.3/xxhash.h +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/pybcsv/__version__.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/pybcsv/pandas_utils.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/pybcsv/polars_utils.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/pybcsv/py.typed +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/sync_headers.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/README.md +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/conftest.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_basic_functionality.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_count_rows.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_csv_writer_reader.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_data_types.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_interoperability.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_minimal_string.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_pybcsv_codecs.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_pybcsv_columnar.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_pybcsv_direct_access.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_pybcsv_errors.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_pybcsv_polars.py +0 -0
- {pybcsv-1.5.7 → pybcsv-1.5.10.dev0}/tests/test_pybcsv_sampler.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pybcsv
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.10.dev0
|
|
4
4
|
Summary: High-performance Python bindings for the BCSV (Binary CSV) library with pandas integration
|
|
5
5
|
Keywords: csv,binary,data-science,compression,performance,pandas,numpy,big-data,data-processing
|
|
6
6
|
Author-Email: Tobias Weber <weber.tobias.md@gmail.com>
|
|
@@ -156,6 +156,44 @@ with pybcsv.ReaderDirectAccess() as da:
|
|
|
156
156
|
print(da.read(100)) # alternative syntax
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
+
## Parquet Conversion Tools (CLI)
|
|
160
|
+
|
|
161
|
+
Installing `pybcsv` provides two streaming command-line converters (require the
|
|
162
|
+
`arrow` extra: `pip install pybcsv[arrow]`). They stream in bounded batches, so
|
|
163
|
+
they handle files larger than memory.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Parquet → BCSV
|
|
167
|
+
parquet2bcsv input.parquet -o output.bcsv
|
|
168
|
+
# --row-codec {delta,zoh,flat} row codec (default: delta)
|
|
169
|
+
# --file-codec {packet_lz4_batch,...} file codec (default: packet_lz4_batch)
|
|
170
|
+
# --chunk-size N rows per streamed batch (default: 512000)
|
|
171
|
+
# -f/--force overwrite an existing output
|
|
172
|
+
|
|
173
|
+
# BCSV → Parquet
|
|
174
|
+
bcsv2parquet input.bcsv -o output.parquet
|
|
175
|
+
# --columns "a,b,c" select/reorder columns (order is honored)
|
|
176
|
+
# --slice 10:100 Python-style row slice
|
|
177
|
+
# --unflatten (default) reconstruct nested structs from dotted/bracketed names
|
|
178
|
+
# --no-unflatten keep flat columns (names like 'a.b', 'vals[0]')
|
|
179
|
+
# --parquet-compression {none,snappy,gzip,zstd,lz4}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Schema mapping.** Parquet structs and fixed-size lists are *flattened* to BCSV
|
|
183
|
+
columns using dotted (`location.lat`) and bracketed (`vals[0]`) names;
|
|
184
|
+
`bcsv2parquet --unflatten` reverses this. Notes and limitations:
|
|
185
|
+
|
|
186
|
+
- **No nulls:** BCSV has no null representation — a null in any converted column
|
|
187
|
+
is rejected with the offending row number. Filter nulls before converting.
|
|
188
|
+
- **Type widening:** `float16`/`bfloat16` widen to `float32`; `large_string`
|
|
189
|
+
maps to `string`.
|
|
190
|
+
- **Unsupported types** (variable-length lists, maps, timestamps, decimals,
|
|
191
|
+
dictionaries) are rejected with a clear error.
|
|
192
|
+
- **Column names ending in `_`** are rejected (the unflatten escape protocol
|
|
193
|
+
reserves trailing underscores).
|
|
194
|
+
- **Colliding names:** if a literal dotted column (`a.b`) and a struct path both
|
|
195
|
+
map to the same nested path, `--unflatten` fails loudly; use `--no-unflatten`.
|
|
196
|
+
|
|
159
197
|
## Available Types
|
|
160
198
|
|
|
161
199
|
| Constant | Description |
|
|
@@ -110,6 +110,44 @@ with pybcsv.ReaderDirectAccess() as da:
|
|
|
110
110
|
print(da.read(100)) # alternative syntax
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
+
## Parquet Conversion Tools (CLI)
|
|
114
|
+
|
|
115
|
+
Installing `pybcsv` provides two streaming command-line converters (require the
|
|
116
|
+
`arrow` extra: `pip install pybcsv[arrow]`). They stream in bounded batches, so
|
|
117
|
+
they handle files larger than memory.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Parquet → BCSV
|
|
121
|
+
parquet2bcsv input.parquet -o output.bcsv
|
|
122
|
+
# --row-codec {delta,zoh,flat} row codec (default: delta)
|
|
123
|
+
# --file-codec {packet_lz4_batch,...} file codec (default: packet_lz4_batch)
|
|
124
|
+
# --chunk-size N rows per streamed batch (default: 512000)
|
|
125
|
+
# -f/--force overwrite an existing output
|
|
126
|
+
|
|
127
|
+
# BCSV → Parquet
|
|
128
|
+
bcsv2parquet input.bcsv -o output.parquet
|
|
129
|
+
# --columns "a,b,c" select/reorder columns (order is honored)
|
|
130
|
+
# --slice 10:100 Python-style row slice
|
|
131
|
+
# --unflatten (default) reconstruct nested structs from dotted/bracketed names
|
|
132
|
+
# --no-unflatten keep flat columns (names like 'a.b', 'vals[0]')
|
|
133
|
+
# --parquet-compression {none,snappy,gzip,zstd,lz4}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Schema mapping.** Parquet structs and fixed-size lists are *flattened* to BCSV
|
|
137
|
+
columns using dotted (`location.lat`) and bracketed (`vals[0]`) names;
|
|
138
|
+
`bcsv2parquet --unflatten` reverses this. Notes and limitations:
|
|
139
|
+
|
|
140
|
+
- **No nulls:** BCSV has no null representation — a null in any converted column
|
|
141
|
+
is rejected with the offending row number. Filter nulls before converting.
|
|
142
|
+
- **Type widening:** `float16`/`bfloat16` widen to `float32`; `large_string`
|
|
143
|
+
maps to `string`.
|
|
144
|
+
- **Unsupported types** (variable-length lists, maps, timestamps, decimals,
|
|
145
|
+
dictionaries) are rejected with a clear error.
|
|
146
|
+
- **Column names ending in `_`** are rejected (the unflatten escape protocol
|
|
147
|
+
reserves trailing underscores).
|
|
148
|
+
- **Colliding names:** if a literal dotted column (`a.b`) and a struct path both
|
|
149
|
+
map to the same nested path, `--unflatten` fails loudly; use `--no-unflatten`.
|
|
150
|
+
|
|
113
151
|
## Available Types
|
|
114
152
|
|
|
115
153
|
| Constant | Description |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.5.9
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Copyright (c) 2025-2026 Tobias Weber <weber.tobias.md@gmail.com>
|
|
2
|
-
#
|
|
2
|
+
#
|
|
3
3
|
# This file is part of the BCSV library.
|
|
4
|
-
#
|
|
5
|
-
# Licensed under the MIT License. See LICENSE file in the project root
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the MIT License. See LICENSE file in the project root
|
|
6
6
|
# for full license information.
|
|
7
7
|
|
|
8
8
|
"""pybcsv - Python bindings for the BCSV library."""
|
|
@@ -12,10 +12,12 @@ from .__version__ import __version__
|
|
|
12
12
|
# Import the compiled extension module — fail immediately if not available
|
|
13
13
|
try:
|
|
14
14
|
from ._bcsv import *
|
|
15
|
+
|
|
15
16
|
_BINDINGS_AVAILABLE = True
|
|
16
17
|
except ImportError:
|
|
17
18
|
try:
|
|
18
|
-
from _bcsv import *
|
|
19
|
+
from _bcsv import * # fallback for legacy in-tree builds
|
|
20
|
+
|
|
19
21
|
_BINDINGS_AVAILABLE = True
|
|
20
22
|
except ImportError as _exc:
|
|
21
23
|
raise ImportError(
|
|
@@ -27,35 +29,86 @@ except ImportError:
|
|
|
27
29
|
# Try to import pandas utilities if pandas is available
|
|
28
30
|
try:
|
|
29
31
|
from .pandas_utils import write_dataframe, read_dataframe, to_csv, from_csv
|
|
32
|
+
|
|
30
33
|
_PANDAS_UTILS_AVAILABLE = True
|
|
31
34
|
except ImportError:
|
|
32
35
|
_PANDAS_UTILS_AVAILABLE = False
|
|
33
|
-
|
|
36
|
+
|
|
34
37
|
# Create stub functions that raise ImportError
|
|
35
38
|
def write_dataframe(*args, **kwargs):
|
|
36
|
-
raise ImportError(
|
|
37
|
-
|
|
39
|
+
raise ImportError(
|
|
40
|
+
"pandas is not available. Please install pandas to use DataFrame functions."
|
|
41
|
+
)
|
|
42
|
+
|
|
38
43
|
def read_dataframe(*args, **kwargs):
|
|
39
|
-
raise ImportError(
|
|
40
|
-
|
|
44
|
+
raise ImportError(
|
|
45
|
+
"pandas is not available. Please install pandas to use DataFrame functions."
|
|
46
|
+
)
|
|
47
|
+
|
|
41
48
|
def to_csv(*args, **kwargs):
|
|
42
|
-
raise ImportError(
|
|
43
|
-
|
|
49
|
+
raise ImportError(
|
|
50
|
+
"pandas is not available. Please install pandas to use CSV conversion functions."
|
|
51
|
+
)
|
|
52
|
+
|
|
44
53
|
def from_csv(*args, **kwargs):
|
|
45
|
-
raise ImportError(
|
|
54
|
+
raise ImportError(
|
|
55
|
+
"pandas is not available. Please install pandas to use CSV conversion functions."
|
|
56
|
+
)
|
|
57
|
+
|
|
46
58
|
|
|
47
59
|
# Try to import Polars utilities if polars + pyarrow are available
|
|
48
60
|
try:
|
|
49
61
|
from .polars_utils import read_polars, write_polars
|
|
62
|
+
|
|
50
63
|
_POLARS_UTILS_AVAILABLE = True
|
|
51
64
|
except ImportError:
|
|
52
65
|
_POLARS_UTILS_AVAILABLE = False
|
|
53
66
|
|
|
54
67
|
def read_polars(*args, **kwargs):
|
|
55
|
-
raise ImportError(
|
|
68
|
+
raise ImportError(
|
|
69
|
+
"polars and pyarrow are required. Install with: pip install pybcsv[polars,arrow]"
|
|
70
|
+
)
|
|
56
71
|
|
|
57
72
|
def write_polars(*args, **kwargs):
|
|
58
|
-
raise ImportError(
|
|
73
|
+
raise ImportError(
|
|
74
|
+
"polars and pyarrow are required. Install with: pip install pybcsv[polars,arrow]"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# Try to import Parquet utilities if pyarrow is available
|
|
79
|
+
try:
|
|
80
|
+
from .parquet_utils import parquet_to_bcsv, bcsv_to_parquet
|
|
81
|
+
|
|
82
|
+
_PARQUET_AVAILABLE = True
|
|
83
|
+
except ImportError:
|
|
84
|
+
_PARQUET_AVAILABLE = False
|
|
85
|
+
|
|
86
|
+
def parquet_to_bcsv(*args, **kwargs):
|
|
87
|
+
raise ImportError(
|
|
88
|
+
"pyarrow is required for Parquet conversion. "
|
|
89
|
+
"Install with: pip install pybcsv[arrow]"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def bcsv_to_parquet(*args, **kwargs):
|
|
93
|
+
raise ImportError(
|
|
94
|
+
"pyarrow is required for Parquet conversion. "
|
|
95
|
+
"Install with: pip install pybcsv[arrow]"
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def iter_arrow_batches(reader, *, batch_size=512000, columns=None, start_row=0):
|
|
100
|
+
"""Yield pa.RecordBatch objects from an already-open ReaderDirectAccess.
|
|
101
|
+
|
|
102
|
+
Memory-bounded: exactly one batch is held at a time. `reader` must be open.
|
|
103
|
+
"""
|
|
104
|
+
pos = start_row
|
|
105
|
+
while True:
|
|
106
|
+
batch = reader.read_arrow_batch(pos, batch_size, columns)
|
|
107
|
+
if batch is None:
|
|
108
|
+
break
|
|
109
|
+
yield batch
|
|
110
|
+
pos += batch.num_rows
|
|
111
|
+
|
|
59
112
|
|
|
60
113
|
__all__ = [
|
|
61
114
|
"__version__",
|
|
@@ -80,6 +133,10 @@ __all__ = [
|
|
|
80
133
|
# Arrow interop
|
|
81
134
|
"read_to_arrow",
|
|
82
135
|
"write_from_arrow",
|
|
136
|
+
"iter_arrow_batches",
|
|
137
|
+
# Parquet interop
|
|
138
|
+
"parquet_to_bcsv",
|
|
139
|
+
"bcsv_to_parquet",
|
|
83
140
|
# Polars interop
|
|
84
141
|
"read_polars",
|
|
85
142
|
"write_polars",
|
|
@@ -89,4 +146,4 @@ __all__ = [
|
|
|
89
146
|
"read_dataframe",
|
|
90
147
|
"to_csv",
|
|
91
148
|
"from_csv",
|
|
92
|
-
]
|
|
149
|
+
]
|
|
@@ -48,15 +48,12 @@ def write_dataframe(
|
|
|
48
48
|
type_hints: Optional[Dict[str, ColumnType]] = None,
|
|
49
49
|
strict: bool = False,
|
|
50
50
|
) -> None: ...
|
|
51
|
-
|
|
52
51
|
def read_dataframe(
|
|
53
52
|
filename: str,
|
|
54
53
|
columns: Optional[list] = None,
|
|
55
54
|
optimize_dtypes: bool = True,
|
|
56
55
|
) -> object: ...
|
|
57
|
-
|
|
58
56
|
def to_csv(bcsv_filename: str, csv_filename: str, **csv_kwargs: object) -> None: ...
|
|
59
|
-
|
|
60
57
|
def from_csv(
|
|
61
58
|
csv_filename: str,
|
|
62
59
|
bcsv_filename: str,
|
|
@@ -64,16 +61,21 @@ def from_csv(
|
|
|
64
61
|
type_hints: Optional[Dict[str, ColumnType]] = None,
|
|
65
62
|
**csv_kwargs: object,
|
|
66
63
|
) -> None: ...
|
|
67
|
-
|
|
68
64
|
def read_polars(
|
|
69
65
|
filename: str,
|
|
70
66
|
columns: object = None,
|
|
71
67
|
chunk_size: int = 0,
|
|
72
68
|
) -> object: ...
|
|
73
|
-
|
|
74
69
|
def write_polars(
|
|
75
70
|
df: object,
|
|
76
71
|
filename: str,
|
|
77
72
|
row_codec: str = "delta",
|
|
78
73
|
compression_level: int = 1,
|
|
79
74
|
) -> None: ...
|
|
75
|
+
def iter_arrow_batches(
|
|
76
|
+
reader: ReaderDirectAccess,
|
|
77
|
+
*,
|
|
78
|
+
batch_size: int = 512000,
|
|
79
|
+
columns: Optional[list] = None,
|
|
80
|
+
start_row: int = 0,
|
|
81
|
+
) -> object: ... # yields pa.RecordBatch
|
|
@@ -4,7 +4,6 @@ from collections.abc import Sequence
|
|
|
4
4
|
import enum
|
|
5
5
|
from typing import overload
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
class ColumnType(enum.Enum):
|
|
9
8
|
BOOL = 0
|
|
10
9
|
|
|
@@ -56,54 +55,35 @@ STRING: ColumnType = ColumnType.STRING
|
|
|
56
55
|
|
|
57
56
|
class ColumnDefinition:
|
|
58
57
|
def __init__(self, name: str, type: ColumnType) -> None: ...
|
|
59
|
-
|
|
60
58
|
@property
|
|
61
59
|
def name(self) -> str: ...
|
|
62
|
-
|
|
63
60
|
@name.setter
|
|
64
61
|
def name(self, arg: str, /) -> None: ...
|
|
65
|
-
|
|
66
62
|
@property
|
|
67
63
|
def type(self) -> ColumnType: ...
|
|
68
|
-
|
|
69
64
|
@type.setter
|
|
70
65
|
def type(self, arg: ColumnType, /) -> None: ...
|
|
71
|
-
|
|
72
66
|
def __repr__(self) -> str: ...
|
|
73
67
|
|
|
74
68
|
class Layout:
|
|
75
69
|
@overload
|
|
76
70
|
def __init__(self) -> None: ...
|
|
77
|
-
|
|
78
71
|
@overload
|
|
79
72
|
def __init__(self, arg: Sequence[ColumnDefinition], /) -> None: ...
|
|
80
|
-
|
|
81
73
|
@overload
|
|
82
74
|
def add_column(self, column: ColumnDefinition) -> None: ...
|
|
83
|
-
|
|
84
75
|
@overload
|
|
85
76
|
def add_column(self, name: str, type: ColumnType) -> None: ...
|
|
86
|
-
|
|
87
77
|
def column_count(self) -> int: ...
|
|
88
|
-
|
|
89
78
|
def column_name(self, index: int) -> str: ...
|
|
90
|
-
|
|
91
79
|
def column_type(self, index: int) -> ColumnType: ...
|
|
92
|
-
|
|
93
80
|
def has_column(self, name: str) -> bool: ...
|
|
94
|
-
|
|
95
81
|
def column_index(self, name: str) -> int: ...
|
|
96
|
-
|
|
97
82
|
def get_column_names(self) -> list[str]: ...
|
|
98
|
-
|
|
99
83
|
def get_column_types(self) -> list[ColumnType]: ...
|
|
100
|
-
|
|
101
84
|
def get_column(self, index: int) -> ColumnDefinition: ...
|
|
102
|
-
|
|
103
85
|
def __len__(self) -> int: ...
|
|
104
|
-
|
|
105
86
|
def __getitem__(self, arg: int, /) -> ColumnDefinition: ...
|
|
106
|
-
|
|
107
87
|
def __repr__(self) -> str: ...
|
|
108
88
|
|
|
109
89
|
class FileFlags(enum.IntEnum):
|
|
@@ -120,9 +100,7 @@ class FileFlags(enum.IntEnum):
|
|
|
120
100
|
DELTA_ENCODING = 16
|
|
121
101
|
|
|
122
102
|
def __or__(self, arg: FileFlags, /) -> int: ...
|
|
123
|
-
|
|
124
103
|
def __and__(self, arg: FileFlags, /) -> int: ...
|
|
125
|
-
|
|
126
104
|
def __invert__(self) -> int: ...
|
|
127
105
|
|
|
128
106
|
NONE: FileFlags = FileFlags.NONE
|
|
@@ -138,58 +116,43 @@ BATCH_COMPRESS: FileFlags = FileFlags.BATCH_COMPRESS
|
|
|
138
116
|
DELTA_ENCODING: FileFlags = FileFlags.DELTA_ENCODING
|
|
139
117
|
|
|
140
118
|
class Writer:
|
|
141
|
-
def __init__(self, layout: Layout, row_codec: str =
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
119
|
+
def __init__(self, layout: Layout, row_codec: str = "delta") -> None: ...
|
|
120
|
+
def open(
|
|
121
|
+
self,
|
|
122
|
+
filename: str,
|
|
123
|
+
overwrite: bool = False,
|
|
124
|
+
compression_level: int = 1,
|
|
125
|
+
block_size_kb: int = 8192,
|
|
126
|
+
flags: FileFlags = FileFlags.BATCH_COMPRESS,
|
|
127
|
+
) -> bool: ...
|
|
145
128
|
def write_row(self, arg: list, /) -> None: ...
|
|
146
|
-
|
|
147
129
|
def write_rows(self, arg: list, /) -> None:
|
|
148
130
|
"""Write multiple rows efficiently with batching"""
|
|
149
131
|
|
|
150
132
|
def close(self) -> None: ...
|
|
151
|
-
|
|
152
133
|
def flush(self) -> None: ...
|
|
153
|
-
|
|
154
134
|
def is_open(self) -> bool: ...
|
|
155
|
-
|
|
156
135
|
def row_count(self) -> int: ...
|
|
157
|
-
|
|
158
136
|
def row_codec(self) -> str: ...
|
|
159
|
-
|
|
160
137
|
def compression_level(self) -> int: ...
|
|
161
|
-
|
|
162
138
|
def layout(self) -> Layout: ...
|
|
163
|
-
|
|
139
|
+
def write_batch(self, batch: object) -> None: ... # batch: pa.RecordBatch
|
|
164
140
|
def __enter__(self) -> Writer: ...
|
|
165
|
-
|
|
166
141
|
def __exit__(self, *args) -> None: ...
|
|
167
|
-
|
|
168
142
|
def __repr__(self) -> str: ...
|
|
169
143
|
|
|
170
144
|
class Reader:
|
|
171
145
|
def __init__(self) -> None: ...
|
|
172
|
-
|
|
173
146
|
def open(self, filename: str) -> bool: ...
|
|
174
|
-
|
|
175
147
|
def layout(self) -> Layout: ...
|
|
176
|
-
|
|
177
148
|
def read_next(self) -> bool: ...
|
|
178
|
-
|
|
179
149
|
def close(self) -> None: ...
|
|
180
|
-
|
|
181
150
|
def is_open(self) -> bool: ...
|
|
182
|
-
|
|
183
151
|
def file_flags(self) -> int: ...
|
|
184
|
-
|
|
185
152
|
def compression_level(self) -> int: ...
|
|
186
|
-
|
|
187
153
|
def row_pos(self) -> int: ...
|
|
188
|
-
|
|
189
154
|
def version_string(self) -> str: ...
|
|
190
|
-
|
|
191
155
|
def creation_time(self) -> int: ...
|
|
192
|
-
|
|
193
156
|
def count_rows(self) -> int:
|
|
194
157
|
"""Count the total number of rows in the file"""
|
|
195
158
|
|
|
@@ -205,115 +168,79 @@ class Reader:
|
|
|
205
168
|
"""
|
|
206
169
|
|
|
207
170
|
def read_row(self) -> object: ...
|
|
208
|
-
|
|
209
171
|
def read_all(self) -> list: ...
|
|
210
|
-
|
|
211
172
|
def __enter__(self) -> Reader: ...
|
|
212
|
-
|
|
213
173
|
def __exit__(self, *args) -> None: ...
|
|
214
|
-
|
|
215
174
|
def __iter__(self) -> Reader: ...
|
|
216
|
-
|
|
217
175
|
def __next__(self) -> object: ...
|
|
218
|
-
|
|
219
176
|
def __repr__(self) -> str: ...
|
|
220
177
|
|
|
221
178
|
def type_to_string(arg: ColumnType, /) -> str:
|
|
222
179
|
"""Convert ColumnType to string"""
|
|
223
180
|
|
|
224
181
|
class CsvWriter:
|
|
225
|
-
def __init__(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
182
|
+
def __init__(
|
|
183
|
+
self, layout: Layout, delimiter: str = ",", decimal_sep: str = "."
|
|
184
|
+
) -> None: ...
|
|
185
|
+
def open(
|
|
186
|
+
self, filename: str, overwrite: bool = False, include_header: bool = True
|
|
187
|
+
) -> bool: ...
|
|
229
188
|
def close(self) -> None: ...
|
|
230
|
-
|
|
231
189
|
def is_open(self) -> bool: ...
|
|
232
|
-
|
|
233
190
|
def row_count(self) -> int: ...
|
|
234
|
-
|
|
235
191
|
def layout(self) -> Layout: ...
|
|
236
|
-
|
|
237
192
|
def delimiter(self) -> str: ...
|
|
238
|
-
|
|
239
193
|
def decimal_separator(self) -> str: ...
|
|
240
|
-
|
|
241
194
|
def __enter__(self) -> CsvWriter: ...
|
|
242
|
-
|
|
243
195
|
def __exit__(self, *args) -> None: ...
|
|
244
|
-
|
|
245
196
|
def write_row(self, arg: list, /) -> None: ...
|
|
246
|
-
|
|
247
197
|
def write_rows(self, arg: list, /) -> None:
|
|
248
198
|
"""Write multiple rows efficiently"""
|
|
249
199
|
|
|
250
200
|
class CsvReader:
|
|
251
|
-
def __init__(
|
|
252
|
-
|
|
201
|
+
def __init__(
|
|
202
|
+
self, layout: Layout, delimiter: str = ",", decimal_sep: str = "."
|
|
203
|
+
) -> None: ...
|
|
253
204
|
def open(self, filename: str, has_header: bool = True) -> bool: ...
|
|
254
|
-
|
|
255
205
|
def read_next(self) -> bool: ...
|
|
256
|
-
|
|
257
206
|
def close(self) -> None: ...
|
|
258
|
-
|
|
259
207
|
def is_open(self) -> bool: ...
|
|
260
|
-
|
|
261
208
|
def row_pos(self) -> int: ...
|
|
262
|
-
|
|
263
209
|
def file_line(self) -> int: ...
|
|
264
|
-
|
|
265
210
|
def layout(self) -> Layout: ...
|
|
266
|
-
|
|
267
211
|
def delimiter(self) -> str: ...
|
|
268
|
-
|
|
269
212
|
def decimal_separator(self) -> str: ...
|
|
270
|
-
|
|
271
213
|
def error_msg(self) -> str: ...
|
|
272
|
-
|
|
273
214
|
def read_row(self) -> object: ...
|
|
274
|
-
|
|
275
215
|
def read_all(self) -> list: ...
|
|
276
|
-
|
|
277
216
|
def __enter__(self) -> CsvReader: ...
|
|
278
|
-
|
|
279
217
|
def __exit__(self, *args) -> None: ...
|
|
280
|
-
|
|
281
218
|
def __iter__(self) -> CsvReader: ...
|
|
282
|
-
|
|
283
219
|
def __next__(self) -> object: ...
|
|
284
220
|
|
|
285
221
|
class ReaderDirectAccess:
|
|
286
222
|
def __init__(self) -> None: ...
|
|
287
|
-
|
|
288
223
|
def open(self, filename: str, rebuild_footer: bool = False) -> bool: ...
|
|
289
|
-
|
|
290
224
|
def read(self, index: int) -> list: ...
|
|
291
|
-
|
|
292
225
|
def row_count(self) -> int: ...
|
|
293
|
-
|
|
294
226
|
def layout(self) -> Layout: ...
|
|
295
|
-
|
|
296
227
|
def close(self) -> None: ...
|
|
297
|
-
|
|
298
228
|
def is_open(self) -> bool: ...
|
|
299
|
-
|
|
300
229
|
def file_flags(self) -> int: ...
|
|
301
|
-
|
|
302
230
|
def compression_level(self) -> int: ...
|
|
303
|
-
|
|
304
231
|
def version_string(self) -> str: ...
|
|
305
|
-
|
|
306
232
|
def creation_time(self) -> int: ...
|
|
307
|
-
|
|
308
233
|
def __enter__(self) -> ReaderDirectAccess: ...
|
|
309
|
-
|
|
310
234
|
def __exit__(self, *args) -> None: ...
|
|
311
|
-
|
|
312
235
|
def __len__(self) -> int: ...
|
|
313
|
-
|
|
314
236
|
def __getitem__(self, arg: int, /) -> list: ...
|
|
315
|
-
|
|
316
237
|
def __repr__(self) -> str: ...
|
|
238
|
+
def read_arrow_batch(
|
|
239
|
+
self,
|
|
240
|
+
start_row: int = 0,
|
|
241
|
+
batch_size: int = 512000,
|
|
242
|
+
columns: list[str] | None = None,
|
|
243
|
+
) -> object: ... # returns pa.RecordBatch or None at EOF
|
|
317
244
|
|
|
318
245
|
class SamplerMode(enum.Enum):
|
|
319
246
|
TRUNCATE = 0
|
|
@@ -340,56 +267,33 @@ SATURATE: SamplerErrorPolicy = SamplerErrorPolicy.SATURATE
|
|
|
340
267
|
class SamplerCompileResult:
|
|
341
268
|
@property
|
|
342
269
|
def success(self) -> bool: ...
|
|
343
|
-
|
|
344
270
|
@property
|
|
345
271
|
def error_msg(self) -> str: ...
|
|
346
|
-
|
|
347
272
|
@property
|
|
348
273
|
def error_position(self) -> int: ...
|
|
349
|
-
|
|
350
274
|
def __bool__(self) -> bool: ...
|
|
351
|
-
|
|
352
275
|
def __repr__(self) -> str: ...
|
|
353
276
|
|
|
354
277
|
class Sampler:
|
|
355
278
|
def __init__(self, reader: Reader) -> None: ...
|
|
356
|
-
|
|
357
279
|
def set_conditional(self, expr: str) -> SamplerCompileResult: ...
|
|
358
|
-
|
|
359
280
|
def get_conditional(self) -> str: ...
|
|
360
|
-
|
|
361
281
|
def set_selection(self, expr: str) -> SamplerCompileResult: ...
|
|
362
|
-
|
|
363
282
|
def get_selection(self) -> str: ...
|
|
364
|
-
|
|
365
283
|
def set_mode(self, mode: SamplerMode) -> None: ...
|
|
366
|
-
|
|
367
284
|
def get_mode(self) -> SamplerMode: ...
|
|
368
|
-
|
|
369
285
|
def set_error_policy(self, policy: SamplerErrorPolicy) -> None: ...
|
|
370
|
-
|
|
371
286
|
def get_error_policy(self) -> SamplerErrorPolicy: ...
|
|
372
|
-
|
|
373
287
|
def output_layout(self) -> Layout: ...
|
|
374
|
-
|
|
375
288
|
def next(self) -> bool: ...
|
|
376
|
-
|
|
377
289
|
def row(self) -> list: ...
|
|
378
|
-
|
|
379
290
|
def source_row_pos(self) -> int: ...
|
|
380
|
-
|
|
381
291
|
def bulk(self) -> list: ...
|
|
382
|
-
|
|
383
292
|
def is_conditional_passthrough(self) -> bool: ...
|
|
384
|
-
|
|
385
293
|
def is_selection_passthrough(self) -> bool: ...
|
|
386
|
-
|
|
387
294
|
def window_capacity(self) -> int: ...
|
|
388
|
-
|
|
389
295
|
def disassemble(self) -> str: ...
|
|
390
|
-
|
|
391
296
|
def __iter__(self) -> Sampler: ...
|
|
392
|
-
|
|
393
297
|
def __next__(self) -> object: ...
|
|
394
298
|
|
|
395
299
|
def read_columns(filename: str) -> dict:
|
|
@@ -397,14 +301,30 @@ def read_columns(filename: str) -> dict:
|
|
|
397
301
|
Read a BCSV file into a dict of numpy arrays (numeric) and lists (strings)
|
|
398
302
|
"""
|
|
399
303
|
|
|
400
|
-
def write_columns(
|
|
304
|
+
def write_columns(
|
|
305
|
+
filename: str,
|
|
306
|
+
columns: dict,
|
|
307
|
+
col_order: list,
|
|
308
|
+
col_types: list,
|
|
309
|
+
row_codec: str = "delta",
|
|
310
|
+
compression_level: int = 1,
|
|
311
|
+
flags: FileFlags = FileFlags.BATCH_COMPRESS,
|
|
312
|
+
) -> None:
|
|
401
313
|
"""Write a dict of numpy arrays/lists to a BCSV file"""
|
|
402
314
|
|
|
403
|
-
def read_to_arrow(
|
|
315
|
+
def read_to_arrow(
|
|
316
|
+
filename: str, columns: list | None = None, chunk_size: int = 0
|
|
317
|
+
) -> object:
|
|
404
318
|
"""
|
|
405
319
|
Read a BCSV file into a pyarrow.Table via Arrow C Data Interface (zero-copy).
|
|
406
320
|
Set chunk_size > 0 for chunked reading (returns Table from multiple batches).
|
|
407
321
|
"""
|
|
408
322
|
|
|
409
|
-
def write_from_arrow(
|
|
323
|
+
def write_from_arrow(
|
|
324
|
+
filename: str,
|
|
325
|
+
table: object,
|
|
326
|
+
row_codec: str = "delta",
|
|
327
|
+
compression_level: int = 1,
|
|
328
|
+
flags: FileFlags = FileFlags.BATCH_COMPRESS,
|
|
329
|
+
) -> None:
|
|
410
330
|
"""Write a pyarrow Table/RecordBatch to a BCSV file"""
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.5.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 5,
|
|
21
|
+
__version__ = version = '1.5.10.dev0'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 5, 10, 'dev0')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g6ec074145'
|