GeneralManager 0.19.1__py3-none-any.whl → 0.20.0__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.

Files changed (64) hide show
  1. general_manager/_types/api.py +4 -4
  2. general_manager/_types/bucket.py +4 -4
  3. general_manager/_types/cache.py +6 -6
  4. general_manager/_types/factory.py +35 -35
  5. general_manager/_types/general_manager.py +11 -9
  6. general_manager/_types/interface.py +5 -5
  7. general_manager/_types/manager.py +4 -4
  8. general_manager/_types/measurement.py +1 -1
  9. general_manager/_types/permission.py +3 -3
  10. general_manager/_types/utils.py +12 -12
  11. general_manager/api/graphql.py +207 -98
  12. general_manager/api/mutation.py +9 -9
  13. general_manager/api/property.py +4 -4
  14. general_manager/apps.py +120 -65
  15. general_manager/bucket/{baseBucket.py → base_bucket.py} +5 -5
  16. general_manager/bucket/{calculationBucket.py → calculation_bucket.py} +10 -10
  17. general_manager/bucket/{databaseBucket.py → database_bucket.py} +16 -19
  18. general_manager/bucket/{groupBucket.py → group_bucket.py} +8 -8
  19. general_manager/cache/{cacheDecorator.py → cache_decorator.py} +27 -6
  20. general_manager/cache/{cacheTracker.py → cache_tracker.py} +1 -1
  21. general_manager/cache/{dependencyIndex.py → dependency_index.py} +24 -8
  22. general_manager/cache/{modelDependencyCollector.py → model_dependency_collector.py} +4 -4
  23. general_manager/cache/signals.py +1 -1
  24. general_manager/factory/{autoFactory.py → auto_factory.py} +24 -19
  25. general_manager/factory/factories.py +10 -13
  26. general_manager/factory/{factoryMethods.py → factory_methods.py} +19 -17
  27. general_manager/interface/{baseInterface.py → base_interface.py} +30 -22
  28. general_manager/interface/{calculationInterface.py → calculation_interface.py} +10 -10
  29. general_manager/interface/{databaseBasedInterface.py → database_based_interface.py} +42 -42
  30. general_manager/interface/{databaseInterface.py → database_interface.py} +21 -21
  31. general_manager/interface/models.py +3 -3
  32. general_manager/interface/{readOnlyInterface.py → read_only_interface.py} +34 -25
  33. general_manager/logging.py +133 -0
  34. general_manager/manager/{generalManager.py → general_manager.py} +75 -17
  35. general_manager/manager/{groupManager.py → group_manager.py} +6 -6
  36. general_manager/manager/input.py +1 -1
  37. general_manager/manager/meta.py +63 -17
  38. general_manager/measurement/measurement.py +3 -3
  39. general_manager/permission/{basePermission.py → base_permission.py} +55 -32
  40. general_manager/permission/{managerBasedPermission.py → manager_based_permission.py} +21 -21
  41. general_manager/permission/{mutationPermission.py → mutation_permission.py} +12 -12
  42. general_manager/permission/{permissionChecks.py → permission_checks.py} +2 -2
  43. general_manager/permission/{permissionDataManager.py → permission_data_manager.py} +6 -6
  44. general_manager/permission/utils.py +6 -6
  45. general_manager/public_api_registry.py +76 -66
  46. general_manager/rule/handler.py +2 -2
  47. general_manager/rule/rule.py +102 -11
  48. general_manager/utils/{filterParser.py → filter_parser.py} +3 -3
  49. general_manager/utils/{jsonEncoder.py → json_encoder.py} +1 -1
  50. general_manager/utils/{makeCacheKey.py → make_cache_key.py} +1 -1
  51. general_manager/utils/{noneToZero.py → none_to_zero.py} +1 -1
  52. general_manager/utils/{pathMapping.py → path_mapping.py} +14 -14
  53. general_manager/utils/public_api.py +19 -0
  54. general_manager/utils/testing.py +14 -14
  55. {generalmanager-0.19.1.dist-info → generalmanager-0.20.0.dist-info}/METADATA +1 -1
  56. generalmanager-0.20.0.dist-info/RECORD +78 -0
  57. generalmanager-0.19.1.dist-info/RECORD +0 -77
  58. /general_manager/measurement/{measurementField.py → measurement_field.py} +0 -0
  59. /general_manager/permission/{fileBasedPermission.py → file_based_permission.py} +0 -0
  60. /general_manager/utils/{argsToKwargs.py → args_to_kwargs.py} +0 -0
  61. /general_manager/utils/{formatString.py → format_string.py} +0 -0
  62. {generalmanager-0.19.1.dist-info → generalmanager-0.20.0.dist-info}/WHEEL +0 -0
  63. {generalmanager-0.19.1.dist-info → generalmanager-0.20.0.dist-info}/licenses/LICENSE +0 -0
  64. {generalmanager-0.19.1.dist-info → generalmanager-0.20.0.dist-info}/top_level.txt +0 -0
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
  from typing import Callable, Optional, TypeVar, Generic, cast
