nextpipe 0.1.0.dev5__tar.gz → 0.1.0.dev6__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.
Files changed (74) hide show
  1. nextpipe-0.1.0.dev5/.github/workflows/python-lint.yml → nextpipe-0.1.0.dev6/.github/workflows/lint.yml +3 -3
  2. nextpipe-0.1.0.dev5/.github/workflows/python-test.yml → nextpipe-0.1.0.dev6/.github/workflows/test.yml +5 -3
  3. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/PKG-INFO +88 -4
  4. nextpipe-0.1.0.dev6/README.md +90 -0
  5. nextpipe-0.1.0.dev6/examples/README.md +18 -0
  6. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/apps/echo/main.py +7 -1
  7. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-chain/README.md +2 -2
  8. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-complex/README.md +2 -2
  9. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-ensemble/README.md +2 -2
  10. nextpipe-0.1.0.dev6/examples/pipeline-foreach/README.md +26 -0
  11. nextpipe-0.1.0.dev6/examples/pipeline-foreach/main.py +56 -0
  12. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-preprocess/README.md +2 -2
  13. nextpipe-0.1.0.dev6/examples/pipeline-preprocess/app.yaml +7 -0
  14. nextpipe-0.1.0.dev6/examples/pipeline-preprocess/requirements.txt +1 -0
  15. nextpipe-0.1.0.dev6/nextpipe/__about__.py +1 -0
  16. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/nextpipe/__init__.py +4 -0
  17. nextpipe-0.1.0.dev6/nextpipe/config.py +22 -0
  18. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/nextpipe/decorators.py +94 -50
  19. nextpipe-0.1.0.dev6/nextpipe/flow.py +455 -0
  20. nextpipe-0.1.0.dev6/nextpipe/graph.py +44 -0
  21. nextpipe-0.1.0.dev6/nextpipe/schema.py +25 -0
  22. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/nextpipe/threads.py +32 -19
  23. nextpipe-0.1.0.dev6/nextpipe/uplink.py +206 -0
  24. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/nextpipe/utils.py +7 -8
  25. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/pyproject.toml +7 -4
  26. nextpipe-0.1.0.dev6/tests/.gitignore +3 -0
  27. nextpipe-0.1.0.dev6/tests/README.md +52 -0
  28. nextpipe-0.1.0.dev6/tests/apps/echo/.gitignore +1 -0
  29. nextpipe-0.1.0.dev6/tests/apps/echo/README.md +19 -0
  30. nextpipe-0.1.0.dev6/tests/apps/echo/app.yaml +6 -0
  31. nextpipe-0.1.0.dev6/tests/apps/echo/main.py +17 -0
  32. nextpipe-0.1.0.dev6/tests/apps/echo/requirements.txt +1 -0
  33. nextpipe-0.1.0.dev6/tests/deploy/app.yaml +7 -0
  34. nextpipe-0.1.0.dev6/tests/deploy/main.py +50 -0
  35. nextpipe-0.1.0.dev6/tests/deploy/requirements.txt +2 -0
  36. nextpipe-0.1.0.dev6/tests/pipelines/chain.json +3 -0
  37. nextpipe-0.1.0.dev6/tests/pipelines/chain.json.golden +10 -0
  38. nextpipe-0.1.0.dev6/tests/pipelines/chain.py +50 -0
  39. nextpipe-0.1.0.dev6/tests/pipelines/complex.json +20 -0
  40. nextpipe-0.1.0.dev6/tests/pipelines/complex.json.golden +72 -0
  41. nextpipe-0.1.0.dev6/tests/pipelines/complex.py +77 -0
  42. nextpipe-0.1.0.dev6/tests/pipelines/fail.py +36 -0
  43. nextpipe-0.1.0.dev6/tests/test_graph.py +40 -0
  44. nextpipe-0.1.0.dev6/tests/test_integration.py +113 -0
  45. nextpipe-0.1.0.dev6/tests/test_threads.py +52 -0
  46. nextpipe-0.1.0.dev6/tests/test_uplink.py +99 -0
  47. nextpipe-0.1.0.dev5/README.md +0 -7
  48. nextpipe-0.1.0.dev5/examples/README.md +0 -3
  49. nextpipe-0.1.0.dev5/nextpipe/__about__.py +0 -1
  50. nextpipe-0.1.0.dev5/nextpipe/flow.py +0 -315
  51. nextpipe-0.1.0.dev5/nextpipe/schema.py +0 -50
  52. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/.github/workflows/release.yml +0 -0
  53. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/.gitignore +0 -0
  54. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/.prettierrc.yml +0 -0
  55. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/LICENSE.md +0 -0
  56. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/apps/echo/.gitignore +0 -0
  57. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/apps/echo/README.md +0 -0
  58. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/apps/echo/app.yaml +0 -0
  59. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/apps/echo/requirements.txt +0 -0
  60. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-chain/app.yaml +0 -0
  61. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-chain/main.py +0 -0
  62. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-chain/requirements.txt +0 -0
  63. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-complex/app.yaml +0 -0
  64. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-complex/main.py +0 -0
  65. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-complex/requirements.txt +0 -0
  66. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-ensemble/app.yaml +0 -0
  67. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-ensemble/main.py +0 -0
  68. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-ensemble/requirements.txt +0 -0
  69. {nextpipe-0.1.0.dev5/examples/pipeline-preprocess → nextpipe-0.1.0.dev6/examples/pipeline-foreach}/app.yaml +0 -0
  70. {nextpipe-0.1.0.dev5/examples/pipeline-preprocess → nextpipe-0.1.0.dev6/examples/pipeline-foreach}/requirements.txt +0 -0
  71. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/examples/pipeline-preprocess/main.py +0 -0
  72. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/nextpipe.code-workspace +0 -0
  73. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/tests/__init__.py +0 -0
  74. {nextpipe-0.1.0.dev5 → nextpipe-0.1.0.dev6}/tests/test_version.py +0 -0
