GeneralManager 0.12.1__tar.gz → 0.12.2__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 (65) hide show
  1. {generalmanager-0.12.1 → generalmanager-0.12.2}/GeneralManager.egg-info/PKG-INFO +1 -1
  2. {generalmanager-0.12.1 → generalmanager-0.12.2}/PKG-INFO +1 -1
  3. {generalmanager-0.12.1 → generalmanager-0.12.2}/pyproject.toml +1 -1
  4. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/interface/databaseBasedInterface.py +46 -9
  5. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/interface/databaseInterface.py +12 -8
  6. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/interface/models.py +1 -1
  7. {generalmanager-0.12.1 → generalmanager-0.12.2}/GeneralManager.egg-info/SOURCES.txt +0 -0
  8. {generalmanager-0.12.1 → generalmanager-0.12.2}/GeneralManager.egg-info/dependency_links.txt +0 -0
  9. {generalmanager-0.12.1 → generalmanager-0.12.2}/GeneralManager.egg-info/requires.txt +0 -0
  10. {generalmanager-0.12.1 → generalmanager-0.12.2}/GeneralManager.egg-info/top_level.txt +0 -0
  11. {generalmanager-0.12.1 → generalmanager-0.12.2}/LICENSE +0 -0
  12. {generalmanager-0.12.1 → generalmanager-0.12.2}/README.md +0 -0
  13. {generalmanager-0.12.1 → generalmanager-0.12.2}/setup.cfg +0 -0
  14. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/__init__.py +0 -0
  15. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/api/graphql.py +0 -0
  16. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/api/mutation.py +0 -0
  17. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/api/property.py +0 -0
  18. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/apps.py +0 -0
  19. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/bucket/baseBucket.py +0 -0
  20. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/bucket/calculationBucket.py +0 -0
  21. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/bucket/databaseBucket.py +0 -0
  22. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/bucket/groupBucket.py +0 -0
  23. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/cache/cacheDecorator.py +0 -0
  24. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/cache/cacheTracker.py +0 -0
  25. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/cache/dependencyIndex.py +0 -0
  26. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/cache/modelDependencyCollector.py +0 -0
  27. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/cache/signals.py +0 -0
  28. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/factory/__init__.py +0 -0
  29. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/factory/autoFactory.py +0 -0
  30. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/factory/factories.py +0 -0
  31. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/factory/factoryMethods.py +0 -0
  32. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/interface/__init__.py +0 -0
  33. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/interface/baseInterface.py +0 -0
  34. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/interface/calculationInterface.py +0 -0
  35. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/interface/readOnlyInterface.py +0 -0
  36. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/manager/__init__.py +0 -0
  37. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/manager/generalManager.py +0 -0
  38. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/manager/groupManager.py +0 -0
  39. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/manager/input.py +0 -0
  40. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/manager/meta.py +0 -0
  41. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/measurement/__init__.py +0 -0
  42. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/measurement/measurement.py +0 -0
  43. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/measurement/measurementField.py +0 -0
  44. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/permission/__init__.py +0 -0
  45. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/permission/basePermission.py +0 -0
  46. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/permission/fileBasedPermission.py +0 -0
  47. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/permission/managerBasedPermission.py +0 -0
  48. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/permission/mutationPermission.py +0 -0
  49. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/permission/permissionChecks.py +0 -0
  50. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/permission/permissionDataManager.py +0 -0
  51. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/permission/utils.py +0 -0
  52. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/rule/__init__.py +0 -0
  53. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/rule/handler.py +0 -0
  54. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/rule/rule.py +0 -0
  55. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/utils/__init__.py +0 -0
  56. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/utils/argsToKwargs.py +0 -0
  57. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/utils/filterParser.py +0 -0
  58. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/utils/formatString.py +0 -0
  59. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/utils/jsonEncoder.py +0 -0
  60. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/utils/makeCacheKey.py +0 -0
  61. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/utils/noneToZero.py +0 -0
  62. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/utils/pathMapping.py +0 -0
  63. {generalmanager-0.12.1 → generalmanager-0.12.2}/src/general_manager/utils/testing.py +0 -0
  64. {generalmanager-0.12.1 → generalmanager-0.12.2}/tests/test_settings.py +0 -0
  65. {generalmanager-0.12.1 → generalmanager-0.12.2}/tests/test_urls.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.12.1
3
+ Version: 0.12.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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.12.1
3
+ Version: 0.12.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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "GeneralManager"
7
- version = "0.12.1"
7
+ version = "0.12.2"
8
8
  description = "Modular Django-based data management framework with ORM, GraphQL, fine-grained permissions, rule validation, calculations and caching."
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Tim Kleindick", email = "tkleindick@yahoo.de" }]
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
  from typing import Type, Any, Callable, TYPE_CHECKING, TypeVar, Generic, cast
3
3
  from django.db import models
4
+
4
5
  from datetime import datetime, timedelta
5
6
  from general_manager.measurement.measurement import Measurement
6
7
  from general_manager.measurement.measurementField import MeasurementField
@@ -66,6 +67,25 @@ class DBBasedInterface(InterfaceBase, Generic[MODEL_TYPE]):
66
67
  instance = self.getHistoricalRecord(instance, search_date)
67
68
  return instance
68
69
 
70
+ @staticmethod
71
+ def __parseKwargs(**kwargs: Any) -> dict[str, Any]:
72
+ """
73
+ Parses keyword arguments to ensure they are compatible with the model's fields.
74
+
75
+ Converts GeneralManager instances to their primary key values and returns a dictionary of parsed arguments.
76
+ """
77
+ from general_manager.manager.generalManager import GeneralManager
78
+
79
+ parsed_kwargs: dict[str, Any] = {}
80
+ for key, value in kwargs.items():
81
+ if isinstance(value, GeneralManager):
82
+ parsed_kwargs[key] = getattr(
83
+ value._interface, "_instance", value.identification["id"]
84
+ )
85
+ else:
86
+ parsed_kwargs[key] = value
87
+ return parsed_kwargs
88
+
69
89
  @classmethod
70
90
  def filter(cls, **kwargs: Any) -> DatabaseBucket:
71
91
  """
@@ -77,6 +97,9 @@ class DBBasedInterface(InterfaceBase, Generic[MODEL_TYPE]):
77
97
  Returns:
78
98
  A DatabaseBucket wrapping the filtered queryset and associated metadata.
79
99
  """
100
+
101
+ kwargs = cls.__parseKwargs(**kwargs)
102
+
80
103
  return DatabaseBucket(
81
104
  cls._model.objects.filter(**kwargs),
82
105
  cls._parent_class,
@@ -94,6 +117,8 @@ class DBBasedInterface(InterfaceBase, Generic[MODEL_TYPE]):
94
117
  Returns:
95
118
  A DatabaseBucket wrapping the queryset of excluded model instances.
96
119
  """
120
+ kwargs = cls.__parseKwargs(**kwargs)
121
+
97
122
  return DatabaseBucket(
98
123
  cls._model.objects.exclude(**kwargs),
99
124
  cls._parent_class,
@@ -135,9 +160,9 @@ class DBBasedInterface(InterfaceBase, Generic[MODEL_TYPE]):
135
160
  @classmethod
136
161
  def getAttributeTypes(cls) -> dict[str, AttributeTypedDict]:
137
162
  """
138
- Return a dictionary mapping each attribute name of the model to its type information and metadata.
163
+ Return a dictionary mapping each model attribute name to its type information and metadata.
139
164
 
140
- The returned dictionary includes all standard model fields, custom fields, foreign keys, many-to-many, and reverse relation fields, excluding any GenericForeignKey fields. For each attribute, the metadata specifies its Python type (translated from Django field types when possible), whether it is required, editable, derived, and its default value. For related models with a general manager class, the type is set to that class.
165
+ Includes standard fields, custom fields, foreign keys, many-to-many, and reverse relation fields, excluding GenericForeignKey fields. For each attribute, provides its Python type (translated from Django field types when possible), required and editable status, whether it is derived, and its default value. For related models with a general manager class, the type is set to that class.
141
166
 
142
167
  Returns:
143
168
  dict[str, AttributeTypedDict]: Mapping of attribute names to their type information and metadata.
@@ -178,7 +203,8 @@ class DBBasedInterface(InterfaceBase, Generic[MODEL_TYPE]):
178
203
  fields[field_name] = {
179
204
  "type": type(field),
180
205
  "is_derived": False,
181
- "is_required": not field.null,
206
+ "is_required": not field.null
207
+ and field.default is models.NOT_PROVIDED,
182
208
  "is_editable": field.editable,
183
209
  "default": field.default,
184
210
  }
@@ -196,7 +222,7 @@ class DBBasedInterface(InterfaceBase, Generic[MODEL_TYPE]):
196
222
  ):
197
223
  related_model = related_model._general_manager_class # type: ignore
198
224
 
199
- elif related_model is not None:
225
+ if related_model is not None:
200
226
  default = None
201
227
  if hasattr(field, "default"):
202
228
  default = field.default # type: ignore
@@ -247,12 +273,12 @@ class DBBasedInterface(InterfaceBase, Generic[MODEL_TYPE]):
247
273
  @classmethod
248
274
  def getAttributes(cls) -> dict[str, Callable[[DBBasedInterface], Any]]:
249
275
  """
250
- Return a dictionary mapping attribute names to callables that retrieve values from a DBBasedInterface instance.
276
+ Return a mapping of attribute names to callables that extract values from a DBBasedInterface instance.
251
277
 
252
- The mapping includes accessors for custom fields, standard model fields, foreign keys, many-to-many relations, and reverse relations. For related models with a general manager class, the accessor returns an instance of that class; otherwise, it returns the related object or queryset. Raises a ValueError if a field name conflict is detected.
278
+ The returned dictionary includes accessors for custom fields, standard model fields, foreign keys, many-to-many relations, and reverse relations. For related models with a general manager class, the accessor returns an instance or queryset of that class; otherwise, it returns the related object or queryset directly. Raises a ValueError if a field name conflict is detected.
253
279
 
254
280
  Returns:
255
- dict: A dictionary where keys are attribute names and values are callables that extract the corresponding value from a DBBasedInterface instance.
281
+ dict[str, Callable[[DBBasedInterface], Any]]: Mapping of attribute names to callables for retrieving values from a DBBasedInterface instance.
256
282
  """
257
283
  from general_manager.manager.generalManager import GeneralManager
258
284
 
@@ -306,12 +332,22 @@ class DBBasedInterface(InterfaceBase, Generic[MODEL_TYPE]):
306
332
  cls._model._meta.get_field(field_name).related_model,
307
333
  "_general_manager_class",
308
334
  ):
335
+ related_model = cast(
336
+ Type[models.Model],
337
+ cls._model._meta.get_field(field_name).related_model,
338
+ )
339
+ related_fields = [
340
+ f
341
+ for f in related_model._meta.get_fields()
342
+ if f.related_model == cls._model
343
+ ]
344
+
309
345
  field_values[
310
346
  f"{field_name}_list"
311
- ] = lambda self, field_name=field_name: self._instance._meta.get_field(
347
+ ] = lambda self, field_name=field_name, related_fields=related_fields: self._instance._meta.get_field(
312
348
  field_name
313
349
  ).related_model._general_manager_class.filter(
314
- **{self._instance.__class__.__name__.lower(): self.pk}
350
+ **{related_field.name: self.pk for related_field in related_fields}
315
351
  )
316
352
  else:
317
353
  field_values[f"{field_name}_list"] = (
@@ -319,6 +355,7 @@ class DBBasedInterface(InterfaceBase, Generic[MODEL_TYPE]):
319
355
  self._instance, field_call
320
356
  ).all()
321
357
  )
358
+
322
359
  return field_values
323
360
 
324
361
  @staticmethod
@@ -84,19 +84,23 @@ class DatabaseInterface(DBBasedInterface[GeneralManagerModel]):
84
84
  instance: GeneralManagerModel, many_to_many_kwargs: dict[str, list[Any]]
85
85
  ) -> GeneralManagerModel:
86
86
  """
87
- Sets many-to-many attributes for the given instance based on the provided kwargs.
87
+ Set many-to-many relationship fields on a model instance using provided values.
88
88
 
89
- Args:
90
- instance: The model instance to update.
91
- many_to_many_kwargs: A dictionary containing many-to-many field names and their corresponding values.
92
-
93
- Returns:
94
- The updated model instance.
89
+ Converts lists of `GeneralManager` instances to their corresponding IDs before updating the relationships. Returns the updated instance.
95
90
  """
91
+ from general_manager.manager.generalManager import GeneralManager
92
+
96
93
  for key, value in many_to_many_kwargs.items():
97
94
  if not value:
98
95
  continue
99
- field_name = key.split("_id_list")[0]
96
+ field_name = key.removesuffix("_id_list")
97
+ if isinstance(value, list) and all(
98
+ isinstance(v, GeneralManager) for v in value
99
+ ):
100
+ value = [
101
+ v.identification["id"] if hasattr(v, "identification") else v
102
+ for v in value
103
+ ]
100
104
  getattr(instance, field_name).set(value)
101
105
 
102
106
  return instance
@@ -39,7 +39,7 @@ def getFullCleanMethode(model: Type[models.Model]) -> Callable[..., None]:
39
39
  except ValidationError as e:
40
40
  errors.update(e.message_dict)
41
41
 
42
- rules: list[Rule] = getattr(self._meta, "rules")
42
+ rules: list[Rule] = getattr(self._meta, "rules", [])
43
43
  for rule in rules:
44
44
  if rule.evaluate(self) is False:
45
45
  error_message = rule.getErrorMessage()
File without changes