Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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 .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "submodules/cat_vrs"]
path = submodules/cat_vrs
url = https://github.com/ga4gh/cat-vrs
branch = 1.1
branch = 1.1.1-ballot.2026-09
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ keywords = ["bioinformatics", "ga4gh", "genomics", "variation"]
requires-python = ">=3.10"
dynamic = ["version"]
dependencies = [
"ga4gh.vrs~=2.4.0-a4",
"ga4gh.vrs~=2.4.0-a5",
"pydantic>=2.0,<3.0",
]

Expand Down
4 changes: 2 additions & 2 deletions src/ga4gh/cat_vrs/metadata.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"""Provide metadata mixins for Cat-VRS models."""

from ga4gh.cat_vrs.version import CATVRS_VERSION
from ga4gh.core.metadata import GKSMetadataMixin
from ga4gh.core.metadata import GKMMetadataMixin


class CatVRSMetadataMixin(GKSMetadataMixin):
class CatVRSMetadataMixin(GKMMetadataMixin):
"""Provide metadata for a concrete Cat-VRS model."""

_product_name = "cat-vrs"
Expand Down
1 change: 1 addition & 0 deletions src/ga4gh/cat_vrs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ class Constraint(CatVRSMetadataMixin, RootModel):
"""Constraints are used to construct an intensional semantics of categorical variant types."""

_maturity: ClassVar[Maturity] = Maturity.TRIAL_USE
_abstract: ClassVar[bool] = True

root: (
DefiningAlleleConstraint
Expand Down
2 changes: 1 addition & 1 deletion src/ga4gh/cat_vrs/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Define Cat-VRS version"""

CATVRS_VERSION = "1.1.0"
CATVRS_VERSION = "1.1.1-ballot.2026-09.1"
2 changes: 1 addition & 1 deletion submodules/cat_vrs
Submodule cat_vrs updated 147 files
6 changes: 3 additions & 3 deletions tests/validation/test_cat_vrs_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@


class CatVrsSchema(str, Enum):
"""Enum for Cat VRS schema"""
"""Enum for Cat-VRS schemas."""

CAT_VRS = "cat_vrs"
RECIPES = "recipes"


class CatVrsSchemaMapping(BaseModel):
"""Model for representing Cat-VRS Schema concrete classes, primitives, and schema"""
"""Represent Cat-VRS JSON Schema classes, primitives, and definitions."""

base_classes: set = set()
concrete_classes: set = set()
Expand All @@ -41,7 +41,7 @@ def _update_cat_vrs_schema_mapping(
spec_class = cls_def["title"]
cat_vrs_schema_mapping.cat_vrs_schema[spec_class] = cls_def

if "properties" in cls_def:
if "properties" in cls_def and not cls_def.get("abstract"):
cat_vrs_schema_mapping.concrete_classes.add(spec_class)
elif cls_def.get("type") in {"array", "integer", "string"}:
cat_vrs_schema_mapping.primitives.add(spec_class)
Expand Down
70 changes: 46 additions & 24 deletions tests/validation/test_model_metadata.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,47 @@
"""Test model metadata against the Cat-VRS source and JSON schemas."""
"""Test model metadata against the Cat-VRS JSON schemas."""

import json
from pathlib import Path

import pytest
import yaml
from pydantic import RootModel

from ga4gh.cat_vrs import CATVRS_VERSION, models, recipes
from ga4gh.core.metadata import Maturity

SCHEMA_DIR = Path(__file__).parents[2] / "submodules" / "cat_vrs" / "schema" / "cat-vrs"
SCHEMAS = (
(models, SCHEMA_DIR / "cat-vrs-source.yaml"),
(recipes, SCHEMA_DIR / "recipes-source.yaml"),
)
SCHEMAS = (models, recipes)
JSON_DIR = SCHEMA_DIR / "json"

with (SCHEMA_DIR / "cat-vrs-source.yaml").open() as source_file:
CATVRS_SOURCE = yaml.safe_load(source_file)
with (JSON_DIR / "CategoricalVariant").open() as schema_file:
SPEC_VERSION = json.load(schema_file)["$id"].split("/")[-3]

SPEC_VERSION = CATVRS_SOURCE["$id"].split("/")[-2]

def _model_params(abstract: bool):
"""Return model metadata discovered from JSON Schema files.

def _model_params():
"""Return model metadata discovered from both source YAML files."""
:param abstract: Whether to return abstract models.
:returns: Pytest parameters for matching Cat-VRS models and schemas.
"""
params = []
for model_module, source_path in SCHEMAS:
with source_path.open() as source_file:
definitions = yaml.safe_load(source_file)["$defs"]
for name, definition in definitions.items():
model = getattr(model_module, name)
with (JSON_DIR / name).open() as schema_file:
schema = json.load(schema_file)
params.append(pytest.param(model, definition, schema, id=name))
assert params, "No concrete Cat-VRS models discovered"
for schema_path in sorted(JSON_DIR.iterdir()):
with schema_path.open() as schema_file:
schema = json.load(schema_file)
if schema.get("abstract", False) is not abstract:
continue
model = next(
(
getattr(module, schema_path.name, None)
for module in SCHEMAS
if hasattr(module, schema_path.name)
),
None,
)
if model is not None:
params.append(pytest.param(model, schema, id=schema_path.name))
assert (
params
), f"No {'abstract' if abstract else 'concrete'} Cat-VRS models discovered"
return params


Expand All @@ -42,17 +50,31 @@ def test_cat_vrs_version_matches_source_schema():
assert CATVRS_VERSION == SPEC_VERSION


@pytest.mark.parametrize(("model", "definition", "schema"), _model_params())
def test_model_metadata(model, definition, schema):
"""Model metadata matches its source and generated JSON Schemas."""
@pytest.mark.parametrize(("model", "schema"), _model_params(abstract=False))
def test_concrete_model_metadata(model, schema):
"""Concrete model metadata matches its published JSON Schema."""
expected_schema_id = (
f"https://w3id.org/ga4gh/schema/cat-vrs/{SPEC_VERSION}/json/"
f"{model.__name__}"
)
assert model.schema_id() == expected_schema_id
assert model.maturity() == Maturity(definition["maturity"])
assert model.maturity() == Maturity(schema["maturity"])

generated_schema = model.model_json_schema()
assert generated_schema["$id"] == expected_schema_id
assert generated_schema["maturity"] == schema["maturity"]
assert "ga4gh" not in generated_schema


@pytest.mark.parametrize(("model", "schema"), _model_params(abstract=True))
def test_abstract_model_metadata(model, schema):
"""Abstract compatibility adapters expose published JSON Schema metadata."""
assert model.maturity() == Maturity(schema["maturity"])

generated_schema = model.model_json_schema()
assert generated_schema["$id"] == schema["$id"]
assert generated_schema["maturity"] == schema["maturity"]
assert generated_schema["abstract"] is True
if issubclass(model, RootModel):
assert generated_schema["discriminator"]["propertyName"] == "type"
assert len(generated_schema["oneOf"]) == len(schema["oneOf"])
Loading