diff --git a/pymatgen/core/composition.py b/pymatgen/core/composition.py index aefdb5045d7..d3d498806ce 100644 --- a/pymatgen/core/composition.py +++ b/pymatgen/core/composition.py @@ -767,11 +767,12 @@ def oxi_state_guesses( element's common oxidation states, e.g. {"V": [2,3,4,5]} target_charge (int): the desired total charge on the structure. Default is 0 signifying charge balance. - all_oxi_states (bool): if True, an element defaults to - all oxidation states in pymatgen Element.icsd_oxidation_states. - Otherwise, default is Element.common_oxidation_states. Note - that the full oxidation state list is *very* inclusive and - can produce nonsensical results. + all_oxi_states (bool): if True, all oxidation states of an element, even rare ones, are used in the search + for guesses. However, the full oxidation state list is *very* inclusive and can produce nonsensical + results. If False, the icsd_oxidation_states list is used when present, or the common_oxidation_states + is used when icsd_oxidation_states is not present. These oxidation states lists comprise more + commonly occurring oxidation states and results in more reliable guesses, albeit at the cost of + missing some uncommon situations. The default is False. max_sites (int): if possible, will reduce Compositions to at most this many sites to speed up oxidation state guesses. If the composition cannot be reduced to this many sites a ValueError @@ -859,11 +860,12 @@ def add_charges_from_oxi_state_guesses( element's common oxidation states, e.g. {"V": [2, 3, 4, 5]} target_charge (float): the desired total charge on the structure. Default is 0 signifying charge balance. - all_oxi_states (bool): If True, an element defaults to - all oxidation states in pymatgen Element.icsd_oxidation_states. - Otherwise, default is Element.common_oxidation_states. Note - that the full oxidation state list is *very* inclusive and - can produce nonsensical results. + all_oxi_states (bool): if True, all oxidation states of an element, even rare ones, are used in the search + for guesses. However, the full oxidation state list is *very* inclusive and can produce nonsensical + results. If False, the icsd_oxidation_states list is used when present, or the common_oxidation_states + is used when icsd_oxidation_states is not present. These oxidation states lists comprise more + commonly occurring oxidation states and results in more reliable guesses, albeit at the cost of + missing some uncommon situations. The default is False. max_sites (int): If possible, will reduce Compositions to at most this many sites to speed up oxidation state guesses. If the composition cannot be reduced to this many sites a ValueError @@ -916,15 +918,15 @@ def _get_oxi_state_guesses( calculation of the most likely oxidation states Args: - oxi_states_override (dict): dict of str->list to override an - element's common oxidation states, e.g. {"V": [2,3,4,5]} - target_charge (float): the desired total charge on the structure. - Default is 0 signifying charge balance. - all_oxi_states (bool): if True, an element defaults to - all oxidation states in pymatgen Element.icsd_oxidation_states. - Otherwise, default is Element.common_oxidation_states. Note - that the full oxidation state list is *very* inclusive and - can produce nonsensical results. + oxi_states_override (dict): dict of str->list to override an element's common oxidation states, e.g. + {"V": [2,3,4,5]}. + target_charge (float): the desired total charge on the structure. Default is 0 signifying charge balance. + all_oxi_states (bool): if True, all oxidation states of an element, even rare ones, are used in the search + for guesses. However, the full oxidation state list is *very* inclusive and can produce nonsensical + results. If False, the icsd_oxidation_states list is used when present, or the common_oxidation_states + is used when icsd_oxidation_states is not present. These oxidation states lists comprise more + commonly occurring oxidation states and results in more reliable guesses, albeit at the cost of + missing some uncommon situations. The default is False. max_sites (int): if possible, will reduce Compositions to at most this many sites to speed up oxidation state guesses. If the composition cannot be reduced to this many sites a ValueError @@ -980,7 +982,7 @@ def _get_oxi_state_guesses( elif all_oxi_states: oxids = Element(el).oxidation_states else: - oxids = Element(el).icsd_oxidation_states or Element(el).oxidation_states + oxids = Element(el).icsd_oxidation_states or Element(el).common_oxidation_states # Get all possible combinations of oxidation states # and sum each combination diff --git a/pymatgen/core/structure.py b/pymatgen/core/structure.py index b82f2076f12..4ef2682e619 100644 --- a/pymatgen/core/structure.py +++ b/pymatgen/core/structure.py @@ -64,6 +64,7 @@ from pymatgen.util.typing import CompositionLike, MillerIndex, PathLike, PbcLike, SpeciesLike FileFormats = Literal["cif", "poscar", "cssr", "json", "yaml", "yml", "xsf", "mcsqs", "res", "pwmat", ""] +StructureSources = Literal["Materials Project", "COD"] class Neighbor(Site): @@ -2937,6 +2938,28 @@ def to(self, filename: PathLike = "", fmt: FileFormats = "", **kwargs) -> str: writer.write_file(filename) return str(writer) + @classmethod + def from_id(cls, id: str, source: StructureSources = "Materials Project", **kwargs) -> Structure: + """ + Load a structure file based on an id, usually from an online source. + + Args: + id: The id. E.g., the materials project id. + source: Source of the data. Defaults to "Materials Project". + **kwargs: Pass-through to any API calls. + """ + if source == "Materials Project": + from pymatgen.ext.matproj import MPRester + + mpr = MPRester(**kwargs) + return mpr.get_structure_by_material_id(id) # type: ignore + if source == "COD": + from pymatgen.ext.cod import COD + + cod = COD() + return cod.get_structure_by_id(int(id)) + raise ValueError(f"Invalid source: {source}") + @classmethod def from_str( # type: ignore[override] cls, diff --git a/pymatgen/ext/matproj.py b/pymatgen/ext/matproj.py index 79654f68da9..a7ccd0801b3 100644 --- a/pymatgen/ext/matproj.py +++ b/pymatgen/ext/matproj.py @@ -229,7 +229,7 @@ def get_structure_by_material_id(self, material_id: str, conventional_unit_cell: Structure object. """ prop = "structure" - response = self.request(f"materials/summary/{material_id}/?_fields={prop}") + response = self.request(f"materials/summary?material_ids={material_id}&_fields={prop}") structure = response[0][prop] if conventional_unit_cell: return SpacegroupAnalyzer(structure).get_conventional_standard_structure() diff --git a/pymatgen/util/testing/__init__.py b/pymatgen/util/testing/__init__.py index c95fff8eada..fcaa9b46724 100644 --- a/pymatgen/util/testing/__init__.py +++ b/pymatgen/util/testing/__init__.py @@ -1,8 +1,8 @@ -"""Common test support for pymatgen test scripts. +"""This module implements testing utilities for materials science codes. -This single module should provide all the common functionality for pymatgen -tests in a single location, so that test scripts can just import it and work -right away. +While the primary use is within pymatgen, the functionality is meant to be useful for external materials science +codes as well. For instance, obtaining example crystal structures to perform tests, specialized assert methods for +materials science, etc. """ from __future__ import annotations diff --git a/pyproject.toml b/pyproject.toml index 22da05a9b2a..155b7d4bf1f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,167 @@ [build-system] requires = [ - "Cython>=0.29.23", - # pin NumPy version used in the build - "oldest-supported-numpy", - "setuptools>=65.0.0", + "Cython>=0.29.23", + # pin NumPy version used in the build + "oldest-supported-numpy", + "setuptools>=65.0.0", ] build-backend = "setuptools.build_meta" + +[project] +name = "pymatgen" +authors = [ + { name = "Pymatgen Development Team", email = "ongsp@ucsd.edu" }, +] +description = """ +Python Materials Genomics is a robust materials analysis code that defines core object representations for structures +and molecules with support for many electronic structure codes. It is currently the core analysis code powering the +Materials Project (https://materialsproject.org).""" +readme = "README.md" +requires-python = ">=3.9" +keywords = [ + "ABINIT", + "analysis", + "crystal", + "diagrams", + "electronic", + "gaussian", + "materials", + "nwchem", + "phase", + "project", + "qchem", + "science", + "structure", + "VASP", +] +license = { text = "MIT" } +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3", + "Topic :: Scientific/Engineering :: Chemistry", + "Topic :: Scientific/Engineering :: Information Analysis", + "Topic :: Scientific/Engineering :: Physics", + "Topic :: Software Development :: Libraries :: Python Modules", +] +dependencies = [ + "matplotlib>=3.8", + "monty>=2024.5.24", + "networkx>=2.2", + "numpy>=1.25.0", + "palettable>=3.1.1", + "pandas>=2", + "plotly>=4.5.0", + "pybtex>=0.24.0", + "requests>=2.32", + "ruamel.yaml>=0.17.0", + "scipy>=1.13.0", + "spglib>=2.0.2", + "sympy>=1.2", + "tabulate>=0.9", + "tqdm>=4.60", + "uncertainties>=3.1.4", + "joblib>=1", +] +version = "2024.6.10" + +[project.urls] +Homepage = "https://pymatgen.org" +Documentation = "https://pymatgen.org" +Repository = "https://github.com/materialsproject/pymatgen" +Issues = "https://github.com/materialsproject/pymatgen/issues" +Pypi = "https://pypi.org/project/pymatgen" + +[project.optional-dependencies] +ase = ["ase>=3.23.0"] +# don't depend on tblite above 3.11 since unsupported https://github.com/tblite/tblite/issues/175 +tblite = ["tblite[ase]>=0.3.0; python_version<'3.12'"] +vis = ["vtk>=6.0.0"] +abinit = ["netcdf4>=1.6.5"] +mlp = ["matgl>=1.1.1", "chgnet>=0.3.8"] +electronic_structure = ["fdint>=2.0.2"] +dev = [ + "mypy>=1.10.0", + "pre-commit>=3", + "pytest-cov>=4", + "pytest-split>=0.8", + "pytest>8", + "ruff>=0.4", +] +ci = [ + "pytest>=8", + "pytest-cov>=4", + "pytest-split>=0.8", +] +docs = [ + "sphinx", + "sphinx_rtd_theme", + "doc2dash", +] +optional = [ + "ase>=3.23.0", + # TODO restore BoltzTraP2 when install fixed, hopefully following merge of + # https://gitlab.com/sousaw/BoltzTraP2/-/merge_requests/18 + # caused CI failure due to ModuleNotFoundError: No module named 'packaging' + # "BoltzTraP2>=22.3.2; platform_system!='Windows'", + "chemview>=0.6", + "chgnet>=0.3.8", + "f90nml>=1.1.2", + "galore>=0.6.1", + "h5py>=3.11.0", + "jarvis-tools>=2020.7.14", + "matgl>=1.1.1", + "netCDF4>=1.6.5", + "phonopy>=2.23", + "seekpath>=2.0.1", + # don't depend on tblite above 3.11 since unsupported https://github.com/tblite/tblite/issues/175 + "tblite[ase]>=0.3.0; platform_system=='Linux' and python_version<'3.12'", + # "hiphive>=0.6", + # "openbabel>=3.1.1; platform_system=='Linux'", +] +numba = ["numba>=0.55"] + +[tool.setuptools.packages.find] +where = ["."] +include = ["pymatgen.*"] + +[tool.setuptools.package-data] +"pymatgen.analysis" = ["*.yaml", "*.json", "*.csv"] +"pymatgen.analysis.chemenv" = [ + "coordination_environments/coordination_geometries_files/*.json", + "coordination_environments/coordination_geometries_files/*.txt", + "coordination_environments/strategy_files/ImprovedConfidenceCutoffDefaultParameters.json", +] +"pymatgen.analysis.structure_prediction" = ["*.yaml", "data/*.json"] +"pymatgen.analysis.diffraction" = ["*.json"] +"pymatgen.analysis.magnetism" = ["default_magmoms.yaml"] +"pymatgen.analysis.solar" = ["am1.5G.dat"] +"pymatgen.entries" = ["*.json.gz", "*.yaml", "data/*.json"] +"pymatgen.core" = ["*.json"] +"pymatgen" = ["py.typed"] +"pymatgen.io.vasp" = ["*.yaml", "*.json", "*.json.gz", "*.json.bz2"] +"pymatgen.io.feff" = ["*.yaml"] +"pymatgen.io.cp2k" = ["*.yaml"] +"pymatgen.io.lobster" = ["lobster_basis/*.yaml"] +"pymatgen.command_line" = ["*"] +"pymatgen.util" = ["structures/*.json", "*.json"] +"pymatgen.vis" = ["*.yaml"] +"pymatgen.io.lammps" = ["CoeffsDataType.yaml", "templates/*.template"] +"pymatgen.symmetry" = ["*.yaml", "*.json", "*.sqlite"] + +[project.scripts] +pmg = "pymatgen.cli.pmg:main" +feff_plot_cross_section = "pymatgen.cli.feff_plot_cross_section:main" +feff_plot_dos = "pymatgen.cli.feff_plot_dos:main" +get_environment = "pymatgen.cli.get_environment:main" + [tool.versioningit.vcs] method = "git" default-tag = "0.0.1" @@ -25,55 +180,55 @@ line-length = 120 [tool.ruff.lint] select = [ - "B", # flake8-bugbear - "C4", # flake8-comprehensions - "D", # pydocstyle - "E", # pycodestyle error - "EXE", # flake8-executable - "F", # pyflakes - "FA", # flake8-future-annotations - "FBT003", # boolean-positional-value-in-call - "FLY", # flynt - "I", # isort - "ICN", # flake8-import-conventions - "ISC", # flake8-implicit-str-concat - "PD", # pandas-vet - "PERF", # perflint - "PIE", # flake8-pie - "PL", # pylint - "PLR0402", - "PLR1714", - "PLR5501", - "PT", # flake8-pytest-style - "PYI", # flakes8-pyi - "Q", # flake8-quotes - "RET", # flake8-return - "RSE", # flake8-raise - "RUF", # Ruff-specific rules - "SIM", # flake8-simplify - "SLOT", # flake8-slots - "TCH", # flake8-type-checking - "TID", # flake8-tidy-imports - "UP", # pyupgrade - "W", # pycodestyle warning - "YTT", # flake8-2020 + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "D", # pydocstyle + "E", # pycodestyle error + "EXE", # flake8-executable + "F", # pyflakes + "FA", # flake8-future-annotations + "FBT003", # boolean-positional-value-in-call + "FLY", # flynt + "I", # isort + "ICN", # flake8-import-conventions + "ISC", # flake8-implicit-str-concat + "PD", # pandas-vet + "PERF", # perflint + "PIE", # flake8-pie + "PL", # pylint + "PLR0402", + "PLR1714", + "PLR5501", + "PT", # flake8-pytest-style + "PYI", # flakes8-pyi + "Q", # flake8-quotes + "RET", # flake8-return + "RSE", # flake8-raise + "RUF", # Ruff-specific rules + "SIM", # flake8-simplify + "SLOT", # flake8-slots + "TCH", # flake8-type-checking + "TID", # flake8-tidy-imports + "UP", # pyupgrade + "W", # pycodestyle warning + "YTT", # flake8-2020 ] ignore = [ - "B023", # Function definition does not bind loop variable - "B028", # No explicit stacklevel keyword argument found - "B904", # Within an except clause, raise exceptions with ... - "C408", # unnecessary-collection-call - "D105", # Missing docstring in magic method - "D205", # 1 blank line required between summary line and description - "D212", # Multi-line docstring summary should start at the first line - "PD901", # pandas-df-variable-name - "PERF203", # try-except-in-loop - "PERF401", # manual-list-comprehension - "PLR", # pylint refactor - "PLW2901", # Outer for loop variable overwritten by inner assignment target - "PT013", # pytest-incorrect-pytest-import - "PTH", # prefer pathlib to os.path - "SIM105", # Use contextlib.suppress() instead of try-except-pass + "B023", # Function definition does not bind loop variable + "B028", # No explicit stacklevel keyword argument found + "B904", # Within an except clause, raise exceptions with ... + "C408", # unnecessary-collection-call + "D105", # Missing docstring in magic method + "D205", # 1 blank line required between summary line and description + "D212", # Multi-line docstring summary should start at the first line + "PD901", # pandas-df-variable-name + "PERF203", # try-except-in-loop + "PERF401", # manual-list-comprehension + "PLR", # pylint refactor + "PLW2901", # Outer for loop variable overwritten by inner assignment target + "PT013", # pytest-incorrect-pytest-import + "PTH", # prefer pathlib to os.path + "SIM105", # Use contextlib.suppress() instead of try-except-pass ] pydocstyle.convention = "google" isort.required-imports = ["from __future__ import annotations"] @@ -97,31 +252,31 @@ addopts = "--durations=30 --quiet -r xXs --color=yes -p no:warnings --import-mod [tool.coverage.run] parallel = true omit = [ - "pymatgen/cli/feff_plot_cross_section.py", - "pymatgen/cli/feff_plot_dos.py", - "pymatgen/cli/pmg_config.py", - "pymatgen/cli/pmg_plot.py", - "pymatgen/cli/pmg_potcar.py", - "pymatgen/cli/pmg_query.py", - "pymatgen/dao.py", + "pymatgen/cli/feff_plot_cross_section.py", + "pymatgen/cli/feff_plot_dos.py", + "pymatgen/cli/pmg_config.py", + "pymatgen/cli/pmg_plot.py", + "pymatgen/cli/pmg_potcar.py", + "pymatgen/cli/pmg_query.py", + "pymatgen/dao.py", ] [tool.coverage.report] exclude_also = [ - "@deprecated", - "@np.deprecate", - "def __repr__", - "except ImportError:", - "if 0:", - "if TYPE_CHECKING:", - "if __name__ == .__main__.:", - "if self.debug:", - "if settings.DEBUG", - "if typing.TYPE_CHECKING:", - "pragma: no cover", - "raise AssertionError", - "raise NotImplementedError", - "show_plot", + "@deprecated", + "@np.deprecate", + "def __repr__", + "except ImportError:", + "if 0:", + "if TYPE_CHECKING:", + "if __name__ == .__main__.:", + "if self.debug:", + "if settings.DEBUG", + "if typing.TYPE_CHECKING:", + "pragma: no cover", + "raise AssertionError", + "raise NotImplementedError", + "show_plot", ] [tool.mypy] diff --git a/requirements-optional.txt b/requirements-optional.txt index 11220380cb6..96ecc8da1af 100644 --- a/requirements-optional.txt +++ b/requirements-optional.txt @@ -9,7 +9,7 @@ h5py==3.11.0 # hiphive>=0.6 icet>=2.2 jarvis-tools>=2022.9.16 -matgl==1.1.1 +matgl==1.1.2 netCDF4>=1.5.8 phonopy==2.23.1 seekpath>=2.0.1 diff --git a/requirements.txt b/requirements.txt index b50daba5ea2..110920a9994 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ numpy==1.26.4 sympy==1.12 -requests==2.32.0 +requests==2.32.3 monty==2024.5.24 ruamel.yaml==0.18.6 -scipy==1.11.3 +scipy==1.13.1 tabulate==0.9.0 matplotlib==3.8.0 palettable==3.3.3 @@ -12,7 +12,7 @@ pandas==2.1.1 networkx==3.3 plotly==5.17.0 uncertainties==3.1.7 -Cython==3.0.2 +Cython==3.0.10 pybtex==0.24.0 tqdm==4.66.4 joblib==1.3.2 diff --git a/setup.py b/setup.py index ad5656dd6b2..8d3b5feed86 100644 --- a/setup.py +++ b/setup.py @@ -6,171 +6,12 @@ import sys import numpy as np -from setuptools import Extension, find_namespace_packages, setup +from setuptools import Extension, setup is_win_64 = sys.platform.startswith("win") and platform.machine().endswith("64") extra_link_args = ["-Wl,--allow-multiple-definition"] if is_win_64 else [] -with open("README.md") as file: - long_description = file.read() - -# unlike GitHub readmes, PyPI doesn't support tags used for responsive images -# (i.e. adaptive to OS light/dark mode) -# NOTE this manual fix won't work once we migrate to pyproject.toml -logo_url = "https://raw.githubusercontent.com/materialsproject/pymatgen/master/docs/_images/pymatgen.svg" -long_description = ( - f"

Logo

" + long_description.split("
")[-1] -) - setup( - name="pymatgen", - packages=find_namespace_packages(include=["pymatgen.*", "pymatgen.**.*"]), - version="2024.6.10", - python_requires=">=3.9", - install_requires=[ - "matplotlib>=3.8", - "monty>=2024.5.24", - "networkx>=2.2", - "numpy>=1.25.0", - "palettable>=3.1.1", - "pandas>=2", - "plotly>=4.5.0", - "pybtex>=0.24.0", - "requests>=2.32", - "ruamel.yaml>=0.17.0", - "scipy>=1.13.0", - "spglib>=2.0.2", - "sympy>=1.2", - "tabulate>=0.9", - "tqdm>=4.60", - "uncertainties>=3.1.4", - "joblib>=1", - ], - extras_require={ - "ase": ["ase>=3.23.0"], - # don't depend on tblite above 3.11 since unsupported https://github.com/tblite/tblite/issues/175 - "tblite": ["tblite[ase]>=0.3.0; python_version<'3.12'"], - "vis": ["vtk>=6.0.0"], - "abinit": ["netcdf4>=1.6.5"], - "relaxation": ["matgl>=1.1.1", "chgnet>=0.3.8"], - "electronic_structure": ["fdint>=2.0.2"], - "dev": [ - "mypy>=1.10.0", - "pre-commit>=3", - "pytest-cov>=4", - "pytest-split>=0.8", - "pytest>8", - "ruff>=0.4", - ], - "ci": [ - "pytest>=8", - "pytest-cov>=4", - "pytest-split>=0.8", - ], - "docs": [ - "sphinx", - "sphinx_rtd_theme", - "doc2dash", - ], - "optional": [ - "ase>=3.23.0", - # TODO restore BoltzTraP2 when install fixed, hopefully following merge of - # https://gitlab.com/sousaw/BoltzTraP2/-/merge_requests/18 - # caused CI failure due to ModuleNotFoundError: No module named 'packaging' - # "BoltzTraP2>=22.3.2; platform_system!='Windows'", - "chemview>=0.6", - "chgnet>=0.3.8", - "f90nml>=1.1.2", - "galore>=0.6.1", - "h5py>=3.11.0", - "jarvis-tools>=2020.7.14", - "matgl>=1.1.1", - "netCDF4>=1.6.5", - "phonopy>=2.23", - "seekpath>=2.0.1", - # don't depend on tblite above 3.11 since unsupported https://github.com/tblite/tblite/issues/175 - "tblite[ase]>=0.3.0; platform_system=='Linux' and python_version<'3.12'", - # "hiphive>=0.6", - # "openbabel>=3.1.1; platform_system=='Linux'", - ], - "numba": ["numba>=0.55"], - }, - # All package data has to be explicitly defined. Do not use automated codes like last time. It adds - # all sorts of useless files like test files and is prone to path errors. - package_data={ - "pymatgen.analysis": ["*.yaml", "*.json", "*.csv"], - "pymatgen.analysis.chemenv": [ - "coordination_environments/coordination_geometries_files/*.json", - "coordination_environments/coordination_geometries_files/*.txt", - "coordination_environments/strategy_files/ImprovedConfidenceCutoffDefaultParameters.json", - ], - "pymatgen.analysis.structure_prediction": ["*.yaml", "data/*.json"], - "pymatgen.analysis.diffraction": ["*.json"], - "pymatgen.analysis.magnetism": ["default_magmoms.yaml"], - "pymatgen.analysis.solar": ["am1.5G.dat"], - "pymatgen.entries": ["*.json.gz", "*.yaml", "data/*.json"], - "pymatgen.core": ["*.json"], - "pymatgen": ["py.typed"], - "pymatgen.io.vasp": ["*.yaml", "*.json", "*.json.gz", "*.json.bz2"], - "pymatgen.io.feff": ["*.yaml"], - "pymatgen.io.cp2k": ["*.yaml"], - "pymatgen.io.lobster": ["lobster_basis/*.yaml"], - "pymatgen.command_line": ["*"], - "pymatgen.util": ["structures/*.json", "*.json"], - "pymatgen.vis": ["*.yaml"], - "pymatgen.io.lammps": ["CoeffsDataType.yaml", "templates/*.template"], - "pymatgen.symmetry": ["*.yaml", "*.json", "*.sqlite"], - }, - author="Pymatgen Development Team", - author_email="ongsp@ucsd.edu", - maintainer="Shyue Ping Ong, Matthew Horton, Janosh Riebesell", - maintainer_email="ongsp@ucsd.edu, mkhorton@lbl.gov, janosh.riebesell@gmail.com", - url="https://pymatgen.org", - license="MIT", - project_urls={ - "Docs": "https://pymatgen.org", - "Package": "https://pypi.org/project/pymatgen", - "Repo": "https://github.com/materialsproject/pymatgen", - }, - description="Python Materials Genomics is a robust materials " - "analysis code that defines core object representations for " - "structures and molecules with support for many electronic " - "structure codes. It is currently the core analysis code " - "powering the Materials Project " - "(https://materialsproject.org).", - long_description=long_description, - long_description_content_type="text/markdown", - keywords=[ - "ABINIT", - "analysis", - "crystal", - "diagrams", - "electronic", - "gaussian", - "materials", - "nwchem", - "phase", - "project", - "qchem", - "science", - "structure", - "VASP", - ], - classifiers=[ - "Development Status :: 4 - Beta", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3", - "Topic :: Scientific/Engineering :: Chemistry", - "Topic :: Scientific/Engineering :: Information Analysis", - "Topic :: Scientific/Engineering :: Physics", - "Topic :: Software Development :: Libraries :: Python Modules", - ], ext_modules=[ Extension( "pymatgen.optimization.linear_assignment", @@ -188,13 +29,5 @@ extra_link_args=extra_link_args, ), ], - entry_points={ - "console_scripts": [ - "pmg = pymatgen.cli.pmg:main", - "feff_plot_cross_section = pymatgen.cli.feff_plot_cross_section:main", - "feff_plot_dos = pymatgen.cli.feff_plot_dos:main", - "get_environment = pymatgen.cli.get_environment:main", - ] - }, include_dirs=[np.get_include()], ) diff --git a/tasks.py b/tasks.py index 00d3cf0ef0d..33220fc4871 100644 --- a/tasks.py +++ b/tasks.py @@ -225,7 +225,7 @@ def release(ctx: Context, version: str | None = None, nodoc: bool = False) -> No release_github(ctx, version) ctx.run("rm -f dist/*.*", warn=True) - ctx.run("python setup.py sdist bdist_wheel", warn=True) + ctx.run("python -m build", warn=True) ctx.run("twine upload --skip-existing dist/*.whl", warn=True) ctx.run("twine upload --skip-existing dist/*.tar.gz", warn=True) # post_discourse(ctx, warn=True) diff --git a/tests/core/test_structure.py b/tests/core/test_structure.py index a0f1a43bf6e..c5a939079a0 100644 --- a/tests/core/test_structure.py +++ b/tests/core/test_structure.py @@ -924,6 +924,13 @@ def setUp(self): self.disordered = Structure.from_spacegroup("Im-3m", Lattice.cubic(3), [Composition("Fe0.5Mn0.5")], [[0, 0, 0]]) self.labeled_structure = Structure(lattice, ["Si", "Si"], coords, labels=["Si1", "Si2"]) + def test_from_id(self): + s = Structure.from_id("mp-1143") + assert isinstance(s, Structure) + assert s.reduced_formula == "Al2O3" + s = Structure.from_id("1101077", source="COD") + assert s.reduced_formula == "LiV2O4" + def test_mutable_sequence_methods(self): struct = self.struct struct[0] = "Fe"