junban 1.0.1__tar.gz → 1.0.3__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.
- junban-1.0.3/PKG-INFO +94 -0
- {junban-1.0.1 → junban-1.0.3}/junban/pipeline.py +7 -3
- {junban-1.0.1 → junban-1.0.3}/junban/pipeline_step.py +8 -0
- junban-1.0.3/junban.egg-info/PKG-INFO +94 -0
- {junban-1.0.1 → junban-1.0.3}/pyproject.toml +2 -1
- junban-1.0.1/PKG-INFO +0 -10
- junban-1.0.1/junban.egg-info/PKG-INFO +0 -10
- {junban-1.0.1 → junban-1.0.3}/LICENSE +0 -0
- {junban-1.0.1 → junban-1.0.3}/README.md +0 -0
- {junban-1.0.1 → junban-1.0.3}/junban/__init__.py +0 -0
- {junban-1.0.1 → junban-1.0.3}/junban/pipeline_context.py +0 -0
- {junban-1.0.1 → junban-1.0.3}/junban.egg-info/SOURCES.txt +0 -0
- {junban-1.0.1 → junban-1.0.3}/junban.egg-info/dependency_links.txt +0 -0
- {junban-1.0.1 → junban-1.0.3}/junban.egg-info/top_level.txt +0 -0
- {junban-1.0.1 → junban-1.0.3}/setup.cfg +0 -0
junban-1.0.3/PKG-INFO
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: junban
|
|
3
|
+
Version: 1.0.3
|
|
4
|
+
Summary: Junban – Simple Sequential Python Workflows
|
|
5
|
+
Author-email: Sebastian Franz <sebastian.franz@tum.de>
|
|
6
|
+
Project-URL: Issues, https://github.com/biocentral/junban/issues
|
|
7
|
+
Project-URL: Repository, https://github.com/biocentral/junban
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
# Junban (順番) – Simple Sequential Python Workflows
|
|
14
|
+
|
|
15
|
+
Junban (english: order) is a lightweight library for defining and executing sequential (scientific) workflows in Python.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Junban is available via [pypi](https://pypi.org/project/junban/):
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
pip install junban
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Example
|
|
26
|
+
|
|
27
|
+
Here is a simple example showing how to define a context and two steps. It showcases how context is passed between steps
|
|
28
|
+
and how entry/exit assumptions (verification) are handled.
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from dataclasses import dataclass
|
|
32
|
+
from junban.pipeline import Pipeline
|
|
33
|
+
from junban.pipeline_step import PipelineStep
|
|
34
|
+
from junban.pipeline_context import PipelineContext
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# 1. Define your context by inheriting from PipelineContext
|
|
38
|
+
@dataclass
|
|
39
|
+
class MyContext(PipelineContext):
|
|
40
|
+
value: int = 0
|
|
41
|
+
is_processed: bool = False
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# 2. Create pipeline steps by inheriting from PipelineStep
|
|
45
|
+
class IncrementStep(PipelineStep[MyContext]):
|
|
46
|
+
def _check_entry_assumptions(self, context: MyContext) -> bool:
|
|
47
|
+
# Verification before step execution
|
|
48
|
+
return context.value == 0
|
|
49
|
+
|
|
50
|
+
def _execute(self, context: MyContext) -> MyContext:
|
|
51
|
+
# Core logic of the step
|
|
52
|
+
context.value += 1
|
|
53
|
+
return context
|
|
54
|
+
|
|
55
|
+
def _check_exit_assumptions(self, context: MyContext) -> bool:
|
|
56
|
+
# Verification after step execution
|
|
57
|
+
return context.value == 1
|
|
58
|
+
|
|
59
|
+
def get_start_message(self) -> str:
|
|
60
|
+
return "Incrementing value..."
|
|
61
|
+
|
|
62
|
+
def get_end_message(self) -> str:
|
|
63
|
+
return "Value incremented."
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ProcessStep(PipelineStep[MyContext]):
|
|
67
|
+
def _check_entry_assumptions(self, context: MyContext) -> bool:
|
|
68
|
+
return context.value > 0
|
|
69
|
+
|
|
70
|
+
def _execute(self, context: MyContext) -> MyContext:
|
|
71
|
+
context.is_processed = True
|
|
72
|
+
return context
|
|
73
|
+
|
|
74
|
+
def _check_exit_assumptions(self, context: MyContext) -> bool:
|
|
75
|
+
return context.is_processed is True
|
|
76
|
+
|
|
77
|
+
def get_start_message(self) -> str:
|
|
78
|
+
return "Processing..."
|
|
79
|
+
|
|
80
|
+
def get_end_message(self) -> str:
|
|
81
|
+
return "Processed."
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# 3. Initialize and execute the pipeline
|
|
85
|
+
if __name__ == "__main__":
|
|
86
|
+
context = MyContext()
|
|
87
|
+
pipeline = Pipeline(
|
|
88
|
+
steps=[IncrementStep(), ProcessStep()],
|
|
89
|
+
name="ExamplePipeline"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
final_context = pipeline.execute(context)
|
|
93
|
+
print(f"Final value: {final_context.value}, Processed: {final_context.is_processed}")
|
|
94
|
+
```
|
|
@@ -41,9 +41,13 @@ class Pipeline(Generic[C]):
|
|
|
41
41
|
current_context = context
|
|
42
42
|
for step in self.steps:
|
|
43
43
|
try:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
skip = step.maybe_skip(context)
|
|
45
|
+
if skip:
|
|
46
|
+
self._log_info(f"[{self.name}] Skipping..")
|
|
47
|
+
else:
|
|
48
|
+
self._log_info(f"[{self.name}] {step.get_start_message()}")
|
|
49
|
+
current_context = step.run(current_context)
|
|
50
|
+
self._log_info(f"[{self.name}] {step.get_end_message()}")
|
|
47
51
|
except AssertionError as e:
|
|
48
52
|
self._log_error(f"[{self.name}] Assertion error in step {step.__class__.__name__}: {str(e)}")
|
|
49
53
|
raise
|
|
@@ -20,6 +20,11 @@ class PipelineStep(ABC, Generic[C]):
|
|
|
20
20
|
"""
|
|
21
21
|
return True
|
|
22
22
|
|
|
23
|
+
def _skip(self, context: C) -> bool:
|
|
24
|
+
""" If this method returns True, the pipeline step will be skipped entirely.
|
|
25
|
+
Should not modify the context in any way."""
|
|
26
|
+
return False
|
|
27
|
+
|
|
23
28
|
@abstractmethod
|
|
24
29
|
def get_start_message(self) -> str:
|
|
25
30
|
raise NotImplementedError
|
|
@@ -32,6 +37,9 @@ class PipelineStep(ABC, Generic[C]):
|
|
|
32
37
|
def _execute(self, context: C) -> C:
|
|
33
38
|
raise NotImplementedError
|
|
34
39
|
|
|
40
|
+
def maybe_skip(self, context: C) -> bool:
|
|
41
|
+
return self._skip(context)
|
|
42
|
+
|
|
35
43
|
def run(self, context: C) -> C:
|
|
36
44
|
if not self._check_entry_assumptions(context):
|
|
37
45
|
assert False, "Entry assumptions not met"
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: junban
|
|
3
|
+
Version: 1.0.3
|
|
4
|
+
Summary: Junban – Simple Sequential Python Workflows
|
|
5
|
+
Author-email: Sebastian Franz <sebastian.franz@tum.de>
|
|
6
|
+
Project-URL: Issues, https://github.com/biocentral/junban/issues
|
|
7
|
+
Project-URL: Repository, https://github.com/biocentral/junban
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
# Junban (順番) – Simple Sequential Python Workflows
|
|
14
|
+
|
|
15
|
+
Junban (english: order) is a lightweight library for defining and executing sequential (scientific) workflows in Python.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Junban is available via [pypi](https://pypi.org/project/junban/):
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
pip install junban
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Example
|
|
26
|
+
|
|
27
|
+
Here is a simple example showing how to define a context and two steps. It showcases how context is passed between steps
|
|
28
|
+
and how entry/exit assumptions (verification) are handled.
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from dataclasses import dataclass
|
|
32
|
+
from junban.pipeline import Pipeline
|
|
33
|
+
from junban.pipeline_step import PipelineStep
|
|
34
|
+
from junban.pipeline_context import PipelineContext
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# 1. Define your context by inheriting from PipelineContext
|
|
38
|
+
@dataclass
|
|
39
|
+
class MyContext(PipelineContext):
|
|
40
|
+
value: int = 0
|
|
41
|
+
is_processed: bool = False
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
# 2. Create pipeline steps by inheriting from PipelineStep
|
|
45
|
+
class IncrementStep(PipelineStep[MyContext]):
|
|
46
|
+
def _check_entry_assumptions(self, context: MyContext) -> bool:
|
|
47
|
+
# Verification before step execution
|
|
48
|
+
return context.value == 0
|
|
49
|
+
|
|
50
|
+
def _execute(self, context: MyContext) -> MyContext:
|
|
51
|
+
# Core logic of the step
|
|
52
|
+
context.value += 1
|
|
53
|
+
return context
|
|
54
|
+
|
|
55
|
+
def _check_exit_assumptions(self, context: MyContext) -> bool:
|
|
56
|
+
# Verification after step execution
|
|
57
|
+
return context.value == 1
|
|
58
|
+
|
|
59
|
+
def get_start_message(self) -> str:
|
|
60
|
+
return "Incrementing value..."
|
|
61
|
+
|
|
62
|
+
def get_end_message(self) -> str:
|
|
63
|
+
return "Value incremented."
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class ProcessStep(PipelineStep[MyContext]):
|
|
67
|
+
def _check_entry_assumptions(self, context: MyContext) -> bool:
|
|
68
|
+
return context.value > 0
|
|
69
|
+
|
|
70
|
+
def _execute(self, context: MyContext) -> MyContext:
|
|
71
|
+
context.is_processed = True
|
|
72
|
+
return context
|
|
73
|
+
|
|
74
|
+
def _check_exit_assumptions(self, context: MyContext) -> bool:
|
|
75
|
+
return context.is_processed is True
|
|
76
|
+
|
|
77
|
+
def get_start_message(self) -> str:
|
|
78
|
+
return "Processing..."
|
|
79
|
+
|
|
80
|
+
def get_end_message(self) -> str:
|
|
81
|
+
return "Processed."
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# 3. Initialize and execute the pipeline
|
|
85
|
+
if __name__ == "__main__":
|
|
86
|
+
context = MyContext()
|
|
87
|
+
pipeline = Pipeline(
|
|
88
|
+
steps=[IncrementStep(), ProcessStep()],
|
|
89
|
+
name="ExamplePipeline"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
final_context = pipeline.execute(context)
|
|
93
|
+
print(f"Final value: {final_context.value}, Processed: {final_context.is_processed}")
|
|
94
|
+
```
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "junban"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.3"
|
|
4
4
|
description = "Junban – Simple Sequential Python Workflows"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "Sebastian Franz", email = "sebastian.franz@tum.de"},
|
|
7
7
|
]
|
|
8
|
+
readme = "README.md"
|
|
8
9
|
requires-python = ">=3.11"
|
|
9
10
|
dependencies = []
|
|
10
11
|
|
junban-1.0.1/PKG-INFO
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: junban
|
|
3
|
-
Version: 1.0.1
|
|
4
|
-
Summary: Junban – Simple Sequential Python Workflows
|
|
5
|
-
Author-email: Sebastian Franz <sebastian.franz@tum.de>
|
|
6
|
-
Project-URL: Issues, https://github.com/biocentral/junban/issues
|
|
7
|
-
Project-URL: Repository, https://github.com/biocentral/junban
|
|
8
|
-
Requires-Python: >=3.11
|
|
9
|
-
License-File: LICENSE
|
|
10
|
-
Dynamic: license-file
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: junban
|
|
3
|
-
Version: 1.0.1
|
|
4
|
-
Summary: Junban – Simple Sequential Python Workflows
|
|
5
|
-
Author-email: Sebastian Franz <sebastian.franz@tum.de>
|
|
6
|
-
Project-URL: Issues, https://github.com/biocentral/junban/issues
|
|
7
|
-
Project-URL: Repository, https://github.com/biocentral/junban
|
|
8
|
-
Requires-Python: >=3.11
|
|
9
|
-
License-File: LICENSE
|
|
10
|
-
Dynamic: license-file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|