tiferet 1.0.0a8__py3-none-any.whl → 1.0.0a10__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 CHANGED
@@ -1 +1,5 @@
1
- from .contexts import *
1
+ # *** imports
2
+
3
+ # ** app
4
+ from .contexts import *
5
+ from .domain import *
tiferet/clients/yaml.py CHANGED
@@ -77,16 +77,25 @@ def save(yaml_file: str, data: dict, data_save_path: str = None):
77
77
 
78
78
  # If the new yaml data does not exist, create it from the yaml data.
79
79
  except TypeError:
80
- new_yaml_data = yaml_data[fragment]
81
- continue
82
-
83
- # If the fragment does not exist on
80
+ try:
81
+ new_yaml_data = yaml_data[fragment]
82
+ continue
83
+
84
+ # If the fragment does not exist, create it.
85
+ except KeyError:
86
+ new_yaml_data = yaml_data[fragment] = {}
87
+
88
+ # If the fragment does not exist, create it.
84
89
  except KeyError:
85
90
  new_yaml_data[fragment] = {}
86
91
  new_yaml_data = new_yaml_data[fragment]
87
92
 
88
93
  # Update the yaml data.
89
- new_yaml_data[save_path_list[-1]] = data
94
+ try:
95
+ new_yaml_data[save_path_list[-1]] = data
96
+ # if there is a type error because the new yaml data is None, update the yaml data directly.
97
+ except TypeError:
98
+ yaml_data[save_path_list[-1]] = data
90
99
 
91
100
  # Save the updated yaml data.
92
101
  with open(yaml_file, 'w') as file:
@@ -1,4 +1,8 @@
1
+ # *** imports
2
+
3
+ # ** app
1
4
  from .app import AppInterfaceContext
2
- from .env import EnvironmentContext
3
- from .request import RequestContext
4
- from .error import ErrorContext
5
+ from .container import ContainerContext
6
+ from .error import ErrorContext
7
+ from .feature import FeatureContext
8
+ from .request import RequestContext
tiferet/contexts/app.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # *** imports
2
2
 
3
3
  # ** core
4
- from typing import Any
4
+ from typing import Any, Tuple
5
5
 
6
6
  # ** app
7
7
  from .request import RequestContext
@@ -70,13 +70,13 @@ class AppInterfaceContext(Model):
70
70
  # Initialize the model.
71
71
  super().__init__(dict(
72
72
  interface_id=interface_id,
73
- name=app_name,
74
- features=feature_context,
75
- errors=error_context
73
+ name=app_name
76
74
  ))
75
+ self.features = feature_context
76
+ self.errors = error_context
77
77
 
78
78
  # * method: parse_request
79
- def parse_request(self, request: Any, **kwargs) -> RequestContext:
79
+ def parse_request(self, request: Any, **kwargs) -> Tuple[RequestContext, dict]:
80
80
  '''
81
81
  Parse the incoming request.
82
82
 
@@ -89,7 +89,7 @@ class AppInterfaceContext(Model):
89
89
  '''
90
90
 
91
91
  # Parse request.
92
- return request
92
+ return request, kwargs
93
93
 
94
94
  # * method: execute_feature
95
95
  def execute_feature(self, request: RequestContext, **kwargs):
@@ -118,7 +118,7 @@ class AppInterfaceContext(Model):
118
118
  import json
119
119
 
120
120
  # Return the response.
121
- return json.loads(request.result)
121
+ return json.loads(request.result) if request.result else ''
122
122
 
123
123
  # * method: run
124
124
  def run(self, **kwargs):
