rxkit 0.1.1__tar.gz → 0.1.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rxkit
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Chemical reaction and molecule SMILES canonicalization toolkit
5
5
  Author: Long
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "rxkit"
7
- version = "0.1.1"
7
+ version = "0.1.2"
8
8
  description = "Chemical reaction and molecule SMILES canonicalization toolkit"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -31,5 +31,5 @@ from .rxn_utils import (
31
31
  UNKNOWN,
32
32
  )
33
33
 
34
- __version__ = "0.1.1"
34
+ __version__ = "0.1.2"
35
35
 
@@ -538,7 +538,7 @@ def is_valid_reaction(rxn, rxn_type=None, allow_empty_products=False, is_strict=
538
538
  False
539
539
  """
540
540
  # Local import to avoid circular import at module load time
541
- from canonicalize.mol_utils import is_valid_molecule
541
+ from .mol_utils import is_valid_molecule
542
542
 
543
543
  if not isinstance(rxn, str) or not rxn.strip():
544
544
  return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rxkit
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Chemical reaction and molecule SMILES canonicalization toolkit
5
5
  Author: Long
6
6
  License: MIT
@@ -127,16 +127,16 @@ class TestTildeStandardConversion:
127
127
  """Tests for tilde <-> standard reaction SMILES conversion."""
128
128
 
129
129
  def test_tilde_to_standard(self):
130
- from canonicalize import tilde_to_standard
130
+ from rxkit.canonicalize import tilde_to_standard
131
131
  assert tilde_to_standard("CC.O.[Na+]~[Cl-]>>CCO") == "CC.O.[Na+].[Cl-]>>CCO"
132
132
 
133
133
  def test_standard_to_tilde_naive(self):
134
134
  """``standard_to_tilde`` is a string-level rewrite: ``.`` -> ``~`` everywhere on each side."""
135
- from canonicalize import standard_to_tilde
135
+ from rxkit.canonicalize import standard_to_tilde
136
136
  assert standard_to_tilde("CC.O.[Na+].[Cl-]>>CCO") == "CC~O~[Na+]~[Cl-]>>CCO"
137
137
 
138
138
  def test_no_tilde_unchanged(self):
139
- from canonicalize import tilde_to_standard
139
+ from rxkit.canonicalize import tilde_to_standard
140
140
  assert tilde_to_standard("CC.O>>CCO") == "CC.O>>CCO"
141
141
 
142
142
 
@@ -150,7 +150,7 @@ class TestExtendedTildeConversion:
150
150
  """
151
151
 
152
152
  def test_split_smiles_and_fragment_info(self):
153
- from canonicalize import split_smiles_and_fragment_info
153
+ from rxkit.canonicalize import split_smiles_and_fragment_info
154
154
  pure, info = split_smiles_and_fragment_info(
155
155
  "CC.O.[Na+].[Cl-]>>CCO |f:2.3|"
156
156
  )
@@ -158,25 +158,25 @@ class TestExtendedTildeConversion:
158
158
  assert info == "|f:2.3|"
159
159
 
160
160
  def test_determine_fragment_groups(self):
161
- from canonicalize import determine_fragment_groups
161
+ from rxkit.canonicalize import determine_fragment_groups
162
162
  assert determine_fragment_groups("|f:2.3|") == [[2, 3]]
163
163
  assert determine_fragment_groups("|f:0.2,5.6|") == [[0, 2], [5, 6]]
164
164
  assert determine_fragment_groups("") == []
165
165
 
166
166
  def test_user_requirement_extended_to_tilde(self):
167
167
  """The exact example from the user's request."""
168
- from canonicalize import extended_to_tilde
168
+ from rxkit.canonicalize import extended_to_tilde
169
169
  src = "CC.O.[Na+].[Cl-]>>CCO |f:2.3|"
170
170
  expected = "CC.O.[Na+]~[Cl-]>>CCO"
171
171
  assert extended_to_tilde(src) == expected
172
172
 
173
173
  def test_roundtrip_tilde_to_extended(self):
174
- from canonicalize import tilde_to_extended
174
+ from rxkit.canonicalize import tilde_to_extended
175
175
  result = tilde_to_extended("CC.O.[Na+]~[Cl-]>>CCO")
176
176
  assert result == "CC.O.[Na+].[Cl-]>>CCO |f:2.3|"
177
177
 
178
178
  def test_parse_extended(self):
179
- from canonicalize import parse_extended_reaction_smiles
179
+ from rxkit.canonicalize import parse_extended_reaction_smiles
180
180
  r, a, p = parse_extended_reaction_smiles(
181
181
  "CC.O.[Na+].[Cl-]>>CCO |f:2.3|"
182
182
  )
@@ -186,7 +186,7 @@ class TestExtendedTildeConversion:
186
186
  assert p == ["CCO"]
187
187
 
188
188
  def test_parse_extended_groups_on_both_sides(self):
189
- from canonicalize import parse_extended_reaction_smiles
189
+ from rxkit.canonicalize import parse_extended_reaction_smiles
190
190
  r, a, p = parse_extended_reaction_smiles(
191
191
  "CC.O.[Na+].[Cl-]>>CCO.[Na+].[Cl-] |f:2.3,5.6|"
192
192
  )
@@ -194,7 +194,7 @@ class TestExtendedTildeConversion:
194
194
  assert p == ["CCO", "[Na+].[Cl-]"]
195
195
 
196
196
  def test_to_extended_reaction_smiles(self):
197
- from canonicalize import to_extended_reaction_smiles
197
+ from rxkit.canonicalize import to_extended_reaction_smiles
198
198
  result = to_extended_reaction_smiles(
199
199
  ["CC", "O", "[Na+].[Cl-]"], [], ["CCO"]
200
200
  )
@@ -202,19 +202,19 @@ class TestExtendedTildeConversion:
202
202
 
203
203
  def test_to_extended_no_groups_returns_standard(self):
204
204
  """If no compound has multiple fragments, the EXTENDED form is just STANDARD."""
205
- from canonicalize import to_extended_reaction_smiles
205
+ from rxkit.canonicalize import to_extended_reaction_smiles
206
206
  result = to_extended_reaction_smiles(["CC", "O"], [], ["CCO"])
207
207
  assert result == "CC.O>>CCO"
208
208
 
209
209
  def test_parse_tilde_reaction_smiles(self):
210
- from canonicalize import parse_tilde_reaction_smiles
210
+ from rxkit.canonicalize import parse_tilde_reaction_smiles
211
211
  r, a, p = parse_tilde_reaction_smiles("CC.O.[Na+]~[Cl-]>>CCO")
212
212
  assert r == ["CC", "O", "[Na+].[Cl-]"]
213
213
  assert a == []
214
214
  assert p == ["CCO"]
215
215
 
216
216
  def test_extended_to_standard_drops_fragment_info(self):
217
- from canonicalize import extended_to_standard
217
+ from rxkit.canonicalize import extended_to_standard
218
218
  assert extended_to_standard(
219
219
  "CC.O.[Na+].[Cl-]>>CCO |f:2.3|"
220
220
  ) == "CC.O.[Na+].[Cl-]>>CCO"
@@ -224,54 +224,54 @@ class TestIsValidMolecule:
224
224
  """Tests for the is_valid_molecule helper."""
225
225
 
226
226
  def test_valid_simple(self):
227
- from canonicalize import is_valid_molecule
227
+ from rxkit.canonicalize import is_valid_molecule
228
228
  assert is_valid_molecule("CCO") is True
229
229
 
230
230
  def test_valid_aromatic(self):
231
- from canonicalize import is_valid_molecule
231
+ from rxkit.canonicalize import is_valid_molecule
232
232
  assert is_valid_molecule("c1ccccc1") is True
233
233
 
234
234
  def test_valid_ionic(self):
235
- from canonicalize import is_valid_molecule
235
+ from rxkit.canonicalize import is_valid_molecule
236
236
  assert is_valid_molecule("[Na+].[Cl-]") is True
237
237
 
238
238
  def test_invalid_garbage(self):
239
- from canonicalize import is_valid_molecule
239
+ from rxkit.canonicalize import is_valid_molecule
240
240
  assert is_valid_molecule("not_a_smiles") is False
241
241
 
242
242
  def test_invalid_unbalanced_bracket(self):
243
- from canonicalize import is_valid_molecule
243
+ from rxkit.canonicalize import is_valid_molecule
244
244
  assert is_valid_molecule("C[C") is False
245
245
 
246
246
  def test_empty_invalid_by_default(self):
247
- from canonicalize import is_valid_molecule
247
+ from rxkit.canonicalize import is_valid_molecule
248
248
  assert is_valid_molecule("") is False
249
249
 
250
250
  def test_empty_allowed_when_flag_set(self):
251
- from canonicalize import is_valid_molecule
251
+ from rxkit.canonicalize import is_valid_molecule
252
252
  assert is_valid_molecule("", allow_empty=True) is True
253
253
 
254
254
  def test_none_is_invalid(self):
255
- from canonicalize import is_valid_molecule
255
+ from rxkit.canonicalize import is_valid_molecule
256
256
  assert is_valid_molecule(None) is False # type: ignore[arg-type]
257
257
 
258
258
  def test_non_string_is_invalid(self):
259
- from canonicalize import is_valid_molecule
259
+ from rxkit.canonicalize import is_valid_molecule
260
260
  assert is_valid_molecule(123) is False # type: ignore[arg-type]
261
261
 
262
262
  def test_list_all_valid(self):
263
- from canonicalize import is_valid_molecule
263
+ from rxkit.canonicalize import is_valid_molecule
264
264
  assert is_valid_molecule(["CCO", "c1ccccc1", "[Na+]"]) is True
265
265
 
266
266
  def test_list_one_invalid(self):
267
- from canonicalize import is_valid_molecule
267
+ from rxkit.canonicalize import is_valid_molecule
268
268
  assert is_valid_molecule(["CCO", "not_a_smiles"]) is False
269
269
 
270
270
  def test_list_with_empty_invalid_by_default(self):
271
- from canonicalize import is_valid_molecule
271
+ from rxkit.canonicalize import is_valid_molecule
272
272
  assert is_valid_molecule(["CCO", ""]) is False
273
273
 
274
274
  def test_list_with_empty_allowed(self):
275
- from canonicalize import is_valid_molecule
275
+ from rxkit.canonicalize import is_valid_molecule
276
276
  assert is_valid_molecule(["CCO", ""], allow_empty=True) is True
277
277
 
@@ -159,52 +159,52 @@ class TestIsValidReaction:
159
159
  """Tests for the is_valid_reaction helper."""
160
160
 
161
161
  def test_valid_standard(self):
162
- from canonicalize import is_valid_reaction
162
+ from rxkit.canonicalize import is_valid_reaction
163
163
  assert is_valid_reaction("CCO.CCO>>CCOCCO") is True
164
164
 
165
165
  def test_valid_standard_agent(self):
166
- from canonicalize import is_valid_reaction
166
+ from rxkit.canonicalize import is_valid_reaction
167
167
  assert is_valid_reaction("C=C.CC(=O)O>O>CC(=O)OC") is True
168
168
 
169
169
  def test_valid_tilde(self):
170
- from canonicalize import is_valid_reaction
170
+ from rxkit.canonicalize import is_valid_reaction
171
171
  assert is_valid_reaction("CC.O.[Na+]~[Cl-]>>CCO") is True
172
172
 
173
173
  def test_valid_extended(self):
174
- from canonicalize import is_valid_reaction
174
+ from rxkit.canonicalize import is_valid_reaction
175
175
  assert is_valid_reaction("CC.O.[Na+].[Cl-]>>CCO |f:2.3|") is True
176
176
 
177
177
  def test_invalid_garbage(self):
178
- from canonicalize import is_valid_reaction
178
+ from rxkit.canonicalize import is_valid_reaction
179
179
  assert is_valid_reaction("not_a_reaction") is False
180
180
 
181
181
  def test_invalid_garbage_fragments(self):
182
- from canonicalize import is_valid_reaction
182
+ from rxkit.canonicalize import is_valid_reaction
183
183
  assert is_valid_reaction("CCO.garbage>>CCOCCO") is False
184
184
 
185
185
  def test_empty_is_invalid(self):
186
- from canonicalize import is_valid_reaction
186
+ from rxkit.canonicalize import is_valid_reaction
187
187
  assert is_valid_reaction("") is False
188
188
  assert is_valid_reaction(" ") is False
189
189
  assert is_valid_reaction(None) is False # type: ignore[arg-type]
190
190
 
191
191
  def test_empty_products_invalid_by_default(self):
192
- from canonicalize import is_valid_reaction
192
+ from rxkit.canonicalize import is_valid_reaction
193
193
  assert is_valid_reaction("CCO>>") is False
194
194
 
195
195
  def test_empty_products_allowed_when_flag(self):
196
- from canonicalize import is_valid_reaction
196
+ from rxkit.canonicalize import is_valid_reaction
197
197
  # Empty products are allowed when the flag is explicitly set
198
198
  assert is_valid_reaction("CCO>>", allow_empty_products=True) is True
199
199
  # Same for STANDARD_agent-style templates with empty products
200
200
  assert is_valid_reaction("CCO>O>", allow_empty_products=True) is True
201
201
 
202
202
  def test_empty_reactants_invalid(self):
203
- from canonicalize import is_valid_reaction
203
+ from rxkit.canonicalize import is_valid_reaction
204
204
  assert is_valid_reaction(">>CCO") is False
205
205
 
206
206
  def test_explicit_rxn_type(self):
207
- from canonicalize import is_valid_reaction, STANDARD
207
+ from rxkit.canonicalize import is_valid_reaction, STANDARD
208
208
  # Pass an EXTENDED SMILES but tell the validator it is STANDARD.
209
209
  # The result should be False because the |f:...| marker is not a
210
210
  # valid molecule SMILES.
@@ -214,7 +214,7 @@ class TestIsValidReaction:
214
214
  assert is_valid_reaction(rxn) is True
215
215
 
216
216
  def test_too_many_sides(self):
217
- from canonicalize import is_valid_reaction
217
+ from rxkit.canonicalize import is_valid_reaction
218
218
  # 4 '>' characters yields 5 sides
219
219
  assert is_valid_reaction("CCO>CCO>CCO>CCO>CCO") is False
220
220
 
@@ -223,18 +223,18 @@ class TestIsValidReactionStrict:
223
223
  """Tests for the ``is_strict`` mode of is_valid_reaction."""
224
224
 
225
225
  def test_duplicate_in_reactants_raises(self):
226
- from canonicalize import is_valid_reaction
226
+ from rxkit.canonicalize import is_valid_reaction
227
227
  # Lenient mode: passes. Strict mode: rejects duplicate reactant.
228
228
  assert is_valid_reaction("CCO.CCO>>CCOCCO") is True
229
229
  assert is_valid_reaction("CCO.CCO>>CCOCCO", is_strict=True) is False
230
230
 
231
231
  def test_duplicate_in_products_raises(self):
232
- from canonicalize import is_valid_reaction
232
+ from rxkit.canonicalize import is_valid_reaction
233
233
  assert is_valid_reaction("CCOCCO>>CCO.CCO") is True
234
234
  assert is_valid_reaction("CCOCCO>>CCO.CCO", is_strict=True) is False
235
235
 
236
236
  def test_duplicate_in_reagents_raises(self):
237
- from canonicalize import is_valid_reaction
237
+ from rxkit.canonicalize import is_valid_reaction
238
238
  assert is_valid_reaction("CCN>c1ccccc1.c1ccccc1>CCNC(=O)c1ccccc1") is True
239
239
  assert (
240
240
  is_valid_reaction(
@@ -245,20 +245,20 @@ class TestIsValidReactionStrict:
245
245
  )
246
246
 
247
247
  def test_same_reactant_and_product_raises(self):
248
- from canonicalize import is_valid_reaction
248
+ from rxkit.canonicalize import is_valid_reaction
249
249
  # No-op reaction: same molecule on both sides.
250
250
  assert is_valid_reaction("CCO>>CCO") is True
251
251
  assert is_valid_reaction("CCO>>CCO", is_strict=True) is False
252
252
 
253
253
  def test_reactant_in_products_raises(self):
254
- from canonicalize import is_valid_reaction
254
+ from rxkit.canonicalize import is_valid_reaction
255
255
  # ``CCO`` appears as both reactant and product. Not a pure
256
256
  # solvent-only reaction, so strict mode rejects it.
257
257
  assert is_valid_reaction("CCO.CCN>>CCO.CCN") is True
258
258
  assert is_valid_reaction("CCO.CCN>>CCO.CCN", is_strict=True) is False
259
259
 
260
260
  def test_reagent_appears_in_reactants_raises(self):
261
- from canonicalize import is_valid_reaction
261
+ from rxkit.canonicalize import is_valid_reaction
262
262
  # Benzene appears as both reagent and reactant.
263
263
  assert is_valid_reaction("c1ccccc1.CC(=O)O>c1ccccc1>CC(=O)OC") is True
264
264
  assert (
@@ -270,7 +270,7 @@ class TestIsValidReactionStrict:
270
270
  )
271
271
 
272
272
  def test_solvent_all_three_sides_is_allowed(self):
273
- from canonicalize import is_valid_reaction
273
+ from rxkit.canonicalize import is_valid_reaction
274
274
  # ``CCO`` is a solvent appearing on all three sides. This is
275
275
  # the canonical "solvent-only" template and must be allowed
276
276
  # even in strict mode.
@@ -280,26 +280,26 @@ class TestIsValidReactionStrict:
280
280
  )
281
281
 
282
282
  def test_empty_fragment_raises(self):
283
- from canonicalize import is_valid_reaction
283
+ from rxkit.canonicalize import is_valid_reaction
284
284
  # Consecutive dots
285
285
  assert is_valid_reaction("CCO..CCN>>CCNCCO") is False
286
286
  assert is_valid_reaction("CCO..CCN>>CCNCCO", is_strict=True) is False
287
287
 
288
288
  def test_leading_dot_fragment_raises(self):
289
- from canonicalize import is_valid_reaction
289
+ from rxkit.canonicalize import is_valid_reaction
290
290
  # Leading dot — also an empty fragment.
291
291
  assert is_valid_reaction(".CCO>>CCO") is False
292
292
  assert is_valid_reaction(".CCO>>CCO", is_strict=True) is False
293
293
 
294
294
  def test_tilde_reaction_with_duplicate(self):
295
- from canonicalize import is_valid_reaction
295
+ from rxkit.canonicalize import is_valid_reaction
296
296
  # Tilde reaction where two fragment groups are actually the
297
297
  # same compound.
298
298
  assert is_valid_reaction("CCO~CCO>>CCOCCO") is True
299
299
  assert is_valid_reaction("CCO~CCO>>CCOCCO", is_strict=True) is False
300
300
 
301
301
  def test_extended_reaction_with_duplicate(self):
302
- from canonicalize import is_valid_reaction
302
+ from rxkit.canonicalize import is_valid_reaction
303
303
  # Same molecule in two different groups — also a duplicate.
304
304
  assert is_valid_reaction("CCO.CCO>>CCOCCO |f:0.1|") is True
305
305
  assert (
@@ -307,7 +307,7 @@ class TestIsValidReactionStrict:
307
307
  )
308
308
 
309
309
  def test_strict_passes_for_clean_reaction(self):
310
- from canonicalize import is_valid_reaction
310
+ from rxkit.canonicalize import is_valid_reaction
311
311
  # A clean, well-formed reaction should still pass in strict mode.
312
312
  assert is_valid_reaction("CCO.CCN>>CCNCCO", is_strict=True) is True
313
313
  assert (
@@ -315,7 +315,7 @@ class TestIsValidReactionStrict:
315
315
  )
316
316
 
317
317
  def test_strict_canonicalisation_isolates_different_writings(self):
318
- from canonicalize import is_valid_reaction
318
+ from rxkit.canonicalize import is_valid_reaction
319
319
  # ``CCO`` and ``OCC`` are the same molecule written differently.
320
320
  assert is_valid_reaction("CCO.OCC>>CCOCCO") is True
321
321
  assert is_valid_reaction("CCO.OCC>>CCOCCO", is_strict=True) is False
File without changes
File without changes
File without changes
File without changes