BUG: User Incar Settings being overridden by `auto_ismear` + others
https://github.com/materialsproject/atomate2/blob/51946bf1a5def3ab50fd4949111f96de37e976ff/src/atomate2/vasp/sets/base.py#L256

@utf the new `auto_ismear` argument (introduced in #270) appears to be overriding my UIS. 

Perhaps the `incar_updates` variable should be used instead of updating the `incar` directly in many places? I.e. I don't know why the `incar` is being updated directly on lines [661](https://github.com/materialsproject/atomate2/blob/51946bf1a5def3ab50fd4949111f96de37e976ff/src/atomate2/vasp/sets/base.py#L661), [664](https://github.com/materialsproject/atomate2/blob/51946bf1a5def3ab50fd4949111f96de37e976ff/src/atomate2/vasp/sets/base.py#L664), [668](https://github.com/materialsproject/atomate2/blob/51946bf1a5def3ab50fd4949111f96de37e976ff/src/atomate2/vasp/sets/base.py#L668), [674-678](https://github.com/materialsproject/atomate2/blob/51946bf1a5def3ab50fd4949111f96de37e976ff/src/atomate2/vasp/sets/base.py#L674), [681](https://github.com/materialsproject/atomate2/blob/51946bf1a5def3ab50fd4949111f96de37e976ff/src/atomate2/vasp/sets/base.py#L681), or [686 and 688](https://github.com/materialsproject/atomate2/blob/51946bf1a5def3ab50fd4949111f96de37e976ff/src/atomate2/vasp/sets/base.py#L686) -- this would overwrite the `user_incar_settings`. So either this should be changed, or the `user_incar_settings` should be applied last.

Separately, given that `auto_ispin` and `auto_lreal` are both false by default, I also feel like `auto_ismear` should be false by default.

I am confused
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 0f02c73e..6f04cb03 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -10,8 +10,7 @@ Include a summary of major changes in bullet points:
 * List all new dependencies needed and justify why. While adding dependencies that bring
   significantly useful functionality is perfectly fine, adding ones that add trivial
   functionality, e.g., to use one single easily implementable function, is frowned upon.
-  Provide a justification why that dependency is needed. Especially frowned upon are
-  circular dependencies.
+  Justify why that dependency is needed. Especially frowned upon are circular dependencies.
 
 ## TODO (if any)
 
@@ -26,20 +25,17 @@ title.
 
 Before a pull request can be merged, the following items must be checked:
 
-- [ ] Code is in the [standard Python style](https://www.python.org/dev/peps/pep-0008/).
+* [ ] Code is in the [standard Python style](https://www.python.org/dev/peps/pep-0008/).
   The easiest way to handle this is to run the following in the **correct sequence** on
-  your local machine. Start with running [black](
-  https://black.readthedocs.io/en/stable/index.html) on your new code. This will
+  your local machine. Start with running [black](https://black.readthedocs.io/en/stable/index.html) on your new code. This will
   automatically reformat your code to PEP8 conventions and removes most issues. Then run
-  [pycodestyle](https://pycodestyle.readthedocs.io/en/latest/), followed by [flake8](
-  http://flake8.pycqa.org/en/latest/).
-- [ ] Docstrings have been added in the[Numpy docstring format](
-  https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html).
-  Run [pydocstyle](http://www.pydocstyle.org/en/2.1.1/index.html) on your code.
-- [ ] Type annotations are **highly** encouraged. Run [mypy](http://mypy-lang.org/) to
+  [ruff](https://ruff.rs).
+* [ ] Docstrings have been added in the [Numpy docstring format](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html).
+  Run [ruff](https://beta.ruff.rs/docs/rules/#pydocstyle-d) on your code.
+* [ ] Type annotations are **highly** encouraged. Run [mypy](http://mypy-lang.org) to
   type check your code.
-- [ ] Tests have been added for any new functionality or bug fixes.
-- [ ] All linting and tests pass.
+* [ ] Tests have been added for any new functionality or bug fixes.
+* [ ] All linting and tests pass.
 
 Note that the CI system will run all the above checks. But it will be much more
 efficient if you already fix most errors prior to submitting the PR. It is highly
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5d79bdc0..78a3dba9 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -2,6 +2,11 @@ default_language_version:
   python: python3
 exclude: '^src/atomate2/vasp/schemas/calc_types/'
 repos:
+- repo: https://github.com/charliermarsh/ruff-pre-commit
+  rev: v0.0.250
+  hooks:
+  - id: ruff
+    args: [--fix]
 - repo: https://github.com/pre-commit/pre-commit-hooks
   rev: v4.4.0
   hooks:
@@ -10,10 +15,6 @@ repos:
     args: [--remove]
   - id: end-of-file-fixer
   - id: trailing-whitespace
-- repo: https://github.com/myint/autoflake
-  rev: v2.0.0
-  hooks:
-  - id: autoflake
 - repo: https://github.com/psf/black
   rev: 22.12.0
   hooks:
@@ -24,10 +25,6 @@ repos:
   - id: blacken-docs
     additional_dependencies: [black]
     exclude: README.md
-- repo: https://github.com/pycqa/isort
-  rev: 5.12.0
-  hooks:
-  - id: isort
 - repo: https://github.com/pycqa/flake8
   rev: 6.0.0
   hooks:
@@ -63,8 +60,3 @@ repos:
   - id: codespell
     stages: [commit, commit-msg]
     args: [--ignore-words-list, 'titel,statics,ba,nd,te']
-- repo: https://github.com/asottile/pyupgrade
-  rev: v3.3.1
-  hooks:
-    - id: pyupgrade
-      args: [--py38-plus]
diff --git a/docs/dev/dev_install.md b/docs/dev/dev_install.md
index 60affc49..8c156f51 100644
--- a/docs/dev/dev_install.md
+++ b/docs/dev/dev_install.md
@@ -10,7 +10,7 @@ You can install the basic functionality of atomate2 using pip:
 pip install atomate2
 ```
 
-If you are planing to use atomate2 with fireworks, you can install the optional
+If you are planning to use atomate2 with fireworks, you can install the optional
 fireworks components:
 
 ```bash
@@ -39,7 +39,7 @@ You can also install fireworks dependencies:
 pip install .[fireworks]
 ```
 
-Or do a developer install by using the ``-e`` flag:
+Or do a developer install by using the `-e` flag:
 
 ```bash
 pip install -e .
@@ -50,13 +50,13 @@ pip install -e .
 If you're planning on contributing to the atomate2 source, you should also install
 the developer requirements with:
 
-```
+```bash
 pip install -e .[dev]
 pre-commit install
 ```
 
-The precommit command will ensure that changes to the source code match the
-atomate2 style guidelines by running code linters such as `black`, `isort`,
+The `pre-commit` command will ensure that changes to the source code match the
+atomate2 style guidelines by running code linters such as `black`, `ruff`,
 and `mypy` automatically with each commit.
 
 ## Running unit tests
@@ -76,8 +76,7 @@ pytest
 
 ## Building the documentation
 
-The atomate2 documentation can be built using the sphinx package. First, install the
-necessary requirement:
+The atomate2 documentation can be built using the sphinx package. First, install the requirements:
 
 ```bash
 pip install .[docs]
diff --git a/pyproject.toml b/pyproject.toml
index 592e9854..a1eb96ca 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -24,7 +24,7 @@ classifiers = [
     "Topic :: Scientific/Engineering",
 ]
 requires-python = ">=3.8"
-dependencies =[
+dependencies = [
     "pymatgen>=2022.8.23",
     "custodian>=2022.5.26",
     "pydantic",
@@ -47,7 +47,7 @@ docs = [
     "FireWorks==2.0.3",
     "autodoc_pydantic==1.8.0",
     "jupyter-book==0.13.1",
-    "jsonschema[format]"
+    "jsonschema[format]",
 ]
 dev = ["pre-commit>=2.12.1"]
 tests = ["pytest==7.2.1", "pytest-cov==4.0.0", "FireWorks==2.0.3"]
@@ -86,9 +86,6 @@ atomate2 = ["py.typed"]
 method = "git"
 default-tag = "0.0.1"
 
-[tool.isort]
-profile = "black"
-
 [tool.flake8]
 max-line-length = 88
 max-doc-length = 88
@@ -128,9 +125,47 @@ exclude_lines = [
     '^\s*@overload( |$)',
 ]
 
-[tool.autoflake]
-in-place = true
-remove-all-unused-imports = true
-remove-unused-variables = true
-ignore-init-module-imports = true
-expand-star-imports = true
+[tool.ruff]
+target-version = "py38"
+select = [
+    "B",   # flake8-bugbear
+    "C4",  # flake8-comprehensions
+    "D",   # pydocstyle
+    "E",   # pycodestyle
+    "F",   # pyflakes
+    "I",   # isort
+    "PLE", # pylint error
+    "PLW", # pylint warning
+    "Q",   # flake8-quotes
+    "RUF", # Ruff-specific rules
+    "SIM", # flake8-simplify
+    "TID", # tidy imports
+    "UP",  # pyupgrade
+    "W",   # pycodestyle
+    "YTT", # flake8-2020
+]
+ignore = [
+    "B019",    # functools.lru_cache on methods can lead to memory leaks
+    "B023",    # Function definition does not bind loop variable
+    "B904",    # Within an except clause, raise exceptions with ...
+    "D100",    # Missing docstring in public module
+    "D104",    # Missing docstring in public package
+    "D105",    # Missing docstring in magic method
+    "D107",    # Missing docstring in __init__
+    "D200",    # One-line docstring should fit on one line with quotes
+    "D205",    # 1 blank line required between summary line and description
+    "D212",    # Multi-line docstring summary should start at the first line
+    "D415",    # First line should end with a period, question mark, or exclamation point
+    "E741",    # tmp: we should fix all ambiguous variable names
+    "PLR2004", # Magic number
+    "PLW0120", # awaiting bug fix https://github.com/charliermarsh/ruff/issues/3019
+    "C408",    # Unnecessary dict call - rewrite as a literal
+    "D416",    # Section name should end with a colon
+    "SIM105",  # Use contextlib.suppress(socket.gaierror, socket.herror) instead of try-except-pass
+]
+pydocstyle.convention = "google"
+isort.known-first-party = ["atomate2"]
+
+[tool.ruff.per-file-ignores]
+"__init__.py" = ["F401"]
+"**/tests/*" = ["D"]
diff --git a/src/atomate2/amset/schemas.py b/src/atomate2/amset/schemas.py
index cb67da37..454ac157 100644
--- a/src/atomate2/amset/schemas.py
+++ b/src/atomate2/amset/schemas.py
@@ -132,7 +132,7 @@ class AmsetTaskDocument(StructureMetadata):
     scattering_labels: List[str] = Field(
         None, description="The scattering types used in the calculation"
     )
-    soc: bool = Field(None, description="Whether spin–orbit coupling was included")
+    soc: bool = Field(None, description="Whether spin-orbit coupling was included")
     structure: Structure = Field(None, description="The structure used in this task")
     _schema: str = Field(
         __version__,
diff --git a/src/atomate2/cli/dev.py b/src/atomate2/cli/dev.py
index 80c29881..27000d11 100644
--- a/src/atomate2/cli/dev.py
+++ b/src/atomate2/cli/dev.py
@@ -115,7 +115,7 @@ def vasp_test_data(test_dir):
         [f"  {v}  ->  {k}" for k, v in original_mapping.items()]
     )
 
-    run_vasp_kwargs = {k: {"incar_settings": ["NSW", "ISMEAR"]} for k in mapping.keys()}
+    run_vasp_kwargs = {k: {"incar_settings": ["NSW", "ISMEAR"]} for k in mapping}
     run_vasp_kwargs_str = pformat(run_vasp_kwargs).replace("\n", "\n    ")
 
     test_function_str = f"""Test files generated in test_data.
diff --git a/src/atomate2/common/analysis/defects/schemas.py b/src/atomate2/common/analysis/defects/schemas.py
index ab176aec..09de30ac 100644
--- a/src/atomate2/common/analysis/defects/schemas.py
+++ b/src/atomate2/common/analysis/defects/schemas.py
@@ -43,32 +43,38 @@ class CCDDocument(BaseModel):
 
     static_dirs1: List[str] = Field(
         None,
-        description="Directories of distorted calculations for the defect (supercell) in charge state (q1).",
+        description="Directories of distorted calculations for the defect (supercell) "
+        "in charge state (q1).",
     )
 
     static_dirs2: List[str] = Field(
         None,
-        description="Directories of distorted calculations for the defect (supercell) in charge state (q2).",
+        description="Directories of distorted calculations for the defect (supercell) "
+        "in charge state (q2).",
     )
 
     static_uuids1: List[str] = Field(
         None,
-        description="UUIDs of distorted calculations for the defect (supercell) in charge state (q1).",
+        description="UUIDs of distorted calculations for the defect (supercell) in "
+        "charge state (q1).",
     )
 
     static_uuids2: List[str] = Field(
         None,
-        description="UUIDs of distorted calculations for the defect (supercell) in charge state (q2).",
+        description="UUIDs of distorted calculations for the defect (supercell) in "
+        "charge state (q2).",
     )
 
     relaxed_index1: int = Field(
         None,
-        description="The index of the static calculation in that corresponds to the relaxed charge state (q1).",
+        description="The index of the static calculation in that corresponds to the "
+        "relaxed charge state (q1).",
     )
 
     relaxed_index2: int = Field(
         None,
-        description="The index of the static calculation in that corresponds to the relaxed charge state (q2).",
+        description="The index of the static calculation in that corresponds to the "
+        "relaxed charge state (q2).",
     )
 
     @classmethod
@@ -291,11 +297,9 @@ def get_dQ(ref: Structure, distorted: Structure) -> float:
     """
     return np.sqrt(
         np.sum(
-            list(
-                map(
-                    lambda x: x[0].distance(x[1]) ** 2 * x[0].specie.atomic_mass,
-                    zip(ref, distorted),
-                )
-            )
+            [
+                x[0].distance(x[1]) ** 2 * x[0].specie.atomic_mass
+                for x in zip(ref, distorted)
+            ]
         )
     )
diff --git a/src/atomate2/common/files.py b/src/atomate2/common/files.py
index 6d6e1a12..ee24495a 100644
--- a/src/atomate2/common/files.py
+++ b/src/atomate2/common/files.py
@@ -357,11 +357,7 @@ def get_zfile(
         found, then ``None`` will be returned.
     """
     for file in directory_listing:
-        if base_name == file.name:
-            return file
-        elif base_name + ".gz" == file.name:
-            return file
-        elif base_name + ".GZ" == file.name:
+        if file.name in [base_name, base_name + ".gz", base_name + ".GZ"]:
             return file
 
     if allow_missing:
diff --git a/src/atomate2/common/jobs.py b/src/atomate2/common/jobs.py
index 0bd07f0f..e1d535b4 100644
--- a/src/atomate2/common/jobs.py
+++ b/src/atomate2/common/jobs.py
@@ -106,7 +106,6 @@ def retrieve_structure_from_materials_project(
         and also the database version and specific task_id
         corresponding to that Structure object also stored
     """
-
     # inline import to avoid required dependency
     try:
         from mp_api.client import MPRester
@@ -132,14 +131,13 @@ def retrieve_structure_from_materials_project(
 
     structure = doc.structure
 
-    if reset_magnetic_moments:
+    if reset_magnetic_moments and "magmom" in structure.site_properties:
         # Materials Project stores magnetic moments via the `magmom` site property
         # and we can safely assume that here. In general, since magnetic order
         # can be represented in multiple ways such as Species.spin, the
         # following method would be better:
         # CollinearMagneticStructureAnalyzer.get_nonmagnetic_structure()
-        if "magmom" in structure.site_properties:
-            structure.remove_site_property("magmom")
+        structure.remove_site_property("magmom")
 
     return Response(
         output=structure,
diff --git a/src/atomate2/common/schemas/cclib.py b/src/atomate2/common/schemas/cclib.py
index 0a048408..290f3e8d 100644
--- a/src/atomate2/common/schemas/cclib.py
+++ b/src/atomate2/common/schemas/cclib.py
@@ -46,7 +46,8 @@ class TaskDocument(MoleculeMetadata):
     )
     metadata: Dict = Field(
         None,
-        description="Calculation metadata, including input parameters and runtime statistics",
+        description="Calculation metadata, including input parameters and runtime "
+        "statistics",
     )
     task_label: str = Field(None, description="A description of the task")
     tags: List[str] = Field(None, description="Optional tags for this task document")
@@ -115,7 +116,7 @@ class TaskDocument(MoleculeMetadata):
         from cclib.io import ccread
 
         logger.info(
-            f"Searching for the most recent log file with extensions {logfile_extensions}"
+            f"Searching for most recent log file with extensions {logfile_extensions}"
         )
 
         # Find the most recent log file with the given extension in the
@@ -155,10 +156,9 @@ class TaskDocument(MoleculeMetadata):
             metadata["cpu_time"] = [str(m) for m in metadata["cpu_time"]]
 
         # Get the final energy to store as its own key/value pair
-        if cclib_obj.scfenergies is not None:
-            energy = cclib_obj.scfenergies[-1]
-        else:
-            energy = None
+        energy = (
+            cclib_obj.scfenergies[-1] if cclib_obj.scfenergies is not None else None
+        )
 
         # Now we construct the input molecule. Note that this is not necessarily
         # the same as the initial molecule from the relaxation because the
diff --git a/src/atomate2/common/schemas/elastic.py b/src/atomate2/common/schemas/elastic.py
index 51aa9ee3..2e3d93a8 100644
--- a/src/atomate2/common/schemas/elastic.py
+++ b/src/atomate2/common/schemas/elastic.py
@@ -44,15 +44,18 @@ class DerivedProperties(BaseModel):
     homogeneous_poisson: float = Field(None, description="Homogeneous poisson ratio.")
     y_mod: float = Field(
         None,
-        description="Young's modulus (SI units) from the Voight-Reuss-Hill averages of the bulk and shear moduli.",
+        description="Young's modulus (SI units) from the Voight-Reuss-Hill averages of "
+        "the bulk and shear moduli.",
     )
     trans_v: float = Field(
         None,
-        description="Transverse sound velocity (SI units) obtained from the Voigt-Reuss-Hill average bulk modulus.",
+        description="Transverse sound velocity (SI units) obtained from the "
+        "Voigt-Reuss-Hill average bulk modulus.",
     )
     long_v: float = Field(
         None,
-        description="Longitudinal sound velocity (SI units) obtained from the Voigt-Reuss-Hill average bulk modulus.",
+        description="Longitudinal sound velocity (SI units) obtained from the "
+        "Voigt-Reuss-Hill average bulk modulus.",
     )
     snyder_ac: float = Field(
         None, description="Synder's acoustic sound velocity (SI units)."
@@ -71,7 +74,8 @@ class DerivedProperties(BaseModel):
     )
     debye_temperature: float = Field(
         None,
-        description="Debye temperature from longitudinal and transverse sound velocities (SI units).",
+        description="Debye temperature from longitudinal and transverse sound "
+        "velocities (SI units).",
     )
 
 
@@ -85,7 +89,7 @@ class FittingData(BaseModel):
         None, description="The strains used to fit the elastic tensor."
     )
     pk_stresses: List[Matrix3D] = Field(
-        None, description="The Piola–Kirchoff stresses used to fit the elastic tensor."
+        None, description="The Piola-Kirchoff stresses used to fit the elastic tensor."
     )
     deformations: List[Matrix3D] = Field(
         None, description="The deformations corresponding to each strain state."
diff --git a/src/atomate2/common/schemas/symmetry.py b/src/atomate2/common/schemas/symmetry.py
index c6c3c51a..52550c88 100644
--- a/src/atomate2/common/schemas/symmetry.py
+++ b/src/atomate2/common/schemas/symmetry.py
@@ -56,7 +56,8 @@ class SymmetryData(BaseModel):
     symprec: float = Field(
         None,
         title="Symmetry Finding Precision",
-        description="The precision given to spglib to determine the symmetry of this lattice",
+        description="The precision given to spglib to determine the symmetry of this "
+        "lattice",
     )
 
     version: str = Field(None, title="SPGLib version")
diff --git a/src/atomate2/utils/file_client.py b/src/atomate2/utils/file_client.py
index 0eb551b5..65d3cb9d 100644
--- a/src/atomate2/utils/file_client.py
+++ b/src/atomate2/utils/file_client.py
@@ -488,7 +488,7 @@ def get_ssh_connection(
         # try reading ssh config file
         ssh_config = paramiko.SSHConfig().from_path(str(config_filename))
 
-        host_config = ssh_config.lookup(hostname)
+        host_config = ssh_config.lookup(hostname)  # type: ignore[attr-defined]
         for k in ("hostname", "user", "port"):
             if k in host_config:
                 config[k.replace("user", "username")] = host_config[k]
diff --git a/src/atomate2/vasp/files.py b/src/atomate2/vasp/files.py
index 59bb6b21..dd4038a4 100644
--- a/src/atomate2/vasp/files.py
+++ b/src/atomate2/vasp/files.py
@@ -61,7 +61,7 @@ def copy_vasp_outputs(
     directory_listing = file_client.listdir(src_dir, host=src_host)
 
     # find required files
-    files = ("INCAR", "OUTCAR", "CONTCAR", "vasprun.xml") + tuple(additional_vasp_files)
+    files = ("INCAR", "OUTCAR", "CONTCAR", "vasprun.xml", *additional_vasp_files)
     required_files = [get_zfile(directory_listing, r + relax_ext) for r in files]
 
     # find optional files; do not fail if KPOINTS is missing, this might be KSPACING
diff --git a/src/atomate2/vasp/flows/defect.py b/src/atomate2/vasp/flows/defect.py
index 65deb80f..b92d4b00 100644
--- a/src/atomate2/vasp/flows/defect.py
+++ b/src/atomate2/vasp/flows/defect.py
@@ -43,6 +43,18 @@ DEFECT_STATIC_GENERATOR = StaticSetGenerator(
 
 @dataclass
 class ConfigurationCoordinateMaker(BaseCCDMaker):
+    """Maker to calculate the configuration coordinate diagram.
+
+    Parameters
+    ----------
+    name: str
+        The name of the flow created by this maker.
+    relax_maker: BaseVaspMaker
+        A maker to perform the relaxation of the defect.
+    static_maker: BaseVaspMaker
+        A maker to perform the static calculation of the defect.
+    """
+
     relax_maker: BaseVaspMaker = field(
         default_factory=lambda: RelaxMaker(
             input_set_generator=DEFECT_RELAX_GENERATOR,
diff --git a/src/atomate2/vasp/flows/phonons.py b/src/atomate2/vasp/flows/phonons.py
index 82067923..b1a62f04 100644
--- a/src/atomate2/vasp/flows/phonons.py
+++ b/src/atomate2/vasp/flows/phonons.py
@@ -196,7 +196,8 @@ class PhononMaker(Maker):
             and self.kpath_scheme != "seekpath"
         ):
             raise ValueError(
-                "You can only use other kpath schemes with the primitive standard structure"
+                "You can only use other kpath schemes with the primitive standard "
+                "structure"
             )
 
         if self.kpath_scheme not in [
diff --git a/src/atomate2/vasp/jobs/elastic.py b/src/atomate2/vasp/jobs/elastic.py
index 4d514519..96954f89 100644
--- a/src/atomate2/vasp/jobs/elastic.py
+++ b/src/atomate2/vasp/jobs/elastic.py
@@ -141,7 +141,9 @@ def generate_elastic_deformations(
 
     strains = []
     for state, magnitudes in zip(strain_states, strain_magnitudes):
-        strains.extend([Strain.from_voigt(m * np.array(state)) for m in magnitudes])  # type: ignore
+        strains.extend(
+            [Strain.from_voigt(m * np.array(state)) for m in magnitudes]  # type: ignore
+        )
 
     # remove zero strains
     strains = [strain for strain in strains if (abs(strain) > 1e-10).any()]
diff --git a/src/atomate2/vasp/jobs/phonons.py b/src/atomate2/vasp/jobs/phonons.py
index 3cd17265..afed22d4 100644
--- a/src/atomate2/vasp/jobs/phonons.py
+++ b/src/atomate2/vasp/jobs/phonons.py
@@ -93,10 +93,7 @@ def get_supercell_size(
         transformation.apply_transformation(structure=structure)
 
     else:
-        if "max_atoms" not in kwargs:
-            max_atoms = 1000
-        else:
-            max_atoms = kwargs["max_atoms"]
+        max_atoms = 1000 if "max_atoms" not in kwargs else kwargs["max_atoms"]
         if "angle_tolerance" not in kwargs:
             kwargs["angle_tolerance"] = 1e-2
         try:
diff --git a/src/atomate2/vasp/run.py b/src/atomate2/vasp/run.py
index ec842597..21fe5af0 100644
--- a/src/atomate2/vasp/run.py
+++ b/src/atomate2/vasp/run.py
@@ -152,7 +152,7 @@ def run_vasp(
         raise ValueError(f"Unsupported job type: {job_type}")
 
     if wall_time is not None:
-        handlers = list(handlers) + [WalltimeHandler(wall_time=wall_time)]
+        handlers = [*handlers, WalltimeHandler(wall_time=wall_time)]
 
     c = Custodian(
         handlers,
diff --git a/src/atomate2/vasp/schemas/calc_types/utils.py b/src/atomate2/vasp/schemas/calc_types/utils.py
index 7d99aeaa..c221caad 100644
--- a/src/atomate2/vasp/schemas/calc_types/utils.py
+++ b/src/atomate2/vasp/schemas/calc_types/utils.py
@@ -28,10 +28,7 @@ def run_type(vasp_parameters: Dict) -> RunType:
     RunType
         The run type.
     """
-    if vasp_parameters.get("LDAU", False):
-        is_hubbard = "+U"
-    else:
-        is_hubbard = ""
+    is_hubbard = "+U" if vasp_parameters.get("LDAU", False) else ""
 
     def _variant_equal(v1, v2) -> bool:
         """Check two strings equal."""
diff --git a/src/atomate2/vasp/schemas/calculation.py b/src/atomate2/vasp/schemas/calculation.py
index 4592e8a5..87f8c33b 100644
--- a/src/atomate2/vasp/schemas/calculation.py
+++ b/src/atomate2/vasp/schemas/calculation.py
@@ -55,7 +55,7 @@ __all__ = [
 ]
 
 
-_BADER_EXE_EXISTS = True if (which("bader") or which("bader.exe")) else False
+_BADER_EXE_EXISTS = bool(which("bader") or which("bader.exe"))
 
 
 class Status(ValueEnum):
diff --git a/src/atomate2/vasp/schemas/defect.py b/src/atomate2/vasp/schemas/defect.py
index 973c486e..ac642247 100644
--- a/src/atomate2/vasp/schemas/defect.py
+++ b/src/atomate2/vasp/schemas/defect.py
@@ -29,7 +29,7 @@ class FiniteDifferenceDocument(BaseModel):
     )
     distorted_dirs: List[str] = Field(
         None,
-        description="List of directories where the distorted W(Q) wavefunctions come from",
+        description="Directories where the distorted W(Q) wavefunctions come from",
     )
 
     @classmethod
diff --git a/src/atomate2/vasp/schemas/phonons.py b/src/atomate2/vasp/schemas/phonons.py
index 9b2aa637..fe09758c 100644
--- a/src/atomate2/vasp/schemas/phonons.py
+++ b/src/atomate2/vasp/schemas/phonons.py
@@ -60,7 +60,8 @@ class ThermalDisplacementData(BaseModel):
     )
     thermal_displacement_matrix: List[List[Matrix3D]] = Field(
         None,
-        description="field including thermal displacement matrices in Cartesian coordinate system",
+        description="field including thermal displacement matrices in Cartesian "
+        "coordinate system",
     )
     temperatures_thermal_displacements: List[int] = Field(
         None,
@@ -158,7 +159,8 @@ class PhononBSDOSDoc(BaseModel):
 
     born: List[Matrix3D] = Field(
         None,
-        description="born charges as computed from phonopy. Only for symmetrically different atoms",
+        description="born charges as computed from phonopy. Only for symmetrically "
+        "different atoms",
     )
 
     epsilon_static: Matrix3D = Field(
@@ -273,13 +275,12 @@ class PhononBSDOSDoc(BaseModel):
                 raise ValueError(
                     "Number of born charges does not agree with number of atoms"
                 )
-            if code == "vasp":
-                if not np.all(np.isclose(borns, 0.0)):
-                    phonon.nac_params = {
-                        "born": borns,
-                        "dielectric": epsilon,
-                        "factor": 14.399652,
-                    }
+            if code == "vasp" and not np.all(np.isclose(borns, 0.0)):
+                phonon.nac_params = {
+                    "born": borns,
+                    "dielectric": epsilon,
+                    "factor": 14.399652,
+                }
             # Other codes could be added here
         else:
             borns = None
@@ -424,10 +425,9 @@ class PhononBSDOSDoc(BaseModel):
             / structure.composition.reduced_composition.num_atoms
         )
 
-        if total_dft_energy is not None:
-            total_dft_energy_per_formula_unit = total_dft_energy / formula_units
-        else:
-            total_dft_energy_per_formula_unit = None
+        total_dft_energy_per_formula_unit = (
+            total_dft_energy / formula_units if total_dft_energy is not None else None
+        )
 
         return cls(
             structure=structure,
@@ -449,7 +449,7 @@ class PhononBSDOSDoc(BaseModel):
             primitive_matrix=phonon.primitive_matrix.tolist(),
             code="vasp",
             thermal_displacement_data={
-                "temperatures_thermal_displacements": temperature_range_thermal_displacements.tolist(),
+                "temperatures_thermal_displacements": temperature_range_thermal_displacements.tolist(),  # noqa: E501
                 "thermal_displacement_matrix_cif": tdisp_mat_cif,
                 "thermal_displacement_matrix": tdisp_mat,
                 "freq_min_thermal_displacements": freq_min_thermal_displacements,
diff --git a/src/atomate2/vasp/schemas/task.py b/src/atomate2/vasp/schemas/task.py
index 599689f6..e2e73e2f 100644
--- a/src/atomate2/vasp/schemas/task.py
+++ b/src/atomate2/vasp/schemas/task.py
@@ -214,7 +214,6 @@ class OutputSummary(BaseModel):
         OutputSummary
             The calculation output summary.
         """
-
         if calc_doc.output.ionic_steps is not None:
             forces = calc_doc.output.ionic_steps[-1].forces
             stress = calc_doc.output.ionic_steps[-1].stress
@@ -389,7 +388,8 @@ class TaskDocument(StructureMetadata):
             completed_at=calcs_reversed[0].completed_at,
             input=InputSummary.from_vasp_calc_doc(calcs_reversed[-1]),
             output=OutputSummary.from_vasp_calc_doc(
-                calcs_reversed[0], vasp_objects.get(VaspObject.TRAJECTORY)  # type: ignore
+                calcs_reversed[0],
+                vasp_objects.get(VaspObject.TRAJECTORY),  # type: ignore
             ),
             state=_get_state(calcs_reversed, analysis),
             entry=cls.get_entry(calcs_reversed),
@@ -561,10 +561,7 @@ def _get_drift_warnings(calc_doc: Calculation) -> List[str]:
         drift = calc_doc.output.outcar.get("drift", [[0, 0, 0]])
         max_drift = max(np.linalg.norm(d) for d in drift)
         ediffg = calc_doc.input.parameters.get("EDIFFG", None)
-        if ediffg and float(ediffg) < 0:
-            max_force = -float(ediffg)
-        else:
-            max_force = np.inf
+        max_force = -float(ediffg) if ediffg and float(ediffg) < 0 else np.inf
         if max_drift > max_force:
             warnings.append(
                 f"Drift ({drift}) > desired force convergence ({max_force}), structure "
diff --git a/src/atomate2/vasp/sets/base.py b/src/atomate2/vasp/sets/base.py
index 976e9960..dd658aea 100644
--- a/src/atomate2/vasp/sets/base.py
+++ b/src/atomate2/vasp/sets/base.py
@@ -166,7 +166,7 @@ class VaspInputSet(InputSet):
             )
 
         if (
-            all(k.is_metal for k in self.poscar.structure.composition.keys())
+            all(k.is_metal for k in self.poscar.structure.composition)
             and self.incar.get("NSW", 0) > 0
             and self.incar.get("ISMEAR", 1) < 1
         ):
@@ -825,6 +825,11 @@ def _get_kspacing(bandgap: float) -> float:
 def _get_magmoms(magmoms, structure):
     """Get the mamgoms."""
     mag = []
+    msg = (
+        "Co without an oxidation state is initialized as low spin by default in "
+        "Atomate2. If this default behavior is not desired, please set the spin on the "
+        "magmom on the site directly to ensure correct initialization."
+    )
     for site in structure:
         if hasattr(site, "magmom"):
             mag.append(site.magmom)
@@ -832,19 +837,11 @@ def _get_magmoms(magmoms, structure):
             mag.append(site.specie.spin)
         elif str(site.specie) in magmoms:
             if site.specie.symbol == "Co" and magmoms[str(site.specie)] <= 1.0:
-                warnings.warn(
-                    "Co without an oxidation state is initialized as low spin by default in Atomate2. "
-                    "If this default behavior is not desired, please set the spin on the magmom on the "
-                    "site directly to ensure correct initialization."
-                )
+                warnings.warn(msg)
             mag.append(magmoms.get(str(site.specie)))
         else:
             if site.specie.symbol == "Co":
-                warnings.warn(
-                    "Co without an oxidation state is initialized as low spin by default in Atomate2. "
-                    "If this default behavior is not desired, please set the spin on the magmom on the "
-                    "site directly to ensure correct initialization."
-                )
+                warnings.warn(msg)
             mag.append(magmoms.get(site.specie.symbol, 0.6))
     return mag
 
diff --git a/src/atomate2/vasp/sets/core.py b/src/atomate2/vasp/sets/core.py
index 9d206f5c..a6e36764 100644
--- a/src/atomate2/vasp/sets/core.py
+++ b/src/atomate2/vasp/sets/core.py
@@ -886,13 +886,12 @@ class MDSetGenerator(VaspInputGenerator):
             }
         )
 
-        if Element("H") in structure.species:
-            if updates["POTIM"] > 0.5:
-                logger.warning(
-                    f"Molecular dynamics time step is {updates['POTIM']}, which is "
-                    "typically too large for a structure containing H. Consider set it "
-                    "to a value of 0.5 or smaller."
-                )
+        if Element("H") in structure.species and updates["POTIM"] > 0.5:
+            logger.warning(
+                f"Molecular dynamics time step is {updates['POTIM']}, which is "
+                "typically too large for a structure containing H. Consider set it "
+                "to a value of 0.5 or smaller."
+            )
 
         return updates
 
diff --git a/tests/conftest.py b/tests/conftest.py
index b7391d96..f1679c14 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -89,7 +89,7 @@ def memory_jobstore():
 
 
 @pytest.fixture(scope="session", autouse=True)
-def log_to_stdout():
+def log_to_stdout_auto_use():
     from atomate2.utils.log import initialize_logger
 
     initialize_logger()
diff --git a/tests/vasp/flows/test_core.py b/tests/vasp/flows/test_core.py
index a5f19484..3ca7f300 100644
--- a/tests/vasp/flows/test_core.py
+++ b/tests/vasp/flows/test_core.py
@@ -224,7 +224,8 @@ def test_hse_band_structure(mock_vasp, clean_dir, si_structure):
     # mapping from job name to directory containing test files
     ref_paths = {
         "hse band structure line": "Si_hse_band_structure/hse_band_structure_line",
-        "hse band structure uniform": "Si_hse_band_structure/hse_band_structure_uniform",
+        "hse band structure uniform": "Si_hse_band_structure/"
+        "hse_band_structure_uniform",
         "hse static": "Si_hse_band_structure/hse_static",
     }
 
@@ -274,7 +275,8 @@ def test_hse_uniform_band_structure(mock_vasp, clean_dir, si_structure):
 
     # mapping from job name to directory containing test files
     ref_paths = {
-        "hse band structure uniform": "Si_hse_band_structure/hse_band_structure_uniform",
+        "hse band structure uniform": "Si_hse_band_structure/"
+        "hse_band_structure_uniform",
         "hse static": "Si_hse_band_structure/hse_static",
     }
 
diff --git a/tests/vasp/flows/test_elph.py b/tests/vasp/flows/test_elph.py
index 65770df4..18acf4d9 100644
--- a/tests/vasp/flows/test_elph.py
+++ b/tests/vasp/flows/test_elph.py
@@ -4,16 +4,18 @@ def test_elph_renormalisation(mock_vasp, clean_dir, si_structure):
     from atomate2.vasp.flows.elph import ElectronPhononMaker
     from atomate2.vasp.schemas.elph import ElectronPhononRenormalisationDoc
 
-    # mapping from job name to directory containing test files
+    # map job name to directory containing test files
     ref_paths = {
         "non-scf uniform T=0.0": "Si_elph_renorm/non-scf_uniform_T=0.0",
         "non-scf uniform T=100.0": "Si_elph_renorm/non-scf_uniform_T=100.0",
-        "non-scf uniform bulk supercell": "Si_elph_renorm/non-scf_uniform_bulk_supercell",
+        "non-scf uniform bulk supercell": "Si_elph_renorm/"
+        "non-scf_uniform_bulk_supercell",
         "static": "Si_elph_renorm/static",
         "static T=0.0": "Si_elph_renorm/static_T=0.0",
         "static T=100.0": "Si_elph_renorm/static_T=100.0",
         "static bulk supercell": "Si_elph_renorm/static_bulk_supercell",
-        "supercell electron phonon displacements": "Si_elph_renorm/supercell_electron_phonon_displacements",
+        "supercell electron phonon displacements": "Si_elph_renorm/"
+        "supercell_electron_phonon_displacements",
     }
 
     # settings passed to fake_run_vasp; adjust these to check for certain INCAR settings
diff --git a/tests/vasp/flows/test_phonon.py b/tests/vasp/flows/test_phonon.py
index 4c2b7299..49b09b38 100644
--- a/tests/vasp/flows/test_phonon.py
+++ b/tests/vasp/flows/test_phonon.py
@@ -72,10 +72,7 @@ def test_phonon_wf_only_displacements3(mock_vasp, clean_dir):
         PhononBandStructureSymmLine,
     )
     assert isinstance(responses[job.jobs[-1].uuid][1].output.phonon_dos, PhononDos)
-    assert (
-        getattr(responses[job.jobs[-1].uuid][1].output, "thermal_displacement_data")
-        is None
-    )
+    assert responses[job.jobs[-1].uuid][1].output.thermal_displacement_data is None
     assert isinstance(responses[job.jobs[-1].uuid][1].output.structure, Structure)
     assert np.allclose(
         responses[job.jobs[-1].uuid][1].output.temperatures, [0, 100, 200, 300, 400]
@@ -83,14 +80,14 @@ def test_phonon_wf_only_displacements3(mock_vasp, clean_dir):
     assert np.allclose(
         responses[job.jobs[-1].uuid][1].output.has_imaginary_modes, False
     )
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "force_constants") is None
+    assert responses[job.jobs[-1].uuid][1].output.force_constants is None
     assert isinstance(responses[job.jobs[-1].uuid][1].output.jobdirs, PhononJobDirs)
     assert isinstance(responses[job.jobs[-1].uuid][1].output.uuids, PhononUUIDs)
     assert np.isclose(
         responses[job.jobs[-1].uuid][1].output.total_dft_energy, -5.74555232
     )
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "born") is None
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "epsilon_static") is None
+    assert responses[job.jobs[-1].uuid][1].output.born is None
+    assert responses[job.jobs[-1].uuid][1].output.epsilon_static is None
     assert np.allclose(
         responses[job.jobs[-1].uuid][1].output.supercell_matrix,
         [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
@@ -242,10 +239,7 @@ def test_phonon_wf_only_displacements_no_structural_transformation(
         PhononBandStructureSymmLine,
     )
     assert isinstance(responses[job.jobs[-1].uuid][1].output.phonon_dos, PhononDos)
-    assert (
-        getattr(responses[job.jobs[-1].uuid][1].output, "thermal_displacement_data")
-        is None
-    )
+    assert responses[job.jobs[-1].uuid][1].output.thermal_displacement_data is None
     assert isinstance(responses[job.jobs[-1].uuid][1].output.structure, Structure)
     assert np.allclose(
         responses[job.jobs[-1].uuid][1].output.temperatures, [0, 100, 200, 300, 400]
@@ -253,14 +247,14 @@ def test_phonon_wf_only_displacements_no_structural_transformation(
     assert np.allclose(
         responses[job.jobs[-1].uuid][1].output.has_imaginary_modes, False
     )
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "force_constants") is None
+    assert responses[job.jobs[-1].uuid][1].output.force_constants is None
     assert isinstance(responses[job.jobs[-1].uuid][1].output.jobdirs, PhononJobDirs)
     assert isinstance(responses[job.jobs[-1].uuid][1].output.uuids, PhononUUIDs)
     assert np.isclose(
         responses[job.jobs[-1].uuid][1].output.total_dft_energy, -5.74525804
     )
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "born") is None
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "epsilon_static") is None
+    assert responses[job.jobs[-1].uuid][1].output.born is None
+    assert responses[job.jobs[-1].uuid][1].output.epsilon_static is None
     assert np.allclose(
         responses[job.jobs[-1].uuid][1].output.supercell_matrix,
         ((-1.0, 1.0, 1.0), (1.0, -1.0, 1.0), (1.0, 1.0, -1.0)),
@@ -392,9 +386,9 @@ def test_phonon_wf_only_displacements_kpath(mock_vasp, clean_dir, kpathscheme):
     )
     assert isinstance(responses[job.jobs[-1].uuid][1].output.jobdirs, PhononJobDirs)
     assert isinstance(responses[job.jobs[-1].uuid][1].output.uuids, PhononUUIDs)
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "total_dft_energy") is None
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "born") is None
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "epsilon_static") is None
+    assert responses[job.jobs[-1].uuid][1].output.total_dft_energy is None
+    assert responses[job.jobs[-1].uuid][1].output.born is None
+    assert responses[job.jobs[-1].uuid][1].output.epsilon_static is None
     assert np.allclose(
         responses[job.jobs[-1].uuid][1].output.supercell_matrix,
         [[-1.0, 1.0, 1.0], [1.0, -1.0, 1.0], [1.0, 1.0, -1.0]],
@@ -667,10 +661,7 @@ def test_phonon_wf_only_displacements_optional_settings(mock_vasp, clean_dir):
         PhononBandStructureSymmLine,
     )
     assert isinstance(responses[job.jobs[-1].uuid][1].output.phonon_dos, PhononDos)
-    assert (
-        getattr(responses[job.jobs[-1].uuid][1].output, "thermal_displacement_data")
-        is None
-    )
+    assert responses[job.jobs[-1].uuid][1].output.thermal_displacement_data is None
     assert isinstance(responses[job.jobs[-1].uuid][1].output.structure, Structure)
     assert np.allclose(
         responses[job.jobs[-1].uuid][1].output.temperatures, [0, 100, 200, 300, 400]
@@ -678,12 +669,12 @@ def test_phonon_wf_only_displacements_optional_settings(mock_vasp, clean_dir):
     assert np.allclose(
         responses[job.jobs[-1].uuid][1].output.has_imaginary_modes, False
     )
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "force_constants") is None
+    assert responses[job.jobs[-1].uuid][1].output.force_constants is None
     assert isinstance(responses[job.jobs[-1].uuid][1].output.jobdirs, PhononJobDirs)
     assert isinstance(responses[job.jobs[-1].uuid][1].output.uuids, PhononUUIDs)
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "total_dft_energy") is None
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "born") is None
-    assert getattr(responses[job.jobs[-1].uuid][1].output, "epsilon_static") is None
+    assert responses[job.jobs[-1].uuid][1].output.total_dft_energy is None
+    assert responses[job.jobs[-1].uuid][1].output.born is None
+    assert responses[job.jobs[-1].uuid][1].output.epsilon_static is None
     assert np.allclose(
         responses[job.jobs[-1].uuid][1].output.supercell_matrix,
         [[-1.0, 1.0, 1.0], [1.0, -1.0, 1.0], [1.0, 1.0, -1.0]],
@@ -819,12 +810,13 @@ def test_phonon_wf_all_steps(mock_vasp, clean_dir):
     )
 
 
-# use a structure where born charges are actually useful for the computation and change the values
+# use a structure where Born charges are actually useful for the computation and change
+# the values
 
 
 # test raises?
-# would be good to check if ValueErrors are raised when certain kpath schemes are combined with
-# non-standard-primitive structures
+# would be good to check if ValueErrors are raised when certain kpath schemes are
+# combined with non-standard-primitive structures
 # this will test all kpath schemes in combination with primitive cell
 @pytest.mark.parametrize(
     "kpathscheme", ["hinuma", "setyawan_curtarolo", "latimer_munro"]
@@ -987,7 +979,8 @@ def test_phonon_wf_all_steps_NaCl(mock_vasp, clean_dir):
             "phonon static 9/10": "Mg3Sb2_phonons/phonon_static_9_10",
         }
 
-        # settings passed to fake_run_vasp; adjust these to check for certain INCAR settings
+        # settings passed to fake_run_vasp; adjust these to check for certain INCAR
+        # settings
         fake_run_vasp_kwargs = {
             "dielectric": {"incar_settings": ["NSW", "ISMEAR"]},
             "phonon static 1/10": {"incar_settings": ["NSW", "ISMEAR"]},
diff --git a/tests/vasp/schemas/conftest.py b/tests/vasp/schemas/conftest.py
index c3c95e80..403e3698 100644
--- a/tests/vasp/schemas/conftest.py
+++ b/tests/vasp/schemas/conftest.py
@@ -3,7 +3,7 @@ import pytest
 
 def assert_schemas_equal(test_schema, valid_schema):
     """
-    Recursively test that all items in valid_schema are present and equal in test_schema.
+    Recursively test all items in valid_schema are present and equal in test_schema.
 
     While test_schema can be a pydantic schema or dictionary, the valid schema must
     be a (nested) dictionary. This function automatically handles accessing the
diff --git a/tests/vasp/schemas/test_defect.py b/tests/vasp/schemas/test_defect.py
index 51e393f8..97ed8a0c 100644
--- a/tests/vasp/schemas/test_defect.py
+++ b/tests/vasp/schemas/test_defect.py
@@ -1,7 +1,8 @@
 def test_sort_pos_dist():
     """
     Test the sorting algorithm with a list of 2D positions.
-    The algorithm should sort the list into a straight line depending on the direction of s1 and s2
+    The algorithm should sort the list into a straight line depending on the direction
+    of s1 and s2
     """
     import numpy as np
 
@@ -29,11 +30,7 @@ def test_CCDDocument(vasp_test_dir):
 
     def is_strict_minimum(min_index, arr):
         min_val = arr[min_index]
-        for i, val in enumerate(arr):
-            if i != min_index:
-                if val < min_val:
-                    return False
-        return True
+        return all(not (i != min_index and val < min_val) for i, val in enumerate(arr))
 
     static_tasks1: list[TaskDocument] = []
     static_tasks2: list[TaskDocument] = []
diff --git a/tests/vasp/schemas/test_task.py b/tests/vasp/schemas/test_task.py
index a660075b..82c01298 100644
--- a/tests/vasp/schemas/test_task.py
+++ b/tests/vasp/schemas/test_task.py
@@ -24,8 +24,9 @@ def test_analysis_summary(vasp_test_dir, object_name):
     for task_name, files in test_object.task_files.items():
         doc, _ = Calculation.from_vasp_files(dir_name, task_name, **files)
         calcs_reversed.append(doc)
-        ## The 2 tasks of double-relaxation have been reversed in "/atomate2/tests/vasp/schemas/conftest.py" for "SiOptimizeDouble"
-        ## task_files are in the order of {"relax2","relax1"}
+        # The 2 tasks of double-relaxation have been reversed in
+        # "/atomate2/tests/vasp/schemas/conftest.py" for "SiOptimizeDouble"
+        # task_files are in the order of {"relax2","relax1"}
 
     test_doc = AnalysisSummary.from_vasp_calc_docs(calcs_reversed)
     valid_doc = test_object.task_doc["analysis"]
['src/atomate2/common/analysis/defects/schemas.py', 'src/atomate2/common/files.py', 'src/atomate2/vasp/schemas/phonons.py', 'src/atomate2/amset/schemas.py', 'src/atomate2/vasp/schemas/defect.py', 'src/atomate2/vasp/flows/phonons.py', 'src/atomate2/vasp/sets/base.py', 'src/atomate2/vasp/flows/defect.py', 'docs/dev/dev_install.md', 'src/atomate2/vasp/schemas/calc_types/utils.py', 'tests/vasp/schemas/test_defect.py', 'src/atomate2/vasp/schemas/task.py', '.github/PULL_REQUEST_TEMPLATE.md', 'tests/vasp/flows/test_core.py', 'src/atomate2/common/jobs.py', 'src/atomate2/utils/file_client.py', 'src/atomate2/vasp/jobs/elastic.py', 'src/atomate2/common/schemas/elastic.py', 'pyproject.toml', '.pre-commit-config.yaml', 'src/atomate2/common/schemas/cclib.py', 'src/atomate2/vasp/sets/core.py', 'tests/vasp/flows/test_elph.py', 'tests/vasp/schemas/conftest.py', 'src/atomate2/vasp/files.py', 'src/atomate2/vasp/jobs/phonons.py', 'src/atomate2/common/schemas/symmetry.py', 'src/atomate2/cli/dev.py', 'tests/conftest.py', 'tests/vasp/flows/test_phonon.py', 'tests/vasp/schemas/test_task.py', 'src/atomate2/vasp/schemas/calculation.py', 'src/atomate2/vasp/run.py']