stricto 0.0.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.
Files changed (56) hide show
  1. stricto-0.0.2/.github/workflows/pylint.yml +23 -0
  2. stricto-0.0.2/.github/workflows/release.yml +27 -0
  3. stricto-0.0.2/.github/workflows/test.yml +25 -0
  4. stricto-0.0.2/.gitignore +5 -0
  5. stricto-0.0.2/LICENSE +21 -0
  6. stricto-0.0.2/PKG-INFO +417 -0
  7. stricto-0.0.2/README.md +381 -0
  8. stricto-0.0.2/htmlcov/.gitignore +2 -0
  9. stricto-0.0.2/htmlcov/coverage_html.js +624 -0
  10. stricto-0.0.2/htmlcov/d_a44f0ac069e85531___init___py.html +97 -0
  11. stricto-0.0.2/htmlcov/d_a44f0ac069e85531_test_bool_py.html +160 -0
  12. stricto-0.0.2/htmlcov/d_a44f0ac069e85531_test_dict_py.html +398 -0
  13. stricto-0.0.2/htmlcov/d_a44f0ac069e85531_test_error_py.html +136 -0
  14. stricto-0.0.2/htmlcov/d_a44f0ac069e85531_test_float_py.html +276 -0
  15. stricto-0.0.2/htmlcov/d_a44f0ac069e85531_test_in_py.html +183 -0
  16. stricto-0.0.2/htmlcov/d_a44f0ac069e85531_test_int_py.html +294 -0
  17. stricto-0.0.2/htmlcov/d_a44f0ac069e85531_test_list_py.html +405 -0
  18. stricto-0.0.2/htmlcov/d_a44f0ac069e85531_test_string_py.html +234 -0
  19. stricto-0.0.2/htmlcov/d_f495c9c796458a5c___init___py.html +110 -0
  20. stricto-0.0.2/htmlcov/d_f495c9c796458a5c_bool_py.html +125 -0
  21. stricto-0.0.2/htmlcov/d_f495c9c796458a5c_dict_py.html +325 -0
  22. stricto-0.0.2/htmlcov/d_f495c9c796458a5c_error_py.html +147 -0
  23. stricto-0.0.2/htmlcov/d_f495c9c796458a5c_float_py.html +133 -0
  24. stricto-0.0.2/htmlcov/d_f495c9c796458a5c_generic_py.html +498 -0
  25. stricto-0.0.2/htmlcov/d_f495c9c796458a5c_in_type_py.html +135 -0
  26. stricto-0.0.2/htmlcov/d_f495c9c796458a5c_int_py.html +138 -0
  27. stricto-0.0.2/htmlcov/d_f495c9c796458a5c_list_py.html +433 -0
  28. stricto-0.0.2/htmlcov/d_f495c9c796458a5c_string_py.html +137 -0
  29. stricto-0.0.2/htmlcov/d_f495c9c796458a5c_time_stamp_py.html +124 -0
  30. stricto-0.0.2/htmlcov/favicon_32.png +0 -0
  31. stricto-0.0.2/htmlcov/index.html +228 -0
  32. stricto-0.0.2/htmlcov/keybd_closed.png +0 -0
  33. stricto-0.0.2/htmlcov/keybd_open.png +0 -0
  34. stricto-0.0.2/htmlcov/status.json +1 -0
  35. stricto-0.0.2/htmlcov/style.css +309 -0
  36. stricto-0.0.2/pyproject.toml +24 -0
  37. stricto-0.0.2/requirements.txt +0 -0
  38. stricto-0.0.2/stricto/__init__.py +13 -0
  39. stricto-0.0.2/stricto/bool.py +28 -0
  40. stricto-0.0.2/stricto/dict.py +228 -0
  41. stricto-0.0.2/stricto/error.py +50 -0
  42. stricto-0.0.2/stricto/float.py +36 -0
  43. stricto-0.0.2/stricto/generic.py +401 -0
  44. stricto-0.0.2/stricto/in_type.py +38 -0
  45. stricto-0.0.2/stricto/int.py +41 -0
  46. stricto-0.0.2/stricto/list.py +336 -0
  47. stricto-0.0.2/stricto/string.py +40 -0
  48. stricto-0.0.2/tests/__init__.py +0 -0
  49. stricto-0.0.2/tests/test_bool.py +63 -0
  50. stricto-0.0.2/tests/test_dict.py +301 -0
  51. stricto-0.0.2/tests/test_error.py +39 -0
  52. stricto-0.0.2/tests/test_float.py +179 -0
  53. stricto-0.0.2/tests/test_in.py +86 -0
  54. stricto-0.0.2/tests/test_int.py +197 -0
  55. stricto-0.0.2/tests/test_list.py +308 -0
  56. stricto-0.0.2/tests/test_string.py +137 -0
