mp-api 0.46.2rc10__tar.gz → 0.46.2rc12__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 (146) hide show
  1. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/PKG-INFO +1 -1
  2. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/core/client.py +64 -15
  3. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/core/settings.py +1 -1
  4. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/materials.py +4 -1
  5. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/phonon.py +21 -12
  6. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api.egg-info/PKG-INFO +1 -1
  7. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/requirements/requirements-ubuntu-latest_py3.11.txt +7 -7
  8. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/requirements/requirements-ubuntu-latest_py3.11_extras.txt +21 -18
  9. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/requirements/requirements-ubuntu-latest_py3.12.txt +7 -7
  10. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/requirements/requirements-ubuntu-latest_py3.12_extras.txt +21 -18
  11. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/requirements/requirements-ubuntu-latest_py3.13.txt +7 -7
  12. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/requirements/requirements-ubuntu-latest_py3.13_extras.txt +21 -18
  13. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/requirements/requirements-ubuntu-latest_py3.14.txt +7 -7
  14. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/requirements/requirements-ubuntu-latest_py3.14_extras.txt +21 -18
  15. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/test_mprester.py +8 -5
  16. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/.coveragerc +0 -0
  17. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/.github/workflows/lint.yml +0 -0
  18. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/.github/workflows/release.yml +0 -0
  19. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/.github/workflows/testing.yml +0 -0
  20. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/.github/workflows/upgrade_dependencies.yml +0 -0
  21. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/.gitignore +0 -0
  22. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/.pre-commit-config.yaml +0 -0
  23. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/CODE_OF_CONDUCT.md +0 -0
  24. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/LICENSE +0 -0
  25. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/README.md +0 -0
  26. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/dev/generate_mcp_tools.py +0 -0
  27. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/dev/inspect_mcp.sh +0 -0
  28. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/docs/Makefile +0 -0
  29. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/docs/_templates/custom-class-template.rst +0 -0
  30. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/docs/_templates/custom-module-template.rst +0 -0
  31. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/docs/conf.py +0 -0
  32. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/docs/index.rst +0 -0
  33. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/docs/make.bat +0 -0
  34. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/docs/modules.rst +0 -0
  35. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/__init__.py +0 -0
  36. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/_test_utils.py +0 -0
  37. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/__init__.py +0 -0
  38. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/_server_utils.py +0 -0
  39. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/contribs/__init__.py +0 -0
  40. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/contribs/_logger.py +0 -0
  41. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/contribs/_types.py +0 -0
  42. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/contribs/_units.py +0 -0
  43. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/contribs/client.py +0 -0
  44. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/contribs/schemas.py +0 -0
  45. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/contribs/settings.py +0 -0
  46. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/contribs/utils.py +0 -0
  47. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/core/__init__.py +0 -0
  48. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/core/_oxygen_evolution.py +0 -0
  49. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/core/exceptions.py +0 -0
  50. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/core/schemas.py +0 -0
  51. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/core/utils.py +0 -0
  52. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/mprester.py +0 -0
  53. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/__init__.py +0 -0
  54. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/_server.py +0 -0
  55. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/__init__.py +0 -0
  56. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/absorption.py +0 -0
  57. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/alloys.py +0 -0
  58. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/bonds.py +0 -0
  59. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/chemenv.py +0 -0
  60. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/dielectric.py +0 -0
  61. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/doi.py +0 -0
  62. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/elasticity.py +0 -0
  63. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/electrodes.py +0 -0
  64. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/electronic_structure.py +0 -0
  65. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/eos.py +0 -0
  66. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/grain_boundaries.py +0 -0
  67. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/magnetism.py +0 -0
  68. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/oxidation_states.py +0 -0
  69. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/piezo.py +0 -0
  70. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/provenance.py +0 -0
  71. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/robocrys.py +0 -0
  72. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/similarity.py +0 -0
  73. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/substrates.py +0 -0
  74. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/summary.py +0 -0
  75. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/surface_properties.py +0 -0
  76. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/synthesis.py +0 -0
  77. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/tasks.py +0 -0
  78. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/thermo.py +0 -0
  79. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/materials/xas.py +0 -0
  80. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/molecules/__init__.py +0 -0
  81. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/molecules/jcesr.py +0 -0
  82. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/molecules/molecules.py +0 -0
  83. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/client/routes/molecules/summary.py +0 -0
  84. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/mcp/__init__.py +0 -0
  85. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/mcp/_schemas.py +0 -0
  86. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/mcp/mp_mcp.py +0 -0
  87. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/mcp/server.py +0 -0
  88. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/mcp/tools.py +0 -0
  89. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/mcp/utils.py +0 -0
  90. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api/py.typed +0 -0
  91. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api.egg-info/SOURCES.txt +0 -0
  92. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api.egg-info/dependency_links.txt +0 -0
  93. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api.egg-info/entry_points.txt +0 -0
  94. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api.egg-info/requires.txt +0 -0
  95. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/mp_api.egg-info/top_level.txt +0 -0
  96. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/pyproject.toml +0 -0
  97. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/setup.cfg +0 -0
  98. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/test_files/Si_mp_149.cif +0 -0
  99. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/__init__.py +0 -0
  100. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/__init__.py +0 -0
  101. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/contribs/conftest.py +0 -0
  102. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/contribs/test_client.py +0 -0
  103. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/contribs/test_contribs_schemas.py +0 -0
  104. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/contribs/test_contribs_utils.py +0 -0
  105. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/contribs/test_types.py +0 -0
  106. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/core/test_oxygen_evolution.py +0 -0
  107. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/core/test_schemas.py +0 -0
  108. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/core/test_utils.py +0 -0
  109. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/__init__.py +0 -0
  110. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_absorption.py +0 -0
  111. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_alloys.py +0 -0
  112. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_bonds.py +0 -0
  113. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_chemenv.py +0 -0
  114. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_dielectric.py +0 -0
  115. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_doi.py +0 -0
  116. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_elasticity.py +0 -0
  117. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_electrodes.py +0 -0
  118. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_electronic_structure.py +0 -0
  119. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_eos.py +0 -0
  120. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_grain_boundary.py +0 -0
  121. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_magnetism.py +0 -0
  122. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_materials.py +0 -0
  123. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_oxidation_states.py +0 -0
  124. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_phonon.py +0 -0
  125. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_piezo.py +0 -0
  126. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_provenance.py +0 -0
  127. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_robocrys.py +0 -0
  128. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_similarity.py +0 -0
  129. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_substrates.py +0 -0
  130. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_summary.py +0 -0
  131. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_surface_properties.py +0 -0
  132. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_synthesis.py +0 -0
  133. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_tasks.py +0 -0
  134. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_thermo.py +0 -0
  135. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/materials/test_xas.py +0 -0
  136. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/molecules/__init__.py +0 -0
  137. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/molecules/test_jcesr.py +0 -0
  138. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/molecules/test_molecules.py +0 -0
  139. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/molecules/test_summary.py +0 -0
  140. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/test_client.py +0 -0
  141. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/test_core_client.py +0 -0
  142. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/client/test_heartbeat.py +0 -0
  143. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/mcp/__init__.py +0 -0
  144. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/mcp/test_server.py +0 -0
  145. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/mcp/test_tools.py +0 -0
  146. {mp_api-0.46.2rc10 → mp_api-0.46.2rc12}/tests/mcp/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mp-api
