diff --git a/mp_api/client/core/settings.py b/mp_api/client/core/settings.py index a7b98376..f5818d57 100644 --- a/mp_api/client/core/settings.py +++ b/mp_api/client/core/settings.py @@ -85,9 +85,7 @@ class MAPIClientSettings(BaseSettings): _MAX_LIST_LENGTH, description="Maximum length of query parameter list" ) - ENDPOINT: str = Field( - _DEFAULT_ENDPOINT, description="The default API endpoint to use." - ) + ENDPOINT: str = Field("", description="The default API endpoint to use.") LTOL: float = Field( _EMMET_SETTINGS.LTOL, diff --git a/mp_api/client/core/utils.py b/mp_api/client/core/utils.py index 23c14164..935e1453 100644 --- a/mp_api/client/core/utils.py +++ b/mp_api/client/core/utils.py @@ -1,6 +1,7 @@ from __future__ import annotations import os +import warnings from importlib import import_module from typing import TYPE_CHECKING, Literal from urllib.parse import urljoin @@ -11,7 +12,7 @@ from monty.json import MontyDecoder from packaging.version import parse as parse_version -from mp_api.client.core.exceptions import MPRestError +from mp_api.client.core.exceptions import MPRestError, MPRestWarning from mp_api.client.core.settings import MAPI_CLIENT_SETTINGS if TYPE_CHECKING: @@ -54,7 +55,7 @@ def load_json( return MontyDecoder().process_decoded(data) if deser else data -def validate_api_key(api_key: str | None = None) -> str: +def validate_api_key(api_key: str | None = None) -> str | None: """Find and validate an API key.""" # SETTINGS tries to read API key from ~/.config/.pmgrc.yaml api_key = api_key or os.getenv("MP_API_KEY") @@ -63,11 +64,22 @@ def validate_api_key(api_key: str | None = None) -> str: api_key = PMG_SETTINGS.get("PMG_MAPI_KEY") - if not api_key or len(api_key) != 32: - addendum = " Valid API keys are 32 characters." if api_key else "" + if not api_key: + # The web server requires the client to initialize without an API key. + # Only warn the user if the API key cannot be identified to permit + # the web server to run. + warnings.warn( + "No API key found, please set explicitly or in " + "the `MP_API_KEY` environment variable.", + category=MPRestWarning, + stacklevel=2, + ) + + elif isinstance(api_key, str) and len(api_key) != 32: raise MPRestError( "Please obtain a valid API key from https://materialsproject.org/api " - f"and export it as an environment variable `MP_API_KEY`.{addendum}" + "and export it as an environment variable `MP_API_KEY`. " + "Valid API keys are 32 characters." ) return api_key diff --git a/mp_api/client/mprester.py b/mp_api/client/mprester.py index cebfba1a..1d9afc5c 100644 --- a/mp_api/client/mprester.py +++ b/mp_api/client/mprester.py @@ -52,11 +52,22 @@ "mp_api.client.routes.materials.materials.MaterialsRester" ), **{f"materials/{k}": v for k, v in MATERIALS_RESTERS.items() if k not in {"doi"}}, - "doi": MATERIALS_RESTERS["doi"], **{f"molecules/{k}": v for k, v in MOLECULES_RESTERS.items()}, +} +GENERIC_RESTERS = { + "doi": MATERIALS_RESTERS["doi"], **GENERIC_RESTERS, } +TOP_LEVEL_RESTERS = [ + "molecules/core", + "materials/core", + "_general_store", + "_messages", + "_user_settings", + "doi", +] + class MPRester: """Access the new Materials Project API.""" @@ -179,27 +190,23 @@ def __init__( # Nested rested are then setup to be loaded dynamically with custom __getattr__ functions. self._all_resters = list(RESTER_LAYOUT.values()) - # Instantiate top level molecules and materials resters and set them as attributes - core_suffix = ["molecules/core", "materials/core"] - - core_resters = { - rest_name.split("/")[0]: lazy_rester( - api_key=self.api_key, - endpoint=self.endpoint, - include_user_agent=self._include_user_agent, - session=self.session, - use_document_model=self.use_document_model, - headers=self.headers, - mute_progress_bars=self.mute_progress_bars, - ) - for rest_name, lazy_rester in RESTER_LAYOUT.items() - if rest_name in core_suffix - } - - # Set remaining top level resters, or get an attribute-class name mapping - - for attr, rester in core_resters.items(): - setattr(self, attr, rester) + # Instantiate top level core molecules, materials, and DOI resters, as well + # as the sunder resters to allow the web server to work. + for rest_name, lazy_rester in (RESTER_LAYOUT | GENERIC_RESTERS).items(): + if rest_name in TOP_LEVEL_RESTERS: + setattr( + self, + rest_name.split("/")[0], + lazy_rester( + api_key=self.api_key, + endpoint=self.endpoint, + include_user_agent=self._include_user_agent, + session=self.session, + use_document_model=self.use_document_model, + headers=self.headers, + mute_progress_bars=self.mute_progress_bars, + ), + ) @property def contribs(self): @@ -249,7 +256,11 @@ def __getattr__(self, attr): ) def __dir__(self): - return dir(MPRester) + self._deprecated_attributes + ["materials", "molecules"] + return ( + dir(MPRester) + + self._deprecated_attributes + + [r.split("/", 1)[0] for r in TOP_LEVEL_RESTERS if not r.startswith("_")] + ) def get_task_ids_associated_with_material_id( self, material_id: str, calc_types: list[CalcType] | None = None diff --git a/mp_api/mcp/tools.py b/mp_api/mcp/tools.py index 3642ab67..451ecd96 100644 --- a/mp_api/mcp/tools.py +++ b/mp_api/mcp/tools.py @@ -72,7 +72,8 @@ def search(self, query: str) -> SearchOutput: Args: query (str) : A natural language query of either: - - comma-delimited keywords, example: "polyhedra, orthorhombic, superconductor" + - comma-delimited keywords, example: "polyhedra,orthorhombic,superconductor". + This should contain no whitespace; all whitespace will be removed. - chemical formula, example: "TiO2" - dash-delimited elements for more general chemical system, example: "Li-P-S" To query by formula or chemical system, no commas should be present in the query. @@ -94,11 +95,16 @@ def search(self, query: str) -> SearchOutput: material_ids=material_ids, fields=["description", "material_id"] ) else: - robo_docs += self.client.materials.robocrys.search(query) + robo_docs += self.client.materials.robocrys.search( + query.replace(" ", "").split(",") + ) return SearchOutput( results=[ - FetchResult(id=doc["material_id"], text=doc["description"]) + FetchResult( + id=doc["material_id"], + text=doc["description"], + ) for doc in robo_docs ] ) diff --git a/pyproject.toml b/pyproject.toml index 9a47e0c2..d91f4029 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ dependencies = [ "typing-extensions>=3.7.4.1", "requests>=2.23.0", "monty>=2024.12.10", - "emmet-core>=0.86.3rc0", + "emmet-core>=0.86.3", "boto3", "orjson >= 3.10,<4", ] @@ -33,12 +33,11 @@ dynamic = ["version"] [project.optional-dependencies] mcp = ["fastmcp"] all = [ - "emmet-core[all]>=0.86.2", + "emmet-core[all]>=0.86.3", "custodian", "mpcontribs-client>=5.10", "fastmcp", - "matminer>=0.9.3", - "scipy<1.17.0", # pending fixes in matminer + "matminer>=0.10.0", ] test = [ "pre-commit", diff --git a/requirements/requirements-ubuntu-latest_py3.11.txt b/requirements/requirements-ubuntu-latest_py3.11.txt index b7c060a9..b83dc92a 100644 --- a/requirements/requirements-ubuntu-latest_py3.11.txt +++ b/requirements/requirements-ubuntu-latest_py3.11.txt @@ -6,13 +6,13 @@ # annotated-types==0.7.0 # via pydantic -bibtexparser==1.4.3 +bibtexparser==1.4.4 # via pymatgen blake3==1.0.8 # via emmet-core -boto3==1.42.30 +boto3==1.42.38 # via mp-api (pyproject.toml) -botocore==1.42.30 +botocore==1.42.38 # via # boto3 # s3transfer @@ -24,13 +24,13 @@ contourpy==1.3.3 # via matplotlib cycler==0.12.1 # via matplotlib -emmet-core==0.87.0.dev4 +emmet-core==0.86.3 # via mp-api (pyproject.toml) fonttools==4.61.1 # via matplotlib idna==3.11 # via requests -jmespath==1.0.1 +jmespath==1.1.0 # via # boto3 # botocore @@ -49,8 +49,6 @@ monty==2025.3.3 # pymatgen mpmath==1.3.0 # via sympy -msgpack==1.1.2 - # via mp-api (pyproject.toml) narwhals==2.15.0 # via plotly networkx==3.6.1 @@ -65,17 +63,17 @@ numpy==2.4.1 # pymatgen-io-validation # scipy # spglib -orjson==3.11.5 +orjson==3.11.6 # via # mp-api (pyproject.toml) # pymatgen -packaging==25.0 +packaging==26.0 # via # matplotlib # plotly palettable==3.3.3 # via pymatgen -pandas==2.3.3 +pandas==3.0.0 # via pymatgen pillow==12.1.0 # via matplotlib @@ -101,7 +99,7 @@ pymatgen==2025.10.7 # pymatgen-io-validation pymatgen-io-validation==0.1.2 # via emmet-core -pyparsing==3.3.1 +pyparsing==3.3.2 # via # bibtexparser # matplotlib @@ -112,8 +110,6 @@ python-dateutil==2.9.0.post0 # pandas python-dotenv==1.2.1 # via pydantic-settings -pytz==2025.2 - # via pandas pyyaml==6.0.3 # via pybtex requests==2.32.5 @@ -127,12 +123,10 @@ ruamel-yaml==0.19.1 # pymatgen s3transfer==0.16.0 # via boto3 -scipy==1.16.3 +scipy==1.17.0 # via pymatgen six==1.17.0 # via python-dateutil -smart-open==7.5.0 - # via mp-api (pyproject.toml) spglib==2.7.0 # via pymatgen sympy==1.14.0 @@ -154,13 +148,9 @@ typing-inspection==0.4.2 # via # pydantic # pydantic-settings -tzdata==2025.3 - # via pandas -uncertainties==3.2.4 +uncertainties==3.2.3 # via pymatgen urllib3==2.6.3 # via # botocore # requests -wrapt==2.0.1 - # via smart-open diff --git a/requirements/requirements-ubuntu-latest_py3.11_extras.txt b/requirements/requirements-ubuntu-latest_py3.11_extras.txt index 1c26d0ef..ffc1a886 100644 --- a/requirements/requirements-ubuntu-latest_py3.11_extras.txt +++ b/requirements/requirements-ubuntu-latest_py3.11_extras.txt @@ -35,17 +35,15 @@ beartype==0.22.9 # via # py-key-value-aio # py-key-value-shared -bibtexparser==1.4.3 +bibtexparser==1.4.4 # via pymatgen blake3==1.0.8 # via emmet-core boltons==25.0.0 # via mpcontribs-client -boto3==1.42.30 - # via - # mp-api - # mp-api (pyproject.toml) -botocore==1.42.30 +boto3==1.42.38 + # via mp-api (pyproject.toml) +botocore==1.42.38 # via # boto3 # s3transfer @@ -53,7 +51,7 @@ bravado==12.0.1 # via mpcontribs-client bravado-core==6.1.1 # via bravado -cachetools==6.2.4 +cachetools==6.2.6 # via # mpcontribs-client # py-key-value-aio @@ -76,9 +74,9 @@ cloudpickle==3.1.2 # via pydocket contourpy==1.3.3 # via matplotlib -coverage[toml]==7.13.1 +coverage[toml]==7.13.2 # via pytest-cov -cryptography==46.0.3 +cryptography==46.0.4 # via # authlib # pyjwt @@ -87,7 +85,7 @@ custodian==2025.12.14 # via mp-api (pyproject.toml) cycler==0.12.1 # via matplotlib -cyclopts==4.5.0 +cyclopts==4.5.1 # via fastmcp decorator==5.2.1 # via ipython @@ -108,10 +106,8 @@ docutils==0.22.4 # sphinx email-validator==2.3.0 # via pydantic -emmet-core[all]==0.87.0.dev4 - # via - # mp-api - # mp-api (pyproject.toml) +emmet-core[all]==0.86.3 + # via mp-api (pyproject.toml) exceptiongroup==1.3.1 # via fastmcp execnet==2.1.2 @@ -120,7 +116,7 @@ executing==2.2.1 # via stack-data fakeredis[lua]==2.33.0 # via pydocket -fastmcp==2.14.3 +fastmcp==2.14.4 # via mp-api (pyproject.toml) filelock==3.20.3 # via virtualenv @@ -193,7 +189,7 @@ jeepney==0.9.0 # secretstorage jinja2==3.1.6 # via sphinx -jmespath==1.0.1 +jmespath==1.1.0 # via # boto3 # botocore @@ -207,7 +203,9 @@ json2html==1.3.0 jsonpointer==3.0.0 # via jsonschema jsonref==1.1.0 - # via bravado-core + # via + # bravado-core + # fastmcp jsonschema[format-nongpl]==4.26.0 # via # bravado-core @@ -235,9 +233,10 @@ markdown-it-py==4.0.0 # via rich markupsafe==3.0.3 # via jinja2 -matminer==0.9.3 +matminer==0.10.0 # via # emmet-core + # mp-api (pyproject.toml) # robocrys matplotlib==3.10.8 # via @@ -248,7 +247,7 @@ matplotlib-inline==0.2.1 # via ipython mccabe==0.7.0 # via flake8 -mcp==1.25.0 +mcp==1.26.0 # via fastmcp mdurl==0.1.2 # via markdown-it-py @@ -259,7 +258,6 @@ monty==2025.3.3 # custodian # emmet-core # matminer - # mp-api # mp-api (pyproject.toml) # pymatgen # robocrys @@ -268,8 +266,6 @@ more-itertools==10.8.0 # inflect # jaraco-classes # jaraco-functools -mp-api[mcp]==0.45.15 - # via mp-api (pyproject.toml) mp-pyrho==0.5.1 # via pymatgen-analysis-defects mpcontribs-client==5.10.4 @@ -280,8 +276,6 @@ msgpack==1.1.2 # via # bravado # bravado-core - # mp-api - # mp-api (pyproject.toml) mypy==1.19.1 # via mp-api (pyproject.toml) mypy-extensions==1.1.0 @@ -339,13 +333,13 @@ opentelemetry-semantic-conventions==0.60b1 # via # opentelemetry-instrumentation # opentelemetry-sdk -orjson==3.11.5 +orjson==3.11.6 # via - # mp-api # mp-api (pyproject.toml) # pymatgen -packaging==25.0 +packaging==26.0 # via + # fastmcp # lazy-loader # matplotlib # opentelemetry-instrumentation @@ -365,7 +359,7 @@ parso==0.8.5 # via jedi pathable==0.4.4 # via jsonschema-path -pathspec==1.0.3 +pathspec==1.0.4 # via mypy pathvalidate==3.3.1 # via py-key-value-aio @@ -399,7 +393,7 @@ prometheus-client==0.24.1 # pydocket prompt-toolkit==3.0.52 # via ipython -psutil==7.2.1 +psutil==7.2.2 # via custodian ptyprocess==0.7.0 # via pexpect @@ -413,7 +407,7 @@ py-key-value-aio[disk,keyring,memory,redis]==0.3.0 # pydocket py-key-value-shared==0.3.0 # via py-key-value-aio -pyarrow==22.0.0 +pyarrow==23.0.0 # via emmet-core pybtex==0.25.1 # via @@ -423,7 +417,7 @@ pycodestyle==2.14.0 # via # flake8 # mp-api (pyproject.toml) -pycparser==2.23 +pycparser==3.0 # via cffi pydantic[email]==2.12.5 # via @@ -459,7 +453,6 @@ pymatgen==2025.10.7 # via # emmet-core # matminer - # mp-api # mp-api (pyproject.toml) # mp-pyrho # mpcontribs-client @@ -480,7 +473,7 @@ pymongo==4.16.0 # via # matminer # mpcontribs-client -pyparsing==3.3.1 +pyparsing==3.3.2 # via # bibtexparser # matplotlib @@ -515,7 +508,7 @@ python-dotenv==1.2.1 # pydantic-settings python-json-logger==4.0.0 # via pydocket -python-multipart==0.0.21 +python-multipart==0.0.22 # via mcp pytz==2025.2 # via @@ -545,7 +538,6 @@ requests==2.32.5 # bravado-core # jsonschema-path # matminer - # mp-api # mp-api (pyproject.toml) # pymatgen # pymatgen-io-validation @@ -559,7 +551,7 @@ rfc3986-validator==0.1.1 # via jsonschema rfc3987-syntax==1.1.0 # via jsonschema -rich==14.2.0 +rich==14.3.1 # via # cyclopts # fastmcp @@ -568,7 +560,7 @@ rich==14.2.0 # typer rich-rst==1.3.2 # via cyclopts -robocrys==0.2.12 +robocrys==0.2.13 # via emmet-core roman-numerals==4.1.0 # via sphinx @@ -587,9 +579,10 @@ scikit-image==0.26.0 # via pymatgen-analysis-defects scikit-learn==1.8.0 # via matminer -scipy==1.16.3 +scipy==1.17.0 # via # ase + # matminer # pymatgen # robocrys # scikit-image @@ -598,7 +591,7 @@ seaborn==0.13.2 # via pymatgen-analysis-diffusion secretstorage==3.5.0 # via keyring -seekpath==2.1.0 +seekpath==2.2.0 # via emmet-core semantic-version==2.10.0 # via mpcontribs-client @@ -617,10 +610,6 @@ six==1.17.0 # flatten-dict # python-dateutil # rfc3339-validator -smart-open==7.5.0 - # via - # mp-api - # mp-api (pyproject.toml) snowballstemmer==3.0.1 # via sphinx sortedcontainers==2.4.0 @@ -644,11 +633,11 @@ sphinxcontrib-qthelp==2.0.0 # via sphinx sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sse-starlette==3.1.2 +sse-starlette==3.2.0 # via mcp stack-data==0.6.3 # via ipython -starlette==0.51.0 +starlette==0.52.1 # via # mcp # sse-starlette @@ -664,7 +653,7 @@ tabulate==0.9.0 # via pymatgen threadpoolctl==3.6.0 # via scikit-learn -tifffile==2026.1.14 +tifffile==2026.1.28 # via scikit-image tqdm==4.67.1 # via @@ -681,7 +670,7 @@ typer==0.21.1 # via pydocket types-requests==2.32.4.20260107 # via mp-api (pyproject.toml) -types-setuptools==80.9.0.20251223 +types-setuptools==80.10.0.20260124 # via mp-api (pyproject.toml) typing-extensions==4.15.0 # via @@ -694,7 +683,6 @@ typing-extensions==4.15.0 # flexparser # ipython # mcp - # mp-api # mp-api (pyproject.toml) # mypy # opentelemetry-api @@ -724,7 +712,7 @@ tzdata==2025.3 # pandas ujson==5.11.0 # via mpcontribs-client -uncertainties==3.2.4 +uncertainties==3.2.3 # via pymatgen uri-template==1.3.0 # via jsonschema @@ -739,15 +727,13 @@ uvicorn==0.40.0 # mcp virtualenv==20.36.1 # via pre-commit -wcwidth==0.2.14 +wcwidth==0.5.2 # via prompt-toolkit webcolors==25.10.0 # via jsonschema websockets==16.0 # via fastmcp wrapt==1.17.3 - # via - # opentelemetry-instrumentation - # smart-open + # via opentelemetry-instrumentation zipp==3.23.0 # via importlib-metadata diff --git a/requirements/requirements-ubuntu-latest_py3.12.txt b/requirements/requirements-ubuntu-latest_py3.12.txt index 12285056..9822afda 100644 --- a/requirements/requirements-ubuntu-latest_py3.12.txt +++ b/requirements/requirements-ubuntu-latest_py3.12.txt @@ -6,13 +6,13 @@ # annotated-types==0.7.0 # via pydantic -bibtexparser==1.4.3 +bibtexparser==1.4.4 # via pymatgen blake3==1.0.8 # via emmet-core -boto3==1.42.30 +boto3==1.42.38 # via mp-api (pyproject.toml) -botocore==1.42.30 +botocore==1.42.38 # via # boto3 # s3transfer @@ -24,13 +24,13 @@ contourpy==1.3.3 # via matplotlib cycler==0.12.1 # via matplotlib -emmet-core==0.87.0.dev4 +emmet-core==0.86.3 # via mp-api (pyproject.toml) fonttools==4.61.1 # via matplotlib idna==3.11 # via requests -jmespath==1.0.1 +jmespath==1.1.0 # via # boto3 # botocore @@ -49,8 +49,6 @@ monty==2025.3.3 # pymatgen mpmath==1.3.0 # via sympy -msgpack==1.1.2 - # via mp-api (pyproject.toml) narwhals==2.15.0 # via plotly networkx==3.6.1 @@ -65,17 +63,17 @@ numpy==2.4.1 # pymatgen-io-validation # scipy # spglib -orjson==3.11.5 +orjson==3.11.6 # via # mp-api (pyproject.toml) # pymatgen -packaging==25.0 +packaging==26.0 # via # matplotlib # plotly palettable==3.3.3 # via pymatgen -pandas==2.3.3 +pandas==3.0.0 # via pymatgen pillow==12.1.0 # via matplotlib @@ -101,7 +99,7 @@ pymatgen==2025.10.7 # pymatgen-io-validation pymatgen-io-validation==0.1.2 # via emmet-core -pyparsing==3.3.1 +pyparsing==3.3.2 # via # bibtexparser # matplotlib @@ -112,8 +110,6 @@ python-dateutil==2.9.0.post0 # pandas python-dotenv==1.2.1 # via pydantic-settings -pytz==2025.2 - # via pandas pyyaml==6.0.3 # via pybtex requests==2.32.5 @@ -127,12 +123,10 @@ ruamel-yaml==0.19.1 # pymatgen s3transfer==0.16.0 # via boto3 -scipy==1.16.3 +scipy==1.17.0 # via pymatgen six==1.17.0 # via python-dateutil -smart-open==7.5.0 - # via mp-api (pyproject.toml) spglib==2.7.0 # via pymatgen sympy==1.14.0 @@ -153,13 +147,9 @@ typing-inspection==0.4.2 # via # pydantic # pydantic-settings -tzdata==2025.3 - # via pandas -uncertainties==3.2.4 +uncertainties==3.2.3 # via pymatgen urllib3==2.6.3 # via # botocore # requests -wrapt==2.0.1 - # via smart-open diff --git a/requirements/requirements-ubuntu-latest_py3.12_extras.txt b/requirements/requirements-ubuntu-latest_py3.12_extras.txt index 5a7a8773..6c0f7e0e 100644 --- a/requirements/requirements-ubuntu-latest_py3.12_extras.txt +++ b/requirements/requirements-ubuntu-latest_py3.12_extras.txt @@ -33,17 +33,15 @@ beartype==0.22.9 # via # py-key-value-aio # py-key-value-shared -bibtexparser==1.4.3 +bibtexparser==1.4.4 # via pymatgen blake3==1.0.8 # via emmet-core boltons==25.0.0 # via mpcontribs-client -boto3==1.42.30 - # via - # mp-api - # mp-api (pyproject.toml) -botocore==1.42.30 +boto3==1.42.38 + # via mp-api (pyproject.toml) +botocore==1.42.38 # via # boto3 # s3transfer @@ -51,7 +49,7 @@ bravado==12.0.1 # via mpcontribs-client bravado-core==6.1.1 # via bravado -cachetools==6.2.4 +cachetools==6.2.6 # via # mpcontribs-client # py-key-value-aio @@ -74,9 +72,9 @@ cloudpickle==3.1.2 # via pydocket contourpy==1.3.3 # via matplotlib -coverage[toml]==7.13.1 +coverage[toml]==7.13.2 # via pytest-cov -cryptography==46.0.3 +cryptography==46.0.4 # via # authlib # pyjwt @@ -85,7 +83,7 @@ custodian==2025.12.14 # via mp-api (pyproject.toml) cycler==0.12.1 # via matplotlib -cyclopts==4.5.0 +cyclopts==4.5.1 # via fastmcp decorator==5.2.1 # via ipython @@ -106,10 +104,8 @@ docutils==0.22.4 # sphinx email-validator==2.3.0 # via pydantic -emmet-core[all]==0.87.0.dev4 - # via - # mp-api - # mp-api (pyproject.toml) +emmet-core[all]==0.86.3 + # via mp-api (pyproject.toml) exceptiongroup==1.3.1 # via fastmcp execnet==2.1.2 @@ -118,7 +114,7 @@ executing==2.2.1 # via stack-data fakeredis[lua]==2.33.0 # via pydocket -fastmcp==2.14.3 +fastmcp==2.14.4 # via mp-api (pyproject.toml) filelock==3.20.3 # via virtualenv @@ -189,7 +185,7 @@ jeepney==0.9.0 # secretstorage jinja2==3.1.6 # via sphinx -jmespath==1.0.1 +jmespath==1.1.0 # via # boto3 # botocore @@ -203,7 +199,9 @@ json2html==1.3.0 jsonpointer==3.0.0 # via jsonschema jsonref==1.1.0 - # via bravado-core + # via + # bravado-core + # fastmcp jsonschema[format-nongpl]==4.26.0 # via # bravado-core @@ -231,9 +229,10 @@ markdown-it-py==4.0.0 # via rich markupsafe==3.0.3 # via jinja2 -matminer==0.9.3 +matminer==0.10.0 # via # emmet-core + # mp-api (pyproject.toml) # robocrys matplotlib==3.10.8 # via @@ -244,7 +243,7 @@ matplotlib-inline==0.2.1 # via ipython mccabe==0.7.0 # via flake8 -mcp==1.25.0 +mcp==1.26.0 # via fastmcp mdurl==0.1.2 # via markdown-it-py @@ -255,7 +254,6 @@ monty==2025.3.3 # custodian # emmet-core # matminer - # mp-api # mp-api (pyproject.toml) # pymatgen # robocrys @@ -264,8 +262,6 @@ more-itertools==10.8.0 # inflect # jaraco-classes # jaraco-functools -mp-api[mcp]==0.45.15 - # via mp-api (pyproject.toml) mp-pyrho==0.5.1 # via pymatgen-analysis-defects mpcontribs-client==5.10.4 @@ -276,8 +272,6 @@ msgpack==1.1.2 # via # bravado # bravado-core - # mp-api - # mp-api (pyproject.toml) mypy==1.19.1 # via mp-api (pyproject.toml) mypy-extensions==1.1.0 @@ -335,13 +329,13 @@ opentelemetry-semantic-conventions==0.60b1 # via # opentelemetry-instrumentation # opentelemetry-sdk -orjson==3.11.5 +orjson==3.11.6 # via - # mp-api # mp-api (pyproject.toml) # pymatgen -packaging==25.0 +packaging==26.0 # via + # fastmcp # lazy-loader # matplotlib # opentelemetry-instrumentation @@ -361,7 +355,7 @@ parso==0.8.5 # via jedi pathable==0.4.4 # via jsonschema-path -pathspec==1.0.3 +pathspec==1.0.4 # via mypy pathvalidate==3.3.1 # via py-key-value-aio @@ -395,7 +389,7 @@ prometheus-client==0.24.1 # pydocket prompt-toolkit==3.0.52 # via ipython -psutil==7.2.1 +psutil==7.2.2 # via custodian ptyprocess==0.7.0 # via pexpect @@ -409,7 +403,7 @@ py-key-value-aio[disk,keyring,memory,redis]==0.3.0 # pydocket py-key-value-shared==0.3.0 # via py-key-value-aio -pyarrow==22.0.0 +pyarrow==23.0.0 # via emmet-core pybtex==0.25.1 # via @@ -419,7 +413,7 @@ pycodestyle==2.14.0 # via # flake8 # mp-api (pyproject.toml) -pycparser==2.23 +pycparser==3.0 # via cffi pydantic[email]==2.12.5 # via @@ -455,7 +449,6 @@ pymatgen==2025.10.7 # via # emmet-core # matminer - # mp-api # mp-api (pyproject.toml) # mp-pyrho # mpcontribs-client @@ -476,7 +469,7 @@ pymongo==4.16.0 # via # matminer # mpcontribs-client -pyparsing==3.3.1 +pyparsing==3.3.2 # via # bibtexparser # matplotlib @@ -511,7 +504,7 @@ python-dotenv==1.2.1 # pydantic-settings python-json-logger==4.0.0 # via pydocket -python-multipart==0.0.21 +python-multipart==0.0.22 # via mcp pytz==2025.2 # via @@ -541,7 +534,6 @@ requests==2.32.5 # bravado-core # jsonschema-path # matminer - # mp-api # mp-api (pyproject.toml) # pymatgen # pymatgen-io-validation @@ -555,7 +547,7 @@ rfc3986-validator==0.1.1 # via jsonschema rfc3987-syntax==1.1.0 # via jsonschema -rich==14.2.0 +rich==14.3.1 # via # cyclopts # fastmcp @@ -564,7 +556,7 @@ rich==14.2.0 # typer rich-rst==1.3.2 # via cyclopts -robocrys==0.2.12 +robocrys==0.2.13 # via emmet-core roman-numerals==4.1.0 # via sphinx @@ -583,9 +575,10 @@ scikit-image==0.26.0 # via pymatgen-analysis-defects scikit-learn==1.8.0 # via matminer -scipy==1.16.3 +scipy==1.17.0 # via # ase + # matminer # pymatgen # robocrys # scikit-image @@ -594,7 +587,7 @@ seaborn==0.13.2 # via pymatgen-analysis-diffusion secretstorage==3.5.0 # via keyring -seekpath==2.1.0 +seekpath==2.2.0 # via emmet-core semantic-version==2.10.0 # via mpcontribs-client @@ -613,10 +606,6 @@ six==1.17.0 # flatten-dict # python-dateutil # rfc3339-validator -smart-open==7.5.0 - # via - # mp-api - # mp-api (pyproject.toml) snowballstemmer==3.0.1 # via sphinx sortedcontainers==2.4.0 @@ -640,11 +629,11 @@ sphinxcontrib-qthelp==2.0.0 # via sphinx sphinxcontrib-serializinghtml==2.0.0 # via sphinx -sse-starlette==3.1.2 +sse-starlette==3.2.0 # via mcp stack-data==0.6.3 # via ipython -starlette==0.51.0 +starlette==0.52.1 # via # mcp # sse-starlette @@ -660,7 +649,7 @@ tabulate==0.9.0 # via pymatgen threadpoolctl==3.6.0 # via scikit-learn -tifffile==2026.1.14 +tifffile==2026.1.28 # via scikit-image tqdm==4.67.1 # via @@ -677,7 +666,7 @@ typer==0.21.1 # via pydocket types-requests==2.32.4.20260107 # via mp-api (pyproject.toml) -types-setuptools==80.9.0.20251223 +types-setuptools==80.10.0.20260124 # via mp-api (pyproject.toml) typing-extensions==4.15.0 # via @@ -688,7 +677,6 @@ typing-extensions==4.15.0 # flexcache # flexparser # mcp - # mp-api # mp-api (pyproject.toml) # mypy # opentelemetry-api @@ -718,7 +706,7 @@ tzdata==2025.3 # pandas ujson==5.11.0 # via mpcontribs-client -uncertainties==3.2.4 +uncertainties==3.2.3 # via pymatgen uri-template==1.3.0 # via jsonschema @@ -733,15 +721,13 @@ uvicorn==0.40.0 # mcp virtualenv==20.36.1 # via pre-commit -wcwidth==0.2.14 +wcwidth==0.5.2 # via prompt-toolkit webcolors==25.10.0 # via jsonschema websockets==16.0 # via fastmcp wrapt==1.17.3 - # via - # opentelemetry-instrumentation - # smart-open + # via opentelemetry-instrumentation zipp==3.23.0 # via importlib-metadata diff --git a/tests/client/core/test_utils.py b/tests/client/core/test_utils.py index b9cba460..c8916a3c 100644 --- a/tests/client/core/test_utils.py +++ b/tests/client/core/test_utils.py @@ -1,9 +1,8 @@ """Test client core utilities.""" -from packaging.version import parse as parse_version import pytest -from mp_api.client.core.exceptions import MPRestError +from mp_api.client.core.exceptions import MPRestError, MPRestWarning from mp_api.client.core.utils import LazyImport @@ -145,7 +144,7 @@ def test_api_key_validation(monkeypatch: pytest.MonkeyPatch): with pytest.raises(MPRestError, match="32 characters"): validate_api_key("invalid_key") - with pytest.raises(MPRestError, match="Please obtain a valid"): + with pytest.warns(MPRestWarning, match="No API key found"): validate_api_key() junk_api_key = "a" * 32 diff --git a/tests/client/test_mprester.py b/tests/client/test_mprester.py index f85a621a..63774a49 100644 --- a/tests/client/test_mprester.py +++ b/tests/client/test_mprester.py @@ -430,8 +430,8 @@ def test_get_default_api_key_endpoint(self, monkeypatch: pytest.MonkeyPatch): monkeypatch.delenv("MP_API_KEY", raising=False) monkeypatch.delenv("PMG_MAPI_KEY", raising=False) monkeypatch.setitem(SETTINGS, "PMG_MAPI_KEY", None) - with pytest.raises(MPRestError, match="Please obtain a valid API key"): - MPRester().get_structure_by_material_id("mp-149") + with pytest.warns(MPRestWarning, match="No API key found"): + MPRester() def test_invalid_api_key(self, monkeypatch): monkeypatch.setenv("MP_API_KEY", "INVALID")