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.
Files changed (59) hide show
  1. tiferet/__init__.py +3 -2
  2. tiferet/commands/__init__.py +6 -0
  3. tiferet/commands/app.py +102 -0
  4. tiferet/commands/core.py +124 -0
  5. tiferet/commands/dependencies.py +76 -0
  6. tiferet/commands/settings.py +101 -0
  7. tiferet/configs/__init__.py +3 -67
  8. tiferet/configs/error.py +48 -0
  9. tiferet/configs/settings.py +37 -0
  10. tiferet/contexts/__init__.py +0 -8
  11. tiferet/contexts/app.py +215 -182
  12. tiferet/contexts/cache.py +76 -0
  13. tiferet/contexts/container.py +92 -190
  14. tiferet/contexts/error.py +78 -80
  15. tiferet/contexts/feature.py +122 -83
  16. tiferet/contracts/__init__.py +4 -0
  17. tiferet/contracts/app.py +92 -0
  18. tiferet/contracts/cache.py +70 -0
  19. tiferet/contracts/container.py +147 -0
  20. tiferet/contracts/error.py +177 -0
  21. tiferet/contracts/feature.py +159 -0
  22. tiferet/contracts/settings.py +34 -0
  23. tiferet/data/__init__.py +3 -4
  24. tiferet/data/app.py +71 -208
  25. tiferet/data/container.py +52 -38
  26. tiferet/data/error.py +15 -24
  27. tiferet/data/feature.py +27 -8
  28. tiferet/{domain/core.py → data/settings.py} +36 -96
  29. tiferet/handlers/__init__.py +0 -0
  30. tiferet/handlers/container.py +116 -0
  31. tiferet/handlers/error.py +49 -0
  32. tiferet/handlers/feature.py +94 -0
  33. tiferet/models/__init__.py +4 -0
  34. tiferet/models/app.py +150 -0
  35. tiferet/models/container.py +135 -0
  36. tiferet/{domain → models}/error.py +86 -36
  37. tiferet/{domain → models}/feature.py +107 -47
  38. tiferet/models/settings.py +148 -0
  39. tiferet/proxies/__init__.py +0 -0
  40. tiferet/proxies/yaml/__init__.py +0 -0
  41. tiferet/{repos → proxies/yaml}/app.py +13 -41
  42. tiferet/{repos → proxies/yaml}/container.py +26 -56
  43. tiferet/{repos → proxies/yaml}/error.py +11 -70
  44. tiferet/proxies/yaml/feature.py +92 -0
  45. {tiferet-1.0.0a19.dist-info → tiferet-1.0.0b1.dist-info}/METADATA +12 -3
  46. tiferet-1.0.0b1.dist-info/RECORD +51 -0
  47. {tiferet-1.0.0a19.dist-info → tiferet-1.0.0b1.dist-info}/WHEEL +1 -1
  48. tiferet/commands/container.py +0 -54
  49. tiferet/commands/error.py +0 -21
  50. tiferet/commands/feature.py +0 -90
  51. tiferet/contexts/request.py +0 -110
  52. tiferet/domain/__init__.py +0 -5
  53. tiferet/domain/app.py +0 -131
  54. tiferet/domain/container.py +0 -141
  55. tiferet/repos/__init__.py +0 -7
  56. tiferet/repos/feature.py +0 -151
  57. tiferet-1.0.0a19.dist-info/RECORD +0 -35
  58. {tiferet-1.0.0a19.dist-info → tiferet-1.0.0b1.dist-info/licenses}/LICENSE +0 -0
  59. {tiferet-1.0.0a19.dist-info → tiferet-1.0.0b1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,135 @@
1
+ # *** imports
2
+
3
+ # ** app
4
+ from .settings import *
5
+
6
+
7
+ # *** models
8
+
9
+ # ** model: flagged_dependency
10
+ class FlaggedDependency(ValueObject):
11
+ '''
12
+ A flagged container dependency object.
13
+ '''
14
+
15
+ # * attribute: module_path
16
+ module_path = StringType(
17
+ required=True,
18
+ metadata=dict(
19
+ description='The module path.'
20
+ )
21
+ )
22
+
23
+ # * attribute: class_name
24
+ class_name = StringType(
25
+ required=True,
26
+ metadata=dict(
27
+ description='The class name.'
28
+ )
29
+ )
30
+
31
+ # * attribute: flag
32
+ flag = StringType(
33
+ required=True,
34
+ metadata=dict(
35
+ description='The flag for the container dependency.'
36
+ )
37
+ )
38
+
39
+ # * attribute: parameters
40
+ parameters = DictType(
41
+ StringType,
42
+ default={},
43
+ metadata=dict(
44
+ description='The container dependency parameters.'
45
+ )
46
+ )
47
+
48
+
49
+ # ** model: container_attribute
50
+ class ContainerAttribute(Entity):
51
+ '''
52
+ An attribute that defines container injectior behavior.
53
+ '''
54
+
55
+ # * attribute: id
56
+ id = StringType(
57
+ required=True,
58
+ metadata=dict(
59
+ description='The unique identifier for the container attribute.'
60
+ )
61
+ )
62
+
63
+ # * attribute: module_path
64
+ module_path = StringType(
65
+ metadata=dict(
66
+ description='The non-flagged module path for the container attribute.'
67
+ )
68
+ )
69
+
70
+ # * attribute: class_name
71
+ class_name = StringType(
72
+ metadata=dict(
73
+ description='The non-flagged class name for the container attribute.'
74
+ )
75
+ )
76
+
77
+ # * attribute: parameters
78
+ parameters = DictType(
79
+ StringType,
80
+ default={},
81
+ metadata=dict(
82
+ description='The container attribute parameters.'
83
+ )
84
+ )
85
+
86
+ # * attribute: dependencies
87
+ dependencies = ListType(
88
+ ModelType(FlaggedDependency),
89
+ default=[],
90
+ metadata=dict(
91
+ description='The container attribute dependencies.'
92
+ )
93
+ )
94
+
95
+ # * method: get_dependency
96
+ def get_dependency(self, *flags) -> FlaggedDependency:
97
+ '''
98
+ Gets a flagged container dependency by flag.
99
+
100
+ :param flags: The flags for the flagged container dependency.
101
+ :type flags: Tuple[str, ...]
102
+ :return: The flagged container dependency that matches the first provided flag.
103
+ :rtype: FlaggedDependency
104
+ '''
105
+
106
+ # Return the first dependency that matches any of the provided flags.
107
+ # Input flags are assumed ordinal in priority, so the first match is returned.
108
+ for flag in flags:
109
+ match = next(
110
+ (dependency for dependency in self.dependencies if dependency.flag == flag),
111
+ None
112
+ )
113
+ if match:
114
+ return match
115
+
116
+ # Return None if no dependency matches the flags.
117
+ return None
118
+
119
+ # * method: set_dependency
120
+ def set_dependency(self, dependency: FlaggedDependency):
121
+ '''
122
+ Sets a flagged container dependency.
123
+
124
+ :param dependency: The flagged container dependency to set.
125
+ :type dependency: ContainerDependency
126
+ '''
127
+
128
+ # Replace the value of the dependency if a dependency with the same flag exists.
129
+ for index, dep in enumerate(self.dependencies):
130
+ if dep.flag == dependency.flag:
131
+ self.dependencies[index] = dependency
132
+ return
133
+
134
+ # Append the dependency otherwise.
135
+ self.dependencies.append(dependency)
@@ -1,19 +1,22 @@
1
1
  # *** imports
2
2
 
3
3
  # ** core
4
- from ..domain import *
4
+ from typing import List, Any
5
+
6
+ # ** app
7
+ from .settings import *
5
8
 
6
9
 
7
10
  # *** models
8
11
 
9
- # ** model: error_message0
12
+ # ** model: error_message
10
13
  class ErrorMessage(ValueObject):
11
14
  '''
12
15
  An error message object.
13
16
  '''
14
17
 
15
18
  # * attribute: lang
16
- lang = t.StringType(
19
+ lang = StringType(
17
20
  required=True,
18
21
  metadata=dict(
19
22
  description='The language of the error message text.'
@@ -21,30 +24,13 @@ class ErrorMessage(ValueObject):
21
24
  )
22
25
 
23
26
  # * attribute: text
24
- text = t.StringType(
27
+ text = StringType(
25
28
  required=True,
26
29
  metadata=dict(
27
30
  description='The error message text.'
28
31
  )
29
32
  )
30
33
 
31
- # * method: new
32
- @staticmethod
33
- def new(**kwargs) -> 'ErrorMessage':
34
- '''Initializes a new ErrorMessage object.
35
-
36
- :param kwargs: Additional keyword arguments.
37
- :type kwargs: dict
38
- :return: A new ErrorMessage object.
39
- :rtype: ErrorMessage
40
- '''
41
-
42
- # Create and return a new ErrorMessage object.
43
- return super(ErrorMessage, ErrorMessage).new(
44
- ErrorMessage,
45
- **kwargs
46
- )
47
-
48
34
  # * method: format
49
35
  def format(self, *args) -> str:
50
36
  '''
@@ -71,7 +57,7 @@ class Error(Entity):
71
57
  '''
72
58
 
73
59
  # * attribute: name
74
- name = t.StringType(
60
+ name = StringType(
75
61
  required=True,
76
62
  metadata=dict(
77
63
  description='The name of the error.'
@@ -79,15 +65,15 @@ class Error(Entity):
79
65
  )
80
66
 
81
67
  # * attribute: error_code
82
- error_code = t.StringType(
68
+ error_code = StringType(
83
69
  metadata=dict(
84
70
  description='The unique code of the error.'
85
71
  )
86
72
  )
87
73
 
88
74
  # * attribute: message
89
- message = t.ListType(
90
- t.ModelType(ErrorMessage),
75
+ message = ListType(
76
+ ModelType(ErrorMessage),
91
77
  required=True,
92
78
  metadata=dict(
93
79
  description='The error message translations for the error.'
@@ -96,7 +82,7 @@ class Error(Entity):
96
82
 
97
83
  # * method: new
98
84
  @staticmethod
99
- def new(name: str, id: str = None, error_code: str = None, **kwargs) -> 'Error':
85
+ def new(name: str, id: str = None, error_code: str = None, message: List[ErrorMessage | Any] = [], **kwargs) -> 'Error':
100
86
  '''Initializes a new Error object.
101
87
 
102
88
  :param name: The name of the error.
@@ -105,33 +91,42 @@ class Error(Entity):
105
91
  :type id: str
106
92
  :param error_code: The error code for the error.
107
93
  :type error_code: str
94
+ :param message: The error message translations for the error.
95
+ :type message: list
108
96
  :param kwargs: Additional keyword arguments.
109
97
  :type kwargs: dict
110
98
  :return: A new Error object.
111
99
  '''
112
-
113
- # Format name as upper case snake case.
114
- name = name.upper().replace(' ', '_')
115
100
 
116
- # Set Id as the name if not provided.
101
+ # Set Id as the name lower cased if not provided.
117
102
  if not id:
118
- id = name
103
+ id = name.lower().replace(' ', '_')
119
104
 
120
- # Set the error code as the name if not provided.
105
+ # Set the error code as the id upper cased if not provided.
121
106
  if not error_code:
122
- error_code = name
107
+ error_code = id.upper().replace(' ', '_')
108
+
109
+ # Convert any error message dicts to ErrorMessage objects.
110
+ message_objs = []
111
+ for msg in message:
112
+ if isinstance(msg, ErrorMessage):
113
+ message_objs.append(msg)
114
+ elif not isinstance(msg, ErrorMessage) and isinstance(msg, dict):
115
+ message_objs.append(ValueObject.new(ErrorMessage, **msg))
116
+
123
117
 
124
118
  # Create and return a new Error object.
125
- return super(Error, Error).new(
119
+ return Entity.new(
126
120
  Error,
127
121
  id=id,
128
122
  name=name,
129
123
  error_code=error_code,
124
+ message=message_objs,
130
125
  **kwargs
131
126
  )
132
127
 
133
- # * method: format
134
- def format(self, lang: str = 'en_US', *args) -> str:
128
+ # * method: format_message
129
+ def format_message(self, lang: str = 'en_US', *args) -> str:
135
130
  '''
136
131
  Formats the error message text for the specified language.
137
132
 
@@ -152,3 +147,58 @@ class Error(Entity):
152
147
 
153
148
  # Format the error message text.
154
149
  return msg.format(*args)
150
+
151
+ # * method: format_response
152
+ def format_response(self, lang: str = 'en_US', *args, **kwargs) -> Any:
153
+ '''
154
+ Formats the error response for the specified language.
155
+
156
+ :param lang: The language of the error message text.
157
+ :type lang: str
158
+ :param args: The format arguments for the error message text.
159
+ :type args: tuple
160
+ :param kwargs: Additional keyword arguments.
161
+ :type kwargs: dict
162
+ :return: The formatted error response.
163
+ :rtype: dict
164
+ '''
165
+
166
+ # Format the error message text.
167
+ error_message = self.format_message(lang, *args)
168
+
169
+ # If the error message is not found, return no response.
170
+ if not error_message:
171
+ return None
172
+
173
+ # Return the formatted error response.
174
+ return dict(
175
+ error_code=self.error_code,
176
+ message=error_message,
177
+ **kwargs
178
+ )
179
+
180
+ # * method: set_message
181
+ def set_message(self, lang: str, text: str):
182
+ '''
183
+ Sets the error message text for the specified language.
184
+
185
+ :param lang: The language of the error message text.
186
+ :type lang: str
187
+ :param text: The error message text.
188
+ :type text: str
189
+ '''
190
+
191
+ # Check if the message already exists for the language.
192
+ for msg in self.message:
193
+ if msg.lang == lang:
194
+ msg.text = text
195
+ return
196
+
197
+ # If not, create a new ErrorMessage object and add it to the message list.
198
+ self.message.append(
199
+ ValueObject.new(
200
+ ErrorMessage,
201
+ lang=lang,
202
+ text=text
203
+ )
204
+ )
@@ -1,11 +1,88 @@
1
1
  # *** imports
2
2
 
3
+ # ** core
4
+ from typing import Any
5
+ import json
6
+
3
7
  # ** app
4
- from ..domain import *
8
+ from .settings import *
5
9
 
6
10
 
7
11
  # *** models
8
12
 
13
+ # ** model: request
14
+ class Request(ValueObject):
15
+ '''
16
+ A request object.
17
+ '''
18
+
19
+ # * attribute: headers
20
+ headers = DictType(
21
+ StringType(),
22
+ metadata=dict(
23
+ description='The request headers.'
24
+ )
25
+ )
26
+
27
+ # * attribute: data
28
+ data = DictType(
29
+ StringType(),
30
+ metadata=dict(
31
+ description='The request data.'
32
+ )
33
+ )
34
+
35
+ # * attribute: result
36
+ result = StringType(
37
+ metadata=dict(
38
+ description='The request result.'
39
+ )
40
+ )
41
+
42
+ # * method: set_result
43
+ def set_result(self, result: Any):
44
+ # Set the result as a serialized empty dictionary if it is None.
45
+ if not result:
46
+ self.result = json.dumps({})
47
+ return
48
+
49
+ # If the result is a Model, convert it to a primitive dictionary and serialize it.
50
+ if isinstance(result, ModelObject):
51
+ self.result = json.dumps(result.to_primitive())
52
+ return
53
+
54
+ # If the result is not a list, it must be a dict, so serialize it and set it.
55
+ if type(result) != list:
56
+ self.result = json.dumps(result)
57
+ return
58
+
59
+ # If the result is a list, convert each item to a primitive dictionary.
60
+ result_list = []
61
+ for item in result:
62
+ if isinstance(item, ModelObject):
63
+ result_list.append(item.to_primitive())
64
+ else:
65
+ result_list.append(item)
66
+
67
+ # Serialize the result and set it.
68
+ self.result = json.dumps(result_list)
69
+
70
+ # * method: handle_response
71
+ def handle_response(self, **kwargs) -> Any:
72
+ '''
73
+ Handle the response.
74
+
75
+ :param kwargs: Additional keyword arguments.
76
+ :type kwargs: dict
77
+ :return: The response object.
78
+ :rtype: Any
79
+ '''
80
+
81
+ # Deserialize the result.
82
+ # Return None if the result is None.
83
+ return json.loads(self.result) if self.result else None
84
+
85
+
9
86
  # ** model: feature_command
10
87
  class FeatureCommand(ValueObject):
11
88
  '''
@@ -13,7 +90,7 @@ class FeatureCommand(ValueObject):
13
90
  '''
14
91
 
15
92
  # * attribute: name
16
- name = t.StringType(
93
+ name = StringType(
17
94
  required=True,
18
95
  metadata=dict(
19
96
  description='The name of the feature handler.'
@@ -21,62 +98,44 @@ class FeatureCommand(ValueObject):
21
98
  )
22
99
 
23
100
  # * attribute: attribute_id
24
- attribute_id = t.StringType(
101
+ attribute_id = StringType(
25
102
  required=True,
26
103
  metadata=dict(
27
104
  description='The container attribute ID for the feature command.'
28
105
  )
29
106
  )
30
107
 
31
- # * attribute: params
32
- params = t.DictType(
33
- t.StringType(),
108
+ # * attribute: parameters
109
+ parameters = DictType(
110
+ StringType(),
34
111
  default={},
35
112
  metadata=dict(
36
113
  description='The custom parameters for the feature handler.'
37
114
  )
38
115
  )
39
116
 
40
- # * attribute: return_to_data
41
- return_to_data = t.BooleanType(
117
+ # * attribute: return_to_data (obsolete)
118
+ return_to_data = BooleanType(
119
+ default=False,
42
120
  metadata=dict(
43
121
  description='Whether to return the feature command result to the feature data context.'
44
122
  )
45
123
  )
46
124
 
47
125
  # * attribute: data_key
48
- data_key = t.StringType(
126
+ data_key = StringType(
49
127
  metadata=dict(
50
128
  description='The data key to store the feature command result in if Return to Data is True.'
51
129
  )
52
130
  )
53
131
 
54
132
  # * attribute: pass_on_error
55
- pass_on_error = t.BooleanType(
133
+ pass_on_error = BooleanType(
56
134
  metadata=dict(
57
135
  description='Whether to pass on the error if the feature handler fails.'
58
136
  )
59
137
  )
60
138
 
61
- # * method: new
62
- @staticmethod
63
- def new(**kwargs) -> 'FeatureCommand':
64
- '''Initializes a new FeatureCommand object.
65
-
66
- :param kwargs: Additional keyword arguments.
67
- :type kwargs: dict
68
- :return: A new FeatureCommand object.
69
- '''
70
-
71
- # Create a new FeatureCommand object.
72
- obj = FeatureCommand(dict(
73
- **kwargs
74
- ), strict=False)
75
-
76
- # Validate and return the new FeatureCommand object.
77
- obj.validate()
78
- return obj
79
-
80
139
 
81
140
  # ** model: feature
82
141
  class Feature(Entity):
@@ -85,7 +144,7 @@ class Feature(Entity):
85
144
  '''
86
145
 
87
146
  # * attribute: name
88
- name = t.StringType(
147
+ name = StringType(
89
148
  required=True,
90
149
  metadata=dict(
91
150
  description='The name of the feature.'
@@ -93,23 +152,23 @@ class Feature(Entity):
93
152
  )
94
153
 
95
154
  # * attribute: group_id
96
- group_id = t.StringType(
155
+ group_id = StringType(
97
156
  required=True,
98
157
  metadata=dict(
99
158
  description='The context group identifier for the feature.'
100
159
  )
101
160
  )
102
161
 
103
- # * attribute: description
104
- description = t.StringType(
162
+ feature_key = StringType(
163
+ required=True,
105
164
  metadata=dict(
106
- description='The description of the feature.'
165
+ description='The key of the feature.'
107
166
  )
108
167
  )
109
168
 
110
169
  # * attribute: commands
111
- commands = t.ListType(
112
- t.ModelType(FeatureCommand),
170
+ commands = ListType(
171
+ ModelType(FeatureCommand),
113
172
  default=[],
114
173
  metadata=dict(
115
174
  description='The command handler workflow for the feature.'
@@ -117,8 +176,8 @@ class Feature(Entity):
117
176
  )
118
177
 
119
178
  # * attribute: log_params
120
- log_params = t.DictType(
121
- t.StringType(),
179
+ log_params = DictType(
180
+ StringType(),
122
181
  default={},
123
182
  metadata=dict(
124
183
  description='The parameters to log for the feature.'
@@ -158,27 +217,28 @@ class Feature(Entity):
158
217
  description = name
159
218
 
160
219
  # Create and return a new Feature object.
161
- return super(Feature, Feature).new(
220
+ return Entity.new(
162
221
  Feature,
163
222
  id=id,
164
223
  name=name,
165
224
  group_id=group_id,
225
+ feature_key=feature_key,
166
226
  description=description,
167
227
  **kwargs
168
228
  )
169
229
 
170
- # * method: add_handler
171
- def add_handler(self, handler: FeatureCommand, position: int = None):
172
- '''Adds a handler to the feature.
230
+ # * method: add_command
231
+ def add_command(self, command: FeatureCommand, position: int = None):
232
+ '''Adds a service command to the feature.
173
233
 
174
- :param handler: The handler to add.
175
- :type handler: FeatureCommand
234
+ :param command: The service command to add.
235
+ :type command: FeatureCommand
176
236
  :param position: The position to add the handler at.
177
237
  :type position: int
178
238
  '''
179
239
 
180
- # Add the handler to the feature.
240
+ # Add the feature command to the feature.
181
241
  if position is not None:
182
- self.commands.insert(position, handler)
242
+ self.commands.insert(position, command)
183
243
  else:
184
- self.commands.append(handler)
244
+ self.commands.append(command)