From 40d086be9ee6b05a1ac8a56784e80b8b76d8f7b0 Mon Sep 17 00:00:00 2001 From: Jochen Sieg Date: Mon, 16 Jun 2025 16:37:18 +0200 Subject: [PATCH 01/11] fix pylint error --- molpipeline/post_prediction.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/molpipeline/post_prediction.py b/molpipeline/post_prediction.py index 38a7b65a..92aede8c 100644 --- a/molpipeline/post_prediction.py +++ b/molpipeline/post_prediction.py @@ -43,7 +43,9 @@ def transform(self, X: Any, **params: Any) -> Any: # pylint: disable=invalid-na """ -class PostPredictionWrapper(PostPredictionTransformation): +class PostPredictionWrapper( + PostPredictionTransformation +): # pylint: disable=too-many-ancestors """Wrapper for post prediction transformations. This class is used to wrap a PipelineElement in a PostPredictionTransformation. From 1a8aa161085a514e9c520e6a97c0d0eba43d0c55 Mon Sep 17 00:00:00 2001 From: Jochen Sieg Date: Mon, 16 Jun 2025 16:40:45 +0200 Subject: [PATCH 02/11] fix ruff format --- molpipeline/post_prediction.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/molpipeline/post_prediction.py b/molpipeline/post_prediction.py index 92aede8c..6116f9ea 100644 --- a/molpipeline/post_prediction.py +++ b/molpipeline/post_prediction.py @@ -43,9 +43,7 @@ def transform(self, X: Any, **params: Any) -> Any: # pylint: disable=invalid-na """ -class PostPredictionWrapper( - PostPredictionTransformation -): # pylint: disable=too-many-ancestors +class PostPredictionWrapper(PostPredictionTransformation): # pylint: disable=too-many-ancestors """Wrapper for post prediction transformations. This class is used to wrap a PipelineElement in a PostPredictionTransformation. From 690d72dd4f4bdf78ae83e40c80ee7d0d0e171ae2 Mon Sep 17 00:00:00 2001 From: Jochen Sieg Date: Mon, 16 Jun 2025 16:45:56 +0200 Subject: [PATCH 03/11] fix mypy issues --- tests/test_estimators/test_leader_picker_clustering.py | 2 +- tests/test_estimators/test_similarity_transformation.py | 2 +- .../test_visualization/test_visualization.py | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_estimators/test_leader_picker_clustering.py b/tests/test_estimators/test_leader_picker_clustering.py index d2011ad0..e18f32df 100644 --- a/tests/test_estimators/test_leader_picker_clustering.py +++ b/tests/test_estimators/test_leader_picker_clustering.py @@ -20,7 +20,7 @@ class TestLeaderPickerEstimator(unittest.TestCase): def test_leader_picker_clustering_estimator(self) -> None: """Test LeaderPicker clustering estimator.""" fingerprint_matrix = [ - DataStructs.CreateFromBitString(x) + DataStructs.CreateFromBitString(x) # type: ignore[attr-defined] for x in [ "000", # 0 "100", # 1 diff --git a/tests/test_estimators/test_similarity_transformation.py b/tests/test_estimators/test_similarity_transformation.py index 2af28265..a940e80b 100644 --- a/tests/test_estimators/test_similarity_transformation.py +++ b/tests/test_estimators/test_similarity_transformation.py @@ -8,7 +8,7 @@ import numpy.typing as npt from rdkit import Chem from rdkit.Chem import rdFingerprintGenerator -from rdkit.DataStructs import BulkTanimotoSimilarity +from rdkit.DataStructs import BulkTanimotoSimilarity # type: ignore[attr-defined] from scipy import sparse from sklearn.neighbors import KNeighborsClassifier diff --git a/tests/test_experimental/test_explainability/test_visualization/test_visualization.py b/tests/test_experimental/test_explainability/test_visualization/test_visualization.py index 307e325f..b55ff247 100644 --- a/tests/test_experimental/test_explainability/test_visualization/test_visualization.py +++ b/tests/test_experimental/test_explainability/test_visualization/test_visualization.py @@ -198,11 +198,11 @@ def test_explicit_hydrogens(self) -> None: """ mol_implicit_hydrogens = Chem.MolFromSmiles("C") explanations1 = self.test_tree_explainer_clf.explain( - [Chem.MolToSmiles(mol_implicit_hydrogens)] + [Chem.MolToSmiles(mol_implicit_hydrogens)] # type: ignore[arg-type] ) - mol_added_hydrogens = Chem.AddHs(mol_implicit_hydrogens) + mol_added_hydrogens = Chem.AddHs(mol_implicit_hydrogens) # type: ignore[arg-type] explanations2 = self.test_tree_explainer_clf.explain( - [Chem.MolToSmiles(mol_added_hydrogens)] + [Chem.MolToSmiles(mol_added_hydrogens)] # type: ignore[arg-type] ) mol_explicit_hydrogens = Chem.MolFromSmiles("[H]C([H])([H])[H]") explanations3 = self.test_tree_explainer_clf.explain( From e14509b9066d90b4f028b8ab03193d94319d983a Mon Sep 17 00:00:00 2001 From: Jochen Sieg Date: Mon, 16 Jun 2025 16:48:20 +0200 Subject: [PATCH 04/11] farther pylint issues --- .../test_visualization/test_visualization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_experimental/test_explainability/test_visualization/test_visualization.py b/tests/test_experimental/test_explainability/test_visualization/test_visualization.py index b55ff247..67b63a05 100644 --- a/tests/test_experimental/test_explainability/test_visualization/test_visualization.py +++ b/tests/test_experimental/test_explainability/test_visualization/test_visualization.py @@ -206,7 +206,7 @@ def test_explicit_hydrogens(self) -> None: ) mol_explicit_hydrogens = Chem.MolFromSmiles("[H]C([H])([H])[H]") explanations3 = self.test_tree_explainer_clf.explain( - [Chem.MolToSmiles(mol_explicit_hydrogens)] + [Chem.MolToSmiles(mol_explicit_hydrogens)] # type: ignore[arg-type] ) # test explanations' atom weights From 6b580fedb4a0492dc870571dd1a46790526d09ef Mon Sep 17 00:00:00 2001 From: Jochen Sieg Date: Mon, 16 Jun 2025 16:58:40 +0200 Subject: [PATCH 05/11] test ci/cd uv sync --dev --- .github/workflows/linting.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 16f70e28..5662ce60 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -32,6 +32,7 @@ jobs: python-version: "3.13" - name: Install dependencies run: | + uv sync --dev uv run mypy . || exit_code=$? uv run mypy --install-types --non-interactive - name: Analysing the code with mypy From 35380bf8b5027e3879c1bdb58d6ca9956d631d1a Mon Sep 17 00:00:00 2001 From: Jochen Sieg Date: Mon, 16 Jun 2025 17:17:47 +0200 Subject: [PATCH 06/11] dbg mypy version --- .github/workflows/linting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 5662ce60..2db093de 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -32,11 +32,11 @@ jobs: python-version: "3.13" - name: Install dependencies run: | - uv sync --dev uv run mypy . || exit_code=$? uv run mypy --install-types --non-interactive - name: Analysing the code with mypy run: | + uv run mypy --version uv run mypy --ignore-missing-imports --disallow-any-generics --disallow-untyped-defs --no-implicit-optional --disallow-incomplete-defs . pydocstyle: runs-on: ubuntu-latest From 2563a86462c5e248d9e81974abdfea0fd92d3f03 Mon Sep 17 00:00:00 2001 From: Jochen Sieg Date: Tue, 17 Jun 2025 08:53:40 +0200 Subject: [PATCH 07/11] some mypy --- .github/workflows/linting.yml | 1 - .../abstract_pipeline_elements/mol2any/mol2bitvector.py | 2 +- molpipeline/estimators/leader_picker_clustering.py | 4 ++-- .../experimental/explainability/visualization/heatmaps.py | 4 ++-- molpipeline/mol2any/mol2bin.py | 2 +- molpipeline/utils/substructure_handling.py | 2 +- tests/utils/fingerprints.py | 2 +- 7 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 2db093de..16f70e28 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -36,7 +36,6 @@ jobs: uv run mypy --install-types --non-interactive - name: Analysing the code with mypy run: | - uv run mypy --version uv run mypy --ignore-missing-imports --disallow-any-generics --disallow-untyped-defs --no-implicit-optional --disallow-incomplete-defs . pydocstyle: runs-on: ubuntu-latest diff --git a/molpipeline/abstract_pipeline_elements/mol2any/mol2bitvector.py b/molpipeline/abstract_pipeline_elements/mol2any/mol2bitvector.py index b4b0e27c..17080112 100644 --- a/molpipeline/abstract_pipeline_elements/mol2any/mol2bitvector.py +++ b/molpipeline/abstract_pipeline_elements/mol2any/mol2bitvector.py @@ -15,7 +15,7 @@ import numpy as np import numpy.typing as npt from rdkit.Chem import rdFingerprintGenerator -from rdkit.DataStructs import ExplicitBitVect +from rdkit.DataStructs import ExplicitBitVect # type: ignore[attr-defined] from scipy import sparse from molpipeline.abstract_pipeline_elements.core import MolToAnyPipelineElement diff --git a/molpipeline/estimators/leader_picker_clustering.py b/molpipeline/estimators/leader_picker_clustering.py index 1640a3ea..cdb1c1b2 100644 --- a/molpipeline/estimators/leader_picker_clustering.py +++ b/molpipeline/estimators/leader_picker_clustering.py @@ -8,7 +8,7 @@ import numpy as np import numpy.typing as npt from rdkit import DataStructs -from rdkit.DataStructs import ExplicitBitVect +from rdkit.DataStructs import ExplicitBitVect # type: ignore[attr-defined] from rdkit.SimDivFilters import rdSimDivPickers from sklearn.base import BaseEstimator, ClusterMixin, _fit_context from sklearn.utils._param_validation import Interval @@ -92,7 +92,7 @@ def _assign_points_to_clusters_based_on_centroid( max_similarities = np.full(len(fps), -np.inf, dtype=np.float64) for i, pick_idx in enumerate(picks): - similarities = DataStructs.BulkTanimotoSimilarity(fps[pick_idx], fps) + similarities = DataStructs.BulkTanimotoSimilarity(fps[pick_idx], fps) # type: ignore[attr-defined] max_mask = similarities > max_similarities labels[max_mask] = i max_similarities[max_mask] = list(compress(similarities, max_mask)) diff --git a/molpipeline/experimental/explainability/visualization/heatmaps.py b/molpipeline/experimental/explainability/visualization/heatmaps.py index 19f65b25..ce78aeb8 100644 --- a/molpipeline/experimental/explainability/visualization/heatmaps.py +++ b/molpipeline/experimental/explainability/visualization/heatmaps.py @@ -299,6 +299,6 @@ def color_canvas(canvas: Draw.MolDraw2D, color_grid: ColorGrid) -> None: for x, y in zip(*mask): upper_left, lower_right = color_grid.grid_field_lim(x, y) - upper_left, lower_right = Point2D(*upper_left), Point2D(*lower_right) - canvas.SetColour(tuple(color_grid.color_grid[x, y])) + upper_left, lower_right = Point2D(*upper_left), Point2D(*lower_right) # type: ignore[assignment] + canvas.SetColour(tuple(color_grid.color_grid[x, y])) # type: ignore[call-arg] canvas.DrawRect(upper_left, lower_right) diff --git a/molpipeline/mol2any/mol2bin.py b/molpipeline/mol2any/mol2bin.py index 3f14b8b7..d3f0df7f 100644 --- a/molpipeline/mol2any/mol2bin.py +++ b/molpipeline/mol2any/mol2bin.py @@ -21,4 +21,4 @@ def pretransform_single(self, value: Chem.Mol) -> str: str Binary representation of molecule. """ - return value.ToBinary() + return value.ToBinary() # type: ignore[call-overload] diff --git a/molpipeline/utils/substructure_handling.py b/molpipeline/utils/substructure_handling.py index 4352a7a1..db56bbea 100644 --- a/molpipeline/utils/substructure_handling.py +++ b/molpipeline/utils/substructure_handling.py @@ -70,6 +70,6 @@ def from_mol( env = Chem.FindAtomEnvironmentOfRadiusN(mol, radius, central_atom_index) amap: dict[int, int] = {} - _ = Chem.PathToSubmol(mol, env, atomMap=amap) + _ = Chem.PathToSubmol(mol, env, atomMap=amap) # type: ignore[call-arg] env_atoms = amap.keys() return CircularAtomEnvironment(central_atom_index, radius, set(env_atoms)) diff --git a/tests/utils/fingerprints.py b/tests/utils/fingerprints.py index 9a97c36b..f59b1915 100644 --- a/tests/utils/fingerprints.py +++ b/tests/utils/fingerprints.py @@ -6,7 +6,7 @@ import numpy.typing as npt from rdkit import Chem from rdkit.Chem import rdFingerprintGenerator as rdkit_fp -from rdkit.DataStructs import ExplicitBitVect, UIntSparseIntVect +from rdkit.DataStructs import ExplicitBitVect, UIntSparseIntVect # type: ignore[attr-defined] from scipy import sparse From 301882dcfde174e96d27e467e14729173ecae08d Mon Sep 17 00:00:00 2001 From: Jochen Sieg Date: Tue, 17 Jun 2025 08:54:51 +0200 Subject: [PATCH 08/11] ruff format --- molpipeline/utils/substructure_handling.py | 2 +- tests/utils/fingerprints.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/molpipeline/utils/substructure_handling.py b/molpipeline/utils/substructure_handling.py index db56bbea..58a9a367 100644 --- a/molpipeline/utils/substructure_handling.py +++ b/molpipeline/utils/substructure_handling.py @@ -70,6 +70,6 @@ def from_mol( env = Chem.FindAtomEnvironmentOfRadiusN(mol, radius, central_atom_index) amap: dict[int, int] = {} - _ = Chem.PathToSubmol(mol, env, atomMap=amap) # type: ignore[call-arg] + _ = Chem.PathToSubmol(mol, env, atomMap=amap) # type: ignore[call-arg] env_atoms = amap.keys() return CircularAtomEnvironment(central_atom_index, radius, set(env_atoms)) diff --git a/tests/utils/fingerprints.py b/tests/utils/fingerprints.py index f59b1915..9a0c6860 100644 --- a/tests/utils/fingerprints.py +++ b/tests/utils/fingerprints.py @@ -6,7 +6,7 @@ import numpy.typing as npt from rdkit import Chem from rdkit.Chem import rdFingerprintGenerator as rdkit_fp -from rdkit.DataStructs import ExplicitBitVect, UIntSparseIntVect # type: ignore[attr-defined] +from rdkit.DataStructs import ExplicitBitVect, UIntSparseIntVect # type: ignore[attr-defined] from scipy import sparse From 1d197889619a397741bb7a096e424417d8ddc856 Mon Sep 17 00:00:00 2001 From: Jochen Sieg Date: Tue, 17 Jun 2025 08:58:38 +0200 Subject: [PATCH 09/11] fix ruff --- tests/utils/fingerprints.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/utils/fingerprints.py b/tests/utils/fingerprints.py index 9a0c6860..8361d640 100644 --- a/tests/utils/fingerprints.py +++ b/tests/utils/fingerprints.py @@ -5,13 +5,18 @@ import numpy as np import numpy.typing as npt from rdkit import Chem -from rdkit.Chem import rdFingerprintGenerator as rdkit_fp -from rdkit.DataStructs import ExplicitBitVect, UIntSparseIntVect # type: ignore[attr-defined] +from rdkit.Chem import rdFingerprintGenerator +from rdkit.DataStructs import ( # type: ignore[attr-defined] + ExplicitBitVect, + UIntSparseIntVect, +) from scipy import sparse def make_sparse_fp( - smiles_list: list[str], radius: int, n_bits: int + smiles_list: list[str], + radius: int, + n_bits: int, ) -> sparse.csr_matrix: """Create a sparse Morgan fingerprint matrix from a list of SMILES. @@ -30,9 +35,10 @@ def make_sparse_fp( ------- sparse.csr_matrix Feature matrix. + """ vector_list = [] - morgan_fp = rdkit_fp.GetMorganGenerator(radius=radius, fpSize=n_bits) + morgan_fp = rdFingerprintGenerator.GetMorganGenerator(radius=radius, fpSize=n_bits) for smiles in smiles_list: mol = Chem.MolFromSmiles(smiles) vector = morgan_fp.GetFingerprintAsNumPy(mol) From bd36ffcd6f2f1d023a0ac949dd3344c2b0a71e17 Mon Sep 17 00:00:00 2001 From: Jochen Sieg Date: Tue, 17 Jun 2025 09:05:42 +0200 Subject: [PATCH 10/11] pyproject.toml: add mypy config ignoring rdkit call-arg errors --- pyproject.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 2eb94220..e3c9054d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -193,6 +193,16 @@ venvPath = "." venv = ".venv" pythonVersion = "3.11" + +[tool.mypy] +# Your existing mypy settings + +[[tool.mypy.overrides]] +# ignore call-arg errors on rdkit. +module = "rdkit.*" +disallow_untyped_calls = false +#warn_return_any = false + [tool.setuptools.dynamic] version = {attr = "molpipeline.__version__"} From c7510a42882ef40d8150ae78039a6060e9d16bd3 Mon Sep 17 00:00:00 2001 From: Jochen Sieg Date: Tue, 17 Jun 2025 14:59:07 +0200 Subject: [PATCH 11/11] ignore mypy errors due incompatibility with RDKit's python bindings --- molpipeline/any2mol/sdf2mol.py | 2 +- .../experimental/explainability/visualization/utils.py | 2 +- molpipeline/mol2any/mol2maccs_key_fingerprint.py | 2 +- molpipeline/mol2any/mol2morgan_fingerprint.py | 2 +- molpipeline/mol2any/mol2rdkit_phys_chem.py | 2 +- pyproject.toml | 10 ---------- 6 files changed, 5 insertions(+), 15 deletions(-) diff --git a/molpipeline/any2mol/sdf2mol.py b/molpipeline/any2mol/sdf2mol.py index 88507f18..4a0fb574 100644 --- a/molpipeline/any2mol/sdf2mol.py +++ b/molpipeline/any2mol/sdf2mol.py @@ -119,7 +119,7 @@ def pretransform_single(self, value: str) -> OptionalMol: "Invalid SDF string!", self.name, ) - supplier = Chem.SDMolSupplier() + supplier = Chem.SDMolSupplier() # type: ignore[call-arg] supplier.SetData(value) mol = next(supplier, None) if mol is None: diff --git a/molpipeline/experimental/explainability/visualization/utils.py b/molpipeline/experimental/explainability/visualization/utils.py index 3fe9c836..b1026e58 100644 --- a/molpipeline/experimental/explainability/visualization/utils.py +++ b/molpipeline/experimental/explainability/visualization/utils.py @@ -34,7 +34,7 @@ def get_mol_lims(mol: Chem.Mol) -> tuple[tuple[float, float], tuple[float, float coords_list = [] conf = mol.GetConformer(0) for i, _ in enumerate(mol.GetAtoms()): - pos = conf.GetAtomPosition(i) + pos = conf.GetAtomPosition(i) # type: ignore[call-arg] coords_list.append((pos.x, pos.y)) coords: npt.NDArray[np.float64] = np.array(coords_list) min_p = np.min(coords, axis=0) diff --git a/molpipeline/mol2any/mol2maccs_key_fingerprint.py b/molpipeline/mol2any/mol2maccs_key_fingerprint.py index 6c3a7663..5e3583f7 100644 --- a/molpipeline/mol2any/mol2maccs_key_fingerprint.py +++ b/molpipeline/mol2any/mol2maccs_key_fingerprint.py @@ -3,7 +3,7 @@ import numpy as np from numpy import typing as npt from rdkit.Chem import MACCSkeys -from rdkit.DataStructs import ExplicitBitVect +from rdkit.DataStructs import ExplicitBitVect # type: ignore[attr-defined] from molpipeline.abstract_pipeline_elements.mol2any.mol2bitvector import ( MolToFingerprintPipelineElement, diff --git a/molpipeline/mol2any/mol2morgan_fingerprint.py b/molpipeline/mol2any/mol2morgan_fingerprint.py index 62b974c2..2b98c90b 100644 --- a/molpipeline/mol2any/mol2morgan_fingerprint.py +++ b/molpipeline/mol2any/mol2morgan_fingerprint.py @@ -163,7 +163,7 @@ def _explain_rdmol(self, mol_obj: RDKitMol) -> dict[int, list[tuple[int, int]]]: Dictionary with bit position as key and list of tuples with atom index and radius as value. """ fp_generator = self._get_fp_generator() - additional_output = AllChem.AdditionalOutput() + additional_output = AllChem.AdditionalOutput() # type: ignore[attr-defined] additional_output.AllocateBitInfoMap() # using the dense fingerprint here, to get indices after folding _ = fp_generator.GetFingerprint(mol_obj, additionalOutput=additional_output) diff --git a/molpipeline/mol2any/mol2rdkit_phys_chem.py b/molpipeline/mol2any/mol2rdkit_phys_chem.py index aebfc30c..2a8b41cf 100644 --- a/molpipeline/mol2any/mol2rdkit_phys_chem.py +++ b/molpipeline/mol2any/mol2rdkit_phys_chem.py @@ -27,7 +27,7 @@ from molpipeline.utils.molpipeline_types import AnyTransformer, RDKitMol RDKIT_DESCRIPTOR_DICT: dict[str, Callable[[Chem.Mol], float]] -RDKIT_DESCRIPTOR_DICT = dict(Descriptors.descList) +RDKIT_DESCRIPTOR_DICT = dict(Descriptors.descList) # type: ignore[attr-defined] # MolWt is removed as ExactMolWt is already included. # Ipc is removed because it causes trouble with numpy. diff --git a/pyproject.toml b/pyproject.toml index e3c9054d..2eb94220 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -193,16 +193,6 @@ venvPath = "." venv = ".venv" pythonVersion = "3.11" - -[tool.mypy] -# Your existing mypy settings - -[[tool.mypy.overrides]] -# ignore call-arg errors on rdkit. -module = "rdkit.*" -disallow_untyped_calls = false -#warn_return_any = false - [tool.setuptools.dynamic] version = {attr = "molpipeline.__version__"}