backo 0.3.4__tar.gz → 0.3.6__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 (130) hide show
  1. backo-0.3.6/.github/workflows/test.yml +97 -0
  2. backo-0.3.4/.github/workflows/test.yml → backo-0.3.6/.github/workflows/test_examples.yml +4 -11
  3. {backo-0.3.4 → backo-0.3.6}/CHANGELOG.md +28 -0
  4. {backo-0.3.4 → backo-0.3.6}/PKG-INFO +25 -8
  5. {backo-0.3.4 → backo-0.3.6}/README.md +23 -6
  6. {backo-0.3.4 → backo-0.3.6}/backo/__init__.py +3 -1
  7. {backo-0.3.4 → backo-0.3.6}/backo/backoffice.py +12 -4
  8. {backo-0.3.4 → backo-0.3.6}/backo/collection.py +136 -52
  9. {backo-0.3.4 → backo-0.3.6}/backo/db/__init__.py +1 -0
  10. {backo-0.3.4 → backo-0.3.6}/backo/db/backo_redirect.py +2 -1
  11. {backo-0.3.4 → backo-0.3.6}/backo/db/generic/db_handler.py +6 -15
  12. {backo-0.3.4 → backo-0.3.6}/backo/db/generic/filter.py +34 -4
  13. {backo-0.3.4 → backo-0.3.6}/backo/db/generic/transformer.py +75 -0
  14. backo-0.3.6/backo/db/generic/transformer_cache.py +101 -0
  15. {backo-0.3.4 → backo-0.3.6}/backo/db/memory.py +9 -6
  16. {backo-0.3.4 → backo-0.3.6}/backo/db/mongo.py +101 -29
  17. {backo-0.3.4 → backo-0.3.6}/backo/db/restfull.py +31 -4
  18. {backo-0.3.4 → backo-0.3.6}/backo/db/sqlite3/db_handler.py +25 -3
  19. backo-0.3.6/backo/db/sqlite3/filter.py +225 -0
  20. {backo-0.3.4 → backo-0.3.6}/backo/db/sqlite3/pragma.py +1 -1
  21. {backo-0.3.4 → backo-0.3.6}/backo/db/sqlite3/transformers.py +22 -0
  22. {backo-0.3.4 → backo-0.3.6}/backo/db/valkeydb.py +8 -5
  23. {backo-0.3.4 → backo-0.3.6}/backo/db/yml.py +4 -2
  24. {backo-0.3.4 → backo-0.3.6}/backo/db/yml_dir.py +12 -8
  25. {backo-0.3.4 → backo-0.3.6}/backo/error.py +40 -0
  26. {backo-0.3.4 → backo-0.3.6}/backo/item.py +16 -5
  27. {backo-0.3.4 → backo-0.3.6}/backo/log.py +17 -1
  28. {backo-0.3.4 → backo-0.3.6}/backo/loop_path.py +10 -3
  29. backo-0.3.4/backo/migration_report.py → backo-0.3.6/backo/migration.py +17 -0
  30. {backo-0.3.4 → backo-0.3.6}/backo/openapi.py +0 -2
  31. backo-0.3.6/backo/ref.py +533 -0
  32. {backo-0.3.4 → backo-0.3.6}/backo/refs_strategies.py +16 -0
  33. backo-0.3.6/backo/refslist.py +703 -0
  34. {backo-0.3.4 → backo-0.3.6}/backo/selection.py +24 -5
  35. backo-0.3.6/backo/sort.py +94 -0
  36. {backo-0.3.4 → backo-0.3.6}/pyproject.toml +2 -2
  37. {backo-0.3.4 → backo-0.3.6}/tests/__init__.py +1 -0
  38. {backo-0.3.4 → backo-0.3.6}/tests/test_db_connector.py +28 -3
  39. backo-0.3.6/tests/test_db_connector_cache.py +95 -0
  40. {backo-0.3.4 → backo-0.3.6}/tests/test_log.py +5 -0
  41. {backo-0.3.4 → backo-0.3.6}/tests/test_migrations.py +11 -8
  42. backo-0.3.6/tests/test_reference.py +756 -0
  43. backo-0.3.6/tests/test_rest_api_connector.py +110 -0
  44. {backo-0.3.4 → backo-0.3.6}/tests/test_routes.py +7 -5
  45. {backo-0.3.4 → backo-0.3.6}/tests/test_selections.py +13 -2
  46. {backo-0.3.4 → backo-0.3.6}/uv.lock +5 -5
  47. backo-0.3.4/.github/workflows/test_examples.yml +0 -35
  48. backo-0.3.4/backo/db/sqlite3/filter.py +0 -149
  49. backo-0.3.4/backo/ref.py +0 -527
  50. backo-0.3.4/backo/refslist.py +0 -634
  51. backo-0.3.4/tests/test_reference.py +0 -1233
  52. backo-0.3.4/tests/test_rest_api_connector.py +0 -498
  53. {backo-0.3.4 → backo-0.3.6}/.coveragerc +0 -0
  54. {backo-0.3.4 → backo-0.3.6}/.github/workflows/pylint.yml +0 -0
  55. {backo-0.3.4 → backo-0.3.6}/.github/workflows/release.yml +0 -0
  56. {backo-0.3.4 → backo-0.3.6}/.gitignore +0 -0
  57. {backo-0.3.4 → backo-0.3.6}/.pylintrc +0 -0
  58. {backo-0.3.4 → backo-0.3.6}/.readthedocs.yaml +0 -0
  59. {backo-0.3.4 → backo-0.3.6}/CONTRIBUTING.md +0 -0
  60. {backo-0.3.4 → backo-0.3.6}/LICENSE +0 -0
  61. {backo-0.3.4 → backo-0.3.6}/backo/action.py +0 -0
  62. {backo-0.3.4 → backo-0.3.6}/backo/api_toolbox.py +0 -0
  63. {backo-0.3.4 → backo-0.3.6}/backo/collection_addon.py +0 -0
  64. {backo-0.3.4 → backo-0.3.6}/backo/current_user.py +0 -0
  65. {backo-0.3.4 → backo-0.3.6}/backo/db/generic/interface.py +0 -0
  66. {backo-0.3.4 → backo-0.3.6}/backo/db/sqlite3/__init__.py +0 -0
  67. {backo-0.3.4 → backo-0.3.6}/backo/file/blob_file.py +0 -0
  68. {backo-0.3.4 → backo-0.3.6}/backo/file/file.py +0 -0
  69. {backo-0.3.4 → backo-0.3.6}/backo/file/file_blob_connector.py +0 -0
  70. {backo-0.3.4 → backo-0.3.6}/backo/file/file_connector.py +0 -0
  71. {backo-0.3.4 → backo-0.3.6}/backo/file/file_system_connector.py +0 -0
  72. {backo-0.3.4 → backo-0.3.6}/backo/initialisation/init_script.py +0 -0
  73. {backo-0.3.4 → backo-0.3.6}/backo/initialisation/templates/__init__.pytemplate +0 -0
  74. {backo-0.3.4 → backo-0.3.6}/backo/initialisation/templates/backoffice.pytemplate +0 -0
  75. {backo-0.3.4 → backo-0.3.6}/backo/initialisation/templates/collection.pytemplate +0 -0
  76. {backo-0.3.4 → backo-0.3.6}/backo/meta_data_handler.py +0 -0
  77. {backo-0.3.4 → backo-0.3.6}/backo/patch.py +0 -0
  78. {backo-0.3.4 → backo-0.3.6}/backo/request_decorators.py +0 -0
  79. {backo-0.3.4 → backo-0.3.6}/backo/status.py +0 -0
  80. {backo-0.3.4 → backo-0.3.6}/backo/transaction.py +0 -0
  81. {backo-0.3.4 → backo-0.3.6}/docs/Makefile +0 -0
  82. {backo-0.3.4 → backo-0.3.6}/docs/make.bat +0 -0
  83. {backo-0.3.4 → backo-0.3.6}/docs/requirements.txt +0 -0
  84. {backo-0.3.4 → backo-0.3.6}/docs/source/DB_management.md +0 -0
  85. {backo-0.3.4 → backo-0.3.6}/docs/source/api_reference.rst +0 -0
  86. {backo-0.3.4 → backo-0.3.6}/docs/source/conf.py +0 -0
  87. {backo-0.3.4 → backo-0.3.6}/docs/source/errors.rst +0 -0
  88. {backo-0.3.4 → backo-0.3.6}/docs/source/index.rst +0 -0
  89. {backo-0.3.4 → backo-0.3.6}/docs/source/readme.rst +0 -0
  90. {backo-0.3.4 → backo-0.3.6}/examples/media_library/README.md +0 -0
  91. {backo-0.3.4 → backo-0.3.6}/examples/media_library/__init__.py +0 -0
  92. {backo-0.3.4 → backo-0.3.6}/examples/media_library/backoffice.py +0 -0
  93. {backo-0.3.4 → backo-0.3.6}/examples/media_library/collections_set/__init__.py +0 -0
  94. {backo-0.3.4 → backo-0.3.6}/examples/media_library/collections_set/books.py +0 -0
  95. {backo-0.3.4 → backo-0.3.6}/examples/media_library/collections_set/users.py +0 -0
  96. {backo-0.3.4 → backo-0.3.6}/examples/media_library/migration.py +0 -0
  97. {backo-0.3.4 → backo-0.3.6}/examples/media_library/tests.py +0 -0
  98. {backo-0.3.4 → backo-0.3.6}/examples/nationality/README.md +0 -0
  99. {backo-0.3.4 → backo-0.3.6}/examples/nationality/__init__.py +0 -0
  100. {backo-0.3.4 → backo-0.3.6}/examples/nationality/backoffice.py +0 -0
  101. {backo-0.3.4 → backo-0.3.6}/examples/nationality/collections_set/__init__.py +0 -0
  102. {backo-0.3.4 → backo-0.3.6}/examples/nationality/collections_set/countries.py +0 -0
  103. {backo-0.3.4 → backo-0.3.6}/examples/nationality/collections_set/db_country_connector.py +0 -0
  104. {backo-0.3.4 → backo-0.3.6}/examples/nationality/collections_set/people.py +0 -0
  105. {backo-0.3.4 → backo-0.3.6}/examples/nationality/tests.py +0 -0
  106. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/README.md +0 -0
  107. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/__init__.py +0 -0
  108. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/backoffice.py +0 -0
  109. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/collections_set/__init__.py +0 -0
  110. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/collections_set/users.py +0 -0
  111. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/collections_set/vms.py +0 -0
  112. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/collections_set/vms_connector.py +0 -0
  113. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/config.yaml +0 -0
  114. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/constants.py +0 -0
  115. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/requirements.txt +0 -0
  116. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/rest-api/README.md +0 -0
  117. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/rest-api/collections_set/__init__.py +0 -0
  118. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/rest-api/collections_set/vms.py +0 -0
  119. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/rest-api/config.yaml +0 -0
  120. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/rest-api/constants.py +0 -0
  121. {backo-0.3.4 → backo-0.3.6}/examples/rest_api_connector/rest-api/rest_api.py +0 -0
  122. {backo-0.3.4 → backo-0.3.6}/requirements.txt +0 -0
  123. {backo-0.3.4 → backo-0.3.6}/tests/test_action.py +0 -0
  124. {backo-0.3.4 → backo-0.3.6}/tests/test_api_toolbox.py +0 -0
  125. {backo-0.3.4 → backo-0.3.6}/tests/test_crud.py +0 -0
  126. {backo-0.3.4 → backo-0.3.6}/tests/test_current_user.py +0 -0
  127. {backo-0.3.4 → backo-0.3.6}/tests/test_file.py +0 -0
  128. {backo-0.3.4 → backo-0.3.6}/tests/test_meta.py +0 -0
  129. {backo-0.3.4 → backo-0.3.6}/tests/test_mongo.py +0 -0
  130. {backo-0.3.4 → backo-0.3.6}/tests/test_openapi.py +0 -0
@@ -0,0 +1,97 @@
1
+ name: CodeCov
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ on_main:
7
+ if: github.ref == 'refs/heads/main'
8
+ runs-on: ubuntu-latest
9
+ strategy:
10
+ matrix:
11
+ python-version:
12
+ - "3.12"
13
+ - "3.13"
14
+ - "3.14"
15
+ services:
16
+ mongodb:
17
+ image: mongo:latest
18
+ env:
19
+ # MONGO_INITDB_ROOT_USERNAME: admin
20
+ # MONGO_INITDB_ROOT_PASSWORD: admin
21
+ MONGO_INITDB_DATABASE: testMongo
22
+ ports:
23
+ - 27017:27017
24
+ valkey:
25
+ image: valkey/valkey:latest
26
+ ports:
27
+ - "6379:6379"
28
+ steps:
29
+ - uses: actions/checkout@v3
30
+ - name: Set up Python ${{ matrix.python-version }}
31
+ uses: actions/setup-python@v3
32
+ with:
33
+ python-version: ${{ matrix.python-version }}
34
+
35
+ - name: Install uv
36
+ uses: astral-sh/setup-uv@v1
37
+ with:
38
+ version: "latest"
39
+
40
+ - name: Install Python
41
+ run: uv python install
42
+
43
+ - name: Install dependencies
44
+ run: |
45
+ sudo apt-get install libmagic1
46
+ uv sync --all-groups --all-extras
47
+
48
+ - name: run tests and coverage
49
+ run: |
50
+ uv run coverage run -m unittest tests
51
+ uv run coverage report -m
52
+ uv run coverage xml
53
+ on_branches:
54
+ if: github.ref != 'refs/heads/main'
55
+ runs-on: ubuntu-latest
56
+ strategy:
57
+ matrix:
58
+ python-version:
59
+ - "3.14"
60
+ services:
61
+ mongodb:
62
+ image: mongo:latest
63
+ env:
64
+ # MONGO_INITDB_ROOT_USERNAME: admin
65
+ # MONGO_INITDB_ROOT_PASSWORD: admin
66
+ MONGO_INITDB_DATABASE: testMongo
67
+ ports:
68
+ - 27017:27017
69
+ valkey:
70
+ image: valkey/valkey:latest
71
+ ports:
72
+ - "6379:6379"
73
+ steps:
74
+ - uses: actions/checkout@v3
75
+ - name: Set up Python ${{ matrix.python-version }}
76
+ uses: actions/setup-python@v3
77
+ with:
78
+ python-version: ${{ matrix.python-version }}
79
+
80
+ - name: Install uv
81
+ uses: astral-sh/setup-uv@v1
82
+ with:
83
+ version: "latest"
84
+
85
+ - name: Install Python
86
+ run: uv python install
87
+
88
+ - name: Install dependencies
89
+ run: |
90
+ sudo apt-get install libmagic1
91
+ uv sync --all-groups --all-extras
92
+
93
+ - name: run tests and coverage
94
+ run: |
95
+ uv run coverage run -m unittest tests
96
+ uv run coverage report -m
97
+ uv run coverage xml
@@ -1,4 +1,4 @@
1
- name: CodeCov
1
+ name: TestExamples
2
2
 
3
3
  on: [push, pull_request]
4
4
 
@@ -12,15 +12,9 @@ jobs:
12
12
  mongodb:
13
13
  image: mongo:latest
14
14
  env:
15
- # MONGO_INITDB_ROOT_USERNAME: admin
16
- # MONGO_INITDB_ROOT_PASSWORD: admin
17
15
  MONGO_INITDB_DATABASE: testMongo
18
16
  ports:
19
17
  - 27017:27017
20
- valkey:
21
- image: valkey/valkey:latest
22
- ports:
23
- - "6379:6379"
24
18
  steps:
25
19
  - uses: actions/checkout@v3
26
20
  - name: Set up Python ${{ matrix.python-version }}
@@ -41,8 +35,7 @@ jobs:
41
35
  sudo apt-get install libmagic1
42
36
  uv sync --all-groups --all-extras
43
37
 
44
- - name: run tests and coverage
38
+ - name: Run media library tests
39
+ working-directory: examples/media_library
45
40
  run: |
46
- uv run coverage run -m unittest tests
47
- uv run coverage report -m
48
- uv run coverage xml
41
+ uv run python -m unittest tests
@@ -5,6 +5,34 @@ 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.3.6] 2026-09-17
9
+
10
+ * Feat
11
+ * sorting on selection
12
+ * sorting in Sqlite3DBConnector and DBMongoConnector
13
+ * sorting in routes with _sort= in the query string
14
+
15
+ * Internal :
16
+ * Adding FilterReport for evaluation of SFilters into the DB
17
+ * test refacto for Ref and RefsList
18
+ * refacto Ref and RefsList
19
+
20
+ * Fix
21
+ * import __futures__ error on validation parameters
22
+ * fix bug on selector in Ref and RefsList
23
+
24
+ ## [0.3.5] 2026-09-15
25
+
26
+ * fix
27
+ * DBHandler pagination bug fix
28
+ * BREAKING CHANGE : New option migration MigrationStrategy (strategy=)
29
+ * BREAKING CHANGE : Removing option FillStrategy (ofs=) for Ref
30
+
31
+ * Internal :
32
+ * Pagination during migration
33
+ * test refacto for Ref and RefsList
34
+ * refacto Ref and RefsList
35
+
8
36
  ## [0.3.4] 2026-09-04
