Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ About changelog [here](https://keepachangelog.com/en/1.0.0/)
- Rework rank model file loading, allowing full URI (#6090)
- Refactored `scout delete` commands and relative tests into separate modules (#6102)
- The gens extension now generates version appropriate links (#6105)
- Refactored snv variants code to share same routines as other variant categories (#6116)
- Refactored snv and cancer snv variants code to share same routines as other variant categories (#6116 and #6128)
- On managed variants page, print maintainers names instead of emails/ids (#6121)
### Fixed
- Comments' text wrapping in ACMG classifications exported as PDF (#6086)
Expand Down
8 changes: 5 additions & 3 deletions scout/server/blueprints/variants/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,14 @@

SV_VARIANT_PAGE = "variant.sv_variant"
VARIANT_PAGE = "variant.variant"
CANCER_VARIANT_PAGE = "variant.cancer_variant"
DISMISS_VARIANT_LINK = {
"sv": SV_VARIANT_PAGE,
"cancer_sv": SV_VARIANT_PAGE,
"mei": SV_VARIANT_PAGE,
"str": VARIANT_PAGE,
"snv": VARIANT_PAGE,
"cancer": CANCER_VARIANT_PAGE,
}

LOG = logging.getLogger(__name__)
Expand Down Expand Up @@ -301,14 +303,14 @@ def render_variants_page(
return data_exporter(store, case_obj, variants_query)

args = [store, institute_obj, case_obj, variants_query, page]
if category in ["snv", "snv_research"]:
if category in ["snv", "cancer"]:
args.append(request.form)

data = decorator(*args)

dismiss_variant_options = (
{**DISMISS_VARIANT_OPTIONS, **CANCER_SPECIFIC_VARIANT_DISMISS_OPTIONS}
if category == "cancer_sv"
if category in ["cancer_sv", "cancer"]
else DISMISS_VARIANT_OPTIONS
)

Expand Down Expand Up @@ -1852,7 +1854,7 @@ def _populate_form_genes_from_file(
form.hgnc_symbols.data = hgnc_symbols_set


def populate_snv_sv_mei_str_filters_form(
def populate_variants_filters_form(
store: MongoAdapter, institute_obj: dict, case_obj: dict, category: str, request_obj: LocalProxy
) -> Union[StrFiltersForm, SvFiltersForm, CancerSvFiltersForm, MeiFiltersForm]:
"""Populate a filters form for SVs, cancer SVs, MEIs and STRs pages."""
Expand Down
132 changes: 27 additions & 105 deletions scout/server/blueprints/variants/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
)

from . import controllers
from .forms import (

Check failure on line 27 in scout/server/blueprints/variants/views.py

View workflow job for this annotation

GitHub Actions / vulture

unused import 'CancerFiltersForm' (90% confidence)
CancerFiltersForm,
FiltersForm,
FusionFiltersForm,
Expand Down Expand Up @@ -57,9 +57,9 @@
def variants(institute_id, case_name):
"""Display a list of SNV variants."""

def form_builder(store, inst, case, cat, vtype):

Check failure on line 60 in scout/server/blueprints/variants/views.py

View workflow job for this annotation

GitHub Actions / vulture

unused variable 'vtype' (100% confidence)
"""Builds the SNVs filters form."""
return controllers.populate_snv_sv_mei_str_filters_form(
return controllers.populate_variants_filters_form(
store=store, institute_obj=inst, case_obj=case, category=cat, request_obj=request
)

Expand Down Expand Up @@ -91,9 +91,9 @@
def str_variants(institute_id: str, case_name: str):
"""Display a list of STR variants (STRs)."""

def form_builder(store, inst, case, cat, vtype):

Check failure on line 94 in scout/server/blueprints/variants/views.py

View workflow job for this annotation

GitHub Actions / vulture

unused variable 'vtype' (100% confidence)
"""Builds the STRs filters form."""
return controllers.populate_snv_sv_mei_str_filters_form(
return controllers.populate_variants_filters_form(
store=store, institute_obj=inst, case_obj=case, category=cat, request_obj=request
)

Expand Down Expand Up @@ -124,9 +124,9 @@
def sv_variants(institute_id: str, case_name: str):
"""Display a list of structural variants (SV)."""

def form_builder(store, inst, case, cat, vtype):

Check failure on line 127 in scout/server/blueprints/variants/views.py

View workflow job for this annotation

GitHub Actions / vulture

unused variable 'vtype' (100% confidence)
"""Builds the SV filters form."""
return controllers.populate_snv_sv_mei_str_filters_form(
return controllers.populate_variants_filters_form(
store=store, institute_obj=inst, case_obj=case, category=cat, request_obj=request
)

Expand Down Expand Up @@ -157,9 +157,9 @@
def cancer_sv_variants(institute_id: str, case_name: str):
"""Display a list of cancer structural variants."""

def form_builder(store, inst, case, cat, vtype):

Check failure on line 160 in scout/server/blueprints/variants/views.py

View workflow job for this annotation

GitHub Actions / vulture

unused variable 'vtype' (100% confidence)
"""Builds the cancer SV filters form."""
return controllers.populate_snv_sv_mei_str_filters_form(
return controllers.populate_variants_filters_form(
store=store, institute_obj=inst, case_obj=case, category=cat, request_obj=request
)

Expand All @@ -184,9 +184,9 @@
def mei_variants(institute_id: str, case_name: str):
"""Display a list of MEI variants."""

def form_builder(store, inst, case, cat, vtype):

Check failure on line 187 in scout/server/blueprints/variants/views.py

View workflow job for this annotation

GitHub Actions / vulture

unused variable 'vtype' (100% confidence)
"""Builds the cancer SV filters form."""
return controllers.populate_snv_sv_mei_str_filters_form(
return controllers.populate_variants_filters_form(
store=store, institute_obj=inst, case_obj=case, category=cat, request_obj=request
)

Expand All @@ -211,110 +211,32 @@
def cancer_variants(institute_id, case_name):
"""Show cancer variants overview."""

page = controllers.get_variants_page(request.form)

category = "cancer"
institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
variant_type = Markup.escape(
request.args.get("variant_type", request.form.get("variant_type", "clinical"))
)
if variant_type not in ["clinical", "research"]:
variant_type = "clinical"
variants_stats = store.case_variants_count(case_obj["_id"], institute_id, variant_type, False)

user_obj = store.user(current_user.email)
if request.method == "POST":
if "dismiss_submit" in request.form: # dismiss a list of variants
controllers.dismiss_variant_list(
store,
institute_obj,
case_obj,
VARIANT_PAGE,
request.form.getlist("dismiss"),
request.form.getlist("dismiss_choices"),
)

form = controllers.populate_filters_form(
store, institute_obj, case_obj, user_obj, category, request.form
def form_builder(store, inst, case, cat, vtype):

Check failure on line 214 in scout/server/blueprints/variants/views.py

View workflow job for this annotation

GitHub Actions / vulture

unused variable 'vtype' (100% confidence)
"""Builds the cancer SNVs filters form."""
return controllers.populate_variants_filters_form(
store=store, institute_obj=inst, case_obj=case, category=cat, request_obj=request
)

# if user is not loading an existing filter, check filter form
if (
request.form.get("load_filter") is None
and request.form.get("audit_filter") is None
and form.validate_on_submit() is False
):
# Flash a message with errors
for field, err_list in form.errors.items():
for err in err_list:
flash(
f"Content of field '{field}' does not have a valid format",
"warning",
)
# And do not submit the form
return redirect(
url_for(".cancer_variants", institute_id=institute_id, case_name=case_name)
)
else:
form = CancerFiltersForm(request.args)
# set chromosome to all chromosomes
form.chrom.data = request.args.get("chrom", "")
if form.gene_panels.data == []:
form.gene_panels.data = controllers.case_default_panels(case_obj)

controllers.populate_force_show_unaffected_vars(institute_obj, form)

# update status of case if visited for the first time
controllers.activate_case(store, institute_obj, case_obj, current_user)

# Populate chromosome select choices
controllers.populate_chrom_choices(form, case_obj)

# Populate custom soft filters
controllers.populate_institute_soft_filters(form=form, institute_obj=institute_obj)

form.gene_panels.choices = controllers.gene_panel_choices(store, institute_obj, case_obj)

genome_build = get_case_genome_build(case_obj)
cytobands = store.cytoband_by_chrom(genome_build)

controllers.update_form_hgnc_symbols(store, case_obj, form)

variants_query = store.variants(
case_obj["_id"], category="cancer", query=form.data, build=genome_build
)
result_size = store.count_variants(
case_obj["_id"], form.data, None, category, build=genome_build
)
def data_exporter(store, case, variants_query):
return controllers.download_variants(store, case, variants_query)

if request.form.get("export"):
return controllers.download_variants(store, case_obj, variants_query)

data = controllers.cancer_variants(
store,
institute_id,
case_name,
variants_query,
form,
page=page,
)
def decorator(store, institute, case, variants_query, page, query_form):
return controllers.variants(
store=store,
institute_obj=institute,
case_obj=case,
variants_query=variants_query,
page=page,
query_form=query_form,
)

return dict(
cytobands=cytobands,
dismiss_variant_options={
**DISMISS_VARIANT_OPTIONS,
**CANCER_SPECIFIC_VARIANT_DISMISS_OPTIONS,
},
scroll_pos=int(float(request.values.get("scroll_pos", 0) or 0)),
expand_search=controllers.get_expand_search(request.form),
filters=controllers.populate_persistent_filters_choices(
institute_id=institute_id, category=category, form=form
),
result_size=result_size,
show_dismiss_block=controllers.get_show_dismiss_block(),
total_variants=variants_stats.get(variant_type, {}).get(category, "NA"),
variant_type=variant_type,
**data,
return controllers.render_variants_page(
category="cancer",
institute_id=institute_id,
case_name=case_name,
form_builder=form_builder,
data_exporter=data_exporter,
decorator=decorator,
)


Expand Down
24 changes: 0 additions & 24 deletions tests/server/blueprints/variants/test_variants_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,30 +401,6 @@ def test_cancer_variants(app, institute_obj, case_obj):
assert resp.status_code == 200


def test_filter_cancer_variants_wrong_params(app, institute_obj, case_obj):
"""test filter cancer SNV variants with filter form filled with parameters having the wrong format"""

# GIVEN an initialized app
with app.test_client() as client:
# GIVEN that the user could be logged in
resp = client.get(url_for("auto_login"))

# When a POST request with filter containing wrongly formatted parameters is sent
form_data = {
"control_frequency": "not a number!",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this test which is testing an impossible condition, as the form now has enforced a HTML5 check, so you can't enter a string - it just accepts numbers

NOTE that the test would have failed with
assert 200 == 302

This is because cancer variant form is currently validated.

Validation is lost with the refactoring - it's complicated to have a common function and just validate cancer variants forms on POST request. Would be much easier to start working on a common validation code for each variant type at a later stage.

}
resp = client.post(
url_for(
"variants.cancer_variants",
institute_id=institute_obj["internal_id"],
case_name=case_obj["display_name"],
),
data=form_data,
)
# THEN it should return a redirected page
assert resp.status_code == 302


def test_filter_cancer_variants_by_vaf(app, institute_obj, cancer_case_obj, cancer_variant_obj):
"""Tests the cancer form filter by VAF"""

Expand Down
Loading