nerdd-module 0.3.28__tar.gz → 0.3.30__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/PKG-INFO +1 -1
  2. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/cli.py +2 -2
  3. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/model/enforce_schema_step.py +4 -6
  4. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/model/simple_model.py +9 -7
  5. nerdd_module-0.3.30/nerdd_module/tests/representations.py +129 -0
  6. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/util/call_with_mappings.py +1 -1
  7. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module.egg-info/PKG-INFO +1 -1
  8. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/pyproject.toml +1 -1
  9. nerdd_module-0.3.28/nerdd_module/tests/representations.py +0 -81
  10. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/LICENSE +0 -0
  11. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/README.md +0 -0
  12. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/__init__.py +0 -0
  13. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/config/__init__.py +0 -0
  14. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/config/configuration.py +0 -0
  15. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/config/default_configuration.py +0 -0
  16. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/config/dict_configuration.py +0 -0
  17. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/config/merged_configuration.py +0 -0
  18. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/config/models.py +0 -0
  19. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/config/package_configuration.py +0 -0
  20. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/config/search_yaml_configuration.py +0 -0
  21. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/config/yaml_configuration.py +0 -0
  22. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/converters/__init__.py +0 -0
  23. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/converters/basic_type_converter.py +0 -0
  24. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/converters/converter.py +0 -0
  25. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/converters/converter_config.py +0 -0
  26. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/converters/mol_converter.py +0 -0
  27. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/converters/problem_list_converter.py +0 -0
  28. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/converters/representation_converter.py +0 -0
  29. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/converters/source_list_converter.py +0 -0
  30. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/converters/void_converter.py +0 -0
  31. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/__init__.py +0 -0
  32. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/depth_first_explorer.py +0 -0
  33. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/explorer.py +0 -0
  34. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/file_reader.py +0 -0
  35. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/gzip_reader.py +0 -0
  36. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/inchi_reader.py +0 -0
  37. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/list_reader.py +0 -0
  38. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/mol_reader.py +0 -0
  39. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/reader.py +0 -0
  40. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/reader_config.py +0 -0
  41. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/sdf_reader.py +0 -0
  42. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/smiles_reader.py +0 -0
  43. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/string_reader.py +0 -0
  44. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/tar_reader.py +0 -0
  45. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/input/zip_reader.py +0 -0
  46. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/model/__init__.py +0 -0
  47. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/model/assign_name_step.py +0 -0
  48. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/model/convert_representations_step.py +0 -0
  49. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/model/model.py +0 -0
  50. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/model/read_input_step.py +0 -0
  51. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/model/write_output_step.py +0 -0
  52. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/output/__init__.py +0 -0
  53. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/output/csv_writer.py +0 -0
  54. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/output/file_writer.py +0 -0
  55. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/output/iterator_writer.py +0 -0
  56. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/output/pandas_writer.py +0 -0
  57. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/output/record_list_writer.py +0 -0
  58. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/output/sdf_writer.py +0 -0
  59. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/output/writer.py +0 -0
  60. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/output/writer_config.py +0 -0
  61. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/polyfills/__init__.py +0 -0
  62. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/polyfills/block_logs.py +0 -0
  63. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/polyfills/files.py +0 -0
  64. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/polyfills/get_entry_points.py +0 -0
  65. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/polyfills/literal.py +0 -0
  66. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/polyfills/typed_dict.py +0 -0
  67. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/polyfills/types.py +0 -0
  68. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/polyfills/version.py +0 -0
  69. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/preprocessing/__init__.py +0 -0
  70. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/preprocessing/check_valid_smiles.py +0 -0
  71. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/preprocessing/chembl_structure_pipeline.py +0 -0
  72. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/preprocessing/filter_by_element.py +0 -0
  73. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/preprocessing/filter_by_weight.py +0 -0
  74. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/preprocessing/preprocessing_step.py +0 -0
  75. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/preprocessing/remove_stereochemistry.py +0 -0
  76. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/preprocessing/sanitize.py +0 -0
  77. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/problem.py +0 -0
  78. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/py.typed +0 -0
  79. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/steps/__init__.py +0 -0
  80. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/steps/map_step.py +0 -0
  81. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/steps/output_step.py +0 -0
  82. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/steps/step.py +0 -0
  83. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/tests/__init__.py +0 -0
  84. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/tests/checks.py +0 -0
  85. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/tests/files.py +0 -0
  86. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/tests/models/AtomicMassModel.py +0 -0
  87. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/tests/models/MolWeightModel.py +0 -0
  88. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/tests/models/__init__.py +0 -0
  89. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/tests/predictions.py +0 -0
  90. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/tests/preprocessing/DummyPreprocessingStep.py +0 -0
  91. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/tests/preprocessing/__init__.py +0 -0
  92. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/util/__init__.py +0 -0
  93. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/util/package.py +0 -0
  94. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module/version.py +0 -0
  95. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module.egg-info/SOURCES.txt +0 -0
  96. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module.egg-info/dependency_links.txt +0 -0
  97. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module.egg-info/requires.txt +0 -0
  98. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/nerdd_module.egg-info/top_level.txt +0 -0
  99. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/setup.cfg +0 -0
  100. {nerdd_module-0.3.28 → nerdd_module-0.3.30}/tests/test_features.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: nerdd-module
