GeneralManager 0.6.0__py3-none-any.whl → 0.6.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.
@@ -151,15 +151,15 @@ class CalculationBucket(Bucket[GeneralManagerType]):
151
151
 
152
152
  def __repr__(self) -> str:
153
153
  """
154
- Returns a string representation of the CalculationBucket, showing a preview of its contents.
154
+ Returns a concise string representation of the CalculationBucket, including the manager class name, filters, excludes, sort key, and sort order.
155
155
  """
156
- return self.__str__()
156
+ return f"{self.__class__.__name__}({self._manager_class.__name__}, {self.filters}, {self.excludes}, {self.sort_key}, {self.reverse})"
157
157
 
158
158
  def filter(self, **kwargs: Any) -> CalculationBucket:
159
159
  """
160
- Returns a new CalculationBucket with additional filters applied to input combinations.
161
-
162
- Additional filters are merged with existing filters, narrowing the set of valid input configurations.
160
+ Returns a new CalculationBucket with additional filters applied.
161
+
162
+ Merges the provided filter criteria with existing filters to further restrict valid input combinations.
163
163
  """
164
164
  filters = self.filters.copy()
165
165
  excludes = self.excludes.copy()
@@ -315,42 +315,45 @@ class CalculationBucket(Bucket[GeneralManagerType]):
315
315
  excludes: dict[str, dict],
316
316
  ) -> List[dict[str, Any]]:
317
317
  """
318
- Recursively generates all valid input combinations based on sorted input fields, applying filters and exclusions.
319
-
318
+ Recursively generates all valid input combinations for the specified input fields, applying filters and exclusions.
319
+
320
320
  Args:
321
- sorted_inputs: List of input field names ordered by dependency.
322
- filters: Dictionary mapping input names to filter definitions.
323
- excludes: Dictionary mapping input names to exclusion definitions.
324
-
321
+ sorted_inputs: Input field names ordered to respect dependency constraints.
322
+ filters: Mapping of input field names to filter definitions.
323
+ excludes: Mapping of input field names to exclusion definitions.
324
+
325
325
  Returns:
326
- A list of dictionaries, each representing a valid combination of input values.
326
+ A list of dictionaries, each representing a valid combination of input values that satisfy all filters and exclusions.
327
327
  """
328
328
 
329
329
  def helper(index, current_combo):
330
+ """
331
+ Recursively generates all valid input combinations for calculation inputs.
332
+
333
+ Yields:
334
+ Dict[str, Any]: A dictionary representing a valid combination of input values, filtered and excluded according to the provided criteria.
335
+ """
330
336
  if index == len(sorted_inputs):
331
337
  yield current_combo.copy()
332
338
  return
333
339
  input_name: str = sorted_inputs[index]
334
340
  input_field = self.input_fields[input_name]
335
341
 
336
- # Hole mögliche Werte
337
342
  possible_values = self.get_possible_values(
338
343
  input_name, input_field, current_combo
339
344
  )
340
345
 
341
- # Wende die Filter an
342
346
  field_filters = filters.get(input_name, {})
343
347
  field_excludes = excludes.get(input_name, {})
344
348
 
349
+ # use filter_funcs and exclude_funcs to filter possible values
345
350
  if isinstance(possible_values, Bucket):
346
- # Wende die Filter- und Exklusionsargumente direkt an
347
351
  filter_kwargs = field_filters.get("filter_kwargs", {})
348
352
  exclude_kwargs = field_excludes.get("filter_kwargs", {})
349
353
  possible_values = possible_values.filter(**filter_kwargs).exclude(
350
354
  **exclude_kwargs
351
355
  )
352
356
  else:
353
- # Wende die Filterfunktionen an
354
357
  filter_funcs = field_filters.get("filter_funcs", [])
355
358
  for filter_func in filter_funcs:
356
359
  possible_values = filter(filter_func, possible_values)
@@ -61,7 +61,15 @@ class CalculationInterface(InterfaceBase):
61
61
  def _preCreate(
62
62
  name: generalManagerClassName, attrs: attributes, interface: interfaceBaseClass
63
63
  ) -> tuple[attributes, interfaceBaseClass, None]:
64
- # Felder aus der Interface-Klasse sammeln
64
+
65
+ """
66
+ Prepares attributes and a new interface class before creating a GeneralManager class.
67
+
68
+ Collects all `Input` instances from the provided interface class, sets the interface type in the attributes, dynamically creates a new interface class with these input fields, and adds it to the attributes.
69
+
70
+ Returns:
71
+ A tuple containing the updated attributes dictionary, the new interface class, and None.
72
+ """
65
73
  input_fields: dict[str, Input[Any]] = {}
66
74
  for key, value in vars(interface).items():
67
75
  if key.startswith("__"):
@@ -69,7 +77,6 @@ class CalculationInterface(InterfaceBase):
69
77
  if isinstance(value, Input):
70
78
  input_fields[key] = value
71
79
 
72
- # Interface-Typ bestimmen
73
80
  attrs["_interface_type"] = interface._interface_type
74
81
  interface_cls = type(
75
82
  interface.__name__, (interface,), {"input_fields": input_fields}
@@ -102,18 +109,12 @@ class CalculationInterface(InterfaceBase):
102
109
  @classmethod
103
110
  def getFieldType(cls, field_name: str) -> type:
104
111
  """
105
- Returns the type of the specified input field.
106
-
107
- Args:
108
- field_name: The name of the input field.
109
-
110
- Returns:
111
- The Python type associated with the input field.
112
+ Returns the Python type of a specified input field.
112
113
 
113
114
  Raises:
114
- ValueError: If the specified field name does not exist in input_fields.
115
+ KeyError: If the field name does not exist in input_fields.
115
116
  """
116
117
  input = cls.input_fields.get(field_name)
117
118
  if input is None:
118
- raise ValueError(f"Field '{field_name}' not found in input fields.")
119
+ raise KeyError(f"Field '{field_name}' not found in input fields.")
119
120
  return input.type
@@ -18,36 +18,24 @@ class DatabaseInterface(DBBasedInterface):
18
18
  def create(
19
19
  cls, creator_id: int, history_comment: str | None = None, **kwargs: Any
20
20
  ) -> int:
21
- from general_manager.manager.generalManager import GeneralManager
22
21
 
23
- cls.__checkForInvalidKwargs(cls._model, kwargs=kwargs)
24
- kwargs, many_to_many_kwargs = cls.__sortKwargs(cls._model, kwargs)
25
- instance = cls._model()
26
- for key, value in kwargs.items():
27
- if isinstance(value, GeneralManager):
28
- value = value.identification["id"]
29
- key = f"{key}_id"
30
- setattr(instance, key, value)
31
- for key, value in many_to_many_kwargs.items():
32
- getattr(instance, key).set(value)
33
- return cls.__save_with_history(instance, creator_id, history_comment)
22
+ cls._checkForInvalidKwargs(cls._model, kwargs=kwargs)
23
+ kwargs, many_to_many_kwargs = cls._sortKwargs(cls._model, kwargs)
24
+ instance = cls.__setAttrForWrite(cls._model(), kwargs)
25
+ pk = cls._save_with_history(instance, creator_id, history_comment)
26
+ cls.__setManyToManyAttributes(instance, many_to_many_kwargs)
27
+ return pk
34
28
 
35
29
  def update(
36
30
  self, creator_id: int, history_comment: str | None = None, **kwargs: Any
37
31
  ) -> int:
38
- from general_manager.manager.generalManager import GeneralManager
39
32
 
40
- self.__checkForInvalidKwargs(self._model, kwargs=kwargs)
41
- kwargs, many_to_many_kwargs = self.__sortKwargs(self._model, kwargs)
42
- instance = self._model.objects.get(pk=self.pk)
43
- for key, value in kwargs.items():
44
- if isinstance(value, GeneralManager):
45
- value = value.identification["id"]
46
- key = f"{key}_id"
47
- setattr(instance, key, value)
48
- for key, value in many_to_many_kwargs.items():
49
- getattr(instance, key).set(value)
50
- return self.__save_with_history(instance, creator_id, history_comment)
33
+ self._checkForInvalidKwargs(self._model, kwargs=kwargs)
34
+ kwargs, many_to_many_kwargs = self._sortKwargs(self._model, kwargs)
35
+ instance = self.__setAttrForWrite(self._model.objects.get(pk=self.pk), kwargs)
36
+ pk = self._save_with_history(instance, creator_id, history_comment)
37
+ self.__setManyToManyAttributes(instance, many_to_many_kwargs)
38
+ return pk
51
39
 
52
40
  def deactivate(self, creator_id: int, history_comment: str | None = None) -> int:
53
41
  instance = self._model.objects.get(pk=self.pk)
@@ -56,32 +44,68 @@ class DatabaseInterface(DBBasedInterface):
56
44
  history_comment = f"{history_comment} (deactivated)"
57
45
  else:
58
46
  history_comment = "Deactivated"
59
- return self.__save_with_history(instance, creator_id, history_comment)
47
+ return self._save_with_history(instance, creator_id, history_comment)
60
48
 
61
49
  @staticmethod
62
- def __checkForInvalidKwargs(model: Type[models.Model], kwargs: dict[Any, Any]):
50
+ def __setManyToManyAttributes(
51
+ instance: GeneralManagerModel, many_to_many_kwargs: dict[str, list[Any]]
52
+ ) -> GeneralManagerModel:
53
+ """
54
+ Sets many-to-many attributes for the given instance based on the provided kwargs.
55
+
56
+ Args:
57
+ instance: The model instance to update.
58
+ many_to_many_kwargs: A dictionary containing many-to-many field names and their corresponding values.
59
+
60
+ Returns:
61
+ The updated model instance.
62
+ """
63
+ for key, value in many_to_many_kwargs.items():
64
+ if not value:
65
+ continue
66
+ field_name = key.split("_id_list")[0]
67
+ getattr(instance, field_name).set(value)
68
+
69
+ return instance
70
+
71
+ @staticmethod
72
+ def __setAttrForWrite(
73
+ instance: GeneralManagerModel,
74
+ kwargs: dict[str, Any],
75
+ ) -> GeneralManagerModel:
76
+ from general_manager.manager.generalManager import GeneralManager
77
+
78
+ for key, value in kwargs.items():
79
+ if isinstance(value, GeneralManager):
80
+ value = value.identification["id"]
81
+ key = f"{key}_id"
82
+ setattr(instance, key, value)
83
+ return instance
84
+
85
+ @staticmethod
86
+ def _checkForInvalidKwargs(model: Type[models.Model], kwargs: dict[str, Any]):
63
87
  attributes = vars(model)
64
- fields = model._meta.get_fields()
88
+ field_names = {f.name for f in model._meta.get_fields()}
65
89
  for key in kwargs:
66
- if key not in attributes and key not in fields:
90
+ temp_key = key.split("_id_list")[0] # Remove '_id_list' suffix
91
+ if temp_key not in attributes and temp_key not in field_names:
67
92
  raise ValueError(f"{key} does not exsist in {model.__name__}")
68
93
 
69
94
  @staticmethod
70
- def __sortKwargs(
95
+ def _sortKwargs(
71
96
  model: Type[models.Model], kwargs: dict[Any, Any]
72
97
  ) -> tuple[dict[str, Any], dict[str, list[Any]]]:
73
- many_to_many_fields = model._meta.many_to_many
98
+ many_to_many_fields = [field.name for field in model._meta.many_to_many]
74
99
  many_to_many_kwargs: dict[Any, Any] = {}
75
- for key, value in kwargs.items():
100
+ for key, value in list(kwargs.items()):
76
101
  many_to_many_key = key.split("_id_list")[0]
77
102
  if many_to_many_key in many_to_many_fields:
78
- many_to_many_kwargs[key] = value
79
- kwargs.pop(key)
103
+ many_to_many_kwargs[key] = kwargs.pop(key)
80
104
  return kwargs, many_to_many_kwargs
81
105
 
82
106
  @classmethod
83
107
  @transaction.atomic
84
- def __save_with_history(
108
+ def _save_with_history(
85
109
  cls, instance: GeneralManagerModel, creator_id: int, history_comment: str | None
86
110
  ) -> int:
87
111
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.6.0
3
+ Version: 0.6.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-Expression: MIT
@@ -11,7 +11,7 @@ general_manager/auxiliary/makeCacheKey.py,sha256=lczutqxlofLSUnheKRi8nazhOyPa04T
11
11
  general_manager/auxiliary/noneToZero.py,sha256=KfQtMQnrT6vsYST0K7lv6pVujkDcK3XL8czHYOhgqKQ,539
12
12
  general_manager/auxiliary/pathMapping.py,sha256=nrz5owQg2a69Yig1eCXorR9U0NSw7NmBAk5OkeoHTdA,6842
13
13
  general_manager/bucket/baseBucket.py,sha256=65oQbSE6C8TE0yVPP_Aoi_Fwq0Uo2TLVPWMG6l2qxyQ,7836
14
- general_manager/bucket/calculationBucket.py,sha256=M2z7H7mvs56BIlr0NKQYqxcbWO92cFsgXSeKgM4oAko,18056
14
+ general_manager/bucket/calculationBucket.py,sha256=c4p4QBV6PVYi1sxM8iReZ2YQtMmD8q5uPXXwkgCX6fQ,18467
15
15
  general_manager/bucket/databaseBucket.py,sha256=V_xiPa8ErnPHVh_-i-oaH8qCa818UJxm5CVl80SVc1U,9060
16
16
  general_manager/bucket/groupBucket.py,sha256=55QdUaH_qO1JFJ2Jc1f2WcxniiLE5LB3vNwbnksKk8A,10939
17
17
  general_manager/cache/cacheDecorator.py,sha256=DK2ANIJgPpMxazfMSiFrI9OuVE_7K9zlIZQRrgaC2Lw,3268
@@ -25,9 +25,9 @@ general_manager/factory/factories.py,sha256=F6_nYFyJRYYc3LQApfoVFdctfLzsWUDHKafn
25
25
  general_manager/factory/factoryMethods.py,sha256=9Bag891j0XHe3dUBAFi7gUKcKeUwcBZN3cDLBobyBiI,3225
26
26
  general_manager/interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  general_manager/interface/baseInterface.py,sha256=b7MH-jVADcpGluvJMogPn2O3Yiy37uCnWOM9j0Ec0o0,8692
28
- general_manager/interface/calculationInterface.py,sha256=ZMYQcJZdfnEimsKOGFVfg-8r6Syjo_D9_HPVJkd59ak,4018
28
+ general_manager/interface/calculationInterface.py,sha256=Kg_OqLw67tcLwdzYNLq31eKVLzkM7taw-8Mzmk0CYi0,4232
29
29
  general_manager/interface/databaseBasedInterface.py,sha256=K2PYxANuLQU8wzrajcl922tuWwko642KJAS3f3PnAmg,21566
30
- general_manager/interface/databaseInterface.py,sha256=rQWeL5u_WCvDtikXLracFkECVM9vZHjs7UXTJlDDCmY,4146
30
+ general_manager/interface/databaseInterface.py,sha256=08dFgxoLQNa13RK2NQ4cDNbNPIG-X9ChLs3NvJcSp6Y,4923
31
31
  general_manager/interface/readOnlyInterface.py,sha256=d2CM2gj5XZNEaVFZeNCgqZf46rwUAetVS3SyePCKNsY,4691
32
32
  general_manager/manager/__init__.py,sha256=l3RYp62aEhj3Y975_XUTIzo35LUnkTJHkb_hgChnXXI,111
33
33
  general_manager/manager/generalManager.py,sha256=HX69KhrnSGVkuJwHY_jzff5gS0VD-6fRxKnd59A5Ct4,6100
@@ -46,8 +46,8 @@ general_manager/permission/permissionDataManager.py,sha256=Ji7fsnuaKTa6M8yzCGyzr
46
46
  general_manager/rule/__init__.py,sha256=4Har5cfPD1fmOsilTDod-ZUz3Com-tkl58jz7yY4fD0,23
47
47
  general_manager/rule/handler.py,sha256=z8SFHTIZ0LbLh3fV56Mud0V4_OvWkqJjlHvFqau7Qfk,7334
48
48
  general_manager/rule/rule.py,sha256=3FVCKGL7BTVoStdgOTdWQwuoVRIxAIAilV4VOzouDpc,10759
49
- generalmanager-0.6.0.dist-info/licenses/LICENSE,sha256=YGFm0ieb4KpkMRRt2qnWue6uFh0cUMtobwEBkHwajhc,1450
50
- generalmanager-0.6.0.dist-info/METADATA,sha256=Z3Eh9kL1htCX6HfL5DVmlU6FGIfvu_1k777eTxiNMjU,6205
51
- generalmanager-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
52
- generalmanager-0.6.0.dist-info/top_level.txt,sha256=sTDtExP9ga-YP3h3h42yivUY-A2Q23C2nw6LNKOho4I,16
53
- generalmanager-0.6.0.dist-info/RECORD,,
49
+ generalmanager-0.6.2.dist-info/licenses/LICENSE,sha256=YGFm0ieb4KpkMRRt2qnWue6uFh0cUMtobwEBkHwajhc,1450
50
+ generalmanager-0.6.2.dist-info/METADATA,sha256=LpZhar2vKhlCPwavT15s1yWSeMCHH6M9rqtC69BjraQ,6205
51
+ generalmanager-0.6.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
52
+ generalmanager-0.6.2.dist-info/top_level.txt,sha256=sTDtExP9ga-YP3h3h42yivUY-A2Q23C2nw6LNKOho4I,16
53
+ generalmanager-0.6.2.dist-info/RECORD,,