pipeline-component-system 0.0.1__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.
- pipeline_component_system-0.0.1/LICENSE +5 -0
- pipeline_component_system-0.0.1/PKG-INFO +20 -0
- pipeline_component_system-0.0.1/README.md +3 -0
- pipeline_component_system-0.0.1/pcs/__init__.py +0 -0
- pipeline_component_system-0.0.1/pcs/argument_parser.py +82 -0
- pipeline_component_system-0.0.1/pcs/init.py +6 -0
- pipeline_component_system-0.0.1/pcs/pipeline.py +89 -0
- pipeline_component_system-0.0.1/pipeline_component_system.egg-info/PKG-INFO +20 -0
- pipeline_component_system-0.0.1/pipeline_component_system.egg-info/SOURCES.txt +11 -0
- pipeline_component_system-0.0.1/pipeline_component_system.egg-info/dependency_links.txt +1 -0
- pipeline_component_system-0.0.1/pipeline_component_system.egg-info/top_level.txt +1 -0
- pipeline_component_system-0.0.1/pyproject.toml +21 -0
- pipeline_component_system-0.0.1/setup.cfg +4 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Copyright 2024 Daniel Cauchi
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pipeline-component-system
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A strange programming framework
|
|
5
|
+
Author-email: Daniel Cauchi <cowkeyman@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/CowKeyMan/PCS
|
|
7
|
+
Project-URL: Issues, https://github.com/CowKeyMan/PCS/issues
|
|
8
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT No Attribution License (MIT-0)
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
|
|
18
|
+
# Pipeline Component System (PCS)
|
|
19
|
+
|
|
20
|
+
|
|
File without changes
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import yaml
|
|
2
|
+
import argparse
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Args(argparse.Namespace):
|
|
6
|
+
def __init__(self):
|
|
7
|
+
super().__init__()
|
|
8
|
+
self.args_files: str = ""
|
|
9
|
+
self.rest: list[str] = []
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parse_arguments(obj: object):
|
|
13
|
+
args = do_parse_arguments()
|
|
14
|
+
update_dict = get_update_dict_from_comma_separated_file_list(args.args_files)
|
|
15
|
+
update_dict_with_rest_arguments(update_dict, args.rest)
|
|
16
|
+
update_object(obj, update_dict)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def do_parse_arguments() -> Args:
|
|
20
|
+
parser = argparse.ArgumentParser()
|
|
21
|
+
_ = parser.add_argument(
|
|
22
|
+
"--args-files",
|
|
23
|
+
"-f",
|
|
24
|
+
required=False,
|
|
25
|
+
help=(
|
|
26
|
+
"A list of comma separated yaml files, where the keys in the "
|
|
27
|
+
"latest files will overwrite those in previous files"
|
|
28
|
+
),
|
|
29
|
+
)
|
|
30
|
+
_ = parser.add_argument(
|
|
31
|
+
"--rest",
|
|
32
|
+
"-r",
|
|
33
|
+
nargs="+",
|
|
34
|
+
help=(
|
|
35
|
+
"Set a number of key-value pairs like <key>=<value>. "
|
|
36
|
+
"Values may have spaces if the whole value is wrapped"
|
|
37
|
+
'in quotes such as <key>="this is a value". These arguments'
|
|
38
|
+
"take precedence over those that come from files"
|
|
39
|
+
),
|
|
40
|
+
)
|
|
41
|
+
args = Args()
|
|
42
|
+
args = parser.parse_args(namespace=args)
|
|
43
|
+
return args
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_update_dict_from_comma_separated_file_list(files: str) -> dict[str, object]:
|
|
47
|
+
return get_update_dict_from_files(files.split(","))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_update_dict_from_files(files: list[str]) -> dict[str, object]:
|
|
51
|
+
if len(files) == 1 and files[0] == "":
|
|
52
|
+
return {}
|
|
53
|
+
args: dict[str, object] = {}
|
|
54
|
+
for file in files:
|
|
55
|
+
with open(file, "r", encoding="utf-8") as f:
|
|
56
|
+
args |= yaml.safe_load(f)
|
|
57
|
+
return args
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def update_dict_with_rest_arguments(update_dict: dict[str, object], rest: list[str]):
|
|
61
|
+
for r in rest:
|
|
62
|
+
key, value = r.split("=")
|
|
63
|
+
if value.isdigit():
|
|
64
|
+
value = int(value)
|
|
65
|
+
else:
|
|
66
|
+
try:
|
|
67
|
+
value = float(value)
|
|
68
|
+
except ValueError:
|
|
69
|
+
print("Not a float")
|
|
70
|
+
update_dict[key] = value
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def update_object(obj: object, update_dict: dict[str, object]):
|
|
74
|
+
for key, value in update_dict.items():
|
|
75
|
+
assert hasattr(obj, key), f"obj has no attribute {key}"
|
|
76
|
+
target_type: type = obj.__annotations__[key]
|
|
77
|
+
assert isinstance(value, target_type), (
|
|
78
|
+
f"Key: {key} with value: {value} of type {type(value)} "
|
|
79
|
+
f"does not have the target type of {target_type}"
|
|
80
|
+
)
|
|
81
|
+
setattr(obj, key, value)
|
|
82
|
+
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
from collections.abc import Mapping
|
|
3
|
+
from typing import Callable, TypeAlias
|
|
4
|
+
|
|
5
|
+
System: TypeAlias = Callable[..., None | Mapping[str, object]]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Pipeline:
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
component: object,
|
|
12
|
+
systems: list[System],
|
|
13
|
+
do_null_checks: bool = True,
|
|
14
|
+
do_type_checks: bool = True,
|
|
15
|
+
):
|
|
16
|
+
assert len(systems) > 0, "Systems in an empty list"
|
|
17
|
+
self.component: object = component
|
|
18
|
+
self.systems: list[System] = systems
|
|
19
|
+
self.do_null_checks: bool = do_null_checks
|
|
20
|
+
self.do_type_checks: bool = do_type_checks
|
|
21
|
+
self.current_system: System = systems[0]
|
|
22
|
+
|
|
23
|
+
def execute(self):
|
|
24
|
+
for system in self.systems:
|
|
25
|
+
self.current_system = system
|
|
26
|
+
self.check_for_nulls(system)
|
|
27
|
+
self.check_for_types(system)
|
|
28
|
+
result = system(
|
|
29
|
+
*[
|
|
30
|
+
getattr(self.component, param_name)
|
|
31
|
+
for param_name in inspect.signature(system).parameters
|
|
32
|
+
]
|
|
33
|
+
)
|
|
34
|
+
self.set_component(result)
|
|
35
|
+
|
|
36
|
+
def check_for_nulls(self, system: System):
|
|
37
|
+
if not self.do_null_checks:
|
|
38
|
+
return
|
|
39
|
+
for parameter in inspect.signature(system).parameters:
|
|
40
|
+
assert (
|
|
41
|
+
getattr(self.component, parameter) is not None
|
|
42
|
+
), f"System: {system.__name__} - Parameter {parameter} was None"
|
|
43
|
+
|
|
44
|
+
def check_for_types(self, system: System):
|
|
45
|
+
if not self.do_type_checks:
|
|
46
|
+
return
|
|
47
|
+
parameters = inspect.signature(system).parameters
|
|
48
|
+
for param in parameters:
|
|
49
|
+
self.assert_type_annotation(
|
|
50
|
+
self.component.__annotations__[param], # pyright: ignore[reportAny]
|
|
51
|
+
parameters[param].annotation, # pyright: ignore[reportAny]
|
|
52
|
+
f"System {system.__name__} - Input {param} has wrong type",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def set_component(self, result: None | Mapping[str, object]):
|
|
56
|
+
if result is None:
|
|
57
|
+
return
|
|
58
|
+
assert isinstance(result, dict), (
|
|
59
|
+
f"System {self.current_system.__name__} - "
|
|
60
|
+
f"Result is not None or a dictionary"
|
|
61
|
+
)
|
|
62
|
+
for name, obj in result.items():
|
|
63
|
+
self.assert_type_obj(
|
|
64
|
+
self.component.__annotations__[name], # pyright: ignore[reportAny]
|
|
65
|
+
obj,
|
|
66
|
+
(
|
|
67
|
+
f"System {self.current_system.__name__} "
|
|
68
|
+
f"- Output {name} has wrong type"
|
|
69
|
+
),
|
|
70
|
+
)
|
|
71
|
+
setattr(self.component, name, obj)
|
|
72
|
+
|
|
73
|
+
@staticmethod
|
|
74
|
+
def assert_type_obj(parent_annotation: type, obj: object, message: str):
|
|
75
|
+
parent_origin = getattr(parent_annotation, "__origin__", parent_annotation)
|
|
76
|
+
assert (type(obj) is parent_annotation) or isinstance(
|
|
77
|
+
obj, parent_origin
|
|
78
|
+
), message
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def assert_type_annotation(
|
|
82
|
+
parent_annotation: TypeAlias, child_annotation: TypeAlias, message: str
|
|
83
|
+
):
|
|
84
|
+
child_origin = getattr(child_annotation, "__origin__", child_annotation)
|
|
85
|
+
parent_origin = getattr(parent_annotation, "__origin__", parent_annotation)
|
|
86
|
+
assert isinstance(parent_origin, type) or parent_origin is TypeAlias
|
|
87
|
+
assert (child_annotation == parent_annotation) or isinstance(
|
|
88
|
+
child_origin, parent_origin
|
|
89
|
+
), message
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pipeline-component-system
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A strange programming framework
|
|
5
|
+
Author-email: Daniel Cauchi <cowkeyman@gmail.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/CowKeyMan/PCS
|
|
7
|
+
Project-URL: Issues, https://github.com/CowKeyMan/PCS/issues
|
|
8
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT No Attribution License (MIT-0)
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
|
|
18
|
+
# Pipeline Component System (PCS)
|
|
19
|
+
|
|
20
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
pcs/__init__.py
|
|
5
|
+
pcs/argument_parser.py
|
|
6
|
+
pcs/init.py
|
|
7
|
+
pcs/pipeline.py
|
|
8
|
+
pipeline_component_system.egg-info/PKG-INFO
|
|
9
|
+
pipeline_component_system.egg-info/SOURCES.txt
|
|
10
|
+
pipeline_component_system.egg-info/dependency_links.txt
|
|
11
|
+
pipeline_component_system.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pcs
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pipeline-component-system"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
authors = [
|
|
5
|
+
{ name="Daniel Cauchi", email="cowkeyman@gmail.com" },
|
|
6
|
+
]
|
|
7
|
+
description = "A strange programming framework"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.9"
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
12
|
+
"License :: OSI Approved :: MIT No Attribution License (MIT-0)",
|
|
13
|
+
"Operating System :: POSIX :: Linux",
|
|
14
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
15
|
+
"Natural Language :: English",
|
|
16
|
+
"Intended Audience :: Developers"
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[project.urls]
|
|
20
|
+
Homepage = "https://github.com/CowKeyMan/PCS"
|
|
21
|
+
Issues = "https://github.com/CowKeyMan/PCS/issues"
|