optimade-maker 0.8.0__tar.gz → 0.9.0__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 (77) hide show
  1. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/.github/workflows/ci.yml +6 -6
  2. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/PKG-INFO +14 -15
  3. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/README.md +4 -2
  4. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/optimade.yaml +3 -3
  5. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/pyproject.toml +9 -11
  6. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/convert.py +3 -3
  7. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/parsers.py +50 -40
  8. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/PKG-INFO +14 -15
  9. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/SOURCES.txt +1 -1
  10. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/requires.txt +9 -15
  11. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/tests/test_convert.py +5 -0
  12. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/tests/test_serve.py +14 -4
  13. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/uv.lock +16 -24
  14. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/.github/CODEOWNERS +0 -0
  15. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/.github/dependabot.yml +0 -0
  16. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/.github/workflows/release_and_publish.yml +0 -0
  17. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/.gitignore +0 -0
  18. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/.pre-commit-config.yaml +0 -0
  19. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/LICENSE +0 -0
  20. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/.gitignore +0 -0
  21. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/.testing/first_entry.json +0 -0
  22. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/README.md +0 -0
  23. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/data.csv +0 -0
  24. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/example.aiida +0 -0
  25. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/aiida_archive/optimade.yaml +0 -0
  26. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/.gitignore +0 -0
  27. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/.testing/first_entry.json +0 -0
  28. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/optimade.yaml +0 -0
  29. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/bzipped_pymatgen/part_1.json.bz2 +0 -0
  30. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl/.testing/first_entry.json +0 -0
  31. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl/optimade.jsonl +0 -0
  32. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl/optimade.yaml +0 -0
  33. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/.gitignore +0 -0
  34. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/.testing/first_entry.json +0 -0
  35. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/example.jsonl.gz +0 -0
  36. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/direct_from_jsonl_gz/optimade.yaml +0 -0
  37. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/.gitignore +0 -0
  38. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/.testing/first_entry.json +0 -0
  39. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/optimade.yaml +0 -0
  40. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/prop1.csv +0 -0
  41. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/prop2.json +0 -0
  42. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/properties/structures.zip +0 -0
  43. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/.gitignore +0 -0
  44. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/.testing/first_entry.json +0 -0
  45. /optimade_maker-0.8.0/examples/simple_zip_of_cif/data.csv → /optimade_maker-0.9.0/examples/simple_zip_of_cif/properties.csv +0 -0
  46. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/simple_zip_of_cif/structures.zip +0 -0
  47. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/.gitignore +0 -0
  48. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/.testing/first_entry.json +0 -0
  49. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/C_1.xyz +0 -0
  50. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/H_1.xyz +0 -0
  51. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/H_2.xyz +0 -0
  52. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/data.csv +0 -0
  53. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/xyz_files_no_compression/optimade.yaml +0 -0
  54. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/.gitignore +0 -0
  55. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/.testing/first_entry.json +0 -0
  56. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/README.md +0 -0
  57. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/data.tar.gz +0 -0
  58. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/optimade.yaml +0 -0
  59. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/override_config.json +0 -0
  60. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif/structures.zip +0 -0
  61. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/.gitignore +0 -0
  62. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/.testing/first_entry.json +0 -0
  63. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/optimade.yaml +0 -0
  64. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/examples/zip_of_cif_and_xyz/structures.zip +0 -0
  65. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/setup.cfg +0 -0
  66. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/__init__.py +0 -0
  67. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/aiida_plugin/__init__.py +0 -0
  68. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/aiida_plugin/config.py +0 -0
  69. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/cli.py +0 -0
  70. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/config.py +0 -0
  71. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/logger.py +0 -0
  72. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/mongo_utils.py +0 -0
  73. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker/serve.py +0 -0
  74. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/dependency_links.txt +0 -0
  75. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/entry_points.txt +0 -0
  76. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/src/optimade_maker.egg-info/top_level.txt +0 -0
  77. {optimade_maker-0.8.0 → optimade_maker-0.9.0}/tests/test_yaml.py +0 -0
