nextmv 0.34.0.dev3__tar.gz → 0.34.1.dev1__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.
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/PKG-INFO +1 -1
- nextmv-0.34.1.dev1/nextmv/__about__.py +1 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/local/application.py +13 -13
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/manifest.py +73 -4
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/run.py +4 -3
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/local/test_executor.py +44 -12
- nextmv-0.34.0.dev3/nextmv/__about__.py +0 -1
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/.gitignore +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/LICENSE +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/README.md +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/__entrypoint__.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/__init__.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/_serialization.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/base_model.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/__init__.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/acceptance_test.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/account.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/application.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/batch_experiment.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/client.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/ensemble.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/input_set.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/instance.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/package.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/scenario.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/secrets.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/url.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/cloud/version.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/default_app/.gitignore +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/default_app/README.md +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/default_app/app.yaml +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/default_app/input.json +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/default_app/main.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/default_app/requirements.txt +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/default_app/src/__init__.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/default_app/src/main.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/default_app/src/visuals.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/deprecated.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/input.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/local/__init__.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/local/executor.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/local/geojson_handler.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/local/local.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/local/plotly_handler.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/local/runner.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/logger.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/model.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/options.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/output.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/polling.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/safe.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/nextmv/status.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/pyproject.toml +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/__init__.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/cloud/__init__.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/cloud/app.yaml +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/cloud/test_client.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/cloud/test_package.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/cloud/test_scenario.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/local/__init__.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/local/test_application.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/local/test_runner.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/scripts/__init__.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/scripts/options1.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/scripts/options2.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/scripts/options3.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/scripts/options4.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/scripts/options5.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/scripts/options6.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/scripts/options7.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/scripts/options_deprecated.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_base_model.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_entrypoint/__init__.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_entrypoint/test_entrypoint.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_input.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_inputs/test_data.csv +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_inputs/test_data.json +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_inputs/test_data.txt +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_logger.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_manifest.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_model.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_options.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_output.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_polling.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_run.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_safe.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_serialization.py +0 -0
- {nextmv-0.34.0.dev3 → nextmv-0.34.1.dev1}/tests/test_version.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "v0.34.1.dev1"
|
|
@@ -892,9 +892,6 @@ class Application:
|
|
|
892
892
|
Auxiliary function to validate the directory path and configuration.
|
|
893
893
|
"""
|
|
894
894
|
|
|
895
|
-
if input_dir_path is None or input_dir_path == "":
|
|
896
|
-
return
|
|
897
|
-
|
|
898
895
|
if configuration is None:
|
|
899
896
|
if self.manifest.configuration is not None and self.manifest.configuration.content is not None:
|
|
900
897
|
configuration = RunConfiguration(
|
|
@@ -904,18 +901,21 @@ class Application:
|
|
|
904
901
|
),
|
|
905
902
|
),
|
|
906
903
|
)
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
"the application's manifest (app.yaml) must include the format under "
|
|
911
|
-
"`configuration.content.format`.",
|
|
912
|
-
)
|
|
913
|
-
|
|
914
|
-
# Forcefully turn the configuration into a RunConfiguration object to
|
|
915
|
-
# make it easier to deal with in the other functions.
|
|
916
|
-
if isinstance(configuration, dict):
|
|
904
|
+
elif isinstance(configuration, dict):
|
|
905
|
+
# Forcefully turn the configuration into a RunConfiguration object to
|
|
906
|
+
# make it easier to deal with in the other functions.
|
|
917
907
|
configuration = RunConfiguration.from_dict(configuration)
|
|
918
908
|
|
|
909
|
+
if input_dir_path is None or input_dir_path == "":
|
|
910
|
+
return configuration
|
|
911
|
+
|
|
912
|
+
if configuration is None:
|
|
913
|
+
raise ValueError(
|
|
914
|
+
"If `dir_path` is provided, either a `RunConfiguration` must also be provided or "
|
|
915
|
+
"the application's manifest (app.yaml) must include the format under "
|
|
916
|
+
"`configuration.content.format`.",
|
|
917
|
+
)
|
|
918
|
+
|
|
919
919
|
config_format = configuration.format
|
|
920
920
|
if config_format is None:
|
|
921
921
|
raise ValueError(
|
|
@@ -11,6 +11,8 @@ ManifestType
|
|
|
11
11
|
Enum for application types based on programming language.
|
|
12
12
|
ManifestRuntime
|
|
13
13
|
Enum for runtime environments where apps run on Nextmv.
|
|
14
|
+
ManifestPythonArch
|
|
15
|
+
Enum for target architecture for bundling Python apps.
|
|
14
16
|
ManifestBuild
|
|
15
17
|
Class for build-specific attributes in the manifest.
|
|
16
18
|
ManifestPythonModel
|
|
@@ -38,6 +40,11 @@ ManifestConfiguration
|
|
|
38
40
|
Manifest
|
|
39
41
|
Main class representing an app manifest for Nextmv.
|
|
40
42
|
|
|
43
|
+
Functions
|
|
44
|
+
---------
|
|
45
|
+
default_python_manifest
|
|
46
|
+
Creates a default Python manifest as a starting point for applications.
|
|
47
|
+
|
|
41
48
|
Constants
|
|
42
49
|
--------
|
|
43
50
|
MANIFEST_FILE_NAME
|
|
@@ -331,7 +338,7 @@ class ManifestPython(BaseModel):
|
|
|
331
338
|
|
|
332
339
|
Parameters
|
|
333
340
|
----------
|
|
334
|
-
pip_requirements : Optional[str], default=None
|
|
341
|
+
pip_requirements : Optional[Union[str, list[str]]], default=None
|
|
335
342
|
Path to a requirements.txt file containing (additional) Python
|
|
336
343
|
dependencies that will be bundled with the app. Alternatively, you can provide a
|
|
337
344
|
list of strings, each representing a package to install, e.g.,
|
|
@@ -358,10 +365,11 @@ class ManifestPython(BaseModel):
|
|
|
358
365
|
default=None,
|
|
359
366
|
)
|
|
360
367
|
"""
|
|
361
|
-
Path to a requirements.txt file.
|
|
368
|
+
Path to a requirements.txt file or list of packages.
|
|
362
369
|
|
|
363
370
|
Contains (additional) Python dependencies that will be bundled with the
|
|
364
|
-
app.
|
|
371
|
+
app. Can be either a string path to a requirements.txt file or a list
|
|
372
|
+
of package specifications.
|
|
365
373
|
"""
|
|
366
374
|
arch: Optional[ManifestPythonArch] = None
|
|
367
375
|
"""
|
|
@@ -383,6 +391,31 @@ class ManifestPython(BaseModel):
|
|
|
383
391
|
@field_validator("version", mode="before")
|
|
384
392
|
@classmethod
|
|
385
393
|
def validate_version(cls, v: Optional[Union[str, float]]) -> Optional[str]:
|
|
394
|
+
"""
|
|
395
|
+
Validate and convert the Python version field to a string.
|
|
396
|
+
|
|
397
|
+
This validator allows the version to be specified as either a float or string
|
|
398
|
+
in the manifest for convenience, but ensures it's stored internally as a string.
|
|
399
|
+
|
|
400
|
+
Parameters
|
|
401
|
+
----------
|
|
402
|
+
v : Optional[Union[str, float]]
|
|
403
|
+
The version value to validate. Can be None, a string, or a float.
|
|
404
|
+
|
|
405
|
+
Returns
|
|
406
|
+
-------
|
|
407
|
+
Optional[str]
|
|
408
|
+
The version as a string, or None if the input was None.
|
|
409
|
+
|
|
410
|
+
Examples
|
|
411
|
+
--------
|
|
412
|
+
>>> ManifestPython.validate_version(3.11)
|
|
413
|
+
'3.11'
|
|
414
|
+
>>> ManifestPython.validate_version("3.11")
|
|
415
|
+
'3.11'
|
|
416
|
+
>>> ManifestPython.validate_version(None) is None
|
|
417
|
+
True
|
|
418
|
+
"""
|
|
386
419
|
# We allow the version to be a float in the manifest for convenience, but we want
|
|
387
420
|
# to store it as a string internally.
|
|
388
421
|
if v is None:
|
|
@@ -917,7 +950,23 @@ class ManifestContent(BaseModel):
|
|
|
917
950
|
"""Configuration for multi-file content format."""
|
|
918
951
|
|
|
919
952
|
def model_post_init(self, __context) -> None:
|
|
920
|
-
"""
|
|
953
|
+
"""
|
|
954
|
+
Post-initialization validation to ensure format field contains valid values.
|
|
955
|
+
|
|
956
|
+
This method is automatically called by Pydantic after the model is initialized
|
|
957
|
+
to validate that the format field contains one of the acceptable values.
|
|
958
|
+
|
|
959
|
+
Parameters
|
|
960
|
+
----------
|
|
961
|
+
__context : Any
|
|
962
|
+
Pydantic context (unused in this implementation).
|
|
963
|
+
|
|
964
|
+
Raises
|
|
965
|
+
------
|
|
966
|
+
ValueError
|
|
967
|
+
If the format field contains an invalid value that is not one of the
|
|
968
|
+
acceptable formats (JSON, MULTI_FILE, or CSV_ARCHIVE).
|
|
969
|
+
"""
|
|
921
970
|
acceptable_formats = [InputFormat.JSON, InputFormat.MULTI_FILE, InputFormat.CSV_ARCHIVE]
|
|
922
971
|
if self.format not in acceptable_formats:
|
|
923
972
|
raise ValueError(f"Invalid format: {self.format}. Must be one of {acceptable_formats}.")
|
|
@@ -1084,6 +1133,26 @@ class Manifest(BaseModel):
|
|
|
1084
1133
|
"""
|
|
1085
1134
|
|
|
1086
1135
|
def model_post_init(self, __context) -> None:
|
|
1136
|
+
"""
|
|
1137
|
+
Post-initialization to set default entrypoint based on runtime if not specified.
|
|
1138
|
+
|
|
1139
|
+
This method is automatically called by Pydantic after the model is initialized.
|
|
1140
|
+
If no entrypoint is provided, it sets a default entrypoint based on the runtime:
|
|
1141
|
+
- Python runtimes (PYTHON, HEXALY, PYOMO, CUOPT): "./main.py"
|
|
1142
|
+
- DEFAULT runtime: "./main"
|
|
1143
|
+
- JAVA runtime: "./main.jar"
|
|
1144
|
+
|
|
1145
|
+
Parameters
|
|
1146
|
+
----------
|
|
1147
|
+
__context : Any
|
|
1148
|
+
Pydantic context (unused in this implementation).
|
|
1149
|
+
|
|
1150
|
+
Raises
|
|
1151
|
+
------
|
|
1152
|
+
ValueError
|
|
1153
|
+
If no entrypoint is provided and the runtime cannot be resolved to
|
|
1154
|
+
establish a default entrypoint.
|
|
1155
|
+
"""
|
|
1087
1156
|
if self.entrypoint is None:
|
|
1088
1157
|
if self.runtime in (
|
|
1089
1158
|
ManifestRuntime.PYTHON,
|
|
@@ -682,9 +682,10 @@ class Metadata(BaseModel):
|
|
|
682
682
|
"""Format of the input and output of the run."""
|
|
683
683
|
status_v2: StatusV2
|
|
684
684
|
"""Status of the run."""
|
|
685
|
-
|
|
686
685
|
status: Optional[Status] = None
|
|
687
686
|
"""Deprecated: use status_v2."""
|
|
687
|
+
statistics: Optional[dict[str, Any]] = None
|
|
688
|
+
"""User defined statistics of the run."""
|
|
688
689
|
|
|
689
690
|
|
|
690
691
|
class SyncedRun(BaseModel):
|
|
@@ -1560,9 +1561,9 @@ class TrackedRun:
|
|
|
1560
1561
|
|
|
1561
1562
|
if isinstance(self.output, Output):
|
|
1562
1563
|
try:
|
|
1563
|
-
_ = serialize_json(self.output.
|
|
1564
|
+
_ = serialize_json(self.output.solution)
|
|
1564
1565
|
except (TypeError, OverflowError) as e:
|
|
1565
|
-
raise ValueError("Output.
|
|
1566
|
+
raise ValueError("`Output.solution` is not JSON serializable") from e
|
|
1566
1567
|
elif isinstance(self.output, dict):
|
|
1567
1568
|
try:
|
|
1568
1569
|
_ = serialize_json(self.output)
|
|
@@ -274,11 +274,11 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
274
274
|
logs_dir = os.path.join(self.run_dir, "logs")
|
|
275
275
|
self.assertTrue(os.path.exists(logs_dir))
|
|
276
276
|
|
|
277
|
-
# Check that
|
|
278
|
-
|
|
279
|
-
self.assertTrue(os.path.exists(
|
|
277
|
+
# Check that logs.log was created with correct content
|
|
278
|
+
logs_file = os.path.join(logs_dir, "logs.log")
|
|
279
|
+
self.assertTrue(os.path.exists(logs_file))
|
|
280
280
|
|
|
281
|
-
with open(
|
|
281
|
+
with open(logs_file) as f:
|
|
282
282
|
content = f.read()
|
|
283
283
|
|
|
284
284
|
self.assertEqual(content, "Error line 1\nError line 2\n")
|
|
@@ -299,7 +299,12 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
299
299
|
stdout_output = {}
|
|
300
300
|
|
|
301
301
|
process_run_statistics(
|
|
302
|
-
temp_outputs_dir,
|
|
302
|
+
temp_outputs_dir,
|
|
303
|
+
outputs_dir,
|
|
304
|
+
stdout_output,
|
|
305
|
+
temp_src=self.temp_src,
|
|
306
|
+
manifest=self.mock_manifest,
|
|
307
|
+
src=self.test_dir,
|
|
303
308
|
)
|
|
304
309
|
|
|
305
310
|
# Check that statistics directory was copied
|
|
@@ -316,7 +321,12 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
316
321
|
stdout_output = {STATISTICS_KEY: {"duration": 2.5, "iterations": 100}}
|
|
317
322
|
|
|
318
323
|
process_run_statistics(
|
|
319
|
-
temp_outputs_dir,
|
|
324
|
+
temp_outputs_dir,
|
|
325
|
+
outputs_dir,
|
|
326
|
+
stdout_output,
|
|
327
|
+
temp_src=self.temp_src,
|
|
328
|
+
manifest=self.mock_manifest,
|
|
329
|
+
src=self.test_dir,
|
|
320
330
|
)
|
|
321
331
|
|
|
322
332
|
# Check that statistics.json was created
|
|
@@ -341,7 +351,12 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
341
351
|
stdout_output = {}
|
|
342
352
|
|
|
343
353
|
process_run_statistics(
|
|
344
|
-
temp_outputs_dir,
|
|
354
|
+
temp_outputs_dir,
|
|
355
|
+
outputs_dir,
|
|
356
|
+
stdout_output,
|
|
357
|
+
temp_src=self.temp_src,
|
|
358
|
+
manifest=self.mock_manifest,
|
|
359
|
+
src=self.test_dir,
|
|
345
360
|
)
|
|
346
361
|
|
|
347
362
|
# Check that statistics directory was not created
|
|
@@ -364,7 +379,12 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
364
379
|
stdout_output = {}
|
|
365
380
|
|
|
366
381
|
process_run_assets(
|
|
367
|
-
temp_outputs_dir,
|
|
382
|
+
temp_outputs_dir,
|
|
383
|
+
outputs_dir,
|
|
384
|
+
stdout_output,
|
|
385
|
+
temp_src=self.temp_src,
|
|
386
|
+
manifest=self.mock_manifest,
|
|
387
|
+
src=self.test_dir,
|
|
368
388
|
)
|
|
369
389
|
|
|
370
390
|
# Check that assets directory was copied
|
|
@@ -386,7 +406,12 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
386
406
|
}
|
|
387
407
|
|
|
388
408
|
process_run_assets(
|
|
389
|
-
temp_outputs_dir,
|
|
409
|
+
temp_outputs_dir,
|
|
410
|
+
outputs_dir,
|
|
411
|
+
stdout_output,
|
|
412
|
+
temp_src=self.temp_src,
|
|
413
|
+
manifest=self.mock_manifest,
|
|
414
|
+
src=self.test_dir,
|
|
390
415
|
)
|
|
391
416
|
|
|
392
417
|
# Check that assets.json was created
|
|
@@ -429,6 +454,7 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
429
454
|
stdout_output,
|
|
430
455
|
output_format=OutputFormat.CSV_ARCHIVE,
|
|
431
456
|
manifest=self.mock_manifest,
|
|
457
|
+
src=self.test_dir,
|
|
432
458
|
)
|
|
433
459
|
|
|
434
460
|
# Check that solutions directory was created and files copied
|
|
@@ -463,6 +489,7 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
463
489
|
stdout_output,
|
|
464
490
|
output_format=OutputFormat.MULTI_FILE,
|
|
465
491
|
manifest=self.mock_manifest,
|
|
492
|
+
src=self.test_dir,
|
|
466
493
|
)
|
|
467
494
|
|
|
468
495
|
# Check that solutions directory was created and files copied
|
|
@@ -490,6 +517,7 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
490
517
|
stdout_output,
|
|
491
518
|
output_format=self.mock_output_format,
|
|
492
519
|
manifest=self.mock_manifest,
|
|
520
|
+
src=self.test_dir,
|
|
493
521
|
)
|
|
494
522
|
|
|
495
523
|
# Check that solution.json was created
|
|
@@ -524,6 +552,7 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
524
552
|
stdout_output,
|
|
525
553
|
output_format=self.mock_output_format,
|
|
526
554
|
manifest=self.mock_manifest,
|
|
555
|
+
src=self.test_dir,
|
|
527
556
|
)
|
|
528
557
|
|
|
529
558
|
# Check that solutions directory was created
|
|
@@ -609,6 +638,7 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
609
638
|
temp_src=temp_src,
|
|
610
639
|
result=mock_result,
|
|
611
640
|
run_dir="/test/run_dir",
|
|
641
|
+
src="/test/src",
|
|
612
642
|
)
|
|
613
643
|
|
|
614
644
|
def test_process_run_output_with_valid_json(self):
|
|
@@ -636,6 +666,7 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
636
666
|
temp_src=self.temp_src,
|
|
637
667
|
result=mock_result,
|
|
638
668
|
run_dir=self.run_dir,
|
|
669
|
+
src=self.test_dir,
|
|
639
670
|
)
|
|
640
671
|
|
|
641
672
|
# Verify all processing functions were called
|
|
@@ -674,11 +705,12 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
674
705
|
temp_src=self.temp_src,
|
|
675
706
|
result=mock_result,
|
|
676
707
|
run_dir=self.run_dir,
|
|
708
|
+
src=self.test_dir,
|
|
677
709
|
)
|
|
678
710
|
|
|
679
|
-
# Verify all processing functions were called with empty
|
|
711
|
+
# Verify all processing functions were called with empty string
|
|
680
712
|
mock_logs.assert_called_once_with(
|
|
681
|
-
output_format=unittest.mock.ANY, run_dir=self.run_dir, result=mock_result, stdout_output=
|
|
713
|
+
output_format=unittest.mock.ANY, run_dir=self.run_dir, result=mock_result, stdout_output=""
|
|
682
714
|
)
|
|
683
715
|
mock_stats.assert_called_once()
|
|
684
716
|
mock_assets.assert_called_once()
|
|
@@ -686,7 +718,7 @@ class TestLocalExecutor(unittest.TestCase):
|
|
|
686
718
|
|
|
687
719
|
# Get the stdout_output that was passed to the functions
|
|
688
720
|
stdout_output = mock_stats.call_args.kwargs["stdout_output"]
|
|
689
|
-
self.assertEqual(stdout_output,
|
|
721
|
+
self.assertEqual(stdout_output, "")
|
|
690
722
|
|
|
691
723
|
|
|
692
724
|
if __name__ == "__main__":
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "v0.34.0.dev3"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|