@@ -1,11 +1,11 @@
1
- name: python lint
1
+ name: lint
2
2
  on: [push]
3
3
  jobs:
4
- python-lint:
4
+ lint:
5
5
  runs-on: ubuntu-latest
6
6
  strategy:
7
7
  matrix:
8
- python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
8
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
9
9
  steps:
10
10
  - name: git clone
11
11
  uses: actions/checkout@v4
@@ -1,11 +1,11 @@
1
- name: python test
1
+ name: test
2
2
  on: [push]
3
3
  jobs:
4
- python-test:
4
+ test:
5
5
  runs-on: ubuntu-latest
6
6
  strategy:
7
7
  matrix:
8
- python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
8
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
9
9
  steps:
10
10
  - name: git clone
11
11
  uses: actions/checkout@v4
@@ -21,4 +21,6 @@ jobs:
21
21
  pip install .[dev]
22
22
 
23
23
  - name: unit tests
24
+ env:
25
+ NEXTMV_API_KEY_NEXTPIPE: ${{ secrets.NEXTMV_API_KEY_NEXTPIPE }}
24
26
  run: python -m unittest
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextpipe
3
- Version: 0.1.0.dev5
3
+ Version: 0.1.0.dev6
4
4
  Summary: Framework for Decision Pipeline modeling and execution
5
5
  Project-URL: Homepage, https://www.nextmv.io
6
6
  Project-URL: Documentation, https://www.nextmv.io/docs
@@ -98,17 +98,18 @@ License-File: LICENSE.md
98
98
  Keywords: decision automation,decision engineering,decision pipelines,decision science,decision workflows,decisions,nextmv,operations research,optimization,pipelines,workflows
99
99
  Classifier: Operating System :: OS Independent
100
100
  Classifier: Programming Language :: Python :: 3
101
- Classifier: Programming Language :: Python :: 3.8
102
101
  Classifier: Programming Language :: Python :: 3.9
103
102
  Classifier: Programming Language :: Python :: 3.10
104
103
  Classifier: Programming Language :: Python :: 3.11
105
104
  Classifier: Programming Language :: Python :: 3.12
106
- Requires-Python: >=3.8
105
+ Classifier: Programming Language :: Python :: 3.13
106
+ Requires-Python: >=3.9
107
107
  Requires-Dist: dataclasses-json>=0.6.7
108
108
  Requires-Dist: nextmv>=0.13.1
109
109
  Requires-Dist: pathos>=0.3.2
110
110
  Requires-Dist: requests>=2.31.0
111
111
  Provides-Extra: dev
112
+ Requires-Dist: goldie>=0.1.6; extra == 'dev'
112
113
  Requires-Dist: ruff>=0.6.4; extra == 'dev'
113
114
  Description-Content-Type: text/markdown
114
115
 
@@ -116,6 +117,89 @@ Description-Content-Type: text/markdown
116
117
 
117
118
  Framework for Decision Pipeline modeling and execution.
118
119
 
120
+ ## Installation
121
+
122
+ ```bash
123
+ pip install nextpipe
124
+ ```
125
+
126
+ ## Preview
127
+
128
+ Example of a pipeline utilizing multiple routing solvers, and picking the best result.
129
+
130
+ ```mermaid
131
+ graph LR
132
+ fetch_data(prepare_data)
133
+ fetch_data --> run_nextroute
134
+ fetch_data --> run_ortools
135
+ fetch_data --> run_pyvroom
136
+ run_nextroute{ }
137
+ run_nextroute_join{ }
138
+ run_nextroute_0(run_nextroute_0)
139
+ run_nextroute --> run_nextroute_0
140
+ run_nextroute_0 --> run_nextroute_join
141
+ run_nextroute_1(run_nextroute_1)
142
+ run_nextroute --> run_nextroute_1
143
+ run_nextroute_1 --> run_nextroute_join
144
+ run_nextroute_2(run_nextroute_2)
145
+ run_nextroute --> run_nextroute_2
146
+ run_nextroute_2 --> run_nextroute_join
147
+ run_nextroute_join --> pick_best
148
+ run_ortools(run_ortools)
149
+ run_ortools --> pick_best
150
+ run_pyvroom(run_pyvroom)
151
+ run_pyvroom --> pick_best
152
+ pick_best(pick_best)
153
+ ```
154
+
155
+ ## Modeling
156
+
157
+ Pipeline modeling is done by defining a flow as steps and decorating them.
158
+ The following example demonstrates a 3 step pipeline that makes use of dynamic fanout and joining of results.
159
+
160
+ ```python
161
+ from nextpipe import AppOption, AppRunConfig, FlowSpec, app, foreach, join, needs, step
162
+
163
+
164
+ class Flow(FlowSpec):
165
+ @foreach() # Run the successor step for each item in the result list of this step
166
+ @step
167
+ def prepare(data: dict):
168
+ """
169
+ Creates 3 copies of the input and configures them for 3 different app parameters.
170
+ """
171
+ inputs = [copy.deepcopy(data) for _ in range(3)]
172
+ run_configs = [AppRunConfig(input, [AppOption("param", i)]) for i, input in enumerate(inputs)]
173
+ return run_configs
174
+
175
+ @app(app_id="echo")
176
+ @needs(predecessors=[prepare])
177
+ @step
178
+ def solve():
179
+ """
180
+ Imitates a solver app.
181
+ """
182
+ pass
183
+
184
+ @needs(predecessors=[solve])
185
+ @join() # Collect the results from the previous 'foreach' step and combine them into a list passed as the arg
186
+ @step
187
+ def merge(results: list[dict]):
188
+ """Merges the results."""
189
+ return results
190
+ ```
191
+
192
+ The pipeline can simply be executed from the main func of the app.
193
+
194
+ ```python
195
+ # Run workflow
196
+ flow = Flow("DecisionFlow", input.data)
197
+ flow.run()
198
+
199
+ # Write out the result
200
+ print(json.dumps(flow.get_result(flow.merge)))
201
+ ```
202
+
119
203
  ## Examples
120
204
 
