mp-api 0.46.1rc8__tar.gz → 0.46.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.
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/.github/workflows/lint.yml +1 -1
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/.github/workflows/release.yml +7 -3
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/.github/workflows/testing.yml +2 -12
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/.github/workflows/upgrade_dependencies.yml +2 -2
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/.pre-commit-config.yaml +5 -5
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/PKG-INFO +18 -6
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/docs/conf.py +2 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/_test_utils.py +54 -7
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/__init__.py +1 -0
- mp_api-0.46.2/mp_api/client/contribs/__init__.py +16 -0
- mp_api-0.46.2/mp_api/client/contribs/_logger.py +97 -0
- mp_api-0.46.2/mp_api/client/contribs/_types.py +351 -0
- mp_api-0.46.2/mp_api/client/contribs/_units.py +21 -0
- mp_api-0.46.2/mp_api/client/contribs/client.py +2541 -0
- mp_api-0.46.2/mp_api/client/contribs/schemas.py +376 -0
- mp_api-0.46.2/mp_api/client/contribs/settings.py +90 -0
- mp_api-0.46.2/mp_api/client/contribs/utils.py +150 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/core/client.py +365 -236
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/core/exceptions.py +4 -0
- mp_api-0.46.2/mp_api/client/core/schemas.py +216 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/core/settings.py +6 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/core/utils.py +12 -5
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/mprester.py +185 -103
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/__init__.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/chemenv.py +12 -12
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/doi.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/electrodes.py +19 -4
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/electronic_structure.py +150 -39
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/eos.py +24 -8
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/grain_boundaries.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/materials.py +4 -1
- mp_api-0.46.2/mp_api/client/routes/materials/phonon.py +422 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/similarity.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/substrates.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/surface_properties.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/synthesis.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/tasks.py +13 -22
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/thermo.py +76 -34
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/xas.py +44 -10
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/molecules/__init__.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/molecules/jcesr.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/molecules/molecules.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/molecules/summary.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/mcp/_schemas.py +2 -2
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/mcp/mp_mcp.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/mcp/server.py +1 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/mcp/tools.py +4 -3
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api.egg-info/PKG-INFO +18 -6
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api.egg-info/SOURCES.txt +19 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api.egg-info/requires.txt +18 -5
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/pyproject.toml +23 -7
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/requirements/requirements-ubuntu-latest_py3.11.txt +27 -27
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/requirements/requirements-ubuntu-latest_py3.11_extras.txt +159 -136
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/requirements/requirements-ubuntu-latest_py3.12.txt +27 -27
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/requirements/requirements-ubuntu-latest_py3.12_extras.txt +157 -136
- mp_api-0.46.2/requirements/requirements-ubuntu-latest_py3.13.txt +175 -0
- mp_api-0.46.2/requirements/requirements-ubuntu-latest_py3.13_extras.txt +698 -0
- mp_api-0.46.2/requirements/requirements-ubuntu-latest_py3.14.txt +175 -0
- mp_api-0.46.2/requirements/requirements-ubuntu-latest_py3.14_extras.txt +698 -0
- mp_api-0.46.2/tests/client/contribs/conftest.py +11 -0
- mp_api-0.46.2/tests/client/contribs/test_client.py +59 -0
- mp_api-0.46.2/tests/client/contribs/test_contribs_schemas.py +162 -0
- mp_api-0.46.2/tests/client/contribs/test_contribs_utils.py +38 -0
- mp_api-0.46.2/tests/client/contribs/test_types.py +87 -0
- mp_api-0.46.2/tests/client/core/test_schemas.py +108 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_chemenv.py +2 -3
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_electrodes.py +8 -12
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_electronic_structure.py +7 -5
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_eos.py +15 -3
- mp_api-0.46.2/tests/client/materials/test_phonon.py +104 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_provenance.py +1 -1
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_summary.py +1 -1
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_thermo.py +3 -3
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_xas.py +13 -10
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/molecules/test_jcesr.py +12 -8
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/molecules/test_summary.py +3 -4
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/test_client.py +5 -2
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/test_core_client.py +5 -4
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/test_mprester.py +162 -131
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/mcp/test_tools.py +1 -1
- mp_api-0.46.1rc8/mp_api/client/routes/materials/phonon.py +0 -156
- mp_api-0.46.1rc8/tests/client/materials/test_phonon.py +0 -80
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/.coveragerc +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/.gitignore +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/CODE_OF_CONDUCT.md +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/LICENSE +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/README.md +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/dev/generate_mcp_tools.py +1 -1
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/dev/inspect_mcp.sh +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/docs/Makefile +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/docs/_templates/custom-class-template.rst +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/docs/_templates/custom-module-template.rst +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/docs/index.rst +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/docs/make.bat +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/docs/modules.rst +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/__init__.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/_server_utils.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/core/__init__.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/core/_oxygen_evolution.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/__init__.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/_server.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/absorption.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/alloys.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/bonds.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/dielectric.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/elasticity.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/magnetism.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/oxidation_states.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/piezo.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/provenance.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/robocrys.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/client/routes/materials/summary.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/mcp/__init__.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/mcp/utils.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api/py.typed +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api.egg-info/dependency_links.txt +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api.egg-info/entry_points.txt +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/mp_api.egg-info/top_level.txt +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/setup.cfg +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/test_files/Si_mp_149.cif +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/__init__.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/__init__.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/core/test_oxygen_evolution.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/core/test_utils.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/__init__.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_absorption.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_alloys.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_bonds.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_dielectric.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_doi.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_elasticity.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_grain_boundary.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_magnetism.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_materials.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_oxidation_states.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_piezo.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_robocrys.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_similarity.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_substrates.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_surface_properties.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_synthesis.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/materials/test_tasks.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/molecules/__init__.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/molecules/test_molecules.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/client/test_heartbeat.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/mcp/__init__.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/mcp/test_server.py +0 -0
- {mp_api-0.46.1rc8 → mp_api-0.46.2}/tests/mcp/test_utils.py +0 -0
|
@@ -16,7 +16,7 @@ jobs:
|
|
|
16
16
|
|
|
17
17
|
- uses: actions/setup-python@v5
|
|
18
18
|
with:
|
|
19
|
-
python-version: 3.
|
|
19
|
+
python-version: 3.12
|
|
20
20
|
|
|
21
21
|
- name: Install dependencies
|
|
22
22
|
run: |
|
|
@@ -36,20 +36,24 @@ jobs:
|
|
|
36
36
|
|
|
37
37
|
docs:
|
|
38
38
|
runs-on: ubuntu-latest
|
|
39
|
+
|
|
39
40
|
needs:
|
|
40
41
|
- deploy
|
|
41
42
|
|
|
43
|
+
env:
|
|
44
|
+
PYTHON_VERSION: 3.12
|
|
45
|
+
|
|
42
46
|
steps:
|
|
43
47
|
- uses: actions/checkout@v4
|
|
44
48
|
|
|
45
49
|
- uses: actions/setup-python@v5
|
|
46
50
|
with:
|
|
47
|
-
python-version:
|
|
51
|
+
python-version: ${{ env.PYTHON_VERSION }}
|
|
48
52
|
|
|
49
53
|
- name: Install dependencies
|
|
50
54
|
run: |
|
|
51
55
|
python -m pip install --upgrade pip
|
|
52
|
-
pip install -r requirements/requirements-ubuntu-
|
|
56
|
+
pip install -r requirements/requirements-ubuntu-latest_py${{ env.PYTHON_VERSION }}_extras.txt
|
|
53
57
|
pip install -e .
|
|
54
58
|
|
|
55
59
|
- name: Build
|
|
@@ -17,7 +17,7 @@ jobs:
|
|
|
17
17
|
strategy:
|
|
18
18
|
matrix:
|
|
19
19
|
os: ["ubuntu-latest"]
|
|
20
|
-
python-version: ["3.
|
|
20
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
21
21
|
|
|
22
22
|
runs-on: ${{ matrix.os }}
|
|
23
23
|
|
|
@@ -43,16 +43,6 @@ jobs:
|
|
|
43
43
|
if: matrix.os == 'windows-latest'
|
|
44
44
|
run: echo "SSL_CERT_FILE=$(python -m certifi)" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
|
45
45
|
|
|
46
|
-
- name: Format API key name (Linux/MacOS)
|
|
47
|
-
if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
|
|
48
|
-
run: |
|
|
49
|
-
echo "API_KEY_NAME=$(echo ${{ format('MP_API_KEY_{0}_{1}', matrix.os, matrix.python-version) }} | awk '{gsub(/-|\./, "_"); print}' | tr '[:lower:]' '[:upper:]')" >> $GITHUB_ENV
|
|
50
|
-
|
|
51
|
-
- name: Format API key name (Windows)
|
|
52
|
-
if: matrix.os == 'windows-latest'
|
|
53
|
-
run: |
|
|
54
|
-
echo "API_KEY_NAME=$(echo ${{ format('MP_API_KEY_{0}_{1}', matrix.os, matrix.python-version) }} | awk '{gsub(/-|\./, "_"); print}' | tr '[:lower:]' '[:upper:]')" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append
|
|
55
|
-
|
|
56
46
|
- name: Lint with mypy
|
|
57
47
|
shell: bash -l {0}
|
|
58
48
|
run: python -m mypy mp_api/
|
|
@@ -60,7 +50,7 @@ jobs:
|
|
|
60
50
|
- name: Test with pytest
|
|
61
51
|
if: always()
|
|
62
52
|
env:
|
|
63
|
-
MP_API_KEY: ${{ secrets
|
|
53
|
+
MP_API_KEY: ${{ secrets.MP_API_KEY_UBUNTU_LATEST_3_12 }}
|
|
64
54
|
# MP_API_ENDPOINT: https://api-preview.materialsproject.org/
|
|
65
55
|
run: |
|
|
66
56
|
pytest -n auto -x --cov=mp_api --cov-report=xml
|
|
@@ -11,7 +11,7 @@ jobs:
|
|
|
11
11
|
matrix:
|
|
12
12
|
os: ['ubuntu-latest']
|
|
13
13
|
package: ["mp-api"]
|
|
14
|
-
python-version: ["3.11", "3.12"]
|
|
14
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
15
15
|
steps:
|
|
16
16
|
- uses: actions/checkout@v4
|
|
17
17
|
with:
|
|
@@ -49,7 +49,7 @@ jobs:
|
|
|
49
49
|
needs: upgrade
|
|
50
50
|
strategy:
|
|
51
51
|
matrix:
|
|
52
|
-
python-version: ["3.
|
|
52
|
+
python-version: ["3.12"]
|
|
53
53
|
steps:
|
|
54
54
|
- uses: actions/checkout@v4
|
|
55
55
|
with:
|
|
@@ -6,24 +6,24 @@ ci:
|
|
|
6
6
|
|
|
7
7
|
repos:
|
|
8
8
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
9
|
-
rev: v0.
|
|
9
|
+
rev: v0.15.12
|
|
10
10
|
hooks:
|
|
11
11
|
- id: ruff
|
|
12
12
|
args: [--fix, --show-fixes]
|
|
13
13
|
|
|
14
14
|
- repo: https://github.com/psf/black
|
|
15
|
-
rev:
|
|
15
|
+
rev: 26.3.1
|
|
16
16
|
hooks:
|
|
17
17
|
- id: black
|
|
18
18
|
|
|
19
19
|
- repo: https://github.com/asottile/blacken-docs
|
|
20
|
-
rev: "1.
|
|
20
|
+
rev: "1.20.0"
|
|
21
21
|
hooks:
|
|
22
22
|
- id: blacken-docs
|
|
23
23
|
additional_dependencies: [black>=23.7.0]
|
|
24
24
|
|
|
25
25
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
26
|
-
rev:
|
|
26
|
+
rev: v6.0.0
|
|
27
27
|
hooks:
|
|
28
28
|
- id: check-case-conflict
|
|
29
29
|
- id: check-symlinks
|
|
@@ -34,7 +34,7 @@ repos:
|
|
|
34
34
|
- id: trailing-whitespace
|
|
35
35
|
|
|
36
36
|
- repo: https://github.com/codespell-project/codespell
|
|
37
|
-
rev: v2.2
|
|
37
|
+
rev: v2.4.2
|
|
38
38
|
hooks:
|
|
39
39
|
- id: codespell
|
|
40
40
|
stages: [pre-commit, commit-msg]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mp-api
|
|
3
|
-
Version: 0.46.
|
|
3
|
+
Version: 0.46.2
|
|
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
|
|
@@ -13,25 +13,36 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
13
13
|
Requires-Python: >=3.11
|
|
14
14
|
Description-Content-Type: text/markdown
|
|
15
15
|
License-File: LICENSE
|
|
16
|
-
Requires-Dist: pymatgen
|
|
16
|
+
Requires-Dist: pymatgen>2024.2.20
|
|
17
17
|
Requires-Dist: typing-extensions>=3.7.4.1
|
|
18
18
|
Requires-Dist: requests>=2.23.0
|
|
19
19
|
Requires-Dist: monty>=2024.12.10
|
|
20
|
-
Requires-Dist: emmet-core<0.
|
|
20
|
+
Requires-Dist: emmet-core<0.87.2,>=0.87.0
|
|
21
21
|
Requires-Dist: boto3
|
|
22
22
|
Requires-Dist: orjson<4,>=3.10
|
|
23
23
|
Requires-Dist: pyarrow>=20.0.0
|
|
24
|
-
Requires-Dist: deltalake
|
|
24
|
+
Requires-Dist: deltalake<1.6.0,>=1.4.0
|
|
25
25
|
Provides-Extra: mcp
|
|
26
26
|
Requires-Dist: fastmcp; extra == "mcp"
|
|
27
27
|
Provides-Extra: server
|
|
28
28
|
Requires-Dist: flask; extra == "server"
|
|
29
|
+
Provides-Extra: contribs
|
|
30
|
+
Requires-Dist: boltons; extra == "contribs"
|
|
31
|
+
Requires-Dist: bravado; extra == "contribs"
|
|
32
|
+
Requires-Dist: filetype; extra == "contribs"
|
|
33
|
+
Requires-Dist: ipython; extra == "contribs"
|
|
34
|
+
Requires-Dist: json2html; extra == "contribs"
|
|
35
|
+
Requires-Dist: pint>=0.25.0; extra == "contribs"
|
|
36
|
+
Requires-Dist: pyIsEmail; extra == "contribs"
|
|
37
|
+
Requires-Dist: requests-futures; extra == "contribs"
|
|
38
|
+
Requires-Dist: swagger-spec-validator; extra == "contribs"
|
|
39
|
+
Requires-Dist: cachetools; extra == "contribs"
|
|
40
|
+
Requires-Dist: pymongo; extra == "contribs"
|
|
29
41
|
Provides-Extra: all
|
|
30
42
|
Requires-Dist: custodian; extra == "all"
|
|
31
|
-
Requires-Dist: emmet-core[all]<0.
|
|
43
|
+
Requires-Dist: emmet-core[all]<0.87.2,>=0.87.0; extra == "all"
|
|
32
44
|
Requires-Dist: fastmcp; extra == "all"
|
|
33
45
|
Requires-Dist: flask; extra == "all"
|
|
34
|
-
Requires-Dist: mpcontribs-client>=5.10; extra == "all"
|
|
35
46
|
Provides-Extra: test
|
|
36
47
|
Requires-Dist: pre-commit; extra == "test"
|
|
37
48
|
Requires-Dist: pytest; extra == "test"
|
|
@@ -46,6 +57,7 @@ Requires-Dist: mypy-extensions; extra == "test"
|
|
|
46
57
|
Requires-Dist: typing-extensions; extra == "test"
|
|
47
58
|
Requires-Dist: types-setuptools; extra == "test"
|
|
48
59
|
Requires-Dist: types-requests; extra == "test"
|
|
60
|
+
Requires-Dist: types-tqdm; extra == "test"
|
|
49
61
|
Provides-Extra: docs
|
|
50
62
|
Requires-Dist: sphinx; extra == "docs"
|
|
51
63
|
Dynamic: license-file
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
# -- Project information -----------------------------------------------------
|
|
7
7
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
|
8
8
|
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
9
11
|
project = "mp-api"
|
|
10
12
|
copyright = "2022, The Materials Project"
|
|
11
13
|
author = "The Materials Project"
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
+
from enum import Enum
|
|
8
|
+
|
|
7
9
|
try:
|
|
8
10
|
import pytest
|
|
9
11
|
except ImportError as exc:
|
|
@@ -86,19 +88,64 @@ def client_search_testing(
|
|
|
86
88
|
assert doc[alt_name_dict.get(param, param)] is not None
|
|
87
89
|
|
|
88
90
|
|
|
89
|
-
def client_pagination(
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
def client_pagination(
|
|
92
|
+
search_method: Callable, id_name: str, additional_fields: list[str] | None = None
|
|
93
|
+
) -> None:
|
|
94
|
+
"""Test pagination on an endpoint.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
search_method (Callable) : Client search method to use
|
|
98
|
+
id_name (str) : the name of a field which uniquely indexes a series of documents
|
|
99
|
+
additional_fields (list of str) : Optional other fields to retrieve.
|
|
100
|
+
|
|
101
|
+
Raises:
|
|
102
|
+
AssertionError if pagination does not result in unique sets of documents
|
|
103
|
+
"""
|
|
104
|
+
fields = [id_name, *(additional_fields or [])]
|
|
105
|
+
page_1 = search_method(_page=1, chunk_size=NUM_DOCS, fields=fields)
|
|
106
|
+
page_2 = search_method(_page=2, chunk_size=NUM_DOCS, fields=fields)
|
|
92
107
|
assert all(len(results) == NUM_DOCS for results in (page_1, page_2))
|
|
93
108
|
assert {str(getattr(doc, id_name)) for doc in page_1}.intersection(
|
|
94
109
|
{str(getattr(doc, id_name)) for doc in page_2}
|
|
95
110
|
) == set()
|
|
96
111
|
|
|
97
112
|
|
|
98
|
-
def client_sort(
|
|
113
|
+
def client_sort(
|
|
114
|
+
search_method: Callable,
|
|
115
|
+
sort_fields: str | Sequence[str],
|
|
116
|
+
aux_query: dict[str, Any] | None = None,
|
|
117
|
+
default_fields: tuple[str, ...] = ("deprecated", "material_id"),
|
|
118
|
+
):
|
|
119
|
+
"""Test sorting on an endpoint.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
search_method (Callable) : Client search method to use
|
|
123
|
+
sort_fields (str or Sequence of str) : fields to sort on
|
|
124
|
+
aux_query (dict) : auxiliary query needed to filter documents
|
|
125
|
+
default_fields (list): default fields to return
|
|
126
|
+
|
|
127
|
+
Raises:
|
|
128
|
+
AssertionError if sorting in ascending or descending order does not work.
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
def _normalize(doc, field: str):
|
|
132
|
+
v = getattr(doc, field)
|
|
133
|
+
# serialize enums
|
|
134
|
+
return v.value if isinstance(v, Enum) else v
|
|
135
|
+
|
|
136
|
+
user_query = {
|
|
137
|
+
k: v
|
|
138
|
+
for k, v in (aux_query or {}).items()
|
|
139
|
+
if k not in ("_page", "_sort_fields", "chunk_size", "fields")
|
|
140
|
+
}
|
|
99
141
|
for sort_field in [sort_fields] if isinstance(sort_fields, str) else sort_fields:
|
|
142
|
+
|
|
100
143
|
asc = search_method(
|
|
101
|
-
_page=1,
|
|
144
|
+
_page=1,
|
|
145
|
+
_sort_fields=sort_field,
|
|
146
|
+
chunk_size=NUM_DOCS,
|
|
147
|
+
fields=[sort_field, *default_fields],
|
|
148
|
+
**user_query,
|
|
102
149
|
)
|
|
103
150
|
desc = search_method(
|
|
104
151
|
_page=1,
|
|
@@ -108,12 +155,12 @@ def client_sort(search_method: Callable, sort_fields: str | Sequence[str]):
|
|
|
108
155
|
)
|
|
109
156
|
|
|
110
157
|
idxs = list(range(NUM_DOCS))
|
|
111
|
-
assert sorted(idxs, key=lambda idx:
|
|
158
|
+
assert sorted(idxs, key=lambda idx: _normalize(asc[idx], sort_field)) == idxs
|
|
112
159
|
|
|
113
160
|
assert (
|
|
114
161
|
sorted(
|
|
115
162
|
idxs,
|
|
116
|
-
key=lambda idx:
|
|
163
|
+
key=lambda idx: _normalize(desc[idx], sort_field),
|
|
117
164
|
reverse=True,
|
|
118
165
|
)
|
|
119
166
|
== idxs
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Pull in core MPContribs client features."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from mp_api.client.contribs._types import Attachment, Table
|
|
6
|
+
from mp_api.client.contribs.client import ContribsClient
|
|
7
|
+
from mp_api.client.contribs.settings import MPCC_SETTINGS
|
|
8
|
+
from mp_api.client.core.exceptions import MPContribsClientError
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"ContribsClient",
|
|
12
|
+
"MPContribsClientError",
|
|
13
|
+
"MPCC_SETTINGS",
|
|
14
|
+
"Table",
|
|
15
|
+
"Attachment",
|
|
16
|
+
]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
from io import StringIO
|
|
7
|
+
|
|
8
|
+
from mp_api.client.contribs.settings import MPCC_SETTINGS
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class LogFilter(logging.Filter):
|
|
12
|
+
def __init__(self, level: int, *args, **kwargs) -> None:
|
|
13
|
+
"""Start an instance of logging.Filter.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
level (int) : logging level
|
|
17
|
+
*args : args to pass to logging.Filter
|
|
18
|
+
**kwargs : kwargs to pass to logging.Filter
|
|
19
|
+
"""
|
|
20
|
+
self.level = level
|
|
21
|
+
super().__init__(*args, **kwargs)
|
|
22
|
+
|
|
23
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
24
|
+
"""Filter whether a message is logged.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
record (logging.LogRecord) : message to test if it
|
|
28
|
+
meets threshold for logging.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
bool : True if message should be suppressed.
|
|
32
|
+
"""
|
|
33
|
+
return record.levelno < self.level
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class CustomLoggerAdapter(logging.LoggerAdapter):
|
|
37
|
+
"""Adapter for logger to enable prefixing."""
|
|
38
|
+
|
|
39
|
+
def process(self, msg, kwargs):
|
|
40
|
+
"""Prefix logging message.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
msg (str) : logging message
|
|
44
|
+
kwargs : args to pass to logging.LoggerAdapter
|
|
45
|
+
"""
|
|
46
|
+
prefix = self.extra.get("prefix")
|
|
47
|
+
return f"[{prefix}] {msg}" if prefix else msg, kwargs
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_logger(name: str = "mp_api.client.contribs") -> CustomLoggerAdapter:
|
|
51
|
+
"""Get the default MPContribs logger.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
name (str) : name of the logger
|
|
55
|
+
Returns:
|
|
56
|
+
CustomLoggerAdapter
|
|
57
|
+
"""
|
|
58
|
+
logger = logging.getLogger(name)
|
|
59
|
+
process = os.environ.get("SUPERVISOR_PROCESS_NAME")
|
|
60
|
+
group = os.environ.get("SUPERVISOR_GROUP_NAME")
|
|
61
|
+
cfg = {"prefix": f"{group}/{process}"} if process and group else {}
|
|
62
|
+
info_handler = logging.StreamHandler(sys.stdout)
|
|
63
|
+
error_handler = logging.StreamHandler(sys.stderr)
|
|
64
|
+
info_handler.addFilter(LogFilter(logging.WARNING))
|
|
65
|
+
error_handler.setLevel(max(logging.DEBUG, logging.WARNING))
|
|
66
|
+
logger.handlers = [info_handler, error_handler]
|
|
67
|
+
logger.setLevel(MPCC_SETTINGS.CLIENT_LOG_LEVEL)
|
|
68
|
+
return CustomLoggerAdapter(logger, cfg)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
MPCC_LOGGER = get_logger()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class TqdmToLogger(StringIO):
|
|
75
|
+
logger: logging.LoggerAdapter = MPCC_LOGGER
|
|
76
|
+
level: int | str = MPCC_SETTINGS.CLIENT_LOG_LEVEL
|
|
77
|
+
buf: str = ""
|
|
78
|
+
|
|
79
|
+
def __init__(
|
|
80
|
+
self, logger: logging.LoggerAdapter = MPCC_LOGGER, level: int | None = None
|
|
81
|
+
) -> None:
|
|
82
|
+
"""Start an instance of a TQDM logger.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
logger (logging.Logger) : Logger to pass through
|
|
86
|
+
level (int) : logging level
|
|
87
|
+
"""
|
|
88
|
+
super().__init__()
|
|
89
|
+
self.logger = logger
|
|
90
|
+
self.level = level or logging.INFO
|
|
91
|
+
|
|
92
|
+
def write(self, buf: str) -> int:
|
|
93
|
+
self.buf = buf.strip("\r\n\t ")
|
|
94
|
+
return 1
|
|
95
|
+
|
|
96
|
+
def flush(self) -> None:
|
|
97
|
+
self.logger.log(self.level, self.buf) # type: ignore[arg-type]
|