GeneralManager 0.10.2__tar.gz → 0.10.4__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 (64) hide show
  1. {generalmanager-0.10.2 → generalmanager-0.10.4}/GeneralManager.egg-info/PKG-INFO +1 -1
  2. {generalmanager-0.10.2 → generalmanager-0.10.4}/PKG-INFO +1 -1
  3. {generalmanager-0.10.2 → generalmanager-0.10.4}/pyproject.toml +1 -1
  4. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/api/graphql.py +31 -38
  5. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/apps.py +6 -6
  6. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/bucket/baseBucket.py +33 -31
  7. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/bucket/calculationBucket.py +9 -10
  8. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/bucket/databaseBucket.py +22 -28
  9. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/bucket/groupBucket.py +1 -1
  10. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/cache/modelDependencyCollector.py +6 -4
  11. generalmanager-0.10.4/src/general_manager/cache/signals.py +60 -0
  12. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/factory/autoFactory.py +34 -34
  13. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/factory/factories.py +73 -43
  14. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/interface/baseInterface.py +3 -3
  15. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/interface/databaseBasedInterface.py +63 -43
  16. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/manager/generalManager.py +52 -42
  17. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/manager/meta.py +19 -10
  18. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/measurement/measurementField.py +19 -3
  19. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/utils/testing.py +66 -7
  20. generalmanager-0.10.2/src/general_manager/cache/signals.py +0 -48
  21. {generalmanager-0.10.2 → generalmanager-0.10.4}/GeneralManager.egg-info/SOURCES.txt +0 -0
  22. {generalmanager-0.10.2 → generalmanager-0.10.4}/GeneralManager.egg-info/dependency_links.txt +0 -0
  23. {generalmanager-0.10.2 → generalmanager-0.10.4}/GeneralManager.egg-info/requires.txt +0 -0
  24. {generalmanager-0.10.2 → generalmanager-0.10.4}/GeneralManager.egg-info/top_level.txt +0 -0
  25. {generalmanager-0.10.2 → generalmanager-0.10.4}/LICENSE +0 -0
  26. {generalmanager-0.10.2 → generalmanager-0.10.4}/README.md +0 -0
  27. {generalmanager-0.10.2 → generalmanager-0.10.4}/setup.cfg +0 -0
  28. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/__init__.py +0 -0
  29. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/api/mutation.py +0 -0
  30. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/api/property.py +0 -0
  31. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/cache/cacheDecorator.py +0 -0
  32. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/cache/cacheTracker.py +0 -0
  33. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/cache/dependencyIndex.py +0 -0
  34. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/factory/__init__.py +0 -0
  35. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/factory/factoryMethods.py +0 -0
  36. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/interface/__init__.py +0 -0
  37. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/interface/calculationInterface.py +0 -0
  38. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/interface/databaseInterface.py +0 -0
  39. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/interface/models.py +0 -0
  40. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/interface/readOnlyInterface.py +0 -0
  41. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/manager/__init__.py +0 -0
  42. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/manager/groupManager.py +0 -0
  43. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/manager/input.py +0 -0
  44. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/measurement/__init__.py +0 -0
  45. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/measurement/measurement.py +0 -0
  46. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/permission/__init__.py +0 -0
  47. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/permission/basePermission.py +0 -0
  48. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/permission/fileBasedPermission.py +0 -0
  49. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/permission/managerBasedPermission.py +0 -0
  50. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/permission/permissionChecks.py +0 -0
  51. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/permission/permissionDataManager.py +0 -0
  52. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/rule/__init__.py +0 -0
  53. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/rule/handler.py +0 -0
  54. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/rule/rule.py +0 -0
  55. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/utils/__init__.py +0 -0
  56. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/utils/argsToKwargs.py +0 -0
  57. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/utils/filterParser.py +0 -0
  58. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/utils/formatString.py +0 -0
  59. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/utils/jsonEncoder.py +0 -0
  60. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/utils/makeCacheKey.py +0 -0
  61. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/utils/noneToZero.py +0 -0
  62. {generalmanager-0.10.2 → generalmanager-0.10.4}/src/general_manager/utils/pathMapping.py +0 -0
  63. {generalmanager-0.10.2 → generalmanager-0.10.4}/tests/test_settings.py +0 -0
  64. {generalmanager-0.10.2 → generalmanager-0.10.4}/tests/test_urls.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GeneralManager
3
- Version: 0.10.2
3
+ Version: 0.10.4
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.10.2
3
+ Version: 0.10.4
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.10.2"
7
+ version = "0.10.4"
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" }]
@@ -102,9 +102,9 @@ class GraphQL:
102
102
  @classmethod
103
103
  def createGraphqlInterface(cls, generalManagerClass: GeneralManagerMeta) -> None:
104
104
  """
105
- Generates and registers a GraphQL ObjectType for the specified GeneralManager class.
105
+ Generates and registers a GraphQL ObjectType for a given GeneralManager class.
106
106
 
107
- This method maps interface attributes and GraphQLProperty attributes to Graphene fields, creates corresponding resolvers, registers the resulting type in the internal registry, and attaches relevant query fields to the schema.
107
+ This method maps interface and GraphQLProperty attributes to Graphene fields, creates resolvers for each field, registers the resulting type in the internal registry, and adds corresponding query fields to the schema.
108
108
  """
109
109
  interface_cls: InterfaceBase | None = getattr(
110
110
  generalManagerClass, "Interface", None
@@ -348,14 +348,7 @@ class GraphQL:
348
348
  base_getter: Callable[[Any], Any], fallback_manager_class: type[GeneralManager]
349
349
  ) -> Callable[..., Any]:
350
350
  """
351
- Creates a resolver function for list fields that applies permission filters, query filters, sorting, pagination, and optional grouping to a queryset.
352
-
353
- Parameters:
354
- base_getter (Callable): Function to obtain the base queryset from the parent instance.
355
- fallback_manager_class (type[GeneralManager]): Manager class to use if the queryset does not specify one.
356
-
357
- Returns:
358
- Callable: A resolver function for use in GraphQL list fields.
351
+ Returns a resolver function for GraphQL list fields that retrieves a queryset, applies permission-based filtering, query filters, sorting, pagination, and optional grouping, and returns the resulting data.
359
352
  """
360
353
 
361
354
  def resolver(
@@ -370,19 +363,19 @@ class GraphQL:
370
363
  group_by: list[str] | None = None,
371
364
  ) -> Any:
372
365
  """
373
- Resolves a list field by applying permission filters, query parameters, sorting, pagination, and optional grouping to a queryset.
366
+ Resolves a list field by returning a queryset filtered by permissions, query parameters, sorting, pagination, and optional grouping.
374
367
 
375
368
  Parameters:
376
- filter: Optional filter criteria as a dictionary or JSON string.
377
- exclude: Optional exclusion criteria as a dictionary or JSON string.
378
- sort_by: Optional sorting field as a Graphene Enum.
379
- reverse: If True, reverses the sort order.
380
- page: Optional page number for pagination.
381
- page_size: Optional number of items per page.
382
- group_by: Optional list of field names to group results by.
369
+ filter: Filter criteria as a dictionary or JSON string.
370
+ exclude: Exclusion criteria as a dictionary or JSON string.
371
+ sort_by: Field to sort by, as a Graphene Enum.
372
+ reverse: Whether to reverse the sort order.
373
+ page: Page number for pagination.
374
+ page_size: Number of items per page.
375
+ group_by: List of field names to group results by.
383
376
 
384
377
  Returns:
385
- The filtered, sorted, paginated, and optionally grouped queryset.
378
+ A queryset with applied permission filters, filtering, sorting, pagination, and grouping.
386
379
  """
387
380
  base_queryset = base_getter(self)
388
381
  # use _manager_class from the attribute if available, otherwise fallback
@@ -460,7 +453,7 @@ class GraphQL:
460
453
  """
461
454
  Adds list and single-item query fields for a GeneralManager-derived class to the GraphQL schema.
462
455
 
463
- This method registers both a list query (with filtering, sorting, pagination, and grouping) and a single-item query (using identification fields) for the specified manager class. The corresponding resolvers are also attached to the schema.
456
+ Registers a list query supporting filtering, sorting, pagination, and grouping, as well as a single-item query using identification fields for the specified manager class. The corresponding resolvers are attached to the schema.
464
457
  """
465
458
  if not issubclass(generalManagerClass, GeneralManager):
466
459
  raise TypeError(
@@ -526,10 +519,10 @@ class GraphQL:
526
519
  """
527
520
  Generate a dictionary of Graphene input fields for mutations based on the attributes of the provided interface class.
528
521
 
529
- Skips fields that are system-managed (`changed_by`, `created_at`, `updated_at`) or marked as derived. For attributes referencing `GeneralManager` subclasses, uses ID fields; for list references, uses a list of IDs. All other types are mapped to their corresponding Graphene scalar types. Each field is annotated with an `editable` attribute indicating if it can be modified. Adds an optional `history_comment` field marked as editable.
522
+ Skips system-managed fields and derived attributes. For attributes referencing `GeneralManager` subclasses, uses ID or list of IDs as appropriate. Other types are mapped to their corresponding Graphene scalar types. Each field is annotated with an `editable` attribute. Adds an optional `history_comment` field marked as editable.
530
523
 
531
524
  Returns:
532
- dict[str, Any]: A dictionary mapping attribute names to Graphene input fields for use in mutation arguments.
525
+ dict[str, Any]: Mapping of attribute names to Graphene input fields for mutation arguments.
533
526
  """
534
527
  fields: dict[str, Any] = {}
535
528
 
@@ -579,12 +572,12 @@ class GraphQL:
579
572
  default_return_values: dict[str, Any],
580
573
  ) -> type[graphene.Mutation] | None:
581
574
  """
582
- Generates a Graphene mutation class for creating an instance of the specified GeneralManager subclass.
575
+ Dynamically generates a Graphene mutation class for creating an instance of the specified GeneralManager subclass.
583
576
 
584
- The generated mutation class defines a `mutate` method that filters out fields with `NOT_PROVIDED` values, invokes the `create` method on the manager class with the provided arguments and the current user's ID, and returns a dictionary indicating success or failure along with any errors and the created instance.
577
+ The generated mutation class includes a `mutate` method that filters out fields with `NOT_PROVIDED` values, invokes the manager's `create` method with the provided arguments and the current user's ID, and returns a dictionary indicating success, any errors, and the created instance. Returns None if the manager class does not define an interface.
585
578
 
586
579
  Returns:
587
- The generated Graphene mutation class, or None if the manager class does not define an interface.
580
+ The generated Graphene mutation class, or None if no interface is defined for the manager class.
588
581
  """
589
582
  interface_cls: InterfaceBase | None = getattr(
590
583
  generalManagerClass, "Interface", None
@@ -595,12 +588,12 @@ class GraphQL:
595
588
  def create_mutation(
596
589
  self,
597
590
  info: GraphQLResolveInfo,
598
- **kwargs: dict[str, Any],
591
+ **kwargs: Any,
599
592
  ) -> dict:
600
593
  """
601
- Creates a new instance of the specified manager class using provided input arguments.
594
+ Creates a new instance of the manager class with the provided arguments.
602
595
 
603
- Filters out fields with default "not provided" values before creation. Returns a dictionary indicating success status, any errors encountered, and the created instance under a key named after the manager class.
596
+ Filters out fields with values marked as `NOT_PROVIDED` before creation. Returns a dictionary containing a success flag, a list of errors (if any), and the created instance under a key named after the manager class.
604
597
  """
605
598
  try:
606
599
  kwargs = {
@@ -651,9 +644,9 @@ class GraphQL:
651
644
  default_return_values: dict[str, Any],
652
645
  ) -> type[graphene.Mutation] | None:
653
646
  """
654
- Generates a GraphQL mutation class for updating an instance of a GeneralManager subclass.
647
+ Generates a GraphQL mutation class for updating instances of a GeneralManager subclass.
655
648
 
656
- The generated mutation accepts editable fields as arguments, calls the `update` method on the manager instance, and returns a dictionary indicating success, errors, and the updated instance. If the manager class does not define an `Interface`, returns None.
649
+ The generated mutation accepts editable fields as arguments, invokes the manager's `update` method with the provided values, and returns a dictionary indicating success, any errors, and the updated instance. Returns None if the manager class does not define an `Interface`.
657
650
 
658
651
  Returns:
659
652
  The generated Graphene mutation class, or None if no interface is defined.
@@ -667,17 +660,17 @@ class GraphQL:
667
660
  def update_mutation(
668
661
  self,
669
662
  info: GraphQLResolveInfo,
670
- **kwargs: dict[str, Any],
663
+ **kwargs: Any,
671
664
  ) -> dict:
672
665
  """
673
- Handles the update mutation for a GeneralManager instance, applying provided field updates and returning the operation result.
666
+ Performs an update mutation on a GeneralManager instance with the specified fields.
674
667
 
675
668
  Parameters:
676
- info (GraphQLResolveInfo): GraphQL resolver context containing user and request information.
669
+ info (GraphQLResolveInfo): The GraphQL resolver context, typically containing user and request information.
677
670
  **kwargs: Fields to update, including the required 'id' of the instance.
678
671
 
679
672
  Returns:
680
- dict: A dictionary containing the success status, any error messages, and the updated instance keyed by its class name.
673
+ dict: Contains the operation's success status, a list of error messages if any, and the updated instance keyed by its class name.
681
674
  """
682
675
  try:
683
676
  manager_id = kwargs.pop("id", None)
@@ -725,7 +718,7 @@ class GraphQL:
725
718
  """
726
719
  Generates a GraphQL mutation class for deleting (deactivating) an instance of a GeneralManager subclass.
727
720
 
728
- The generated mutation accepts input fields defined in the manager's interface, deactivates the specified instance, and returns a dictionary indicating success or failure, along with any errors and the deleted instance.
721
+ The generated mutation accepts input fields defined in the manager's interface, deactivates the specified instance using its ID, and returns a dictionary with the operation's success status, any error messages, and the deactivated instance.
729
722
  """
730
723
  interface_cls: InterfaceBase | None = getattr(
731
724
  generalManagerClass, "Interface", None
@@ -736,13 +729,13 @@ class GraphQL:
736
729
  def delete_mutation(
737
730
  self,
738
731
  info: GraphQLResolveInfo,
739
- **kwargs: dict[str, Any],
732
+ **kwargs: Any,
740
733
  ) -> dict:
741
734
  """
742
- Deletes (deactivates) an instance of the specified GeneralManager class and returns the operation result.
735
+ Deactivates an instance of the specified GeneralManager class and returns the result.
743
736
 
744
737
  Returns:
745
- dict: A dictionary containing the success status, any error messages, and the deactivated instance under the class name key.
738
+ dict: Contains the operation's success status, a list of error messages if any, and the deactivated instance keyed by the class name.
746
739
  """
747
740
  try:
748
741
  manager_id = kwargs.pop("id", None)
@@ -43,12 +43,12 @@ class GeneralmanagerConfig(AppConfig):
43
43
 
44
44
  @staticmethod
45
45
  def handleReadOnlyInterface(
46
- read_only_classes: list[Type[GeneralManager[Any, ReadOnlyInterface]]],
46
+ read_only_classes: list[Type[GeneralManager]],
47
47
  ):
48
48
  """
49
- Configures synchronization and schema validation for the provided read-only interface classes.
50
-
51
- Ensures that each read-only interface is synchronized before Django management commands run, and registers system checks to validate that their schemas are up to date.
49
+ Configures synchronization and schema validation for the given read-only GeneralManager classes.
50
+
51
+ For each provided class, ensures that its data is synchronized before any Django management command executes, and registers a system check to verify that the associated schema remains up to date.
52
52
  """
53
53
  GeneralmanagerConfig.patchReadOnlyInterfaceSync(read_only_classes)
54
54
  from general_manager.interface.readOnlyInterface import ReadOnlyInterface
@@ -68,11 +68,11 @@ class GeneralmanagerConfig(AppConfig):
68
68
 
69
69
  @staticmethod
70
70
  def patchReadOnlyInterfaceSync(
71
- general_manager_classes: list[Type[GeneralManager[Any, ReadOnlyInterface]]],
71
+ general_manager_classes: list[Type[GeneralManager]],
72
72
  ):
73
73
  """
74
74
  Monkey-patches Django's management command runner to synchronize all provided read-only interfaces before executing any management command, except during autoreload subprocesses of 'runserver'.
75
-
75
+
76
76
  For each class in `general_manager_classes`, the associated read-only interface's `syncData` method is called prior to command execution, ensuring data consistency before management operations.
77
77
  """
78
78
  from general_manager.interface.readOnlyInterface import ReadOnlyInterface
@@ -15,6 +15,7 @@ if TYPE_CHECKING:
15
15
  from general_manager.manager.generalManager import GeneralManager
16
16
  from general_manager.manager.groupManager import GroupManager
17
17
  from general_manager.bucket.groupBucket import GroupBucket
18
+ from general_manager.interface.baseInterface import InterfaceBase
18
19
 
19
20
 
20
21
  class Bucket(ABC, Generic[GeneralManagerType]):
@@ -22,7 +23,7 @@ class Bucket(ABC, Generic[GeneralManagerType]):
22
23
  def __init__(self, manager_class: Type[GeneralManagerType]):
23
24
  """
24
25
  Initializes the Bucket with a specified manager class.
25
-
26
+
26
27
  Args:
27
28
  manager_class: The class of manager objects this bucket will manage.
28
29
  """
@@ -34,7 +35,7 @@ class Bucket(ABC, Generic[GeneralManagerType]):
34
35
  def __eq__(self, other: object) -> bool:
35
36
  """
36
37
  Checks if this Bucket is equal to another by comparing class, data, and manager class.
37
-
38
+
38
39
  Returns:
39
40
  True if both objects are of the same class and have equal internal data and manager class; otherwise, False.
40
41
  """
@@ -45,7 +46,7 @@ class Bucket(ABC, Generic[GeneralManagerType]):
45
46
  def __reduce__(self) -> str | tuple[Any, ...]:
46
47
  """
47
48
  Prepares the object for pickling by returning the class and initialization arguments.
48
-
49
+
49
50
  Returns:
50
51
  A tuple containing the class and a tuple of arguments needed to reconstruct the object during unpickling.
51
52
  """
@@ -56,12 +57,13 @@ class Bucket(ABC, Generic[GeneralManagerType]):
56
57
 
57
58
  @abstractmethod
58
59
  def __or__(
59
- self, other: Bucket[GeneralManagerType] | GeneralManager[GeneralManagerType]
60
+ self,
61
+ other: Bucket[GeneralManagerType] | GeneralManagerType,
60
62
  ) -> Bucket[GeneralManagerType]:
61
63
  """
62
- Returns a new bucket representing the union of this bucket and another bucket or manager instance.
64
+ Return a new bucket containing the union of this bucket and another bucket or manager instance.
63
65
 
64
- Args:
66
+ Parameters:
65
67
  other: Another bucket or a single manager instance to combine with this bucket.
66
68
 
67
69
  Returns:
@@ -72,10 +74,10 @@ class Bucket(ABC, Generic[GeneralManagerType]):
72
74
  @abstractmethod
73
75
  def __iter__(
74
76
  self,
75
- ) -> Generator[GeneralManagerType | GroupManager[GeneralManagerType]]:
77
+ ) -> Generator[GeneralManagerType | GroupManager[GeneralManagerType], None, None]:
76
78
  """
77
79
  Returns an iterator over the items in the bucket.
78
-
80
+
79
81
  Yields:
80
82
  Instances of the managed type or group manager contained in the bucket.
81
83
  """
@@ -85,10 +87,10 @@ class Bucket(ABC, Generic[GeneralManagerType]):
85
87
  def filter(self, **kwargs: Any) -> Bucket[GeneralManagerType]:
86
88
  """
87
89
  Returns a new bucket containing only items that match the specified filter criteria.
88
-
90
+
89
91
  Args:
90
92
  **kwargs: Field-value pairs used to filter items in the bucket.
91
-
93
+
92
94
  Returns:
93
95
  A new Bucket instance with items matching the given criteria.
94
96
  """
@@ -98,10 +100,10 @@ class Bucket(ABC, Generic[GeneralManagerType]):
98
100
  def exclude(self, **kwargs: Any) -> Bucket[GeneralManagerType]:
99
101
  """
100
102
  Returns a new Bucket excluding items that match the specified criteria.
101
-
103
+
102
104
  Args:
103
105
  **kwargs: Field-value pairs specifying the exclusion criteria.
104
-
106
+
105
107
  Returns:
106
108
  A new Bucket instance with items matching the criteria excluded.
107
109
  """
@@ -111,7 +113,7 @@ class Bucket(ABC, Generic[GeneralManagerType]):
111
113
  def first(self) -> GeneralManagerType | GroupManager[GeneralManagerType] | None:
112
114
  """
113
115
  Returns the first item in the bucket, or None if the bucket is empty.
114
-
116
+
115
117
  Returns:
116
118
  The first GeneralManager or GroupManager instance, or None if no items exist.
117
119
  """
@@ -121,7 +123,7 @@ class Bucket(ABC, Generic[GeneralManagerType]):
121
123
  def last(self) -> GeneralManagerType | GroupManager[GeneralManagerType] | None:
122
124
  """
123
125
  Returns the last item in the bucket, or None if the bucket is empty.
124
-
126
+
125
127
  Returns:
126
128
  The last GeneralManager or GroupManager instance, or None if no items exist.
127
129
  """
@@ -131,7 +133,7 @@ class Bucket(ABC, Generic[GeneralManagerType]):
131
133
  def count(self) -> int:
132
134
  """
133
135
  Returns the number of items in the bucket.
134
-
136
+
135
137
  Subclasses must implement this method to provide the count of contained elements.
136
138
  """
137
139
  raise NotImplementedError
@@ -140,7 +142,7 @@ class Bucket(ABC, Generic[GeneralManagerType]):
140
142
  def all(self) -> Bucket[GeneralManagerType]:
141
143
  """
142
144
  Returns a bucket containing all items managed by this instance.
143
-
145
+
144
146
  Subclasses must implement this method to provide access to the complete collection without filters or exclusions applied.
145
147
  """
146
148
  raise NotImplementedError
@@ -151,13 +153,13 @@ class Bucket(ABC, Generic[GeneralManagerType]):
151
153
  ) -> GeneralManagerType | GroupManager[GeneralManagerType]:
152
154
  """
153
155
  Retrieves a single item matching the specified criteria.
154
-
156
+
155
157
  Args:
156
158
  **kwargs: Field-value pairs used to identify the item.
157
-
159
+
158
160
  Returns:
159
161
  The matching GeneralManager or GroupManager instance.
160
-
162
+
161
163
  Raises:
162
164
  NotImplementedError: If the method is not implemented by a subclass.
163
165
  """
@@ -173,13 +175,13 @@ class Bucket(ABC, Generic[GeneralManagerType]):
173
175
  ):
174
176
  """
175
177
  Retrieves an item or a slice from the bucket.
176
-
178
+
177
179
  Args:
178
180
  item: An integer index to retrieve a single element, or a slice to retrieve a subset.
179
-
181
+
180
182
  Returns:
181
183
  A single manager instance if an integer is provided, or a new Bucket containing the sliced elements if a slice is provided.
182
-
184
+
183
185
  Raises:
184
186
  NotImplementedError: This method must be implemented by subclasses.
185
187
  """
@@ -189,7 +191,7 @@ class Bucket(ABC, Generic[GeneralManagerType]):
189
191
  def __len__(self) -> int:
190
192
  """
191
193
  Returns the number of items in the bucket.
192
-
194
+
193
195
  Subclasses must implement this method to provide the count of contained elements.
194
196
  """
195
197
  raise NotImplementedError
@@ -198,12 +200,12 @@ class Bucket(ABC, Generic[GeneralManagerType]):
198
200
  def __contains__(self, item: GeneralManagerType) -> bool:
199
201
  """
200
202
  Checks whether the specified item is present in the bucket.
201
-
203
+
202
204
  Args:
203
- item: The manager instance to check for membership.
204
-
205
+ item: The manager instance to check for membership.
206
+
205
207
  Returns:
206
- True if the item is contained in the bucket, otherwise False.
208
+ True if the item is contained in the bucket, otherwise False.
207
209
  """
208
210
  raise NotImplementedError
209
211
 
@@ -215,11 +217,11 @@ class Bucket(ABC, Generic[GeneralManagerType]):
215
217
  ) -> Bucket[GeneralManagerType]:
216
218
  """
217
219
  Returns a new Bucket with items sorted by the specified key or keys.
218
-
220
+
219
221
  Args:
220
222
  key: A string or tuple of strings specifying the attribute(s) to sort by.
221
223
  reverse: If True, sorts in descending order. Defaults to False.
222
-
224
+
223
225
  Returns:
224
226
  A new Bucket instance with items sorted according to the given key(s).
225
227
  """
@@ -228,10 +230,10 @@ class Bucket(ABC, Generic[GeneralManagerType]):
228
230
  def group_by(self, *group_by_keys: str) -> GroupBucket[GeneralManagerType]:
229
231
  """
230
232
  Groups the bucket's data by one or more specified keys.
231
-
233
+
232
234
  Args:
233
235
  *group_by_keys: One or more attribute names to group the data by.
234
-
236
+
235
237
  Returns:
236
238
  A GroupBucket instance containing the grouped data.
237
239
  """
@@ -92,19 +92,18 @@ class CalculationBucket(Bucket[GeneralManagerType]):
92
92
 
93
93
  def __or__(
94
94
  self,
95
- other: (
96
- Bucket[GeneralManagerType]
97
- | GeneralManager[GeneralManagerType, CalculationInterface]
98
- ),
95
+ other: Bucket[GeneralManagerType] | GeneralManagerType,
99
96
  ) -> CalculationBucket[GeneralManagerType]:
100
97
  """
101
- Combines this CalculationBucket with another bucket or manager of the same type.
102
-
103
- If combined with a manager instance, returns a bucket filtered to that manager's identification.
104
- If combined with another CalculationBucket of the same manager class, returns a new bucket with filters and excludes that are present and identical in both.
105
-
98
+ Combine this CalculationBucket with another bucket or manager instance of the same manager class.
99
+
100
+ If combined with a manager instance, returns a bucket filtered to that manager's identification. If combined with another CalculationBucket of the same manager class, returns a new bucket containing only the filters and excludes that are present and identical in both buckets.
101
+
106
102
  Raises:
107
103
  ValueError: If the other object is not a CalculationBucket or manager of the same class.
104
+
105
+ Returns:
106
+ CalculationBucket[GeneralManagerType]: A new CalculationBucket representing the intersection of filters and excludes, or a filtered bucket for the given manager instance.
108
107
  """
109
108
  from general_manager.manager.generalManager import GeneralManager
110
109
 
@@ -190,7 +189,7 @@ class CalculationBucket(Bucket[GeneralManagerType]):
190
189
  """
191
190
  return self
192
191
 
193
- def __iter__(self) -> Generator[GeneralManagerType]:
192
+ def __iter__(self) -> Generator[GeneralManagerType, None, None]:
194
193
  """
195
194
  Yields manager instances for each valid combination of input parameters.
196
195
 
@@ -1,10 +1,5 @@
1
1
  from __future__ import annotations
2
- from typing import (
3
- Type,
4
- Any,
5
- Generator,
6
- TypeVar,
7
- )
2
+ from typing import Type, Any, Generator, TypeVar, TYPE_CHECKING
8
3
  from django.db import models
9
4
  from general_manager.interface.baseInterface import (
10
5
  GeneralManagerType,
@@ -15,6 +10,9 @@ from general_manager.manager.generalManager import GeneralManager
15
10
 
16
11
  modelsModel = TypeVar("modelsModel", bound=models.Model)
17
12
 
13
+ if TYPE_CHECKING:
14
+ from general_manager.interface.databaseInterface import DatabaseInterface
15
+
18
16
 
19
17
  class DatabaseBucket(Bucket[GeneralManagerType]):
20
18
 
@@ -26,21 +24,20 @@ class DatabaseBucket(Bucket[GeneralManagerType]):
26
24
  exclude_definitions: dict[str, list[Any]] | None = None,
27
25
  ):
28
26
  """
29
- Initializes a DatabaseBucket with a queryset, manager class, and optional filter and exclude definitions.
27
+ Initialize a DatabaseBucket with a Django queryset, a manager class, and optional filter and exclude definitions.
30
28
 
31
- If no queryset is provided, constructs one using the manager class and the given filters and excludes. Stores the queryset, manager class, and copies of the filter and exclude definitions for further operations.
29
+ Parameters:
30
+ data (QuerySet): The Django queryset containing model instances to be managed.
31
+ manager_class (Type[GeneralManagerType]): The manager class used to wrap model instances.
32
+ filter_definitions (dict[str, list[Any]], optional): Initial filter criteria for the queryset.
33
+ exclude_definitions (dict[str, list[Any]], optional): Initial exclude criteria for the queryset.
32
34
  """
33
- if data is None:
34
- data = manager_class.Interface._model.objects.filter(
35
- **filter_definitions
36
- ).exclude(**exclude_definitions)
37
35
  self._data = data
38
-
39
36
  self._manager_class = manager_class
40
37
  self.filters = {**(filter_definitions or {})}
41
38
  self.excludes = {**(exclude_definitions or {})}
42
39
 
43
- def __iter__(self) -> Generator[GeneralManagerType]:
40
+ def __iter__(self) -> Generator[GeneralManagerType, None, None]:
44
41
  """
45
42
  Yields manager instances for each item in the underlying queryset.
46
43
 
@@ -51,15 +48,15 @@ class DatabaseBucket(Bucket[GeneralManagerType]):
51
48
 
52
49
  def __or__(
53
50
  self,
54
- other: Bucket[GeneralManagerType] | GeneralManager[GeneralManagerType],
51
+ other: Bucket[GeneralManagerType] | GeneralManagerType,
55
52
  ) -> DatabaseBucket[GeneralManagerType]:
56
53
  """
57
- Combines this bucket with another bucket or manager instance using the union operator.
54
+ Return a new bucket containing the union of this bucket and another bucket or manager instance.
58
55
 
59
- If `other` is a manager instance of the same class, creates a bucket containing only that instance and combines it. If `other` is a compatible bucket, returns a new bucket containing the union of both buckets' querysets. Raises a `ValueError` if the types or manager classes are incompatible.
56
+ If `other` is a manager instance of the same class, it is converted to a bucket before combining. If `other` is a compatible bucket, the resulting bucket contains all unique items from both. Raises a `ValueError` if the types or manager classes are incompatible.
60
57
 
61
58
  Returns:
62
- A new `DatabaseBucket` containing the combined items.
59
+ DatabaseBucket[GeneralManagerType]: A new bucket with the combined items.
63
60
  """
64
61
  if isinstance(other, GeneralManager) and other.__class__ == self._manager_class:
65
62
  return self.__or__(
@@ -195,10 +192,7 @@ class DatabaseBucket(Bucket[GeneralManagerType]):
195
192
 
196
193
  def __contains__(self, item: GeneralManagerType | models.Model) -> bool:
197
194
  """
198
- Checks if a manager instance or model instance is present in the bucket.
199
-
200
- Args:
201
- item: A manager instance or Django model instance to check for membership.
195
+ Determine whether a manager instance or Django model instance is present in the bucket.
202
196
 
203
197
  Returns:
204
198
  True if the item's primary key exists in the underlying queryset; otherwise, False.
@@ -209,7 +203,7 @@ class DatabaseBucket(Bucket[GeneralManagerType]):
209
203
  return item.identification.get("id", None) in self._data.values_list(
210
204
  "pk", flat=True
211
205
  )
212
- return item in self._data
206
+ return item.pk in self._data.values_list("pk", flat=True)
213
207
 
214
208
  def sort(
215
209
  self,
@@ -217,14 +211,14 @@ class DatabaseBucket(Bucket[GeneralManagerType]):
217
211
  reverse: bool = False,
218
212
  ) -> DatabaseBucket:
219
213
  """
220
- Returns a new DatabaseBucket sorted by the specified field or fields.
214
+ Return a new DatabaseBucket sorted by the specified field or fields.
221
215
 
222
- Args:
223
- key: A field name or tuple of field names to sort by.
224
- reverse: If True, sorts in descending order.
216
+ Parameters:
217
+ key (str or tuple of str): Field name or tuple of field names to sort by.
218
+ reverse (bool): If True, sort in descending order.
225
219
 
226
220
  Returns:
227
- A new DatabaseBucket instance with the sorted queryset.
221
+ DatabaseBucket: A new bucket instance containing the sorted queryset.
228
222
  """
229
223
  if isinstance(key, str):
230
224
  key = (key,)
@@ -117,7 +117,7 @@ class GroupBucket(Bucket[GeneralManagerType]):
117
117
  self._basis_data | other._basis_data,
118
118
  )
119
119
 
120
- def __iter__(self) -> Generator[GroupManager[GeneralManagerType]]:
120
+ def __iter__(self) -> Generator[GroupManager[GeneralManagerType], None, None]:
121
121
  """
122
122
  Yields each grouped manager in the current GroupBucket.
123
123
 
@@ -11,15 +11,17 @@ from general_manager.cache.dependencyIndex import (
11
11
  class ModelDependencyCollector:
12
12
 
13
13
  @staticmethod
14
- def collect(obj) -> Generator[tuple[general_manager_name, filter_type, str]]:
14
+ def collect(
15
+ obj,
16
+ ) -> Generator[tuple[general_manager_name, filter_type, str], None, None]:
15
17
  """
16
18
  Recursively extracts dependency information from Django model-related objects.
17
-
19
+
18
20
  Inspects the input object and its nested structures to identify instances of GeneralManager and Bucket, yielding a tuple for each dependency found. Each tuple contains the manager class name, the dependency type ("identification", "filter", or "exclude"), and the string representation of the dependency value.
19
-
21
+
20
22
  Args:
21
23
  obj: The object or collection to inspect for model dependencies.
22
-
24
+
23
25
  Yields:
24
26
  Tuples of (manager class name, dependency type, dependency value) for each dependency discovered.
25
27
  """