GeneralManager 0.4.6__tar.gz → 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. {generalmanager-0.4.6 → generalmanager-0.5.1}/GeneralManager.egg-info/PKG-INFO +1 -1
  2. {generalmanager-0.4.6 → generalmanager-0.5.1}/GeneralManager.egg-info/SOURCES.txt +2 -0
  3. {generalmanager-0.4.6 → generalmanager-0.5.1}/PKG-INFO +1 -1
  4. {generalmanager-0.4.6 → generalmanager-0.5.1}/pyproject.toml +1 -1
  5. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/apps.py +1 -1
  6. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/interface/baseInterface.py +6 -6
  7. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/manager/groupManager.py +34 -22
  8. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/manager/meta.py +18 -5
  9. generalmanager-0.5.1/tests/test_generalManagerMeta.py +581 -0
  10. generalmanager-0.5.1/tests/test_groupManager.py +319 -0
  11. {generalmanager-0.4.6 → generalmanager-0.5.1}/GeneralManager.egg-info/dependency_links.txt +0 -0
  12. {generalmanager-0.4.6 → generalmanager-0.5.1}/GeneralManager.egg-info/requires.txt +0 -0
  13. {generalmanager-0.4.6 → generalmanager-0.5.1}/GeneralManager.egg-info/top_level.txt +0 -0
  14. {generalmanager-0.4.6 → generalmanager-0.5.1}/LICENSE +0 -0
  15. {generalmanager-0.4.6 → generalmanager-0.5.1}/README.md +0 -0
  16. {generalmanager-0.4.6 → generalmanager-0.5.1}/setup.cfg +0 -0
  17. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/__init__.py +0 -0
  18. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/api/graphql.py +0 -0
  19. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/api/mutation.py +0 -0
  20. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/api/property.py +0 -0
  21. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/auxiliary/__init__.py +0 -0
  22. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/auxiliary/argsToKwargs.py +0 -0
  23. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/auxiliary/filterParser.py +0 -0
  24. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/auxiliary/jsonEncoder.py +0 -0
  25. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/auxiliary/makeCacheKey.py +0 -0
  26. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/auxiliary/noneToZero.py +0 -0
  27. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/auxiliary/pathMapping.py +0 -0
  28. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/cache/cacheDecorator.py +0 -0
  29. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/cache/cacheTracker.py +0 -0
  30. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/cache/dependencyIndex.py +0 -0
  31. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/cache/modelDependencyCollector.py +0 -0
  32. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/cache/signals.py +0 -0
  33. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/factory/__init__.py +0 -0
  34. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/factory/autoFactory.py +0 -0
  35. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/factory/factories.py +0 -0
  36. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/factory/factoryMethods.py +0 -0
  37. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/interface/__init__.py +0 -0
  38. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/interface/calculationInterface.py +0 -0
  39. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/interface/databaseInterface.py +0 -0
  40. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/manager/__init__.py +0 -0
  41. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/manager/generalManager.py +0 -0
  42. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/manager/input.py +0 -0
  43. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/measurement/__init__.py +0 -0
  44. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/measurement/measurement.py +0 -0
  45. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/measurement/measurementField.py +0 -0
  46. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/permission/__init__.py +0 -0
  47. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/permission/basePermission.py +0 -0
  48. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/permission/fileBasedPermission.py +0 -0
  49. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/permission/managerBasedPermission.py +0 -0
  50. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/permission/permissionChecks.py +0 -0
  51. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/permission/permissionDataManager.py +0 -0
  52. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/rule/__init__.py +0 -0
  53. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/rule/handler.py +0 -0
  54. {generalmanager-0.4.6 → generalmanager-0.5.1}/src/general_manager/rule/rule.py +0 -0
  55. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_argsToKwargs.py +0 -0
  56. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_autoFactory.py +0 -0
  57. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_basePermission.py +0 -0
  58. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_cacheDecorator.py +0 -0
  59. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_cacheTracker.py +0 -0
  60. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_dependencyIndex.py +0 -0
  61. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_factories.py +0 -0
  62. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_factoryMethods.py +0 -0
  63. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_filterParser.py +0 -0
  64. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_generalManager.py +0 -0
  65. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_graph_ql.py +0 -0
  66. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_input.py +0 -0
  67. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_jsonEncoder.py +0 -0
  68. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_makeCacheKey.py +0 -0
  69. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_managerBasedPermission.py +0 -0
  70. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_measurement.py +0 -0
  71. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_measurement_field.py +0 -0
  72. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_modelDependencyCollector.py +0 -0
  73. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_noneToZero.py +0 -0
  74. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_rule_handler.py +0 -0
  75. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_rules.py +0 -0
  76. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_settings.py +0 -0
  77. {generalmanager-0.4.6 → generalmanager-0.5.1}/tests/test_signals.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.4.6
