from time import sleep  from unittest.mock import patch    import pytest    from src.taipy.core import Core  from src.taipy.core._version._cli._version_cli import _VersionCLI  from src.taipy.core._version._version_manager import _VersionManager  from src.taipy.core.data._data_manager import _DataManager  from src.taipy.core.job._job_manager import _JobManager  from src.taipy.core.scenario._scenario_manager import _ScenarioManager  from src.taipy.core.scenario._scenario_manager_factory import _ScenarioManagerFactory  from src.taipy.core.sequence._sequence_manager import _SequenceManager  from src.taipy.core.task._task_manager import _TaskManager  from taipy.config.common.frequency import Frequency  from taipy.config.common.scope import Scope  from taipy.config.config import Config    from ...conftest import init_config      def test_delete_version(caplog, init_sql_repo):      _ScenarioManagerFactory._build_manager()        scenario_config = config_scenario()        with patch("sys.argv", ["prog", "--development"]):          core = Core()          core.run()          scenario = _ScenarioManager._create(scenario_config)          _ScenarioManager._submit(scenario)          core.stop()        with patch("sys.argv", ["prog", "--experiment", "1.0"]):          core = Core()          core.run()          scenario = _ScenarioManager._create(scenario_config)          _ScenarioManager._submit(scenario)          core.stop()        with patch("sys.argv", ["prog", "--experiment", "1.1"]):          core = Core()          core.run()          scenario = _ScenarioManager._create(scenario_config)          _ScenarioManager._submit(scenario)          core.stop()        with patch("sys.argv", ["prog", "--production", "1.1"]):          core = Core()          core.run()          core.stop()        with patch("sys.argv", ["prog", "--experiment", "2.0"]):          core = Core()          core.run()          scenario = _ScenarioManager._create(scenario_config)          _ScenarioManager._submit(scenario)          core.stop()        with patch("sys.argv", ["prog", "--experiment", "2.1"]):          core = Core()          core.run()          scenario = _ScenarioManager._create(scenario_config)          _ScenarioManager._submit(scenario)          core.stop()        with patch("sys.argv", ["prog", "--production", "2.1"]):          core = Core()          core.run()          core.stop()        all_versions = [version.id for version in _VersionManager._get_all()]      production_version = _VersionManager._get_production_versions()      assert len(all_versions) == 5      assert len(production_version) == 2      assert "1.0" in all_versions      assert "1.1" in all_versions and "1.1" in production_version      assert "2.0" in all_versions      assert "2.1" in all_versions and "2.1" in production_version        _VersionCLI.create_parser()      with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--delete", "1.0"]):              _VersionCLI.parse_arguments()        assert "Successfully delete version 1.0." in caplog.text      all_versions = [version.id for version in _VersionManager._get_all()]      assert len(all_versions) == 4      assert "1.0" not in all_versions        # Test delete a non-existed version      with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--delete", "non_exist_version"]):              _VersionCLI.parse_arguments()      assert "Version 'non_exist_version' does not exist." in caplog.text        # Test delete production version will change the version from production to experiment      with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--delete-production", "1.1"]):              _VersionCLI.parse_arguments()        assert "Successfully delete version 1.1 from the production version list." in caplog.text      all_versions = [version.id for version in _VersionManager._get_all()]      production_version = _VersionManager._get_production_versions()      assert len(all_versions) == 4      assert "1.1" in all_versions and "1.1" not in production_version        # Test delete a non-existed production version      with pytest.raises(SystemExit) as e:          with patch("sys.argv", ["prog", "manage-versions", "--delete-production", "non_exist_version"]):              _VersionCLI.parse_arguments()        assert str(e.value) == "Version 'non_exist_version' is not a production version."      def test_list_versions(capsys, init_sql_repo):      _ScenarioManagerFactory._build_manager()        with patch("sys.argv", ["prog", "--development"]):          core = Core()          core.run()          core.stop()      sleep(0.05)      with patch("sys.argv", ["prog", "--experiment", "1.0"]):          core = Core()          core.run()          core.stop()      sleep(0.05)      with patch("sys.argv", ["prog", "--experiment", "1.1"]):          core = Core()          core.run()          core.stop()      sleep(0.05)      with patch("sys.argv", ["prog", "--production", "1.1"]):          core = Core()          core.run()          core.stop()      sleep(0.05)      with patch("sys.argv", ["prog", "--experiment", "2.0"]):          core = Core()          core.run()          core.stop()      sleep(0.05)      with patch("sys.argv", ["prog", "--experiment", "2.1"]):          core = Core()          core.run()          core.stop()      sleep(0.05)      with patch("sys.argv", ["prog", "--production", "2.1"]):          core = Core()          core.run()          core.stop()        _VersionCLI.create_parser()      with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--list"]):              _VersionCLI.parse_arguments()        out, _ = capsys.readouterr()      version_list = str(out).strip().split("\n")      assert len(version_list) == 6  # 5 versions with the header      assert all(column in version_list[0] for column in ["Version number", "Mode", "Creation date"])      assert all(column in version_list[1] for column in ["2.1", "Production", "latest"])      assert all(column in version_list[2] for column in ["2.0", "Experiment"]) and "latest" not in version_list[2]      assert all(column in version_list[3] for column in ["1.1", "Production"]) and "latest" not in version_list[3]      assert all(column in version_list[4] for column in ["1.0", "Experiment"]) and "latest" not in version_list[4]      assert "Development" in version_list[5] and "latest" not in version_list[5]      def test_rename_version(caplog, init_sql_repo):      _ScenarioManagerFactory._build_manager()        scenario_config = config_scenario()        with patch("sys.argv", ["prog", "--experiment", "1.0"]):          core = Core()          core.run()          scenario = _ScenarioManager._create(scenario_config)          _ScenarioManager._submit(scenario)          core.stop()        with patch("sys.argv", ["prog", "--production", "2.0"]):          core = Core()          core.run()          scenario = _ScenarioManager._create(scenario_config)          _ScenarioManager._submit(scenario)          core.stop()        dev_ver = _VersionManager._get_development_version()        _VersionCLI.create_parser()      with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--rename", "non_exist_version", "1.1"]):              # This should raise an exception since version "non_exist_version" does not exist              _VersionCLI.parse_arguments()      assert "Version 'non_exist_version' does not exist." in caplog.text        _VersionCLI.create_parser()      with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--rename", "1.0", "2.0"]):              # This should raise an exception since 2.0 already exists              _VersionCLI.parse_arguments()      assert "Version name '2.0' is already used." in caplog.text        _VersionCLI.create_parser()      with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--rename", "1.0", "1.1"]):              _VersionCLI.parse_arguments()      assert _VersionManager._get("1.0") is None      assert [version.id for version in _VersionManager._get_all()].sort() == [dev_ver, "1.1", "2.0"].sort()      # All entities are assigned to the new version      assert len(_DataManager._get_all("1.1")) == 2      assert len(_TaskManager._get_all("1.1")) == 1      assert len(_SequenceManager._get_all("1.1")) == 0      assert len(_ScenarioManager._get_all("1.1")) == 1      assert len(_JobManager._get_all("1.1")) == 1        _VersionCLI.create_parser()      with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--rename", "2.0", "2.1"]):              _VersionCLI.parse_arguments()      assert _VersionManager._get("2.0") is None      assert [version.id for version in _VersionManager._get_all()].sort() == [dev_ver, "1.1", "2.1"].sort()      assert _VersionManager._get_production_versions() == ["2.1"]      # All entities are assigned to the new version      assert len(_DataManager._get_all("2.1")) == 2      assert len(_TaskManager._get_all("2.1")) == 1      assert len(_SequenceManager._get_all("2.1")) == 0      assert len(_ScenarioManager._get_all("2.1")) == 1      assert len(_JobManager._get_all("2.1")) == 1      def test_compare_version_config(caplog, init_sql_repo):      _ScenarioManagerFactory._build_manager()        scenario_config_1 = config_scenario()        with patch("sys.argv", ["prog", "--experiment", "1.0"]):          core = Core()          core.run()          scenario = _ScenarioManager._create(scenario_config_1)          _ScenarioManager._submit(scenario)          core.stop()        init_config()      Config.configure_core(repository_type="sql", repository_properties={"db_location": init_sql_repo})      _ScenarioManagerFactory._build_manager()        scenario_config_2 = config_scenario()      Config.configure_data_node(id="d2", storage_type="csv", default_path="bar.csv")        with patch("sys.argv", ["prog", "--experiment", "2.0"]):          core = Core()          core.run()          scenario = _ScenarioManager._create(scenario_config_2)          _ScenarioManager._submit(scenario)          core.stop()        _VersionCLI.create_parser()      with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "non_exist_version", "2.0"]):              # This should raise an exception since version "non_exist_version" does not exist              _VersionCLI.parse_arguments()      assert "Version 'non_exist_version' does not exist." in caplog.text        with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "non_exist_version"]):              # This should raise an exception since 2.0 already exists              _VersionCLI.parse_arguments()      assert "Version 'non_exist_version' does not exist." in caplog.text        with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "1.0"]):              _VersionCLI.parse_arguments()      assert "There is no difference between version 1.0 Configuration and version 1.0 Configuration." in caplog.text        with pytest.raises(SystemExit):          with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "2.0"]):              _VersionCLI.parse_arguments()      expected_message = """Differences between version 1.0 Configuration and version 2.0 Configuration:  \tDATA_NODE "d2" has attribute "default_path" modified: foo.csv -> bar.csv"""      assert expected_message in caplog.text      def twice(a):      return a * 2      def config_scenario():      data_node_1_config = Config.configure_data_node(          id="d1", storage_type="pickle", default_data="abc", scope=Scope.SCENARIO      )      data_node_2_config = Config.configure_data_node(id="d2", storage_type="csv", default_path="foo.csv")      task_config = Config.configure_task("my_task", twice, data_node_1_config, data_node_2_config)      scenario_config = Config.configure_scenario("my_scenario", [task_config], frequency=Frequency.DAILY)        return scenario_config