@@ -63,21 +63,21 @@ jobs:
63
63
  version: "0.8.x"
64
64
  enable-cache: true
65
65
 
66
- - name: Install latest compatible versions of immediate dependencies
66
+ - name: Install the minimum environment with testing
67
67
  run: |
68
- uv sync --locked --all-extras --dev
68
+ uv sync --locked --extra dev
69
69
 
70
70
  - name: Run tests
71
71
  run: |
72
72
  uv run pytest -vv --cov=./src/optimade_maker --cov-report=xml --cov-report=term ./tests
73
73
 
74
- - name: Reinstall environment without aiida
74
+ - name: Reinstall the full environment with all extras
75
75
  run: |
76
- uv sync --locked --extra core --extra tests
76
+ uv sync --locked --all-extras --dev
77
77
 
78
- - name: Rerun tests without aiida
78
+ - name: Rerun tests
79
79
  run: |
80
- uv run pytest -vv --cov=./src/optimade_maker --cov-report=xml --cov-report=term ./tests --ignore=./tests/aiida
80
+ uv run pytest -vv --cov=./src/optimade_maker --cov-report=xml --cov-report=term ./tests
81
81
 
82
82
  - name: Upload coverage
83
83
  uses: codecov/codecov-action@v3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: optimade-maker
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: Tools for making OPTIMADE APIs from raw structural data.
5
5
  License: MIT
6
6
  Keywords: optimade,jsonapi,materials
@@ -15,30 +15,27 @@ Classifier: Topic :: Scientific/Engineering
15
15
  Requires-Python: <3.13,>=3.10
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
- Requires-Dist: pydantic~=2.2
19
- Requires-Dist: optimade[server]~=1.4.1
20
- Requires-Dist: pymongo
18
+ Requires-Dist: pydantic<3,>=2
19
+ Requires-Dist: optimade[server]~=1.4
20
+ Requires-Dist: pymongo<5,>=4
21
21
  Requires-Dist: pyyaml~=6.0
22
22
  Requires-Dist: tqdm~=4.65
23
23
  Requires-Dist: requests~=2.31
24
- Requires-Dist: numpy<3,>=1.22
25
24
  Requires-Dist: click~=8.1
26
- Provides-Extra: ase
27
- Requires-Dist: ase~=3.22; extra == "ase"
25
+ Requires-Dist: pandas<3,>=1.5
26
+ Requires-Dist: ase~=3.22
28
27
  Provides-Extra: pymatgen
29
28
  Requires-Dist: pymatgen>=2023.9; extra == "pymatgen"
30
- Provides-Extra: pandas
31
- Requires-Dist: pandas<3,>=1.5; extra == "pandas"
32
29
  Provides-Extra: aiida
33
- Requires-Dist: aiida-core>=2.6.3; extra == "aiida"
34
- Provides-Extra: core
35
- Requires-Dist: optimade-maker[ase,pandas,pymatgen]; extra == "core"
30
+ Requires-Dist: aiida-core~=2.6; extra == "aiida"
36
31
  Provides-Extra: ingest
37
- Requires-Dist: optimade-maker[aiida,ase,pandas,pymatgen]; extra == "ingest"
32
+ Requires-Dist: optimade-maker[aiida,pymatgen]; extra == "ingest"
38
33
  Provides-Extra: tests
39
34
  Requires-Dist: pytest~=8.3; extra == "tests"
40
35
  Requires-Dist: pytest-cov~=6.0; extra == "tests"
36
+ Requires-Dist: numpy<3,>=1.22; extra == "tests"
41
37
  Provides-Extra: dev
38
+ Requires-Dist: optimade-maker[tests]; extra == "dev"
42
39
  Requires-Dist: ruff; extra == "dev"
43
40
  Requires-Dist: pre-commit; extra == "dev"
44
41
  Requires-Dist: mypy; extra == "dev"
@@ -75,6 +72,8 @@ This repository contains the src/optimade-maker Python package and the correspon
75
72
  Install with
76
73
 
77
74
  ```bash
75
+ pip install optimade-maker
76
+ # or to get all ingestion plugins (e.g. pymatgen, aiida):
78
77
  pip install optimade-maker[ingest]
79
78
  ```
80
79
 
@@ -106,8 +105,8 @@ entries:
106
105
  - file: properties.csv
107
106
  property_definitions:
108
107
  - name: energy
109
- title: Total energy per atom
110
- description: DFT total energy per atom
108
+ title: Total energy
109
+ description: DFT total energy
111
110
  unit: eV/atom
112
111
  type: float
113
112
  ```
@@ -29,6 +29,8 @@ This repository contains the src/optimade-maker Python package and the correspon
29
29
  Install with
30
30
 
31
31
  ```bash
32
+ pip install optimade-maker
33
+ # or to get all ingestion plugins (e.g. pymatgen, aiida):
32
34
  pip install optimade-maker[ingest]
33
35
  ```
34
36
 
@@ -60,8 +62,8 @@ entries:
60
62
  - file: properties.csv
61
63
  property_definitions:
62
64
  - name: energy
63
- title: Total energy per atom
64
- description: DFT total energy per atom
65
+ title: Total energy
66
+ description: DFT total energy
65
67
  unit: eV/atom
66
68
  type: float
67
69
  ```
@@ -9,10 +9,10 @@ entries:
9
9
  - cifs/*/*.cif
10
10
  # (optional) property file and definitions:
11
11
  property_paths:
12
- - file: data.csv
12
+ - file: properties.csv
13
13
  property_definitions:
14
14
  - name: energy
15
- title: Total energy per atom
16
- description: The total energy per atom as computed by DFT
15
+ title: Total energy
16
+ description: DFT total energy
17
17
  unit: eV/atom
18
18
  type: float
@@ -19,14 +19,15 @@ classifiers = [
19
19
  ]
20
20
 
21
21
  dependencies = [
22
- "pydantic~=2.2",
23
- "optimade[server]~=1.4.1",
24
- "pymongo",
22
+ "pydantic>=2,<3",
23
+ "optimade[server]~=1.4",
24
+ "pymongo>=4,<5",
25
25
  "pyyaml~=6.0",
26
26
  "tqdm~=4.65",
27
27
  "requests~=2.31",
28
- "numpy >= 1.22, < 3",
29
28
  "click~=8.1",
29
+ "pandas>=1.5,<3",
30
+ "ase~=3.22",
30
31
  ]
31
32
 
32
33
  [project.scripts]
@@ -41,14 +42,11 @@ fallback_version = "0.1.0"
41
42
  version_scheme = "post-release"
42
43
 
43
44
  [project.optional-dependencies]
44
- ase = ["ase ~= 3.22"]
45
45
  pymatgen = ["pymatgen >= 2023.9"]
46
- pandas = ["pandas >= 1.5, < 3"]
47
- aiida = ["aiida-core >= 2.6.3"]
48
- core = ["optimade-maker[ase,pymatgen,pandas]"]
49
- ingest = ["optimade-maker[ase,pymatgen,pandas,aiida]"]
50
- tests = ["pytest~=8.3", "pytest-cov~=6.0"]
51
- dev = ["ruff", "pre-commit", "mypy"]
46
+ aiida = ["aiida-core ~= 2.6"]
47
+ ingest = ["optimade-maker[pymatgen,aiida]"]
48
+ tests = ["pytest~=8.3", "pytest-cov~=6.0", "numpy >= 1.22, < 3"]
49
+ dev = ["optimade-maker[tests]", "ruff", "pre-commit", "mypy"]
52
50
 
53
51
  [tool.ruff]
54
52
  target-version = "py311"
@@ -173,7 +173,7 @@ def inflate_archive(archive_path: Path, data_path: Path) -> None:
173
173
  # If .tar in filename suffixes, use `tarfile`'s compression detection
174
174
  elif ".tar" in real_path.suffixes:
175
175
  with tarfile.open(real_path, "r") as tar:
176
- tar.extractall(path=real_path.parent)
176
+ tar.extractall(path=real_path.parent, filter="data")
177
177
 
178
178
  # Otherwise assume this is a single compressed file
179
179
  # Decompress it and write it using the appropriate
@@ -306,11 +306,11 @@ def _parse_entries(
306
306
  entry_ids.append(id_root)
307
307
  break
308
308
  except Exception as exc:
309
- exceptions[parser] = exc
309
+ exceptions[parser.__name__] = exc
310
310
  continue
311
311
  else:
312
312
  raise RuntimeError(
313
- f"None of the provided parsers {ENTRY_PARSERS[entry_type]} could parse {_path}. Errors: {exceptions}"
313
+ f"None of the provided parsers could parse {_path}. Errors: {exceptions}"
314
314
  )
315
315
 
316
316
  if len(set(entry_ids)) != len(entry_ids):
@@ -3,19 +3,8 @@ import warnings
3
3
  from pathlib import Path
4
4
  from typing import Any, Callable
5
5
 
6
- import numpy as np
7
-
8
- try:
9
- import ase.io
10
- import pandas
11
- import pymatgen.core
12
- import pymatgen.entries.computed_entries
13
- from pymatgen.entries.computed_entries import ComputedStructureEntry
14
- except ImportError as exc:
15
- raise ImportError(
16
- "The parsers module requires the `ingest` extra of this package to be installed."
17
- ) from exc
18
-
6
+ import ase.io
7
+ import pandas
19
8
  from optimade.adapters import Structure
20
9
  from optimade.models import DataType, EntryResource
21
10
 
@@ -71,9 +60,7 @@ def load_csv_file(
71
60
  and prop_def.name in df.columns
72
61
  ):
73
62
  # Replace NaN -> "null"
74
- df[prop_def.name] = (
75
- df[prop_def.name].fillna(np.nan).replace({np.nan: "null"})
76
- )
63
+ df[prop_def.name] = df[prop_def.name].fillna("null")
77
64
  try:
78
65
  df[prop_def.name] = df[prop_def.name].apply(
79
66
  lambda v: json.loads(v) if isinstance(v, str) else v
@@ -139,6 +126,29 @@ TYPE_MAP: dict[DataType, type] = {
139
126
  }
140
127
 
141
128
 
129
+ ENTRY_PARSERS: dict[str, list[Callable[[Path], Any]]] = {
130
+ "structures": [ase.io.read],
131
+ }
132
+
133
+
134
+ def structure_ingest_wrapper(entry, prop_defs=None, prefix=None): # type: ignore
135
+ return Structure.ingest_from(entry)
136
+
137
+
138
+ OPTIMADE_CONVERTERS: dict[
139
+ str,
140
+ list[
141
+ Callable[
142
+ [Any, list[PropertyDefinition] | None, str | None], EntryResource | dict
143
+ ]
144
+ ],
145
+ ] = {
146
+ "structures": [structure_ingest_wrapper],
147
+ }
148
+
149
+ #### Wrappers for third-party parsers and converters, such as pymatgen ####
150
+
151
+
142
152
  def wrapped_json_parser(parser):
143
153
  """This wrapper allows `from_dict` parser functions to be called
144
154
  on a single JSON file.
@@ -174,19 +184,8 @@ def wrapped_json_parser(parser):
174
184
  return _wrapped_json_parser
175
185
 
176
186
 
177
- ENTRY_PARSERS: dict[str, list[Callable[[Path], Any]]] = {
178
- "structures": [
179
- ase.io.read,
180
- wrapped_json_parser(
181
- pymatgen.entries.computed_entries.ComputedStructureEntry.from_dict
182
- ),
183
- wrapped_json_parser(pymatgen.core.Structure.from_dict),
184
- ],
185
- }
186
-
187
-
188
187
  def convert_pymatgen_computed_structure_entry(
189
- pmg_entry: ComputedStructureEntry,
188
+ pmg_entry,
190
189
  prop_defs: list[PropertyDefinition] | None = None,
191
190
  prefix: str | None = None,
192
191
  ) -> dict:
@@ -213,17 +212,28 @@ def convert_pymatgen_computed_structure_entry(
213
212
  return entry
214
213
 
215
214
 
216
- def structure_ingest_wrapper(entry, prop_defs=None, prefix=None): # type: ignore
217
- return Structure.ingest_from(entry)
215
+ def add_pymatgen_parsers():
216
+ try:
217
+ import pymatgen.core
218
+ import pymatgen.entries.computed_entries
218
219
 
220
+ ENTRY_PARSERS["structures"].extend(
221
+ [
222
+ wrapped_json_parser(
223
+ pymatgen.entries.computed_entries.ComputedStructureEntry.from_dict
224
+ ),
225
+ wrapped_json_parser(pymatgen.core.Structure.from_dict),
226
+ ]
227
+ )
219
228
 
220
- OPTIMADE_CONVERTERS: dict[
221
- str,
222
- list[
223
- Callable[
224
- [Any, list[PropertyDefinition] | None, str | None], EntryResource | dict
225
- ]
226
- ],
227
- ] = {
228
- "structures": [structure_ingest_wrapper, convert_pymatgen_computed_structure_entry],
229
- }
229
+ OPTIMADE_CONVERTERS["structures"].append(
230
+ convert_pymatgen_computed_structure_entry
231
+ )
232
+ except ImportError:
233
+ warnings.warn(
234
+ "pymatgen is not installed, so corresponding parsers and converters will not be available. "
235
+ "To use these, install the 'pymatgen' extra."
236
+ )
237
+
238
+
239
+ add_pymatgen_parsers()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: optimade-maker
3
- Version: 0.8.0
3
+ Version: 0.9.0
4
4
  Summary: Tools for making OPTIMADE APIs from raw structural data.
5
5
  License: MIT
6
6
  Keywords: optimade,jsonapi,materials
@@ -15,30 +15,27 @@ Classifier: Topic :: Scientific/Engineering
15
15
  Requires-Python: <3.13,>=3.10
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
- Requires-Dist: pydantic~=2.2
19
- Requires-Dist: optimade[server]~=1.4.1
20
- Requires-Dist: pymongo
18
+ Requires-Dist: pydantic<3,>=2
19
+ Requires-Dist: optimade[server]~=1.4
20
+ Requires-Dist: pymongo<5,>=4
21
21
  Requires-Dist: pyyaml~=6.0
22
22
  Requires-Dist: tqdm~=4.65
23
23
  Requires-Dist: requests~=2.31
24
- Requires-Dist: numpy<3,>=1.22
25
24
  Requires-Dist: click~=8.1
26
- Provides-Extra: ase
27
- Requires-Dist: ase~=3.22; extra == "ase"
25
+ Requires-Dist: pandas<3,>=1.5
26
+ Requires-Dist: ase~=3.22
28
27
  Provides-Extra: pymatgen
29
28
  Requires-Dist: pymatgen>=2023.9; extra == "pymatgen"
30
- Provides-Extra: pandas
31
- Requires-Dist: pandas<3,>=1.5; extra == "pandas"
32
29
  Provides-Extra: aiida
33
- Requires-Dist: aiida-core>=2.6.3; extra == "aiida"
34
- Provides-Extra: core
35
- Requires-Dist: optimade-maker[ase,pandas,pymatgen]; extra == "core"
30
+ Requires-Dist: aiida-core~=2.6; extra == "aiida"
36
31
  Provides-Extra: ingest
37
- Requires-Dist: optimade-maker[aiida,ase,pandas,pymatgen]; extra == "ingest"
32
+ Requires-Dist: optimade-maker[aiida,pymatgen]; extra == "ingest"
38
33
  Provides-Extra: tests
39
34
  Requires-Dist: pytest~=8.3; extra == "tests"
40
35
  Requires-Dist: pytest-cov~=6.0; extra == "tests"
36
+ Requires-Dist: numpy<3,>=1.22; extra == "tests"
41
37
  Provides-Extra: dev
38
+ Requires-Dist: optimade-maker[tests]; extra == "dev"
42
39
  Requires-Dist: ruff; extra == "dev"
43
40
  Requires-Dist: pre-commit; extra == "dev"
44
41
  Requires-Dist: mypy; extra == "dev"
@@ -75,6 +72,8 @@ This repository contains the src/optimade-maker Python package and the correspon
75
72
  Install with
76
73
 
77
74
  ```bash
75
+ pip install optimade-maker
76
+ # or to get all ingestion plugins (e.g. pymatgen, aiida):
78
77
  pip install optimade-maker[ingest]
79
78
  ```
80
79
 
@@ -106,8 +105,8 @@ entries:
106
105
  - file: properties.csv
107
106
  property_definitions:
108
107
  - name: energy
109
- title: Total energy per atom
110
- description: DFT total energy per atom
108
+ title: Total energy
109
+ description: DFT total energy
111
110
  unit: eV/atom
112
111
  type: float
113
112
  ```
@@ -32,8 +32,8 @@ examples/properties/prop2.json
32
32
  examples/properties/structures.zip
33
33
  examples/properties/.testing/first_entry.json
34
34
  examples/simple_zip_of_cif/.gitignore
35
- examples/simple_zip_of_cif/data.csv
36
35
  examples/simple_zip_of_cif/optimade.yaml
36
+ examples/simple_zip_of_cif/properties.csv
37
37
  examples/simple_zip_of_cif/structures.zip
38
38
  examples/simple_zip_of_cif/.testing/first_entry.json
39
39
  examples/xyz_files_no_compression/.gitignore
@@ -1,31 +1,24 @@
1
- pydantic~=2.2
2
- optimade[server]~=1.4.1
3
- pymongo
1
+ pydantic<3,>=2
2
+ optimade[server]~=1.4
3
+ pymongo<5,>=4
4
4
  pyyaml~=6.0
5
5
  tqdm~=4.65
6
6
  requests~=2.31
7
- numpy<3,>=1.22
8
7
  click~=8.1
9
-
10
- [aiida]
11
- aiida-core>=2.6.3
12
-
13
- [ase]
8
+ pandas<3,>=1.5
14
9
  ase~=3.22
15
10
 
16
- [core]
17
- optimade-maker[ase,pandas,pymatgen]
11
+ [aiida]
12
+ aiida-core~=2.6
18
13
 
19
14
  [dev]
15
+ optimade-maker[tests]
20
16
  ruff
21
17
  pre-commit
22
18
  mypy
23
19
 
24
20
  [ingest]
25
- optimade-maker[aiida,ase,pandas,pymatgen]
26
-
27
- [pandas]
28
- pandas<3,>=1.5
21
+ optimade-maker[aiida,pymatgen]
29
22
 
30
23
  [pymatgen]
31
24
  pymatgen>=2023.9
@@ -33,3 +26,4 @@ pymatgen>=2023.9
33
26
  [tests]
34
27
  pytest~=8.3
35
28
  pytest-cov~=6.0
29
+ numpy<3,>=1.22
@@ -10,6 +10,7 @@ from optimade.models import EntryInfoResource
10
10
  from optimade_maker.convert import convert_archive
11
11
 
12
12
  AIIDA_AVAILABLE = bool(importlib.util.find_spec("aiida"))
13
+ PYMATGEN_AVAILABLE = bool(importlib.util.find_spec("pymatgen"))
13
14
 
14
15
  EXAMPLE_ARCHIVES = (Path(__file__).parent.parent / "examples").glob("*")
15
16
 
@@ -28,6 +29,10 @@ def test_convert_example_archives(archive_path, tmp_path):
28
29
  pytest.skip(
29
30
  "Skipping test for AiiDA archive, as it requires AiiDA to be installed."
30
31
  )
32
+ if "pymatgen" in archive_path.name and not PYMATGEN_AVAILABLE:
33
+ pytest.skip(
34
+ "Skipping test for pymatgen archive, as it requires pymatgen to be installed."
35
+ )
31
36
  # copy example into temporary path
32
37
  tmp_path = tmp_path / archive_path.name
33
38
  shutil.copytree(archive_path, tmp_path)
@@ -1,6 +1,7 @@
1
1
  import importlib.util
2
2
  import json
3
3
  import shutil
4
+ import socket
4
5
  import subprocess
5
6
  import time
6
7
  from pathlib import Path
@@ -9,11 +10,18 @@ import pytest
9
10
  import requests
10
11
 
11
12
  AIIDA_AVAILABLE = bool(importlib.util.find_spec("aiida"))
13
+ PYMATGEN_AVAILABLE = bool(importlib.util.find_spec("pymatgen"))
12
14
 
13
15
  EXAMPLE_ARCHIVES = (Path(__file__).parent.parent / "examples").glob("*")
14
16
 
15
17
 
16
- def wait_for_server_to_start(url, retries=20, delay=1):
18
+ def _get_free_port(host: str) -> int:
19
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
20
+ s.bind((host, 0))
21
+ return s.getsockname()[1]
22
+
23
+
24
+ def wait_for_server_to_start(url, retries=10, delay=1):
17
25
  for _ in range(retries):
18
26
  try:
19
27
  response = requests.get(url)
@@ -33,6 +41,10 @@ def test_serve_example_archives(archive_path, tmp_path):
33
41
  pytest.skip(
34
42
  "Skipping test for AiiDA archive, as it requires AiiDA to be installed."
35
43
  )
44
+ if "pymatgen" in archive_path.name and not PYMATGEN_AVAILABLE:
45
+ pytest.skip(
46
+ "Skipping test for pymatgen archive, as it requires pymatgen to be installed."
47
+ )
36
48
  # copy example into temporary path
37
49
  tmp_path = tmp_path / archive_path.name
38
50
  shutil.copytree(archive_path, tmp_path)
@@ -46,11 +58,9 @@ def test_serve_example_archives(archive_path, tmp_path):
46
58
  if override_config is not None:
47
59
  custom_prefix = override_config.get("provider", {}).get("prefix")
48
60
 
49
- # use an uncommon port that hopefully is unused
50
- port = 43486
51
61
  host = "127.0.0.1"
62
+ port = _get_free_port(host)
52
63
 
53
- # use subprocess to start the api via the cli
54
64
  command = [
55
65
  "optimake",
56
66
  "serve",
@@ -1391,9 +1391,10 @@ server = [
1391
1391
  name = "optimade-maker"
1392
1392
  source = { editable = "." }
1393
1393
  dependencies = [
1394
+ { name = "ase" },
1394
1395
  { name = "click" },
1395
- { name = "numpy" },
1396
1396
  { name = "optimade", extra = ["server"] },
1397
+ { name = "pandas" },
1397
1398
  { name = "pydantic" },
1398
1399
  { name = "pymongo" },
1399
1400
  { name = "pyyaml" },
@@ -1405,51 +1406,42 @@ dependencies = [
1405
1406
  aiida = [
1406
1407
  { name = "aiida-core" },
1407
1408
  ]
1408
- ase = [
1409
- { name = "ase" },
1410
- ]
1411
- core = [
1412
- { name = "ase" },
1413
- { name = "pandas" },
1414
- { name = "pymatgen" },
1415
- ]
1416
1409
  dev = [
1417
1410
  { name = "mypy" },
1411
+ { name = "numpy" },
1418
1412
  { name = "pre-commit" },
1413
+ { name = "pytest" },
1414
+ { name = "pytest-cov" },
1419
1415
  { name = "ruff" },
1420
1416
  ]
1421
1417
  ingest = [
1422
1418
  { name = "aiida-core" },
1423
- { name = "ase" },
1424
- { name = "pandas" },
1425
1419
  { name = "pymatgen" },
1426
1420
  ]
1427
- pandas = [
1428
- { name = "pandas" },
1429
- ]
1430
1421
  pymatgen = [
1431
1422
  { name = "pymatgen" },
1432
1423
  ]
1433
1424
  tests = [
1425
+ { name = "numpy" },
1434
1426
  { name = "pytest" },
1435
1427
  { name = "pytest-cov" },
1436
1428
  ]
1437
1429
 
1438
1430
  [package.metadata]
1439
1431
  requires-dist = [
1440
- { name = "aiida-core", marker = "extra == 'aiida'", specifier = ">=2.6.3" },
1441
- { name = "ase", marker = "extra == 'ase'", specifier = "~=3.22" },
1432
+ { name = "aiida-core", marker = "extra == 'aiida'", specifier = "~=2.6" },
1433
+ { name = "ase", specifier = "~=3.22" },
1442
1434
  { name = "click", specifier = "~=8.1" },
1443
1435
  { name = "mypy", marker = "extra == 'dev'" },
1444
- { name = "numpy", specifier = ">=1.22,<3" },
1445
- { name = "optimade", extras = ["server"], specifier = "~=1.4.1" },
1446
- { name = "optimade-maker", extras = ["aiida", "ase", "pandas", "pymatgen"], marker = "extra == 'ingest'" },
1447
- { name = "optimade-maker", extras = ["ase", "pandas", "pymatgen"], marker = "extra == 'core'" },
1448
- { name = "pandas", marker = "extra == 'pandas'", specifier = ">=1.5,<3" },
1436
+ { name = "numpy", marker = "extra == 'tests'", specifier = ">=1.22,<3" },
1437
+ { name = "optimade", extras = ["server"], specifier = "~=1.4" },
1438
+ { name = "optimade-maker", extras = ["aiida", "pymatgen"], marker = "extra == 'ingest'" },
1439
+ { name = "optimade-maker", extras = ["tests"], marker = "extra == 'dev'" },
1440
+ { name = "pandas", specifier = ">=1.5,<3" },
1449
1441
  { name = "pre-commit", marker = "extra == 'dev'" },
1450
- { name = "pydantic", specifier = "~=2.2" },
1442
+ { name = "pydantic", specifier = ">=2,<3" },
1451
1443
  { name = "pymatgen", marker = "extra == 'pymatgen'", specifier = ">=2023.9" },
1452
- { name = "pymongo" },
1444
+ { name = "pymongo", specifier = ">=4,<5" },
1453
1445
  { name = "pytest", marker = "extra == 'tests'", specifier = "~=8.3" },
1454
1446
  { name = "pytest-cov", marker = "extra == 'tests'", specifier = "~=6.0" },
1455
1447
  { name = "pyyaml", specifier = "~=6.0" },
@@ -1457,7 +1449,7 @@ requires-dist = [
1457
1449
  { name = "ruff", marker = "extra == 'dev'" },
1458
1450
  { name = "tqdm", specifier = "~=4.65" },
1459
1451
  ]
1460
- provides-extras = ["ase", "pymatgen", "pandas", "aiida", "core", "ingest", "tests", "dev"]
1452
+ provides-extras = ["pymatgen", "aiida", "ingest", "tests", "dev"]
1461
1453
 
1462
1454
  [[package]]
1463
1455
  name = "orjson"
File without changes
File without changes