3
+ Version: 0.5.1
4
4
  Summary: Kurzbeschreibung deines Pakets
5
5
  Author-email: Tim Kleindick <tkleindick@yahoo.de>
6
6
  License-Expression: MIT
@@ -58,7 +58,9 @@ tests/test_factories.py
58
58
  tests/test_factoryMethods.py
59
59
  tests/test_filterParser.py
60
60
  tests/test_generalManager.py
61
+ tests/test_generalManagerMeta.py
61
62
  tests/test_graph_ql.py
63
+ tests/test_groupManager.py
62
64
  tests/test_input.py
63
65
  tests/test_jsonEncoder.py
64
66
  tests/test_makeCacheKey.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.4.6
3
+ Version: 0.5.1
4
4
  Summary: Kurzbeschreibung deines Pakets
5
5
  Author-email: Tim Kleindick <tkleindick@yahoo.de>
6
6
  License-Expression: MIT
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "GeneralManager"
10
- version = "0.4.6"
10
+ version = "0.5.1"
11
11
  description = "Kurzbeschreibung deines Pakets"
12
12
  readme = "README.md"
13
13
  authors = [
@@ -41,7 +41,7 @@ class GeneralmanagerConfig(AppConfig):
41
41
  attributes = general_manager_class.Interface.getAttributes()
42
42
  setattr(general_manager_class, "_attributes", attributes)
43
43
  GeneralManagerMeta.createAtPropertiesForAttributes(
44
- attributes, general_manager_class
44
+ attributes.keys(), general_manager_class
45
45
  )
46
46
 
47
47
  if getattr(settings, "AUTOCREATE_GRAPHQL", False):
@@ -21,7 +21,7 @@ if TYPE_CHECKING:
21
21
  from general_manager.manager.input import Input
22
22
  from general_manager.manager.generalManager import GeneralManager
23
23
  from general_manager.manager.meta import GeneralManagerMeta
24
- from general_manager.manager.groupManager import GroupedManager, GroupBucket
24
+ from general_manager.manager.groupManager import GroupManager, GroupBucket
25
25
 
26
26
 
27
27
  GeneralManagerType = TypeVar("GeneralManagerType", bound="GeneralManager")
@@ -239,7 +239,7 @@ class Bucket(ABC, Generic[GeneralManagerType]):
239
239
  @abstractmethod
240
240
  def __iter__(
241
241
  self,
242
- ) -> Generator[GeneralManagerType | GroupedManager[GeneralManagerType]]:
242
+ ) -> Generator[GeneralManagerType | GroupManager[GeneralManagerType]]:
243
243
  raise NotImplementedError
244
244
 
245
245
  @abstractmethod
@@ -251,11 +251,11 @@ class Bucket(ABC, Generic[GeneralManagerType]):
251
251
  raise NotImplementedError
252
252
 
253
253
  @abstractmethod
254
- def first(self) -> GeneralManagerType | GroupedManager[GeneralManagerType] | None:
254
+ def first(self) -> GeneralManagerType | GroupManager[GeneralManagerType] | None:
255
255
  raise NotImplementedError
256
256
 
257
257
  @abstractmethod
258
- def last(self) -> GeneralManagerType | GroupedManager[GeneralManagerType] | None:
258
+ def last(self) -> GeneralManagerType | GroupManager[GeneralManagerType] | None:
259
259
  raise NotImplementedError
260
260
 
261
261
  @abstractmethod
@@ -269,7 +269,7 @@ class Bucket(ABC, Generic[GeneralManagerType]):
269
269
  @abstractmethod
270
270
  def get(
271
271
  self, **kwargs: Any
272
- ) -> GeneralManagerType | GroupedManager[GeneralManagerType]:
272
+ ) -> GeneralManagerType | GroupManager[GeneralManagerType]:
273
273
  raise NotImplementedError
274
274
 
275
275
  @abstractmethod
@@ -277,7 +277,7 @@ class Bucket(ABC, Generic[GeneralManagerType]):
277
277
  self, item: int | slice
278
278
  ) -> (
279
279
  GeneralManagerType
280
- | GroupedManager[GeneralManagerType]
280
+ | GroupManager[GeneralManagerType]
281
281
  | Bucket[GeneralManagerType]
282
282
  ):
283
283
  raise NotImplementedError
@@ -32,6 +32,15 @@ class GroupBucket(Bucket[GeneralManagerType]):
32
32
  self._data = self.__buildGroupedManager(data)
33
33
  self._basis_data = data
34
34
 
35
+ def __eq__(self, other: object) -> bool:
36
+ if not isinstance(other, self.__class__):
37
+ return False
38
+ return (
39
+ self._data == other._data
40
+ and self._manager_class == other._manager_class
41
+ and self._group_by_keys == other._group_by_keys
42
+ )
43
+
35
44
  def __checkGroupByArguments(self, group_by_keys: tuple[str, ...]) -> None:
36
45
  """
37
46
  This method checks if the given arguments are valid for the groupBy method.
@@ -50,7 +59,7 @@ class GroupBucket(Bucket[GeneralManagerType]):
50
59
  def __buildGroupedManager(
51
60
  self,
52
61
  data: Bucket[GeneralManagerType],
53
- ) -> list[GroupedManager[GeneralManagerType]]:
62
+ ) -> list[GroupManager[GeneralManagerType]]:
54
63
  """
55
64
  This method builds the grouped manager.
56
65
  It returns a GroupBucket with the grouped data.
@@ -63,11 +72,11 @@ class GroupBucket(Bucket[GeneralManagerType]):
63
72
  group_by_values.add(json.dumps(group_by_value))
64
73
 
65
74
  groups = []
66
- for group_by_value in group_by_values:
75
+ for group_by_value in sorted(group_by_values):
67
76
  group_by_value = json.loads(group_by_value)
68
77
  grouped_manager_objects = data.filter(**group_by_value)
69
78
  groups.append(
70
- GroupedManager(
79
+ GroupManager(
71
80
  self._manager_class, group_by_value, grouped_manager_objects
72
81
  )
73
82
  )
@@ -84,7 +93,7 @@ class GroupBucket(Bucket[GeneralManagerType]):
84
93
  self._basis_data | other._basis_data,
85
94
  )
86
95
 
87
- def __iter__(self) -> Generator[GroupedManager[GeneralManagerType]]:
96
+ def __iter__(self) -> Generator[GroupManager[GeneralManagerType]]:
88
97
  for grouped_manager in self._data:
89
98
  yield grouped_manager
90
99
 
@@ -104,13 +113,13 @@ class GroupBucket(Bucket[GeneralManagerType]):
104
113
  new_basis_data,
105
114
  )
106
115
 
107
- def first(self) -> GroupedManager[GeneralManagerType] | None:
116
+ def first(self) -> GroupManager[GeneralManagerType] | None:
108
117
  try:
109
118
  return next(iter(self))
110
119
  except StopIteration:
111
120
  return None
112
121
 
113
- def last(self) -> GroupedManager[GeneralManagerType] | None:
122
+ def last(self) -> GroupManager[GeneralManagerType] | None:
114
123
  items = list(self)
115
124
  if items:
116
125
  return items[-1]
@@ -122,7 +131,7 @@ class GroupBucket(Bucket[GeneralManagerType]):
122
131
  def all(self) -> Bucket[GeneralManagerType]:
123
132
  return self
124
133
 
125
- def get(self, **kwargs: Any) -> GroupedManager[GeneralManagerType]:
134
+ def get(self, **kwargs: Any) -> GroupManager[GeneralManagerType]:
126
135
  first_value = self.filter(**kwargs).first()
127
136
  if first_value is None:
128
137
  raise ValueError(
@@ -132,7 +141,7 @@ class GroupBucket(Bucket[GeneralManagerType]):
132
141
 
133
142
  def __getitem__(
134
143
  self, item: int | slice
135
- ) -> GroupedManager[GeneralManagerType] | GroupBucket[GeneralManagerType]:
144
+ ) -> GroupManager[GeneralManagerType] | GroupBucket[GeneralManagerType]:
136
145
  if isinstance(item, int):
137
146
  return self._data[item]
138
147
  elif isinstance(item, slice):
@@ -162,12 +171,14 @@ class GroupBucket(Bucket[GeneralManagerType]):
162
171
  if isinstance(key, str):
163
172
  key = (key,)
164
173
  if reverse:
165
- sorted_data = self._data.sort(
166
- key=lambda x: tuple([-getattr(x, k) for k in key])
174
+ sorted_data = sorted(
175
+ self._data,
176
+ key=lambda x: tuple(getattr(x, k) for k in key),
177
+ reverse=True,
167
178
  )
168
179
  else:
169
- sorted_data = self._data.sort(
170
- key=lambda x: tuple([getattr(x, k) for k in key])
180
+ sorted_data = sorted(
181
+ self._data, key=lambda x: tuple(getattr(x, k) for k in key)
171
182
  )
172
183
 
173
184
  new_bucket = GroupBucket(
@@ -182,11 +193,13 @@ class GroupBucket(Bucket[GeneralManagerType]):
182
193
  It returns a GroupBucket with the grouped data.
183
194
  """
184
195
  return GroupBucket(
185
- self._manager_class, tuple([*self._group_by_keys, *group_by_keys]), self
196
+ self._manager_class,
197
+ tuple([*self._group_by_keys, *group_by_keys]),
198
+ self._basis_data,
186
199
  )
187
200
 
188
201
 
189
- class GroupedManager(Generic[GeneralManagerType]):
202
+ class GroupManager(Generic[GeneralManagerType]):
190
203
  """
191
204
  This class is used to group the data of a GeneralManager.
192
205
  It is used to create a new GeneralManager with the grouped data.
@@ -212,11 +225,6 @@ class GroupedManager(Generic[GeneralManagerType]):
212
225
  and self._group_by_value == other._group_by_value
213
226
  )
214
227
 
215
- def __hash__(self) -> int:
216
- return hash(
217
- (self._manager_class, frozenset(self._group_by_value.items()), self._data)
218
- )
219
-
220
228
  def __repr__(self) -> str:
221
229
  return f"{self.__class__.__name__}({self._manager_class}, {self._group_by_value}, {self._data})"
222
230
 
@@ -277,12 +285,16 @@ class GroupedManager(Generic[GeneralManagerType]):
277
285
  for entry in total_data:
278
286
  new_data.update(entry)
279
287
  elif issubclass(data_type, str):
280
- new_data = " ".join(total_data)
288
+ temp_data = []
289
+ for entry in total_data:
290
+ if entry not in temp_data:
291
+ temp_data.append(str(entry))
292
+ new_data = ", ".join(temp_data)
293
+ elif issubclass(data_type, bool):
294
+ new_data = any(total_data)
281
295
  elif issubclass(data_type, (int, float, Measurement)):
282
296
  new_data = sum(total_data)
283
297
  elif issubclass(data_type, (datetime, date, time)):
284
298
  new_data = max(total_data)
285
- elif issubclass(data_type, bool):
286
- new_data = any(total_data)
287
299
 
288
300
  return new_data
@@ -3,7 +3,7 @@ from general_manager.interface.baseInterface import (
3
3
  InterfaceBase,
4
4
  )
5
5
  from django.conf import settings
6
- from typing import Any, Type, TYPE_CHECKING, Generic, TypeVar
6
+ from typing import Any, Type, TYPE_CHECKING, Generic, TypeVar, Iterable
7
7
 
8
8
  if TYPE_CHECKING:
9
9
  from general_manager.interface.databaseInterface import ReadOnlyInterface
@@ -12,6 +12,10 @@ if TYPE_CHECKING:
12
12
  GeneralManagerType = TypeVar("GeneralManagerType", bound="GeneralManager")
13
13
 
14
14
 
15
+ class _nonExistent:
16
+ pass
17
+
18
+
15
19
  class GeneralManagerMeta(type):
16
20
  all_classes: list[Type[GeneralManager]] = []
17
21
  read_only_classes: list[Type[ReadOnlyInterface]] = []
@@ -48,7 +52,7 @@ class GeneralManagerMeta(type):
48
52
 
49
53
  @staticmethod
50
54
  def createAtPropertiesForAttributes(
51
- attributes: dict[str, Any], new_class: Type[GeneralManager]
55
+ attributes: Iterable[str], new_class: Type[GeneralManager]
52
56
  ):
53
57
 
54
58
  def desciptorMethod(attr_name: str, new_class: type):
@@ -64,12 +68,21 @@ class GeneralManagerMeta(type):
64
68
  ):
65
69
  if instance is None:
66
70
  return self.new_class.Interface.getFieldType(self.attr_name)
67
- attribute = instance._attributes[attr_name]
71
+ attribute = instance._attributes.get(attr_name, _nonExistent)
72
+ if attribute is _nonExistent:
73
+ raise AttributeError(
74
+ f"{self.attr_name} not found in {instance.__class__.__name__}"
75
+ )
68
76
  if callable(attribute):
69
- return attribute(instance._interface)
77
+ try:
78
+ attribute = attribute(instance._interface)
79
+ except Exception as e:
80
+ raise AttributeError(
81
+ f"Error calling attribute {self.attr_name}: {e}"
82
+ ) from e
70
83
  return attribute
71
84
 
72
85
  return Descriptor(attr_name, new_class)
73
86
 
74
- for attr_name in attributes.keys():
87
+ for attr_name in attributes:
75
88
  setattr(new_class, attr_name, desciptorMethod(attr_name, new_class))