Skip to content

Commit

Permalink
rm IsEnumType, fix IsEnum __equals__
Browse files Browse the repository at this point in the history
  • Loading branch information
FBruzzesi committed Sep 4, 2023
1 parent b49b2c7 commit 5066c00
Show file tree
Hide file tree
Showing 4 changed files with 8 additions and 187 deletions.
6 changes: 0 additions & 6 deletions dirty_equals/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,11 @@
IsDataclass,
IsDataclassType,
IsEnum,
IsEnumType,
IsHash,
IsIP,
IsJson,
IsPartialDataclass,
IsPartialEnumType,
IsStrictDataclass,
IsStrictEnumType,
IsUrl,
IsUUID,
)
Expand Down Expand Up @@ -67,9 +64,6 @@
'IsStrictDict',
# enum
'IsEnum',
'IsEnumType',
'IsPartialEnumType',
'IsStrictEnumType',
# sequence
'Contains',
'HasLen',
Expand Down
136 changes: 4 additions & 132 deletions dirty_equals/_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -571,138 +571,10 @@ def __init__(self, enum_cls: type[Enum] = Enum):
enum_cls: Enum class to check against.
"""
self._enum_cls = enum_cls
self._enum_values = {i.value for i in enum_cls}

def equals(self, other: Any) -> bool:
return isinstance(other, self._enum_cls)


class IsEnumType(DirtyEquals[Enum]):
"""
Checks that a class definition is subclass of Enum.
Inherits from [`DirtyEquals`][dirty_equals.DirtyEquals] and it can be initialised with specific keyword arguments to
check exactness of enum members by comparing `other.__members__` with [`IsStrictDict`][dirty_equals.IsStrictDict].
Moreover it is possible to check for strictness and partialness of the enum, by setting the `strict` and
`partial` attributes using the `.settings(strict=..., partial=...)` method.
Remark that passing no kwargs to `IsEnumType` initialization means members are not checked, not that the class
is empty, namely `IsEnumType()` is the same as `IsEnumType`.
```py title="IsEnumType"
from enum import Enum, auto
from dirty_equals import IsEnumType
class FooEnum(Enum):
a = auto()
b = auto()
c = 'c'
assert FooEnum == IsEnumType
assert FooEnum == IsEnumType(a=1, b=2, c='c')
assert FooEnum != IsEnumType(b=2, a=1, c='c').settings(strict=True)
assert FooEnum != IsEnumType(a=1)
assert FooEnum == IsEnumType(a=1).settings(partial=True)
assert FooEnum == IsEnumType(c='c', b=2).settings(partial=True, strict=False)
assert FooEnum.a != IsEnumType
```
"""

def __init__(self, **members: Any):
"""
Args:
**members: key-value pairs to check against enum members.
"""
self.strict = False
self.partial = False
self._post_init()
super().__init__(**members)

def _post_init(self) -> None:
pass

def equals(self, other: Any) -> bool:
if issubclass(other, Enum):
if self._repr_kwargs:
return self._members_check(other)
else:
return True
if isinstance(other, Enum):
return isinstance(other, self._enum_cls)
else:
return False

def settings(
self,
*,
strict: bool | None = None,
partial: bool | None = None,
) -> IsEnumType:
"""Allows to customise the behaviour of `IsEnumType`, technically a new `IsEnumType` to allow chaining."""
new_cls = self.__class__(**self._repr_kwargs)
new_cls.__dict__ = self.__dict__.copy()

if strict is not None:
new_cls.strict = strict
if partial is not None:
new_cls.partial = partial

return new_cls

def _members_check(self, other: Any) -> bool:
"""
Checks exactness of fields using [`IsDict`][dirty_equals.IsDict] with given settings.
Remark that if this method is called, then `other` is a subclass of Enum, therefore we can iterate over it to
get its member names and values.
"""
members = {i.name: i.value for i in other}
return members == IsDict(self._repr_kwargs).settings(strict=self.strict, partial=self.partial)


class IsPartialEnumType(IsEnumType):
"""
Inherits from [`IsEnumType`][dirty_equals.IsEnumType] with `partial=True` by default.
```py title="IsPartialEnumType"
from enum import Enum, auto
from dirty_equals import IsPartialEnumType
class FooEnum(Enum):
a = auto()
b = auto()
c = 'c'
assert FooEnum == IsPartialEnumType
assert FooEnum == IsPartialEnumType(a=1, b=2)
assert FooEnum == IsPartialEnumType(c='c', b=2).settings(strict=False)
assert FooEnum != IsPartialEnumType(c='c', b=2).settings(strict=True)
assert FooEnum.a != IsPartialEnumType
```
"""

def _post_init(self) -> None:
self.partial = True


class IsStrictEnumType(IsEnumType):
"""
Inherits from [`IsEnumType`][dirty_equals.IsEnumType] with `strict=True` by default.
```py title="IsStrictEnumType"
from enum import Enum, auto
from dirty_equals import IsStrictEnumType
class FooEnum(Enum):
a = auto()
b = auto()
c = 'c'
assert FooEnum == IsStrictEnumType
assert FooEnum == IsStrictEnumType(a=1, b=2, c='c')
assert FooEnum == IsStrictEnumType(b=2, c='c').settings(partial=True)
assert FooEnum != IsStrictEnumType(b=2, c='c', a=1)
assert FooEnum.a != IsStrictEnumType
```
"""

def _post_init(self) -> None:
self.strict = True
return other in self._enum_values
6 changes: 0 additions & 6 deletions docs/types/other.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,3 @@
::: dirty_equals.IsStrictDataclass

::: dirty_equals.IsEnum

::: dirty_equals.IsEnumType

::: dirty_equals.IsPartialEnumType

::: dirty_equals.IsStrictEnumType
47 changes: 4 additions & 43 deletions tests/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,13 @@
IsDataclass,
IsDataclassType,
IsEnum,
IsEnumType,
IsHash,
IsInt,
IsIP,
IsJson,
IsPartialDataclass,
IsPartialEnumType,
IsStr,
IsStrictDataclass,
IsStrictEnumType,
IsUrl,
IsUUID,
)
Expand Down Expand Up @@ -380,9 +377,9 @@ def test_is_dataclass_false(other, dirty):
'other,dirty',
[
(FooEnum.a, IsEnum),
(FooEnum.a, IsEnum(FooEnum)),
(FooEnum.c, IsEnum),
(FooEnum.c, IsEnum(FooEnum)),
(FooEnum.b, IsEnum(FooEnum)),
(2, IsEnum(FooEnum)),
('c', IsEnum(FooEnum)),
],
)
def test_is_enum_true(other, dirty):
Expand All @@ -394,44 +391,8 @@ def test_is_enum_true(other, dirty):
[
(FooEnum, IsEnum),
(FooEnum, IsEnum(FooEnum)),
(FooEnum.a, IsEnumType),
(FooEnum.c, IsEnumType),
(4, IsEnum(FooEnum)),
],
)
def test_is_enum_false(other, dirty):
assert other != dirty


@pytest.mark.parametrize(
'other,dirty',
[
(FooEnum, IsEnumType),
(FooEnum, IsEnumType(a=1, b=IsInt, c='c')),
(FooEnum, IsEnumType(a=1).settings(partial=True)),
(FooEnum, IsEnumType(c=IsStr, b=2).settings(partial=True, strict=False)),
(FooEnum, IsPartialEnumType),
(FooEnum, IsPartialEnumType(a=1, b=2)),
(FooEnum, IsPartialEnumType(c='c', b=2).settings(strict=False)),
(FooEnum, IsStrictEnumType),
(FooEnum, IsStrictEnumType(a=1, b=2, c=IsStr)),
(FooEnum, IsStrictEnumType(b=IsInt, c='c').settings(partial=True)),
],
)
def test_is_enum_type_true(other, dirty):
assert other == dirty


@pytest.mark.parametrize(
'other,dirty',
[
(FooEnum.a, IsEnumType),
(FooEnum, IsEnumType(b=2, a=1, c='c').settings(strict=True)),
(FooEnum, IsEnumType(a=1)),
(FooEnum, IsPartialEnumType(c='c', b=2).settings(strict=True)),
(FooEnum.a, IsPartialEnumType),
(FooEnum, IsStrictEnumType(b=2, c='c', a=1)),
(FooEnum.a, IsStrictEnumType),
],
)
def test_is_enum_type_false(other, dirty):
assert other != dirty

0 comments on commit 5066c00

Please sign in to comment.