maleo-foundation 0.2.47__tar.gz → 0.2.48__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 (129) hide show
  1. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/PKG-INFO +1 -1
  2. maleo_foundation-0.2.48/maleo_foundation/utils/controller.py +124 -0
  3. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation.egg-info/PKG-INFO +1 -1
  4. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/pyproject.toml +1 -1
  5. maleo_foundation-0.2.47/maleo_foundation/utils/controller.py +0 -87
  6. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/README.md +0 -0
  7. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/__init__.py +0 -0
  8. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/authentication.py +0 -0
  9. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/authorization.py +0 -0
  10. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/__init__.py +0 -0
  11. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/manager.py +0 -0
  12. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/services/__init__.py +0 -0
  13. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/services/encryption/__init__.py +0 -0
  14. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/services/encryption/aes.py +0 -0
  15. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/services/encryption/rsa.py +0 -0
  16. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/services/hash/__init__.py +0 -0
  17. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/services/hash/bcrypt.py +0 -0
  18. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/services/hash/hmac.py +0 -0
  19. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/services/hash/sha256.py +0 -0
  20. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/services/key.py +0 -0
  21. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/services/signature.py +0 -0
  22. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/client/services/token.py +0 -0
  23. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/constants.py +0 -0
  24. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/enums.py +0 -0
  25. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/__init__.py +0 -0
  26. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/client.py +0 -0
  27. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/encryption/__init__.py +0 -0
  28. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/encryption/aes.py +0 -0
  29. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/encryption/rsa.py +0 -0
  30. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/general.py +0 -0
  31. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/hash.py +0 -0
  32. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/key.py +0 -0
  33. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/repository.py +0 -0
  34. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/service.py +0 -0
  35. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/signature.py +0 -0
  36. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/expanded_types/token.py +0 -0
  37. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/extended_types.py +0 -0
  38. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/__init__.py +0 -0
  39. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/cache/__init__.py +0 -0
  40. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/cache/base.py +0 -0
  41. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/cache/redis.py +0 -0
  42. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/client/__init__.py +0 -0
  43. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/client/base.py +0 -0
  44. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/client/google/__init__.py +0 -0
  45. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/client/google/base.py +0 -0
  46. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/client/google/parameter.py +0 -0
  47. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/client/google/secret.py +0 -0
  48. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/client/google/storage.py +0 -0
  49. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/client/maleo.py +0 -0
  50. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/db.py +0 -0
  51. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/middleware.py +0 -0
  52. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/managers/service.py +0 -0
  53. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/middlewares/authentication.py +0 -0
  54. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/middlewares/base.py +0 -0
  55. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/middlewares/cors.py +0 -0
  56. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/__init__.py +0 -0
  57. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/responses.py +0 -0
  58. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/schemas/__init__.py +0 -0
  59. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/schemas/encryption.py +0 -0
  60. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/schemas/general.py +0 -0
  61. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/schemas/hash.py +0 -0
  62. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/schemas/key.py +0 -0
  63. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/schemas/parameter.py +0 -0
  64. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/schemas/result.py +0 -0
  65. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/schemas/signature.py +0 -0
  66. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/schemas/token.py +0 -0
  67. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/table.py +0 -0
  68. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/__init__.py +0 -0
  69. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/general/__init__.py +0 -0
  70. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/general/key.py +0 -0
  71. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/general/signature.py +0 -0
  72. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/general/token.py +0 -0
  73. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/__init__.py +0 -0
  74. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/client.py +0 -0
  75. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/encryption/__init__.py +0 -0
  76. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/encryption/aes.py +0 -0
  77. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/encryption/rsa.py +0 -0
  78. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/general.py +0 -0
  79. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/hash/__init__.py +0 -0
  80. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/hash/bcrypt.py +0 -0
  81. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/hash/hmac.py +0 -0
  82. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/hash/sha256.py +0 -0
  83. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/key.py +0 -0
  84. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/service.py +0 -0
  85. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/signature.py +0 -0
  86. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/parameters/token.py +0 -0
  87. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/__init__.py +0 -0
  88. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/client/__init__.py +0 -0
  89. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/client/controllers/__init__.py +0 -0
  90. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/client/controllers/http.py +0 -0
  91. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/client/service.py +0 -0
  92. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/encryption/__init__.py +0 -0
  93. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/encryption/aes.py +0 -0
  94. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/encryption/rsa.py +0 -0
  95. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/hash.py +0 -0
  96. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/key.py +0 -0
  97. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/service/__init__.py +0 -0
  98. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/service/controllers/__init__.py +0 -0
  99. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/service/controllers/rest.py +0 -0
  100. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/service/general.py +0 -0
  101. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/service/repository.py +0 -0
  102. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/signature.py +0 -0
  103. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/models/transfers/results/token.py +0 -0
  104. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/rest_controller_result.py +0 -0
  105. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/types.py +0 -0
  106. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/__init__.py +0 -0
  107. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/client.py +0 -0
  108. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/dependencies/__init__.py +0 -0
  109. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/dependencies/auth.py +0 -0
  110. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/exceptions.py +0 -0
  111. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/extractor.py +0 -0
  112. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/formatter/__init__.py +0 -0
  113. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/formatter/case.py +0 -0
  114. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/loaders/__init__.py +0 -0
  115. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/loaders/credential/__init__.py +0 -0
  116. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/loaders/credential/google.py +0 -0
  117. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/loaders/json.py +0 -0
  118. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/loaders/key/__init__.py +0 -0
  119. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/loaders/key/rsa.py +0 -0
  120. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/loaders/yaml.py +0 -0
  121. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/logging.py +0 -0
  122. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/mergers.py +0 -0
  123. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/query.py +0 -0
  124. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation/utils/repository.py +0 -0
  125. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation.egg-info/SOURCES.txt +0 -0
  126. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation.egg-info/dependency_links.txt +0 -0
  127. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation.egg-info/requires.txt +0 -0
  128. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/maleo_foundation.egg-info/top_level.txt +0 -0
  129. {maleo_foundation-0.2.47 → maleo_foundation-0.2.48}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo_foundation
