Skip to content

Commit

Permalink
rearrange docs, add IsOneOf type
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelcolvin committed Feb 25, 2022
1 parent 6995c83 commit 4ffc811
Show file tree
Hide file tree
Showing 13 changed files with 196 additions and 109 deletions.
8 changes: 5 additions & 3 deletions dirty_equals/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from ._base import AnyThing, IsInstance
from ._base import AnyThing, DirtyEquals, IsInstance, IsOneOf
from ._datetime import IsDatetime, IsNow
from ._dict import IsDict, IsIgnoreDict, IsPartialDict, IsStrictDict
from ._list_tuple import Contains, HasLen, IsList, IsListOrTuple, IsTuple
from ._numeric import (
IsApprox,
IsFloat,
Expand All @@ -18,12 +17,15 @@
IsPositiveInt,
)
from ._other import FunctionCheck, IsJson, IsUUID
from ._sequence import Contains, HasLen, IsList, IsListOrTuple, IsTuple
from ._strings import IsAnyStr, IsBytes, IsStr

__all__ = (
# base
'DirtyEquals',
'AnyThing',
'IsInstance',
'IsOneOf',
# datetime
'IsDatetime',
'IsNow',
Expand All @@ -32,7 +34,7 @@
'IsPartialDict',
'IsIgnoreDict',
'IsStrictDict',
# list or tuple
# sequence
'Contains',
'HasLen',
'IsList',
Expand Down
30 changes: 29 additions & 1 deletion dirty_equals/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
if TYPE_CHECKING:
from typing import TypeAlias

__all__ = 'DirtyEqualsMeta', 'DirtyEquals', 'IsInstance', 'AnyThing'
__all__ = 'DirtyEqualsMeta', 'DirtyEquals', 'IsInstance', 'AnyThing', 'IsOneOf'


class DirtyEqualsMeta(ABCMeta):
Expand Down Expand Up @@ -257,3 +257,31 @@ class AnyThing(DirtyEquals[Any]):

def equals(self, other: Any) -> bool:
return True


class IsOneOf(DirtyEquals[Any]):
"""
A type which checks that the value is equal to one of the given values.
Can be useful with boolean operators.
"""

def __init__(self, expected_value: Any, *more_expected_values: Any):
"""
Args:
expected_value: Expected value for equals to return true.
*more_expected_values: More expected values for equals to return true.
```py title="IsOneOf"
from dirty_equals import IsOneOf, Contains
assert 1 == IsOneOf(1, 2, 3)
assert 4 != IsOneOf(1, 2, 3)
assert [1, 2, 3] == Contains(1) | IsOneOf([])
assert [] == Contains(1) | IsOneOf([])
"""
self.expected_values: Tuple[Any, ...] = (expected_value,) + more_expected_values
super().__init__(*self.expected_values)

def equals(self, other: Any) -> bool:
return any(other == e for e in self.expected_values)
File renamed without changes.
38 changes: 38 additions & 0 deletions docs/types/custom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Custom Types

::: dirty_equals._base.DirtyEquals
rendering:
merge_init_into_class: false

## Custom Type Example

To demonstrate the use of custom types, we'll create a custom type that matches any even number.

We won't inherit from [`IsNumeric`][dirty_equals.IsNumeric] in this case to keep the example simple.

```py
title="IsEven"
from decimal import Decimal
from typing import Any, Union
from dirty_equals import IsOneOf
from dirty_equals import DirtyEquals

class IsEven(DirtyEquals[Union[int, float, Decimal]]):
def equals(self, other: Any) -> bool:
return other % 2 == 0

assert 2 == IsEven
assert 3 != IsEven
assert 'foobar' != IsEven
assert 3 == IsEven | IsOneOf(3)
```

There are a few advantages of inheriting from [`DirtyEquals`][dirty_equals.DirtyEquals] compared to just
implementing your own class with an `__eq__` method:

1. `TypeError` and `ValueError` in `equals` are caught and result in a not-equals result.
2. A useful `__repr__` is generated, and modified if the `==` operation returns `True`,
see [pytest compatibility](../usage.md#__repr__-and-pytest-compatibility)
3. [boolean logic](../usage.md#boolean-logic) works out of the box
4. [Uninitialised usage](../usage.md#initialised-vs-class-comparison)
(`IsEven` rather than `IsEven()`) works out of the box
102 changes: 2 additions & 100 deletions docs/types.md → docs/types/datetime.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,8 @@
## Numeric Types

::: dirty_equals.IsInt
rendering:
merge_init_into_class: false
separate_signature: false

::: dirty_equals.IsFloat
rendering:
merge_init_into_class: false
separate_signature: false

::: dirty_equals.IsPositive
rendering:
merge_init_into_class: false

::: dirty_equals.IsNegative
rendering:
merge_init_into_class: false

::: dirty_equals.IsNonNegative
rendering:
merge_init_into_class: false

::: dirty_equals.IsNonPositive
rendering:
merge_init_into_class: false

::: dirty_equals.IsPositiveInt
rendering:
merge_init_into_class: false

::: dirty_equals.IsNegativeInt
rendering:
merge_init_into_class: false

::: dirty_equals.IsPositiveFloat
rendering:
merge_init_into_class: false

::: dirty_equals.IsNegativeFloat
rendering:
merge_init_into_class: false

::: dirty_equals.IsApprox

::: dirty_equals.IsNumber
rendering:
merge_init_into_class: false

::: dirty_equals.IsNumeric

## Date and Time Types
# Date and Time Types

::: dirty_equals.IsDatetime

#### Timezones
### Timezones

Timezones are hard, anyone who claims otherwise is either a genius, a liar, or an idiot.

Expand Down Expand Up @@ -98,49 +46,3 @@ assert new_year_eve_nyc != IsDatetime(approx=new_year_naive, enforce_tz=False)
```

::: dirty_equals.IsNow

## Dictionary Types

::: dirty_equals.IsDict

::: dirty_equals.IsPartialDict

::: dirty_equals.IsIgnoreDict

::: dirty_equals.IsStrictDict

## List and Tuples Types

::: dirty_equals.IsListOrTuple

::: dirty_equals.IsList

::: dirty_equals.IsTuple

::: dirty_equals.HasLen

::: dirty_equals.Contains

## String Types

::: dirty_equals.IsAnyStr

::: dirty_equals.IsStr

::: dirty_equals.IsBytes

## Other Types

::: dirty_equals.FunctionCheck

::: dirty_equals.IsInstance

::: dirty_equals.IsJson

::: dirty_equals.IsUUID

::: dirty_equals.AnyThing

::: dirty_equals._base.DirtyEquals
rendering:
merge_init_into_class: false
9 changes: 9 additions & 0 deletions docs/types/dict.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Dictionary Types

::: dirty_equals.IsDict

::: dirty_equals.IsPartialDict

::: dirty_equals.IsIgnoreDict

::: dirty_equals.IsStrictDict
51 changes: 51 additions & 0 deletions docs/types/numeric.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Numeric Types

::: dirty_equals.IsInt
rendering:
merge_init_into_class: false
separate_signature: false

::: dirty_equals.IsFloat
rendering:
merge_init_into_class: false
separate_signature: false

::: dirty_equals.IsPositive
rendering:
merge_init_into_class: false

::: dirty_equals.IsNegative
rendering:
merge_init_into_class: false

::: dirty_equals.IsNonNegative
rendering:
merge_init_into_class: false

::: dirty_equals.IsNonPositive
rendering:
merge_init_into_class: false

::: dirty_equals.IsPositiveInt
rendering:
merge_init_into_class: false

::: dirty_equals.IsNegativeInt
rendering:
merge_init_into_class: false

::: dirty_equals.IsPositiveFloat
rendering:
merge_init_into_class: false

::: dirty_equals.IsNegativeFloat
rendering:
merge_init_into_class: false

::: dirty_equals.IsApprox

::: dirty_equals.IsNumber
rendering:
merge_init_into_class: false

::: dirty_equals.IsNumeric
13 changes: 13 additions & 0 deletions docs/types/other.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Other Types

::: dirty_equals.FunctionCheck

::: dirty_equals.IsInstance

::: dirty_equals.IsJson

::: dirty_equals.IsUUID

::: dirty_equals.AnyThing

::: dirty_equals.IsOneOf
11 changes: 11 additions & 0 deletions docs/types/sequence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Sequence Types

::: dirty_equals.IsListOrTuple

::: dirty_equals.IsList

::: dirty_equals.IsTuple

::: dirty_equals.HasLen

::: dirty_equals.Contains
7 changes: 7 additions & 0 deletions docs/types/string.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# String Types

::: dirty_equals.IsAnyStr

::: dirty_equals.IsStr

::: dirty_equals.IsBytes
7 changes: 6 additions & 1 deletion docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,19 @@ This saves users adding `()` in lots of places.

Example:

```py title="Initialised vs. Uninitialised"
```py
title="Initialised vs. Uninitialised"
from dirty_equals import IsInt

# these two cases are the same
assert 1 == IsInt
assert 1 == IsInt()
```

!!! Note
Types that require at least on argument when being initialised (like [`IsApprox`][dirty_equals.IsApprox])
cannot be used like this, comparisons will just return `False`.

## `__repr__` and pytest compatibility

dirty-equals types have reasonable `__repr__` methods, which describe types and generally are a close match
Expand Down
12 changes: 9 additions & 3 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,18 @@ edit_uri: ''
nav:
- Introduction: index.md
- Usage: usage.md
- Types: types.md
- Types:
- types/numeric.md
- types/datetime.md
- types/dict.md
- types/sequence.md
- types/string.md
- types/other.md
- types/custom.md

markdown_extensions:
- toc:
permalink: true
toc_depth: 3
- admonition
- pymdownx.details
- pymdownx.superfences
Expand Down Expand Up @@ -72,7 +78,7 @@ plugins:
show_root_heading: true
show_root_full_path: false
show_source: false
heading_level: 3
heading_level: 2
merge_init_into_class: true
show_signature_annotations: true
separate_signature: true
Expand Down
Loading

0 comments on commit 4ffc811

Please sign in to comment.