3
- Version: 0.46.2rc10
3
+ Version: 0.46.2rc12
4
4
  Summary: API Client for the Materials Project
5
5
  Author-email: The Materials Project <feedback@materialsproject.org>
6
6
  License-Expression: BSD-3-Clause-LBNL
@@ -33,7 +33,7 @@ import requests
33
33
  from botocore import UNSIGNED
34
34
  from botocore.config import Config
35
35
  from botocore.exceptions import ClientError
36
- from deltalake import DeltaTable, QueryBuilder, convert_to_deltalake
36
+ from deltalake import DeltaTable, QueryBuilder, Schema, convert_to_deltalake
37
37
  from emmet.core.arrow import arrowize
38
38
  from emmet.core.utils import jsanitize
39
39
  from pydantic import BaseModel
@@ -79,6 +79,13 @@ STATIC_COLLECTIONS = [
79
79
  "synth-descriptions",
80
80
  "xas",
81
81
  ]
82
+ CONTROLLED_COLLECTIONS = [
83
+ "chemenv",
84
+ "materials",
85
+ "oxidation-states",
86
+ "summary",
87
+ "thermo",
88
+ ]
82
89
 
83
90
  hdlr = logging.StreamHandler()
84
91
  fmt = logging.Formatter("%(name)s - %(levelname)s - %(message)s")
