Skip to content

fix: unreachable chromid warning, shared mutable defaults, unclosed bed file handles - #6

Open
sanjaynagi-eit wants to merge 1 commit into
mainfrom
fix/correctness-issues
Open

fix: unreachable chromid warning, shared mutable defaults, unclosed bed file handles#6
sanjaynagi-eit wants to merge 1 commit into
mainfrom
fix/correctness-issues

Conversation

@sanjaynagi-eit

Copy link
Copy Markdown
Owner

Three unrelated correctness issues found while profiling. None are performance changes; opening them separately so the perf PRs stay reviewable.

1. The multiple-chromosome warning could never fire

c = 1
...
if c == 1:
    dna_header = "chromosome"
else:
    if c == "2":   # <- c is an int
        logger.info("Multiple contigs above the specified chromosome length -c have been detected. ...")

c is an integer, so c == "2" is always False. A user assembling something with two chromosome-sized contigs — chromids, or simply -c set too low — silently got no hint that this had happened, which is exactly the case the message exists for. Three copies, in the raven, flye and flye_long variants.

2. Mutable and import-time-evaluated default arguments

depth_df: pd.DataFrame() = pd.DataFrame({"col1": [1, 2, 3], "col2": [4, 5, 6]}),
filtered_out_contig_ids: list = [],
plasmid_names: list = ["1"],
  • The list defaults are created once at import and shared by every instance. Currently benign because both are always reassigned before use, but it is a trap waiting for the first .append().
  • pd.DataFrame() in annotation position is not a type — it constructs and discards a DataFrame at import time, six times across the two classes.
  • The default value was a dummy {"col1": [1,2,3], "col2": [4,5,6]} frame rather than an empty one, so an un-populated Plass carried fake data.

All now default to None and are materialised per instance.

Separately, Assembly.__init__ accepted chromosome_name and plasmid_names and then never stored them. It does now.

3. BED file handles were never closed

bed_file = open(os.path.join(outdir, "non_chromosome.bed"), "w")
bed_chrom_file = open(os.path.join(outdir, "chromosome.bed"), "w")

Bare open(), no with, no .close(). samtools view -L reads both files later in the run, which works today only because CPython's refcounting happens to flush and close them when the method returns — it would break under a non-refcounting implementation, and it makes the ordering guarantee invisible. Closed explicitly.

Tests

New tests/test_plass_class_defaults.py: two instances no longer share default containers, explicitly supplied values still win, the DataFrame defaults are empty rather than dummy data, and the multiple-chromosome warning actually fires for an assembly with two chromosome-sized contigs.

All existing tests pass (74 non-slow).

@sanjaynagi-eit
sanjaynagi-eit force-pushed the fix/correctness-issues branch from c825491 to c1a95a7 Compare August 13, 2026 21:46
…ed files

Three unrelated correctness issues found while profiling.

1. The 'Multiple contigs above the specified chromosome length -c' warning
   could never fire. c is an int (c = 1; c += 1) but was compared against the
   string "2", so users assembling something with two chromosome-sized
   contigs - chromids, or a -c set too low - silently got no hint. Three
   copies, in the raven, flye and flye_long variants.

2. Mutable and import-time-evaluated default arguments in Plass.__init__ and
   Assembly.__init__: 'filtered_out_contig_ids: list = []',
   'plasmid_names: list = ["1"]', and three
   'depth_df: pd.DataFrame() = pd.DataFrame({...})' defaults. The list
   defaults are shared by every instance; the annotation 'pd.DataFrame()'
   also constructs a throwaway DataFrame at import time, six times, and the
   default value itself was a dummy {'col1': [1,2,3]} frame rather than an
   empty one. All now default to None and are materialised per instance.
   Assembly.__init__ also accepted chromosome_name and plasmid_names without
   ever storing them; it does now.

3. non_chromosome.bed and chromosome.bed were opened with a bare open() and
   never closed. samtools later reads both with -L, which worked only
   because CPython's refcounting flushed them when the method returned.
   Closed explicitly.

New tests/test_plass_class_defaults.py covers each: instances no longer share
default containers, supplied values still win, the DataFrame defaults are
empty, and the multiple-chromosome warning actually fires.
@sanjaynagi-eit
sanjaynagi-eit force-pushed the fix/correctness-issues branch from c1a95a7 to 53ebeac Compare August 13, 2026 21:54
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.

1 participant