Skip to content

Remove required Polars dependency and default to pandas (3.0.0) - #89

Merged
iskandr merged 2 commits into
masterfrom
feat/pandas-reader-optional-polars
Oct 6, 2026
Merged

iskandr merged 2 commits into
masterfrom
feat/pandas-reader-optional-polars

Conversation

@iskandr

@iskandr iskandr commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

gtfparse currently requires Polars for every import, read, and write, while its transformations already use pandas. Version 3.0.0 reads fixed GTF columns with typed PyArrow CSV, processes attributes and writes bounded batches with pandas, and returns pandas by default. Installing ordinary gtfparse no longer installs or imports Polars. Explicit result_type="polars", the legacy lazy adapter, and writing existing Polars frames remain supported through gtfparse[polars].

This is a major release: callers using the old default should request Polars explicitly and install the extra, or use pandas methods. Lower-level parse_gtf/parse_gtf_and_expand_attributes also return pandas. Empty/malformed fields raise the package's ParsingError. The README documents migration and retains progress, converters, aliases, biotype inference, raw attributes, version casts and dictionary output.

The reader handles whole-line comments without truncating literal #, UTF-8 BOM, text/binary/non-seekable streams, content-detected gzip, exact field counts, declared numeric types and filtering before pandas conversion. It does not alter global Polars string-cache state. The optional legacy Polars join test can emit its native categorical-remapping warning.

Dependency validation also reproduced pandas 2.1.0's NumPy 2 ABI failure (#87); raise the pandas floor to 2.2.2 and exercise it with NumPy 2, rather than a CI-only NumPy 1 restriction. Archive validation reproduced mismatched Python/pytest environments (#88); test.sh now launches python -m pytest using the interpreter used for xdist detection. Minimum and no-Polars jobs derive dependency floors from installed metadata.

