nextpipe 0.6.2.dev3__tar.gz → 0.6.2.dev4__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 (107) hide show
  1. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/PKG-INFO +2 -2
  2. nextpipe-0.6.2.dev4/nextpipe/__about__.py +1 -0
  3. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/nextpipe/decorators.py +15 -0
  4. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/nextpipe/flow.py +27 -5
  5. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/nextpipe/utils.py +8 -2
  6. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/pyproject.toml +1 -1
  7. nextpipe-0.6.2.dev3/nextpipe/__about__.py +0 -1
  8. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/.github/workflows/lint.yml +0 -0
  9. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/.github/workflows/release.yml +0 -0
  10. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/.github/workflows/test.yml +0 -0
  11. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/.gitignore +0 -0
  12. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/.markdownlint.jsonc +0 -0
  13. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/.nextmv/bump_requirements.sh +0 -0
  14. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/.prettierrc.yml +0 -0
  15. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/.readthedocs.yaml +0 -0
  16. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/LICENSE.md +0 -0
  17. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/README.md +0 -0
  18. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/RELEASE.md +0 -0
  19. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/examples/basic-chained-workflow.md +0 -0
  20. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/examples/complex-workflow-csv.md +0 -0
  21. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/examples/complex-workflow.md +0 -0
  22. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/examples/ensemble-workflow.md +0 -0
  23. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/examples/fanout-workflow.md +0 -0
  24. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/examples/multifile-workflow.md +0 -0
  25. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/active-plan.png +0 -0
  26. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/api-keys.png +0 -0
  27. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/app-diagram.png +0 -0
  28. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/apps-orchestrate-full.png +0 -0
  29. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/apps-orchestrate.png +0 -0
  30. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/innovator.png +0 -0
  31. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/logo-180.png +0 -0
  32. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/new-run-orchestrate.png +0 -0
  33. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/nextmv-favicon.svg +0 -0
  34. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/plans.png +0 -0
  35. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/pushed-app.png +0 -0
  36. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/routing-ortools-pyvroom-selected.png +0 -0
  37. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/routing-selected.png +0 -0
  38. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/run-metadata.png +0 -0
  39. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/run-summary.png +0 -0
  40. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/run-workflow.png +0 -0
  41. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/secrets-collection-orchestrate.png +0 -0
  42. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/images/workflow-diagram.png +0 -0
  43. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/index.md +0 -0
  44. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/reference/config.md +0 -0
  45. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/reference/decorators.md +0 -0
  46. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/reference/echo-multi.md +0 -0
  47. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/reference/echo.md +0 -0
  48. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/reference/flow.md +0 -0
  49. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/reference/graph.md +0 -0
  50. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/reference/schema.md +0 -0
  51. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/reference/threads.md +0 -0
  52. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/reference/uplink.md +0 -0
  53. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/reference/utils.md +0 -0
  54. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/requirements.txt +0 -0
  55. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/docs/tutorials/orchestrate-multiple-models.md +0 -0
  56. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/mkdocs.yml +0 -0
  57. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/nextpipe/__init__.py +0 -0
  58. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/nextpipe/config.py +0 -0
  59. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/nextpipe/constants.py +0 -0
  60. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/nextpipe/graph.py +0 -0
  61. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/nextpipe/schema.py +0 -0
  62. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/nextpipe/threads.py +0 -0
  63. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/nextpipe/uplink.py +0 -0
  64. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/nextpipe.code-workspace +0 -0
  65. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/.gitignore +0 -0
  66. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/README.md +0 -0
  67. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/__init__.py +0 -0
  68. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo/.gitignore +0 -0
  69. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo/README.md +0 -0
  70. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo/app.yaml +0 -0
  71. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo/main.py +0 -0
  72. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo/requirements.txt +0 -0
  73. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo-multi/.gitignore +0 -0
  74. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo-multi/README.md +0 -0
  75. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo-multi/app.yaml +0 -0
  76. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo-multi/inputs/data.csv +0 -0
  77. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo-multi/inputs/input.xlsx +0 -0
  78. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo-multi/main.py +0 -0
  79. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/apps/echo-multi/requirements.txt +0 -0
  80. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/deploy/app.yaml +0 -0
  81. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/deploy/main.py +0 -0
  82. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/deploy/requirements.txt +0 -0
  83. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/appapp.json +0 -0
  84. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/appapp.json.golden +0 -0
  85. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/appapp.py +0 -0
  86. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/chain.json +0 -0
  87. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/chain.json.golden +0 -0
  88. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/chain.py +0 -0
  89. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/complex.json +0 -0
  90. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/complex.json.golden +0 -0
  91. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/complex.py +0 -0
  92. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/fail.py +0 -0
  93. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/foreach-2-pred.json +0 -0
  94. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/foreach-2-pred.json.golden +0 -0
  95. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/foreach-2-pred.py +0 -0
  96. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/foreach.json +0 -0
  97. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/foreach.json.golden +0 -0
  98. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/foreach.py +0 -0
  99. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/inputs/data.csv +0 -0
  100. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/inputs/input.xlsx +0 -0
  101. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/pipelines/multifile.py +0 -0
  102. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/test_graph.py +0 -0
  103. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/test_integration.py +0 -0
  104. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/test_schema.py +0 -0
  105. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/test_threads.py +0 -0
  106. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/test_uplink.py +0 -0
  107. {nextpipe-0.6.2.dev3 → nextpipe-0.6.2.dev4}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextpipe
3
- Version: 0.6.2.dev3
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>=0.40.0
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 @@
1
+ __version__ = "v0.6.2-dev.4"
@@ -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
 
@@ -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
@@ -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="unavailable",
1038
- duration="unavailable",
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
- for filename in os.listdir(app_step.bypass_result):
1056
- shutil.copy(os.path.join(app_step.bypass_result, filename), temp_dir)
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
@@ -46,7 +46,10 @@ def __get_step_name() -> str:
46
46
  return "main"
47
47
 
48
48
 
49
- def log(message: str) -> None:
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:
@@ -17,7 +17,7 @@ classifiers = [
17
17
  ]
18
18
  dependencies = [
19
19
  "requests>=2.31.0",
20
- "nextmv>=0.40.0",
20
+ "nextmv>=1.2.2",
21
21
  "dataclasses-json>=0.6.7",
22
22
  ]
23
23
  description = "Framework for Decision Pipeline modeling and execution"
@@ -1 +0,0 @@
1
- __version__ = "v0.6.2-dev.3"
File without changes
File without changes
File without changes
File without changes
File without changes