#  # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with  # the License. You may obtain a copy of the License at  #  #        http://www.apache.org/licenses/LICENSE-2.0  #  # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on  # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the  # specific language governing permissions and limitations under the License.


import multiprocessing  import random  import string  from concurrent.futures import ProcessPoolExecutor  from datetime import datetime, timedelta  from functools import partial  from time import sleep    import pytest    from src.taipy.core import taipy  from src.taipy.core._orchestrator._orchestrator import _Orchestrator  from src.taipy.core._orchestrator._orchestrator_factory import _OrchestratorFactory  from src.taipy.core.config.job_config import JobConfig  from src.taipy.core.data._data_manager import _DataManager  from src.taipy.core.data.in_memory import InMemoryDataNode  from src.taipy.core.scenario._scenario_manager import _ScenarioManager  from src.taipy.core.scenario.scenario import Scenario  from src.taipy.core.sequence._sequence_manager import _SequenceManager  from src.taipy.core.sequence.sequence import Sequence  from src.taipy.core.task._task_manager import _TaskManager  from src.taipy.core.task.task import Task  from taipy.config import Config  from taipy.config.common.scope import Scope  from taipy.config.exceptions.exceptions import ConfigurationUpdateBlocked  from tests.core.utils import assert_true_after_time    # ################################  USER FUNCTIONS  ##################################      def multiply(nb1: float, nb2: float):      sleep(0.1)      return nb1 * nb2      def lock_multiply(lock, nb1: float, nb2: float):      with lock:          return multiply(nb1, nb2)      def mult_by_2(n):      return n * 2      def nothing():      return True      def concat(a, b):      return a + b      def _error():      raise Exception      # ################################  TEST METHODS    ##################################      def test_submit_task():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)        before_creation = datetime.now()      sleep(0.1)      task = _create_task(multiply)      output_dn_id = task.output[f"{task.config_id}_output0"].id        _OrchestratorFactory._build_dispatcher()        assert _DataManager._get(output_dn_id).last_edit_date > before_creation      assert _DataManager._get(output_dn_id).job_ids == []      assert _DataManager._get(output_dn_id).is_ready_for_reading        before_submission_creation = datetime.now()      sleep(0.1)      job = _Orchestrator.submit_task(task)      sleep(0.1)      after_submission_creation = datetime.now()      assert _DataManager._get(output_dn_id).read() == 42      assert _DataManager._get(output_dn_id).last_edit_date > before_submission_creation      assert _DataManager._get(output_dn_id).last_edit_date < after_submission_creation      assert _DataManager._get(output_dn_id).job_ids == [job.id]      assert _DataManager._get(output_dn_id).is_ready_for_reading      assert job.is_completed()      def test_submit_sequence_generate_unique_submit_id():        dn_1 = InMemoryDataNode("dn_config_id_1", Scope.SCENARIO)      dn_2 = InMemoryDataNode("dn_config_id_2", Scope.SCENARIO)      task_1 = Task("task_config_id_1", {}, print, [dn_1])      task_2 = Task("task_config_id_2", {}, print, [dn_1], [dn_2])        _DataManager._set(dn_1)      _DataManager._set(dn_2)      _TaskManager._set(task_1)      _TaskManager._set(task_2)        scenario = Scenario("scenario", [task_1, task_2], {}, sequences={"sequence": {"tasks": [task_1, task_2]}})      _ScenarioManager._set(scenario)        sequence = scenario.sequences["sequence"]        jobs_1 = taipy.submit(sequence)      jobs_2 = taipy.submit(sequence)      assert len(jobs_1) == 2      assert len(jobs_2) == 2      submit_ids_1 = [job.submit_id for job in jobs_1]      submit_ids_2 = [job.submit_id for job in jobs_2]      assert len(set(submit_ids_1)) == 1      assert len(set(submit_ids_2)) == 1      assert set(submit_ids_1) != set(submit_ids_2)      def test_submit_scenario_generate_unique_submit_id():      dn_1 = InMemoryDataNode("dn_config_id_1", Scope.SCENARIO)      dn_2 = InMemoryDataNode("dn_config_id_2", Scope.SCENARIO)      dn_3 = InMemoryDataNode("dn_config_id_3", Scope.SCENARIO)      task_1 = Task("task_config_id_1", {}, print, [dn_1])      task_2 = Task("task_config_id_2", {}, print, [dn_2])      task_3 = Task("task_config_id_3", {}, print, [dn_3])      scenario = Scenario("scenario_config_id", [task_1, task_2, task_3], {})        _DataManager._set(dn_1)      _DataManager._set(dn_2)      _TaskManager._set(task_1)      _TaskManager._set(task_2)      _TaskManager._set(task_3)      _ScenarioManager._set(scenario)        jobs_1 = taipy.submit(scenario)      jobs_2 = taipy.submit(scenario)        assert len(jobs_1) == 3      assert len(jobs_2) == 3      def test_submit_entity_store_entity_id_in_job():      dn_1 = InMemoryDataNode("dn_config_id_1", Scope.SCENARIO)      dn_2 = InMemoryDataNode("dn_config_id_2", Scope.SCENARIO)      dn_3 = InMemoryDataNode("dn_config_id_3", Scope.SCENARIO)      task_1 = Task("task_config_id_1", {}, print, [dn_1])      task_2 = Task("task_config_id_2", {}, print, [dn_2])      task_3 = Task("task_config_id_3", {}, print, [dn_3])      scenario = Scenario("scenario_config_id", [task_1, task_2, task_3], {})        _DataManager._set(dn_1)      _DataManager._set(dn_2)      _TaskManager._set(task_1)      _TaskManager._set(task_2)      _TaskManager._set(task_3)      _ScenarioManager._set(scenario)        jobs_1 = taipy.submit(scenario)      assert all(job.submit_entity_id == scenario.id for job in jobs_1)        job_1 = taipy.submit(task_1)      assert job_1.submit_entity_id == task_1.id      def test_submit_task_that_return_multiple_outputs():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)        def return_2tuple(nb1, nb2):          return multiply(nb1, nb2), multiply(nb1, nb2) / 2        def return_list(nb1, nb2):          return [multiply(nb1, nb2), multiply(nb1, nb2) / 2]        with_tuple = _create_task(return_2tuple, 2)      with_list = _create_task(return_list, 2)        _OrchestratorFactory._build_dispatcher()        _Orchestrator.submit_task(with_tuple)      _Orchestrator.submit_task(with_list)        assert (          with_tuple.output[f"{with_tuple.config_id}_output0"].read()          == with_list.output[f"{with_list.config_id}_output0"].read()          == 42      )      assert (          with_tuple.output[f"{with_tuple.config_id}_output1"].read()          == with_list.output[f"{with_list.config_id}_output1"].read()          == 21      )      def test_submit_task_returns_single_iterable_output():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)        def return_2tuple(nb1, nb2):          return multiply(nb1, nb2), multiply(nb1, nb2) / 2        def return_list(nb1, nb2):          return [multiply(nb1, nb2), multiply(nb1, nb2) / 2]        task_with_tuple = _create_task(return_2tuple, 1)      task_with_list = _create_task(return_list, 1)        _OrchestratorFactory._build_dispatcher()        _Orchestrator.submit_task(task_with_tuple)      assert task_with_tuple.output[f"{task_with_tuple.config_id}_output0"].read() == (42, 21)      assert len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0      _Orchestrator.submit_task(task_with_list)      assert task_with_list.output[f"{task_with_list.config_id}_output0"].read() == [42, 21]      assert len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0      def test_data_node_not_written_due_to_wrong_result_nb():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)        def return_2tuple():          return lambda nb1, nb2: (multiply(nb1, nb2), multiply(nb1, nb2) / 2)        task = _create_task(return_2tuple(), 3)        _OrchestratorFactory._build_dispatcher()        job = _Orchestrator.submit_task(task)      assert task.output[f"{task.config_id}_output0"].read() == 0      assert job.is_failed()      assert len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0      def test_scenario_only_submit_same_task_once():        Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)      _OrchestratorFactory._build_dispatcher()        dn_0 = InMemoryDataNode("dn_config_0", Scope.SCENARIO, properties={"default_data": 0})      dn_1 = InMemoryDataNode("dn_config_1", Scope.SCENARIO, properties={"default_data": 1})      dn_2 = InMemoryDataNode("dn_config_2", Scope.SCENARIO, properties={"default_data": 2})      task_1 = Task("task_config_1", {}, print, input=[dn_0], output=[dn_1], id="task_1")      task_2 = Task("task_config_2", {}, print, input=[dn_1], id="task_2")      task_3 = Task("task_config_3", {}, print, input=[dn_1], output=[dn_2], id="task_3")      scenario_1 = Scenario(          "scenario_config_1",          [task_1, task_2, task_3],          {},          "scenario_1",          sequences={"sequence_1": {"tasks": [task_1, task_2]}, "sequence_2": {"tasks": [task_1, task_3]}},      )      sequence_1 = scenario_1.sequences["sequence_1"]      sequence_2 = scenario_1.sequences["sequence_2"]        jobs = _Orchestrator.submit(scenario_1)      assert len(jobs) == 3      assert all([job.is_completed() for job in jobs])      assert all(not _Orchestrator._is_blocked(job) for job in jobs)        jobs = _Orchestrator.submit(sequence_1)      assert len(jobs) == 2      assert all([job.is_completed() for job in jobs])      assert all(not _Orchestrator._is_blocked(job) for job in jobs)        jobs = _Orchestrator.submit(sequence_2)      assert len(jobs) == 2      assert all([job.is_completed() for job in jobs])      assert all(not _Orchestrator._is_blocked(job) for job in jobs)      def test_update_status_fail_job():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)      _OrchestratorFactory._build_dispatcher()        dn_0 = InMemoryDataNode("dn_config_0", Scope.SCENARIO, properties={"default_data": 0})      dn_1 = InMemoryDataNode("dn_config_1", Scope.SCENARIO, properties={"default_data": 1})      dn_2 = InMemoryDataNode("dn_config_2", Scope.SCENARIO, properties={"default_data": 2})      task_0 = Task("task_config_0", {}, _error, output=[dn_0], id="task_0")      task_1 = Task("task_config_1", {}, print, input=[dn_0], output=[dn_1], id="task_1")      task_2 = Task("task_config_2", {}, print, input=[dn_1], id="task_2")      task_3 = Task("task_config_3", {}, print, input=[dn_2], id="task_3")      scenario_1 = Scenario("scenario_config_1", [task_0, task_1, task_2, task_3], {}, "scenario_1")      scenario_2 = Scenario("scenario_config_2", [task_0, task_1, task_2, task_3], {}, "scenario_2")        _DataManager._set(dn_0)      _DataManager._set(dn_1)      _DataManager._set(dn_2)      _TaskManager._set(task_0)      _TaskManager._set(task_1)      _TaskManager._set(task_2)      _TaskManager._set(task_3)      _ScenarioManager._set(scenario_1)      _ScenarioManager._set(scenario_2)        job = _Orchestrator.submit_task(task_0)      assert job.is_failed()        jobs = _Orchestrator.submit(scenario_1)      tasks_jobs = {job._task.id: job for job in jobs}      assert tasks_jobs["task_0"].is_failed()      assert all([job.is_abandoned() for job in [tasks_jobs["task_1"], tasks_jobs["task_2"]]])      assert tasks_jobs["task_3"].is_completed()      assert all(not _Orchestrator._is_blocked(job) for job in jobs)        jobs = _Orchestrator.submit(scenario_2)      tasks_jobs = {job._task.id: job for job in jobs}      assert tasks_jobs["task_0"].is_failed()      assert all([job.is_abandoned() for job in [tasks_jobs["task_1"], tasks_jobs["task_2"]]])      assert tasks_jobs["task_3"].is_completed()      assert all(not _Orchestrator._is_blocked(job) for job in jobs)      def test_update_status_fail_job_in_parallel():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)      _OrchestratorFactory._build_dispatcher()        dn_0 = InMemoryDataNode("dn_config_0", Scope.SCENARIO, properties={"default_data": 0})      dn_1 = InMemoryDataNode("dn_config_1", Scope.SCENARIO, properties={"default_data": 1})      dn_2 = InMemoryDataNode("dn_config_2", Scope.SCENARIO, properties={"default_data": 2})      task_0 = Task("task_config_0", {}, _error, output=[dn_0], id="task_0")      task_1 = Task("task_config_1", {}, print, input=[dn_0], output=[dn_1], id="task_1")      task_2 = Task("task_config_2", {}, print, input=[dn_1], id="task_2")      task_3 = Task("task_config_3", {}, print, input=[dn_2], id="task_3")      scenario_1 = Scenario(          "scenario_config_1",          set([task_0, task_1, task_2, task_3]),          {},          set(),          "scenario_1",          sequences={"sequence_1": {"tasks": [task_0, task_1, task_2]}},      )      scenario_2 = Scenario(          "scenario_config_2",          set([task_0, task_1, task_2, task_3]),          {},          set(),          "scenario_2",      )        _DataManager._set(dn_0)      _DataManager._set(dn_1)      _DataManager._set(dn_2)      _TaskManager._set(task_0)      _TaskManager._set(task_1)      _TaskManager._set(task_2)      _TaskManager._set(task_3)      _ScenarioManager._set(scenario_1)      _ScenarioManager._set(scenario_2)        sequence_1 = scenario_1.sequences["sequence_1"]        job = _Orchestrator.submit_task(task_0)      assert_true_after_time(job.is_failed)        jobs = _Orchestrator.submit(sequence_1)      tasks_jobs = {job._task.id: job for job in jobs}      assert_true_after_time(tasks_jobs["task_0"].is_failed)      assert_true_after_time(lambda: all([job.is_abandoned() for job in [tasks_jobs["task_1"], tasks_jobs["task_2"]]]))      assert_true_after_time(lambda: all(not _Orchestrator._is_blocked(job) for job in jobs))        jobs = _Orchestrator.submit(scenario_1.sequences["sequence_1"])      tasks_jobs = {job._task.id: job for job in jobs}      assert_true_after_time(tasks_jobs["task_0"].is_failed)      assert_true_after_time(lambda: all([job.is_abandoned() for job in [tasks_jobs["task_1"], tasks_jobs["task_2"]]]))      assert_true_after_time(lambda: all(not _Orchestrator._is_blocked(job) for job in jobs))        jobs = _Orchestrator.submit(scenario_1)      tasks_jobs = {job._task.id: job for job in jobs}      assert_true_after_time(tasks_jobs["task_0"].is_failed)      assert_true_after_time(tasks_jobs["task_3"].is_completed)      assert_true_after_time(lambda: all([job.is_abandoned() for job in [tasks_jobs["task_1"], tasks_jobs["task_2"]]]))      assert_true_after_time(lambda: all(not _Orchestrator._is_blocked(job) for job in jobs))        jobs = _Orchestrator.submit(scenario_2)      tasks_jobs = {job._task.id: job for job in jobs}      assert_true_after_time(tasks_jobs["task_0"].is_failed)      assert_true_after_time(tasks_jobs["task_3"].is_completed)      assert_true_after_time(lambda: all([job.is_abandoned() for job in [tasks_jobs["task_1"], tasks_jobs["task_2"]]]))      assert_true_after_time(lambda: all(not _Orchestrator._is_blocked(job) for job in jobs))      def test_submit_task_in_parallel():      m = multiprocessing.Manager()      lock = m.Lock()        Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        task = _create_task(partial(lock_multiply, lock))        _OrchestratorFactory._build_dispatcher()        with lock:          assert task.output[f"{task.config_id}_output0"].read() == 0          job = _Orchestrator.submit_task(task)          assert_true_after_time(job.is_running)          assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)        assert_true_after_time(lambda: task.output[f"{task.config_id}_output0"].read() == 42)      assert_true_after_time(job.is_completed)      assert len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0      def test_submit_sequence_in_parallel():        m = multiprocessing.Manager()      lock = m.Lock()        Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        task = _create_task(partial(lock_multiply, lock))      sequence = Sequence({}, [task], "sequence_id")        _OrchestratorFactory._build_dispatcher()        with lock:          assert task.output[f"{task.config_id}_output0"].read() == 0          job = _Orchestrator.submit(sequence)[0]          assert_true_after_time(job.is_running)          assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)        assert_true_after_time(lambda: task.output[f"{task.config_id}_output0"].read() == 42)      assert_true_after_time(job.is_completed)      assert len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0      def test_submit_scenario_in_parallel():      m = multiprocessing.Manager()      lock = m.Lock()        Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        task = _create_task(partial(lock_multiply, lock))      scenario = Scenario("scenario_config", [task], {}, [], "scenario_id")        _OrchestratorFactory._build_dispatcher()        with lock:          assert task.output[f"{task.config_id}_output0"].read() == 0          job = _Orchestrator.submit(scenario)[0]          assert_true_after_time(job.is_running)          assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)        assert_true_after_time(lambda: task.output[f"{task.config_id}_output0"].read() == 42)      assert_true_after_time(job.is_completed)      assert len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0      def sleep_fct(seconds):      sleep(seconds)      def sleep_and_raise_error_fct(seconds):      sleep(seconds)      raise Exception      def test_submit_task_synchronously_in_parallel():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)      _OrchestratorFactory._build_dispatcher()        sleep_period = 1      start_time = datetime.now()      task = Task("sleep_task", {}, function=partial(sleep, sleep_period))      job = _Orchestrator.submit_task(task, wait=True)      assert (datetime.now() - start_time).seconds >= sleep_period      assert_true_after_time(job.is_completed)      def test_submit_sequence_synchronously_in_parallel():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)      _OrchestratorFactory._build_dispatcher()        sleep_period = 1      start_time = datetime.now()      task = Task("sleep_task", {}, function=partial(sleep, sleep_period))      sequence = Sequence({}, [task], "sequence_id")        job = _Orchestrator.submit(sequence, wait=True)[0]      assert (datetime.now() - start_time).seconds >= sleep_period      assert_true_after_time(job.is_completed)      def test_submit_scenario_synchronously_in_parallel():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)      _OrchestratorFactory._build_dispatcher()        sleep_period = 1      start_time = datetime.now()      task = Task("sleep_task", {}, function=partial(sleep, sleep_period))      scenario = Scenario("scenario_config", [task], {})        job = _Orchestrator.submit(scenario, wait=True)[0]      assert (datetime.now() - start_time).seconds >= sleep_period      assert_true_after_time(job.is_completed)      def test_submit_fail_task_synchronously_in_parallel():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)      _OrchestratorFactory._build_dispatcher()        sleep_period = 1.0      start_time = datetime.now()      task = Task("sleep_task", {}, function=partial(sleep_and_raise_error_fct, sleep_period))      job = _Orchestrator.submit_task(task, wait=True)      assert (datetime.now() - start_time).seconds >= sleep_period      assert_true_after_time(job.is_failed)      def test_submit_fail_sequence_synchronously_in_parallel():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)      _OrchestratorFactory._build_dispatcher()        sleep_period = 1.0      start_time = datetime.now()      task = Task("sleep_task", {}, function=partial(sleep_and_raise_error_fct, sleep_period))      sequence = Sequence({}, [task], "sequence_id")        job = _Orchestrator.submit(sequence, wait=True)[0]      assert (datetime.now() - start_time).seconds >= sleep_period      assert_true_after_time(job.is_failed)      def test_submit_fail_scenario_synchronously_in_parallel():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)      _OrchestratorFactory._build_dispatcher()        sleep_period = 1.0      start_time = datetime.now()      task = Task("sleep_task", {}, function=partial(sleep_and_raise_error_fct, sleep_period))      scenario = Scenario("scenario_config", [task], {})        job = _Orchestrator.submit(scenario, wait=True)[0]      assert (datetime.now() - start_time).seconds >= sleep_period      assert_true_after_time(job.is_failed)      def test_submit_task_synchronously_in_parallel_with_timeout():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)      _OrchestratorFactory._build_dispatcher()        task_duration = 2      timeout_duration = task_duration - 1      task = Task("sleep_task", {}, function=partial(sleep, task_duration))        start_time = datetime.now()      job = _Orchestrator.submit_task(task, wait=True, timeout=timeout_duration)      end_time = datetime.now()        assert timeout_duration <= (end_time - start_time).seconds      assert_true_after_time(job.is_completed)      def test_submit_task_multithreading_multiple_task():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        m = multiprocessing.Manager()      lock_1 = m.Lock()      lock_2 = m.Lock()        task_1 = _create_task(partial(lock_multiply, lock_1))      task_2 = _create_task(partial(lock_multiply, lock_2))        _OrchestratorFactory._build_dispatcher()        with lock_1:          with lock_2:              job_1 = _Orchestrator.submit_task(task_1)              job_2 = _Orchestrator.submit_task(task_2)                assert task_1.output[f"{task_1.config_id}_output0"].read() == 0              assert task_2.output[f"{task_2.config_id}_output0"].read() == 0              assert_true_after_time(job_1.is_running)              assert_true_after_time(job_2.is_running)              assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 2)            assert_true_after_time(lambda: task_2.output[f"{task_2.config_id}_output0"].read() == 42)          assert task_1.output[f"{task_1.config_id}_output0"].read() == 0          assert_true_after_time(job_2.is_completed)          assert_true_after_time(job_1.is_running)          assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)        assert_true_after_time(lambda: task_1.output[f"{task_1.config_id}_output0"].read() == 42)      assert_true_after_time(job_1.is_completed)      assert_true_after_time(job_2.is_completed)      assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0)      def test_submit_sequence_multithreading_multiple_task():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        m = multiprocessing.Manager()      lock_1 = m.Lock()      lock_2 = m.Lock()        task_1 = _create_task(partial(lock_multiply, lock_1))      task_2 = _create_task(partial(lock_multiply, lock_2))        sequence = Sequence({}, [task_1, task_2], "sequence_id")        _OrchestratorFactory._build_dispatcher()        with lock_1:          with lock_2:              tasks_jobs = {job._task.id: job for job in _Orchestrator.submit(sequence)}              job_1 = tasks_jobs[task_1.id]              job_2 = tasks_jobs[task_2.id]                assert task_1.output[f"{task_1.config_id}_output0"].read() == 0              assert task_2.output[f"{task_2.config_id}_output0"].read() == 0              assert_true_after_time(job_1.is_running)              assert_true_after_time(job_2.is_running)              assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 2)            assert_true_after_time(lambda: task_2.output[f"{task_2.config_id}_output0"].read() == 42)          assert task_1.output[f"{task_1.config_id}_output0"].read() == 0          assert_true_after_time(job_2.is_completed)          assert_true_after_time(job_1.is_running)          assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)        assert_true_after_time(lambda: task_1.output[f"{task_1.config_id}_output0"].read() == 42)      assert_true_after_time(job_1.is_completed)      assert_true_after_time(job_2.is_completed)      assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0)      def test_submit_scenario_multithreading_multiple_task():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        m = multiprocessing.Manager()      lock_1 = m.Lock()      lock_2 = m.Lock()        task_1 = _create_task(partial(lock_multiply, lock_1))      task_2 = _create_task(partial(lock_multiply, lock_2))        scenario = Scenario("scenario_config", [task_1, task_2], {})        _OrchestratorFactory._build_dispatcher()        with lock_1:          with lock_2:              tasks_jobs = {job._task.id: job for job in _Orchestrator.submit(scenario)}              job_1 = tasks_jobs[task_1.id]              job_2 = tasks_jobs[task_2.id]                assert task_1.output[f"{task_1.config_id}_output0"].read() == 0              assert task_2.output[f"{task_2.config_id}_output0"].read() == 0              assert_true_after_time(job_1.is_running)              assert_true_after_time(job_2.is_running)              assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 2)            assert_true_after_time(lambda: task_2.output[f"{task_2.config_id}_output0"].read() == 42)          assert task_1.output[f"{task_1.config_id}_output0"].read() == 0          assert_true_after_time(job_2.is_completed)          assert_true_after_time(job_1.is_running)          assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)        assert_true_after_time(lambda: task_1.output[f"{task_1.config_id}_output0"].read() == 42)      assert_true_after_time(job_1.is_completed)      assert_true_after_time(job_2.is_completed)      assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0)      def test_submit_task_multithreading_multiple_task_in_sync_way_to_check_job_status():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        m = multiprocessing.Manager()      lock_0 = m.Lock()      lock_1 = m.Lock()      lock_2 = m.Lock()        task_0 = _create_task(partial(lock_multiply, lock_0))      task_1 = _create_task(partial(lock_multiply, lock_1))      task_2 = _create_task(partial(lock_multiply, lock_2))        _OrchestratorFactory._build_dispatcher()        with lock_0:          job_0 = _Orchestrator.submit_task(task_0)          assert_true_after_time(job_0.is_running)          assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)          with lock_1:              with lock_2:                  assert task_1.output[f"{task_1.config_id}_output0"].read() == 0                  assert task_2.output[f"{task_2.config_id}_output0"].read() == 0                  job_2 = _Orchestrator.submit_task(task_2)                  job_1 = _Orchestrator.submit_task(task_1)                  assert_true_after_time(job_0.is_running)                  assert_true_after_time(job_1.is_pending)                  assert_true_after_time(job_2.is_running)                  assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 2)                assert_true_after_time(lambda: task_2.output[f"{task_2.config_id}_output0"].read() == 42)              assert task_1.output[f"{task_1.config_id}_output0"].read() == 0              assert_true_after_time(job_0.is_running)              assert_true_after_time(job_1.is_running)              assert_true_after_time(job_2.is_completed)              assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 2)            assert_true_after_time(lambda: task_1.output[f"{task_1.config_id}_output0"].read() == 42)          assert task_0.output[f"{task_0.config_id}_output0"].read() == 0          assert_true_after_time(job_0.is_running)          assert_true_after_time(job_1.is_completed)          assert job_2.is_completed()          assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)        assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0)      assert task_0.output[f"{task_0.config_id}_output0"].read() == 42      assert job_0.is_completed()      assert job_1.is_completed()      assert job_2.is_completed()      def test_blocked_task():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        m = multiprocessing.Manager()      lock_1 = m.Lock()      lock_2 = m.Lock()        foo_cfg = Config.configure_data_node("foo", default_data=1)      bar_cfg = Config.configure_data_node("bar")      baz_cfg = Config.configure_data_node("baz")        _OrchestratorFactory._build_dispatcher()        dns = _DataManager._bulk_get_or_create([foo_cfg, bar_cfg, baz_cfg])      foo = dns[foo_cfg]      bar = dns[bar_cfg]      baz = dns[baz_cfg]      task_1 = Task("by_2", {}, partial(lock_multiply, lock_1, 2), [foo], [bar])      task_2 = Task("by_3", {}, partial(lock_multiply, lock_2, 3), [bar], [baz])        assert task_1.foo.is_ready_for_reading  # foo is ready      assert not task_1.bar.is_ready_for_reading  # But bar is not ready      assert not task_2.baz.is_ready_for_reading  # neither does baz        assert len(_Orchestrator.blocked_jobs) == 0      job_2 = _Orchestrator.submit_task(task_2)  # job 2 is submitted first      assert job_2.is_blocked()  # since bar is not is_valid the job 2 is blocked      assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0)      assert len(_Orchestrator.blocked_jobs) == 1      with lock_2:          with lock_1:              job_1 = _Orchestrator.submit_task(                  task_1,              )  # job 1 is submitted and locked              assert_true_after_time(job_1.is_running)  # so it is still running              assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)              assert not _DataManager._get(task_1.bar.id).is_ready_for_reading  # And bar still not ready              assert_true_after_time(job_2.is_blocked)  # the job_2 remains blocked          assert_true_after_time(job_1.is_completed)  # job1 unlocked and can complete          assert _DataManager._get(task_1.bar.id).is_ready_for_reading  # bar becomes ready          assert _DataManager._get(task_1.bar.id).read() == 2  # the data is computed and written          assert_true_after_time(job_2.is_running)  # And job 2 can start running          assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)          assert len(_Orchestrator.blocked_jobs) == 0      assert_true_after_time(job_2.is_completed)  # job 2 unlocked so it can complete      assert _DataManager._get(task_2.baz.id).is_ready_for_reading  # baz becomes ready      assert _DataManager._get(task_2.baz.id).read() == 6  # the data is computed and written      assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0)      def test_blocked_sequence():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        m = multiprocessing.Manager()      lock_1 = m.Lock()      lock_2 = m.Lock()        foo_cfg = Config.configure_data_node("foo", default_data=1)      bar_cfg = Config.configure_data_node("bar")      baz_cfg = Config.configure_data_node("baz")        _OrchestratorFactory._build_dispatcher()        dns = _DataManager._bulk_get_or_create([foo_cfg, bar_cfg, baz_cfg])      foo = dns[foo_cfg]      bar = dns[bar_cfg]      baz = dns[baz_cfg]      task_1 = Task("by_2", {}, partial(lock_multiply, lock_1, 2), [foo], [bar])      task_2 = Task("by_3", {}, partial(lock_multiply, lock_2, 3), [bar], [baz])      sequence = Sequence({}, [task_1, task_2], "sequence_id")        assert task_1.foo.is_ready_for_reading  # foo is ready      assert not task_1.bar.is_ready_for_reading  # But bar is not ready      assert not task_2.baz.is_ready_for_reading  # neither does baz        assert len(_Orchestrator.blocked_jobs) == 0      with lock_2:          with lock_1:              jobs = _Orchestrator.submit(sequence)  # sequence is submitted              tasks_jobs = {job._task.id: job for job in jobs}              job_1, job_2 = tasks_jobs[task_1.id], tasks_jobs[task_2.id]              assert_true_after_time(job_1.is_running)  # job 1 is submitted and locked so it is still running              assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)              assert not _DataManager._get(task_1.bar.id).is_ready_for_reading  # And bar still not ready              assert_true_after_time(job_2.is_blocked)  # the job_2 remains blocked          assert_true_after_time(job_1.is_completed)  # job1 unlocked and can complete          assert _DataManager._get(task_1.bar.id).is_ready_for_reading  # bar becomes ready          assert _DataManager._get(task_1.bar.id).read() == 2  # the data is computed and written          assert_true_after_time(job_2.is_running)  # And job 2 can start running          assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)          assert len(_Orchestrator.blocked_jobs) == 0      assert_true_after_time(job_2.is_completed)  # job 2 unlocked so it can complete      assert _DataManager._get(task_2.baz.id).is_ready_for_reading  # baz becomes ready      assert _DataManager._get(task_2.baz.id).read() == 6  # the data is computed and written      assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0)      def test_blocked_scenario():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        m = multiprocessing.Manager()      lock_1 = m.Lock()      lock_2 = m.Lock()        foo_cfg = Config.configure_data_node("foo", default_data=1)      bar_cfg = Config.configure_data_node("bar")      baz_cfg = Config.configure_data_node("baz")        _OrchestratorFactory._build_dispatcher()        dns = _DataManager._bulk_get_or_create([foo_cfg, bar_cfg, baz_cfg])      foo = dns[foo_cfg]      bar = dns[bar_cfg]      baz = dns[baz_cfg]      task_1 = Task("by_2", {}, partial(lock_multiply, lock_1, 2), [foo], [bar])      task_2 = Task("by_3", {}, partial(lock_multiply, lock_2, 3), [bar], [baz])      scenario = Scenario("scenario_config", [task_1, task_2], {})        assert task_1.foo.is_ready_for_reading  # foo is ready      assert not task_1.bar.is_ready_for_reading  # But bar is not ready      assert not task_2.baz.is_ready_for_reading  # neither does baz        assert len(_Orchestrator.blocked_jobs) == 0      with lock_2:          with lock_1:              jobs = _Orchestrator.submit(scenario)  # scenario is submitted              tasks_jobs = {job._task.id: job for job in jobs}              job_1, job_2 = tasks_jobs[task_1.id], tasks_jobs[task_2.id]              assert_true_after_time(job_1.is_running)  # job 1 is submitted and locked so it is still running              assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)              assert not _DataManager._get(task_1.bar.id).is_ready_for_reading  # And bar still not ready              assert_true_after_time(job_2.is_blocked)  # the job_2 remains blocked          assert_true_after_time(job_1.is_completed)  # job1 unlocked and can complete          assert _DataManager._get(task_1.bar.id).is_ready_for_reading  # bar becomes ready          assert _DataManager._get(task_1.bar.id).read() == 2  # the data is computed and written          assert_true_after_time(job_2.is_running)  # And job 2 can start running          assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 1)          assert len(_Orchestrator.blocked_jobs) == 0      assert_true_after_time(job_2.is_completed)  # job 2 unlocked so it can complete      assert _DataManager._get(task_2.baz.id).is_ready_for_reading  # baz becomes ready      assert _DataManager._get(task_2.baz.id).read() == 6  # the data is computed and written      assert_true_after_time(lambda: len(_OrchestratorFactory._dispatcher._dispatched_processes) == 0)      def test_task_orchestrator_create_synchronous_dispatcher():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)      _OrchestratorFactory._build_dispatcher()        assert _OrchestratorFactory._dispatcher._nb_available_workers == 1      def test_task_orchestrator_create_standalone_dispatcher():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=3)      _OrchestratorFactory._build_dispatcher()      assert isinstance(_OrchestratorFactory._dispatcher._executor, ProcessPoolExecutor)      assert _OrchestratorFactory._dispatcher._nb_available_workers == 3      def modified_config_task(n):      from taipy.config import Config        assert_true_after_time(lambda: Config.core.storage_folder == ".my_data/")      assert_true_after_time(lambda: Config.core.custom_property == "custom_property")      return n * 2      def test_can_exec_task_with_modified_config():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)      Config.configure_core(storage_folder=".my_data/", custom_property="custom_property")        dn_input_config = Config.configure_data_node("input", "pickle", scope=Scope.SCENARIO, default_data=1)      dn_output_config = Config.configure_data_node("output", "pickle")      task_config = Config.configure_task("task_config", modified_config_task, dn_input_config, dn_output_config)      scenario_config = Config.configure_scenario("scenario_config", [task_config])        _OrchestratorFactory._build_dispatcher()        scenario = _ScenarioManager._create(scenario_config)        jobs = scenario.submit()      assert_true_after_time(jobs[0].is_finished, time=120)      assert_true_after_time(          jobs[0].is_completed      )  # If the job is completed, that means the asserts in the task are successful      def update_config_task(n):      from taipy.config import Config        # The exception will be saved to logger, and there is no way to check for it      # so it will be checked here      with pytest.raises(ConfigurationUpdateBlocked):          Config.core.storage_folder = ".new_storage_folder/"      with pytest.raises(ConfigurationUpdateBlocked):          Config.core.properties = {"custom_property": "new_custom_property"}        Config.core.storage_folder = ".new_storage_folder/"      Config.core.properties = {"custom_property": "new_custom_property"}        return n * 2      def test_cannot_exec_task_that_update_config():      """      _ConfigBlocker singleton is not passed to the subprocesses. That means in each subprocess,      the config update will not be blocked.        After rebuilding a new Config in each subprocess, the Config should be blocked.      """      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        dn_input_config = Config.configure_data_node("input", "pickle", scope=Scope.SCENARIO, default_data=1)      dn_output_config = Config.configure_data_node("output", "pickle")      task_config = Config.configure_task("task_config", update_config_task, dn_input_config, dn_output_config)      scenario_config = Config.configure_scenario("scenario_config", [task_config])        _OrchestratorFactory._build_dispatcher()        scenario = _ScenarioManager._create(scenario_config)        jobs = scenario.submit()        # The job should fail due to an exception is raised      assert_true_after_time(jobs[0].is_failed)      def test_can_execute_task_with_development_mode():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)        dn_input_config = Config.configure_data_node("input", "pickle", scope=Scope.SCENARIO, default_data=1)      dn_output_config = Config.configure_data_node("output", "pickle")      task_config = Config.configure_task("task_config", mult_by_2, dn_input_config, dn_output_config)      scenario_config = Config.configure_scenario("scenario_config", [task_config])        _OrchestratorFactory._build_dispatcher()        scenario = _ScenarioManager._create(scenario_config)      scenario.submit()      while scenario.output.edit_in_progress:          sleep(1)      assert 2 == scenario.output.read()      def test_need_to_run_no_output():      hello_cfg = Config.configure_data_node("hello", default_data="Hello ")      world_cfg = Config.configure_data_node("world", default_data="world !")      task_cfg = Config.configure_task("name", input=[hello_cfg, world_cfg], function=concat, output=[])      task = _create_task_from_config(task_cfg)        assert _OrchestratorFactory._dispatcher._needs_to_run(task)      def test_need_to_run_task_not_skippable():      hello_cfg = Config.configure_data_node("hello", default_data="Hello ")      world_cfg = Config.configure_data_node("world", default_data="world !")      hello_world_cfg = Config.configure_data_node("hello_world")      task_cfg = Config.configure_task(          "name", input=[hello_cfg, world_cfg], function=concat, output=[hello_world_cfg], skippable=False      )      task = _create_task_from_config(task_cfg)        assert _OrchestratorFactory._dispatcher._needs_to_run(task)      def test_need_to_run_skippable_task_no_input():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)        hello_world_cfg = Config.configure_data_node("hello_world")      task_cfg = Config.configure_task("name", input=[], function=nothing, output=[hello_world_cfg], skippable=True)        _OrchestratorFactory._build_dispatcher()        task = _create_task_from_config(task_cfg)      assert _OrchestratorFactory._dispatcher._needs_to_run(task)      _Orchestrator.submit_task(task)        assert not _OrchestratorFactory._dispatcher._needs_to_run(task)      def test_need_to_run_skippable_task_no_validity_period_on_output():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)        hello_cfg = Config.configure_data_node("hello", default_data="Hello ")      world_cfg = Config.configure_data_node("world", default_data="world !")      hello_world_cfg = Config.configure_data_node("hello_world")      task_cfg = Config.configure_task(          "name", input=[hello_cfg, world_cfg], function=concat, output=[hello_world_cfg], skippable=True      )        _OrchestratorFactory._build_dispatcher()        task = _create_task_from_config(task_cfg)      assert _OrchestratorFactory._dispatcher._needs_to_run(task)      _Orchestrator.submit_task(task)        assert not _OrchestratorFactory._dispatcher._needs_to_run(task)      def test_need_to_run_skippable_task_with_validity_period_is_valid_on_output():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)        hello_cfg = Config.configure_data_node("hello", default_data="Hello ")      world_cfg = Config.configure_data_node("world", default_data="world !")      hello_world_cfg = Config.configure_data_node("hello_world", validity_days=1)      task_cfg = Config.configure_task(          "name", input=[hello_cfg, world_cfg], function=concat, output=[hello_world_cfg], skippable=True      )      _OrchestratorFactory._build_dispatcher()        task = _create_task_from_config(task_cfg)        assert _OrchestratorFactory._dispatcher._needs_to_run(task)      job = _Orchestrator.submit_task(task)        assert not _OrchestratorFactory._dispatcher._needs_to_run(task)      job_skipped = _Orchestrator.submit_task(task)        assert job.is_completed()      assert job.is_finished()      assert job_skipped.is_skipped()      assert job_skipped.is_finished()      def test_need_to_run_skippable_task_with_validity_period_obsolete_on_output():      hello_cfg = Config.configure_data_node("hello", default_data="Hello ")      world_cfg = Config.configure_data_node("world", default_data="world !")      hello_world_cfg = Config.configure_data_node("hello_world", validity_days=1)      task_cfg = Config.configure_task(          "name", input=[hello_cfg, world_cfg], function=concat, output=[hello_world_cfg], skippable=True      )      task = _create_task_from_config(task_cfg)        assert _OrchestratorFactory._dispatcher._needs_to_run(task)      _Orchestrator.submit_task(task)        output = task.hello_world      output._last_edit_date = datetime.now() - timedelta(days=1, minutes=30)      _DataManager()._set(output)      assert _OrchestratorFactory._dispatcher._needs_to_run(task)      # ################################  UTIL METHODS    ##################################      def _create_task(function, nb_outputs=1):      output_dn_config_id = "".join(random.choice(string.ascii_lowercase) for _ in range(10))      dn_input_configs = [          Config.configure_data_node("input1", "pickle", Scope.SCENARIO, default_data=21),          Config.configure_data_node("input2", "pickle", Scope.SCENARIO, default_data=2),      ]      dn_output_configs = [          Config.configure_data_node(f"{output_dn_config_id}_output{i}", "pickle", Scope.SCENARIO, default_data=0)          for i in range(nb_outputs)      ]      input_dn = _DataManager._bulk_get_or_create(dn_input_configs).values()      output_dn = _DataManager._bulk_get_or_create(dn_output_configs).values()      return Task(          output_dn_config_id,          {},          function=function,          input=input_dn,          output=output_dn,      )      def _create_task_from_config(task_cfg):      return _TaskManager()._bulk_get_or_create([task_cfg])[0]


