Skip to content

Global mutable state (_tally, _fail) prevents clean library reuse #43

@jlevy

Description

@jlevy

Summary

The module uses global mutable state for tallying (_tally) and error handling (_fail), which prevents clean reuse as a library and makes the code non-reentrant/non-threadsafe.

Details

In repren.py:

  • _tally (line 579): A module-level _Tally() instance that gets mutated by multi_replace() and transform_file(). This means calling these functions from library code accumulates state across calls with no way to reset it.

  • _fail (line 527): A module-level function pointer that defaults to _fail_with_exception but gets reassigned to _fail_with_exit inside _run_cli(). This means library callers who import after main() has run get different behavior.

  • _tally mutation inside multi_replace() (lines 669-673): The core replacement function has a side effect of mutating global state, mixing pure computation with I/O bookkeeping.

Suggestion

Pass a Tally (or context) object through the call chain instead of relying on module-level globals. This would make the functions pure, reentrant, and safe for concurrent use. The Rust port (repren-rs) already uses this pattern — each function returns counts as part of its return value.

Context

Found during the repren-rs Rust port review, where this pattern was identified as a porting friction point.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions