diff --git a/Pipfile b/Pipfile index 5de6f28d..b11fcf2a 100644 --- a/Pipfile +++ b/Pipfile @@ -14,11 +14,12 @@ gffutils = "*" requests = "*" "biocommons.seqrepo" = "*" seqrepo = "*" -"ga4gh.vrs" = "==0.6.3rc0" +"ga4gh.vrs" = {version = "==0.7.0rc3", extras = ["extras"]} uvloop = "*" websockets = "*" httptools = "*" typing-extensions = "*" +"ga4gh.vrsatile.pydantic" = "*" [dev-packages] gene = {editable = true, path = "."} diff --git a/gene/query.py b/gene/query.py index 11997f02..c5559ef8 100644 --- a/gene/query.py +++ b/gene/query.py @@ -7,8 +7,9 @@ from gene import NAMESPACE_LOOKUP, PREFIX_LOOKUP, ITEM_TYPES from gene.database import Database from gene.schemas import Gene, SourceMeta, MatchType, SourceName, \ - ServiceMeta, GeneDescriptor, GeneValueObject, Extension, SourcePriority, \ - NormalizeService, SearchService + ServiceMeta, SourcePriority, NormalizeService, SearchService +from ga4gh.vrsatile.pydantic.vrs_model import Gene as GeneValueObject +from ga4gh.vrsatile.pydantic.vrsatile_model import GeneDescriptor, Extension from botocore.exceptions import ClientError from boto3.dynamodb.conditions import Key from datetime import datetime @@ -93,9 +94,11 @@ def add_record(self, # DynamoDB Numbers get converted to Decimal if 'locations' in item: for loc in item['locations']: - if loc['interval']['type'] == "SimpleInterval": - loc['interval']['start'] = int(loc['interval']['start']) - loc['interval']['end'] = int(loc['interval']['end']) + if loc['interval']['type'] == "SequenceInterval": + loc['interval']['start']['value'] = \ + int(loc['interval']['start']['value']) + loc['interval']['end']['value'] = \ + int(loc['interval']['end']['value']) gene = Gene(**item) src_name = item['src_name'] @@ -373,7 +376,7 @@ def _add_merged_meta(self, response: Dict) -> Dict: """ sources_meta = {} gene_descr = response['gene_descriptor'] - ids = [gene_descr['value']['id']] + gene_descr.get('xrefs', []) + ids = [gene_descr['gene']['gene_id']] + gene_descr.get('xrefs', []) for concept_id in ids: prefix = concept_id.split(':')[0] src_name = PREFIX_LOOKUP[prefix.lower()] @@ -396,7 +399,7 @@ def add_gene_descriptor(self, response, record, match_type, params = { "id": f"normalize.gene:{quote(response['query'])}", "label": record["symbol"], - "value": GeneValueObject(id=record["concept_id"]) + "gene": GeneValueObject(gene_id=record["concept_id"]) } # xrefs diff --git a/gene/schemas.py b/gene/schemas.py index eef4a9bb..992e2a63 100644 --- a/gene/schemas.py +++ b/gene/schemas.py @@ -2,37 +2,14 @@ gene records. """ from typing import Type, List, Optional, Dict, Union, Any -from pydantic import BaseModel, StrictInt, StrictBool, validator, \ - root_validator +from pydantic import BaseModel, StrictBool, validator from enum import Enum, IntEnum -from pydantic.fields import Field +from ga4gh.vrsatile.pydantic import return_value +from ga4gh.vrsatile.pydantic.vrs_model import SequenceLocation, \ + ChromosomeLocation, CURIE +from ga4gh.vrsatile.pydantic.vrsatile_model import GeneDescriptor from datetime import datetime from pydantic.types import StrictStr -import re - - -def check_curie(cls, v): - """Validate curies.""" - if v is not None: - def _is_curie(value): - """Check that value is a curie - - :param str value: Value to validate - """ - assert all( - [ - value.count(':') == 1, - value.find(' ') == -1, - value[-1] != ':' - ] - ), 'must be a CURIE' - - if isinstance(v, str): - _is_curie(v) - elif isinstance(v, list): - for item in v: - _is_curie(item) - return v class SymbolStatus(str, Enum): @@ -50,72 +27,6 @@ class Strand(str, Enum): REVERSE = "-" -class CytobandInterval(BaseModel): - """GA4GH cytoband interval definition.""" - - end: StrictStr - start: StrictStr - type = "CytobandInterval" - - @validator('start', 'end') - def valid_loc(cls, v): - """Validate start, end""" - assert bool(re.match(r"^cen|[pq](ter|([1-9][0-9]*(\.[1-9][0-9]*)?))$", - v)), r'start/end positions must match the ' \ - r'regular expression ^cen|[pq](ter|([1-9]' \ - r'[0-9]*(\.[1-9][0-9]*)?))$' - return v - - class Config: - """Configure model example""" - - @staticmethod - def schema_extra(schema: Dict[str, Any], - model: Type['CytobandInterval']) -> None: - """Configure OpenAPI schema""" - if 'title' in schema.keys(): - schema.pop('title', None) - for p in schema.get('properties', {}).values(): - p.pop('title', None) - schema['example'] = { - "end": "q22.2", - "start": "q22.3", - "type": "CytobandInterval" - } - - -class SimpleInterval(BaseModel): - """GA4GH simple interval definition.""" - - end: StrictInt - start: StrictInt - type = "SimpleInterval" - - class Config: - """Configure model example""" - - @staticmethod - def schema_extra(schema: Dict[str, Any], - model: Type['SimpleInterval']) -> None: - """Configure OpenAPI schema""" - if 'title' in schema.keys(): - schema.pop('title', None) - for p in schema.get('properties', {}).values(): - p.pop('title', None) - schema['example'] = { - "end": 44908822, - "start": 44908821, - "type": "SimpleInterval" - } - - -class LocationType(str, Enum): - """Define string constraints for location type attribute.""" - - CHROMOSOME = "ChromosomeLocation" - SEQUENCE = "SequenceLocation" - - class Annotation(str, Enum): """Define string constraints for annotations when gene location is absent. @@ -133,87 +44,10 @@ class Chromosome(str, Enum): MITOCHONDRIA = 'MT' -class Location(BaseModel): - """Define string constraints for the location attribute.""" - - id: Optional[StrictStr] = Field(alias='_id') - type: LocationType - - -class ChromosomeLocation(Location): - """GA4GH Chromosome Location definition.""" - - species_id: StrictStr - chr: StrictStr - interval: CytobandInterval - type = LocationType.CHROMOSOME - - _validate_curie = validator('species_id', allow_reuse=True)(check_curie) - - @validator('chr') - def valid_chr(cls, v): - """Validate chr""" - assert v.isalnum(), 'chr must have only alphanumeric characters' - return v - - class Config: - """Configure model example""" - - @staticmethod - def schema_extra(schema: Dict[str, Any], - model: Type['ChromosomeLocation']) -> None: - """Configure OpenAPI schema""" - if 'title' in schema.keys(): - schema.pop('title', None) - for p in schema.get('properties', {}).values(): - p.pop('title', None) - schema['example'] = { - "chr": "11", - "interval": { - "end": "q22.2", - "start": "q22.3", - "type": "CytobandInterval" - }, - "species_id": "taxonomy:9606", - "type": "ChromosomeLocation" - } - - -class SequenceLocation(Location): - """GA4GH Sequence Location definition.""" - - sequence_id: StrictStr - interval: SimpleInterval - type = LocationType.SEQUENCE - - _validate_curie = validator('sequence_id', allow_reuse=True)(check_curie) - - class Config: - """Configure model example""" - - @staticmethod - def schema_extra(schema: Dict[str, Any], - model: Type['SequenceLocation']) -> None: - """Configure OpenAPI schema""" - if 'title' in schema.keys(): - schema.pop('title', None) - for p in schema.get('properties', {}).values(): - p.pop('title', None) - schema['example'] = { - "interval": { - "end": 44908822, - "start": 44908821, - "type": "SimpleInterval" - }, - "sequence_id": "ga4gh:SQ.IIB53T8CNeJJdUqzn9V_JnRtQadwWCbl", - "type": "SequenceLocation" - } - - class Gene(BaseModel): """Gene""" - concept_id: StrictStr + concept_id: CURIE symbol: StrictStr symbol_status: Optional[SymbolStatus] label: Optional[StrictStr] @@ -222,14 +56,14 @@ class Gene(BaseModel): locations: Optional[List[Union[SequenceLocation, ChromosomeLocation]]] = [] aliases: Optional[List[StrictStr]] = [] previous_symbols: Optional[List[StrictStr]] = [] - xrefs: Optional[List[str]] = [] - associated_with: Optional[List[StrictStr]] = [] + xrefs: Optional[List[CURIE]] = [] + associated_with: Optional[List[CURIE]] = [] - _validate_concept_id = \ - validator('concept_id', allow_reuse=True)(check_curie) - _validate_xrefs = validator('xrefs', allow_reuse=True)(check_curie) - _validate_associated_with = \ - validator('associated_with', allow_reuse=True)(check_curie) + _get_concept_id_val = \ + validator('concept_id', allow_reuse=True)(return_value) + _get_xrefs_val = validator('xrefs', allow_reuse=True)(return_value) + _get_associated_with_val = \ + validator('associated_with', allow_reuse=True)(return_value) class Config: """Configure model example""" @@ -255,150 +89,6 @@ def schema_extra(schema: Dict[str, Any], } -class Extension(BaseModel): - """Define model for VRSATILE Extension.""" - - type = "Extension" - name: StrictStr - value: Union[StrictStr, List[Dict], List[StrictStr], Dict] - - class Config: - """Configure model example""" - - @staticmethod - def schema_extra(schema: Dict[str, Any], - model: Type['Extension']) -> None: - """Configure OpenAPI schema""" - if 'title' in schema.keys(): - schema.pop('title', None) - for p in schema.get('properties', {}).values(): - p.pop('title', None) - schema['example'] = { - "type": "Extension", - "name": "strand", - "value": "-" - } - - -class GeneValueObject(BaseModel): - """Define model for VRS Gene Value Object.""" - - id: StrictStr - type = "Gene" - - _validate_curie = validator('id', allow_reuse=True)(check_curie) - - class Config: - """Configure model example""" - - @staticmethod - def schema_extra(schema: Dict[str, Any], - model: Type['Gene']) -> None: - """Configure OpenAPI schema""" - if 'title' in schema.keys(): - schema.pop('title', None) - for p in schema.get('properties', {}).values(): - p.pop('title', None) - schema['example'] = { - "type": "Gene", - "id": "hgnc:5" - } - - -class GeneDescriptor(BaseModel): - """Define model for VRSATILE Gene Descriptor.""" - - id: StrictStr - type = "GeneDescriptor" - value: Optional[GeneValueObject] - value_id: Optional[StrictStr] - label: Optional[StrictStr] - xrefs: Optional[List[StrictStr]] - alternate_labels: Optional[List[StrictStr]] - extensions: Optional[List[Extension]] - - _validate_id = validator('id', allow_reuse=True)(check_curie) - _validate_value_id = validator('value_id', allow_reuse=True)(check_curie) - - @root_validator(pre=True) - def check_value_or_value_id_present(cls, values): - """Check that at least one of {`value`, `value_id`} is provided.""" - msg = 'Must give values for either `value`, `value_id`, or both' - value, value_id = values.get('value'), values.get('value_id') - assert value or value_id, msg - return values - - class Config: - """Configure model example""" - - @staticmethod - def schema_extra(schema: Dict[str, Any], - model: Type['Extension']) -> None: - """Configure OpenAPI schema""" - if 'title' in schema.keys(): - schema.pop('title', None) - for p in schema.get('properties', {}).values(): - p.pop('title', None) - schema['example'] = { - "id": "normalize.gene:BRAF", - "name": "GeneDescriptor", - "value": { - "id": "hgnc:1097", - "type": "Gene" - }, - "label": "BRAF", - "xrefs": [ - "ncbigene:673", - "ensembl:ENSG00000157764" - ], - "alternate_labels": [ - "B-Raf proto-oncogene, serine/threonine kinase", - "BRAF1" - ], - "extensions": [ - { - "name": "symbol_status", - "value": "approved", - "type": "Extension" - }, - { - "name": "associated_with", - "value": [ - "vega:OTTHUMG00000157457", - "ucsc:uc003vwc.5", - "ccds:CCDS5863", - "ccds:CCDS87555", - "uniprot:P15056", - "pubmed:2284096", - "pubmed:1565476", - "cosmic:BRAF", - "omim:164757", - "orphanet:119066", - "iuphar:1943", - "ena.embl:M95712", - "refseq:NM_004333" - ], - "type": "Extension" - }, - { - "name": "chromosome_location", - "value": { - "_id": "ga4gh:VCL.O6yCQ1cnThOrTfK9YUgMlTfM6HTqbrKw", # noqa: E501 - "type": "ChromosomeLocation", - "species_id": "taxonomy:9606", - "chr": "7", - "interval": { - "end": "q34", - "start": "q34", - "type": "CytobandInterval" - } - }, - "type": "Extension" - } - ] - } - - class GeneGroup(Gene): """A grouping of genes based on common attributes.""" @@ -733,7 +423,7 @@ def schema_extra(schema: Dict[str, Any], "gene_descriptor": { "id": "normalize.gene:BRAF", "name": "GeneDescriptor", - "value": { + "gene": { "id": "hgnc:1097", "type": "Gene" }, diff --git a/gene/version.py b/gene/version.py index 86205cba..08f934f4 100644 --- a/gene/version.py +++ b/gene/version.py @@ -1 +1 @@ -__version__ = "0.1.17" +__version__ = "0.1.18" diff --git a/gene/vrs_locations/sequence_location.py b/gene/vrs_locations/sequence_location.py index 49a6bb7d..3deeb2a3 100644 --- a/gene/vrs_locations/sequence_location.py +++ b/gene/vrs_locations/sequence_location.py @@ -37,14 +37,14 @@ def add_location(self, seqid, gene, params, sr): if 0 <= gene.start <= gene.end: seq_location = models.SequenceLocation( sequence_id=sequence_id, - interval=models.SimpleInterval( - start=gene.start, - end=gene.end + interval=models.SequenceInterval( + start=models.Number(value=gene.start - 1), + end=models.Number(value=gene.end) ) ) seq_location._id = ga4gh_identify(seq_location) location = seq_location.as_dict() else: logger.info(f"{params['concept_id']} has invalid interval:" - f"start={gene.start} end={gene.end}") + f"start={gene.start - 1} end={gene.end}") return location diff --git a/requirements-dev.txt b/requirements-dev.txt index b7354771..dde5933f 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -15,8 +15,8 @@ appdirs==1.4.4 appnope==0.1.2; sys_platform == 'darwin' argcomplete==1.12.3 argh==0.26.2 -argon2-cffi==20.1.0 -asgiref==3.4.1; python_version >= '3.6' +argon2-cffi==21.1.0; python_version >= '3.5' +asgiref==3.4.1; python_full_version >= '3.6.0' attrs==21.2.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' babel==2.9.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' backcall==0.2.0 @@ -24,19 +24,20 @@ backports-datetime-fromisoformat==1.0.0 backports.entry-points-selectable==1.1.0; python_version >= '2.7' beautifulsoup4==4.9.3 biocommons.seqrepo==0.6.4 -bioutils==0.5.5; python_version >= '3.6' -bleach==4.0.0; python_version >= '3.6' -boto3==1.18.22 -botocore==1.21.22; python_version >= '3.6' +bioutils==0.5.5; python_full_version >= '3.6.0' +bleach==4.1.0; python_version >= '3.6' +boto3==1.18.32 +botocore==1.21.32; python_full_version >= '3.6.0' bs4==0.0.1 canonicaljson==1.4.0; python_version ~= '3.5' certifi==2021.5.30 cffi==1.14.6 -cfgv==3.3.0; python_full_version >= '3.6.1' +cfgv==3.3.1; python_full_version >= '3.6.1' charset-normalizer==2.0.4; python_version >= '3' civicpy==1.1.3; python_version >= '3.5' click==8.0.1 coloredlogs==15.0.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +configparser==5.0.2; python_full_version >= '3.6.0' coverage==5.5 coveralls==3.2.0 cssselect==1.1.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' @@ -48,37 +49,39 @@ distlib==0.3.2 docopt==0.6.2 entrypoints==0.3; python_version >= '2.7' fake-useragent==0.1.11 -fastapi==0.68.0 +fastapi==0.68.1 filelock==3.0.12 flake8-docstrings==1.6.0 flake8==3.9.2 -frozendict==2.0.6; python_version >= '3.6' -ga4gh.vrs==0.6.3rc0 +frozendict==2.0.6; python_full_version >= '3.6.0' +ga4gh.vrs[extras]==0.7.0rc3 +ga4gh.vrsatile.pydantic==0.0.1 gffutils==0.10.1 -h11==0.12.0; python_version >= '3.6' +h11==0.12.0; python_full_version >= '3.6.0' +hgvs==1.5.1 httptools==0.3.0 humanfriendly==9.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' identify==2.2.13; python_full_version >= '3.6.1' idna==3.2; python_version >= '3' -importlib-metadata==4.6.4; python_version >= '3.6' +importlib-metadata==4.8.1; python_full_version >= '3.6.0' inflection==0.5.1; python_version >= '3.5' iniconfig==1.1.1 -ipykernel==6.2.0; python_version >= '3.7' +ipykernel==6.3.1; python_version >= '3.7' ipython-genutils==0.2.0 -ipython==7.26.0; python_version >= '3.7' -jedi==0.18.0; python_version >= '3.6' +ipython==7.27.0; python_version >= '3.7' +jedi==0.18.0; python_full_version >= '3.6.0' jinja2==3.0.1; python_version >= '3.6' jmespath==0.10.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3' json5==0.9.6 jsonschema==3.2.0 -jupyter-client==6.1.12; python_version >= '3.5' +jupyter-client==7.0.2; python_full_version >= '3.6.1' jupyter-core==4.7.1; python_version >= '3.6' jupyter-server==1.10.2; python_version >= '3.6' jupyterlab-pygments==0.1.2 -jupyterlab-server==2.7.0; python_version >= '3.6' -jupyterlab==3.1.7 +jupyterlab-server==2.7.2; python_version >= '3.6' +jupyterlab==3.1.9 lxml==4.6.3; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -markdown==3.3.4; python_version >= '3.6' +markdown==3.3.4; python_full_version >= '3.6.0' markupsafe==2.0.1; python_version >= '3.6' matplotlib-inline==0.1.2; python_version >= '3.5' mccabe==0.6.1 @@ -98,14 +101,16 @@ packaging==21.0; python_version >= '3.6' pandas==1.3.2; python_full_version >= '3.7.1' pandocfilters==1.4.3 parse==1.19.0 -parso==0.8.2; python_version >= '3.6' +parsley==1.3 +parso==0.8.2; python_full_version >= '3.6.0' pexpect==4.8.0; sys_platform != 'win32' pickleshare==0.7.5 -platformdirs==2.2.0; python_version >= '3.6' -pluggy==0.13.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -pre-commit==2.14.0 +platformdirs==2.3.0; python_version >= '3.6' +pluggy==1.0.0; python_version >= '3.6' +pre-commit==2.14.1 prometheus-client==0.11.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -prompt-toolkit==3.0.19; python_full_version >= '3.6.1' +prompt-toolkit==3.0.20; python_full_version >= '3.6.2' +psycopg2-binary==2.9.1; python_full_version >= '3.6.0' ptyprocess==0.7.0 py==1.10.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' pycodestyle==2.7.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' @@ -113,42 +118,42 @@ pycparser==2.20; python_version >= '2.7' and python_version not in '3.0, 3.1, 3. pydantic==1.8.2 pydocstyle==6.1.1; python_version >= '3.6' pyee==8.2.2 -pyfaidx==0.6.1 +pyfaidx==0.6.2 pyflakes==2.3.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' pygments==2.10.0; python_version >= '3.5' pyparsing==2.4.7; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3' pyppeteer==0.2.6; python_version < '4' and python_full_version >= '3.6.1' pyquery==1.4.3 -pyrsistent==0.18.0; python_version >= '3.6' +pyrsistent==0.18.0; python_full_version >= '3.6.0' pysam==0.16.0.1 pytest-cov==2.12.1 -pytest==6.2.4 +pytest==6.2.5 python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' python-jsonschema-objects==0.3.10 pytz==2021.1 pyyaml==5.4.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' pyzmq==22.2.1; python_version >= '3.6' -requests-html==0.10.0; python_version >= '3.6' +requests-html==0.10.0; python_full_version >= '3.6.0' requests-unixsocket==0.2.0 requests==2.26.0 -s3transfer==0.5.0; python_version >= '3.6' +s3transfer==0.5.0; python_full_version >= '3.6.0' send2trash==1.8.0 seqrepo==0.0.0 -simplejson==3.17.3; python_version >= '2.5' and python_version not in '3.0, 3.1, 3.2, 3.3' +simplejson==3.17.5; python_version >= '2.5' and python_version not in '3.0, 3.1, 3.2, 3.3' six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' sniffio==1.2.0; python_version >= '3.5' snowballstemmer==2.1.0 soupsieve==2.2.1; python_version >= '3' sqlparse==0.4.1; python_version >= '3.5' -starlette==0.14.2; python_version >= '3.6' +starlette==0.14.2; python_full_version >= '3.6.0' tabulate==0.8.9 -terminado==0.11.0; python_version >= '3.6' +terminado==0.11.1; python_version >= '3.6' testpath==0.5.0; python_version >= '3.5' toml==0.10.2; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3' tornado==6.1; python_version >= '3.5' -tqdm==4.62.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -traitlets==5.0.5; python_version >= '3.7' -typing-extensions==3.10.0.0 +tqdm==4.62.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +traitlets==5.1.0; python_version >= '3.7' +typing-extensions==3.10.0.2 urllib3==1.26.6; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4' uvicorn==0.15.0 uvloop==0.16.0 @@ -160,4 +165,4 @@ webencodings==0.5.1 websocket-client==1.2.1; python_version >= '3.6' websockets==9.1 yoyo-migrations==7.3.2 -zipp==3.5.0; python_version >= '3.6' +zipp==3.5.0; python_full_version >= '3.6.0' diff --git a/requirements.txt b/requirements.txt index c35f1db5..7a6b519b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,72 +10,76 @@ appdirs==1.4.4 appnope==0.1.2; sys_platform == 'darwin' argcomplete==1.12.3 argh==0.26.2 -asgiref==3.4.1; python_version >= '3.6' +asgiref==3.4.1; python_full_version >= '3.6.0' attrs==21.2.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' backcall==0.2.0 beautifulsoup4==4.9.3 biocommons.seqrepo==0.6.4 -bioutils==0.5.5; python_version >= '3.6' -boto3==1.18.22 -botocore==1.21.22; python_version >= '3.6' +bioutils==0.5.5; python_full_version >= '3.6.0' +boto3==1.18.32 +botocore==1.21.32; python_full_version >= '3.6.0' bs4==0.0.1 canonicaljson==1.4.0; python_version ~= '3.5' certifi==2021.5.30 charset-normalizer==2.0.4; python_version >= '3' click==8.0.1 coloredlogs==15.0.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' +configparser==5.0.2; python_full_version >= '3.6.0' cssselect==1.1.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' decorator==5.0.9; python_version >= '3.5' fake-useragent==0.1.11 -fastapi==0.68.0 -frozendict==2.0.6; python_version >= '3.6' -ga4gh.vrs==0.6.3rc0 +fastapi==0.68.1 +frozendict==2.0.6; python_full_version >= '3.6.0' +ga4gh.vrs[extras]==0.7.0rc3 +ga4gh.vrsatile.pydantic==0.0.1 gffutils==0.10.1 -h11==0.12.0; python_version >= '3.6' +h11==0.12.0; python_full_version >= '3.6.0' +hgvs==1.5.1 httptools==0.3.0 humanfriendly==9.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' idna==3.2; python_version >= '3' -importlib-metadata==4.6.4; python_version >= '3.6' +importlib-metadata==4.8.1; python_full_version >= '3.6.0' inflection==0.5.1; python_version >= '3.5' -ipython-genutils==0.2.0 -ipython==7.26.0; python_version >= '3.7' -jedi==0.18.0; python_version >= '3.6' +ipython==7.27.0; python_version >= '3.7' +jedi==0.18.0; python_full_version >= '3.6.0' jmespath==0.10.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3' jsonschema==3.2.0 lxml==4.6.3; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' -markdown==3.3.4; python_version >= '3.6' +markdown==3.3.4; python_full_version >= '3.6.0' matplotlib-inline==0.1.2; python_version >= '3.5' numpy==1.21.2; python_version < '3.11' and python_version >= '3.7' parse==1.19.0 -parso==0.8.2; python_version >= '3.6' +parsley==1.3 +parso==0.8.2; python_full_version >= '3.6.0' pexpect==4.8.0; sys_platform != 'win32' pickleshare==0.7.5 -prompt-toolkit==3.0.19; python_full_version >= '3.6.1' +prompt-toolkit==3.0.20; python_full_version >= '3.6.2' +psycopg2-binary==2.9.1; python_full_version >= '3.6.0' ptyprocess==0.7.0 pydantic==1.8.2 pyee==8.2.2 -pyfaidx==0.6.1 +pyfaidx==0.6.2 pygments==2.10.0; python_version >= '3.5' pyppeteer==0.2.6; python_version < '4' and python_full_version >= '3.6.1' pyquery==1.4.3 -pyrsistent==0.18.0; python_version >= '3.6' +pyrsistent==0.18.0; python_full_version >= '3.6.0' pysam==0.16.0.1 python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' python-jsonschema-objects==0.3.10 pyyaml==5.4.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' -requests-html==0.10.0; python_version >= '3.6' +requests-html==0.10.0; python_full_version >= '3.6.0' requests==2.26.0 -s3transfer==0.5.0; python_version >= '3.6' +s3transfer==0.5.0; python_full_version >= '3.6.0' seqrepo==0.0.0 -simplejson==3.17.3; python_version >= '2.5' and python_version not in '3.0, 3.1, 3.2, 3.3' +simplejson==3.17.5; python_version >= '2.5' and python_version not in '3.0, 3.1, 3.2, 3.3' six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' soupsieve==2.2.1; python_version >= '3' sqlparse==0.4.1; python_version >= '3.5' -starlette==0.14.2; python_version >= '3.6' +starlette==0.14.2; python_full_version >= '3.6.0' tabulate==0.8.9 -tqdm==4.62.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' -traitlets==5.0.5; python_version >= '3.7' -typing-extensions==3.10.0.0 +tqdm==4.62.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3' +traitlets==5.1.0; python_version >= '3.7' +typing-extensions==3.10.0.2 urllib3==1.26.6; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4' uvicorn==0.15.0 uvloop==0.16.0 @@ -83,4 +87,4 @@ w3lib==1.22.0 wcwidth==0.2.5 websockets==9.1 yoyo-migrations==7.3.2 -zipp==3.5.0; python_version >= '3.6' +zipp==3.5.0; python_full_version >= '3.6.0' diff --git a/setup.cfg b/setup.cfg index 57b5730d..0da92e52 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,13 +30,12 @@ install_requires = fastapi uvicorn click - civicpy boto3 beautifulsoup4 gffutils requests biocommons.seqrepo - ga4gh.vrs + ga4gh.vrs[extras] == 0.7.0rc3 tests_require = diff --git a/tests/unit/test_ensembl_source.py b/tests/unit/test_ensembl_source.py index 117f8162..ee68f01d 100644 --- a/tests/unit/test_ensembl_source.py +++ b/tests/unit/test_ensembl_source.py @@ -34,11 +34,11 @@ def ddx11l1(): 'location_annotations': [], 'locations': [ { - '_id': 'ga4gh:VSL.iTXYEeSmSj73q-lpxtKLlnp_1OlX658F', + '_id': 'ga4gh:VSL.naD2_Q0JKCEKkGj8FvMzerePKnNNcF5N', 'interval': { - 'end': 14409, - 'start': 11869, - 'type': 'SimpleInterval' + 'end': {'value': 14409, 'type': 'Number'}, + 'start': {'value': 11868, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.Ya6Rs7DHhDeg7YaOSg1EoNi3U_nQ9SvO', 'type': 'SequenceLocation' @@ -64,11 +64,11 @@ def tp53(): 'location_annotations': [], 'locations': [ { - '_id': 'ga4gh:VSL.FfERYK71L10OLwk6QGoG8OPLgl7PItgK', + '_id': 'ga4gh:VSL.7q-vAjxSYARaPbbUjhDng2oay795NfbE', 'interval': { - 'end': 7687538, - 'start': 7661779, - 'type': 'SimpleInterval' + 'end': {'value': 7687538, 'type': 'Number'}, + 'start': {'value': 7661778, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.dLZ15tNO1Ur0IcGjwc3Sdi_0A6Yf4zm7', 'type': 'SequenceLocation' @@ -94,11 +94,11 @@ def u6(): 'location_annotations': [], 'locations': [ { - '_id': 'ga4gh:VSL.7Gh2fIORi69Fm1UMai49Ek-6HQNzuyqv', + '_id': 'ga4gh:VSL.mtPBK609IiOFy0gztyTnEGdWM_k_e85C', 'interval': { - 'end': 516479, - 'start': 516376, - 'type': 'SimpleInterval' + 'end': {'value': 516479, 'type': 'Number'}, + 'start': {'value': 516375, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.Ya6Rs7DHhDeg7YaOSg1EoNi3U_nQ9SvO', 'type': 'SequenceLocation' @@ -124,11 +124,11 @@ def CH17_340M24_3(): 'location_annotations': [], 'locations': [ { - '_id': 'ga4gh:VSL.L5PJ5tioPr5ozAj1Ad0VIG-qHrGXnMUh', + '_id': 'ga4gh:VSL.EJaq2KK3bIftDcyP1YAmJLb08JbBAmAn', 'interval': { - 'end': 154428479, - 'start': 154424380, - 'type': 'SimpleInterval' + 'end': {'value': 154428479, 'type': 'Number'}, + 'start': {'value': 154424379, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.w0WZEvgJF0zf_P4yyTzjjv9oW1z61HHP', 'type': 'SequenceLocation' @@ -154,11 +154,11 @@ def AC091057_5(): 'location_annotations': [], 'locations': [ { - '_id': 'ga4gh:VSL.UJx3xHRkDuoALaGxyic-cPQNQnXYiAM8', + '_id': 'ga4gh:VSL.sZGLn8Ah76rP34pu8-7W73lkCwQ7XSJD', 'interval': { - 'end': 30685606, - 'start': 30624548, - 'type': 'SimpleInterval' + 'end': {'value': 30685606, 'type': 'Number'}, + 'start': {'value': 30624547, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.AsXvWL1-2i5U_buw6_niVIxD6zTbAuS6', 'type': 'SequenceLocation' @@ -184,11 +184,11 @@ def hsa_mir_1253(): 'location_annotations': [], 'locations': [ { - '_id': 'ga4gh:VSL.hS8fW7o0qqy15qOnQOKv1VqOZQDBswNI', + '_id': 'ga4gh:VSL.goBvYPYef2mQildG6AiiRNVhTo-g4-1E', 'interval': { - 'end': 2748182, - 'start': 2748078, - 'type': 'SimpleInterval' + 'end': {'value': 2748182, 'type': 'Number'}, + 'start': {'value': 2748077, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.dLZ15tNO1Ur0IcGjwc3Sdi_0A6Yf4zm7', 'type': 'SequenceLocation' @@ -214,11 +214,11 @@ def spry3(): 'location_annotations': [], 'locations': [ { - '_id': 'ga4gh:VSL.h8YcFZq0v-Vwj6aGarOvh1R3LFNGD0YU', + '_id': 'ga4gh:VSL.7Jax3UNlW_EZrZ44U-R1eLe_OeCC71IR', 'interval': { - 'end': 155782459, - 'start': 155612572, - 'type': 'SimpleInterval' + 'end': {'value': 155782459, 'type': 'Number'}, + 'start': {'value': 155612571, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.w0WZEvgJF0zf_P4yyTzjjv9oW1z61HHP', 'type': 'SequenceLocation' diff --git a/tests/unit/test_ncbi_source.py b/tests/unit/test_ncbi_source.py index d78ad5d0..e1b7e39c 100644 --- a/tests/unit/test_ncbi_source.py +++ b/tests/unit/test_ncbi_source.py @@ -48,11 +48,11 @@ def dpf1(): 'type': 'ChromosomeLocation' }, { - '_id': 'ga4gh:VSL.5ddLPk8gIdQm3YA4r4p5NAsty9SPwXvJ', + '_id': 'ga4gh:VSL.MbzGuoGI9MRB8oPe6eE-ULk3FIBdpMF8', 'interval': { - 'end': 38229695, - 'start': 38211006, - 'type': 'SimpleInterval' + 'end': {'value': 38229695, 'type': 'Number'}, + 'start': {'value': 38211005, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.IIB53T8CNeJJdUqzn9V_JnRtQadwWCbl', 'type': 'SequenceLocation' @@ -89,11 +89,11 @@ def pdp1(): 'type': 'ChromosomeLocation' }, { - '_id': 'ga4gh:VSL.s8NNWWCxWeiOCUa90ge6x8wxFWpO34gV', + '_id': 'ga4gh:VSL.KmLM61Mm2jxuep7cdgg7lvOOXaIxSW0Y', 'interval': { - 'end': 93926068, - 'start': 93916923, - 'type': 'SimpleInterval' + 'end': {'value': 93926068, 'type': 'Number'}, + 'start': {'value': 93916922, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.209Z7zJ-mFypBEWLk4rNC6S_OxY5p7bs', 'type': 'SequenceLocation' @@ -143,21 +143,21 @@ def spry3(): 'type': 'ChromosomeLocation' }, { - '_id': 'ga4gh:VSL.ILQGzmwapQ5xuIBoFPDTKUOuN9gJNSqp', + '_id': 'ga4gh:VSL.r6_z0hmAdPdufX0g1ciRj_zPU6poQviA', 'interval': { - 'end': 155782459, - 'start': 155612586, - 'type': 'SimpleInterval' + 'end': {'value': 155782459, 'type': 'Number'}, + 'start': {'value': 155612585, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.w0WZEvgJF0zf_P4yyTzjjv9oW1z61HHP', 'type': 'SequenceLocation' }, { - '_id': 'ga4gh:VSL.R8x4-hQzGNmp654J83nUT2RJlIXOucno', + '_id': 'ga4gh:VSL.Cr_HtUTpUe6KB37Y7zOTDbx9JglIzE1O', 'interval': { - 'end': 56968979, - 'start': 56923423, - 'type': 'SimpleInterval' + 'end': {'value': 56968979, 'type': 'Number'}, + 'start': {'value': 56923422, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.8_liLu1aycC0tPQPFmUaGXJLDs5SbPZ5', 'type': 'SequenceLocation' @@ -235,11 +235,11 @@ def znf84(): 'type': 'ChromosomeLocation' }, { - '_id': 'ga4gh:VSL.xuSNWLM7M4vru2gbt2hOfmjL7GD_UYdA', + '_id': 'ga4gh:VSL.w5FE3al-0SUkARxk_RdCD5ypYIh_WtSM', 'interval': { - 'end': 133063299, - 'start': 133037301, - 'type': 'SimpleInterval' + 'end': {'value': 133063299, 'type': 'Number'}, + 'start': {'value': 133037300, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.6wlJpONE3oNb4D69ULmEXhqyDZ4vwNfl', 'type': 'SequenceLocation' @@ -266,21 +266,21 @@ def slc25a6(): 'strand': '-', 'locations': [ { - '_id': 'ga4gh:VSL.8LvkImsib1GaFH8UQrz9DwjdrgkWNmdD', + '_id': 'ga4gh:VSL.HG0bXHwmZoxZzU2ckz4T6lvxIswXhLQZ', 'interval': { - 'end': 1392113, - 'start': 1386152, - 'type': 'SimpleInterval' + 'end': {'value': 1392113, 'type': 'Number'}, + 'start': {'value': 1386151, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.w0WZEvgJF0zf_P4yyTzjjv9oW1z61HHP', 'type': 'SequenceLocation' }, { - '_id': 'ga4gh:VSL.QLShSFmwPqUKTzjNS-x3Y3DZtOV4SK4J', + '_id': 'ga4gh:VSL.1J-MNAWJ9hvZtIM_90lqLbxEt707zL_A', 'interval': { - 'end': 1392113, - 'start': 1386152, - 'type': 'SimpleInterval' + 'end': {'value': 1392113, 'type': 'Number'}, + 'start': {'value': 1386151, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.8_liLu1aycC0tPQPFmUaGXJLDs5SbPZ5', 'type': 'SequenceLocation' @@ -415,21 +415,21 @@ def prkrap1(): 'type': 'ChromosomeLocation' }, { - '_id': 'ga4gh:VSL.Sk6GHE3MekN_PaimBKBmsQR6pLqQ-SAN', + '_id': 'ga4gh:VSL.WB_2IFcms7VmbkPBXUgUaH-R1EdKRs4s', 'interval': { - 'end': 3941874, - 'start': 3940270, - 'type': 'SimpleInterval' + 'end': {'value': 3941874, 'type': 'Number'}, + 'start': {'value': 3940269, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.MjujHSAsgNWRTX4w3ysM7b5OVhZpdXu1', 'type': 'SequenceLocation' }, { - '_id': 'ga4gh:VSL.WTVn8f6OmsdbiEniT8W4CHuHJdp78oBP', + '_id': 'ga4gh:VSL.PIeADExe9_iSJkTLQbSvhxAJ8PM19R6r', 'interval': { - 'end': 3932085, - 'start': 3930481, - 'type': 'SimpleInterval' + 'end': {'value': 3932085, 'type': 'Number'}, + 'start': {'value': 3930480, 'type': 'Number'}, + 'type': 'SequenceInterval' }, 'sequence_id': 'ga4gh:SQ.Q8IworEhpLeXwpz1CHM7C3luysh-ltx-', 'type': 'SequenceLocation' diff --git a/tests/unit/test_query.py b/tests/unit/test_query.py index 3a9187f4..0fd4651e 100644 --- a/tests/unit/test_query.py +++ b/tests/unit/test_query.py @@ -30,8 +30,8 @@ def normalized_ache(): return { "id": "normalize.gene:ACHE", "type": "GeneDescriptor", - "value": { - "id": "hgnc:108", + "gene": { + "gene_id": "hgnc:108", "type": "Gene" }, "label": "ACHE", @@ -107,8 +107,8 @@ def normalized_braf(): return { "id": "normalize.gene:BRAF", "type": "GeneDescriptor", - "value": { - "id": "hgnc:1097", + "gene": { + "gene_id": "hgnc:1097", "type": "Gene" }, "label": "BRAF", @@ -178,8 +178,8 @@ def normalized_abl1(): return { "id": "normalize.gene:ABL1", "type": "GeneDescriptor", - "value": { - "id": "hgnc:76", + "gene": { + "gene_id": "hgnc:76", "type": "Gene" }, "label": "ABL1", @@ -264,8 +264,8 @@ def normalized_p150(): return { "id": "normalize.gene:P150", "type": "GeneDescriptor", - "value": { - "id": "hgnc:1910", + "gene": { + "gene_id": "hgnc:1910", "type": "Gene" }, "label": "CHAF1A", @@ -375,7 +375,7 @@ def compare_gene_descriptor(test, actual): """Test that actual and expected gene descriptors match.""" assert actual["id"] == test["id"] assert actual["type"] == test["type"] - assert actual["value"] == test["value"] + assert actual["gene"] == test["gene"] assert actual["label"] == test["label"] assert set(actual["xrefs"]) == set(test["xrefs"]), "xrefs" assert set(actual["alternate_labels"]) == set(test["alternate_labels"]), \ diff --git a/tests/unit/test_schemas.py b/tests/unit/test_schemas.py index 0d075fb2..32a5bc36 100644 --- a/tests/unit/test_schemas.py +++ b/tests/unit/test_schemas.py @@ -1,9 +1,10 @@ """Module to test validators in the schemas module.""" import pytest import pydantic -from gene.schemas import ChromosomeLocation, SequenceLocation, Gene, \ - GeneDescriptor, CytobandInterval, SimpleInterval, GeneValueObject, \ - Extension +from gene.schemas import Gene +from ga4gh.vrsatile.pydantic.vrs_model import ChromosomeLocation, \ + SequenceLocation, Gene as GeneValueObject, CytobandInterval, \ + SequenceInterval, Number @pytest.fixture(scope='module') @@ -26,50 +27,20 @@ def chromosome_location(cytoband_interval): @pytest.fixture(scope='module') -def simple_interval(): +def sequence_interval(): """Create a valid simple interval test fixture.""" - return SimpleInterval( - start=140719327, - end=140924929 + return SequenceInterval( + start=Number(value=140719327), + end=Number(value=140924929) ) @pytest.fixture(scope='module') -def sequence_location(simple_interval): +def sequence_location(sequence_interval): """Create a valid sequence location test fixture.""" return SequenceLocation( sequence_id='ga4gh:SQ.F-LrLMe1SRpfUZHkQmvkVKFEGaoDeHul', - interval=simple_interval - ) - - -@pytest.fixture(scope='module') -def gene_value_object(): - """Create a valid gene value object test fixture.""" - return GeneValueObject( - id='hgnc:1097' - ) - - -@pytest.fixture(scope='module') -def gene_descriptor(gene_value_object): - """Create a valid gene descriptor test fixture.""" - return GeneDescriptor( - id='normalize.gene:BRAF', - value=gene_value_object - ) - - -@pytest.fixture(scope='module') -def extension(): - """Create a valid extension test fixture.""" - return Extension( - name="associated_with", - value=[ - "ucsc:uc003vwc.5", - "pubmed:1565476", - "omim:164757" - ] + interval=sequence_interval ) @@ -82,167 +53,6 @@ def gene(): ) -def test_chromosome_location(chromosome_location, cytoband_interval): - """Test that validators for Chromosome Location work correctly.""" - assert chromosome_location - - # species_id not a valid curie - with pytest.raises(pydantic.error_wrappers.ValidationError): - ChromosomeLocation( - species_id='taxonomy9606', - chr='7', - interval=cytoband_interval - ) - - # chromosome not a str - with pytest.raises(pydantic.error_wrappers.ValidationError): - ChromosomeLocation( - species_id='taxonomy:9606', - chr=7, - interval=cytoband_interval - ) - - # cytoband interval does not match regex pattern - with pytest.raises(pydantic.error_wrappers.ValidationError): - ChromosomeLocation( - species_id='taxonomy9:606', - chr='7', - interval=CytobandInterval( - end='end', - start='q34' - ) - ) - - # cytoband interval does not match regex pattern - with pytest.raises(pydantic.error_wrappers.ValidationError): - ChromosomeLocation( - species_id='taxonomy9:606', - chr='7', - interval=CytobandInterval( - end=5, - start=2 - ) - ) - - with pytest.raises(pydantic.error_wrappers.ValidationError): - ChromosomeLocation( - species_ud='taxonomy:4232', chr='5', - interval=CytobandInterval( - start=17, - end=18 - ) - ) - - -def test_sequence_location(sequence_location, simple_interval): - """Test that validators for Sequence Location work correctly.""" - assert sequence_location - - # sequence_id is not a valid curie - with pytest.raises(pydantic.error_wrappers.ValidationError): - SequenceLocation( - sequence_id='ga4ghSQ.F-LrLMe1SRpfUZHkQmvkVKFEGaoDeHul', - interval=simple_interval - ) - - # Simple interval start/end not int - with pytest.raises(pydantic.error_wrappers.ValidationError): - SequenceLocation( - sequence_id='ga4gh:SQ.F-LrLMe1SRpfUZHkQmvkVKFEGaoDeHul', - interval=SimpleInterval( - start='140719327', - end='140924929' - ) - ) - - with pytest.raises(pydantic.error_wrappers.ValidationError): - SequenceLocation( - sequence_id='ga4gh:SQ.F-LrLMe1SRpfUZHkQmvkVKFEGaoDeHul', - interval=SimpleInterval( - start='s', - end='q' - ) - ) - - with pytest.raises(pydantic.error_wrappers.ValidationError): - SequenceLocation( - sequence_id='ncbiNC_000001.11', - interval=SimpleInterval( - start='s', - end='p' - ) - ) - - -def test_gene_value_object(gene_value_object): - """Test that validators for gene value object work correctly.""" - assert gene_value_object - - with pytest.raises(pydantic.error_wrappers.ValidationError): - GeneValueObject( - id='hgnc1097' - ) - - -def test_extension(extension): - """Test that validators for extension work correctly.""" - assert extension - - assert Extension(name='strand', value='-') - - # name is not a str - with pytest.raises(pydantic.error_wrappers.ValidationError): - Extension(name=3, value=['ucsc:uc003vwc.5']) - - -def test_gene_descriptor(gene_descriptor): - """Test that validators for gene descriptor work correctly.""" - assert gene_descriptor - assert GeneDescriptor( - id='test:g1', - value=GeneValueObject(id='hgnc:1497', type='Gene'), - label='G1', - xrefs=['ncbi:g1'], - alternate_labels=['gen1'] - ) - - with pytest.raises(pydantic.error_wrappers.ValidationError): - GeneDescriptor( - id=1, - value=GeneValueObject(id='hgnc1497', type='Gene'), - label='G1', - xrefs=['ncbi:g1'], - alternate_labels=['gen1'] - ) - - # No value or value_id - with pytest.raises(pydantic.error_wrappers.ValidationError): - GeneDescriptor( - id='normalize.gene:BRAF' - ) - - # id not a valid curie - with pytest.raises(pydantic.error_wrappers.ValidationError): - GeneDescriptor( - id='normalize.geneBRAF', - value_id='hgnc:1' - ) - - # value_id not a valid curie - with pytest.raises(pydantic.error_wrappers.ValidationError): - GeneDescriptor( - id='normalize.gene:BRAF', - value_id='value_id' - ) - - # value not a gene value object - with pytest.raises(pydantic.error_wrappers.ValidationError): - GeneDescriptor( - id='normalize.gene:BRAF', - value=['value'] - ) - - def test_gene(gene, chromosome_location, sequence_location): """Test that validators for gene work correctly.""" assert gene