Skip to content

Commit d088e1a

Browse files
authored
Merge pull request #516 from VariantEffect/release-2025.4.0
Release 2025.4.0
2 parents fe06b4a + 79e9ad4 commit d088e1a

18 files changed

+153
-139
lines changed

alembic/versions/019eb75ad9ae_rename_tax_id_to_code.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,25 @@
55
Create Date: 2025-08-20 16:21:15.872816
66
77
"""
8+
89
from alembic import op
910
import sqlalchemy as sa
1011

1112

1213
# revision identifiers, used by Alembic.
13-
revision = '019eb75ad9ae'
14-
down_revision = '0b29eefbe1dd'
14+
revision = "019eb75ad9ae"
15+
down_revision = "0b29eefbe1dd"
1516
branch_labels = None
1617
depends_on = None
1718

1819

1920
def upgrade():
2021
# ### commands auto generated by Alembic - please adjust! ###
21-
op.alter_column('taxonomies', 'tax_id', new_column_name='code', existing_type=sa.Integer(), existing_nullable=False)
22+
op.alter_column("taxonomies", "tax_id", new_column_name="code", existing_type=sa.Integer(), existing_nullable=False)
2223
# ### end Alembic commands ###
2324

2425

2526
def downgrade():
2627
# ### commands auto generated by Alembic - please adjust! ###
27-
op.alter_column('taxonomies', 'code', new_column_name='tax_id', existing_type=sa.Integer(), existing_nullable=False)
28+
op.alter_column("taxonomies", "code", new_column_name="tax_id", existing_type=sa.Integer(), existing_nullable=False)
2829
# ### end Alembic commands ###

alembic/versions/0b29eefbe1dd_controlled_keyword_modification.py

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,33 @@
55
Create Date: 2025-08-07 15:45:43.241567
66
77
"""
8+
89
from alembic import op
910
import sqlalchemy as sa
1011

1112

1213
# revision identifiers, used by Alembic.
13-
revision = '0b29eefbe1dd'
14-
down_revision = '2b7a977e7e98'
14+
revision = "0b29eefbe1dd"
15+
down_revision = "2b7a977e7e98"
1516
branch_labels = None
1617
depends_on = None
1718

1819

1920
def upgrade():
2021
# ### commands auto generated by Alembic - please adjust! ###
2122
# Rename existing columns
22-
op.alter_column('controlled_keywords', 'value', new_column_name='label', existing_type=sa.String(), existing_nullable=False)
23-
op.alter_column('controlled_keywords', 'vocabulary', new_column_name='system', existing_type=sa.String(), existing_nullable=True)
23+
op.alter_column(
24+
"controlled_keywords", "value", new_column_name="label", existing_type=sa.String(), existing_nullable=False
25+
)
26+
op.alter_column(
27+
"controlled_keywords", "vocabulary", new_column_name="system", existing_type=sa.String(), existing_nullable=True
28+
)
2429
# Add new columns
25-
op.add_column('controlled_keywords', sa.Column('code', sa.String(), nullable=True))
26-
op.add_column('controlled_keywords', sa.Column('version', sa.String(), nullable=True))
30+
op.add_column("controlled_keywords", sa.Column("code", sa.String(), nullable=True))
31+
op.add_column("controlled_keywords", sa.Column("version", sa.String(), nullable=True))
2732
# Drop and recreate the correct unique constraint
28-
op.drop_constraint('ix_controlled_keywords_key_value', 'controlled_keywords', type_='unique')
29-
op.create_unique_constraint('ix_controlled_keywords_key_label', 'controlled_keywords', ['key', 'label'])
33+
op.drop_constraint("ix_controlled_keywords_key_value", "controlled_keywords", type_="unique")
34+
op.create_unique_constraint("ix_controlled_keywords_key_label", "controlled_keywords", ["key", "label"])
3035
# ### end Alembic commands ###
3136

3237
# TODO: Will modify this part when we get the final GO terms.
@@ -37,10 +42,14 @@ def upgrade():
3742

3843
def downgrade():
3944
# ### commands auto generated by Alembic - please adjust! ###
40-
op.alter_column('controlled_keywords', 'label', new_column_name='value', existing_type=sa.String(), existing_nullable=False)
41-
op.alter_column('controlled_keywords', 'system', new_column_name='vocabulary', existing_type=sa.String(), existing_nullable=True)
42-
op.drop_constraint('ix_controlled_keywords_key_label', 'controlled_keywords', type_='unique')
43-
op.create_unique_constraint('ix_controlled_keywords_key_value', 'controlled_keywords', ['key', 'value'])
44-
op.drop_column('controlled_keywords', 'version')
45-
op.drop_column('controlled_keywords', 'code')
45+
op.alter_column(
46+
"controlled_keywords", "label", new_column_name="value", existing_type=sa.String(), existing_nullable=False
47+
)
48+
op.alter_column(
49+
"controlled_keywords", "system", new_column_name="vocabulary", existing_type=sa.String(), existing_nullable=True
50+
)
51+
op.drop_constraint("ix_controlled_keywords_key_label", "controlled_keywords", type_="unique")
52+
op.create_unique_constraint("ix_controlled_keywords_key_value", "controlled_keywords", ["key", "value"])
53+
op.drop_column("controlled_keywords", "version")
54+
op.drop_column("controlled_keywords", "code")
4655
# ### end Alembic commands ###

