valarray 0.4.1__tar.gz → 0.4.2__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.
- {valarray-0.4.1 → valarray-0.4.2}/PKG-INFO +44 -40
- {valarray-0.4.1 → valarray-0.4.2}/README.md +43 -39
- {valarray-0.4.1 → valarray-0.4.2}/pyproject.toml +1 -1
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/classes_for_testing/errors_exceptions.py +5 -3
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/test_validators.py +0 -3
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/validation_functions/field_values/test_val_field_values_utils.py +5 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/validation_functions/test_val_array_values.py +4 -3
- {valarray-0.4.1 → valarray-0.4.2}/tests/test_imports.py +3 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/array.py +7 -3
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/array_type_adapter/adapter.py +3 -1
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/array_type_adapter/errors.py +16 -4
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/axes_and_fields.py +6 -4
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/errors_exceptions/exceptions.py +4 -7
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/errors_exceptions/validation_errors/values.py +14 -8
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validation_functions/array.py +26 -7
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validation_functions/array_values.py +11 -10
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validation_functions/field_values/core.py +13 -7
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validation_functions/field_values/types_and_data_structures.py +5 -8
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validation_functions/field_values/utils.py +2 -2
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validators/__init__.py +11 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validators/base.py +10 -1
- valarray-0.4.2/valarray/core/validators/types.py +29 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/numpy/array.py +2 -5
- {valarray-0.4.1 → valarray-0.4.2}/valarray/numpy/array_type_adapter/errors.py +1 -1
- {valarray-0.4.1 → valarray-0.4.2}/valarray/numpy/errors_exceptions.py +2 -2
- {valarray-0.4.1 → valarray-0.4.2}/valarray/numpy/validation_functions.py +11 -6
- {valarray-0.4.1 → valarray-0.4.2}/valarray/numpy/validators.py +18 -2
- {valarray-0.4.1 → valarray-0.4.2}/.coveragerc +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/.gitignore +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/assets/images/valarray_logo.svg +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/docs/dependency_graphs/core.mmd +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/docs/dependency_graphs/core_validation_errors.mmd +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/docs/dependency_graphs/core_validation_functions.mmd +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/docs/dependency_graphs/numpy.mmd +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/docs/example_code/introduction/issue1_problem.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/docs/example_code/introduction/issue1_solution.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/docs/example_code/introduction/issue2_problem.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/docs/example_code/introduction/issue2_solution.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/docs/example_code/introduction/issue_3_problem.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/docs/example_code/introduction/issue_3_solution.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/requirements.txt +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/requirements_dev.txt +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/requirements_dev_optional.txt +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/test_data/core/string_utils.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/classes_for_testing/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/classes_for_testing/array_and_dtype.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/classes_for_testing/array_type_adapter.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/classes_for_testing/comparisons.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/classes_for_testing/validated_array.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/classes_for_testing/validators.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/errors_exceptions/test_axes_errors.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/errors_exceptions/test_dtype_errors.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/errors_exceptions/test_error_list.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/errors_exceptions/test_exceptions.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/errors_exceptions/test_values_errors.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/test_array.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/test_axes_and_fields.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/test_data_structures.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/test_misc.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/test_string_utils.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/test_utils.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/validation_functions/field_values/test_ax_and_field_strings.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/validation_functions/field_values/test_val_field_values_core.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/validation_functions/test_val_array.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/validation_functions/test_val_dtype.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/core/validation_functions/test_val_shape.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/numpy/common.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/numpy/test_adapter.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/numpy/test_numpy_array.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/numpy/test_numpy_comparisons.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/numpy/test_numpy_errors_and_exceptions.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/tests/numpy/test_validation.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/array_type_adapter/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/array_type_adapter/comparisons.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/data_structures.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/errors_exceptions/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/errors_exceptions/error_list.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/errors_exceptions/validation_errors/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/errors_exceptions/validation_errors/array_creation.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/errors_exceptions/validation_errors/axes.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/errors_exceptions/validation_errors/base.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/errors_exceptions/validation_errors/dtype.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/string_utils/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/string_utils/array.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/string_utils/field.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/string_utils/general.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/string_utils/headings.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/types/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/types/generics.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/types/other.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/utils.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validation_functions/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validation_functions/dtype.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validation_functions/field_values/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validation_functions/shape.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validation_functions/utils.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/core/validators/value_comparisons.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/numpy/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/numpy/array_type_adapter/__init__.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/numpy/array_type_adapter/adapter.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/numpy/array_type_adapter/comparisons.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/numpy/axes_and_fields.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/numpy/types.py +0 -0
- {valarray-0.4.1 → valarray-0.4.2}/valarray/settings.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: valarray
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Library for validating numpy arrays.
|
|
5
5
|
Project-URL: Homepage, https://codeberg.org/jfranek/valarray
|
|
6
6
|
Author-email: "J. Franek" <franek.j27@email.cz>
|
|
@@ -14,7 +14,7 @@ Requires-Python: >=3.7
|
|
|
14
14
|
Requires-Dist: numpy>=2
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
|
|
17
|
-

|
|
17
|
+

