diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f7d92dc..e0f0fd3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ ### Deprecated ### Removed ### Fixed +- Updated deprecated `typing` types to be compliant with Python >=3.11 guidelines (#216) ## [2.0.0] - 2026-02-10 diff --git a/src/opi/execution/base.py b/src/opi/execution/base.py index 4069e863..19931191 100644 --- a/src/opi/execution/base.py +++ b/src/opi/execution/base.py @@ -14,11 +14,12 @@ import os import shutil import subprocess +from collections.abc import Callable, Sequence from contextlib import nullcontext from io import TextIOWrapper from pathlib import Path from subprocess import CompletedProcess -from typing import Any, Callable, Concatenate, ParamSpec, Sequence, TypeVar, cast +from typing import Any, Concatenate, ParamSpec, TypeVar, cast from opi import ORCA_MINIMAL_VERSION from opi.lib.orca_binary import OrcaBinary diff --git a/src/opi/execution/core.py b/src/opi/execution/core.py index da560b70..8388a945 100644 --- a/src/opi/execution/core.py +++ b/src/opi/execution/core.py @@ -3,8 +3,8 @@ """ import json +from collections.abc import Sequence from pathlib import Path -from typing import Sequence from opi.execution.base import BaseRunner from opi.lib.orca_binary import OrcaBinary diff --git a/src/opi/input/blocks/block_cpcm.py b/src/opi/input/blocks/block_cpcm.py index bdbfbee7..6b0e4eb8 100644 --- a/src/opi/input/blocks/block_cpcm.py +++ b/src/opi/input/blocks/block_cpcm.py @@ -1,4 +1,5 @@ -from typing import Any, Callable, Literal, Union +from collections.abc import Callable +from typing import Any, Literal from pydantic import BaseModel, Field @@ -128,7 +129,7 @@ class BlockCpcm(Block): smdsolvent: Solvent | None = None def format_orca(self) -> str: - special_handlers: dict[str, Callable[[Any], Union[str, None]]] = { + special_handlers: dict[str, Callable[[Any], str | None]] = { "aftercoord": lambda v: None, # Skip this field "radii": lambda v: f" radii{str(v)}", "radius": lambda v: f" radius{str(v)}", diff --git a/src/opi/input/blocks/block_frag.py b/src/opi/input/blocks/block_frag.py index 9d3e48f0..b778a28b 100644 --- a/src/opi/input/blocks/block_frag.py +++ b/src/opi/input/blocks/block_frag.py @@ -1,4 +1,4 @@ -from typing import List, Literal +from typing import Literal from pydantic import BaseModel, field_validator @@ -23,7 +23,7 @@ class FragProc(BaseModel): Class to model `fragproc` attribute in `BlockFrag` """ - flags: List[ + flags: list[ Literal[ "extlib", "connectivity", diff --git a/src/opi/input/structures/properties.py b/src/opi/input/structures/properties.py index a7aadd4f..f4bb2020 100644 --- a/src/opi/input/structures/properties.py +++ b/src/opi/input/structures/properties.py @@ -1,8 +1,8 @@ import re -from collections.abc import Iterator +from collections.abc import Iterator, Sequence from os import PathLike from pathlib import Path -from typing import Literal, Sequence +from typing import Literal from opi.utils.tracking_text_io import TrackingTextIO diff --git a/src/opi/input/structures/structure.py b/src/opi/input/structures/structure.py index f78802f9..8dccf329 100644 --- a/src/opi/input/structures/structure.py +++ b/src/opi/input/structures/structure.py @@ -1,8 +1,8 @@ import re -from collections.abc import Iterator +from collections.abc import Iterable, Iterator, Sequence from os import PathLike from pathlib import Path -from typing import TYPE_CHECKING, Any, Iterable, Sequence, cast +from typing import TYPE_CHECKING, Any, cast from warnings import warn import numpy as np diff --git a/src/opi/output/core.py b/src/opi/output/core.py index 16a5b629..db542984 100644 --- a/src/opi/output/core.py +++ b/src/opi/output/core.py @@ -4,9 +4,9 @@ """ import json -from collections.abc import Sequence +from collections.abc import Callable, Sequence from pathlib import Path -from typing import Any, Callable, cast +from typing import Any, cast from warnings import warn import numpy as np diff --git a/src/opi/output/cube.py b/src/opi/output/cube.py index 6e1b9c79..e3987152 100644 --- a/src/opi/output/cube.py +++ b/src/opi/output/cube.py @@ -1,5 +1,5 @@ +from collections.abc import Iterator from pathlib import Path -from typing import Iterator class CubeOutput: diff --git a/src/opi/output/grepper/core.py b/src/opi/output/grepper/core.py index c6ec631f..495c8cc9 100644 --- a/src/opi/output/grepper/core.py +++ b/src/opi/output/grepper/core.py @@ -1,7 +1,7 @@ -from collections.abc import Iterator +from collections.abc import Callable, Iterator from pathlib import Path from re import IGNORECASE, Pattern, RegexFlag, compile, escape, split -from typing import Any, Callable +from typing import Any from opi.output.grepper.pre_condition import ( ConditionStatus, diff --git a/src/opi/output/ir_mode.py b/src/opi/output/ir_mode.py index fc8314c8..83b9e4ef 100644 --- a/src/opi/output/ir_mode.py +++ b/src/opi/output/ir_mode.py @@ -1,5 +1,4 @@ from dataclasses import dataclass -from typing import Tuple @dataclass @@ -17,7 +16,7 @@ class IrMode: Partial molar absorptivity (epsilon) of the mode in L/(mol*cm). intensity: float IR intensity of the mode in km/mol. - dipole: Tuple[float, float, float] + dipole: tuple[float, float, float] Dipole derivatives TX TY TZ in atomic units. """ @@ -25,7 +24,7 @@ class IrMode: wavenumber: float eps: float intensity: float - dipole: Tuple[float, float, float] + dipole: tuple[float, float, float] @classmethod def from_string(cls, line: str) -> "IrMode": diff --git a/src/opi/output/models/base/get_item.py b/src/opi/output/models/base/get_item.py index 6db571b7..ccb4c1b5 100644 --- a/src/opi/output/models/base/get_item.py +++ b/src/opi/output/models/base/get_item.py @@ -1,7 +1,8 @@ import re import typing from abc import ABC -from typing import Any, Union, get_args, get_origin +from types import UnionType +from typing import Any, get_args, get_origin from pydantic import BaseModel @@ -12,7 +13,7 @@ def get_clean_type_name(t: Any) -> str: origin = get_origin(t) # > If the type is a Union we have to dissect it # > typically it will be Union[Something | None] so we do not want the None part - if origin is Union: + if origin is UnionType: # > Generate a list of the types in the Union args = [a for a in get_args(t) if a is not type(None)] # > recursively call the function on the first argument diff --git a/src/opi/output/models/base/strict_types.py b/src/opi/output/models/base/strict_types.py index 9807262d..e3f66fdd 100644 --- a/src/opi/output/models/base/strict_types.py +++ b/src/opi/output/models/base/strict_types.py @@ -1,4 +1,4 @@ -from typing import Literal, Union +from typing import Literal from pydantic import Field, FiniteFloat, NonNegativeInt, PositiveInt, Strict from typing_extensions import Annotated @@ -16,9 +16,7 @@ StrictNegativeFloat = Annotated[FiniteFloat, Strict(), Field(lt=0)] StrictPositiveFloatOrMinusOne = Annotated[ - Union[ - Annotated[FiniteFloat, Strict(), Field(gt=0)], # Positive float - Literal[-1], - ], + Annotated[FiniteFloat, Strict(), Field(gt=0)] # Positive float + | Literal[-1], Field(description="Positive float or -1"), ] diff --git a/src/opi/output/models/json/property/properties/energy_list.py b/src/opi/output/models/json/property/properties/energy_list.py index ef0abd77..bc6b02d3 100644 --- a/src/opi/output/models/json/property/properties/energy_list.py +++ b/src/opi/output/models/json/property/properties/energy_list.py @@ -1,4 +1,5 @@ -from typing import ClassVar, Iterator +from collections.abc import Iterator +from typing import ClassVar from pydantic import ConfigDict, RootModel diff --git a/src/opi/utils/misc.py b/src/opi/utils/misc.py index 90d85c59..b54be02c 100644 --- a/src/opi/utils/misc.py +++ b/src/opi/utils/misc.py @@ -1,8 +1,9 @@ import os import platform import sys +from collections.abc import Mapping, Sequence from pathlib import Path -from typing import Any, Mapping, Sequence, cast +from typing import Any, cast from opi import ORCA_MINIMAL_VERSION from opi.lib.orca_binary import OrcaBinary diff --git a/src/opi/utils/tracking_text_io.py b/src/opi/utils/tracking_text_io.py index 705868d0..54795a53 100644 --- a/src/opi/utils/tracking_text_io.py +++ b/src/opi/utils/tracking_text_io.py @@ -1,6 +1,6 @@ import types from io import StringIO -from typing import Any, Optional, TextIO, Type +from typing import Any, TextIO class TrackingTextIO: @@ -20,9 +20,9 @@ def __enter__(self) -> "TrackingTextIO": def __exit__( self, - _exc_type: Optional[Type[BaseException]], - _exc_value: Optional[BaseException], - _traceback: Optional[types.TracebackType], + _exc_type: type[BaseException] | None, + _exc_value: BaseException | None, + _traceback: types.TracebackType | None, ) -> bool | None: self._stream.close() return None diff --git a/tests/conftest.py b/tests/conftest.py index 8fa94e13..098e2fe3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,7 +9,7 @@ from collections.abc import Generator from dataclasses import dataclass from pathlib import Path -from typing import Any, Optional, cast +from typing import Any, cast import pytest from _pytest._code.code import ExceptionRepr @@ -119,7 +119,7 @@ def pytest_runtest_makereport( funcargs = cast(dict[str, Any], getattr(item, "funcargs", {})) # > if `tmp_path` is in the functions signature - tmp = cast(Optional[Path], funcargs.get("tmp_path")) + tmp = cast(Path | None, funcargs.get("tmp_path")) if tmp is not None: # > make mypy happy by making sure `when` is not None when = rep.when or "call" diff --git a/tests/fixtures/example_input_file.py b/tests/fixtures/example_input_file.py index 0184db8d..ebfd9367 100644 --- a/tests/fixtures/example_input_file.py +++ b/tests/fixtures/example_input_file.py @@ -1,6 +1,6 @@ import inspect +from collections.abc import Callable from pathlib import Path -from typing import Callable import pytest diff --git a/tests/fixtures/output_object.py b/tests/fixtures/output_object.py index 51ce1a8f..b0063f97 100644 --- a/tests/fixtures/output_object.py +++ b/tests/fixtures/output_object.py @@ -1,5 +1,5 @@ +from collections.abc import Callable from pathlib import Path -from typing import Callable import pytest diff --git a/tests/unit/test_output_attributes.py b/tests/unit/test_output_attributes.py index f6a9b6b4..00eed84d 100644 --- a/tests/unit/test_output_attributes.py +++ b/tests/unit/test_output_attributes.py @@ -1,6 +1,6 @@ import inspect from pathlib import Path -from typing import Any, Set, get_args, get_origin +from typing import Any, get_args, get_origin import pytest from pydantic import BaseModel @@ -89,8 +89,8 @@ def test_attributes(self, tmp_path: Path, json_dir: Path, json_file_list: list[P assert not output_attr def get_all_attributes( - self, model: type[BaseModel], visited: Set[type] = None, prefix: str = "" - ) -> Set[str]: + self, model: type[BaseModel], visited: set[type] = None, prefix: str = "" + ) -> set[str]: """ Recursively get all attribute names from a Pydantic model, including nested custom types. Attribute names include their parent class prefix (e.g., "A.attr1.attr2"). @@ -164,7 +164,7 @@ def collect_non_none_attrs( depth: int = -1, prefix: str | None = None, _visited=None, - ) -> Set[str]: + ) -> set[str]: """ Collect a set of attribute paths whose values are not None. - Accepts a single object or a list of objects