@@ -0,0 +1,23 @@
1
+ name: Pylint
2
+
3
+ on: [ push, pull_request ]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ python-version: ["3.10"]
11
+ steps:
12
+ - uses: actions/checkout@v3
13
+ - name: Set up Python ${{ matrix.python-version }}
14
+ uses: actions/setup-python@v3
15
+ with:
16
+ python-version: ${{ matrix.python-version }}
17
+ - name: Install dependencies
18
+ run: |
19
+ python -m pip install --upgrade pip
20
+ pip install pylint
21
+ - name: Analysing the code with pylint
22
+ run: |
23
+ pylint $(git ls-files '*.py')
@@ -0,0 +1,27 @@
1
+ name: Build_Package
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ python-version: ["3.10"]
13
+ steps:
14
+ - uses: actions/checkout@v3
15
+ - name: Set up Python ${{ matrix.python-version }}
16
+ uses: actions/setup-python@v3
17
+ with:
18
+ python-version: ${{ matrix.python-version }}
19
+ - name: Install dependencies
20
+ run: |
21
+ python -m pip install --upgrade pip
22
+ python3 -m pip install --upgrade build
23
+ python3 -m pip install --upgrade twine
24
+ - name: uploading package
25
+ run: |
26
+ python3 -m build
27
+ python3 -m twine upload --username ${{ secrets.PYPI_LOGIN }} --password ${{ secrets.PYPI_PASSWORD }} dist/*
@@ -0,0 +1,25 @@
1
+ name: CodeCov
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ python-version: ["3.10"]
11
+ steps:
12
+ - uses: actions/checkout@v3
13
+ - name: Set up Python ${{ matrix.python-version }}
14
+ uses: actions/setup-python@v3
15
+ with:
16
+ python-version: ${{ matrix.python-version }}
17
+ - name: Install dependencies
18
+ run: |
19
+ python -m pip install --upgrade pip
20
+ pip install coverage
21
+ - name: run tests and coverage
22
+ run: |
23
+ coverage run -m unittest
24
+ - name: Coverage Badge
25
+ uses: tj-actions/coverage-badge-py@v2
@@ -0,0 +1,5 @@
1
+ *workspace
2
+ __pycache__/
3
+ *.pyc
4
+ dist/
5
+ .coverage
stricto-0.0.2/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Bertrand Wallrich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
stricto-0.0.2/PKG-INFO ADDED
@@ -0,0 +1,417 @@
1
+ Metadata-Version: 2.3
2
+ Name: stricto
3
+ Version: 0.0.2
4
+ Summary: Strict Dict (json) with schema validation embedded
5
+ Project-URL: GitHub, https://github.com/NiziL/esnpy
6
+ Project-URL: Homepage, https://github.com/bwallrich/stricto
7
+ Project-URL: Issues, https://github.com/bwallrich/stricto/issues
8
+ Author-email: Bertrand Wallrich <Bertrand.Wallrich@inria.fr>
9
+ License: MIT License
10
+
11
+ Copyright (c) 2023 Bertrand Wallrich
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
30
+ License-File: LICENSE
31
+ Classifier: License :: OSI Approved :: MIT License
32
+ Classifier: Operating System :: OS Independent
33
+ Classifier: Programming Language :: Python :: 3
34
+ Requires-Python: >=3.8
35
+ Description-Content-Type: text/markdown
36
+
37
+ # stricto
38
+
39
+
40
+
41
+ ![release](https://img.shields.io/github/v/release/bwallrich/stricto.svg?label=latest)
42
+
43
+
44
+ ![pylint](https://img.shields.io/github/actions/workflow/status/bwallrich/stricto/pylint.yml?label=linter) ![test](https://img.shields.io/github/actions/workflow/status/bwallrich/stricto/test.yml?label=test)
45
+
46
+ Strict json structure with schema validation
47
+
48
+ The way to use is very simple, see [Quickstart](#quickstart) for a basic setup.
49
+
50
+ The main difference with [jsonschema](https://github.com/python-jsonschema/jsonschema) is that the schema is directly in types of data. You don't have to *validate* them.
51
+
52
+
53
+ ## Installation
54
+
55
+ ```bash
56
+ pip install git+https://github.com/bwallrich/stricto
57
+ ```
58
+
59
+ ## Quickstart
60
+
61
+ ```python
62
+ from stricto import Dict, Int, String, List
63
+
64
+ a=Dict({
65
+ "name" : String(),
66
+ "address" : Dict({
67
+ "num" : Int(),
68
+ "street" : String()
69
+ }),
70
+ "nicknames" : List( String() )
71
+ })
72
+
73
+
74
+ a.set({
75
+ "name" : "Edward",
76
+ "address" : {
77
+ "num" : 22,
78
+ "street" : "acacia avenue"
79
+ },
80
+ "nicknames" : [ "Ed" ]
81
+ })
82
+
83
+
84
+ print(a.address.num) # 22
85
+ print(a.address) # { "num" : 22, "street" : "acacia avenue" }
86
+
87
+ a.name = 666 # -> raise a typeError (must be a string)
88
+
89
+ print (a) # { "name" : "Edward", ... }
90
+
91
+ a.nicknames.append(666) # -> raise a typeError (must be a string)
92
+ a.nicknames.append("Eddy")
93
+ a.nickname[1] # -> Eddy
94
+
95
+ b=a # b is a reference on a
96
+ c=a.copy() # c is a different object : c is a copy
97
+
98
+ c == b # return True (you can test and do operators directly on objects)
99
+ b.nicknames.pop()
100
+ c == b # return False
101
+ ```
102
+
103
+ ## Basic types
104
+
105
+ All basic class from python are implemented in ```stricto```.
106
+
107
+ | python class | type in stricto |
108
+ | - | - |
109
+ | bool | Bool() |
110
+ | int | Int() |
111
+ | float | Float() |
112
+ | string | String() |
113
+ | list | List() |
114
+ | dict | Dict() |
115
+ | | In() |
116
+
117
+ ```python
118
+ # example
119
+ from stricto import Dict, Int
120
+
121
+ a = Int()
122
+ a.set(22) # -> ok
123
+ a.set(23.1) # raise an error
124
+ a.set("the number of the beast") # raise an error
125
+
126
+ # WARNING
127
+ a = "the number of the beast" # works ! the affectation of "a" change. Now it is a string. This is python.
128
+
129
+ # Inside a Dict().
130
+ test=Dict({
131
+ "a" : Int()
132
+ })
133
+
134
+ test.a = 22 # -> ok
135
+ test.a = 23.1 # raise an error
136
+ test.a = "the number of the beast" # raise an error
137
+
138
+ ```
139
+
140
+ ## json
141
+
142
+
143
+ use ```.get_value()``` to extract a dict from a Dict and do the *json.dumps* like usual.
144
+
145
+
146
+ ```python
147
+ # example
148
+ from stricto import Int, List, String, Dict, Error
149
+ import json
150
+
151
+ model={
152
+ "b" : Int(),
153
+ "e" : List( String())
154
+ }
155
+ a=Dict(model)
156
+ b=Dict(model)
157
+ a.set({ "b" : 1, "e" : [ "aa", "bb"]})
158
+
159
+ sa = json.dumps(a.get_value()) # json dumps
160
+ b.set( json.loads(sa) )
161
+ b == a # return True
162
+ ```
163
+
164
+ ## Types and options
165
+
166
+ ### All types
167
+
168
+ available options for all types ares :
169
+
170
+ | Option | Default | Description |
171
+ | - | - | - |
172
+ | ```notNone=True\|False``` | False | cannot be **None** |
173
+ | ```required=True\|False``` | False | similar to ```notNone``` |
174
+ | ```description="whatever you want"``` | None | a description of this object |
175
+ | ```default=666``` | None | the default value |
176
+ | ```in=[ 1, 2, 3, 5 ]\|func``` | None | the value must be one of those elements |
177
+ | ```union=[ 1, 2, 3, 5 ]\|func``` | None | similar to ```in``` |
178
+ | ```transform=func``` | None | a [function](#functions) to [transform](#transform) the value before setting it |
179
+ | ```constraint=func``` | None | a [constraints](#constraints) to check the value before setting it |
180
+ | ```constraints=[func]``` | None | a list of [constraints](#constraints) to check the value before setting it |
181
+ | ```onchange=func``` | None | a [onchange](#onchange) function trigged when the value change |
182
+ | ```onChange=func``` | None | similar to ```onchange``` |
183
+ | ```set=func``` | None | a read only value, calculated from other .See [set or compute function](#set-or-compute) |
184
+ | ```compute=func``` | None | similar to ```set``` |
185
+ | ```exists=func``` | True | a function to say if the object "exists", depending on values from other attributs. See [exists](#exists) for details |
186
+
187
+ See [functions](#functions) for mor details and examples how to use them.
188
+
189
+ ### Int()
190
+
191
+ ```Int( options )``` is for integer.
192
+
193
+ ```Int( options )``` use [generic options](#all-types).
194
+
195
+ available specific options for Int() ares :
196
+
197
+ | Option | Default | Description |
198
+ | - | - | - |
199
+ | ```min=``` | None | minimum value |
200
+ | ```minimum=21``` | None | similar to ```min``` |
201
+ | ```max=99``` | None | maximum value |
202
+ | ```maximum=99``` | None | similar to ```max=99``` |
203
+
204
+ ```python
205
+ # example
206
+ from stricto import Dict, Int, String
207
+
208
+ client = Dict{
209
+ "age" : Int( min=21, max=120)
210
+ }
211
+
212
+ client.age = 12 # -> raise an error
213
+ client.age = 120 # -> Ok
214
+
215
+ newAge = client.age+1 # -> raise an Error ( > max ) newAge is implicitly an Int( min=21, max=120))
216
+ newAge = 1+client.age # -> Ok (newAge is implicitly an int)
217
+ ```
218
+
219
+ ### String()
220
+
221
+ ```String( options )``` is for strings.
222
+
223
+ ```String( options )``` use [generic options](#all-types).
224
+
225
+ available specific options for Int() ares :
226
+
227
+ | Option | Default | Description |
228
+ | - | - | - |
229
+ | ```pattern=regexp``` | None | must match this regexp |
230
+ | ```patterns=[reg1, reg2]``` | None | must match all regexps |
231
+ | ```regexp=``` | None | similar to ```pattern``` |
232
+
233
+ Examples
234
+
235
+ ```python
236
+ a=String( pattern='^A' )
237
+ a.set('Foo') # -> raise an error
238
+ a.set('AZERTY') # OK
239
+
240
+ # list of regexp
241
+ a=String( patterns=[ '^A', r'.*Z$' ] )
242
+ a.set('Allo') # -> raise an error
243
+ a.set('AtoZ') # OK
244
+
245
+ # function return a regexp
246
+ a=String( pattern=lambda self, value, root : r'.*Z$')
247
+ a.set('Allo') # -> raise an error
248
+ a.set('AtoZ') # OK
249
+
250
+ ```
251
+
252
+ ### In()
253
+
254
+ ```In( [ Array of types ] )``` is not a type, but an **union** of diffferent types.
255
+
256
+ ```In( options )``` use [generic options](#all-types).
257
+
258
+
259
+ ```python
260
+ # example
261
+ from stricto import In, Int, String
262
+
263
+ a = In( [ Int(), String() ] )
264
+
265
+ a.set("hello") # -> OK
266
+ a.count('h') # -> return 1
267
+
268
+ a.set(12) # -> OK
269
+ a.bit_length() # -> return 4
270
+ a.count('h') # -> return None
271
+
272
+ a.set(3.14) # -> raise an error
273
+ ```
274
+
275
+ ## Functions
276
+
277
+ a ```func``` can return a value to adapt the result. It can bee a lambda too.
278
+
279
+ ### transform
280
+
281
+ Please see [transform function](#all-types)
282
+
283
+ ```python
284
+ # example
285
+ from stricto import Dict, Int, String
286
+
287
+ def upper(value, o):
288
+ """
289
+ transform the value into upper
290
+
291
+ value : the current value given ("worldcompagny" in this example).
292
+ o : the full object
293
+ """
294
+ return value.upper()
295
+
296
+ company=Dict({
297
+ "name" : String( transform=upper ),
298
+ })
299
+
300
+ company.name="worldcompagny"
301
+ print(company.name) # -> "WORLDCOMPAGNY"
302
+ ```
303
+
304
+ ### set or compute
305
+
306
+ ```python
307
+ # example
308
+ from stricto import Dict, Int, String
309
+
310
+ a=Dict({
311
+ "b" : Int( default = 0, set=lambda o: o.c+1 ),
312
+ "d" : Int( default = 0, set=lambda o: o.b+1 ),
313
+ "c" : Int( ),
314
+ })
315
+
316
+ # "b" and "d" cannot be modified by hand. the are recalculated every time another value
317
+ # change in the Dict.
318
+
319
+ a.b = 3 # -> raise an error
320
+
321
+ a.c = 2
322
+ print(a.b) # -> 3
323
+ print(a.d) # -> 4
324
+ ```
325
+
326
+ ### constraints
327
+
328
+ ```python
329
+ # example
330
+ from stricto import Dict, Int, String
331
+
332
+
333
+
334
+ def check_pair(value, o): # pylint: disable=unused-argument
335
+ """
336
+ return true if pair
337
+ """
338
+ return not value % 2
339
+
340
+ a=Dict({
341
+ "b" : Int( default = 0, constraint=check_pair ), # check before setting
342
+ "d" : Int( constraint=lambda value, o : not value % 2 ), # same as above, with a lambda
343
+ "c" : Int( constraints=[ check_pair ] ), # A list of constraints
344
+ })
345
+
346
+ a.b = 2 # OK
347
+ a.c = 3 # -> raise an error
348
+ ```
349
+
350
+
351
+
352
+ ### onchange
353
+
354
+ ```python
355
+ # example
356
+ from stricto import Dict, Int, String
357
+
358
+
359
+
360
+ def change_test(old_value, value, o): # pylint: disable=unused-argument
361
+ """
362
+ just a change option
363
+ old_value -> The previous value
364
+ value -> the new one
365
+ o -> the root object = a in our example
366
+ """
367
+ print(f"The value of b as changed from {old_value} to {value}")
368
+
369
+ a=Dict({
370
+ "b" : Int( default = 0, onchange=change_test )
371
+ })
372
+
373
+ a.b = 2 # -> output "The value of b as changed from 0 to 2"
374
+ a.b = 3-1 # -> nothing displayed
375
+ ```
376
+
377
+ ### exists
378
+
379
+ A function wich must return ```True|False``` to say if this key exists.
380
+
381
+ ```python
382
+ # example
383
+ from stricto import Dict, Int, String
384
+
385
+ def check_if_female(value, o):
386
+ """
387
+ return true if Female
388
+ """
389
+ if o.gender == "Male":
390
+ return False
391
+ return True
392
+
393
+ cat=Dict({
394
+ "name" : String(),
395
+ "gender" : String( default = 'Male', in=[ 'Male', 'Female' ]),
396
+ "female_infos" : Dict(
397
+ {
398
+ "number_of_litter" : Int(default=0, required=True)
399
+ # ... some other attributes
400
+
401
+ }, exists=check_if_female )
402
+ })
403
+
404
+ a.set({ "name" : "Felix", "gender" : "Male" }
405
+ a.female_infos # -> None
406
+ a.female_infos.number_of_litter = 2 # -> Raise an Error
407
+
408
+ a.gender = "Female"
409
+ a.female_infos.number_of_litter = 2 # -> Ok
410
+ a.female_infos # -> { "number_of_litter" : 2 }
411
+ ```
412
+
413
+ ## Tests
414
+
415
+ ```bash
416
+ python -m unittest
417
+ ```