tiferet 1.0.0a0__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.
- app/__init__.py +0 -0
- app/clients/__init__.py +0 -0
- app/clients/yaml.py +93 -0
- app/commands/__init__.py +0 -0
- app/commands/container.py +54 -0
- app/commands/error.py +21 -0
- app/commands/feature.py +90 -0
- app/configs/__init__.py +69 -0
- app/configs/app.py +16 -0
- app/configs/container.py +91 -0
- app/contexts/__init__.py +2 -0
- app/contexts/app.py +130 -0
- app/contexts/container.py +167 -0
- app/contexts/env.py +109 -0
- app/contexts/error.py +95 -0
- app/contexts/feature.py +79 -0
- app/contexts/request.py +108 -0
- app/data/__init__.py +4 -0
- app/data/app.py +227 -0
- app/data/container.py +179 -0
- app/data/error.py +99 -0
- app/data/feature.py +132 -0
- app/domain/__init__.py +5 -0
- app/domain/app.py +330 -0
- app/domain/container.py +141 -0
- app/domain/core.py +199 -0
- app/domain/error.py +136 -0
- app/domain/feature.py +176 -0
- app/repos/__init__.py +0 -0
- app/repos/app.py +102 -0
- app/repos/container.py +164 -0
- app/repos/error.py +173 -0
- app/repos/feature.py +169 -0
- app/services/__init__.py +4 -0
- app/services/cli.py +186 -0
- app/services/container.py +44 -0
- tiferet-1.0.0a0.dist-info/LICENSE +28 -0
- tiferet-1.0.0a0.dist-info/METADATA +13 -0
- tiferet-1.0.0a0.dist-info/RECORD +41 -0
- tiferet-1.0.0a0.dist-info/WHEEL +5 -0
- tiferet-1.0.0a0.dist-info/top_level.txt +1 -0
app/__init__.py
ADDED
File without changes
|
app/clients/__init__.py
ADDED
File without changes
|
app/clients/yaml.py
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# *** imports
|
2
|
+
|
3
|
+
# ** infra
|
4
|
+
import yaml
|
5
|
+
|
6
|
+
|
7
|
+
# *** functions
|
8
|
+
|
9
|
+
# ** function: load
|
10
|
+
def load(path: str, create_data = lambda data: data, start_node = lambda data: data, **kwargs):
|
11
|
+
'''
|
12
|
+
Load the data from the yaml file.
|
13
|
+
|
14
|
+
:param path: The path to the yaml file.
|
15
|
+
:type path: str
|
16
|
+
:param create_data: The function to create the data.
|
17
|
+
:type create_data: function
|
18
|
+
:param start_node: The function to start the node.
|
19
|
+
:type start_node: function
|
20
|
+
:param kwargs: Additional keyword arguments.
|
21
|
+
:type kwargs: dict
|
22
|
+
:return: The data.
|
23
|
+
:rtype: dict
|
24
|
+
'''
|
25
|
+
|
26
|
+
# Load the data from the yaml file.
|
27
|
+
with open(path, 'r') as file:
|
28
|
+
data = yaml.safe_load(file)
|
29
|
+
|
30
|
+
# Find the start node.
|
31
|
+
try:
|
32
|
+
data = start_node(data)
|
33
|
+
except AttributeError:
|
34
|
+
return None
|
35
|
+
|
36
|
+
# Return the data if it is None.
|
37
|
+
if data == None:
|
38
|
+
return None
|
39
|
+
|
40
|
+
# Create and return the data.
|
41
|
+
return create_data(data, **kwargs)
|
42
|
+
|
43
|
+
|
44
|
+
# ** function: save
|
45
|
+
def save(yaml_file: str, data: dict, data_save_path: str = None):
|
46
|
+
'''
|
47
|
+
Save the data to the yaml file.
|
48
|
+
|
49
|
+
:param yaml_file: The path to the yaml file.
|
50
|
+
:type yaml_file: str
|
51
|
+
:param data: The data to save.
|
52
|
+
:type data: dict
|
53
|
+
:param data_save_path: The path to save the data to.
|
54
|
+
:type data_save_path: str
|
55
|
+
'''
|
56
|
+
|
57
|
+
# Save the data to the yaml file and exit if no save path is provided.
|
58
|
+
if not data_save_path:
|
59
|
+
with open(yaml_file, 'w') as file:
|
60
|
+
yaml.safe_dump(data, file)
|
61
|
+
return
|
62
|
+
|
63
|
+
# Load the yaml data.
|
64
|
+
with open(yaml_file, 'r') as file:
|
65
|
+
yaml_data = yaml.safe_load(file)
|
66
|
+
|
67
|
+
# Get the data save path list.
|
68
|
+
save_path_list = data_save_path.split('/')
|
69
|
+
|
70
|
+
# Update the yaml data.
|
71
|
+
new_yaml_data = None
|
72
|
+
for fragment in save_path_list[:-1]:
|
73
|
+
|
74
|
+
# If the new yaml data exists, update it.
|
75
|
+
try:
|
76
|
+
new_yaml_data = new_yaml_data[fragment]
|
77
|
+
|
78
|
+
# If the new yaml data does not exist, create it from the yaml data.
|
79
|
+
except TypeError:
|
80
|
+
new_yaml_data = yaml_data[fragment]
|
81
|
+
continue
|
82
|
+
|
83
|
+
# If the fragment does not exist on
|
84
|
+
except KeyError:
|
85
|
+
new_yaml_data[fragment] = {}
|
86
|
+
new_yaml_data = new_yaml_data[fragment]
|
87
|
+
|
88
|
+
# Update the yaml data.
|
89
|
+
new_yaml_data[save_path_list[-1]] = data
|
90
|
+
|
91
|
+
# Save the updated yaml data.
|
92
|
+
with open(yaml_file, 'w') as file:
|
93
|
+
yaml.safe_dump(yaml_data, file)
|
app/commands/__init__.py
ADDED
File without changes
|
@@ -0,0 +1,54 @@
|
|
1
|
+
from ..repos.container import ContainerRepository
|
2
|
+
from ..domain.container import ContainerAttribute, ContainerDependency
|
3
|
+
from ..services import container as container_service
|
4
|
+
|
5
|
+
|
6
|
+
class SetContainerAttribute(object):
|
7
|
+
'''
|
8
|
+
Command to set a new container attribute
|
9
|
+
'''
|
10
|
+
|
11
|
+
container_repo: ContainerRepository
|
12
|
+
|
13
|
+
def __init__(self, container_repo: ContainerRepository):
|
14
|
+
'''
|
15
|
+
Initialize the command to set a new container attribute.
|
16
|
+
|
17
|
+
:param container_repo: The container repository.
|
18
|
+
:type container_repo: ContainerRepository
|
19
|
+
'''
|
20
|
+
|
21
|
+
self.container_repo = container_repo
|
22
|
+
|
23
|
+
def execute(self, attribute_id: str, type: str, **kwargs):
|
24
|
+
'''
|
25
|
+
Execute the command to set a new container attribute.
|
26
|
+
|
27
|
+
:param attribute_id: The attribute id.
|
28
|
+
:type attribute_id: str
|
29
|
+
:param type: The attribute type.
|
30
|
+
:type type: str
|
31
|
+
:param kwargs: Additional keyword arguments.
|
32
|
+
:type kwargs: dict
|
33
|
+
'''
|
34
|
+
|
35
|
+
# Look up the container attribute.
|
36
|
+
attribute: ContainerAttribute = self.container_repo.get_attribute(attribute_id, type)
|
37
|
+
|
38
|
+
# If not attribute is found, create a new one.
|
39
|
+
if not attribute:
|
40
|
+
attribute = ContainerAttribute.new(
|
41
|
+
id=attribute_id,
|
42
|
+
type=type,
|
43
|
+
dependencies=[ContainerDependency.new(**kwargs)])
|
44
|
+
|
45
|
+
# Otherwise, create the container depenedency and add it to the attribute.
|
46
|
+
else:
|
47
|
+
dependency = ContainerDependency.new(**kwargs)
|
48
|
+
attribute.set_dependency(dependency)
|
49
|
+
|
50
|
+
# Save the container attribute.
|
51
|
+
self.container_repo.save_attribute(attribute=attribute)
|
52
|
+
|
53
|
+
# Return the new container attribute.
|
54
|
+
return attribute
|
app/commands/error.py
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
from ..domain.error import Error
|
2
|
+
from ..repos.error import ErrorRepository
|
3
|
+
|
4
|
+
class AddNewError(object):
|
5
|
+
|
6
|
+
def __init__(self, error_repo: ErrorRepository):
|
7
|
+
self.error_repo = error_repo
|
8
|
+
|
9
|
+
def execute(self, **kwargs) -> Error:
|
10
|
+
|
11
|
+
# Create a new error.
|
12
|
+
error: Error = Error.new(**kwargs)
|
13
|
+
|
14
|
+
# Assert that the error does not already exist.
|
15
|
+
assert not self.error_repo.exists(error.id), f'ERROR_ALREADY_EXISTS: {error.id}'
|
16
|
+
|
17
|
+
# Save the error.
|
18
|
+
self.error_repo.save(error)
|
19
|
+
|
20
|
+
# Return the new error.
|
21
|
+
return error
|
app/commands/feature.py
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
from ..domain.feature import Feature
|
2
|
+
from ..domain.feature import FeatureHandler
|
3
|
+
from ..repos.feature import FeatureRepository
|
4
|
+
|
5
|
+
|
6
|
+
class AddNewFeature(object):
|
7
|
+
'''
|
8
|
+
Add a new feature.
|
9
|
+
'''
|
10
|
+
|
11
|
+
def __init__(self, feature_repo: FeatureRepository):
|
12
|
+
'''
|
13
|
+
Initialize the command.
|
14
|
+
|
15
|
+
:param feature_repo: The feature repository.
|
16
|
+
:type feature_repo: FeatureRepository
|
17
|
+
'''
|
18
|
+
|
19
|
+
# Set the feature repository.
|
20
|
+
self.feature_repo = feature_repo
|
21
|
+
|
22
|
+
def execute(self, **kwargs) -> Feature:
|
23
|
+
'''
|
24
|
+
Execute the command to add a new feature.
|
25
|
+
|
26
|
+
:param kwargs: The keyword arguments.
|
27
|
+
:type kwargs: dict
|
28
|
+
:return: The new feature.
|
29
|
+
'''
|
30
|
+
|
31
|
+
# Create a new feature.
|
32
|
+
feature = Feature.new(**kwargs)
|
33
|
+
|
34
|
+
# Assert that the feature does not already exist.
|
35
|
+
assert not self.feature_repo.exists(
|
36
|
+
feature.id), f'FEATURE_ALREADY_EXISTS: {feature.id}'
|
37
|
+
|
38
|
+
# Save and return the feature.
|
39
|
+
self.feature_repo.save(feature)
|
40
|
+
return feature
|
41
|
+
|
42
|
+
|
43
|
+
class AddFeatureHandler(object):
|
44
|
+
'''
|
45
|
+
Adds a feature handler to a feature.
|
46
|
+
'''
|
47
|
+
|
48
|
+
def __init__(self, feature_repo: FeatureRepository):
|
49
|
+
'''
|
50
|
+
Initialize the command.
|
51
|
+
|
52
|
+
:param feature_repo: The feature repository.
|
53
|
+
:type feature_repo: FeatureRepository
|
54
|
+
'''
|
55
|
+
|
56
|
+
# Set the feature repository.
|
57
|
+
self.feature_repo = feature_repo
|
58
|
+
|
59
|
+
def execute(self, feature_id: str, position: int = None, **kwargs):
|
60
|
+
'''
|
61
|
+
Execute the command to add a feature handler to a feature.
|
62
|
+
|
63
|
+
:param feature_id: The feature ID.
|
64
|
+
:type feature_id: str
|
65
|
+
:param position: The position of the handler.
|
66
|
+
:type position: int
|
67
|
+
:param kwargs: Additional keyword arguments.
|
68
|
+
:type kwargs: dict
|
69
|
+
:return: The updated feature.
|
70
|
+
:rtype: Feature
|
71
|
+
'''
|
72
|
+
|
73
|
+
# Create a new feature handler instance.
|
74
|
+
handler = FeatureHandler.new(**kwargs)
|
75
|
+
|
76
|
+
# Get the feature using the feature ID.
|
77
|
+
feature = self.feature_repo.get(feature_id)
|
78
|
+
|
79
|
+
# Assert that the feature was successfully found.
|
80
|
+
assert feature is not None, f'FEATURE_NOT_FOUND: {feature_id}'
|
81
|
+
|
82
|
+
# Add the feature handler to the feature.
|
83
|
+
feature.add_handler(
|
84
|
+
handler,
|
85
|
+
position=position
|
86
|
+
)
|
87
|
+
|
88
|
+
# Save and return the feature.
|
89
|
+
self.feature_repo.save(feature)
|
90
|
+
return feature
|
app/configs/__init__.py
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# *** imports
|
2
|
+
|
3
|
+
# ** infra
|
4
|
+
from schematics import types as t
|
5
|
+
|
6
|
+
|
7
|
+
# *** config
|
8
|
+
|
9
|
+
# ** config (class): string_type
|
10
|
+
class StringType(t.StringType):
|
11
|
+
'''
|
12
|
+
A string type.
|
13
|
+
'''
|
14
|
+
|
15
|
+
pass
|
16
|
+
|
17
|
+
|
18
|
+
# ** config (class): integer_type
|
19
|
+
class IntegerType(t.IntType):
|
20
|
+
'''
|
21
|
+
An integer type.
|
22
|
+
'''
|
23
|
+
|
24
|
+
pass
|
25
|
+
|
26
|
+
|
27
|
+
# ** config (class): float_type
|
28
|
+
class FloatType(t.FloatType):
|
29
|
+
'''
|
30
|
+
A float type.
|
31
|
+
'''
|
32
|
+
|
33
|
+
pass
|
34
|
+
|
35
|
+
|
36
|
+
# ** config (class): boolean_type
|
37
|
+
class BooleanType(t.BooleanType):
|
38
|
+
'''
|
39
|
+
A boolean type.
|
40
|
+
'''
|
41
|
+
|
42
|
+
pass
|
43
|
+
|
44
|
+
|
45
|
+
# ** config (class): list_type
|
46
|
+
class ListType(t.ListType):
|
47
|
+
'''
|
48
|
+
A list type.
|
49
|
+
'''
|
50
|
+
|
51
|
+
pass
|
52
|
+
|
53
|
+
|
54
|
+
# ** config (class): dict_type
|
55
|
+
class DictType(t.DictType):
|
56
|
+
'''
|
57
|
+
A dictionary type.
|
58
|
+
'''
|
59
|
+
|
60
|
+
pass
|
61
|
+
|
62
|
+
|
63
|
+
# ** config (class): model_type
|
64
|
+
class ModelType(t.ModelType):
|
65
|
+
'''
|
66
|
+
A model type.
|
67
|
+
'''
|
68
|
+
|
69
|
+
pass
|
app/configs/app.py
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# *** imports
|
2
|
+
|
3
|
+
# ** app
|
4
|
+
from ..domain.app import AppRepositoryConfiguration
|
5
|
+
|
6
|
+
|
7
|
+
# *** constants
|
8
|
+
|
9
|
+
# ** constant: APP_REPO
|
10
|
+
APP_REPO = AppRepositoryConfiguration.new(
|
11
|
+
module_path='app.repositories.app',
|
12
|
+
class_name='YamlProxy',
|
13
|
+
params=dict(
|
14
|
+
app_config_file='app/configs/app.yaml'
|
15
|
+
),
|
16
|
+
)
|
app/configs/container.py
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# *** imports
|
2
|
+
|
3
|
+
# ** app
|
4
|
+
from ..domain.container import ContainerAttribute, ContainerDependency
|
5
|
+
|
6
|
+
|
7
|
+
# *** configs (container_attribute)
|
8
|
+
|
9
|
+
# ** config: feature_repo
|
10
|
+
feature_repo = ContainerAttribute.new(
|
11
|
+
id='feature_repo',
|
12
|
+
type='data',
|
13
|
+
flags=[
|
14
|
+
ContainerDependency.new(
|
15
|
+
flag='yaml',
|
16
|
+
module_path='app.repositories.feature',
|
17
|
+
class_name='YamlProxy',
|
18
|
+
parameters={
|
19
|
+
'feature_config_file': 'app/configs/features.yml'
|
20
|
+
}
|
21
|
+
)
|
22
|
+
]
|
23
|
+
)
|
24
|
+
|
25
|
+
# ** config: error_repo
|
26
|
+
error_repo = ContainerAttribute.new(
|
27
|
+
id='error_repo',
|
28
|
+
type='data',
|
29
|
+
flags=[
|
30
|
+
ContainerDependency.new(
|
31
|
+
flag='yaml',
|
32
|
+
module_path='app.repositories.error',
|
33
|
+
class_name='YamlProxy',
|
34
|
+
parameters={
|
35
|
+
'error_config_file': 'app/configs/errors.yml'
|
36
|
+
}
|
37
|
+
)
|
38
|
+
]
|
39
|
+
)
|
40
|
+
|
41
|
+
# ** config: set_container_attribute
|
42
|
+
set_container_attribute = ContainerAttribute.new(
|
43
|
+
id='set_container_attribute',
|
44
|
+
type='feature',
|
45
|
+
flags=[
|
46
|
+
ContainerDependency.new(
|
47
|
+
flag='core',
|
48
|
+
module_path='app.commands.container',
|
49
|
+
class_name='SetContainerAttribute'
|
50
|
+
)
|
51
|
+
]
|
52
|
+
)
|
53
|
+
|
54
|
+
# ** config: add_new_feature
|
55
|
+
add_new_feature = ContainerAttribute.new(
|
56
|
+
id='add_new_feature',
|
57
|
+
type='feature',
|
58
|
+
flags=[
|
59
|
+
ContainerDependency.new(
|
60
|
+
flag='core',
|
61
|
+
module_path='app.commands.feature',
|
62
|
+
class_name='AddNewFeature'
|
63
|
+
)
|
64
|
+
]
|
65
|
+
)
|
66
|
+
|
67
|
+
# ** config: add_feature_command
|
68
|
+
add_feature_command = ContainerAttribute.new(
|
69
|
+
id='add_feature_command',
|
70
|
+
type='feature',
|
71
|
+
flags=[
|
72
|
+
ContainerDependency.new(
|
73
|
+
flag='core',
|
74
|
+
module_path='app.commands.feature',
|
75
|
+
class_name='AddFeatureCommand'
|
76
|
+
)
|
77
|
+
]
|
78
|
+
)
|
79
|
+
|
80
|
+
# ** config: add_new_error
|
81
|
+
add_new_error = ContainerAttribute.new(
|
82
|
+
id='add_new_error',
|
83
|
+
type='feature',
|
84
|
+
flags=[
|
85
|
+
ContainerDependency.new(
|
86
|
+
flag='core',
|
87
|
+
module_path='app.commands.error',
|
88
|
+
class_name='AddNewError'
|
89
|
+
)
|
90
|
+
]
|
91
|
+
)
|
app/contexts/__init__.py
ADDED
app/contexts/app.py
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
# *** imports
|
2
|
+
|
3
|
+
# ** core
|
4
|
+
from typing import Any
|
5
|
+
|
6
|
+
# ** app
|
7
|
+
from .request import RequestContext
|
8
|
+
from .feature import FeatureContext
|
9
|
+
from .error import ErrorContext
|
10
|
+
from ..domain import *
|
11
|
+
|
12
|
+
|
13
|
+
# *** contexts
|
14
|
+
|
15
|
+
# ** context: app_interface_context
|
16
|
+
class AppInterfaceContext(Model):
|
17
|
+
|
18
|
+
# * attribute: name
|
19
|
+
name = StringType(
|
20
|
+
required=True,
|
21
|
+
metadata=dict(
|
22
|
+
description='The application name.'
|
23
|
+
)
|
24
|
+
)
|
25
|
+
|
26
|
+
# * field: features
|
27
|
+
features = ModelType(
|
28
|
+
FeatureContext,
|
29
|
+
required=True,
|
30
|
+
metadata=dict(
|
31
|
+
description='The feature context.'
|
32
|
+
)
|
33
|
+
)
|
34
|
+
|
35
|
+
# * field: errors
|
36
|
+
errors = ModelType(
|
37
|
+
ErrorContext,
|
38
|
+
required=True,
|
39
|
+
metadata=dict(
|
40
|
+
description='The error context.'
|
41
|
+
)
|
42
|
+
)
|
43
|
+
|
44
|
+
# * method: init
|
45
|
+
def __init__(self, app_name: str, feature_context: FeatureContext, error_context: ErrorContext):
|
46
|
+
'''
|
47
|
+
Initialize the application interface context.
|
48
|
+
|
49
|
+
:param app_name: The application name.
|
50
|
+
:type app_name: str
|
51
|
+
:param feature_context: The feature context.
|
52
|
+
:type feature_context: FeatureContext
|
53
|
+
:param error_context: The error context.
|
54
|
+
:type error_context: ErrorContext
|
55
|
+
'''
|
56
|
+
|
57
|
+
# Initialize the model.
|
58
|
+
super().__init__(dict(
|
59
|
+
name=app_name,
|
60
|
+
features=feature_context,
|
61
|
+
errors=error_context
|
62
|
+
))
|
63
|
+
|
64
|
+
# * method: parse_request
|
65
|
+
def parse_request(self, request: Any, **kwargs) -> RequestContext:
|
66
|
+
'''
|
67
|
+
Parse the incoming request.
|
68
|
+
|
69
|
+
:param request: The incoming request.
|
70
|
+
:type request: Any
|
71
|
+
:param kwargs: Additional keyword arguments.
|
72
|
+
:type kwargs: dict
|
73
|
+
:return: The request context.
|
74
|
+
:rtype: RequestContext
|
75
|
+
'''
|
76
|
+
|
77
|
+
# Parse request.
|
78
|
+
return request
|
79
|
+
|
80
|
+
# * method: execute_feature
|
81
|
+
def execute_feature(self, request: RequestContext, **kwargs):
|
82
|
+
'''
|
83
|
+
Execute the feature context.
|
84
|
+
|
85
|
+
:param request: The request context.
|
86
|
+
:type request: RequestContext
|
87
|
+
'''
|
88
|
+
|
89
|
+
# Execute feature context and return session.
|
90
|
+
self.features.execute(request, **kwargs)
|
91
|
+
|
92
|
+
# * method: handle_response
|
93
|
+
def handle_response(self, request: RequestContext) -> Any:
|
94
|
+
'''
|
95
|
+
Handle the response.
|
96
|
+
|
97
|
+
:param request: The request context.
|
98
|
+
:type request: RequestContext
|
99
|
+
:return: The response.
|
100
|
+
:rtype: Any
|
101
|
+
'''
|
102
|
+
|
103
|
+
# Import the JSON module.
|
104
|
+
import json
|
105
|
+
|
106
|
+
# Return the response.
|
107
|
+
return json.loads(request.result)
|
108
|
+
|
109
|
+
# * method: run
|
110
|
+
def run(self, **kwargs):
|
111
|
+
'''
|
112
|
+
Run the application interface.
|
113
|
+
|
114
|
+
:param kwargs: Additional keyword arguments.
|
115
|
+
:type kwargs: dict
|
116
|
+
'''
|
117
|
+
|
118
|
+
# Parse request.
|
119
|
+
request = self.parse_request(**kwargs)
|
120
|
+
|
121
|
+
# Execute feature context and return session.
|
122
|
+
# Handle error and return response if triggered.
|
123
|
+
has_error, message = self.errors.handle_error(lambda: self.execute_feature(request, **kwargs))
|
124
|
+
|
125
|
+
# Handle error if present.
|
126
|
+
if has_error:
|
127
|
+
return message
|
128
|
+
|
129
|
+
# Handle response.
|
130
|
+
return self.handle_response(request)
|