tiferet 1.0.0a19__py3-none-any.whl → 1.0.0b1__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.
- tiferet/__init__.py +3 -2
- tiferet/commands/__init__.py +6 -0
- tiferet/commands/app.py +102 -0
- tiferet/commands/core.py +124 -0
- tiferet/commands/dependencies.py +76 -0
- tiferet/commands/settings.py +101 -0
- tiferet/configs/__init__.py +3 -67
- tiferet/configs/error.py +48 -0
- tiferet/configs/settings.py +37 -0
- tiferet/contexts/__init__.py +0 -8
- tiferet/contexts/app.py +215 -182
- tiferet/contexts/cache.py +76 -0
- tiferet/contexts/container.py +92 -190
- tiferet/contexts/error.py +78 -80
- tiferet/contexts/feature.py +122 -83
- tiferet/contracts/__init__.py +4 -0
- tiferet/contracts/app.py +92 -0
- tiferet/contracts/cache.py +70 -0
- tiferet/contracts/container.py +147 -0
- tiferet/contracts/error.py +177 -0
- tiferet/contracts/feature.py +159 -0
- tiferet/contracts/settings.py +34 -0
- tiferet/data/__init__.py +3 -4
- tiferet/data/app.py +71 -208
- tiferet/data/container.py +52 -38
- tiferet/data/error.py +15 -24
- tiferet/data/feature.py +27 -8
- tiferet/{domain/core.py → data/settings.py} +36 -96
- tiferet/handlers/__init__.py +0 -0
- tiferet/handlers/container.py +116 -0
- tiferet/handlers/error.py +49 -0
- tiferet/handlers/feature.py +94 -0
- tiferet/models/__init__.py +4 -0
- tiferet/models/app.py +150 -0
- tiferet/models/container.py +135 -0
- tiferet/{domain → models}/error.py +86 -36
- tiferet/{domain → models}/feature.py +107 -47
- tiferet/models/settings.py +148 -0
- tiferet/proxies/__init__.py +0 -0
- tiferet/proxies/yaml/__init__.py +0 -0
- tiferet/{repos → proxies/yaml}/app.py +13 -41
- tiferet/{repos → proxies/yaml}/container.py +26 -56
- tiferet/{repos → proxies/yaml}/error.py +11 -70
- tiferet/proxies/yaml/feature.py +92 -0
- {tiferet-1.0.0a19.dist-info → tiferet-1.0.0b1.dist-info}/METADATA +12 -3
- tiferet-1.0.0b1.dist-info/RECORD +51 -0
- {tiferet-1.0.0a19.dist-info → tiferet-1.0.0b1.dist-info}/WHEEL +1 -1
- tiferet/commands/container.py +0 -54
- tiferet/commands/error.py +0 -21
- tiferet/commands/feature.py +0 -90
- tiferet/contexts/request.py +0 -110
- tiferet/domain/__init__.py +0 -5
- tiferet/domain/app.py +0 -131
- tiferet/domain/container.py +0 -141
- tiferet/repos/__init__.py +0 -7
- tiferet/repos/feature.py +0 -151
- tiferet-1.0.0a19.dist-info/RECORD +0 -35
- {tiferet-1.0.0a19.dist-info → tiferet-1.0.0b1.dist-info/licenses}/LICENSE +0 -0
- {tiferet-1.0.0a19.dist-info → tiferet-1.0.0b1.dist-info}/top_level.txt +0 -0
tiferet/data/feature.py
CHANGED
@@ -4,8 +4,9 @@
|
|
4
4
|
from schematics.types.serializable import serializable
|
5
5
|
|
6
6
|
#
|
7
|
-
from ..
|
8
|
-
from ..
|
7
|
+
from ..data import DataObject
|
8
|
+
from ..contracts.feature import Feature as FeatureContract, FeatureCommand as FeatureCommandContract
|
9
|
+
from ..models.feature import *
|
9
10
|
|
10
11
|
|
11
12
|
class FeatureCommandData(FeatureCommand, DataObject):
|
@@ -23,11 +24,22 @@ class FeatureCommandData(FeatureCommand, DataObject):
|
|
23
24
|
|
24
25
|
# Define the roles for the feature handler data.
|
25
26
|
roles = {
|
26
|
-
'to_model': DataObject.
|
27
|
+
'to_model': DataObject.deny('parameters'),
|
27
28
|
'to_data': DataObject.allow()
|
28
29
|
}
|
29
30
|
|
30
|
-
|
31
|
+
# * attributes
|
32
|
+
parameters = DictType(
|
33
|
+
StringType(),
|
34
|
+
default={},
|
35
|
+
serialized_name='params',
|
36
|
+
deserialize_from=['params', 'parameters'],
|
37
|
+
metadata=dict(
|
38
|
+
description='The parameters for the feature.'
|
39
|
+
)
|
40
|
+
)
|
41
|
+
|
42
|
+
def map(self, role: str = 'to_model', **kwargs) -> FeatureCommandContract:
|
31
43
|
'''
|
32
44
|
Maps the feature handler data to a feature handler object.
|
33
45
|
|
@@ -38,7 +50,10 @@ class FeatureCommandData(FeatureCommand, DataObject):
|
|
38
50
|
:return: A new feature handler object.
|
39
51
|
:rtype: f.FeatureCommand
|
40
52
|
'''
|
41
|
-
return super().map(FeatureCommand,
|
53
|
+
return super().map(FeatureCommand,
|
54
|
+
role,
|
55
|
+
parameters=self.parameters,
|
56
|
+
**kwargs)
|
42
57
|
|
43
58
|
|
44
59
|
class FeatureData(Feature, DataObject):
|
@@ -59,8 +74,9 @@ class FeatureData(Feature, DataObject):
|
|
59
74
|
'to_model': DataObject.deny('feature_key'),
|
60
75
|
'to_data': DataObject.deny('feature_key', 'group_id', 'id')
|
61
76
|
}
|
62
|
-
|
63
|
-
|
77
|
+
|
78
|
+
# * attributes
|
79
|
+
commands = ListType(ModelType(FeatureCommandData),
|
64
80
|
deserialize_from=['handlers', 'functions', 'commands'],)
|
65
81
|
|
66
82
|
@serializable
|
@@ -72,7 +88,7 @@ class FeatureData(Feature, DataObject):
|
|
72
88
|
# Return the feature key.
|
73
89
|
return self.id.split('.')[-1]
|
74
90
|
|
75
|
-
def map(self, role: str = 'to_model', **kwargs) ->
|
91
|
+
def map(self, role: str = 'to_model', **kwargs) -> FeatureContract:
|
76
92
|
'''
|
77
93
|
Maps the feature data to a feature object.
|
78
94
|
|
@@ -87,6 +103,9 @@ class FeatureData(Feature, DataObject):
|
|
87
103
|
# Map the feature data to a feature object.
|
88
104
|
return super().map(Feature, role,
|
89
105
|
feature_key=self.feature_key,
|
106
|
+
commands=[
|
107
|
+
command.map(role, **kwargs) for command in self.commands
|
108
|
+
],
|
90
109
|
**kwargs
|
91
110
|
)
|
92
111
|
|
@@ -3,82 +3,23 @@
|
|
3
3
|
# ** core
|
4
4
|
from typing import Any
|
5
5
|
|
6
|
-
# ** infra
|
7
|
-
from schematics import Model
|
8
|
-
|
9
6
|
# ** app
|
10
|
-
from ..
|
11
|
-
|
12
|
-
|
13
|
-
# *** models
|
14
|
-
|
15
|
-
# ** model: model_object
|
16
|
-
class ModelObject(Model):
|
17
|
-
'''
|
18
|
-
A domain model object.
|
19
|
-
'''
|
20
|
-
|
21
|
-
# * method: new
|
22
|
-
@staticmethod
|
23
|
-
def new(
|
24
|
-
model_type: type,
|
25
|
-
validate: bool = True,
|
26
|
-
strict: bool = True,
|
27
|
-
**kwargs
|
28
|
-
) -> Any:
|
29
|
-
'''
|
30
|
-
Initializes a new model object.
|
31
|
-
|
32
|
-
:param model_type: The type of model object to create.
|
33
|
-
:type model_type: type
|
34
|
-
:param validate: True to validate the model object.
|
35
|
-
:type validate: bool
|
36
|
-
:param strict: True to enforce strict mode for the model object.
|
37
|
-
:type strict: bool
|
38
|
-
:param kwargs: Keyword arguments.
|
39
|
-
:type kwargs: dict
|
40
|
-
:return: A new model object.
|
41
|
-
:rtype: Any
|
42
|
-
'''
|
43
|
-
|
44
|
-
# Create a new model object.
|
45
|
-
_object = model_type(dict(
|
46
|
-
**kwargs
|
47
|
-
), strict=strict)
|
48
|
-
|
49
|
-
# Validate if specified.
|
50
|
-
if validate:
|
51
|
-
_object.validate()
|
7
|
+
from ..contracts.settings import ModelContract
|
8
|
+
from ..models.settings import *
|
52
9
|
|
53
|
-
# Return the new model object.
|
54
|
-
return _object
|
55
10
|
|
11
|
+
# *** constants
|
56
12
|
|
57
|
-
# **
|
58
|
-
|
59
|
-
'''
|
60
|
-
A domain model entity.
|
61
|
-
'''
|
13
|
+
# ** constant: default_module_path
|
14
|
+
DEFAULT_MODULE_PATH = 'tiferet.contexts.app'
|
62
15
|
|
63
|
-
|
64
|
-
|
65
|
-
required=True,
|
66
|
-
metadata=dict(
|
67
|
-
description='The entity unique identifier.'
|
68
|
-
)
|
69
|
-
)
|
16
|
+
# ** constant: default_class_name
|
17
|
+
DEFAULT_CLASS_NAME = 'AppInterfaceContext'
|
70
18
|
|
71
19
|
|
72
|
-
#
|
73
|
-
class ValueObject(ModelObject):
|
74
|
-
'''
|
75
|
-
A domain model value object.
|
76
|
-
'''
|
77
|
-
|
78
|
-
pass
|
79
|
-
|
20
|
+
# *** classes
|
80
21
|
|
81
|
-
# **
|
22
|
+
# ** class: data_object
|
82
23
|
class DataObject(Model):
|
83
24
|
'''
|
84
25
|
A data representation object.
|
@@ -90,7 +31,7 @@ class DataObject(Model):
|
|
90
31
|
role: str = 'to_model',
|
91
32
|
validate: bool = True,
|
92
33
|
**kwargs
|
93
|
-
) ->
|
34
|
+
) -> ModelContract:
|
94
35
|
'''
|
95
36
|
Maps the model data to a model object.
|
96
37
|
|
@@ -102,8 +43,8 @@ class DataObject(Model):
|
|
102
43
|
:type validate: bool
|
103
44
|
:param kwargs: Additional keyword arguments for mapping.
|
104
45
|
:type kwargs: dict
|
105
|
-
:return: A new model object.
|
106
|
-
:rtype:
|
46
|
+
:return: A new model object as a contract.
|
47
|
+
:rtype: ModelContract
|
107
48
|
'''
|
108
49
|
|
109
50
|
# Get primitive of the model data and merge with the keyword arguments.
|
@@ -113,7 +54,12 @@ class DataObject(Model):
|
|
113
54
|
_data[key] = value
|
114
55
|
|
115
56
|
# Map the data object to a model object.
|
116
|
-
|
57
|
+
# Attempt to create a new model object with a custom factory method.
|
58
|
+
# If the factory method does not exist, employ the standard method.
|
59
|
+
try:
|
60
|
+
_object = type.new(**_data, strict=False)
|
61
|
+
except Exception:
|
62
|
+
_object = ModelObject.new(type, **_data, strict=False)
|
117
63
|
|
118
64
|
# Validate if specified.
|
119
65
|
if validate:
|
@@ -158,6 +104,7 @@ class DataObject(Model):
|
|
158
104
|
# Return the data object.
|
159
105
|
return obj
|
160
106
|
|
107
|
+
# ** method: from_data
|
161
108
|
@staticmethod
|
162
109
|
def from_data(
|
163
110
|
data: type,
|
@@ -179,6 +126,14 @@ class DataObject(Model):
|
|
179
126
|
# ** method: allow
|
180
127
|
@staticmethod
|
181
128
|
def allow(*args) -> Any:
|
129
|
+
'''
|
130
|
+
Creates a whitelist transform for data mapping.
|
131
|
+
|
132
|
+
:param args: Fields to allow in the transform.
|
133
|
+
:type args: tuple
|
134
|
+
:return: The whitelist transform.
|
135
|
+
:rtype: Any
|
136
|
+
'''
|
182
137
|
|
183
138
|
# Create a whitelist transform.
|
184
139
|
# Create a wholelist transform if no arguments are specified.
|
@@ -190,30 +145,15 @@ class DataObject(Model):
|
|
190
145
|
# ** method: deny
|
191
146
|
@staticmethod
|
192
147
|
def deny(*args) -> Any:
|
148
|
+
'''
|
149
|
+
Creates a blacklist transform for data mapping.
|
150
|
+
|
151
|
+
:param args: Fields to deny in the transform.
|
152
|
+
:type args: tuple
|
153
|
+
:return: The blacklist transform.
|
154
|
+
:rtype: Any
|
155
|
+
'''
|
193
156
|
|
194
157
|
# Create a blacklist transform.
|
195
158
|
from schematics.transforms import blacklist
|
196
|
-
return blacklist(*args)
|
197
|
-
|
198
|
-
|
199
|
-
# ** model: module_dependency
|
200
|
-
class ModuleDependency(ValueObject):
|
201
|
-
'''
|
202
|
-
A module dependency.
|
203
|
-
'''
|
204
|
-
|
205
|
-
# * attribute: module_path
|
206
|
-
module_path = StringType(
|
207
|
-
required=True,
|
208
|
-
metadata=dict(
|
209
|
-
description='The module path.'
|
210
|
-
)
|
211
|
-
)
|
212
|
-
|
213
|
-
# * attribute: class_name
|
214
|
-
class_name = StringType(
|
215
|
-
required=True,
|
216
|
-
metadata=dict(
|
217
|
-
description='The class name.'
|
218
|
-
)
|
219
|
-
)
|
159
|
+
return blacklist(*args)
|
File without changes
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# *** imports
|
2
|
+
|
3
|
+
# ** app
|
4
|
+
from ..commands import *
|
5
|
+
from ..contracts.container import *
|
6
|
+
|
7
|
+
|
8
|
+
# *** handlers
|
9
|
+
|
10
|
+
# ** handler: container_handler
|
11
|
+
class ContainerHandler(ContainerService):
|
12
|
+
|
13
|
+
'''
|
14
|
+
A container handler is a class that is used to create a container object.
|
15
|
+
'''
|
16
|
+
|
17
|
+
# * attribute: container_repo
|
18
|
+
container_repo: ContainerRepository
|
19
|
+
|
20
|
+
# * method: __init__
|
21
|
+
def __init__(self, container_repo: ContainerRepository):
|
22
|
+
'''
|
23
|
+
Initialize the container handler.
|
24
|
+
|
25
|
+
:param name: The name of the container.
|
26
|
+
:type name: str
|
27
|
+
:param dependencies: The dependencies.
|
28
|
+
:type dependencies: dict
|
29
|
+
'''
|
30
|
+
|
31
|
+
# Assign the container repository.
|
32
|
+
self.container_repo = container_repo
|
33
|
+
|
34
|
+
# * method: list_all
|
35
|
+
def list_all(self) -> Tuple[List[ContainerAttribute], Dict[str, str]]:
|
36
|
+
'''
|
37
|
+
List all container attributes and constants.
|
38
|
+
|
39
|
+
:return: A tuple containing a list of container attributes and a dictionary of constants.
|
40
|
+
:rtype: Tuple[List[ContainerAttribute], Dict[str, str]]
|
41
|
+
'''
|
42
|
+
|
43
|
+
# Retrieve all container attributes and constants from the repository.
|
44
|
+
attributes, constants = self.container_repo.list_all()
|
45
|
+
|
46
|
+
# Return the attributes and constants.
|
47
|
+
return attributes, constants
|
48
|
+
|
49
|
+
# * method: load_constants
|
50
|
+
def load_constants(self, attributes: List[ContainerAttribute], constants: Dict[str, str] = {}, flags: List[str] = []) -> Dict[str, str]:
|
51
|
+
'''
|
52
|
+
Load constants from the container attributes.
|
53
|
+
|
54
|
+
:param attributes: The list of container attributes.
|
55
|
+
:type attributes: List[ContainerAttribute]
|
56
|
+
:param constants: The dictionary of constants.
|
57
|
+
:type constants: Dict[str, str]
|
58
|
+
:return: A dictionary of constants.
|
59
|
+
:rtype: Dict[str, str]
|
60
|
+
'''
|
61
|
+
|
62
|
+
# Raise an error if there are no attributes provided.
|
63
|
+
if not attributes:
|
64
|
+
raise_error.execute(
|
65
|
+
'CONTAINER_ATTRIBUTES_NOT_FOUND',
|
66
|
+
'No container attributes provided to load the container.',
|
67
|
+
)
|
68
|
+
|
69
|
+
# If constants are provided, clean the parameters using the parse_parameter command.
|
70
|
+
constants = {k: parse_parameter.execute(v) for k, v in constants.items()}
|
71
|
+
|
72
|
+
# Iterate through each attribute to clean parameter dictionaries.
|
73
|
+
# For each attribute, parse its parameters and add them to the constants dictionary.
|
74
|
+
# For each dependency, parse its parameters and add them to the constants dictionary.
|
75
|
+
for attr in attributes:
|
76
|
+
constants.update({k: parse_parameter.execute(v) for k, v in attr.parameters.items()})
|
77
|
+
dependency = attr.get_dependency(flags)
|
78
|
+
if dependency:
|
79
|
+
constants.update({k: parse_parameter.execute(v) for k, v in dependency.parameters.items()})
|
80
|
+
|
81
|
+
# Return the updated constants dictionary.
|
82
|
+
return constants
|
83
|
+
|
84
|
+
# * method: get_dependency_type
|
85
|
+
def get_dependency_type(self, attribute: ContainerAttribute, flags: List[str] = []) -> type:
|
86
|
+
'''
|
87
|
+
Get the type of a container attribute.
|
88
|
+
|
89
|
+
:param attribute: The container attribute.
|
90
|
+
:type attribute: ContainerAttribute
|
91
|
+
:return: The type of the container attribute.
|
92
|
+
:rtype: type
|
93
|
+
'''
|
94
|
+
|
95
|
+
# Check the flagged dependencies for the type first.
|
96
|
+
for dep in attribute.dependencies:
|
97
|
+
if dep.flag in flags:
|
98
|
+
return import_dependency.execute(
|
99
|
+
dep.module_path,
|
100
|
+
dep.class_name
|
101
|
+
)
|
102
|
+
|
103
|
+
# Otherwise defer to an available default type.
|
104
|
+
if attribute.module_path and attribute.class_name:
|
105
|
+
return import_dependency.execute(
|
106
|
+
attribute.module_path,
|
107
|
+
attribute.class_name
|
108
|
+
)
|
109
|
+
|
110
|
+
# If no type is found, raise an error.
|
111
|
+
raise_error.execute(
|
112
|
+
'DEPENDENCY_TYPE_NOT_FOUND',
|
113
|
+
f'No dependency type found for attribute {attribute.id} with flags {flags}.',
|
114
|
+
attribute.id,
|
115
|
+
flags
|
116
|
+
)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# *** imports
|
2
|
+
|
3
|
+
# ** app
|
4
|
+
from ..contracts.error import *
|
5
|
+
|
6
|
+
|
7
|
+
# *** handlers
|
8
|
+
|
9
|
+
# ** handler: error_handler
|
10
|
+
class ErrorHandler(ErrorService):
|
11
|
+
'''
|
12
|
+
A handler for error objects.
|
13
|
+
'''
|
14
|
+
|
15
|
+
# * attribute: error_repo
|
16
|
+
error_repo: ErrorRepository
|
17
|
+
|
18
|
+
# * method: init
|
19
|
+
def __init__(self, error_repo: ErrorRepository):
|
20
|
+
'''
|
21
|
+
Initialize the error handler.
|
22
|
+
|
23
|
+
:param error_repo: The error repository to use for handling errors.
|
24
|
+
:type error_repo: ErrorRepository
|
25
|
+
'''
|
26
|
+
|
27
|
+
# Assign the attributes.
|
28
|
+
self.error_repo = error_repo
|
29
|
+
|
30
|
+
# * method: load_errors
|
31
|
+
def load_errors(self, configured_errors: List[Error] = []) -> List[Error]:
|
32
|
+
'''
|
33
|
+
Load errors by their codes.
|
34
|
+
|
35
|
+
:param configured_errors: The list of hard-coded errors to load.
|
36
|
+
:type configured_errors: List[Error]
|
37
|
+
:return: The list of loaded errors.
|
38
|
+
:rtype: List[Error]
|
39
|
+
'''
|
40
|
+
|
41
|
+
# Load the errors from the repository.
|
42
|
+
errors = self.error_repo.list()
|
43
|
+
|
44
|
+
# If there are configured errors, extend the list with them.
|
45
|
+
if configured_errors:
|
46
|
+
errors.extend(configured_errors)
|
47
|
+
|
48
|
+
# Return the list of errors.
|
49
|
+
return errors
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# *** imports
|
2
|
+
|
3
|
+
# ** app
|
4
|
+
from ..commands import *
|
5
|
+
from ..contracts.feature import *
|
6
|
+
|
7
|
+
|
8
|
+
# *** handlers
|
9
|
+
|
10
|
+
# ** handler: feature_handler
|
11
|
+
class FeatureHandler(FeatureService):
|
12
|
+
'''
|
13
|
+
Feature handler for executing feature requests.
|
14
|
+
'''
|
15
|
+
|
16
|
+
# * attribute: feature_repo
|
17
|
+
feature_repo: FeatureRepository
|
18
|
+
|
19
|
+
# * method: __init__
|
20
|
+
def __init__(self, feature_repo: FeatureRepository):
|
21
|
+
'''
|
22
|
+
Initialize the feature handler.
|
23
|
+
|
24
|
+
:param feature_repo: The feature repository to use for retrieving features.
|
25
|
+
:type feature_repo: FeatureRepository
|
26
|
+
'''
|
27
|
+
|
28
|
+
# Assign the feature repository.
|
29
|
+
self.feature_repo = feature_repo
|
30
|
+
|
31
|
+
# * method: parse_parameter
|
32
|
+
def parse_parameter(self, parameter: str, request: Request = None) -> str:
|
33
|
+
'''
|
34
|
+
Parse a parameter.
|
35
|
+
|
36
|
+
|
37
|
+
:param parameter: The parameter to parse.
|
38
|
+
:type parameter: str:
|
39
|
+
param request: The request object containing data for parameter parsing.
|
40
|
+
:type request: Request
|
41
|
+
:return: The parsed parameter.
|
42
|
+
:rtype: str
|
43
|
+
'''
|
44
|
+
|
45
|
+
# Parse the parameter if it not a request parameter.
|
46
|
+
if not parameter.startswith('$r.'):
|
47
|
+
return parse_parameter.execute(parameter)
|
48
|
+
|
49
|
+
# Raise an error if the request is and the parameter comes from the request.
|
50
|
+
if not request and parameter.startswith('$r.'):
|
51
|
+
raise_error.execute(
|
52
|
+
'REQUEST_NOT_FOUND',
|
53
|
+
'Request data is not available for parameter parsing.',
|
54
|
+
parameter
|
55
|
+
)
|
56
|
+
|
57
|
+
# Parse the parameter from the request if provided.
|
58
|
+
result = request.data.get(parameter[3:], None)
|
59
|
+
|
60
|
+
# Raise an error if the parameter is not found in the request data.
|
61
|
+
if result is None:
|
62
|
+
raise_error.execute(
|
63
|
+
'PARAMETER_NOT_FOUND',
|
64
|
+
f'Parameter {parameter} not found in request data.',
|
65
|
+
parameter
|
66
|
+
)
|
67
|
+
|
68
|
+
# Return the parsed parameter.
|
69
|
+
return result
|
70
|
+
|
71
|
+
# * method: get_feature
|
72
|
+
def get_feature(self, feature_id: str) -> Feature:
|
73
|
+
'''
|
74
|
+
Get a feature by its ID.
|
75
|
+
|
76
|
+
:param feature_id: The ID of the feature to retrieve.
|
77
|
+
:type feature_id: str
|
78
|
+
:return: The feature model contract.
|
79
|
+
:rtype: Feature
|
80
|
+
'''
|
81
|
+
|
82
|
+
# Retrieve the feature from the repository.
|
83
|
+
feature = self.feature_repo.get(feature_id)
|
84
|
+
|
85
|
+
# Verify the feature is not None.
|
86
|
+
if not feature:
|
87
|
+
raise_error.execute(
|
88
|
+
'FEATURE_NOT_FOUND',
|
89
|
+
f'Feature not found: {feature_id}',
|
90
|
+
feature_id
|
91
|
+
)
|
92
|
+
|
93
|
+
# Return the feature.
|
94
|
+
return feature
|
tiferet/models/app.py
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
# *** imports
|
2
|
+
|
3
|
+
# ** app
|
4
|
+
from .settings import *
|
5
|
+
|
6
|
+
|
7
|
+
# *** models
|
8
|
+
|
9
|
+
# ** model: app_attribute
|
10
|
+
class AppAttribute(ValueObject):
|
11
|
+
|
12
|
+
# * attribute: module_path
|
13
|
+
module_path = StringType(
|
14
|
+
required=True,
|
15
|
+
metadata=dict(
|
16
|
+
description='The module path for the app dependency.'
|
17
|
+
)
|
18
|
+
)
|
19
|
+
|
20
|
+
# * attribute: class_name
|
21
|
+
class_name = StringType(
|
22
|
+
required=True,
|
23
|
+
metadata=dict(
|
24
|
+
description='The class name for the app dependency.'
|
25
|
+
)
|
26
|
+
)
|
27
|
+
|
28
|
+
# * attribute: attribute_id
|
29
|
+
attribute_id = StringType(
|
30
|
+
required=True,
|
31
|
+
metadata=dict(
|
32
|
+
description='The attribute id for the application dependency.'
|
33
|
+
),
|
34
|
+
)
|
35
|
+
|
36
|
+
# * attribute: parameters
|
37
|
+
parameters = DictType(
|
38
|
+
StringType,
|
39
|
+
default={},
|
40
|
+
metadata=dict(
|
41
|
+
description='The parameters for the application dependency.'
|
42
|
+
),
|
43
|
+
)
|
44
|
+
|
45
|
+
|
46
|
+
# ** model: app_interface
|
47
|
+
class AppInterface(Entity):
|
48
|
+
'''
|
49
|
+
The base application interface object.
|
50
|
+
'''
|
51
|
+
|
52
|
+
# * attribute: name
|
53
|
+
name = StringType(
|
54
|
+
required=True,
|
55
|
+
metadata=dict(
|
56
|
+
description='The name of the application interface.'
|
57
|
+
),
|
58
|
+
)
|
59
|
+
|
60
|
+
# * attribute: module_path
|
61
|
+
module_path = StringType(
|
62
|
+
required=True,
|
63
|
+
metadata=dict(
|
64
|
+
description='The module path for the application instance context.'
|
65
|
+
),
|
66
|
+
)
|
67
|
+
|
68
|
+
# * attribute: class_name
|
69
|
+
class_name = StringType(
|
70
|
+
required=True,
|
71
|
+
metadata=dict(
|
72
|
+
description='The class name for the application instance context.'
|
73
|
+
),
|
74
|
+
)
|
75
|
+
|
76
|
+
# attribute: feature_flag
|
77
|
+
feature_flag = StringType(
|
78
|
+
default='default',
|
79
|
+
metadata=dict(
|
80
|
+
description='The feature flag.'
|
81
|
+
),
|
82
|
+
)
|
83
|
+
|
84
|
+
# attribute: data_flag
|
85
|
+
data_flag = StringType(
|
86
|
+
default='default',
|
87
|
+
metadata=dict(
|
88
|
+
description='The data flag.'
|
89
|
+
),
|
90
|
+
)
|
91
|
+
|
92
|
+
# * attribute: attributes
|
93
|
+
attributes = ListType(
|
94
|
+
ModelType(AppAttribute),
|
95
|
+
required=True,
|
96
|
+
default=[],
|
97
|
+
metadata=dict(
|
98
|
+
description='The application instance attributes.'
|
99
|
+
),
|
100
|
+
)
|
101
|
+
|
102
|
+
# * attribute: constants
|
103
|
+
constants = DictType(
|
104
|
+
StringType,
|
105
|
+
default={},
|
106
|
+
metadata=dict(
|
107
|
+
description='The application dependency constants.'
|
108
|
+
),
|
109
|
+
)
|
110
|
+
|
111
|
+
# * method: add_attribute
|
112
|
+
def add_attribute(self, module_path: str, class_name: str, attribute_id: str):
|
113
|
+
'''
|
114
|
+
Add a dependency attribute to the app interface.
|
115
|
+
|
116
|
+
:param module_path: The module path for the app dependency attribute.
|
117
|
+
:type module_path: str
|
118
|
+
:param class_name: The class name for the app dependency attribute.
|
119
|
+
:type class_name: str
|
120
|
+
:param attribute_id: The id for the app dependency attribute.
|
121
|
+
:type attribute_id: str
|
122
|
+
:return: The added dependency.
|
123
|
+
:rtype: AppDependency
|
124
|
+
'''
|
125
|
+
|
126
|
+
# Create a new AppDependency object.
|
127
|
+
dependency = ValueObject.new(
|
128
|
+
AppAttribute,
|
129
|
+
module_path=module_path,
|
130
|
+
class_name=class_name,
|
131
|
+
attribute_id=attribute_id
|
132
|
+
)
|
133
|
+
|
134
|
+
# Add the dependency to the list of dependencies.
|
135
|
+
self.attributes.append(dependency)
|
136
|
+
|
137
|
+
# * method: get_attribute
|
138
|
+
def get_attribute(self, attribute_id: str) -> AppAttribute:
|
139
|
+
'''
|
140
|
+
Get the dependency attribute by attribute id.
|
141
|
+
|
142
|
+
:param attribute_id: The attribute id of the dependency attribute.
|
143
|
+
:type attribute_id: str
|
144
|
+
:return: The dependency attribute.
|
145
|
+
:rtype: AppAttribute
|
146
|
+
'''
|
147
|
+
|
148
|
+
# Get the dependency attribute by attribute id.
|
149
|
+
return next((attr for attr in self.attributes if attr.attribute_id == attribute_id), None)
|
150
|
+
|