Răsfoiți Sursa

Merge branch 'develop' into feature/gui-builder-direct-variable-passing

Dinh Long Nguyen 1 an în urmă
părinte
comite
2db60f2c89
74 a modificat fișierele cu 331 adăugiri și 377 ștergeri
  1. 5 4
      .github/workflows/build-and-release-dev.yml
  2. 1 1
      .github/workflows/build-and-release-prod.yml
  3. 6 2
      taipy/config/common/_config_blocker.py
  4. 1 0
      taipy/config/setup.py
  5. 1 1
      taipy/config/version.json
  6. 33 15
      taipy/core/_core.py
  7. 1 0
      taipy/core/_init.py
  8. 2 2
      taipy/core/_version/_cli/_version_cli.py
  9. 2 2
      taipy/core/_version/_version_manager.py
  10. 2 2
      taipy/core/common/_warnings.py
  11. 1 0
      taipy/core/setup.py
  12. 37 9
      taipy/core/taipy.py
  13. 1 1
      taipy/core/version.json
  14. 5 1
      taipy/gui/partial.py
  15. 1 0
      taipy/gui/setup.py
  16. 1 1
      taipy/gui/version.json
  17. 1 0
      taipy/rest/setup.py
  18. 1 1
      taipy/rest/version.json
  19. 1 0
      taipy/templates/setup.py
  20. 1 1
      taipy/templates/version.json
  21. 1 1
      taipy/version.json
  22. 2 4
      tests/core/_backup/test_backup.py
  23. 1 0
      tests/core/_orchestrator/test_orchestrator__cancel_jobs.py
  24. 4 4
      tests/core/_orchestrator/test_orchestrator__is_blocked.py
  25. 2 2
      tests/core/_orchestrator/test_orchestrator__lock_dn_output_and_create_job.py
  26. 3 2
      tests/core/_orchestrator/test_orchestrator__orchestrate_job_to_run_or_block.py
  27. 1 9
      tests/core/config/checkers/test_migration_config_checker.py
  28. 4 1
      tests/core/conftest.py
  29. 12 12
      tests/core/data/test_data_manager.py
  30. 2 1
      tests/core/notification/test_core_event_consumer.py
  31. 6 4
      tests/core/notification/test_events_published.py
  32. 9 7
      tests/core/notification/test_notifier.py
  33. 23 26
      tests/core/test_complex_application.py
  34. 59 66
      tests/core/test_core.py
  35. 19 14
      tests/core/test_taipy.py
  36. 1 3
      tests/gui/actions/test_download.py
  37. 1 3
      tests/gui/actions/test_get_state_id.py
  38. 1 3
      tests/gui/actions/test_hold_control.py
  39. 1 3
      tests/gui/actions/test_invoke_callback.py
  40. 1 3
      tests/gui/actions/test_navigate.py
  41. 1 3
      tests/gui/actions/test_notify.py
  42. 1 3
      tests/gui/actions/test_resume_control.py
  43. 7 0
      tests/gui/conftest.py
  44. 1 3
      tests/gui/data/test_pandas_data_accessor.py
  45. 1 3
      tests/gui/gui_specific/test_folder_pages_binding.py
  46. 7 15
      tests/gui/gui_specific/test_gui.py
  47. 1 3
      tests/gui/gui_specific/test_locals_context.py
  48. 2 4
      tests/gui/gui_specific/test_multiple_instances.py
  49. 4 9
      tests/gui/gui_specific/test_navigate.py
  50. 2 5
      tests/gui/gui_specific/test_partial.py
  51. 1 3
      tests/gui/gui_specific/test_render_route.py
  52. 2 5
      tests/gui/gui_specific/test_run_thread.py
  53. 1 3
      tests/gui/gui_specific/test_state.py
  54. 3 7
      tests/gui/gui_specific/test_variable_binding.py
  55. 3 7
      tests/gui/helpers.py
  56. 1 3
      tests/gui/ignore/no_file/test_ignore.py
  57. 2 5
      tests/gui/ignore/with_file/test_with_ignore.py
  58. 1 3
      tests/gui/long_runnig/test_long_running.py
  59. 1 3
      tests/gui/renderers/test_html_parsing.py
  60. 2 5
      tests/gui/server/http/test_extension.py
  61. 6 13
      tests/gui/server/http/test_file_upload.py
  62. 2 5
      tests/gui/server/http/test_image_path.py
  63. 3 7
      tests/gui/server/http/test_status.py
  64. 3 7
      tests/gui/server/http/test_user_content.py
  65. 1 3
      tests/gui/server/ws/test_a.py
  66. 1 3
      tests/gui/server/ws/test_broadcast.py
  67. 1 3
      tests/gui/server/ws/test_df.py
  68. 1 3
      tests/gui/server/ws/test_du.py
  69. 2 5
      tests/gui/server/ws/test_on_change.py
  70. 1 3
      tests/gui/server/ws/test_ru.py
  71. 1 3
      tests/gui/server/ws/test_u.py
  72. 1 3
      tests/gui/server/ws/test_with.py
  73. 6 13
      tests/gui/utils/test_evaluator.py
  74. 1 3
      tests/gui/utils/test_map_dict.py

+ 5 - 4
.github/workflows/build-and-release-dev.yml

@@ -193,11 +193,12 @@ jobs:
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
+      - uses: stefanzweifel/git-auto-commit-action@v4
+        with:
+          file_pattern: '*/version.json'
+          commit_message: Update version to ${{ needs.fetch-versions.outputs.NEW_VERSION }}
+
       - name: Reset changes
         run: |
           git reset --hard HEAD
           git clean -fdx
-
-      - uses: stefanzweifel/git-auto-commit-action@v4
-        with:
-          commit_message: Update version to ${{ needs.fetch-versions.outputs.NEW_VERSION }}

+ 1 - 1
.github/workflows/build-and-release-prod.yml

@@ -1,4 +1,4 @@
-name: Build a dev version for all packages and release them
+name: Build a prod version for all packages and release them
 
 on:
   workflow_dispatch:

+ 6 - 2
taipy/config/common/_config_blocker.py

@@ -23,11 +23,15 @@ class _ConfigBlocker:
 
     @classmethod
     def _block(cls):
-        cls.__block_config_update = True
+        if not cls.__block_config_update:
+            cls.__logger.info("Blocking configuration update.")
+            cls.__block_config_update = True
 
     @classmethod
     def _unblock(cls):
-        cls.__block_config_update = False
+        if cls.__block_config_update:
+            cls.__logger.info("Unblocking configuration update.")
+            cls.__block_config_update = False
 
     @classmethod
     def _check(cls):

+ 1 - 0
taipy/config/setup.py

@@ -57,6 +57,7 @@ setup(
     packages=find_namespace_packages(where=".")
     + find_packages(include=["taipy", "taipy.config", "taipy.config.*", "taipy.logger", "taipy.logger.*"]),
     include_package_data=True,
+    data_files=[('version', ['version.json'])],
     test_suite="tests",
     tests_require=test_requirements,
     url="https://github.com/avaiga/taipy-config",

+ 1 - 1
taipy/config/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 0, "ext": "dev0"}
+{"major": 3, "minor": 1, "patch": 0, "ext": "dev1"}

+ 33 - 15
taipy/core/_core.py

@@ -33,6 +33,9 @@ class Core:
     _is_running = False
     __lock_is_running = Lock()
 
+    _version_is_initialized = False
+    __lock_version_is_initialized = Lock()
+
     __logger = _TaipyLogger._get_logger()
 
     _orchestrator: Optional[_Orchestrator] = None
@@ -48,8 +51,8 @@ class Core:
         """
         Start a Core service.
 
-        This function checks the configuration, manages application's version,
-        and starts a dispatcher and lock the Config.
+        This function checks and locks the configuration, manages application's version,
+        and starts a job dispatcher.
         """
         if self.__class__._is_running:
             raise CoreServiceIsAlreadyRunning
@@ -57,13 +60,7 @@ class Core:
         with self.__class__.__lock_is_running:
             self.__class__._is_running = True
 
-        self.__update_core_section()
-        self.__manage_version()
-        self.__check_and_block_config()
-
-        if self._orchestrator is None:
-            self._orchestrator = _OrchestratorFactory._build_orchestrator()
-
+        self._manage_version_and_block_config()
         self.__start_dispatcher(force_restart)
 
     def stop(self, wait: bool = True, timeout: Optional[float] = None):
@@ -84,25 +81,46 @@ class Core:
         with self.__class__.__lock_is_running:
             self.__class__._is_running = False
 
-    @staticmethod
-    def __update_core_section():
+        with self.__class__.__lock_version_is_initialized:
+            self.__class__._version_is_initialized = False
+
+    @classmethod
+    def _manage_version_and_block_config(cls):
+        """
+        Manage the application's version and block the Config from updates.
+        """
+        if cls._version_is_initialized:
+            return
+
+        with cls.__lock_version_is_initialized:
+            cls._version_is_initialized = True
+
+        cls.__update_core_section()
+        cls.__manage_version()
+        cls.__check_and_block_config()
+
+    @classmethod
+    def __update_core_section(cls):
         _CoreCLI.create_parser()
         Config._applied_config._unique_sections[CoreSection.name]._update(_CoreCLI.parse_arguments())
 
-    @staticmethod
-    def __manage_version():
+    @classmethod
+    def __manage_version(cls):
         _VersionManagerFactory._build_manager()._manage_version()
         Config._applied_config._unique_sections[CoreSection.name]._update(
             {"version_number": _VersionManagerFactory._build_manager()._get_latest_version()}
         )
 
-    @staticmethod
-    def __check_and_block_config():
+    @classmethod
+    def __check_and_block_config(cls):
         Config.check()
         Config.block_update()
         _init_backup_file_with_storage_folder()
 
     def __start_dispatcher(self, force_restart):
+        if self._orchestrator is None:
+            self._orchestrator = _OrchestratorFactory._build_orchestrator()
+
         if dispatcher := _OrchestratorFactory._build_dispatcher(force_restart=force_restart):
             self._dispatcher = dispatcher
 

