Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ jobs:
- uses: chartboost/ruff-action@v1
with:
src: './pyenzyme'
version: 0.15.22 # keep in sync with .pre-commit-config.yaml
version: 0.16.10 # keep in sync with .pre-commit-config.yaml
- uses: chartboost/ruff-action@v1
with:
src: './tests'
version: 0.15.22
version: 0.16.10
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ repos:
- id: uv-lock

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.22
rev: v0.16.10
hooks:
# Same lint gate CI runs (lint.yml lints ./pyenzyme and ./tests only).
- id: ruff-check
Expand Down
14 changes: 7 additions & 7 deletions pyenzyme/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,23 @@
write_enzymeml = EnzymeMLHandler.write_enzymeml

__all__ = [
"EnzymeMLHandler",
"EnzymeMLSuite",
"UnitDefinition",
"UnitType",
"EnzymeMLSuite",
"EnzymeMLHandler",
"compose",
"from_csv",
"from_dataframe",
"from_excel",
"from_sbml",
"group_measurements",
"plot",
"plot_interactive",
"read_enzymeml",
"summary",
"to_pandas",
"to_sbml",
"write_enzymeml",
"compose",
"plot",
"plot_interactive",
"summary",
"group_measurements",
]

__version__ = version("pyenzyme")
21 changes: 11 additions & 10 deletions pyenzyme/composer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import List, Optional, Tuple, Callable, Any
from collections.abc import Callable
from typing import Any

from rich.console import Console

Expand Down Expand Up @@ -28,11 +29,11 @@

def compose(
name: str,
proteins: Optional[list[str]] = None,
small_molecules: Optional[list[str]] = None,
reactions: Optional[list[str]] = None,
vessel: Optional[v2.Vessel] = None,
id_mapping: Optional[dict[str, str]] = None,
proteins: list[str] | None = None,
small_molecules: list[str] | None = None,
reactions: list[str] | None = None,
vessel: v2.Vessel | None = None,
id_mapping: dict[str, str] | None = None,
) -> v2.EnzymeMLDocument:
"""
Compose an EnzymeML document from proteins, small molecules, and reactions.
Expand Down Expand Up @@ -162,7 +163,7 @@ def _fetch_small_molecule(small_molecule_id: str) -> v2.SmallMolecule:
)


def _fetch_reaction(reaction_id: str) -> Tuple[v2.Reaction, List[v2.SmallMolecule]]:
def _fetch_reaction(reaction_id: str) -> tuple[v2.Reaction, list[v2.SmallMolecule]]:
"""
Fetch reaction information using available fetchers.

