You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
*Validating types for python - use `isinstance()` to validate both type and value.*
8
8
9
-
`vtypes` is a small library to define "validating types". These types can be used to add value validation on top of type checking anywhere where you usually rely on `isinstance()`. This can in particular be used to make validation schemas simpler and more readable, for example used in [`pyfields`](https://smarie.github.io/python-pyfields/#3-autofields).
9
+
`vtypes` is a small library to define "validating types". These types can be used to **add value validation on top of type checking** anywhere where you usually rely on `isinstance()`. This can in particular be used to make validation schemas simpler and more readable, for example used in [`pyfields`](https://smarie.github.io/python-pyfields/#3-autofields).
10
10
11
11
12
12
## Installing
@@ -19,7 +19,11 @@
19
19
20
20
### a - basics
21
21
22
-
You create a `VType` by combining one or several base types with optional value validators following the [`valid8` simple syntax](https://smarie.github.io/python-valid8/validation_funcs/c_simple_syntax/).
22
+
A `VType` is a combination of :
23
+
24
+
- a type **name**, for example `'PositiveInt'`
25
+
- one or several **base types**: for example `int`.
26
+
- one or several **validators**: for example `lambda x: x >= 0`
23
27
24
28
For example we can create a positive int:
25
29
@@ -29,37 +33,124 @@ from vtypes import vtype
29
33
PositiveInt = vtype('PositiveInt', int, {'should be positive': lambdax: x >=0})
30
34
```
31
35
32
-
`isinstance` works as expected:
36
+
A `VType`'s main purpose is to behave like a type (therefore to be compliant with `isinstance`) and to validate both type and values at the same time when `isinstance` is called:
33
37
34
38
```python
35
39
assertisinstance(1, PositiveInt)
36
40
assertnotisinstance(-1, PositiveInt)
37
41
```
38
42
39
-
You can also get a more detailed error if you wish:
43
+
### b - goodies
44
+
45
+
In addition to this primary feature, a `VType` provides a few handy methods:
46
+
47
+
- detailed error messages with `validate` (note: a variable name should be provided, for example `'size'`).
InvalidValue: should be positive. Function [<lambda>] returned [False] for value -1.
67
+
from vtypes import is_vtype
68
+
69
+
assert is_vtype(PositiveInt)
70
+
assertnot is_vtype(int)
71
+
assertnot is_vtype(1)
45
72
```
46
73
47
-
### b - composition
74
+
### c - validators syntax
75
+
76
+
There are many ways to declare validators:
77
+
78
+
- a single callable
79
+
80
+
- a single tuple`(<callable>, <error_msg>)`, `(<callable>, <failure_type>)`or`(<callable>, <error_msg>, <failure_type>)`
81
+
82
+
- a list of such callables and tuples
83
+
84
+
- a **dictionary** where keys are `<callable>`, `<error_msg>`, or`<failure_type>`and values are one or two (tuple) of such elements. This is at least for the author, the most intuitive and readable style:
85
+
86
+
```python
87
+
ConstrainedInt = vtype('ConstrainedInt', int,
88
+
{'should be positive': lambdax: x >=0,
89
+
'should be a multiple of 3': lambdax: x %3})
90
+
```
91
+
92
+
Note that this syntax is [`valid8` simple syntax](https://smarie.github.io/python-valid8/validation_funcs/c_simple_syntax/).
93
+
94
+
If you wish to create even more compact callables, you may wish to look at [`mini_lambda`](https://smarie.github.io/python-mini-lambda/).
95
+
96
+
### d - composition
97
+
98
+
You can combine types, for example a nonempty string can be obtained by mixing `NonEmpty`and`str`:
99
+
100
+
```python
101
+
NonEmpty= vtype('NonEmpty', (), {'should be non empty': lambdax: len(x) >0})
102
+
"""A VType describing non-empty containers, with strictly positive length."""
An alternate way to define `VType`s is to define a python class inheriting from`VType`.
112
+
113
+
- the validators can be provided as a class member named `__validators__`
114
+
115
+
- the base type(s) can be either provided as superclass(es), oras a class member named `__type__`.
116
+
117
+
This provides an alternate style that developers might find handy in particular for entering docstrings andfor making `VTypes` composition appear "just like normal python inheritance".
118
+
119
+
```python
120
+
from vtypes import VType
121
+
122
+
class NonEmpty(VType):
123
+
"""A VType describing non-empty containers, with strictly positive length."""
124
+
__validators__= {'should be non empty': lambdax: len(x) >0}
125
+
126
+
class NonEmptyStr(NonEmpty, str):
127
+
"""A VType for non-empty strings"""
128
+
129
+
class AlternateNonEmptyStr(VType):
130
+
"""A VType for non-empty strings - alternate style"""
131
+
__type__= NonEmpty, str
132
+
```
48
133
49
-
You can combine types, for example a positive int can be obtained by mixing `Positive`and`int`:
134
+
The vtypes work as expected:
50
135
51
136
```python
52
-
TODO
137
+
assertisinstance('hoho', NonEmptyStr)
138
+
assertnotisinstance('', NonEmptyStr)
139
+
assertnotisinstance(1, NonEmptyStr)
53
140
```
54
141
55
142
56
143
## Main features
57
144
58
-
***TODO**
145
+
* Validate both typeand value with`isinstance`, thanks to easy-to-write "validating types"
146
+
*`has_valid_type`and`has_valid_value` methods provided for easy auditing, as well as`is_vtype`
147
+
* Validation syntax fully compliant with`valid8`. Compliant error message available through a `validate()` method
148
+
* v-types are composable so that creating a library of reusable elements is straightforward (note: should we provide one in this library based on `valid8` [library](https://smarie.github.io/python-valid8/validation_funcs/b_base_validation_lib/) ?)
149
+
* Alternate class-style available to perform composition using inheritance, and write docstrings more easily.
59
150
60
151
## See Also
61
152
62
-
* [`checktypes`](https://gitlab.com/yahya-abou-imran/checktypes), that was a great source of inspiration. The only reason forrecreating something new was the capability to use the `valid8` syntax for validators (as well as its standardized exceptions).
153
+
* [`checktypes`](https://gitlab.com/yahya-abou-imran/checktypes), that was a great source of inspiration. The only reason I ended up recreating something new a couple years after discovering it, was that I really wanted to leverage the `valid8` syntax for validators (as well as its standardized exceptions).
63
154
64
155
*Do you like this library ? You might also like [my other python libraries](https://github.com/smarie/OVERVIEW#python)*
0 commit comments