Skip to content

Commit

Permalink
Adding test coverage for the Python 3.12 way to defining generic clas…
Browse files Browse the repository at this point in the history
…ses (#24)
  • Loading branch information
jcal-15 authored Mar 22, 2024
1 parent 5554d2f commit 692602b
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 53 deletions.
60 changes: 60 additions & 0 deletions tests/_type_checking_classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from dataclasses import dataclass
from typing import Any, Dict, List, Optional, Union, TypeVar, Generic, Literal

import attr

# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# Classes used by the tests

class NormalClass:
def __init__(self, v: str) -> None:
self.value = v

def __eq__(self, other: object) -> bool:
return isinstance(other, NormalClass) and self.value == other.value


@dataclass(frozen=True)
class DataClass:
field: str


@attr.s(auto_attribs=True)
class AttrClass:
attrib: str

TTestType = TypeVar("TTestType")
TSelfRef = TypeVar("TSelfRef")

@dataclass
class ClassBase(Generic[TTestType, TSelfRef]):
normal: TTestType
optional: Optional[TTestType]
union: Union[str, NormalClass, DataClass, TTestType]
any: Any
self_ref: Optional[TSelfRef]

list_normal: List[TTestType]
list_optional: List[Optional[TTestType]]
list_union: List[Union[str, NormalClass, DataClass, TTestType]]
list_any: List[Any]
list_self_ref: List[TSelfRef]

dict_normal: Dict[str, TTestType]
dict_optional: Dict[str, Optional[TTestType]]
dict_union: Dict[str, Union[str, NormalClass, DataClass, TTestType]]
dict_any: Dict[str, Any]
dict_self_ref: Dict[str, TSelfRef]


ClassPrimitives = ClassBase[int, "ClassPrimitives"]
ClassDict = ClassBase[Dict[str,str], "ClassDict"]
ClassDictSimple = ClassBase[dict, "ClassDictSimple"]
ClassList = ClassBase[List[str], "ClassList"]
ClassDataClass = ClassBase[DataClass, "ClassDataClass"]
ClassNormalClass = ClassBase[NormalClass, "ClassNormalClass"]
ClassAttrClass = ClassBase[AttrClass, "ClassAttrClass"]
ClassListDataClass = ClassBase[List[DataClass], "ClassListDataClass"]
ClassDictDataClass = ClassBase[Dict[str, DataClass], "ClassDictDataClass"]
ClassLiteral = ClassBase[Literal["my-literal"], "ClassLiteral"]
ClassMultiLiteral = ClassBase[Literal[2, 3, 5, 7, 11], "ClassMultiLiteral"]
38 changes: 38 additions & 0 deletions tests/_type_checking_classes_py312.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from dataclasses import dataclass
from typing import Any, Optional, Literal


from _type_checking_classes import DataClass, NormalClass, AttrClass

@dataclass
class ClassBase[TTestType, TSelfRef]:
normal: TTestType
optional: Optional[TTestType]
union: str | NormalClass | DataClass | TTestType
any: Any
self_ref: Optional[TSelfRef]

list_normal: list[TTestType]
list_optional: list[Optional[TTestType]]
list_union: list[str | NormalClass | DataClass | TTestType]
list_any: list[Any]
list_self_ref: list[TSelfRef]

dict_normal: dict[str, TTestType]
dict_optional: dict[str, Optional[TTestType]]
dict_union: dict[str, str | NormalClass | DataClass | TTestType]
dict_any: dict[str, Any]
dict_self_ref: dict[str, TSelfRef]


ClassPrimitives = ClassBase[int, "ClassPrimitives"]
ClassDict = ClassBase[dict[str,str], "ClassDict"]
ClassDictSimple = ClassBase[dict, "ClassDictSimple"]
ClassList = ClassBase[list[str], "ClassList"]
ClassDataClass = ClassBase[DataClass, "ClassDataClass"]
ClassNormalClass = ClassBase[NormalClass, "ClassNormalClass"]
ClassAttrClass = ClassBase[AttrClass, "ClassAttrClass"]
ClassListDataClass = ClassBase[list[DataClass], "ClassListDataClass"]
ClassDictDataClass = ClassBase[dict[str, DataClass], "ClassDictDataClass"]
ClassLiteral = ClassBase[Literal["my-literal"], "ClassLiteral"]
ClassMultiLiteral = ClassBase[Literal[2, 3, 5, 7, 11], "ClassMultiLiteral"]
71 changes: 18 additions & 53 deletions tests/test_type_checking.py
Original file line number Diff line number Diff line change
@@ -1,69 +1,34 @@
import sys
import copy
import datetime
from contextlib import contextmanager
from dataclasses import dataclass
from typing import Any, Dict, List, Optional, Union, Type, Callable, TypeVar, Generic, Literal
from typing import Type, Callable

from from_dict import FromDictTypeError, from_dict

import attr
import pytest

# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# Classes used by the tests

class NormalClass:
def __init__(self, v: str) -> None:
self.value = v

def __eq__(self, other: object) -> bool:
return isinstance(other, NormalClass) and self.value == other.value


@dataclass(frozen=True)
class DataClass:
field: str


@attr.s(auto_attribs=True)
class AttrClass:
attrib: str

TTestType = TypeVar("TTestType")
TSelfRef = TypeVar("TSelfRef")
if sys.version_info[0:1] < (3, 12):
from _type_checking_classes import (
NormalClass, DataClass, AttrClass,
ClassPrimitives, ClassDict, ClassDictSimple,
ClassList, ClassDataClass, ClassNormalClass,
ClassAttrClass, ClassListDataClass, ClassDictDataClass,
ClassLiteral, ClassMultiLiteral
)
else:
from _type_checking_classes_py312 import (
NormalClass, DataClass, AttrClass,
ClassPrimitives, ClassDict, ClassDictSimple,
ClassList, ClassDataClass, ClassNormalClass,
ClassAttrClass, ClassListDataClass, ClassDictDataClass,
ClassLiteral, ClassMultiLiteral
)

@dataclass
class ClassBase(Generic[TTestType, TSelfRef]):
normal: TTestType
optional: Optional[TTestType]
union: Union[str, NormalClass, DataClass, TTestType]
any: Any
self_ref: Optional[TSelfRef]

list_normal: List[TTestType]
list_optional: List[Optional[TTestType]]
list_union: List[Union[str, NormalClass, DataClass, TTestType]]
list_any: List[Any]
list_self_ref: List[TSelfRef]

dict_normal: Dict[str, TTestType]
dict_optional: Dict[str, Optional[TTestType]]
dict_union: Dict[str, Union[str, NormalClass, DataClass, TTestType]]
dict_any: Dict[str, Any]
dict_self_ref: Dict[str, TSelfRef]


ClassPrimitives = ClassBase[int, "ClassPrimitives"]
ClassDict = ClassBase[Dict[str,str], "ClassDict"]
ClassDictSimple = ClassBase[dict, "ClassDictSimple"]
ClassList = ClassBase[List[str], "ClassList"]
ClassDataClass = ClassBase[DataClass, "ClassDataClass"]
ClassNormalClass = ClassBase[NormalClass, "ClassNormalClass"]
ClassAttrClass = ClassBase[AttrClass, "ClassAttrClass"]
ClassListDataClass = ClassBase[List[DataClass], "ClassListDataClass"]
ClassDictDataClass = ClassBase[Dict[str, DataClass], "ClassDictDataClass"]
ClassLiteral = ClassBase[Literal["my-literal"], "ClassLiteral"]
ClassMultiLiteral = ClassBase[Literal[2, 3, 5, 7, 11], "ClassMultiLiteral"]

# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
# helper functions
Expand Down

0 comments on commit 692602b

Please sign in to comment.