Expand All @@ -179,7 +180,7 @@ def _fetch_reaction(reaction_id: str) -> Tuple[v2.Reaction, List[v2.SmallMolecul


def _fetch_with_fetchers(
entity_id: str, fetchers: List[Callable], entity_type: str
entity_id: str, fetchers: list[Callable], entity_type: str
) -> Any:
"""
Generic function to attempt fetching with multiple fetchers.
Expand Down Expand Up @@ -210,7 +211,7 @@ def _fetch_with_fetchers(
) from last_error


def _remove_duplicates(objects: List[Any]) -> List[Any]:
def _remove_duplicates(objects: list[Any]) -> list[Any]:
"""
Remove duplicate objects based on their ID attribute.

Expand All @@ -235,7 +236,7 @@ def _remove_duplicates(objects: List[Any]) -> List[Any]:


def _apply_id_mapping(
objects: List[Any],
objects: list[Any],
id_mapping: dict[str, str],
) -> dict[str, str]:
"""
Expand Down
4 changes: 2 additions & 2 deletions pyenzyme/equations/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .math import build_equation, build_equations # noqa: F401
from .chem import build_reaction, build_reactions # noqa: F401
from .chem import build_reaction, build_reactions
from .math import build_equation, build_equations

__all__ = ["build_equation", "build_equations", "build_reaction", "build_reactions"]
2 changes: 1 addition & 1 deletion pyenzyme/equations/math.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import rich
from loguru import logger
from mdmodels.units.unit_definition import UnitDefinition
from sympy import sympify

from pyenzyme.logging import add_logger
from mdmodels.units.unit_definition import UnitDefinition
from pyenzyme.versions.v2 import (
EnzymeMLDocument,
Equation,
Expand Down
4 changes: 2 additions & 2 deletions pyenzyme/fetcher/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from .chebi import fetch_chebi
from .pdb import fetch_pdb
from .pubchem import fetch_pubchem
from .uniprot import fetch_uniprot
from .rhea import fetch_rhea
from .uniprot import fetch_uniprot

__all__ = [
"fetch_chebi",
"fetch_pdb",
"fetch_pubchem",
"fetch_uniprot",
"fetch_rhea",
"fetch_uniprot",
]
53 changes: 26 additions & 27 deletions pyenzyme/fetcher/chebi.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"""

import re
from typing import List, Optional

import httpx
from pydantic import BaseModel, ConfigDict, Field
Expand All @@ -19,7 +18,7 @@
class ChEBIError(Exception):
"""Error class for ChEBI-specific errors."""

def __init__(self, message: str, cause: Optional[Exception] = None):
def __init__(self, message: str, cause: Exception | None = None):
super().__init__(message)
self.cause = cause

Expand All @@ -30,19 +29,19 @@ class ChebiSearchSource(BaseModel):
model_config = ConfigDict(extra="ignore")

chebi_accession: str
name: Optional[str] = None
name: str | None = None
ascii_name: str
smiles: Optional[str] = None
inchi: Optional[str] = None
inchikey: Optional[str] = None
definition: Optional[str] = None
formula: Optional[str] = None
charge: Optional[int] = None
mass: Optional[float] = None
monoisotopicmass: Optional[float] = None
stars: Optional[int] = None
default_structure: Optional[int] = None
structures: Optional[List[int]] = None
smiles: str | None = None
inchi: str | None = None
inchikey: str | None = None
definition: str | None = None
formula: str | None = None
charge: int | None = None
mass: float | None = None
monoisotopicmass: float | None = None
stars: int | None = None
default_structure: int | None = None
structures: list[int] | None = None


class ChebiSearchResult(BaseModel):
Expand All @@ -56,7 +55,7 @@ class ChebiSearchResult(BaseModel):
class ChebiSearchResponse(BaseModel):
"""Search response structure from ChEBI search API."""

results: List[ChebiSearchResult]
results: list[ChebiSearchResult]
total: int
number_pages: int

Expand Down Expand Up @@ -105,14 +104,14 @@ def get_entry_by_id(self, chebi_id: str) -> ChebiSearchSource:
except Exception as e:
if isinstance(e, ChEBIError):
raise e
raise ChEBIError(f"Failed to parse ChEBI response: {str(e)}", e)
raise ChEBIError(f"Failed to parse ChEBI response: {e!s}", e)
else:
raise ChEBIError(f"HTTP {response.status_code}: {response.text}")

except httpx.HTTPStatusError as e:
raise ChEBIError(f"Failed to fetch ChEBI ID {chebi_id}: {str(e)}", e)
raise ChEBIError(f"Failed to fetch ChEBI ID {chebi_id}: {e!s}", e)

def get_entries_batch(self, chebi_ids: List[str]) -> List[ChebiSearchSource]:
def get_entries_batch(self, chebi_ids: list[str]) -> list[ChebiSearchSource]:
"""
Fetch multiple ChEBI entries by their IDs using the search API.

Expand All @@ -136,13 +135,13 @@ def get_entries_batch(self, chebi_ids: List[str]) -> List[ChebiSearchSource]:
results.append(entry)
except ChEBIError as e:
# Continue with other IDs even if one fails
raise ChEBIError(f"Failed to fetch ChEBI ID {chebi_id}: {str(e)}", e)
raise ChEBIError(f"Failed to fetch ChEBI ID {chebi_id}: {e!s}", e)

return results

def search_entries(
self, query: str, size: Optional[int] = None, page: int = 1
) -> List[ChebiSearchSource]:
self, query: str, size: int | None = None, page: int = 1
) -> list[ChebiSearchSource]:
"""
Search for ChEBI entries by query string.

Expand Down Expand Up @@ -178,14 +177,14 @@ def search_entries(
except Exception as e:
if isinstance(e, ChEBIError):
raise e
raise ChEBIError(f"Invalid search response format: {str(e)}", e)
raise ChEBIError(f"Invalid search response format: {e!s}", e)
else:
raise ChEBIError(
f"Search failed: HTTP {response.status_code}: {response.text}"
)

except httpx.HTTPStatusError as e:
raise ChEBIError(f"Failed to search ChEBI: {str(e)}", e)
raise ChEBIError(f"Failed to search ChEBI: {e!s}", e)


def process_search_result(source: ChebiSearchSource) -> v2.SmallMolecule:
Expand Down Expand Up @@ -227,8 +226,8 @@ def process_search_result(source: ChebiSearchSource) -> v2.SmallMolecule:

def fetch_chebi(
chebi_id: str,
smallmol_id: Optional[str] = None,
vessel_id: Optional[str] = None,
smallmol_id: str | None = None,
vessel_id: str | None = None,
) -> v2.SmallMolecule:
"""
Fetch a ChEBI entry by ID and convert it to a SmallMolecule object.
Expand Down Expand Up @@ -264,7 +263,7 @@ def fetch_chebi(
raise ValueError(str(e)) from e


def fetch_chebi_batch(chebi_ids: List[str]) -> List[v2.SmallMolecule]:
def fetch_chebi_batch(chebi_ids: list[str]) -> list[v2.SmallMolecule]:
"""
Fetch multiple ChEBI entries by their IDs and convert them to SmallMolecule objects.

Expand All @@ -287,7 +286,7 @@ def fetch_chebi_batch(chebi_ids: List[str]) -> List[v2.SmallMolecule]:
return [process_search_result(source) for source in chebi_sources]


def search_chebi(query: str, size: Optional[int] = None) -> List[v2.SmallMolecule]:
def search_chebi(query: str, size: int | None = None) -> list[v2.SmallMolecule]:
"""
Search for ChEBI entries by query string.

Expand Down
56 changes: 28 additions & 28 deletions pyenzyme/fetcher/pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Protein Data Bank by ID and map it to the PyEnzyme data model (v2).
"""

from typing import Any, Dict, List, Optional
from typing import Any

import httpx
from pydantic import BaseModel, Field
Expand All @@ -19,50 +19,50 @@
class Citation(BaseModel):
"""Model for PDB citation data"""

title: Optional[str] = None
authors: Optional[List[str]] = None
journal_name: Optional[str] = Field(default=None, alias="journal_abbrev")
year: Optional[int] = None
doi: Optional[str] = None
pubmed_id: Optional[int] = Field(default=None, alias="pdbx_database_id_PubMed")
title: str | None = None
authors: list[str] | None = None
journal_name: str | None = Field(default=None, alias="journal_abbrev")
year: int | None = None
doi: str | None = None
pubmed_id: int | None = Field(default=None, alias="pdbx_database_id_PubMed")


class StructInfo(BaseModel):
"""Model for PDB structure information"""

title: Optional[str] = None
experimental_method: Optional[str] = None
resolution: Optional[float] = None
title: str | None = None
experimental_method: str | None = None
resolution: float | None = None


class EntityInfo(BaseModel):
"""Model for PDB entity information"""

description: Optional[str] = None
polymer_type: Optional[str] = None
ec_number: Optional[str] = None
sequence: Optional[str] = None
organism_scientific_name: Optional[str] = None
organism_taxid: Optional[int] = None
description: str | None = None
polymer_type: str | None = None
ec_number: str | None = None
sequence: str | None = None
organism_scientific_name: str | None = None
organism_taxid: int | None = None


class PDBResponse(BaseModel):
"""Model for PDB API response"""

pdb_id: str
citation: List[Citation] = []
struct: Optional[StructInfo] = None
polymer_entities: Optional[Dict[str, EntityInfo]] = None
rcsb_primary_citation: Optional[Dict[str, Any]] = None
rcsb_entry_info: Optional[Dict[str, Any]] = None
citation: list[Citation] = []
struct: StructInfo | None = None
polymer_entities: dict[str, EntityInfo] | None = None
rcsb_primary_citation: dict[str, Any] | None = None
rcsb_entry_info: dict[str, Any] | None = None


class PDBClient:
"""Client for accessing the PDB API"""

BASE_URL = "https://data.rcsb.org/rest/v1/core"

def get_entry_by_id(self, pdb_id: str) -> Optional[PDBResponse]:
def get_entry_by_id(self, pdb_id: str) -> PDBResponse | None:
"""
Fetch a PDB entry by its ID.

Expand Down Expand Up @@ -139,9 +139,9 @@ def get_entry_by_id(self, pdb_id: str) -> Optional[PDBResponse]:
)

except ValueError as e:
raise ValueError(f"Failed to retrieve PDB entry: {str(e)}")
raise ValueError(f"Failed to retrieve PDB entry: {e!s}")
except ConnectionError as e:
raise ValueError(f"Connection to PDB server failed: {str(e)}")
raise ValueError(f"Connection to PDB server failed: {e!s}")

def _fetch_json(self, url: str) -> dict:
"""
Expand Down Expand Up @@ -170,16 +170,16 @@ def _fetch_json(self, url: str) -> dict:
)

except httpx.HTTPStatusError as e:
raise ConnectionError(f"Connection failed: {str(e)}")
raise ConnectionError(f"Connection failed: {e!s}")
except ValueError as e:
raise ValueError(f"Failed to parse response: {str(e)}")
raise ValueError(f"Failed to parse response: {e!s}")


def fetch_pdb(
pdb_id: str,
protein_id: Optional[str] = None,
protein_id: str | None = None,
entity_id: str = "1",
vessel_id: Optional[str] = None,
vessel_id: str | None = None,
) -> v2.Protein:
"""
Fetch a PDB entry by ID and convert it to a Protein object.
Expand Down
Loading
Loading