From dcb7385f67d3923fea7cbc37eed42575f4a7c8bc Mon Sep 17 00:00:00 2001 From: Laura Luebbert Date: Mon, 22 Jun 2026 13:11:14 -0400 Subject: [PATCH 1/5] fix(utils): ruff D205 in diagnose_binary_load_error docstring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Multi-line summary lacked a blank line before the description body. Collapse to a single-line summary, then explanatory paragraph. Flagged by pre-commit.ci on PR #222 — not specific to that PR, but the same lint check would block every future PR until cleared. --- gget/utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gget/utils.py b/gget/utils.py index 7aa372550..2df6638f5 100644 --- a/gget/utils.py +++ b/gget/utils.py @@ -1237,8 +1237,10 @@ def write(records: Iterable[Any], filename: str, format: str | None = None) -> N def diagnose_binary_load_error(stderr_text: str, module_name: str) -> str | None: - """If stderr indicates a missing shared-library / dynamic-linker error, return a - human-friendly diagnostic + fix instructions. Otherwise return None. + """Return a human-friendly diagnostic for a missing shared-library / dynamic-linker error. + + If stderr indicates a missing shared library, return a diagnostic with fix + instructions. Otherwise return None. Covers: - macOS dyld: 'Library not loaded: ' From af9fae79e424d7d70bd6d5bd2674efef6a99a16e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2026 17:13:23 +0000 Subject: [PATCH 2/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .github/badges/tests.json | 7 +++- gget/gget_cbio.py | 4 ++- gget/gget_g2p.py | 15 +++----- gget/gget_muscle.py | 4 +-- gget/gget_pdb.py | 3 +- gget/gget_search.py | 3 +- gget/gget_setup.py | 4 +-- gget/gget_virus.py | 75 +++++++++++++++++++++++++++++++-------- gget/main.py | 31 +++------------- gget/utils.py | 6 ++-- pyproject.toml | 8 ++--- tests/pytest_results.txt | 30 ++++++++-------- tests/test_g2p.py | 1 + 13 files changed, 105 insertions(+), 86 deletions(-) diff --git a/.github/badges/tests.json b/.github/badges/tests.json index ee922eff3..b902293bd 100644 --- a/.github/badges/tests.json +++ b/.github/badges/tests.json @@ -1 +1,6 @@ -{"schemaVersion": 1, "label": "tests", "message": "394/400 passing", "color": "yellow"} +{ + "schemaVersion": 1, + "label": "tests", + "message": "394/400 passing", + "color": "yellow" +} diff --git a/gget/gget_cbio.py b/gget/gget_cbio.py index d957525b2..55659a060 100644 --- a/gget/gget_cbio.py +++ b/gget/gget_cbio.py @@ -415,7 +415,9 @@ def _get_ensembl_gene_name_bulk(gene_ids: list[str]) -> dict[str, Any]: raise e -def _get_valid_ensembl_gene_id(row: pd.Series, transcript_column: str = "seq_ID", gene_column: str = "gene_name") -> Any: +def _get_valid_ensembl_gene_id( + row: pd.Series, transcript_column: str = "seq_ID", gene_column: str = "gene_name" +) -> Any: ensembl_gene_id = _get_ensembl_gene_id(row[transcript_column]) if ensembl_gene_id == "Unknown": return row[gene_column] diff --git a/gget/gget_g2p.py b/gget/gget_g2p.py index 224ae1876..2a4e42616 100644 --- a/gget/gget_g2p.py +++ b/gget/gget_g2p.py @@ -1,11 +1,12 @@ from __future__ import annotations import io + import pandas as pd import requests from .constants import G2P_API -from .utils import set_up_logger, DEFAULT_REQUESTS_TIMEOUT +from .utils import DEFAULT_REQUESTS_TIMEOUT, set_up_logger logger = set_up_logger() @@ -43,9 +44,7 @@ def g2p( """ resources = ["features", "map", "alignment"] if resource not in resources: - raise ValueError( - f"'resource' argument specified as {resource}. Expected one of: {', '.join(resources)}" - ) + raise ValueError(f"'resource' argument specified as {resource}. Expected one of: {', '.join(resources)}") if not uniprot_id: raise ValueError( @@ -69,9 +68,7 @@ def g2p( url = f"{base}/{isoform}/alignment" if verbose: - logger.info( - f"Querying the Genomics 2 Proteins portal ('{resource}') for {gene} / {uniprot_id}..." - ) + logger.info(f"Querying the Genomics 2 Proteins portal ('{resource}') for {gene} / {uniprot_id}...") try: r = requests.get( @@ -92,9 +89,7 @@ def g2p( return if not r.text.strip(): - logger.warning( - "The Genomics 2 Proteins portal returned an empty result for this query." - ) + logger.warning("The Genomics 2 Proteins portal returned an empty result for this query.") return pd.DataFrame() df = pd.read_csv(io.StringIO(r.text), sep="\t") diff --git a/gget/gget_muscle.py b/gget/gget_muscle.py index 12bb7b7d7..69d0dcd82 100644 --- a/gget/gget_muscle.py +++ b/gget/gget_muscle.py @@ -113,9 +113,7 @@ def muscle(fasta: str | list[str], super5: bool = False, out: str | None = None, diagnosis = diagnose_binary_load_error(stderr_2, "muscle") if diagnosis: raise RuntimeError(diagnosis) - raise RuntimeError( - f"MUSCLE failed with exit code {process_2.returncode}. See stderr above for details." - ) + raise RuntimeError(f"MUSCLE failed with exit code {process_2.returncode}. See stderr above for details.") if verbose: logger.info(f"MUSCLE alignment complete. Alignment time: {round(time.time() - start_time, 2)} seconds") diff --git a/gget/gget_pdb.py b/gget/gget_pdb.py index dd657e0b0..d58a9a5c7 100644 --- a/gget/gget_pdb.py +++ b/gget/gget_pdb.py @@ -1,8 +1,7 @@ from __future__ import annotations -from typing import Any - import json +from typing import Any from urllib.error import HTTPError from urllib.request import urlopen diff --git a/gget/gget_search.py b/gget/gget_search.py index 76aa18767..a5ed75529 100644 --- a/gget/gget_search.py +++ b/gget/gget_search.py @@ -310,8 +310,7 @@ def search( # inside the list to None so an empty-synonym row is [None] rather than # [nan]. (SQL LEFT JOIN on external_synonym surfaces missing rows as NaN.) df["synonym"] = [ - [None if pd.isna(item) else item - for item in np.sort(syn if isinstance(syn, list) else [syn]).tolist()] + [None if pd.isna(item) else item for item in np.sort(syn if isinstance(syn, list) else [syn]).tolist()] for syn in df["synonym"].values ] diff --git a/gget/gget_setup.py b/gget/gget_setup.py index 53340b7d5..e83927059 100644 --- a/gget/gget_setup.py +++ b/gget/gget_setup.py @@ -115,9 +115,7 @@ def setup(module: str, verbose: bool = True, out: str | None = None) -> None: raise ValueError(f"'module' argument specified as {module}. Expected one of: {', '.join(supported_modules)}") if module == "gpt": - logger.warning( - "gget gpt is no longer actively maintained." - ) + logger.warning("gget gpt is no longer actively maintained.") _install("openai<=0.28.1", "openai", verbose=verbose) elif module == "cellxgene": diff --git a/gget/gget_virus.py b/gget/gget_virus.py index 807d06a83..8a04dfdec 100644 --- a/gget/gget_virus.py +++ b/gget/gget_virus.py @@ -341,7 +341,10 @@ def _retry_with_exponential_backoff( initial_delay: float = API_INITIAL_RETRY_DELAY, backoff_multiplier: float = API_RETRY_BACKOFF_MULTIPLIER, max_delay: int = MAX_RETRY_DELAY, - retryable_exceptions: tuple[type[BaseException], ...] = (requests.exceptions.ConnectionError, requests.exceptions.HTTPError), + retryable_exceptions: tuple[type[BaseException], ...] = ( + requests.exceptions.ConnectionError, + requests.exceptions.HTTPError, + ), failed_commands: dict[str, Any] | None = None, ) -> tuple[bool, Any, dict[str, Any] | None]: """Execute an operation with exponential backoff retry logic. @@ -414,7 +417,9 @@ def _retry_with_exponential_backoff( return False, None, error_info -def _track_failed_operation(failed_commands: dict[str, Any] | None, operation_type: str, batch_info: dict[str, Any], error_info: dict[str, Any]) -> None: +def _track_failed_operation( + failed_commands: dict[str, Any] | None, operation_type: str, batch_info: dict[str, Any], error_info: dict[str, Any] +) -> None: """Track a failed operation in the failed_commands dictionary. This ensures consistent error tracking across all operation types for @@ -864,7 +869,9 @@ def _parse_baseline_file(baseline_path: str) -> set[str]: return baseline_accessions -def _deduplicate_metadata_against_baseline(metadata_dict: dict[str, Any], baseline_accessions: set[str]) -> tuple[dict[str, Any], int]: +def _deduplicate_metadata_against_baseline( + metadata_dict: dict[str, Any], baseline_accessions: set[str] +) -> tuple[dict[str, Any], int]: """Remove metadata records whose accessions are already in the baseline set. Args: @@ -889,7 +896,9 @@ def _deduplicate_metadata_against_baseline(metadata_dict: dict[str, Any], baseli return new_metadata, skipped_count -def _save_partial_metadata(metadata_dict: dict[str, Any], outfolder: str, virus_clean: str, reason: str = "api_failure") -> str | None: +def _save_partial_metadata( + metadata_dict: dict[str, Any], outfolder: str, virus_clean: str, reason: str = "api_failure" +) -> str | None: """Save partial metadata to CSV for recovery via --baseline. Args: @@ -2786,7 +2795,9 @@ def process_cached_download(zip_file: str, virus_type: str = "virus") -> tuple[s return cached_fasta_file, cached_metadata_jsonl_path, True -def _monitor_subprocess_with_progress(process: subprocess.Popen[Any], cmd: list[str], timeout: int | None = None, progress_timeout: int | None = None) -> subprocess.CompletedProcess[Any]: +def _monitor_subprocess_with_progress( + process: subprocess.Popen[Any], cmd: list[str], timeout: int | None = None, progress_timeout: int | None = None +) -> subprocess.CompletedProcess[Any]: """Monitor a subprocess with progress tracking and timeout handling. This helper function monitors a running subprocess. When stdout/stderr are piped, it checks for progress indicators. When they're not piped (output goes to console), it simply polls for completion. @@ -3463,7 +3474,13 @@ def download_alphainfluenza_optimized( ) -def download_sequences_by_accessions(accessions: list[str], outdir: str | None = None, batch_size: int = 200, failed_commands: dict[str, Any] | None = None, api_key: str | None = None) -> str: +def download_sequences_by_accessions( + accessions: list[str], + outdir: str | None = None, + batch_size: int = 200, + failed_commands: dict[str, Any] | None = None, + api_key: str | None = None, +) -> str: """Download virus genome sequences for a specific list of accession numbers. This function downloads sequences for a pre-filtered list of accessions, @@ -3590,7 +3607,9 @@ def download_sequences_by_accessions(accessions: list[str], outdir: str | None = ) -def _download_sequences_epost_efetch(accessions: list[str], fasta_path: str, failed_commands: dict[str, Any] | None = None, api_key: str | None = None) -> str: +def _download_sequences_epost_efetch( + accessions: list[str], fasta_path: str, failed_commands: dict[str, Any] | None = None, api_key: str | None = None +) -> str: """Download FASTA sequences using NCBI EPost + EFetch History Server pipeline. This is NCBI's recommended approach for large datasets. It uploads accession @@ -3756,7 +3775,11 @@ def _fetch_fasta_batch(rs=retstart): def _download_sequences_single_batch( - accessions: list[str], NCBI_EUTILS_BASE_EFETCH: str, fasta_path: str, failed_commands: dict[str, Any] | None = None, api_key: str | None = None + accessions: list[str], + NCBI_EUTILS_BASE_EFETCH: str, + fasta_path: str, + failed_commands: dict[str, Any] | None = None, + api_key: str | None = None, ) -> str: """Download sequences in a single E-utilities request with exponential backoff retries. @@ -3882,7 +3905,12 @@ def execute_request(): def _download_sequences_batched( - accessions: list[str], NCBI_EUTILS_BASE_EFETCH: str, fasta_path: str, batch_size: int, failed_commands: dict[str, Any] | None = None, api_key: str | None = None + accessions: list[str], + NCBI_EUTILS_BASE_EFETCH: str, + fasta_path: str, + batch_size: int, + failed_commands: dict[str, Any] | None = None, + api_key: str | None = None, ) -> str: """Download sequences using multiple batched E-utilities requests with incremental file writing. @@ -4154,7 +4182,9 @@ def _parse_date(date_str: str, filtername: str = "") -> datetime: # return None -def _parse_partial_date_for_range_check(date_str: str, for_min_comparison: bool = True, filtername: str = "") -> datetime: +def _parse_partial_date_for_range_check( + date_str: str, for_min_comparison: bool = True, filtername: str = "" +) -> datetime: """Parse partial dates with range-aware handling for comparison. When comparing partial dates (year-only or year-month) against specific dates, @@ -4749,7 +4779,9 @@ def load_metadata_from_api_reports(api_reports: list[dict[str, Any]]) -> dict[st return metadata_dict -def _check_protein_requirements(record: Any, metadata: dict[str, Any], has_proteins: Any, proteins_complete: bool) -> bool: +def _check_protein_requirements( + record: Any, metadata: dict[str, Any], has_proteins: Any, proteins_complete: bool +) -> bool: """Check if a sequence meets protein/gene requirements based on FASTA header. This function validates whether a virus sequence contains required proteins @@ -5491,7 +5523,9 @@ def merge_metadata_csvs(genbank_csv_path: str, standard_csv_path: str) -> bool: return False -def save_metadata_to_csv(filtered_metadata: list[dict[str, Any]], protein_headers: list[Any], output_metadata_file: str) -> None: +def save_metadata_to_csv( + filtered_metadata: list[dict[str, Any]], protein_headers: list[Any], output_metadata_file: str +) -> None: """Save filtered metadata to a CSV file with a specific column order. This function creates a comprehensive CSV file containing all relevant metadata @@ -5968,7 +6002,14 @@ def _epost_accessions(accessions: list[str], api_key: str | None = None) -> tupl return None, None -def _efetch_with_history(web_env: str, query_key: str, retstart: int, retmax: int, api_key: str | None = None, failed_log_path: str | None = None) -> tuple[dict[str, Any], str]: +def _efetch_with_history( + web_env: str, + query_key: str, + retstart: int, + retmax: int, + api_key: str | None = None, + failed_log_path: str | None = None, +) -> tuple[dict[str, Any], str]: """Fetch GenBank records using History Server reference (WebEnv/query_key). This is the NCBI-recommended method for large datasets. After uploading UIDs @@ -6609,7 +6650,9 @@ def fetch_genbank_metadata( return all_metadata, failed_log_path if os.path.exists(failed_log_path) else None -def _fetch_genbank_batch(accessions: list[str], failed_log_path: str | None = None) -> tuple[dict[str, Any], str | None]: +def _fetch_genbank_batch( + accessions: list[str], failed_log_path: str | None = None +) -> tuple[dict[str, Any], str | None]: """Fetch GenBank metadata for a single batch of accessions. Includes retry logic with exponential backoff and automatic batch splitting @@ -7188,7 +7231,9 @@ def _parse_genbank_xml(xml_content: str) -> dict[str, Any]: return metadata_dict -def save_genbank_metadata_to_csv(genbank_metadata: dict[str, Any], output_file: str, virus_metadata: list[dict[str, Any]] | None = None) -> None: +def save_genbank_metadata_to_csv( + genbank_metadata: dict[str, Any], output_file: str, virus_metadata: list[dict[str, Any]] | None = None +) -> None: """Save GenBank metadata to a CSV file with the same column headers as the standard metadata CSV. Args: diff --git a/gget/main.py b/gget/main.py index 8c8467b28..c626917dd 100644 --- a/gget/main.py +++ b/gget/main.py @@ -1,10 +1,9 @@ from __future__ import annotations -from typing import Any - import argparse import sys from datetime import datetime +from typing import Any import pandas as pd @@ -31,6 +30,7 @@ from .gget_diamond import diamond # noqa: E402 from .gget_elm import elm # noqa: E402 from .gget_enrichr import enrichr # noqa: E402 +from .gget_g2p import g2p from .gget_gpt import gpt # noqa: E402 from .gget_info import info # noqa: E402 from .gget_muscle import muscle # noqa: E402 @@ -41,27 +41,8 @@ # Module functions from .gget_ref import ref from .gget_search import search -from .gget_info import info from .gget_seq import seq -from .gget_muscle import muscle -from .gget_blast import blast -from .gget_blat import blat -from .gget_enrichr import enrichr -from .gget_archs4 import archs4 -from .gget_alphafold import alphafold from .gget_setup import setup -from .gget_pdb import pdb -from .gget_gpt import gpt -from .gget_cellxgene import cellxgene -from .gget_elm import elm -from .gget_diamond import diamond -from .gget_cosmic import cosmic -from .gget_mutate import mutate -from .gget_opentargets import opentargets, OPENTARGETS_RESOURCES -from .gget_cbio import cbio_plot, cbio_search -from .gget_bgee import bgee -from .gget_g2p import g2p -from .gget_8cube import specificity, psi_block, gene_expression from .gget_virus import virus @@ -3835,16 +3816,12 @@ def main() -> None: if args.csv: g2p_results.to_csv(f, index=False) else: - g2p_results.to_json( - f, orient="records", force_ascii=False, indent=4 - ) + g2p_results.to_json(f, orient="records", force_ascii=False, indent=4) else: if args.csv: g2p_results.to_csv(sys.stdout, index=False) else: - print( - g2p_results.to_json(orient="records", force_ascii=False, indent=4) - ) + print(g2p_results.to_json(orient="records", force_ascii=False, indent=4)) ## 8cube return if args.command == "8cube": diff --git a/gget/utils.py b/gget/utils.py index 2df6638f5..2d86a564c 100644 --- a/gget/utils.py +++ b/gget/utils.py @@ -7,7 +7,8 @@ import os import time import uuid -from typing import TYPE_CHECKING, Any, Callable, Iterable +from collections.abc import Callable, Iterable +from typing import TYPE_CHECKING, Any import numpy as np import pandas as pd @@ -1298,8 +1299,7 @@ def _shared_library_install_hint(lib_basename: str, system: str) -> str: if system == "Darwin": return ( - "Install the package that provides this library via Homebrew (https://brew.sh) " - "or another package manager." + "Install the package that provides this library via Homebrew (https://brew.sh) or another package manager." ) if system == "Linux": return "Install the package that provides this library via your system package manager." diff --git a/pyproject.toml b/pyproject.toml index ebe4ee23c..2b7f7fb57 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -126,7 +126,6 @@ lint.per-file-ignores."tests/*" = [ "D" ] lint.pydocstyle.convention = "numpy" [tool.mypy] -python_version = "3.12" files = [ "gget" ] # `gget/constants.py` (module) coexists with `gget/constants/` (data dir, no # __init__.py). Mypy's default namespace-package discovery treats the data dir @@ -135,11 +134,12 @@ files = [ "gget" ] namespace_packages = false ignore_missing_imports = true follow_imports = "silent" -check_untyped_defs = false -disallow_untyped_defs = false +python_version = "3.12" disallow_any_generics = false -warn_unused_ignores = true +disallow_untyped_defs = false +check_untyped_defs = false warn_redundant_casts = true +warn_unused_ignores = true show_error_codes = true [tool.pytest] diff --git a/tests/pytest_results.txt b/tests/pytest_results.txt index d1d7e3966..c67c897e3 100644 --- a/tests/pytest_results.txt +++ b/tests/pytest_results.txt @@ -422,8 +422,8 @@ self = > result_to_test = do_call(func, td[test]["args"]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -tests/from_json.py:68: -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +tests/from_json.py:68: +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/from_json.py:60: in do_call return func(**args) ^^^^^^^^^^^^ @@ -435,7 +435,7 @@ gget/gget_bgee.py:60: in _bgee_orthologs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ gget/gget_bgee.py:24: in _bgee_species payload = http_json( -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ method = 'GET', url = 'https://bgee.org/api/' context = 'Bgee API (species lookup)', timeout = (10, 60), retries = 3 @@ -453,10 +453,10 @@ kwargs = {'params': {'display_type': 'json', 'page': 'gene', 'action': 'general_ **kwargs: Any, ) -> Any: """Issue an HTTP request and return the parsed JSON body, raising a - + RuntimeError with consistent context if the request fails or the body is not valid JSON. - + `context` is a short human-readable label (e.g. "Bgee API") used in error messages so users can identify which upstream service failed. Transient failures (connection errors, read timeouts, HTTP 5xx) are @@ -505,8 +505,8 @@ self = > result_to_test = do_call(func, td[test]["args"]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -tests/from_json.py:68: -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +tests/from_json.py:68: +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/from_json.py:60: in do_call return func(**args) ^^^^^^^^^^^^ @@ -518,7 +518,7 @@ gget/gget_bgee.py:117: in _bgee_expression ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ gget/gget_bgee.py:24: in _bgee_species payload = http_json( -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ method = 'GET', url = 'https://bgee.org/api/' context = 'Bgee API (species lookup)', timeout = (10, 60), retries = 3 @@ -536,10 +536,10 @@ kwargs = {'params': {'display_type': 'json', 'page': 'gene', 'action': 'general_ **kwargs: Any, ) -> Any: """Issue an HTTP request and return the parsed JSON body, raising a - + RuntimeError with consistent context if the request fails or the body is not valid JSON. - + `context` is a short human-readable label (e.g. "Bgee API") used in error messages so users can identify which upstream service failed. Transient failures (connection errors, read timeouts, HTTP 5xx) are @@ -588,8 +588,8 @@ self = > result_to_test = do_call(func, td[test]["args"]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -tests/from_json.py:68: -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +tests/from_json.py:68: +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/from_json.py:60: in do_call return func(**args) ^^^^^^^^^^^^ @@ -601,7 +601,7 @@ gget/gget_bgee.py:117: in _bgee_expression ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ gget/gget_bgee.py:24: in _bgee_species payload = http_json( -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ method = 'GET', url = 'https://bgee.org/api/' context = 'Bgee API (species lookup)', timeout = (10, 60), retries = 3 @@ -619,10 +619,10 @@ kwargs = {'params': {'display_type': 'json', 'page': 'gene', 'action': 'general_ **kwargs: Any, ) -> Any: """Issue an HTTP request and return the parsed JSON body, raising a - + RuntimeError with consistent context if the request fails or the body is not valid JSON. - + `context` is a short human-readable label (e.g. "Bgee API") used in error messages so users can identify which upstream service failed. Transient failures (connection errors, read timeouts, HTTP 5xx) are diff --git a/tests/test_g2p.py b/tests/test_g2p.py index 48afd9332..e3ecbc18b 100644 --- a/tests/test_g2p.py +++ b/tests/test_g2p.py @@ -1,4 +1,5 @@ import unittest + from gget.gget_g2p import g2p From a9ae6fa4d5470fad25c990e93340751d05243e19 Mon Sep 17 00:00:00 2001 From: Laura Luebbert Date: Mon, 22 Jun 2026 13:21:40 -0400 Subject: [PATCH 3/5] fix: zero remaining ruff errors on main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After pre-commit.ci's autofix commit (af9fae79) cleared the bulk of the baseline, 7 unfixable errors remained — same set of violations that PR #222 also carries. Apply the same fix here so main is ruff-clean independently of PR #222's merge: - gget_g2p.py: collapse the multi-line docstring summary into a single line + paragraph break (ruff D205). - main.py: add # noqa: E402 to the 6 module-function imports (g2p, ref, search, seq, setup, virus). main.py has executable code (dt_string assignment) above the import block, so every later import needs the noqa. Drops the now-redundant "# Module functions" comment that was splitting one alphabetical list into two. After this commit, `ruff check gget/` reports zero errors, so new PRs no longer inherit a ruff failure on pre-commit.ci. --- gget/gget_g2p.py | 6 +++--- gget/main.py | 14 ++++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/gget/gget_g2p.py b/gget/gget_g2p.py index 2a4e42616..cc7bd77ea 100644 --- a/gget/gget_g2p.py +++ b/gget/gget_g2p.py @@ -19,9 +19,9 @@ def g2p( save: bool = False, verbose: bool = True, ) -> pd.DataFrame | None: - """ - Query the Genomics 2 Proteins (G2P) portal (https://g2p.broadinstitute.org/) to link - genes/proteins to per-residue structural and functional annotations. + """Query the Genomics 2 Proteins (G2P) portal to link genes/proteins to per-residue structural and functional annotations. + + Portal: https://g2p.broadinstitute.org/ Args: - gene Gene symbol, e.g. "BRCA1" (str). diff --git a/gget/main.py b/gget/main.py index c626917dd..49cfe7b4c 100644 --- a/gget/main.py +++ b/gget/main.py @@ -30,20 +30,18 @@ from .gget_diamond import diamond # noqa: E402 from .gget_elm import elm # noqa: E402 from .gget_enrichr import enrichr # noqa: E402 -from .gget_g2p import g2p +from .gget_g2p import g2p # noqa: E402 from .gget_gpt import gpt # noqa: E402 from .gget_info import info # noqa: E402 from .gget_muscle import muscle # noqa: E402 from .gget_mutate import mutate # noqa: E402 from .gget_opentargets import OPENTARGETS_RESOURCES, opentargets # noqa: E402 from .gget_pdb import pdb # noqa: E402 - -# Module functions -from .gget_ref import ref -from .gget_search import search -from .gget_seq import seq -from .gget_setup import setup -from .gget_virus import virus +from .gget_ref import ref # noqa: E402 +from .gget_search import search # noqa: E402 +from .gget_seq import seq # noqa: E402 +from .gget_setup import setup # noqa: E402 +from .gget_virus import virus # noqa: E402 # Custom formatter for help messages that preserved the text formatting and adds the default value to the end of the help message From 6de38630074381ca56188554a3bbfb90395358d9 Mon Sep 17 00:00:00 2001 From: Laura Luebbert Date: Mon, 22 Jun 2026 13:33:20 -0400 Subject: [PATCH 4/5] fix(pre-commit): update exclude pattern for renamed pytest results file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The exclude block listed tests/pytest_results_py.*\.txt — the per- Python report filename that was used before commit 244d4d23 consolidated CI to a single tests/pytest_results.txt. The new filename doesn't match the old pattern, so pre-commit was processing the autogenerated report and trimming its trailing whitespace on every run (see autofix commit af9fae79 in this PR). Widen the pattern to tests/pytest_results.*\.txt so it covers both the current canonical name and any future variant. Pre-existing whitespace changes to tests/pytest_results.txt are left as-is — CI rewrites the file on every scheduled run anyway, so the diff is ephemeral. --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cb9079a59..ccff9d2d3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ exclude: | gget/bins/ | gget/constants/ | tests/fixtures/ - | tests/pytest_results_py.*\.txt + | tests/pytest_results.*\.txt ) repos: - repo: https://github.com/biomejs/pre-commit From fcb2f672b055158dd81a0a1348d3e0968dd5cee9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2026 17:33:54 +0000 Subject: [PATCH 5/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .github/badges/tests.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/badges/tests.json b/.github/badges/tests.json index f4c54a216..3ebecd1dc 100644 --- a/.github/badges/tests.json +++ b/.github/badges/tests.json @@ -1 +1,6 @@ -{"schemaVersion": 1, "label": "tests", "message": "397/400 passing", "color": "brightgreen"} +{ + "schemaVersion": 1, + "label": "tests", + "message": "397/400 passing", + "color": "brightgreen" +}