backo 0.1.2__tar.gz → 0.2.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.
- {backo-0.1.2 → backo-0.2.0}/.pylintrc +1 -1
- {backo-0.1.2 → backo-0.2.0}/CHANGELOG.md +4 -0
- {backo-0.1.2 → backo-0.2.0}/PKG-INFO +3 -3
- {backo-0.1.2 → backo-0.2.0}/README.md +1 -1
- {backo-0.1.2 → backo-0.2.0}/backo/__init__.py +4 -1
- {backo-0.1.2 → backo-0.2.0}/backo/collection.py +5 -3
- {backo-0.1.2 → backo-0.2.0}/backo/file/file.py +47 -7
- {backo-0.1.2 → backo-0.2.0}/backo/file/file_blob_connector.py +6 -7
- {backo-0.1.2 → backo-0.2.0}/backo/file/file_connector.py +8 -2
- {backo-0.1.2 → backo-0.2.0}/backo/file/file_system_connector.py +9 -7
- {backo-0.1.2 → backo-0.2.0}/backo/item.py +16 -10
- {backo-0.1.2 → backo-0.2.0}/backo/meta_data_handler.py +6 -5
- {backo-0.1.2 → backo-0.2.0}/backo/patch.py +16 -1
- backo-0.2.0/backo/ref.py +411 -0
- backo-0.1.2/backo/reference.py → backo-0.2.0/backo/refslist.py +117 -410
- {backo-0.1.2 → backo-0.2.0}/pyproject.toml +2 -2
- {backo-0.1.2 → backo-0.2.0}/requirements.txt +1 -1
- {backo-0.1.2 → backo-0.2.0}/tests/test_file.py +9 -13
- {backo-0.1.2 → backo-0.2.0}/tests/test_migrations.py +3 -1
- {backo-0.1.2 → backo-0.2.0}/tests/test_reference.py +2 -2
- {backo-0.1.2 → backo-0.2.0}/tests/test_routes.py +1 -1
- {backo-0.1.2 → backo-0.2.0}/tests/test_selections.py +1 -1
- {backo-0.1.2 → backo-0.2.0}/.github/workflows/pylint.yml +0 -0
- {backo-0.1.2 → backo-0.2.0}/.github/workflows/release.yml +0 -0
- {backo-0.1.2 → backo-0.2.0}/.github/workflows/test.yml +0 -0
- {backo-0.1.2 → backo-0.2.0}/.gitignore +0 -0
- {backo-0.1.2 → backo-0.2.0}/.readthedocs.yaml +0 -0
- {backo-0.1.2 → backo-0.2.0}/CONTRIBUTING.md +0 -0
- {backo-0.1.2 → backo-0.2.0}/LICENSE +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/action.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/api_toolbox.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/backoffice.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/collection_addon.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/current_user.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/db_connector.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/db_mongo_connector.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/db_yml_connector.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/error.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/file/blob_file.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/log.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/loop_path.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/migration_report.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/request_decorators.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/selection.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/status.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/transaction.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/backo/view.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/docs/Makefile +0 -0
- {backo-0.1.2 → backo-0.2.0}/docs/make.bat +0 -0
- {backo-0.1.2 → backo-0.2.0}/docs/requirements.txt +0 -0
- {backo-0.1.2 → backo-0.2.0}/docs/source/api_reference.rst +0 -0
- {backo-0.1.2 → backo-0.2.0}/docs/source/conf.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/docs/source/errors.rst +0 -0
- {backo-0.1.2 → backo-0.2.0}/docs/source/index.rst +0 -0
- {backo-0.1.2 → backo-0.2.0}/docs/source/readme.rst +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/media_library/README.md +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/media_library/__init__.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/media_library/backoffice.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/media_library/collections_set/__init__.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/media_library/collections_set/books.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/media_library/collections_set/users.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/media_library/migration.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/media_library/tests.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/nationality/README.md +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/nationality/__init__.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/nationality/backoffice.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/nationality/collections_set/__init__.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/nationality/collections_set/countries.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/nationality/collections_set/db_country_connector.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/nationality/collections_set/people.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/examples/nationality/tests.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/tests/__init__.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/tests/test_action.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/tests/test_api_toolbox.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/tests/test_crud.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/tests/test_current_user.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/tests/test_log.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/tests/test_meta.py +0 -0
- {backo-0.1.2 → backo-0.2.0}/tests/test_mongo.py +0 -0
|
@@ -28,7 +28,7 @@ ignore-imports=no
|
|
|
28
28
|
[MESSAGES CONTROL]
|
|
29
29
|
disable =
|
|
30
30
|
import-error,
|
|
31
|
-
|
|
31
|
+
cyclic-import, # due to Ref and RefsList mutual import
|
|
32
32
|
wrong-import-position,
|
|
33
33
|
dangerous-default-value,
|
|
34
34
|
super-init-not-called, # Bug ?
|
|
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [0.2.0] 2026-06-01
|
|
9
|
+
* Internal
|
|
10
|
+
* Refactoring to follow stricto 0.1.x to 0.2.0
|
|
11
|
+
|
|
8
12
|
## [0.1.2] 2026-04-29
|
|
9
13
|
* Feature
|
|
10
14
|
* Files management with File() / BlobFile() objects & co, with documentations, tests.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: backo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Back office low code
|
|
5
5
|
Project-URL: GitHub, https://github.com/bwallrich/backo
|
|
6
6
|
Project-URL: Homepage, https://github.com/bwallrich/backo
|
|
@@ -37,7 +37,7 @@ Requires-Dist: flask
|
|
|
37
37
|
Requires-Dist: pyjwt
|
|
38
38
|
Requires-Dist: python-magic
|
|
39
39
|
Requires-Dist: pyyaml
|
|
40
|
-
Requires-Dist: stricto>=0.
|
|
40
|
+
Requires-Dist: stricto>=0.2.0
|
|
41
41
|
Description-Content-Type: text/markdown
|
|
42
42
|
|
|
43
43
|
|
|
@@ -1169,7 +1169,7 @@ Ask the backoffice the current meta informations for this collection object.
|
|
|
1169
1169
|
"type": ty,
|
|
1170
1170
|
"type_short" : re.sub(".*\.|\'>", '', ty),
|
|
1171
1171
|
"description": self.get_as_string(self._description),
|
|
1172
|
-
"required": self.get_as_string(self.
|
|
1172
|
+
"required": self.get_as_string(self._required),
|
|
1173
1173
|
"in": self.get_as_string(self._union),
|
|
1174
1174
|
"constraints": self.get_as_string(self._constraints),
|
|
1175
1175
|
"default": self.get_as_string(self._default),
|
|
@@ -1127,7 +1127,7 @@ Ask the backoffice the current meta informations for this collection object.
|
|
|
1127
1127
|
"type": ty,
|
|
1128
1128
|
"type_short" : re.sub(".*\.|\'>", '', ty),
|
|
1129
1129
|
"description": self.get_as_string(self._description),
|
|
1130
|
-
"required": self.get_as_string(self.
|
|
1130
|
+
"required": self.get_as_string(self._required),
|
|
1131
1131
|
"in": self.get_as_string(self._union),
|
|
1132
1132
|
"constraints": self.get_as_string(self._constraints),
|
|
1133
1133
|
"default": self.get_as_string(self._default),
|
|
@@ -27,7 +27,10 @@ from .backoffice import Backoffice
|
|
|
27
27
|
from .collection import Collection
|
|
28
28
|
from .selection import Selection
|
|
29
29
|
from .log import Logger, log_system, LogLevel, stack
|
|
30
|
-
|
|
30
|
+
|
|
31
|
+
# from .reference import Ref, RefsList, FillStrategy, DeleteStrategy
|
|
32
|
+
from .refslist import RefsList, FillStrategy, DeleteStrategy
|
|
33
|
+
from .ref import Ref
|
|
31
34
|
from .file.file import File
|
|
32
35
|
from .file.file_connector import FileConnector
|
|
33
36
|
from .file.file_system_connector import FileSystemConnector
|
|
@@ -365,7 +365,8 @@ class Collection:
|
|
|
365
365
|
|
|
366
366
|
# Check if the object match the model despite the fact there is no change
|
|
367
367
|
o = self.new_item()
|
|
368
|
-
print(o)
|
|
368
|
+
print(f">> {o}")
|
|
369
|
+
print(f"<< {new_obj}")
|
|
369
370
|
o.set(new_obj)
|
|
370
371
|
|
|
371
372
|
return None
|
|
@@ -877,7 +878,7 @@ class Collection:
|
|
|
877
878
|
|
|
878
879
|
# Create a partial object with values given in request.item
|
|
879
880
|
obj = self.new_item()
|
|
880
|
-
obj.
|
|
881
|
+
obj.set_value(c.item.get_value())
|
|
881
882
|
obj.enable_permissions()
|
|
882
883
|
sub_object = obj.select(c.path)
|
|
883
884
|
if sub_object is None:
|
|
@@ -916,7 +917,7 @@ class Collection:
|
|
|
916
917
|
|
|
917
918
|
# Create a partial object with values given in request.item
|
|
918
919
|
obj = self.new_item()
|
|
919
|
-
obj.
|
|
920
|
+
obj.set_value(c.get_value())
|
|
920
921
|
obj.enable_permissions()
|
|
921
922
|
|
|
922
923
|
return (json.dumps(obj.get_current_meta()), 200)
|
|
@@ -952,6 +953,7 @@ class Collection:
|
|
|
952
953
|
# apply patches
|
|
953
954
|
for p in patch_list:
|
|
954
955
|
patch = Patch()
|
|
956
|
+
print(f"patch {p}")
|
|
955
957
|
patch.set(p)
|
|
956
958
|
obj.patch(patch.op, patch.path, patch.value)
|
|
957
959
|
|
|
@@ -46,7 +46,6 @@ def transform_to_filestorage( # pylint: disable=unused-argument
|
|
|
46
46
|
:rtype: FileStorage
|
|
47
47
|
"""
|
|
48
48
|
if v is None:
|
|
49
|
-
print("transform None")
|
|
50
49
|
return None
|
|
51
50
|
|
|
52
51
|
if isinstance(v, File):
|
|
@@ -106,11 +105,17 @@ KPARSE_MODEL = {
|
|
|
106
105
|
|
|
107
106
|
|
|
108
107
|
class File(Dict):
|
|
108
|
+
"""
|
|
109
|
+
Object to manage files.
|
|
110
|
+
inherite from https://stricto.readthedocs.io/en/latest/api_reference.html#stricto.Dict
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
:param Dict: Dict
|
|
114
|
+
:type Dict: https://stricto.readthedocs.io/en/latest/api_reference.html#stricto.Dict
|
|
115
|
+
"""
|
|
109
116
|
|
|
110
117
|
def __init__(self, **kwargs):
|
|
111
118
|
"""
|
|
112
|
-
Object to manage files.
|
|
113
|
-
inherite from https://stricto.readthedocs.io/en/latest/api_reference.html#stricto.Dict
|
|
114
119
|
|
|
115
120
|
|
|
116
121
|
:param buffer_size=: The buffer size to read chunk on this file
|
|
@@ -268,13 +273,40 @@ class File(Dict):
|
|
|
268
273
|
transform_to_filestorage(content, None)
|
|
269
274
|
)
|
|
270
275
|
|
|
271
|
-
def
|
|
276
|
+
def set_value(self, value: Any) -> bool:
|
|
277
|
+
"""Set the value of the file.
|
|
278
|
+
|
|
279
|
+
If the value is a dict, handle it as file structure. if a str|bytes|FileStorage,
|
|
280
|
+
set the content and fill meta datas in the structure.
|
|
272
281
|
|
|
282
|
+
:param value: The file Structure or content
|
|
283
|
+
:type value: Any
|
|
284
|
+
:return: True if modifications or False if nothing changed.
|
|
285
|
+
:rtype: bool
|
|
286
|
+
"""
|
|
273
287
|
if isinstance(value, (FileStorage, str, bytes)):
|
|
288
|
+
old_content = None
|
|
289
|
+
if self.has_file() is True:
|
|
290
|
+
old_content = self.get_content()
|
|
274
291
|
self.set_content(value)
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
292
|
+
if self.get_content() == old_content:
|
|
293
|
+
return False
|
|
294
|
+
return True
|
|
295
|
+
|
|
296
|
+
return super().set_value(value)
|
|
297
|
+
|
|
298
|
+
def compute_value(self) -> bool:
|
|
299
|
+
"""compute the value if needed
|
|
300
|
+
|
|
301
|
+
:return: True if changed
|
|
302
|
+
:rtype: bool
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
if callable(self._auto_set):
|
|
306
|
+
value = self._auto_set(self.get_root())
|
|
307
|
+
return self.set_value(value)
|
|
308
|
+
|
|
309
|
+
return False
|
|
278
310
|
|
|
279
311
|
def delete_content(self) -> None:
|
|
280
312
|
"""Delete the file"""
|
|
@@ -407,6 +439,8 @@ class File(Dict):
|
|
|
407
439
|
size = value.size.get_value()
|
|
408
440
|
if isinstance(value, FileStorage):
|
|
409
441
|
size = value.content_length
|
|
442
|
+
if isinstance(value, dict):
|
|
443
|
+
size = value.get("size")
|
|
410
444
|
|
|
411
445
|
if size is not None and size > self._max_size:
|
|
412
446
|
raise SConstraintError(
|
|
@@ -417,11 +451,17 @@ class File(Dict):
|
|
|
417
451
|
|
|
418
452
|
# check the content_type
|
|
419
453
|
if self._authorized_mime_types is not None:
|
|
454
|
+
print(
|
|
455
|
+
f"File check constraint mime types {type(value)} {self._authorized_mime_types}"
|
|
456
|
+
)
|
|
457
|
+
|
|
420
458
|
mt = None
|
|
421
459
|
if isinstance(value, File):
|
|
422
460
|
mt = value.content_type.get_value()
|
|
423
461
|
if isinstance(value, FileStorage):
|
|
424
462
|
mt = value.content_type
|
|
463
|
+
if isinstance(value, dict):
|
|
464
|
+
mt = value.get("content_type")
|
|
425
465
|
|
|
426
466
|
if mt not in self._authorized_mime_types:
|
|
427
467
|
raise SConstraintError(
|
|
@@ -17,16 +17,15 @@ log = log_system.get_or_create_logger("file", LogLevel.DEBUG)
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class FileBlobConnector(FileConnector): # pylint: disable=too-many-instance-attributes
|
|
20
|
+
"""
|
|
21
|
+
File connector in memory
|
|
22
|
+
This is the way to save files just in memory.
|
|
23
|
+
|
|
24
|
+
"""
|
|
20
25
|
|
|
21
26
|
@validation_parameters
|
|
22
27
|
def __init__(self, **kwargs):
|
|
23
|
-
"""
|
|
24
|
-
File connector in memory
|
|
25
|
-
|
|
26
|
-
This is the way to save files just in memory.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"""
|
|
28
|
+
""" """
|
|
30
29
|
|
|
31
30
|
# The array of bytes
|
|
32
31
|
self._blobs = {}
|
|
@@ -19,13 +19,19 @@ KPARSE_MODEL = {
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class FileConnector: # pylint: disable=too-many-instance-attributes
|
|
22
|
+
"""
|
|
23
|
+
Abstract Class fir File connector.
|
|
24
|
+
this is the family (parent) object for files connector
|
|
25
|
+
"""
|
|
22
26
|
|
|
23
27
|
@validation_parameters
|
|
24
28
|
def __init__(self, **kwargs):
|
|
25
29
|
"""
|
|
26
|
-
|
|
30
|
+
:param kwargs: arguments as kwargs for the FileConnector
|
|
31
|
+
:type kwargs: object
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
:keyword buffer_size: The biffer size (default = 0812)
|
|
34
|
+
:type buffer_size: int
|
|
29
35
|
"""
|
|
30
36
|
|
|
31
37
|
options = Kparse(kwargs, KPARSE_MODEL, strict=True)
|
|
@@ -29,18 +29,20 @@ KPARSE_MODEL = {
|
|
|
29
29
|
class FileSystemConnector(
|
|
30
30
|
FileConnector
|
|
31
31
|
): # pylint: disable=too-many-instance-attributes
|
|
32
|
+
"""
|
|
33
|
+
File connector on a file system
|
|
34
|
+
|
|
35
|
+
This is the way to save / store / retrieve objects
|
|
36
|
+
"""
|
|
32
37
|
|
|
33
38
|
@validation_parameters
|
|
34
39
|
def __init__(self, **kwargs):
|
|
35
40
|
"""
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
This is the way to save / store / retrieve objects
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
:param path=: The directory to store files
|
|
42
|
-
:type path=: str
|
|
41
|
+
:param kwargs: arguments as kwargs for the FileSystemConnector
|
|
42
|
+
:type kwargs: object
|
|
43
43
|
|
|
44
|
+
:keyword path: The path to store files
|
|
45
|
+
:type path: str
|
|
44
46
|
"""
|
|
45
47
|
|
|
46
48
|
options = Kparse(kwargs, KPARSE_MODEL)
|
|
@@ -21,7 +21,14 @@ log = log_system.get_or_create_logger("Item")
|
|
|
21
21
|
# used for developpement
|
|
22
22
|
sys.path.insert(1, "../../stricto")
|
|
23
23
|
|
|
24
|
-
from stricto import
|
|
24
|
+
from stricto import (
|
|
25
|
+
Dict,
|
|
26
|
+
String,
|
|
27
|
+
SRightError,
|
|
28
|
+
Kparse,
|
|
29
|
+
EVENT_MANAGER,
|
|
30
|
+
validation_parameters,
|
|
31
|
+
)
|
|
25
32
|
|
|
26
33
|
KPARSE_MODEL = {
|
|
27
34
|
"meta_data_handler": {
|
|
@@ -83,9 +90,7 @@ class Item(Dict): # pylint: disable=too-many-instance-attributes
|
|
|
83
90
|
Dict.__init__(self, schema, **kwargs)
|
|
84
91
|
|
|
85
92
|
# Append then change event to the item
|
|
86
|
-
|
|
87
|
-
self._events["change"] = []
|
|
88
|
-
self._events["change"].append(self.on_change)
|
|
93
|
+
EVENT_MANAGER.register_event(self, "change", self.on_change)
|
|
89
94
|
|
|
90
95
|
# adding _id to the model
|
|
91
96
|
self.add_to_model("_id", String(can_modify=False))
|
|
@@ -192,7 +197,7 @@ class Item(Dict): # pylint: disable=too-many-instance-attributes
|
|
|
192
197
|
# if kwargs.get("m_path") is None:
|
|
193
198
|
# kwargs["m_path"] = []
|
|
194
199
|
|
|
195
|
-
self.trigg("loaded",
|
|
200
|
+
self.trigg("loaded", **kwargs)
|
|
196
201
|
|
|
197
202
|
# print(f"Load {int(datetime.timestamp(datetime.now()))}", self)
|
|
198
203
|
|
|
@@ -227,7 +232,7 @@ class Item(Dict): # pylint: disable=too-many-instance-attributes
|
|
|
227
232
|
# if kwargs.get("m_path") is None:
|
|
228
233
|
# kwargs["m_path"] = []
|
|
229
234
|
|
|
230
|
-
self.trigg("loaded",
|
|
235
|
+
self.trigg("loaded", **kwargs)
|
|
231
236
|
|
|
232
237
|
def save(self, **kwargs) -> None:
|
|
233
238
|
"""
|
|
@@ -275,7 +280,7 @@ class Item(Dict): # pylint: disable=too-many-instance-attributes
|
|
|
275
280
|
self.__dict__["_loaded_object"] = a
|
|
276
281
|
|
|
277
282
|
kwargs["old_object"] = self.__dict__["_loaded_object"]
|
|
278
|
-
self.trigg("before_save",
|
|
283
|
+
self.trigg("before_save", **kwargs)
|
|
279
284
|
|
|
280
285
|
# print(f"Save {int(datetime.timestamp(datetime.now()))}", self)
|
|
281
286
|
dict_to_save = self.get_view("save").get_encoded()
|
|
@@ -295,7 +300,7 @@ class Item(Dict): # pylint: disable=too-many-instance-attributes
|
|
|
295
300
|
self.__dict__["_loaded_object"].get_value(),
|
|
296
301
|
)
|
|
297
302
|
|
|
298
|
-
self.trigg("saved",
|
|
303
|
+
self.trigg("saved", **kwargs)
|
|
299
304
|
|
|
300
305
|
def delete(self, **kwargs) -> None:
|
|
301
306
|
"""
|
|
@@ -332,7 +337,7 @@ class Item(Dict): # pylint: disable=too-many-instance-attributes
|
|
|
332
337
|
)
|
|
333
338
|
|
|
334
339
|
# Send delete event before deletion to do some stufs
|
|
335
|
-
self.trigg("before_delete",
|
|
340
|
+
self.trigg("before_delete", **kwargs)
|
|
336
341
|
self.db_handler.delete_by_id(self._id.get_value())
|
|
337
342
|
|
|
338
343
|
log.info(
|
|
@@ -437,4 +442,5 @@ class Item(Dict): # pylint: disable=too-many-instance-attributes
|
|
|
437
442
|
self._collection.name,
|
|
438
443
|
self._id,
|
|
439
444
|
)
|
|
440
|
-
|
|
445
|
+
print(f"Item trigg created {id(self)} {self.get_value()}")
|
|
446
|
+
self.trigg("created", **kwargs)
|
|
@@ -64,14 +64,15 @@ class StandardMetaDataHandler(
|
|
|
64
64
|
if o._meta.ctime == None: # pylint: disable=singleton-comparison
|
|
65
65
|
o._meta.ctime = now
|
|
66
66
|
|
|
67
|
+
login = current_user.login.copy()
|
|
68
|
+
user_id = current_user._id.copy()
|
|
69
|
+
|
|
67
70
|
if o._meta.created_by._id == None: # pylint: disable=singleton-comparison
|
|
68
|
-
o._meta.created_by._id
|
|
69
|
-
o._meta.created_by.login = current_user.login.copy()
|
|
71
|
+
o._meta.created_by.set({"_id": user_id, "login": login})
|
|
70
72
|
|
|
71
73
|
# Set modificattion time and last updater
|
|
72
|
-
o._meta.
|
|
73
|
-
o._meta.
|
|
74
|
-
o._meta.modified_by.login = current_user.login.copy()
|
|
74
|
+
o._meta.modified_by.set({"_id": user_id, "login": login})
|
|
75
|
+
o._meta.mtime.set(now)
|
|
75
76
|
|
|
76
77
|
# Put permission back
|
|
77
78
|
if permission_enabled is True:
|
|
@@ -14,6 +14,20 @@ sys.path.insert(1, "../../stricto")
|
|
|
14
14
|
from stricto import Dict, String
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
def must(value, o) -> bool: # pylint: disable=unused-argument
|
|
18
|
+
"""check if start with a $.
|
|
19
|
+
|
|
20
|
+
:param value: _description_
|
|
21
|
+
:type value: _type_
|
|
22
|
+
:param o: Not used
|
|
23
|
+
:type o: _tyAnype_
|
|
24
|
+
:return: True if start with a $.
|
|
25
|
+
:rtype: bool
|
|
26
|
+
"""
|
|
27
|
+
print(f'MUST "{value}" -> {bool(re.match(r"^\$.*", value))}')
|
|
28
|
+
return bool(re.match(r"^\$.*", value))
|
|
29
|
+
|
|
30
|
+
|
|
17
31
|
class Patch(Dict): # pylint: disable=too-many-instance-attributes
|
|
18
32
|
"""
|
|
19
33
|
A Object for patching
|
|
@@ -29,7 +43,8 @@ class Patch(Dict): # pylint: disable=too-many-instance-attributes
|
|
|
29
43
|
"op": String(require=True, union=["test", "replace", "remove", "add"]),
|
|
30
44
|
"path": String(
|
|
31
45
|
require=True,
|
|
32
|
-
constraint=lambda value, o: bool(re.match(r"^\$.*", value)),
|
|
46
|
+
# constraint=lambda value, o: bool(re.match(r"^\$.*", value)),
|
|
47
|
+
constraint=must,
|
|
33
48
|
),
|
|
34
49
|
"value": String(),
|
|
35
50
|
},
|