From 259cf7e7e9c2402534c914b6fb4ace89aa47950c Mon Sep 17 00:00:00 2001 From: "Wid L. Hacker" Date: Thu, 22 Oct 2026 19:38:08 -1000 Subject: [PATCH 1/3] Raise Python floor to >=3.10; modernize runtime-evaluated annotations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit setup.py python_requires, README (x2), and the conda recipe move from >=3.6 to >=3.10. With the floor at 3.10, the binding's runtime-evaluated annotations can use the PEP 585/604 spellings: __init__.py modernized by ruff autofix (UP006 x4, UP045 x18), the stale typing imports removed, and the UP006/UP045 global ruff opt-outs deleted — ruff.toml now has no global opt-outs, only the vendored-file per-file scoping. target-version pinned to py310 in ruff.toml so lint tracks the declared floor. Verified: ruff 0.17.2 check/format clean; test/test_gri.py 11 passed under Python 3.12; the package imports and connects under a real CPython 3.10.22 (annotations evaluate at import). --- README.md | 4 +- bindings/python/conda/genomicsqlite/meta.yaml | 2 +- bindings/python/genomicsqlite/__init__.py | 40 +++++++++---------- bindings/python/setup.py | 2 +- ruff.toml | 6 +-- 5 files changed, 26 insertions(+), 28 deletions(-) mode change 100755 => 100644 bindings/python/genomicsqlite/__init__.py mode change 100755 => 100644 bindings/python/setup.py diff --git a/README.md b/README.md index f31a516..c09a0cc 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ We supply the extension [prepackaged](https://github.com/mlin/GenomicSQLite/rele Programming language support: * C/C++ -* Python ≥3.6 +* Python ≥3.10 * Java & JVM languages * Rust @@ -54,7 +54,7 @@ cmake --build build -j 4 --target genomicsqlite * htslib ≥ 1.9, samtools, and tabix * pigz -* Python ≥ 3.6 and packages: pytest pytest-xdist pre-commit ruff +* Python ≥ 3.10 and packages: pytest pytest-xdist pre-commit ruff * JDK, mvn, rust * clang-format & cppcheck diff --git a/bindings/python/conda/genomicsqlite/meta.yaml b/bindings/python/conda/genomicsqlite/meta.yaml index 3ae1048..6379324 100644 --- a/bindings/python/conda/genomicsqlite/meta.yaml +++ b/bindings/python/conda/genomicsqlite/meta.yaml @@ -20,7 +20,7 @@ requirements: - python - pip run: - - python >=3.6 + - python >=3.10 - sqlite >=3.31.0 test: diff --git a/bindings/python/genomicsqlite/__init__.py b/bindings/python/genomicsqlite/__init__.py old mode 100755 new mode 100644 index 152a5c4..f32ffd0 --- a/bindings/python/genomicsqlite/__init__.py +++ b/bindings/python/genomicsqlite/__init__.py @@ -8,7 +8,7 @@ import platform import sqlite3 import sys -from typing import Any, Dict, NamedTuple, Optional # noqa: UP035 +from typing import Any, NamedTuple _HERE = os.path.dirname(__file__) _YES = ("1", "true", "t", "yes", "y") @@ -110,7 +110,7 @@ def create_genomic_range_index_sql( rid: str, beg: str, end: str, - floor: Optional[int] = None, + floor: int | None = None, ) -> str: return _execute1( conn, "SELECT create_genomic_range_index_sql(?,?,?,?,?)", (table, rid, beg, end, floor) @@ -120,11 +120,11 @@ def create_genomic_range_index_sql( def genomic_range_rowids_sql( conn: sqlite3.Connection, indexed_table: str, - qrid: Optional[str] = None, - qbeg: Optional[str] = None, - qend: Optional[str] = None, - ceiling: Optional[int] = None, - floor: Optional[int] = None, + qrid: str | None = None, + qbeg: str | None = None, + qend: str | None = None, + ceiling: int | None = None, + floor: int | None = None, ) -> str: """ Generate SQL subquery selecting the rowids of indexed_table entries overlapping a range. @@ -145,7 +145,7 @@ def genomic_range_rowids_sql( def put_reference_assembly_sql( - conn: sqlite3.Connection, assembly: str, schema: Optional[str] = None + conn: sqlite3.Connection, assembly: str, schema: str | None = None ) -> str: return _execute1(conn, "SELECT put_genomic_reference_assembly_sql(?,?)", (assembly, schema)) @@ -154,11 +154,11 @@ def put_reference_sequence_sql( conn: sqlite3.Connection, name: str, length: int, - assembly: Optional[str] = None, - refget_id: Optional[str] = None, - meta: Optional[Dict[str, Any]] = None, - rid: Optional[int] = None, - schema: Optional[str] = None, + assembly: str | None = None, + refget_id: str | None = None, + meta: dict[str, Any] | None = None, + rid: int | None = None, + schema: str | None = None, ): meta_json = json.dumps(meta) if meta else None return _execute1( @@ -172,14 +172,14 @@ class ReferenceSequence(NamedTuple): rid: int name: str length: int - assembly: Optional[str] - refget_id: Optional[str] - meta: Dict[str, Any] + assembly: str | None + refget_id: str | None + meta: dict[str, Any] def get_reference_sequences_by_rid( - con: sqlite3.Connection, assembly: Optional[str] = None, schema: Optional[str] = None -) -> Dict[int, ReferenceSequence]: + con: sqlite3.Connection, assembly: str | None = None, schema: str | None = None +) -> dict[int, ReferenceSequence]: table = "_gri_refseq" if schema: table = f"{schema}.{table}" @@ -208,8 +208,8 @@ def get_reference_sequences_by_rid( def get_reference_sequences_by_name( - con: sqlite3.Connection, assembly: Optional[str] = None, schema: Optional[str] = None -) -> Dict[str, ReferenceSequence]: + con: sqlite3.Connection, assembly: str | None = None, schema: str | None = None +) -> dict[str, ReferenceSequence]: ans = {} for item in get_reference_sequences_by_rid(con, assembly, schema).values(): assert item.name not in ans, "genomicsqlite: non-unique reference sequence names" diff --git a/bindings/python/setup.py b/bindings/python/setup.py old mode 100755 new mode 100644 index cfd8a19..88101a6 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -9,7 +9,7 @@ README = f.read() setup( - python_requires=">=3.6", + python_requires=">=3.10", name="genomicsqlite", version=get_version(), url="https://github.com/mlin/GenomicSQLite", diff --git a/ruff.toml b/ruff.toml index 440afff..84372fb 100644 --- a/ruff.toml +++ b/ruff.toml @@ -2,12 +2,10 @@ # Opt out of specific rules only where warranted; each opt-out is documented # inline. No rule sets are selected or opted into. line-length = 100 # exception to the ruff default (88): matches this codebase's black -l 100 formatting; avoids a whole-tree reformat +target-version = "py310" # matches the package's declared floor (python_requires>=3.10); binding annotations are evaluated at runtime [lint] -ignore = [ - "UP006", # non-pep585-annotation: binding annotations are evaluated at runtime; package declares python_requires>=3.6 - "UP045", # non-pep604-annotation-optional: same runtime-annotation / python>=3.6 constraint as UP006 -] +ignore = [] # no global opt-outs; per-file opt-outs for the vendored file are scoped below [lint.per-file-ignores] # bindings/python/version.py is vendored (third-party, public domain) and not From 136cf9080debb08114b95129a77faa9956a2d330 Mon Sep 17 00:00:00 2001 From: Mike Lin Date: Thu, 22 Oct 2026 19:47:39 -1000 Subject: [PATCH 2/3] restore exec bit on __init__.py (stripped by connector push) --- bindings/python/genomicsqlite/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bindings/python/genomicsqlite/__init__.py diff --git a/bindings/python/genomicsqlite/__init__.py b/bindings/python/genomicsqlite/__init__.py old mode 100644 new mode 100755 From 63fc73fdb988a1a6b4a3dbb1bd09527f7d6778ee Mon Sep 17 00:00:00 2001 From: Mike Lin Date: Thu, 22 Oct 2026 20:29:50 -1000 Subject: [PATCH 3/3] restore exec bit on setup.py (stripped by connector push) --- bindings/python/setup.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bindings/python/setup.py diff --git a/bindings/python/setup.py b/bindings/python/setup.py old mode 100644 new mode 100755