From 09a4963a22634382847e3bc917f92d7eace2a8c4 Mon Sep 17 00:00:00 2001 From: Godot Bian <13778003+godobyte@users.noreply.github.com> Date: Wed, 5 Nov 2025 16:07:16 -0800 Subject: [PATCH 1/3] feat: add _run_task_with_optional_env function to the Session class Signed-off-by: Godot Bian <13778003+godobyte@users.noreply.github.com> --- src/openjd/sessions/_session.py | 79 ++++ test/openjd/sessions/test_session.py | 530 +++++++++++++++++++++++++++ 2 files changed, 609 insertions(+) diff --git a/src/openjd/sessions/_session.py b/src/openjd/sessions/_session.py index cb051352..7834ae4f 100644 --- a/src/openjd/sessions/_session.py +++ b/src/openjd/sessions/_session.py @@ -843,6 +843,85 @@ def run_task( # than after -- run() itself may end up setting the action state to FAILED. self._runner.run() + def _run_task_with_optional_env( + self, + *, + step_script: StepScriptModel, + task_parameter_values: TaskParameterSet, + os_env_vars: Optional[dict[str, str]] = None, + use_session_env_vars: Optional[bool] = True, + log_task_banner: bool = True, + ) -> None: + """Run a Task within the Session. + This method is non-blocking; it will exit when the subprocess is either confirmed to have + started running, or has failed to be started. + + Arguments: + step_script (StepScriptModel): The Step Script that the Task will be running. + task_parameter_values (TaskParameterSet): Values of the Task parameters that define the + specific Task. This is a dictionary where the keys are parameter names, and the values + are instances of ParameterValue (a dataclass containing the type and value of the parameter) + os_env_vars (Optional[dict[str,str]): Definitions for additional OS Environment + Variables that should be injected into the process that is run for this action. + Values provided override values provided to the Session constructor, and are overriden + by values defined in Environments. + Key: Environment variable name + Value: Value for the environment variable. + use_session_env_vars (Optional[bool]): Whether to apply environment variable changes from + entered environments. When True (default), applies changes from all entered environments + in order. When False, only uses base session and os_env_vars. + log_task_banner (bool): Whether to log a banner before running the Task. + Default: True + """ + if self.state != SessionState.READY: + raise RuntimeError("Session must be in the READY state to run a task.") + + if log_task_banner: + log_section_banner(self._logger, "Running Task") + + if task_parameter_values: + self._logger.info( + "Parameter values:", + extra=LogExtraInfo(openjd_log_content=LogContent.PARAMETER_INFO), + ) + for name, value in task_parameter_values.items(): + self._logger.info( + f"{name}({str(value.type.value)}) = {value.value}", + extra=LogExtraInfo(openjd_log_content=LogContent.PARAMETER_INFO), + ) + + self._reset_action_state() + symtab = self._symbol_table(step_script.revision, task_parameter_values) + + # Evaluate environment variables + if use_session_env_vars: + action_env_vars = self._evaluate_current_session_env_vars(os_env_vars) + else: + action_env_vars = dict[str, Optional[str]](self._process_env) # Make a copy + if os_env_vars: + action_env_vars.update(**os_env_vars) + + self._materialize_path_mapping(step_script.revision, action_env_vars, symtab) + self._runner = StepScriptRunner( + logger=self._logger, + user=self._user, + os_env_vars=action_env_vars, + session_working_directory=self.working_directory, + startup_directory=self.working_directory, + callback=self._action_callback, + script=step_script, + symtab=symtab, + session_files_directory=self.files_directory, + ) + # Sets the subprocess running. + # Returns immediately after it has started, or is running + self._action_state = ActionState.RUNNING + self._state = SessionState.RUNNING + # Note: This may fail immediately (e.g. if we cannot write embedded files to disk), + # so it's important to set the action_state to RUNNING before calling run(), rather + # than after -- run() itself may end up setting the action state to FAILED. + self._runner.run() + # ========================= # Helpers diff --git a/test/openjd/sessions/test_session.py b/test/openjd/sessions/test_session.py index e4490d72..7a09a796 100644 --- a/test/openjd/sessions/test_session.py +++ b/test/openjd/sessions/test_session.py @@ -3459,3 +3459,533 @@ def test_multiple_different_redacted_env_vars( log_content = "\n".join(caplog.messages) assert "secret123" not in log_content assert "mysecret123" not in log_content + + +class TestSessionRunTaskWithOptionalEnv_2023_09: # noqa: N801 + """Testing running tasks with the 2023-09 schema.""" + + @staticmethod + @pytest.fixture + def fix_basic_task_script(python_exe: str) -> StepScript_2023_09: + return StepScript_2023_09( + actions=StepActions_2023_09( + onRun=Action_2023_09( + command=CommandString_2023_09(python_exe), + args=[ArgString_2023_09("{{ Task.File.Foo }}")], + ) + ), + embeddedFiles=[ + EmbeddedFileText_2023_09( + name="Foo", + type=EmbeddedFileTypes_2023_09.TEXT, + data=DataString_2023_09( + "import time; time.sleep(0.5); print('{{ Task.Param.P }} {{ Task.RawParam.P }}'); print('{{ Param.J }} {{ RawParam.J }}')" + ), + ) + ], + ) + + @staticmethod + @pytest.fixture + def fix_foo_baz_environment() -> Environment_2023_09: + return Environment_2023_09( + name="FooBazEnvironment", + variables={ + "FOO": EnvironmentVariableValueString_2023_09("bar"), + "BAZ": EnvironmentVariableValueString_2023_09("qux"), + }, + ) + + def test_run_task_with_optional_env( + self, caplog: pytest.LogCaptureFixture, fix_basic_task_script: StepScript_2023_09 + ) -> None: + # GIVEN + # Crafting a StepScript that ensures that references both Job & Task parameters. + # This ensures that we are correctly constructing the symbol table for the run. + session_id = uuid.uuid4().hex + job_params = {"J": ParameterValue(type=ParameterValueType.STRING, value="Jvalue")} + task_params = {"P": ParameterValue(type=ParameterValueType.STRING, value="Pvalue")} + with Session(session_id=session_id, job_parameter_values=job_params) as session: + # WHEN + session._run_task_with_optional_env( + step_script=fix_basic_task_script, task_parameter_values=task_params + ) + + # THEN + assert session.state == SessionState.RUNNING + assert session.action_status == ActionStatus(state=ActionState.RUNNING) + # Wait for the process to exit + while session.state == SessionState.RUNNING: + time.sleep(0.1) + assert session.state == SessionState.READY + assert session.action_status == ActionStatus(state=ActionState.SUCCESS, exit_code=0) + assert "Jvalue Jvalue" in caplog.messages + assert "Pvalue Pvalue" in caplog.messages + assert "--------- Running Task" in caplog.messages + + def test_run_task_with_optional_env_no_log_banners( + self, caplog: pytest.LogCaptureFixture, fix_basic_task_script: StepScript_2023_09 + ) -> None: + # GIVEN + # This ensures that the log_task_banner argument is correctly controlling the task banner logging. + session_id = uuid.uuid4().hex + job_params = {"J": ParameterValue(type=ParameterValueType.STRING, value="Jvalue")} + task_params = {"P": ParameterValue(type=ParameterValueType.STRING, value="Pvalue")} + with Session(session_id=session_id, job_parameter_values=job_params) as session: + # WHEN + session._run_task_with_optional_env( + step_script=fix_basic_task_script, + task_parameter_values=task_params, + log_task_banner=False, + ) + + # THEN + assert "--------- Running Task" not in caplog.messages + + def test_run_task_with_optional_env_with_env_vars( + self, caplog: pytest.LogCaptureFixture, python_exe: str + ) -> None: + # GIVEN + step_script = StepScript_2023_09( + actions=StepActions_2023_09( + onRun=Action_2023_09( + command=CommandString_2023_09(python_exe), + args=[ArgString_2023_09("{{ Task.File.Foo }}")], + ) + ), + embeddedFiles=[ + EmbeddedFileText_2023_09( + name="Foo", + type=EmbeddedFileTypes_2023_09.TEXT, + data=DataString_2023_09( + 'import time; import os; time.sleep(0.5); print(f\'{os.environ["SESSION_VAR"]} {os.environ["ACTION_VAR"]}\')' + ), + ) + ], + ) + + session_id = uuid.uuid4().hex + job_params = dict[str, ParameterValue]() + task_params = dict[str, ParameterValue]() + session_env_vars = {"SESSION_VAR": "session_value"} + action_env_vars = {"ACTION_VAR": "action_value"} + with Session( + session_id=session_id, job_parameter_values=job_params, os_env_vars=session_env_vars + ) as session: + # WHEN + session._run_task_with_optional_env( + step_script=step_script, + task_parameter_values=task_params, + os_env_vars=action_env_vars, + ) + + # THEN + assert session.state == SessionState.RUNNING + assert session.action_status == ActionStatus(state=ActionState.RUNNING) + # Wait for the process to exit + while session.state == SessionState.RUNNING: + time.sleep(0.1) + assert session.state == SessionState.READY + assert session.action_status == ActionStatus(state=ActionState.SUCCESS, exit_code=0) + assert "session_value action_value" in caplog.messages + + @pytest.mark.parametrize( + "state", + [ + pytest.param(state, id=state.value) + for state in SessionState + if state != SessionState.READY + ], + ) + def test_cannot_run_not_ready(self, state: SessionState, python_exe: str) -> None: + # This is checking that we cannot run a task unless the Session is READY + + # GIVEN + # Crafting a EnvironmentScript that ensures that references to Job parameters. + # This ensures that we are correctly constructing the symbol table for the run. + script = StepScript_2023_09( + actions=StepActions_2023_09( + onRun=Action_2023_09( + command=CommandString_2023_09(python_exe), + args=[ArgString_2023_09("-c"), ArgString_2023_09("print('hi')")], + ) + ), + ) + session_id = uuid.uuid4().hex + job_params = dict[str, ParameterValue]() + task_params = dict[str, ParameterValue]() + with Session(session_id=session_id, job_parameter_values=job_params) as session: + # WHEN + session._state = state + + # THEN + with pytest.raises(RuntimeError): + session._run_task_with_optional_env( + step_script=script, task_parameter_values=task_params + ) + + def test_run_task_with_optional_env_fail_early(self, python_exe: str) -> None: + # Testing a task that fails before running. + # This'll fail because we're referencing a Task parameter that doesn't exist. + + # GIVEN + session_id = uuid.uuid4().hex + job_params = {"J": ParameterValue(type=ParameterValueType.STRING, value="Jvalue")} + task_params = dict[str, ParameterValue]() + step_script = StepScript_2023_09( + actions=StepActions_2023_09( + onRun=Action_2023_09( + command=CommandString_2023_09(python_exe), + args=[ArgString_2023_09("{{ Task.File.Foo }}")], + ) + ), + embeddedFiles=[ + EmbeddedFileText_2023_09( + name="Foo", + type=EmbeddedFileTypes_2023_09.TEXT, + data=DataString_2023_09( + "import time; time.sleep(0.5); print('{{ Task.Param.P }}'); print('{{ Param.J }}')" + ), + ) + ], + ) + with Session(session_id=session_id, job_parameter_values=job_params) as session: + # WHEN + session._run_task_with_optional_env( + step_script=step_script, task_parameter_values=task_params + ) + + # THEN + assert session.state == SessionState.READY_ENDING + assert session.action_status == ActionStatus( + state=ActionState.FAILED, + fail_message="Error resolving format string: Failed to parse interpolation expression at [37, 55]. Expression: Task.Param.P . Reason: Expression failed validation: Task.Param.P has no value.", + ) + + def test_run_task_with_optional_env_fail_run(self, python_exe: str) -> None: + # Testing a task that fails while running + + # GIVEN + script = StepScript_2023_09( + actions=StepActions_2023_09( + onRun=Action_2023_09( + command=CommandString_2023_09(python_exe), + args=[ArgString_2023_09("{{ Task.File.Foo }}")], + ) + ), + embeddedFiles=[ + EmbeddedFileText_2023_09( + name="Foo", + type=EmbeddedFileTypes_2023_09.TEXT, + data=DataString_2023_09("import sys; sys.exit(1)"), + ) + ], + ) + session_id = uuid.uuid4().hex + job_params = dict[str, ParameterValue]() + task_params = dict[str, ParameterValue]() + with Session(session_id=session_id, job_parameter_values=job_params) as session: + # WHEN + session._run_task_with_optional_env( + step_script=script, task_parameter_values=task_params + ) + # Wait for the process to exit + while session.state == SessionState.RUNNING: + time.sleep(0.1) + + # THEN + assert session.state == SessionState.READY_ENDING + assert session.action_status == ActionStatus(state=ActionState.FAILED, exit_code=1) + + def test_no_task_run_after_fail(self, fix_basic_task_script: StepScript_2023_09) -> None: + # Testing that we cannot run a task if we've had a failure. + # This'll fail because we're referencing a Task parameter that doesn't exist. + + # GIVEN + session_id = uuid.uuid4().hex + job_params = {"J": ParameterValue(type=ParameterValueType.STRING, value="Jvalue")} + task_params = dict[str, ParameterValue]() + with Session(session_id=session_id, job_parameter_values=job_params) as session: + # WHEN + session._state = SessionState.READY_ENDING + + # THEN + with pytest.raises(RuntimeError): + session._run_task_with_optional_env( + step_script=fix_basic_task_script, task_parameter_values=task_params + ) + + def test_run_task_with_optional_env_with_variables( + self, + fix_basic_task_script: StepScript_2023_09, + fix_foo_baz_environment: Environment_2023_09, + ) -> None: + # GIVEN + session_id = uuid.uuid4().hex + job_params = {"J": ParameterValue(type=ParameterValueType.STRING, value="Jvalue")} + task_params = {"P": ParameterValue(type=ParameterValueType.STRING, value="Pvalue")} + with Session(session_id=session_id, job_parameter_values=job_params) as session: + # WHEN + session.enter_environment(environment=fix_foo_baz_environment) + assert session.state == SessionState.READY + session._run_task_with_optional_env( + step_script=fix_basic_task_script, task_parameter_values=task_params + ) + # Wait for the process to exit + while session.state == SessionState.RUNNING: + time.sleep(0.1) + # THEN + assert session._runner is not None + assert fix_foo_baz_environment.variables is not None + assert session._runner._os_env_vars == dict(fix_foo_baz_environment.variables) + + # Additional tests for use_session_env_vars functionality + @pytest.mark.parametrize( + "use_session_env_vars,expected_foo,expected_baz", + [ + (True, "bar", "qux"), # Environment vars should be available + (False, "NOT_SET", "NOT_SET"), # Environment vars should be ignored + ], + ) + def test_run_task_with_optional_env_use_session_env_vars( + self, + caplog: pytest.LogCaptureFixture, + python_exe: str, + fix_foo_baz_environment: Environment_2023_09, + use_session_env_vars: bool, + expected_foo: str, + expected_baz: str, + ) -> None: + """Test use_session_env_vars parameter behavior with entered environments.""" + # GIVEN + script = StepScript_2023_09( + actions=StepActions_2023_09( + onRun=Action_2023_09( + command=CommandString_2023_09(python_exe), + args=[ArgString_2023_09("{{ Task.File.Foo }}")], + ) + ), + embeddedFiles=[ + EmbeddedFileText_2023_09( + name="Foo", + type=EmbeddedFileTypes_2023_09.TEXT, + data=DataString_2023_09( + "import os; print(f\"FOO={os.environ.get('FOO', 'NOT_SET')}\"); print(f\"BAZ={os.environ.get('BAZ', 'NOT_SET')}\")" + ), + ) + ], + ) + + with Session(session_id=uuid.uuid4().hex, job_parameter_values={}) as session: + session.enter_environment(environment=fix_foo_baz_environment) + while session.state == SessionState.RUNNING: + time.sleep(0.1) + + # WHEN + session._run_task_with_optional_env( + step_script=script, + task_parameter_values={}, + use_session_env_vars=use_session_env_vars, + ) + while session.state == SessionState.RUNNING: + time.sleep(0.1) + + # THEN + assert session.action_status == ActionStatus(state=ActionState.SUCCESS, exit_code=0) + assert f"FOO={expected_foo}" in caplog.messages + assert f"BAZ={expected_baz}" in caplog.messages + + @pytest.mark.parametrize( + "use_session_env_vars,os_env_vars,expected_foo,expected_baz,expected_new_var", + [ + ( + True, + {"FOO": "overridden_value", "NEW_VAR": "new_value"}, + "bar", + "qux", + "new_value", + ), # env overrides os_env_vars + ( + False, + {"FOO": "os_value", "NEW_VAR": "new_value"}, + "os_value", + "NOT_SET", + "new_value", + ), # only os_env_vars + ], + ) + def test_run_task_with_optional_env_use_session_env_vars_with_os_env_vars( + self, + caplog: pytest.LogCaptureFixture, + python_exe: str, + fix_foo_baz_environment: Environment_2023_09, + use_session_env_vars: bool, + os_env_vars: dict, + expected_foo: str, + expected_baz: str, + expected_new_var: str, + ) -> None: + """Test interaction between use_session_env_vars and os_env_vars parameters.""" + # GIVEN + script = StepScript_2023_09( + actions=StepActions_2023_09( + onRun=Action_2023_09( + command=CommandString_2023_09(python_exe), + args=[ArgString_2023_09("{{ Task.File.Foo }}")], + ) + ), + embeddedFiles=[ + EmbeddedFileText_2023_09( + name="Foo", + type=EmbeddedFileTypes_2023_09.TEXT, + data=DataString_2023_09( + "import os; print(f\"FOO={os.environ.get('FOO', 'NOT_SET')}\"); print(f\"BAZ={os.environ.get('BAZ', 'NOT_SET')}\"); print(f\"NEW_VAR={os.environ.get('NEW_VAR', 'NOT_SET')}\")" + ), + ) + ], + ) + + with Session(session_id=uuid.uuid4().hex, job_parameter_values={}) as session: + session.enter_environment(environment=fix_foo_baz_environment) + while session.state == SessionState.RUNNING: + time.sleep(0.1) + + # WHEN + session._run_task_with_optional_env( + step_script=script, + task_parameter_values={}, + use_session_env_vars=use_session_env_vars, + os_env_vars=os_env_vars, + ) + while session.state == SessionState.RUNNING: + time.sleep(0.1) + + # THEN + assert session.action_status == ActionStatus(state=ActionState.SUCCESS, exit_code=0) + assert f"FOO={expected_foo}" in caplog.messages + assert f"BAZ={expected_baz}" in caplog.messages + assert f"NEW_VAR={expected_new_var}" in caplog.messages + + def test_run_task_with_optional_env_session_constructor_env_vars_always_applied( + self, caplog: pytest.LogCaptureFixture, python_exe: str + ) -> None: + """Test that session constructor env vars are always included regardless of use_session_env_vars.""" + # GIVEN + script = StepScript_2023_09( + actions=StepActions_2023_09( + onRun=Action_2023_09( + command=CommandString_2023_09(python_exe), + args=[ArgString_2023_09("{{ Task.File.Foo }}")], + ) + ), + embeddedFiles=[ + EmbeddedFileText_2023_09( + name="Foo", + type=EmbeddedFileTypes_2023_09.TEXT, + data=DataString_2023_09( + "import os; print(f\"SESSION_VAR={os.environ.get('SESSION_VAR', 'NOT_SET')}\"); print(f\"CONSTRUCTOR_VAR={os.environ.get('CONSTRUCTOR_VAR', 'NOT_SET')}\")" + ), + ) + ], + ) + + session_env_vars = {"SESSION_VAR": "session_value", "CONSTRUCTOR_VAR": "constructor_value"} + + with Session( + session_id=uuid.uuid4().hex, job_parameter_values={}, os_env_vars=session_env_vars + ) as session: + # WHEN + session._run_task_with_optional_env( + step_script=script, + task_parameter_values={}, + use_session_env_vars=False, + ) + while session.state == SessionState.RUNNING: + time.sleep(0.1) + + # THEN + assert session.action_status == ActionStatus(state=ActionState.SUCCESS, exit_code=0) + assert "SESSION_VAR=session_value" in caplog.messages + assert "CONSTRUCTOR_VAR=constructor_value" in caplog.messages + + @pytest.mark.parametrize( + "use_session_env_vars,expected_foo,expected_env1_var,expected_env2_var", + [ + ( + True, + "second_value", + "env1_value", + "env2_value", + ), # All env vars available, env2 overrides env1 + (False, "NOT_SET", "NOT_SET", "NOT_SET"), # All env vars ignored + ], + ) + def test_run_task_with_optional_env_multiple_environments( + self, + caplog: pytest.LogCaptureFixture, + python_exe: str, + use_session_env_vars: bool, + expected_foo: str, + expected_env1_var: str, + expected_env2_var: str, + ) -> None: + """Test use_session_env_vars behavior with multiple entered environments.""" + # GIVEN + # Create test environments + env1 = Environment_2023_09( + name="FirstEnvironment", + variables={ + "FOO": EnvironmentVariableValueString_2023_09("first_value"), + "ENV1_VAR": EnvironmentVariableValueString_2023_09("env1_value"), + }, + ) + env2 = Environment_2023_09( + name="SecondEnvironment", + variables={ + "FOO": EnvironmentVariableValueString_2023_09( + "second_value" + ), # Should override env1 + "ENV2_VAR": EnvironmentVariableValueString_2023_09("env2_value"), + }, + ) + + # Create test script + script = StepScript_2023_09( + actions=StepActions_2023_09( + onRun=Action_2023_09( + command=CommandString_2023_09(python_exe), + args=[ArgString_2023_09("{{ Task.File.Foo }}")], + ) + ), + embeddedFiles=[ + EmbeddedFileText_2023_09( + name="Foo", + type=EmbeddedFileTypes_2023_09.TEXT, + data=DataString_2023_09( + "import os; print(f\"FOO={os.environ.get('FOO', 'NOT_SET')}\"); print(f\"ENV1_VAR={os.environ.get('ENV1_VAR', 'NOT_SET')}\"); print(f\"ENV2_VAR={os.environ.get('ENV2_VAR', 'NOT_SET')}\")" + ), + ) + ], + ) + + with Session(session_id=uuid.uuid4().hex, job_parameter_values={}) as session: + # Enter multiple environments + for env in [env1, env2]: + session.enter_environment(environment=env) + while session.state == SessionState.RUNNING: + time.sleep(0.1) + + # WHEN + session._run_task_with_optional_env( + step_script=script, + task_parameter_values={}, + use_session_env_vars=use_session_env_vars, + ) + while session.state == SessionState.RUNNING: + time.sleep(0.1) + + # THEN + assert session.action_status == ActionStatus(state=ActionState.SUCCESS, exit_code=0) + assert f"FOO={expected_foo}" in caplog.messages + assert f"ENV1_VAR={expected_env1_var}" in caplog.messages + assert f"ENV2_VAR={expected_env2_var}" in caplog.messages From 12a0b5ff50d1e6a63d0fab73fe415f48cbaa9a10 Mon Sep 17 00:00:00 2001 From: Godot Bian <13778003+godobyte@users.noreply.github.com> Date: Wed, 5 Nov 2025 16:58:10 -0800 Subject: [PATCH 2/3] rename function Signed-off-by: Godot Bian <13778003+godobyte@users.noreply.github.com> --- src/openjd/sessions/_session.py | 2 +- test/openjd/sessions/test_session.py | 44 ++++++++++++++-------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/openjd/sessions/_session.py b/src/openjd/sessions/_session.py index 7834ae4f..b0c6368c 100644 --- a/src/openjd/sessions/_session.py +++ b/src/openjd/sessions/_session.py @@ -843,7 +843,7 @@ def run_task( # than after -- run() itself may end up setting the action state to FAILED. self._runner.run() - def _run_task_with_optional_env( + def _run_task_with_optional_session_env( self, *, step_script: StepScriptModel, diff --git a/test/openjd/sessions/test_session.py b/test/openjd/sessions/test_session.py index 7a09a796..6b9bebe8 100644 --- a/test/openjd/sessions/test_session.py +++ b/test/openjd/sessions/test_session.py @@ -3496,7 +3496,7 @@ def fix_foo_baz_environment() -> Environment_2023_09: }, ) - def test_run_task_with_optional_env( + def test_run_task_with_optional_session_env( self, caplog: pytest.LogCaptureFixture, fix_basic_task_script: StepScript_2023_09 ) -> None: # GIVEN @@ -3507,7 +3507,7 @@ def test_run_task_with_optional_env( task_params = {"P": ParameterValue(type=ParameterValueType.STRING, value="Pvalue")} with Session(session_id=session_id, job_parameter_values=job_params) as session: # WHEN - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=fix_basic_task_script, task_parameter_values=task_params ) @@ -3523,7 +3523,7 @@ def test_run_task_with_optional_env( assert "Pvalue Pvalue" in caplog.messages assert "--------- Running Task" in caplog.messages - def test_run_task_with_optional_env_no_log_banners( + def test_run_task_with_optional_session_env_no_log_banners( self, caplog: pytest.LogCaptureFixture, fix_basic_task_script: StepScript_2023_09 ) -> None: # GIVEN @@ -3533,7 +3533,7 @@ def test_run_task_with_optional_env_no_log_banners( task_params = {"P": ParameterValue(type=ParameterValueType.STRING, value="Pvalue")} with Session(session_id=session_id, job_parameter_values=job_params) as session: # WHEN - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=fix_basic_task_script, task_parameter_values=task_params, log_task_banner=False, @@ -3542,7 +3542,7 @@ def test_run_task_with_optional_env_no_log_banners( # THEN assert "--------- Running Task" not in caplog.messages - def test_run_task_with_optional_env_with_env_vars( + def test_run_task_with_optional_session_env_with_env_vars( self, caplog: pytest.LogCaptureFixture, python_exe: str ) -> None: # GIVEN @@ -3573,7 +3573,7 @@ def test_run_task_with_optional_env_with_env_vars( session_id=session_id, job_parameter_values=job_params, os_env_vars=session_env_vars ) as session: # WHEN - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=step_script, task_parameter_values=task_params, os_env_vars=action_env_vars, @@ -3620,11 +3620,11 @@ def test_cannot_run_not_ready(self, state: SessionState, python_exe: str) -> Non # THEN with pytest.raises(RuntimeError): - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=script, task_parameter_values=task_params ) - def test_run_task_with_optional_env_fail_early(self, python_exe: str) -> None: + def test_run_task_with_optional_session_env_fail_early(self, python_exe: str) -> None: # Testing a task that fails before running. # This'll fail because we're referencing a Task parameter that doesn't exist. @@ -3651,7 +3651,7 @@ def test_run_task_with_optional_env_fail_early(self, python_exe: str) -> None: ) with Session(session_id=session_id, job_parameter_values=job_params) as session: # WHEN - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=step_script, task_parameter_values=task_params ) @@ -3662,7 +3662,7 @@ def test_run_task_with_optional_env_fail_early(self, python_exe: str) -> None: fail_message="Error resolving format string: Failed to parse interpolation expression at [37, 55]. Expression: Task.Param.P . Reason: Expression failed validation: Task.Param.P has no value.", ) - def test_run_task_with_optional_env_fail_run(self, python_exe: str) -> None: + def test_run_task_with_optional_session_env_fail_run(self, python_exe: str) -> None: # Testing a task that fails while running # GIVEN @@ -3686,7 +3686,7 @@ def test_run_task_with_optional_env_fail_run(self, python_exe: str) -> None: task_params = dict[str, ParameterValue]() with Session(session_id=session_id, job_parameter_values=job_params) as session: # WHEN - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=script, task_parameter_values=task_params ) # Wait for the process to exit @@ -3711,11 +3711,11 @@ def test_no_task_run_after_fail(self, fix_basic_task_script: StepScript_2023_09) # THEN with pytest.raises(RuntimeError): - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=fix_basic_task_script, task_parameter_values=task_params ) - def test_run_task_with_optional_env_with_variables( + def test_run_task_with_optional_session_env_with_variables( self, fix_basic_task_script: StepScript_2023_09, fix_foo_baz_environment: Environment_2023_09, @@ -3728,7 +3728,7 @@ def test_run_task_with_optional_env_with_variables( # WHEN session.enter_environment(environment=fix_foo_baz_environment) assert session.state == SessionState.READY - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=fix_basic_task_script, task_parameter_values=task_params ) # Wait for the process to exit @@ -3747,7 +3747,7 @@ def test_run_task_with_optional_env_with_variables( (False, "NOT_SET", "NOT_SET"), # Environment vars should be ignored ], ) - def test_run_task_with_optional_env_use_session_env_vars( + def test_run_task_with_optional_session_env_use_session_env_vars( self, caplog: pytest.LogCaptureFixture, python_exe: str, @@ -3782,7 +3782,7 @@ def test_run_task_with_optional_env_use_session_env_vars( time.sleep(0.1) # WHEN - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=script, task_parameter_values={}, use_session_env_vars=use_session_env_vars, @@ -3814,7 +3814,7 @@ def test_run_task_with_optional_env_use_session_env_vars( ), # only os_env_vars ], ) - def test_run_task_with_optional_env_use_session_env_vars_with_os_env_vars( + def test_run_task_with_optional_session_env_use_session_env_vars_with_os_env_vars( self, caplog: pytest.LogCaptureFixture, python_exe: str, @@ -3851,7 +3851,7 @@ def test_run_task_with_optional_env_use_session_env_vars_with_os_env_vars( time.sleep(0.1) # WHEN - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=script, task_parameter_values={}, use_session_env_vars=use_session_env_vars, @@ -3866,7 +3866,7 @@ def test_run_task_with_optional_env_use_session_env_vars_with_os_env_vars( assert f"BAZ={expected_baz}" in caplog.messages assert f"NEW_VAR={expected_new_var}" in caplog.messages - def test_run_task_with_optional_env_session_constructor_env_vars_always_applied( + def test_run_task_with_optional_session_env_session_constructor_env_vars_always_applied( self, caplog: pytest.LogCaptureFixture, python_exe: str ) -> None: """Test that session constructor env vars are always included regardless of use_session_env_vars.""" @@ -3895,7 +3895,7 @@ def test_run_task_with_optional_env_session_constructor_env_vars_always_applied( session_id=uuid.uuid4().hex, job_parameter_values={}, os_env_vars=session_env_vars ) as session: # WHEN - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=script, task_parameter_values={}, use_session_env_vars=False, @@ -3920,7 +3920,7 @@ def test_run_task_with_optional_env_session_constructor_env_vars_always_applied( (False, "NOT_SET", "NOT_SET", "NOT_SET"), # All env vars ignored ], ) - def test_run_task_with_optional_env_multiple_environments( + def test_run_task_with_optional_session_env_multiple_environments( self, caplog: pytest.LogCaptureFixture, python_exe: str, @@ -3976,7 +3976,7 @@ def test_run_task_with_optional_env_multiple_environments( time.sleep(0.1) # WHEN - session._run_task_with_optional_env( + session._run_task_with_optional_session_env( step_script=script, task_parameter_values={}, use_session_env_vars=use_session_env_vars, From 3f66115237efc9f7ae17cee66d9cf5c9ef4372e0 Mon Sep 17 00:00:00 2001 From: Godot Bian <13778003+godobyte@users.noreply.github.com> Date: Wed, 5 Nov 2025 17:52:02 -0800 Subject: [PATCH 3/3] remove use_session_env_vars, only support without session env Signed-off-by: Godot Bian <13778003+godobyte@users.noreply.github.com> --- src/openjd/sessions/_session.py | 34 +--- test/openjd/sessions/test_session.py | 259 +++++++-------------------- 2 files changed, 73 insertions(+), 220 deletions(-) diff --git a/src/openjd/sessions/_session.py b/src/openjd/sessions/_session.py index b0c6368c..6cdac0d3 100644 --- a/src/openjd/sessions/_session.py +++ b/src/openjd/sessions/_session.py @@ -843,35 +843,16 @@ def run_task( # than after -- run() itself may end up setting the action state to FAILED. self._runner.run() - def _run_task_with_optional_session_env( + def _run_task_without_session_env( self, *, step_script: StepScriptModel, task_parameter_values: TaskParameterSet, os_env_vars: Optional[dict[str, str]] = None, - use_session_env_vars: Optional[bool] = True, log_task_banner: bool = True, ) -> None: - """Run a Task within the Session. - This method is non-blocking; it will exit when the subprocess is either confirmed to have - started running, or has failed to be started. - - Arguments: - step_script (StepScriptModel): The Step Script that the Task will be running. - task_parameter_values (TaskParameterSet): Values of the Task parameters that define the - specific Task. This is a dictionary where the keys are parameter names, and the values - are instances of ParameterValue (a dataclass containing the type and value of the parameter) - os_env_vars (Optional[dict[str,str]): Definitions for additional OS Environment - Variables that should be injected into the process that is run for this action. - Values provided override values provided to the Session constructor, and are overriden - by values defined in Environments. - Key: Environment variable name - Value: Value for the environment variable. - use_session_env_vars (Optional[bool]): Whether to apply environment variable changes from - entered environments. When True (default), applies changes from all entered environments - in order. When False, only uses base session and os_env_vars. - log_task_banner (bool): Whether to log a banner before running the Task. - Default: True + """Private API to run a task within the session. + This method directly use os_env_vars passed in without applying additional session env setup. """ if self.state != SessionState.READY: raise RuntimeError("Session must be in the READY state to run a task.") @@ -894,12 +875,9 @@ def _run_task_with_optional_session_env( symtab = self._symbol_table(step_script.revision, task_parameter_values) # Evaluate environment variables - if use_session_env_vars: - action_env_vars = self._evaluate_current_session_env_vars(os_env_vars) - else: - action_env_vars = dict[str, Optional[str]](self._process_env) # Make a copy - if os_env_vars: - action_env_vars.update(**os_env_vars) + action_env_vars = dict[str, Optional[str]](self._process_env) # Make a copy + if os_env_vars: + action_env_vars.update(**os_env_vars) self._materialize_path_mapping(step_script.revision, action_env_vars, symtab) self._runner = StepScriptRunner( diff --git a/test/openjd/sessions/test_session.py b/test/openjd/sessions/test_session.py index 6b9bebe8..c74e75ca 100644 --- a/test/openjd/sessions/test_session.py +++ b/test/openjd/sessions/test_session.py @@ -3461,8 +3461,8 @@ def test_multiple_different_redacted_env_vars( assert "mysecret123" not in log_content -class TestSessionRunTaskWithOptionalEnv_2023_09: # noqa: N801 - """Testing running tasks with the 2023-09 schema.""" +class TestSessionRunTaskWithoutSessionEnv_2023_09: # noqa: N801 + """Testing running tasks without session environment variables with the 2023-09 schema.""" @staticmethod @pytest.fixture @@ -3496,7 +3496,7 @@ def fix_foo_baz_environment() -> Environment_2023_09: }, ) - def test_run_task_with_optional_session_env( + def test_run_task_without_session_env( self, caplog: pytest.LogCaptureFixture, fix_basic_task_script: StepScript_2023_09 ) -> None: # GIVEN @@ -3507,7 +3507,7 @@ def test_run_task_with_optional_session_env( task_params = {"P": ParameterValue(type=ParameterValueType.STRING, value="Pvalue")} with Session(session_id=session_id, job_parameter_values=job_params) as session: # WHEN - session._run_task_with_optional_session_env( + session._run_task_without_session_env( step_script=fix_basic_task_script, task_parameter_values=task_params ) @@ -3523,7 +3523,7 @@ def test_run_task_with_optional_session_env( assert "Pvalue Pvalue" in caplog.messages assert "--------- Running Task" in caplog.messages - def test_run_task_with_optional_session_env_no_log_banners( + def test_run_task_without_session_env_no_log_banners( self, caplog: pytest.LogCaptureFixture, fix_basic_task_script: StepScript_2023_09 ) -> None: # GIVEN @@ -3533,7 +3533,7 @@ def test_run_task_with_optional_session_env_no_log_banners( task_params = {"P": ParameterValue(type=ParameterValueType.STRING, value="Pvalue")} with Session(session_id=session_id, job_parameter_values=job_params) as session: # WHEN - session._run_task_with_optional_session_env( + session._run_task_without_session_env( step_script=fix_basic_task_script, task_parameter_values=task_params, log_task_banner=False, @@ -3542,7 +3542,7 @@ def test_run_task_with_optional_session_env_no_log_banners( # THEN assert "--------- Running Task" not in caplog.messages - def test_run_task_with_optional_session_env_with_env_vars( + def test_run_task_without_session_env_with_env_vars( self, caplog: pytest.LogCaptureFixture, python_exe: str ) -> None: # GIVEN @@ -3573,7 +3573,7 @@ def test_run_task_with_optional_session_env_with_env_vars( session_id=session_id, job_parameter_values=job_params, os_env_vars=session_env_vars ) as session: # WHEN - session._run_task_with_optional_session_env( + session._run_task_without_session_env( step_script=step_script, task_parameter_values=task_params, os_env_vars=action_env_vars, @@ -3620,11 +3620,11 @@ def test_cannot_run_not_ready(self, state: SessionState, python_exe: str) -> Non # THEN with pytest.raises(RuntimeError): - session._run_task_with_optional_session_env( + session._run_task_without_session_env( step_script=script, task_parameter_values=task_params ) - def test_run_task_with_optional_session_env_fail_early(self, python_exe: str) -> None: + def test_run_task_without_session_env_fail_early(self, python_exe: str) -> None: # Testing a task that fails before running. # This'll fail because we're referencing a Task parameter that doesn't exist. @@ -3651,7 +3651,7 @@ def test_run_task_with_optional_session_env_fail_early(self, python_exe: str) -> ) with Session(session_id=session_id, job_parameter_values=job_params) as session: # WHEN - session._run_task_with_optional_session_env( + session._run_task_without_session_env( step_script=step_script, task_parameter_values=task_params ) @@ -3662,7 +3662,7 @@ def test_run_task_with_optional_session_env_fail_early(self, python_exe: str) -> fail_message="Error resolving format string: Failed to parse interpolation expression at [37, 55]. Expression: Task.Param.P . Reason: Expression failed validation: Task.Param.P has no value.", ) - def test_run_task_with_optional_session_env_fail_run(self, python_exe: str) -> None: + def test_run_task_without_session_env_fail_run(self, python_exe: str) -> None: # Testing a task that fails while running # GIVEN @@ -3686,7 +3686,7 @@ def test_run_task_with_optional_session_env_fail_run(self, python_exe: str) -> N task_params = dict[str, ParameterValue]() with Session(session_id=session_id, job_parameter_values=job_params) as session: # WHEN - session._run_task_with_optional_session_env( + session._run_task_without_session_env( step_script=script, task_parameter_values=task_params ) # Wait for the process to exit @@ -3711,121 +3711,40 @@ def test_no_task_run_after_fail(self, fix_basic_task_script: StepScript_2023_09) # THEN with pytest.raises(RuntimeError): - session._run_task_with_optional_session_env( + session._run_task_without_session_env( step_script=fix_basic_task_script, task_parameter_values=task_params ) - def test_run_task_with_optional_session_env_with_variables( - self, - fix_basic_task_script: StepScript_2023_09, - fix_foo_baz_environment: Environment_2023_09, - ) -> None: - # GIVEN - session_id = uuid.uuid4().hex - job_params = {"J": ParameterValue(type=ParameterValueType.STRING, value="Jvalue")} - task_params = {"P": ParameterValue(type=ParameterValueType.STRING, value="Pvalue")} - with Session(session_id=session_id, job_parameter_values=job_params) as session: - # WHEN - session.enter_environment(environment=fix_foo_baz_environment) - assert session.state == SessionState.READY - session._run_task_with_optional_session_env( - step_script=fix_basic_task_script, task_parameter_values=task_params - ) - # Wait for the process to exit - while session.state == SessionState.RUNNING: - time.sleep(0.1) - # THEN - assert session._runner is not None - assert fix_foo_baz_environment.variables is not None - assert session._runner._os_env_vars == dict(fix_foo_baz_environment.variables) - - # Additional tests for use_session_env_vars functionality - @pytest.mark.parametrize( - "use_session_env_vars,expected_foo,expected_baz", - [ - (True, "bar", "qux"), # Environment vars should be available - (False, "NOT_SET", "NOT_SET"), # Environment vars should be ignored - ], - ) - def test_run_task_with_optional_session_env_use_session_env_vars( - self, - caplog: pytest.LogCaptureFixture, - python_exe: str, - fix_foo_baz_environment: Environment_2023_09, - use_session_env_vars: bool, - expected_foo: str, - expected_baz: str, - ) -> None: - """Test use_session_env_vars parameter behavior with entered environments.""" - # GIVEN - script = StepScript_2023_09( - actions=StepActions_2023_09( - onRun=Action_2023_09( - command=CommandString_2023_09(python_exe), - args=[ArgString_2023_09("{{ Task.File.Foo }}")], - ) - ), - embeddedFiles=[ - EmbeddedFileText_2023_09( - name="Foo", - type=EmbeddedFileTypes_2023_09.TEXT, - data=DataString_2023_09( - "import os; print(f\"FOO={os.environ.get('FOO', 'NOT_SET')}\"); print(f\"BAZ={os.environ.get('BAZ', 'NOT_SET')}\")" - ), - ) - ], - ) - - with Session(session_id=uuid.uuid4().hex, job_parameter_values={}) as session: - session.enter_environment(environment=fix_foo_baz_environment) - while session.state == SessionState.RUNNING: - time.sleep(0.1) - - # WHEN - session._run_task_with_optional_session_env( - step_script=script, - task_parameter_values={}, - use_session_env_vars=use_session_env_vars, - ) - while session.state == SessionState.RUNNING: - time.sleep(0.1) - - # THEN - assert session.action_status == ActionStatus(state=ActionState.SUCCESS, exit_code=0) - assert f"FOO={expected_foo}" in caplog.messages - assert f"BAZ={expected_baz}" in caplog.messages - + # Testing os_env_vars behaviour which is different from run_task @pytest.mark.parametrize( - "use_session_env_vars,os_env_vars,expected_foo,expected_baz,expected_new_var", + "os_env_vars,expected_foo,expected_baz,expected_custom", [ + (None, "NOT_SET", "NOT_SET", "NOT_SET"), # No os_env_vars, entered env ignored ( - True, - {"FOO": "overridden_value", "NEW_VAR": "new_value"}, - "bar", - "qux", - "new_value", - ), # env overrides os_env_vars + {"CUSTOM": "custom_value"}, + "NOT_SET", + "NOT_SET", + "custom_value", + ), # Only os_env_vars used ( - False, - {"FOO": "os_value", "NEW_VAR": "new_value"}, + {"FOO": "os_value", "CUSTOM": "custom_value"}, "os_value", "NOT_SET", - "new_value", - ), # only os_env_vars + "custom_value", + ), # os_env_vars override ], ) - def test_run_task_with_optional_session_env_use_session_env_vars_with_os_env_vars( + def test_run_task_without_session_env_ignores_entered_environments( self, caplog: pytest.LogCaptureFixture, python_exe: str, fix_foo_baz_environment: Environment_2023_09, - use_session_env_vars: bool, - os_env_vars: dict, + os_env_vars: Optional[dict[str, str]], expected_foo: str, expected_baz: str, - expected_new_var: str, + expected_custom: str, ) -> None: - """Test interaction between use_session_env_vars and os_env_vars parameters.""" + """Test that entered environment variables are ignored and only os_env_vars are used.""" # GIVEN script = StepScript_2023_09( actions=StepActions_2023_09( @@ -3839,7 +3758,7 @@ def test_run_task_with_optional_session_env_use_session_env_vars_with_os_env_var name="Foo", type=EmbeddedFileTypes_2023_09.TEXT, data=DataString_2023_09( - "import os; print(f\"FOO={os.environ.get('FOO', 'NOT_SET')}\"); print(f\"BAZ={os.environ.get('BAZ', 'NOT_SET')}\"); print(f\"NEW_VAR={os.environ.get('NEW_VAR', 'NOT_SET')}\")" + "import os; print(f\"FOO={os.environ.get('FOO', 'NOT_SET')}\"); print(f\"BAZ={os.environ.get('BAZ', 'NOT_SET')}\"); print(f\"CUSTOM={os.environ.get('CUSTOM', 'NOT_SET')}\")" ), ) ], @@ -3851,10 +3770,9 @@ def test_run_task_with_optional_session_env_use_session_env_vars_with_os_env_var time.sleep(0.1) # WHEN - session._run_task_with_optional_session_env( + session._run_task_without_session_env( step_script=script, task_parameter_values={}, - use_session_env_vars=use_session_env_vars, os_env_vars=os_env_vars, ) while session.state == SessionState.RUNNING: @@ -3864,128 +3782,85 @@ def test_run_task_with_optional_session_env_use_session_env_vars_with_os_env_var assert session.action_status == ActionStatus(state=ActionState.SUCCESS, exit_code=0) assert f"FOO={expected_foo}" in caplog.messages assert f"BAZ={expected_baz}" in caplog.messages - assert f"NEW_VAR={expected_new_var}" in caplog.messages + assert f"CUSTOM={expected_custom}" in caplog.messages - def test_run_task_with_optional_session_env_session_constructor_env_vars_always_applied( + def test_run_task_without_session_env_includes_constructor_env_vars( self, caplog: pytest.LogCaptureFixture, python_exe: str ) -> None: - """Test that session constructor env vars are always included regardless of use_session_env_vars.""" + """Test that session constructor env vars are always included in the base process environment.""" # GIVEN script = StepScript_2023_09( actions=StepActions_2023_09( onRun=Action_2023_09( command=CommandString_2023_09(python_exe), - args=[ArgString_2023_09("{{ Task.File.Foo }}")], + args=[ + ArgString_2023_09("-c"), + ArgString_2023_09( + "import os; print(f\"CONSTRUCTOR_VAR={os.environ.get('CONSTRUCTOR_VAR', 'NOT_SET')}\")" + ), + ], ) ), - embeddedFiles=[ - EmbeddedFileText_2023_09( - name="Foo", - type=EmbeddedFileTypes_2023_09.TEXT, - data=DataString_2023_09( - "import os; print(f\"SESSION_VAR={os.environ.get('SESSION_VAR', 'NOT_SET')}\"); print(f\"CONSTRUCTOR_VAR={os.environ.get('CONSTRUCTOR_VAR', 'NOT_SET')}\")" - ), - ) - ], ) - session_env_vars = {"SESSION_VAR": "session_value", "CONSTRUCTOR_VAR": "constructor_value"} - with Session( - session_id=uuid.uuid4().hex, job_parameter_values={}, os_env_vars=session_env_vars + session_id=uuid.uuid4().hex, + job_parameter_values={}, + os_env_vars={"CONSTRUCTOR_VAR": "constructor_value"}, ) as session: # WHEN - session._run_task_with_optional_session_env( - step_script=script, - task_parameter_values={}, - use_session_env_vars=False, - ) + session._run_task_without_session_env(step_script=script, task_parameter_values={}) while session.state == SessionState.RUNNING: time.sleep(0.1) # THEN assert session.action_status == ActionStatus(state=ActionState.SUCCESS, exit_code=0) - assert "SESSION_VAR=session_value" in caplog.messages assert "CONSTRUCTOR_VAR=constructor_value" in caplog.messages - @pytest.mark.parametrize( - "use_session_env_vars,expected_foo,expected_env1_var,expected_env2_var", - [ - ( - True, - "second_value", - "env1_value", - "env2_value", - ), # All env vars available, env2 overrides env1 - (False, "NOT_SET", "NOT_SET", "NOT_SET"), # All env vars ignored - ], - ) - def test_run_task_with_optional_session_env_multiple_environments( + def test_run_task_without_session_env_ignores_multiple_environments( self, caplog: pytest.LogCaptureFixture, python_exe: str, - use_session_env_vars: bool, - expected_foo: str, - expected_env1_var: str, - expected_env2_var: str, ) -> None: - """Test use_session_env_vars behavior with multiple entered environments.""" - # GIVEN - # Create test environments - env1 = Environment_2023_09( - name="FirstEnvironment", - variables={ - "FOO": EnvironmentVariableValueString_2023_09("first_value"), - "ENV1_VAR": EnvironmentVariableValueString_2023_09("env1_value"), - }, - ) - env2 = Environment_2023_09( - name="SecondEnvironment", - variables={ - "FOO": EnvironmentVariableValueString_2023_09( - "second_value" - ), # Should override env1 - "ENV2_VAR": EnvironmentVariableValueString_2023_09("env2_value"), - }, - ) + """Test that multiple entered environments are ignored.""" + # GIVEN - Create environments with overlapping variables + environments = [ + Environment_2023_09( + name="FirstEnvironment", + variables={"FOO": EnvironmentVariableValueString_2023_09("first_value")}, + ), + Environment_2023_09( + name="SecondEnvironment", + variables={"FOO": EnvironmentVariableValueString_2023_09("second_value")}, + ), + ] - # Create test script script = StepScript_2023_09( actions=StepActions_2023_09( onRun=Action_2023_09( command=CommandString_2023_09(python_exe), - args=[ArgString_2023_09("{{ Task.File.Foo }}")], + args=[ + ArgString_2023_09("-c"), + ArgString_2023_09( + "import os; print(f\"FOO={os.environ.get('FOO', 'NOT_SET')}\")" + ), + ], ) ), - embeddedFiles=[ - EmbeddedFileText_2023_09( - name="Foo", - type=EmbeddedFileTypes_2023_09.TEXT, - data=DataString_2023_09( - "import os; print(f\"FOO={os.environ.get('FOO', 'NOT_SET')}\"); print(f\"ENV1_VAR={os.environ.get('ENV1_VAR', 'NOT_SET')}\"); print(f\"ENV2_VAR={os.environ.get('ENV2_VAR', 'NOT_SET')}\")" - ), - ) - ], ) with Session(session_id=uuid.uuid4().hex, job_parameter_values={}) as session: # Enter multiple environments - for env in [env1, env2]: + for env in environments: session.enter_environment(environment=env) while session.state == SessionState.RUNNING: time.sleep(0.1) # WHEN - session._run_task_with_optional_session_env( - step_script=script, - task_parameter_values={}, - use_session_env_vars=use_session_env_vars, - ) + session._run_task_without_session_env(step_script=script, task_parameter_values={}) while session.state == SessionState.RUNNING: time.sleep(0.1) - # THEN + # THEN - All entered environment variables should be ignored assert session.action_status == ActionStatus(state=ActionState.SUCCESS, exit_code=0) - assert f"FOO={expected_foo}" in caplog.messages - assert f"ENV1_VAR={expected_env1_var}" in caplog.messages - assert f"ENV2_VAR={expected_env2_var}" in caplog.messages + assert "FOO=NOT_SET" in caplog.messages