molify 0.2.4__tar.gz → 0.2.6__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 (59) hide show
  1. {molify-0.2.4 → molify-0.2.6}/PKG-INFO +11 -1
  2. {molify-0.2.4 → molify-0.2.6}/README.md +9 -0
  3. {molify-0.2.4 → molify-0.2.6}/docs/source/index.rst +9 -0
  4. {molify-0.2.4 → molify-0.2.6}/pyproject.toml +4 -0
  5. molify-0.2.6/src/molify/__main__.py +6 -0
  6. {molify-0.2.4 → molify-0.2.6}/src/molify/_version.py +2 -2
  7. molify-0.2.6/src/molify/cli.py +97 -0
  8. {molify-0.2.4 → molify-0.2.6}/src/molify/compress.py +1 -1
  9. molify-0.2.6/tests/test_cli.py +70 -0
  10. {molify-0.2.4 → molify-0.2.6}/uv.lock +98 -29
  11. {molify-0.2.4 → molify-0.2.6}/.github/workflows/build-wheels.yaml +0 -0
  12. {molify-0.2.4 → molify-0.2.6}/.github/workflows/pages.yaml +0 -0
  13. {molify-0.2.4 → molify-0.2.6}/.github/workflows/pytest.yaml +0 -0
  14. {molify-0.2.4 → molify-0.2.6}/.gitignore +0 -0
  15. {molify-0.2.4 → molify-0.2.6}/.pre-commit-config.yaml +0 -0
  16. {molify-0.2.4 → molify-0.2.6}/.python-version +0 -0
  17. {molify-0.2.4 → molify-0.2.6}/CITATION.cff +0 -0
  18. {molify-0.2.4 → molify-0.2.6}/CONTRIBUTING.md +0 -0
  19. {molify-0.2.4 → molify-0.2.6}/LICENSE +0 -0
  20. {molify-0.2.4 → molify-0.2.6}/docs/Makefile +0 -0
  21. {molify-0.2.4 → molify-0.2.6}/docs/make.bat +0 -0
  22. {molify-0.2.4 → molify-0.2.6}/docs/source/ase_tools.ipynb +0 -0
  23. {molify-0.2.4 → molify-0.2.6}/docs/source/atom_selection.ipynb +0 -0
  24. {molify-0.2.4 → molify-0.2.6}/docs/source/conf.py +0 -0
  25. {molify-0.2.4 → molify-0.2.6}/docs/source/modules.rst +0 -0
  26. {molify-0.2.4 → molify-0.2.6}/docs/source/networkx_tools.ipynb +0 -0
  27. {molify-0.2.4 → molify-0.2.6}/docs/source/packmol_tools.ipynb +0 -0
  28. {molify-0.2.4 → molify-0.2.6}/docs/source/rdkit_tools.ipynb +0 -0
  29. {molify-0.2.4 → molify-0.2.6}/paper/.gitignore +0 -0
  30. {molify-0.2.4 → molify-0.2.6}/paper/bibliography.bib +0 -0
  31. {molify-0.2.4 → molify-0.2.6}/paper/build.sh +0 -0
  32. {molify-0.2.4 → molify-0.2.6}/paper/paper.md +0 -0
  33. {molify-0.2.4 → molify-0.2.6}/paper/zndraw_rdkit.svg +0 -0
  34. {molify-0.2.4 → molify-0.2.6}/src/molify/__init__.py +0 -0
  35. {molify-0.2.4 → molify-0.2.6}/src/molify/ase2x.py +0 -0
  36. {molify-0.2.4 → molify-0.2.6}/src/molify/bond_order.py +0 -0
  37. {molify-0.2.4 → molify-0.2.6}/src/molify/com.py +0 -0
  38. {molify-0.2.4 → molify-0.2.6}/src/molify/constants.py +0 -0
  39. {molify-0.2.4 → molify-0.2.6}/src/molify/networkx2x.py +0 -0
  40. {molify-0.2.4 → molify-0.2.6}/src/molify/pack.py +0 -0
  41. {molify-0.2.4 → molify-0.2.6}/src/molify/rdkit2x.py +0 -0
  42. {molify-0.2.4 → molify-0.2.6}/src/molify/smiles2x.py +0 -0
  43. {molify-0.2.4 → molify-0.2.6}/src/molify/substructure.py +0 -0
  44. {molify-0.2.4 → molify-0.2.6}/src/molify/utils.py +0 -0
  45. {molify-0.2.4 → molify-0.2.6}/tests/conftest.py +0 -0
  46. {molify-0.2.4 → molify-0.2.6}/tests/data/ec_emc.xyz +0 -0
  47. {molify-0.2.4 → molify-0.2.6}/tests/integration/test_ase2x.py +0 -0
  48. {molify-0.2.4 → molify-0.2.6}/tests/integration/test_networkx2x.py +0 -0
  49. {molify-0.2.4 → molify-0.2.6}/tests/integration/test_rdkit2x.py +0 -0
  50. {molify-0.2.4 → molify-0.2.6}/tests/test_com.py +0 -0
  51. {molify-0.2.4 → molify-0.2.6}/tests/test_compress.py +0 -0
  52. {molify-0.2.4 → molify-0.2.6}/tests/test_connectivity.py +0 -0
  53. {molify-0.2.4 → molify-0.2.6}/tests/test_edgecases.py +0 -0
  54. {molify-0.2.4 → molify-0.2.6}/tests/test_examples.py +0 -0
  55. {molify-0.2.4 → molify-0.2.6}/tests/test_rdkit2ase.py +0 -0
  56. {molify-0.2.4 → molify-0.2.6}/tests/test_smiles2conformers.py +0 -0
  57. {molify-0.2.4 → molify-0.2.6}/tests/test_solvate.py +0 -0
  58. {molify-0.2.4 → molify-0.2.6}/tests/test_substructure.py +0 -0
  59. {molify-0.2.4 → molify-0.2.6}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: molify
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Molecular Structure Interface with RDKit, ASE, Packmol and NetworkX
5
5
  Project-URL: Repository, https://github.com/zincware/molify