CI rerun validation exposed a reused, already-closed Coveralls parallel report (#90). Set the workflow-wide COVERALLS_SERVICE_NUMBER to github.run_id plus github.run_attempt so uploads and finalization share a unique report per attempt. Preserve all matrix flags and aggregation.

Validation:

  • ./lint.sh and ./test.sh -W error::DeprecationWarning pass: 172 tests with current optional Polars, 97% coverage.
  • No-Polars environments pass 158 tests/10 optional skips: pandas 3.0.6 with current/minimum Arrow, plus Python 3.9/pandas 2.2.2/Arrow 18.0.0/NumPy 2.0.2. Optional Polars 0.20.31 passes 171/one modern-only skip.
  • 100 old/new API comparisons and 60 prototype comparisons pass across pandas 2.3.3 and 3.0.6. Regressions cover nullable filtered coordinates, callbacks/cancellation, comments, exact int64s, streams and writer round trips/batches.
  • Wheel/sdist pass strict twine validation. Metadata declares Polars only for the extra. Fresh wheel installation without Polars round-trips all five real fixtures; extracted source scripts pass lint/tests.
  • benchmarks/results.json contains 122 fresh-process records, corpus hashes, versions, stage medians and ranges. Three-run 250k-row Ensembl/GENCODE plain/gzip medians show 1.10–1.20x total time and about 1.03–1.10x peak RSS. A single full 4,119,244-row GENCODE check matches all columns: 38.88s/6189 MiB old versus 45.40s/5348 MiB new. The full pair checks scaling, not stable throughput. Complete load meets Evaluate migration from polars to pyarrow + pandas (with measurement plan) #69's 1.5x criterion; differing read-stage conversion work does not establish its 3x raw-CSV target. The user requested the dependency removal after considering the pandas default/optional Polars policy.

Fixes #69
Fixes #85
Fixes #87
Fixes #88
Fixes #90

Related downstream conversion issue: openvax/pyensembl#423 (already resolved; requests pandas explicitly). After merge, deploy with ./deploy.sh from clean master and verify both published distributions and a fresh base installation.

@coveralls

coveralls commented Oct 5, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 37486959393

Coverage increased (+0.3%) to 97.011%

Details

  • Coverage increased (+0.3%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 5 coverage regressions across 2 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

5 previously-covered lines in 2 files lost coverage.

File Lines Losing Coverage Coverage
read_gtf.py 4 97.01%
write_gtf.py 1 97.67%

Coverage Stats

Coverage Status
Relevant Lines: 368
Covered Lines: 357
Line Coverage: 97.01%
Coverage Strength: 6.75 hits per line

💛 - Coveralls

@iskandr
iskandr merged commit be449cb into master Oct 6, 2026
45 checks passed
@iskandr
iskandr deleted the feat/pandas-reader-optional-polars branch October 6, 2026 15:25
@iskandr

iskandr commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Released gtfparse 3.0.0: https://pypi.org/project/gtfparse/3.0.0/

  • PR merged as be449cbed70be8f515bb92b3eb2f43e55276917c.
  • Required ./lint.sh and ./test.sh pass. Optional-Polars suite: 172 passed, 97% coverage; deployment base environment: 158 passed, 10 optional skips.
  • All PR matrix/packaging/coverage checks pass. Full rerun of workflow 37486959393 (attempt 2) also passes, proving Coveralls parallel report fails on GitHub Actions reruns #90's unique-attempt coverage report works. Post-merge master workflows 37487408027 and 37487400152 pass.
  • Ran ./deploy.sh from clean, synchronized master. Wheel and sdist uploaded successfully and pass strict Twine checks.
  • Downloaded both published artifacts, checked SHA-256 against PyPI, and verified matching version/dependencies in wheel metadata, sdist PKG-INFO, and PyPI JSON. Pandas >=2.2.2 and PyArrow >=18.0.0 are required; Polars >=0.20.31 exists only in the polars extra.
  • Fresh pip install gtfparse==3.0.0 loads the published package from site-packages, installs/imports no Polars, defaults to pandas, and passes all five real-fixture round trips in expanded/raw and plain/gzip modes (20 checks). Explicit Polars output gives the documented extra-install error before consuming input. pip check passes.
  • Reviewed remaining gtfparse, pyensembl, and related datacache issues. No open pyensembl issues were returned. Master remains clean.

Published SHA-256:

  • Wheel: 0591ded1a5045c6b646f8d31da9bd2d5dd8bd54b0700d36091df512b1851bfdb
  • Source: 6e85f3f238f8eaa126cafcf59ea7888caf9ca2c20415b37e58fb6fc316b77ab0

Next-work review (recommendations only; no unrelated implementation started):

Group Dependency and urgency Candidate
Feature synthesis and input diagnostics Next foundational work within gtfparse; preserve best-effort defaults and define caller-selected policy before biological completeness rules. Missing identifiers alone do not establish biological incompleteness. #65, then complementary #66
Large-file parsing Independent reader API foundation for bounded-memory consumers; now easier to build on the Arrow/pandas backend. #37
First-use documentation Small independent improvements; the docs revision can cover filtering examples and explain pandas table display. #86 with #13 and #16
Bundle adoption in related datacache Immediate performance/platform prerequisites: metadata-only lookup before routine query adoption, and cross-platform installation before general adoption. openvax/datacache#88 and #89
Shared/derived artifacts in datacache Define caller-declared identity separately from integrity before consolidating derived-artifact lifecycle; explicit generation cleanup becomes important before default multi-GB storage. openvax/datacache#92, then #90; #91
Other cache follow-ups Layout callbacks/local overrides are migration conveniences; shared-reference storage remains an investigation gated on another consumer. openvax/datacache#93, #94; #95 later

The final release checklist is recorded here as anticipated in tasks/todo.md, preserving the clean-master deployment rule. The measured performance tradeoff remains the one documented in the PR and benchmark report: repeated subset loads take 1.10–1.20x the old total time; the full-file correctness/scaling check uses less peak memory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment