Skip to content

Commit 5b4941c

Browse files
Declare minimum Python version (#2097)
* Declare minimum Python version * Fix * Autoupdate
1 parent e391261 commit 5b4941c

19 files changed

+187
-194
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ ci:
33
files: ^openff|(^examples/((?!deprecated).)*$)|^docs|(^utilities/((?!deprecated).)*$)
44
repos:
55
- repo: https://github.com/astral-sh/ruff-pre-commit
6-
rev: v0.12.8
6+
rev: v0.12.11
77
hooks:
88
- id: ruff-format
99
- id: ruff-check

openff/toolkit/_tests/utils.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import pprint
1414
import textwrap
1515
from contextlib import contextmanager
16-
from typing import Union
1716

1817
import numpy as np
1918
import openmm
@@ -47,7 +46,7 @@
4746
)
4847

4948

50-
def _get_readme_path() -> Union[pathlib.Path, None]:
49+
def _get_readme_path() -> pathlib.Path | None:
5150
"""
5251
Return a path to the README file or None if it cannot be assured to be the toolkit's README.
5352
"""

openff/toolkit/topology/_mm_molecule.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import functools
1414
from collections.abc import Generator, Iterable
15-
from typing import TYPE_CHECKING, NoReturn, Optional, Union
15+
from typing import TYPE_CHECKING, NoReturn, Union
1616

1717
from openff.units.elements import MASSES, SYMBOLS
1818

@@ -62,7 +62,7 @@ def add_bond(self, atom1, atom2, **kwargs):
6262
self.bonds.append(bond)
6363

6464
@property
65-
def conformers(self) -> Optional[list["Quantity"]]:
65+
def conformers(self) -> list["Quantity"] | None:
6666
return self._conformers
6767

6868
def add_conformer(self, conformer):
@@ -457,7 +457,7 @@ def are_isomorphic(
457457
mol1: Union["FrozenMolecule", "_SimpleMolecule", "nx.Graph"],
458458
mol2: Union["FrozenMolecule", "_SimpleMolecule", "nx.Graph"],
459459
return_atom_map: bool = False,
460-
) -> tuple[bool, Optional[dict[int, int]]]:
460+
) -> tuple[bool, dict[int, int] | None]:
461461
import networkx
462462

463463
_cls = _SimpleMolecule
@@ -540,8 +540,8 @@ class _SimpleAtom:
540540
def __init__(
541541
self,
542542
atomic_number: int,
543-
molecule: Optional[_SimpleMolecule] = None,
544-
metadata: Optional[AtomMetadataDict] = None,
543+
molecule: _SimpleMolecule | None = None,
544+
metadata: AtomMetadataDict | None = None,
545545
name: str = "",
546546
**kwargs,
547547
):
@@ -609,8 +609,8 @@ def bonded_atoms(self):
609609
def molecule_atom_index(self) -> int:
610610
return self.molecule.atoms.index(self)
611611

612-
def to_dict(self) -> dict[str, Union[dict, str, int]]:
613-
atom_dict: dict[str, Union[dict, str, int]] = dict()
612+
def to_dict(self) -> dict[str, dict | str | int]:
613+
atom_dict: dict[str, dict | str | int] = dict()
614614
atom_dict["metadata"] = dict(self.metadata)
615615
atom_dict["atomic_number"] = self._atomic_number
616616
atom_dict["name"] = self._name

openff/toolkit/topology/molecule.py

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939
TYPE_CHECKING,
4040
Any,
4141
Literal,
42-
Optional,
4342
TextIO,
43+
TypeAlias,
4444
TypeVar,
4545
Union,
4646
overload,
@@ -50,7 +50,6 @@
5050
from openff.units import Unit
5151
from openff.units.elements import MASSES, SYMBOLS
5252
from openff.utilities.exceptions import MissingOptionalDependencyError
53-
from typing_extensions import TypeAlias
5453

5554
from openff.toolkit import Quantity, unit
5655
from openff.toolkit.utils.constants import DEFAULT_AROMATICITY_MODEL
@@ -105,7 +104,7 @@
105104