121
- You can find examples of how to use `nextpipe` in the [examples](./examples) directory.
205
+ You can find further examples of how to use `nextpipe` in the [examples](./examples) directory.
@@ -0,0 +1,90 @@
1
+ # nextpipe
2
+
3
+ Framework for Decision Pipeline modeling and execution.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install nextpipe
9
+ ```
10
+
11
+ ## Preview
12
+
13
+ Example of a pipeline utilizing multiple routing solvers, and picking the best result.
14
+
15
+ ```mermaid
16
+ graph LR
17
+ fetch_data(prepare_data)
18
+ fetch_data --> run_nextroute
19
+ fetch_data --> run_ortools
20
+ fetch_data --> run_pyvroom
21
+ run_nextroute{ }
22
+ run_nextroute_join{ }
23
+ run_nextroute_0(run_nextroute_0)
24
+ run_nextroute --> run_nextroute_0
25
+ run_nextroute_0 --> run_nextroute_join
26
+ run_nextroute_1(run_nextroute_1)
27
+ run_nextroute --> run_nextroute_1
28
+ run_nextroute_1 --> run_nextroute_join
29
+ run_nextroute_2(run_nextroute_2)
30
+ run_nextroute --> run_nextroute_2
31
+ run_nextroute_2 --> run_nextroute_join
32
+ run_nextroute_join --> pick_best
33
+ run_ortools(run_ortools)
34
+ run_ortools --> pick_best
35
+ run_pyvroom(run_pyvroom)
36
+ run_pyvroom --> pick_best
37
+ pick_best(pick_best)
38
+ ```
39
+
40
+ ## Modeling
41
+
42
+ Pipeline modeling is done by defining a flow as steps and decorating them.
43
+ The following example demonstrates a 3 step pipeline that makes use of dynamic fanout and joining of results.
44
+
45
+ ```python
46
+ from nextpipe import AppOption, AppRunConfig, FlowSpec, app, foreach, join, needs, step
47
+
48
+
49
+ class Flow(FlowSpec):
50
+ @foreach() # Run the successor step for each item in the result list of this step
51
+ @step
52
+ def prepare(data: dict):
53
+ """
54
+ Creates 3 copies of the input and configures them for 3 different app parameters.
55
+ """
56
+ inputs = [copy.deepcopy(data) for _ in range(3)]
57
+ run_configs = [AppRunConfig(input, [AppOption("param", i)]) for i, input in enumerate(inputs)]
58
+ return run_configs
59
+
60
+ @app(app_id="echo")
61
+ @needs(predecessors=[prepare])
62
+ @step
63
+ def solve():
64
+ """
65
+ Imitates a solver app.
66
+ """
67
+ pass
68
+
69
+ @needs(predecessors=[solve])
70
+ @join() # Collect the results from the previous 'foreach' step and combine them into a list passed as the arg
71
+ @step
72
+ def merge(results: list[dict]):
73
+ """Merges the results."""
74
+ return results
75
+ ```
76
+
77
+ The pipeline can simply be executed from the main func of the app.
78
+
79
+ ```python
80
+ # Run workflow
81
+ flow = Flow("DecisionFlow", input.data)
82
+ flow.run()
83
+
84
+ # Write out the result
85
+ print(json.dumps(flow.get_result(flow.merge)))
86
+ ```
87
+
88
+ ## Examples
89
+
90
+ You can find further examples of how to use `nextpipe` in the [examples](./examples) directory.
@@ -0,0 +1,18 @@
1
+ # Examples
2
+
3
+ This directory contains examples of how to use `nextpipe`.
4
+
5
+ ## Prerequisites
6
+
7
+ - Create and push all necessary apps in your account (check the README of the example and look for `@app` in the pipeline definition).
8
+ - Some simple apps are available in the `./apps` directory. Push them as described in their READMEs.
9
+ - Some examples make use of marketplace apps. Follow instructions in the example READMEs to subscribe to them.
10
+ - Alternative, you can use the `nextmv community clone -a <app-id>` command to clone the app from the community apps repository.
11
+
12
+ ## Table of contents
13
+
14
+ - [pipeline-chain](./pipeline-chain): Example of a simple pipeline with a chain of steps.
15
+ - [pipeline-foreach](./pipeline-foreach): Example of a pipeline with a fanout step (`@foreach`) that runs the same input through a solve step with different app options.
16
+ - [pipeline-complex](./pipeline-complex): A more complex pipeline combining some concepts and multiple solvers.
17
+ - [pipeline-ensemble](./pipeline-ensemble): Example of a pipeline ensembling the results of multiple solvers.
18
+ - [pipeline-preprocess](./pipeline-preprocess): Example of a pipeline doing some preprocessing before running a solver.
@@ -1,3 +1,4 @@
1
+ import sys
1
2
  import time
2
3
 
3
4
  import nextmv
@@ -5,7 +6,12 @@ import nextmv
5
6
  before = time.time()
6
7
  input = nextmv.load_local()
7
8
  output = nextmv.Output(
8
- solution={"echo": input.data},
9
+ solution={
10
+ "echo": {
11
+ "data": input.data,
12
+ "args": sys.argv[1:],
13
+ },
14
+ },
9
15
  statistics={"run": {"duration": time.time() - before}},
10
16
  )
11
17
  nextmv.write_local(output)
@@ -5,7 +5,7 @@ A simple chain pipeline.
5
5
  ## Graph
6
6
 
7
7
  ```mermaid