6
6
  Project-URL: Releases, https://github.com/zincware/molify/releases
@@ -15,6 +15,7 @@ Requires-Dist: matplotlib>=3.10.1
15
15
  Requires-Dist: networkx>=3.4.2
16
16
  Requires-Dist: packmol>=21.1.2
17
17
  Requires-Dist: rdkit>=2024
18
+ Requires-Dist: typer>=0.27.1
18
19
  Provides-Extra: vesin
19
20
  Requires-Dist: vesin>=0.3.7; extra == 'vesin'
20
21
  Description-Content-Type: text/markdown
@@ -58,6 +59,15 @@ print(atoms)
58
59
  >>> Atoms(symbols='OH2', pbc=False)
59
60
  ```
60
61
 
62
+ ## Command Line Interface
63
+
64
+ Commands mirror the molify functions and write to standard output. `--format`
65
+ takes any ASE format name or extension, defaulting to extxyz.
66
+
67
+ ```bash
68
+ molify smiles2atoms CCO > etoh.xyz
69
+ ```
70
+
61
71
  ## Packmol Interface
62
72
 
63
73
  Given the molecular units, you can build periodic boxes with a given density
@@ -37,6 +37,15 @@ print(atoms)
37
37
  >>> Atoms(symbols='OH2', pbc=False)
38
38
  ```
39
39
 
40
+ ## Command Line Interface
41
+
42
+ Commands mirror the molify functions and write to standard output. `--format`
43
+ takes any ASE format name or extension, defaulting to extxyz.
44
+
45
+ ```bash
46
+ molify smiles2atoms CCO > etoh.xyz
47
+ ```
48
+
40
49
  ## Packmol Interface
41
50
 
42
51
  Given the molecular units, you can build periodic boxes with a given density
@@ -100,6 +100,15 @@ The networkx.Graph representation can be obtained from either RDKit or ASE objec
100
100
  nh3_graph = molify.ase2networkx(nh3_atoms)
101
101
 
102
102
 
103
+ **Command Line Interface**
104
+
105
+ Commands mirror the molify functions and write to standard output. ``--format``
106
+ takes any ASE format name or extension, defaulting to extxyz.
107
+
108
+ .. code-block:: console
109
+
110
+ $ molify smiles2atoms CCO > etoh.xyz
111
+
103
112
  Advanced Features
104
113
  -----------------
105
114
 
