twobitreader-rs 0.2.2__tar.gz → 0.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.
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/CHANGELOG.md +22 -6
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/Cargo.lock +23 -23
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/Cargo.toml +1 -1
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/PKG-INFO +1 -1
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/README.md +20 -14
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/src/lib.rs +11 -16
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/LICENSE-APACHE +0 -0
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/LICENSE-MIT +0 -0
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/README-PY.md +0 -0
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/custom.css +0 -0
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/py.typed +0 -0
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/pyproject.toml +0 -0
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/src/decode.rs +0 -0
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/src/prefetch.rs +0 -0
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/src/python.rs +0 -0
- {twobitreader_rs-0.2.2 → twobitreader_rs-0.2.3}/twobitreader_rs.pyi +0 -0
|
@@ -4,10 +4,25 @@ All notable changes to this project are documented here.
|
|
|
4
4
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this
|
|
6
6
|
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). The Rust
|
|
7
|
-
crate `twobitreader` and the Python package `
|
|
7
|
+
crate `twobitreader` and the Python package `twobitreader-rs` share a version number.
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [0.2.3] - 2026-11-03
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- `TwobitReader::open` no longer rejects a valid 2bit file that contains exactly one sequence
|
|
16
|
+
record. The record's data starts immediately after the index, so its offset equals the end
|
|
17
|
+
of the index, which the offset check wrongly treated as invalid.
|
|
18
|
+
- Missing word and a misplaced sentence in the Benchmarks section of the documentation.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- README.md is now generated from the crate documentation with `cargo rdme`, and CI checks
|
|
23
|
+
that it is up to date. The badges moved from the crate documentation into README.md, so
|
|
24
|
+
they no longer appear on docs.rs.
|
|
25
|
+
|
|
11
26
|
## [0.2.2] - 2026-10-01
|
|
12
27
|
|
|
13
28
|
### Added
|
|
@@ -16,7 +31,7 @@ crate `twobitreader` and the Python package `twobitreader_rs` share a version nu
|
|
|
16
31
|
|
|
17
32
|
## [0.2.1] - 2026-10-01
|
|
18
33
|
|
|
19
|
-
First release of `
|
|
34
|
+
First release of `twobitreader-rs` on PyPI. There are no library changes; 0.2.0 reached
|
|
20
35
|
crates.io before the wheel-building workflow was in place, so it was never published for
|
|
21
36
|
Python.
|
|
22
37
|
|
|
@@ -31,13 +46,13 @@ Python.
|
|
|
31
46
|
|
|
32
47
|
## [0.2.0] - 2026-10-01
|
|
33
48
|
|
|
34
|
-
`twobitreader` is now available from Python as **`
|
|
49
|
+
`twobitreader` is now available from Python as **`twobitreader-rs`**, built with PyO3 and
|
|
35
50
|
published as a wheel. The Python API mirrors the Rust one, with speed close to pure Rust.
|
|
36
51
|
|
|
37
52
|
### Added
|
|
38
53
|
|
|
39
|
-
- **Python bindings** (`twobitreader_rs`), exposing `TwobitReader` and
|
|
40
|
-
Available for CPython 3.9+ on Linux, macOS and Windows.
|
|
54
|
+
- **Python bindings** (`import twobitreader_rs`), exposing `TwobitReader` and
|
|
55
|
+
`reverse_complement`. Available for CPython 3.9+ on Linux, macOS and Windows.
|
|
41
56
|
- **Free-threaded CPython support.** The extension is marked `gil_used = false` and the
|
|
42
57
|
reader is immutable and shareable. A thread pool over batches scales across cores on a
|
|
43
58
|
free-threaded build.
|
|
@@ -71,7 +86,8 @@ extraction with `get_batch`, exon concatenation with `concat`, reverse complemen
|
|
|
71
86
|
`prefetch` for cold files. Sequence records are parsed lazily so that opening a large file
|
|
72
87
|
stays cheap. No git tag was made for this version.
|
|
73
88
|
|
|
74
|
-
[Unreleased]: https://github.com/andrewdelong/twobitreader-rust/compare/v0.2.
|
|
89
|
+
[Unreleased]: https://github.com/andrewdelong/twobitreader-rust/compare/v0.2.3...HEAD
|
|
90
|
+
[0.2.3]: https://github.com/andrewdelong/twobitreader-rust/compare/v0.2.2...v0.2.3
|
|
75
91
|
[0.2.2]: https://github.com/andrewdelong/twobitreader-rust/compare/v0.2.1...v0.2.2
|
|
76
92
|
[0.2.1]: https://github.com/andrewdelong/twobitreader-rust/compare/v0.2.0...v0.2.1
|
|
77
93
|
[0.2.0]: https://github.com/andrewdelong/twobitreader-rust/compare/v0.1.1...v0.2.0
|
|
@@ -22,9 +22,9 @@ checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
|
|
|
22
22
|
|
|
23
23
|
[[package]]
|
|
24
24
|
name = "crc32fast"
|
|
25
|
-
version = "1.5.
|
|
25
|
+
version = "1.5.4"
|
|
26
26
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
-
checksum = "
|
|
27
|
+
checksum = "5f97d3416d5337d15c4b0d78c8c91df922ca143f57ec20e2d1c188333047ef04"
|
|
28
28
|
dependencies = [
|
|
29
29
|
"cfg-if",
|
|
30
30
|
]
|
|
@@ -56,9 +56,9 @@ checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6"
|
|
|
56
56
|
|
|
57
57
|
[[package]]
|
|
58
58
|
name = "either"
|
|
59
|
-
version = "1.
|
|
59
|
+
version = "1.19.0"
|
|
60
60
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
61
|
-
checksum = "
|
|
61
|
+
checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be"
|
|
62
62
|
|
|
63
63
|
[[package]]
|
|
64
64
|
name = "flate2"
|
|
@@ -88,15 +88,15 @@ dependencies = [
|
|
|
88
88
|
|
|
89
89
|
[[package]]
|
|
90
90
|
name = "libc"
|
|
91
|
-
version = "0.2.
|
|
91
|
+
version = "0.2.191"
|
|
92
92
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
93
|
-
checksum = "
|
|
93
|
+
checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
|
|
94
94
|
|
|
95
95
|
[[package]]
|
|
96
96
|
name = "memmap2"
|
|
97
|
-
version = "0.9.
|
|
97
|
+
version = "0.9.12"
|
|
98
98
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
99
|
-
checksum = "
|
|
99
|
+
checksum = "6b0ca1155a9ecc25aa12e8313a119f32edf0255fea2f44839c4ac0a12b2ac157"
|
|
100
100
|
dependencies = [
|
|
101
101
|
"libc",
|
|
102
102
|
]
|
|
@@ -134,9 +134,9 @@ dependencies = [
|
|
|
134
134
|
|
|
135
135
|
[[package]]
|
|
136
136
|
name = "pyo3"
|
|
137
|
-
version = "0.
|
|
137
|
+
version = "0.30.1"
|
|
138
138
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
139
|
-
checksum = "
|
|
139
|
+
checksum = "229ca13b8a15bb0d1487b81ab975bfcd97513416499a8312011b6036e42e0de4"
|
|
140
140
|
dependencies = [
|
|
141
141
|
"libc",
|
|
142
142
|
"once_cell",
|
|
@@ -148,18 +148,18 @@ dependencies = [
|
|
|
148
148
|
|
|
149
149
|
[[package]]
|
|
150
150
|
name = "pyo3-build-config"
|
|
151
|
-
version = "0.
|
|
151
|
+
version = "0.30.1"
|
|
152
152
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
153
|
-
checksum = "
|
|
153
|
+
checksum = "70130e2b6dd1ee589a8788026a429561ca5c40fa7a2fa7914c2282eddae24700"
|
|
154
154
|
dependencies = [
|
|
155
155
|
"target-lexicon",
|
|
156
156
|
]
|
|
157
157
|
|
|
158
158
|
[[package]]
|
|
159
159
|
name = "pyo3-ffi"
|
|
160
|
-
version = "0.
|
|
160
|
+
version = "0.30.1"
|
|
161
161
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
162
|
-
checksum = "
|
|
162
|
+
checksum = "5e7ff73c555c286d212d4ce7e5fbda845a973c4f61bd5f160f5f2c3c2a04d1c4"
|
|
163
163
|
dependencies = [
|
|
164
164
|
"libc",
|
|
165
165
|
"pyo3-build-config",
|
|
@@ -167,9 +167,9 @@ dependencies = [
|
|
|
167
167
|
|
|
168
168
|
[[package]]
|
|
169
169
|
name = "pyo3-macros"
|
|
170
|
-
version = "0.
|
|
170
|
+
version = "0.30.1"
|
|
171
171
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
172
|
-
checksum = "
|
|
172
|
+
checksum = "c46d2e5862c7bb8207e3b639f713dda3c499933444784154c11d013c5a691b60"
|
|
173
173
|
dependencies = [
|
|
174
174
|
"proc-macro2",
|
|
175
175
|
"pyo3-macros-backend",
|
|
@@ -179,9 +179,9 @@ dependencies = [
|
|
|
179
179
|
|
|
180
180
|
[[package]]
|
|
181
181
|
name = "pyo3-macros-backend"
|
|
182
|
-
version = "0.
|
|
182
|
+
version = "0.30.1"
|
|
183
183
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
184
|
-
checksum = "
|
|
184
|
+
checksum = "38b89f066f2ae72a2aef52d1537ca2fcd104440ebfadee06e97aa90738a25b9b"
|
|
185
185
|
dependencies = [
|
|
186
186
|
"heck",
|
|
187
187
|
"proc-macro2",
|
|
@@ -238,9 +238,9 @@ checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
|
|
|
238
238
|
|
|
239
239
|
[[package]]
|
|
240
240
|
name = "syn"
|
|
241
|
-
version = "
|
|
241
|
+
version = "3.0.9"
|
|
242
242
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
243
|
-
checksum = "
|
|
243
|
+
checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b"
|
|
244
244
|
dependencies = [
|
|
245
245
|
"proc-macro2",
|
|
246
246
|
"quote",
|
|
@@ -255,7 +255,7 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
|
255
255
|
|
|
256
256
|
[[package]]
|
|
257
257
|
name = "twobitreader"
|
|
258
|
-
version = "0.2.
|
|
258
|
+
version = "0.2.3"
|
|
259
259
|
dependencies = [
|
|
260
260
|
"byteorder",
|
|
261
261
|
"flate2",
|
|
@@ -271,9 +271,9 @@ dependencies = [
|
|
|
271
271
|
|
|
272
272
|
[[package]]
|
|
273
273
|
name = "unicode-ident"
|
|
274
|
-
version = "1.0.
|
|
274
|
+
version = "1.0.27"
|
|
275
275
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
276
|
-
checksum = "
|
|
276
|
+
checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
|
|
277
277
|
|
|
278
278
|
[[package]]
|
|
279
279
|
name = "windows-link"
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# twobitreader
|
|
2
2
|
|
|
3
|
+
[](https://github.com/andrewdelong/twobitreader-rust/actions/workflows/ci.yml)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
[](https://anaconda.org/conda-forge/twobitreader-rs)
|
|
8
|
+
[](https://pypi.org/project/twobitreader-rs/)
|
|
9
|
+
|
|
10
|
+
<!-- cargo-rdme start -->
|
|
3
11
|
|
|
4
12
|
This crate provides fast DNA sequence extraction from 2bit files, a
|
|
5
13
|
[standard format](http://genome.ucsc.edu/FAQ/FAQformat.html#format7) in bioinformatics.
|
|
@@ -10,13 +18,6 @@ It is also available as a Python package named `twobitreader-rs`.
|
|
|
10
18
|
The focus is raw reading from 2bit, but fast concatenation and reverse-complement methods
|
|
11
19
|
are also provided to make higher-level use cases easier.
|
|
12
20
|
|
|
13
|
-
[](https://github.com/andrewdelong/twobitreader-rust/actions/workflows/ci.yml)
|
|
14
|
-

|
|
15
|
-

|
|
16
|
-

|
|
17
|
-
[](https://anaconda.org/conda-forge/twobitreader-rs)
|
|
18
|
-
[](https://pypi.org/project/twobitreader-rs/)
|
|
19
|
-
|
|
20
21
|
## Examples
|
|
21
22
|
|
|
22
23
|
**Extracting sequences** is straightforward:
|
|
@@ -89,13 +90,13 @@ Speed depends on parallelism and page cache (hot vs cold):
|
|
|
89
90
|
- **cold** runs represent a first run of a genomics pipeline, bound by disk speed;
|
|
90
91
|
- **prefetch** runs are cold but with a `prefetch` call preceding extraction.
|
|
91
92
|
|
|
92
|
-
The table below shows running times in milliseconds. Experimental details are `BENCH.md`.
|
|
93
|
-
This crate provides *twobitreader*
|
|
93
|
+
The table below shows running times in milliseconds. Experimental details are in `BENCH.md`.
|
|
94
|
+
This crate provides the *twobitreader* and *twobitreader-rs* rows.
|
|
94
95
|
|
|
95
96
|
| EXONS | 1-thread / hot | 1-thread / cold | 1-thread / prefetch | 16-thread / hot | 16-thread / cold |
|
|
96
97
|
|---|---:|---:|---:|---:|---:|
|
|
97
98
|
| **twobitreader** (rs) | 90 | 1,700 | 180 | 10 | 190 |
|
|
98
|
-
| **
|
|
99
|
+
| **twobitreader-rs** (rs, py) | 100 | 1,900 | 190 | *27 | *210 |
|
|
99
100
|
| **py2bit** (c, py) | 220 | 2,800 | n/a | n/a | n/a |
|
|
100
101
|
| **GenomeKit** (cpp, py) | 340 | 2,400 | n/a | n/a | n/a |
|
|
101
102
|
| **twobit** (rs) | 390 | 3,500 | n/a | n/a | n/a |
|
|
@@ -106,7 +107,7 @@ This crate provides *twobitreader* (pure rust) and *twobitreader_rs* (python wra
|
|
|
106
107
|
| TRANSCRIPTS | 1-thread / hot | 1-thread / cold | 1-thread / prefetch | 16-thread / hot | 16-thread / cold |
|
|
107
108
|
|---|---:|---:|---:|---:|---:|
|
|
108
109
|
| **twobitreader** (rs) | 140 | 1,700 | 230 | 13 | 190 |
|
|
109
|
-
| **
|
|
110
|
+
| **twobitreader-rs** (rs, py) | 180 | 2,100 | 310 | *27 | *220 |
|
|
110
111
|
| **py2bit** (c, py) | 490 | 3,600 | n/a | n/a | n/a |
|
|
111
112
|
| **GenomeKit** (cpp, py) | 720 | 2,900 | n/a | n/a | n/a |
|
|
112
113
|
| **twobit** (rs) | 930 | 1,900 | n/a | n/a | n/a |
|
|
@@ -126,8 +127,13 @@ Entries marked * were run in free-threaded Python.
|
|
|
126
127
|
|
|
127
128
|
## Use of AI
|
|
128
129
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
The Rust library was written primarily by hand.
|
|
131
|
+
|
|
132
|
+
Claude was used to generated the OS-specific prefetch loops, to improve handling of
|
|
133
|
+
corrupt or malicious files, to document the Python bindings and mirrored their tests
|
|
134
|
+
and benchmark, to improved error checking and propagation to Python more broadly,
|
|
135
|
+
and generated the CI configurations.
|
|
136
|
+
|
|
137
|
+
<!-- cargo-rdme end -->
|
|
132
138
|
|
|
133
139
|
License: MIT OR Apache-2.0
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
#![deny(missing_docs)]
|
|
3
3
|
#![deny(unreachable_pub)]
|
|
4
4
|
#![warn(rust_2018_idioms)]
|
|
5
|
-
//!
|
|
6
5
|
//! This crate provides fast DNA sequence extraction from 2bit files, a
|
|
7
6
|
//! [standard format](http://genome.ucsc.edu/FAQ/FAQformat.html#format7) in bioinformatics.
|
|
8
7
|
//!
|
|
@@ -12,13 +11,6 @@
|
|
|
12
11
|
//! The focus is raw reading from 2bit, but fast concatenation and reverse-complement methods
|
|
13
12
|
//! are also provided to make higher-level use cases easier.
|
|
14
13
|
//!
|
|
15
|
-
//! [](https://github.com/andrewdelong/twobitreader-rust/actions/workflows/ci.yml)
|
|
16
|
-
//! 
|
|
17
|
-
//! 
|
|
18
|
-
//! 
|
|
19
|
-
//! [](https://anaconda.org/conda-forge/twobitreader-rs)
|
|
20
|
-
//! [](https://pypi.org/project/twobitreader-rs/)
|
|
21
|
-
//!
|
|
22
14
|
//! # Examples
|
|
23
15
|
//!
|
|
24
16
|
//! **Extracting sequences** is straightforward:
|
|
@@ -117,13 +109,13 @@
|
|
|
117
109
|
//! - **cold** runs represent a first run of a genomics pipeline, bound by disk speed;
|
|
118
110
|
//! - **prefetch** runs are cold but with a `prefetch` call preceding extraction.
|
|
119
111
|
//!
|
|
120
|
-
//! The table below shows running times in milliseconds. Experimental details are `BENCH.md`.
|
|
121
|
-
//! This crate provides *twobitreader*
|
|
112
|
+
//! The table below shows running times in milliseconds. Experimental details are in `BENCH.md`.
|
|
113
|
+
//! This crate provides the *twobitreader* and *twobitreader-rs* rows.
|
|
122
114
|
//!
|
|
123
115
|
//! | EXONS | 1-thread / hot | 1-thread / cold | 1-thread / prefetch | 16-thread / hot | 16-thread / cold |
|
|
124
116
|
//! |---|---:|---:|---:|---:|---:|
|
|
125
117
|
//! | **twobitreader** (rs) | 90 | 1,700 | 180 | 10 | 190 |
|
|
126
|
-
//! | **
|
|
118
|
+
//! | **twobitreader-rs** (rs, py) | 100 | 1,900 | 190 | *27 | *210 |
|
|
127
119
|
//! | **py2bit** (c, py) | 220 | 2,800 | n/a | n/a | n/a |
|
|
128
120
|
//! | **GenomeKit** (cpp, py) | 340 | 2,400 | n/a | n/a | n/a |
|
|
129
121
|
//! | **twobit** (rs) | 390 | 3,500 | n/a | n/a | n/a |
|
|
@@ -134,7 +126,7 @@
|
|
|
134
126
|
//! | TRANSCRIPTS | 1-thread / hot | 1-thread / cold | 1-thread / prefetch | 16-thread / hot | 16-thread / cold |
|
|
135
127
|
//! |---|---:|---:|---:|---:|---:|
|
|
136
128
|
//! | **twobitreader** (rs) | 140 | 1,700 | 230 | 13 | 190 |
|
|
137
|
-
//! | **
|
|
129
|
+
//! | **twobitreader-rs** (rs, py) | 180 | 2,100 | 310 | *27 | *220 |
|
|
138
130
|
//! | **py2bit** (c, py) | 490 | 3,600 | n/a | n/a | n/a |
|
|
139
131
|
//! | **GenomeKit** (cpp, py) | 720 | 2,900 | n/a | n/a | n/a |
|
|
140
132
|
//! | **twobit** (rs) | 930 | 1,900 | n/a | n/a | n/a |
|
|
@@ -154,9 +146,12 @@
|
|
|
154
146
|
//!
|
|
155
147
|
//! # Use of AI
|
|
156
148
|
//!
|
|
157
|
-
//!
|
|
158
|
-
//!
|
|
159
|
-
//!
|
|
149
|
+
//! The Rust library was written primarily by hand.
|
|
150
|
+
//!
|
|
151
|
+
//! Claude was used to generated the OS-specific prefetch loops, to improve handling of
|
|
152
|
+
//! corrupt or malicious files, to document the Python bindings and mirrored their tests
|
|
153
|
+
//! and benchmark, to improved error checking and propagation to Python more broadly,
|
|
154
|
+
//! and generated the CI configurations.
|
|
160
155
|
|
|
161
156
|
// Standard library
|
|
162
157
|
use std::borrow::Borrow;
|
|
@@ -910,7 +905,7 @@ fn read_seqs_endian<B: ByteOrder>(mmap: &Mmap) -> io::Result<Vec<TwobitSequence>
|
|
|
910
905
|
// Get the offset of the data arrays for this sequence
|
|
911
906
|
let data_offset = cursor.read_u32::<B>()? as u64;
|
|
912
907
|
let curr_offset = cursor.position();
|
|
913
|
-
if data_offset
|
|
908
|
+
if data_offset < curr_offset {
|
|
914
909
|
return Err(io::Error::new(InvalidData, "invalid data offset; file may be malformed."));
|
|
915
910
|
}
|
|
916
911
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|