pyvista-validation 0.1.0__py3-none-any.whl
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.
- pyvista_validation/__init__.py +36 -0
- pyvista_validation/_cast_array.py +134 -0
- pyvista_validation/_lazy_import.py +46 -0
- pyvista_validation/_typing/__init__.py +15 -0
- pyvista_validation/_typing/_aliases.py +23 -0
- pyvista_validation/_typing/_array_like.py +86 -0
- pyvista_validation/_version.py +24 -0
- pyvista_validation/check.py +1235 -0
- pyvista_validation/py.typed +0 -0
- pyvista_validation/validate.py +1246 -0
- pyvista_validation-0.1.0.dist-info/METADATA +222 -0
- pyvista_validation-0.1.0.dist-info/RECORD +15 -0
- pyvista_validation-0.1.0.dist-info/WHEEL +5 -0
- pyvista_validation-0.1.0.dist-info/licenses/LICENSE +21 -0
- pyvista_validation-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Input validation functions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .check import check_contains as check_contains
|
|
6
|
+
from .check import check_finite as check_finite
|
|
7
|
+
from .check import check_greater_than as check_greater_than
|
|
8
|
+
from .check import check_instance as check_instance
|
|
9
|
+
from .check import check_integer as check_integer
|
|
10
|
+
from .check import check_iterable as check_iterable
|
|
11
|
+
from .check import check_iterable_items as check_iterable_items
|
|
12
|
+
from .check import check_length as check_length
|
|
13
|
+
from .check import check_less_than as check_less_than
|
|
14
|
+
from .check import check_ndim as check_ndim
|
|
15
|
+
from .check import check_nonnegative as check_nonnegative
|
|
16
|
+
from .check import check_number as check_number
|
|
17
|
+
from .check import check_range as check_range
|
|
18
|
+
from .check import check_real as check_real
|
|
19
|
+
from .check import check_sequence as check_sequence
|
|
20
|
+
from .check import check_shape as check_shape
|
|
21
|
+
from .check import check_sorted as check_sorted
|
|
22
|
+
from .check import check_string as check_string
|
|
23
|
+
from .check import check_subdtype as check_subdtype
|
|
24
|
+
from .check import check_type as check_type
|
|
25
|
+
from .validate import validate_array as validate_array
|
|
26
|
+
from .validate import validate_array3 as validate_array3
|
|
27
|
+
from .validate import validate_arrayN as validate_arrayN
|
|
28
|
+
from .validate import validate_arrayN_unsigned as validate_arrayN_unsigned
|
|
29
|
+
from .validate import validate_arrayNx3 as validate_arrayNx3
|
|
30
|
+
from .validate import validate_axes as validate_axes
|
|
31
|
+
from .validate import validate_data_range as validate_data_range
|
|
32
|
+
from .validate import validate_dimensionality as validate_dimensionality
|
|
33
|
+
from .validate import validate_number as validate_number
|
|
34
|
+
from .validate import validate_rotation as validate_rotation
|
|
35
|
+
from .validate import validate_transform3x3 as validate_transform3x3
|
|
36
|
+
from .validate import validate_transform4x4 as validate_transform4x4
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Array casting functions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import numpy.typing as npt
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from pyvista_validation._typing import ArrayLike
|
|
12
|
+
from pyvista_validation._typing import NumberType
|
|
13
|
+
from pyvista_validation._typing import NumpyArray
|
|
14
|
+
from pyvista_validation._typing import _ArrayLikeOrScalar
|
|
15
|
+
from pyvista_validation._typing import _FiniteNestedList
|
|
16
|
+
from pyvista_validation._typing import _FiniteNestedTuple
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _cast_to_list(
|
|
20
|
+
arr: _ArrayLikeOrScalar[NumberType],
|
|
21
|
+
) -> NumberType | _FiniteNestedList[NumberType]:
|
|
22
|
+
"""Cast an array to a nested list.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
arr : float | ArrayLike[float]
|
|
27
|
+
Array to cast.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
list
|
|
32
|
+
List or nested list array.
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
return _cast_to_numpy(arr).tolist()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _cast_to_tuple(
|
|
39
|
+
arr: ArrayLike[NumberType],
|
|
40
|
+
) -> NumberType | _FiniteNestedTuple[NumberType]:
|
|
41
|
+
"""Cast an array to a nested tuple.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
arr : float | ArrayLike[float]
|
|
46
|
+
Array to cast.
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
tuple
|
|
51
|
+
Tuple or nested tuple array.
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
arr = _cast_to_numpy(arr).tolist()
|
|
55
|
+
|
|
56
|
+
def _to_tuple(s):
|
|
57
|
+
return tuple(_to_tuple(i) for i in s) if isinstance(s, list) else s
|
|
58
|
+
|
|
59
|
+
return _to_tuple(arr)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _cast_to_numpy(
|
|
63
|
+
arr: _ArrayLikeOrScalar[NumberType],
|
|
64
|
+
/,
|
|
65
|
+
*,
|
|
66
|
+
as_any: bool = True,
|
|
67
|
+
dtype: npt.DTypeLike | None = None,
|
|
68
|
+
copy: bool = False,
|
|
69
|
+
must_be_real: bool = False,
|
|
70
|
+
) -> NumpyArray[NumberType]:
|
|
71
|
+
"""Cast array to a NumPy ``ndarray``.
|
|
72
|
+
|
|
73
|
+
Object arrays are not allowed but the ``dtype`` is otherwise unchecked by default.
|
|
74
|
+
String arrays and complex numbers are therefore allowed.
|
|
75
|
+
|
|
76
|
+
.. warning::
|
|
77
|
+
|
|
78
|
+
Arrays intended for use with vtk should set ``must_be_real=True``
|
|
79
|
+
since ``numpy_to_vtk`` uses the array values directly without
|
|
80
|
+
checking for complex arrays.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
arr : float | ArrayLike[float]
|
|
85
|
+
Array to cast.
|
|
86
|
+
|
|
87
|
+
as_any : bool, default: True
|
|
88
|
+
Allow subclasses of ``np.ndarray`` to pass through without
|
|
89
|
+
making a copy.
|
|
90
|
+
|
|
91
|
+
dtype : npt.typing.DTypeLike, optional
|
|
92
|
+
The data-type of the returned array.
|
|
93
|
+
|
|
94
|
+
copy : bool, default: False
|
|
95
|
+
If ``True``, a copy of the array is returned. A copy is always
|
|
96
|
+
returned if the array:
|
|
97
|
+
|
|
98
|
+
* is a nested sequence
|
|
99
|
+
* is a subclass of ``np.ndarray`` and ``as_any`` is ``False``.
|
|
100
|
+
|
|
101
|
+
must_be_real : bool, default: True
|
|
102
|
+
Raise a ``TypeError`` if the array does not have real numbers, that is
|
|
103
|
+
its data type is not integer or floating.
|
|
104
|
+
|
|
105
|
+
Raises
|
|
106
|
+
------
|
|
107
|
+
ValueError
|
|
108
|
+
If input cannot be cast as a NumPy ``ndarray``.
|
|
109
|
+
TypeError
|
|
110
|
+
If an object array is created or if the data is not real numbers
|
|
111
|
+
and ``must_be_real`` is ``True``.
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
np.ndarray
|
|
116
|
+
NumPy ``ndarray``.
|
|
117
|
+
|
|
118
|
+
"""
|
|
119
|
+
try:
|
|
120
|
+
out = np.asanyarray(arr, dtype=dtype) if as_any else np.asarray(arr, dtype=dtype)
|
|
121
|
+
|
|
122
|
+
if copy and out is arr:
|
|
123
|
+
# we requested a copy but didn't end up with one
|
|
124
|
+
out = out.copy()
|
|
125
|
+
except ValueError as e:
|
|
126
|
+
msg = f'Input cannot be cast as {np.ndarray}.'
|
|
127
|
+
raise ValueError(msg) from e
|
|
128
|
+
if must_be_real and not issubclass(out.dtype.type, (np.floating, np.integer)):
|
|
129
|
+
msg = f'Array must have real numbers. Got dtype {out.dtype.type}'
|
|
130
|
+
raise TypeError(msg)
|
|
131
|
+
if out.dtype.kind == 'O':
|
|
132
|
+
msg = f'Object arrays are not supported. Got {arr} when casting to a NumPy array.'
|
|
133
|
+
raise TypeError(msg)
|
|
134
|
+
return out
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Lazily imported names from this package's optional dependencies.
|
|
2
|
+
|
|
3
|
+
VTK and SciPy are both optional and both slow to import, so their names are
|
|
4
|
+
resolved from their own submodules on first access and then cached in this
|
|
5
|
+
module's globals. Importing from ``vtkmodules`` rather than ``vtk`` keeps the
|
|
6
|
+
cost to the one submodule a name actually lives in.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import importlib
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from scipy.spatial.transform import Rotation
|
|
17
|
+
from vtkmodules.vtkCommonMath import vtkMatrix3x3
|
|
18
|
+
from vtkmodules.vtkCommonMath import vtkMatrix4x4
|
|
19
|
+
from vtkmodules.vtkCommonTransforms import vtkTransform
|
|
20
|
+
|
|
21
|
+
__all__ = ['Rotation', 'vtkMatrix3x3', 'vtkMatrix4x4', 'vtkTransform']
|
|
22
|
+
|
|
23
|
+
_MODULES = {
|
|
24
|
+
'Rotation': 'scipy.spatial.transform',
|
|
25
|
+
'vtkMatrix3x3': 'vtkmodules.vtkCommonMath',
|
|
26
|
+
'vtkMatrix4x4': 'vtkmodules.vtkCommonMath',
|
|
27
|
+
'vtkTransform': 'vtkmodules.vtkCommonTransforms',
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def __getattr__(name: str) -> Any:
|
|
32
|
+
"""Import a name from its optional dependency, caching it for next time."""
|
|
33
|
+
if name not in _MODULES:
|
|
34
|
+
msg = f'module {__name__!r} has no attribute {name!r}'
|
|
35
|
+
raise AttributeError(msg)
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
value: Any = getattr(importlib.import_module(_MODULES[name]), name)
|
|
39
|
+
except ModuleNotFoundError:
|
|
40
|
+
# No object of this type can exist without its package installed. A
|
|
41
|
+
# placeholder class is never an instance and still composes into the
|
|
42
|
+
# `Union` type aliases, unlike None or an empty tuple.
|
|
43
|
+
value = type(name, (), {})
|
|
44
|
+
|
|
45
|
+
globals()[name] = value # __getattr__ only runs on a miss, so this caches
|
|
46
|
+
return value
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Type aliases for type hints."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ._aliases import ArrayLike as ArrayLike
|
|
6
|
+
from ._aliases import MatrixLike as MatrixLike
|
|
7
|
+
from ._aliases import Number as Number
|
|
8
|
+
from ._aliases import RotationLike as RotationLike
|
|
9
|
+
from ._aliases import TransformLike as TransformLike
|
|
10
|
+
from ._aliases import VectorLike as VectorLike
|
|
11
|
+
from ._aliases import _ArrayLikeOrScalar as _ArrayLikeOrScalar
|
|
12
|
+
from ._array_like import NumberType as NumberType
|
|
13
|
+
from ._array_like import NumpyArray as NumpyArray
|
|
14
|
+
from ._array_like import _FiniteNestedList as _FiniteNestedList
|
|
15
|
+
from ._array_like import _FiniteNestedTuple as _FiniteNestedTuple
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Core type aliases."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Union
|
|
6
|
+
|
|
7
|
+
from pyvista_validation import _lazy_import
|
|
8
|
+
|
|
9
|
+
from ._array_like import NumberType
|
|
10
|
+
from ._array_like import _ArrayLike
|
|
11
|
+
from ._array_like import _ArrayLike1D
|
|
12
|
+
from ._array_like import _ArrayLike2D
|
|
13
|
+
|
|
14
|
+
Number = Union[int, float]
|
|
15
|
+
VectorLike = _ArrayLike1D[NumberType]
|
|
16
|
+
MatrixLike = _ArrayLike2D[NumberType]
|
|
17
|
+
ArrayLike = _ArrayLike[NumberType]
|
|
18
|
+
|
|
19
|
+
RotationLike = Union[MatrixLike[float], _lazy_import.vtkMatrix3x3, _lazy_import.Rotation]
|
|
20
|
+
TransformLike = Union[RotationLike, _lazy_import.vtkMatrix4x4, _lazy_import.vtkTransform]
|
|
21
|
+
|
|
22
|
+
# Undocumented alias - should be expanded in docs
|
|
23
|
+
_ArrayLikeOrScalar = Union[NumberType, ArrayLike[NumberType]]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Generic array-like type definitions.
|
|
2
|
+
|
|
3
|
+
Definitions here are loosely based on code in ``numpy._typing._array_like``.
|
|
4
|
+
Some key differences include:
|
|
5
|
+
|
|
6
|
+
- Some npt._array_like definitions explicitly support dual-types for
|
|
7
|
+
handling Python and NumPy scalar data types separately.
|
|
8
|
+
Here, only a single generic type is used for simplicity.
|
|
9
|
+
|
|
10
|
+
- The npt._array_like definitions use a recursive _NestedSequence protocol.
|
|
11
|
+
Here, finite sequences are used instead.
|
|
12
|
+
|
|
13
|
+
- The npt._array_like definitions use a generic _SupportsArray protocol.
|
|
14
|
+
Here, we use ``ndarray`` directly.
|
|
15
|
+
|
|
16
|
+
- The npt._array_like definitions include scalar types (for example, float, int).
|
|
17
|
+
Here they are excluded (that is, scalars are not considered to be arrays).
|
|
18
|
+
|
|
19
|
+
- The npt._array_like TypeVar is bound to np.generic. Here, the
|
|
20
|
+
TypeVar is bound to a subset of numeric types only.
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from collections.abc import Sequence
|
|
27
|
+
from typing import TypeVar
|
|
28
|
+
from typing import Union
|
|
29
|
+
|
|
30
|
+
import numpy as np
|
|
31
|
+
import numpy.typing as npt
|
|
32
|
+
|
|
33
|
+
# Define numeric types
|
|
34
|
+
NumberType = TypeVar(
|
|
35
|
+
'NumberType',
|
|
36
|
+
bound=np.floating | np.integer | np.bool_ | float | int | bool,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Create a copy of the typevar which can be used for annotating a second variable.
|
|
40
|
+
# Its definition should be identical to `NumberType`
|
|
41
|
+
_NumberType = TypeVar( # noqa: PYI018
|
|
42
|
+
'_NumberType',
|
|
43
|
+
bound=np.floating | np.integer | np.bool_ | float | int | bool,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
NumpyArray = npt.NDArray[NumberType]
|
|
47
|
+
|
|
48
|
+
_FiniteNestedList = (
|
|
49
|
+
list[NumberType]
|
|
50
|
+
| list[list[NumberType]]
|
|
51
|
+
| list[list[list[NumberType]]]
|
|
52
|
+
| list[list[list[list[NumberType]]]]
|
|
53
|
+
)
|
|
54
|
+
_FiniteNestedTuple = (
|
|
55
|
+
tuple[NumberType]
|
|
56
|
+
| tuple[tuple[NumberType]]
|
|
57
|
+
| tuple[tuple[tuple[NumberType]]]
|
|
58
|
+
| tuple[tuple[tuple[tuple[NumberType]]]]
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
_ArrayLike1D = Union[
|
|
62
|
+
NumpyArray[NumberType],
|
|
63
|
+
Sequence[NumberType],
|
|
64
|
+
Sequence[NumpyArray[NumberType]],
|
|
65
|
+
]
|
|
66
|
+
_ArrayLike2D = Union[
|
|
67
|
+
NumpyArray[NumberType],
|
|
68
|
+
Sequence[Sequence[NumberType]],
|
|
69
|
+
Sequence[Sequence[NumpyArray[NumberType]]],
|
|
70
|
+
]
|
|
71
|
+
_ArrayLike3D = Union[
|
|
72
|
+
NumpyArray[NumberType],
|
|
73
|
+
Sequence[Sequence[Sequence[NumberType]]],
|
|
74
|
+
Sequence[Sequence[Sequence[NumpyArray[NumberType]]]],
|
|
75
|
+
]
|
|
76
|
+
_ArrayLike4D = Union[
|
|
77
|
+
NumpyArray[NumberType],
|
|
78
|
+
Sequence[Sequence[Sequence[Sequence[NumberType]]]],
|
|
79
|
+
Sequence[Sequence[Sequence[Sequence[NumpyArray[NumberType]]]]],
|
|
80
|
+
]
|
|
81
|
+
_ArrayLike = Union[
|
|
82
|
+
_ArrayLike1D[NumberType],
|
|
83
|
+
_ArrayLike2D[NumberType],
|
|
84
|
+
_ArrayLike3D[NumberType],
|
|
85
|
+
_ArrayLike4D[NumberType],
|
|
86
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '0.1.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 0)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = 'g623faa28b'
|