3
- Version: 0.3.28
3
+ Version: 0.3.30
4
4
  Summary: Base package to create NERDD modules
5
5
  Author-email: Steffen Hirte <steffen.hirte@univie.ac.at>
6
6
  Maintainer-email: Steffen Hirte <steffen.hirte@univie.ac.at>
@@ -67,8 +67,8 @@ def auto_cli(f: Callable[..., Model], *args: Any, **kwargs: Any) -> None:
67
67
 
68
68
  # compose footer with examples
69
69
  examples = []
70
- if hasattr(model, "get_config"):
71
- example_smiles = model.get_config().example_smiles
70
+ if hasattr(model, "config"):
71
+ example_smiles = model.config.example_smiles
72
72
  if example_smiles is not None:
73
73
  examples.append(example_smiles)
74
74
 
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  from typing import Iterator
3
3
 
4
- from ..config import Configuration
4
+ from ..config import Module
5
5
  from ..steps import Step
6
6
 
7
7
  __all__ = ["EnforceSchemaStep"]
@@ -10,11 +10,9 @@ logger = logging.getLogger(__name__)
10
10
 
11
11
 
12
12
  class EnforceSchemaStep(Step):
13
- def __init__(self, config: Configuration, output_format: str) -> None:
13
+ def __init__(self, config: Module, output_format: str) -> None:
14
14
  super().__init__()
15
- self._property_names = [
16
- p.name for p in config.get_dict().get_visible_properties(output_format)
17
- ]
15
+ self._property_names = [p.name for p in config.get_visible_properties(output_format)]
18
16
 
19
17
  # check that properties are unique
20
18
  if len(self._property_names) != len(set(self._property_names)):
@@ -22,7 +20,7 @@ class EnforceSchemaStep(Step):
22
20
  x for x in self._property_names if self._property_names.count(x) > 1
23
21
  }
24
22
  logger.warning(
25
- f"Duplicate properties in result_properties: " f"{', '.join(duplicate_properties)}"
23
+ f"Duplicate properties in result_properties: {', '.join(duplicate_properties)}"
26
24
  )
27
25
 
28
26
  def _run(self, source: Iterator[dict]) -> Iterator[dict]:
@@ -1,4 +1,5 @@
1
1
  from abc import abstractmethod
2
+ from functools import cached_property
2
3
  from typing import Any, Iterable, List, Optional, Tuple, Union
3
4
 
4
5
  from rdkit.Chem import Mol
@@ -61,8 +62,8 @@ class SimpleModel(Model):
61
62
  def _get_postprocessing_steps(self, output_format: Optional[str], **kwargs: Any) -> List[Step]:
62
63
  output_format = output_format or "pandas"
63
64
  return [
64
- EnforceSchemaStep(self._get_config(), output_format),
65
- ConvertRepresentationsStep(self.get_config(), output_format, **kwargs),
65
+ EnforceSchemaStep(self.config, output_format),
66
+ ConvertRepresentationsStep(self.config, output_format, **kwargs),
66
67
  WriteOutputStep(output_format, **kwargs),
67
68
  ]
68
69
 
@@ -187,23 +188,24 @@ class SimpleModel(Model):
187
188
 
188
189
  return MergedConfiguration(*configs)
189
190
 
190
- def get_config(self) -> Module:
191
+ @cached_property
192
+ def config(self) -> Module:
191
193
  return self._get_config().get_dict()
192
194
 
193
195
  def _get_batch_size(self) -> int:
194
196
  default = super()._get_batch_size()
195
- return self.get_config().batch_size or default
197
+ return self.config.batch_size or default
196
198
 
197
199
  def _get_name(self) -> str:
198
200
  default = super()._get_name()
199
- return self.get_config().name or default
201
+ return self.config.name or default
200
202
 