@@ -683,6 +690,7 @@ class BaseRester(_Rester):
683
690
  bucket: str,
684
691
  prefix: str,
685
692
  access_controlled: bool = True,
693
+ versioned: bool = False,
686
694
  timeout: int | None = None,
687
695
  label: str | None = None,
688
696
  ) -> dict[str, Any]:
@@ -692,12 +700,16 @@ class BaseRester(_Rester):
692
700
  bucket (str) : S3 OpenData bucket
693
701
  prefix (str) : S3 object prefix
694
702
  access_controlled (bool): whether or not table has access controlled data
703
+ versioned (bool): whether or not table is partitioned on db version
695
704
  timeout (int or None) : timeout on getting access-controlled groups
696
705
  label (str or None) : label of the table in QueryBuilder
697
706
 
698
707
  Returns:
699
708
  dict of str to Any
700
709
  """
710
+ # just in case
711
+ prefix = prefix.rstrip("/")
712
+
701
713
  # Check if user has access to GNoMe
702
714
  # temp suppress tqdm
703
715
  re_enable = not self.mute_progress_bars
@@ -755,11 +767,15 @@ class BaseRester(_Rester):
755
767
  controlled_batch_str = ",".join(
756
768
  [f"'{tag}'" for tag in self.access_controlled_batch_ids]
757
769
  )
770
+ _coll = prefix.split("/")[-1]
771
+
772
+ if _coll == "tasks":
773
+ condition = f"batch_id NOT IN ({controlled_batch_str})"
774
+ else:
775
+ condition = "builder_meta.license != 'BY-NC'"
758
776
 
759
777
  predicate = (
760
- f"WHERE batch_id NOT IN ({controlled_batch_str})"
761
- if not has_gnome_access and controlled_batch_str and access_controlled
762
- else ""
778
+ f"WHERE {condition}" if not has_gnome_access and access_controlled else ""
763
779
  )
764
780
  # TODO: do we need something like this?
765
781
  # predicate += f"{' AND ' if predicate else 'WHERE '}version='{self.db_version}'"
@@ -768,10 +784,13 @@ class BaseRester(_Rester):
768
784
  num_docs_needed: int = tbl.count()
769
785
 
770
786
  if not has_gnome_access:
787
+ mongo_predicate = (
788
+ {"batch_id_neq_any": self.access_controlled_batch_ids}
789
+ if _coll == "tasks"
790
+ else {"license": "BY-NC"}
791
+ )
771
792
  try:
772
- num_docs_needed = self.count(
773
- {"batch_id_neq_any": self.access_controlled_batch_ids}
774
- )
793
+ num_docs_needed = self.count(mongo_predicate)
775
794
  except MPRestError:
776
795
  # batch_id isn't a valid field
777
796
  num_docs_needed = self.count()
@@ -793,7 +812,12 @@ class BaseRester(_Rester):
793
812
 
794
813
  file_options = ds.ParquetFileFormat().make_write_options(compression="zstd")
795
814
 
796
- def _flush(accumulator: list[pa.RecordBatch], group: int, schema: pa.Schema):
815
+ def _flush(
816
+ accumulator: list[pa.RecordBatch],
817
+ group: int,
818
+ schema: pa.Schema,
819
+ partitioning: pa.dataset.partitioning,
820
+ ):
797
821
  # somewhere post datafusion 51.0.0 and arrow-rs 57.0.0
798
822
  # casts to *View types began, need to cast back to base schema
799
823
  # -> pyarrow is behind on implementation support for *View types
@@ -807,6 +831,7 @@ class BaseRester(_Rester):
807
831
  tbl,
808
832
  base_dir=target_path,
809
833
  format="parquet",
834
+ partitioning=partitioning,
810
835
  basename_template=f"group-{group}-" + "part-{i}.zstd.parquet",
811
836
  existing_data_behavior="overwrite_or_ignore",
812
837
  max_rows_per_group=1024,
@@ -816,7 +841,18 @@ class BaseRester(_Rester):
816
841
  group = 1
817
842
  size = 0
818
843
  accumulator = []
819
- schema = pa.schema(arrowize(self.document_model))
844
+ _schema = pa.schema(arrowize(self.document_model))
845
+ schema = (
846
+ _schema.insert(0, pa.field("version", pa.string()))
847
+ if versioned
848
+ else _schema
849
+ )
850
+ partitioning_schema = pa.schema([pa.field("version", pa.string())])
851
+ partitioning = (
852
+ pa.dataset.partitioning(partitioning_schema, flavor="hive")
853
+ if versioned
854
+ else None
855
+ )
820
856
  for page in iterator:
821
857
  # arro3 rb to pyarrow rb for compat w/ pyarrow ds writer
822
858
  rg = pa.record_batch(page)
@@ -828,13 +864,13 @@ class BaseRester(_Rester):
828
864
  pbar.update(page_size)
829
865
 
830
866
  if size >= MAPI_CLIENT_SETTINGS.DATASET_FLUSH_THRESHOLD:
831
- _flush(accumulator, group, schema)
867
+ _flush(accumulator, group, schema, partitioning)
832
868
  group += 1
833
869
  size = 0
834
870
  accumulator.clear()
835
871
 
836
872
  if accumulator:
837
- _flush(accumulator, group + 1, schema)
873
+ _flush(accumulator, group + 1, schema, partitioning)
838
874
 
839
875
  if pbar is not None:
840
876
  pbar.close()
@@ -842,7 +878,13 @@ class BaseRester(_Rester):
842
878
  logger.info(f"Dataset for {suffix} written to {target_path}")
843
879
  logger.info("Converting to DeltaTable...")
844
880
 
845
- convert_to_deltalake(target_path)
881
+ delta_paritioning = Schema.from_arrow(partitioning_schema)
882
+
883
+ convert_to_deltalake(
884
+ target_path,
885
+ partition_by=delta_paritioning if versioned else None,
886
+ partition_strategy="hive" if versioned else None,
887
+ )
846
888
 
847
889
  logger.info(
848
890
  "Consult the delta-rs and pyarrow documentation for advanced usage: "
@@ -928,13 +970,15 @@ class BaseRester(_Rester):
928
970
  suffix = self.suffix
929
971
  elif self.suffix == "molecules/summary":
930
972
  suffix = "molecules"
973
+ elif self.suffix == "molecules/jcesr":
974
+ suffix = "jcesr"
931
975
  else:
932
976
  infix, suffix = self.suffix.split("/", 1)
933
977
  suffix = infix if suffix == "core" else suffix
934
978
  suffix = suffix.replace("_", "-")
935
979
 
936
980
  if "tasks" in suffix:
937
- bucket_suffix, prefix = ("parsed", "core/tasks/")
981
+ bucket_suffix, prefix = ("parsed", "core/tasks")
938
982
  elif suffix in STATIC_COLLECTIONS:
939
983
  bucket_suffix = "build"
940
984
  prefix = f"static-collections/{suffix}"
@@ -946,9 +990,14 @@ class BaseRester(_Rester):
946
990
  bucket = f"materialsproject-{bucket_suffix}"
947
991
 
948
992
  if self.delta_backed:
949
- access_controlled = suffix not in STATIC_COLLECTIONS
993
+ access_controlled = suffix in CONTROLLED_COLLECTIONS
994
+ versioned = suffix != "tasks" and suffix not in STATIC_COLLECTIONS
950
995
  return self._query_delta_backed(
951
- bucket, prefix, access_controlled, timeout=timeout
996
+ bucket=bucket,
997
+ prefix=prefix,
998
+ access_controlled=access_controlled,
999
+ versioned=versioned,
1000
+ timeout=timeout,
952
1001
  )
953
1002
 
954
1003
  # Paginate over all entries in the bucket.
@@ -21,7 +21,7 @@ _MUTE_PROGRESS_BAR = PMG_SETTINGS.get("MPRESTER_MUTE_PROGRESS_BARS", False)
21
21
  _MAX_LIST_LENGTH = min(PMG_SETTINGS.get("MPRESTER_MAX_LIST_LENGTH", 10000), 10000)
22
22
 
23
23
  _EMMET_SETTINGS = EmmetSettings() # type: ignore[call-arg]
24
- _DEFAULT_ENDPOINT = "https://api-preview.materialsproject.org/"
24
+ _DEFAULT_ENDPOINT = "https://api.materialsproject.org/"
25
25
 
26
26
 
27
27
  class MAPIClientSettings(BaseSettings):
@@ -102,7 +102,7 @@ class MaterialsRester(CoreRester):
102
102
  Returns:
103
103
  ([MaterialsDoc], [dict]) List of material documents or dictionaries.
104
104
  """