@@ -130,15 +130,15 @@ class AppInterfaceContext(Model):
130
130
  '''
131
131
 
132
132
  # Parse request.
133
- request = self.parse_request(**kwargs)
133
+ request, kwargs = self.parse_request(**kwargs)
134
134
 
135
135
  # Execute feature context and return session.
136
136
  # Handle error and return response if triggered.
137
- has_error, message = self.errors.handle_error(lambda: self.execute_feature(request, **kwargs))
138
-
139
- # Handle error if present.
140
- if has_error:
141
- return message
137
+ try:
138
+ self.execute_feature(request, **kwargs)
139
+ except Exception as e:
140
+ print('Error:', e)
141
+ return self.errors.handle_error(e)
142
142
 
143
143
  # Handle response.
144
144
  return self.handle_response(request)
@@ -86,17 +86,21 @@ class ContainerContext(Model):
86
86
 
87
87
  # Add the attributes to the context.
88
88
  for attr in attrs:
89
- attribute: ContainerAttribute = attributes[attr.id]
90
-
89
+
91
90
  # If the attribute already exists, set the dependencies.
92
91
  if attr.id in attributes:
93
92
  for dep in attr.dependencies:
94
- attribute.set_dependency(dep)
93
+ attr.set_dependency(dep)
95
94
  continue
96
95
 
97
96
  # Otherwise, add the attribute.
98
97
  attributes[attr.id] = attr
99
98
 
99
+ # Add any parameters as constants.
100
+ for dep in attr.dependencies:
101
+ for key in dep.parameters:
102
+ consts[key] = dep.parameters[key]
103
+
100
104
  # Add the constants and attributes to the context.
101
105
  super().__init__(dict(
102
106
  interface_id=interface_id,
@@ -145,7 +149,7 @@ class ContainerContext(Model):
145
149
  dependencies[attribute_id] = self.import_dependency(attribute, flag_map[attribute.type])
146
150
 
147
151
  # Create container.
148
- return container_service.create_injector(self,
152
+ return container_service.create_injector(
149
153
  self.interface_id,
150
154
  **self.constants,
151
155
  **dependencies,
tiferet/contexts/error.py CHANGED
@@ -42,25 +42,24 @@ class ErrorContext(Model):
42
42
  self.validate()
43
43
 
44
44
  # * method: handle_error
45
- def handle_error(self, execute_feature: Any) -> Tuple[bool, Any]:
45
+ def handle_error(self, exception: Exception, lang: str = 'en_US', **kwargs) -> Tuple[bool, Any]:
46
46
  '''
47
47
  Handle an error.
48
48
 
49
- :param func: The execute feature function to handle.
50
- :type func: function
49
+ :param exception: The exception to handle.
50
+ :type exception: Exception
51
+ :param lang: The language to use for the error message.
52
+ :type lang: str
51
53
  :return: Whether the error was handled.
52
54
  :rtype: bool
53
55
  '''
54
56
 
55
57
  # Execute the feature function and handle the errors.
56
- try:
57
- execute_feature()
58
- return (False, None)
59
- except AssertionError as e:
60
- return (True, self.format_error_response(str(e)))
58
+ if isinstance(exception, AssertionError):
59
+ return self.format_error_response(str(exception), lang, **kwargs)
61
60
 
62
61
  # * method: format_error_response
63
- def format_error_response(self, error_message: str, lang: str = 'en_US', **kwargs) -> Any:
62
+ def format_error_response(self, error_message: str, lang: str, **kwargs) -> Any:
64
63
  '''
65
64
  Format the error response.
66
65
 
@@ -45,10 +45,12 @@ class FeatureContext(Model):
45
45
  features = {feature.id: feature for feature in feature_repo.list()}
46
46
 
47
47
  # Set the features and container.
48
+ ## NOTE: There is a bug in the schematics library that does not allow us to initialize
49
+ ## the feature context with the container context directly.
48
50
  super().__init__(dict(
49
51
  features=features,
50
- container=container_context,
51
52
  ))
53
+ self.container = container_context
52
54
 
53
55
  # * method: execute
54
56
  def execute(self, request: RequestContext, debug: bool = False, **kwargs):
