Skip to content

Commit 0913da4

Browse files
committed
introduced SeqOverFrag and SeqOverAtom
Proper generic new subtypes of generics are not possible :( python/mypy#3331
1 parent dfb1f7d commit 0913da4

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

src/quemb/molbe/chemfrag.py

+24-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from collections import defaultdict
22
from collections.abc import Sequence
3-
from typing import Final, NewType, cast
3+
from typing import Final, NewType, TypeAlias, cast
44

55
import chemcoord as cc
66
from attr import define
@@ -59,6 +59,21 @@
5959
#:
6060
OriginIdx = NewType("OriginIdx", CenterIdx)
6161

62+
# We would like to have a subtype of Sequence that also behaves generically
63+
# so that we could write
64+
# `SeqOverFrag[AOIdx]` for a sequence that contains all AO indices in a fragment
65+
# or `SeqOverAtom[AOIdx]` for a sequence that contains all AO indices in an atom,
66+
# where the Sequence types are different, i.e. a function that takes a `SeqOverFrag`
67+
# would neither accept a `SeqOverAtom` nor a generic `Sequence`.
68+
# However, this is (currently) not possible in Python, see this issue:
69+
# https://github.com/python/mypy/issues/3331
70+
#
71+
# Hence we have to use just TypeAliases, which means that `SeqOverFrag`, `SeqOverAtom`
72+
# and `Sequence` are all the same type.
73+
# This is not ideal, but it is the best we can do at the moment.
74+
SeqOverFrag: TypeAlias = Sequence
75+
SeqOverAtom: TypeAlias = Sequence
76+
6277

6378
def merge_seqs(*seqs: Sequence[T]) -> OrderedSet[T]:
6479
"""Merge multiple sequences into a single :class:`OrderedSet`.
@@ -272,19 +287,19 @@ class FragmentedStructure:
272287
"""
273288

274289
#: The atomic orbital indices per fragment
275-
atoms_per_frag: Final[Sequence[OrderedSet[AtomIdx]]]
290+
atoms_per_frag: Final[SeqOverFrag[OrderedSet[AtomIdx]]]
276291
#: The motifs per fragment.
277292
#: Note that the set of motifs in the fragment
278293
#: is the union of centers and edges.
279-
motifs_per_frag: Final[Sequence[OrderedSet[MotifIdx]]]
294+
motifs_per_frag: Final[SeqOverFrag[OrderedSet[MotifIdx]]]
280295
#: The centers per fragment.
281296
#: Note that the set of centers is the complement of the edges.
282-
center_per_frag: Final[Sequence[OrderedSet[CenterIdx]]]
297+
center_per_frag: Final[SeqOverFrag[OrderedSet[CenterIdx]]]
283298
#: The edges per fragment.
284299
#: Note that the set of edges is the complement of the centers.
285-
edge_per_frag: Final[Sequence[OrderedSet[EdgeIdx]]]
300+
edge_per_frag: Final[SeqOverFrag[OrderedSet[EdgeIdx]]]
286301
#: The origins per frag
287-
origin_per_frag: Final[Sequence[OrderedSet[OriginIdx]]]
302+
origin_per_frag: Final[SeqOverFrag[OrderedSet[OriginIdx]]]
288303
#: Connectivity data of the molecule.
289304
conn_data: Final[ConnectivityData]
290305
n_BE: Final[int]
@@ -378,9 +393,10 @@ class FragmentedMolecule:
378393
mol: Final[Mole]
379394

380395
#: The atomic orbital indices per atom
381-
AO_per_atom: Final[Sequence[Sequence[AOIdx]]]
396+
AO_per_atom: Final[SeqOverAtom[Sequence[AOIdx]]]
397+
382398
#: The atomic orbital indices per fragment
383-
AO_per_frag: Final[Sequence[Sequence[AOIdx]]]
399+
AO_per_frag: Final[SeqOverFrag[Sequence[AOIdx]]]
384400

385401
@classmethod
386402
def from_frag_structure(

0 commit comments

Comments
 (0)