106105
# TODO: These aliases are duplicated in a few places, might make sense to consolidate them
107106
# into a single location, but that'd weirdly nudge them towards first-class existence
108-
TKR: TypeAlias = Union[ToolkitRegistry, ToolkitWrapper]
107+
TKR: TypeAlias = ToolkitRegistry | ToolkitWrapper
109108
MoleculeLike: TypeAlias = Union["Molecule", "FrozenMolecule", "_SimpleMolecule"]
110109
FM = TypeVar("FM", bound="FrozenMolecule")
111110
P = TypeVar("P", bound="Particle")
@@ -195,7 +194,7 @@ def __init__(self, *args, **kwargs):
195194
def __setitem__(self, key, value):
196195
if not isinstance(key, str):
197196
raise InvalidAtomMetadataError(f"Attempted to set atom metadata with a non-string key. (key: {key}")
198-
if not isinstance(value, (str, int)):
197+
if not isinstance(value, str | int):
199198
raise InvalidAtomMetadataError(
200199
f"Attempted to set atom metadata with a non-string or integer value. (value: {value})"
201200
)
@@ -219,9 +218,9 @@ class Atom(Particle):
219218
def __init__(
220219
self,
221220
atomic_number: int,
222-
formal_charge: Union[int, Quantity],
221+
formal_charge: int | Quantity,
223222
is_aromatic: bool,
224-
name: Optional[str] = None,
223+
name: str | None = None,
225224
molecule=None,
226225
stereochemistry: Literal["R", "S", None] = None,
227226
metadata: Mapping[str, int | str] | None = None,
@@ -301,7 +300,7 @@ def add_bond(self, bond: "Bond"):
301300

302301
self._bonds.append(bond)
303302

304-
def to_dict(self) -> dict[str, Union[None, str, int, bool, dict[Any, Any]]]:
303+
def to_dict(self) -> dict[str, None | str | int | bool | dict[Any, Any]]:
305304
"""Return a dict representation of the :class:`Atom` class instance.
306305
307306
Output dictionary keys and values align with parameters used to initialize
@@ -400,7 +399,7 @@ def partial_charge(self, charge):
400399
"please raise an issue describing your use case."
401400
)
402401

403-
if not isinstance(charge, (Quantity, float)):
402+
if not isinstance(charge, Quantity | float):
404403
raise ValueError(
405404
"Cannot set partial charge with an object that is not a openff.unit.Quantity or float. "
406405
f"Found object of type {type(charge)}."
@@ -693,7 +692,7 @@ def __init__(
693692
self._is_aromatic = is_aromatic
694693
self._stereochemistry = stereochemistry
695694

696-
def to_dict(self) -> dict[str, Union[int, bool, str, float]]:
695+
def to_dict(self) -> dict[str, int | bool | str | float]:
697696
"""Return a ``dict`` representation of the bond.
698697
699698
The output dictionary keys and values align with parameters used to initialize
@@ -895,15 +894,15 @@ class FrozenMolecule(Serializable):
895894
896895
"""
897896

898-
_partial_charges: Optional[Quantity]
899-
_conformers: Optional[list[Quantity]]
897+
_partial_charges: Quantity | None
898+
_conformers: list[Quantity] | None
900899
_properties: dict
901900
_hierarchy_schemes: dict
902901

903902
def __init__(
904903
self,
905904
other=None,
906-
file_format: Optional[str] = None,
905+
file_format: str | None = None,
907906
toolkit_registry: TKR = GLOBAL_TOOLKIT_REGISTRY,
908907
allow_undefined_stereo: bool = False,
909908
):
@@ -990,7 +989,7 @@ def __init__(
990989
"""
991990

992991
self._cached_smiles: dict[str, str] = dict()
993-
self._ordered_connection_table_hash: Optional[int] = None
992+
self._ordered_connection_table_hash: int | None = None
994993

995994
# Figure out if toolkit_registry is a whole registry, or just a single wrapper
996995
if isinstance(toolkit_registry, ToolkitRegistry):
@@ -1051,7 +1050,7 @@ def __init__(
10511050
loaded = True
10521051
# TODO: Make this compatible with file-like objects (I couldn't figure out how to make an oemolistream
10531052
# from a fileIO object)
1054-
if isinstance(other, (str, pathlib.Path)) or (hasattr(other, "read") and not loaded):
1053+
if isinstance(other, str | pathlib.Path) or (hasattr(other, "read") and not loaded):
10551054
try:
10561055
mol = Molecule.from_file(
10571056
other,
@@ -1180,16 +1179,14 @@ def to_dict(self) -> dict:
11801179
# https://mypy.readthedocs.io/en/latest/typed_dict.html#typeddict
11811180
molecule_dict: dict[
11821181
str,
1183-
Union[
1184-
None,
1185-
str,
1186-
bytes,
1187-
dict[str, Any],
1188-
list[str],
1189-
list[bytes],
1190-
list[HierarchyElement],
1191-
list[dict[str, Any]],
1192-
],
1182+
None
1183+
| str
1184+
| bytes
1185+
| dict[str, Any]
1186+
| list[str]
1187+
| list[bytes]
1188+
| list[HierarchyElement]
1189+
| list[dict[str, Any]],
11931190
] = dict()
11941191
molecule_dict["name"] = self._name
11951192

@@ -1310,7 +1307,7 @@ def _initialize_from_dict(self, molecule_dict: dict):
13101307
)
13111308

13121309
if molecule_dict["conformers"] is None:
1313-
self._conformers: Optional[list[Quantity]] = None
1310+
self._conformers: list[Quantity] | None = None
13141311
else:
13151312
from openff.toolkit.utils.utils import deserialize_numpy
13161313

@@ -1572,7 +1569,7 @@ def delete_hierarchy_scheme(self, iter_name: str):
15721569
)
15731570
self._hierarchy_schemes.pop(iter_name)
15741571

1575-
def update_hierarchy_schemes(self, iter_names: Optional[list[str]] = None):
1572+
def update_hierarchy_schemes(self, iter_names: list[str] | None = None):
15761573
"""
15771574
Infer a hierarchy from atom metadata according to the existing hierarchy
15781575
schemes.
@@ -2134,7 +2131,7 @@ def edge_match_func(x, y):
21342131
edge_match_func = None # type: ignore
21352132

21362133
# Here we should work out what data type we have, also deal with lists?
2137-
def to_networkx(data: Union[FrozenMolecule, nx.Graph]) -> nx.Graph:
2134+
def to_networkx(data: FrozenMolecule | nx.Graph) -> nx.Graph:
21382135
"""For the given data type, return the networkx graph"""
21392136
if strip_pyrimidal_n_atom_stereo:
21402137
SMARTS = "[N+0X3:1](-[*])(-[*])(-[*])"
@@ -2552,7 +2549,7 @@ def assign_partial_charges(
25522549
self,
25532550
partial_charge_method: str,
25542551
strict_n_conformers: bool = False,
2555-
use_conformers: Optional[Iterable[Quantity]] = None,
2552+
use_conformers: Iterable[Quantity] | None = None,
25562553
toolkit_registry: TKR = GLOBAL_TOOLKIT_REGISTRY,
25572554
normalize_partial_charges: bool = True,
25582555
):
@@ -2720,9 +2717,9 @@ def _normalize_partial_charges(self):
27202717

27212718
def assign_fractional_bond_orders(
27222719
self,
2723-
bond_order_model: Optional[str] = None,
2720+
bond_order_model: str | None = None,
27242721
toolkit_registry: TKR = GLOBAL_TOOLKIT_REGISTRY,
2725-
use_conformers: Optional[Iterable[Quantity]] = None,
2722+
use_conformers: Iterable[Quantity] | None = None,
27262723
):
27272724
"""
27282725
Update and store list of bond orders this molecule.
@@ -2849,7 +2846,7 @@ def to_networkx(self) -> "nx.Graph":
28492846

28502847
def find_rotatable_bonds(
28512848
self,
2852-
ignore_functional_groups: Optional[list[str]] = None,
2849+
ignore_functional_groups: list[str] | None = None,
28532850
toolkit_registry: TKR = GLOBAL_TOOLKIT_REGISTRY,
28542851
) -> list[Bond]:
28552852
"""
@@ -3805,7 +3802,7 @@ def from_file(
38053802
>>> molecule = Molecule.from_file(sdf_file_path)
38063803
38073804
"""
3808-
toolkit: Optional[ToolkitWrapper]
3805+
toolkit: ToolkitWrapper | None
38093806

38103807
if file_format is None:
38113808
if isinstance(file_path, pathlib.Path):
@@ -3884,7 +3881,7 @@ def from_file(
38843881

38853882
mols = list()
38863883

3887-
if isinstance(file_path, (str, pathlib.Path)):
3884+
if isinstance(file_path, str | pathlib.Path):
38883885
if isinstance(file_path, pathlib.Path):
38893886
file_path = file_path.as_posix()
38903887
mols = toolkit.from_file( # type: ignore[call-arg]
@@ -3913,7 +3910,7 @@ def from_file(
39133910
@requires_package("openmm")
39143911
def from_polymer_pdb(
39153912
cls: type[FM],
3916-
file_path: Union[str, pathlib.Path, TextIO],
3913+
file_path: str | pathlib.Path | TextIO,
39173914
toolkit_registry=GLOBAL_TOOLKIT_REGISTRY,
39183915
name: str = "",
39193916
) -> FM:
@@ -3982,7 +3979,7 @@ def from_polymer_pdb(
39823979
if isinstance(toolkit_registry, ToolkitWrapper):
39833980
toolkit_registry = ToolkitRegistry([type(toolkit_registry)])
39843981

3985-
if isinstance(file_path, (str, io.TextIOWrapper)):
3982+
if isinstance(file_path, str | io.TextIOWrapper):
39863983
pass
39873984
elif isinstance(file_path, pathlib.Path):
39883985
file_path = file_path.as_posix()
@@ -4047,7 +4044,7 @@ def _has_multiple_molecules(self) -> bool:
40474044
num_disconnected_subgraphs = sum(1 for _ in nx.connected_components(graph))
40484045
return num_disconnected_subgraphs > 1
40494046

4050-
def _to_xyz_file(self, file_path: Union[str, IO[str]]):
4047+
def _to_xyz_file(self, file_path: str | IO[str]):
40514048
"""
40524049
Write the current molecule and its conformers to a multiframe xyz file, if the molecule
40534050
has no current coordinates all atoms will be set to 0,0,0 in keeping with the behaviour of the
@@ -4069,7 +4066,7 @@ def _to_xyz_file(self, file_path: Union[str, IO[str]]):
40694066
conformers = self._conformers
40704067

40714068
if len(conformers) == 1:
4072-
end: Union[str, int] = ""
4069+
end: str | int = ""
40734070

40744071
def title(frame):
40754072
return f"{self.name if self.name != '' else self.hill_formula}{frame}\n"
@@ -4126,7 +4123,7 @@ def to_file(self, file_path, file_format, toolkit_registry=GLOBAL_TOOLKIT_REGIST
41264123
>>> molecule.to_file('imatinib.pdb', file_format='pdb') # doctest: +SKIP
41274124
41284125
"""
4129-
toolkit: Optional[ToolkitRegistry]
4126+
toolkit: ToolkitRegistry | None
41304127

41314128
if isinstance(toolkit_registry, ToolkitRegistry):
41324129
pass
@@ -4161,7 +4158,7 @@ def to_file(self, file_path, file_format, toolkit_registry=GLOBAL_TOOLKIT_REGIST
41614158
f"(supported formats: {supported_formats})"
41624159
)
41634160

4164-
if isinstance(file_path, (str, pathlib.Path)):
4161+
if isinstance(file_path, str | pathlib.Path):
41654162
toolkit.to_file(self, file_path, file_format)
41664163
else:
41674164
toolkit.to_file_obj(self, file_path, file_format)
@@ -5122,7 +5119,7 @@ def _is_bonded(self, atom_index_1: int, atom_index_2: int) -> bool:
51225119
atom2 = self._atoms[atom_index_2]
51235120
return atom2 in self._bonded_atoms[atom1]
51245121

5125-
def get_bond_between(self, i: Union[int, Atom], j: Union[int, Atom]) -> Bond:
5122+
def get_bond_between(self, i: int | Atom, j: int | Atom) -> Bond:
51265123
"""Returns the bond between two atoms
51275124
51285125
Parameters
@@ -5226,8 +5223,8 @@ def add_atom(
52265223
formal_charge: int,
52275224
is_aromatic: bool,
52285225
stereochemistry: Literal["R", "S", None] = None,
5229-
name: Optional[str] = None,
5230-
metadata: Optional[dict[str, Union[int, str]]] = None,
5226+
name: str | None = None,
5227+
metadata: dict[str, int | str] | None = None,
52315228
) -> int:
52325229
"""
52335230
Add an atom to the molecule.
@@ -5292,7 +5289,7 @@ def add_bond(
52925289
bond_order: int,
52935290
is_aromatic: bool,
52945291
stereochemistry: Literal["E", "Z", None] = None,
5295-
fractional_bond_order: Optional[float] = None,
5292+
fractional_bond_order: float | None = None,
52965293
) -> int:
52975294
"""
52985295
Add a bond between two specified atom indices
@@ -5525,7 +5522,7 @@ def visualize(
55255522

55265523
def perceive_residues(
55275524
self,
5528-
substructure_file_path: Optional[str] = None,
5525+
substructure_file_path: str | None = None,
55295526
strict_chirality: bool = True,
55305527
):
55315528
"""
@@ -5812,7 +5809,7 @@ def to_dict(self) -> dict:
58125809
58135810
Keys and values align with parameters used to initialize the :class:`HierarchyScheme` class.
58145811
"""
5815-
return_dict: dict[str, Union[str, Sequence[Union[str, int, dict]]]] = dict()
5812+
return_dict: dict[str, str | Sequence[str | int | dict]] = dict()
58165813
return_dict["uniqueness_criteria"] = self.uniqueness_criteria
58175814
return_dict["iterator_name"] = self.iterator_name
58185815
return_dict["hierarchy_elements"] = [e.to_dict() for e in self.hierarchy_elements]

0 commit comments

Comments
 (0)