8
- graph TD
8
+ graph LR
9
9
  prepare(prepare)
10
10
  prepare --> solve
11
11
  solve(solve)
@@ -21,5 +21,5 @@ graph TD
21
21
 
22
22
  ```bash
23
23
  nextmv app push -a <app-id>
24
- echo '{"hello": "world!"}' | nextmv app run -a <app-id> -e "8c16gb12h"
24
+ echo '{"hello": "world!"}' | nextmv app run -a <app-id>
25
25
  ```
@@ -5,7 +5,7 @@ A more complex pipeline combining some concepts.
5
5
  ## Graph
6
6
 
7
7
  ```mermaid
8
- graph TD
8
+ graph LR
9
9
  fetch_data(fetch_data)
10
10
  fetch_data --> run_nextroute
11
11
  fetch_data --> run_ortools
@@ -40,5 +40,5 @@ graph TD
40
40
 
41
41
  ```bash
42
42
  nextmv app push -a <app-id>
43
- echo '{}' | nextmv app run -a <app-id> -e "8c16gb12h"
43
+ echo '{}' | nextmv app run -a <app-id>
44
44
  ```
@@ -5,7 +5,7 @@ A basic ensemble pipeline.
5
5
  ## Graph
6
6
 
7
7
  ```mermaid
8
- graph TD
8
+ graph LR
9
9
  run_nextroute{ }
10
10
  run_nextroute_join{ }
11
11
  run_nextroute_0(run_nextroute_0)
@@ -30,5 +30,5 @@ graph TD
30
30
 
31
31
  ```bash
32
32
  nextmv app push -a <app-id>
33
- cat /path/to/routing/input.json | nextmv app run -a <app-id> -e "8c16gb12h" -o 'instance=v171-5s'
33
+ cat /path/to/routing/input.json | nextmv app run -a <app-id> -o 'instance=v171-5s'
34
34
  ```