9
37
 
10
38
  * fix : total routes bug fix
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: backo
3
- Version: 0.3.4
3
+ Version: 0.3.6
4
4
  Summary: Back office low code
5
5
  Project-URL: GitHub, https://github.com/backo-stricto/backo
6
6
  Project-URL: Homepage, https://github.com/backo-stricto/backo
@@ -41,7 +41,7 @@ Requires-Dist: pyyaml
41
41
  Requires-Dist: questionary
42
42
  Requires-Dist: redis>=8.1.0
43
43
  Requires-Dist: requests
44
- Requires-Dist: stricto>=0.2.5
44
+ Requires-Dist: stricto>=0.2.6
45
45
  Provides-Extra: mongo
46
46
  Requires-Dist: pymongo>=4.17.0; extra == 'mongo'
47
47
  Description-Content-Type: text/markdown
@@ -878,6 +878,7 @@ Get a list of objects matching the query string. The query string can be with th
878
878
  | \_view | string | "client" | selects the view ([stricto views](https://github.com/backo-stricto/stricto?tab=readme-ov-file#views)) |
879
879
  | \_page | int | - | sets the desired number of items per page in paginated data presentation |
880
880
  | \_skip | int | - | skips the n-first items of the result list in paginated data presentation. |
881
+ | \_sort | string | - | give the list of sorting fields |
881
882
  | \_total | whatyouwant | None | Just compute the total of object and return { 'total' : x } without taking pagination in account |
882
883
 
883
884
 
@@ -893,9 +894,9 @@ The request returns a HTTP status `200` with that JSON object:
893
894
  ```
894
895
 
895
896
  ##### Example
896
- Select all users whose name includes 'do' and present the result list with 10 items per page.
897
+ Select all users whose name includes 'do' and present the result list with 10 items per page, sorted by surname.
897
898
  ```bash
898
- curl -X GET 'http://localhost/myApp/users/?name.$re=do&_page=10'
899
+ curl -X GET 'http://localhost/myApp/users/?name.$re=do&_page=10&_sort=$.surname'
899
900
  ```
900
901
 
901
902
  #### GET \<my-app-name\>/\<collection name\>/\<_id\>/\<path\>
@@ -1479,6 +1480,11 @@ log = log_system.get_or_create_logger("custom")
1479
1480
  log.setLevel(logging.DEBUG)
1480
1481
  log.addHandler ( my_own_handler )
1481
1482
  # ...
1483
+
1484
+ # To see
1485
+ log_system.infos()
1486
+ # print some available informations about log system (levels, handlers)
1487
+
1482
1488
  ```
1483
1489
 
1484
1490
  ### stack()
@@ -1554,7 +1560,7 @@ def transform_function( o: dict) -> dict:
1554
1560
  ```
1555
1561
 
1556
1562
 
1557
- By default, the flag ```dry_run``` is ```True```. so you will broke nothing. ```dry_run``` will do all work except saving the object in the DB.
1563
+ By default, the strategy for migration is ```MigrationStrategy.DRY_RUN```. So you will broke nothing. ```MigrationStrategy.DRY_RUN``` will do all work except saving the object in the DB.
1558
1564
 
1559
1565
  > [!IMPORTANT]
1560
1566
  > there is no check of *rights* and *current_user* during migration. metadatas (see [_meta](#_meta)) are not updated.
@@ -1571,7 +1577,7 @@ This is an example for migrating data.
1571
1577
 
1572
1578
  ```python
1573
1579
  from media_library import mybackoffice
1574
- from backo import log_system, LogLevel
1580
+ from backo import log_system, LogLevel, MigrationStrategy
1575
1581
 
1576
1582
  # Set migration level to debug
1577
1583
  log_migration = log_system.get_or_create_logger("migration")
@@ -1611,13 +1617,24 @@ report = mybackoffice.migrate("books", update_with_note) # All ids
1611
1617
  report = mybackoffice.migrate("books", update_with_note, _id="my_book_id", dry_run=False)
1612
1618
  # or
1613
1619
  report = mybackoffice.migrate(
1614
- "books", update_with_note, _ids=["my_book_id1", "my_book_id2"], dry_run=False
1620
+ "books", update_with_note, _ids=["my_book_id1", "my_book_id2"], strategy=MigrationStrategy.EXECUTE
1615
1621
  )
1616
1622
  # or
1617
- report = mybackoffice.migrate("books", update_with_note, dry_run=False) # All ids
1623
+ report = mybackoffice.migrate("books", update_with_note, strategy=MigrationStrategy.EXECUTE) # All ids
1618
1624
 
1619
1625
  ```
1620
1626
 
1627
+ ### MigrationStrategy options
1628
+
1629
+ | option | description |
1630
+ | - | - |
1631
+ | ```MigrationStrategy.DRY_RUN``` | Don't change anything, just display and report diffs |
1632
+ | ```MigrationStrategy.EXECUTE``` | Do changements and save in DB if needed. report diffs |
1633
+ | ```MigrationStrategy.FORCE``` | Do changements and rewrite data in DB. report diffs |
1634
+
1635
+
1636
+
1637
+
1621
1638
  ### report
1622
1639
 
1623
1640
  The migration returns a report structure :
@@ -830,6 +830,7 @@ Get a list of objects matching the query string. The query string can be with th
830
830
  | \_view | string | "client" | selects the view ([stricto views](https://github.com/backo-stricto/stricto?tab=readme-ov-file#views)) |
831
831
  | \_page | int | - | sets the desired number of items per page in paginated data presentation |
832
832
  | \_skip | int | - | skips the n-first items of the result list in paginated data presentation. |
833
+ | \_sort | string | - | give the list of sorting fields |
833
834
  | \_total | whatyouwant | None | Just compute the total of object and return { 'total' : x } without taking pagination in account |
834
835
 
835
836
 
@@ -845,9 +846,9 @@ The request returns a HTTP status `200` with that JSON object:
845
846
  ```
846
847
 
847
848
  ##### Example
848
- Select all users whose name includes 'do' and present the result list with 10 items per page.
849
+ Select all users whose name includes 'do' and present the result list with 10 items per page, sorted by surname.
849
850
  ```bash
850
- curl -X GET 'http://localhost/myApp/users/?name.$re=do&_page=10'
851
+ curl -X GET 'http://localhost/myApp/users/?name.$re=do&_page=10&_sort=$.surname'
851
852
  ```
852
853
 
853
854
  #### GET \<my-app-name\>/\<collection name\>/\<_id\>/\<path\>
@@ -1431,6 +1432,11 @@ log = log_system.get_or_create_logger("custom")
1431
1432
  log.setLevel(logging.DEBUG)
1432
1433
  log.addHandler ( my_own_handler )
1433
1434
  # ...
1435
+
1436
+ # To see
1437
+ log_system.infos()
1438
+ # print some available informations about log system (levels, handlers)
1439
+
1434
1440
  ```
1435
1441
 
1436
1442
  ### stack()
@@ -1506,7 +1512,7 @@ def transform_function( o: dict) -> dict:
1506
1512
  ```
1507
1513
 
1508
1514
 
1509
- By default, the flag ```dry_run``` is ```True```. so you will broke nothing. ```dry_run``` will do all work except saving the object in the DB.
1515
+ By default, the strategy for migration is ```MigrationStrategy.DRY_RUN```. So you will broke nothing. ```MigrationStrategy.DRY_RUN``` will do all work except saving the object in the DB.
1510
1516
 
1511
1517
  > [!IMPORTANT]
1512
1518
  > there is no check of *rights* and *current_user* during migration. metadatas (see [_meta](#_meta)) are not updated.
@@ -1523,7 +1529,7 @@ This is an example for migrating data.
1523
1529
 
1524
1530
  ```python
1525
1531
  from media_library import mybackoffice
1526
- from backo import log_system, LogLevel
1532
+ from backo import log_system, LogLevel, MigrationStrategy
1527
1533
 
1528
1534
  # Set migration level to debug
1529
1535
  log_migration = log_system.get_or_create_logger("migration")
@@ -1563,13 +1569,24 @@ report = mybackoffice.migrate("books", update_with_note) # All ids
1563
1569
  report = mybackoffice.migrate("books", update_with_note, _id="my_book_id", dry_run=False)
1564
1570
  # or
1565
1571
  report = mybackoffice.migrate(
1566
- "books", update_with_note, _ids=["my_book_id1", "my_book_id2"], dry_run=False
1572
+ "books", update_with_note, _ids=["my_book_id1", "my_book_id2"], strategy=MigrationStrategy.EXECUTE
1567
1573
  )
1568
1574
  # or
1569
- report = mybackoffice.migrate("books", update_with_note, dry_run=False) # All ids
1575
+ report = mybackoffice.migrate("books", update_with_note, strategy=MigrationStrategy.EXECUTE) # All ids
1570
1576
 
1571
1577
  ```
1572
1578
 
1579
+ ### MigrationStrategy options
1580
+
1581
+ | option | description |
1582
+ | - | - |
1583
+ | ```MigrationStrategy.DRY_RUN``` | Don't change anything, just display and report diffs |
1584
+ | ```MigrationStrategy.EXECUTE``` | Do changements and save in DB if needed. report diffs |
1585
+ | ```MigrationStrategy.FORCE``` | Do changements and rewrite data in DB. report diffs |
1586
+
1587
+
1588
+
1589
+
1573
1590
  ### report
1574
1591
 
1575
1592
  The migration returns a report structure :
@@ -20,6 +20,7 @@ from .error import (
20
20
  BackoError,
21
21
  SessionError,
22
22
  FileError,
23
+ ExpiredError,
23
24
  )
24
25
  from .backoffice import Backoffice
25
26
  from .collection import Collection
@@ -37,7 +38,7 @@ from .file.blob_file import BlobFile
37
38
  from .meta_data_handler import GenericMetaDataHandler, StandardMetaDataHandler
38
39
  from .status import StatusType
39
40
  from .action import Action
40
- from .migration_report import MigrationReport
41
+ from .migration import MigrationReport, MigrationStrategy
41
42
  from .request_decorators import (
42
43
  check_content_type,
43
44
  return_http_error,
@@ -48,4 +49,5 @@ from .api_toolbox import (
48
49
  multidict_to_sfilter,
49
50
  dict_to_sfilter,
50
51
  )
52
+ from .sort import SortItem, Sort
51
53
  from .initialisation.init_script import backo_init
@@ -15,7 +15,7 @@ from stricto import Kparse, SSyntaxError, validation_parameters
15
15
 
16
16
  from .collection import Collection
17
17
  from .item import Item
18
- from .migration_report import MigrationReport
18
+ from .migration import MigrationReport, MigrationStrategy
19
19
  from .log import log_system
20
20
  from .openapi import BACKO_FILTER_SCHEMA, BACKO_META_SCHEMA, JSON_PATCH_SCHEMA
21
21
  from .request_decorators import error_to_http_handler
@@ -27,6 +27,7 @@ KPARSE_MIGRATION_MODEL = {
27
27
  "_id": str,
28
28
  "_ids": list[str],
29
29
  "dry_run": {"type": bool, "default": True},
30
+ "strategy": {"type": MigrationStrategy, "default": MigrationStrategy.DRY_RUN},
30
31
  }
31
32
 
32
33
 
@@ -56,9 +57,9 @@ class Backoffice: # pylint: disable=too-many-instance-attributes
56
57
  def __init__(self, name: str):
57
58
  """Constructor for backoffice"""
58
59
  self.name = name
59
- self.collections = {}
60
+ self.collections: dict[str, Collection] = {}
60
61
  self._transaction_id_reference = 1
61
- self.transactions = {}
62
+ self.transactions: dict[int, list[Transaction]] = {}
62
63
 
63
64
  @validation_parameters
64
65
  def register_collection(self, coll: Collection) -> None:
@@ -169,8 +170,15 @@ class Backoffice: # pylint: disable=too-many-instance-attributes
169
170
  if _ids is None and options.get("_id") is not None:
170
171
  _ids = [options.get("_id")]
171
172
 
173
+ strategy: MigrationStrategy = options.get("strategy")
174
+ if strategy not in MigrationStrategy:
175
+ raise SSyntaxError(
176
+ 'Migration Strategy "{0}" not found',
177
+ strategy,
178
+ )
179
+
172
180
  coll = self.collections.get(collection_name)
173
- return coll.migrate(migration_function, _ids, options.get("dry_run"))
181
+ return coll.migrate(migration_function, _ids, strategy)
174
182
 
175
183
  @validation_parameters
176
184
  def build_routes(