0
# Type-Checked Collections
1
2
Runtime type validation for persistent collections with optional invariant checking. These collections provide the same functionality as core collections but with automatic type checking and validation.
3
4
## Capabilities
5
6
### CheckedPMap - Type-Checked Persistent Map
7
8
Persistent map with runtime validation of key and value types. Raises CheckedKeyTypeError or CheckedValueTypeError when invalid types are used.
9
10
```python { .api }
11
class CheckedPMap(PMap):
12
"""
13
Type-checked persistent map with key and value type validation.
14
15
Class attributes:
16
- __key_type__: Required key type or tuple of allowed types
17
- __value_type__: Required value type or tuple of allowed types
18
"""
19
20
__key_type__: type
21
__value_type__: type
22
23
def __new__(cls, source: Mapping = {}, size: int = 0) -> 'CheckedPMap': ...
24
25
@classmethod
26
def create(cls, source_data: Mapping, _factory_fields=None) -> 'CheckedPMap':
27
"""Create instance with type validation."""
28
29
def serialize(self, format=None) -> dict:
30
"""Serialize to regular dict."""
31
```
32
33
### CheckedPVector - Type-Checked Persistent Vector
34
35
Persistent vector with runtime validation of element types.
36
37
```python { .api }
38
class CheckedPVector(PVector):
39
"""
40
Type-checked persistent vector with element type validation.
41
42
Class attributes:
43
- __type__: Required element type or tuple of allowed types
44
"""
45
46
__type__: type
47
48
def __new__(cls, initial: Iterable = ()) -> 'CheckedPVector': ...
49
50
@classmethod
51
def create(cls, source_data: Iterable, _factory_fields=None) -> 'CheckedPVector':
52
"""Create instance with type validation."""
53
54
def serialize(self, format=None) -> list:
55
"""Serialize to regular list."""
56
```
57
58
### CheckedPSet - Type-Checked Persistent Set
59
60
Persistent set with runtime validation of element types.
61
62
```python { .api }
63
class CheckedPSet(PSet):
64
"""
65
Type-checked persistent set with element type validation.
66
67
Class attributes:
68
- __type__: Required element type or tuple of allowed types
69
"""
70
71
__type__: type
72
73
def __new__(cls, initial: Iterable = ()) -> 'CheckedPSet': ...
74
75
@classmethod
76
def create(cls, source_data: Iterable, _factory_fields=None) -> 'CheckedPSet':
77
"""Create instance with type validation."""
78
79
def serialize(self, format=None) -> set:
80
"""Serialize to regular set."""
81
```
82
83
### CheckedType Base Class
84
85
Abstract base class for all type-checked collections providing common validation infrastructure.
86
87
```python { .api }
88
class CheckedType:
89
"""Abstract base class for type-checked collections."""
90
91
@classmethod
92
def create(cls, source_data, _factory_fields=None):
93
"""Factory method for creating instances with validation."""
94
95
def serialize(self, format=None):
96
"""Serialize to corresponding Python built-in type."""
97
```
98
99
## Type Specification Functions
100
101
### Optional Types
102
103
Allow a field or collection to accept specified types or None.
104
105
```python { .api }
106
def optional(*types) -> tuple:
107
"""
108
Create a type specification that allows specified types or None.
109
110
Parameters:
111
- *types: Types to allow (in addition to None)
112
113
Returns:
114
Tuple of types including None
115
116
Example:
117
optional(int, str) -> (int, str, type(None))
118
"""
119
```
120
121
## Exception Classes
122
123
Type checking exceptions raised when validation fails:
124
125
```python { .api }
126
class InvariantException(Exception):
127
"""
128
Raised when invariant validation fails.
129
130
Attributes:
131
- invariant_errors: Tuple of validation error messages
132
- missing_fields: Tuple of missing required field names
133
"""
134
135
invariant_errors: tuple
136
missing_fields: tuple
137
138
class CheckedTypeError(TypeError):
139
"""
140
Base exception for type validation errors in checked collections.
141
142
Attributes:
143
- source_class: Class that raised the error
144
- expected_types: Tuple of expected types
145
- actual_type: Actual type that was provided
146
- actual_value: The value that caused the error
147
"""
148
149
source_class: type
150
expected_types: tuple
151
actual_type: type
152
actual_value: object
153
154
class CheckedKeyTypeError(CheckedTypeError):
155
"""Raised when CheckedPMap receives invalid key type."""
156
157
class CheckedValueTypeError(CheckedTypeError):
158
"""Raised when CheckedPMap/CheckedPVector/CheckedPSet receives invalid value/element type."""
159
```
160
161
## Usage Examples
162
163
### Basic Type Checking
164
165
```python
166
from pyrsistent import CheckedPMap, CheckedPVector, CheckedPSet, optional
167
168
# Define a type-checked map for string keys and integer values
169
class StringIntMap(CheckedPMap):
170
__key_type__ = str
171
__value_type__ = int
172
173
# Create and use the map
174
sim = StringIntMap({'a': 1, 'b': 2})
175
sim2 = sim.set('c', 3) # OK
176
# sim.set(123, 4) # Raises CheckedKeyTypeError
177
# sim.set('d', 'invalid') # Raises CheckedValueTypeError
178
179
# Define a type-checked vector for integers
180
class IntVector(CheckedPVector):
181
__type__ = int
182
183
iv = IntVector([1, 2, 3])
184
iv2 = iv.append(4) # OK
185
# iv.append('invalid') # Raises CheckedValueTypeError
186
187
# Define a type-checked set with optional types
188
class MixedSet(CheckedPSet):
189
__type__ = optional(int, str) # Allows int, str, or None
190
191
ms = MixedSet([1, 'hello', None, 2]) # OK
192
# ms.add(3.14) # Raises CheckedValueTypeError
193
```
194
195
### Custom Invariants
196
197
```python
198
# Type-checked collections can include custom validation
199
class PositiveIntVector(CheckedPVector):
200
__type__ = int
201
202
def __new__(cls, initial=()):
203
# Custom validation in constructor
204
for item in initial:
205
if not isinstance(item, int) or item <= 0:
206
raise ValueError("All elements must be positive integers")
207
return super().__new__(cls, initial)
208
209
piv = PositiveIntVector([1, 2, 3]) # OK
210
# PositiveIntVector([1, -2, 3]) # Raises ValueError
211
```
212
213
### Serialization
214
215
```python
216
# Type-checked collections can be serialized to regular Python types
217
class PersonMap(CheckedPMap):
218
__key_type__ = str
219
__value_type__ = (str, int)
220
221
pm = PersonMap({'name': 'Alice', 'age': 30})
222
regular_dict = pm.serialize() # Returns {'name': 'Alice', 'age': 30}
223
print(type(regular_dict)) # <class 'dict'>
224
```
225
226
### Factory Methods
227
228
```python
229
# Use create() class method for explicit construction with validation
230
data = {'valid_key': 42}
231
validated_map = StringIntMap.create(data)
232
233
# Validation happens during creation
234
try:
235
invalid_data = {123: 'invalid'}
236
StringIntMap.create(invalid_data)
237
except CheckedKeyTypeError as e:
238
print(f"Key type error: {e}")
239
```
240
241
### Error Handling
242
243
```python
244
from pyrsistent import CheckedKeyTypeError, CheckedValueTypeError
245
246
class TypedData(CheckedPMap):
247
__key_type__ = str
248
__value_type__ = (int, float)
249
250
try:
251
td = TypedData()
252
td = td.set(42, 'invalid') # Wrong key type
253
except CheckedKeyTypeError as e:
254
print(f"Expected key types: {e.expected_types}")
255
print(f"Actual key type: {e.actual_type}")
256
print(f"Actual key value: {e.actual_value}")
257
258
try:
259
td = TypedData()
260
td = td.set('key', 'invalid') # Wrong value type
261
except CheckedValueTypeError as e:
262
print(f"Expected value types: {e.expected_types}")
263
print(f"Actual value type: {e.actual_type}")
264
print(f"Actual value: {e.actual_value}")
265
```