|
|
18
18
|
|
|
19
19
|
In short, library for validating numpy arrays that also helps with static analysis and documentation. In long, see [Library rationale](#library-rationale).
|
|
20
20
|
|
|
@@ -55,8 +55,10 @@ except ValidationException as v_exc:
|
|
|
55
55
|
>>> [-2.0, -6.0]
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
-
|
|
58
|
+
<!-- NOTE: Headings that are used as relative links (so most of them) must have id tag defined
|
|
59
|
+
(see https://github.com/pypa/readme_renderer/issues/169#issuecomment-808577486) otherwise links do not work on pypi.-->
|
|
60
|
+
|
|
61
|
+
# Table of contents <!-- omit from toc -->
|
|
60
62
|
- [Library rationale](#library-rationale)
|
|
61
63
|
- [1) Invalid values causing unintended behaviour](#1-invalid-values-causing-unintended-behaviour)
|
|
62
64
|
- [Problem](#problem)
|
|
@@ -86,15 +88,16 @@ except ValidationException as v_exc:
|
|
|
86
88
|
- [Settings](#settings)
|
|
87
89
|
- [Caveats](#caveats)
|
|
88
90
|
- [Changelog](#changelog)
|
|
91
|
+
- [0.4.2](#042)
|
|
89
92
|
- [0.4.1](#041)
|
|
90
93
|
- [0.4](#04)
|
|
91
94
|
- [Breaking changes](#breaking-changes)
|
|
92
95
|
|
|
93
|
-
# Library rationale
|
|
96
|
+
# Library rationale<a id="library-rationale"></a>
|
|
94
97
|
This library aims to help with 3 issues encountered when working with numpy arrays:
|
|
95
98
|
|
|
96
|
-
## 1) Invalid values causing unintended behaviour
|
|
97
|
-
### Problem
|
|
99
|
+
## 1) Invalid values causing unintended behaviour<a id="1-invalid-values-causing-unintended-behaviour"></a>
|
|
100
|
+
### Problem<a id="problem"></a>
|
|
98
101
|
Invalid values can cause crashes, or worse, cause silent failures.
|
|
99
102
|
|
|
100
103
|
For example the following code fails silently when attempting to cut patches from image using bounding boxes with invalid coordinates.
|
|
@@ -128,7 +131,7 @@ for patch in patches:
|
|
|
128
131
|
>>> (50, 200, 3)
|
|
129
132
|
```
|
|
130
133
|
|
|
131
|
-
### Solution
|
|
134
|
+
### Solution<a id="solution"></a>
|
|
132
135
|
Validate boxes array first. If errors are encountered, print descriptive error message(s).
|
|
133
136
|
|
|
134
137
|
```python
|
|
@@ -182,8 +185,8 @@ except ValidationException as exc:
|
|
|
182
185
|
>>> Field < 0 >: [-10]
|
|
183
186
|
```
|
|
184
187
|
|
|
185
|
-
## 2) Limited support for static analysis
|
|
186
|
-
### Problem
|
|
188
|
+
## 2) Limited support for static analysis<a id="2-limited-support-for-static-analysis"></a>
|
|
189
|
+
### Problem<a id="problem-1"></a>
|
|
187
190
|
Support for static analysis is limited. Tools can only check whether the datatype is correct, but not shape, values or what those values actually represent.
|
|
188
191
|
|
|
189
192
|
For example, the function to crop patches needs the boxes to be defined by `xmin, ymin, xmax, ymax` but doesn't throw an error if input boxes are defined by `x_center, y_center, width, height` and static analysis tools cannot detect this error using bulit-in numpy types.
|
|
@@ -227,7 +230,7 @@ for patch in patches_inv:
|
|
|
227
230
|
>>> (0, 200, 3)
|
|
228
231
|
```
|
|
229
232
|
|
|
230
|
-
### Solution
|
|
233
|
+
### Solution<a id="solution-1"></a>
|
|
231
234
|
`ValidatedNumpyArray` subclasses can represent these two types of boxes arrays, and can be used instead of bare numpy arrays in function/method signatures and such.
|
|
232
235
|
```python
|
|
233
236
|
import numpy as np
|
|
@@ -294,8 +297,8 @@ for patch in patches_inv:
|
|
|
294
297
|
print(patch.shape)
|
|
295
298
|
```
|
|
296
299
|
|
|
297
|
-
## 3) Need for explicit documentation
|
|
298
|
-
### Problem
|
|
300
|
+
## 3) Need for explicit documentation<a id="3-need-for-explicit-documentation"></a>
|
|
301
|
+
### Problem<a id="problem-2"></a>
|
|
299
302
|
Using built-in numpy types provides only documentation for data types. Shape, values, constraints and what the array represents need to be explicitly documented either in comments or docstrings.
|
|
300
303
|
|
|
301
304
|
If this type of array is used in multiple places / functions, this can cause duplicated documentation.
|
|
@@ -324,7 +327,7 @@ def cut_patches(
|
|
|
324
327
|
return patches
|
|
325
328
|
```
|
|
326
329
|
|
|
327
|
-
### Solution
|
|
330
|
+
### Solution<a id="solution-2"></a>
|
|
328
331
|
Defining data type, schema and constraints on a `ValidatedNumpyArray` subclass already implicitly documents them.
|
|
329
332
|
|
|
330
333
|
This can be complemented by adding additional (or summary) documentation in the class docstring.
|
|
@@ -372,8 +375,8 @@ def cut_patches(
|
|
|
372
375
|
```
|
|
373
376
|
|
|
374
377
|
|
|
375
|
-
# Validated Array
|
|
376
|
-
## Defining a validated array
|
|
378
|
+
# Validated Array<a id="validated-array"></a>
|
|
379
|
+
## Defining a validated array<a id="defining-a-validated-array"></a>
|
|
377
380
|
Subclass `ValidatedNumpyArray` and define:
|
|
378
381
|
- `dtype` - expected data type specification (such as `float`, `"float64"`, `np.float64`).
|
|
379
382
|
If not specified, data type is not validated.
|
|
@@ -382,7 +385,7 @@ Subclass `ValidatedNumpyArray` and define:
|
|
|
382
385
|
- `schema` - expected shape specification (of type `valarray.numpy.axes_and_fields.AxesTuple`). For details, see [Array Schema](#array-schema).
|
|
383
386
|
If not specified, shape is not validated (and no field validators are applied).
|
|
384
387
|
- `lt`/`le`/`ge`/`gt`/`eq` - basic array value constraints -> less (or equal) than, greater (or equal) than, equal to
|
|
385
|
-
- `validators` - optional
|
|
388
|
+
- `validators` - optional validator or a tuple of validators applied to the whole array. For details, see [Validators](##validators).
|
|
386
389
|
|
|
387
390
|
```python
|
|
388
391
|
import numpy as np
|
|
@@ -393,7 +396,7 @@ class ExampleValidatedNumpyArray(ValidatedNumpyArray):
|
|
|
393
396
|
schema = ('batch_size', 3, 5)
|
|
394
397
|
```
|
|
395
398
|
|
|
396
|
-
## Creating a validated array instance
|
|
399
|
+
## Creating a validated array instance<a id="creating-a-validated-array-instance"></a>
|
|
397
400
|
There are 4 ways to create a validated array instance:
|
|
398
401
|
- validate an existing array
|
|
399
402
|
```python
|
|
@@ -436,7 +439,7 @@ v_arr = ExampleValidatedNumpyArray(np.array([1,2],dtype=np.float32), coerce_dtyp
|
|
|
436
439
|
v_arr = ExampleValidatedNumpyArray(np.array([1,2],dtype=np.float32), coerce_dtype=True, validate=False)
|
|
437
440
|
```
|
|
438
441
|
|
|
439
|
-
## Accessing array values
|
|
442
|
+
## Accessing array values<a id="accessing-array-values"></a>
|
|
440
443
|
You can access the underlying array using the `.array`/`.a_` property:
|
|
441
444
|
```python
|
|
442
445
|
arr = v_arr.array
|
|
@@ -459,7 +462,7 @@ class SpecifiedDataTypeArray(ValidatedNumpyArray[np.float32]): ...
|
|
|
459
462
|
arr = SpecifiedDataTypeArray(...).array # np.typing.NDArray[np.float32]
|
|
460
463
|
```
|
|
461
464
|
|
|
462
|
-
# Validation functions
|
|
465
|
+
# Validation functions<a id="validation-functions"></a>
|
|
463
466
|
Array validation is designed to be modular and composable and validation functions can be used on they own if only runtime validation is required.
|
|
464
467
|
Each validation function returns a list of errors, from which a `ValidationException` can be raised. For details see [Catching exceptions](#catching-exceptions).
|
|
465
468
|
```python
|
|
@@ -498,7 +501,7 @@ and a "composite" validation function:
|
|
|
498
501
|
- *returns* `NumpyInvalidArrayValuesError`/`NumpyInvalidFieldValuesError` or no errors.
|
|
499
502
|
|
|
500
503
|
|
|
501
|
-
# Array schema
|
|
504
|
+
# Array schema<a id="array-schema"></a>
|
|
502
505
|
Schema defines expected axes, and for each axis its' fields and optionally constraints on the field values.
|
|
503
506
|
|
|
504
507
|
Axes can be defined with:
|
|
@@ -519,11 +522,11 @@ schema = (
|
|
|
519
522
|
("field_a", Field())
|
|
520
523
|
)
|
|
521
524
|
```
|
|
522
|
-
## Field
|
|
525
|
+
## Field<a id="field"></a>
|
|
523
526
|
Defines (optional) name and value constrints for array field. More specifically:
|
|
524
527
|
- `name` - descriptive name used in error messages (if missing, field index is used instead)
|
|
525
528
|
- `lt`/`le`/`ge`/`gt`/`eq` - basic array value constraints -> less (or equal) than, greater (or equal) than, equal to
|
|
526
|
-
- `validators` -
|
|
529
|
+
- `validators` - optional validator or a tuple of validators applied to fields values. For details, see [Validators](##validators).
|
|
527
530
|
|
|
528
531
|
```python
|
|
529
532
|
from typing import Any
|
|
@@ -538,8 +541,8 @@ f1 = Field("example_named_field", ge=0)
|
|
|
538
541
|
f2 = Field(gt=10, validators=(ExampleNumpyValidator(),))
|
|
539
542
|
```
|
|
540
543
|
|
|
541
|
-
## Array schema examples
|
|
542
|
-
### rectangles
|
|
544
|
+
## Array schema examples<a id="array-schema-examples"></a>
|
|
545
|
+
### rectangles<a id="rectangles"></a>
|
|
543
546
|
An array of arbitrary number of rectangles defined by min and max coordinates which has two axes: *n_rects* and *rect*.
|
|
544
547
|
Axis *rect* is has 4 fields: *x_min*,*y_min*,*x_max*,*y_max*, where values must be greater or equal to zero.
|
|
545
548
|
|
|
@@ -572,10 +575,10 @@ arr = np.array(
|
|
|
572
575
|
Rect.validate(arr)
|
|
573
576
|
```
|
|
574
577
|
|
|
575
|
-
# Validators
|
|
578
|
+
# Validators<a id="validators"></a>
|
|
576
579
|
Validators are objects that perform arbitrary validation of array or field values defined by user.
|
|
577
580
|
|
|
578
|
-
## Defining a validator
|
|
581
|
+
## Defining a validator<a id="defining-a-validator"></a>
|
|
579
582
|
Validators must subclass `valarray.numpy.NumpyValidator` Abstract Base Class
|
|
580
583
|
and implement the `.validate()` method that takes an array as an input and results in success/failure of validation using these options:
|
|
581
584
|
|
|
@@ -588,7 +591,7 @@ and implement the `.validate()` method that takes an array as an input and resul
|
|
|
588
591
|
- *returns* `False`
|
|
589
592
|
- *raises* `ValueError`
|
|
590
593
|
|
|
591
|
-
### ValidationResult
|
|
594
|
+
### ValidationResult<a id="validationresult"></a>
|
|
592
595
|
Contains result status of validation `status="OK"`/`status="FAIL"`
|
|
593
596
|
|
|
594
597
|
Can also optionally contain:
|
|
@@ -620,7 +623,7 @@ indices = (np.array([0, 1, 1]), np.array([1, 0, 1]))
|
|
|
620
623
|
res = ValidationResult(status="FAIL", indices_invalid=indices, msg="Optional error message.")
|
|
621
624
|
```
|
|
622
625
|
|
|
623
|
-
### Example Validator
|
|
626
|
+
### Example Validator<a id="example-validator"></a>
|
|
624
627
|
```python
|
|
625
628
|
from dataclasses import dataclass
|
|
626
629
|
from typing import Literal
|
|
@@ -657,7 +660,7 @@ class ExampleIsEvenValidator(NumpyValidator[np.uint8]):
|
|
|
657
660
|
return ValidationResult("FAIL", indices_invalid=~even)
|
|
658
661
|
```
|
|
659
662
|
|
|
660
|
-
# Catching exceptions
|
|
663
|
+
# Catching exceptions<a id="catching-exceptions"></a>
|
|
661
664
|
Failed validation results in `valarray.core.errors_exceptions.ValidationException` being raised containing list of errors responsible (and name of array class if available).
|
|
662
665
|
|
|
663
666
|
Main error types are:
|
|
@@ -683,42 +686,43 @@ except ValidationException as exc:
|
|
|
683
686
|
axis_errs = exc.errs[(IncorrectAxSizesError, IncorrectAxNumberError)]
|
|
684
687
|
```
|
|
685
688
|
|
|
686
|
-
## Special exceptions and errors
|
|
689
|
+
## Special exceptions and errors<a id="special-exceptions-and-errors"></a>
|
|
687
690
|
There are two special subclasses of `ValidationException` with associated validation errors raised during [instantiation](#creating-a-validated-array-instance):
|
|
688
691
|
- `CreateArrayException` -> `CannotCreateArrayError` - Array cannot be created from supplied object.
|
|
689
692
|
- `CoerceDTypeException` -> `CannotCoerceDTypeError` - If array data type cannot be coerced when creating array with `ValidatedArray(coerce_dtype=True)`
|
|
690
693
|
|
|
691
694
|
|
|
692
|
-
## Generic Errors
|
|
695
|
+
## Generic Errors<a id="generic-errors"></a>
|
|
693
696
|
These error types have subclasses ensuring proper type hints:
|
|
694
697
|
- `IncorrectDTypeError` -> `NumpyIncorrectDTypeError`
|
|
695
698
|
- `CannotCoerceDTypeError` -> `NumpyCannotCoerceDTypeError`
|
|
696
699
|
- `InvalidArrayValuesError` -> `NumpyInvalidArrayValuesError`
|
|
697
700
|
- `InvalidFieldValuesError` -> `NumpyInvalidFieldValuesError`
|
|
698
701
|
|
|
699
|
-
# Settings
|
|
702
|
+
# Settings<a id="settings"></a>
|
|
700
703
|
Global settings for the library are defined in `valarray.settings` and can be modified using environment variables.
|
|
701
704
|
| ***variable name*** | ***environment variable*** | default value | description |
|
|
702
705
|
|---------------------|------------------------------|---------------|-----------------------------------------------------|
|
|
703
706
|
| function_cache_size | VALARRAY_FUNCTION_CACHE_SIZE | 512 | cache size for (internal) frequently used functions |
|
|
704
707
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
# Caveats
|
|
708
|
+
# Caveats<a id="caveats"></a>
|
|
708
709
|
- I cannot guarantee that the test suite is foolproof ATM as I'm currently the only one testing this library.
|
|
709
710
|
- Library has so far only been tested with `python==3.12` and `numpy==2.4.0`
|
|
710
711
|
- Library isn't tested for performance, use in production only if the primary bottleneck is brain and not hardware.
|
|
711
712
|
|
|
712
|
-
# Changelog
|
|
713
|
-
## 0.4.
|
|
713
|
+
# Changelog<a id="changelog"></a>
|
|
714
|
+
## 0.4.2<a id="042"></a>
|
|
715
|
+
- changed `ValidatedArray`, `Field` classes and `validate_array`, `validate_array_values` to accept a single validator as a parameter.
|
|
716
|
+
|
|
717
|
+
## 0.4.1<a id="041"></a>
|
|
714
718
|
- added cache for often used functions
|
|
715
719
|
- added __str__ and __len__ methods
|
|
716
720
|
|
|
717
|
-
## 0.4
|
|
721
|
+
## 0.4<a id="04"></a>
|
|
718
722
|
- first version with all basic features: creating a validated array, validating dtype, shape, array and field values
|
|
719
723
|
|
|
720
724
|
|
|
721
|
-
# Breaking changes
|
|
725
|
+
# Breaking changes<a id="breaking-changes"></a>
|
|
722
726
|
- **0.4** -> **0.4.1**
|
|
723
727
|
- changed __str__ method for `Validator` to `.error_string` property (to allow different string representation for error messages and general printing)
|
|
724
728
|
- changed imports due to refactoring to simplify dependencies:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-

|
|
1
|
+

|
|
2
2
|
|
|
3
3
|
In short, library for validating numpy arrays that also helps with static analysis and documentation. In long, see [Library rationale](#library-rationale).
|
|
4
4
|
|
|
@@ -39,8 +39,10 @@ except ValidationException as v_exc:
|
|
|
39
39
|
>>> [-2.0, -6.0]
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
-
|
|
42
|
+
<!-- NOTE: Headings that are used as relative links (so most of them) must have id tag defined
|
|
43
|
+
(see https://github.com/pypa/readme_renderer/issues/169#issuecomment-808577486) otherwise links do not work on pypi.-->
|
|
44
|
+
|
|
45
|
+
# Table of contents <!-- omit from toc -->
|
|
44
46
|
- [Library rationale](#library-rationale)
|
|
45
47
|
- [1) Invalid values causing unintended behaviour](#1-invalid-values-causing-unintended-behaviour)
|
|
46
48
|
- [Problem](#problem)
|
|
@@ -70,15 +72,16 @@ except ValidationException as v_exc:
|
|
|
70
72
|
- [Settings](#settings)
|
|
71
73
|
- [Caveats](#caveats)
|
|
72
74
|
- [Changelog](#changelog)
|
|
75
|
+
- [0.4.2](#042)
|
|
73
76
|
- [0.4.1](#041)
|
|
74
77
|
- [0.4](#04)
|
|
75
78
|
- [Breaking changes](#breaking-changes)
|
|
76
79
|
|
|
77
|
-
# Library rationale
|
|
80
|
+
# Library rationale<a id="library-rationale"></a>
|
|
78
81
|
This library aims to help with 3 issues encountered when working with numpy arrays:
|
|
79
82
|
|
|
80
|
-
## 1) Invalid values causing unintended behaviour
|
|
81
|
-
### Problem
|
|
83
|
+
## 1) Invalid values causing unintended behaviour<a id="1-invalid-values-causing-unintended-behaviour"></a>
|
|
84
|
+
### Problem<a id="problem"></a>
|
|
82
85
|
Invalid values can cause crashes, or worse, cause silent failures.
|
|
83
86
|
|
|
84
87
|
For example the following code fails silently when attempting to cut patches from image using bounding boxes with invalid coordinates.
|
|
@@ -112,7 +115,7 @@ for patch in patches:
|
|
|
112
115
|
>>> (50, 200, 3)
|
|
113
116
|
```
|
|
114
117
|
|
|
115
|
-
### Solution
|
|
118
|
+
### Solution<a id="solution"></a>
|
|
116
119
|
Validate boxes array first. If errors are encountered, print descriptive error message(s).
|
|
117
120
|
|
|
118
121
|
```python
|
|
@@ -166,8 +169,8 @@ except ValidationException as exc:
|
|
|
166
169
|
>>> Field < 0 >: [-10]
|
|
167
170
|
```
|
|
168
171
|
|
|
169
|
-
## 2) Limited support for static analysis
|
|
170
|
-
### Problem
|
|
172
|
+
## 2) Limited support for static analysis<a id="2-limited-support-for-static-analysis"></a>
|
|
173
|
+
### Problem<a id="problem-1"></a>
|
|
171
174
|
Support for static analysis is limited. Tools can only check whether the datatype is correct, but not shape, values or what those values actually represent.
|
|
172
175
|
|
|
173
176
|
For example, the function to crop patches needs the boxes to be defined by `xmin, ymin, xmax, ymax` but doesn't throw an error if input boxes are defined by `x_center, y_center, width, height` and static analysis tools cannot detect this error using bulit-in numpy types.
|
|
@@ -211,7 +214,7 @@ for patch in patches_inv:
|
|
|
211
214
|
>>> (0, 200, 3)
|
|
212
215
|
```
|
|
213
216
|
|
|
214
|
-
### Solution
|
|
217
|
+
### Solution<a id="solution-1"></a>
|
|
215
218
|
`ValidatedNumpyArray` subclasses can represent these two types of boxes arrays, and can be used instead of bare numpy arrays in function/method signatures and such.
|
|
216
219
|
```python
|
|
217
220
|
import numpy as np
|
|
@@ -278,8 +281,8 @@ for patch in patches_inv:
|
|
|
278
281
|
print(patch.shape)
|
|
279
282
|
```
|
|
280
283
|
|
|
281
|
-
## 3) Need for explicit documentation
|
|
282
|
-
### Problem
|
|
284
|
+
## 3) Need for explicit documentation<a id="3-need-for-explicit-documentation"></a>
|
|
285
|
+
### Problem<a id="problem-2"></a>
|
|
283
286
|
Using built-in numpy types provides only documentation for data types. Shape, values, constraints and what the array represents need to be explicitly documented either in comments or docstrings.
|
|
284
287
|
|
|
285
288
|
If this type of array is used in multiple places / functions, this can cause duplicated documentation.
|
|
@@ -308,7 +311,7 @@ def cut_patches(
|
|
|
308
311
|
return patches
|
|
309
312
|
```
|
|
310
313
|
|
|
311
|
-
### Solution
|
|
314
|
+
### Solution<a id="solution-2"></a>
|
|
312
315
|
Defining data type, schema and constraints on a `ValidatedNumpyArray` subclass already implicitly documents them.
|
|
313
316
|
|
|
314
317
|
This can be complemented by adding additional (or summary) documentation in the class docstring.
|
|
@@ -356,8 +359,8 @@ def cut_patches(
|
|
|
356
359
|
```
|
|
357
360
|
|
|
358
361
|
|
|
359
|
-
# Validated Array
|
|
360
|
-
## Defining a validated array
|
|
362
|
+
# Validated Array<a id="validated-array"></a>
|
|
363
|
+
## Defining a validated array<a id="defining-a-validated-array"></a>
|
|
361
364
|
Subclass `ValidatedNumpyArray` and define:
|
|
362
365
|
- `dtype` - expected data type specification (such as `float`, `"float64"`, `np.float64`).
|
|
363
366
|
If not specified, data type is not validated.
|
|
@@ -366,7 +369,7 @@ Subclass `ValidatedNumpyArray` and define:
|
|
|
366
369
|
- `schema` - expected shape specification (of type `valarray.numpy.axes_and_fields.AxesTuple`). For details, see [Array Schema](#array-schema).
|
|
367
370
|
If not specified, shape is not validated (and no field validators are applied).
|
|
368
371
|
- `lt`/`le`/`ge`/`gt`/`eq` - basic array value constraints -> less (or equal) than, greater (or equal) than, equal to
|
|
369
|
-
- `validators` - optional
|
|
372
|
+
- `validators` - optional validator or a tuple of validators applied to the whole array. For details, see [Validators](##validators).
|
|
370
373
|
|
|
371
374
|
```python
|
|
372
375
|
import numpy as np
|
|
@@ -377,7 +380,7 @@ class ExampleValidatedNumpyArray(ValidatedNumpyArray):
|
|
|
377
380
|
schema = ('batch_size', 3, 5)
|
|
378
381
|
```
|
|
379
382
|
|
|
380
|
-
## Creating a validated array instance
|
|
383
|
+
## Creating a validated array instance<a id="creating-a-validated-array-instance"></a>
|
|
381
384
|
There are 4 ways to create a validated array instance:
|
|
382
385
|
- validate an existing array
|
|
383
386
|
```python
|
|
@@ -420,7 +423,7 @@ v_arr = ExampleValidatedNumpyArray(np.array([1,2],dtype=np.float32), coerce_dtyp
|
|
|
420
423
|
v_arr = ExampleValidatedNumpyArray(np.array([1,2],dtype=np.float32), coerce_dtype=True, validate=False)
|
|
421
424
|
```
|
|
422
425
|
|
|
423
|
-
## Accessing array values
|
|
426
|
+
## Accessing array values<a id="accessing-array-values"></a>
|
|
424
427
|
You can access the underlying array using the `.array`/`.a_` property:
|
|
425
428
|
```python
|
|
426
429
|
arr = v_arr.array
|
|
@@ -443,7 +446,7 @@ class SpecifiedDataTypeArray(ValidatedNumpyArray[np.float32]): ...
|
|
|
443
446
|
arr = SpecifiedDataTypeArray(...).array # np.typing.NDArray[np.float32]
|
|
444
447
|
```
|
|
445
448
|
|
|
446
|
-
# Validation functions
|
|
449
|
+
# Validation functions<a id="validation-functions"></a>
|
|
447
450
|
Array validation is designed to be modular and composable and validation functions can be used on they own if only runtime validation is required.
|
|
448
451
|
Each validation function returns a list of errors, from which a `ValidationException` can be raised. For details see [Catching exceptions](#catching-exceptions).
|
|
449
452
|
```python
|
|
@@ -482,7 +485,7 @@ and a "composite" validation function:
|
|
|
482
485
|
- *returns* `NumpyInvalidArrayValuesError`/`NumpyInvalidFieldValuesError` or no errors.
|
|
483
486
|
|
|
484
487
|
|
|
485
|
-
# Array schema
|
|
488
|
+
# Array schema<a id="array-schema"></a>
|
|
486
489
|
Schema defines expected axes, and for each axis its' fields and optionally constraints on the field values.
|
|
487
490
|
|
|
488
491
|
Axes can be defined with:
|
|
@@ -503,11 +506,11 @@ schema = (
|
|
|
503
506
|
("field_a", Field())
|
|
504
507
|
)
|
|
505
508
|
```
|
|
506
|
-
## Field
|
|
509
|
+
## Field<a id="field"></a>
|
|
507
510
|
Defines (optional) name and value constrints for array field. More specifically:
|
|
508
511
|
- `name` - descriptive name used in error messages (if missing, field index is used instead)
|
|
509
512
|
- `lt`/`le`/`ge`/`gt`/`eq` - basic array value constraints -> less (or equal) than, greater (or equal) than, equal to
|
|
510
|
-
- `validators` -
|
|
513
|
+
- `validators` - optional validator or a tuple of validators applied to fields values. For details, see [Validators](##validators).
|
|
511
514
|
|
|
512
515
|
```python
|
|
513
516
|
from typing import Any
|
|
@@ -522,8 +525,8 @@ f1 = Field("example_named_field", ge=0)
|
|
|
522
525
|
f2 = Field(gt=10, validators=(ExampleNumpyValidator(),))
|
|
523
526
|
```
|
|
524
527
|
|
|
525
|
-
## Array schema examples
|
|
526
|
-
### rectangles
|
|
528
|
+
## Array schema examples<a id="array-schema-examples"></a>
|
|
529
|
+
### rectangles<a id="rectangles"></a>
|
|
527
530
|
An array of arbitrary number of rectangles defined by min and max coordinates which has two axes: *n_rects* and *rect*.
|
|
528
531
|
Axis *rect* is has 4 fields: *x_min*,*y_min*,*x_max*,*y_max*, where values must be greater or equal to zero.
|
|
529
532
|
|
|
@@ -556,10 +559,10 @@ arr = np.array(
|
|
|
556
559
|
Rect.validate(arr)
|
|
557
560
|
```
|
|
558
561
|
|
|
559
|
-
# Validators
|
|
562
|
+
# Validators<a id="validators"></a>
|
|
560
563
|
Validators are objects that perform arbitrary validation of array or field values defined by user.
|
|
561
564
|
|
|
562
|
-
## Defining a validator
|
|
565
|
+
## Defining a validator<a id="defining-a-validator"></a>
|
|
563
566
|
Validators must subclass `valarray.numpy.NumpyValidator` Abstract Base Class
|
|
564
567
|
and implement the `.validate()` method that takes an array as an input and results in success/failure of validation using these options:
|
|
565
568
|
|
|
@@ -572,7 +575,7 @@ and implement the `.validate()` method that takes an array as an input and resul
|
|
|
572
575
|
- *returns* `False`
|
|
573
576
|
- *raises* `ValueError`
|
|
574
577
|
|
|
575
|
-
### ValidationResult
|
|
578
|
+
### ValidationResult<a id="validationresult"></a>
|
|
576
579
|
Contains result status of validation `status="OK"`/`status="FAIL"`
|
|
577
580
|
|
|
578
581
|
Can also optionally contain:
|
|
@@ -604,7 +607,7 @@ indices = (np.array([0, 1, 1]), np.array([1, 0, 1]))
|
|
|
604
607
|
res = ValidationResult(status="FAIL", indices_invalid=indices, msg="Optional error message.")
|
|
605
608
|
```
|
|
606
609
|
|
|
607
|
-
### Example Validator
|
|
610
|
+
### Example Validator<a id="example-validator"></a>
|
|
608
611
|
```python
|
|
609
612
|
from dataclasses import dataclass
|
|
610
613
|
from typing import Literal
|
|
@@ -641,7 +644,7 @@ class ExampleIsEvenValidator(NumpyValidator[np.uint8]):
|
|
|
641
644
|
return ValidationResult("FAIL", indices_invalid=~even)
|
|
642
645
|
```
|
|
643
646
|
|
|
644
|
-
# Catching exceptions
|
|
647
|
+
# Catching exceptions<a id="catching-exceptions"></a>
|
|
645
648
|
Failed validation results in `valarray.core.errors_exceptions.ValidationException` being raised containing list of errors responsible (and name of array class if available).
|
|
646
649
|
|
|
647
650
|
Main error types are:
|
|
@@ -667,42 +670,43 @@ except ValidationException as exc:
|
|
|
667
670
|
axis_errs = exc.errs[(IncorrectAxSizesError, IncorrectAxNumberError)]
|
|
668
671
|
```
|
|
669
672
|
|
|
670
|
-
## Special exceptions and errors
|
|
673
|
+
## Special exceptions and errors<a id="special-exceptions-and-errors"></a>
|
|
671
674
|
There are two special subclasses of `ValidationException` with associated validation errors raised during [instantiation](#creating-a-validated-array-instance):
|
|
672
675
|
- `CreateArrayException` -> `CannotCreateArrayError` - Array cannot be created from supplied object.
|
|
673
676
|
- `CoerceDTypeException` -> `CannotCoerceDTypeError` - If array data type cannot be coerced when creating array with `ValidatedArray(coerce_dtype=True)`
|
|
674
677
|
|
|
675
678
|
|
|
676
|
-
## Generic Errors
|
|
679
|
+
## Generic Errors<a id="generic-errors"></a>
|
|
677
680
|
These error types have subclasses ensuring proper type hints:
|
|
678
681
|
- `IncorrectDTypeError` -> `NumpyIncorrectDTypeError`
|
|
679
682
|
- `CannotCoerceDTypeError` -> `NumpyCannotCoerceDTypeError`
|
|
680
683
|
- `InvalidArrayValuesError` -> `NumpyInvalidArrayValuesError`
|
|
681
684
|
- `InvalidFieldValuesError` -> `NumpyInvalidFieldValuesError`
|
|
682
685
|
|
|
683
|
-
# Settings
|
|
686
|
+
# Settings<a id="settings"></a>
|
|
684
687
|
Global settings for the library are defined in `valarray.settings` and can be modified using environment variables.
|
|
685
688
|
| ***variable name*** | ***environment variable*** | default value | description |
|
|
686
689
|
|---------------------|------------------------------|---------------|-----------------------------------------------------|
|
|
687
690
|
| function_cache_size | VALARRAY_FUNCTION_CACHE_SIZE | 512 | cache size for (internal) frequently used functions |
|
|
688
691
|
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
# Caveats
|
|
692
|
+
# Caveats<a id="caveats"></a>
|
|
692
693
|
- I cannot guarantee that the test suite is foolproof ATM as I'm currently the only one testing this library.
|
|
693
694
|
- Library has so far only been tested with `python==3.12` and `numpy==2.4.0`
|
|
694
695
|
- Library isn't tested for performance, use in production only if the primary bottleneck is brain and not hardware.
|
|
695
696
|
|
|
696
|
-
# Changelog
|
|
697
|
-
## 0.4.
|
|
697
|
+
# Changelog<a id="changelog"></a>
|
|
698
|
+
## 0.4.2<a id="042"></a>
|
|
699
|
+
- changed `ValidatedArray`, `Field` classes and `validate_array`, `validate_array_values` to accept a single validator as a parameter.
|
|
700
|
+
|
|
701
|
+
## 0.4.1<a id="041"></a>
|
|
698
702
|
- added cache for often used functions
|
|
699
703
|
- added __str__ and __len__ methods
|
|
700
704
|
|
|
701
|
-
## 0.4
|
|
705
|
+
## 0.4<a id="04"></a>
|
|
702
706
|
- first version with all basic features: creating a validated array, validating dtype, shape, array and field values
|
|
703
707
|
|
|
704
708
|
|
|
705
|
-
# Breaking changes
|
|
709
|
+
# Breaking changes<a id="breaking-changes"></a>
|
|
706
710
|
- **0.4** -> **0.4.1**
|
|
707
711
|
- changed __str__ method for `Validator` to `.error_string` property (to allow different string representation for error messages and general printing)
|
|
708
712
|
- changed imports due to refactoring to simplify dependencies:
|
|
@@ -17,15 +17,17 @@ class TestIncorrectDTypeError(IncorrectDTypeError[TestDtypeLike, TestDtype]): ..
|
|
|
17
17
|
class TestCannotCoerceDTypeError(CannotCoerceDTypeError[TestDtypeLike, TestDtype]): ...
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
class TestInvalidArrayValuesError(InvalidArrayValuesError[TestArray, list[int]]):
|
|
20
|
+
class TestInvalidArrayValuesError(InvalidArrayValuesError[TestArray, list[int], int]):
|
|
21
21
|
"""Blank"""
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
class TestInvalidFieldValuesError(
|
|
24
|
+
class TestInvalidFieldValuesError(
|
|
25
|
+
InvalidFieldValuesError[TestArray, list[int], int]
|
|
26
|
+
): ...
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
@dataclass
|
|
28
|
-
class TestErrors(GenericErrors[TestArray, TestDtypeLike, TestDtype, list[int]]):
|
|
30
|
+
class TestErrors(GenericErrors[TestArray, TestDtypeLike, TestDtype, list[int], int]):
|
|
29
31
|
incorrect_dtype: type[TestIncorrectDTypeError] = TestIncorrectDTypeError
|
|
30
32
|
cannot_coerce_dtype: type[TestCannotCoerceDTypeError] = TestCannotCoerceDTypeError
|
|
31
33
|
invalid_array_values: type[TestInvalidArrayValuesError] = (
|
|
@@ -127,6 +127,3 @@ def test_apply_validator(
|
|
|
127
127
|
assert (
|
|
128
128
|
validation_result == expected_validation_result
|
|
129
129
|
), "actual/expected values for 'validation_result' are not equal"
|
|
130
|
-
assert (
|
|
131
|
-
validation_result == expected_validation_result
|
|
132
|
-
), "actual/expected values for 'validation_result' are not equal"
|
|
@@ -52,6 +52,11 @@ RESOLVED_FIELD_WITH_VALIDATORS = _ResolvedField(
|
|
|
52
52
|
Field(name="example_field", ge=0, validators=(TestDummyValidator(),)),
|
|
53
53
|
RESOLVED_FIELD_WITH_VALIDATORS,
|
|
54
54
|
),
|
|
55
|
+
(
|
|
56
|
+
0,
|
|
57
|
+
Field(name="example_field", ge=0, validators=TestDummyValidator()),
|
|
58
|
+
RESOLVED_FIELD_WITH_VALIDATORS,
|
|
59
|
+
),
|
|
55
60
|
],
|
|
56
61
|
)
|
|
57
62
|
def test__resolve_field(
|
|
@@ -10,7 +10,7 @@ from tests.core.classes_for_testing import (
|
|
|
10
10
|
)
|
|
11
11
|
from valarray.core.errors_exceptions import ValidationErrorList
|
|
12
12
|
from valarray.core.validation_functions import validate_array_values
|
|
13
|
-
from valarray.core.validators import ComparisonValidator,
|
|
13
|
+
from valarray.core.validators import ComparisonValidator, ValidatorOrValidatorSequence
|
|
14
14
|
|
|
15
15
|
COMP_VAL = ComparisonValidator("gt", 0, TestComparisons())
|
|
16
16
|
|
|
@@ -18,6 +18,7 @@ COMP_VAL = ComparisonValidator("gt", 0, TestComparisons())
|
|
|
18
18
|
@pytest.mark.parametrize(
|
|
19
19
|
"arr, validator, expected_errs",
|
|
20
20
|
[
|
|
21
|
+
(TestArray(val=[1, 2, 3]), [COMP_VAL], []),
|
|
21
22
|
(TestArray(val=[1, 2, 3]), COMP_VAL, []),
|
|
22
23
|
(
|
|
23
24
|
TestArray(val=[1, 1, 0]),
|
|
@@ -42,10 +43,10 @@ COMP_VAL = ComparisonValidator("gt", 0, TestComparisons())
|
|
|
42
43
|
)
|
|
43
44
|
def test_validate_array_values(
|
|
44
45
|
arr: TestArray,
|
|
45
|
-
validator:
|
|
46
|
+
validator: ValidatorOrValidatorSequence,
|
|
46
47
|
expected_errs: ValidationErrorList[TestInvalidArrayValuesError],
|
|
47
48
|
):
|
|
48
49
|
|
|
49
|
-
errs = validate_array_values(arr,
|
|
50
|
+
errs = validate_array_values(arr, validator, TestArrayTypeAdapter())
|
|
50
51
|
|
|
51
52
|
assert errs == expected_errs, "actual/expected values for 'errs' are not equal"
|
|
@@ -52,6 +52,9 @@ class M:
|
|
|
52
52
|
(M("valarray.core.validators", "ComparisonValidator")),
|
|
53
53
|
(M("valarray.core.validators", "ValidationResult")),
|
|
54
54
|
(M("valarray.core.validators", "Validator")),
|
|
55
|
+
(M("valarray.core.validators", "ValidatorOrValidatorTuple")),
|
|
56
|
+
(M("valarray.core.validators", "ValidatorOrComparisonValidator")),
|
|
57
|
+
(M("valarray.core.validators", "ValidatorOrValidatorSequence")),
|
|
55
58
|
### 1.5 utils
|
|
56
59
|
(M("valarray.core.utils", "ax_sizes_from_schema")),
|
|
57
60
|
(M("valarray.core.utils", "constraints_to_validators")),
|
|
@@ -20,7 +20,7 @@ from .errors_exceptions import ValidationException
|
|
|
20
20
|
from .types import ArrayIndicesT, ArrayT, ComparableValueT, DTypeLikeT, DTypeT
|
|
21
21
|
from .utils import constraints_to_validators, setup_array
|
|
22
22
|
from .validation_functions import validate_array
|
|
23
|
-
from .validators
|
|
23
|
+
from .validators import ValidatorOrValidatorTuple
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class ValidatedArray(
|
|
@@ -44,7 +44,7 @@ class ValidatedArray(
|
|
|
44
44
|
|
|
45
45
|
dtype: DTypeLikeT | EllipsisType = ...
|
|
46
46
|
schema: AxesTuple[ArrayT, ArrayIndicesT, ComparableValueT] | EllipsisType = ...
|
|
47
|
-
validators:
|
|
47
|
+
validators: ValidatorOrValidatorTuple[ArrayT, ArrayIndicesT, ComparableValueT] = ()
|
|
48
48
|
|
|
49
49
|
lt: Optional[ComparableValueT] = None
|
|
50
50
|
le: Optional[ComparableValueT] = None
|
|
@@ -116,7 +116,11 @@ class ValidatedArray(
|
|
|
116
116
|
)
|
|
117
117
|
|
|
118
118
|
if errs:
|
|
119
|
-
|
|
119
|
+
# T!: need to refactor exceptions
|
|
120
|
+
# so ValidationException only accepts a list of errors returned by validation functions.
|
|
121
|
+
raise ValidationException(
|
|
122
|
+
self.__class__.__name__, errs # pyright: ignore[reportArgumentType]
|
|
123
|
+
)
|
|
120
124
|
|
|
121
125
|
self.is_validated = True
|
|
122
126
|
|
|
@@ -73,7 +73,9 @@ class ArrayTypeAdapter(
|
|
|
73
73
|
|
|
74
74
|
@property
|
|
75
75
|
@abstractmethod
|
|
76
|
-
def errors(
|
|
76
|
+
def errors(
|
|
77
|
+
self,
|
|
78
|
+
) -> GenericErrors[ArrayT, DTypeLikeT, DTypeT, ArrayIndicesT, ComparableValueT]: ...
|
|
77
79
|
|
|
78
80
|
@property
|
|
79
81
|
@abstractmethod
|