@@ -14,6 +14,7 @@ dependencies = [
14
14
  "networkx>=3.4.2",
15
15
  "packmol>=21.1.2",
16
16
  "rdkit>=2024",
17
+ "typer>=0.27.1",
17
18
  ]
18
19
 
19
20
  [dependency-groups]
@@ -32,6 +33,9 @@ docs = [
32
33
  "sphinxcontrib-mermaid>=1.0.0",
33
34
  ]
34
35
 
36
+ [project.scripts]
37
+ molify = "molify.cli:app"
38
+
35
39
  [project.optional-dependencies]
36
40
 
37
41
  vesin = [
@@ -0,0 +1,6 @@
1
+ """Entry point for ``python -m molify``."""
2
+
3
+ from molify.cli import app
4
+
5
+ if __name__ == "__main__":
6
+ app()
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.2.4'
22
- __version_tuple__ = version_tuple = (0, 2, 4)
21
+ __version__ = version = '0.2.6'
22
+ __version_tuple__ = version_tuple = (0, 2, 6)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -0,0 +1,97 @@
1
+ """Command line interface for molify."""
2
+
3
+ import io
4
+ import sys
5
+ from typing import Annotated
6
+
7
+ import ase.io
8
+ import typer
9
+ from ase.io.formats import extension2format
10
+
11
+ from molify import __version__
12
+ from molify import smiles2atoms as _smiles2atoms
13
+
14
+ app = typer.Typer(
15
+ no_args_is_help=True,
16
+ add_completion=False,
17
+ pretty_exceptions_show_locals=False,
18
+ )
19
+
20
+
21
+ def _resolve_format(value: str) -> str:
22
+ """Map a format name or file extension onto an ASE format name.
23
+
24
+ Extensions resolve first, so ``XYZ`` selects ASE's ``extxyz`` writer, which
25
+ keeps the cell and the ``atoms.info`` payload such as the SMILES string and
26
+ the connectivity.
27
+
28
+ Parameters
29
+ ----------
30
+ value : str
31
+ Format name or file extension, in any capitalisation.
32
+
33
+ Returns
34
+ -------
35
+ str
36
+ The format name passed on to :func:`ase.io.write`.
37
+ """
38
+ key = value.strip().lower()
39
+ fmt = extension2format.get(key)
40
+ return fmt.name if fmt is not None else key
41
+
42
+
43
+ def _version(value: bool) -> None:
44
+ """Print the molify version and exit."""
45
+ if value:
46
+ typer.echo(__version__)
47
+ raise typer.Exit
48
+
49
+
50
+ @app.callback()
51
+ def main(
52
+ version: Annotated[
53
+ bool,
54
+ typer.Option(
55
+ "--version",
56
+ callback=_version,
57
+ is_eager=True,
58
+ help="Show the molify version and exit.",
59
+ ),
60
+ ] = False,
61
+ ) -> None:
62
+ """Build molecular structures from the command line.
63
+
64
+ Each command mirrors the molify function of the same name and writes the
65
+ structure to standard output.
66
+ """
67
+
68
+
69
+ @app.command()
70
+ def smiles2atoms(
71
+ smiles: Annotated[
72
+ str, typer.Argument(help="SMILES string of the molecule, such as 'CCO'.")
73
+ ],
74
+ fmt: Annotated[
75
+ str,
76
+ typer.Option(
77
+ "--format",
78
+ "-f",
79
+ help=(
80
+ "Output format, given as an ASE format name or file extension."
81
+ " 'XYZ' selects extxyz, which keeps the SMILES string and the"
82
+ " connectivity."
83
+ ),
84
+ ),
85
+ ] = "extxyz",
86
+ seed: Annotated[
87
+ int, typer.Option(help="Random seed for conformer generation.")
88
+ ] = 42,
89
+ ) -> None:
90
+ """Convert a SMILES string into a single 3D structure on standard output.
91
+
92
+ Example: molify smiles2atoms CCO --format XYZ > etoh.xyz
93
+ """
94
+ atoms = _smiles2atoms(smiles, seed=seed)
95
+ with io.StringIO() as handle:
96
+ ase.io.write(handle, atoms, format=_resolve_format(fmt))
97
+ sys.stdout.write(handle.getvalue())
@@ -18,7 +18,7 @@ def compress(
18
18
  atoms : ase.Atoms
19
19
  The Atoms object to compress.
20
20
  density : float
21
- The target density in g/cm^3.
21
+ The target density in kg/m^3.
22
22
  freeze_molecules : bool
23
23
  If True, freeze the internal degrees of freedom of the molecules
24
24
  during compression, to prevent bond compression.
@@ -0,0 +1,70 @@
1
+ import io
2
+
3
+ import ase.io
4
+ import pytest
5
+ from typer.testing import CliRunner
6
+
7
+ from molify import __version__
8
+ from molify.cli import app
9
+
10
+ runner = CliRunner()
11
+
12
+
13
+ def read_output(result) -> ase.Atoms:
14
+ """Read the structure the CLI wrote to standard output."""
15
+ return ase.io.read(io.StringIO(result.output), format="extxyz")
16
+
17
+
18
+ def test_version():
19
+ result = runner.invoke(app, ["--version"])
20
+ assert result.exit_code == 0
21
+ assert result.output.strip() == __version__
22
+
23
+
24
+ def test_no_args_shows_help():
25
+ result = runner.invoke(app, [])
26
+ assert "smiles2atoms" in result.output
27
+
28
+
29
+ @pytest.mark.parametrize("fmt", ["XYZ", "xyz", "extxyz"])
30
+ def test_smiles2atoms_format_aliases(fmt):
31
+ result = runner.invoke(app, ["smiles2atoms", "CCO", "--format", fmt])
32
+ assert result.exit_code == 0
33
+
34
+ lines = result.output.strip().split("\n")
35
+ assert lines[0] == "9"
36
+ assert "smiles=CCO" in lines[1]
37
+ assert "connectivity=" in lines[1]
38
+
39
+
40
+ def test_smiles2atoms_defaults_to_extxyz():
41
+ result = runner.invoke(app, ["smiles2atoms", "CCO"])
42
+ assert result.exit_code == 0
43
+
44
+ atoms = read_output(result)
45
+ assert atoms.get_chemical_formula() == "C2H6O"
46
+ assert atoms.info["smiles"] == "CCO"
47
+ assert len(atoms.info["connectivity"]) == 8
48
+
49
+
50
+ def test_smiles2atoms_pdb():
51
+ result = runner.invoke(app, ["smiles2atoms", "CCO", "-f", "pdb"])
52
+ assert result.exit_code == 0
53
+ assert result.output.startswith("MODEL")
54
+ assert ase.io.read(io.StringIO(result.output), format="proteindatabank")
55
+
56
+
57
+ def test_smiles2atoms_seed_changes_positions():
58
+ positions = [
59
+ read_output(
60
+ runner.invoke(app, ["smiles2atoms", "CCO", "--seed", str(seed)])
61
+ ).get_positions()
62
+ for seed in (42, 1234)
63
+ ]
64
+ assert not (positions[0] == positions[1]).all()
65
+
66
+
67
+ @pytest.mark.parametrize("fmt", ["zzz", "cif"])
68
+ def test_smiles2atoms_ase_rejects_format(fmt):
69
+ result = runner.invoke(app, ["smiles2atoms", "CCO", "-f", fmt])
70
+ assert result.exit_code != 0
@@ -27,6 +27,15 @@ wheels = [
27
27
  { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" },
28
28
  ]
29
29
 
30
+ [[package]]
31
+ name = "annotated-doc"
32
+ version = "0.0.5"
33
+ source = { registry = "https://pypi.org/simple" }
34
+ sdist = { url = "https://files.pythonhosted.org/packages/5a/8e/38aa427ed5402449e226975b649c5dc73ccadfefeb95e6aecb8f8ea4b6b6/annotated_doc-0.0.5.tar.gz", hash = "sha256:c7e58ce09192557605d8bbd92836d7e1d520ac9580096042c0bfd197efacf1bb", size = 10758, upload-time = "2026-07-28T13:50:58.129Z" }
35
+ wheels = [
36
+ { url = "https://files.pythonhosted.org/packages/3e/30/e900b21425a860e195f32e37657aa1f7c7f2b1bfb26f03ca209b90933c06/annotated_doc-0.0.5-py3-none-any.whl", hash = "sha256:117bac03a25ede5df5440e855b32d556049ca169ead221505badf432fed4b101", size = 5302, upload-time = "2026-07-28T13:50:57.239Z" },
37
+ ]
38
+
30
39
  [[package]]
31
40
  name = "appnope"
32
41
  version = "0.1.4"
@@ -123,7 +132,7 @@ name = "cffi"
123
132
  version = "2.0.0"
124
133
  source = { registry = "https://pypi.org/simple" }
125
134
  dependencies = [
126
- { name = "pycparser", marker = "implementation_name != 'PyPy'" },
135
+ { name = "pycparser" },
127
136
  ]
128
137
  sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
129
138
  wheels = [
@@ -315,7 +324,7 @@ resolution-markers = [
315
324
  "python_full_version < '3.11'",
316
325
  ]
317
326
  dependencies = [
318
- { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
327
+ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } },
319
328
  ]
320
329
  sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" }
321
330
  wheels = [
@@ -385,7 +394,7 @@ resolution-markers = [
385
394
  "python_full_version >= '3.11'",
386
395
  ]
387
396
  dependencies = [
388
- { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
397
+ { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" } },
389
398
  ]
390
399
  sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" }
391
400
  wheels = [
@@ -636,7 +645,7 @@ name = "exceptiongroup"
636
645
  version = "1.3.0"
637
646
  source = { registry = "https://pypi.org/simple" }
638
647
  dependencies = [
639
- { name = "typing-extensions", marker = "python_full_version < '3.11'" },
648
+ { name = "typing-extensions" },
640
649
  ]
641
650
  sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" }
642
651
  wheels = [
@@ -794,17 +803,17 @@ resolution-markers = [
794
803
  "python_full_version < '3.11'",
795
804
  ]
796
805
  dependencies = [
797
- { name = "colorama", marker = "python_full_version < '3.11' and sys_platform == 'win32'" },
798
- { name = "decorator", marker = "python_full_version < '3.11'" },
799
- { name = "exceptiongroup", marker = "python_full_version < '3.11'" },
800
- { name = "jedi", marker = "python_full_version < '3.11'" },
801
- { name = "matplotlib-inline", marker = "python_full_version < '3.11'" },
802
- { name = "pexpect", marker = "python_full_version < '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" },
803
- { name = "prompt-toolkit", marker = "python_full_version < '3.11'" },
804
- { name = "pygments", marker = "python_full_version < '3.11'" },
805
- { name = "stack-data", marker = "python_full_version < '3.11'" },
806
- { name = "traitlets", marker = "python_full_version < '3.11'" },
807
- { name = "typing-extensions", marker = "python_full_version < '3.11'" },
806
+ { name = "colorama", marker = "sys_platform == 'win32'" },
807
+ { name = "decorator" },
808
+ { name = "exceptiongroup" },
809
+ { name = "jedi" },
810
+ { name = "matplotlib-inline" },
811
+ { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
812
+ { name = "prompt-toolkit" },
813
+ { name = "pygments" },
814
+ { name = "stack-data" },
815
+ { name = "traitlets" },
816
+ { name = "typing-extensions" },
808
817
  ]
809
818
  sdist = { url = "https://files.pythonhosted.org/packages/85/31/10ac88f3357fc276dc8a64e8880c82e80e7459326ae1d0a211b40abf6665/ipython-8.37.0.tar.gz", hash = "sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216", size = 5606088, upload-time = "2025-05-31T16:39:09.613Z" }
810
819
  wheels = [
@@ -819,17 +828,17 @@ resolution-markers = [
819
828
  "python_full_version >= '3.11'",
820
829
  ]
821
830
  dependencies = [
822
- { name = "colorama", marker = "python_full_version >= '3.11' and sys_platform == 'win32'" },
823
- { name = "decorator", marker = "python_full_version >= '3.11'" },
824
- { name = "ipython-pygments-lexers", marker = "python_full_version >= '3.11'" },
825
- { name = "jedi", marker = "python_full_version >= '3.11'" },
826
- { name = "matplotlib-inline", marker = "python_full_version >= '3.11'" },
827
- { name = "pexpect", marker = "python_full_version >= '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" },
828
- { name = "prompt-toolkit", marker = "python_full_version >= '3.11'" },
829
- { name = "pygments", marker = "python_full_version >= '3.11'" },
830
- { name = "stack-data", marker = "python_full_version >= '3.11'" },
831
- { name = "traitlets", marker = "python_full_version >= '3.11'" },
832
- { name = "typing-extensions", marker = "python_full_version == '3.11.*'" },
831
+ { name = "colorama", marker = "sys_platform == 'win32'" },
832
+ { name = "decorator" },
833
+ { name = "ipython-pygments-lexers" },
834
+ { name = "jedi" },
835
+ { name = "matplotlib-inline" },
836
+ { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" },
837
+ { name = "prompt-toolkit" },
838
+ { name = "pygments" },
839
+ { name = "stack-data" },
840
+ { name = "traitlets" },
841
+ { name = "typing-extensions", marker = "python_full_version < '3.12'" },
833
842
  ]
834
843
  sdist = { url = "https://files.pythonhosted.org/packages/29/e6/48c74d54039241a456add616464ea28c6ebf782e4110d419411b83dae06f/ipython-9.7.0.tar.gz", hash = "sha256:5f6de88c905a566c6a9d6c400a8fed54a638e1f7543d17aae2551133216b1e4e", size = 4422115, upload-time = "2025-11-05T12:18:54.646Z" }
835
844
  wheels = [
@@ -841,7 +850,7 @@ name = "ipython-pygments-lexers"
841
850
  version = "1.1.1"
842
851
  source = { registry = "https://pypi.org/simple" }
843
852
  dependencies = [
844
- { name = "pygments", marker = "python_full_version >= '3.11'" },
853
+ { name = "pygments" },
845
854
  ]
846
855
  sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" }
847
856
  wheels = [
@@ -1045,6 +1054,18 @@ wheels = [
1045
1054
  { url = "https://files.pythonhosted.org/packages/da/e9/0d4add7873a73e462aeb45c036a2dead2562b825aa46ba326727b3f31016/kiwisolver-1.4.9-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:fb940820c63a9590d31d88b815e7a3aa5915cad3ce735ab45f0c730b39547de1", size = 73929, upload-time = "2025-08-10T21:27:48.236Z" },
1046
1055
  ]
1047
1056
 
1057
+ [[package]]
1058
+ name = "markdown-it-py"
1059
+ version = "4.2.0"
1060
+ source = { registry = "https://pypi.org/simple" }
1061
+ dependencies = [
1062
+ { name = "mdurl" },
1063
+ ]
1064
+ sdist = { url = "https://files.pythonhosted.org/packages/06/ff/7841249c247aa650a76b9ee4bbaeae59370dc8bfd2f6c01f3630c35eb134/markdown_it_py-4.2.0.tar.gz", hash = "sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49", size = 82454, upload-time = "2026-05-07T12:08:28.36Z" }
1065
+ wheels = [
1066
+ { url = "https://files.pythonhosted.org/packages/b3/81/4da04ced5a082363ecfa159c010d200ecbd959ae410c10c0264a38cac0f5/markdown_it_py-4.2.0-py3-none-any.whl", hash = "sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a", size = 91687, upload-time = "2026-05-07T12:08:27.182Z" },
1067
+ ]
1068
+
1048
1069
  [[package]]
1049
1070
  name = "markupsafe"
1050
1071
  version = "3.0.3"
@@ -1217,6 +1238,15 @@ wheels = [
1217
1238
  { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" },
1218
1239
  ]
1219
1240
 
1241
+ [[package]]
1242
+ name = "mdurl"
1243
+ version = "0.1.2"
1244
+ source = { registry = "https://pypi.org/simple" }
1245
+ sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
1246
+ wheels = [
1247
+ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
1248
+ ]
1249
+
1220
1250
  [[package]]
1221
1251
  name = "mistune"
1222
1252
  version = "3.1.4"
@@ -1239,6 +1269,7 @@ dependencies = [
1239
1269
  { name = "networkx", version = "3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
1240
1270
  { name = "packmol" },
1241
1271
  { name = "rdkit" },
1272
+ { name = "typer" },
1242
1273
  ]
1243
1274
 
1244
1275
  [package.optional-dependencies]
@@ -1270,6 +1301,7 @@ requires-dist = [
1270
1301
  { name = "networkx", specifier = ">=3.4.2" },
1271
1302
  { name = "packmol", specifier = ">=21.1.2" },
1272
1303
  { name = "rdkit", specifier = ">=2024" },
1304
+ { name = "typer", specifier = ">=0.27.1" },
1273
1305
  { name = "vesin", marker = "extra == 'vesin'", specifier = ">=0.3.7" },
1274
1306
  ]
1275
1307
  provides-extras = ["vesin"]
@@ -2091,6 +2123,19 @@ wheels = [
2091
2123
  { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
2092
2124
  ]
2093
2125
 
2126
+ [[package]]
2127
+ name = "rich"
2128
+ version = "15.0.0"
2129
+ source = { registry = "https://pypi.org/simple" }
2130
+ dependencies = [
2131
+ { name = "markdown-it-py" },
2132
+ { name = "pygments" },
2133
+ ]
2134
+ sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" }
2135
+ wheels = [
2136
+ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" },
2137
+ ]
2138
+
2094
2139
  [[package]]
2095
2140
  name = "rpds-py"
2096
2141
  version = "0.29.0"
@@ -2247,7 +2292,7 @@ resolution-markers = [
2247
2292
  "python_full_version < '3.11'",
2248
2293
  ]
2249
2294
  dependencies = [
2250
- { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
2295
+ { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } },
2251
2296
  ]
2252
2297
  sdist = { url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", size = 59419214, upload-time = "2025-05-08T16:13:05.955Z" }
2253
2298
  wheels = [
@@ -2306,7 +2351,7 @@ resolution-markers = [
2306
2351
  "python_full_version >= '3.11'",
2307
2352
  ]
2308
2353
  dependencies = [
2309
- { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
2354
+ { name = "numpy", version = "2.3.5", source = { registry = "https://pypi.org/simple" } },
2310
2355
  ]
2311
2356
  sdist = { url = "https://files.pythonhosted.org/packages/0a/ca/d8ace4f98322d01abcd52d381134344bf7b431eba7ed8b42bdea5a3c2ac9/scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb", size = 30597883, upload-time = "2025-10-28T17:38:54.068Z" }
2312
2357
  wheels = [
@@ -2372,6 +2417,15 @@ wheels = [
2372
2417
  { url = "https://files.pythonhosted.org/packages/64/47/a494741db7280eae6dc033510c319e34d42dd41b7ac0c7ead39354d1a2b5/scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562", size = 26464127, upload-time = "2025-10-28T17:38:11.34Z" },
2373
2418
  ]
2374
2419
 
2420
+ [[package]]
2421
+ name = "shellingham"
2422
+ version = "1.5.4"
2423
+ source = { registry = "https://pypi.org/simple" }
2424
+ sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" }
2425
+ wheels = [
2426
+ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
2427
+ ]
2428
+
2375
2429
  [[package]]
2376
2430
  name = "six"
2377
2431
  version = "1.17.0"
@@ -2621,6 +2675,21 @@ wheels = [
2621
2675
  { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" },
2622
2676
  ]
2623
2677
 
2678
+ [[package]]
2679
+ name = "typer"
2680
+ version = "0.27.1"
2681
+ source = { registry = "https://pypi.org/simple" }
2682
+ dependencies = [
2683
+ { name = "annotated-doc" },
2684
+ { name = "colorama", marker = "sys_platform == 'win32'" },
2685
+ { name = "rich" },
2686
+ { name = "shellingham" },
2687
+ ]
2688
+ sdist = { url = "https://files.pythonhosted.org/packages/ae/40/4a3db7990d1f62a53182aa96eaef57aeb2886a27f90a195bc66713565d31/typer-0.27.1.tar.gz", hash = "sha256:a79bef8469a79c45498e7b814ecf8d603cc7644e9acbd9e19cac0334240b18df", size = 203994, upload-time = "2026-08-03T14:41:03.438Z" }
2689
+ wheels = [
2690
+ { url = "https://files.pythonhosted.org/packages/43/89/9518bc0c3929bee36b3a4a8e3daddd6e03f92f9961c66d4983b837160543/typer-0.27.1-py3-none-any.whl", hash = "sha256:53150287edd11baeb4e4722c8e394fcdf8181c0ae89485cba8d25c778d5edd56", size = 122874, upload-time = "2026-08-03T14:41:04.391Z" },
2691
+ ]
2692
+
2624
2693
  [[package]]
2625
2694
  name = "typing-extensions"
2626
2695
  version = "4.15.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes