GeneralManager 0.14.1__py3-none-any.whl → 0.15.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.
- general_manager/__init__.py +49 -0
- general_manager/api/__init__.py +36 -0
- general_manager/api/graphql.py +92 -43
- general_manager/api/mutation.py +35 -10
- general_manager/api/property.py +26 -3
- general_manager/apps.py +23 -16
- general_manager/bucket/__init__.py +32 -0
- general_manager/bucket/baseBucket.py +76 -64
- general_manager/bucket/calculationBucket.py +188 -108
- general_manager/bucket/databaseBucket.py +130 -49
- general_manager/bucket/groupBucket.py +113 -60
- general_manager/cache/__init__.py +38 -0
- general_manager/cache/cacheDecorator.py +29 -17
- general_manager/cache/cacheTracker.py +34 -15
- general_manager/cache/dependencyIndex.py +117 -33
- general_manager/cache/modelDependencyCollector.py +17 -8
- general_manager/cache/signals.py +17 -6
- general_manager/factory/__init__.py +34 -5
- general_manager/factory/autoFactory.py +57 -60
- general_manager/factory/factories.py +39 -14
- general_manager/factory/factoryMethods.py +38 -1
- general_manager/interface/__init__.py +36 -0
- general_manager/interface/baseInterface.py +71 -27
- general_manager/interface/calculationInterface.py +18 -10
- general_manager/interface/databaseBasedInterface.py +102 -71
- general_manager/interface/databaseInterface.py +66 -20
- general_manager/interface/models.py +10 -4
- general_manager/interface/readOnlyInterface.py +44 -30
- general_manager/manager/__init__.py +36 -3
- general_manager/manager/generalManager.py +73 -47
- general_manager/manager/groupManager.py +72 -17
- general_manager/manager/input.py +23 -15
- general_manager/manager/meta.py +53 -53
- general_manager/measurement/__init__.py +37 -2
- general_manager/measurement/measurement.py +135 -58
- general_manager/measurement/measurementField.py +161 -61
- general_manager/permission/__init__.py +32 -1
- general_manager/permission/basePermission.py +29 -12
- general_manager/permission/managerBasedPermission.py +32 -26
- general_manager/permission/mutationPermission.py +32 -3
- general_manager/permission/permissionChecks.py +9 -1
- general_manager/permission/permissionDataManager.py +49 -15
- general_manager/permission/utils.py +14 -3
- general_manager/rule/__init__.py +27 -1
- general_manager/rule/handler.py +90 -5
- general_manager/rule/rule.py +40 -27
- general_manager/utils/__init__.py +44 -2
- general_manager/utils/argsToKwargs.py +17 -9
- general_manager/utils/filterParser.py +29 -30
- general_manager/utils/formatString.py +2 -0
- general_manager/utils/jsonEncoder.py +14 -1
- general_manager/utils/makeCacheKey.py +18 -12
- general_manager/utils/noneToZero.py +8 -6
- general_manager/utils/pathMapping.py +92 -29
- general_manager/utils/public_api.py +49 -0
- general_manager/utils/testing.py +135 -69
- {generalmanager-0.14.1.dist-info → generalmanager-0.15.0.dist-info}/METADATA +10 -2
- generalmanager-0.15.0.dist-info/RECORD +62 -0
- generalmanager-0.14.1.dist-info/RECORD +0 -58
- {generalmanager-0.14.1.dist-info → generalmanager-0.15.0.dist-info}/WHEEL +0 -0
- {generalmanager-0.14.1.dist-info → generalmanager-0.15.0.dist-info}/licenses/LICENSE +0 -0
- {generalmanager-0.14.1.dist-info → generalmanager-0.15.0.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,5 @@
|
|
1
|
+
"""Bucket implementation that enumerates calculation interface combinations."""
|
2
|
+
|
1
3
|
from __future__ import annotations
|
2
4
|
from types import UnionType
|
3
5
|
from typing import (
|
@@ -11,6 +13,7 @@ from typing import (
|
|
11
13
|
List,
|
12
14
|
TypedDict,
|
13
15
|
get_origin,
|
16
|
+
get_args,
|
14
17
|
)
|
15
18
|
from operator import attrgetter
|
16
19
|
from copy import deepcopy
|
@@ -34,6 +37,8 @@ class SortedFilters(TypedDict):
|
|
34
37
|
|
35
38
|
|
36
39
|
class CalculationBucket(Bucket[GeneralManagerType]):
|
40
|
+
"""Bucket that builds cartesian products of calculation input fields."""
|
41
|
+
|
37
42
|
def __init__(
|
38
43
|
self,
|
39
44
|
manager_class: Type[GeneralManagerType],
|
@@ -41,19 +46,22 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
41
46
|
exclude_definitions: Optional[dict[str, dict]] = None,
|
42
47
|
sort_key: Optional[Union[str, tuple[str]]] = None,
|
43
48
|
reverse: bool = False,
|
44
|
-
):
|
49
|
+
) -> None:
|
45
50
|
"""
|
46
|
-
|
51
|
+
Prepare a calculation bucket that enumerates all input combinations.
|
47
52
|
|
48
|
-
|
49
|
-
manager_class:
|
50
|
-
filter_definitions: Optional
|
51
|
-
exclude_definitions: Optional
|
52
|
-
sort_key
|
53
|
-
reverse:
|
53
|
+
Parameters:
|
54
|
+
manager_class (type[GeneralManagerType]): Manager subclass whose interface derives from `CalculationInterface`.
|
55
|
+
filter_definitions (dict[str, dict] | None): Optional filter constraints applied to generated combinations.
|
56
|
+
exclude_definitions (dict[str, dict] | None): Optional exclude constraints removing combinations.
|
57
|
+
sort_key (str | tuple[str, ...] | None): Key(s) used to order generated combinations.
|
58
|
+
reverse (bool): When True, reverse the ordering defined by `sort_key`.
|
59
|
+
|
60
|
+
Returns:
|
61
|
+
None
|
54
62
|
|
55
63
|
Raises:
|
56
|
-
TypeError: If the
|
64
|
+
TypeError: If the interface does not inherit from `CalculationInterface`.
|
57
65
|
"""
|
58
66
|
from general_manager.interface.calculationInterface import (
|
59
67
|
CalculationInterface,
|
@@ -88,10 +96,13 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
88
96
|
|
89
97
|
def __eq__(self, other: object) -> bool:
|
90
98
|
"""
|
91
|
-
|
99
|
+
Compare two calculation buckets for structural equality.
|
100
|
+
|
101
|
+
Parameters:
|
102
|
+
other (object): Candidate bucket.
|
92
103
|
|
93
104
|
Returns:
|
94
|
-
True
|
105
|
+
bool: True when both buckets share the same manager class and identical filter/exclude state.
|
95
106
|
"""
|
96
107
|
if not isinstance(other, self.__class__):
|
97
108
|
return False
|
@@ -103,10 +114,10 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
103
114
|
|
104
115
|
def __reduce__(self) -> generalManagerClassName | tuple[Any, ...]:
|
105
116
|
"""
|
106
|
-
|
117
|
+
Provide pickling support for calculation buckets.
|
107
118
|
|
108
119
|
Returns:
|
109
|
-
|
120
|
+
tuple[Any, ...]: Reconstruction data representing the class, arguments, and state.
|
110
121
|
"""
|
111
122
|
return (
|
112
123
|
self.__class__,
|
@@ -122,10 +133,13 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
122
133
|
|
123
134
|
def __setstate__(self, state: dict[str, Any]) -> None:
|
124
135
|
"""
|
125
|
-
|
136
|
+
Restore the bucket after unpickling.
|
137
|
+
|
138
|
+
Parameters:
|
139
|
+
state (dict[str, Any]): Pickled state containing cached combination data.
|
126
140
|
|
127
|
-
|
128
|
-
|
141
|
+
Returns:
|
142
|
+
None
|
129
143
|
"""
|
130
144
|
self._data = state.get("data")
|
131
145
|
|
@@ -134,15 +148,16 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
134
148
|
other: Bucket[GeneralManagerType] | GeneralManagerType,
|
135
149
|
) -> CalculationBucket[GeneralManagerType]:
|
136
150
|
"""
|
137
|
-
|
138
|
-
|
139
|
-
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.
|
151
|
+
Merge two calculation buckets or intersect with a single manager instance.
|
140
152
|
|
141
|
-
|
142
|
-
|
153
|
+
Parameters:
|
154
|
+
other (Bucket[GeneralManagerType] | GeneralManagerType): Calculation bucket or manager instance to merge.
|
143
155
|
|
144
156
|
Returns:
|
145
|
-
CalculationBucket[GeneralManagerType]:
|
157
|
+
CalculationBucket[GeneralManagerType]: Bucket reflecting the combined constraints.
|
158
|
+
|
159
|
+
Raises:
|
160
|
+
ValueError: If `other` is incompatible or uses a different manager class.
|
146
161
|
"""
|
147
162
|
from general_manager.manager.generalManager import GeneralManager
|
148
163
|
|
@@ -175,9 +190,10 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
175
190
|
|
176
191
|
def __str__(self) -> str:
|
177
192
|
"""
|
178
|
-
|
193
|
+
Return a compact preview of the generated combinations.
|
179
194
|
|
180
|
-
|
195
|
+
Returns:
|
196
|
+
str: Human-readable summary of up to five combinations.
|
181
197
|
"""
|
182
198
|
PRINT_MAX = 5
|
183
199
|
combinations = self.generate_combinations()
|
@@ -196,7 +212,10 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
196
212
|
|
197
213
|
def __repr__(self) -> str:
|
198
214
|
"""
|
199
|
-
|
215
|
+
Return a detailed representation of the bucket configuration.
|
216
|
+
|
217
|
+
Returns:
|
218
|
+
str: Debug string listing filters, excludes, sort key, and ordering.
|
200
219
|
"""
|
201
220
|
return f"{self.__class__.__name__}({self._manager_class.__name__}, {self.filter_definitions}, {self.exclude_definitions}, {self.sort_key}, {self.reverse})"
|
202
221
|
|
@@ -205,40 +224,51 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
205
224
|
properties: dict[str, GraphQLProperty], input_fields: dict[str, Input]
|
206
225
|
) -> dict[str, Input]:
|
207
226
|
"""
|
208
|
-
|
209
|
-
|
210
|
-
This method analyzes the properties and input fields to determine valid values for each input parameter.
|
227
|
+
Derive input-field definitions for GraphQL properties without explicit inputs.
|
211
228
|
|
212
|
-
|
213
|
-
properties (dict[str,
|
214
|
-
input_fields (dict[str,
|
229
|
+
Parameters:
|
230
|
+
properties (dict[str, GraphQLProperty]): GraphQL properties declared on the manager.
|
231
|
+
input_fields (dict[str, Input]): Existing input field definitions.
|
215
232
|
|
216
233
|
Returns:
|
217
|
-
dict[str,
|
234
|
+
dict[str, Input]: Combined mapping of input field names to `Input` definitions.
|
218
235
|
"""
|
219
236
|
parsed_inputs = {**input_fields}
|
220
237
|
for prop_name, prop in properties.items():
|
221
|
-
|
222
|
-
origin = get_origin(
|
238
|
+
current_hint = prop.graphql_type_hint
|
239
|
+
origin = get_origin(current_hint)
|
240
|
+
args = list(get_args(current_hint))
|
241
|
+
|
223
242
|
if origin in (Union, UnionType):
|
224
|
-
|
243
|
+
non_none_args = [arg for arg in args if arg is not type(None)]
|
244
|
+
current_hint = non_none_args[0] if non_none_args else object
|
245
|
+
origin = get_origin(current_hint)
|
246
|
+
args = list(get_args(current_hint))
|
247
|
+
|
248
|
+
if origin in (list, tuple, set):
|
249
|
+
inner = args[0] if args else object
|
250
|
+
resolved_type = inner if isinstance(inner, type) else object
|
251
|
+
elif isinstance(current_hint, type):
|
252
|
+
resolved_type = current_hint
|
253
|
+
else:
|
254
|
+
resolved_type = object
|
225
255
|
|
226
|
-
|
227
|
-
|
228
|
-
)
|
229
|
-
type_hint: type = (
|
230
|
-
type_hint.__args__[0] if hasattr(type_hint, "__args__") else str # type: ignore
|
231
|
-
)
|
232
|
-
prop_input = Input(type=type_hint, possible_values=None, depends_on=None)
|
256
|
+
prop_input = Input(
|
257
|
+
type=resolved_type, possible_values=None, depends_on=None
|
258
|
+
)
|
233
259
|
parsed_inputs[prop_name] = prop_input
|
234
260
|
|
235
261
|
return parsed_inputs
|
236
262
|
|
237
263
|
def filter(self, **kwargs: Any) -> CalculationBucket:
|
238
264
|
"""
|
239
|
-
|
265
|
+
Add additional filters and return a new calculation bucket.
|
266
|
+
|
267
|
+
Parameters:
|
268
|
+
**kwargs (Any): Filter expressions applied to generated combinations.
|
240
269
|
|
241
|
-
|
270
|
+
Returns:
|
271
|
+
CalculationBucket: Bucket reflecting the updated filter definitions.
|
242
272
|
"""
|
243
273
|
return CalculationBucket(
|
244
274
|
manager_class=self._manager_class,
|
@@ -251,9 +281,13 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
251
281
|
|
252
282
|
def exclude(self, **kwargs: Any) -> CalculationBucket:
|
253
283
|
"""
|
254
|
-
|
284
|
+
Add additional exclusion rules and return a new calculation bucket.
|
285
|
+
|
286
|
+
Parameters:
|
287
|
+
**kwargs (Any): Exclusion expressions removing combinations from the result.
|
255
288
|
|
256
|
-
|
289
|
+
Returns:
|
290
|
+
CalculationBucket: Bucket reflecting the updated exclusion definitions.
|
257
291
|
"""
|
258
292
|
return CalculationBucket(
|
259
293
|
manager_class=self._manager_class,
|
@@ -266,24 +300,34 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
266
300
|
|
267
301
|
def all(self) -> CalculationBucket:
|
268
302
|
"""
|
269
|
-
Return a deep copy of
|
270
|
-
|
271
|
-
|
303
|
+
Return a deep copy of this calculation bucket.
|
304
|
+
|
305
|
+
Returns:
|
306
|
+
CalculationBucket: Independent copy that can be mutated without affecting the original.
|
272
307
|
"""
|
273
308
|
return deepcopy(self)
|
274
309
|
|
275
310
|
def __iter__(self) -> Generator[GeneralManagerType, None, None]:
|
276
311
|
"""
|
277
|
-
Iterate over
|
278
|
-
|
312
|
+
Iterate over every generated combination as a manager instance.
|
313
|
+
|
279
314
|
Yields:
|
280
|
-
Manager
|
315
|
+
GeneralManagerType: Manager constructed from each valid set of inputs.
|
281
316
|
"""
|
282
317
|
combinations = self.generate_combinations()
|
283
318
|
for combo in combinations:
|
284
319
|
yield self._manager_class(**combo)
|
285
320
|
|
286
321
|
def _sortFilters(self, sorted_inputs: List[str]) -> SortedFilters:
|
322
|
+
"""
|
323
|
+
Partition filters into input- and property-based buckets.
|
324
|
+
|
325
|
+
Parameters:
|
326
|
+
sorted_inputs (list[str]): Input names ordered by dependency.
|
327
|
+
|
328
|
+
Returns:
|
329
|
+
SortedFilters: Mapping that separates filters/excludes for inputs and properties.
|
330
|
+
"""
|
287
331
|
input_filters: dict[str, dict] = {}
|
288
332
|
prop_filters: dict[str, dict] = {}
|
289
333
|
input_excludes: dict[str, dict] = {}
|
@@ -309,10 +353,10 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
309
353
|
|
310
354
|
def generate_combinations(self) -> List[dict[str, Any]]:
|
311
355
|
"""
|
312
|
-
|
356
|
+
Compute (and cache) the list of valid input combinations.
|
313
357
|
|
314
358
|
Returns:
|
315
|
-
|
359
|
+
list[dict[str, Any]]: Cached list of input dictionaries satisfying filters, excludes, and ordering.
|
316
360
|
"""
|
317
361
|
|
318
362
|
def key_func(manager_obj: GeneralManagerType) -> tuple:
|
@@ -349,13 +393,13 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
349
393
|
|
350
394
|
def topological_sort_inputs(self) -> List[str]:
|
351
395
|
"""
|
352
|
-
|
396
|
+
Produce a dependency-respecting order of input fields.
|
353
397
|
|
354
398
|
Returns:
|
355
|
-
|
399
|
+
list[str]: Input names ordered so each dependency appears before dependants.
|
356
400
|
|
357
401
|
Raises:
|
358
|
-
ValueError: If
|
402
|
+
ValueError: If the dependency graph contains a cycle.
|
359
403
|
"""
|
360
404
|
from collections import defaultdict
|
361
405
|
|
@@ -370,16 +414,19 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
370
414
|
visited = set()
|
371
415
|
sorted_inputs = []
|
372
416
|
|
373
|
-
def visit(node, temp_mark):
|
417
|
+
def visit(node: str, temp_mark: set[str]) -> None:
|
374
418
|
"""
|
375
|
-
|
419
|
+
Perform DFS while detecting cycles in the dependency graph.
|
376
420
|
|
377
|
-
|
378
|
-
node:
|
379
|
-
temp_mark
|
421
|
+
Parameters:
|
422
|
+
node (str): Input field currently being processed.
|
423
|
+
temp_mark (set[str]): Nodes visited along the current path.
|
424
|
+
|
425
|
+
Returns:
|
426
|
+
None
|
380
427
|
|
381
428
|
Raises:
|
382
|
-
ValueError: If a cyclic dependency
|
429
|
+
ValueError: If a cyclic dependency involves `node`.
|
383
430
|
"""
|
384
431
|
if node in visited:
|
385
432
|
return
|
@@ -402,22 +449,20 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
402
449
|
def get_possible_values(
|
403
450
|
self, key_name: str, input_field: Input, current_combo: dict
|
404
451
|
) -> Union[Iterable[Any], Bucket[Any]]:
|
405
|
-
#
|
452
|
+
# Retrieve possible values
|
406
453
|
"""
|
407
|
-
|
408
|
-
|
409
|
-
If the input field's `possible_values` is a callable, it is invoked with the current values of its dependencies. If it is an iterable or a `Bucket`, it is returned directly. Raises a `TypeError` if `possible_values` is not a valid type.
|
454
|
+
Resolve the potential values for an input field given the current combination.
|
410
455
|
|
411
|
-
|
412
|
-
key_name:
|
413
|
-
input_field:
|
414
|
-
current_combo:
|
456
|
+
Parameters:
|
457
|
+
key_name (str): Name of the input field.
|
458
|
+
input_field (Input): Input definition describing type and dependencies.
|
459
|
+
current_combo (dict): Current partial assignment of input values.
|
415
460
|
|
416
461
|
Returns:
|
417
|
-
|
462
|
+
Iterable[Any] | Bucket[Any]: Collection of permissible values.
|
418
463
|
|
419
464
|
Raises:
|
420
|
-
TypeError: If `possible_values`
|
465
|
+
TypeError: If the configured `possible_values` cannot be evaluated.
|
421
466
|
"""
|
422
467
|
if callable(input_field.possible_values):
|
423
468
|
depends_on = input_field.depends_on
|
@@ -436,23 +481,30 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
436
481
|
excludes: dict[str, dict],
|
437
482
|
) -> List[dict[str, Any]]:
|
438
483
|
"""
|
439
|
-
|
484
|
+
Generate all valid input combinations while honouring filters and excludes.
|
440
485
|
|
441
|
-
|
442
|
-
sorted_inputs: Input
|
443
|
-
filters
|
444
|
-
excludes
|
486
|
+
Parameters:
|
487
|
+
sorted_inputs (list[str]): Input names ordered by dependency.
|
488
|
+
filters (dict[str, dict]): Filter definitions keyed by input name.
|
489
|
+
excludes (dict[str, dict]): Exclusion definitions keyed by input name.
|
445
490
|
|
446
491
|
Returns:
|
447
|
-
|
492
|
+
list[dict[str, Any]]: Valid input combinations.
|
448
493
|
"""
|
449
494
|
|
450
|
-
def helper(
|
495
|
+
def helper(
|
496
|
+
index: int,
|
497
|
+
current_combo: dict[str, Any],
|
498
|
+
) -> Generator[dict[str, Any], None, None]:
|
451
499
|
"""
|
452
|
-
Recursively
|
500
|
+
Recursively emit input combinations that satisfy filters and excludes.
|
501
|
+
|
502
|
+
Parameters:
|
503
|
+
index (int): Position within `sorted_inputs` currently being assigned.
|
504
|
+
current_combo (dict[str, Any]): Partial assignment of inputs built so far.
|
453
505
|
|
454
506
|
Yields:
|
455
|
-
|
507
|
+
dict[str, Any]: Completed combination of input values.
|
456
508
|
"""
|
457
509
|
if index == len(sorted_inputs):
|
458
510
|
yield current_combo.copy()
|
@@ -502,6 +554,17 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
502
554
|
prop_filters: dict[str, Any],
|
503
555
|
prop_excludes: dict[str, Any],
|
504
556
|
) -> list[GeneralManagerType]:
|
557
|
+
"""
|
558
|
+
Apply property-level filters and excludes to manager combinations.
|
559
|
+
|
560
|
+
Parameters:
|
561
|
+
current_combos (list[dict[str, Any]]): Input combinations already passing input filters.
|
562
|
+
prop_filters (dict[str, Any]): Filter definitions keyed by property name.
|
563
|
+
prop_excludes (dict[str, Any]): Exclude definitions keyed by property name.
|
564
|
+
|
565
|
+
Returns:
|
566
|
+
list[GeneralManagerType]: Manager instances that satisfy property constraints.
|
567
|
+
"""
|
505
568
|
|
506
569
|
prop_filter_needed = set(prop_filters.keys()) | set(prop_excludes.keys())
|
507
570
|
manager_combinations = [
|
@@ -537,7 +600,10 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
537
600
|
|
538
601
|
def first(self) -> GeneralManagerType | None:
|
539
602
|
"""
|
540
|
-
|
603
|
+
Return the first generated manager instance.
|
604
|
+
|
605
|
+
Returns:
|
606
|
+
GeneralManagerType | None: First instance or None when no combinations exist.
|
541
607
|
"""
|
542
608
|
try:
|
543
609
|
return next(iter(self))
|
@@ -546,7 +612,10 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
546
612
|
|
547
613
|
def last(self) -> GeneralManagerType | None:
|
548
614
|
"""
|
549
|
-
|
615
|
+
Return the last generated manager instance.
|
616
|
+
|
617
|
+
Returns:
|
618
|
+
GeneralManagerType | None: Last instance or None when no combinations exist.
|
550
619
|
"""
|
551
620
|
items = list(self)
|
552
621
|
if items:
|
@@ -555,13 +624,19 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
555
624
|
|
556
625
|
def count(self) -> int:
|
557
626
|
"""
|
558
|
-
|
627
|
+
Return the number of calculation combinations.
|
628
|
+
|
629
|
+
Returns:
|
630
|
+
int: Number of generated combinations.
|
559
631
|
"""
|
560
632
|
return self.__len__()
|
561
633
|
|
562
634
|
def __len__(self) -> int:
|
563
635
|
"""
|
564
|
-
|
636
|
+
Return the number of generated combinations.
|
637
|
+
|
638
|
+
Returns:
|
639
|
+
int: Cached number of combinations.
|
565
640
|
"""
|
566
641
|
return len(self.generate_combinations())
|
567
642
|
|
@@ -569,10 +644,14 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
569
644
|
self, item: int | slice
|
570
645
|
) -> GeneralManagerType | CalculationBucket[GeneralManagerType]:
|
571
646
|
"""
|
572
|
-
|
647
|
+
Retrieve a manager instance or subset of combinations.
|
648
|
+
|
649
|
+
Parameters:
|
650
|
+
item (int | slice): Index or slice specifying which combinations to return.
|
573
651
|
|
574
|
-
|
575
|
-
|
652
|
+
Returns:
|
653
|
+
GeneralManagerType | CalculationBucket[GeneralManagerType]:
|
654
|
+
Manager instance for single indices or bucket wrapping the sliced combinations.
|
576
655
|
"""
|
577
656
|
items = self.generate_combinations()
|
578
657
|
result = items[item]
|
@@ -590,28 +669,28 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
590
669
|
|
591
670
|
def __contains__(self, item: GeneralManagerType) -> bool:
|
592
671
|
"""
|
593
|
-
|
672
|
+
Determine whether the provided manager instance exists among generated combinations.
|
594
673
|
|
595
|
-
|
596
|
-
|
674
|
+
Parameters:
|
675
|
+
item (GeneralManagerType): Manager instance to test for membership.
|
597
676
|
|
598
677
|
Returns:
|
599
|
-
|
678
|
+
bool: True when the instance matches one of the generated combinations.
|
600
679
|
"""
|
601
680
|
return any(item == mgr for mgr in self)
|
602
681
|
|
603
682
|
def get(self, **kwargs: Any) -> GeneralManagerType:
|
604
683
|
"""
|
605
|
-
|
684
|
+
Retrieve a single manager instance that satisfies the given filters.
|
606
685
|
|
607
|
-
|
608
|
-
**kwargs: Filter
|
686
|
+
Parameters:
|
687
|
+
**kwargs (Any): Filter expressions narrowing the calculation results.
|
609
688
|
|
610
689
|
Returns:
|
611
|
-
|
690
|
+
GeneralManagerType: Matching manager instance.
|
612
691
|
|
613
692
|
Raises:
|
614
|
-
ValueError: If
|
693
|
+
ValueError: If zero or multiple calculations match the filters.
|
615
694
|
"""
|
616
695
|
filtered_bucket = self.filter(**kwargs)
|
617
696
|
items = list(filtered_bucket)
|
@@ -626,14 +705,14 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
626
705
|
self, key: str | tuple[str], reverse: bool = False
|
627
706
|
) -> CalculationBucket[GeneralManagerType]:
|
628
707
|
"""
|
629
|
-
Return a new
|
630
|
-
|
708
|
+
Return a new bucket with updated sorting preferences.
|
709
|
+
|
631
710
|
Parameters:
|
632
|
-
key (str
|
633
|
-
reverse (bool): Whether to
|
634
|
-
|
711
|
+
key (str | tuple[str, ...]): Attribute name(s) used for ordering combinations.
|
712
|
+
reverse (bool): Whether to apply descending order.
|
713
|
+
|
635
714
|
Returns:
|
636
|
-
CalculationBucket:
|
715
|
+
CalculationBucket[GeneralManagerType]: Bucket configured with the provided sorting options.
|
637
716
|
"""
|
638
717
|
return CalculationBucket(
|
639
718
|
self._manager_class,
|
@@ -645,12 +724,13 @@ class CalculationBucket(Bucket[GeneralManagerType]):
|
|
645
724
|
|
646
725
|
def none(self) -> CalculationBucket[GeneralManagerType]:
|
647
726
|
"""
|
648
|
-
Return
|
649
|
-
|
650
|
-
|
727
|
+
Return an empty calculation bucket with the same configuration.
|
728
|
+
|
729
|
+
Returns:
|
730
|
+
CalculationBucket[GeneralManagerType]: Bucket with no combinations and cleared cached data.
|
651
731
|
"""
|
652
732
|
own = self.all()
|
653
|
-
own.
|
733
|
+
own._data = []
|
654
734
|
own.filters = {}
|
655
735
|
own.excludes = {}
|
656
736
|
return own
|