105
- query_params: dict = {"deprecated": deprecated}
105
+ query_params: dict = dict()
106
106
 
107
107
  if material_ids:
108
108
  if isinstance(material_ids, str):
@@ -163,6 +163,9 @@ class MaterialsRester(CoreRester):
163
163
  if query_params[entry] is not None
164
164
  }
165
165
 
166
+ if query_params:
167
+ query_params.update({"deprecated": deprecated})
168
+
166
169
  return super()._search( # type: ignore[return-value]
167
170
  num_chunks=num_chunks,
168
171
  chunk_size=chunk_size,
@@ -89,8 +89,8 @@ class PhononRester(BaseRester):
89
89
  missing: list[str] = []
90
90
  found_material_ids: set[str] = set()
91
91
  for doc in summary_docs:
92
- mid = str(doc["material_id"])
93
- phonon_ids_by_method = doc.get("phonon_IDs") or {}
92
+ mid = str(doc["material_id"]) # type: ignore[arg-type, index]
93
+ phonon_ids_by_method = doc.get("phonon_IDs") or {} # type: ignore[union-attr]
94
94
 
95
95
  if phonon_method:
96
96
  method_ids = phonon_ids_by_method.get(phonon_method) or []
@@ -215,13 +215,13 @@ class PhononRester(BaseRester):
215
215
  f"No phonon bandstructure data found for material ID {material_id}."
216
216
  )
217
217
 
218
- if phonon_method not in summary_doc[0]["phonon_IDs"]:
218
+ if phonon_method not in summary_doc[0]["phonon_IDs"]: # type: ignore[arg-type, index]
219
219
  raise MPRestError(
220
220
  f"No phonon bandstructure data found for material ID: {material_id} and phonon method: {phonon_method}."
221
221
  )
222
222
 
223
223
  return self.get_bandstructure_from_phonon_id(
224
- summary_doc[0]["phonon_IDs"][phonon_method][0], phonon_method, pt
224
+ summary_doc[0]["phonon_IDs"][phonon_method][0], phonon_method, pt # type: ignore[arg-type, index]
225
225
  )
226
226
 
227
227
  def get_dos_from_phonon_id(
@@ -280,13 +280,13 @@ class PhononRester(BaseRester):
280
280
  f"No phonon dos data found for material ID {material_id}."
281
281
  )
282
282
 
283
- if phonon_method not in summary_doc[0]["phonon_IDs"]:
283
+ if phonon_method not in summary_doc[0]["phonon_IDs"]: # type: ignore[arg-type, index]
284
284
  raise MPRestError(
285
285
  f"No phonon dos data found for material ID: {material_id} and phonon method: {phonon_method}."
286
286
  )
287
287
 
288
288
  return self.get_dos_from_phonon_id(
289
- summary_doc[0]["phonon_IDs"][phonon_method][0], phonon_method
289
+ summary_doc[0]["phonon_IDs"][phonon_method][0], phonon_method # type: ignore[arg-type, index]
290
290
  )
291
291
 
292
292
  def get_forceconstants_from_phonon_id(
@@ -344,20 +344,20 @@ class PhononRester(BaseRester):
344
344
  f"No phonon force constants data found for material ID {material_id}."
345
345
  )
346
346
 