@@ -75,16 +77,21 @@ class FeatureContext(Model):
75
77
  result = handler.execute(
76
78
  **request.data,
77
79
  **command.params,
80
+ debug=debug,
78
81
  **kwargs)
82
+
83
+ # Return the result to the session context if return to data is set.
84
+ if command.return_to_data:
85
+ request.data[command.data_key] = result
86
+ continue
87
+
88
+ # Set the result in the request context.
89
+ if result:
90
+ request.set_result(result)
91
+
92
+ # Handle assertion errors if pass on error is not set.
79
93
  except AssertionError as e:
80
94
  if not command.pass_on_error:
81
95
  raise e
82
96
 
83
- # Return the result to the session context if return to data is set.
84
- if command.return_to_data:
85
- request.data[command.data_key] = result
86
- continue
87
-
88
- # Set the result in the request context.
89
- if result:
90
- request.set_result(result)
97
+
@@ -62,9 +62,11 @@ class RequestContext(Model):
62
62
  '''
63
63
 
64
64
  # Set the context attributes.
65
- self.feature_id = feature_id
66
- self.headers = headers
67
- self.data = data
65
+ super().__init__(dict(
66
+ feature_id=feature_id,
67
+ headers=headers,
68
+ data=data
69
+ ))
68
70
 
69
71
  # Validate the context.
70
72
  self.validate()
@@ -92,7 +94,7 @@ class RequestContext(Model):
92
94
  return
93
95
 
94
96
  # If the result is not a list, it must be a dict, so serialize it and set it.
95
- if type(self.result) != list:
97
+ if type(result) != list:
96
98
  self.result = json.dumps(result)
97
99
  return
98
100
 
tiferet/data/__init__.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from typing import List, Dict
2
2
 
3
3
  from .error import *
4
- from .feature import *
4
+ from .feature import *
5
+ from .app import *
tiferet/data/app.py CHANGED
@@ -9,6 +9,50 @@ from ..domain import DataObject
9
9
  from ..domain.app import AppDependency, AppInterface, AppRepositoryConfiguration
10
10
 
11
11
 
12
+ # *** constants
13
+
14
+ # ** constant: app_dependency_default
15
+ FEATURE_CONTEXT_DEFAULT = dict(
16
+ module_path='tiferet.contexts.feature',
17
+ class_name='FeatureContext',
18
+ )
19
+
20
+ # * constant: app_dependency_default
21
+ CONTAINER_CONTEXT_DEFAULT = dict(
22
+ module_path='tiferet.contexts.container',
23
+ class_name='ContainerContext',
24
+ )
25
+
26
+ ERROR_CONTEXT_DEFAULT = dict(
27
+ module_path='tiferet.contexts.error',
28
+ class_name='ErrorContext',
29
+ )
30
+
31
+ FEATURE_REPO_DEFAULT = dict(
32
+ module_path='tiferet.repos.feature',
33
+ class_name='YamlProxy',
34
+ )
35
+
36
+ CONTAINER_REPO_DEFAULT = dict(
37
+ module_path='tiferet.repos.container',
38
+ class_name='YamlProxy',
39
+ )
40
+
41
+ ERROR_REPO_DEFAULT = dict(
42
+ module_path='tiferet.repos.error',
43
+ class_name='YamlProxy',
44
+ )
45
+
46
+ # ** constant: context_list_default
47
+ CONTEXT_LIST_DEFAULT = {
48
+ 'feature_context': FEATURE_CONTEXT_DEFAULT,
49
+ 'container_context': CONTAINER_CONTEXT_DEFAULT,
50
+ 'error_context': ERROR_CONTEXT_DEFAULT,
51
+ 'feature_repo': FEATURE_REPO_DEFAULT,
52
+ 'container_repo': CONTAINER_REPO_DEFAULT,
53
+ 'error_repo': ERROR_REPO_DEFAULT,
54
+ }
55
+
12
56
  # *** data
13
57
 
14
58
  # ** data: app_dependency_yaml_data
@@ -34,9 +78,27 @@ class AppDependencyYamlData(AppDependency, DataObject):
34
78
  'to_data.yaml': DataObject.deny('attribute_id')
35
79
  }
36
80
 
81
+ # * method: from_data
82
+ @staticmethod
83
+ def from_data(**kwargs) -> 'AppDependencyYamlData':
84
+ '''
85
+ Initializes a new YAML representation of an AppDependency object.
86
+
87
+ :param kwargs: Additional keyword arguments.
88
+ :type kwargs: dict
89
+ :return: A new AppDependencyData object.
90
+ :rtype: AppDependencyData
91
+ '''
92
+
93
+ # Create a new AppDependencyData object.
94
+ return super(AppDependencyYamlData, AppDependencyYamlData).from_data(
95
+ AppDependencyYamlData,
96
+ **kwargs
97
+ )
98
+
37
99
  # * method: new
38
100
  @staticmethod
39
- def new(**kwargs) -> 'AppDependencyYamlData':
101
+ def from_data(**kwargs) -> 'AppDependencyYamlData':
40
102
  '''