from unittest import mock    import pytest    from src.taipy.core._orchestrator._dispatcher import _DevelopmentJobDispatcher, _JobDispatcher, _StandaloneJobDispatcher  from src.taipy.core._orchestrator._orchestrator import _Orchestrator  from src.taipy.core._orchestrator._orchestrator_factory import _OrchestratorFactory  from src.taipy.core.config.job_config import JobConfig  from src.taipy.core.exceptions.exceptions import OrchestratorNotBuilt  from taipy.config import Config      def test_build_orchestrator():      _OrchestratorFactory._orchestrator = None      _OrchestratorFactory._dispatcher = None        assert _OrchestratorFactory._orchestrator is None      assert _OrchestratorFactory._dispatcher is None        orchestrator = _OrchestratorFactory._build_orchestrator()      assert orchestrator == _Orchestrator      assert _OrchestratorFactory._orchestrator == _Orchestrator      dispatcher = _OrchestratorFactory._build_dispatcher()      assert isinstance(dispatcher, _JobDispatcher)      assert isinstance(_OrchestratorFactory._dispatcher, _JobDispatcher)        _OrchestratorFactory._orchestrator = None      assert _OrchestratorFactory._orchestrator is None      assert _OrchestratorFactory._dispatcher is not None        with mock.patch(          "src.taipy.core._orchestrator._orchestrator_factory._OrchestratorFactory._build_dispatcher"      ) as build_dispatcher, mock.patch(          "src.taipy.core._orchestrator._orchestrator._Orchestrator.initialize"      ) as initialize:          orchestrator = _OrchestratorFactory._build_orchestrator()          assert orchestrator == _Orchestrator          assert _OrchestratorFactory._orchestrator == _Orchestrator          build_dispatcher.assert_not_called()          initialize.assert_called_once()      def test_build_development_dispatcher():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)      _OrchestratorFactory._orchestrator = None      _OrchestratorFactory._dispatcher = None        assert _OrchestratorFactory._orchestrator is None      assert _OrchestratorFactory._dispatcher is None        with pytest.raises(OrchestratorNotBuilt):          _OrchestratorFactory._build_dispatcher()        _OrchestratorFactory._build_orchestrator()      assert _OrchestratorFactory._orchestrator is not None      assert _OrchestratorFactory._dispatcher is None        _OrchestratorFactory._build_dispatcher()      assert isinstance(_OrchestratorFactory._dispatcher, _DevelopmentJobDispatcher)      def test_build_standalone_dispatcher():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)      _OrchestratorFactory._build_dispatcher()      assert isinstance(_OrchestratorFactory._dispatcher, _StandaloneJobDispatcher)      assert not isinstance(_OrchestratorFactory._dispatcher, _DevelopmentJobDispatcher)      assert _OrchestratorFactory._dispatcher.is_running()      assert _OrchestratorFactory._dispatcher._nb_available_workers == 2      _OrchestratorFactory._dispatcher._nb_available_workers = 1        _OrchestratorFactory._build_dispatcher(force_restart=False)      assert _OrchestratorFactory._dispatcher.is_running()      assert _OrchestratorFactory._dispatcher._nb_available_workers == 1        _OrchestratorFactory._build_dispatcher(force_restart=True)      assert _OrchestratorFactory._dispatcher.is_running()      assert _OrchestratorFactory._dispatcher._nb_available_workers == 2


