nextpipe 0.6.2.dev2__py3-none-any.whl → 0.6.2.dev4__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.
- nextpipe/__about__.py +1 -1
- nextpipe/constants.py +12 -1
- nextpipe/decorators.py +15 -0
- nextpipe/flow.py +29 -7
- nextpipe/uplink.py +2 -2
- nextpipe/utils.py +8 -2
- {nextpipe-0.6.2.dev2.dist-info → nextpipe-0.6.2.dev4.dist-info}/METADATA +2 -2
- nextpipe-0.6.2.dev4.dist-info/RECORD +15 -0
- nextpipe-0.6.2.dev2.dist-info/RECORD +0 -15
- {nextpipe-0.6.2.dev2.dist-info → nextpipe-0.6.2.dev4.dist-info}/WHEEL +0 -0
- {nextpipe-0.6.2.dev2.dist-info → nextpipe-0.6.2.dev4.dist-info}/licenses/LICENSE.md +0 -0
nextpipe/__about__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "v0.6.2-dev.
|
|
1
|
+
__version__ = "v0.6.2-dev.4"
|
nextpipe/constants.py
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Constants for nextpipe.
|
|
3
|
+
|
|
4
|
+
This module provides constants used across the nextpipe package.
|
|
5
|
+
|
|
6
|
+
Functions
|
|
7
|
+
--------
|
|
8
|
+
_get_run_info
|
|
9
|
+
Retrieves information about the run from environment variables.
|
|
10
|
+
"""
|
|
11
|
+
|
|
1
12
|
import os
|
|
2
13
|
|
|
3
14
|
ENV_APP_ID = "NEXTMV_APP_ID"
|
|
@@ -7,7 +18,7 @@ ENV_RUN_ID = "NEXTMV_RUN_ID"
|
|
|
7
18
|
"""Environment variable name for the run ID."""
|
|
8
19
|
|
|
9
20
|
|
|
10
|
-
def
|
|
21
|
+
def _get_run_info():
|
|
11
22
|
"""
|
|
12
23
|
Retrieves information about the run from environment variables.
|
|
13
24
|
If the environment variables are not set, it returns None for both values.
|
nextpipe/decorators.py
CHANGED
|
@@ -769,6 +769,11 @@ class App:
|
|
|
769
769
|
The configuration to apply when running the app.
|
|
770
770
|
polling_options : Optional[nextmv.PollingOptions]
|
|
771
771
|
Options for polling for the results of the app run.
|
|
772
|
+
bypass_result : typing.Any
|
|
773
|
+
A value that can be provided to bypass the actual execution of the app.
|
|
774
|
+
emit_live_logs : bool
|
|
775
|
+
Whether to emit live logs from the application run. If set to `True`, logs from
|
|
776
|
+
the sub-run will be relayed to the workflow.
|
|
772
777
|
"""
|
|
773
778
|
|
|
774
779
|
def __init__(
|
|
@@ -782,6 +787,7 @@ class App:
|
|
|
782
787
|
run_configuration: nextmv.RunConfiguration = None,
|
|
783
788
|
polling_options: nextmv.PollingOptions | None = nextmv.DEFAULT_POLLING_OPTIONS,
|
|
784
789
|
bypass_result: typing.Any = None,
|
|
790
|
+
emit_live_logs: bool = False,
|
|
785
791
|
):
|
|
786
792
|
"""
|
|
787
793
|
Initialize an App object.
|
|
@@ -803,6 +809,9 @@ class App:
|
|
|
803
809
|
bypass_result : typing.Any, optional
|
|
804
810
|
A value that can be provided to bypass the actual execution of the app.
|
|
805
811
|
This is mainly used for testing purposes, by default None.
|
|
812
|
+
emit_live_logs : bool, optional
|
|
813
|
+
Whether to emit live logs from the application run. If set to `True`, logs
|
|
814
|
+
from the sub-run will be relayed to the workflow. Default is False.
|
|
806
815
|
"""
|
|
807
816
|
|
|
808
817
|
if input_type:
|
|
@@ -829,6 +838,7 @@ class App:
|
|
|
829
838
|
self.run_configuration = run_configuration
|
|
830
839
|
self.polling_options = polling_options
|
|
831
840
|
self.bypass_result = bypass_result
|
|
841
|
+
self.emit_live_logs = emit_live_logs
|
|
832
842
|
|
|
833
843
|
def __repr__(self):
|
|
834
844
|
"""Return a string representation of the app.
|
|
@@ -852,6 +862,7 @@ def app(
|
|
|
852
862
|
run_configuration: nextmv.RunConfiguration = None,
|
|
853
863
|
polling_options: nextmv.PollingOptions | None = nextmv.DEFAULT_POLLING_OPTIONS,
|
|
854
864
|
bypass_result: typing.Any = None,
|
|
865
|
+
emit_live_logs: bool = False,
|
|
855
866
|
):
|
|
856
867
|
"""
|
|
857
868
|
Decorator to mark a step as a Nextmv Application (external application)
|
|
@@ -894,6 +905,9 @@ def app(
|
|
|
894
905
|
bypass_result : typing.Any, optional
|
|
895
906
|
A value that can be provided to bypass the actual execution of the app.
|
|
896
907
|
This is mainly used for testing purposes, by default None.
|
|
908
|
+
emit_live_logs : bool
|
|
909
|
+
Whether to emit live logs from the application run. If set to `True`, logs from
|
|
910
|
+
the sub-run will be relayed to the workflow.
|
|
897
911
|
|
|
898
912
|
Example
|
|
899
913
|
-------
|
|
@@ -967,6 +981,7 @@ def app(
|
|
|
967
981
|
run_configuration=run_configuration,
|
|
968
982
|
polling_options=polling_options,
|
|
969
983
|
bypass_result=bypass_result,
|
|
984
|
+
emit_live_logs=emit_live_logs,
|
|
970
985
|
)
|
|
971
986
|
wrapper.step.type = StepType.APP
|
|
972
987
|
|
nextpipe/flow.py
CHANGED
|
@@ -25,9 +25,11 @@ The module also defines status constants used throughout pipeline execution.
|
|
|
25
25
|
import ast
|
|
26
26
|
import base64
|
|
27
27
|
import copy
|
|
28
|
+
import datetime
|
|
28
29
|
import inspect
|
|
29
30
|
import io
|
|
30
31
|
import os
|
|
32
|
+
import pathlib
|
|
31
33
|
import random
|
|
32
34
|
import shutil
|
|
33
35
|
import tempfile
|
|
@@ -40,7 +42,7 @@ from typing import Any
|
|
|
40
42
|
import nextmv
|
|
41
43
|
from nextmv.cloud import Application, Client
|
|
42
44
|
|
|
43
|
-
from nextpipe.constants import
|
|
45
|
+
from nextpipe.constants import _get_run_info
|
|
44
46
|
|
|
45
47
|
from . import config, decorators, graph, schema, threads, uplink, utils
|
|
46
48
|
from .__about__ import __version__
|
|
@@ -885,7 +887,7 @@ class Runner:
|
|
|
885
887
|
"""
|
|
886
888
|
Determine name and description to use for sub-runs.
|
|
887
889
|
"""
|
|
888
|
-
wf_app_id, wf_run_id =
|
|
890
|
+
wf_app_id, wf_run_id = _get_run_info()
|
|
889
891
|
wf_app_id = wf_app_id or app_step_id # Fallback if dynamic detection fails
|
|
890
892
|
wf_run_id = wf_run_id or "local" # Use "local" for non-platform runs
|
|
891
893
|
step_name = step_name[:50] # Truncate step name to 50 chars to keep overall name within limits
|
|
@@ -1014,16 +1016,29 @@ class Runner:
|
|
|
1014
1016
|
# Run the application
|
|
1015
1017
|
try:
|
|
1016
1018
|
if app_step.bypass_result is None:
|
|
1019
|
+
# Start the run.
|
|
1017
1020
|
run_id = app.new_run(*run_args[0], **run_args[1])
|
|
1018
1021
|
console_url = f"{client.console_url}/app/{app_step.app_id}/run/{run_id}?view=details"
|
|
1019
1022
|
utils.log_internal(f"Started app step {node.id} run, find it at {console_url}")
|
|
1020
1023
|
node.run_id = run_id
|
|
1021
1024
|
update_dag() # Update the node with the run_id before we start polling for results
|
|
1025
|
+
|
|
1026
|
+
# Emit live logs if requested.
|
|
1027
|
+
if app_step.emit_live_logs:
|
|
1028
|
+
utils.log_internal(f"Emitting live logs for app step {node.id} ...")
|
|
1029
|
+
app.run_logs_with_polling(
|
|
1030
|
+
run_id=run_id,
|
|
1031
|
+
verbose=True,
|
|
1032
|
+
log_func=lambda msg: utils.log(message=msg.log, step_name=node.id),
|
|
1033
|
+
)
|
|
1034
|
+
|
|
1035
|
+
# Wait for run to finish and get the result.
|
|
1022
1036
|
result = app.run_result_with_polling(
|
|
1023
1037
|
run_id=run_id, polling_options=polling_options, output_dir_path=temp_dir
|
|
1024
1038
|
)
|
|
1025
1039
|
else:
|
|
1026
1040
|
utils.log_internal(f"Bypassing app step {node.id} run, using bypass result")
|
|
1041
|
+
|
|
1027
1042
|
# We wrap the bypass result in a dummy RunResult to ensure consistent behavior.
|
|
1028
1043
|
result = nextmv.RunResult(
|
|
1029
1044
|
id="bypassed-run",
|
|
@@ -1034,8 +1049,8 @@ class Runner:
|
|
|
1034
1049
|
application_id="unavailable",
|
|
1035
1050
|
application_instance_id="unavailable",
|
|
1036
1051
|
application_version_id="unavailable",
|
|
1037
|
-
created_at=
|
|
1038
|
-
duration=
|
|
1052
|
+
created_at=datetime.datetime.now(),
|
|
1053
|
+
duration=0.0,
|
|
1039
1054
|
error="unavailable",
|
|
1040
1055
|
input_size=0.0,
|
|
1041
1056
|
output_size=0.0,
|
|
@@ -1048,12 +1063,19 @@ class Runner:
|
|
|
1048
1063
|
),
|
|
1049
1064
|
status_v2=nextmv.StatusV2.succeeded,
|
|
1050
1065
|
),
|
|
1051
|
-
output=app_step.bypass_result,
|
|
1052
1066
|
)
|
|
1067
|
+
result.output = app_step.bypass_result
|
|
1068
|
+
|
|
1053
1069
|
# If the user supplied a bypass result, we need to write it to the temp dir if it's in dir mode
|
|
1054
1070
|
if isinstance(app_step.bypass_result, str) and os.path.isdir(app_step.bypass_result):
|
|
1055
|
-
|
|
1056
|
-
|
|
1071
|
+
src = pathlib.Path(app_step.bypass_result)
|
|
1072
|
+
dst = pathlib.Path(temp_dir)
|
|
1073
|
+
for item in src.iterdir():
|
|
1074
|
+
if item.is_file():
|
|
1075
|
+
shutil.copy2(item, dst / item.name)
|
|
1076
|
+
elif item.is_dir():
|
|
1077
|
+
shutil.copytree(item, dst / item.name)
|
|
1078
|
+
|
|
1057
1079
|
finally: # Make sure we clean up temp dir on failure too
|
|
1058
1080
|
# If the temp dir is empty, remove it
|
|
1059
1081
|
dir_result = False
|
nextpipe/uplink.py
CHANGED
|
@@ -34,7 +34,7 @@ from dataclasses import dataclass, field
|
|
|
34
34
|
from dataclasses_json import config, dataclass_json
|
|
35
35
|
from nextmv.cloud import Client
|
|
36
36
|
|
|
37
|
-
from nextpipe.constants import
|
|
37
|
+
from nextpipe.constants import _get_run_info
|
|
38
38
|
from nextpipe.utils import log_internal
|
|
39
39
|
|
|
40
40
|
FAILED_UPDATES_THRESHOLD = 10
|
|
@@ -272,7 +272,7 @@ class UplinkClient:
|
|
|
272
272
|
|
|
273
273
|
if config is None:
|
|
274
274
|
# Load config from environment
|
|
275
|
-
app_id, run_id =
|
|
275
|
+
app_id, run_id = _get_run_info()
|
|
276
276
|
config = UplinkConfig(application_id=app_id, run_id=run_id)
|
|
277
277
|
self.config = config
|
|
278
278
|
self.inactive = False
|
nextpipe/utils.py
CHANGED
|
@@ -46,7 +46,10 @@ def __get_step_name() -> str:
|
|
|
46
46
|
return "main"
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
def log(
|
|
49
|
+
def log(
|
|
50
|
+
message: str,
|
|
51
|
+
step_name: str | None = None,
|
|
52
|
+
) -> None:
|
|
50
53
|
"""
|
|
51
54
|
Logs a message using stderr. Furthermore, prepends the name of the calling function if it is a step.
|
|
52
55
|
|
|
@@ -62,6 +65,9 @@ def log(message: str) -> None:
|
|
|
62
65
|
----------
|
|
63
66
|
message : str
|
|
64
67
|
The message to log.
|
|
68
|
+
step_name : str, optional
|
|
69
|
+
The name of the step to include in the log message. If not provided, it will
|
|
70
|
+
attempt to determine it automatically.
|
|
65
71
|
|
|
66
72
|
Examples
|
|
67
73
|
--------
|
|
@@ -72,7 +78,7 @@ def log(message: str) -> None:
|
|
|
72
78
|
>>> # [step_name] Processing data
|
|
73
79
|
"""
|
|
74
80
|
|
|
75
|
-
step_name = __get_step_name()
|
|
81
|
+
step_name = step_name or __get_step_name()
|
|
76
82
|
if step_name:
|
|
77
83
|
print(f"[{step_name}] {message}", file=sys.stderr)
|
|
78
84
|
else:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nextpipe
|
|
3
|
-
Version: 0.6.2.
|
|
3
|
+
Version: 0.6.2.dev4
|
|
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://nextpipe.docs.nextmv.io/en/latest/
|
|
@@ -105,7 +105,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
105
105
|
Classifier: Programming Language :: Python :: 3.14
|
|
106
106
|
Requires-Python: >=3.10
|
|
107
107
|
Requires-Dist: dataclasses-json>=0.6.7
|
|
108
|
-
Requires-Dist: nextmv>=
|
|
108
|
+
Requires-Dist: nextmv>=1.2.2
|
|
109
109
|
Requires-Dist: requests>=2.31.0
|
|
110
110
|
Provides-Extra: dev
|
|
111
111
|
Requires-Dist: goldie>=0.1.8; extra == 'dev'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
nextpipe/__about__.py,sha256=KIn7qdq_AeTnzP-pjx9UBfss83kfsVtubPPrKJOBGes,29
|
|
2
|
+
nextpipe/__init__.py,sha256=SzRhi2z33zmvskfgqoRHwaKvRnt8G1_JJR1M7BXlda0,694
|
|
3
|
+
nextpipe/config.py,sha256=JSShEaK3fnqieGofalQysKxEJUkyrWIRbwhdyH9yYZM,1659
|
|
4
|
+
nextpipe/constants.py,sha256=ws1_khUbZFau_kShi6nweLhg24_2fjPWyXY6VPVAH7E,667
|
|
5
|
+
nextpipe/decorators.py,sha256=kLYOVYqx0QWtTbVkgw6US8ZZSa0YijZ5qzMX0mRiO7k,26539
|
|
6
|
+
nextpipe/flow.py,sha256=zJLYl3ptRYxDPao0umCfMxE1gjpG_xaWNjLqT2JnQtY,43295
|
|
7
|
+
nextpipe/graph.py,sha256=Oi8HQ4fgvBYxpRK6xBoLtoxftGb-gCOb09BqFwzrwWs,2867
|
|
8
|
+
nextpipe/schema.py,sha256=HsJnzpYhemXUa8IZvFEChPB-_5YXTCbkYSPf5zpPqo8,3263
|
|
9
|
+
nextpipe/threads.py,sha256=5s7jF-hgVF_Eqfxgf6hsF6dhXsRSfqTsq5F0JBy4hNw,9039
|
|
10
|
+
nextpipe/uplink.py,sha256=oW8rIt6byUqKhex5-Nk0KwTOBuPvRAMtuDfP-fmM6_E,11475
|
|
11
|
+
nextpipe/utils.py,sha256=jAeWautNhUZsjuF00K7BVaU5grLRWlBmtLkcNnPYnXg,8279
|
|
12
|
+
nextpipe-0.6.2.dev4.dist-info/METADATA,sha256=XFGgOhlOzdhp9Q4eq1h7uTQeg6W4t3Ru5-yU44qyB5Y,8759
|
|
13
|
+
nextpipe-0.6.2.dev4.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
14
|
+
nextpipe-0.6.2.dev4.dist-info/licenses/LICENSE.md,sha256=FpVScuRcgdbeBNVsMzoPyBbKL2eCB1vFor1vfNNFEj4,4106
|
|
15
|
+
nextpipe-0.6.2.dev4.dist-info/RECORD,,
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
nextpipe/__about__.py,sha256=1-zmKDjeDRIz4nXrUOXUKYbr__bsifB-n1WTe2B-bAc,29
|
|
2
|
-
nextpipe/__init__.py,sha256=SzRhi2z33zmvskfgqoRHwaKvRnt8G1_JJR1M7BXlda0,694
|
|
3
|
-
nextpipe/config.py,sha256=JSShEaK3fnqieGofalQysKxEJUkyrWIRbwhdyH9yYZM,1659
|
|
4
|
-
nextpipe/constants.py,sha256=zvfSKKL4QDZ3D68H5bIW1YicaZf9mKEVTMFeviM3mbo,467
|
|
5
|
-
nextpipe/decorators.py,sha256=MLTwuTONn30-esVaF7q3hNdOp8AnJ5ksNswQHpFrGlE,25727
|
|
6
|
-
nextpipe/flow.py,sha256=bSiAIIMBRLSx1gYErJfm3BdsS64rnjGeW3IDL0HBDzY,42474
|
|
7
|
-
nextpipe/graph.py,sha256=Oi8HQ4fgvBYxpRK6xBoLtoxftGb-gCOb09BqFwzrwWs,2867
|
|
8
|
-
nextpipe/schema.py,sha256=HsJnzpYhemXUa8IZvFEChPB-_5YXTCbkYSPf5zpPqo8,3263
|
|
9
|
-
nextpipe/threads.py,sha256=5s7jF-hgVF_Eqfxgf6hsF6dhXsRSfqTsq5F0JBy4hNw,9039
|
|
10
|
-
nextpipe/uplink.py,sha256=I1gwTcXn-FuIwvQWC_EarrBzHQLgTIShwUQ_aHgmiuE,11477
|
|
11
|
-
nextpipe/utils.py,sha256=-ni6Em1QfatgVMh95hYSPVCdTboozB8vRKkakti3gls,8063
|
|
12
|
-
nextpipe-0.6.2.dev2.dist-info/METADATA,sha256=V842M8UKeo2nlgePGCFRlFTtD-VnTmacGkQWJ2pqB0Q,8760
|
|
13
|
-
nextpipe-0.6.2.dev2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
14
|
-
nextpipe-0.6.2.dev2.dist-info/licenses/LICENSE.md,sha256=FpVScuRcgdbeBNVsMzoPyBbKL2eCB1vFor1vfNNFEj4,4106
|
|
15
|
-
nextpipe-0.6.2.dev2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|