0
# dirty-equals
1
2
A Python library that (mis)uses the `__eq__` method to make Python code more declarative and easier to read and write. The library provides a comprehensive collection of comparison classes that enable flexible and expressive equality checks, particularly useful in unit tests where you need to validate data structures without exact value matching.
3
4
## Package Information
5
6
- **Package Name**: dirty-equals
7
- **Language**: Python
8
- **Installation**: `pip install dirty-equals`
9
- **Python Requirements**: 3.8+
10
11
## Core Imports
12
13
```python
14
from dirty_equals import (
15
# Base classes
16
DirtyEquals, AnyThing, IsOneOf,
17
18
# Boolean types
19
IsTrueLike, IsFalseLike,
20
21
# Numeric types
22
IsPositive, IsNegative, IsInt, IsFloat, IsApprox,
23
24
# String types
25
IsStr, IsBytes,
26
27
# DateTime types
28
IsDatetime, IsNow, IsDate, IsToday,
29
30
# Dict types
31
IsDict, IsPartialDict, IsStrictDict,
32
33
# Sequence types
34
IsList, IsTuple, Contains, HasLen,
35
36
# Inspection types
37
IsInstance, HasAttributes, HasName, HasRepr,
38
39
# Other specialized types
40
IsJson, IsUUID, IsUrl, IsHash, IsIP, IsDataclass, IsEnum,
41
FunctionCheck
42
)
43
```
44
45
All types can be imported from the main package:
46
47
```python
48
from dirty_equals import IsPositive, IsStr, IsJson
49
```
50
51
Version information:
52
53
```python
54
from dirty_equals import __version__
55
```
56
57
## Basic Usage
58
59
```python
60
from datetime import datetime
61
from dirty_equals import IsPositive, IsStr, IsJson, IsNow, IsDict, IsPartialDict, IsInt, IsNegative
62
63
# Simple comparisons
64
assert 42 == IsPositive
65
assert "hello world" == IsStr(regex=r"hello \w+")
66
assert '{"key": "value"}' == IsJson({"key": "value"})
67
68
# Complex data structure validation
69
user_data = {
70
'id': 123,
71
'username': 'john_doe',
72
'email': 'john@example.com',
73
'profile': '{"theme": "dark", "notifications": true}',
74
'created_at': datetime.now(),
75
'is_active': True
76
}
77
78
# Validate entire structure declaratively
79
assert user_data == {
80
'id': IsPositive,
81
'username': IsStr(min_length=3),
82
'email': IsStr(regex=r'.+@.+\..+'),
83
'profile': IsJson({'theme': IsStr, 'notifications': bool}),
84
'created_at': IsNow(delta=60), # within last minute
85
'is_active': True
86
}
87
88
# Partial dictionary matching
89
assert user_data == IsPartialDict({
90
'id': IsPositive,
91
'username': IsStr
92
}) # Only checks specified keys
93
94
# Boolean logic combinations
95
assert 42 == (IsInt & IsPositive) # AND
96
assert "test" == (IsStr | IsInt) # OR
97
assert 42 == ~IsNegative # NOT
98
```
99
100
## Architecture
101
102
The dirty-equals library is built around a core `DirtyEquals` base class that leverages Python's `__eq__` method to provide custom equality semantics. This design enables the library's declarative testing approach.
103
104
### Core Design Principles
105
106
- **`DirtyEquals` Base Class**: All comparison types inherit from this abstract base class, which implements the `__eq__` method and provides operator overloading support
107
- **Abstract `equals()` Method**: Each subclass implements its own comparison logic through the `equals()` method
108
- **Operator Overloading**: Support for boolean logic operators (`&`, `|`, `~`) to combine and negate comparisons
109
- **Value Retention**: The `value` property provides access to the last successfully compared value
110
- **Type Safety**: Each comparison class is designed for specific data types and use cases
111
112
### Key Components
113
114
```python { .api }
115
class DirtyEquals:
116
"""Base class for all dirty-equals comparison types."""
117
118
def __init__(self, *repr_args: Any, **repr_kwargs: Any): ...
119
def equals(self, other: Any) -> bool: ... # Abstract method
120
121
@property
122
def value(self) -> Any: ... # Last successfully compared value
123
124
def __eq__(self, other: Any) -> bool: ...
125
def __ne__(self, other: Any) -> bool: ...
126
def __or__(self, other: 'DirtyEquals') -> 'DirtyOr': ... # |
127
def __and__(self, other: 'DirtyEquals') -> 'DirtyAnd': ... # &
128
def __invert__(self) -> 'DirtyNot': ... # ~
129
```
130
131
This architecture allows for:
132
- **Composable Comparisons**: Combine multiple comparison types with boolean operators
133
- **Flexible Validation**: Each type can implement sophisticated comparison logic
134
- **Readable Tests**: Test assertions read like natural language descriptions of expected data
135
136
## Capabilities
137
138
### Base Types
139
140
Core foundation classes that provide the building blocks for all other comparison types, including the abstract base class, universal matchers, and choice validators.
141
142
```python { .api }
143
class DirtyEquals: ... # Abstract base class
144
class AnyThing: ... # Matches any value
145
class IsOneOf: ... # Matches one of several values
146
```
147
148
[Base Types](./base-types.md)
149
150
### Boolean Types
151
152
Comparison classes for validating truthiness and falsiness with configurable behavior for different data types including special string handling.
153
154
```python { .api }
155
class IsTrueLike: ... # Checks truthiness
156
class IsFalseLike: ... # Checks falsiness with string support
157
```
158
159
[Boolean Types](./boolean-types.md)
160
161
### Numeric Types
162
163
Comprehensive numeric comparison types supporting integers, floats, decimals, and special float values with range checking, approximation, and sign validation.
164
165
```python { .api }
166
class IsNumeric: ... # Base numeric comparison
167
class IsNumber: ... # Number type base
168
class IsApprox: ... # Approximate equality
169
class IsPositive: ... # Value > 0
170
class IsNegative: ... # Value < 0
171
class IsInt: ... # Integer type checking
172
class IsFloat: ... # Float type checking
173
# ... and many more specialized numeric types
174
```
175
176
[Numeric Types](./numeric-types.md)
177
178
### String and Bytes Types
179
180
String and byte sequence validation with support for length constraints, case sensitivity, and regular expression matching.
181
182
```python { .api }
183
class IsAnyStr: ... # Base string/bytes comparison
184
class IsStr: ... # String comparison with constraints
185
class IsBytes: ... # Bytes comparison with constraints
186
```
187
188
[String Types](./string-types.md)
189
190
### DateTime Types
191
192
Date and time comparison classes with support for approximate matching, range validation, timezone handling, and format parsing.
193
194
```python { .api }
195
class IsDatetime: ... # Datetime comparison with conditions
196
class IsNow: ... # Close to current time
197
class IsDate: ... # Date comparison
198
class IsToday: ... # Current date matching
199
```
200
201
[DateTime Types](./datetime-types.md)
202
203
### Dictionary Types
204
205
Dictionary comparison with flexible matching strategies including partial matching, strict ordering, and key filtering.
206
207
```python { .api }
208
class IsDict: ... # Configurable dictionary comparison
209
class IsPartialDict: ... # Subset matching
210
class IsIgnoreDict: ... # Ignoring None values
211
class IsStrictDict: ... # Order-sensitive matching
212
```
213
214
[Dictionary Types](./dict-types.md)
215
216
### Sequence Types
217
218
List, tuple, and general sequence validation with support for partial matching, order constraints, containment checking, and length validation.
219
220
```python { .api }
221
class IsListOrTuple: ... # List/tuple with constraints
222
class IsList: ... # List-specific comparison
223
class IsTuple: ... # Tuple-specific comparison
224
class Contains: ... # Containment checking
225
class HasLen: ... # Length validation
226
```
227
228
[Sequence Types](./sequence-types.md)
229
230
### Inspection Types
231
232
Object introspection and type validation classes for checking instances, attributes, names, and string representations.
233
234
```python { .api }
235
class IsInstance: ... # Type instance checking
236
class HasAttributes: ... # Attribute presence checking
237
class HasName: ... # Object name validation
238
class HasRepr: ... # String representation checking
239
```
240
241
[Inspection Types](./inspection-types.md)
242
243
### Other Specialized Types
244
245
Specialized comparison types for common data formats including JSON, UUIDs, URLs, hashes, IP addresses, dataclasses, enums, and custom function-based validation.
246
247
```python { .api }
248
class IsJson: ... # JSON parsing and validation
249
class IsUUID: ... # UUID validation
250
class IsUrl: ... # URL validation (requires Pydantic)
251
class IsHash: ... # Hash string validation
252
class IsIP: ... # IP address validation
253
class IsDataclass: ... # Dataclass validation
254
class IsEnum: ... # Enum validation
255
class FunctionCheck: ... # Custom function validation
256
```
257
258
[Other Types](./other-types.md)