import multiprocessing  from concurrent.futures import ProcessPoolExecutor  from functools import partial  from unittest import mock  from unittest.mock import MagicMock    from pytest import raises    from src.taipy.core import DataNodeId, JobId, TaskId  from src.taipy.core._orchestrator._dispatcher._development_job_dispatcher import _DevelopmentJobDispatcher  from src.taipy.core._orchestrator._dispatcher._standalone_job_dispatcher import _StandaloneJobDispatcher  from src.taipy.core._orchestrator._orchestrator_factory import _OrchestratorFactory  from src.taipy.core.config.job_config import JobConfig  from src.taipy.core.data._data_manager import _DataManager  from src.taipy.core.job.job import Job  from src.taipy.core.submission._submission_manager_factory import _SubmissionManagerFactory  from src.taipy.core.task.task import Task  from taipy.config.config import Config  from tests.core.utils import assert_true_after_time      def execute(lock):      with lock:          ...      return None      def _error():      raise RuntimeError("Something bad has happened")      def test_build_development_job_dispatcher():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)      _OrchestratorFactory._build_dispatcher()      dispatcher = _OrchestratorFactory._dispatcher        assert isinstance(dispatcher, _DevelopmentJobDispatcher)      assert dispatcher._nb_available_workers == 1        with raises(NotImplementedError):          assert dispatcher.start()        assert dispatcher.is_running()        with raises(NotImplementedError):          dispatcher.stop()      def test_build_standalone_job_dispatcher():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)      _OrchestratorFactory._build_dispatcher()      dispatcher = _OrchestratorFactory._dispatcher        assert not isinstance(dispatcher, _DevelopmentJobDispatcher)      assert isinstance(dispatcher, _StandaloneJobDispatcher)      assert isinstance(dispatcher._executor, ProcessPoolExecutor)      assert dispatcher._nb_available_workers == 2      assert_true_after_time(dispatcher.is_running)      dispatcher.stop()      dispatcher.join()      assert_true_after_time(lambda: not dispatcher.is_running())      def test_can_execute_2_workers():      Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)        m = multiprocessing.Manager()      lock = m.Lock()        task_id = TaskId("task_id1")      output = list(_DataManager._bulk_get_or_create([Config.configure_data_node("input1", default_data=21)]).values())        _OrchestratorFactory._build_dispatcher()        task = Task(          config_id="name",          properties={},          input=[],          function=partial(execute, lock),          output=output,          id=task_id,      )      job_id = JobId("id1")      job = Job(job_id, task, "submit_id", task.id)        dispatcher = _StandaloneJobDispatcher(_OrchestratorFactory._orchestrator)        with lock:          assert dispatcher._can_execute()          dispatcher._dispatch(job)          assert dispatcher._can_execute()          dispatcher._dispatch(job)          assert not dispatcher._can_execute()        assert_true_after_time(lambda: dispatcher._can_execute())      def test_can_execute_synchronous():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)      _OrchestratorFactory._build_dispatcher()        task_id = TaskId("task_id1")      task = Task(config_id="name", properties={}, input=[], function=print, output=[], id=task_id)      submission = _SubmissionManagerFactory._build_manager()._create(task_id)      job_id = JobId("id1")      job = Job(job_id, task, submission.id, task.id)        dispatcher = _OrchestratorFactory._dispatcher        assert dispatcher._can_execute()      dispatcher._dispatch(job)      assert dispatcher._can_execute()      def test_exception_in_user_function():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)      _OrchestratorFactory._build_dispatcher()        task_id = TaskId("task_id1")      job_id = JobId("id1")      task = Task(config_id="name", properties={}, input=[], function=_error, output=[], id=task_id)      submission = _SubmissionManagerFactory._build_manager()._create(task_id)      job = Job(job_id, task, submission.id, task.id)        dispatcher = _OrchestratorFactory._dispatcher      dispatcher._dispatch(job)      assert job.is_failed()      assert 'RuntimeError("Something bad has happened")' in str(job.stacktrace[0])      def test_exception_in_writing_data():      Config.configure_job_executions(mode=JobConfig._DEVELOPMENT_MODE)      _OrchestratorFactory._build_dispatcher()        task_id = TaskId("task_id1")      job_id = JobId("id1")      output = MagicMock()      output.id = DataNodeId("output_id")      output.config_id = "my_raising_datanode"      output._is_in_cache = False      output.write.side_effect = ValueError()      task = Task(config_id="name", properties={}, input=[], function=print, output=[output], id=task_id)      submission = _SubmissionManagerFactory._build_manager()._create(task_id)      job = Job(job_id, task, submission.id, task.id)        dispatcher = _OrchestratorFactory._dispatcher        with mock.patch("src.taipy.core.data._data_manager._DataManager._get") as get:          get.return_value = output          dispatcher._dispatch(job)          assert job.is_failed()          assert "node" in job.stacktrace[0]