41
103
  Initializes a new YAML representation of an AppDependency object.
42
104
 
@@ -47,11 +109,11 @@ class AppDependencyYamlData(AppDependency, DataObject):
47
109
  '''
48
110
 
49
111
  # Create a new AppDependencyData object.
50
- return AppDependencyYamlData(
51
- dict(**kwargs),
52
- strict=False,
112
+ return super(AppDependencyYamlData, AppDependencyYamlData).from_data(
113
+ AppDependencyYamlData,
114
+ **kwargs
53
115
  )
54
-
116
+
55
117
  # * method: map
56
118
  def map(self, **kwargs) -> AppDependency:
57
119
  '''
@@ -67,7 +129,7 @@ class AppDependencyYamlData(AppDependency, DataObject):
67
129
 
68
130
  # Map the app dependency data.
69
131
  return super().map(AppDependency, **kwargs)
70
-
132
+
71
133
 
72
134
  # ** data: app_interface_yaml_data
73
135
  class AppInterfaceYamlData(AppInterface, DataObject):
@@ -82,7 +144,7 @@ class AppInterfaceYamlData(AppInterface, DataObject):
82
144
  serialize_when_none = False
83
145
  roles = {
84
146
  'to_model': DataObject.deny('app_context', 'container_context', 'feature_context', 'error_context', 'feature_repo', 'container_repo', 'error_repo'),
85
- 'to_data.yaml': DataObject.deny('id')
147
+ 'to_data': DataObject.deny('id')
86
148
  }
87
149
 
88
150
  # attribute: app_context
