Compatibility modules¶
Modules that exist so a gffutils import keeps resolving. They are not
import shims: each symbol has a behavioural test, and every deliberate
difference is declared in tests/parity/deviations.toml with the test that
pins it.
Current parity: 86 of 89 symbols (97%), zero modules outstanding.
| Module | What it is |
|---|---|
gffbase.bins |
UCSC genomic binning. Differentially tested against the oracle over 20,044 comparisons. |
gffbase.helpers |
Thirteen functions, including make_query, infer_dialect, sanitize_gff_db and canonical_transcripts. |
gffbase.constants |
Schema and dialect constants, plus the two documented global toggles. |
gffbase.attributes |
The attribute mapping, under its compatibility name. |
gffbase.convert |
to_bed12. |
gffbase.create |
_DBCreator and friends, as adapters over create_db. |
gffbase.inspect |
Summarise a source without building a database. |
gffbase.version |
version, read from the package rather than from installed metadata. |
gffbase.biopython_integration |
to_seqfeature / from_seqfeature. Needs the biopython extra. |
gffbase.pybedtools_integration |
to_bedtool / tsses. Needs the pybedtools extra. |
gffbase.contrib.plotting |
The Gene track renderer. Needs pybedtools and matplotlib. |
Two live global toggles¶
constants.always_return_list and constants.ignore_url_escape_characters
are read at runtime by live code, not merely exported. The first decides
whether feature.attributes["ID"] gives you ["x"] or "x"; the second
turns percent decoding and re-encoding off together.
gffbase.helpers ¶
Compatibility helpers.
merge_attributes ¶
Union two attribute mappings, key by key.
Values are deduplicated and sorted, not kept in insertion order: the
result is a set union with a deterministic rendering, which is what makes
two features merge to the same attributes regardless of which was seen
first. numeric_sort sorts numerically where every value of a key parses
as a number, so ["2", "10"] does not come back as ["10", "2"].
Used by every derived-feature method; ported from gffutils.helpers so
that a caller comparing derived output against the oracle sees the same
ordering.
Source code in python/gffbase/helpers.py
example_filename ¶
Return the absolute path to a packaged example file under tests/data.
Mirrors the legacy gffutils.example_filename API. The legacy package
shipped fixtures inside the package itself; we point at the test fixtures
directory bundled with the source distribution.
Source code in python/gffbase/helpers.py
infer_dialect ¶
Infer a dialect from one attribute string.
Returns the full dialect dict, with everything the single string does not speak to left at its default.
Source code in python/gffbase/helpers.py
dialect_compare ¶
What changed between two dialects, as {"added": ..., "removed": ...}.
Unhashable values (order is a list) are compared by key rather than
through a set of items, so this works on real dialects. The oracle's
version raises TypeError: unhashable type: 'list' on any dialect that
carries an order, which is all of them.
Source code in python/gffbase/helpers.py
to_unicode ¶
Decode bytes to str; pass anything else through.
A Python-2-era shim. Upstream's body is unreachable after 2to3 and is the
identity for every input, including bytes; this one actually decodes,
because returning bytes from a function named to_unicode is not useful to
anybody.
Source code in python/gffbase/helpers.py
is_gff_db ¶
True if the path looks like an existing database file.
Extension-based, as upstream: .db for a gffutils database, plus
.duckdb, which is what gffbase writes.
Source code in python/gffbase/helpers.py
get_gff_db ¶
Open the database beside a GFF file, or build one.
Always returns a FeatureDB. Upstream returns a path string when a
sibling database exists and a FeatureDB when it had to build one, which
is why gffutils-cli fetch raises TypeError: string indices must be
integers in its common case -- it indexes whatever it gets. Returning one
type is the fix.
The sibling filename is <gff_fname><ext>; upstream's "%s.%s" inserts a
second dot, so it looks for foo.gff..db.
Source code in python/gffbase/helpers.py
sanitize_gff_db ¶
Return a copy of db with coordinates ordered and a gene id stamped on.
Two repairs, both aimed at making a file greppable and self-consistent:
every record gets start <= end, and every record inherits its gene's id
under gid_field, so a gene's whole block can be found with one grep.
Source code in python/gffbase/helpers.py
sanitize_gff_file ¶
Sanitize a GFF file, writing to stdout or over the input.
Source code in python/gffbase/helpers.py
annotate_gff_db ¶
Cross-reference a GFF database against another.
Not implemented, and not implemented upstream either -- gffutils'
body is a bare pass, so it silently returns None. The name exists so an
import resolves; calling it raises rather than pretending to work, because
a function that quietly does nothing is worse than one that says so.
Source code in python/gffbase/helpers.py
canonical_transcripts ¶
Yield (transcript, sequence) for the canonical transcript of each gene.
Canonical means the longest CDS, falling back to the longest transcript when a gene has no CDS at all.
Two upstream defects are not reproduced: its fallback sorts ascending and
takes [0], selecting the shortest transcript against its own comment;
and it print()s an internal tuple to stdout on every gene, which corrupts
any piped output.
Source code in python/gffbase/helpers.py
asinterval ¶
make_query ¶
make_query(args, other=None, limit=None, strand=None, featuretype=None, extra=None, order_by=None, reverse=False, completely_within=False)
Compose a legacy SQLite query and its arguments.
Provided for code that builds queries against an exported database, or
that reads gffutils' generated SQL. gffbase's own queries do not go through
it -- they are built in gffbase.interface against the DuckDB schema.
One deviation, and it is the point of having this here: order_by is
validated even when it is a plain string. Upstream checks its whitelist
only for the iterable form and interpolates a bare string verbatim, which
is the same class of hole that FeatureDB.order_by had. See
docs/security/2026-sql-injection.md.
other and extra are raw SQL
featuretype, limit and strand become bound parameters, and
order_by is checked against a whitelist -- but other and extra
are interpolated verbatim, because they exist to carry a caller's own
SQL fragment (upstream builds its relation joins through other).
Passing untrusted input to either is equivalent to passing it to
execute(). No gffbase code path routes caller data into them; the
asymmetry is documented here because the surrounding validation makes
it easy to assume otherwise.
Source code in python/gffbase/helpers.py
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 | |
gffbase.bins ¶
UCSC genomic binning, the public surface.
gffbase._bins has the arithmetic and is what the SQLite export uses; this
module is the compatibility face of it, under the names gffutils.bins
exports. The two must not diverge, so everything here delegates rather than
reimplements — tests/test_bins_surface.py pins that.
The one thing this adds over _bins is one=False: the set of bins a range
overlaps, rather than the single smallest bin containing it. That is what a
query needs (WHERE bin IN (...)) as opposed to what a write needs, and it is
required by helpers.make_query.
bins ¶
The UCSC bin(s) for the range [start, stop].
Parameters¶
start, stop
Range endpoints, inclusive.
fmt : {"gff", "bed"}
Coordinate convention of start; see COORD_OFFSETS.
one : bool
True (default) returns the single smallest bin that fully contains the
range -- what you store on a row. False returns the set of every bin
the range overlaps at any level -- what you query with, since a feature
in a coarser bin can still overlap your range.
Ranges at or beyond MAX_CHROM_SIZE, and negative ones, collapse to bin 1
("somewhere on this chromosome"), which is how the scheme degrades rather
than raising on a coordinate it cannot represent.
Source code in python/gffbase/bins.py
print_bin_sizes ¶
Report each level's bin count and width. A debugging aid, kept because the oracle exports it and upstream examples call it.
Source code in python/gffbase/bins.py
gffbase.inspect ¶
Summarise a GFF/GTF source without building a database.
The point is to answer "what featuretypes are in this file?" before deciding what to keep, on a file too large to want to ingest twice.
inspect ¶
inspect(data, look_for=['featuretype', 'chrom', 'attribute_keys', 'feature_count'], limit=None, verbose: bool = True) -> dict
Count things in a GFF/GTF source.
Parameters¶
data
A filename, a FeatureDB (its all_features() is used), or any
iterable of features.
look_for : list
What to tally. Any Feature attribute name works (chrom, source,
strand, ...), plus the special "attribute_keys", which counts
column-9 keys rather than a field. "feature_count" is always
reported whether or not it is requested.
limit : int
Stop after this many features.
verbose : bool
Report progress to stderr.
Returns¶
dict
One key per entry in look_for, each mapping value -> count, plus
feature_count.
The mutable default for look_for is upstream's and is part of the pinned
signature. It is never mutated here, which is what makes it harmless.
Source code in python/gffbase/inspect.py
gffbase.convert ¶
Conversions that operate on a FeatureDB.
to_bed12 ¶
Build one BED12 line for a top-level feature.
Superseded by FeatureDB.bed12, which this delegates to so the two cannot
disagree, but still importable because gffutils exports it.
Two differences from FeatureDB.bed12 are upstream's, not ours, and are
preserved: the line ends with a newline, and the thick span always covers
the whole feature (this function predates thick/thin handling and never
looks at CDS children).