201
203
  def _get_description(self) -> str:
202
204
  default = super()._get_description()
203
- return self.get_config().description or default
205
+ return self.config.description or default
204
206
 
205
207
  def _get_job_parameters(self) -> List[JobParameter]:
206
- return super()._get_job_parameters() + self.get_config().job_parameters
208
+ return super()._get_job_parameters() + self.config.job_parameters
207
209
 
208
210
 
209
211
  class CustomPreprocessingStep(PreprocessingStep):
@@ -0,0 +1,129 @@
1
+ import numpy as np
2
+ from hypothesis import given as hgiven
3
+ from hypothesis import seed, settings
4
+ from hypothesis import strategies as st
5
+ from hypothesis_rdkit import mols
6
+ from pytest_bdd import given, parsers
7
+ from rdkit.Chem import MolToInchi, MolToMolBlock, MolToSmiles
8
+ from ..polyfills import BlockLogs
9
+ from rdkit.Chem.rdMolDescriptors import CalcExactMolWt
10
+ import re
11
+ from functools import reduce
12
+
13
+
14
+ @given(parsers.parse("a random seed set to {seed:d}"), target_fixture="random_seed")
15
+ def random_seed(seed):
16
+ return seed
17
+
18
+
19
+ @given(
20
+ parsers.parse("an input molecule specified by '{input}'"),
21
+ target_fixture="representations",
22
+ )
23
+ def representations_from_input(input):
24
+ return [input]
25
+
26
+
27
+ @given(
28
+ parsers.parse("the representations of the molecules in {input_type} format"),
29
+ target_fixture="representations",
30
+ )
31
+ def representations_from_molecules(molecules, input_type):
32
+ input_type = input_type.lower()
33
+
34
+ if input_type == "smiles":
35
+ converter = MolToSmiles
36
+ elif input_type == "mol_block":
37
+ converter = MolToMolBlock
38
+ elif input_type == "inchi":
39
+ converter = MolToInchi
40
+ elif input_type == "rdkit_mol":
41
+ converter = lambda mol: mol
42
+ else:
43
+ raise ValueError(f"Unknown input_type: {input_type}")
44
+
45
+ with BlockLogs():
46
+ result = [converter(mol) if mol is not None else None for mol in molecules]
47
+
48
+ return result
49
+
50
+
51
+ @given(
52
+ parsers.re(
53
+ r"a list of (?P<num>\d+) random molecules(?:, where(?P<conditions>[\s\S]*))?"
54
+ ),
55
+ target_fixture="molecules",
56
+ )
57
+ def molecules(num, conditions, random_seed=0):
58
+ num = int(num)
59
+
60
+ filters = []
61
+ maps = []
62
+
63
+ if conditions is not None:
64
+ def filter_weight(min_weight, max_weight):
65
+ min_weight = float(min_weight)
66
+ max_weight = float(max_weight)
67
+ return lambda mol: (min_weight <= CalcExactMolWt(mol) <= max_weight)
68
+
69
+ def map_to_none(num_none):
70
+ num_none = int(num_none)
71
+
72
+ # draw indices of molecules that should be set to None
73
+ indices = np.random.choice(num, num_none, replace=False)
74
+
75
+ return lambda ms: [m if i not in indices else None for i, m in enumerate(ms)]
76
+
77
+ expressions = [
78
+ # filters are functions that return True if the molecule should be kept
79
+ ("filter", r"each mol has a weight between (?P<min_weight>\d+) and (?P<max_weight>\d+)", filter_weight),
80
+ # maps are functions that modify the molecule
81
+ ("map", r"(?P<num_none>\d+) entries are None", map_to_none)
82
+ ]
83
+
84
+ conditions_list = [c for c in conditions.split("\n") if c.strip() != ""]
85
+
86
+ for condition in conditions_list:
87
+ for kind, expression, f in expressions:
88
+ # conditions might be a markdown list (starting with a star character)
89
+ expression = r"\s*(\*\s*)?" + expression + r"\s*"
90
+
91
+ match = re.match(expression, condition)
92
+ if match:
93
+ params = match.groupdict()
94
+ break
95
+
96
+ assert match is not None, f"Could not parse condition: {condition}"
97
+
98
+ if kind == "filter":
99
+ filters.append(f(**params))
100
+ elif kind == "map":
101
+ maps.append(f(**params))
102
+ else:
103
+ raise ValueError(f"Unknown kind: {kind}")
104
+
105
+ filter_func = lambda mol: all(f(mol) for f in filters)
106
+ map_func = lambda ms: reduce(lambda ms, f: f(ms), maps, ms)
107
+
108
+ result = None
109
+
110
+ # pytest-bdd and hypothesis don't play well together (yet)
111
+ # --> use this workaround to generate random molecules
112
+ @hgiven(st.lists(mols().filter(filter_func), min_size=num, max_size=num, unique_by=MolToSmiles))
113
+ @settings(max_examples=1, deadline=None)
114
+ @seed(random_seed)
115
+ def generate(ms):
116
+ nonlocal result
117
+ result = ms
118
+
119
+ generate()
120
+
121
+ # apply maps
122
+ result = map_func(result)
123
+
124
+ for m in result:
125
+ if m is None:
126
+ continue
127
+ m.SetProp("_Name", "mol")
128
+
129
+ return result
@@ -23,7 +23,7 @@ def call_with_mappings(
23
23
  # copy config
24
24
  config = config.copy()
25
25
 
26
- # we check what arguments the constructor of the writer class can take
26
+ # check what arguments the class or function can take
27
27
  spec = inspect.getfullargspec(class_or_function)
28
28
  parameter_names = [a for a in spec.args if a != "self"]
29
29
  accept_any_args = spec.varargs is not None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: nerdd-module
3
- Version: 0.3.28
3
+ Version: 0.3.30
4
4
  Summary: Base package to create NERDD modules
5
5
  Author-email: Steffen Hirte <steffen.hirte@univie.ac.at>
6
6
  Maintainer-email: Steffen Hirte <steffen.hirte@univie.ac.at>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nerdd-module"
7
- version = "0.3.28"
7
+ version = "0.3.30"
8
8
  description = "Base package to create NERDD modules"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -1,81 +0,0 @@
1
- import numpy as np
2
- from hypothesis import given as hgiven
3
- from hypothesis import seed, settings
4
- from hypothesis import strategies as st
5
- # TODO: remove "type: ignore" later
6
- from hypothesis_rdkit import mols # type: ignore
7
- from pytest_bdd import given, parsers
8
- from rdkit.Chem import MolToInchi, MolToMolBlock, MolToSmiles
9
- from ..polyfills import BlockLogs
10
-
11
-
12
- @given(parsers.parse("a random seed set to {seed:d}"), target_fixture="random_seed")
13
- def random_seed(seed):
14
- return seed
15
-
16
-
17
- @given(
18
- parsers.parse("an input molecule specified by '{input}'"),
19
- target_fixture="representations",
20
- )
21
- def representations_from_input(input):
22
- return [input]
23
-
24
-
25
- @given(
26
- parsers.parse("the representations of the molecules in {input_type} format"),
27
- target_fixture="representations",
28
- )
29
- def representations_from_molecules(molecules, input_type):
30
- input_type = input_type.lower()
31
-
32
- if input_type == "smiles":
33
- converter = MolToSmiles
34
- elif input_type == "mol_block":
35
- converter = MolToMolBlock
36
- elif input_type == "inchi":
37
- converter = MolToInchi
38
- elif input_type == "rdkit_mol":
39
- converter = lambda mol: mol
40
- else:
41
- raise ValueError(f"Unknown input_type: {input_type}")
42
-
43
- with BlockLogs():
44
- result = [converter(mol) if mol is not None else None for mol in molecules]
45
-
46
- return result
47
-
48
-
49
- @given(
50
- parsers.re(
51
- r"a list of (?P<num>\d+) random molecules(?:, where (?P<num_none>\d+) entries are None)?"
52
- ),
53
- target_fixture="molecules",
54
- )
55
- def molecules_with_none(num, num_none=None, random_seed=0):
56
- num = int(num)
57
- num_none = int(num_none) if num_none is not None else 0
58
- result = None
59
-
60
- # pytest-bdd and hypothesis don't play well together (yet)
61
- # --> use this workaround to generate random molecules
62
- @hgiven(st.lists(mols(), min_size=num, max_size=num, unique_by=MolToSmiles))
63
- @settings(max_examples=1, deadline=None)
64
- @seed(random_seed)
65
- def generate(ms):
66
- nonlocal result
67
- result = ms
68
-
69
- generate()
70
-
71
- for m in result:
72
- if m is None:
73
- continue
74
- m.SetProp("_Name", "mol")
75
-
76
- # replace random entries with None
77
- indices = np.random.choice(num, num_none, replace=False)
78
- for i in indices:
79
- result[i] = None
80
-
81
- return result
File without changes
File without changes
File without changes