@@ -98,11 +160,6 @@ class AppInterfaceYamlData(AppInterface, DataObject):
98
160
  feature_context = ModelType(
99
161
  AppDependencyYamlData,
100
162
  required=True,
101
- default=AppDependencyYamlData.new(
102
- attribute_id='feature_context',
103
- module_path='tiferet.contexts.feature',
104
- class_name='FeatureContext',
105
- ),
106
163
  metadata=dict(
107
164
  description='The feature context dependency.'
108
165
  ),
@@ -112,11 +169,6 @@ class AppInterfaceYamlData(AppInterface, DataObject):
112
169
  container_context = ModelType(
113
170
  AppDependencyYamlData,
114
171
  required=True,
115
- default=AppDependencyYamlData.new(
116
- attribute_id='container_context',
117
- module_path='tiferet.contexts.container',
118
- class_name='ContainerContext',
119
- ),
120
172
  metadata=dict(
121
173
  description='The container context dependency.'
122
174
  ),
@@ -126,11 +178,6 @@ class AppInterfaceYamlData(AppInterface, DataObject):
126
178
  error_context = ModelType(
127
179
  AppDependencyYamlData,
128
180
  required=True,
129
- default=AppDependencyYamlData.new(
130
- attribute_id='error_context',
131
- module_path='tiferet.contexts.error',
132
- class_name='ErrorContext',
133
- ),
134
181
  metadata=dict(
135
182
  description='The error context dependency.'
136
183
  ),
@@ -140,11 +187,6 @@ class AppInterfaceYamlData(AppInterface, DataObject):
140
187
  feature_repo = ModelType(
141
188
  AppDependencyYamlData,
142
189
  required=True,
143
- default=AppDependencyYamlData.new(
144
- attribute_id='feature_repo',
145
- module_path='tiferet.repos.feature',
146
- class_name='YamlProxy',
147
- ),
148
190
  metadata=dict(
149
191
  description='The feature repository dependency.'
150
192
  ),
@@ -154,11 +196,6 @@ class AppInterfaceYamlData(AppInterface, DataObject):
154
196
  container_repo = ModelType(
155
197
  AppDependencyYamlData,
156
198
  required=True,
157
- default=AppDependencyYamlData.new(
158
- attribute_id='container_repo',
159
- module_path='tiferet.repos.container',
160
- class_name='YamlProxy',
161
- ),
162
199
  metadata=dict(
163
200
  description='The container repository dependency.'
164
201
  ),
@@ -168,11 +205,6 @@ class AppInterfaceYamlData(AppInterface, DataObject):
168
205
  error_repo = ModelType(
169
206
  AppDependencyYamlData,
170
207
  required=True,
171
- default=AppDependencyYamlData.new(
172
- attribute_id='error_repo',
173
- module_path='tiferet.repos.error',
174
- class_name='YamlProxy',
175
- ),
176
208
  metadata=dict(
177
209
  description='The error repository dependency.'
178
210
  ),
@@ -180,14 +212,8 @@ class AppInterfaceYamlData(AppInterface, DataObject):
180
212
 
181
213
  # * method: new
182
214
  @staticmethod
183
- def new(app_context: Dict[str, str],
184
- container_context: Dict[str, str] = None,
185
- feature_context: Dict[str, str] = None,
186
- error_context: Dict[str, str] = None,
187
- feature_repo: Dict[str, str] = None,
188
- container_repo: Dict[str, str] = None,
189
- error_repo: Dict[str, str] = None,
190
- **kwargs) -> 'AppInterfaceYamlData':
215
+ def from_data(app_context: Dict[str, str],
216
+ **kwargs) -> 'AppInterfaceYamlData':
191
217
  '''
192
218
  Initializes a new YAML representation of an AppInterface object.
193
219
 
@@ -197,34 +223,36 @@ class AppInterfaceYamlData(AppInterface, DataObject):
197
223
  :rtype: AppInterfaceData
198
224
  '''
199
225
 
200
- # Format the dependencies.
201
- dependencies = {}
202
- if app_context:
203
- dependencies['app_context'] = AppDependencyYamlData.new(attribute_id='app_context', **app_context)
204
- if container_context:
205
- dependencies['container_context'] = AppDependencyYamlData.new(attribute_id='container_context', **container_context)
206
- if feature_context:
207
- dependencies['feature_context'] = AppDependencyYamlData.new(attribute_id='feature_context', **feature_context)
208
- if error_context:
209
- dependencies['error_context'] = AppDependencyYamlData.new(attribute_id='error_context', **error_context)
210
- if feature_repo:
211
- dependencies['feature_repo'] = AppDependencyYamlData.new(attribute_id='feature_repo', **feature_repo)
212
- if container_repo:
213
- dependencies['container_repo'] = AppDependencyYamlData.new(attribute_id='container_repo', **container_repo)
214
- if error_repo:
215
- dependencies['error_repo'] = AppDependencyYamlData.new(attribute_id='error_repo', **error_repo)
226
+ # Add the app context to the dependencies.
227
+ dependencies = dict(
228
+ app_context=AppDependencyYamlData.from_data(
229
+ attribute_id='app_context',
230
+ **app_context
231
+ )
232
+ )
233
+
234
+ # Going through the default dependencies...
235
+ for key, value in CONTEXT_LIST_DEFAULT.items():
236
+
237
+ # If the key is in the kwargs, add it and continue.
238
+ if key in kwargs:
239
+ dependencies[key] = AppDependencyYamlData.from_data(
240
+ attribute_id=key,
241
+ **kwargs.pop(key)) # Pop the key to avoid duplication.
242
+ continue
243
+
244
+ # Otherwise, add the default value.
245
+ dependencies[key] = AppDependencyYamlData.from_data(
246
+ attribute_id=key,
247
+ **value)
216
248
 
217
249
  # Create a new AppInterfaceData object.
218
- data = AppInterfaceYamlData(dict(
250
+ return super(AppInterfaceYamlData, AppInterfaceYamlData).from_data(
251
+ AppInterfaceYamlData,
219
252
  **dependencies,
220
- **kwargs),
221
- strict=False,
253
+ **kwargs
222
254
  )
223
255
 
224
- # Validate and return the new AppInterfaceData object.
225
- data.validate()
226
- return data
227
-
228
256
  # * method: map
229
257
  def map(self, **kwargs) -> AppInterface:
230
258
  '''
@@ -250,15 +278,15 @@ class AppInterfaceYamlData(AppInterface, DataObject):
250
278
  ]
251
279
 
252
280
  # Map the app interface data.
253
- return super().map(AppInterface,
254
- dependencies=dependencies,
255
- **self.to_primitive('to_model'),
281
+ return super().map(AppInterface,
282
+ dependencies=dependencies,
283
+ **self.to_primitive('to_model'),
256
284
  **kwargs
257
285
  )
258
286
 
259
287
 
260
288
  # ** data: app_repository_configuration_yaml_data
261
- class AppRepositoryConfigurationYamlData(DataObject):
289
+ class AppRepositoryConfigurationYamlData(DataObject, AppRepositoryConfiguration):
262
290
  '''
263
291
  A YAML data representation of an app repository configuration object.
264
292
  '''
@@ -270,12 +298,12 @@ class AppRepositoryConfigurationYamlData(DataObject):
270
298
  serialize_when_none = False
271
299
  roles = {
272
300
  'to_model': DataObject.allow(),
273
- 'to_data.yaml': DataObject.allow()
301
+ 'to_data': DataObject.allow()
274
302
  }
275
303
 
276
304
  # * method: new
277
305
  @staticmethod
278
- def new(**kwargs) -> 'AppRepositoryConfigurationYamlData':
306
+ def from_data(**kwargs) -> 'AppRepositoryConfigurationYamlData':
279
307
  '''
280
308
  Initializes a new YAML representation of an AppRepositoryConfiguration object.
281
309
 
@@ -286,12 +314,11 @@ class AppRepositoryConfigurationYamlData(DataObject):
286
314
  '''
287
315
 
288
316
  # Create a new AppRepositoryConfigurationData object.
289
- return AppRepositoryConfigurationYamlData(
290
- super(AppRepositoryConfigurationYamlData, AppRepositoryConfigurationYamlData).new(
291
- **kwargs
292
- )
317
+ return super(AppRepositoryConfigurationYamlData, AppRepositoryConfigurationYamlData).from_data(
318
+ AppRepositoryConfigurationYamlData,
319
+ **kwargs
293
320
  )
294
-
321
+
295
322
  # * method: map
296
323
  def map(self, **kwargs) -> AppRepositoryConfiguration:
297
324
  '''
@@ -306,4 +333,4 @@ class AppRepositoryConfigurationYamlData(DataObject):
306
333
  '''
307
334
 
308
335
  # Map the app repository configuration data.
309
- return super().map(AppRepositoryConfiguration, **kwargs)
336
+ return super().map(AppRepositoryConfiguration, **kwargs)