diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ccff9d2d3..7513579ff 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,6 +26,7 @@ exclude: | | gget/constants/ | tests/fixtures/ | tests/pytest_results.*\.txt + | \.github/badges/.*\.json ) repos: - repo: https://github.com/biomejs/pre-commit diff --git a/gget/gget_8cube.py b/gget/gget_8cube.py index 16481e7cf..4e76c4dde 100644 --- a/gget/gget_8cube.py +++ b/gget/gget_8cube.py @@ -2,7 +2,7 @@ import io import json as json_package -from typing import Any +from typing import Any, Literal, overload import pandas as pd import requests @@ -54,12 +54,30 @@ def _normalize_gene_list(gene_list: list[str] | tuple[str, ...]) -> list[str]: # -------------------------------------------------------------------- # 1. SPECIFICITY # -------------------------------------------------------------------- +@overload +def specificity( + gene_list: list[str] | tuple[str, ...], + json: Literal[False] = False, + save: bool = False, + verbose: bool = True, +) -> pd.DataFrame: ... + + +@overload +def specificity( + gene_list: list[str] | tuple[str, ...], + json: Literal[True], + save: bool = False, + verbose: bool = True, +) -> list[dict[str, Any]]: ... + + def specificity( gene_list: list[str] | tuple[str, ...], json: bool = False, save: bool = False, verbose: bool = True, -) -> Any: +) -> pd.DataFrame | list[dict[str, Any]]: """Retrieve gene-level specificity statistics from the 8cubeDB. (https://eightcubedb.onrender.com/). @@ -126,6 +144,28 @@ def specificity( # -------------------------------------------------------------------- # 2. PSI BLOCK # -------------------------------------------------------------------- +@overload +def psi_block( + gene_list: list[str] | tuple[str, ...], + analysis_level: str, + analysis_type: str, + json: Literal[False] = False, + save: bool = False, + verbose: bool = True, +) -> pd.DataFrame: ... + + +@overload +def psi_block( + gene_list: list[str] | tuple[str, ...], + analysis_level: str, + analysis_type: str, + json: Literal[True], + save: bool = False, + verbose: bool = True, +) -> list[dict[str, Any]]: ... + + def psi_block( gene_list: list[str] | tuple[str, ...], analysis_level: str, @@ -133,7 +173,7 @@ def psi_block( json: bool = False, save: bool = False, verbose: bool = True, -) -> Any: +) -> pd.DataFrame | list[dict[str, Any]]: """Retrieve ψ_block (psi-block) specificity scores from the 8cubeDB. ψ_block quantifies the specificity of a gene to a particular block @@ -194,6 +234,28 @@ def psi_block( # -------------------------------------------------------------------- # 3. GENE EXPRESSION # -------------------------------------------------------------------- +@overload +def gene_expression( + gene_list: list[str] | tuple[str, ...], + analysis_level: str, + analysis_type: str, + json: Literal[False] = False, + save: bool = False, + verbose: bool = True, +) -> pd.DataFrame: ... + + +@overload +def gene_expression( + gene_list: list[str] | tuple[str, ...], + analysis_level: str, + analysis_type: str, + json: Literal[True], + save: bool = False, + verbose: bool = True, +) -> list[dict[str, Any]]: ... + + def gene_expression( gene_list: list[str] | tuple[str, ...], analysis_level: str, @@ -201,7 +263,7 @@ def gene_expression( json: bool = False, save: bool = False, verbose: bool = True, -) -> Any: +) -> pd.DataFrame | list[dict[str, Any]]: """Retrieve normalized gene expression values from 8cubeDB. This endpoint returns mean and variance of normalized expression for the diff --git a/gget/gget_archs4.py b/gget/gget_archs4.py index 36a46d4e0..e582dfaf5 100644 --- a/gget/gget_archs4.py +++ b/gget/gget_archs4.py @@ -2,7 +2,7 @@ import io import json as json_package -from typing import Any +from typing import Any, Literal, overload import pandas as pd import requests @@ -17,6 +17,32 @@ from .gget_info import info # noqa: E402 +@overload +def archs4( + gene: str, + ensembl: bool = False, + which: str = "correlation", + gene_count: int = 100, + species: str = "human", + json: Literal[True] = ..., + save: bool = False, + verbose: bool = True, +) -> list[dict[str, Any]] | None: ... + + +@overload +def archs4( + gene: str, + ensembl: bool = False, + which: str = "correlation", + gene_count: int = 100, + species: str = "human", + json: Literal[False] = False, + save: bool = False, + verbose: bool = True, +) -> pd.DataFrame | None: ... + + def archs4( gene: str, ensembl: bool = False, diff --git a/gget/gget_bgee.py b/gget/gget_bgee.py index 0fe5ac3ef..d35e629b5 100644 --- a/gget/gget_bgee.py +++ b/gget/gget_bgee.py @@ -2,7 +2,7 @@ import json as json_ from importlib.metadata import PackageNotFoundError, version -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Literal, overload from .utils import dig, http_json, json_list_to_df, set_up_logger @@ -180,13 +180,41 @@ def _bgee_expression(gene_id: str | list[str], json: bool = False, verbose: bool return df +@overload +def bgee( + gene_id: str | list[str], + type: str, + json: Literal[True], + verbose: bool = ..., +) -> list[dict[str, Any]]: ... + + +@overload +def bgee( + gene_id: str | list[str], + type: str = ..., + *, + json: Literal[True], + verbose: bool = ..., +) -> list[dict[str, Any]]: ... + + +@overload +def bgee( + gene_id: str | list[str], + type: str = ..., + json: Literal[False] = False, + verbose: bool = ..., +) -> pd.DataFrame: ... + + # noinspection PyShadowingBuiltins def bgee( gene_id: str | list[str], type: str = "orthologs", json: bool = False, verbose: bool = True, -) -> pd.DataFrame | Any: +) -> pd.DataFrame | list[dict[str, Any]]: """Get orthologs/expression data for a gene from Bgee (https://www.bgee.org/). Args: diff --git a/gget/gget_blast.py b/gget/gget_blast.py index bb0f5b48c..c072820d3 100644 --- a/gget/gget_blast.py +++ b/gget/gget_blast.py @@ -3,7 +3,7 @@ import json as json_package import time from io import StringIO -from typing import Any +from typing import Any, Literal, overload from urllib.parse import urlencode # Using urllib instead of requests here because requests does not @@ -25,6 +25,39 @@ ) +@overload +def blast( + sequence: str, + program: str = "default", + database: str = "default", + limit: int = 50, + expect: float = 10.0, + low_comp_filt: bool = False, + megablast: bool = True, + verbose: bool = True, + wrap_text: bool = False, + *, + json: Literal[True], + save: bool = False, +) -> list[dict[str, Any]] | None: ... + + +@overload +def blast( + sequence: str, + program: str = "default", + database: str = "default", + limit: int = 50, + expect: float = 10.0, + low_comp_filt: bool = False, + megablast: bool = True, + verbose: bool = True, + wrap_text: bool = False, + json: Literal[False] = False, + save: bool = False, +) -> pd.DataFrame | None: ... + + def blast( sequence: str, program: str = "default", diff --git a/gget/gget_blat.py b/gget/gget_blat.py index d1f88509f..0939eb0a0 100644 --- a/gget/gget_blat.py +++ b/gget/gget_blat.py @@ -3,7 +3,7 @@ import json as json_package import time from json.decoder import JSONDecodeError -from typing import Any +from typing import Any, Literal, overload from urllib import request from urllib.error import HTTPError, URLError @@ -18,6 +18,28 @@ _BLAT_BACKOFF_BASE_SECONDS = 1.5 +@overload +def blat( + sequence: str, + seqtype: str = ..., + assembly: str = ..., + json: Literal[True] = ..., + save: bool = ..., + verbose: bool = ..., +) -> list[dict[str, Any]] | None: ... + + +@overload +def blat( + sequence: str, + seqtype: str = ..., + assembly: str = ..., + json: Literal[False] = ..., + save: bool = ..., + verbose: bool = ..., +) -> pd.DataFrame | None: ... + + def blat( sequence: str, seqtype: str = "default", @@ -133,7 +155,7 @@ def blat( ## Build data frame to resemble BLAT web search results # Define dataframe from dictionary - df_dict = {} + df_dict: dict[str, list[Any]] = {} for field in results["fields"]: df_dict.update({field: []}) diff --git a/gget/gget_cosmic.py b/gget/gget_cosmic.py index 020fdad58..594e9bf8e 100644 --- a/gget/gget_cosmic.py +++ b/gget/gget_cosmic.py @@ -9,7 +9,7 @@ import shutil import subprocess import tarfile -from typing import Any +from typing import Any, Literal, overload import pandas as pd @@ -315,6 +315,53 @@ def match_and_limit(mask, extract_fn): return results +@overload +def cosmic( + searchterm: str | None, + cosmic_tsv_path: str | None = None, + limit: int = 100, + *, + json: Literal[True], + download_cosmic: bool = False, + cosmic_project: str | None = None, + cosmic_version: int | None = None, + grch_version: int = 37, + email: str | None = None, + password: str | None = None, + gget_mutate: bool = False, + keep_genome_info: bool = False, + remove_duplicates: bool = False, + seq_id_column: str = "seq_ID", + mutation_column: str = "mutation", + mut_id_column: str = "mutation_id", + out: str | None = None, + verbose: bool = True, +) -> list[dict[str, Any]] | None: ... + + +@overload +def cosmic( + searchterm: str | None, + cosmic_tsv_path: str | None = None, + limit: int = 100, + json: Literal[False] = False, + download_cosmic: bool = False, + cosmic_project: str | None = None, + cosmic_version: int | None = None, + grch_version: int = 37, + email: str | None = None, + password: str | None = None, + gget_mutate: bool = False, + keep_genome_info: bool = False, + remove_duplicates: bool = False, + seq_id_column: str = "seq_ID", + mutation_column: str = "mutation", + mut_id_column: str = "mutation_id", + out: str | None = None, + verbose: bool = True, +) -> pd.DataFrame | None: ... + + def cosmic( searchterm: str | None, cosmic_tsv_path: str | None = None, @@ -334,7 +381,7 @@ def cosmic( mut_id_column: str = "mutation_id", out: str | None = None, verbose: bool = True, -) -> Any: +) -> pd.DataFrame | list[dict[str, Any]] | None: """Search for genes, mutations, etc associated with cancers using the COSMIC database. (Catalogue Of Somatic Mutations In Cancer) database diff --git a/gget/gget_diamond.py b/gget/gget_diamond.py index f68bef39f..455b2bf7d 100644 --- a/gget/gget_diamond.py +++ b/gget/gget_diamond.py @@ -6,7 +6,9 @@ import subprocess import sys import uuid -from typing import Any +from typing import Any, Literal, overload + +import pandas as pd from .compile import PACKAGE_PATH from .utils import ( @@ -26,6 +28,37 @@ PRECOMPILED_DIAMOND_PATH = os.path.join(PACKAGE_PATH, f"bins/{platform.system()}/diamond") +@overload +def diamond( + query: str | list[str], + reference: str | list[str], + translated: bool = ..., + diamond_db: str | None = ..., + sensitivity: str = ..., + threads: int = ..., + diamond_binary: str | None = ..., + verbose: bool = ..., + *, + json: Literal[True], + out: str | None = ..., +) -> list[dict[str, Any]]: ... + + +@overload +def diamond( + query: str | list[str], + reference: str | list[str], + translated: bool = ..., + diamond_db: str | None = ..., + sensitivity: str = ..., + threads: int = ..., + diamond_binary: str | None = ..., + verbose: bool = ..., + json: Literal[False] = False, + out: str | None = ..., +) -> pd.DataFrame: ... + + def diamond( query: str | list[str], reference: str | list[str], @@ -37,7 +70,7 @@ def diamond( verbose: bool = True, json: bool = False, out: str | None = None, -) -> Any: +) -> pd.DataFrame | list[dict[str, Any]]: """Align multiple protein or translated DNA sequences using DIAMOND (https://www.nature.com/articles/nmeth.3176). Args: diff --git a/gget/gget_elm.py b/gget/gget_elm.py index f53e6f59e..f45680ae9 100644 --- a/gget/gget_elm.py +++ b/gget/gget_elm.py @@ -3,7 +3,7 @@ import json as json_package import os import re -from typing import Any +from typing import Any, Literal, overload import numpy as np import pandas as pd @@ -223,6 +223,34 @@ def regex_match(sequence: str) -> pd.DataFrame: return df_final +@overload +def elm( + sequence: str, + uniprot: bool = ..., + sensitivity: str = ..., + threads: int = ..., + diamond_binary: str | None = ..., + expand: bool = ..., + verbose: bool = ..., + json: Literal[True] = ..., + out: str | None = ..., +) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]: ... + + +@overload +def elm( + sequence: str, + uniprot: bool = ..., + sensitivity: str = ..., + threads: int = ..., + diamond_binary: str | None = ..., + expand: bool = ..., + verbose: bool = ..., + json: Literal[False] = ..., + out: str | None = ..., +) -> tuple[pd.DataFrame, pd.DataFrame]: ... + + def elm( sequence: str, uniprot: bool = False, @@ -233,7 +261,7 @@ def elm( verbose: bool = True, json: bool = False, out: str | None = None, -) -> tuple[Any, Any]: +) -> tuple[pd.DataFrame, pd.DataFrame] | tuple[list[dict[str, Any]], list[dict[str, Any]]]: """Locally predicts Eukaryotic Linear Motifs from an amino acid sequence or UniProt Acc using data from the ELM database (http://elm.eu.org/). diff --git a/gget/gget_enrichr.py b/gget/gget_enrichr.py index 769316d6c..deb2c75b7 100644 --- a/gget/gget_enrichr.py +++ b/gget/gget_enrichr.py @@ -2,7 +2,7 @@ import json as json_package import textwrap -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Literal, overload # Plotting packages import matplotlib.pyplot as plt @@ -64,6 +64,46 @@ def clean_genes_list(genes_list: list[Any]) -> list[Any]: return genes_clean +@overload +def enrichr( + genes: str | list[str], + database: str, + species: str = "human", + background_list: list[str] | None = None, + background: bool = False, + ensembl: bool = False, + ensembl_bkg: bool = False, + plot: bool = False, + figsize: tuple[float, float] = (10, 10), + ax: Axes | None = None, + kegg_out: str | None = None, + kegg_rank: int = 1, + json: Literal[True] = ..., + save: bool = False, + verbose: bool = True, +) -> list[dict[str, Any]] | None: ... + + +@overload +def enrichr( + genes: str | list[str], + database: str, + species: str = "human", + background_list: list[str] | None = None, + background: bool = False, + ensembl: bool = False, + ensembl_bkg: bool = False, + plot: bool = False, + figsize: tuple[float, float] = (10, 10), + ax: Axes | None = None, + kegg_out: str | None = None, + kegg_rank: int = 1, + json: Literal[False] = False, + save: bool = False, + verbose: bool = True, +) -> pd.DataFrame | None: ... + + def enrichr( genes: str | list[str], database: str, diff --git a/gget/gget_info.py b/gget/gget_info.py index c38bd794f..a4005f612 100644 --- a/gget/gget_info.py +++ b/gget/gget_info.py @@ -1,7 +1,7 @@ from __future__ import annotations import json as json_package -from typing import Any +from typing import Any, Literal, overload import numpy as np import pandas as pd @@ -29,6 +29,37 @@ ## gget info +@overload +def info( + ens_ids: str | list[str], + wrap_text: bool = ..., + ncbi: bool = ..., + uniprot: bool = ..., + pdb: bool = ..., + *, + json: Literal[True], + verbose: bool = ..., + save: bool = ..., + expand: bool = ..., + ensembl_only: bool = ..., +) -> dict[str, Any] | None: ... + + +@overload +def info( + ens_ids: str | list[str], + wrap_text: bool = ..., + ncbi: bool = ..., + uniprot: bool = ..., + pdb: bool = ..., + json: Literal[False] = ..., + verbose: bool = ..., + save: bool = ..., + expand: bool = ..., + ensembl_only: bool = ..., +) -> pd.DataFrame | None: ... + + def info( ens_ids: str | list[str], wrap_text: bool = False, @@ -393,7 +424,7 @@ def info( ens_ids = [] # Dictionary to save clean info - data = { + data: dict[str, list[Any]] = { "all_transcripts": [], "transcript_biotypes": [], "transcript_names": [], diff --git a/gget/gget_muscle.py b/gget/gget_muscle.py index 69d0dcd82..a5053954d 100644 --- a/gget/gget_muscle.py +++ b/gget/gget_muscle.py @@ -122,7 +122,7 @@ def muscle(fasta: str | list[str], super5: bool = False, out: str | None = None, # Get the titles and sequences from the generated .afa file titles = [] seqs_master = [] - seqs = [] + seqs: list[str] = [] with open(abs_out_path) as aln_file: for i, line in enumerate(aln_file): # Recognize title lines by the '>' character diff --git a/gget/gget_opentargets.py b/gget/gget_opentargets.py index edd90bc3f..8037fb342 100644 --- a/gget/gget_opentargets.py +++ b/gget/gget_opentargets.py @@ -2,7 +2,7 @@ import json as json_ import textwrap -from typing import Any +from typing import Any, Literal, overload import pandas as pd @@ -255,6 +255,30 @@ def _unhash(x: Any) -> Any: return x +@overload +def opentargets( + ensembl_id: str, + resource: str = "diseases", + limit: int | None = None, + verbose: bool = True, + wrap_text: bool = False, + filters: dict[str, Any] | None = None, + json: Literal[False] = False, +) -> pd.DataFrame: ... + + +@overload +def opentargets( + ensembl_id: str, + resource: str = "diseases", + limit: int | None = None, + verbose: bool = True, + wrap_text: bool = False, + filters: dict[str, Any] | None = None, + json: Literal[True] = ..., +) -> list[dict[str, Any]]: ... + + def opentargets( ensembl_id: str, resource: str = "diseases", @@ -263,7 +287,7 @@ def opentargets( wrap_text: bool = False, filters: dict[str, Any] | None = None, json: bool = False, -) -> Any: +) -> pd.DataFrame | list[dict[str, Any]]: """Query OpenTargets for data associated with a given Ensembl gene ID. Args: diff --git a/gget/gget_ref.py b/gget/gget_ref.py index f81b7fc4a..b16391c41 100644 --- a/gget/gget_ref.py +++ b/gget/gget_ref.py @@ -359,7 +359,7 @@ def ref( ## Return results # If FTP=False, return dictionary/json of specified results if ftp is False: - ref_dict = {species: {}} + ref_dict: dict[str, dict[str, Any]] = {species: {}} for return_val in which: if return_val == "all": ref_dict = { diff --git a/gget/gget_search.py b/gget/gget_search.py index a5ed75529..e8df84c85 100644 --- a/gget/gget_search.py +++ b/gget/gget_search.py @@ -3,7 +3,7 @@ import json as json_package import time import warnings -from typing import Any +from typing import Any, Literal, overload import mysql.connector as sql import numpy as np @@ -37,6 +37,38 @@ def clean_cols(x: Any) -> Any: return x +@overload +def search( + searchwords: str | list[str], + species: str, + release: int | None = None, + id_type: str = "gene", + seqtype: str | None = None, + andor: str = "or", + limit: int | None = None, + wrap_text: bool = False, + json: Literal[True] = ..., + save: bool = False, + verbose: bool = True, +) -> list[dict[str, Any]] | None: ... + + +@overload +def search( + searchwords: str | list[str], + species: str, + release: int | None = None, + id_type: str = "gene", + seqtype: str | None = None, + andor: str = "or", + limit: int | None = None, + wrap_text: bool = False, + json: Literal[False] = False, + save: bool = False, + verbose: bool = True, +) -> pd.DataFrame | None: ... + + def search( searchwords: str | list[str], species: str, @@ -49,7 +81,7 @@ def search( json: bool = False, save: bool = False, verbose: bool = True, -) -> Any: +) -> pd.DataFrame | list[dict[str, Any]] | None: """Function to query Ensembl for genes based on species and free form search terms. Automatically fetches results from latest Ensembl release, unless user specifies database (see 'species' argument) diff --git a/gget/gget_virus.py b/gget/gget_virus.py index 8a04dfdec..7742e6a91 100644 --- a/gget/gget_virus.py +++ b/gget/gget_virus.py @@ -1453,7 +1453,7 @@ def fetch_virus_metadata( # e.g., "NC_045512.2%2CMN908947.3%2CMT020781.1" url = f"{NCBI_API_BASE}/virus/accession/{virus}/dataset_report" logger.debug("Using accession endpoint for virus: %s", virus) - params = {} + params: dict[str, Any] = {} else: # For taxon names/IDs (e.g., 'Zika Virus', 'influenza'), use the taxon endpoint url = f"{NCBI_API_BASE}/virus/taxon/{virus}/dataset_report" @@ -4381,7 +4381,7 @@ def _load_metadata_dict_from_temp_jsonl(temp_file_path: str) -> dict[str, Any]: Same format as load_metadata_from_api_reports(). """ - metadata_dict = {} + metadata_dict: dict[str, Any] = {} processed_count = 0 skipped_count = 0 @@ -4471,7 +4471,7 @@ def _load_cached_metadata_from_jsonl(jsonl_path: str) -> dict[str, Any]: dict: Dictionary mapping accession numbers to metadata dictionaries. """ - metadata_dict = {} + metadata_dict: dict[str, Any] = {} processed_count = 0 if not jsonl_path or not os.path.exists(jsonl_path): @@ -4565,7 +4565,7 @@ def _stream_filter_cached_metadata_from_jsonl( if "min_release_date" in filters_active: min_release_date_parsed = _parse_date(min_release_date, filtername="min_release_date") - metadata_dict = {} + metadata_dict: dict[str, Any] = {} total_records = 0 filter_stats = { "host": 0, @@ -4967,7 +4967,7 @@ def filter_sequences( # Initialize lists to store filtered results (metadata is small, kept in memory) filtered_metadata = [] # Will store corresponding metadata dictionaries - protein_headers = [] # Will store protein/segment information from FASTA headers + protein_headers: list[Any] = [] # Will store protein/segment information from FASTA headers filtered_count = 0 # Count of sequences passing all filters # Counters for logging filter statistics @@ -5264,7 +5264,7 @@ def save_command_summary( f.write(f"Average sequence length: {sum(lengths) / len(lengths):.0f} bp\n\n") # Completeness breakdown - completeness_counts = {} + completeness_counts: dict[str, int] = {} for meta in filtered_metadata: comp = meta.get("completeness", "unknown") completeness_counts[comp] = completeness_counts.get(comp, 0) + 1 @@ -5274,7 +5274,7 @@ def save_command_summary( f.write("\n") # Source database breakdown - source_counts = {} + source_counts: dict[str, int] = {} for meta in filtered_metadata: source = meta.get("sourceDatabase", "unknown") source_counts[source] = source_counts.get(source, 0) + 1 @@ -6181,7 +6181,7 @@ def fetch_genbank_metadata( _log_memory_usage("GenBank fetch start") # Initialize tracking variables - all_metadata = {} # Only used for final return; populated from temp JSONL at end + all_metadata: dict[str, Any] = {} # Only used for final return; populated from temp JSONL at end failed_batches = [] total_metadata_written = 0 # Counter for metadata records streamed to disk @@ -7053,7 +7053,7 @@ def _parse_genbank_xml(xml_content: str) -> dict[str, Any]: logger.debug("Processing GenBank record: %s", accession) # Initialize metadata dictionary for this record - metadata = { + metadata: dict[str, Any] = { "accession": accession, "genbank_data": {}, # Store GenBank-specific fields } @@ -8741,14 +8741,14 @@ def virus( refseq_only = False # Initialize filter stats for each stage (populated by filter functions) - metadata_filter_stats = {} - genbank_filter_stats = {} - sequence_filter_stats = {} + metadata_filter_stats: dict[str, int] = {} + genbank_filter_stats: dict[str, int] = {} + sequence_filter_stats: dict[str, int] = {} total_after_genbank_filter = None total_after_sequence_filter = None # Initialize failed commands tracker for tracking all types of failures - failed_commands = { + failed_commands: dict[str, Any] = { "api_timeout": None, "empty_response": None, "sequence_batches": [], @@ -9768,7 +9768,7 @@ def virus( logger.warning("No sequences will pass the GenBank-based filters.") filtered_accessions = [] filtered_metadata = [] - genbank_data_prefetch = {} + genbank_data_prefetch: dict[str, Any] = {} save_command_summary( outfolder=outfolder, @@ -9985,7 +9985,7 @@ def virus( # For large datasets (millions of sequences), this avoids OOM errors total_final_sequences = _stream_copy_fasta(fna_file, output_fasta_file) filtered_metadata_final = filtered_metadata # No change to metadata - protein_headers = [] + protein_headers: list[Any] = [] logger.info("All %d downloaded sequences were streamed to output", total_final_sequences) _log_memory_usage("after streaming sequences to output") else: diff --git a/gget/utils.py b/gget/utils.py index 2d86a564c..dfa4a2011 100644 --- a/gget/utils.py +++ b/gget/utils.py @@ -1138,7 +1138,7 @@ def json_list_to_df(json_list: list[Any], columns: list[tuple[str, str]]) -> pd. Returns data frame with columns as specified in keys. """ - tmp_columns = [[] for _ in range(len(columns))] + tmp_columns: list[list[Any]] = [[] for _ in range(len(columns))] for json_obj in json_list: for i, column_key in enumerate(columns): @@ -1186,7 +1186,7 @@ def parse(filename: str, format: str | None = None) -> Iterator[FastaRecord]: with open(filename, encoding="utf-8") as handle: current_id = None current_description = "" - current_seq = [] + current_seq: list[str] = [] for line in handle: line = line.strip()