Remaining duplicate implementations: annotation, snpdb, and cross-app pairs
- Dominant language
- Python
- Stars
- 30
- Forks
- 3
- Avg merge
- 9h 28m
- Merged PRs (30d)
- 42
Description
🤖 Written by Claude
Last of the duplication found by the same scan (token-normalised clone detection + AST structural similarity, then manual verification) — everything outside the `classification` (#1796) and `analysis` (#1799) apps, plus the cross-app pairs.
### 1. `dump_external_annotation_runs` / `dump_existing_annotation_runs`
`annotation/external_annotation.py:155` and `:213` share a ~25-line block verbatim: the already-counted too-small rejection, `dump()`, the `dump_count == 0` skip, the too-small revert, the lazily-computed `identity`, `write_dump_metadata`, and then the whole `write_snakemake_bundle` / `reverted` / logging tail. Only how each acquires its runs differs — one creates them from range locks, the other adopts existing CREATED ones. The comments are copied too, which is the giveaway.
### 2. Trio and Quad models
`snpdb/models/models_cohort.py:773` and `:843` — `get_permission_class`, `preview_icon`, `preview`, `get_permission_object`, `_filter_from_permission_object_qs`, `genome_build`, `data_archived`, `get_samples`, `mother_details` and `father_details` are identical, and `__str__` differs only in the class name it prints. `sibling_details` is a third copy of the same two-line shape.
The fields can't move (`related_name` differs per model: `trio_mother` vs `quad_mother`), but nothing stops the methods sharing.
### 3. Trio and Quad grids, and the two collection grids
`snpdb/grids.py:369` / `:400` — `QuadsListColumns` is `TriosListColumns` plus two sibling columns; the id/name/user/modified/delete columns and `filter_queryset` are identical.
`snpdb/grids.py:454` / `:624` — `CustomColumnsCollectionColumns` and `TagColorsCollectionColumns` are identical bar the model: the same five columns and the same `filter_for_user` queryset.
### 4. Chromosome density and homozygosity percent graphs
`snpdb/graphs/chromosome_density_graph.py:88` and `homozygosity_percent_graph.py:113` share an identical ~20-line `pcolormesh` setup — the dimension juggling, the `y_top`/`y_bottom` padding, the masked array and `set_clim` — including the copied `# pcolor says x,y should have dimensions 1 greater than colors` comment. Only `vmax` differs.
### 5. `as_table` / `as_p` template filters
`snpdb/templatetags/model_helpers.py:16` and `:38` share their whole row-formatting loop; only the HTML each wraps a row in differs. (They also differ in that `as_p` returns `mark_safe`, while `as_table`'s callers apply `|safe` at the template — worth preserving as is.)
### 6. Fake-data helpers copied between apps
`_variant_ids_by_gene` and `_zipf_weight` are byte-identical in `classification/fake_reclassifications.py:415,411` and `analysis/fake_variant_tags.py:336,348`. Both modules are subcommands of `manage.py create_fake_data`, so they want a shared home at a level both can import. (Moved out of #1798.)
### 7. Popover hover-stay handler in `global.js`
`variantgrid/static_files/default_static/js/global.js:186` and `:211` bind the same mouseenter/mouseleave pair with the same 300ms `.popover:hover` grace check.
### Identified but deliberately left alone
* **`annotation/tasks/calculate_sample_stats.py`** has the same ~15-line counter-bump sequence three times (`:482` aggregate, `:533` per trio mode, `:570` comp-het post-processing). It is real duplication and a genuine "add a counter, update three places" hazard, but it is the innermost per-variant accumulation loop of a whole-database stats task, and factoring it into a helper adds a Python call per bucket per variant. Not worth the throughput on a task that walks every variant in the database.
* **`ClassificationAttachment.get_file_dict` / `PatientAttachment.get_file_dict`** (`classification/models/variant_models.py:21`, `patients/models.py:594`) are identical bar the URL names, and both models declare the same `file`/`file_type`/`thumbnail_path` fields. Sharing them properly means an abstract attachment model across two apps and the migrations that come with it — a bigger change than the rest of this issue.
* **Test fixtures.** `annotation/tests/` has roughly six copies of the same `setUpTestData`, and there are repeated blocks within `test_annotation_vcf.py`. Worth a tidy-up, but sharing fixtures across test classes is a different exercise to deduplicating production code.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reading the duplicated implementations in annotation/external_annotation.py, snpdb/models/models_cohort.py, snpdb/grids.py, the two graph modules, model_helpers.py, the fake-data modules, and global.js. Check manage.py create_fake_data as the shared-helper entry point, then verify that the extracted implementations preserve each caller's model-specific behavior and exclusions while removing the listed duplication.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, python
- Domain
- backend, frontend
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100