from unittest import mock    import pytest    from src.taipy.core.config.data_node_config import DataNodeConfig  from src.taipy.core.data._data_manager import _DataManager  from src.taipy.core.data.csv import CSVDataNode  from src.taipy.core.data.data_node import DataNode  from src.taipy.core.data.in_memory import InMemoryDataNode  from src.taipy.core.task._task_manager import _TaskManager  from src.taipy.core.task.task import Task  from taipy.config.common.scope import Scope  from taipy.config.config import Config  from taipy.config.exceptions.exceptions import InvalidConfigurationId      @pytest.fixture  def output():      return [DataNode("name_1"), DataNode("name_2"), DataNode("name_3")]      @pytest.fixture  def output_config():      return [DataNodeConfig("name_1"), DataNodeConfig("name_2"), DataNodeConfig("name_3")]      @pytest.fixture  def input():      return [DataNode("input_name_1"), DataNode("input_name_2"), DataNode("input_name_3")]      @pytest.fixture  def input_config():      return [DataNodeConfig("input_name_1"), DataNodeConfig("input_name_2"), DataNodeConfig("input_name_3")]      def test_create_task():      name = "name_1"      task = Task(name, {}, print, [], [])      assert f"TASK_{name}_" in task.id      assert task.config_id == "name_1"        with pytest.raises(InvalidConfigurationId):          Task("foo bar", {}, print, [], [])        path = "my/csv/path"      foo_dn = CSVDataNode("foo", Scope.SCENARIO, properties={"path": path, "has_header": True})      task = Task("name_1", {}, print, [foo_dn], [])      assert task.config_id == "name_1"      assert task.id is not None      assert task.owner_id is None      assert task.parent_ids == set()      assert task.foo == foo_dn      assert task.foo.path == path      with pytest.raises(AttributeError):          task.bar        task = Task("name_1", {}, print, [foo_dn], [], parent_ids={"parent_id"})      assert task.parent_ids == {"parent_id"}        path = "my/csv/path"      abc_dn = InMemoryDataNode("name_1ea", Scope.SCENARIO, properties={"path": path})        task = Task("name_1ea", {}, print, [abc_dn], [], owner_id="owner_id", parent_ids={"parent_id_1", "parent_id_2"})      assert task.config_id == "name_1ea"      assert task.id is not None      assert task.owner_id == "owner_id"      assert task.parent_ids == {"parent_id_1", "parent_id_2"}      assert task.name_1ea == abc_dn      assert task.name_1ea.path == path      with pytest.raises(AttributeError):          task.bar      with mock.patch("src.taipy.core.get") as get_mck:            class MockOwner:              label = "owner_label"                def get_label(self):                  return self.label            get_mck.return_value = MockOwner()          assert task.get_label() == "owner_label > " + task.config_id          assert task.get_simple_label() == task.config_id      def test_can_not_change_task_output(output):      task = Task("name_1", {}, print, output=output)        with pytest.raises(Exception):          task.output = {}        assert list(task.output.values()) == output      output.append(output[0])      assert list(task.output.values()) != output      def test_can_not_change_task_input(input):      task = Task("name_1", {}, print, input=input)        with pytest.raises(Exception):          task.input = {}        assert list(task.input.values()) == input      input.append(input[0])      assert list(task.input.values()) != input      def test_can_not_change_task_config_output(output_config):      task_config = Config.configure_task("name_1", print, [], output=output_config)        assert task_config.output_configs == output_config      with pytest.raises(Exception):          task_config.output_configs = []        output_config.append(output_config[0])      assert task_config._output != output_config      def test_can_not_update_task_output_values(output_config):      data_node_cfg = Config.configure_data_node("data_node_cfg")      task_config = Config.configure_task("name_1", print, [], output=output_config)        task_config.output_configs.append(data_node_cfg)      assert task_config.output_configs == output_config        task_config.output_configs[0] = data_node_cfg      assert task_config.output_configs[0] != data_node_cfg      def test_can_not_update_task_input_values(input_config):      data_node_config = DataNodeConfig("data_node")      task_config = Config.configure_task("name_1", print, input=input_config, output=[])        task_config.input_configs.append(data_node_config)      assert task_config.input_configs == input_config        task_config.input_configs[0] = data_node_config      assert task_config.input_configs[0] != data_node_config      def mock_func():      pass      def test_auto_set_and_reload(data_node):      task_1 = Task(          config_id="foo", properties={}, function=print, input=None, output=None, owner_id=None, skippable=False      )        _DataManager._set(data_node)      _TaskManager._set(task_1)        task_2 = _TaskManager._get(task_1)        # auto set & reload on function attribute      assert task_1.function == print      assert task_2.function == print      task_1.function = sum      assert task_1.function == sum      assert task_2.function == sum      task_2.function = mock_func      assert task_1.function == mock_func      assert task_2.function == mock_func        # auto set & reload on skippable attribute      assert not task_1.skippable      assert not task_2.skippable      task_1.skippable = True      assert task_1.skippable      assert task_2.skippable      task_2.skippable = False      assert not task_1.skippable      assert not task_2.skippable        # auto set & reload on parent_ids attribute (set() object does not have auto set yet)      assert task_1.parent_ids == set()      assert task_2.parent_ids == set()      task_1._parent_ids.update(["sc2"])      _TaskManager._set(task_1)      assert task_1.parent_ids == {"sc2"}      assert task_2.parent_ids == {"sc2"}      task_2._parent_ids.clear()      task_2._parent_ids.update(["sc1"])      _TaskManager._set(task_2)      assert task_1.parent_ids == {"sc1"}      assert task_2.parent_ids == {"sc1"}        # auto set & reload on properties attribute      assert task_1.properties == {}      assert task_2.properties == {}      task_1._properties["qux"] = 4      assert task_1.properties["qux"] == 4      assert task_2.properties["qux"] == 4        assert task_1.properties == {"qux": 4}      assert task_2.properties == {"qux": 4}      task_2._properties["qux"] = 5      assert task_1.properties["qux"] == 5      assert task_2.properties["qux"] == 5        task_1.properties["temp_key_1"] = "temp_value_1"      task_1.properties["temp_key_2"] = "temp_value_2"      assert task_1.properties == {          "qux": 5,          "temp_key_1": "temp_value_1",          "temp_key_2": "temp_value_2",      }      assert task_2.properties == {          "qux": 5,          "temp_key_1": "temp_value_1",          "temp_key_2": "temp_value_2",      }      task_1.properties.pop("temp_key_1")      assert "temp_key_1" not in task_1.properties.keys()      assert "temp_key_1" not in task_1.properties.keys()      assert task_1.properties == {          "qux": 5,          "temp_key_2": "temp_value_2",      }      assert task_2.properties == {          "qux": 5,          "temp_key_2": "temp_value_2",      }      task_2.properties.pop("temp_key_2")      assert task_1.properties == {"qux": 5}      assert task_2.properties == {"qux": 5}      assert "temp_key_2" not in task_1.properties.keys()      assert "temp_key_2" not in task_2.properties.keys()        task_1.properties["temp_key_3"] = 0      assert task_1.properties == {"qux": 5, "temp_key_3": 0}      assert task_2.properties == {"qux": 5, "temp_key_3": 0}      task_1.properties.update({"temp_key_3": 1})      assert task_1.properties == {"qux": 5, "temp_key_3": 1}      assert task_2.properties == {"qux": 5, "temp_key_3": 1}      task_1.properties.update(dict())      assert task_1.properties == {"qux": 5, "temp_key_3": 1}      assert task_2.properties == {"qux": 5, "temp_key_3": 1}      task_1.properties["temp_key_4"] = 0      task_1.properties["temp_key_5"] = 0        with task_1 as task:          assert task.config_id == "foo"          assert task.owner_id is None          assert task.function == mock_func          assert not task.skippable          assert task._is_in_context          assert task.properties["qux"] == 5          assert task.properties["temp_key_3"] == 1          assert task.properties["temp_key_4"] == 0          assert task.properties["temp_key_5"] == 0            task.function = print          task.skippable = True          task.properties["qux"] = 9          task.properties.pop("temp_key_3")          task.properties.pop("temp_key_4")          task.properties.update({"temp_key_4": 1})          task.properties.update({"temp_key_5": 2})          task.properties.pop("temp_key_5")          task.properties.update(dict())            assert task.config_id == "foo"          assert task.owner_id is None          assert task.function == mock_func          assert not task.skippable          assert task._is_in_context          assert task.properties["qux"] == 5          assert task.properties["temp_key_3"] == 1          assert task.properties["temp_key_4"] == 0          assert task.properties["temp_key_5"] == 0        assert task_1.config_id == "foo"      assert task_1.owner_id is None      assert task_1.function == print      assert task.skippable      assert not task_1._is_in_context      assert task_1.properties["qux"] == 9      assert "temp_key_3" not in task_1.properties.keys()      assert task_1.properties["temp_key_4"] == 1      assert "temp_key_5" not in task_1.properties.keys()      def test_get_parents(task):      with mock.patch("src.taipy.core.get_parents") as mck:          task.get_parents()          mck.assert_called_once_with(task)      def test_submit_task(task: Task):      with mock.patch("src.taipy.core.task._task_manager._TaskManager._submit") as mock_submit:          task.submit([], True)          mock_submit.assert_called_once_with(task, [], True, False, None)


