content: [build-system]
  requires = ["setuptools >= 42, < 81", "versioningit >= 1,< 4", "wheel"]
  build-backend = "setuptools.build_meta"
  
  [project]
  name = "atomate2"
  description = "atomate2 is a library of materials science workflows"
  readme = "README.md"
  keywords = ["automated", "dft", "high-throughput", "vasp", "workflow"]
  license = { text = "modified BSD" }
  authors = [{ name = "Alex Ganose", email = "alexganose@gmail.com" }]
  dynamic = ["version"]
  classifiers = [
      "Development Status :: 5 - Production/Stable",
      "Intended Audience :: Information Technology",
      "Intended Audience :: Science/Research",
      "Intended Audience :: System Administrators",
      "Operating System :: OS Independent",
      "Programming Language :: Python :: 3",
      "Programming Language :: Python :: 3.10",
      "Programming Language :: Python :: 3.11",
      "Programming Language :: Python :: 3.12",
      "Topic :: Other/Nonlisted Topic",
      "Topic :: Scientific/Engineering",
  ]
  requires-python = ">=3.10"
  dependencies = [
      "PyYAML",
      "click",
      "custodian>=2024.4.18",
      "emmet-core>=v0.84.10",
      "jobflow>=0.1.11",
      "monty>=2024.12.10",
      "numpy",
      "pydantic-settings>=2.0.3",
      "pydantic>=2.0.1",
      "pymatgen>=2024.11.13,<2025.10.7",
      "pymongo<=4.10.1",
  ]
  
  [project.optional-dependencies]
  abinit = ["abipy>=0.9.3"]
  amset = ["amset>=0.4.15", "pydash"]
  cclib = ["cclib>=1.8.1"]
  mp = ["mp-api>=0.37.5"]
  phonons = ["phonopy>=1.10.8", "seekpath>=2.0.0"]
  lobster = ["ijson>=3.2.2", "lobsterpy>=0.4.0"]
  defects = [
      "dscribe>=1.2.0",
      "pymatgen-analysis-defects>=2024.5.11",
      "python-ulid>=2.7",
  ]
  forcefields = [
      "ase>=3.26.0",
      "calorine>=3.0",
      "chgnet>=0.2.2",
      "mace-torch>=0.3.3",
      "matgl>=1.2.1",
      "torchdata<=0.7.1",
      # quippy-ase support for py3.12 tracked in https://github.com/libAtoms/QUIP/issues/645
      "quippy-ase>=0.9.14; python_version < '3.12'",
      "sevenn>=0.9.3",
      "torchdata<=0.7.1",                            # TODO: remove when issue fixed
  ]
  approxneb = ["pymatgen-analysis-diffusion>=2024.7.15"]
  ase = ["ase>=3.26.0"]
  ase-ext = ["tblite>=0.3.0; platform_system=='Linux'"]
  openmm = [
      "mdanalysis>=2.8.0",
      "openmm-mdanalysis-reporter>=0.1.0",
      "openmm>=8.1.0",
  ]
  fireworks = ["fireworks==2.0.5"]
  docs = [
      "fireworks==2.0.5",
      "autodoc_pydantic==2.2.0",
      "furo==2025.7.19",
      "ipython==8.37.0",
      "jsonschema[format]",
      "myst_parser==4.0.1",
      "numpydoc==1.9.0",
      "sphinx-copybutton==0.5.2",
      "sphinx==8.1.3",
      "sphinx_design==0.6.1",
      "jupyterlab==4.4.7",
  ]
  dev = ["pre-commit>=2.12.1"]
  tests = [
      "fireworks==2.0.5",
      "nbmake==1.5.5",
      "pytest-cov==7.0.0",
      "pytest-mock==3.15.1",
      "pytest-split==0.10.0",
      "pytest-xdist==3.8.0",
      "pytest==8.4.2",
  ]
  strict-openff = [
      "mdanalysis==2.9.0",
      "monty==2025.3.3",
      "openmm-mdanalysis-reporter==0.1.0",
      "openmm==8.1.1",
      "pymatgen==2025.6.14", # EXERCISE CAUTION WHEN UPDATING - open ff is extremely sensitive to pymatgen version
  ]
  strict-forcefields = [
      "calorine==3.1",
      "chgnet==0.3.8",
      "mace-torch==0.3.14",
      "matgl==1.3.0",
      "quippy-ase==0.9.14; python_version < '3.12'",
      "sevenn==0.10.4",
      "torch==2.2.0",
      "torchdata==0.7.1",                            # TODO: remove when issue fixed
  ]
  strict = [
      "atomate2[strict-forcefields, docs, cclib, phonons, lobster, openmm, mp, defects, ase, ase-ext]",
  ]
  
  [project.scripts]
  atm = "atomate2.cli:cli"
  
  [project.urls]
  homepage = "https://materialsproject.github.io/atomate2/"
  repository = "https://github.com/materialsproject/atomate2"
  documentation = "https://materialsproject.github.io/atomate2/"
  changelog = "https://github.com/materialsproject/atomate2/blob/main/CHANGELOG.md"
  
  [tool.setuptools.package-data]
  atomate2 = ["py.typed"]
  "atomate2.vasp.sets" = ["*.yaml"]
  "atomate2.cp2k.sets" = ["*.yaml"]
  "atomate2.cp2k.schemas.calc_types" = ["*.yaml"]
  
  [tool.versioningit.vcs]
  method = "git"
  default-tag = "0.0.1"
  
  [tool.mypy]
  ignore_missing_imports = true
  no_strict_optional = true
  
  [tool.pytest.ini_options]
  addopts = "-p no:warnings --import-mode=importlib --cov-config=pyproject.toml"
  filterwarnings = [
      "ignore:.*POTCAR.*:UserWarning",
      "ignore:.*input structure.*:UserWarning",
      "ignore:.*is not gzipped.*:UserWarning",
      "ignore:.*magmom.*:UserWarning",
      "ignore::DeprecationWarning",
  ]
  
  [tool.coverage.run]
  include = ["src/*"]
  parallel = true
  branch = true
  
  [tool.coverage.paths]
  source = ["src/"]
  
  [tool.coverage.report]
  skip_covered = true
  show_missing = true
  exclude_lines = [
      '^\s*@overload( |$)',
      '^\s*assert False(,|$)',
      'if typing.TYPE_CHECKING:',
      'if TYPE_CHECKING:',
  ]
  
  [tool.ruff]
  target-version = "py310"
  output-format = "concise"
  
  [tool.ruff.lint]
  select = ["ALL"]
  ignore = [
      "ANN002",  # Missing type annotation for *arg
      "ANN003",  # Missing type annotation for **kwargs
      "ANN401",  # typing.Any disallowed
      "ARG002",  # unused method argument
      "C408",    # Unnecessary (dict/list/tuple) call - remove call
      "C901",    # function too complex
      "COM812",  # trailing comma missing
      "EM",      # exception message must not use f-string literal
      "ERA001",  # found commented out code
      "FBT001",
      "FBT002",
      "FIX002",
      "G004",    # logging uses f-string
      "ISC001",
      "PD011",   # pandas-use-of-dot-values
      "PERF203", # try-except-in-loop
      "PLC0415", # imports not at top level are OK
      "PLR0911", # too many returns
      "PLR0912", # too many branches
      "PLR0913", # too many arguments
      "PLR0915", # too many local statements
      "PLR2004",
      "PT006",   # pytest-parametrize-names-wrong-type
      "PT013",   # pytest-incorrect-pytest-import
      "PTH",     # prefer Pathlib to os.path
      "RUF013",  # implicit-optional
      "S324",    # use of insecure hash function
      "S507",    # paramiko auto trust
      "S603",    # use of insecure subprocess
      "TD",      # todos
      "TRY003",  # long message outside exception class
  ]
  pydocstyle.convention = "numpy"
  isort.known-first-party = ["atomate2"]
  isort.split-on-trailing-comma = false
  
  [tool.ruff.format]
  docstring-code-format = true
  
  [tool.ruff.lint.per-file-ignores]
  "__init__.py" = ["F401"]
  "**/tests/*" = ["ANN", "ARG001", "D", "INP001", "PLR2004", "S101"]
  # flake8-type-checking (TCH): things inside TYPE_CHECKING aren't available
  #     at runtime and so can't be used by pydantic models
  # flake8-future-annotations (FA): pipe operator for type unions only work in pydantic models in python 3.10+
  "**/schemas/*" = ["FA", "TCH", "UP007"]
  "**/schemas.py" = ["FA", "TCH", "UP007"]
  "**/settings.py" = ["FA", "TCH", "UP007"]
  "docs/*" = ["INP001"]
  