GeneralManager 0.16.0__py3-none-any.whl → 0.17.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.
Potentially problematic release.
This version of GeneralManager might be problematic. Click here for more details.
- general_manager/api/graphql.py +689 -74
- general_manager/api/graphql_subscription_consumer.py +429 -0
- general_manager/apps.py +164 -9
- general_manager/cache/dependencyIndex.py +169 -17
- general_manager/manager/groupManager.py +1 -1
- general_manager/py.typed +0 -0
- general_manager/utils/testing.py +26 -17
- {generalmanager-0.16.0.dist-info → generalmanager-0.17.0.dist-info}/METADATA +10 -3
- {generalmanager-0.16.0.dist-info → generalmanager-0.17.0.dist-info}/RECORD +12 -10
- {generalmanager-0.16.0.dist-info → generalmanager-0.17.0.dist-info}/WHEEL +0 -0
- {generalmanager-0.16.0.dist-info → generalmanager-0.17.0.dist-info}/licenses/LICENSE +0 -0
- {generalmanager-0.16.0.dist-info → generalmanager-0.17.0.dist-info}/top_level.txt +0 -0
|
@@ -5,6 +5,7 @@ import time
|
|
|
5
5
|
import ast
|
|
6
6
|
import re
|
|
7
7
|
import logging
|
|
8
|
+
from datetime import date, datetime
|
|
8
9
|
|
|
9
10
|
from django.core.cache import cache
|
|
10
11
|
from general_manager.cache.signals import post_data_change, pre_data_change
|
|
@@ -138,6 +139,9 @@ def record_dependencies(
|
|
|
138
139
|
action_key = cast(Literal["filter", "exclude"], action)
|
|
139
140
|
params = ast.literal_eval(identifier)
|
|
140
141
|
section = idx[action_key].setdefault(model_name, {})
|
|
142
|
+
if len(params) > 1:
|
|
143
|
+
cache_dependencies = section.setdefault("__cache_dependencies__", {})
|
|
144
|
+
cache_dependencies.setdefault(cache_key, set()).add(identifier)
|
|
141
145
|
for lookup, val in params.items():
|
|
142
146
|
lookup_map = section.setdefault(lookup, {})
|
|
143
147
|
val_key = repr(val)
|
|
@@ -183,7 +187,10 @@ def remove_cache_key_from_index(cache_key: str) -> None:
|
|
|
183
187
|
for action in ("filter", "exclude"):
|
|
184
188
|
action_section = idx.get(action, {})
|
|
185
189
|
for mname, model_section in list(action_section.items()):
|
|
190
|
+
cache_dependencies = model_section.get("__cache_dependencies__", {})
|
|
186
191
|
for lookup, lookup_map in list(model_section.items()):
|
|
192
|
+
if lookup.startswith("__"):
|
|
193
|
+
continue
|
|
187
194
|
for val_key, key_set in list(lookup_map.items()):
|
|
188
195
|
if cache_key in key_set:
|
|
189
196
|
key_set.remove(cache_key)
|
|
@@ -191,6 +198,10 @@ def remove_cache_key_from_index(cache_key: str) -> None:
|
|
|
191
198
|
del lookup_map[val_key]
|
|
192
199
|
if not lookup_map:
|
|
193
200
|
del model_section[lookup]
|
|
201
|
+
if cache_dependencies:
|
|
202
|
+
cache_dependencies.pop(cache_key, None)
|
|
203
|
+
if not cache_dependencies:
|
|
204
|
+
model_section.pop("__cache_dependencies__", None)
|
|
194
205
|
if not model_section:
|
|
195
206
|
del action_section[mname]
|
|
196
207
|
set_full_index(idx)
|
|
@@ -238,7 +249,15 @@ def capture_old_values(
|
|
|
238
249
|
# get all lookups for this model
|
|
239
250
|
lookups = set()
|
|
240
251
|
for action in ("filter", "exclude"):
|
|
241
|
-
|
|
252
|
+
model_section = idx.get(action, {}).get(manager_name, {})
|
|
253
|
+
if isinstance(model_section, dict):
|
|
254
|
+
lookups |= {
|
|
255
|
+
lookup
|
|
256
|
+
for lookup in model_section.keys()
|
|
257
|
+
if isinstance(lookup, str) and not lookup.startswith("__")
|
|
258
|
+
}
|
|
259
|
+
elif isinstance(model_section, list):
|
|
260
|
+
lookups |= set(model_section)
|
|
242
261
|
if lookups and instance.identification:
|
|
243
262
|
# save old values for later comparison
|
|
244
263
|
vals: dict[str, object] = {}
|
|
@@ -276,27 +295,86 @@ def generic_cache_invalidation(
|
|
|
276
295
|
manager_name = sender.__name__
|
|
277
296
|
idx = get_full_index()
|
|
278
297
|
|
|
298
|
+
def _safe_literal_eval(value: Any) -> Any:
|
|
299
|
+
if isinstance(value, str):
|
|
300
|
+
try:
|
|
301
|
+
return ast.literal_eval(value)
|
|
302
|
+
except (ValueError, SyntaxError):
|
|
303
|
+
return value
|
|
304
|
+
return value
|
|
305
|
+
|
|
306
|
+
def _coerce_to_type(sample: Any, raw: Any) -> Any | None:
|
|
307
|
+
if sample is None:
|
|
308
|
+
return None
|
|
309
|
+
|
|
310
|
+
if isinstance(sample, datetime):
|
|
311
|
+
if isinstance(raw, datetime):
|
|
312
|
+
parsed = raw
|
|
313
|
+
elif isinstance(raw, str):
|
|
314
|
+
candidate = raw.replace("Z", "+00:00")
|
|
315
|
+
candidate = candidate.replace(" ", "T", 1)
|
|
316
|
+
try:
|
|
317
|
+
parsed = datetime.fromisoformat(candidate)
|
|
318
|
+
except ValueError:
|
|
319
|
+
return None
|
|
320
|
+
else:
|
|
321
|
+
return None
|
|
322
|
+
|
|
323
|
+
if sample.tzinfo and parsed.tzinfo is None:
|
|
324
|
+
parsed = parsed.replace(tzinfo=sample.tzinfo)
|
|
325
|
+
elif not sample.tzinfo and parsed.tzinfo is not None:
|
|
326
|
+
parsed = parsed.replace(tzinfo=None)
|
|
327
|
+
return parsed
|
|
328
|
+
|
|
329
|
+
if isinstance(sample, date) and not isinstance(sample, datetime):
|
|
330
|
+
if isinstance(raw, date) and not isinstance(raw, datetime):
|
|
331
|
+
return raw
|
|
332
|
+
if isinstance(raw, str):
|
|
333
|
+
try:
|
|
334
|
+
return date.fromisoformat(raw)
|
|
335
|
+
except ValueError:
|
|
336
|
+
return None
|
|
337
|
+
return None
|
|
338
|
+
|
|
339
|
+
try:
|
|
340
|
+
return type(sample)(raw) # type: ignore
|
|
341
|
+
except Exception:
|
|
342
|
+
if isinstance(raw, type(sample)):
|
|
343
|
+
return raw
|
|
344
|
+
return None
|
|
345
|
+
|
|
279
346
|
def matches(op: str, value: Any, val_key: Any) -> bool:
|
|
280
347
|
if value is None:
|
|
281
348
|
return False
|
|
282
349
|
|
|
283
350
|
# eq
|
|
284
351
|
if op == "eq":
|
|
285
|
-
|
|
352
|
+
literal_val = _safe_literal_eval(val_key)
|
|
353
|
+
comparable = _coerce_to_type(value, literal_val)
|
|
354
|
+
if comparable is None:
|
|
355
|
+
return repr(value) == val_key
|
|
356
|
+
return value == comparable
|
|
286
357
|
|
|
287
358
|
# in
|
|
288
359
|
if op == "in":
|
|
289
360
|
try:
|
|
290
361
|
seq = ast.literal_eval(val_key)
|
|
291
|
-
|
|
292
|
-
except:
|
|
362
|
+
except (ValueError, SyntaxError):
|
|
293
363
|
return False
|
|
364
|
+
for item in seq:
|
|
365
|
+
comparable = _coerce_to_type(value, item)
|
|
366
|
+
if comparable is not None:
|
|
367
|
+
if value == comparable:
|
|
368
|
+
return True
|
|
369
|
+
elif repr(value) == repr(item):
|
|
370
|
+
return True
|
|
371
|
+
return False
|
|
294
372
|
|
|
295
373
|
# range comparisons
|
|
296
374
|
if op in ("gt", "gte", "lt", "lte"):
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
375
|
+
literal_val = _safe_literal_eval(val_key)
|
|
376
|
+
thr = _coerce_to_type(value, literal_val)
|
|
377
|
+
if thr is None:
|
|
300
378
|
return False
|
|
301
379
|
if op == "gt":
|
|
302
380
|
return value > thr
|
|
@@ -311,7 +389,7 @@ def generic_cache_invalidation(
|
|
|
311
389
|
if op in ("contains", "startswith", "endswith", "regex"):
|
|
312
390
|
try:
|
|
313
391
|
literal = ast.literal_eval(val_key)
|
|
314
|
-
except
|
|
392
|
+
except (ValueError, SyntaxError):
|
|
315
393
|
literal = val_key
|
|
316
394
|
|
|
317
395
|
# ensure we always work with strings to avoid TypeErrors
|
|
@@ -325,16 +403,78 @@ def generic_cache_invalidation(
|
|
|
325
403
|
# regex: treat the stored key as the regex pattern
|
|
326
404
|
if op == "regex":
|
|
327
405
|
try:
|
|
328
|
-
|
|
406
|
+
pattern_source = literal if isinstance(literal, str) else str(literal)
|
|
407
|
+
pattern = re.compile(pattern_source)
|
|
329
408
|
except re.error:
|
|
330
409
|
return False
|
|
331
410
|
return bool(pattern.search(text))
|
|
332
411
|
|
|
333
412
|
return False
|
|
334
413
|
|
|
414
|
+
def current_value_for_path(path: list[str]) -> Any:
|
|
415
|
+
current: object = instance
|
|
416
|
+
for attr in path:
|
|
417
|
+
current = getattr(current, attr, UNDEFINED)
|
|
418
|
+
if current is UNDEFINED:
|
|
419
|
+
return None
|
|
420
|
+
return current
|
|
421
|
+
|
|
422
|
+
def evaluate_composite(
|
|
423
|
+
cache_key: str, lookup_key: str, action: str
|
|
424
|
+
) -> bool | None:
|
|
425
|
+
cache_dependencies = model_section.get("__cache_dependencies__", {})
|
|
426
|
+
identifiers = cache_dependencies.get(cache_key) if cache_dependencies else None
|
|
427
|
+
if not identifiers:
|
|
428
|
+
return None
|
|
429
|
+
|
|
430
|
+
for identifier in identifiers:
|
|
431
|
+
params = ast.literal_eval(identifier)
|
|
432
|
+
if lookup_key not in params:
|
|
433
|
+
continue
|
|
434
|
+
old_all = True
|
|
435
|
+
new_all = True
|
|
436
|
+
for param_lookup, expected in params.items():
|
|
437
|
+
parts_param = param_lookup.split("__")
|
|
438
|
+
if parts_param[-1] in (
|
|
439
|
+
"gt",
|
|
440
|
+
"gte",
|
|
441
|
+
"lt",
|
|
442
|
+
"lte",
|
|
443
|
+
"in",
|
|
444
|
+
"contains",
|
|
445
|
+
"startswith",
|
|
446
|
+
"endswith",
|
|
447
|
+
"regex",
|
|
448
|
+
):
|
|
449
|
+
op_param = parts_param[-1]
|
|
450
|
+
attr_path_param = parts_param[:-1]
|
|
451
|
+
else:
|
|
452
|
+
op_param = "eq"
|
|
453
|
+
attr_path_param = parts_param
|
|
454
|
+
expected_key = repr(expected)
|
|
455
|
+
old_val_param = old_relevant_values.get("__".join(attr_path_param))
|
|
456
|
+
new_val_param = current_value_for_path(attr_path_param)
|
|
457
|
+
if not matches(op_param, old_val_param, expected_key):
|
|
458
|
+
old_all = False
|
|
459
|
+
if not matches(op_param, new_val_param, expected_key):
|
|
460
|
+
new_all = False
|
|
461
|
+
if not old_all and not new_all and action == "filter":
|
|
462
|
+
break
|
|
463
|
+
if action == "filter":
|
|
464
|
+
if old_all or new_all:
|
|
465
|
+
return True
|
|
466
|
+
else: # exclude
|
|
467
|
+
if old_all != new_all:
|
|
468
|
+
return True
|
|
469
|
+
return False
|
|
470
|
+
|
|
335
471
|
for action in ("filter", "exclude"):
|
|
336
472
|
model_section = idx.get(action, {}).get(manager_name, {})
|
|
473
|
+
if not model_section:
|
|
474
|
+
continue
|
|
337
475
|
for lookup, lookup_map in model_section.items():
|
|
476
|
+
if lookup.startswith("__"):
|
|
477
|
+
continue
|
|
338
478
|
# 1) get operator and attribute path
|
|
339
479
|
parts = lookup.split("__")
|
|
340
480
|
if parts[-1] in (
|
|
@@ -371,20 +511,32 @@ def generic_cache_invalidation(
|
|
|
371
511
|
|
|
372
512
|
if action == "filter":
|
|
373
513
|
# Filter: invalidate if new match or old match
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
514
|
+
for ck in list(cache_keys):
|
|
515
|
+
composite_decision = evaluate_composite(ck, lookup, action)
|
|
516
|
+
should_invalidate = (
|
|
517
|
+
composite_decision
|
|
518
|
+
if composite_decision is not None
|
|
519
|
+
else (new_match or old_match)
|
|
377
520
|
)
|
|
378
|
-
|
|
521
|
+
if should_invalidate:
|
|
522
|
+
logger.info(
|
|
523
|
+
f"Invalidate cache key {ck} for filter {lookup} with value {val_key}"
|
|
524
|
+
)
|
|
379
525
|
invalidate_cache_key(ck)
|
|
380
526
|
remove_cache_key_from_index(ck)
|
|
381
527
|
|
|
382
528
|
else: # action == 'exclude'
|
|
383
529
|
# Excludes: invalidate only if matches changed
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
530
|
+
for ck in list(cache_keys):
|
|
531
|
+
composite_decision = evaluate_composite(ck, lookup, action)
|
|
532
|
+
should_invalidate = (
|
|
533
|
+
composite_decision
|
|
534
|
+
if composite_decision is not None
|
|
535
|
+
else (old_match != new_match)
|
|
387
536
|
)
|
|
388
|
-
|
|
537
|
+
if should_invalidate:
|
|
538
|
+
logger.info(
|
|
539
|
+
f"Invalidate cache key {ck} for exclude {lookup} with value {val_key}"
|
|
540
|
+
)
|
|
389
541
|
invalidate_cache_key(ck)
|
|
390
542
|
remove_cache_key_from_index(ck)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
from typing import Any, Generic, Iterator, Type, cast, get_args
|
|
5
5
|
from datetime import datetime, date, time
|
|
6
|
-
from general_manager.api.
|
|
6
|
+
from general_manager.api.property import GraphQLProperty
|
|
7
7
|
from general_manager.measurement import Measurement
|
|
8
8
|
from general_manager.manager.generalManager import GeneralManager
|
|
9
9
|
from general_manager.bucket.baseBucket import (
|
general_manager/py.typed
ADDED
|
File without changes
|
general_manager/utils/testing.py
CHANGED
|
@@ -80,15 +80,18 @@ class GMTestCaseMeta(type):
|
|
|
80
80
|
attrs: dict[str, object],
|
|
81
81
|
) -> type:
|
|
82
82
|
"""
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
Create a new test case class that injects GeneralManager-specific initialization into `setUpClass`.
|
|
84
|
+
|
|
85
|
+
The constructed class replaces or wraps any user-defined `setUpClass` with logic that resets GraphQL and manager registries, configures an optional fallback app lookup, ensures database tables for managed models exist, initializes GeneralManager and GraphQL registrations, and then calls the standard GraphQL test setup.
|
|
86
|
+
|
|
85
87
|
Parameters:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
mcs (type[GMTestCaseMeta]): Metaclass constructing the new class.
|
|
89
|
+
name (str): Name of the class to create.
|
|
90
|
+
bases (tuple[type, ...]): Base classes for the new class.
|
|
91
|
+
attrs (dict[str, object]): Class namespace; may contain a user-defined `setUpClass` and `fallback_app`.
|
|
92
|
+
|
|
90
93
|
Returns:
|
|
91
|
-
type:
|
|
94
|
+
type: The newly created test case class whose `setUpClass` has been augmented for GeneralManager testing.
|
|
92
95
|
"""
|
|
93
96
|
user_setup = attrs.get("setUpClass")
|
|
94
97
|
fallback_app = cast(str | None, attrs.get("fallback_app", "general_manager"))
|
|
@@ -99,22 +102,22 @@ class GMTestCaseMeta(type):
|
|
|
99
102
|
cls: type["GeneralManagerTransactionTestCase"],
|
|
100
103
|
) -> None:
|
|
101
104
|
"""
|
|
102
|
-
Prepare the test
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
Parameters:
|
|
107
|
-
cls (type[GeneralManagerTransactionTestCase]): Test case subclass whose environment is being initialised.
|
|
108
|
-
|
|
109
|
-
Returns:
|
|
110
|
-
None
|
|
105
|
+
Prepare the test environment for GeneralManager GraphQL tests.
|
|
106
|
+
|
|
107
|
+
Resets GraphQL and manager registries, optionally patches Django's app-config lookup to use a fallback app, ensures database tables exist for models provided by the test's configured manager classes, initializes GeneralManager classes (including read-only interfaces) and GraphQL registrations, and finally invokes the base class setUpClass.
|
|
111
108
|
"""
|
|
112
109
|
GraphQL._query_class = None
|
|
113
110
|
GraphQL._mutation_class = None
|
|
111
|
+
GraphQL._subscription_class = None
|
|
114
112
|
GraphQL._mutations = {}
|
|
115
113
|
GraphQL._query_fields = {}
|
|
114
|
+
GraphQL._subscription_fields = {}
|
|
116
115
|
GraphQL.graphql_type_registry = {}
|
|
117
116
|
GraphQL.graphql_filter_type_registry = {}
|
|
117
|
+
GraphQL._subscription_payload_registry = {}
|
|
118
|
+
GraphQL._page_type_registry = {}
|
|
119
|
+
GraphQL.manager_registry = {}
|
|
120
|
+
GraphQL._schema = None
|
|
118
121
|
|
|
119
122
|
if fallback_app is not None:
|
|
120
123
|
setattr(
|
|
@@ -219,11 +222,17 @@ class LoggingCache(LocMemCache):
|
|
|
219
222
|
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
|
220
223
|
"LOCATION": "test-cache",
|
|
221
224
|
}
|
|
222
|
-
}
|
|
225
|
+
},
|
|
226
|
+
CHANNEL_LAYERS={
|
|
227
|
+
"default": {
|
|
228
|
+
"BACKEND": "channels.layers.InMemoryChannelLayer",
|
|
229
|
+
}
|
|
230
|
+
},
|
|
223
231
|
)
|
|
224
232
|
class GeneralManagerTransactionTestCase(
|
|
225
233
|
GraphQLTransactionTestCase, metaclass=GMTestCaseMeta
|
|
226
234
|
):
|
|
235
|
+
GRAPHQL_URL = "/graphql/"
|
|
227
236
|
general_manager_classes: list[type[GeneralManager]] = []
|
|
228
237
|
read_only_classes: list[type[GeneralManager]] = []
|
|
229
238
|
fallback_app: str | None = "general_manager"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GeneralManager
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.17.0
|
|
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: MIT License
|
|
@@ -24,6 +24,12 @@ License: MIT License
|
|
|
24
24
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
25
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
26
|
SOFTWARE.
|
|
27
|
+
Project-URL: Homepage, https://github.com/TimKleindick/general_manager
|
|
28
|
+
Project-URL: Documentation, https://timkleindick.github.io/general_manager/
|
|
29
|
+
Project-URL: Repository, https://github.com/TimKleindick/general_manager
|
|
30
|
+
Project-URL: Issues, https://github.com/TimKleindick/general_manager/issues
|
|
31
|
+
Project-URL: Changelog, https://github.com/TimKleindick/general_manager/releases
|
|
32
|
+
Keywords: django,orm,graphql,permissions,validation,caching,framework
|
|
27
33
|
Classifier: License :: OSI Approved :: MIT License
|
|
28
34
|
Classifier: Programming Language :: Python :: 3
|
|
29
35
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
@@ -32,10 +38,12 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
32
38
|
Classifier: Framework :: Django
|
|
33
39
|
Classifier: Intended Audience :: Developers
|
|
34
40
|
Classifier: Operating System :: OS Independent
|
|
41
|
+
Classifier: Typing :: Typed
|
|
35
42
|
Requires-Python: >=3.12
|
|
36
43
|
Description-Content-Type: text/markdown
|
|
37
44
|
License-File: LICENSE
|
|
38
45
|
Requires-Dist: asgiref>=3.8.1
|
|
46
|
+
Requires-Dist: channels>=4.1.0
|
|
39
47
|
Requires-Dist: Django>=5.2.7
|
|
40
48
|
Requires-Dist: django-simple-history>=3.8.0
|
|
41
49
|
Requires-Dist: exrex>=0.12.0
|
|
@@ -54,7 +62,6 @@ Requires-Dist: Pint>=0.24.4
|
|
|
54
62
|
Requires-Dist: platformdirs>=4.3.7
|
|
55
63
|
Requires-Dist: promise>=2.3
|
|
56
64
|
Requires-Dist: python-dateutil>=2.9.0.post0
|
|
57
|
-
Requires-Dist: setuptools==80.0.0
|
|
58
65
|
Requires-Dist: six>=1.17.0
|
|
59
66
|
Requires-Dist: smmap>=5.0.2
|
|
60
67
|
Requires-Dist: sqlparse>=0.5.3
|
|
@@ -161,7 +168,7 @@ The example above defines a project model, exposes it through the auto-generated
|
|
|
161
168
|
|
|
162
169
|
- Python >= 3.12
|
|
163
170
|
- Django >= 5.2
|
|
164
|
-
- Additional dependencies (see `requirements.txt`):
|
|
171
|
+
- Additional dependencies (see `requirements/base.txt`):
|
|
165
172
|
- `graphene`
|
|
166
173
|
- `numpy`
|
|
167
174
|
- `Pint`
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
general_manager/__init__.py,sha256=OmRYpjg3N9w0yX1eAq32WdLtcf8I55M3sqhO-Qrawjo,742
|
|
2
|
-
general_manager/apps.py,sha256=
|
|
2
|
+
general_manager/apps.py,sha256=Fsqvh7Xznp_7zOAyHABGtwJz10oT4kdY3C4MgmOGnAs,16723
|
|
3
3
|
general_manager/public_api_registry.py,sha256=xKfgbyvXB_oZZku9ksLNzOGQbmL5QfWuRGE2qH2FOtc,7338
|
|
4
|
+
general_manager/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
5
|
general_manager/_types/__init__.py,sha256=RmS0Ok-1-CwWOZL_socLWksEk9MfsshL9eQx879I4mU,60
|
|
5
6
|
general_manager/_types/api.py,sha256=EnEUKCr24Ac2klzZJvx17dJNxDRyfI9zEx9I0vCfpio,489
|
|
6
7
|
general_manager/_types/bucket.py,sha256=-kK46YX7mGwv3OVEjZTnmMqR9qpq8fT09Ez-wMF80nc,432
|
|
@@ -14,7 +15,8 @@ general_manager/_types/permission.py,sha256=BG-RMsGgVCRVHyJgns9a1VTcwtqS9WzbG2HO
|
|
|
14
15
|
general_manager/_types/rule.py,sha256=Ju5t7NhGO76KnqwOElXk2cMI6cIYyMW5sEPayXExJPM,239
|
|
15
16
|
general_manager/_types/utils.py,sha256=jze1yRZQw_OKVOmJNMv4MEu92rP01CVtjLBCEMqxCqk,1026
|
|
16
17
|
general_manager/api/__init__.py,sha256=6Usf6aEc5RalaOE4xzqqSp7KChxi9W4Nts4nFIFHtt4,677
|
|
17
|
-
general_manager/api/graphql.py,sha256=
|
|
18
|
+
general_manager/api/graphql.py,sha256=2OYYYtCDu5-L5aBRTv2Ns6s6O2lnyEQvootmoXQiuPY,74261
|
|
19
|
+
general_manager/api/graphql_subscription_consumer.py,sha256=JXJ8FRi3kP07jTXs9kSeSLaAc_AueiqJf_eeaVu8w4s,17916
|
|
18
20
|
general_manager/api/mutation.py,sha256=6T-UHElnTxWubG99-Svy7AeFlHuXaKc8nKvRPADmI0E,7347
|
|
19
21
|
general_manager/api/property.py,sha256=tT-eAKcuPhy0q_v0fKL4gPXcCVASC5M15_DYWMCQXjc,4358
|
|
20
22
|
general_manager/bucket/__init__.py,sha256=Ay3kVmdxWC8nt3jYx3FFnND89ysD_z0GaD5rIr-v7Ec,690
|
|
@@ -25,7 +27,7 @@ general_manager/bucket/groupBucket.py,sha256=-cN9jA_AOsnrpwmjiy6jTB_TFoUqLMeM1Sd
|
|
|
25
27
|
general_manager/cache/__init__.py,sha256=_jwrpqGzlwaL1moqG1B9XL9V-QW08VVdtDbkVDfN_sU,698
|
|
26
28
|
general_manager/cache/cacheDecorator.py,sha256=kgUvJHcC8tilqf1JH2QvyG-158AT_rmuKf6pgUy1IBs,3406
|
|
27
29
|
general_manager/cache/cacheTracker.py,sha256=rb637hGHOe79sehpTZLhfO979qrYLw3ATufo7kr_VvM,2991
|
|
28
|
-
general_manager/cache/dependencyIndex.py,sha256=
|
|
30
|
+
general_manager/cache/dependencyIndex.py,sha256=FWUqnG1BAqF7FdAFl8bqa4JX3ecN8dpesyeRbo0JsQU,19389
|
|
29
31
|
general_manager/cache/modelDependencyCollector.py,sha256=iFiuuQKO3-sEcUxbpA1svxL2TMkr8F6afAtRXK5fUBk,2645
|
|
30
32
|
general_manager/cache/signals.py,sha256=pKibv1EL7fYL4KB7O13TpqVTKZLnqo6A620vKlXaNkg,2015
|
|
31
33
|
general_manager/factory/__init__.py,sha256=t9RLlp_ZPU_0Xu5I7hg-xwo3yy1eSwnvfXMYvpGCFtE,714
|
|
@@ -41,7 +43,7 @@ general_manager/interface/models.py,sha256=rtuhOKeSgD2DboeZIMAQU99JyCOT7SuiuGqWv
|
|
|
41
43
|
general_manager/interface/readOnlyInterface.py,sha256=UcaCClVJv8IT-EBm__IN4jU6td_sXRRCN_Y_OKngs_4,11392
|
|
42
44
|
general_manager/manager/__init__.py,sha256=UwvLs13_UpYsq5igSY78cbyg11C6iTrHlr-rtDql43I,703
|
|
43
45
|
general_manager/manager/generalManager.py,sha256=A6kYjM2duxT0AAeN0er87gRWjLmcPmEjPmNHTQgACgs,9577
|
|
44
|
-
general_manager/manager/groupManager.py,sha256=
|
|
46
|
+
general_manager/manager/groupManager.py,sha256=zGSupjNVgASinyjLkpaM_SeR4Kb61hyXbkcj-R3sPa0,6429
|
|
45
47
|
general_manager/manager/input.py,sha256=UoVU0FDXHDEmuOk7mppx63DuwbPK2_qolcILar2Kk6U,3031
|
|
46
48
|
general_manager/manager/meta.py,sha256=iGYwuVrM0SWyvzVPLTS0typ8VT38QoxFuWhA1b1FBnA,5032
|
|
47
49
|
general_manager/measurement/__init__.py,sha256=Tt2Es7J-dGWcd8bFK4PR2m4AKBlRoj2WGXcKy64fOTY,711
|
|
@@ -67,9 +69,9 @@ general_manager/utils/makeCacheKey.py,sha256=T9YTHDW8VN50iW_Yzklm9Xw-mp1Q7PKMphQ
|
|
|
67
69
|
general_manager/utils/noneToZero.py,sha256=e3zk8Ofh3AsYW8spYmZWiv7FjOsr0jvfB9AOQbaPMWY,665
|
|
68
70
|
general_manager/utils/pathMapping.py,sha256=3BWRUM1EimUKeh8i_UK6nYsKtOJDykgmZgCA9dgYjqU,9531
|
|
69
71
|
general_manager/utils/public_api.py,sha256=SNTI_tRMcbv0qMttm-wMBoAEkqSEFMTI6ZHMajOnDlg,1437
|
|
70
|
-
general_manager/utils/testing.py,sha256=
|
|
71
|
-
generalmanager-0.
|
|
72
|
-
generalmanager-0.
|
|
73
|
-
generalmanager-0.
|
|
74
|
-
generalmanager-0.
|
|
75
|
-
generalmanager-0.
|
|
72
|
+
general_manager/utils/testing.py,sha256=etf_JlSaulD85A1CjPeOS0M0CbWCfPnaOxgHi0ozJLQ,14083
|
|
73
|
+
generalmanager-0.17.0.dist-info/licenses/LICENSE,sha256=OezwCA4X2-xXmRDvMaqHvHCeUmGtyCYjZ8F3XUxSGwc,1069
|
|
74
|
+
generalmanager-0.17.0.dist-info/METADATA,sha256=-YVROYZscJ9qFKOuwPEN7IJ8vunvto6P4OEm_Elsevo,8206
|
|
75
|
+
generalmanager-0.17.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
76
|
+
generalmanager-0.17.0.dist-info/top_level.txt,sha256=sTDtExP9ga-YP3h3h42yivUY-A2Q23C2nw6LNKOho4I,16
|
|
77
|
+
generalmanager-0.17.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|