src/mavedb/lib/clingen/content_constructors.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ def construct_ldh_submission_entity(variant: Variant, mapped_variant: Optional[M
5454
return entity
5555

5656

57-
def construct_ldh_submission(variant_content: list[tuple[str, Variant, Optional[MappedVariant]]]) -> list[LdhSubmission]:
57+
def construct_ldh_submission(
58+
variant_content: list[tuple[str, Variant, Optional[MappedVariant]]],
59+
) -> list[LdhSubmission]:
5860
content_submission: list[LdhSubmission] = []
5961
for hgvs, variant, mapped_variant in variant_content:
6062
subject = construct_ldh_submission_subject(hgvs)

src/mavedb/lib/target_genes.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ def search_target_genes(
3232
TargetGene.score_set.has(
3333
or_(
3434
ScoreSet.created_by_id == owner_or_contributor.id,
35-
ScoreSet.contributors.any(
36-
Contributor.orcid_id == owner_or_contributor.username
37-
),
35+
ScoreSet.contributors.any(Contributor.orcid_id == owner_or_contributor.username),
3836
)
3937
)
4038
)

src/mavedb/lib/validation/dataframe/column.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -73,38 +73,49 @@ def validate_variant_formatting(column: pd.Series, prefixes: list[str], targets:
7373

7474
# if there is more than one target, we expect variants to be fully qualified
7575
if fully_qualified:
76-
invalid_fully_qualified = [f"{len(str(v).split(':'))} invalid fully qualified found from row {idx}"
77-
for idx, v in enumerate(variants) if len(str(v).split(":")) != 2]
76+
invalid_fully_qualified = [
77+
f"{len(str(v).split(':'))} invalid fully qualified found from row {idx}"
78+
for idx, v in enumerate(variants)
79+
if len(str(v).split(":")) != 2
80+
]
7881
if invalid_fully_qualified:
7982
raise ValidationError(
8083
f"variant column '{column.name}' has {len(invalid_fully_qualified)} unqualified variants.",
81-
triggers=invalid_fully_qualified
84+
triggers=invalid_fully_qualified,
8285
)
8386

84-
inconsistent_prefixes = [f"row {idx}: '{v}' uses inconsistent prefix '{str(v).split(':')[1][:2]}'"
85-
for idx, v in enumerate(variants)
86-
if len(set(str(v).split(":")[1][:2] for v in variants)) > 1]
87+
inconsistent_prefixes = [
88+
f"row {idx}: '{v}' uses inconsistent prefix '{str(v).split(':')[1][:2]}'"
89+
for idx, v in enumerate(variants)
90+
if len(set(str(v).split(":")[1][:2] for v in variants)) > 1
91+
]
8792
if inconsistent_prefixes:
8893
raise ValidationError(
8994
f"variant column '{column.name}' has {len(inconsistent_prefixes)} inconsistent variant prefixes.",
90-
triggers=inconsistent_prefixes
95+
triggers=inconsistent_prefixes,
9196
)
9297

93-
invalid_prefixes = [f"row {idx}: '{v}' uses invalid prefix '{str(v).split(':')[1][:2]}'"
94-
for idx, v in enumerate(variants) if str(v).split(":")[1][:2] not in prefixes]
98+
invalid_prefixes = [
99+
f"row {idx}: '{v}' uses invalid prefix '{str(v).split(':')[1][:2]}'"
100+
for idx, v in enumerate(variants)
101+
if str(v).split(":")[1][:2] not in prefixes
102+
]
95103
if invalid_prefixes:
96104
raise ValidationError(
97105
f"variant column '{column.name}' has {len(invalid_prefixes)} invalid variant prefixes.",
98-
triggers=invalid_prefixes
106+
triggers=invalid_prefixes,
99107
)
100108

101-
invalid_accessions = [f"accession identifier {str(v).split(':')[0]} from row {idx}, variant {v} not found"
102-
for idx, v in enumerate(variants) if str(v).split(":")[0] not in targets]
109+
invalid_accessions = [
110+
f"accession identifier {str(v).split(':')[0]} from row {idx}, variant {v} not found"
111+
for idx, v in enumerate(variants)
112+
if str(v).split(":")[0] not in targets
113+
]
103114
if invalid_accessions:
104115
raise ValidationError(
105116
f"variant column '{column.name}' has invalid accession identifiers; "
106117
f"{len(invalid_accessions)} accession identifiers present in the score file were not added as targets.",
107-
triggers=invalid_accessions
118+
triggers=invalid_accessions,
108119
)
109120

110121
else:

src/mavedb/lib/validation/dataframe/variant.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ def _validate_allelic_variation(variant: Variant) -> bool:
217217
If the variant is not a valid HGVS string (for reasons of transcript/variant inconsistency).
218218
"""
219219

220-
for variant_sub_string in variant.components(): # type: ignore
220+
for variant_sub_string in variant.components(): # type: ignore
221221
validator.validate(parser.parse(variant_sub_string), strict=False)
222222

223223
return True

src/mavedb/lib/validation/keywords.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
import re
21
from typing import Optional
32

43
from mavedb.lib.validation.exceptions import ValidationError
54
from mavedb.lib.validation.utilities import is_null
65

76

87
def validate_code(key: str, label: str, code: Optional[str]):
9-
if key.lower() == "phenotypic assay mechanism" and label.lower() != "other":
10-
# The Gene Ontology accession is a unique seven digit identifier prefixed by GO:.
11-
# e.g. GO:0005739, GO:1904659, or GO:0016597.
12-
if code is None or not re.match(r"^GO:\d{7}$", code):
13-
raise ValidationError("Invalid Gene Ontology accession.")
8+
# TODO(#511) Re-enable the Gene Ontology code requirement.
9+
pass
10+
# if key.lower() == "phenotypic assay mechanism" and label.lower() != "other":
11+
# # The Gene Ontology accession is a unique seven digit identifier prefixed by GO:.
12+
# # e.g. GO:0005739, GO:1904659, or GO:0016597.
13+
# if code is None or not re.match(r"^GO:\d{7}$", code):
14+
# raise ValidationError("Invalid Gene Ontology accession.")
1415

1516

1617
# TODO: label will not be Optional when we confirm the final controlled keyword list.

src/mavedb/routers/experiment_sets.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,9 @@ def fetch_experiment_set(
5252

5353
# Filter experiment sub-resources to only those experiments readable by the requesting user.
5454
item.experiments[:] = [exp for exp in item.experiments if has_permission(user_data, exp, Action.READ).permitted]
55-
enriched_experiments = [
56-
enrich_experiment_with_num_score_sets(exp, user_data)
57-
for exp in item.experiments
58-
]
59-
enriched_item = experiment_set.ExperimentSet.model_validate(item).copy(update={
60-
"experiments": enriched_experiments,
61-
"num_experiments": len(enriched_experiments)
62-
})
55+
enriched_experiments = [enrich_experiment_with_num_score_sets(exp, user_data) for exp in item.experiments]
56+
enriched_item = experiment_set.ExperimentSet.model_validate(item).copy(
57+
update={"experiments": enriched_experiments, "num_experiments": len(enriched_experiments)}
58+
)
6359

6460
return enriched_item

src/mavedb/routers/experiments.py

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,7 @@ def search_experiments(search: ExperimentsSearch, db: Session = Depends(deps.get
8989
Search experiments.
9090
"""
9191
items = _search_experiments(db, None, search)
92-
return [
93-
enrich_experiment_with_num_score_sets(exp, None)
94-
for exp in items
95-
]
92+
return [enrich_experiment_with_num_score_sets(exp, None) for exp in items]
9693

9794

9895
@router.post(
@@ -109,10 +106,7 @@ def search_my_experiments(
109106
Search experiments created by the current user..
110107
"""
111108
items = _search_experiments(db, user_data.user, search)
112-
return [
113-
enrich_experiment_with_num_score_sets(exp, user_data)
114-
for exp in items
115-
]
109+
return [enrich_experiment_with_num_score_sets(exp, user_data) for exp in items]
116110

117111

118112
@router.get(
@@ -176,11 +170,7 @@ def get_experiment_score_sets(
176170
)
177171

178172
filter_superseded_score_set_tails = [
179-
find_superseded_score_set_tail(
180-
score_set,
181-
Action.READ,
182-
user_data
183-
) for score_set in score_set_result
173+
find_superseded_score_set_tail(score_set, Action.READ, user_data) for score_set in score_set_result
184174
]
185175
filtered_score_sets = [score_set for score_set in filter_superseded_score_set_tails if score_set is not None]
186176
if not filtered_score_sets:

src/mavedb/routers/score_sets.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,10 +1465,7 @@ async def get_clinical_controls_for_score_set(
14651465
select(ClinicalControl)
14661466
.join(ClinicalControl.mapped_variants)
14671467
.join(MappedVariant.variant)
1468-
.options(
1469-
contains_eager(ClinicalControl.mapped_variants)
1470-
.contains_eager(MappedVariant.variant)
1471-
)
1468+
.options(contains_eager(ClinicalControl.mapped_variants).contains_eager(MappedVariant.variant))
14721469
.filter(MappedVariant.current.is_(True))
14731470
.filter(Variant.score_set_id == item.id)
14741471
)

0 commit comments

Comments
 (0)