+ 1 - 0
taipy/core/_init.py

@@ -26,6 +26,7 @@ from .submission.submission import Submission
 from .submission.submission_id import SubmissionId
 from .taipy import (
     cancel_job,
+    clean_all_entities,
     clean_all_entities_by_version,
     compare_scenarios,
     create_global_data_node,

+ 2 - 2
taipy/core/_version/_cli/_version_cli.py

@@ -21,7 +21,7 @@ from ...exceptions.exceptions import VersionIsNotProductionVersion
 from ...job._job_manager_factory import _JobManagerFactory
 from ...scenario._scenario_manager_factory import _ScenarioManagerFactory
 from ...sequence._sequence_manager_factory import _SequenceManagerFactory
-from ...taipy import clean_all_entities_by_version
+from ...taipy import clean_all_entities
 from ...task._task_manager_factory import _TaskManagerFactory
 from .._version_manager_factory import _VersionManagerFactory
 from ._bcolor import _Bcolors
@@ -102,7 +102,7 @@ class _VersionCLI:
                 raise SystemExit(e) from None
 
         if args.delete:
-            if clean_all_entities_by_version(args.delete):
+            if clean_all_entities(args.delete):
                 cls.__logger.info(f"Successfully delete version {args.delete}.")
             else:
                 sys.exit(1)

+ 2 - 2
taipy/core/_version/_version_manager.py

@@ -182,12 +182,12 @@ class _VersionManager(_Manager[_Version]):
 
     @classmethod
     def _manage_version(cls):
-        from ..taipy import clean_all_entities_by_version
+        from ..taipy import clean_all_entities
 
         if Config.core.mode == "development":
             current_version_number = cls._get_development_version()
             cls.__logger.info(f"Development mode: Clean all entities of version {current_version_number}")
-            clean_all_entities_by_version(current_version_number)
+            clean_all_entities(current_version_number)
             cls._set_development_version(current_version_number)
 
         elif Config.core.mode in ["experiment", "production"]:

+ 2 - 2
taipy/core/common/_warnings.py

@@ -24,14 +24,14 @@ def _warn_deprecated(deprecated: str, suggest: Optional[str] = None, stacklevel:
     warnings.warn(message=message, category=category, stacklevel=stacklevel)
 
 
-def _warn_no_core_service(stacklevel: int = 3):
+def _warn_no_core_service(specific_message, stacklevel: int = 3):
     def inner(f):
         @functools.wraps(f)
         def _check_if_core_service_is_running(*args, **kwargs):
             from .._orchestrator._orchestrator_factory import _OrchestratorFactory
 
             if not _OrchestratorFactory._dispatcher:
-                message = "The Core service is NOT running"
+                message = f"The Core service is NOT running. {specific_message}"
                 warnings.warn(message=message, category=ResourceWarning, stacklevel=stacklevel)
 
             return f(*args, **kwargs)

+ 1 - 0
taipy/core/setup.py

@@ -78,6 +78,7 @@ setup(
     name="taipy-core",
     packages=find_namespace_packages(where=".") + find_packages(include=["taipy", "taipy.core", "taipy.core.*"]),
     include_package_data=True,
+    data_files=[('version', ['version.json'])],
     test_suite="tests",
     tests_require=test_requirements,
     url="https://github.com/avaiga/taipy-core",

+ 37 - 9
taipy/core/taipy.py

@@ -17,6 +17,7 @@ from typing import Any, Callable, Dict, List, Optional, Set, Union, overload
 from taipy.config.common.scope import Scope
 from taipy.logger._taipy_logger import _TaipyLogger
 
+from ._core import Core
 from ._entity._entity import _Entity
 from ._version._version_manager_factory import _VersionManagerFactory
 from .common._check_instance import (
@@ -28,7 +29,7 @@ from .common._check_instance import (
     _is_submission,
     _is_task,
 )
-from .common._warnings import _warn_no_core_service
+from .common._warnings import _warn_deprecated, _warn_no_core_service
 from .config.data_node_config import DataNodeConfig
 from .config.scenario_config import ScenarioConfig
 from .cycle._cycle_manager_factory import _CycleManagerFactory
@@ -219,7 +220,7 @@ def is_readable(
     return False
 
 
-@_warn_no_core_service()
+@_warn_no_core_service("The submitted entity will not be executed until the Core service is running.")
 def submit(
     entity: Union[Scenario, Sequence, Task],
     force: bool = False,
@@ -835,7 +836,10 @@ def create_scenario(
 ) -> Scenario:
     """Create and return a new scenario based on a scenario configuration.
 
-    If the scenario belongs to a cycle, a cycle (corresponding to the _creation_date_
+    This function checks and locks the configuration, manages application's version,
+    and creates a new scenario from the scenario configuration provided.
+
+    If the scenario belongs to a cycle, the cycle (corresponding to the _creation_date_
     and the configuration frequency attribute) is created if it does not exist yet.
 
     Parameters:
@@ -846,13 +850,22 @@ def create_scenario(
 
     Returns:
         The new scenario.
+
+    Raises:
+        SystemExit: If the configuration check returns some errors.
+
     """
+    Core._manage_version_and_block_config()
+
     return _ScenarioManagerFactory._build_manager()._create(config, creation_date, name)
 
 
 def create_global_data_node(config: DataNodeConfig) -> DataNode:
     """Create and return a new GLOBAL data node from a data node configuration.
 
+    This function checks and locks the configuration, manages application's version,
+    and creates the new data node from the data node configuration provided.
+
     Parameters:
         config (DataNodeConfig^): The data node configuration. It must have a `GLOBAL` scope.
 
@@ -861,32 +874,40 @@ def create_global_data_node(config: DataNodeConfig) -> DataNode:
 
     Raises:
         DataNodeConfigIsNotGlobal^: If the data node configuration does not have GLOBAL scope.
+        SystemExit: If the configuration check returns some errors.
     """
     # Check if the data node config has GLOBAL scope
     if config.scope is not Scope.GLOBAL:
         raise DataNodeConfigIsNotGlobal(config.id)
 
+    Core._manage_version_and_block_config()
+
     if dns := _DataManagerFactory._build_manager()._get_by_config_id(config.id):
         return dns[0]
     return _DataManagerFactory._build_manager()._create_and_set(config, None, None)
 
 
 def clean_all_entities_by_version(version_number=None) -> bool:
-    """Delete all entities of a specific version.
+    """Deprecated. Use `clean_all_entities` function instead."""
+    _warn_deprecated("'clean_all_entities_by_version'", suggest="the 'clean_all_entities' function")
+    return clean_all_entities(version_number)
+
 
-    This function deletes all entities associated with the specified version.
+def clean_all_entities(version_number: str) -> bool:
+    """Deletes all entities associated with the specified version.
 
     Parameters:
-        version_number (optional[str]): The version number of the entities to be deleted.
-            If None, the default behavior may apply.
+        version_number (str): The version number of the entities to be deleted.
+            The version_number should not be a production version.
 
     Returns:
         True if the operation succeeded, False otherwise.
 
     Notes:
         - If the specified version does not exist, the operation will be aborted, and False will be returned.
-        - This function cleans all entities, including jobs, scenarios, sequences, tasks, and data nodes.
-        - The production version of the specified version is also deleted if it exists.
+        - If the specified version is a production version, the operation will be aborted, and False will be returned.
+        - This function cleans all entities, including jobs, submissions, scenarios, cycles, sequences, tasks,
+            and data nodes.
     """
     version_manager = _VersionManagerFactory._build_manager()
     try:
@@ -895,6 +916,12 @@ def clean_all_entities_by_version(version_number=None) -> bool:
         __logger.warning(f"{e.message} Abort cleaning the entities of version '{version_number}'.")
         return False
 
+    if version_number in version_manager._get_production_versions():
+        __logger.warning(
+            f"Abort cleaning the entities of version '{version_number}'. A production version can not be deleted."
+        )
+        return False
+
     _JobManagerFactory._build_manager()._delete_by_version(version_number)
     _SubmissionManagerFactory._build_manager()._delete_by_version(version_number)
     _ScenarioManagerFactory._build_manager()._delete_by_version(version_number)
@@ -903,6 +930,7 @@ def clean_all_entities_by_version(version_number=None) -> bool:
     _DataManagerFactory._build_manager()._delete_by_version(version_number)
 
     version_manager._delete(version_number)
+
     try:
         version_manager._delete_production_version(version_number)
     except VersionIsNotProductionVersion:

+ 1 - 1
taipy/core/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 0, "ext": "dev0"}
+{"major": 3, "minor": 1, "patch": 0, "ext": "dev1"}

+ 5 - 1
taipy/gui/partial.py

@@ -72,5 +72,9 @@ class Partial(_Page):
         if isinstance(content, Page):
             new_partial._renderer = content
         else:
-            new_partial._renderer = type(self._renderer)(content=content) if self._renderer is not None else None
+            new_partial._renderer = (
+                type(self._renderer)(content=content, frame=self._renderer._get_frame())
+                if self._renderer is not None
+                else None
+            )
         return new_partial

+ 1 - 0
taipy/gui/setup.py

@@ -89,6 +89,7 @@ setup(
     install_requires=get_requirements(),
     license="Apache License 2.0",
     include_package_data=True,
+    data_files=[('version', ['version.json'])],
     keywords="taipy-gui",
     name="taipy-gui",
     packages=find_namespace_packages(where=".") + find_packages(include=["taipy", "taipy.gui", "taipy.gui.*"]),

+ 1 - 1
taipy/gui/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 0, "ext": "dev0"}
+{"major": 3, "minor": 1, "patch": 0, "ext": "dev1"}

+ 1 - 0
taipy/rest/setup.py

@@ -47,6 +47,7 @@ setup(
     author_email="dev@taipy.io",
     packages=find_namespace_packages(where=".") + find_packages(include=["taipy", "taipy.rest"]),
     include_package_data=True,
+    data_files=[('version', ['version.json'])],
     long_description=readme,
     long_description_content_type="text/markdown",
     description="Library to expose taipy-core REST APIs.",

+ 1 - 1
taipy/rest/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 0, "ext": "dev0"}
+{"major": 3, "minor": 1, "patch": 0, "ext": "dev1"}

+ 1 - 0
taipy/templates/setup.py

@@ -51,6 +51,7 @@ setup(
     name="taipy-templates",
     packages=find_namespace_packages(where=".") + find_packages(include=["taipy"]),
     include_package_data=True,
+    data_files=[('version', ['version.json'])],
     test_suite="tests",
     url="https://github.com/avaiga/taipy-templates",
     version=version_string,

+ 1 - 1
taipy/templates/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 0, "ext": "dev0"}
+{"major": 3, "minor": 1, "patch": 0, "ext": "dev1"}

+ 1 - 1
taipy/version.json

@@ -1 +1 @@
-{"major": 3, "minor": 1, "patch": 0, "ext": "dev0"}
+{"major": 3, "minor": 1, "patch": 0, "ext": "dev1"}

+ 2 - 4
tests/core/_backup/test_backup.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import os
-from unittest.mock import patch
 
 import pytest
 
@@ -47,9 +46,8 @@ backup_file_path = ".taipy_backups"
 
 
 def test_backup_storage_folder_when_core_run():
-    with patch("sys.argv", ["prog"]):
-        core = Core()
-        core.run()
+    core = Core()
+    core.run()
     backup_files = read_backup_file(backup_file_path)
     assert backup_files == [f"{Config.core.storage_folder}\n"]
     core.stop()

+ 1 - 0
tests/core/_orchestrator/test_orchestrator__cancel_jobs.py

@@ -8,6 +8,7 @@
 # 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.
+
 from taipy import Job, JobId, Status
 from taipy.config import Config
 from taipy.core import taipy

+ 4 - 4
tests/core/_orchestrator/test_orchestrator__is_blocked.py

@@ -35,7 +35,7 @@ def test_is_not_blocked_task_multiple_input_and_output():
     dn_0 = Config.configure_data_node("in_0", default_data="THIS")
     dn_1 = Config.configure_data_node("in_1", default_data="IS")
     dn_2 = Config.configure_data_node("in_2", default_data="DEFAULT")
-    out = Config.configure_data_node("output")
+    out = Config.configure_data_node("output_dn")
     t = Config.configure_task("the_task", nothing, [dn_0, dn_1, dn_2], [out])
     sc_conf = Config.configure_scenario("scenario", [t])
     scenario = taipy.create_scenario(sc_conf)
@@ -74,7 +74,7 @@ def test_is_blocked_task_single_input_edit_in_progress():
 def test_is_blocked_task_multiple_input_no_data():
     dn_0 = Config.configure_data_node("input_0", default_data="THIS")
     dn_1 = Config.configure_data_node("input_1")
-    out = Config.configure_data_node("output")
+    out = Config.configure_data_node("output_dn")
     t_config = Config.configure_task("the_task", nothing, [dn_0, dn_1], [out])
     sc_conf = Config.configure_scenario("scenario", [t_config])
     scenario = taipy.create_scenario(sc_conf)
@@ -101,7 +101,7 @@ def test_is_not_blocked_job_single_input():
 def test_is_not_blocked_job_multiple_input_and_output():
     in_0 = Config.configure_data_node("in_0", default_data="THIS")
     in_1 = Config.configure_data_node("in_1", default_data="IS")
-    out = Config.configure_data_node("output")
+    out = Config.configure_data_node("output_dn")
     t = Config.configure_task("the_task", nothing, [in_0, in_1], [out])
     sc_conf = Config.configure_scenario("scenario", [t])
     scenario = taipy.create_scenario(sc_conf)
@@ -144,7 +144,7 @@ def test_is_blocked_job_multiple_input_no_data():
     dn_0 = Config.configure_data_node("in_0", default_data="THIS")
     dn_1 = Config.configure_data_node("in_1", default_data="IS")
     dn_2 = Config.configure_data_node("in_2")
-    out = Config.configure_data_node("output")
+    out = Config.configure_data_node("output_dn")
     t = Config.configure_task("the_task", nothing, [dn_0, dn_1, dn_2], [out])
     sc_conf = Config.configure_scenario("scenario", [t])
     scenario = taipy.create_scenario(sc_conf)

+ 2 - 2
tests/core/_orchestrator/test_orchestrator__lock_dn_output_and_create_job.py

@@ -63,14 +63,14 @@ def test_lock_dn_and_create_job_with_callback_and_force():
 
 
 def test_lock_dn_and_create_job_one_output():
-    dn = Config.configure_data_node("output")
+    dn = Config.configure_data_node("output_dn")
     t = Config.configure_task("one_output", nothing, [], [dn])
     sc_conf = Config.configure_scenario("scenario", [t])
     scenario = taipy.create_scenario(sc_conf)
     orchestrator = _OrchestratorFactory._build_orchestrator()
     orchestrator._lock_dn_output_and_create_job(scenario.one_output, "submit_id", "scenario_id")
 
-    assert scenario.output.edit_in_progress
+    assert scenario.output_dn.edit_in_progress
 
 
 def test_lock_dn_and_create_job_multiple_outputs_one_input():

+ 3 - 2
tests/core/_orchestrator/test_orchestrator__orchestrate_job_to_run_or_block.py

@@ -8,6 +8,7 @@
 # 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.
+
 from taipy import Status
 from taipy.config import Config
 from taipy.core import taipy
@@ -50,9 +51,9 @@ def test_orchestrate_job_to_run_or_block_single_pending_job():
 
 
 def test_orchestrate_job_to_run_or_block_multiple_jobs():
-    input = Config.configure_data_node("input", default_data=1)  # Has default data
+    input = Config.configure_data_node("input_dn", default_data=1)  # Has default data
     intermediate = Config.configure_data_node("intermediate")  # Has default data
-    output = Config.configure_data_node("output")  # Has default data
+    output = Config.configure_data_node("output_dn")  # Has default data
     t1 = Config.configure_task("my_task_1", nothing, [input], [])
     t2 = Config.configure_task("my_task_2", nothing, [], [intermediate])
     t3 = Config.configure_task("my_task_3", nothing, [intermediate], [output])

+ 1 - 9
tests/core/config/checkers/test_migration_config_checker.py

@@ -24,14 +24,6 @@ def mock_func():
 
 
 def test_check_if_entity_property_key_used_is_predefined(caplog):
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        core = Core()
-        core.run()
-    assert caplog.text == ""
-    core.stop()
-
-    caplog.clear()
-
     Config.unique_sections[MigrationConfig.name]._properties["_entity_owner"] = None
     with patch("sys.argv", ["prog", "--production", "1.0"]):
         with pytest.raises(SystemExit):
@@ -72,9 +64,9 @@ def test_check_valid_version(caplog):
     Config.unblock_update()
 
     with patch("sys.argv", ["prog", "--production", "2.0"]):
+        # No SystemExit should be raised
         core = Core()
         core.run()
-    assert caplog.text == ""
     core.stop()
 
 

+ 4 - 1
tests/core/conftest.py

@@ -14,6 +14,7 @@ import pickle
 import shutil
 from datetime import datetime
 from queue import Queue
+from unittest.mock import patch
 
 import pandas as pd
 import pytest
@@ -327,7 +328,8 @@ def clean_repository(init_config, init_managers, init_orchestrator, init_notifie
     init_config()
     init_notifier()
 
-    yield
+    with patch("sys.argv", ["prog"]):
+        yield
 
 
 @pytest.fixture
@@ -346,6 +348,7 @@ def init_config(reset_configuration_singleton, inject_core_sections):
 
         Config.configure_core(read_entity_retry=0)
         Core._is_running = False
+        Core._version_is_initialized = False
 
     return _init_config
 

+ 12 - 12
tests/core/data/test_data_manager.py

@@ -549,18 +549,18 @@ class TestDataManager:
             """
             [TAIPY]
 
-            [DATA_NODE.input]
+            [DATA_NODE.input_dn]
             scope = "SCENARIO:SCOPE"
             default_data = "21:int"
 
-            [DATA_NODE.output]
+            [DATA_NODE.output_dn]
             storage_type = "in_memory"
             scope = "SCENARIO:SCOPE"
 
             [TASK.double]
-            inputs = [ "input:SECTION",]
+            inputs = [ "input_dn:SECTION",]
             function = "math.sqrt:function"
-            outputs = [ "output:SECTION",]
+            outputs = [ "output_dn:SECTION",]
             skippable = "False:bool"
 
             [SCENARIO.my_scenario]
@@ -575,26 +575,26 @@ class TestDataManager:
         Config.override(file_config.filename)
         scenario = tp.create_scenario(Config.scenarios["my_scenario"])
 
-        assert isinstance(scenario.input, PickleDataNode)
-        assert isinstance(scenario.output, InMemoryDataNode)
+        assert isinstance(scenario.input_dn, PickleDataNode)
+        assert isinstance(scenario.output_dn, InMemoryDataNode)
 
     def test_create_dn_from_loaded_config_modified_default_config(self):
         file_config = NamedTemporaryFile(
             """
             [TAIPY]
 
-            [DATA_NODE.input]
+            [DATA_NODE.input_dn]
             scope = "SCENARIO:SCOPE"
             default_path="fake/path.csv"
 
-            [DATA_NODE.output]
+            [DATA_NODE.output_dn]
             storage_type = "in_memory"
             scope = "SCENARIO:SCOPE"
 
             [TASK.double]
-            inputs = [ "input:SECTION",]
+            inputs = [ "input_dn:SECTION",]
             function = "math.sqrt:function"
-            outputs = [ "output:SECTION",]
+            outputs = [ "output_dn:SECTION",]
             skippable = "False:bool"
 
             [SCENARIO.my_scenario]
@@ -610,8 +610,8 @@ class TestDataManager:
         Config.override(file_config.filename)
         scenario = tp.create_scenario(Config.scenarios["my_scenario"])
 
-        assert isinstance(scenario.input, CSVDataNode)
-        assert isinstance(scenario.output, InMemoryDataNode)
+        assert isinstance(scenario.input_dn, CSVDataNode)
+        assert isinstance(scenario.output_dn, InMemoryDataNode)
 
     def test_get_tasks_by_config_id(self):
         dn_config_1 = Config.configure_data_node("dn_1", scope=Scope.SCENARIO)

+ 2 - 1
tests/core/notification/test_core_event_consumer.py

@@ -16,6 +16,7 @@ from taipy.core import taipy as tp
 from taipy.core.notification.core_event_consumer import CoreEventConsumerBase
 from taipy.core.notification.event import Event, EventEntityType, EventOperation
 from taipy.core.notification.notifier import Notifier
+from taipy.core.scenario._scenario_manager_factory import _ScenarioManagerFactory
 from tests.core.utils import assert_true_after_time
 
 
@@ -79,7 +80,7 @@ def test_core_event_consumer():
     )
 
     # Create a scenario trigger 5 creation events
-    scenario = tp.create_scenario(scenario_config)
+    scenario = _ScenarioManagerFactory._build_manager()._create(scenario_config)
     assert_true_after_time(lambda: all_evt_csumer_0.event_collected == 5, time=10)
     assert_true_after_time(lambda: len(all_evt_csumer_0.event_entity_type_collected) == 5, time=10)
     assert_true_after_time(lambda: all_evt_csumer_0.event_operation_collected[EventOperation.CREATION] == 5, time=10)

+ 6 - 4
tests/core/notification/test_events_published.py

@@ -17,6 +17,7 @@ from taipy.core.job.status import Status
 from taipy.core.notification.core_event_consumer import CoreEventConsumerBase
 from taipy.core.notification.event import Event, EventEntityType, EventOperation
 from taipy.core.notification.notifier import Notifier
+from taipy.core.scenario._scenario_manager_factory import _ScenarioManagerFactory
 
 
 class Snapshot:
@@ -85,8 +86,9 @@ def test_events_published_for_scenario_creation():
     register_id_0, register_queue_0 = Notifier.register()
     all_evts = RecordingConsumer(register_id_0, register_queue_0)
     all_evts.start()
-    # Create a scenario only trigger 6 creation events (for cycle, data node(x2), task, sequence and scenario)
-    tp.create_scenario(sc_config)
+    # Create a scenario via the manager
+    # should only trigger 6 creation events (for cycle, data node(x2), task, sequence and scenario)
+    _ScenarioManagerFactory._build_manager()._create(sc_config)
     snapshot = all_evts.capture()
 
     assert len(snapshot.collected_events) == 6
@@ -249,7 +251,7 @@ def test_job_events():
     consumer.start()
 
     # Create scenario
-    scenario = tp.create_scenario(sc_config)
+    scenario = _ScenarioManagerFactory._build_manager()._create(sc_config)
     snapshot = consumer.capture()
     assert len(snapshot.collected_events) == 0
 
@@ -329,7 +331,7 @@ def test_data_node_events():
     consumer = RecordingConsumer(register_id, register_queue)
     consumer.start()
 
-    scenario = tp.create_scenario(sc_config)
+    scenario = _ScenarioManagerFactory._build_manager()._create(sc_config)
 
     snapshot = consumer.capture()
     # We expect two creation events since we have two data nodes:

+ 9 - 7
tests/core/notification/test_notifier.py

@@ -13,10 +13,12 @@ from queue import SimpleQueue
 
 from taipy.config import Config, Frequency
 from taipy.core import taipy as tp
+from taipy.core._version._version_manager_factory import _VersionManagerFactory
 from taipy.core.notification import EventEntityType, EventOperation
 from taipy.core.notification._topic import _Topic
 from taipy.core.notification.event import Event
 from taipy.core.notification.notifier import Notifier
+from taipy.core.scenario._scenario_manager_factory import _ScenarioManagerFactory
 
 
 def test_register():
@@ -317,7 +319,7 @@ def test_publish_creation_event():
 
     # Test CREATION Event
 
-    scenario = tp.create_scenario(scenario_config)
+    scenario = _ScenarioManagerFactory._build_manager()._create(scenario_config)
     cycle = scenario.cycle
     task = scenario.tasks[task_config.id]
     dn = scenario.data_nodes[dn_config.id]
@@ -357,7 +359,7 @@ def test_publish_update_event():
     )
     scenario_config.add_sequences({"sequence_config": [task_config]})
 
-    scenario = tp.create_scenario(scenario_config)
+    scenario = _ScenarioManagerFactory._build_manager()._create(scenario_config)
     cycle = scenario.cycle
     task = scenario.tasks[task_config.id]
     dn = scenario.data_nodes[dn_config.id]
@@ -554,7 +556,7 @@ def test_publish_update_event_in_context_manager():
     )
     scenario_config.add_sequences({"sequence_config": [task_config]})
 
-    scenario = tp.create_scenario(scenario_config)
+    scenario = _ScenarioManagerFactory._build_manager()._create(scenario_config)
     cycle = scenario.cycle
     task = scenario.tasks[task_config.id]
     dn = scenario.data_nodes[dn_config.id]
@@ -699,7 +701,7 @@ def test_publish_submission_event():
         "scenario_config", [task_config], frequency=Frequency.DAILY, flag="test"
     )
     scenario_config.add_sequences({"sequence_config": [task_config]})
-    scenario = tp.create_scenario(scenario_config)
+    scenario = _ScenarioManagerFactory._build_manager()._create(scenario_config)
 
     assert registration_queue.qsize() == 5
     while registration_queue.qsize() > 0:
@@ -751,7 +753,7 @@ def test_publish_deletion_event():
         "scenario_config", [task_config], frequency=Frequency.DAILY, flag="test"
     )
     scenario_config.add_sequences({"sequence_config": [task_config]})
-    scenario = tp.create_scenario(scenario_config)
+    scenario = _ScenarioManagerFactory._build_manager()._create(scenario_config)
     cycle = scenario.cycle
     task = scenario.tasks[task_config.id]
     dn = scenario.data_nodes[dn_config.id]
@@ -793,7 +795,7 @@ def test_publish_deletion_event():
         for i, event in enumerate(published_events)
     )
 
-    scenario = tp.create_scenario(scenario_config)
+    scenario = _ScenarioManagerFactory._build_manager()._create(scenario_config)
     cycle = scenario.cycle
     assert registration_queue.qsize() == 5
 
@@ -801,7 +803,7 @@ def test_publish_deletion_event():
     while registration_queue.qsize() != 0:
         registration_queue.get()
 
-    tp.clean_all_entities_by_version()
+    tp.clean_all_entities(_VersionManagerFactory._build_manager()._get_latest_version())
     assert registration_queue.qsize() == 6
 
     published_events = []

+ 23 - 26
tests/core/test_complex_application.py

@@ -12,7 +12,6 @@
 import os
 import pathlib
 from time import sleep
-from unittest.mock import patch
 
 import pandas as pd
 
@@ -76,25 +75,24 @@ def test_skipped_jobs():
     task_config_2 = Config.configure_task("second", mult_by_2, intermediate_config, output_config, skippable=True)
     scenario_config = Config.configure_scenario("scenario", [task_config_1, task_config_2])
 
-    with patch("sys.argv", ["prog"]):
-        core = Core()
-        core.run()
-
-        scenario = tp.create_scenario(scenario_config)
-        scenario.input_dn.write(2)
-        scenario.submit()
-        assert len(tp.get_jobs()) == 2
-        for job in tp.get_jobs():
-            assert job.status == Status.COMPLETED
-        scenario.submit()
-        assert len(tp.get_jobs()) == 4
-        skipped = []
-        for job in tp.get_jobs():
-            if job.status != Status.COMPLETED:
-                assert job.status == Status.SKIPPED
-                skipped.append(job)
-        assert len(skipped) == 2
-        core.stop()
+    core = Core()
+    core.run()
+
+    scenario = tp.create_scenario(scenario_config)
+    scenario.input_dn.write(2)
+    scenario.submit()
+    assert len(tp.get_jobs()) == 2
+    for job in tp.get_jobs():
+        assert job.status == Status.COMPLETED
+    scenario.submit()
+    assert len(tp.get_jobs()) == 4
+    skipped = []
+    for job in tp.get_jobs():
+        if job.status != Status.COMPLETED:
+            assert job.status == Status.SKIPPED
+            skipped.append(job)
+    assert len(skipped) == 2
+    core.stop()
 
 
 def test_complex():
@@ -173,12 +171,11 @@ def test_complex():
         ],
     )
 
-    with patch("sys.argv", ["prog"]):
-        core = Core()
-        core.run()
-        scenario = tp.create_scenario(scenario_config)
-        tp.submit(scenario)
-        core.stop()
+    core = Core()
+    core.run()
+    scenario = tp.create_scenario(scenario_config)
+    tp.submit(scenario)
+    core.stop()
 
     csv_sum_res = pd.read_csv(csv_path_sum)
     excel_sum_res = pd.read_excel(excel_path_sum)

+ 59 - 66
tests/core/test_core.py

@@ -9,7 +9,6 @@
 # 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.
 
-from unittest.mock import patch
 
 import pytest
 
@@ -26,10 +25,9 @@ from taipy.core.exceptions.exceptions import CoreServiceIsAlreadyRunning
 class TestCore:
     def test_run_core_trigger_config_check(self, caplog):
         Config.configure_data_node(id="d0", storage_type="toto")
-        with patch("sys.argv", ["prog"]):
-            with pytest.raises(SystemExit):
-                core = Core()
-                core.run()
+        with pytest.raises(SystemExit):
+            core = Core()
+            core.run()
         expected_error_message = (
             "`storage_type` field of DataNodeConfig `d0` must be either csv, sql_table,"
             " sql, mongo_collection, pickle, excel, generic, json, parquet, s3_object, or in_memory."
@@ -41,83 +39,78 @@ class TestCore:
     def test_run_core_as_a_service_development_mode(self):
         _OrchestratorFactory._dispatcher = None
 
-        with patch("sys.argv", ["prog"]):
-            core = Core()
-            assert core._orchestrator is None
-            assert core._dispatcher is None
-            assert _OrchestratorFactory._dispatcher is None
-
-            core.run()
-            assert core._orchestrator is not None
-            assert core._orchestrator == _Orchestrator
-            assert _OrchestratorFactory._orchestrator is not None
-            assert _OrchestratorFactory._orchestrator == _Orchestrator
-            assert core._dispatcher is not None
-            assert isinstance(core._dispatcher, _DevelopmentJobDispatcher)
-            assert isinstance(_OrchestratorFactory._dispatcher, _DevelopmentJobDispatcher)
-            core.stop()
+        core = Core()
+        assert core._orchestrator is None
+        assert core._dispatcher is None
+        assert _OrchestratorFactory._dispatcher is None
+
+        core.run()
+        assert core._orchestrator is not None
+        assert core._orchestrator == _Orchestrator
+        assert _OrchestratorFactory._orchestrator is not None
+        assert _OrchestratorFactory._orchestrator == _Orchestrator
+        assert core._dispatcher is not None
+        assert isinstance(core._dispatcher, _DevelopmentJobDispatcher)
+        assert isinstance(_OrchestratorFactory._dispatcher, _DevelopmentJobDispatcher)
+        core.stop()
 
     def test_run_core_as_a_service_standalone_mode(self):
         _OrchestratorFactory._dispatcher = None
 
-        with patch("sys.argv", ["prog"]):
-            core = Core()
-            assert core._orchestrator is None
-
-            assert core._dispatcher is None
-            assert _OrchestratorFactory._dispatcher is None
-
-            Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)
-            core.run()
-            assert core._orchestrator is not None
-            assert core._orchestrator == _Orchestrator
-            assert _OrchestratorFactory._orchestrator is not None
-            assert _OrchestratorFactory._orchestrator == _Orchestrator
-            assert core._dispatcher is not None
-            assert isinstance(core._dispatcher, _StandaloneJobDispatcher)
-            assert isinstance(_OrchestratorFactory._dispatcher, _StandaloneJobDispatcher)
-            assert core._dispatcher.is_running()
-            assert _OrchestratorFactory._dispatcher.is_running()
-            core.stop()
+        core = Core()
+        assert core._orchestrator is None
+
+        assert core._dispatcher is None
+        assert _OrchestratorFactory._dispatcher is None
+
+        Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)
+        core.run()
+        assert core._orchestrator is not None
+        assert core._orchestrator == _Orchestrator
+        assert _OrchestratorFactory._orchestrator is not None
+        assert _OrchestratorFactory._orchestrator == _Orchestrator
+        assert core._dispatcher is not None
+        assert isinstance(core._dispatcher, _StandaloneJobDispatcher)
+        assert isinstance(_OrchestratorFactory._dispatcher, _StandaloneJobDispatcher)
+        assert core._dispatcher.is_running()
+        assert _OrchestratorFactory._dispatcher.is_running()
+        core.stop()
 
     def test_core_service_can_only_be_run_once(self):
-        with patch("sys.argv", ["prog"]):
-            core_instance_1 = Core()
-            core_instance_2 = Core()
+        core_instance_1 = Core()
+        core_instance_2 = Core()
 
-            core_instance_1.run()
-
-            with pytest.raises(CoreServiceIsAlreadyRunning):
-                core_instance_1.run()
-            with pytest.raises(CoreServiceIsAlreadyRunning):
-                core_instance_2.run()
-
-            # Stop the Core service and run it again should work
-            core_instance_1.stop()
+        core_instance_1.run()
 
+        with pytest.raises(CoreServiceIsAlreadyRunning):
             core_instance_1.run()
-            core_instance_1.stop()
+        with pytest.raises(CoreServiceIsAlreadyRunning):
             core_instance_2.run()
-            core_instance_2.stop()
+
+        # Stop the Core service and run it again should work
+        core_instance_1.stop()
+
+        core_instance_1.run()
+        core_instance_1.stop()
+        core_instance_2.run()
+        core_instance_2.stop()
 
     def test_block_config_update_when_core_service_is_running_development_mode(self):
         _OrchestratorFactory._dispatcher = None
 
-        with patch("sys.argv", ["prog"]):
-            core = Core()
-            core.run()
-            with pytest.raises(ConfigurationUpdateBlocked):
-                Config.configure_data_node(id="i1")
-            core.stop()
+        core = Core()
+        core.run()
+        with pytest.raises(ConfigurationUpdateBlocked):
+            Config.configure_data_node(id="i1")
+        core.stop()
 
     @pytest.mark.standalone
     def test_block_config_update_when_core_service_is_running_standalone_mode(self):
         _OrchestratorFactory._dispatcher = None
 
-        with patch("sys.argv", ["prog"]):
-            core = Core()
-            Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)
-            core.run()
-            with pytest.raises(ConfigurationUpdateBlocked):
-                Config.configure_data_node(id="i1")
-            core.stop()
+        core = Core()
+        Config.configure_job_executions(mode=JobConfig._STANDALONE_MODE, max_nb_of_workers=2)
+        core.run()
+        with pytest.raises(ConfigurationUpdateBlocked):
+            Config.configure_data_node(id="i1")
+        core.stop()

+ 19 - 14
tests/core/test_taipy.py

@@ -352,7 +352,7 @@ class TestTaipy:
                 tp.submit(scenario)
 
         assert len(warning) == 1
-        assert warning[0].message.args[0] == "The Core service is NOT running"
+        assert "The Core service is NOT running" in warning[0].message.args[0]
 
     def test_get_tasks(self):
         with mock.patch("taipy.core.task._task_manager._TaskManager._get_all") as mck:
@@ -636,28 +636,33 @@ class TestTaipy:
             mck.assert_called_once_with(cycle_id)
 
     def test_create_global_data_node(self):
-        dn_cfg = DataNodeConfig("id", "pickle", Scope.GLOBAL)
-        with mock.patch("taipy.core.data._data_manager._DataManager._create_and_set") as mck:
-            dn = tp.create_global_data_node(dn_cfg)
-            mck.assert_called_once_with(dn_cfg, None, None)
-
-        dn = tp.create_global_data_node(dn_cfg)
+        dn_cfg_global = DataNodeConfig("id", "pickle", Scope.GLOBAL)
+        dn_cfg_scenario = DataNodeConfig("id", "pickle", Scope.SCENARIO)
+        with mock.patch("taipy.core.data._data_manager._DataManager._create_and_set") as dn_create_mock:
+            with mock.patch("taipy.core._core.Core._manage_version_and_block_config") as mv_mock:
+                dn = tp.create_global_data_node(dn_cfg_global)
+                dn_create_mock.assert_called_once_with(dn_cfg_global, None, None)
+                mv_mock.assert_called_once()
+
+        dn = tp.create_global_data_node(dn_cfg_global)
         assert dn.scope == Scope.GLOBAL
-        assert dn.config_id == dn_cfg.id
+        assert dn.config_id == dn_cfg_global.id
+        assert _VersionManager._get(dn.version) is not None
 
         # Create a global data node from the same configuration should return the same data node
-        dn_2 = tp.create_global_data_node(dn_cfg)
+        dn_2 = tp.create_global_data_node(dn_cfg_global)
         assert dn_2.id == dn.id
 
-        dn_cfg.scope = Scope.SCENARIO
         with pytest.raises(DataNodeConfigIsNotGlobal):
-            tp.create_global_data_node(dn_cfg)
+            tp.create_global_data_node(dn_cfg_scenario)
 
-    def test_create_scenario(self, scenario):
+    def test_create_scenario(self):
         scenario_config = ScenarioConfig("scenario_config")
         with mock.patch("taipy.core.scenario._scenario_manager._ScenarioManager._create") as mck:
-            tp.create_scenario(scenario_config)
-            mck.assert_called_once_with(scenario_config, None, None)
+            with mock.patch("taipy.core._core.Core._manage_version_and_block_config") as mv_mock:
+                tp.create_scenario(scenario_config)
+                mck.assert_called_once_with(scenario_config, None, None)
+                mv_mock.assert_called_once()
         with mock.patch("taipy.core.scenario._scenario_manager._ScenarioManager._create") as mck:
             tp.create_scenario(scenario_config, datetime.datetime(2022, 2, 5))
             mck.assert_called_once_with(scenario_config, datetime.datetime(2022, 2, 5), None)

+ 1 - 3
tests/gui/actions/test_download.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from flask import g
 
@@ -28,8 +27,7 @@ def test_download(gui: Gui, helpers):
     gui._set_frame(inspect.currentframe())
 
     gui.add_page("test", Markdown("<|Hello {name}|button|id={btn_id}|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 1 - 3
tests/gui/actions/test_get_state_id.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from flask import g
 
@@ -25,8 +24,7 @@ def test_get_state_id(gui: Gui, helpers):
     gui._set_frame(inspect.currentframe())
 
     gui.add_page("test", Markdown("<|Hello {name}|button|id={btn_id}|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     cid = helpers.create_scope_and_get_sid(gui)
     # Get the jsx once so that the page will be evaluated -> variable will be registered

+ 1 - 3
tests/gui/actions/test_hold_control.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from flask import g
 
@@ -25,8 +24,7 @@ def test_hold_control(gui: Gui, helpers):
     gui._set_frame(inspect.currentframe())
 
     gui.add_page("test", Markdown("<|Hello {name}|button|id={btn_id}|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 1 - 3
tests/gui/actions/test_invoke_callback.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from flask import g
 
@@ -30,8 +29,7 @@ def test_invoke_callback(gui: Gui, helpers):
     gui._set_frame(inspect.currentframe())
 
     gui.add_page("test", Markdown("<|Hello {name}|button|id={btn_id}|>\n<|{val}|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     flask_client = gui._server.test_client()
     # client id
     cid = helpers.create_scope_and_get_sid(gui)

+ 1 - 3
tests/gui/actions/test_navigate.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from flask import g
 
@@ -25,8 +24,7 @@ def test_navigate(gui: Gui, helpers):
     gui._set_frame(inspect.currentframe())
 
     gui.add_page("test", Markdown("<|Hello {name}|button|id={btn_id}|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 1 - 3
tests/gui/actions/test_notify.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from flask import g
 
@@ -25,8 +24,7 @@ def test_notify(gui: Gui, helpers):
     gui._set_frame(inspect.currentframe())
 
     gui.add_page("test", Markdown("<|Hello {name}|button|id={btn_id}|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 1 - 3
tests/gui/actions/test_resume_control.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from flask import g
 
@@ -25,8 +24,7 @@ def test_resume_control(gui: Gui, helpers):
     gui._set_frame(inspect.currentframe())
 
     gui.add_page("test", Markdown("<|Hello {name}|button|id={btn_id}|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 7 - 0
tests/gui/conftest.py

@@ -11,6 +11,7 @@
 
 import os
 from pathlib import Path
+from unittest.mock import patch
 
 import pandas as pd  # type: ignore
 import pytest
@@ -60,3 +61,9 @@ def test_client():
         with flask_app.app_context():
             g.client_id = "test client id"
             yield testing_client  # this is where the testing happens!
+
+
+@pytest.fixture(scope="function", autouse=True)
+def patch_cli_args():
+    with patch("sys.argv", ["prog"]):
+        yield

+ 1 - 3
tests/gui/data/test_pandas_data_accessor.py

@@ -12,7 +12,6 @@
 import inspect
 from datetime import datetime
 from importlib import util
-from unittest.mock import patch
 
 import pandas  # type: ignore
 from flask import g
@@ -212,8 +211,7 @@ def test_decimator(gui: Gui, helpers, small_dataframe):
     gui._set_frame(inspect.currentframe())
 
     gui.add_page("test", "<|Hello {a_decimator}|button|id={btn_id}|>")
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
 
     cid = helpers.create_scope_and_get_sid(gui)

+ 1 - 3
tests/gui/gui_specific/test_folder_pages_binding.py

@@ -12,7 +12,6 @@
 import inspect
 import os
 from pathlib import Path
-from unittest.mock import patch
 
 from taipy.gui import Gui
 
@@ -21,7 +20,6 @@ def test_folder_pages_binding(gui: Gui):
     folder_path = f"{Path(Path(__file__).parent.resolve())}{os.path.sep}sample_assets"
     gui._set_frame(inspect.currentframe())
     gui.add_pages(folder_path)
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     assert len(gui._config.routes) == 3  # 2 files -> 2 routes + 1 default route
     assert len(gui._config.pages) == 3  # 2 files -> 2 pages + 1 default page

+ 7 - 15
tests/gui/gui_specific/test_gui.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import json
-from unittest.mock import patch
 
 import pandas as pd
 import pytest
@@ -25,24 +24,21 @@ def test__get_real_var_name(gui: Gui):
     assert res[0] == ""
     assert res[1] == ""
 
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     with gui.get_flask_app().app_context():
         with pytest.raises(NameError):
             res = gui._get_real_var_name(f"{_TaipyContent.get_hash()}_var")
 
 
 def test__get_user_instance(gui: Gui):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     with gui.get_flask_app().app_context():
         with pytest.warns(UserWarning):
             gui._get_user_instance("", type(None))
 
 
 def test__call_broadcast_callback(gui: Gui):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     with gui.get_flask_app().app_context():
         res = gui._call_broadcast_callback(lambda s, t: t, ["Hello World"], "mine")
         assert res == "Hello World"
@@ -54,8 +50,7 @@ def test__call_broadcast_callback(gui: Gui):
 
 
 def test__refresh_expr(gui: Gui):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     with gui.get_flask_app().app_context():
         res = gui._refresh_expr("var", None)
         assert res is None
@@ -63,8 +58,7 @@ def test__refresh_expr(gui: Gui):
 
 def test__tbl_cols(gui: Gui):
     data = pd.DataFrame({"col1": [0, 1, 2], "col2": [True, True, False]})
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     with gui.get_flask_app().app_context():
         res = gui._tbl_cols(True, None, json.dumps({}), json.dumps({"data": "data"}), data=data)
         assert isinstance(res, str)
@@ -79,8 +73,7 @@ def test__tbl_cols(gui: Gui):
 
 def test__chart_conf(gui: Gui):
     data = pd.DataFrame({"col1": [0, 1, 2], "col2": [True, True, False]})
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     with gui.get_flask_app().app_context():
         res = gui._chart_conf(True, None, json.dumps({}), json.dumps({"data": "data"}), data=data)
         assert isinstance(res, str)
@@ -98,8 +91,7 @@ def test__chart_conf(gui: Gui):
 
 
 def test__get_valid_adapter_result(gui: Gui):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     with gui.get_flask_app().app_context():
         res = gui._get_valid_adapter_result(("id", "label"))
         assert isinstance(res, tuple)

+ 1 - 3
tests/gui/gui_specific/test_locals_context.py

@@ -9,7 +9,6 @@
 # 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.
 
-from unittest.mock import patch
 
 import pytest
 
@@ -19,8 +18,7 @@ from taipy.gui.utils._locals_context import _LocalsContext
 
 def test_locals_context(gui: Gui):
     lc = _LocalsContext()
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     with gui.get_flask_app().app_context():
         with pytest.raises(KeyError):
             lc.get_default()

+ 2 - 4
tests/gui/gui_specific/test_multiple_instances.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import json
-from unittest.mock import patch
 
 from taipy.gui.gui import Gui
 
@@ -18,9 +17,8 @@ from taipy.gui.gui import Gui
 def test_multiple_instance():
     gui1 = Gui("<|gui1|>")
     gui2 = Gui("<|gui2|>")
-    with patch("sys.argv", ["prog"]):
-        gui1.run(run_server=False)
-        gui2.run(run_server=False)
+    gui1.run(run_server=False)
+    gui2.run(run_server=False)
     client1 = gui1._server.test_client()
     client2 = gui2._server.test_client()
     assert_multiple_instance(client1, 'value="gui1"')

+ 4 - 9
tests/gui/gui_specific/test_navigate.py

@@ -11,7 +11,6 @@
 
 import inspect
 import warnings
-from unittest.mock import patch
 
 from taipy.gui import Gui, Markdown, State, navigate
 
@@ -23,8 +22,7 @@ def test_navigate(gui: Gui, helpers):
     with warnings.catch_warnings(record=True):
         gui._set_frame(inspect.currentframe())
         gui.add_page("test", Markdown("#This is a page"))
-        with patch("sys.argv", ["prog"]):
-            gui.run(run_server=False)
+        gui.run(run_server=False)
         client = gui._server.test_client()
         # WS client and emit
         ws_client = gui._server._ws.test_client(gui._server.get_flask())
@@ -43,8 +41,7 @@ def test_navigate_to_no_route(gui: Gui, helpers):
     with warnings.catch_warnings(record=True):
         gui._set_frame(inspect.currentframe())
         gui.add_page("test", Markdown("#This is a page"))
-        with patch("sys.argv", ["prog"]):
-            gui.run(run_server=False)
+        gui.run(run_server=False)
         client = gui._server.test_client()
         # WS client and emit
         ws_client = gui._server._ws.test_client(gui._server.get_flask())
@@ -63,8 +60,7 @@ def test_on_navigate_to_inexistant(gui: Gui, helpers):
     with warnings.catch_warnings(record=True) as records:
         gui._set_frame(inspect.currentframe())
         gui.add_page("test", Markdown("#This is a page"))
-        with patch("sys.argv", ["prog"]):
-            gui.run(run_server=False)
+        gui.run(run_server=False)
         client = gui._server.test_client()
         # Get the jsx once so that the page will be evaluated -> variable will be registered
         sid = helpers.create_scope_and_get_sid(gui)
@@ -83,8 +79,7 @@ def test_on_navigate_to_existant(gui: Gui, helpers):
         gui._set_frame(inspect.currentframe())
         gui.add_page("test1", Markdown("#This is a page test1"))
         gui.add_page("test2", Markdown("#This is a page test2"))
-        with patch("sys.argv", ["prog"]):
-            gui.run(run_server=False)
+        gui.run(run_server=False)
         client = gui._server.test_client()
         # Get the jsx once so that the page will be evaluated -> variable will be registered
         sid = helpers.create_scope_and_get_sid(gui)

+ 2 - 5
tests/gui/gui_specific/test_partial.py

@@ -12,7 +12,6 @@
 import json
 import warnings
 from types import SimpleNamespace
-from unittest.mock import patch
 
 from taipy.gui import Gui, Markdown
 
@@ -20,8 +19,7 @@ from taipy.gui import Gui, Markdown
 def test_partial(gui: Gui):
     with warnings.catch_warnings(record=True):
         gui.add_partial(Markdown("#This is a partial"))
-        with patch("sys.argv", ["prog"]):
-            gui.run(run_server=False)
+        gui.run(run_server=False)
         client = gui._server.test_client()
         response = client.get(f"/taipy-jsx/{gui._config.partial_routes[0]}")
         response_data = json.loads(response.get_data().decode("utf-8", "ignore"))
@@ -32,8 +30,7 @@ def test_partial(gui: Gui):
 def test_partial_update(gui: Gui):
     with warnings.catch_warnings(record=True):
         partial = gui.add_partial(Markdown("#This is a partial"))
-        with patch("sys.argv", ["prog"]):
-            gui.run(run_server=False, single_client=True)
+        gui.run(run_server=False, single_client=True)
         client = gui._server.test_client()
         response = client.get(f"/taipy-jsx/{gui._config.partial_routes[0]}")
         response_data = json.loads(response.get_data().decode("utf-8", "ignore"))

+ 1 - 3
tests/gui/gui_specific/test_render_route.py

@@ -12,7 +12,6 @@
 import inspect
 import json
 import warnings
-from unittest.mock import patch
 
 from taipy.gui import Gui
 
@@ -21,8 +20,7 @@ def test_render_route(gui: Gui):
     gui._set_frame(inspect.currentframe())
     gui.add_page("page1", "# first page")
     gui.add_page("page2", "# second page")
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     with warnings.catch_warnings(record=True):
         client = gui._server.test_client()
         response = client.get("/taipy-init")

+ 2 - 5
tests/gui/gui_specific/test_run_thread.py

@@ -11,7 +11,6 @@
 
 import inspect
 import time
-from unittest.mock import patch
 from urllib.request import urlopen
 
 from taipy.gui import Gui
@@ -21,16 +20,14 @@ from taipy.gui import Gui
 def test_run_thread(gui: Gui, helpers):
     gui._set_frame(inspect.currentframe())
     gui.add_page("page1", "# first page")
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_in_thread=True, run_browser=False)
+    gui.run(run_in_thread=True, run_browser=False)
     while not helpers.port_check():
         time.sleep(0.1)
     assert ">first page</h1>" in urlopen("http://127.0.0.1:5000/taipy-jsx/page1").read().decode("utf-8")
     gui.stop()
     while helpers.port_check():
         time.sleep(0.1)
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_in_thread=True, run_browser=False)
+    gui.run(run_in_thread=True, run_browser=False)
     while not helpers.port_check():
         time.sleep(0.1)
     assert ">first page</h1>" in urlopen("http://127.0.0.1:5000/taipy-jsx/page1").read().decode("utf-8")

+ 1 - 3
tests/gui/gui_specific/test_state.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 import pytest
 
@@ -23,8 +22,7 @@ def test_state(gui: Gui):
     a = 10  # noqa: F841
     gui._set_frame(inspect.currentframe())
     gui.add_page("page1", md_page1)
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     state = gui._Gui__state  # type: ignore[attr-defined]
     with gui.get_flask_app().app_context():
         assert state.a == 10

+ 3 - 7
tests/gui/gui_specific/test_variable_binding.py

@@ -9,7 +9,6 @@
 # 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.
 
-from unittest.mock import patch
 
 from taipy.gui import Gui, Markdown
 
@@ -27,8 +26,7 @@ def test_variable_binding(helpers):
     z = "button label"
     gui = Gui()
     gui.add_page("test", Markdown("<|{x}|> | <|{y}|> | <|{z}|button|on_action=another_function|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     client = gui._server.test_client()
     jsx = client.get("/taipy-jsx/test").json["jsx"]
     for expected in ["<Button", 'defaultLabel="button label"', "label={tpec_TpExPr_z_TPMDL_0}"]:
@@ -46,8 +44,7 @@ def test_properties_binding(helpers):
     modifier = "nice "  # noqa: F841
     button_properties = {"label": "A {modifier}button"}  # noqa: F841
     gui.add_page("test", Markdown("<|button|properties=button_properties|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     client = gui._server.test_client()
     jsx = client.get("/taipy-jsx/test").json["jsx"]
     for expected in ["<Button", 'defaultLabel="A nice button"']:
@@ -61,8 +58,7 @@ def test_dict_binding(helpers):
     """
     d = {"k": "test"}  # noqa: F841
     gui = Gui("<|{d.k}|>")
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     client = gui._server.test_client()
     jsx = client.get("/taipy-jsx/TaiPy_root_page").json["jsx"]
     for expected in ["<Field", 'defaultValue="test"']:

+ 3 - 7
tests/gui/helpers.py

@@ -15,7 +15,6 @@ import socket
 import time
 import typing as t
 import warnings
-from unittest.mock import patch
 
 from taipy.gui import Gui, Html, Markdown
 from taipy.gui._renderers.builder import _Builder
@@ -48,8 +47,7 @@ class Helpers:
 
     @staticmethod
     def _test_control(gui: Gui, expected_values: t.Union[str, t.List]):
-        with patch("sys.argv", ["prog"]):
-            gui.run(run_server=False, single_client=True, stylekit=False)
+        gui.run(run_server=False, single_client=True, stylekit=False)
         client = gui._server.test_client()
         response = client.get("/taipy-jsx/test")
         assert response.status_code == 200, f"response.status_code {response.status_code} != 200"
@@ -138,16 +136,14 @@ class Helpers:
         kwargs["run_browser"] = False
         kwargs["stylekit"] = kwargs.get("stylekit", False)
         with warnings.catch_warnings(record=True):
-            with patch("sys.argv", ["prog"]):
-                gui.run(**kwargs)
+            gui.run(**kwargs)
         while not Helpers.port_check():
             time.sleep(0.1)
 
     @staticmethod
     def run_e2e_multi_client(gui: Gui):
         with warnings.catch_warnings(record=True):
-            with patch("sys.argv", ["prog"]):
-                gui.run(run_server=False, run_browser=False, single_client=False, stylekit=False)
+            gui.run(run_server=False, run_browser=False, single_client=False, stylekit=False)
             gui._server.run(
                 host=gui._get_config("host", "127.0.0.1"),
                 port=gui._get_config("port", 5000),

+ 1 - 3
tests/gui/ignore/no_file/test_ignore.py

@@ -11,7 +11,6 @@
 
 import inspect
 import warnings
-from unittest.mock import patch
 
 from taipy.gui import Gui
 
@@ -19,8 +18,7 @@ from taipy.gui import Gui
 def test_no_ignore_file(gui: Gui):
     with warnings.catch_warnings(record=True):
         gui._set_frame(inspect.currentframe())
-        with patch("sys.argv", ["prog"]):
-            gui.run(run_server=False)
+        gui.run(run_server=False)
         client = gui._server.test_client()
         response = client.get("/resource.txt")
         assert (

+ 2 - 5
tests/gui/ignore/with_file/test_with_ignore.py

@@ -11,7 +11,6 @@
 
 import inspect
 import warnings
-from unittest.mock import patch
 
 from taipy.gui import Gui
 
@@ -19,8 +18,7 @@ from taipy.gui import Gui
 def test_ignore_file_found(gui: Gui):
     with warnings.catch_warnings(record=True):
         gui._set_frame(inspect.currentframe())
-        with patch("sys.argv", ["prog"]):
-            gui.run(run_server=False)
+        gui.run(run_server=False)
         client = gui._server.test_client()
         response = client.get("/resource.txt")
         assert (
@@ -31,8 +29,7 @@ def test_ignore_file_found(gui: Gui):
 def test_ignore_file_not_found(gui: Gui):
     with warnings.catch_warnings(record=True):
         gui._set_frame(inspect.currentframe())
-        with patch("sys.argv", ["prog"]):
-            gui.run(run_server=False)
+        gui.run(run_server=False)
         client = gui._server.test_client()
         response = client.get("/resource2.txt")
         assert (

+ 1 - 3
tests/gui/long_runnig/test_long_running.py

@@ -11,7 +11,6 @@
 
 import inspect
 from time import sleep
-from unittest.mock import patch
 
 from taipy.gui import Gui, State, invoke_long_callback
 
@@ -33,8 +32,7 @@ def test_long_callback(gui: Gui):
         state.status = -1
 
     gui._set_frame(inspect.currentframe())
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     state = gui._Gui__state  # type: ignore[attr-defined]
 
     with gui.get_flask_app().app_context():

+ 1 - 3
tests/gui/renderers/test_html_parsing.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from taipy.gui import Gui, Html
 
@@ -20,8 +19,7 @@ def test_simple_html(gui: Gui, helpers):
     html_string = "<html><head></head><body><h1>test</h1></body></html>"
     gui._set_frame(inspect.currentframe())
     gui.add_page("test", Html(html_string))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     client = gui._server.test_client()
     jsx = client.get("/taipy-jsx/test").json["jsx"]
     assert jsx == "<h1>test</h1>"

+ 2 - 5
tests/gui/server/http/test_extension.py

@@ -9,7 +9,6 @@
 # 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.
 
-from unittest.mock import patch
 
 import pytest
 
@@ -26,8 +25,7 @@ class MyLibrary(ElementLibrary):
 
 
 def test_extension_no_config(gui: Gui, helpers):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     flask_client = gui._server.test_client()
     with pytest.warns(UserWarning):
         ret = flask_client.get("/taipy-extension/toto/titi")
@@ -36,8 +34,7 @@ def test_extension_no_config(gui: Gui, helpers):
 
 def test_extension_config_wrong_path(gui: Gui, helpers):
     Gui.add_library(MyLibrary())
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     flask_client = gui._server.test_client()
     with pytest.warns(UserWarning):
         ret = flask_client.get("/taipy-extension/taipy_extension_example/titi")

+ 6 - 13
tests/gui/server/http/test_file_upload.py

@@ -13,7 +13,6 @@ import inspect
 import io
 import pathlib
 import tempfile
-from unittest.mock import patch
 
 import pytest
 
@@ -23,8 +22,7 @@ from taipy.gui.utils import _get_non_existent_file_path
 
 
 def test_file_upload_no_varname(gui: Gui, helpers):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # Get the jsx once so that the page will be evaluated -> variable will be registered
     sid = helpers.create_scope_and_get_sid(gui)
@@ -34,8 +32,7 @@ def test_file_upload_no_varname(gui: Gui, helpers):
 
 
 def test_file_upload_no_blob(gui: Gui, helpers):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # Get the jsx once so that the page will be evaluated -> variable will be registered
     sid = helpers.create_scope_and_get_sid(gui)
@@ -45,8 +42,7 @@ def test_file_upload_no_blob(gui: Gui, helpers):
 
 
 def test_file_upload_no_filename(gui: Gui, helpers):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     file = (io.BytesIO(b"abcdef"), "")
     # Get the jsx once so that the page will be evaluated -> variable will be registered
@@ -57,8 +53,7 @@ def test_file_upload_no_filename(gui: Gui, helpers):
 
 
 def test_file_upload_simple(gui: Gui, helpers):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # Get the jsx once so that the page will be evaluated -> variable will be registered
     sid = helpers.create_scope_and_get_sid(gui)
@@ -77,8 +72,7 @@ def test_file_upload_simple(gui: Gui, helpers):
 
 
 def test_file_upload_multi_part(gui: Gui, helpers):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # Get the jsx once so that the page will be evaluated -> variable will be registered
     sid = helpers.create_scope_and_get_sid(gui)
@@ -110,8 +104,7 @@ def test_file_upload_multi_part(gui: Gui, helpers):
 def test_file_upload_multiple(gui: Gui, helpers):
     var_name = "varname"
     gui._set_frame(inspect.currentframe())
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     flask_client = gui._server.test_client()
     with gui.get_flask_app().app_context():
         gui._bind_var_val(var_name, None)

+ 2 - 5
tests/gui/server/http/test_image_path.py

@@ -10,14 +10,12 @@
 # specific language governing permissions and limitations under the License.
 
 import pathlib
-from unittest.mock import patch
 
 from taipy.gui import Gui
 
 
 def test_image_path_not_found(gui: Gui, helpers):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # Get the jsx once so that the page will be evaluated -> variable will be registered
     sid = helpers.create_scope_and_get_sid(gui)
@@ -29,8 +27,7 @@ def test_image_path_found(gui: Gui, helpers):
     url = gui._get_content(
         "img", str((pathlib.Path(__file__).parent.parent.parent / "resources" / "fred.png").resolve()), True
     )
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # Get the jsx once so that the page will be evaluated -> variable will be registered
     sid = helpers.create_scope_and_get_sid(gui)

+ 3 - 7
tests/gui/server/http/test_status.py

@@ -11,14 +11,12 @@
 
 import inspect
 from os import path
-from unittest.mock import patch
 
 from taipy.gui import Gui
 
 
 def test_get_status(gui: Gui):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     ret = flask_client.get("/taipy.status.json")
     assert ret.status_code == 200, f"status_code => {ret.status_code} != 200"
@@ -32,8 +30,7 @@ def test_get_status(gui: Gui):
 
 
 def test_get_extended_status(gui: Gui):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, extended_status=True)
+    gui.run(run_server=False, extended_status=True)
     flask_client = gui._server.test_client()
     ret = flask_client.get("/taipy.status.json")
     assert ret.status_code == 200, f"status_code => {ret.status_code} != 200"
@@ -58,8 +55,7 @@ def test_get_status_with_user_status(gui: Gui):
 
     gui._set_frame(inspect.currentframe())
 
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     ret = flask_client.get("/taipy.status.json")
     assert ret.status_code == 200, f"status_code => {ret.status_code} != 200"

+ 3 - 7
tests/gui/server/http/test_user_content.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 import pytest
 
@@ -18,8 +17,7 @@ from taipy.gui import Gui
 
 
 def test_user_content_without_callback(gui: Gui, helpers):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     flask_client = gui._server.test_client()
     with pytest.warns(UserWarning):
         ret = flask_client.get(gui._get_user_content_url("path"))
@@ -32,8 +30,7 @@ def test_user_content_with_wrong_callback(gui: Gui, helpers):
 
     on_user_content = on_user_content_cb  # noqa: F841
     gui._set_frame(inspect.currentframe())
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     flask_client = gui._server.test_client()
     with pytest.warns(UserWarning):
         ret = flask_client.get(gui._get_user_content_url("path", {"a": "b"}))
@@ -46,8 +43,7 @@ def test_user_content_with_callback(gui: Gui, helpers):
 
     on_user_content = on_user_content_cb  # noqa: F841
     gui._set_frame(inspect.currentframe())
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     flask_client = gui._server.test_client()
     ret = flask_client.get(gui._get_user_content_url("path"))
     assert ret.status_code == 200

+ 1 - 3
tests/gui/server/ws/test_a.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from taipy.gui import Gui, Markdown
 
@@ -28,8 +27,7 @@ def test_a_button_pressed(gui: Gui, helpers):
     gui.add_page(
         "test", Markdown("<|Do something!|button|on_action=do_something|id=my_button|> | <|{x}|> | <|{text}|>")
     )
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 1 - 3
tests/gui/server/ws/test_broadcast.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from taipy.gui import Gui, Markdown
 
@@ -27,8 +26,7 @@ def test_broadcast(gui: Gui, helpers):
         "test",
         Markdown("<|{selected_val}|selector|multiple|>"),
     )
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 1 - 3
tests/gui/server/ws/test_df.py

@@ -12,7 +12,6 @@
 import inspect
 import logging
 import pathlib
-from unittest.mock import patch
 
 from taipy.gui import Gui, download
 
@@ -28,8 +27,7 @@ def test_download_file(gui: Gui, helpers):
     # set gui frame
     gui._set_frame(inspect.currentframe())
 
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())
     # Get the jsx once so that the page will be evaluated -> variable will be registered

+ 1 - 3
tests/gui/server/ws/test_du.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from taipy.gui import Gui, Markdown
 
@@ -30,8 +29,7 @@ def test_du_table_data_fetched(gui: Gui, helpers, csvdata):
             "<|{csvdata}|table|page_size=10|page_size_options=10;30;100|columns=Day;Entity;Code;Daily hospital occupancy|date_format=eee dd MMM yyyy|>"  # noqa: E501
         ),
     )
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 2 - 5
tests/gui/server/ws/test_on_change.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from taipy.gui import Gui, Markdown
 
@@ -27,8 +26,7 @@ def test_default_on_change(gui: Gui, helpers):
     gui._set_frame(inspect.currentframe())
 
     gui.add_page("test", Markdown("<|{x}|input|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())
@@ -56,8 +54,7 @@ def test_specific_on_change(gui: Gui, helpers):
     gui._set_frame(inspect.currentframe())
 
     gui.add_page("test", Markdown("<|{x}|input|on_change=on_input_change|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 1 - 3
tests/gui/server/ws/test_ru.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from taipy.gui import Gui, Markdown
 
@@ -27,8 +26,7 @@ def test_ru_selector(gui: Gui, helpers, csvdata):
         "test",
         Markdown("<|{selected_val}|selector|multiple|>"),
     )
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 1 - 3
tests/gui/server/ws/test_u.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from taipy.gui import Gui, Markdown
 
@@ -24,8 +23,7 @@ def ws_u_assert_template(gui: Gui, helpers, value_before_update, value_after_upd
 
     # Bind a page so that the variable will be evaluated as expression
     gui.add_page("test", Markdown("<|{var}|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 1 - 3
tests/gui/server/ws/test_with.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 from taipy.gui import Gui, Markdown
 from taipy.gui.data.data_scope import _DataScopes
@@ -24,8 +23,7 @@ def test_sending_messages_in_group(gui: Gui, helpers):
     gui._set_frame(inspect.currentframe())
 
     gui.add_page("test", Markdown("<|Hello {name}|button|id={btn_id}|>"))
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     flask_client = gui._server.test_client()
     # WS client and emit
     ws_client = gui._server._ws.test_client(gui._server.get_flask())

+ 6 - 13
tests/gui/utils/test_evaluator.py

@@ -11,7 +11,6 @@
 
 import inspect
 import warnings
-from unittest.mock import patch
 
 from flask import g
 
@@ -20,8 +19,7 @@ from taipy.gui.utils.types import _TaipyNumber
 
 
 def test_unbind_variable_in_expression(gui: Gui, helpers):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     with warnings.catch_warnings(record=True) as records:
         with gui.get_flask_app().app_context():
             gui._evaluate_expr("{x}")
@@ -36,8 +34,7 @@ def test_unbind_variable_in_expression(gui: Gui, helpers):
 def test_evaluate_same_expression_multiple_times(gui: Gui):
     x = 10  # noqa: F841
     gui._set_frame(inspect.currentframe())
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     with gui.get_flask_app().app_context():
         s1 = gui._evaluate_expr("x + 10 = {x + 10}")
         s2 = gui._evaluate_expr("x + 10 = {x + 10}")
@@ -47,8 +44,7 @@ def test_evaluate_same_expression_multiple_times(gui: Gui):
 def test_evaluate_expressions_same_variable(gui: Gui):
     x = 10  # noqa: F841
     gui._set_frame(inspect.currentframe())
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     with gui.get_flask_app().app_context():
         s1 = gui._evaluate_expr("x + 10 = {x + 10}")
         s2 = gui._evaluate_expr("x = {x}")
@@ -58,8 +54,7 @@ def test_evaluate_expressions_same_variable(gui: Gui):
 def test_evaluate_holder(gui: Gui):
     x = 10  # noqa: F841
     gui._set_frame(inspect.currentframe())
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     with warnings.catch_warnings(record=True):
         with gui.get_flask_app().app_context():
             gui._evaluate_expr("{x + 10}")
@@ -74,8 +69,7 @@ def test_evaluate_holder(gui: Gui):
 
 
 def test_evaluate_not_expression_type(gui: Gui):
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     with gui.get_flask_app().app_context():
         assert "x + 10" == gui._evaluate_expr("x + 10")
 
@@ -84,8 +78,7 @@ def test_evaluate_expression_2_clients(gui: Gui):
     x = 10  # noqa: F841
     y = 20  # noqa: F841
     gui._set_frame(inspect.currentframe())
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False)
+    gui.run(run_server=False)
     with gui.get_flask_app().app_context():
         gui._bindings()._get_or_create_scope("A")
         gui._bindings()._get_or_create_scope("B")

+ 1 - 3
tests/gui/utils/test_map_dict.py

@@ -10,7 +10,6 @@
 # specific language governing permissions and limitations under the License.
 
 import inspect
-from unittest.mock import patch
 
 import pytest
 
@@ -112,8 +111,7 @@ def test_map_dict_set(gui: Gui, test_client):
     # set gui frame
     gui._set_frame(inspect.currentframe())
 
-    with patch("sys.argv", ["prog"]):
-        gui.run(run_server=False, single_client=True)
+    gui.run(run_server=False, single_client=True)
     with gui.get_flask_app().app_context():
         assert isinstance(gui._Gui__state.d, _MapDict)  # type: ignore[attr-defined]
         gui._Gui__state.d = {"b": 2}  # type: ignore[attr-defined]