347
- if phonon_method not in summary_doc[0]["phonon_IDs"]:
347
+ if phonon_method not in summary_doc[0]["phonon_IDs"]: # type: ignore[arg-type, index]
348
348
  raise MPRestError(
349
349
  f"No phonon force constants data found for material ID: {material_id} and phonon method: {phonon_method}."
350
350
  )
351
351
 
352
352
  return self.get_forceconstants_from_phonon_id(
353
- summary_doc[0]["phonon_IDs"][phonon_method][0], phonon_method
353
+ summary_doc[0]["phonon_IDs"][phonon_method][0], phonon_method # type: ignore[arg-type, index]
354
354
  )
355
355
 
356
356
  def compute_thermo_quantities(
357
357
  self,
358
- identifier: str | None = None,
359
358
  material_id: str | None = None,
360
359
  phonon_method: str | None = None,
360
+ identifier: str | None = None,
361
361
  ):
362
362
  """Compute thermodynamical quantities for a given phonon ID or material ID and phonon_method.
363
363
 
@@ -392,12 +392,21 @@ class PhononRester(BaseRester):
392
392
  raise MPRestError(
393
393
  f"No phonon data found for material ID {material_id}."
394
394
  )
395
- if phonon_method not in summary_doc[0]["phonon_IDs"]:
395
+ if phonon_method not in summary_doc[0]["phonon_IDs"]: # type: ignore[arg-type, index]
396
396
  raise MPRestError(
397
397
  f"No phonon data found for material ID: {material_id} and "
398
398
  f"phonon method: {phonon_method}."
399
399
  )
400
- identifier = summary_doc[0]["phonon_IDs"][phonon_method][0]
400
+ identifier = summary_doc[0]["phonon_IDs"][phonon_method][0] # type: ignore[arg-type, index]
401
+
402
+ if identifier is None or phonon_method is None:
403
+ suffix = (
404
+ f" for {material_id=}" if material_id else f" for {identifier=}"
405
+ )
406
+ raise MPRestError(
407
+ f"Could not resolve a phonon identifier or method{suffix} "
408
+ f"({phonon_method=})."
409
+ )
401
410
 
402
411
  ph_dos = self.get_dos_from_phonon_id(identifier, phonon_method)
403
412
  docs = self.search(identifiers=identifier, phonon_method=phonon_method)
@@ -406,7 +415,7 @@ class PhononRester(BaseRester):
406
415
 
407
416
  self.use_document_model = True
408
417
  docs[0]["phonon_dos"] = ph_dos # type: ignore[index]
409
- doc = PhononBSDOSDoc(**docs[0]) # type: ignore[arg-type]
418
+ doc = PhononBSDOSDoc(**docs[0]) # type: ignore[arg-type, index]
410
419
  finally:
411
420
  self.use_document_model = use_document_model
412
421
  # below: same as numpy.linspace(0,800,100) but written out for mypy
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mp-api
3
- Version: 0.46.2rc10
3
+ Version: 0.46.2rc12
4
4
  Summary: API Client for the Materials Project
5
5
  Author-email: The Materials Project <feedback@materialsproject.org>
6
6
  License-Expression: BSD-3-Clause-LBNL
@@ -12,9 +12,9 @@ bibtexparser==1.4.4
12
12
  # via pymatgen-core
13
13
  blake3==1.0.8
14
14
  # via emmet-core
15
- boto3==1.43.19
15
+ boto3==1.43.24
16
16
  # via mp-api (pyproject.toml)
17
- botocore==1.43.19
17
+ botocore==1.43.24
18
18
  # via
19
19
  # boto3
20
20
  # s3transfer
@@ -30,11 +30,11 @@ deltalake==1.5.1
30
30
  # via mp-api (pyproject.toml)
31
31
  deprecated==1.3.1
32
32
  # via deltalake
33
- emmet-core==0.87.0rc10
33
+ emmet-core==0.87.0rc13
34
34
  # via mp-api (pyproject.toml)
35
35
  fonttools==4.63.0
36
36
  # via matplotlib
37
- idna==3.17
37
+ idna==3.18
38
38
  # via requests
39
39
  inflect==7.5.0
40
40
  # via emmet-core
@@ -61,7 +61,7 @@ more-itertools==11.1.0
61
61
  # via inflect
62
62
  mpmath==1.3.0
63
63
  # via sympy
64
- narwhals==2.22.0
64
+ narwhals==2.22.1
65
65
  # via plotly
66
66
  networkx==3.6.1
67
67
  # via pymatgen-core
@@ -89,7 +89,7 @@ pandas==3.0.3
89
89
  # via pymatgen-core
90
90
  pillow==12.2.0
91
91
  # via matplotlib
92
- plotly==6.7.0
92
+ plotly==6.8.0
93
93
  # via pymatgen-core
94
94
  pubchempy==1.0.5
95
95
  # via emmet-core
@@ -149,7 +149,7 @@ sympy==1.14.0
149
149
  # via pymatgen-core
150
150
  tabulate==0.10.0
151
151
  # via pymatgen-core
152
- tqdm==4.67.3
152
+ tqdm==4.68.1
153
153
  # via pymatgen-core
154
154
  typeguard==4.5.2
155
155
  # via inflect
@@ -50,9 +50,9 @@ blinker==1.9.0
50
50
  # via flask
51
51
  boltons==25.0.0
52
52
  # via mp-api (pyproject.toml)
53
- boto3==1.43.19
53
+ boto3==1.43.24
54
54
  # via mp-api (pyproject.toml)
55
- botocore==1.43.19
55
+ botocore==1.43.24
56
56
  # via
57
57
  # boto3
58
58
  # s3transfer
@@ -103,7 +103,7 @@ deltalake==1.5.1
103
103
  # via mp-api (pyproject.toml)
104
104
  deprecated==1.3.1
105
105
  # via deltalake
106
- distlib==0.4.0
106
+ distlib==0.4.1
107
107
  # via virtualenv
108
108
  dnspython==2.8.0
109
109
  # via
@@ -116,7 +116,7 @@ docutils==0.22.4
116
116
  # via sphinx
117
117
  email-validator==2.3.0
118
118
  # via pydantic
119
- emmet-core[all]==0.87.0rc10
119
+ emmet-core[all]==0.87.0rc13
120
120
  # via mp-api (pyproject.toml)
121
121
  exceptiongroup==1.3.1
122
122
  # via fastmcp-slim
@@ -124,11 +124,11 @@ execnet==2.1.2
124
124
  # via pytest-xdist
125
125
  executing==2.2.1
126
126
  # via stack-data
127
- fastmcp==3.3.1
127
+ fastmcp==3.4.1
128
128
  # via mp-api (pyproject.toml)
129
- fastmcp-slim[client,server]==3.3.1
129
+ fastmcp-slim[client,server]==3.4.1
130
130
  # via fastmcp
131
- filelock==3.29.0
131
+ filelock==3.29.1
132
132
  # via
133
133
  # python-discovery
134
134
  # virtualenv
@@ -164,7 +164,7 @@ httpx-sse==0.4.3
164
164
  # via mcp
165
165
  identify==2.6.19
166
166
  # via pre-commit
167
- idna==3.17
167
+ idna==3.18
168
168
  # via
169
169
  # anyio
170
170
  # email-validator
@@ -183,7 +183,7 @@ inflect==7.5.0
183
183
  # via emmet-core
184
184
  iniconfig==2.3.0
185
185
  # via pytest
186
- ipython==9.14.0
186
+ ipython==9.14.1
187
187
  # via mp-api (pyproject.toml)
188
188
  ipython-pygments-lexers==1.1.1
189
189
  # via ipython
@@ -215,8 +215,10 @@ joblib==1.5.3
215
215
  # via
216
216
  # pymatgen-analysis-diffusion
217
217
  # pymatgen-core
218
- joserfc==1.6.8
219
- # via authlib
218
+ joserfc==1.7.0
219
+ # via
220
+ # authlib
221
+ # fastmcp-slim
220
222
  json2html==1.3.0
221
223
  # via mp-api (pyproject.toml)
222
224
  jsonpointer==3.1.1
@@ -298,7 +300,7 @@ mypy-extensions==1.1.0
298
300
  # via
299
301
  # mp-api (pyproject.toml)
300
302
  # mypy
301
- narwhals==2.22.0
303
+ narwhals==2.22.1
302
304
  # via plotly
303
305
  networkx==3.6.1
304
306
  # via
@@ -377,7 +379,7 @@ platformdirs==4.10.0
377
379
  # pint
378
380
  # python-discovery
379
381
  # virtualenv
380
- plotly==6.7.0
382
+ plotly==6.8.0
381
383
  # via pymatgen-core
382
384
  pluggy==1.6.0
383
385
  # via
@@ -502,7 +504,7 @@ python-dotenv==1.2.2
502
504
  # via
503
505
  # fastmcp-slim
504
506
  # pydantic-settings
505
- python-multipart==0.0.30
507
+ python-multipart==0.0.32
506
508
  # via
507
509
  # fastmcp-slim
508
510
  # mcp
@@ -585,7 +587,7 @@ six==1.17.0
585
587
  # bravado-core
586
588
  # python-dateutil
587
589
  # rfc3339-validator
588
- snowballstemmer==3.1.0
590
+ snowballstemmer==3.1.1
589
591
  # via sphinx
590
592
  spglib==2.7.0
591
593
  # via
@@ -613,6 +615,7 @@ stack-data==0.6.3
613
615
  # via ipython
614
616
  starlette==1.2.1
615
617
  # via
618
+ # fastmcp-slim
616
619
  # mcp
617
620
  # sse-starlette
618
621
  swagger-spec-validator==3.0.4
@@ -627,9 +630,9 @@ tabulate==0.10.0
627
630
  # via pymatgen-core
628
631
  tifffile==2026.3.3
629
632
  # via scikit-image
630
- tqdm==4.67.3
633
+ tqdm==4.68.1
631
634
  # via pymatgen-core
632
- traitlets==5.15.0
635
+ traitlets==5.15.1
633
636
  # via
634
637
  # ipython
635
638
  # matplotlib-inline
@@ -688,7 +691,7 @@ urllib3==2.7.0
688
691
  # botocore
689
692
  # requests
690
693
  # types-requests
691
- uvicorn==0.48.0
694
+ uvicorn==0.49.0
692
695
  # via
693
696
  # fastmcp-slim
694
697
  # mcp
@@ -12,9 +12,9 @@ bibtexparser==1.4.4
12
12
  # via pymatgen-core
13
13
  blake3==1.0.8
14
14
  # via emmet-core
15
- boto3==1.43.19
15
+ boto3==1.43.24
16
16
  # via mp-api (pyproject.toml)
17
- botocore==1.43.19
17
+ botocore==1.43.24
18
18
  # via
19
19
  # boto3
20
20
  # s3transfer
@@ -30,11 +30,11 @@ deltalake==1.5.1
30
30
  # via mp-api (pyproject.toml)
31
31
  deprecated==1.3.1
32
32
  # via deltalake
33
- emmet-core==0.87.0rc10
33
+ emmet-core==0.87.0rc13
34
34
  # via mp-api (pyproject.toml)
35
35
  fonttools==4.63.0
36
36
  # via matplotlib
37
- idna==3.17
37
+ idna==3.18
38
38
  # via requests
39
39
  inflect==7.5.0
40
40
  # via emmet-core
@@ -61,7 +61,7 @@ more-itertools==11.1.0
61
61
  # via inflect
62
62
  mpmath==1.3.0
63
63
  # via sympy
64
- narwhals==2.22.0
64
+ narwhals==2.22.1
65
65
  # via plotly
66
66
  networkx==3.6.1
67
67
  # via pymatgen-core
@@ -89,7 +89,7 @@ pandas==3.0.3
89
89
  # via pymatgen-core
90
90
  pillow==12.2.0
91
91
  # via matplotlib
92
- plotly==6.7.0
92
+ plotly==6.8.0
93
93
  # via pymatgen-core
94
94
  pubchempy==1.0.5
95
95
  # via emmet-core
@@ -149,7 +149,7 @@ sympy==1.14.0
149
149
  # via pymatgen-core
150
150
  tabulate==0.10.0
151
151
  # via pymatgen-core
152
- tqdm==4.67.3
152
+ tqdm==4.68.1
153
153
  # via pymatgen-core
154
154
  typeguard==4.5.2
155
155
  # via inflect