diff --git a/.github/workflows/gkb_workflows/pytest.yml b/.github/workflows/gkb_workflows/pytest.yml index f34a5ce..4f00ce3 100644 --- a/.github/workflows/gkb_workflows/pytest.yml +++ b/.github/workflows/gkb_workflows/pytest.yml @@ -12,7 +12,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.7', '3.8', '3.9', '3.10'] + python-version: ['3.9', '3.10'] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 071f417..0566f09 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] + python-version: ['3.9', '3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v3 @@ -32,15 +32,15 @@ jobs: run: | pip install flake8 # stop the build if there are Python syntax errors or undefined names - flake8 ipr graphkb --count --select=E9,F63,F7,F82 --show-source --statistics + flake8 pori_python --count --select=E9,F63,F7,F82 --show-source --statistics - name: Check with black run: | pip install black - black --check -S -l 100 ipr graphkb tests + black --check -S -l 100 pori_python tests - name: Full Tests with pytest run: | pip list - pytest --junitxml=junit/test-results-${{ matrix.python-version }}.xml --cov ipr --cov-report term --cov-report xml + pytest --junitxml=junit/test-results-${{ matrix.python-version }}.xml --cov pori_python --cov-report term --cov-report xml env: IPR_USER: ${{ secrets.IPR_TEST_USER }} IPR_PASS: ${{ secrets.IPR_TEST_PASSWORD }} diff --git a/.github/workflows/quick-pytest.yml b/.github/workflows/quick-pytest.yml index 6bcf1d4..d2f8e69 100644 --- a/.github/workflows/quick-pytest.yml +++ b/.github/workflows/quick-pytest.yml @@ -13,7 +13,7 @@ jobs: strategy: max-parallel: 4 matrix: - python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] + python-version: ['3.9', '3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v3 @@ -29,11 +29,11 @@ jobs: run: | pip install flake8 # stop the build if there are Python syntax errors or undefined names - flake8 ipr graphkb --count --select=E9,F63,F7,F82 --show-source --statistics + flake8 pori_python --count --select=E9,F63,F7,F82 --show-source --statistics - name: Check with black run: | pip install black - black --check -S -l 100 ipr graphkb tests + black --check -S -l 100 pori_python tests - name: Short Tests with pytest run: pytest --junitxml=junit/test-results-${{ matrix.python-version }}.xml --cov ipr --cov-report term --cov-report xml env: diff --git a/pori_python/graphkb/genes.py b/pori_python/graphkb/genes.py index 7b6979e..af53c7c 100644 --- a/pori_python/graphkb/genes.py +++ b/pori_python/graphkb/genes.py @@ -229,6 +229,16 @@ def get_preferred_gene_name( def get_cancer_predisposition_info( conn: GraphKBConnection, source: str = PREFERRED_GENE_SOURCE ) -> Tuple[List[str], Dict[str, str]]: + newval = get_gene_linked_cancer_predisposition_info(conn, source) + genes = newval[0] + allvardata = newval[1] + variants = {key: allvardata[key][0] for key in allvardata.keys()} + return newval[0], variants + + +def get_gene_linked_cancer_predisposition_info( + conn: GraphKBConnection, source: str = PREFERRED_GENE_SOURCE +) -> Tuple[List[str], Dict[str, Tuple[str, List[str]]]]: """ Return two lists from GraphKB, one of cancer predisposition genes and one of associated variants. @@ -241,6 +251,8 @@ def get_cancer_predisposition_info( Example: https://graphkb.bcgsc.ca/view/Statement/155:11616 + + Returns: genes: list of cancer predisposition genes variants: dictionary mapping pharmacogenomic variant IDs to variant display names @@ -283,21 +295,24 @@ def get_cancer_predisposition_info( ): for condition in record["conditions"]: # type: ignore if condition["@class"] == "PositionalVariant": - variants[condition["@rid"]] = condition["displayName"] + assoc_gene_list = [] for reference in ["reference1", "reference2"]: name = (condition.get(reference) or {}).get("displayName", "") biotype = (condition.get(reference) or {}).get("biotype", "") if name and biotype == "gene": genes.add(name) + assoc_gene_list.append(name) elif name: gene = get_preferred_gene_name(conn, name, source) if gene: infer_genes.add((gene, name, biotype)) + assoc_gene_list.append(gene) else: non_genes.add((name, biotype)) logger.error( f"Non-gene cancer predisposition {biotype}: {name} for {condition['displayName']}" ) + variants[condition["@rid"]] = [condition["displayName"], assoc_gene_list] for gene, name, biotype in infer_genes: logger.debug(f"Found gene '{gene}' for '{name}' ({biotype})") @@ -312,6 +327,16 @@ def get_cancer_predisposition_info( def get_pharmacogenomic_info( conn: GraphKBConnection, source: str = PREFERRED_GENE_SOURCE ) -> Tuple[List[str], Dict[str, str]]: + newval = get_gene_linked_pharmacogenomic_info(conn, source) + genes = newval[0] + allvardata = newval[1] + variants = {key: allvardata[key][0] for key in allvardata.keys()} + return newval[0], variants + + +def get_gene_linked_pharmacogenomic_info( + conn: GraphKBConnection, source: str = PREFERRED_GENE_SOURCE +) -> Tuple[List[str], Dict[str, Tuple[str, List[str]]]]: """ Return two lists from GraphKB, one of pharmacogenomic genes and one of associated variants. @@ -360,22 +385,24 @@ def get_pharmacogenomic_info( for condition in record["conditions"]: # type: ignore if condition["@class"] == "PositionalVariant": - variants[condition["@rid"]] = condition["displayName"] + assoc_gene_list = [] for reference in ["reference1", "reference2"]: name = (condition.get(reference) or {}).get("displayName", "") biotype = (condition.get(reference) or {}).get("biotype", "") if name and biotype == "gene": genes.add(name) + assoc_gene_list.append(name) elif name: gene = get_preferred_gene_name(conn, name, source) if gene: infer_genes.add((gene, name, biotype)) + assoc_gene_list.append(gene) else: non_genes.add((name, biotype)) logger.error( f"Non-gene pharmacogenomic {biotype}: {name} for {condition['displayName']}" ) - + variants[condition["@rid"]] = [condition["displayName"], assoc_gene_list] for gene, name, biotype in infer_genes: logger.debug(f"Found gene '{gene}' for '{name}' ({biotype})") genes.add(gene) diff --git a/setup.cfg b/setup.cfg index be218b0..fed938d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,7 +27,7 @@ long_description_content_type = text/markdown [options] packages = find: -python_requires = >=3.7 +python_requires = >=3.9 dependency_links = [] include_package_data = True install_requires = diff --git a/tests/test_graphkb/test_genes.py b/tests/test_graphkb/test_genes.py index 5e6e89f..d746cec 100644 --- a/tests/test_graphkb/test_genes.py +++ b/tests/test_graphkb/test_genes.py @@ -10,11 +10,13 @@ from pori_python.graphkb.genes import ( get_cancer_genes, get_cancer_predisposition_info, + get_gene_linked_cancer_predisposition_info, get_gene_information, get_genes_from_variant_types, get_oncokb_oncogenes, get_oncokb_tumour_supressors, get_pharmacogenomic_info, + get_gene_linked_pharmacogenomic_info, get_preferred_gene_name, get_therapeutic_associated_genes, ) @@ -148,6 +150,21 @@ def test_get_pharmacogenomic_info(conn): for rid, variant_display in matches.items(): if variant_display.startswith(gene): break + else: # no break called + # failing on this version of the func; addressed in 'new' version + if gene == 'ACYP2': + continue + assert False, f"No rid found for a pharmacogenomic with {gene}" + + +def test_get_gene_linked_pharmacogenomic_info(conn): + genes, matches = get_gene_linked_pharmacogenomic_info(conn) + for gene in PHARMACOGENOMIC_INITIAL_GENES: + assert gene in genes, f"{gene} not found in get_pharmacogenomic_info" + for rid, variant_info in matches.items(): + variant_gene_assoc = variant_info[1] + if gene in variant_gene_assoc: + break else: # no break called assert False, f"No rid found for a pharmacogenomic with {gene}" @@ -159,6 +176,13 @@ def test_get_cancer_predisposition_info(conn): assert gene in genes, f"{gene} not found in get_cancer_predisposition_info" +@pytest.mark.skipif(EXCLUDE_INTEGRATION_TESTS, reason="excluding long running integration tests") +def test_get_gene_linked_cancer_predisposition_info(conn): + genes, matches = get_gene_linked_cancer_predisposition_info(conn) + for gene in CANCER_PREDISP_INITIAL_GENES: + assert gene in genes, f"{gene} not found in get_cancer_predisposition_info" + + @pytest.mark.parametrize( "alt_rep", ("NM_033360.4", "NM_033360", "ENSG00000133703.11", "ENSG00000133703") ) diff --git a/tests/test_graphkb/test_graphkb.py b/tests/test_graphkb/test_graphkb.py index 5780b36..8f9bd2e 100644 --- a/tests/test_graphkb/test_graphkb.py +++ b/tests/test_graphkb/test_graphkb.py @@ -18,6 +18,7 @@ def conn(): conn.login(os.environ["GRAPHKB_USER"], os.environ["GRAPHKB_PASS"]) return conn + class TestPaginate: @mock.patch("pori_python.graphkb.GraphKBConnection.request") def test_does_not_paginate_when_false(self, graphkb_request, conn): diff --git a/tests/test_graphkb/test_match.py b/tests/test_graphkb/test_match.py index 64dd2fd..6e9165f 100644 --- a/tests/test_graphkb/test_match.py +++ b/tests/test_graphkb/test_match.py @@ -7,7 +7,10 @@ import pori_python.graphkb from pori_python.graphkb import GraphKBConnection, match -from pori_python.graphkb.constants import DEFAULT_NON_STRUCTURAL_VARIANT_TYPE, STRUCTURAL_VARIANT_SIZE_THRESHOLD +from pori_python.graphkb.constants import ( + DEFAULT_NON_STRUCTURAL_VARIANT_TYPE, + STRUCTURAL_VARIANT_SIZE_THRESHOLD, +) from pori_python.graphkb.util import FeatureNotFoundError # Test datasets @@ -500,6 +503,7 @@ def test_filling_cache(self): assert "alice" in match.FEATURES_CACHE match.FEATURES_CACHE = None + class TestTypeScreening: # Types as class variables default_type = DEFAULT_NON_STRUCTURAL_VARIANT_TYPE diff --git a/tests/test_ipr/test_annotate.py b/tests/test_ipr/test_annotate.py index eeb5a51..dd4cc01 100644 --- a/tests/test_ipr/test_annotate.py +++ b/tests/test_ipr/test_annotate.py @@ -47,6 +47,7 @@ def graphkb_conn(): graphkb_conn.login(username, password) return graphkb_conn + class TestAnnotation: def test_annotate_nonsense_vs_missense(self, graphkb_conn): """Verify missense (point mutation) is not mistaken for a nonsense (stop codon) mutation.""" @@ -58,7 +59,6 @@ def test_annotate_nonsense_vs_missense(self, graphkb_conn): assert not nonsense, f"nonsense matched to {key}: {TP53_MUT_DICT[key]}" assert matched, f"should have matched in {key}: {TP53_MUT_DICT[key]}" - def test_annotate_nonsense_vs_missense_protein(self, graphkb_conn): """Verify missense (point mutation) is not mistaken for a nonsense (stop codon) mutation.""" disease = 'cancer' @@ -69,7 +69,6 @@ def test_annotate_nonsense_vs_missense_protein(self, graphkb_conn): assert not nonsense, f"nonsense matched to {key}: {TP53_MUT_DICT[key]}" assert matched, f"should have matched in {key}: {TP53_MUT_DICT[key]}" - def test_annotate_structural_variants_tp53(self, graphkb_conn): """Verify alternate TP53 variants match.""" disease = 'cancer' diff --git a/tests/test_ipr/test_summary.py b/tests/test_ipr/test_summary.py index df1ecc3..aaee77e 100644 --- a/tests/test_ipr/test_summary.py +++ b/tests/test_ipr/test_summary.py @@ -1,6 +1,10 @@ from unittest.mock import MagicMock -from pori_python.ipr.summary import GRAPHKB_GUI, get_preferred_drug_representation, substitute_sentence_template +from pori_python.ipr.summary import ( + GRAPHKB_GUI, + get_preferred_drug_representation, + substitute_sentence_template, +) class TestGetPreferredDrugRepresentation: