GeneralManager 0.19.0__py3-none-any.whl → 0.19.2__py3-none-any.whl
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.
Potentially problematic release.
This version of GeneralManager might be problematic. Click here for more details.
- general_manager/_types/api.py +4 -4
- general_manager/_types/bucket.py +4 -4
- general_manager/_types/cache.py +6 -6
- general_manager/_types/factory.py +35 -35
- general_manager/_types/general_manager.py +9 -9
- general_manager/_types/interface.py +5 -5
- general_manager/_types/manager.py +4 -4
- general_manager/_types/measurement.py +1 -1
- general_manager/_types/permission.py +3 -3
- general_manager/_types/utils.py +12 -12
- general_manager/api/graphql.py +118 -95
- general_manager/api/mutation.py +9 -9
- general_manager/api/property.py +4 -4
- general_manager/apps.py +31 -31
- general_manager/bucket/{baseBucket.py → base_bucket.py} +5 -5
- general_manager/bucket/{calculationBucket.py → calculation_bucket.py} +10 -10
- general_manager/bucket/{databaseBucket.py → database_bucket.py} +16 -19
- general_manager/bucket/{groupBucket.py → group_bucket.py} +8 -8
- general_manager/cache/{cacheDecorator.py → cache_decorator.py} +5 -5
- general_manager/cache/{cacheTracker.py → cache_tracker.py} +1 -1
- general_manager/cache/{dependencyIndex.py → dependency_index.py} +1 -1
- general_manager/cache/{modelDependencyCollector.py → model_dependency_collector.py} +4 -4
- general_manager/cache/signals.py +1 -1
- general_manager/factory/{autoFactory.py → auto_factory.py} +24 -19
- general_manager/factory/factories.py +10 -13
- general_manager/factory/{factoryMethods.py → factory_methods.py} +19 -17
- general_manager/interface/{baseInterface.py → base_interface.py} +29 -21
- general_manager/interface/{calculationInterface.py → calculation_interface.py} +10 -10
- general_manager/interface/{databaseBasedInterface.py → database_based_interface.py} +42 -42
- general_manager/interface/{databaseInterface.py → database_interface.py} +15 -15
- general_manager/interface/models.py +3 -3
- general_manager/interface/{readOnlyInterface.py → read_only_interface.py} +12 -12
- general_manager/manager/{generalManager.py → general_manager.py} +11 -11
- general_manager/manager/{groupManager.py → group_manager.py} +6 -6
- general_manager/manager/input.py +1 -1
- general_manager/manager/meta.py +15 -15
- general_manager/measurement/measurement.py +3 -3
- general_manager/permission/{basePermission.py → base_permission.py} +21 -21
- general_manager/permission/{managerBasedPermission.py → manager_based_permission.py} +21 -21
- general_manager/permission/{mutationPermission.py → mutation_permission.py} +12 -12
- general_manager/permission/{permissionChecks.py → permission_checks.py} +2 -2
- general_manager/permission/{permissionDataManager.py → permission_data_manager.py} +6 -6
- general_manager/permission/utils.py +6 -6
- general_manager/public_api_registry.py +75 -66
- general_manager/rule/handler.py +2 -2
- general_manager/rule/rule.py +17 -11
- general_manager/utils/{filterParser.py → filter_parser.py} +3 -3
- general_manager/utils/{jsonEncoder.py → json_encoder.py} +1 -1
- general_manager/utils/{makeCacheKey.py → make_cache_key.py} +1 -1
- general_manager/utils/{noneToZero.py → none_to_zero.py} +1 -1
- general_manager/utils/{pathMapping.py → path_mapping.py} +14 -14
- general_manager/utils/testing.py +14 -14
- {generalmanager-0.19.0.dist-info → generalmanager-0.19.2.dist-info}/METADATA +1 -1
- generalmanager-0.19.2.dist-info/RECORD +77 -0
- generalmanager-0.19.0.dist-info/RECORD +0 -77
- /general_manager/measurement/{measurementField.py → measurement_field.py} +0 -0
- /general_manager/permission/{fileBasedPermission.py → file_based_permission.py} +0 -0
- /general_manager/utils/{argsToKwargs.py → args_to_kwargs.py} +0 -0
- /general_manager/utils/{formatString.py → format_string.py} +0 -0
- {generalmanager-0.19.0.dist-info → generalmanager-0.19.2.dist-info}/WHEEL +0 -0
- {generalmanager-0.19.0.dist-info → generalmanager-0.19.2.dist-info}/licenses/LICENSE +0 -0
- {generalmanager-0.19.0.dist-info → generalmanager-0.19.2.dist-info}/top_level.txt +0 -0
|
@@ -14,24 +14,24 @@ LazyExportMap = Mapping[str, str | tuple[str, str]]
|
|
|
14
14
|
|
|
15
15
|
GENERAL_MANAGER_EXPORTS: LazyExportMap = {
|
|
16
16
|
"GraphQL": ("general_manager.api.graphql", "GraphQL"),
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"GeneralManager": ("general_manager.manager.
|
|
17
|
+
"graph_ql_property": ("general_manager.api.property", "graph_ql_property"),
|
|
18
|
+
"graph_ql_mutation": ("general_manager.api.mutation", "graph_ql_mutation"),
|
|
19
|
+
"GeneralManager": ("general_manager.manager.general_manager", "GeneralManager"),
|
|
20
20
|
"Input": ("general_manager.manager.input", "Input"),
|
|
21
21
|
"CalculationInterface": (
|
|
22
|
-
"general_manager.interface.
|
|
22
|
+
"general_manager.interface.calculation_interface",
|
|
23
23
|
"CalculationInterface",
|
|
24
24
|
),
|
|
25
25
|
"DatabaseInterface": (
|
|
26
|
-
"general_manager.interface.
|
|
26
|
+
"general_manager.interface.database_interface",
|
|
27
27
|
"DatabaseInterface",
|
|
28
28
|
),
|
|
29
29
|
"ReadOnlyInterface": (
|
|
30
|
-
"general_manager.interface.
|
|
30
|
+
"general_manager.interface.read_only_interface",
|
|
31
31
|
"ReadOnlyInterface",
|
|
32
32
|
),
|
|
33
33
|
"ManagerBasedPermission": (
|
|
34
|
-
"general_manager.permission.
|
|
34
|
+
"general_manager.permission.manager_based_permission",
|
|
35
35
|
"ManagerBasedPermission",
|
|
36
36
|
),
|
|
37
37
|
"Rule": ("general_manager.rule.rule", "Rule"),
|
|
@@ -42,36 +42,45 @@ API_EXPORTS: LazyExportMap = {
|
|
|
42
42
|
"GraphQL": ("general_manager.api.graphql", "GraphQL"),
|
|
43
43
|
"MeasurementType": ("general_manager.api.graphql", "MeasurementType"),
|
|
44
44
|
"MeasurementScalar": ("general_manager.api.graphql", "MeasurementScalar"),
|
|
45
|
-
"
|
|
46
|
-
"
|
|
45
|
+
"graph_ql_property": ("general_manager.api.property", "graph_ql_property"),
|
|
46
|
+
"graph_ql_mutation": ("general_manager.api.mutation", "graph_ql_mutation"),
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
FACTORY_EXPORTS: LazyExportMap = {
|
|
51
|
-
"AutoFactory": ("general_manager.factory.
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
),
|
|
73
|
-
"
|
|
74
|
-
"
|
|
51
|
+
"AutoFactory": ("general_manager.factory.auto_factory", "AutoFactory"),
|
|
52
|
+
"lazy_measurement": ("general_manager.factory.factory_methods", "lazy_measurement"),
|
|
53
|
+
"lazy_delta_date": ("general_manager.factory.factory_methods", "lazy_delta_date"),
|
|
54
|
+
"lazy_project_name": (
|
|
55
|
+
"general_manager.factory.factory_methods",
|
|
56
|
+
"lazy_project_name",
|
|
57
|
+
),
|
|
58
|
+
"lazy_date_today": ("general_manager.factory.factory_methods", "lazy_date_today"),
|
|
59
|
+
"lazy_date_between": (
|
|
60
|
+
"general_manager.factory.factory_methods",
|
|
61
|
+
"lazy_date_between",
|
|
62
|
+
),
|
|
63
|
+
"lazy_date_time_between": (
|
|
64
|
+
"general_manager.factory.factory_methods",
|
|
65
|
+
"lazy_date_time_between",
|
|
66
|
+
),
|
|
67
|
+
"lazy_integer": ("general_manager.factory.factory_methods", "lazy_integer"),
|
|
68
|
+
"lazy_decimal": ("general_manager.factory.factory_methods", "lazy_decimal"),
|
|
69
|
+
"lazy_choice": ("general_manager.factory.factory_methods", "lazy_choice"),
|
|
70
|
+
"lazy_sequence": ("general_manager.factory.factory_methods", "lazy_sequence"),
|
|
71
|
+
"lazy_boolean": ("general_manager.factory.factory_methods", "lazy_boolean"),
|
|
72
|
+
"lazy_uuid": ("general_manager.factory.factory_methods", "lazy_uuid"),
|
|
73
|
+
"lazy_faker_name": ("general_manager.factory.factory_methods", "lazy_faker_name"),
|
|
74
|
+
"lazy_faker_email": ("general_manager.factory.factory_methods", "lazy_faker_email"),
|
|
75
|
+
"lazy_faker_sentence": (
|
|
76
|
+
"general_manager.factory.factory_methods",
|
|
77
|
+
"lazy_faker_sentence",
|
|
78
|
+
),
|
|
79
|
+
"lazy_faker_address": (
|
|
80
|
+
"general_manager.factory.factory_methods",
|
|
81
|
+
"lazy_faker_address",
|
|
82
|
+
),
|
|
83
|
+
"lazy_faker_url": ("general_manager.factory.factory_methods", "lazy_faker_url"),
|
|
75
84
|
}
|
|
76
85
|
|
|
77
86
|
|
|
@@ -80,88 +89,88 @@ MEASUREMENT_EXPORTS: LazyExportMap = {
|
|
|
80
89
|
"ureg": ("general_manager.measurement.measurement", "ureg"),
|
|
81
90
|
"currency_units": ("general_manager.measurement.measurement", "currency_units"),
|
|
82
91
|
"MeasurementField": (
|
|
83
|
-
"general_manager.measurement.
|
|
92
|
+
"general_manager.measurement.measurement_field",
|
|
84
93
|
"MeasurementField",
|
|
85
94
|
),
|
|
86
95
|
}
|
|
87
96
|
|
|
88
97
|
|
|
89
98
|
UTILS_EXPORTS: LazyExportMap = {
|
|
90
|
-
"
|
|
91
|
-
"args_to_kwargs": ("general_manager.utils.
|
|
92
|
-
"make_cache_key": ("general_manager.utils.
|
|
93
|
-
"parse_filters": ("general_manager.utils.
|
|
99
|
+
"none_to_zero": ("general_manager.utils.none_to_zero", "none_to_zero"),
|
|
100
|
+
"args_to_kwargs": ("general_manager.utils.args_to_kwargs", "args_to_kwargs"),
|
|
101
|
+
"make_cache_key": ("general_manager.utils.make_cache_key", "make_cache_key"),
|
|
102
|
+
"parse_filters": ("general_manager.utils.filter_parser", "parse_filters"),
|
|
94
103
|
"create_filter_function": (
|
|
95
|
-
"general_manager.utils.
|
|
104
|
+
"general_manager.utils.filter_parser",
|
|
96
105
|
"create_filter_function",
|
|
97
106
|
),
|
|
98
|
-
"snake_to_pascal": ("general_manager.utils.
|
|
99
|
-
"snake_to_camel": ("general_manager.utils.
|
|
100
|
-
"pascal_to_snake": ("general_manager.utils.
|
|
101
|
-
"camel_to_snake": ("general_manager.utils.
|
|
102
|
-
"CustomJSONEncoder": ("general_manager.utils.
|
|
103
|
-
"PathMap": ("general_manager.utils.
|
|
107
|
+
"snake_to_pascal": ("general_manager.utils.format_string", "snake_to_pascal"),
|
|
108
|
+
"snake_to_camel": ("general_manager.utils.format_string", "snake_to_camel"),
|
|
109
|
+
"pascal_to_snake": ("general_manager.utils.format_string", "pascal_to_snake"),
|
|
110
|
+
"camel_to_snake": ("general_manager.utils.format_string", "camel_to_snake"),
|
|
111
|
+
"CustomJSONEncoder": ("general_manager.utils.json_encoder", "CustomJSONEncoder"),
|
|
112
|
+
"PathMap": ("general_manager.utils.path_mapping", "PathMap"),
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
|
|
107
116
|
PERMISSION_EXPORTS: LazyExportMap = {
|
|
108
|
-
"BasePermission": ("general_manager.permission.
|
|
117
|
+
"BasePermission": ("general_manager.permission.base_permission", "BasePermission"),
|
|
109
118
|
"ManagerBasedPermission": (
|
|
110
|
-
"general_manager.permission.
|
|
119
|
+
"general_manager.permission.manager_based_permission",
|
|
111
120
|
"ManagerBasedPermission",
|
|
112
121
|
),
|
|
113
122
|
"MutationPermission": (
|
|
114
|
-
"general_manager.permission.
|
|
123
|
+
"general_manager.permission.mutation_permission",
|
|
115
124
|
"MutationPermission",
|
|
116
125
|
),
|
|
117
126
|
}
|
|
118
127
|
|
|
119
128
|
|
|
120
129
|
INTERFACE_EXPORTS: LazyExportMap = {
|
|
121
|
-
"InterfaceBase": "general_manager.interface.
|
|
122
|
-
"DBBasedInterface": "general_manager.interface.
|
|
123
|
-
"DatabaseInterface": "general_manager.interface.
|
|
124
|
-
"ReadOnlyInterface": "general_manager.interface.
|
|
125
|
-
"CalculationInterface": "general_manager.interface.
|
|
130
|
+
"InterfaceBase": "general_manager.interface.base_interface",
|
|
131
|
+
"DBBasedInterface": "general_manager.interface.database_based_interface",
|
|
132
|
+
"DatabaseInterface": "general_manager.interface.database_interface",
|
|
133
|
+
"ReadOnlyInterface": "general_manager.interface.read_only_interface",
|
|
134
|
+
"CalculationInterface": "general_manager.interface.calculation_interface",
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
|
|
129
138
|
CACHE_EXPORTS: LazyExportMap = {
|
|
130
|
-
"cached": ("general_manager.cache.
|
|
131
|
-
"CacheBackend": ("general_manager.cache.
|
|
132
|
-
"DependencyTracker": ("general_manager.cache.
|
|
139
|
+
"cached": ("general_manager.cache.cache_decorator", "cached"),
|
|
140
|
+
"CacheBackend": ("general_manager.cache.cache_decorator", "CacheBackend"),
|
|
141
|
+
"DependencyTracker": ("general_manager.cache.cache_tracker", "DependencyTracker"),
|
|
133
142
|
"record_dependencies": (
|
|
134
|
-
"general_manager.cache.
|
|
143
|
+
"general_manager.cache.dependency_index",
|
|
135
144
|
"record_dependencies",
|
|
136
145
|
),
|
|
137
146
|
"remove_cache_key_from_index": (
|
|
138
|
-
"general_manager.cache.
|
|
147
|
+
"general_manager.cache.dependency_index",
|
|
139
148
|
"remove_cache_key_from_index",
|
|
140
149
|
),
|
|
141
150
|
"invalidate_cache_key": (
|
|
142
|
-
"general_manager.cache.
|
|
151
|
+
"general_manager.cache.dependency_index",
|
|
143
152
|
"invalidate_cache_key",
|
|
144
153
|
),
|
|
145
154
|
}
|
|
146
155
|
|
|
147
156
|
|
|
148
157
|
BUCKET_EXPORTS: LazyExportMap = {
|
|
149
|
-
"Bucket": ("general_manager.bucket.
|
|
150
|
-
"DatabaseBucket": ("general_manager.bucket.
|
|
158
|
+
"Bucket": ("general_manager.bucket.base_bucket", "Bucket"),
|
|
159
|
+
"DatabaseBucket": ("general_manager.bucket.database_bucket", "DatabaseBucket"),
|
|
151
160
|
"CalculationBucket": (
|
|
152
|
-
"general_manager.bucket.
|
|
161
|
+
"general_manager.bucket.calculation_bucket",
|
|
153
162
|
"CalculationBucket",
|
|
154
163
|
),
|
|
155
|
-
"GroupBucket": ("general_manager.bucket.
|
|
164
|
+
"GroupBucket": ("general_manager.bucket.group_bucket", "GroupBucket"),
|
|
156
165
|
}
|
|
157
166
|
|
|
158
167
|
|
|
159
168
|
MANAGER_EXPORTS: LazyExportMap = {
|
|
160
|
-
"GeneralManager": ("general_manager.manager.
|
|
169
|
+
"GeneralManager": ("general_manager.manager.general_manager", "GeneralManager"),
|
|
161
170
|
"GeneralManagerMeta": ("general_manager.manager.meta", "GeneralManagerMeta"),
|
|
162
171
|
"Input": ("general_manager.manager.input", "Input"),
|
|
163
|
-
"GroupManager": ("general_manager.manager.
|
|
164
|
-
"
|
|
172
|
+
"GroupManager": ("general_manager.manager.group_manager", "GroupManager"),
|
|
173
|
+
"graph_ql_property": ("general_manager.api.property", "graph_ql_property"),
|
|
165
174
|
}
|
|
166
175
|
|
|
167
176
|
|
general_manager/rule/handler.py
CHANGED
|
@@ -213,7 +213,7 @@ class LenHandler(FunctionHandler):
|
|
|
213
213
|
var_name = rule._get_node_name(arg_node)
|
|
214
214
|
var_value = var_values.get(var_name)
|
|
215
215
|
|
|
216
|
-
# ---
|
|
216
|
+
# --- Type guard for right_value ---
|
|
217
217
|
raw = rule._eval_node(right_node)
|
|
218
218
|
if not isinstance(raw, (int, float)):
|
|
219
219
|
raise InvalidLenThresholdError()
|
|
@@ -230,7 +230,7 @@ class LenHandler(FunctionHandler):
|
|
|
230
230
|
else:
|
|
231
231
|
threshold = right_value
|
|
232
232
|
|
|
233
|
-
#
|
|
233
|
+
# Formulate the error message
|
|
234
234
|
if op_symbol in (">", ">="):
|
|
235
235
|
msg = f"[{var_name}] ({var_value}) is too short (min length {threshold})!"
|
|
236
236
|
elif op_symbol in ("<", "<="):
|
general_manager/rule/rule.py
CHANGED
|
@@ -18,7 +18,7 @@ from general_manager.rule.handler import (
|
|
|
18
18
|
MinHandler,
|
|
19
19
|
SumHandler,
|
|
20
20
|
)
|
|
21
|
-
from general_manager.manager.
|
|
21
|
+
from general_manager.manager.general_manager import GeneralManager
|
|
22
22
|
|
|
23
23
|
GeneralManagerType = TypeVar("GeneralManagerType", bound=GeneralManager)
|
|
24
24
|
|
|
@@ -137,7 +137,7 @@ class Rule(Generic[GeneralManagerType]):
|
|
|
137
137
|
return self._func
|
|
138
138
|
|
|
139
139
|
@property
|
|
140
|
-
def
|
|
140
|
+
def custom_error_message(self) -> Optional[str]:
|
|
141
141
|
return self._custom_error_message
|
|
142
142
|
|
|
143
143
|
@property
|
|
@@ -145,15 +145,15 @@ class Rule(Generic[GeneralManagerType]):
|
|
|
145
145
|
return self._variables
|
|
146
146
|
|
|
147
147
|
@property
|
|
148
|
-
def
|
|
148
|
+
def last_evaluation_result(self) -> Optional[bool]:
|
|
149
149
|
return self._last_result
|
|
150
150
|
|
|
151
151
|
@property
|
|
152
|
-
def
|
|
152
|
+
def last_evaluation_input(self) -> Optional[GeneralManagerType]:
|
|
153
153
|
return self._last_input
|
|
154
154
|
|
|
155
155
|
@property
|
|
156
|
-
def
|
|
156
|
+
def ignore_if_none(self) -> bool:
|
|
157
157
|
return self._ignore_if_none
|
|
158
158
|
|
|
159
159
|
def evaluate(self, x: GeneralManagerType) -> Optional[bool]:
|
|
@@ -181,7 +181,7 @@ class Rule(Generic[GeneralManagerType]):
|
|
|
181
181
|
self._last_result = self._func(x)
|
|
182
182
|
return self._last_result
|
|
183
183
|
|
|
184
|
-
def
|
|
184
|
+
def validate_custom_error_message(self) -> None:
|
|
185
185
|
"""
|
|
186
186
|
Validate that a provided custom error message template includes placeholders for every variable referenced by the rule.
|
|
187
187
|
|
|
@@ -196,7 +196,7 @@ class Rule(Generic[GeneralManagerType]):
|
|
|
196
196
|
if missing:
|
|
197
197
|
raise MissingErrorTemplateVariableError(missing)
|
|
198
198
|
|
|
199
|
-
def
|
|
199
|
+
def get_error_message(self) -> Optional[Dict[str, str]]:
|
|
200
200
|
"""
|
|
201
201
|
Constructs error messages for the last failed evaluation and returns them keyed by variable name.
|
|
202
202
|
|
|
@@ -212,7 +212,7 @@ class Rule(Generic[GeneralManagerType]):
|
|
|
212
212
|
raise ErrorMessageGenerationError()
|
|
213
213
|
|
|
214
214
|
# Validate and substitute template placeholders
|
|
215
|
-
self.
|
|
215
|
+
self.validate_custom_error_message()
|
|
216
216
|
vals = self._extract_variable_values(self._last_input)
|
|
217
217
|
|
|
218
218
|
if self._custom_error_message:
|
|
@@ -250,7 +250,7 @@ class Rule(Generic[GeneralManagerType]):
|
|
|
250
250
|
self.vars: set[str] = set()
|
|
251
251
|
self.params = params
|
|
252
252
|
|
|
253
|
-
def
|
|
253
|
+
def visit_attribute(self, node: ast.Attribute) -> None:
|
|
254
254
|
"""
|
|
255
255
|
Record dotted attribute accesses that originate from allowed parameter names.
|
|
256
256
|
|
|
@@ -268,6 +268,8 @@ class Rule(Generic[GeneralManagerType]):
|
|
|
268
268
|
self.vars.add(".".join(reversed(parts)))
|
|
269
269
|
self.generic_visit(node)
|
|
270
270
|
|
|
271
|
+
visit_Attribute = visit_attribute
|
|
272
|
+
|
|
271
273
|
visitor = VarVisitor(param_names)
|
|
272
274
|
visitor.visit(self._tree)
|
|
273
275
|
return sorted(visitor.vars)
|
|
@@ -301,10 +303,12 @@ class Rule(Generic[GeneralManagerType]):
|
|
|
301
303
|
def __init__(self) -> None:
|
|
302
304
|
self.comps: list[ast.Compare] = []
|
|
303
305
|
|
|
304
|
-
def
|
|
306
|
+
def visit_compare(self, node: ast.Compare) -> None:
|
|
305
307
|
self.comps.append(node)
|
|
306
308
|
self.generic_visit(node)
|
|
307
309
|
|
|
310
|
+
visit_Compare = visit_compare
|
|
311
|
+
|
|
308
312
|
visitor = CompVisitor()
|
|
309
313
|
visitor.visit(self._tree)
|
|
310
314
|
return visitor.comps
|
|
@@ -313,11 +317,13 @@ class Rule(Generic[GeneralManagerType]):
|
|
|
313
317
|
class LogicVisitor(ast.NodeVisitor):
|
|
314
318
|
found: bool = False
|
|
315
319
|
|
|
316
|
-
def
|
|
320
|
+
def visit_bool_op(self, node: ast.BoolOp) -> None:
|
|
317
321
|
if isinstance(node.op, (ast.And, ast.Or)):
|
|
318
322
|
self.found = True
|
|
319
323
|
self.generic_visit(node)
|
|
320
324
|
|
|
325
|
+
visit_BoolOp = visit_bool_op
|
|
326
|
+
|
|
321
327
|
visitor = LogicVisitor()
|
|
322
328
|
visitor.visit(self._tree)
|
|
323
329
|
return visitor.found
|
|
@@ -36,7 +36,7 @@ def parse_filters(
|
|
|
36
36
|
Raises:
|
|
37
37
|
UnknownInputFieldError: If a filter references a field name not present in `possible_values`.
|
|
38
38
|
"""
|
|
39
|
-
from general_manager.manager.
|
|
39
|
+
from general_manager.manager.general_manager import GeneralManager
|
|
40
40
|
|
|
41
41
|
filters: dict[str, dict[str, Any]] = {}
|
|
42
42
|
for kwarg, value in filter_kwargs.items():
|
|
@@ -49,7 +49,7 @@ def parse_filters(
|
|
|
49
49
|
lookup = "__".join(parts[1:]) if len(parts) > 1 else ""
|
|
50
50
|
|
|
51
51
|
if issubclass(input_field.type, GeneralManager):
|
|
52
|
-
#
|
|
52
|
+
# Collect filter keyword arguments for the input field
|
|
53
53
|
if lookup == "":
|
|
54
54
|
lookup = "id"
|
|
55
55
|
if not isinstance(value, GeneralManager):
|
|
@@ -59,7 +59,7 @@ def parse_filters(
|
|
|
59
59
|
lookup
|
|
60
60
|
] = value
|
|
61
61
|
else:
|
|
62
|
-
#
|
|
62
|
+
# Build filter functions for non-bucket types
|
|
63
63
|
if isinstance(value, (list, tuple)) and not isinstance(
|
|
64
64
|
value, input_field.type
|
|
65
65
|
):
|
|
@@ -5,8 +5,8 @@ from typing import TYPE_CHECKING, Any, ClassVar, cast, get_args
|
|
|
5
5
|
from general_manager.manager.meta import GeneralManagerMeta
|
|
6
6
|
from general_manager.api.property import GraphQLProperty
|
|
7
7
|
|
|
8
|
-
from general_manager.bucket.
|
|
9
|
-
from general_manager.manager.
|
|
8
|
+
from general_manager.bucket.base_bucket import Bucket
|
|
9
|
+
from general_manager.manager.general_manager import GeneralManager
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
type PathStart = str
|
|
@@ -20,9 +20,9 @@ class MissingStartInstanceError(ValueError):
|
|
|
20
20
|
"""
|
|
21
21
|
Create the MissingStartInstanceError with its default message.
|
|
22
22
|
|
|
23
|
-
This initializer constructs the exception with the message: "Cannot call
|
|
23
|
+
This initializer constructs the exception with the message: "Cannot call go_to on a PathMap without a start instance."
|
|
24
24
|
"""
|
|
25
|
-
super().__init__("Cannot call
|
|
25
|
+
super().__init__("Cannot call go_to on a PathMap without a start instance.")
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class PathMap:
|
|
@@ -40,11 +40,11 @@ class PathMap:
|
|
|
40
40
|
"""
|
|
41
41
|
if not hasattr(cls, "instance"):
|
|
42
42
|
cls.instance = super().__new__(cls)
|
|
43
|
-
cls.
|
|
43
|
+
cls.create_path_mapping()
|
|
44
44
|
return cls.instance
|
|
45
45
|
|
|
46
46
|
@classmethod
|
|
47
|
-
def
|
|
47
|
+
def create_path_mapping(cls) -> None:
|
|
48
48
|
"""
|
|
49
49
|
Populate the path mapping with tracers for every distinct pair of managed classes.
|
|
50
50
|
|
|
@@ -110,7 +110,7 @@ class PathMap:
|
|
|
110
110
|
return None
|
|
111
111
|
return tracer
|
|
112
112
|
|
|
113
|
-
def
|
|
113
|
+
def go_to(
|
|
114
114
|
self, path_destination: PathDestination | type[GeneralManager] | str
|
|
115
115
|
) -> GeneralManager | Bucket | None:
|
|
116
116
|
"""
|
|
@@ -133,9 +133,9 @@ class PathMap:
|
|
|
133
133
|
return None
|
|
134
134
|
if self.start_instance is None:
|
|
135
135
|
raise MissingStartInstanceError()
|
|
136
|
-
return tracer.
|
|
136
|
+
return tracer.traverse_path(self.start_instance)
|
|
137
137
|
|
|
138
|
-
def
|
|
138
|
+
def get_all_connected(self) -> set[str]:
|
|
139
139
|
"""
|
|
140
140
|
Return the set of destination class names that are reachable from the configured start.
|
|
141
141
|
|
|
@@ -173,9 +173,9 @@ class PathTracer:
|
|
|
173
173
|
if self.start_class == self.destination_class:
|
|
174
174
|
self.path: list[str] | None = []
|
|
175
175
|
else:
|
|
176
|
-
self.path = self.
|
|
176
|
+
self.path = self.create_path(start_class, [])
|
|
177
177
|
|
|
178
|
-
def
|
|
178
|
+
def create_path(
|
|
179
179
|
self, current_manager: type[GeneralManager], path: list[str]
|
|
180
180
|
) -> list[str] | None:
|
|
181
181
|
"""
|
|
@@ -190,7 +190,7 @@ class PathTracer:
|
|
|
190
190
|
"""
|
|
191
191
|
current_connections = {
|
|
192
192
|
attr_name: attr_value["type"]
|
|
193
|
-
for attr_name, attr_value in current_manager.Interface.
|
|
193
|
+
for attr_name, attr_value in current_manager.Interface.get_attribute_types().items()
|
|
194
194
|
}
|
|
195
195
|
for attr_name, attr_value in current_manager.__dict__.items():
|
|
196
196
|
if not isinstance(attr_value, GraphQLProperty):
|
|
@@ -211,13 +211,13 @@ class PathTracer:
|
|
|
211
211
|
continue
|
|
212
212
|
if attr_type == self.destination_class:
|
|
213
213
|
return [*path, attr]
|
|
214
|
-
result = self.
|
|
214
|
+
result = self.create_path(attr_type, [*path, attr])
|
|
215
215
|
if result:
|
|
216
216
|
return result
|
|
217
217
|
|
|
218
218
|
return None
|
|
219
219
|
|
|
220
|
-
def
|
|
220
|
+
def traverse_path(
|
|
221
221
|
self, start_instance: GeneralManager | Bucket
|
|
222
222
|
) -> GeneralManager | Bucket | None:
|
|
223
223
|
"""
|
general_manager/utils/testing.py
CHANGED
|
@@ -15,8 +15,8 @@ from unittest.mock import ANY
|
|
|
15
15
|
|
|
16
16
|
from general_manager.api.graphql import GraphQL
|
|
17
17
|
from general_manager.apps import GeneralmanagerConfig
|
|
18
|
-
from general_manager.cache.
|
|
19
|
-
from general_manager.manager.
|
|
18
|
+
from general_manager.cache.cache_decorator import _SENTINEL
|
|
19
|
+
from general_manager.manager.general_manager import GeneralManager
|
|
20
20
|
from general_manager.manager.meta import GeneralManagerMeta
|
|
21
21
|
|
|
22
22
|
_original_get_app: Callable[[str], AppConfig | None] = (
|
|
@@ -24,7 +24,7 @@ _original_get_app: Callable[[str], AppConfig | None] = (
|
|
|
24
24
|
)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def
|
|
27
|
+
def create_fallback_get_app(fallback_app: str) -> Callable[[str], AppConfig | None]:
|
|
28
28
|
"""
|
|
29
29
|
Create an app-config lookup that falls back to a specific Django app.
|
|
30
30
|
|
|
@@ -32,7 +32,7 @@ def createFallbackGetApp(fallback_app: str) -> Callable[[str], AppConfig | None]
|
|
|
32
32
|
fallback_app (str): App label used when the default lookup cannot resolve the object.
|
|
33
33
|
|
|
34
34
|
Returns:
|
|
35
|
-
Callable[[str],
|
|
35
|
+
Callable[[str], AppConfig | None]: Function returning either the resolved configuration or the fallback app configuration when available.
|
|
36
36
|
"""
|
|
37
37
|
|
|
38
38
|
def _fallback_get_app(object_name: str) -> AppConfig | None:
|
|
@@ -120,7 +120,7 @@ class GMTestCaseMeta(type):
|
|
|
120
120
|
GraphQL._schema = None
|
|
121
121
|
|
|
122
122
|
if fallback_app is not None:
|
|
123
|
-
handler =
|
|
123
|
+
handler = create_fallback_get_app(fallback_app)
|
|
124
124
|
global_apps.get_containing_app_config = cast( # type: ignore[assignment]
|
|
125
125
|
Callable[[str], AppConfig | None], handler
|
|
126
126
|
)
|
|
@@ -154,11 +154,11 @@ class GMTestCaseMeta(type):
|
|
|
154
154
|
if history_model:
|
|
155
155
|
editor.create_model(history_model.model) # type: ignore[attr-defined]
|
|
156
156
|
# 4) GM & GraphQL initialization
|
|
157
|
-
GeneralmanagerConfig.
|
|
157
|
+
GeneralmanagerConfig.initialize_general_manager_classes(
|
|
158
158
|
cls.general_manager_classes, cls.general_manager_classes
|
|
159
159
|
)
|
|
160
|
-
GeneralmanagerConfig.
|
|
161
|
-
GeneralmanagerConfig.
|
|
160
|
+
GeneralmanagerConfig.handle_read_only_interface(cls.read_only_classes)
|
|
161
|
+
GeneralmanagerConfig.handle_graph_ql(cls.general_manager_classes)
|
|
162
162
|
# 5) GraphQLTransactionTestCase.setUpClass
|
|
163
163
|
base_setup.__func__(cls)
|
|
164
164
|
|
|
@@ -245,7 +245,7 @@ class GeneralManagerTransactionTestCase(
|
|
|
245
245
|
"""
|
|
246
246
|
super().setUp()
|
|
247
247
|
caches._connections.default = LoggingCache("test-cache", {}) # type: ignore[attr-defined]
|
|
248
|
-
self.
|
|
248
|
+
self.__reset_cache_counter()
|
|
249
249
|
|
|
250
250
|
@classmethod
|
|
251
251
|
def tearDownClass(cls) -> None:
|
|
@@ -311,7 +311,7 @@ class GeneralManagerTransactionTestCase(
|
|
|
311
311
|
super().tearDownClass()
|
|
312
312
|
|
|
313
313
|
#
|
|
314
|
-
def
|
|
314
|
+
def assert_cache_miss(self) -> None:
|
|
315
315
|
"""
|
|
316
316
|
Assert that a cache retrieval missed and was followed by a write.
|
|
317
317
|
|
|
@@ -328,9 +328,9 @@ class GeneralManagerTransactionTestCase(
|
|
|
328
328
|
"Cache.get should have been called and found nothing",
|
|
329
329
|
)
|
|
330
330
|
self.assertIn(("set", ANY), ops, "Cache.set should have stored the value")
|
|
331
|
-
self.
|
|
331
|
+
self.__reset_cache_counter()
|
|
332
332
|
|
|
333
|
-
def
|
|
333
|
+
def assert_cache_hit(self) -> None:
|
|
334
334
|
"""
|
|
335
335
|
Assert that a cache lookup succeeded without triggering a write.
|
|
336
336
|
|
|
@@ -352,9 +352,9 @@ class GeneralManagerTransactionTestCase(
|
|
|
352
352
|
ops,
|
|
353
353
|
"Cache.set should not have stored anything",
|
|
354
354
|
)
|
|
355
|
-
self.
|
|
355
|
+
self.__reset_cache_counter()
|
|
356
356
|
|
|
357
|
-
def
|
|
357
|
+
def __reset_cache_counter(self) -> None:
|
|
358
358
|
"""
|
|
359
359
|
Clear the log of cache operations recorded by the LoggingCache instance.
|
|
360
360
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.19.
|
|
3
|
+
Version: 0.19.2
|
|
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
6
|
License: MIT License
|