statica 1.2.0__tar.gz → 1.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: statica
3
- Version: 1.2.0
3
+ Version: 1.4.0
4
4
  Summary: A minimalistic data validation library
5
5
  Author-email: Marcel Kröker <kroeker.marcel@gmail.com>
6
6
  License: MIT License
@@ -31,10 +31,11 @@ Classifier: Operating System :: OS Independent
31
31
  Classifier: Intended Audience :: Developers
32
32
  Classifier: Programming Language :: Python
33
33
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
34
- Requires-Python: <3.14,>=3.10
34
+ Requires-Python: <3.14,>=3.11
35
35
  Description-Content-Type: text/markdown
36
36
 
37
- # Statica
37
+ Statica
38
+ ========================================================================================
38
39
 
39
40
  ![Tests](https://github.com/mkrd/statica/actions/workflows/test.yml/badge.svg)
40
41
  ![Coverage](https://github.com/mkrd/statica/blob/main/assets/coverage.svg?raw=true)
@@ -42,28 +43,36 @@ Description-Content-Type: text/markdown
42
43
 
43
44
  Statica is a Python library for defining and validating structured data with type annotations and constraints. It provides an easy-to-use framework for creating type-safe models with comprehensive validation for both types and constraints.
44
45
 
45
- ## Why Statica?
46
46
 
47
- Statica was created to address the need for a lightweight, flexible, and dependency-free alternative to libraries like pydantic.
47
+ Why Statica?
48
+ ----------------------------------------------------------------------------------------
49
+
50
+ Statica was created to address the need for a lightweight, flexible, and dependency-free alternative to Pydantic.
48
51
  While pydantic is a powerful tool for data validation and parsing, Statica offers some distinct advantages in specific situations:
49
52
 
50
- 1. **Lightweight**: Statica does not rely on any third-party dependencies, making it ideal for projects where minimizing external dependencies is a priority.
53
+ 1. **Lightweight**: Statica has zero dependencies, making it ideal for projects where minimizing external dependencies is a priority.
51
54
  2. **Performance**: For use cases where performance is critical. Pydantic needs `3x` more memory than Statica for the same models.
52
- 3. **Ease of Use**: With its simple, Pythonic design, Statica is intuitive for developers already familiar with Python's `dataclasses` and type hinting. It avoids much of the magic that pydantic employs.
53
- 4. **Customizable Validation**: Statica allows fine-grained control over type and constraint validation through customizable field descriptors (`Field`) and error classes.
55
+ 3. **Ease of Use**: With its simple, Pythonic design, Statica is intuitive for developers already familiar with Python's `dataclasses` and type hinting. It avoids much of the magic and complexity of Pydantic.
56
+ 4. **Customizable**: Statica allows fine-grained control over type and constraint validation through customizable fields and error classes.
57
+
54
58
 
55
- ## Features
59
+ Features
60
+ ----------------------------------------------------------------------------------------
56
61
 
57
62
  - **Type Validation**: Automatically validates types for attributes based on type hints.
58
63
  - **Constraint Validation**: Define constraints like minimum/maximum length, value ranges, and more.
64
+ - **Default Field Values**: Set default values for fields that are used when not explicitly provided.
59
65
  - **Customizable Error Handling**: Use custom exception classes for type and constraint errors.
60
66
  - **Flexible Field Descriptors**: Add constraints, casting, and other behaviors to your fields.
61
67
  - **Optional Fields**: Support for optional fields with default values.
62
68
  - **Automatic Initialization**: Automatically generate constructors (`__init__`) for your models.
63
69
  - **String Manipulation**: Strip whitespace from string fields if needed.
64
70
  - **Casting**: Automatically cast values to the desired type.
71
+ - **Field Aliasing**: Support for field aliases for parsing and serialization.
65
72
 
66
- ## Installation
73
+
74
+ Installation
75
+ ----------------------------------------------------------------------------------------
67
76
 
68
77
  You can install Statica via pip:
69
78
 
@@ -71,7 +80,9 @@ You can install Statica via pip:
71
80
  pip install statica
72
81
  ```
73
82
 
74
- ## Getting Started
83
+
84
+ Getting Started
85
+ ----------------------------------------------------------------------------------------
75
86
 
76
87
  ### Basic Usage
77
88
 
@@ -142,13 +153,92 @@ payload = OptionalPayload()
142
153
  print(payload.name) # Output: None
143
154
  ```
144
155
 
156
+ ### Default Field Values
157
+
158
+ You can specify default values for fields in two ways:
159
+
160
+ #### Using Field() with default parameter
161
+
162
+ ```python
163
+ class User(Statica):
164
+ name: str
165
+ age: int = Field(default=25)
166
+ active: bool = Field(default=True)
167
+
168
+ # Using direct initialization
169
+ user = User(name="John")
170
+ print(user.name) # Output: "John"
171
+ print(user.age) # Output: 25
172
+ print(user.active) # Output: True
173
+
174
+ # Using from_map
175
+ user = User.from_map({"name": "Jane"})
176
+ print(user.age) # Output: 25 (default used)
177
+
178
+ # Explicit values override defaults
179
+ user = User(name="Bob", age=30, active=False)
180
+ print(user.age) # Output: 30
181
+ ```
182
+
183
+ #### Direct assignment (without Field)
184
+
185
+ You can also assign default values directly to fields without using `Field()`:
186
+
187
+ ```python
188
+ class Config(Statica):
189
+ name: str
190
+ timeout: float = 30.0 # Direct assignment
191
+ retries: int = 3 # Direct assignment
192
+ debug: bool = False # Direct assignment
193
+
194
+ config = Config(name="server")
195
+ print(config.timeout) # Output: 30.0
196
+ print(config.retries) # Output: 3
197
+ print(config.debug) # Output: False
198
+
199
+ # Works with from_map too
200
+ config = Config.from_map({"name": "api-server"})
201
+ print(config.timeout) # Output: 30.0 (default used)
202
+ ```
203
+
204
+ Both approaches work identically and can be mixed within the same class. Use `Field(default=...)` when you need additional constraints or options, and direct assignment for simple defaults.
205
+
206
+ #### Validation and Safety
207
+
208
+ Default values are validated against any constraints you've defined:
209
+
210
+ ```python
211
+ class Config(Statica):
212
+ timeout: float = Field(default=30.0, min_value=1.0, max_value=120.0)
213
+ retries: int = Field(default=3, min_value=1)
214
+
215
+ config = Config() # Uses defaults: timeout=30.0, retries=3
216
+ ```
217
+
218
+ For mutable default values (like lists, dicts, sets), Statica automatically creates copies to prevent shared state issues:
219
+
220
+ ```python
221
+ class UserProfile(Statica):
222
+ name: str
223
+ tags: list[str] = Field(default=[]) # or tags: list[str] = []
224
+
225
+ user1 = UserProfile(name="Alice")
226
+ user2 = UserProfile(name="Bob")
227
+
228
+ user1.tags.append("admin")
229
+ print(user1.tags) # Output: ["admin"]
230
+ print(user2.tags) # Output: [] (not affected)
231
+ ```
232
+
145
233
  ### Field Constraints
146
234
 
147
- You can specify constraints on fields:
235
+ You can specify constraints and options on fields:
148
236
 
237
+ - **Default Values**: `default` (using `Field()`) or direct assignment
149
238
  - **String Constraints**: `min_length`, `max_length`, `strip_whitespace`
150
239
  - **Numeric Constraints**: `min_value`, `max_value`
151
240
  - **Casting**: `cast_to`
241
+ - **Aliasing**: `alias`
152
242
 
153
243
  ```python
154
244
  class StringTest(Statica):
@@ -156,6 +246,15 @@ class StringTest(Statica):
156
246
 
157
247
  class IntTest(Statica):
158
248
  num: int = Field(min_value=1, max_value=10, cast_to=int)
249
+
250
+ class DefaultTest(Statica):
251
+ # Using Field() for defaults with constraints
252
+ status: str = Field(default="active")
253
+ priority: int = Field(default=1, min_value=1, max_value=5)
254
+
255
+ # Direct assignment for simple defaults
256
+ timeout: float = 30.0
257
+ retries: int = 3
159
258
  ```
160
259
 
161
260
  ### Custom Error Classes
@@ -177,20 +276,57 @@ except CustomError as e:
177
276
  print(e) # Output: "num: must be at least 1"
178
277
  ```
179
278
 
180
- ## Advanced Usage
279
+ Or, define a BaseClass which configures the error classes globally:
280
+
281
+ ```python
282
+ from statica.core import Statica, ConstraintValidationError, TypeValidationError
283
+
284
+ class BaseClass(Statica):
285
+ constraint_error_class = ConstraintValidationError
286
+ type_error_class = TypeValidationError
287
+
288
+ class CustomPayload(BaseClass):
289
+ num: int = Field(min_value=1, max_value=10)
290
+
291
+ try:
292
+ payload = CustomPayload(num=0)
293
+ except ConstraintValidationError as e:
294
+ print(e) # Output: "num: must be at least 1"
295
+ ```
296
+
297
+
298
+ Aliasing
299
+ ----------------------------------------------------------------------------------------
181
300
 
182
- ### Short Syntax for Fields
301
+ Statica supports field aliasing, allowing you to map different field names for parsing and serialization.
302
+ This is particularly useful when working with external APIs that use different naming conventions.
183
303
 
184
- You can use simple type annotations without explicitly defining `Field` descriptors:
304
+ Use the `alias` parameter to define an alternative name for both parsing and serialization:
185
305
 
186
306
  ```python
187
- class ShortSyntax(Statica):
188
- name: str
307
+ class User(Statica):
308
+ full_name: str = Field(alias="fullName")
309
+ age: int = Field(alias="userAge", default=25)
310
+
311
+ # Parse data with aliases
312
+ data = {"fullName": "John Doe"} # userAge not provided, uses default
313
+ user = User.from_map(data)
314
+ print(user.full_name) # Output: "John Doe"
315
+ print(user.age) # Output: 25
316
+
317
+ # Serialize back with aliases (uses the alias for serialization by default)
318
+ result = user.to_dict()
319
+ print(result) # Output: {"fullName": "John Doe", "userAge": 25}
320
+
321
+ # Serialize without aliases
322
+ result_no_alias = user.to_dict(with_aliases=False)
323
+ print(result_no_alias) # Output: {"full_name": "John Doe", "age": 25}
189
324
 
190
- short = ShortSyntax(name="Test")
191
- print(short.name) # Output: "Test"
192
325
  ```
193
326
 
327
+ Advanced Usage
328
+ ----------------------------------------------------------------------------------------
329
+
194
330
  ### Custom Initialization
195
331
 
196
332
  Statica automatically generates an `__init__` method based on type annotations, ensuring that all required fields are provided during initialization.
@@ -207,7 +343,15 @@ instance = CastingExample(num="42")
207
343
  print(instance.num) # Output: 42
208
344
  ```
209
345
 
210
- ## Contributing
346
+
347
+ Design Decisions
348
+ ----------------------------------------------------------------------------------------
349
+
350
+ - [Inheritance over Decorators](docs/decision-inheritance-over-decorators.md)
351
+
352
+
353
+ Contributing
354
+ ----------------------------------------------------------------------------------------
211
355
 
212
356
  We welcome contributions to Statica! To contribute:
213
357
 
@@ -216,11 +360,14 @@ We welcome contributions to Statica! To contribute:
216
360
  3. Write tests for your changes.
217
361
  4. Submit a pull request.
218
362
 
219
- ## License
363
+
364
+ License
365
+ ----------------------------------------------------------------------------------------
220
366
 
221
367
  Statica is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
222
368
 
223
- ## Acknowledgments
224
369
 
225
- Statica was built to simplify data validation and provide a robust and simple framework for type-safe models in Python, inspired by `pydantic` and `dataclasses`.
370
+ Acknowledgments
371
+ ----------------------------------------------------------------------------------------
226
372
 
373
+ Statica was built to simplify data validation and provide a robust and simple framework for type-safe models in Python, inspired by `pydantic` and `dataclasses`.
@@ -0,0 +1,337 @@
1
+ Statica
2
+ ========================================================================================
3
+
4
+ ![Tests](https://github.com/mkrd/statica/actions/workflows/test.yml/badge.svg)
5
+ ![Coverage](https://github.com/mkrd/statica/blob/main/assets/coverage.svg?raw=true)
6
+
7
+
8
+ Statica is a Python library for defining and validating structured data with type annotations and constraints. It provides an easy-to-use framework for creating type-safe models with comprehensive validation for both types and constraints.
9
+
10
+
11
+ Why Statica?
12
+ ----------------------------------------------------------------------------------------
13
+
14
+ Statica was created to address the need for a lightweight, flexible, and dependency-free alternative to Pydantic.
15
+ While pydantic is a powerful tool for data validation and parsing, Statica offers some distinct advantages in specific situations:
16
+
17
+ 1. **Lightweight**: Statica has zero dependencies, making it ideal for projects where minimizing external dependencies is a priority.
18
+ 2. **Performance**: For use cases where performance is critical. Pydantic needs `3x` more memory than Statica for the same models.
19
+ 3. **Ease of Use**: With its simple, Pythonic design, Statica is intuitive for developers already familiar with Python's `dataclasses` and type hinting. It avoids much of the magic and complexity of Pydantic.
20
+ 4. **Customizable**: Statica allows fine-grained control over type and constraint validation through customizable fields and error classes.
21
+
22
+
23
+ Features
24
+ ----------------------------------------------------------------------------------------
25
+
26
+ - **Type Validation**: Automatically validates types for attributes based on type hints.
27
+ - **Constraint Validation**: Define constraints like minimum/maximum length, value ranges, and more.
28
+ - **Default Field Values**: Set default values for fields that are used when not explicitly provided.
29
+ - **Customizable Error Handling**: Use custom exception classes for type and constraint errors.
30
+ - **Flexible Field Descriptors**: Add constraints, casting, and other behaviors to your fields.
31
+ - **Optional Fields**: Support for optional fields with default values.
32
+ - **Automatic Initialization**: Automatically generate constructors (`__init__`) for your models.
33
+ - **String Manipulation**: Strip whitespace from string fields if needed.
34
+ - **Casting**: Automatically cast values to the desired type.
35
+ - **Field Aliasing**: Support for field aliases for parsing and serialization.
36
+
37
+
38
+ Installation
39
+ ----------------------------------------------------------------------------------------
40
+
41
+ You can install Statica via pip:
42
+
43
+ ```bash
44
+ pip install statica
45
+ ```
46
+
47
+
48
+ Getting Started
49
+ ----------------------------------------------------------------------------------------
50
+
51
+ ### Basic Usage
52
+
53
+ Define a model with type annotations and constraints:
54
+
55
+ ```python
56
+ from statica.core import Statica, Field
57
+
58
+ class Payload(Statica):
59
+ name: str = Field(min_length=3, max_length=50, strip_whitespace=True)
60
+ description: str | None = Field(max_length=200)
61
+ num: int | float
62
+ float_num: float | None
63
+ ```
64
+
65
+ Instantiate the model using a dictionary:
66
+
67
+ ```python
68
+ data = {
69
+ "name": "Test Payload",
70
+ "description": "A short description.",
71
+ "num": 42,
72
+ "float_num": 3.14,
73
+ }
74
+
75
+ payload = Payload.from_map(data)
76
+ print(payload.name) # Output: "Test Payload"
77
+ ```
78
+
79
+ Or instantiate directly:
80
+
81
+ ```python
82
+ payload = Payload(
83
+ name="Test",
84
+ description="This is a test description.",
85
+ num=42,
86
+ float_num=3.14,
87
+ )
88
+ ```
89
+
90
+ ### Validation
91
+
92
+ Statica automatically validates attributes based on type annotations and constraints:
93
+
94
+ ```python
95
+ from statica.core import ConstraintValidationError, TypeValidationError
96
+
97
+ try:
98
+ payload = Payload(name="Te", description="Valid", num=42)
99
+ except ConstraintValidationError as e:
100
+ print(e) # Output: "name: length must be at least 3"
101
+
102
+ try:
103
+ payload = Payload(name="Test", description="Valid", num="Invalid")
104
+ except TypeValidationError as e:
105
+ print(e) # Output: "num: expected type 'int | float', got 'str'"
106
+ ```
107
+
108
+ ### Optional Fields
109
+
110
+ Fields annotated with `| None` are optional and default to `None`:
111
+
112
+ ```python
113
+ class OptionalPayload(Statica):
114
+ name: str | None
115
+
116
+ payload = OptionalPayload()
117
+ print(payload.name) # Output: None
118
+ ```
119
+
120
+ ### Default Field Values
121
+
122
+ You can specify default values for fields in two ways:
123
+
124
+ #### Using Field() with default parameter
125
+
126
+ ```python
127
+ class User(Statica):
128
+ name: str
129
+ age: int = Field(default=25)
130
+ active: bool = Field(default=True)
131
+
132
+ # Using direct initialization
133
+ user = User(name="John")
134
+ print(user.name) # Output: "John"
135
+ print(user.age) # Output: 25
136
+ print(user.active) # Output: True
137
+
138
+ # Using from_map
139
+ user = User.from_map({"name": "Jane"})
140
+ print(user.age) # Output: 25 (default used)
141
+
142
+ # Explicit values override defaults
143
+ user = User(name="Bob", age=30, active=False)
144
+ print(user.age) # Output: 30
145
+ ```
146
+
147
+ #### Direct assignment (without Field)
148
+
149
+ You can also assign default values directly to fields without using `Field()`:
150
+
151
+ ```python
152
+ class Config(Statica):
153
+ name: str
154
+ timeout: float = 30.0 # Direct assignment
155
+ retries: int = 3 # Direct assignment
156
+ debug: bool = False # Direct assignment
157
+
158
+ config = Config(name="server")
159
+ print(config.timeout) # Output: 30.0
160
+ print(config.retries) # Output: 3
161
+ print(config.debug) # Output: False
162
+
163
+ # Works with from_map too
164
+ config = Config.from_map({"name": "api-server"})
165
+ print(config.timeout) # Output: 30.0 (default used)
166
+ ```
167
+
168
+ Both approaches work identically and can be mixed within the same class. Use `Field(default=...)` when you need additional constraints or options, and direct assignment for simple defaults.
169
+
170
+ #### Validation and Safety
171
+
172
+ Default values are validated against any constraints you've defined:
173
+
174
+ ```python
175
+ class Config(Statica):
176
+ timeout: float = Field(default=30.0, min_value=1.0, max_value=120.0)
177
+ retries: int = Field(default=3, min_value=1)
178
+
179
+ config = Config() # Uses defaults: timeout=30.0, retries=3
180
+ ```
181
+
182
+ For mutable default values (like lists, dicts, sets), Statica automatically creates copies to prevent shared state issues:
183
+
184
+ ```python
185
+ class UserProfile(Statica):
186
+ name: str
187
+ tags: list[str] = Field(default=[]) # or tags: list[str] = []
188
+
189
+ user1 = UserProfile(name="Alice")
190
+ user2 = UserProfile(name="Bob")
191
+
192
+ user1.tags.append("admin")
193
+ print(user1.tags) # Output: ["admin"]
194
+ print(user2.tags) # Output: [] (not affected)
195
+ ```
196
+
197
+ ### Field Constraints
198
+
199
+ You can specify constraints and options on fields:
200
+
201
+ - **Default Values**: `default` (using `Field()`) or direct assignment
202
+ - **String Constraints**: `min_length`, `max_length`, `strip_whitespace`
203
+ - **Numeric Constraints**: `min_value`, `max_value`
204
+ - **Casting**: `cast_to`
205
+ - **Aliasing**: `alias`
206
+
207
+ ```python
208
+ class StringTest(Statica):
209
+ name: str = Field(min_length=3, max_length=5, strip_whitespace=True)
210
+
211
+ class IntTest(Statica):
212
+ num: int = Field(min_value=1, max_value=10, cast_to=int)
213
+
214
+ class DefaultTest(Statica):
215
+ # Using Field() for defaults with constraints
216
+ status: str = Field(default="active")
217
+ priority: int = Field(default=1, min_value=1, max_value=5)
218
+
219
+ # Direct assignment for simple defaults
220
+ timeout: float = 30.0
221
+ retries: int = 3
222
+ ```
223
+
224
+ ### Custom Error Classes
225
+
226
+ You can define custom error classes for type and constraint validation:
227
+
228
+ ```python
229
+ class CustomError(Exception):
230
+ pass
231
+
232
+ class CustomPayload(Statica):
233
+ constraint_error_class = CustomError
234
+
235
+ num: int = Field(min_value=1, max_value=10)
236
+
237
+ try:
238
+ payload = CustomPayload(num=0)
239
+ except CustomError as e:
240
+ print(e) # Output: "num: must be at least 1"
241
+ ```
242
+
243
+ Or, define a BaseClass which configures the error classes globally:
244
+
245
+ ```python
246
+ from statica.core import Statica, ConstraintValidationError, TypeValidationError
247
+
248
+ class BaseClass(Statica):
249
+ constraint_error_class = ConstraintValidationError
250
+ type_error_class = TypeValidationError
251
+
252
+ class CustomPayload(BaseClass):
253
+ num: int = Field(min_value=1, max_value=10)
254
+
255
+ try:
256
+ payload = CustomPayload(num=0)
257
+ except ConstraintValidationError as e:
258
+ print(e) # Output: "num: must be at least 1"
259
+ ```
260
+
261
+
262
+ Aliasing
263
+ ----------------------------------------------------------------------------------------
264
+
265
+ Statica supports field aliasing, allowing you to map different field names for parsing and serialization.
266
+ This is particularly useful when working with external APIs that use different naming conventions.
267
+
268
+ Use the `alias` parameter to define an alternative name for both parsing and serialization:
269
+
270
+ ```python
271
+ class User(Statica):
272
+ full_name: str = Field(alias="fullName")
273
+ age: int = Field(alias="userAge", default=25)
274
+
275
+ # Parse data with aliases
276
+ data = {"fullName": "John Doe"} # userAge not provided, uses default
277
+ user = User.from_map(data)
278
+ print(user.full_name) # Output: "John Doe"
279
+ print(user.age) # Output: 25
280
+
281
+ # Serialize back with aliases (uses the alias for serialization by default)
282
+ result = user.to_dict()
283
+ print(result) # Output: {"fullName": "John Doe", "userAge": 25}
284
+
285
+ # Serialize without aliases
286
+ result_no_alias = user.to_dict(with_aliases=False)
287
+ print(result_no_alias) # Output: {"full_name": "John Doe", "age": 25}
288
+
289
+ ```
290
+
291
+ Advanced Usage
292
+ ----------------------------------------------------------------------------------------
293
+
294
+ ### Custom Initialization
295
+
296
+ Statica automatically generates an `__init__` method based on type annotations, ensuring that all required fields are provided during initialization.
297
+
298
+ ### Casting
299
+
300
+ You can automatically cast input values to the desired type:
301
+
302
+ ```python
303
+ class CastingExample(Statica):
304
+ num: int = Field(cast_to=int)
305
+
306
+ instance = CastingExample(num="42")
307
+ print(instance.num) # Output: 42
308
+ ```
309
+
310
+
311
+ Design Decisions
312
+ ----------------------------------------------------------------------------------------
313
+
314
+ - [Inheritance over Decorators](docs/decision-inheritance-over-decorators.md)
315
+
316
+
317
+ Contributing
318
+ ----------------------------------------------------------------------------------------
319
+
320
+ We welcome contributions to Statica! To contribute:
321
+
322
+ 1. Fork the repository.
323
+ 2. Create a new branch for your feature or bug fix.
324
+ 3. Write tests for your changes.
325
+ 4. Submit a pull request.
326
+
327
+
328
+ License
329
+ ----------------------------------------------------------------------------------------
330
+
331
+ Statica is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
332
+
333
+
334
+ Acknowledgments
335
+ ----------------------------------------------------------------------------------------
336
+
337
+ Statica was built to simplify data validation and provide a robust and simple framework for type-safe models in Python, inspired by `pydantic` and `dataclasses`.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "statica"
3
- version = "1.2.0"
3
+ version = "1.4.0"
4
4
  description = "A minimalistic data validation library"
5
5
  readme = "README.md"
6
6
  authors = [{ name = "Marcel Kröker", email = "kroeker.marcel@gmail.com" }]
@@ -13,7 +13,7 @@ classifiers=[
13
13
  "Programming Language :: Python",
14
14
  "Topic :: Software Development :: Libraries :: Python Modules"
15
15
  ]
16
- requires-python = ">=3.10, <3.14"
16
+ requires-python = ">=3.11, <3.14"
17
17
 
18
18
 
19
19
  ########################################################################################
@@ -51,7 +51,7 @@ package = true
51
51
 
52
52
  [tool.ruff]
53
53
  show-fixes = true
54
- line-length = 120
54
+ line-length = 100
55
55
 
56
56
 
57
57
  [tool.ruff.lint]
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+
6
+ @dataclass(frozen=True, slots=True)
7
+ class StaticaConfig:
8
+ type_error_message: str
9
+ min_length_error_message: str
10
+ max_length_error_message: str
11
+ min_value_error_message: str
12
+ max_value_error_message: str
13
+
14
+ @classmethod
15
+ def create(
16
+ cls,
17
+ *,
18
+ type_error_message: str = "expected type '{expected_type}', got '{found_type}'",
19
+ min_length_error_message: str = "{field_name} length must be at least {min_length}",
20
+ max_length_error_message: str = "{field_name} length must be at most {max_length}",
21
+ min_value_error_message: str = "{field_name} must be at least {min_value}",
22
+ max_value_error_message: str = "{field_name} must be at most {max_value}",
23
+ ) -> StaticaConfig:
24
+ return cls(
25
+ type_error_message=type_error_message,
26
+ min_length_error_message=min_length_error_message,
27
+ max_length_error_message=max_length_error_message,
28
+ min_value_error_message=min_value_error_message,
29
+ max_value_error_message=max_value_error_message,
30
+ )
31
+
32
+
33
+ default_config = StaticaConfig.create()