3
- Version: 0.2.47
3
+ Version: 0.2.48
4
4
  Summary: Foundation package for Maleo
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: MIT
@@ -0,0 +1,124 @@
1
+ import inspect
2
+ from fastapi import status
3
+ from functools import wraps
4
+ from typing import Awaitable, Callable, Dict, List, Union
5
+ from maleo_foundation.types import BaseTypes
6
+ from maleo_foundation.models.responses import BaseResponses
7
+ from maleo_foundation.models.transfers.parameters.general \
8
+ import BaseGeneralParametersTransfers
9
+ from maleo_foundation.models.transfers.results.service.controllers.rest \
10
+ import BaseServiceRESTControllerResults
11
+ from maleo_foundation.expanded_types.general import BaseGeneralExpandedTypes
12
+
13
+ class BaseControllerUtils:
14
+ @staticmethod
15
+ def field_expansion_handler(
16
+ expandable_fields_dependencies_map:BaseTypes.OptionalStringToListOfStringDict = None,
17
+ field_expansion_processors:BaseGeneralExpandedTypes.OptionalListOfFieldExpansionProcessor = None
18
+ ):
19
+ """
20
+ Decorator to handle expandable fields validation and processing.
21
+
22
+ Args:
23
+ expandable_fields_dependencies_map: Dictionary where keys are dependency fields and values are lists of dependent fields
24
+ field_expansion_processors: List of processor functions that handle that field's data
25
+ """
26
+ def decorator(func:Callable[..., Awaitable[BaseServiceRESTControllerResults]]):
27
+ @wraps(func)
28
+ async def wrapper(*args, **kwargs):
29
+ sig = inspect.signature(func)
30
+ bound = sig.bind(*args, **kwargs)
31
+ bound.apply_defaults()
32
+
33
+ parameters = bound.arguments.get("parameters")
34
+ expand:BaseTypes.OptionalListOfStrings = getattr(parameters, 'expand', None)
35
+
36
+ #* Validate expandable fields dependencies
37
+ if expand is not None and expandable_fields_dependencies_map is not None:
38
+ for dependency, dependents in expandable_fields_dependencies_map.items():
39
+ if dependency not in expand:
40
+ for dependent in dependents:
41
+ if dependent in expand:
42
+ other = f"'{dependency}' must also be expanded if '{dependent}' is expanded"
43
+ content = BaseResponses.InvalidExpand(other=other).model_dump()
44
+ return BaseServiceRESTControllerResults(
45
+ success=False,
46
+ content=content,
47
+ status_code=status.HTTP_400_BAD_REQUEST
48
+ )
49
+
50
+ #* Call the original function
51
+ result = await func(*args, **kwargs)
52
+
53
+ if not isinstance(result.content, Dict):
54
+ return result
55
+
56
+ #* Recursive function to apply expansion processors
57
+ def recursive_expand(data:Union[Dict, List], expand:List[str]):
58
+ if isinstance(data, list):
59
+ for idx, item in enumerate(data):
60
+ data[idx] = recursive_expand(item, expand)
61
+ return data
62
+ elif isinstance(data, dict):
63
+ #* Apply each processor to current dict
64
+ for processor in field_expansion_processors or []:
65
+ raw_parameters = {"data": data, "expand": expand}
66
+ parameters = (
67
+ BaseGeneralParametersTransfers
68
+ .FieldExpansionProcessor
69
+ .model_validate(raw_parameters)
70
+ )
71
+ data = processor(parameters)
72
+
73
+ #* Now recursively apply to nested fields if they are in expand
74
+ for key in expand:
75
+ if key in data and isinstance(data[key], (dict, list)):
76
+ #* Recursively expand nested field with same expand
77
+ data[key] = recursive_expand(data[key], expand)
78
+
79
+ return data
80
+ else:
81
+ return data
82
+
83
+ #* Process expansions recursively if needed
84
+ if (
85
+ result.success
86
+ and result.content.get("data", None) is not None
87
+ and field_expansion_processors is not None
88
+ and expand is not None
89
+ ):
90
+ data = result.content["data"]
91
+ result.content["data"] = recursive_expand(data, expand)
92
+
93
+ # #* Process the fields if needed
94
+ # if (result.success
95
+ # and result.content.get("data", None) is not None
96
+ # and field_expansion_processors is not None
97
+ # ):
98
+ # data = result.content["data"]
99
+ # if isinstance(data, List):
100
+ # for idx, dt in enumerate(data):
101
+ # for processor in field_expansion_processors:
102
+ # raw_parameters = {"data": dt, "expand": expand}
103
+ # parameters = (
104
+ # BaseGeneralParametersTransfers
105
+ # .FieldExpansionProcessor
106
+ # .model_validate(raw_parameters)
107
+ # )
108
+ # dt = processor(parameters)
109
+ # data[idx] = dt
110
+ # elif isinstance(data, Dict):
111
+ # raw_parameters = {"data": data, "expand": expand}
112
+ # parameters = (
113
+ # BaseGeneralParametersTransfers
114
+ # .FieldExpansionProcessor
115
+ # .model_validate(raw_parameters)
116
+ # )
117
+ # for processor in field_expansion_processors:
118
+ # data = processor(parameters)
119
+ # result.content["data"] = data
120
+ # result.process_response()
121
+
122
+ return result
123
+ return wrapper
124
+ return decorator
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: maleo_foundation
3
- Version: 0.2.47
3
+ Version: 0.2.48
4
4
  Summary: Foundation package for Maleo
