Skip to content

Fix #70: don't call logging.basicConfig() at import#73

Closed
iskandr wants to merge 1 commit into
masterfrom
fix-70-no-import-time-basicconfig
Closed

Fix #70: don't call logging.basicConfig() at import#73
iskandr wants to merge 1 commit into
masterfrom
fix-70-no-import-time-basicconfig

Conversation

@iskandr

@iskandr iskandr commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #70.

attribute_parsing.py, create_missing_features.py, and read_gtf.py each call logging.basicConfig(level=logging.INFO) at module import. That mutates the root logger (adds a handler, sets the root level to INFO) as an import side effect, which hijacks a downstream application's logging configuration and breaks pytest's caplog in downstream test suites.

Change

Per the Python logging HOWTO ("Configuring Logging for a Library"):

  • Remove the three import-time logging.basicConfig(...) calls (keep each module's logger = logging.getLogger(__name__)).
  • Attach a logging.NullHandler() to the top-level gtfparse logger in __init__.py, so importing gtfparse emits nothing and reconfigures nothing by default. Applications opt in to gtfparse's INFO logs via their own logging config.

Before / after

import logging; import gtfparse
print(logging.getLogger().handlers, logging.getLogger().level)
# before: [<StreamHandler <stderr> (NOTSET)>] 20   (root hijacked, level INFO)
# after : []                                    30   (untouched, default WARNING)

Tests

Full suite green (59 passed). No behavior change beyond logging side effects.

attribute_parsing, create_missing_features and read_gtf each called
logging.basicConfig(level=logging.INFO) at import, which adds a handler to the
ROOT logger and sets the root level to INFO — hijacking downstream applications'
logging configuration and breaking pytest's caplog in their test suites.

Per the Python logging HOWTO ("Configuring Logging for a Library"), remove the
import-time basicConfig calls and attach a NullHandler to the top-level gtfparse
logger instead, so importing gtfparse is side-effect-free. Applications opt in
to gtfparse's INFO logs via their own logging configuration.

Claude-Session: https://claude.ai/code/session_01Nc9jzi2yp77EVa8yjN1mog
@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 28965821496

Coverage decreased (-0.02%) to 95.192%

Details

  • Coverage decreased (-0.02%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 8 coverage regressions across 3 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

8 previously-covered lines in 3 files lost coverage.

File Lines Losing Coverage Coverage
read_gtf.py 4 95.93%
create_missing_features.py 3 88.89%
attribute_parsing.py 1 97.44%

Coverage Stats

Coverage Status
Relevant Lines: 208
Covered Lines: 198
Line Coverage: 95.19%
Coverage Strength: 0.95 hits per line

💛 - Coveralls

@iskandr

iskandr commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Closing as a duplicate of #71, which fixes the same issue (#70), and was merged to master and released in 2.7.2. Thanks!

@iskandr iskandr closed this Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gtfparse calls logging.basicConfig() at import — hijacks root logging in downstream apps

2 participants