@@ -0,0 +1,26 @@
1
+ # Foreach fanout example
2
+
3
+ Example of a pipeline with a fanout step (`@foreach`) that runs the same input through a solve step with different app options.
4
+
5
+ ## Graph
6
+
7
+ ```mermaid
8
+ graph LR
9
+ prepare{ }
10
+ prepare(prepare)
11
+ prepare -- foreach --> solve
12
+ solve(solve)
13
+ solve -- join --> enhance
14
+ enhance(enhance)
15
+ ```
16
+
17
+ ## Pre-requisites
18
+
19
+ - Push the echo app as described in the [echo app README](../apps/echo/README.md)`
20
+
21
+ ## Usage
22
+
23
+ ```bash
24
+ nextmv app push -a <app-id>
25
+ echo '{}' | nextmv app run -a <app-id>
26
+ ```
@@ -0,0 +1,56 @@
1
+ import copy
2
+ import json
3
+ import os
4
+
5
+ import nextmv
6
+ import nextmv.cloud
7
+
8
+ from nextpipe import AppOption, AppRunConfig, FlowSpec, app, foreach, join, needs, step
9
+
10
+
11
+ class Flow(FlowSpec):
12
+ @foreach() # Run the successor step for each item in the result list of this step
13
+ @step
14
+ def prepare(data: dict):
15
+ """
16
+ Creates 3 copies of the input and configures them for 3 different app parameters.
17
+ """
18
+ inputs = [copy.deepcopy(data) for _ in range(3)]
19
+ run_configs = [AppRunConfig(input, [AppOption("param", i)]) for i, input in enumerate(inputs)]
20
+ return run_configs
21
+
22
+ @app(app_id="echo")
23
+ @needs(predecessors=[prepare])
24
+ @step
25
+ def solve():
26
+ """
27
+ Runs the model.
28
+ """
29
+ pass
30
+
31
+ @needs(predecessors=[solve])
32
+ @join() # Collect the results from the previous 'foreach' step and combine them into a list passed as the arg
33
+ @step
34
+ def merge(results: list[dict]):
35
+ """Merges the results."""
36
+ return results
37
+
38
+
39
+ def main():
40
+ # Read API key from file (until secrets management support)
41
+ with open("key.json") as f:
42
+ os.environ["NEXTMV_API_KEY"] = json.load(f)["nextmv_api_key"]
43
+
44
+ # Load input data
45
+ input = nextmv.load_local()
46
+
47
+ # Run workflow
48
+ flow = Flow("DecisionFlow", input.data)
49
+ flow.run()
50
+
51
+ # Write out the result
52
+ print(json.dumps(flow.get_result(flow.merge)))
53
+
54
+
55
+ if __name__ == "__main__":
56
+ main()
@@ -5,7 +5,7 @@ An example of a pipeline fetching CSV data, converting it to JSON, ensembling ac
5
5
  ## Graph
6
6
 
7
7
  ```mermaid
8
- graph TD
8
+ graph LR
9
9
  fetch(fetch)
10
10
  fetch --> convert
11
11
  convert(convert)
@@ -42,5 +42,5 @@ graph TD
42
42
 
43
43
  ```bash
44
44
  nextmv app push -a <app-id>
45
- echo '{}' | nextmv app run -a <app-id> -e "8c16gb12h"
45
+ echo '{}' | nextmv app run -a <app-id>
46
46
  ```
@@ -0,0 +1,7 @@
1
+ type: python
2
+ runtime: ghcr.io/nextmv-io/runtime/python:3.11
3
+ files:
4
+ - main.py
5
+ - key.json
6
+ python:
7
+ pip-requirements: requirements.txt
@@ -0,0 +1 @@
1
+ nextpipe==0.1.0.dev3
@@ -0,0 +1 @@
1
+ __version__ = "v0.1.0.dev6"
@@ -2,12 +2,16 @@
2
2
 
3
3
  from .__about__ import __version__
4
4
  from .decorators import app as app
5
+ from .decorators import foreach as foreach
6
+ from .decorators import join as join
5
7
  from .decorators import needs as needs
6
8
  from .decorators import optional as optional
7
9
  from .decorators import repeat as repeat
8
10
  from .decorators import step as step
9
11
  from .flow import FlowGraph as FlowGraph
10
12
  from .flow import FlowSpec as FlowSpec
13
+ from .schema import AppOption as AppOption
14
+ from .schema import AppRunConfig as AppRunConfig
11
15
 
12
16
  VERSION = __version__
13
17
  """The version of the nextpipe package."""
@@ -0,0 +1,22 @@
1
+ from dataclasses import dataclass
2
+
3
+ from dataclasses_json import dataclass_json
4
+
5
+
6
+ @dataclass_json
7
+ @dataclass
8
+ class Configuration:
9
+ """Configuration for the pipeline."""
10
+
11
+ thread_count: int = 0
12
+ """
13
+ Number of threads to use for parallel processing.
14
+ If 0, the number of threads is set to the number of available CPUs.
15
+ """
16
+ max_step_inputs: int = 50
17
+ """
18
+ Maximum number of inputs to a step.
19
+ This is used to avoid accidental combinatorial explosions due to the Cartesian product
20
+ of inputs used when a step has multiple predecessors which are themselves repeated or
21
+ foreach steps.
22
+ """