GeneralManager 0.14.0__tar.gz → 0.15.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.
- generalmanager-0.15.0/LICENSE +21 -0
- {generalmanager-0.14.0/GeneralManager.egg-info → generalmanager-0.15.0}/PKG-INFO +38 -4
- {generalmanager-0.14.0 → generalmanager-0.15.0}/README.md +7 -1
- {generalmanager-0.14.0 → generalmanager-0.15.0}/pyproject.toml +14 -5
- {generalmanager-0.14.0 → generalmanager-0.15.0/src/GeneralManager.egg-info}/PKG-INFO +38 -4
- {generalmanager-0.14.0 → generalmanager-0.15.0/src}/GeneralManager.egg-info/SOURCES.txt +9 -5
- {generalmanager-0.14.0 → generalmanager-0.15.0/src}/GeneralManager.egg-info/requires.txt +1 -1
- generalmanager-0.15.0/src/general_manager/__init__.py +49 -0
- generalmanager-0.15.0/src/general_manager/api/__init__.py +36 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/api/graphql.py +92 -43
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/api/mutation.py +35 -10
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/api/property.py +26 -3
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/apps.py +23 -16
- generalmanager-0.15.0/src/general_manager/bucket/__init__.py +32 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/bucket/baseBucket.py +76 -64
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/bucket/calculationBucket.py +188 -108
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/bucket/databaseBucket.py +130 -49
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/bucket/groupBucket.py +113 -60
- generalmanager-0.15.0/src/general_manager/cache/__init__.py +38 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/cache/cacheDecorator.py +29 -17
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/cache/cacheTracker.py +34 -15
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/cache/dependencyIndex.py +117 -33
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/cache/modelDependencyCollector.py +17 -8
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/cache/signals.py +17 -6
- generalmanager-0.15.0/src/general_manager/factory/__init__.py +34 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/factory/autoFactory.py +57 -60
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/factory/factories.py +39 -14
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/factory/factoryMethods.py +38 -1
- generalmanager-0.15.0/src/general_manager/interface/__init__.py +36 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/interface/baseInterface.py +71 -27
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/interface/calculationInterface.py +18 -10
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/interface/databaseBasedInterface.py +102 -71
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/interface/databaseInterface.py +66 -20
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/interface/models.py +10 -4
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/interface/readOnlyInterface.py +44 -30
- generalmanager-0.15.0/src/general_manager/manager/__init__.py +36 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/manager/generalManager.py +73 -47
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/manager/groupManager.py +72 -17
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/manager/input.py +23 -15
- generalmanager-0.15.0/src/general_manager/manager/meta.py +127 -0
- generalmanager-0.15.0/src/general_manager/measurement/__init__.py +37 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/measurement/measurement.py +135 -58
- generalmanager-0.15.0/src/general_manager/measurement/measurementField.py +371 -0
- generalmanager-0.15.0/src/general_manager/permission/__init__.py +32 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/permission/basePermission.py +29 -12
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/permission/managerBasedPermission.py +32 -26
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/permission/mutationPermission.py +32 -3
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/permission/permissionChecks.py +9 -1
- generalmanager-0.15.0/src/general_manager/permission/permissionDataManager.py +85 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/permission/utils.py +14 -3
- generalmanager-0.15.0/src/general_manager/rule/__init__.py +27 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/rule/handler.py +90 -5
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/rule/rule.py +40 -27
- generalmanager-0.15.0/src/general_manager/utils/__init__.py +44 -0
- generalmanager-0.15.0/src/general_manager/utils/argsToKwargs.py +33 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/utils/filterParser.py +29 -30
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/utils/formatString.py +2 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/utils/jsonEncoder.py +14 -1
- generalmanager-0.15.0/src/general_manager/utils/makeCacheKey.py +39 -0
- generalmanager-0.15.0/src/general_manager/utils/noneToZero.py +23 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/utils/pathMapping.py +92 -29
- generalmanager-0.15.0/src/general_manager/utils/public_api.py +49 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/utils/testing.py +135 -69
- generalmanager-0.14.0/LICENSE +0 -29
- generalmanager-0.14.0/src/general_manager/__init__.py +0 -0
- generalmanager-0.14.0/src/general_manager/factory/__init__.py +0 -5
- generalmanager-0.14.0/src/general_manager/interface/__init__.py +0 -0
- generalmanager-0.14.0/src/general_manager/manager/__init__.py +0 -3
- generalmanager-0.14.0/src/general_manager/manager/meta.py +0 -127
- generalmanager-0.14.0/src/general_manager/measurement/__init__.py +0 -2
- generalmanager-0.14.0/src/general_manager/measurement/measurementField.py +0 -271
- generalmanager-0.14.0/src/general_manager/permission/__init__.py +0 -1
- generalmanager-0.14.0/src/general_manager/permission/permissionDataManager.py +0 -51
- generalmanager-0.14.0/src/general_manager/rule/__init__.py +0 -1
- generalmanager-0.14.0/src/general_manager/utils/__init__.py +0 -2
- generalmanager-0.14.0/src/general_manager/utils/argsToKwargs.py +0 -25
- generalmanager-0.14.0/src/general_manager/utils/makeCacheKey.py +0 -33
- generalmanager-0.14.0/src/general_manager/utils/noneToZero.py +0 -21
- {generalmanager-0.14.0 → generalmanager-0.15.0}/setup.cfg +0 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0/src}/GeneralManager.egg-info/dependency_links.txt +0 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0/src}/GeneralManager.egg-info/top_level.txt +0 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/src/general_manager/permission/fileBasedPermission.py +0 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/tests/test_settings.py +0 -0
- {generalmanager-0.14.0 → generalmanager-0.15.0}/tests/test_urls.py +0 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Tim Kleindick
|
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.
|
@@ -1,14 +1,42 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: GeneralManager
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.15.0
|
4
4
|
Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
|
5
5
|
Author-email: Tim Kleindick <tkleindick@yahoo.de>
|
6
|
-
License
|
6
|
+
License: MIT License
|
7
|
+
|
8
|
+
Copyright (c) 2025 Tim Kleindick
|
9
|
+
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
12
|
+
in the Software without restriction, including without limitation the rights
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
15
|
+
furnished to do so, subject to the following conditions:
|
16
|
+
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
18
|
+
copies or substantial portions of the Software.
|
19
|
+
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
|
+
SOFTWARE.
|
27
|
+
Classifier: License :: OSI Approved :: MIT License
|
28
|
+
Classifier: Programming Language :: Python :: 3
|
29
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
30
|
+
Classifier: Programming Language :: Python :: 3.12
|
31
|
+
Classifier: Programming Language :: Python :: 3.13
|
32
|
+
Classifier: Framework :: Django
|
33
|
+
Classifier: Intended Audience :: Developers
|
34
|
+
Classifier: Operating System :: OS Independent
|
7
35
|
Requires-Python: >=3.12
|
8
36
|
Description-Content-Type: text/markdown
|
9
37
|
License-File: LICENSE
|
10
38
|
Requires-Dist: asgiref>=3.8.1
|
11
|
-
Requires-Dist: Django>=5.2
|
39
|
+
Requires-Dist: Django>=5.2.7
|
12
40
|
Requires-Dist: django-simple-history>=3.8.0
|
13
41
|
Requires-Dist: exrex>=0.12.0
|
14
42
|
Requires-Dist: factory_boy>=3.3.3
|
@@ -37,6 +65,12 @@ Dynamic: license-file
|
|
37
65
|
|
38
66
|
# GeneralManager
|
39
67
|
|
68
|
+
[](https://pypi.org/project/GeneralManager/)
|
69
|
+
[](https://pypi.org/project/GeneralManager/)
|
70
|
+
[](https://github.com/TimKleindick/general_manager/actions/workflows/test.yml)
|
71
|
+
[](https://app.codecov.io/gh/TimKleindick/general_manager)
|
72
|
+
[](LICENSE)
|
73
|
+
|
40
74
|
## Overview
|
41
75
|
|
42
76
|
GeneralManager is a powerful and flexible framework designed for managing and processing data. It provides a modular structure that enables developers to implement complex business logic efficiently. The module is written entirely in Python and uses Django as the backend framework.
|
@@ -176,4 +210,4 @@ query {
|
|
176
210
|
|
177
211
|
## License
|
178
212
|
|
179
|
-
This project is distributed under the **
|
213
|
+
This project is distributed under the **MIT License**. For further details see the [LICENSE](./LICENSE) file.
|
@@ -1,5 +1,11 @@
|
|
1
1
|
# GeneralManager
|
2
2
|
|
3
|
+
[](https://pypi.org/project/GeneralManager/)
|
4
|
+
[](https://pypi.org/project/GeneralManager/)
|
5
|
+
[](https://github.com/TimKleindick/general_manager/actions/workflows/test.yml)
|
6
|
+
[](https://app.codecov.io/gh/TimKleindick/general_manager)
|
7
|
+
[](LICENSE)
|
8
|
+
|
3
9
|
## Overview
|
4
10
|
|
5
11
|
GeneralManager is a powerful and flexible framework designed for managing and processing data. It provides a modular structure that enables developers to implement complex business logic efficiently. The module is written entirely in Python and uses Django as the backend framework.
|
@@ -139,4 +145,4 @@ query {
|
|
139
145
|
|
140
146
|
## License
|
141
147
|
|
142
|
-
This project is distributed under the **
|
148
|
+
This project is distributed under the **MIT License**. For further details see the [LICENSE](./LICENSE) file.
|
@@ -4,16 +4,25 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "GeneralManager"
|
7
|
-
version = "0.
|
7
|
+
version = "0.15.0"
|
8
8
|
description = "Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching."
|
9
9
|
readme = "README.md"
|
10
10
|
authors = [{ name = "Tim Kleindick", email = "tkleindick@yahoo.de" }]
|
11
|
-
license = "
|
12
|
-
|
11
|
+
license = { file = "LICENSE" }
|
12
|
+
classifiers = [
|
13
|
+
"License :: OSI Approved :: MIT License",
|
14
|
+
"Programming Language :: Python :: 3",
|
15
|
+
"Programming Language :: Python :: 3 :: Only",
|
16
|
+
"Programming Language :: Python :: 3.12",
|
17
|
+
"Programming Language :: Python :: 3.13",
|
18
|
+
"Framework :: Django",
|
19
|
+
"Intended Audience :: Developers",
|
20
|
+
"Operating System :: OS Independent",
|
21
|
+
]
|
13
22
|
requires-python = ">=3.12"
|
14
23
|
dependencies = [
|
15
24
|
"asgiref>=3.8.1",
|
16
|
-
"Django>=5.2",
|
25
|
+
"Django>=5.2.7",
|
17
26
|
"django-simple-history>=3.8.0",
|
18
27
|
"exrex>=0.12.0",
|
19
28
|
"factory_boy>=3.3.3",
|
@@ -41,7 +50,7 @@ dependencies = [
|
|
41
50
|
]
|
42
51
|
|
43
52
|
[tool.setuptools.packages.find]
|
44
|
-
where = ["src"
|
53
|
+
where = ["src"]
|
45
54
|
|
46
55
|
[tool.semantic_release]
|
47
56
|
allow_zero_version = true
|
@@ -1,14 +1,42 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: GeneralManager
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.15.0
|
4
4
|
Summary: Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching.
|
5
5
|
Author-email: Tim Kleindick <tkleindick@yahoo.de>
|
6
|
-
License
|
6
|
+
License: MIT License
|
7
|
+
|
8
|
+
Copyright (c) 2025 Tim Kleindick
|
9
|
+
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
12
|
+
in the Software without restriction, including without limitation the rights
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
15
|
+
furnished to do so, subject to the following conditions:
|
16
|
+
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
18
|
+
copies or substantial portions of the Software.
|
19
|
+
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
|
+
SOFTWARE.
|
27
|
+
Classifier: License :: OSI Approved :: MIT License
|
28
|
+
Classifier: Programming Language :: Python :: 3
|
29
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
30
|
+
Classifier: Programming Language :: Python :: 3.12
|
31
|
+
Classifier: Programming Language :: Python :: 3.13
|
32
|
+
Classifier: Framework :: Django
|
33
|
+
Classifier: Intended Audience :: Developers
|
34
|
+
Classifier: Operating System :: OS Independent
|
7
35
|
Requires-Python: >=3.12
|
8
36
|
Description-Content-Type: text/markdown
|
9
37
|
License-File: LICENSE
|
10
38
|
Requires-Dist: asgiref>=3.8.1
|
11
|
-
Requires-Dist: Django>=5.2
|
39
|
+
Requires-Dist: Django>=5.2.7
|
12
40
|
Requires-Dist: django-simple-history>=3.8.0
|
13
41
|
Requires-Dist: exrex>=0.12.0
|
14
42
|
Requires-Dist: factory_boy>=3.3.3
|
@@ -37,6 +65,12 @@ Dynamic: license-file
|
|
37
65
|
|
38
66
|
# GeneralManager
|
39
67
|
|
68
|
+
[](https://pypi.org/project/GeneralManager/)
|
69
|
+
[](https://pypi.org/project/GeneralManager/)
|
70
|
+
[](https://github.com/TimKleindick/general_manager/actions/workflows/test.yml)
|
71
|
+
[](https://app.codecov.io/gh/TimKleindick/general_manager)
|
72
|
+
[](LICENSE)
|
73
|
+
|
40
74
|
## Overview
|
41
75
|
|
42
76
|
GeneralManager is a powerful and flexible framework designed for managing and processing data. It provides a modular structure that enables developers to implement complex business logic efficiently. The module is written entirely in Python and uses Django as the backend framework.
|
@@ -176,4 +210,4 @@ query {
|
|
176
210
|
|
177
211
|
## License
|
178
212
|
|
179
|
-
This project is distributed under the **
|
213
|
+
This project is distributed under the **MIT License**. For further details see the [LICENSE](./LICENSE) file.
|
@@ -1,20 +1,23 @@
|
|
1
1
|
LICENSE
|
2
2
|
README.md
|
3
3
|
pyproject.toml
|
4
|
-
GeneralManager.egg-info/PKG-INFO
|
5
|
-
GeneralManager.egg-info/SOURCES.txt
|
6
|
-
GeneralManager.egg-info/dependency_links.txt
|
7
|
-
GeneralManager.egg-info/requires.txt
|
8
|
-
GeneralManager.egg-info/top_level.txt
|
4
|
+
src/GeneralManager.egg-info/PKG-INFO
|
5
|
+
src/GeneralManager.egg-info/SOURCES.txt
|
6
|
+
src/GeneralManager.egg-info/dependency_links.txt
|
7
|
+
src/GeneralManager.egg-info/requires.txt
|
8
|
+
src/GeneralManager.egg-info/top_level.txt
|
9
9
|
src/general_manager/__init__.py
|
10
10
|
src/general_manager/apps.py
|
11
|
+
src/general_manager/api/__init__.py
|
11
12
|
src/general_manager/api/graphql.py
|
12
13
|
src/general_manager/api/mutation.py
|
13
14
|
src/general_manager/api/property.py
|
15
|
+
src/general_manager/bucket/__init__.py
|
14
16
|
src/general_manager/bucket/baseBucket.py
|
15
17
|
src/general_manager/bucket/calculationBucket.py
|
16
18
|
src/general_manager/bucket/databaseBucket.py
|
17
19
|
src/general_manager/bucket/groupBucket.py
|
20
|
+
src/general_manager/cache/__init__.py
|
18
21
|
src/general_manager/cache/cacheDecorator.py
|
19
22
|
src/general_manager/cache/cacheTracker.py
|
20
23
|
src/general_manager/cache/dependencyIndex.py
|
@@ -58,6 +61,7 @@ src/general_manager/utils/jsonEncoder.py
|
|
58
61
|
src/general_manager/utils/makeCacheKey.py
|
59
62
|
src/general_manager/utils/noneToZero.py
|
60
63
|
src/general_manager/utils/pathMapping.py
|
64
|
+
src/general_manager/utils/public_api.py
|
61
65
|
src/general_manager/utils/testing.py
|
62
66
|
tests/test_settings.py
|
63
67
|
tests/test_urls.py
|
@@ -0,0 +1,49 @@
|
|
1
|
+
"""Convenience access to GeneralManager core components."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from typing import Any
|
6
|
+
|
7
|
+
from general_manager.utils.public_api import build_module_dir, resolve_export
|
8
|
+
|
9
|
+
__all__ = [
|
10
|
+
"GraphQL",
|
11
|
+
"GeneralManager",
|
12
|
+
"GeneralManagerMeta",
|
13
|
+
"Input",
|
14
|
+
"graphQlProperty",
|
15
|
+
"graphQlMutation",
|
16
|
+
"Bucket",
|
17
|
+
"DatabaseBucket",
|
18
|
+
"CalculationBucket",
|
19
|
+
"GroupBucket",
|
20
|
+
]
|
21
|
+
|
22
|
+
_MODULE_MAP = {
|
23
|
+
"GraphQL": ("general_manager.api.graphql", "GraphQL"),
|
24
|
+
"graphQlProperty": ("general_manager.api.property", "graphQlProperty"),
|
25
|
+
"graphQlMutation": ("general_manager.api.mutation", "graphQlMutation"),
|
26
|
+
"GeneralManager": ("general_manager.manager.generalManager", "GeneralManager"),
|
27
|
+
"GeneralManagerMeta": ("general_manager.manager.meta", "GeneralManagerMeta"),
|
28
|
+
"Input": ("general_manager.manager.input", "Input"),
|
29
|
+
"Bucket": ("general_manager.bucket.baseBucket", "Bucket"),
|
30
|
+
"DatabaseBucket": ("general_manager.bucket.databaseBucket", "DatabaseBucket"),
|
31
|
+
"CalculationBucket": (
|
32
|
+
"general_manager.bucket.calculationBucket",
|
33
|
+
"CalculationBucket",
|
34
|
+
),
|
35
|
+
"GroupBucket": ("general_manager.bucket.groupBucket", "GroupBucket"),
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
def __getattr__(name: str) -> Any:
|
40
|
+
return resolve_export(
|
41
|
+
name,
|
42
|
+
module_all=__all__,
|
43
|
+
module_map=_MODULE_MAP,
|
44
|
+
module_globals=globals(),
|
45
|
+
)
|
46
|
+
|
47
|
+
|
48
|
+
def __dir__() -> list[str]:
|
49
|
+
return build_module_dir(module_all=__all__, module_globals=globals())
|
@@ -0,0 +1,36 @@
|
|
1
|
+
"""GraphQL helpers for GeneralManager."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from typing import Any
|
6
|
+
|
7
|
+
from general_manager.utils.public_api import build_module_dir, resolve_export
|
8
|
+
|
9
|
+
__all__ = [
|
10
|
+
"GraphQL",
|
11
|
+
"MeasurementType",
|
12
|
+
"MeasurementScalar",
|
13
|
+
"graphQlProperty",
|
14
|
+
"graphQlMutation",
|
15
|
+
]
|
16
|
+
|
17
|
+
_MODULE_MAP = {
|
18
|
+
"GraphQL": ("general_manager.api.graphql", "GraphQL"),
|
19
|
+
"MeasurementType": ("general_manager.api.graphql", "MeasurementType"),
|
20
|
+
"MeasurementScalar": ("general_manager.api.graphql", "MeasurementScalar"),
|
21
|
+
"graphQlProperty": ("general_manager.api.property", "graphQlProperty"),
|
22
|
+
"graphQlMutation": ("general_manager.api.mutation", "graphQlMutation"),
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
def __getattr__(name: str) -> Any:
|
27
|
+
return resolve_export(
|
28
|
+
name,
|
29
|
+
module_all=__all__,
|
30
|
+
module_map=_MODULE_MAP,
|
31
|
+
module_globals=globals(),
|
32
|
+
)
|
33
|
+
|
34
|
+
|
35
|
+
def __dir__() -> list[str]:
|
36
|
+
return build_module_dir(module_all=__all__, module_globals=globals())
|
@@ -1,5 +1,7 @@
|
|
1
|
+
"""GraphQL schema utilities for exposing GeneralManager models via Graphene."""
|
2
|
+
|
1
3
|
from __future__ import annotations
|
2
|
-
import graphene
|
4
|
+
import graphene # type: ignore[import]
|
3
5
|
from typing import (
|
4
6
|
Any,
|
5
7
|
Callable,
|
@@ -73,9 +75,14 @@ def getReadPermissionFilter(
|
|
73
75
|
info: GraphQLResolveInfo,
|
74
76
|
) -> list[tuple[dict[str, Any], dict[str, Any]]]:
|
75
77
|
"""
|
76
|
-
|
78
|
+
Return permission-derived filter and exclude pairs for the given manager class.
|
79
|
+
|
80
|
+
Parameters:
|
81
|
+
generalManagerClass (GeneralManagerMeta): Manager class being queried.
|
82
|
+
info (GraphQLResolveInfo): GraphQL resolver info containing the request user.
|
77
83
|
|
78
|
-
|
84
|
+
Returns:
|
85
|
+
list[tuple[dict[str, Any], dict[str, Any]]]: List of ``(filter, exclude)`` mappings.
|
79
86
|
"""
|
80
87
|
filters = []
|
81
88
|
PermissionClass: type[BasePermission] | None = getattr(
|
@@ -93,10 +100,7 @@ def getReadPermissionFilter(
|
|
93
100
|
|
94
101
|
|
95
102
|
class GraphQL:
|
96
|
-
"""
|
97
|
-
Baut die GraphQL-Oberfläche auf und erstellt Resolver-Funktionen
|
98
|
-
dynamisch für die angegebene GeneralManager-Klasse.
|
99
|
-
"""
|
103
|
+
"""Static helper that builds GraphQL types, queries, and mutations for managers."""
|
100
104
|
|
101
105
|
_query_class: type[graphene.ObjectType] | None = None
|
102
106
|
_mutation_class: type[graphene.ObjectType] | None = None
|
@@ -109,16 +113,17 @@ class GraphQL:
|
|
109
113
|
@classmethod
|
110
114
|
def createGraphqlMutation(cls, generalManagerClass: type[GeneralManager]) -> None:
|
111
115
|
"""
|
112
|
-
|
116
|
+
Register create, update, and delete mutations for ``generalManagerClass``.
|
113
117
|
|
114
|
-
|
118
|
+
Parameters:
|
119
|
+
generalManagerClass (type[GeneralManager]): Manager class whose interface drives mutation generation.
|
115
120
|
"""
|
116
121
|
|
117
122
|
interface_cls: InterfaceBase | None = getattr(
|
118
123
|
generalManagerClass, "Interface", None
|
119
124
|
)
|
120
125
|
if not interface_cls:
|
121
|
-
return
|
126
|
+
return None
|
122
127
|
|
123
128
|
default_return_values = {
|
124
129
|
"success": graphene.Boolean(),
|
@@ -147,15 +152,16 @@ class GraphQL:
|
|
147
152
|
@classmethod
|
148
153
|
def createGraphqlInterface(cls, generalManagerClass: GeneralManagerMeta) -> None:
|
149
154
|
"""
|
150
|
-
|
155
|
+
Build and register a Graphene ``ObjectType`` for the supplied manager class.
|
151
156
|
|
152
|
-
|
157
|
+
Parameters:
|
158
|
+
generalManagerClass (GeneralManagerMeta): Manager class whose attributes drive field generation.
|
153
159
|
"""
|
154
160
|
interface_cls: InterfaceBase | None = getattr(
|
155
161
|
generalManagerClass, "Interface", None
|
156
162
|
)
|
157
163
|
if not interface_cls:
|
158
|
-
return
|
164
|
+
return None
|
159
165
|
|
160
166
|
graphene_type_name = f"{generalManagerClass.__name__}Type"
|
161
167
|
fields: dict[str, Any] = {}
|
@@ -217,10 +223,13 @@ class GraphQL:
|
|
217
223
|
generalManagerClass: GeneralManagerMeta,
|
218
224
|
) -> type[graphene.Enum] | None:
|
219
225
|
"""
|
220
|
-
|
226
|
+
Build an enum of sortable fields for the provided manager class.
|
227
|
+
|
228
|
+
Parameters:
|
229
|
+
generalManagerClass (GeneralManagerMeta): Manager class being inspected.
|
221
230
|
|
222
231
|
Returns:
|
223
|
-
|
232
|
+
type[graphene.Enum] | None: Enum of sortable fields, or ``None`` when no options exist.
|
224
233
|
"""
|
225
234
|
sort_options = []
|
226
235
|
for (
|
@@ -264,6 +273,16 @@ class GraphQL:
|
|
264
273
|
None,
|
265
274
|
None,
|
266
275
|
]:
|
276
|
+
"""
|
277
|
+
Yield filter field names and Graphene types for a given attribute.
|
278
|
+
|
279
|
+
Parameters:
|
280
|
+
attribute_type (type): Python type declared for the attribute.
|
281
|
+
attribute_name (str): Name of the attribute.
|
282
|
+
|
283
|
+
Yields:
|
284
|
+
tuple[str, Graphene type | None]: Filter name and corresponding Graphene type.
|
285
|
+
"""
|
267
286
|
number_options = ["exact", "gt", "gte", "lt", "lte"]
|
268
287
|
string_options = [
|
269
288
|
"exact",
|
@@ -306,22 +325,20 @@ class GraphQL:
|
|
306
325
|
field_type: GeneralManagerMeta,
|
307
326
|
) -> type[graphene.InputObjectType] | None:
|
308
327
|
"""
|
309
|
-
|
310
|
-
|
311
|
-
Creates filter fields for each attribute based on its type, supporting numeric and string filter operations, and specialized handling for Measurement attributes. Returns the generated InputObjectType, or None if no applicable filter fields exist.
|
328
|
+
Create a Graphene ``InputObjectType`` for filters on ``field_type``.
|
312
329
|
|
313
330
|
Parameters:
|
314
|
-
field_type (GeneralManagerMeta):
|
331
|
+
field_type (GeneralManagerMeta): Manager class whose attributes drive filter generation.
|
315
332
|
|
316
333
|
Returns:
|
317
|
-
type[graphene.InputObjectType] | None:
|
334
|
+
type[graphene.InputObjectType] | None: Input type containing filter fields, or ``None`` if not applicable.
|
318
335
|
"""
|
319
336
|
|
320
337
|
graphene_filter_type_name = f"{field_type.__name__}FilterType"
|
321
338
|
if graphene_filter_type_name in GraphQL.graphql_filter_type_registry:
|
322
339
|
return GraphQL.graphql_filter_type_registry[graphene_filter_type_name]
|
323
340
|
|
324
|
-
filter_fields = {}
|
341
|
+
filter_fields: dict[str, Any] = {}
|
325
342
|
for attr_name, attr_info in field_type.Interface.getAttributeTypes().items():
|
326
343
|
attr_type = attr_info["type"]
|
327
344
|
filter_fields = {
|
@@ -360,9 +377,14 @@ class GraphQL:
|
|
360
377
|
@staticmethod
|
361
378
|
def _mapFieldToGrapheneRead(field_type: type, field_name: str) -> Any:
|
362
379
|
"""
|
363
|
-
|
380
|
+
Map a field type and name to the appropriate Graphene field for reads.
|
364
381
|
|
365
|
-
|
382
|
+
Parameters:
|
383
|
+
field_type (type): Python type declared on the interface.
|
384
|
+
field_name (str): Attribute name being exposed.
|
385
|
+
|
386
|
+
Returns:
|
387
|
+
Any: Graphene field or type configured for the attribute.
|
366
388
|
"""
|
367
389
|
if issubclass(field_type, Measurement):
|
368
390
|
return graphene.Field(MeasurementType, target_unit=graphene.String())
|
@@ -398,7 +420,13 @@ class GraphQL:
|
|
398
420
|
@staticmethod
|
399
421
|
def _mapFieldToGrapheneBaseType(field_type: type) -> Type[Any]:
|
400
422
|
"""
|
401
|
-
|
423
|
+
Map a Python type to the corresponding Graphene scalar/class.
|
424
|
+
|
425
|
+
Parameters:
|
426
|
+
field_type (type): Python type declared on the interface.
|
427
|
+
|
428
|
+
Returns:
|
429
|
+
Type[Any]: Graphene scalar or type implementing the field.
|
402
430
|
"""
|
403
431
|
if issubclass(field_type, dict):
|
404
432
|
raise TypeError("GraphQL does not support dict fields")
|
@@ -422,7 +450,13 @@ class GraphQL:
|
|
422
450
|
@staticmethod
|
423
451
|
def _parseInput(input_val: dict[str, Any] | str | None) -> dict[str, Any]:
|
424
452
|
"""
|
425
|
-
|
453
|
+
Normalise filter/exclude input into a dictionary.
|
454
|
+
|
455
|
+
Parameters:
|
456
|
+
input_val (dict[str, Any] | str | None): Raw filter/exclude value.
|
457
|
+
|
458
|
+
Returns:
|
459
|
+
dict[str, Any]: Parsed dictionary suitable for queryset filtering.
|
426
460
|
"""
|
427
461
|
if input_val is None:
|
428
462
|
return {}
|
@@ -474,10 +508,15 @@ class GraphQL:
|
|
474
508
|
info: GraphQLResolveInfo,
|
475
509
|
) -> Bucket:
|
476
510
|
"""
|
477
|
-
|
511
|
+
Apply permission-based filters to ``queryset`` for the current user.
|
512
|
+
|
513
|
+
Parameters:
|
514
|
+
queryset (Bucket): Queryset being filtered.
|
515
|
+
general_manager_class (type[GeneralManager]): Manager class providing permissions.
|
516
|
+
info (GraphQLResolveInfo): Resolver info containing the request user.
|
478
517
|
|
479
518
|
Returns:
|
480
|
-
|
519
|
+
Bucket: Queryset constrained by read permissions.
|
481
520
|
"""
|
482
521
|
permission_filters = getReadPermissionFilter(general_manager_class, info)
|
483
522
|
if not permission_filters:
|
@@ -494,9 +533,7 @@ class GraphQL:
|
|
494
533
|
def _checkReadPermission(
|
495
534
|
instance: GeneralManager, info: GraphQLResolveInfo, field_name: str
|
496
535
|
) -> bool:
|
497
|
-
"""
|
498
|
-
Überprüft, ob der Benutzer Lesezugriff auf das jeweilige Feld hat.
|
499
|
-
"""
|
536
|
+
"""Return True if the user may read ``field_name`` on ``instance``."""
|
500
537
|
PermissionClass: type[BasePermission] | None = getattr(
|
501
538
|
instance, "Permission", None
|
502
539
|
)
|
@@ -511,9 +548,14 @@ class GraphQL:
|
|
511
548
|
base_getter: Callable[[Any], Any], fallback_manager_class: type[GeneralManager]
|
512
549
|
) -> Callable[..., Any]:
|
513
550
|
"""
|
514
|
-
|
551
|
+
Build a resolver for list fields applying filters, permissions, and paging.
|
515
552
|
|
516
|
-
|
553
|
+
Parameters:
|
554
|
+
base_getter (Callable[[Any], Any]): Callable returning the base queryset.
|
555
|
+
fallback_manager_class (type[GeneralManager]): Manager used when ``base_getter`` returns ``None``.
|
556
|
+
|
557
|
+
Returns:
|
558
|
+
Callable[..., Any]: Resolver function compatible with Graphene.
|
517
559
|
"""
|
518
560
|
|
519
561
|
def resolver(
|
@@ -691,9 +733,11 @@ class GraphQL:
|
|
691
733
|
cls, graphene_type: type, generalManagerClass: GeneralManagerMeta
|
692
734
|
) -> None:
|
693
735
|
"""
|
694
|
-
|
736
|
+
Register list and detail query fields for ``generalManagerClass``.
|
695
737
|
|
696
|
-
|
738
|
+
Parameters:
|
739
|
+
graphene_type (type): Graphene ``ObjectType`` representing the manager.
|
740
|
+
generalManagerClass (GeneralManagerMeta): Manager class being exposed.
|
697
741
|
"""
|
698
742
|
if not issubclass(generalManagerClass, GeneralManager):
|
699
743
|
raise TypeError(
|
@@ -701,7 +745,7 @@ class GraphQL:
|
|
701
745
|
)
|
702
746
|
|
703
747
|
if not hasattr(cls, "_query_fields"):
|
704
|
-
cls._query_fields
|
748
|
+
cls._query_fields = cast(dict[str, Any], {})
|
705
749
|
|
706
750
|
# resolver and field for the list query
|
707
751
|
list_field_name = f"{generalManagerClass.__name__.lower()}_list"
|
@@ -761,12 +805,13 @@ class GraphQL:
|
|
761
805
|
@classmethod
|
762
806
|
def createWriteFields(cls, interface_cls: InterfaceBase) -> dict[str, Any]:
|
763
807
|
"""
|
764
|
-
|
808
|
+
Generate Graphene input fields for writable interface attributes.
|
765
809
|
|
766
|
-
|
810
|
+
Parameters:
|
811
|
+
interface_cls (InterfaceBase): Interface whose attributes drive the input field map.
|
767
812
|
|
768
813
|
Returns:
|
769
|
-
dict[str, Any]: Mapping of attribute names to Graphene
|
814
|
+
dict[str, Any]: Mapping of attribute names to Graphene field definitions.
|
770
815
|
"""
|
771
816
|
fields: dict[str, Any] = {}
|
772
817
|
|
@@ -827,7 +872,7 @@ class GraphQL:
|
|
827
872
|
generalManagerClass, "Interface", None
|
828
873
|
)
|
829
874
|
if not interface_cls:
|
830
|
-
return
|
875
|
+
return None
|
831
876
|
|
832
877
|
def create_mutation(
|
833
878
|
self,
|
@@ -898,7 +943,7 @@ class GraphQL:
|
|
898
943
|
generalManagerClass, "Interface", None
|
899
944
|
)
|
900
945
|
if not interface_cls:
|
901
|
-
return
|
946
|
+
return None
|
902
947
|
|
903
948
|
def update_mutation(
|
904
949
|
self,
|
@@ -975,7 +1020,7 @@ class GraphQL:
|
|
975
1020
|
generalManagerClass, "Interface", None
|
976
1021
|
)
|
977
1022
|
if not interface_cls:
|
978
|
-
return
|
1023
|
+
return None
|
979
1024
|
|
980
1025
|
def delete_mutation(
|
981
1026
|
self,
|
@@ -1030,9 +1075,13 @@ class GraphQL:
|
|
1030
1075
|
@staticmethod
|
1031
1076
|
def _handleGraphQLError(error: Exception) -> None:
|
1032
1077
|
"""
|
1033
|
-
|
1078
|
+
Raise a ``GraphQLError`` with a code based on the exception type.
|
1079
|
+
|
1080
|
+
Parameters:
|
1081
|
+
error (Exception): Exception raised during mutation execution.
|
1034
1082
|
|
1035
|
-
|
1083
|
+
Raises:
|
1084
|
+
GraphQLError: Error with an appropriate ``extensions['code']`` value.
|
1036
1085
|
"""
|
1037
1086
|
if isinstance(error, PermissionError):
|
1038
1087
|
raise GraphQLError(
|