import os import sys from typing import Dict, Any # Workaround for Python 3.10: Add NotRequired to typing module if sys.version_info < (3, 11): try: from typing_extensions import NotRequired import typing if not hasattr(typing, 'NotRequired'): typing.NotRequired = NotRequired except ImportError: pass # Try to import MPRester, handle case where key is missing/invalid gracefully try: from mp_api.client import MPRester except ImportError: MPRester = None class MaterialsProjectAdapter: def __init__(self, api_key: str = None): self.api_key = api_key self.has_key = api_key is not None and len(api_key) > 10 and MPRester is not None def get_material_properties(self, formula: str) -> Dict[str, Any]: print(f"CONTACTING MATERIALS PROJECT: {formula}...") if self.has_key: try: with MPRester(self.api_key) as mpr: docs = mpr.materials.summary.search( formula=[formula], fields=["band_gap", "volume", "formation_energy_per_atom"] ) if docs: best_match = min(docs, key=lambda x: x.formation_energy_per_atom) return { "source": "Materials Project (Real Data)", "band_gap": float(best_match.band_gap), "volume": float(best_match.volume), "is_estimated": False } except Exception as e: print(f"❌ API ERROR: {str(e)}. Switching to fallback.") # Fallback if no key or API fails return self._generate_fallback(formula) def _generate_fallback(self, formula: str) -> Dict[str, Any]: return { "source": "Theoretical Estimation (Fallback)", "band_gap": 2.0, "volume": 200.0, "is_estimated": True }