import os    import pytest    from src.taipy.core.data._data_sql_repository import _DataSQLRepository  from src.taipy.core.exceptions import ModelNotFound  from src.taipy.core.task._task_fs_repository import _TaskFSRepository  from src.taipy.core.task._task_sql_repository import _TaskSQLRepository  from src.taipy.core.task.task import Task, TaskId      class TestTaskFSRepository:      @pytest.mark.parametrize("repo", [_TaskFSRepository, _TaskSQLRepository])      def test_save_and_load(self, data_node, repo, init_sql_repo):          repository = repo()          _DataSQLRepository()._save(data_node)          task = Task("task_config_id", {}, print, [data_node], [data_node])            repository._save(task)            obj = repository._load(task.id)          assert isinstance(obj, Task)        @pytest.mark.parametrize("repo", [_TaskFSRepository, _TaskSQLRepository])      def test_exists(self, data_node, repo, init_sql_repo):          repository = repo()          _DataSQLRepository()._save(data_node)          task = Task("task_config_id", {}, print, [data_node], [data_node])            repository._save(task)            assert repository._exists(task.id)          assert not repository._exists("not-existed-task")        @pytest.mark.parametrize("repo", [_TaskFSRepository, _TaskSQLRepository])      def test_load_all(self, data_node, repo, init_sql_repo):          repository = repo()          _DataSQLRepository()._save(data_node)          task = Task("task_config_id", {}, print, [data_node], [data_node])            for i in range(10):              task.id = TaskId(f"task-{i}")              repository._save(task)          data_nodes = repository._load_all()            assert len(data_nodes) == 10        @pytest.mark.parametrize("repo", [_TaskFSRepository, _TaskSQLRepository])      def test_load_all_with_filters(self, data_node, repo, init_sql_repo):          repository = repo()          _DataSQLRepository()._save(data_node)          task = Task("task_config_id", {}, print, [data_node], [data_node])            for i in range(10):              task.id = TaskId(f"task-{i}")              task.owner_id = f"owner-{i}"              repository._save(task)          objs = repository._load_all(filters=[{"owner_id": "owner-2"}])            assert len(objs) == 1        @pytest.mark.parametrize("repo", [_TaskFSRepository, _TaskSQLRepository])      def test_delete(self, data_node, repo, init_sql_repo):          repository = repo()          _DataSQLRepository()._save(data_node)          task = Task("task_config_id", {}, print, [data_node], [data_node])          repository._save(task)            repository._delete(task.id)            with pytest.raises(ModelNotFound):              repository._load(task.id)        @pytest.mark.parametrize("repo", [_TaskFSRepository, _TaskSQLRepository])      def test_delete_all(self, data_node, repo, init_sql_repo):          repository = repo()          _DataSQLRepository()._save(data_node)          task = Task("task_config_id", {}, print, [data_node], [data_node])            for i in range(10):              task.id = TaskId(f"task-{i}")              repository._save(task)            assert len(repository._load_all()) == 10            repository._delete_all()            assert len(repository._load_all()) == 0        @pytest.mark.parametrize("repo", [_TaskFSRepository, _TaskSQLRepository])      def test_delete_many(self, data_node, repo, init_sql_repo):          repository = repo()          _DataSQLRepository()._save(data_node)          task = Task("task_config_id", {}, print, [data_node], [data_node])            for i in range(10):              task.id = TaskId(f"task-{i}")              repository._save(task)            objs = repository._load_all()          assert len(objs) == 10          ids = [x.id for x in objs[:3]]          repository._delete_many(ids)            assert len(repository._load_all()) == 7        @pytest.mark.parametrize("repo", [_TaskFSRepository, _TaskSQLRepository])      def test_delete_by(self, data_node, repo, init_sql_repo):          repository = repo()          _DataSQLRepository()._save(data_node)          task = Task("task_config_id", {}, print, [data_node], [data_node])            # Create 5 entities with version 1.0 and 5 entities with version 2.0          for i in range(10):              task.id = TaskId(f"task-{i}")              task._version = f"{(i+1) // 5}.0"              repository._save(task)            objs = repository._load_all()          assert len(objs) == 10          repository._delete_by("version", "1.0")            assert len(repository._load_all()) == 5        @pytest.mark.parametrize("repo", [_TaskFSRepository, _TaskSQLRepository])      def test_search(self, data_node, repo, init_sql_repo):          repository = repo()          _DataSQLRepository()._save(data_node)          task = Task("task_config_id", {}, print, [data_node], [data_node], version="random_version_number")            for i in range(10):              task.id = TaskId(f"task-{i}")              task.owner_id = f"owner-{i}"              repository._save(task)            assert len(repository._load_all()) == 10            objs = repository._search("owner_id", "owner-2")          assert len(objs) == 1          assert isinstance(objs[0], Task)            objs = repository._search("owner_id", "owner-2", filters=[{"version": "random_version_number"}])          assert len(objs) == 1          assert isinstance(objs[0], Task)            assert repository._search("owner_id", "owner-2", filters=[{"version": "non_existed_version"}]) == []        @pytest.mark.parametrize("repo", [_TaskFSRepository, _TaskSQLRepository])      def test_export(self, tmpdir, data_node, repo, init_sql_repo):          repository = repo()          _DataSQLRepository()._save(data_node)          task = Task("task_config_id", {}, print, [data_node], [data_node])          repository._save(task)            repository._export(task.id, tmpdir.strpath)          dir_path = repository.dir_path if repo == _TaskFSRepository else os.path.join(tmpdir.strpath, "task")            assert os.path.exists(os.path.join(dir_path, f"{task.id}.json"))