5
5
  from django.contrib.auth.models import AbstractUser
6
6
 
7
- from general_manager.manager.generalManager import GeneralManager
7
+ from general_manager.manager.general_manager import GeneralManager
8
8
 
9
9
 
10
10
  class InvalidPermissionDataError(TypeError):
@@ -42,7 +42,7 @@ class PermissionDataManager(Generic[GeneralManagerData]):
42
42
  Raises:
43
43
  InvalidPermissionDataError: If `permission_data` is neither a dict nor an instance of GeneralManager.
44
44
  """
45
- self.getData: Callable[[str], object]
45
+ self.get_data: Callable[[str], object]
46
46
  self._permission_data = permission_data
47
47
  self._manager: type[GeneralManagerData] | None
48
48
  if isinstance(permission_data, GeneralManager):
@@ -51,7 +51,7 @@ class PermissionDataManager(Generic[GeneralManagerData]):
51
51
  def manager_getter(name: str) -> object:
52
52
  return getattr(gm_instance, name)
53
53
 
54
- self.getData = manager_getter
54
+ self.get_data = manager_getter
55
55
  self._manager = cast(type[GeneralManagerData], permission_data.__class__)
56
56
  elif isinstance(permission_data, dict):
57
57
  data_mapping = permission_data
@@ -59,13 +59,13 @@ class PermissionDataManager(Generic[GeneralManagerData]):
59
59
  def dict_getter(name: str) -> object:
60
60
  return data_mapping.get(name)
61
61
 
62
- self.getData = dict_getter
62
+ self.get_data = dict_getter
63
63
  self._manager = manager
64
64
  else:
65
65
  raise InvalidPermissionDataError()
66
66
 
67
67
  @classmethod
68
- def forUpdate(
68
+ def for_update(
69
69
  cls,
70
70
  base_data: GeneralManagerData,
71
71
  update_data: dict[str, object],
@@ -95,4 +95,4 @@ class PermissionDataManager(Generic[GeneralManagerData]):
95
95
 
96
96
  def __getattr__(self, name: str) -> object:
97
97
  """Proxy attribute access to the wrapped permission data."""
98
- return self.getData(name)
98
+ return self.get_data(name)
@@ -1,12 +1,12 @@
1
1
  """Utility helpers for evaluating permission expressions."""
2
2
 
3
- from general_manager.permission.permissionChecks import (
3
+ from general_manager.permission.permission_checks import (
4
4
  permission_functions,
5
5
  )
6
- from general_manager.permission.permissionDataManager import PermissionDataManager
6
+ from general_manager.permission.permission_data_manager import PermissionDataManager
7
7
  from django.contrib.auth.models import AbstractUser, AnonymousUser
8
8
 
9
- from general_manager.manager.generalManager import GeneralManager
9
+ from general_manager.manager.general_manager import GeneralManager
10
10
  from general_manager.manager.meta import GeneralManagerMeta
11
11
 
12
12
 
@@ -23,7 +23,7 @@ class PermissionNotFoundError(ValueError):
23
23
  super().__init__(f"Permission {permission} not found.")
24
24
 
25
25
 
26
- def validatePermissionString(
26
+ def validate_permission_string(
27
27
  permission: str,
28
28
  data: PermissionDataManager | GeneralManager | GeneralManagerMeta,
29
29
  request_user: AbstractUser | AnonymousUser,
@@ -43,7 +43,7 @@ def validatePermissionString(
43
43
  PermissionNotFoundError: If a referenced permission function is not registered.
44
44
  """
45
45
 
46
- def _validateSinglePermission(
46
+ def _validate_single_permission(
47
47
  permission: str,
48
48
  ) -> bool:
49
49
  """
@@ -68,7 +68,7 @@ def validatePermissionString(
68
68
 
69
69
  return all(
70
70
  [
71
- _validateSinglePermission(sub_permission)
71
+ _validate_single_permission(sub_permission)
72
72
  for sub_permission in permission.split("&")
73
73
  ]
74
74
  )
@@ -14,24 +14,25 @@ LazyExportMap = Mapping[str, str | tuple[str, str]]
14
14
 
15
15
  GENERAL_MANAGER_EXPORTS: LazyExportMap = {
16
16
  "GraphQL": ("general_manager.api.graphql", "GraphQL"),
17
- "graphQlProperty": ("general_manager.api.property", "graphQlProperty"),
18
- "graphQlMutation": ("general_manager.api.mutation", "graphQlMutation"),
19
- "GeneralManager": ("general_manager.manager.generalManager", "GeneralManager"),
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
+ "get_logger": ("general_manager.logging", "get_logger"),
21
22
  "CalculationInterface": (
22
- "general_manager.interface.calculationInterface",
23
+ "general_manager.interface.calculation_interface",
23
24
  "CalculationInterface",
24
25
  ),
25
26
  "DatabaseInterface": (
26
- "general_manager.interface.databaseInterface",
27
+ "general_manager.interface.database_interface",
27
28
  "DatabaseInterface",
28
29
  ),
29
30
  "ReadOnlyInterface": (
30
- "general_manager.interface.readOnlyInterface",
31
+ "general_manager.interface.read_only_interface",
31
32
  "ReadOnlyInterface",
32
33
  ),
33
34
  "ManagerBasedPermission": (
34
- "general_manager.permission.managerBasedPermission",
35
+ "general_manager.permission.manager_based_permission",
35
36
  "ManagerBasedPermission",
36
37
  ),
37
38
  "Rule": ("general_manager.rule.rule", "Rule"),
@@ -42,36 +43,45 @@ API_EXPORTS: LazyExportMap = {
42
43
  "GraphQL": ("general_manager.api.graphql", "GraphQL"),
43
44
  "MeasurementType": ("general_manager.api.graphql", "MeasurementType"),
44
45
  "MeasurementScalar": ("general_manager.api.graphql", "MeasurementScalar"),
45
- "graphQlProperty": ("general_manager.api.property", "graphQlProperty"),
46
- "graphQlMutation": ("general_manager.api.mutation", "graphQlMutation"),
46
+ "graph_ql_property": ("general_manager.api.property", "graph_ql_property"),
47
+ "graph_ql_mutation": ("general_manager.api.mutation", "graph_ql_mutation"),
47
48
  }
48
49
 
49
50
 
50
51
  FACTORY_EXPORTS: LazyExportMap = {
51
- "AutoFactory": ("general_manager.factory.autoFactory", "AutoFactory"),
52
- "LazyMeasurement": ("general_manager.factory.factoryMethods", "LazyMeasurement"),
53
- "LazyDeltaDate": ("general_manager.factory.factoryMethods", "LazyDeltaDate"),
54
- "LazyProjectName": ("general_manager.factory.factoryMethods", "LazyProjectName"),
55
- "LazyDateToday": ("general_manager.factory.factoryMethods", "LazyDateToday"),
56
- "LazyDateBetween": ("general_manager.factory.factoryMethods", "LazyDateBetween"),
57
- "LazyDateTimeBetween": (
58
- "general_manager.factory.factoryMethods",
59
- "LazyDateTimeBetween",
60
- ),
61
- "LazyInteger": ("general_manager.factory.factoryMethods", "LazyInteger"),
62
- "LazyDecimal": ("general_manager.factory.factoryMethods", "LazyDecimal"),
63
- "LazyChoice": ("general_manager.factory.factoryMethods", "LazyChoice"),
64
- "LazySequence": ("general_manager.factory.factoryMethods", "LazySequence"),
65
- "LazyBoolean": ("general_manager.factory.factoryMethods", "LazyBoolean"),
66
- "LazyUUID": ("general_manager.factory.factoryMethods", "LazyUUID"),
67
- "LazyFakerName": ("general_manager.factory.factoryMethods", "LazyFakerName"),
68
- "LazyFakerEmail": ("general_manager.factory.factoryMethods", "LazyFakerEmail"),
69
- "LazyFakerSentence": (
70
- "general_manager.factory.factoryMethods",
71
- "LazyFakerSentence",
72
- ),
73
- "LazyFakerAddress": ("general_manager.factory.factoryMethods", "LazyFakerAddress"),
74
- "LazyFakerUrl": ("general_manager.factory.factoryMethods", "LazyFakerUrl"),
52
+ "AutoFactory": ("general_manager.factory.auto_factory", "AutoFactory"),
53
+ "lazy_measurement": ("general_manager.factory.factory_methods", "lazy_measurement"),
54
+ "lazy_delta_date": ("general_manager.factory.factory_methods", "lazy_delta_date"),
55
+ "lazy_project_name": (
56
+ "general_manager.factory.factory_methods",
57
+ "lazy_project_name",
58
+ ),
59
+ "lazy_date_today": ("general_manager.factory.factory_methods", "lazy_date_today"),
60
+ "lazy_date_between": (
61
+ "general_manager.factory.factory_methods",
62
+ "lazy_date_between",
63
+ ),
64
+ "lazy_date_time_between": (
65
+ "general_manager.factory.factory_methods",
66
+ "lazy_date_time_between",
67
+ ),
68
+ "lazy_integer": ("general_manager.factory.factory_methods", "lazy_integer"),
69
+ "lazy_decimal": ("general_manager.factory.factory_methods", "lazy_decimal"),
70
+ "lazy_choice": ("general_manager.factory.factory_methods", "lazy_choice"),
71
+ "lazy_sequence": ("general_manager.factory.factory_methods", "lazy_sequence"),
72
+ "lazy_boolean": ("general_manager.factory.factory_methods", "lazy_boolean"),
73
+ "lazy_uuid": ("general_manager.factory.factory_methods", "lazy_uuid"),
74
+ "lazy_faker_name": ("general_manager.factory.factory_methods", "lazy_faker_name"),
75
+ "lazy_faker_email": ("general_manager.factory.factory_methods", "lazy_faker_email"),
76
+ "lazy_faker_sentence": (
77
+ "general_manager.factory.factory_methods",
78
+ "lazy_faker_sentence",
79
+ ),
80
+ "lazy_faker_address": (
81
+ "general_manager.factory.factory_methods",
82
+ "lazy_faker_address",
83
+ ),
84
+ "lazy_faker_url": ("general_manager.factory.factory_methods", "lazy_faker_url"),
75
85
  }
76
86
 
77
87
 
@@ -80,88 +90,88 @@ MEASUREMENT_EXPORTS: LazyExportMap = {
80
90
  "ureg": ("general_manager.measurement.measurement", "ureg"),
81
91
  "currency_units": ("general_manager.measurement.measurement", "currency_units"),
82
92
  "MeasurementField": (
83
- "general_manager.measurement.measurementField",
93
+ "general_manager.measurement.measurement_field",
84
94
  "MeasurementField",
85
95
  ),
86
96
  }
87
97
 
88
98
 
89
99
  UTILS_EXPORTS: LazyExportMap = {
90
- "noneToZero": ("general_manager.utils.noneToZero", "noneToZero"),
91
- "args_to_kwargs": ("general_manager.utils.argsToKwargs", "args_to_kwargs"),
92
- "make_cache_key": ("general_manager.utils.makeCacheKey", "make_cache_key"),
93
- "parse_filters": ("general_manager.utils.filterParser", "parse_filters"),
100
+ "none_to_zero": ("general_manager.utils.none_to_zero", "none_to_zero"),
101
+ "args_to_kwargs": ("general_manager.utils.args_to_kwargs", "args_to_kwargs"),
102
+ "make_cache_key": ("general_manager.utils.make_cache_key", "make_cache_key"),
103
+ "parse_filters": ("general_manager.utils.filter_parser", "parse_filters"),
94
104
  "create_filter_function": (
95
- "general_manager.utils.filterParser",
105
+ "general_manager.utils.filter_parser",
96
106
  "create_filter_function",
97
107
  ),
98
- "snake_to_pascal": ("general_manager.utils.formatString", "snake_to_pascal"),
99
- "snake_to_camel": ("general_manager.utils.formatString", "snake_to_camel"),
100
- "pascal_to_snake": ("general_manager.utils.formatString", "pascal_to_snake"),
101
- "camel_to_snake": ("general_manager.utils.formatString", "camel_to_snake"),
102
- "CustomJSONEncoder": ("general_manager.utils.jsonEncoder", "CustomJSONEncoder"),
103
- "PathMap": ("general_manager.utils.pathMapping", "PathMap"),
108
+ "snake_to_pascal": ("general_manager.utils.format_string", "snake_to_pascal"),
109
+ "snake_to_camel": ("general_manager.utils.format_string", "snake_to_camel"),
110
+ "pascal_to_snake": ("general_manager.utils.format_string", "pascal_to_snake"),
111
+ "camel_to_snake": ("general_manager.utils.format_string", "camel_to_snake"),
112
+ "CustomJSONEncoder": ("general_manager.utils.json_encoder", "CustomJSONEncoder"),
113
+ "PathMap": ("general_manager.utils.path_mapping", "PathMap"),
104
114
  }
105
115
 
106
116
 
107
117
  PERMISSION_EXPORTS: LazyExportMap = {
108
- "BasePermission": ("general_manager.permission.basePermission", "BasePermission"),
118
+ "BasePermission": ("general_manager.permission.base_permission", "BasePermission"),
109
119
  "ManagerBasedPermission": (
110
- "general_manager.permission.managerBasedPermission",
120
+ "general_manager.permission.manager_based_permission",
111
121
  "ManagerBasedPermission",
112
122
  ),
113
123
  "MutationPermission": (
114
- "general_manager.permission.mutationPermission",
124
+ "general_manager.permission.mutation_permission",
115
125
  "MutationPermission",
116
126
  ),
117
127
  }
118
128
 
119
129
 
120
130
  INTERFACE_EXPORTS: LazyExportMap = {
121
- "InterfaceBase": "general_manager.interface.baseInterface",
122
- "DBBasedInterface": "general_manager.interface.databaseBasedInterface",
123
- "DatabaseInterface": "general_manager.interface.databaseInterface",
124
- "ReadOnlyInterface": "general_manager.interface.readOnlyInterface",
125
- "CalculationInterface": "general_manager.interface.calculationInterface",
131
+ "InterfaceBase": "general_manager.interface.base_interface",
132
+ "DBBasedInterface": "general_manager.interface.database_based_interface",
133
+ "DatabaseInterface": "general_manager.interface.database_interface",
134
+ "ReadOnlyInterface": "general_manager.interface.read_only_interface",
135
+ "CalculationInterface": "general_manager.interface.calculation_interface",
126
136
  }
127
137
 
128
138
 
129
139
  CACHE_EXPORTS: LazyExportMap = {
130
- "cached": ("general_manager.cache.cacheDecorator", "cached"),
131
- "CacheBackend": ("general_manager.cache.cacheDecorator", "CacheBackend"),
132
- "DependencyTracker": ("general_manager.cache.cacheTracker", "DependencyTracker"),
140
+ "cached": ("general_manager.cache.cache_decorator", "cached"),
141
+ "CacheBackend": ("general_manager.cache.cache_decorator", "CacheBackend"),
142
+ "DependencyTracker": ("general_manager.cache.cache_tracker", "DependencyTracker"),
133
143
  "record_dependencies": (
134
- "general_manager.cache.dependencyIndex",
144
+ "general_manager.cache.dependency_index",
135
145
  "record_dependencies",
136
146
  ),
137
147
  "remove_cache_key_from_index": (
138
- "general_manager.cache.dependencyIndex",
148
+ "general_manager.cache.dependency_index",
139
149
  "remove_cache_key_from_index",
140
150
  ),
141
151
  "invalidate_cache_key": (
142
- "general_manager.cache.dependencyIndex",
152
+ "general_manager.cache.dependency_index",
143
153
  "invalidate_cache_key",
144
154
  ),
145
155
  }
146
156
 
147
157
 
148
158
  BUCKET_EXPORTS: LazyExportMap = {
149
- "Bucket": ("general_manager.bucket.baseBucket", "Bucket"),
150
- "DatabaseBucket": ("general_manager.bucket.databaseBucket", "DatabaseBucket"),
159
+ "Bucket": ("general_manager.bucket.base_bucket", "Bucket"),
160
+ "DatabaseBucket": ("general_manager.bucket.database_bucket", "DatabaseBucket"),
151
161
  "CalculationBucket": (
152
- "general_manager.bucket.calculationBucket",
162
+ "general_manager.bucket.calculation_bucket",
153
163
  "CalculationBucket",
154
164
  ),
155
- "GroupBucket": ("general_manager.bucket.groupBucket", "GroupBucket"),
165
+ "GroupBucket": ("general_manager.bucket.group_bucket", "GroupBucket"),
156
166
  }
157
167
 
158
168
 
159
169
  MANAGER_EXPORTS: LazyExportMap = {
160
- "GeneralManager": ("general_manager.manager.generalManager", "GeneralManager"),
170
+ "GeneralManager": ("general_manager.manager.general_manager", "GeneralManager"),
161
171
  "GeneralManagerMeta": ("general_manager.manager.meta", "GeneralManagerMeta"),
162
172
  "Input": ("general_manager.manager.input", "Input"),
163
- "GroupManager": ("general_manager.manager.groupManager", "GroupManager"),
164
- "graphQlProperty": ("general_manager.api.property", "graphQlProperty"),
173
+ "GroupManager": ("general_manager.manager.group_manager", "GroupManager"),
174
+ "graph_ql_property": ("general_manager.api.property", "graph_ql_property"),
165
175
  }
166
176
 
167
177
 
@@ -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
- # --- Hier der Typ-Guard für right_value ---
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
- # Fehlermeldung formulieren
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 ("<", "<="):
@@ -18,11 +18,13 @@ from general_manager.rule.handler import (
18
18
  MinHandler,
19
19
  SumHandler,
20
20
  )
21
- from general_manager.manager.generalManager import GeneralManager
21
+ from general_manager.manager.general_manager import GeneralManager
22
+ from general_manager.logging import get_logger
22
23
 
23
24
  GeneralManagerType = TypeVar("GeneralManagerType", bound=GeneralManager)
24
25
 
25
26
  NOTEXISTENT = object()
27
+ logger = get_logger("rule.engine")
26
28
 
27
29
 
28
30
  class NonexistentAttributeError(AttributeError):
@@ -131,13 +133,20 @@ class Rule(Generic[GeneralManagerType]):
131
133
  handler_cls: type[BaseRuleHandler] = import_string(path)
132
134
  inst = handler_cls()
133
135
  self._handlers[inst.function_name] = inst
136
+ logger.debug(
137
+ "initialised rule",
138
+ context={
139
+ "rule": self._func.__qualname__,
140
+ "variables": self._variables,
141
+ },
142
+ )
134
143
 
135
144
  @property
136
145
  def func(self) -> Callable[[GeneralManagerType], bool]:
137
146
  return self._func
138
147
 
139
148
  @property
140
- def customErrorMessage(self) -> Optional[str]:
149
+ def custom_error_message(self) -> Optional[str]:
141
150
  return self._custom_error_message
142
151
 
143
152
  @property
@@ -145,15 +154,15 @@ class Rule(Generic[GeneralManagerType]):
145
154
  return self._variables
146
155
 
147
156
  @property
148
- def lastEvaluationResult(self) -> Optional[bool]:
157
+ def last_evaluation_result(self) -> Optional[bool]:
149
158
  return self._last_result
150
159
 
151
160
  @property
152
- def lastEvaluationInput(self) -> Optional[GeneralManagerType]:
161
+ def last_evaluation_input(self) -> Optional[GeneralManagerType]:
153
162
  return self._last_input
154
163
 
155
164
  @property
156
- def ignoreIfNone(self) -> bool:
165
+ def ignore_if_none(self) -> bool:
157
166
  return self._ignore_if_none
158
167
 
159
168
  def evaluate(self, x: GeneralManagerType) -> Optional[bool]:
@@ -173,15 +182,50 @@ class Rule(Generic[GeneralManagerType]):
173
182
  if self._primary_param is not None:
174
183
  self._last_args[self._primary_param] = x
175
184
 
185
+ logger.debug(
186
+ "evaluating rule",
187
+ context={
188
+ "rule": self._func.__qualname__,
189
+ "manager": type(x).__name__,
190
+ },
191
+ )
192
+
176
193
  vals = self._extract_variable_values(x)
177
194
  if self._ignore_if_none and any(v is None for v in vals.values()):
178
195
  self._last_result = None
196
+ logger.debug(
197
+ "skipped rule evaluation due to missing values",
198
+ context={
199
+ "rule": self._func.__qualname__,
200
+ "manager": type(x).__name__,
201
+ "null_variables": [
202
+ name for name, value in vals.items() if value is None
203
+ ],
204
+ },
205
+ )
179
206
  return None
180
207
 
181
208
  self._last_result = self._func(x)
209
+ if self._last_result:
210
+ logger.debug(
211
+ "rule evaluation passed",
212
+ context={
213
+ "rule": self._func.__qualname__,
214
+ "manager": type(x).__name__,
215
+ },
216
+ )
217
+ else:
218
+ logger.info(
219
+ "rule evaluation failed",
220
+ context={
221
+ "rule": self._func.__qualname__,
222
+ "manager": type(x).__name__,
223
+ "variables": self._variables,
224
+ },
225
+ )
182
226
  return self._last_result
183
227
 
184
- def validateCustomErrorMessage(self) -> None:
228
+ def validate_custom_error_message(self) -> None:
185
229
  """
186
230
  Validate that a provided custom error message template includes placeholders for every variable referenced by the rule.
187
231
 
@@ -196,7 +240,7 @@ class Rule(Generic[GeneralManagerType]):
196
240
  if missing:
197
241
  raise MissingErrorTemplateVariableError(missing)
198
242
 
199
- def getErrorMessage(self) -> Optional[Dict[str, str]]:
243
+ def get_error_message(self) -> Optional[Dict[str, str]]:
200
244
  """
201
245
  Constructs error messages for the last failed evaluation and returns them keyed by variable name.
202
246
 
@@ -212,8 +256,16 @@ class Rule(Generic[GeneralManagerType]):
212
256
  raise ErrorMessageGenerationError()
213
257
 
214
258
  # Validate and substitute template placeholders
215
- self.validateCustomErrorMessage()
259
+ self.validate_custom_error_message()
216
260
  vals = self._extract_variable_values(self._last_input)
261
+ manager_class = type(self._last_input).__name__
262
+ logger.debug(
263
+ "generating rule error messages",
264
+ context={
265
+ "rule": self._func.__qualname__,
266
+ "manager": manager_class,
267
+ },
268
+ )
217
269
 
218
270
  if self._custom_error_message:
219
271
  formatted = re.sub(
@@ -221,9 +273,34 @@ class Rule(Generic[GeneralManagerType]):
221
273
  lambda m: str(vals.get(m.group(1), m.group(0))),
222
274
  self._custom_error_message,
223
275
  )
276
+ logger.info(
277
+ "rule produced custom error message",
278
+ context={
279
+ "rule": self._func.__qualname__,
280
+ "manager": manager_class,
281
+ "variables": self._variables,
282
+ },
283
+ )
224
284
  return {v: formatted for v in self._variables}
225
285
 
226
286
  errors = self._generate_error_messages(vals)
287
+ if errors:
288
+ logger.info(
289
+ "rule produced error messages",
290
+ context={
291
+ "rule": self._func.__qualname__,
292
+ "manager": manager_class,
293
+ "variables": list(errors.keys()),
294
+ },
295
+ )
296
+ else:
297
+ logger.debug(
298
+ "rule generated no error messages",
299
+ context={
300
+ "rule": self._func.__qualname__,
301
+ "manager": manager_class,
302
+ },
303
+ )
227
304
  return errors or None
228
305
 
229
306
  def _extract_variables(self) -> List[str]:
@@ -250,7 +327,7 @@ class Rule(Generic[GeneralManagerType]):
250
327
  self.vars: set[str] = set()
251
328
  self.params = params
252
329
 
253
- def visit_Attribute(self, node: ast.Attribute) -> None:
330
+ def visit_attribute(self, node: ast.Attribute) -> None:
254
331
  """
255
332
  Record dotted attribute accesses that originate from allowed parameter names.
256
333
 
@@ -268,6 +345,8 @@ class Rule(Generic[GeneralManagerType]):
268
345
  self.vars.add(".".join(reversed(parts)))
269
346
  self.generic_visit(node)
270
347
 
348
+ visit_Attribute = visit_attribute
349
+
271
350
  visitor = VarVisitor(param_names)
272
351
  visitor.visit(self._tree)
273
352
  return sorted(visitor.vars)
@@ -301,10 +380,12 @@ class Rule(Generic[GeneralManagerType]):
301
380
  def __init__(self) -> None:
302
381
  self.comps: list[ast.Compare] = []
303
382
 
304
- def visit_Compare(self, node: ast.Compare) -> None:
383
+ def visit_compare(self, node: ast.Compare) -> None:
305
384
  self.comps.append(node)
306
385
  self.generic_visit(node)
307
386
 
387
+ visit_Compare = visit_compare
388
+
308
389
  visitor = CompVisitor()
309
390
  visitor.visit(self._tree)
310
391
  return visitor.comps
@@ -313,11 +394,13 @@ class Rule(Generic[GeneralManagerType]):
313
394
  class LogicVisitor(ast.NodeVisitor):
314
395
  found: bool = False
315
396
 
316
- def visit_BoolOp(self, node: ast.BoolOp) -> None:
397
+ def visit_bool_op(self, node: ast.BoolOp) -> None:
317
398
  if isinstance(node.op, (ast.And, ast.Or)):
318
399
  self.found = True
319
400
  self.generic_visit(node)
320
401
 
402
+ visit_BoolOp = visit_bool_op
403
+
321
404
  visitor = LogicVisitor()
322
405
  visitor.visit(self._tree)
323
406
  return visitor.found
@@ -349,6 +432,14 @@ class Rule(Generic[GeneralManagerType]):
349
432
  fn = self._get_node_name(left.func)
350
433
  handler = self._handlers.get(fn)
351
434
  if handler:
435
+ logger.debug(
436
+ "rule handler invoked",
437
+ context={
438
+ "rule": self._func.__qualname__,
439
+ "handler": handler.__class__.__name__,
440
+ "function": fn,
441
+ },
442
+ )
352
443
  errors.update(
353
444
  handler.handle(cmp, left, right, op, var_values, self)
354
445
  )
@@ -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.generalManager import GeneralManager
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
- # Sammle die Filter-Keyword-Argumente für das InputField
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
- # Erstelle Filterfunktionen für Nicht-Bucket-Typen
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
  ):
@@ -2,7 +2,7 @@
2
2
 
3
3
  from datetime import datetime, date, time
4
4
  import json
5
- from general_manager.manager.generalManager import GeneralManager
5
+ from general_manager.manager.general_manager import GeneralManager
6
6
 
7
7
 
8
8
  class CustomJSONEncoder(json.JSONEncoder):
@@ -5,7 +5,7 @@ import json
5
5
  from hashlib import sha256
6
6
  from typing import Callable, Mapping
7
7
 
8
- from general_manager.utils.jsonEncoder import CustomJSONEncoder
8
+ from general_manager.utils.json_encoder import CustomJSONEncoder
9
9
 
10
10
 
11
11
  def make_cache_key(
@@ -6,7 +6,7 @@ from general_manager.measurement import Measurement
6
6
  NUMBERVALUE = TypeVar("NUMBERVALUE", int, float, Measurement)
7
7
 
8
8
 
9
- def noneToZero(
9
+ def none_to_zero(
10
10
  value: Optional[NUMBERVALUE],
11
11
  ) -> NUMBERVALUE | Literal[0]:
12
12
  """