5
5
  Author-email: Agra Bima Yuda <agra@nexmedis.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "maleo_foundation"
7
- version = "0.2.47"
7
+ version = "0.2.48"
8
8
  description = "Foundation package for Maleo"
9
9
  authors = [
10
10
  { name = "Agra Bima Yuda", email = "agra@nexmedis.com" }
@@ -1,87 +0,0 @@
1
- import inspect
2
- from fastapi import status
3
- from functools import wraps
4
- from typing import Awaitable, Callable, Dict, List
5
- from maleo_foundation.types import BaseTypes
6
- from maleo_foundation.models.responses import BaseResponses
7
- from maleo_foundation.models.transfers.parameters.general \
8
- import BaseGeneralParametersTransfers
9
- from maleo_foundation.models.transfers.results.service.controllers.rest \
10
- import BaseServiceRESTControllerResults
11
- from maleo_foundation.expanded_types.general import BaseGeneralExpandedTypes
12
-
13
- class BaseControllerUtils:
14
- @staticmethod
15
- def field_expansion_handler(
16
- expandable_fields_dependencies_map:BaseTypes.OptionalStringToListOfStringDict = None,
17
- field_expansion_processors:BaseGeneralExpandedTypes.OptionalListOfFieldExpansionProcessor = None
18
- ):
19
- """
20
- Decorator to handle expandable fields validation and processing.
21
-
22
- Args:
23
- expandable_fields_dependencies_map: Dictionary where keys are dependency fields and values are lists of dependent fields
24
- field_expansion_processors: List of processor functions that handle that field's data
25
- """
26
- def decorator(func:Callable[..., Awaitable[BaseServiceRESTControllerResults]]):
27
- @wraps(func)
28
- async def wrapper(*args, **kwargs):
29
- sig = inspect.signature(func)
30
- bound = sig.bind(*args, **kwargs)
31
- bound.apply_defaults()
32
-
33
- parameters = bound.arguments.get("parameters")
34
- expand:BaseTypes.OptionalListOfStrings = getattr(parameters, 'expand', None)
35
-
36
- #* Validate expandable fields dependencies
37
- if expand is not None and expandable_fields_dependencies_map is not None:
38
- for dependency, dependents in expandable_fields_dependencies_map.items():
39
- if dependency not in expand:
40
- for dependent in dependents:
41
- if dependent in expand:
42
- other = f"'{dependency}' must also be expanded if '{dependent}' is expanded"
43
- content = BaseResponses.InvalidExpand(other=other).model_dump()
44
- return BaseServiceRESTControllerResults(
45
- success=False,
46
- content=content,
47
- status_code=status.HTTP_400_BAD_REQUEST
48
- )
49
-
50
- #* Call the original function
51
- result = await func(*args, **kwargs)
52
-
53
- if not isinstance(result.content, Dict):
54
- return result
55
-
56
- #* Process the fields if needed
57
- if (result.success
58
- and result.content.get("data", None) is not None
59
- and field_expansion_processors is not None
60
- ):
61
- data = result.content["data"]
62
- if isinstance(data, List):
63
- for idx, dt in enumerate(data):
64
- for processor in field_expansion_processors:
65
- raw_parameters = {"data": dt, "expand": expand}
66
- parameters = (
67
- BaseGeneralParametersTransfers
68
- .FieldExpansionProcessor
69
- .model_validate(raw_parameters)
70
- )
71
- dt = processor(parameters)
72
- data[idx] = dt
73
- elif isinstance(data, Dict):
74
- raw_parameters = {"data": data, "expand": expand}
75
- parameters = (
76
- BaseGeneralParametersTransfers
77
- .FieldExpansionProcessor
78
- .model_validate(raw_parameters)
79
- )
80
- for processor in field_expansion_processors:
81
- data = processor(parameters)
82
- result.content["data"] = data
83
- result.process_response()
84
-
85
- return result
86
- return wrapper
87
- return decorator