From 16278386ca0826d99c1249cd1fdea2b027f3c35e Mon Sep 17 00:00:00 2001 From: Andrew Tarzia Date: Tue, 13 Feb 2024 10:24:05 +0100 Subject: [PATCH] Add more detailed exception message for bad topology graph. (#521) Related Issues: #463 #462 Reviewed By: @lukasturcani This commit starts the process of adding more clear errors for issues with construction with stk, to help the user as they build new topology graphs. --- .github/workflows/tests.yml | 4 +- justfile | 4 +- pyproject.toml | 9 +-- src/stk/_internal/building_block.py | 70 ++++++++++++------- .../implementations/implementation.py | 2 +- .../_internal/ea/fitness_normalizers/add.py | 13 ++-- .../ea/fitness_normalizers/divide_by_mean.py | 13 ++-- .../ea/fitness_normalizers/multiply.py | 13 ++-- .../_internal/ea/fitness_normalizers/power.py | 13 ++-- .../ea/fitness_normalizers/replace_fitness.py | 13 ++-- .../ea/fitness_normalizers/shift_up.py | 13 ++-- .../_internal/ea/fitness_normalizers/sum.py | 13 ++-- .../amide_factory.py | 1 - .../bromo_factory.py | 1 - .../carboxylic_acid_factory.py | 1 - .../dibromo_factory.py | 1 - .../difluoro_factory.py | 1 - .../diol_factory.py | 1 - .../fluoro_factory.py | 1 - .../iodo_factory.py | 1 - .../primary_amino_factory.py | 1 - .../ring_amine_factory.py | 1 - .../secondary_amino_factory.py | 1 - .../functional_group_factories/smarts.py | 1 - .../terminal_alkene_factory.py | 1 - .../thioacid_factory.py | 1 - .../thiol_factory.py | 1 - .../generic_functional_group.py | 1 - .../generic_reaction_factory.py | 17 ++++- .../reactions/ring_amine_reaction.py | 22 +++--- .../_internal/topology_graphs/cage/cage.py | 17 +++-- .../topology_graphs/cage/m3l3_triangle.py | 10 +-- .../topology_graphs/cage/m4l4_square.py | 10 +-- .../topology_graphs/cage/one_plus_one.py | 5 +- .../topology_graphs/cage/six_plus_twelve.py | 1 + .../topology_graphs/cage/ten_plus_twenty.py | 1 + src/stk/_internal/topology_graphs/cof/cof.py | 15 ++-- .../topology_graphs/cof/periodic_hexagonal.py | 5 +- .../topology_graphs/cof/periodic_honeycomb.py | 5 +- .../topology_graphs/cof/periodic_kagome.py | 5 +- .../cof/periodic_linkerless_honeycomb.py | 5 +- .../topology_graphs/cof/periodic_square.py | 5 +- .../topology_graphs/host_guest/vertices.py | 1 - .../metal_complex/metal_complex.py | 12 ++-- .../topology_graphs/rotaxane/nrotaxane.py | 3 +- .../topology_graph/utilities.py | 1 - src/stk/_internal/utilities/updaters/mae.py | 1 - tests/drop_test_database.py | 1 - .../molecules/building_block/case_data.py | 8 +++ .../building_block/fixtures/default_init.py | 20 ++++++ .../molecules/building_block/fixtures/init.py | 15 ++++ .../building_block/fixtures/init_from_file.py | 24 +++++++ .../fixtures/init_from_molecule.py | 15 ++++ .../fixtures/init_from_rdkit_mol.py | 15 ++++ .../molecules/building_block/test_repr.py | 41 +++++++++++ 55 files changed, 326 insertions(+), 150 deletions(-) create mode 100644 tests/molecular/molecules/building_block/test_repr.py diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 13aaf64ab..4fa24373f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,7 +26,7 @@ jobs: cache: "pip" - run: "pip install -e '.[dev]'" - run: mypy src - black: + ruff-format: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 @@ -35,7 +35,7 @@ jobs: python-version: "3.11" cache: "pip" - run: "pip install -e '.[dev]'" - - run: black --check . + - run: ruff format --check . pytest: runs-on: ubuntu-22.04 services: diff --git a/justfile b/justfile index ccca7a793..d68a90512 100644 --- a/justfile +++ b/justfile @@ -22,7 +22,7 @@ check: (set -x; ruff . ) echo - ( set -x; black --check . ) + ( set -x; ruff format --check . ) echo ( set -x; mypy src ) @@ -37,7 +37,7 @@ check: # Auto-fix code issues. fix: - black . + ruff format . ruff --fix . # Start a MongoDB instance in docker. diff --git a/pyproject.toml b/pyproject.toml index 763668ac3..fe9011eaa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,12 +28,13 @@ readme = "README.rst" [project.optional-dependencies] dev = [ - "black", "ruff", "moldoc", "mypy", "pip-tools", - "pytest", + # TODO: Remove pin when https://github.com/TvoroG/pytest-lazy-fixture/issues/65 is resolved. + # pytest-lazy-fixture 0.6.0 is incompatible with pytest 8.0.0 + "pytest<8", "pytest-benchmark", "pytest-datadir", "pytest-lazy-fixture", @@ -51,11 +52,11 @@ documentation = "https://stk.readthedocs.io" [tool.setuptools_scm] write_to = "src/stk/_version.py" -[tool.black] -line-length = 79 [tool.ruff] line-length = 79 + +[too.ruff.lint] extend-select = ["I"] [tool.pytest.ini_options] diff --git a/src/stk/_internal/building_block.py b/src/stk/_internal/building_block.py index e49c02b5e..f3f01f160 100644 --- a/src/stk/_internal/building_block.py +++ b/src/stk/_internal/building_block.py @@ -50,9 +50,11 @@ class BuildingBlock(Molecule): def __init__( self, smiles: str, - functional_groups: FunctionalGroup - | FunctionalGroupFactory - | Iterable[FunctionalGroup | FunctionalGroupFactory] = (), + functional_groups: ( + FunctionalGroup + | FunctionalGroupFactory + | Iterable[FunctionalGroup | FunctionalGroupFactory] + ) = (), placer_ids: Iterable[int] | None = None, position_matrix: np.ndarray | None = None, ) -> None: @@ -137,9 +139,11 @@ def __init__( def init_from_molecule( cls, molecule: Molecule, - functional_groups: FunctionalGroup - | FunctionalGroupFactory - | Iterable[FunctionalGroup | FunctionalGroupFactory] = (), + functional_groups: ( + FunctionalGroup + | FunctionalGroupFactory + | Iterable[FunctionalGroup | FunctionalGroupFactory] + ) = (), placer_ids: Iterable[int] | None = None, ) -> typing.Self: """ @@ -200,9 +204,11 @@ def init_from_molecule( def init_from_vabene_molecule( cls, molecule: vabene.Molecule, - functional_groups: FunctionalGroup - | FunctionalGroupFactory - | Iterable[FunctionalGroup | FunctionalGroupFactory] = (), + functional_groups: ( + FunctionalGroup + | FunctionalGroupFactory + | Iterable[FunctionalGroup | FunctionalGroupFactory] + ) = (), placer_ids: Iterable[int] | None = None, position_matrix: np.ndarray | None = None, ) -> typing.Self: @@ -316,9 +322,11 @@ def init( atoms: Iterable[Atom], bonds: Iterable[Bond], position_matrix: np.ndarray, - functional_groups: FunctionalGroup - | FunctionalGroupFactory - | Iterable[FunctionalGroup | FunctionalGroupFactory] = (), + functional_groups: ( + FunctionalGroup + | FunctionalGroupFactory + | Iterable[FunctionalGroup | FunctionalGroupFactory] + ) = (), placer_ids: Iterable[int] | None = None, ) -> typing.Self: """ @@ -380,11 +388,13 @@ def init( bonds=bonds, position_matrix=position_matrix, ) - building_block._fg_repr = repr(functional_groups) functional_groups = building_block._extract_functional_groups( functional_groups=functional_groups, ) building_block._with_functional_groups(functional_groups) + building_block._fg_repr = repr( # type: ignore[has-type] + tuple(building_block.get_functional_groups()) + ) building_block._placer_ids = building_block._normalize_placer_ids( placer_ids=placer_ids, functional_groups=building_block._functional_groups, @@ -400,9 +410,11 @@ def init( def init_from_file( cls, path: pathlib.Path | str, - functional_groups: FunctionalGroup - | FunctionalGroupFactory - | Iterable[FunctionalGroup | FunctionalGroupFactory] = (), + functional_groups: ( + FunctionalGroup + | FunctionalGroupFactory + | Iterable[FunctionalGroup | FunctionalGroupFactory] + ) = (), placer_ids: Iterable[int] | None = None, ) -> typing.Self: """ @@ -479,9 +491,11 @@ def init_from_file( def init_from_rdkit_mol( cls, molecule: rdkit.Mol, - functional_groups: FunctionalGroup - | FunctionalGroupFactory - | Iterable[FunctionalGroup | FunctionalGroupFactory] = (), + functional_groups: ( + FunctionalGroup + | FunctionalGroupFactory + | Iterable[FunctionalGroup | FunctionalGroupFactory] + ) = (), placer_ids: Iterable[int] | None = None, ) -> typing.Self: """ @@ -548,9 +562,11 @@ def init_from_rdkit_mol( def _init_from_rdkit_mol( self, molecule: rdkit.Mol, - functional_groups: FunctionalGroup - | FunctionalGroupFactory - | Iterable[FunctionalGroup | FunctionalGroupFactory], + functional_groups: ( + FunctionalGroup + | FunctionalGroupFactory + | Iterable[FunctionalGroup | FunctionalGroupFactory] + ), placer_ids: Iterable[int] | None, ) -> None: """ @@ -595,7 +611,6 @@ def _init_from_rdkit_mol( """ - self._fg_repr = repr(functional_groups) atoms = tuple( Atom(a.GetIdx(), a.GetAtomicNum(), a.GetFormalCharge()) for a in molecule.GetAtoms() @@ -620,6 +635,7 @@ def _init_from_rdkit_mol( functional_groups=functional_groups, ) ) + self._fg_repr = repr(self._functional_groups) self._placer_ids = self._normalize_placer_ids( placer_ids=placer_ids, functional_groups=self._functional_groups, @@ -714,9 +730,11 @@ def _get_core_ids( def _extract_functional_groups( self, - functional_groups: FunctionalGroup - | FunctionalGroupFactory - | Iterable[FunctionalGroup | FunctionalGroupFactory], + functional_groups: ( + FunctionalGroup + | FunctionalGroupFactory + | Iterable[FunctionalGroup | FunctionalGroupFactory] + ), ) -> Iterator[FunctionalGroup]: """ Yield functional groups. diff --git a/src/stk/_internal/ea/evolutionary_algorithm/implementations/implementation.py b/src/stk/_internal/ea/evolutionary_algorithm/implementations/implementation.py index f616fbce4..7eaa7b7d9 100644 --- a/src/stk/_internal/ea/evolutionary_algorithm/implementations/implementation.py +++ b/src/stk/_internal/ea/evolutionary_algorithm/implementations/implementation.py @@ -138,7 +138,7 @@ def get_key(record: T) -> str: population, keys = dedupe( items=( molecule_record - for molecule_record, in self._generation_selector.select( + for (molecule_record,) in self._generation_selector.select( population=normalized_fitness_values ) ), diff --git a/src/stk/_internal/ea/fitness_normalizers/add.py b/src/stk/_internal/ea/fitness_normalizers/add.py index 7f0dca334..dbbba349d 100644 --- a/src/stk/_internal/ea/fitness_normalizers/add.py +++ b/src/stk/_internal/ea/fitness_normalizers/add.py @@ -106,9 +106,8 @@ class Add(FitnessNormalizer[T]): def __init__( self, number: float | Iterable[float], - filter: Callable[ - [dict[T, Any], T], bool - ] = lambda fitness_values, record: True, + filter: Callable[[dict[T, Any], T], bool] = lambda fitness_values, + record: True, ) -> None: """ Parameters: @@ -134,8 +133,10 @@ def __init__( def normalize(self, fitness_values: dict[T, Any]) -> dict[T, Any]: return { - record: np.add(self._number, fitness_value) - if self._filter(fitness_values, record) - else fitness_value + record: ( + np.add(self._number, fitness_value) + if self._filter(fitness_values, record) + else fitness_value + ) for record, fitness_value in fitness_values.items() } diff --git a/src/stk/_internal/ea/fitness_normalizers/divide_by_mean.py b/src/stk/_internal/ea/fitness_normalizers/divide_by_mean.py index 58b8c4473..a4c45fdc8 100644 --- a/src/stk/_internal/ea/fitness_normalizers/divide_by_mean.py +++ b/src/stk/_internal/ea/fitness_normalizers/divide_by_mean.py @@ -85,9 +85,8 @@ class DivideByMean(FitnessNormalizer[T]): def __init__( self, - filter: Callable[ - [dict[T, Any], T], bool - ] = lambda fitness_values, record: True, + filter: Callable[[dict[T, Any], T], bool] = lambda fitness_values, + record: True, ) -> None: """ Parameters: @@ -116,8 +115,10 @@ def normalize(self, fitness_values: dict[T, Any]) -> dict[T, Any]: logger.debug(f"Means used: {mean}") return { - record: np.divide(fitness_value, mean) - if self._filter(fitness_values, record) - else fitness_value + record: ( + np.divide(fitness_value, mean) + if self._filter(fitness_values, record) + else fitness_value + ) for record, fitness_value in fitness_values.items() } diff --git a/src/stk/_internal/ea/fitness_normalizers/multiply.py b/src/stk/_internal/ea/fitness_normalizers/multiply.py index 697ae19ba..ca7754ebf 100644 --- a/src/stk/_internal/ea/fitness_normalizers/multiply.py +++ b/src/stk/_internal/ea/fitness_normalizers/multiply.py @@ -107,9 +107,8 @@ class Multiply(FitnessNormalizer[T]): def __init__( self, coefficient: float | Iterable[float], - filter: Callable[ - [dict[T, Any], T], bool - ] = lambda fitness_values, record: True, + filter: Callable[[dict[T, Any], T], bool] = lambda fitness_values, + record: True, ) -> None: """ Parameters: @@ -135,8 +134,10 @@ def __init__( def normalize(self, fitness_values: dict[T, Any]) -> dict[T, Any]: return { - record: np.multiply(self._coefficient, fitness_value) - if self._filter(fitness_values, record) - else fitness_value + record: ( + np.multiply(self._coefficient, fitness_value) + if self._filter(fitness_values, record) + else fitness_value + ) for record, fitness_value in fitness_values.items() } diff --git a/src/stk/_internal/ea/fitness_normalizers/power.py b/src/stk/_internal/ea/fitness_normalizers/power.py index b42e6a21e..fd3dc594c 100644 --- a/src/stk/_internal/ea/fitness_normalizers/power.py +++ b/src/stk/_internal/ea/fitness_normalizers/power.py @@ -141,9 +141,8 @@ class Power(FitnessNormalizer[T]): def __init__( self, power: float | Iterable[float], - filter: Callable[ - [dict[T, Any], T], bool - ] = lambda fitness_values, record: True, + filter: Callable[[dict[T, Any], T], bool] = lambda fitness_values, + record: True, ) -> None: """ Parameters: @@ -169,8 +168,10 @@ def __init__( def normalize(self, fitness_values: dict[T, Any]) -> dict[T, Any]: return { - record: np.float_power(fitness_value, self._power) - if self._filter(fitness_values, record) - else fitness_value + record: ( + np.float_power(fitness_value, self._power) + if self._filter(fitness_values, record) + else fitness_value + ) for record, fitness_value in fitness_values.items() } diff --git a/src/stk/_internal/ea/fitness_normalizers/replace_fitness.py b/src/stk/_internal/ea/fitness_normalizers/replace_fitness.py index 611c8f7a5..477265a87 100644 --- a/src/stk/_internal/ea/fitness_normalizers/replace_fitness.py +++ b/src/stk/_internal/ea/fitness_normalizers/replace_fitness.py @@ -68,9 +68,8 @@ def get_minimum_fitness_value(fitness_values): def __init__( self, get_replacement: Callable[[dict[T, Any]], Any], - filter: Callable[ - [dict[T, Any], T], bool - ] = lambda fitness_values, record: True, + filter: Callable[[dict[T, Any], T], bool] = lambda fitness_values, + record: True, ) -> None: """ Parameters: @@ -97,8 +96,10 @@ def __init__( def normalize(self, fitness_values: dict[T, Any]) -> dict[T, Any]: replacement = self._get_replacement(fitness_values) return { - record: replacement - if self._filter(fitness_values, record) - else fitness_value + record: ( + replacement + if self._filter(fitness_values, record) + else fitness_value + ) for record, fitness_value in fitness_values.items() } diff --git a/src/stk/_internal/ea/fitness_normalizers/shift_up.py b/src/stk/_internal/ea/fitness_normalizers/shift_up.py index 1e8d3c98d..eba2fcad7 100644 --- a/src/stk/_internal/ea/fitness_normalizers/shift_up.py +++ b/src/stk/_internal/ea/fitness_normalizers/shift_up.py @@ -144,9 +144,8 @@ class ShiftUp(FitnessNormalizer[T]): def __init__( self, - filter: Callable[ - [dict[T, Any], T], bool - ] = lambda fitness_values, record: True, + filter: Callable[[dict[T, Any], T], bool] = lambda fitness_values, + record: True, ) -> None: """ Parameters: @@ -184,8 +183,10 @@ def normalize(self, fitness_values: dict[T, Any]) -> dict[T, Any]: shift[i] = 1 - min_ return { - record: fitness_value + shift - if self._filter(fitness_values, record) - else fitness_value + record: ( + fitness_value + shift + if self._filter(fitness_values, record) + else fitness_value + ) for record, fitness_value in fitness_values.items() } diff --git a/src/stk/_internal/ea/fitness_normalizers/sum.py b/src/stk/_internal/ea/fitness_normalizers/sum.py index 97cc1391a..1af0d963d 100644 --- a/src/stk/_internal/ea/fitness_normalizers/sum.py +++ b/src/stk/_internal/ea/fitness_normalizers/sum.py @@ -86,9 +86,8 @@ class Sum(FitnessNormalizer[T]): def __init__( self, - filter: Callable[ - [dict[T, Any], T], bool - ] = lambda fitness_values, record: True, + filter: Callable[[dict[T, Any], T], bool] = lambda fitness_values, + record: True, ) -> None: """ Parameters: @@ -106,8 +105,10 @@ def __init__( def normalize(self, fitness_values: dict[T, Any]) -> dict[T, Any]: return { - record: sum(fitness_value) - if self._filter(fitness_values, record) - else fitness_value + record: ( + sum(fitness_value) + if self._filter(fitness_values, record) + else fitness_value + ) for record, fitness_value in fitness_values.items() } diff --git a/src/stk/_internal/functional_group_factories/amide_factory.py b/src/stk/_internal/functional_group_factories/amide_factory.py index b7e2e3561..25966c779 100644 --- a/src/stk/_internal/functional_group_factories/amide_factory.py +++ b/src/stk/_internal/functional_group_factories/amide_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/bromo_factory.py b/src/stk/_internal/functional_group_factories/bromo_factory.py index c7e151f94..cbd37f8d0 100644 --- a/src/stk/_internal/functional_group_factories/bromo_factory.py +++ b/src/stk/_internal/functional_group_factories/bromo_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/carboxylic_acid_factory.py b/src/stk/_internal/functional_group_factories/carboxylic_acid_factory.py index a6ef8e576..cf2d8bd27 100644 --- a/src/stk/_internal/functional_group_factories/carboxylic_acid_factory.py +++ b/src/stk/_internal/functional_group_factories/carboxylic_acid_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/dibromo_factory.py b/src/stk/_internal/functional_group_factories/dibromo_factory.py index a9d0dce76..12e3aaa93 100644 --- a/src/stk/_internal/functional_group_factories/dibromo_factory.py +++ b/src/stk/_internal/functional_group_factories/dibromo_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/difluoro_factory.py b/src/stk/_internal/functional_group_factories/difluoro_factory.py index 7c7f284e1..d660df2e0 100644 --- a/src/stk/_internal/functional_group_factories/difluoro_factory.py +++ b/src/stk/_internal/functional_group_factories/difluoro_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/diol_factory.py b/src/stk/_internal/functional_group_factories/diol_factory.py index fc612bc7e..e2b26444f 100644 --- a/src/stk/_internal/functional_group_factories/diol_factory.py +++ b/src/stk/_internal/functional_group_factories/diol_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/fluoro_factory.py b/src/stk/_internal/functional_group_factories/fluoro_factory.py index c3e41a67b..d291c15ed 100644 --- a/src/stk/_internal/functional_group_factories/fluoro_factory.py +++ b/src/stk/_internal/functional_group_factories/fluoro_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/iodo_factory.py b/src/stk/_internal/functional_group_factories/iodo_factory.py index 7d4c1e7fe..b01ee800f 100644 --- a/src/stk/_internal/functional_group_factories/iodo_factory.py +++ b/src/stk/_internal/functional_group_factories/iodo_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/primary_amino_factory.py b/src/stk/_internal/functional_group_factories/primary_amino_factory.py index 1669bd88d..486cc5037 100644 --- a/src/stk/_internal/functional_group_factories/primary_amino_factory.py +++ b/src/stk/_internal/functional_group_factories/primary_amino_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/ring_amine_factory.py b/src/stk/_internal/functional_group_factories/ring_amine_factory.py index 22e78dfd3..6363764db 100644 --- a/src/stk/_internal/functional_group_factories/ring_amine_factory.py +++ b/src/stk/_internal/functional_group_factories/ring_amine_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/secondary_amino_factory.py b/src/stk/_internal/functional_group_factories/secondary_amino_factory.py index 4447d8094..2aaddf344 100644 --- a/src/stk/_internal/functional_group_factories/secondary_amino_factory.py +++ b/src/stk/_internal/functional_group_factories/secondary_amino_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/smarts.py b/src/stk/_internal/functional_group_factories/smarts.py index 7e1485cf1..595dcedd0 100644 --- a/src/stk/_internal/functional_group_factories/smarts.py +++ b/src/stk/_internal/functional_group_factories/smarts.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/terminal_alkene_factory.py b/src/stk/_internal/functional_group_factories/terminal_alkene_factory.py index 87f72908c..8c0aee31b 100644 --- a/src/stk/_internal/functional_group_factories/terminal_alkene_factory.py +++ b/src/stk/_internal/functional_group_factories/terminal_alkene_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/thioacid_factory.py b/src/stk/_internal/functional_group_factories/thioacid_factory.py index abd1a4646..f966ef200 100644 --- a/src/stk/_internal/functional_group_factories/thioacid_factory.py +++ b/src/stk/_internal/functional_group_factories/thioacid_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_group_factories/thiol_factory.py b/src/stk/_internal/functional_group_factories/thiol_factory.py index 8b33a45b8..d0b84b983 100644 --- a/src/stk/_internal/functional_group_factories/thiol_factory.py +++ b/src/stk/_internal/functional_group_factories/thiol_factory.py @@ -4,7 +4,6 @@ """ - from stk._internal.functional_group_factories.functional_group_factory import ( FunctionalGroupFactory, ) diff --git a/src/stk/_internal/functional_groups/generic_functional_group.py b/src/stk/_internal/functional_groups/generic_functional_group.py index b73e583d5..66f93e827 100644 --- a/src/stk/_internal/functional_groups/generic_functional_group.py +++ b/src/stk/_internal/functional_groups/generic_functional_group.py @@ -4,7 +4,6 @@ """ - from __future__ import annotations import typing diff --git a/src/stk/_internal/reaction_factories/generic_reaction_factory.py b/src/stk/_internal/reaction_factories/generic_reaction_factory.py index 2743f9a93..a9c658a3d 100644 --- a/src/stk/_internal/reaction_factories/generic_reaction_factory.py +++ b/src/stk/_internal/reaction_factories/generic_reaction_factory.py @@ -4,6 +4,8 @@ """ +import textwrap + from stk._internal.functional_groups.aldehyde import Aldehyde from stk._internal.functional_groups.alkene import Alkene from stk._internal.functional_groups.alkyne import Alkyne @@ -159,7 +161,20 @@ def get_reaction(self, construction_state, edge_group): edge_group=edge_group, ) ) - functional_group1, functional_group2 = functional_groups + + try: + functional_group1, functional_group2 = functional_groups + except ValueError as ex: + ex.add_note( + textwrap.dedent( + f"""\ + Two functional groups not found during reaction. + This suggests an issue with edge id {next(edge_group.get_edge_ids())} + in your topology graph. (edge group: {edge_group})""" + ) + ) + raise + edge = construction_state.get_edge( edge_id=next(edge_group.get_edge_ids()), ) diff --git a/src/stk/_internal/reactions/ring_amine_reaction.py b/src/stk/_internal/reactions/ring_amine_reaction.py index 1dfbaffb6..a36c21270 100644 --- a/src/stk/_internal/reactions/ring_amine_reaction.py +++ b/src/stk/_internal/reactions/ring_amine_reaction.py @@ -99,17 +99,17 @@ def _get_new_bonds(self): nc2h1 = C(-8) nc2h2 = C(-9) - yield Bond(n1, n_joiner, 1), - yield Bond(n_joiner, n2, 1, self._periodicity), - yield Bond(n_joiner, nh1, 1), - yield Bond(n_joiner, nh2, 1), - yield Bond(c1, nc_joiner1, 1), - yield Bond(nc_joiner1, n2, 1, self._periodicity), - yield Bond(nc_joiner1, nc1h1, 1), - yield Bond(nc_joiner1, nc1h2, 1), - yield Bond(nc_joiner2, c2, 1, self._periodicity), - yield Bond(n1, nc_joiner2, 1), - yield Bond(nc_joiner2, nc2h1, 1), + yield (Bond(n1, n_joiner, 1),) + yield (Bond(n_joiner, n2, 1, self._periodicity),) + yield (Bond(n_joiner, nh1, 1),) + yield (Bond(n_joiner, nh2, 1),) + yield (Bond(c1, nc_joiner1, 1),) + yield (Bond(nc_joiner1, n2, 1, self._periodicity),) + yield (Bond(nc_joiner1, nc1h1, 1),) + yield (Bond(nc_joiner1, nc1h2, 1),) + yield (Bond(nc_joiner2, c2, 1, self._periodicity),) + yield (Bond(n1, nc_joiner2, 1),) + yield (Bond(nc_joiner2, nc2h1, 1),) yield Bond(nc_joiner2, nc2h2, 1) def _get_deleted_atoms(self): diff --git a/src/stk/_internal/topology_graphs/cage/cage.py b/src/stk/_internal/topology_graphs/cage/cage.py index d1e43f4aa..b6cd66b48 100644 --- a/src/stk/_internal/topology_graphs/cage/cage.py +++ b/src/stk/_internal/topology_graphs/cage/cage.py @@ -966,8 +966,9 @@ def __init_subclass__(cls, **kwargs) -> None: def __init__( self, - building_blocks: abc.Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], + building_blocks: ( + abc.Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), vertex_alignments: dict[int, int] | None = None, vertex_positions: dict[int, np.ndarray] | None = None, reaction_factory: ReactionFactory = GenericReactionFactory(), @@ -1160,11 +1161,13 @@ def _normalize_edge_prototypes( @classmethod def _normalize_building_blocks( cls, - building_blocks: abc.Iterable[BuildingBlock] - | dict[ - BuildingBlock, - tuple[int, ...], - ], + building_blocks: ( + abc.Iterable[BuildingBlock] + | dict[ + BuildingBlock, + tuple[int, ...], + ] + ), ) -> dict[BuildingBlock, abc.Sequence[_CageVertex]]: # Use tuple here because it prints nicely. allowed_degrees = tuple(cls._vertices_of_degree.keys()) diff --git a/src/stk/_internal/topology_graphs/cage/m3l3_triangle.py b/src/stk/_internal/topology_graphs/cage/m3l3_triangle.py index 98073d797..8004c78cf 100644 --- a/src/stk/_internal/topology_graphs/cage/m3l3_triangle.py +++ b/src/stk/_internal/topology_graphs/cage/m3l3_triangle.py @@ -145,10 +145,12 @@ class M3L3Triangle(Cage): def __init__( self, - corners: Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], - linkers: Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], + corners: ( + Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), + linkers: ( + Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), vertex_alignments: dict[int, int] | None = None, vertex_positions: dict[int, np.ndarray] | None = None, reaction_factory: ReactionFactory = GenericReactionFactory(), diff --git a/src/stk/_internal/topology_graphs/cage/m4l4_square.py b/src/stk/_internal/topology_graphs/cage/m4l4_square.py index f05fca434..dc8cc0772 100644 --- a/src/stk/_internal/topology_graphs/cage/m4l4_square.py +++ b/src/stk/_internal/topology_graphs/cage/m4l4_square.py @@ -149,10 +149,12 @@ class M4L4Square(Cage): def __init__( self, - corners: Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], - linkers: Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], + corners: ( + Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), + linkers: ( + Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), vertex_alignments: dict[int, int] | None = None, vertex_positions: dict[int, np.ndarray] | None = None, reaction_factory: ReactionFactory = GenericReactionFactory(), diff --git a/src/stk/_internal/topology_graphs/cage/one_plus_one.py b/src/stk/_internal/topology_graphs/cage/one_plus_one.py index f0357807c..06f519bfe 100644 --- a/src/stk/_internal/topology_graphs/cage/one_plus_one.py +++ b/src/stk/_internal/topology_graphs/cage/one_plus_one.py @@ -176,8 +176,9 @@ class OnePlusOne(Cage): def __init__( self, - building_blocks: Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], + building_blocks: ( + Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), vertex_alignments: dict[int, int] | None = None, reaction_factory: ReactionFactory = GenericReactionFactory(), num_processes: int = 1, diff --git a/src/stk/_internal/topology_graphs/cage/six_plus_twelve.py b/src/stk/_internal/topology_graphs/cage/six_plus_twelve.py index 258abd134..40a883ec8 100644 --- a/src/stk/_internal/topology_graphs/cage/six_plus_twelve.py +++ b/src/stk/_internal/topology_graphs/cage/six_plus_twelve.py @@ -3,6 +3,7 @@ =============== """ + import numpy as np from stk._internal.topology_graphs.edge import Edge diff --git a/src/stk/_internal/topology_graphs/cage/ten_plus_twenty.py b/src/stk/_internal/topology_graphs/cage/ten_plus_twenty.py index 94abc6a01..8eb51da44 100644 --- a/src/stk/_internal/topology_graphs/cage/ten_plus_twenty.py +++ b/src/stk/_internal/topology_graphs/cage/ten_plus_twenty.py @@ -3,6 +3,7 @@ =============== """ + import numpy as np from stk._internal.topology_graphs.edge import Edge diff --git a/src/stk/_internal/topology_graphs/cof/cof.py b/src/stk/_internal/topology_graphs/cof/cof.py index 31130a850..9391e7fa8 100644 --- a/src/stk/_internal/topology_graphs/cof/cof.py +++ b/src/stk/_internal/topology_graphs/cof/cof.py @@ -336,8 +336,9 @@ def __init_subclass__(cls, **kwargs): def __init__( self, - building_blocks: abc.Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], + building_blocks: ( + abc.Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), lattice_size: tuple[int, int, int], periodic: bool = False, vertex_alignments: dict[int, int] | None = None, @@ -457,12 +458,10 @@ def __init__( for building_block, ids in building_blocks.items() } else: - building_block_vertices = ( - self._get_building_block_vertices( # type: ignore[assignment] - building_blocks=building_blocks, - vertices=vertices, - edges=edges, - ) + building_block_vertices = self._get_building_block_vertices( # type: ignore[assignment] + building_blocks=building_blocks, + vertices=vertices, + edges=edges, ) building_block_vertices = self._with_unaligning_vertices( diff --git a/src/stk/_internal/topology_graphs/cof/periodic_hexagonal.py b/src/stk/_internal/topology_graphs/cof/periodic_hexagonal.py index 488c0d684..6ceeabe40 100644 --- a/src/stk/_internal/topology_graphs/cof/periodic_hexagonal.py +++ b/src/stk/_internal/topology_graphs/cof/periodic_hexagonal.py @@ -119,8 +119,9 @@ class PeriodicHexagonal(Cof): def __init__( self, - building_blocks: abc.Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], + building_blocks: ( + abc.Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), lattice_size: tuple[int, int, int], vertex_alignments: dict[int, int] | None = None, reaction_factory: ReactionFactory = GenericReactionFactory(), diff --git a/src/stk/_internal/topology_graphs/cof/periodic_honeycomb.py b/src/stk/_internal/topology_graphs/cof/periodic_honeycomb.py index a6ee84a6e..c2564e476 100644 --- a/src/stk/_internal/topology_graphs/cof/periodic_honeycomb.py +++ b/src/stk/_internal/topology_graphs/cof/periodic_honeycomb.py @@ -121,8 +121,9 @@ class PeriodicHoneycomb(Cof): def __init__( self, - building_blocks: abc.Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], + building_blocks: ( + abc.Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), lattice_size: tuple[int, int, int], vertex_alignments: dict[int, int] | None = None, reaction_factory: ReactionFactory = GenericReactionFactory(), diff --git a/src/stk/_internal/topology_graphs/cof/periodic_kagome.py b/src/stk/_internal/topology_graphs/cof/periodic_kagome.py index c0da9f208..28f243ca7 100644 --- a/src/stk/_internal/topology_graphs/cof/periodic_kagome.py +++ b/src/stk/_internal/topology_graphs/cof/periodic_kagome.py @@ -133,8 +133,9 @@ class PeriodicKagome(Cof): def __init__( self, - building_blocks: abc.Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], + building_blocks: ( + abc.Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), lattice_size: tuple[int, int, int], vertex_alignments: dict[int, int] | None = None, reaction_factory: ReactionFactory = GenericReactionFactory(), diff --git a/src/stk/_internal/topology_graphs/cof/periodic_linkerless_honeycomb.py b/src/stk/_internal/topology_graphs/cof/periodic_linkerless_honeycomb.py index 7bea9e4c3..aa8bbdb16 100644 --- a/src/stk/_internal/topology_graphs/cof/periodic_linkerless_honeycomb.py +++ b/src/stk/_internal/topology_graphs/cof/periodic_linkerless_honeycomb.py @@ -116,8 +116,9 @@ class PeriodicLinkerlessHoneycomb(Cof): def __init__( self, - building_blocks: abc.Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], + building_blocks: ( + abc.Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), lattice_size: tuple[int, int, int], vertex_alignments: dict[int, int] | None = None, reaction_factory: ReactionFactory = GenericReactionFactory(), diff --git a/src/stk/_internal/topology_graphs/cof/periodic_square.py b/src/stk/_internal/topology_graphs/cof/periodic_square.py index 9eb744643..832b5f548 100644 --- a/src/stk/_internal/topology_graphs/cof/periodic_square.py +++ b/src/stk/_internal/topology_graphs/cof/periodic_square.py @@ -125,8 +125,9 @@ class PeriodicSquare(Cof): def __init__( self, - building_blocks: abc.Iterable[BuildingBlock] - | dict[BuildingBlock, tuple[int, ...]], + building_blocks: ( + abc.Iterable[BuildingBlock] | dict[BuildingBlock, tuple[int, ...]] + ), lattice_size: tuple[int, int, int], vertex_alignments: dict[int, int] | None = None, reaction_factory: ReactionFactory = GenericReactionFactory(), diff --git a/src/stk/_internal/topology_graphs/host_guest/vertices.py b/src/stk/_internal/topology_graphs/host_guest/vertices.py index df772d836..0aea6b288 100644 --- a/src/stk/_internal/topology_graphs/host_guest/vertices.py +++ b/src/stk/_internal/topology_graphs/host_guest/vertices.py @@ -4,7 +4,6 @@ """ - import numpy as np from stk._internal.topology_graphs.vertex import Vertex diff --git a/src/stk/_internal/topology_graphs/metal_complex/metal_complex.py b/src/stk/_internal/topology_graphs/metal_complex/metal_complex.py index 6fb01afb6..333ae47d6 100644 --- a/src/stk/_internal/topology_graphs/metal_complex/metal_complex.py +++ b/src/stk/_internal/topology_graphs/metal_complex/metal_complex.py @@ -609,11 +609,13 @@ def __init__( def _normalize_metals( self, - metals: BuildingBlock - | dict[ - BuildingBlock, - tuple[int, ...], - ], + metals: ( + BuildingBlock + | dict[ + BuildingBlock, + tuple[int, ...], + ] + ), ) -> dict[BuildingBlock, abc.Sequence[Vertex]]: """ Return a map between metals and vertices. diff --git a/src/stk/_internal/topology_graphs/rotaxane/nrotaxane.py b/src/stk/_internal/topology_graphs/rotaxane/nrotaxane.py index b3d3e4dfc..87ce9a093 100644 --- a/src/stk/_internal/topology_graphs/rotaxane/nrotaxane.py +++ b/src/stk/_internal/topology_graphs/rotaxane/nrotaxane.py @@ -489,7 +489,8 @@ def __init__( # Save the chosen orientations for __repr__. self._orientations = tuple( - int(vertex.get_flip()) for vertex in vertices[1:] # type:ignore + int(vertex.get_flip()) # type: ignore[union-attr] + for vertex in vertices[1:] ) super().__init__( diff --git a/src/stk/_internal/topology_graphs/topology_graph/utilities.py b/src/stk/_internal/topology_graphs/topology_graph/utilities.py index 772edb09b..886c6eddf 100644 --- a/src/stk/_internal/topology_graphs/topology_graph/utilities.py +++ b/src/stk/_internal/topology_graphs/topology_graph/utilities.py @@ -4,7 +4,6 @@ """ - import typing import numpy as np diff --git a/src/stk/_internal/utilities/updaters/mae.py b/src/stk/_internal/utilities/updaters/mae.py index 4a8cf8310..6cdd9e11b 100644 --- a/src/stk/_internal/utilities/updaters/mae.py +++ b/src/stk/_internal/utilities/updaters/mae.py @@ -4,7 +4,6 @@ """ - from stk._internal.utilities.utilities import mol_from_mae_file diff --git a/tests/drop_test_database.py b/tests/drop_test_database.py index e0a0335ba..3fdab1d63 100644 --- a/tests/drop_test_database.py +++ b/tests/drop_test_database.py @@ -6,7 +6,6 @@ """ - import pymongo diff --git a/tests/molecular/molecules/building_block/case_data.py b/tests/molecular/molecules/building_block/case_data.py index 8655eb877..0fb4a3a44 100644 --- a/tests/molecular/molecules/building_block/case_data.py +++ b/tests/molecular/molecules/building_block/case_data.py @@ -11,6 +11,9 @@ class CaseData: The functional groups :attr:`.building_block` should be holding. + known_repr : str + The representation of the building block. + core_atom_ids : :class:`tuple` of :class:`int` The correct core atom ids for :attr:`.building_block`. @@ -23,6 +26,7 @@ def __init__( self, building_block, functional_groups, + known_repr, core_atom_ids, placer_ids, ): @@ -37,6 +41,9 @@ def __init__( functional_groups : :class:`tuple` of :class:`.FunctionalGroup` The functional groups `building_block` should be holding. + known_repr : str + The representation of the building block. + core_atom_ids : :class:`tuple` of :class:`int` The correct core atom ids for `building_block`. @@ -47,5 +54,6 @@ def __init__( self.building_block = building_block self.functional_groups = functional_groups + self.known_repr = known_repr self.core_atom_ids = core_atom_ids self.placer_ids = placer_ids diff --git a/tests/molecular/molecules/building_block/fixtures/default_init.py b/tests/molecular/molecules/building_block/fixtures/default_init.py index 41fe19292..9122c4d16 100644 --- a/tests/molecular/molecules/building_block/fixtures/default_init.py +++ b/tests/molecular/molecules/building_block/fixtures/default_init.py @@ -10,6 +10,7 @@ lambda: CaseData( building_block=stk.BuildingBlock("Br[C+2][C+2]Br"), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(0, 1, 2, 3), ), @@ -32,6 +33,12 @@ deleters=(stk.Br(3),), ), ), + known_repr=( + "BuildingBlock('Br[C+2][C+2]Br', (Bromo(Br(0), C(1, charge=2)," + " bonders=(C(1, charge=2),), deleters=(Br(0),)), Bromo(Br(3), " + "C(2, charge=2), bonders=(C(2, charge=2),), deleters=(Br(3),))" + "))" + ), core_atom_ids=(1, 2), placer_ids=(1, 2), ), @@ -41,6 +48,7 @@ placer_ids=(1, 2), ), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(1, 2), ), @@ -64,6 +72,12 @@ deleters=(stk.Br(3),), ), ), + known_repr=( + "BuildingBlock('Br[C+2][C+2]Br', (Bromo(Br(0), C(1, charge=2)," + " bonders=(C(1, charge=2),), deleters=(Br(0),)), Bromo(Br(3), " + "C(2, charge=2), bonders=(C(2, charge=2),), deleters=(Br(3),))" + "))" + ), core_atom_ids=(1, 2), placer_ids=(0, 3), ), @@ -73,6 +87,7 @@ functional_groups=[stk.IodoFactory()], ), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(0, 1, 2, 3), ), @@ -95,6 +110,11 @@ deleters=(stk.Br(2),), ), ), + known_repr=( + "BuildingBlock('Br[C+2]Br', (Bromo(Br(0), C(1, charge=2), bond" + "ers=(C(1, charge=2),), deleters=(Br(0),)), Bromo(Br(2), C(1, " + "charge=2), bonders=(C(1, charge=2),), deleters=(Br(2),))))" + ), core_atom_ids=(1,), placer_ids=(1,), ), diff --git a/tests/molecular/molecules/building_block/fixtures/init.py b/tests/molecular/molecules/building_block/fixtures/init.py index 747b22b62..4fd4c941d 100644 --- a/tests/molecular/molecules/building_block/fixtures/init.py +++ b/tests/molecular/molecules/building_block/fixtures/init.py @@ -26,6 +26,7 @@ ), ), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(0, 1, 2, 3), ), @@ -61,6 +62,12 @@ deleters=(stk.Br(3),), ), ), + known_repr=( + "BuildingBlock('Br[C+2][C+2]Br', (Bromo(Br(0), C(1, charge=2)," + " bonders=(C(1, charge=2),), deleters=(Br(0),)), Bromo(Br(3), " + "C(2, charge=2), bonders=(C(2, charge=2),), deleters=(Br(3),))" + "))" + ), core_atom_ids=(1, 2), placer_ids=(1, 2), ), @@ -83,6 +90,7 @@ placer_ids=(1, 2), ), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(1, 2), ), @@ -119,6 +127,12 @@ deleters=(stk.Br(3),), ), ), + known_repr=( + "BuildingBlock('Br[C+2][C+2]Br', (Bromo(Br(0), C(1, charge=2)," + " bonders=(C(1, charge=2),), deleters=(Br(0),)), Bromo(Br(3), " + "C(2, charge=2), bonders=(C(2, charge=2),), deleters=(Br(3),))" + "))" + ), core_atom_ids=(1, 2), placer_ids=(0, 3), ), @@ -141,6 +155,7 @@ functional_groups=[stk.IodoFactory()], ), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(0, 1, 2, 3), ), diff --git a/tests/molecular/molecules/building_block/fixtures/init_from_file.py b/tests/molecular/molecules/building_block/fixtures/init_from_file.py index 175cd0d3b..606d0be86 100644 --- a/tests/molecular/molecules/building_block/fixtures/init_from_file.py +++ b/tests/molecular/molecules/building_block/fixtures/init_from_file.py @@ -43,6 +43,9 @@ class InitFromFileData: The ids of *placer* atoms the initialized building block should have. + known_repr : str + The representation of the building block. + """ def __init__( @@ -53,6 +56,7 @@ def __init__( case_data_functional_groups, case_data_core_atom_ids, case_data_placer_ids, + known_repr, ): """ Initialize a :class:`.InitFromData` instance. @@ -83,6 +87,9 @@ def __init__( The ids of *placer* atoms the initialized building block should have. + known_repr : str + The representation of the building block. + """ self.building_block = building_block @@ -91,6 +98,7 @@ def __init__( self.case_data_functional_groups = case_data_functional_groups self.case_data_core_atom_ids = case_data_core_atom_ids self.case_data_placer_ids = case_data_placer_ids + self.known_repr = known_repr @pytest.fixture( @@ -103,6 +111,7 @@ def __init__( case_data_functional_groups=(), case_data_core_atom_ids=(0, 1, 2, 3), case_data_placer_ids=(0, 1, 2, 3), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", ), lambda: InitFromFileData( building_block=stk.BuildingBlock("Br[C+2][C+2]Br"), @@ -124,6 +133,12 @@ def __init__( ), case_data_core_atom_ids=(1, 2), case_data_placer_ids=(1, 2), + known_repr=( + "BuildingBlock('Br[C+2][C+2]Br', (Bromo(Br(0), C(1, charge=2)," + " bonders=(C(1, charge=2),), deleters=(Br(0),)), Bromo(Br(3), " + "C(2, charge=2), bonders=(C(2, charge=2),), deleters=(Br(3),))" + "))" + ), ), lambda: InitFromFileData( building_block=stk.BuildingBlock("Br[C+2][C+2]Br"), @@ -132,6 +147,7 @@ def __init__( case_data_functional_groups=(), case_data_core_atom_ids=(0, 1, 2, 3), case_data_placer_ids=(1, 2), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", ), lambda: InitFromFileData( building_block=stk.BuildingBlock("Br[C+2][C+2]Br"), @@ -153,6 +169,12 @@ def __init__( ), case_data_core_atom_ids=(1, 2), case_data_placer_ids=(0, 3), + known_repr=( + "BuildingBlock('Br[C+2][C+2]Br', (Bromo(Br(0), C(1, charge=2)," + " bonders=(C(1, charge=2),), deleters=(Br(0),)), Bromo(Br(3), " + "C(2, charge=2), bonders=(C(2, charge=2),), deleters=(Br(3),))" + "))" + ), ), lambda: InitFromFileData( building_block=stk.BuildingBlock("Br[C+2][C+2]Br"), @@ -161,6 +183,7 @@ def __init__( case_data_functional_groups=(), case_data_core_atom_ids=(0, 1, 2, 3), case_data_placer_ids=(0, 1, 2, 3), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", ), ), ) @@ -191,4 +214,5 @@ def init_from_file(path, init_from_file_data): functional_groups=data.case_data_functional_groups, core_atom_ids=data.case_data_core_atom_ids, placer_ids=data.case_data_placer_ids, + known_repr=data.known_repr, ) diff --git a/tests/molecular/molecules/building_block/fixtures/init_from_molecule.py b/tests/molecular/molecules/building_block/fixtures/init_from_molecule.py index 6bb49d045..0d1355a20 100644 --- a/tests/molecular/molecules/building_block/fixtures/init_from_molecule.py +++ b/tests/molecular/molecules/building_block/fixtures/init_from_molecule.py @@ -12,6 +12,7 @@ molecule=stk.BuildingBlock("Br[C+2][C+2]Br"), ), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(0, 1, 2, 3), ), @@ -34,6 +35,12 @@ deleters=(stk.Br(3),), ), ), + known_repr=( + "BuildingBlock('Br[C+2][C+2]Br', (Bromo(Br(0), C(1, charge=2)," + " bonders=(C(1, charge=2),), deleters=(Br(0),)), Bromo(Br(3), " + "C(2, charge=2), bonders=(C(2, charge=2),), deleters=(Br(3),))" + "))" + ), core_atom_ids=(1, 2), placer_ids=(1, 2), ), @@ -43,6 +50,7 @@ placer_ids=(1, 2), ), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(1, 2), ), @@ -66,6 +74,12 @@ deleters=(stk.Br(3),), ), ), + known_repr=( + "BuildingBlock('Br[C+2][C+2]Br', (Bromo(Br(0), C(1, charge=2)," + " bonders=(C(1, charge=2),), deleters=(Br(0),)), Bromo(Br(3), " + "C(2, charge=2), bonders=(C(2, charge=2),), deleters=(Br(3),))" + "))" + ), core_atom_ids=(1, 2), placer_ids=(0, 3), ), @@ -75,6 +89,7 @@ functional_groups=[stk.IodoFactory()], ), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(0, 1, 2, 3), ), diff --git a/tests/molecular/molecules/building_block/fixtures/init_from_rdkit_mol.py b/tests/molecular/molecules/building_block/fixtures/init_from_rdkit_mol.py index 00ec7547e..a9d96cf27 100644 --- a/tests/molecular/molecules/building_block/fixtures/init_from_rdkit_mol.py +++ b/tests/molecular/molecules/building_block/fixtures/init_from_rdkit_mol.py @@ -19,6 +19,7 @@ def _get_rdkit_molecule() -> rdkit.Mol: molecule=_get_rdkit_molecule(), ), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(0, 1, 2, 3), ), @@ -41,6 +42,12 @@ def _get_rdkit_molecule() -> rdkit.Mol: deleters=(stk.Br(3),), ), ), + known_repr=( + "BuildingBlock('Br[C+2][C+2]Br', (Bromo(Br(0), C(1, charge=2)," + " bonders=(C(1, charge=2),), deleters=(Br(0),)), Bromo(Br(3), " + "C(2, charge=2), bonders=(C(2, charge=2),), deleters=(Br(3),))" + "))" + ), core_atom_ids=(1, 2), placer_ids=(1, 2), ), @@ -50,6 +57,7 @@ def _get_rdkit_molecule() -> rdkit.Mol: placer_ids=(1, 2), ), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(1, 2), ), @@ -73,6 +81,12 @@ def _get_rdkit_molecule() -> rdkit.Mol: deleters=(stk.Br(3),), ), ), + known_repr=( + "BuildingBlock('Br[C+2][C+2]Br', (Bromo(Br(0), C(1, charge=2)," + " bonders=(C(1, charge=2),), deleters=(Br(0),)), Bromo(Br(3), " + "C(2, charge=2), bonders=(C(2, charge=2),), deleters=(Br(3),))" + "))" + ), core_atom_ids=(1, 2), placer_ids=(0, 3), ), @@ -82,6 +96,7 @@ def _get_rdkit_molecule() -> rdkit.Mol: functional_groups=[stk.IodoFactory()], ), functional_groups=(), + known_repr="BuildingBlock('Br[C+2][C+2]Br', ())", core_atom_ids=(0, 1, 2, 3), placer_ids=(0, 1, 2, 3), ), diff --git a/tests/molecular/molecules/building_block/test_repr.py b/tests/molecular/molecules/building_block/test_repr.py new file mode 100644 index 000000000..ae8735aa5 --- /dev/null +++ b/tests/molecular/molecules/building_block/test_repr.py @@ -0,0 +1,41 @@ +def test_repr(case_data): + """ + Test :meth:`.BuildingBlock.__repr__`. + + Parameters + ---------- + case_data : :class:`.CaseData` + A test case. Holds the building block to test and the correct + functional groups. + + Returns + ------- + None : :class:`NoneType` + + """ + + _test_repr( + building_block=case_data.building_block, + known_repr=case_data.known_repr, + ) + + +def _test_repr(building_block, known_repr): + """ + Test :meth:`.BuildingBlock.get_functional_groups`. + + Parameters + ---------- + building_block : :class:`.BuildingBlock` + The building block to test. + + functional_groups : :class:`tuple` of :class:`.FunctionalGroup` + The correct functional groups. + + Returns + ------- + None : :class:`NoneType` + + """ + print(building_block.__repr__(), known_repr) + assert building_block.__repr__() == known_repr