Forráskód Böngészése

Merge pull request #1633 from Avaiga/feature/enterprise#431-remove-production-version

Feature/enterprise#431 - Remove production version
Đỗ Trường Giang 9 hónapja
szülő
commit
421f854374
47 módosított fájl, 218 hozzáadás és 1345 törlés
  1. 0 1
      .gitignore
  2. 7 5
      taipy/_entrypoint.py
  3. 2 2
      taipy/_run.py
  4. 4 25
      taipy/config/config.pyi
  5. 2 3
      taipy/config/stubs/generate_pyi.py
  6. 1 1
      taipy/config/stubs/pyi_header.py
  7. 0 0
      taipy/core/_cli/__init__.py
  8. 6 20
      taipy/core/_cli/_core_cli.py
  9. 33 0
      taipy/core/_cli/_core_cli_factory.py
  10. 4 3
      taipy/core/_core.py
  11. 8 38
      taipy/core/_version/_cli/_version_cli.py
  12. 33 0
      taipy/core/_version/_cli/_version_cli_factory.py
  13. 0 49
      taipy/core/_version/_utils.py
  14. 4 54
      taipy/core/_version/_version_fs_repository.py
  15. 50 90
      taipy/core/_version/_version_manager.py
  16. 0 46
      taipy/core/_version/_version_repository_interface.py
  17. 0 9
      taipy/core/config/__init__.py
  18. 0 66
      taipy/core/config/checkers/_migration_config_checker.py
  19. 6 7
      taipy/core/config/core_section.py
  20. 0 113
      taipy/core/config/migration_config.py
  21. 1 3
      taipy/core/data/_data_converter.py
  22. 6 2
      taipy/core/exceptions/exceptions.py
  23. 1 3
      taipy/core/scenario/_scenario_converter.py
  24. 7 24
      taipy/core/taipy.py
  25. 1 4
      taipy/core/task/_task_converter.py
  26. 1 8
      tests/conftest.py
  27. 10 0
      tests/core/_version/__init__.py
  28. 0 0
      tests/core/_version/dataset_2.0/cycles/CYCLE_Frequency.DAILY_2023-01-18T172525.892619_8956558e-d108-4ac4-8684-60f3e5ef9e8f.json
  29. 0 0
      tests/core/_version/dataset_2.0/data_nodes/DATANODE_d1_3d65c33b-b188-4402-8d2c-3b26d98b9a9e.json
  30. 0 0
      tests/core/_version/dataset_2.0/data_nodes/DATANODE_d2_bd8ee43e-6fa9-4832-b2e7-c0c9516b1e1c.json
  31. 0 0
      tests/core/_version/dataset_2.0/scenarios/SCENARIO_my_scenario_c4307ae8-d2ce-4802-8b16-8307baa7cff1.json
  32. 0 0
      tests/core/_version/dataset_2.0/sequences/SEQUENCE_my_sequence_1b97a539-ca51-4eb8-aa64-c232269618c6.json
  33. 0 0
      tests/core/_version/dataset_2.0/tasks/TASK_my_task_53cf9993-047f-4220-9c03-e28fa250f6b3.json
  34. 0 0
      tests/core/_version/test_version.py
  35. 23 99
      tests/core/_version/test_version_cli.py
  36. 0 0
      tests/core/_version/test_version_manager.py
  37. 0 0
      tests/core/_version/test_version_repositories.py
  38. 0 132
      tests/core/config/checkers/test_migration_config_checker.py
  39. 5 35
      tests/core/config/test_config_serialization.py
  40. 2 2
      tests/core/config/test_core_section.py
  41. 0 5
      tests/core/config/test_core_version.py
  42. 1 12
      tests/core/config/test_default_config.py
  43. 0 2
      tests/core/config/test_file_config.py
  44. 0 65
      tests/core/config/test_migration_config.py
  45. 0 1
      tests/core/conftest.py
  46. 0 136
      tests/core/test_core_cli.py
  47. 0 280
      tests/core/version/test_production_version_migration.py

+ 0 - 1
.gitignore

@@ -95,5 +95,4 @@ demo_*/
 *.dags
 *.dags
 data_sources
 data_sources
 pipelines
 pipelines
-tasks
 pickles
 pickles

+ 7 - 5
taipy/_entrypoint.py

@@ -14,9 +14,9 @@ import sys
 from importlib.util import find_spec
 from importlib.util import find_spec
 
 
 from taipy._cli._base_cli._taipy_parser import _TaipyParser
 from taipy._cli._base_cli._taipy_parser import _TaipyParser
-from taipy.core._core_cli import _CoreCLI
+from taipy.core._cli._core_cli_factory import _CoreCLIFactory
 from taipy.core._entity._migrate_cli import _MigrateCLI
 from taipy.core._entity._migrate_cli import _MigrateCLI
-from taipy.core._version._cli._version_cli import _VersionCLI
+from taipy.core._version._cli._version_cli_factory import _VersionCLIFactory
 from taipy.gui._gui_cli import _GuiCLI
 from taipy.gui._gui_cli import _GuiCLI
 
 
 from ._cli._create_cli import _CreateCLI
 from ._cli._create_cli import _CreateCLI
@@ -41,11 +41,13 @@ def _entrypoint():
 
 
         _enterprise_entrypoint_initialize()
         _enterprise_entrypoint_initialize()
 
 
+    _core_cli = _CoreCLIFactory._build_cli()
+
     _RunCLI.create_parser()
     _RunCLI.create_parser()
     _GuiCLI.create_run_parser()
     _GuiCLI.create_run_parser()
-    _CoreCLI.create_run_parser()
+    _core_cli.create_run_parser()
 
 
-    _VersionCLI.create_parser()
+    _VersionCLIFactory._build_cli().create_parser()
     _CreateCLI.generate_template_map()
     _CreateCLI.generate_template_map()
     _CreateCLI.create_parser()
     _CreateCLI.create_parser()
     _MigrateCLI.create_parser()
     _MigrateCLI.create_parser()
@@ -63,7 +65,7 @@ def _entrypoint():
 
 
     _RunCLI.handle_command()
     _RunCLI.handle_command()
     _HelpCLI.handle_command()
     _HelpCLI.handle_command()
-    _VersionCLI.handle_command()
+    _VersionCLIFactory._build_cli().handle_command()
     _MigrateCLI.handle_command()
     _MigrateCLI.handle_command()
     _CreateCLI.handle_command()
     _CreateCLI.handle_command()
 
 

+ 2 - 2
taipy/_run.py

@@ -42,10 +42,10 @@ def _run(*services: _AppType, **kwargs) -> t.Optional[Flask]:
     core = __get_app(services, Core)
     core = __get_app(services, Core)
 
 
     if gui and core:
     if gui and core:
-        from taipy.core._core_cli import _CoreCLI
+        from taipy.core._cli._core_cli_factory import _CoreCLIFactory
         from taipy.gui._gui_cli import _GuiCLI
         from taipy.gui._gui_cli import _GuiCLI
 
 
-        _CoreCLI.create_parser()
+        _CoreCLIFactory._build_cli().create_parser()
         _GuiCLI.create_parser()
         _GuiCLI.create_parser()
 
 
     if rest or core:
     if rest or core:

+ 4 - 25
taipy/config/config.pyi

@@ -14,7 +14,7 @@ from datetime import timedelta
 from typing import Any, Callable, Dict, List, Optional, Union
 from typing import Any, Callable, Dict, List, Optional, Union
 
 
 from taipy.config._config import _Config
 from taipy.config._config import _Config
-from taipy.core.config import CoreSection, DataNodeConfig, JobConfig, MigrationConfig, ScenarioConfig, TaskConfig
+from taipy.core.config import CoreSection, DataNodeConfig, JobConfig, ScenarioConfig, TaskConfig
 
 
 from .checker.issue_collector import IssueCollector
 from .checker.issue_collector import IssueCollector
 from .common._classproperty import _Classproperty
 from .common._classproperty import _Classproperty
@@ -169,10 +169,6 @@ class Config:
     def scenarios(cls) -> Dict[str, ScenarioConfig]:
     def scenarios(cls) -> Dict[str, ScenarioConfig]:
         """"""
         """"""
 
 
-    @_Classproperty
-    def migration_functions(cls) -> Dict[str, MigrationConfig]:
-        """"""
-
     @_Classproperty
     @_Classproperty
     def core(cls) -> Dict[str, CoreSection]:
     def core(cls) -> Dict[str, CoreSection]:
         """"""
         """"""
@@ -852,25 +848,6 @@ class Config:
             The new job execution configuration.
             The new job execution configuration.
         """
         """
 
 
-    @staticmethod
-    def add_migration_function(
-        target_version: str,
-        config: Union[Section, str],
-        migration_fct: Callable,
-        **properties,
-    ):
-        """Add a migration function for a Configuration to migrate entities to the target version.
-
-        Parameters:
-            target_version (str): The production version that entities are migrated to.
-            config (Union[Section, str]): The configuration or the `id` of the config that needs to migrate.
-            migration_fct (Callable): Migration function that takes an entity as input and returns a new entity
-                that is compatible with the target production version.
-            **properties (Dict[str, Any]): A keyworded variable length list of additional arguments.
-        Returns:
-            `MigrationConfig^`: The Migration configuration.
-        """
-
     @staticmethod
     @staticmethod
     def configure_core(
     def configure_core(
         root_folder: Optional[str] = None,
         root_folder: Optional[str] = None,
@@ -902,7 +879,9 @@ class Config:
             read_entity_retry (Optional[int]): Number of retries to read an entity from the repository
             read_entity_retry (Optional[int]): Number of retries to read an entity from the repository
                 before return failure. The default value is 3.
                 before return failure. The default value is 3.
             mode (Optional[str]): Indicates the mode of the version management system.
             mode (Optional[str]): Indicates the mode of the version management system.
-                Possible values are *"development"*, *"experiment"*, or *"production"*.
+                Possible values are *"development"* or *"experiment"*. On Enterprise edition of Taipy,
+                *production* mode is also available. Please refer to the
+                [Versioning management](../../userman/versioning/index.md) documentation page for more details.
             version_number (Optional[str]): The string identifier of the version.
             version_number (Optional[str]): The string identifier of the version.
                  In development mode, the version number is ignored.
                  In development mode, the version number is ignored.
             force (Optional[bool]): If True, Taipy will override a version even if the configuration
             force (Optional[bool]): If True, Taipy will override a version even if the configuration

+ 2 - 3
taipy/config/stubs/generate_pyi.py

@@ -14,7 +14,8 @@ import re
 from pathlib import Path
 from pathlib import Path
 from typing import List
 from typing import List
 
 
-_end_doc = re.compile(r'\"\"\"\s*(#\s*noqa\s*:\s*E501)?\s*\n')
+_end_doc = re.compile(r"\"\"\"\s*(#\s*noqa\s*:\s*E501)?\s*\n")
+
 
 
 def _get_function_delimiters(initial_line, lines):
 def _get_function_delimiters(initial_line, lines):
     begin = end = initial_line
     begin = end = initial_line
@@ -148,7 +149,6 @@ if __name__ == "__main__":
     job_filename = "taipy/core/config/job_config.py"
     job_filename = "taipy/core/config/job_config.py"
     scenario_filename = "taipy/core/config/scenario_config.py"
     scenario_filename = "taipy/core/config/scenario_config.py"
     task_filename = "taipy/core/config/task_config.py"
     task_filename = "taipy/core/config/task_config.py"
-    migration_filename = "taipy/core/config/migration_config.py"
     core_filename = "taipy/core/config/core_section.py"
     core_filename = "taipy/core/config/core_section.py"
 
 
     entities_map, property_map = _generate_entity_and_property_maps(config_init)
     entities_map, property_map = _generate_entity_and_property_maps(config_init)
@@ -159,7 +159,6 @@ if __name__ == "__main__":
     pyi = _build_entity_config_pyi(pyi, dn_filename, entities_map["DataNodeConfig"])
     pyi = _build_entity_config_pyi(pyi, dn_filename, entities_map["DataNodeConfig"])
     pyi = _build_entity_config_pyi(pyi, task_filename, entities_map["TaskConfig"])
     pyi = _build_entity_config_pyi(pyi, task_filename, entities_map["TaskConfig"])
     pyi = _build_entity_config_pyi(pyi, job_filename, entities_map["JobConfig"])
     pyi = _build_entity_config_pyi(pyi, job_filename, entities_map["JobConfig"])
-    pyi = _build_entity_config_pyi(pyi, migration_filename, entities_map["MigrationConfig"])
     pyi = _build_entity_config_pyi(pyi, core_filename, entities_map["CoreSection"])
     pyi = _build_entity_config_pyi(pyi, core_filename, entities_map["CoreSection"])
 
 
     # Remove the final redundant \n
     # Remove the final redundant \n

+ 1 - 1
taipy/config/stubs/pyi_header.py

@@ -14,7 +14,7 @@ from datetime import timedelta
 from typing import Any, Callable, Dict, List, Optional, Union
 from typing import Any, Callable, Dict, List, Optional, Union
 
 
 from taipy.config._config import _Config
 from taipy.config._config import _Config
-from taipy.core.config import CoreSection, DataNodeConfig, JobConfig, MigrationConfig, ScenarioConfig, TaskConfig
+from taipy.core.config import CoreSection, DataNodeConfig, JobConfig, ScenarioConfig, TaskConfig
 
 
 from .checker.issue_collector import IssueCollector
 from .checker.issue_collector import IssueCollector
 from .common._classproperty import _Classproperty
 from .common._classproperty import _Classproperty

+ 0 - 0
tests/core/version/__init__.py → taipy/core/_cli/__init__.py


+ 6 - 20
taipy/core/_core_cli.py → taipy/core/_cli/_core_cli.py

@@ -14,13 +14,13 @@ from typing import Dict
 from taipy._cli._base_cli._abstract_cli import _AbstractCLI
 from taipy._cli._base_cli._abstract_cli import _AbstractCLI
 from taipy._cli._base_cli._taipy_parser import _TaipyParser
 from taipy._cli._base_cli._taipy_parser import _TaipyParser
 
 
-from .config import CoreSection
+from ..config import CoreSection
 
 
 
 
 class _CoreCLI(_AbstractCLI):
 class _CoreCLI(_AbstractCLI):
     """Command-line interface for Taipy Core application."""
     """Command-line interface for Taipy Core application."""
 
 
-    __MODE_ARGS: Dict[str, Dict] = {
+    _mode_args: Dict[str, Dict] = {
         "--development": {
         "--development": {
             "action": "store_true",
             "action": "store_true",
             "dest": "taipy_development",
             "dest": "taipy_development",
@@ -40,17 +40,6 @@ class _CoreCLI(_AbstractCLI):
                 application. Without being specified, the version number will be a random string.
                 application. Without being specified, the version number will be a random string.
             """,
             """,
         },
         },
-        "--production": {
-            "dest": "taipy_production",
-            "nargs": "?",
-            "const": "",
-            "metavar": "VERSION",
-            "help": """
-                When execute in `production` mode, the current version is used in production. All production versions
-                should have the same configuration and share all entities. Without being specified, the latest version
-                is used.
-            """,
-        },
     }
     }
 
 
     __FORCE_ARGS: Dict[str, Dict] = {
     __FORCE_ARGS: Dict[str, Dict] = {
@@ -73,7 +62,7 @@ class _CoreCLI(_AbstractCLI):
         core_parser = _TaipyParser._add_groupparser("Taipy Core", "Optional arguments for Taipy Core service")
         core_parser = _TaipyParser._add_groupparser("Taipy Core", "Optional arguments for Taipy Core service")
 
 
         mode_group = core_parser.add_mutually_exclusive_group()
         mode_group = core_parser.add_mutually_exclusive_group()
-        for mode_arg, mode_arg_dict in cls.__MODE_ARGS.items():
+        for mode_arg, mode_arg_dict in cls._mode_args.items():
             mode_group.add_argument(mode_arg, cls.__add_taipy_prefix(mode_arg), **mode_arg_dict)
             mode_group.add_argument(mode_arg, cls.__add_taipy_prefix(mode_arg), **mode_arg_dict)
 
 
         force_group = core_parser.add_mutually_exclusive_group()
         force_group = core_parser.add_mutually_exclusive_group()
@@ -84,7 +73,7 @@ class _CoreCLI(_AbstractCLI):
     def create_run_parser(cls):
     def create_run_parser(cls):
         run_parser = _TaipyParser._add_subparser("run", help="Run a Taipy application.")
         run_parser = _TaipyParser._add_subparser("run", help="Run a Taipy application.")
         mode_group = run_parser.add_mutually_exclusive_group()
         mode_group = run_parser.add_mutually_exclusive_group()
-        for mode_arg, mode_arg_dict in cls.__MODE_ARGS.items():
+        for mode_arg, mode_arg_dict in cls._mode_args.items():
             mode_group.add_argument(mode_arg, **mode_arg_dict)
             mode_group.add_argument(mode_arg, **mode_arg_dict)
 
 
         force_group = run_parser.add_mutually_exclusive_group()
         force_group = run_parser.add_mutually_exclusive_group()
@@ -97,13 +86,10 @@ class _CoreCLI(_AbstractCLI):
 
 
         as_dict = {}
         as_dict = {}
         if args.taipy_development:
         if args.taipy_development:
-            as_dict[CoreSection._MODE_KEY] = CoreSection._DEVELOPMENT_MODE
+            as_dict[CoreSection._MODE_KEY] = "development"
         elif args.taipy_experiment is not None:
         elif args.taipy_experiment is not None:
-            as_dict[CoreSection._MODE_KEY] = CoreSection._EXPERIMENT_MODE
+            as_dict[CoreSection._MODE_KEY] = "experiment"
             as_dict[CoreSection._VERSION_NUMBER_KEY] = args.taipy_experiment
             as_dict[CoreSection._VERSION_NUMBER_KEY] = args.taipy_experiment
-        elif args.taipy_production is not None:
-            as_dict[CoreSection._MODE_KEY] = CoreSection._PRODUCTION_MODE
-            as_dict[CoreSection._VERSION_NUMBER_KEY] = args.taipy_production
 
 
         if args.taipy_force:
         if args.taipy_force:
             as_dict[CoreSection._FORCE_KEY] = True
             as_dict[CoreSection._FORCE_KEY] = True

+ 33 - 0
taipy/core/_cli/_core_cli_factory.py

@@ -0,0 +1,33 @@
+# Copyright 2021-2024 Avaiga Private Limited
+#
+# 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.
+
+from importlib import import_module, util
+from operator import attrgetter
+from typing import Type
+
+from taipy._cli._base_cli._abstract_cli import _AbstractCLI
+
+from ._core_cli import _CoreCLI
+
+
+class _CoreCLIFactory:
+    _TAIPY_ENTERPRISE_MODULE = "taipy.enterprise"
+    _TAIPY_ENTERPRISE_CORE_MODULE = _TAIPY_ENTERPRISE_MODULE + ".core"
+
+    @classmethod
+    def _build_cli(cls) -> Type[_AbstractCLI]:
+        if util.find_spec(cls._TAIPY_ENTERPRISE_MODULE) is not None:
+            module = import_module(cls._TAIPY_ENTERPRISE_CORE_MODULE + "._cli._core_cli")
+            core_cli = attrgetter("_CoreCLI")(module)
+        else:
+            core_cli = _CoreCLI
+
+        return core_cli

+ 4 - 3
taipy/core/_core.py

@@ -15,7 +15,7 @@ from typing import Optional
 from taipy.config import Config
 from taipy.config import Config
 from taipy.logger._taipy_logger import _TaipyLogger
 from taipy.logger._taipy_logger import _TaipyLogger
 
 
-from ._core_cli import _CoreCLI
+from ._cli._core_cli_factory import _CoreCLIFactory
 from ._orchestrator._dispatcher._job_dispatcher import _JobDispatcher
 from ._orchestrator._dispatcher._job_dispatcher import _JobDispatcher
 from ._orchestrator._orchestrator import _Orchestrator
 from ._orchestrator._orchestrator import _Orchestrator
 from ._orchestrator._orchestrator_factory import _OrchestratorFactory
 from ._orchestrator._orchestrator_factory import _OrchestratorFactory
@@ -102,8 +102,9 @@ class Core:
     @classmethod
     @classmethod
     def __update_core_section(cls):
     def __update_core_section(cls):
         cls.__logger.info("Updating configuration with command-line arguments...")
         cls.__logger.info("Updating configuration with command-line arguments...")
-        _CoreCLI.create_parser()
-        Config._applied_config._unique_sections[CoreSection.name]._update(_CoreCLI.handle_command())
+        _core_cli = _CoreCLIFactory._build_cli()
+        _core_cli.create_parser()
+        Config._applied_config._unique_sections[CoreSection.name]._update(_core_cli.handle_command())
 
 
     @classmethod
     @classmethod
     def __manage_version(cls):
     def __manage_version(cls):

+ 8 - 38
taipy/core/_version/_cli/_version_cli.py

@@ -10,6 +10,7 @@
 # specific language governing permissions and limitations under the License.
 # specific language governing permissions and limitations under the License.
 
 
 import sys
 import sys
+from importlib.util import find_spec
 
 
 from taipy._cli._base_cli._abstract_cli import _AbstractCLI
 from taipy._cli._base_cli._abstract_cli import _AbstractCLI
 from taipy._cli._base_cli._taipy_parser import _TaipyParser
 from taipy._cli._base_cli._taipy_parser import _TaipyParser
@@ -17,7 +18,6 @@ from taipy.config import Config
 from taipy.config.exceptions.exceptions import InconsistentEnvVariableError
 from taipy.config.exceptions.exceptions import InconsistentEnvVariableError
 
 
 from ...data._data_manager_factory import _DataManagerFactory
 from ...data._data_manager_factory import _DataManagerFactory
-from ...exceptions.exceptions import VersionIsNotProductionVersion
 from ...job._job_manager_factory import _JobManagerFactory
 from ...job._job_manager_factory import _JobManagerFactory
 from ...scenario._scenario_manager_factory import _ScenarioManagerFactory
 from ...scenario._scenario_manager_factory import _ScenarioManagerFactory
 from ...sequence._sequence_manager_factory import _SequenceManagerFactory
 from ...sequence._sequence_manager_factory import _SequenceManagerFactory
@@ -31,7 +31,7 @@ class _VersionCLI(_AbstractCLI):
     """Command-line interface of the versioning system."""
     """Command-line interface of the versioning system."""
 
 
     _COMMAND_NAME = "manage-versions"
     _COMMAND_NAME = "manage-versions"
-    _ARGUMENTS = ["-l", "--list", "--rename", "--compare-config", "-d", "--delete", "-dp", "--delete-production"]
+    _ARGUMENTS = ["-l", "--list", "--rename", "--compare-config", "-d", "--delete"]
 
 
     @classmethod
     @classmethod
     def create_parser(cls):
     def create_parser(cls):
@@ -56,14 +56,6 @@ class _VersionCLI(_AbstractCLI):
             "-d", "--delete", metavar="VERSION", help="Delete a Taipy version by version number."
             "-d", "--delete", metavar="VERSION", help="Delete a Taipy version by version number."
         )
         )
 
 
-        version_parser.add_argument(
-            "-dp",
-            "--delete-production",
-            metavar="VERSION",
-            help="Delete a Taipy version from production by version number. The version is still kept as an experiment "
-            "version.",
-        )
-
     @classmethod
     @classmethod
     def handle_command(cls):
     def handle_command(cls):
         args = cls._parse_arguments()
         args = cls._parse_arguments()
@@ -91,16 +83,6 @@ class _VersionCLI(_AbstractCLI):
             cls.__compare_version_config(args.compare_config[0], args.compare_config[1])
             cls.__compare_version_config(args.compare_config[0], args.compare_config[1])
             sys.exit(0)
             sys.exit(0)
 
 
-        if args.delete_production:
-            try:
-                _VersionManagerFactory._build_manager()._delete_production_version(args.delete_production)
-                cls._logger.info(
-                    f"Successfully delete version {args.delete_production} from the production version list."
-                )
-                sys.exit(0)
-            except VersionIsNotProductionVersion as e:
-                raise SystemExit(e) from None
-
         if args.delete:
         if args.delete:
             if clean_all_entities(args.delete):
             if clean_all_entities(args.delete):
                 cls._logger.info(f"Successfully delete version {args.delete}.")
                 cls._logger.info(f"Successfully delete version {args.delete}.")
@@ -115,7 +97,10 @@ class _VersionCLI(_AbstractCLI):
 
 
         latest_version_number = _VersionManagerFactory._build_manager()._get_latest_version()
         latest_version_number = _VersionManagerFactory._build_manager()._get_latest_version()
         development_version_number = _VersionManagerFactory._build_manager()._get_development_version()
         development_version_number = _VersionManagerFactory._build_manager()._get_development_version()
-        production_version_numbers = _VersionManagerFactory._build_manager()._get_production_versions()
+        if find_spec("taipy.enterprise"):
+            production_version_numbers = _VersionManagerFactory._build_manager()._get_production_versions()
+        else:
+            production_version_numbers = []
 
 
         versions = _VersionManagerFactory._build_manager()._get_all()
         versions = _VersionManagerFactory._build_manager()._get_all()
         versions.sort(key=lambda x: x.creation_date, reverse=True)
         versions.sort(key=lambda x: x.creation_date, reverse=True)
@@ -186,23 +171,8 @@ class _VersionCLI(_AbstractCLI):
             datanode._version = new_version
             datanode._version = new_version
             _DataManagerFactory._build_manager()._set(datanode)
             _DataManagerFactory._build_manager()._set(datanode)
 
 
-        # Update the version entity
-        if old_version in _version_manager._get_production_versions():
-            _version_manager._set_production_version(new_version)
-        if old_version == _version_manager._get_latest_version():
-            _version_manager._set_experiment_version(new_version)
-        if old_version == _version_manager._get_development_version():
-            _version_manager._set_development_version(new_version)
-        _version_manager._delete(old_version)
-
-        try:
-            _version_manager._delete_production_version(old_version)
-        except VersionIsNotProductionVersion:
-            pass
-
-        if not _version_manager._get(new_version):
-            version_entity.id = new_version
-            _version_manager._set(version_entity)
+        # Rename the _Version entity
+        _version_manager._rename_version(old_version, new_version)
 
 
     @classmethod
     @classmethod
     def __compare_version_config(cls, version_1: str, version_2: str):
     def __compare_version_config(cls, version_1: str, version_2: str):

+ 33 - 0
taipy/core/_version/_cli/_version_cli_factory.py

@@ -0,0 +1,33 @@
+# Copyright 2021-2024 Avaiga Private Limited
+#
+# 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.
+
+from importlib import import_module, util
+from operator import attrgetter
+from typing import Type
+
+from taipy._cli._base_cli._abstract_cli import _AbstractCLI
+
+from ._version_cli import _VersionCLI
+
+
+class _VersionCLIFactory:
+    _TAIPY_ENTERPRISE_MODULE = "taipy.enterprise"
+    _TAIPY_ENTERPRISE_CORE_MODULE = _TAIPY_ENTERPRISE_MODULE + ".core"
+
+    @classmethod
+    def _build_cli(cls) -> Type[_AbstractCLI]:
+        if util.find_spec(cls._TAIPY_ENTERPRISE_MODULE) is not None:
+            module = import_module(cls._TAIPY_ENTERPRISE_CORE_MODULE + "._version._cli._version_cli")
+            core_cli = attrgetter("_VersionCLI")(module)
+        else:
+            core_cli = _VersionCLI
+
+        return core_cli

+ 0 - 49
taipy/core/_version/_utils.py

@@ -1,49 +0,0 @@
-# Copyright 2021-2024 Avaiga Private Limited
-#
-# 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.
-
-from typing import Callable, List
-
-from taipy.config.config import Config
-
-from .._entity._reload import _Reloader
-from ..config import MigrationConfig
-from ._version_manager_factory import _VersionManagerFactory
-
-
-def _migrate_entity(entity):
-    if (
-        latest_version := _VersionManagerFactory._build_manager()._get_latest_version()
-    ) in _VersionManagerFactory._build_manager()._get_production_versions():
-        if migration_fcts := __get_migration_fcts_to_latest(entity._version, entity.config_id):
-            with _Reloader():
-                for fct in migration_fcts:
-                    entity = fct(entity)
-                entity._version = latest_version
-
-    return entity
-
-
-def __get_migration_fcts_to_latest(source_version: str, config_id: str) -> List[Callable]:
-    migration_fcts_to_latest: List[Callable] = []
-
-    production_versions = _VersionManagerFactory._build_manager()._get_production_versions()
-    try:
-        start_index = production_versions.index(source_version) + 1
-    except ValueError:
-        return migration_fcts_to_latest
-
-    versions_to_migrate = production_versions[start_index:]
-
-    for version in versions_to_migrate:
-        if migration_fct := Config.unique_sections[MigrationConfig.name].migration_fcts.get(version, {}).get(config_id):
-            migration_fcts_to_latest.append(migration_fct)
-
-    return migration_fcts_to_latest

+ 4 - 54
taipy/core/_version/_version_fs_repository.py

@@ -10,18 +10,16 @@
 # specific language governing permissions and limitations under the License.
 # specific language governing permissions and limitations under the License.
 
 
 import json
 import json
-from typing import List
-
-from taipy.logger._taipy_logger import _TaipyLogger
 
 
 from .._repository._filesystem_repository import _FileSystemRepository
 from .._repository._filesystem_repository import _FileSystemRepository
-from ..exceptions.exceptions import VersionIsNotProductionVersion
 from ._version_converter import _VersionConverter
 from ._version_converter import _VersionConverter
 from ._version_model import _VersionModel
 from ._version_model import _VersionModel
-from ._version_repository_interface import _VersionRepositoryInterface
 
 
 
 
-class _VersionFSRepository(_FileSystemRepository, _VersionRepositoryInterface):
+class _VersionFSRepository(_FileSystemRepository):
+    _LATEST_VERSION_KEY = "latest_version"
+    _DEVELOPMENT_VERSION_KEY = "development_version"
+
     def __init__(self) -> None:
     def __init__(self) -> None:
         super().__init__(model_type=_VersionModel, converter=_VersionConverter, dir_name="version")
         super().__init__(model_type=_VersionModel, converter=_VersionConverter, dir_name="version")
 
 
@@ -45,7 +43,6 @@ class _VersionFSRepository(_FileSystemRepository, _VersionRepositoryInterface):
             file_content = {
             file_content = {
                 self._LATEST_VERSION_KEY: version_number,
                 self._LATEST_VERSION_KEY: version_number,
                 self._DEVELOPMENT_VERSION_KEY: "",
                 self._DEVELOPMENT_VERSION_KEY: "",
-                self._PRODUCTION_VERSION_KEY: [],
             }
             }
         self._version_file_path.write_text(
         self._version_file_path.write_text(
             json.dumps(
             json.dumps(
@@ -72,7 +69,6 @@ class _VersionFSRepository(_FileSystemRepository, _VersionRepositoryInterface):
             file_content = {
             file_content = {
                 self._LATEST_VERSION_KEY: version_number,
                 self._LATEST_VERSION_KEY: version_number,
                 self._DEVELOPMENT_VERSION_KEY: version_number,
                 self._DEVELOPMENT_VERSION_KEY: version_number,
-                self._PRODUCTION_VERSION_KEY: [],
             }
             }
         self._version_file_path.write_text(
         self._version_file_path.write_text(
             json.dumps(
             json.dumps(
@@ -86,49 +82,3 @@ class _VersionFSRepository(_FileSystemRepository, _VersionRepositoryInterface):
         with open(self._version_file_path, "r") as f:
         with open(self._version_file_path, "r") as f:
             file_content = json.load(f)
             file_content = json.load(f)
         return file_content[self._DEVELOPMENT_VERSION_KEY]
         return file_content[self._DEVELOPMENT_VERSION_KEY]
-
-    def _set_production_version(self, version_number):
-        if self._version_file_path.exists():
-            with open(self._version_file_path, "r") as f:
-                file_content = json.load(f)
-            file_content[self._LATEST_VERSION_KEY] = version_number
-            if version_number not in file_content[self._PRODUCTION_VERSION_KEY]:
-                file_content[self._PRODUCTION_VERSION_KEY].append(version_number)
-            else:
-                _TaipyLogger._get_logger().info(f"Version {version_number} is already a production version.")
-        else:
-            self.dir_path.mkdir(parents=True, exist_ok=True)
-            file_content = {
-                self._LATEST_VERSION_KEY: version_number,
-                self._DEVELOPMENT_VERSION_KEY: "",
-                self._PRODUCTION_VERSION_KEY: [version_number],
-            }
-        self._version_file_path.write_text(
-            json.dumps(
-                file_content,
-                ensure_ascii=False,
-                indent=0,
-            )
-        )
-
-    def _get_production_versions(self) -> List[str]:
-        with open(self._version_file_path, "r") as f:
-            file_content = json.load(f)
-        return file_content[self._PRODUCTION_VERSION_KEY]
-
-    def _delete_production_version(self, version_number):
-        try:
-            with open(self._version_file_path, "r") as f:
-                file_content = json.load(f)
-            if version_number not in file_content[self._PRODUCTION_VERSION_KEY]:
-                raise VersionIsNotProductionVersion(f"Version '{version_number}' is not a production version.")
-            file_content[self._PRODUCTION_VERSION_KEY].remove(version_number)
-            self._version_file_path.write_text(
-                json.dumps(
-                    file_content,
-                    ensure_ascii=False,
-                    indent=0,
-                )
-            )
-        except FileNotFoundError:
-            raise VersionIsNotProductionVersion(f"Version '{version_number}' is not a production version.") from None

+ 50 - 90
taipy/core/_version/_version_manager.py

@@ -14,13 +14,18 @@ from typing import List, Optional, Union
 
 
 from taipy.config import Config
 from taipy.config import Config
 from taipy.config._config_comparator._comparator_result import _ComparatorResult
 from taipy.config._config_comparator._comparator_result import _ComparatorResult
-from taipy.config.checker.issue_collector import IssueCollector
 from taipy.config.exceptions.exceptions import InconsistentEnvVariableError
 from taipy.config.exceptions.exceptions import InconsistentEnvVariableError
-from taipy.core.exceptions.exceptions import ConfigCoreVersionMismatched
 from taipy.logger._taipy_logger import _TaipyLogger
 from taipy.logger._taipy_logger import _TaipyLogger
 
 
 from .._manager._manager import _Manager
 from .._manager._manager import _Manager
-from ..exceptions.exceptions import ConflictedConfigurationError, ModelNotFound, NonExistingVersion
+from ..exceptions.exceptions import (
+    ConfigCoreVersionMismatched,
+    ConflictedConfigurationError,
+    ModelNotFound,
+    NonExistingVersion,
+    VersionAlreadyExistsAsDevelopment,
+)
+from ..reason import ReasonCollection
 from ._version import _Version
 from ._version import _Version
 from ._version_fs_repository import _VersionFSRepository
 from ._version_fs_repository import _VersionFSRepository
 
 
@@ -28,14 +33,13 @@ from ._version_fs_repository import _VersionFSRepository
 class _VersionManager(_Manager[_Version]):
 class _VersionManager(_Manager[_Version]):
     _ENTITY_NAME = _Version.__name__
     _ENTITY_NAME = _Version.__name__
 
 
-    __logger = _TaipyLogger._get_logger()
+    _logger = _TaipyLogger._get_logger()
 
 
-    __DEVELOPMENT_VERSION = ["development", "dev"]
-    __LATEST_VERSION = "latest"
-    __PRODUCTION_VERSION = "production"
-    __ALL_VERSION = ["all", ""]
+    _DEVELOPMENT_VERSION = ["development", "dev"]
+    _LATEST_VERSION = "latest"
+    _ALL_VERSION = ["all", ""]
 
 
-    _DEFAULT_VERSION = __LATEST_VERSION
+    _DEFAULT_VERSION = _LATEST_VERSION
 
 
     _repository: _VersionFSRepository
     _repository: _VersionFSRepository
 
 
@@ -58,7 +62,7 @@ class _VersionManager(_Manager[_Version]):
                 if not force:
                 if not force:
                     raise ConflictedConfigurationError()
                     raise ConflictedConfigurationError()
 
 
-                cls.__logger.warning(f"Option --force is detected, overriding the configuration of version {id} ...")
+                cls._logger.warning(f"Option --force is detected, overriding the configuration of version {id} ...")
                 version.config = Config._applied_config  # type: ignore[attr-defined]
                 version.config = Config._applied_config  # type: ignore[attr-defined]
 
 
         else:
         else:
@@ -78,6 +82,10 @@ class _VersionManager(_Manager[_Version]):
         filters = [{"version": version} for version in version_number]
         filters = [{"version": version} for version in version_number]
         return cls._repository._load_all(filters)
         return cls._repository._load_all(filters)
 
 
+    @classmethod
+    def _is_deletable(cls, version_number: Optional[str]) -> ReasonCollection:
+        return ReasonCollection()
+
     @classmethod
     @classmethod
     def _set_development_version(cls, version_number: str) -> str:
     def _set_development_version(cls, version_number: str) -> str:
         cls._get_or_create(version_number, force=True)
         cls._get_or_create(version_number, force=True)
@@ -94,16 +102,7 @@ class _VersionManager(_Manager[_Version]):
     @classmethod
     @classmethod
     def _set_experiment_version(cls, version_number: str, force: bool = False) -> str:
     def _set_experiment_version(cls, version_number: str, force: bool = False) -> str:
         if version_number == cls._get_development_version():
         if version_number == cls._get_development_version():
-            raise SystemExit(
-                f"Version number {version_number} is the development version. Please choose a different name"
-                f" for this experiment."
-            )
-
-        if version_number in cls._get_production_versions():
-            raise SystemExit(
-                f"Version number {version_number} is already a production version. Please choose a different name"
-                f" for this experiment."
-            )
+            raise VersionAlreadyExistsAsDevelopment(version_number)
 
 
         try:
         try:
             cls._get_or_create(version_number, force)
             cls._get_or_create(version_number, force)
@@ -124,51 +123,16 @@ class _VersionManager(_Manager[_Version]):
             # This set the default versioning behavior on Jupyter notebook to Development mode
             # This set the default versioning behavior on Jupyter notebook to Development mode
             return cls._set_development_version(str(uuid.uuid4()))
             return cls._set_development_version(str(uuid.uuid4()))
 
 
-    @classmethod
-    def _set_production_version(cls, version_number: str, force: bool = False) -> str:
-        if version_number == cls._get_development_version():
-            cls._set_development_version(str(uuid.uuid4()))
-
-        try:
-            cls._get_or_create(version_number, force)
-        except ConflictedConfigurationError:
-            raise SystemExit(
-                f"Please add a new production version with migration functions.\n"
-                f"If old entities remain compatible with the new configuration, you can also run your application with"
-                f" --force option to override the production configuration of version {version_number}."
-            ) from None
-        cls._repository._set_production_version(version_number)
-        return version_number
-
-    @classmethod
-    def _get_production_versions(cls) -> List[str]:
-        try:
-            return cls._repository._get_production_versions()
-        except (FileNotFoundError, ModelNotFound):
-            return []
-
-    @classmethod
-    def _delete_production_version(cls, version_number) -> str:
-        return cls._repository._delete_production_version(version_number)
-
     @classmethod
     @classmethod
     def _replace_version_number(cls, version_number: Optional[str] = None):
     def _replace_version_number(cls, version_number: Optional[str] = None):
         if version_number is None:
         if version_number is None:
-            version_number = cls._replace_version_number(cls._DEFAULT_VERSION)
+            return cls._replace_version_number(cls._DEFAULT_VERSION)
 
 
-            production_versions = cls._get_production_versions()
-            if version_number in production_versions:
-                return production_versions
-
-            return version_number
-
-        if version_number == cls.__LATEST_VERSION:
+        if version_number == cls._LATEST_VERSION:
             return cls._get_latest_version()
             return cls._get_latest_version()
-        if version_number in cls.__DEVELOPMENT_VERSION:
+        if version_number in cls._DEVELOPMENT_VERSION:
             return cls._get_development_version()
             return cls._get_development_version()
-        if version_number == cls.__PRODUCTION_VERSION:
-            return cls._get_production_versions()
-        if version_number in cls.__ALL_VERSION:
+        if version_number in cls._ALL_VERSION:
             return ""
             return ""
 
 
         try:
         try:
@@ -183,50 +147,46 @@ class _VersionManager(_Manager[_Version]):
         raise NonExistingVersion(version_number)
         raise NonExistingVersion(version_number)
 
 
     @classmethod
     @classmethod
-    def _manage_version(cls):
-        from ..taipy import clean_all_entities
+    def _rename_version(cls, old_version: str, new_version: str) -> None:
+        version_entity = cls._get(old_version)
+
+        if old_version == cls._get_latest_version():
+            try:
+                cls._set_experiment_version(new_version)
+            except VersionAlreadyExistsAsDevelopment as err:
+                raise SystemExit(err.message) from None
+        if old_version == cls._get_development_version():
+            cls._set_development_version(new_version)
+        cls._delete(old_version)
+
+        if not cls._get(new_version):
+            version_entity.id = new_version
+            cls._set(version_entity)
 
 
+    @classmethod
+    def _manage_version(cls) -> None:
         if Config.core.mode == "development":
         if Config.core.mode == "development":
+            from ..taipy import clean_all_entities
+
             current_version_number = cls._get_development_version()
             current_version_number = cls._get_development_version()
-            cls.__logger.info(f"Development mode: Clean all entities of version {current_version_number}")
+            cls._logger.info(f"Development mode: Clean all entities of version {current_version_number}")
             clean_all_entities(current_version_number)
             clean_all_entities(current_version_number)
             cls._set_development_version(current_version_number)
             cls._set_development_version(current_version_number)
 
 
-        elif Config.core.mode in ["experiment", "production"]:
-            default_version_number = {
-                "experiment": str(uuid.uuid4()),
-                "production": cls._get_latest_version(),
-            }
-            version_setter = {
-                "experiment": cls._set_experiment_version,
-                "production": cls._set_production_version,
-            }
-
+        elif Config.core.mode == "experiment":
             if Config.core.version_number:
             if Config.core.version_number:
                 current_version_number = Config.core.version_number
                 current_version_number = Config.core.version_number
             else:
             else:
-                current_version_number = default_version_number[Config.core.mode]
+                current_version_number = str(uuid.uuid4())
+
+            try:
+                cls._set_experiment_version(current_version_number, Config.core.force)
+            except VersionAlreadyExistsAsDevelopment as err:
+                raise SystemExit(err.message) from None
 
 
-            version_setter[Config.core.mode](current_version_number, Config.core.force)
-            if Config.core.mode == "production":
-                cls.__check_production_migration_config()
         else:
         else:
             raise SystemExit(f"Undefined execution mode: {Config.core.mode}.")
             raise SystemExit(f"Undefined execution mode: {Config.core.mode}.")
 
 
-    @classmethod
-    def __check_production_migration_config(cls):
-        from ..config.checkers._migration_config_checker import _MigrationConfigChecker
-
-        collector = _MigrationConfigChecker(Config._applied_config, IssueCollector())._check()
-        for issue in collector._warnings:
-            cls.__logger.warning(str(issue))
-        for issue in collector._infos:
-            cls.__logger.info(str(issue))
-        for issue in collector._errors:
-            cls.__logger.error(str(issue))
-        if len(collector._errors) != 0:
-            raise SystemExit("Configuration errors found. Please check the error log for more information.")
-
     @classmethod
     @classmethod
     def _delete_entities_of_multiple_types(cls, _entity_ids):
     def _delete_entities_of_multiple_types(cls, _entity_ids):
         raise NotImplementedError
         raise NotImplementedError

+ 0 - 46
taipy/core/_version/_version_repository_interface.py

@@ -1,46 +0,0 @@
-# Copyright 2021-2024 Avaiga Private Limited
-#
-# 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.
-
-from abc import ABC, abstractmethod
-
-
-class _VersionRepositoryInterface(ABC):
-    _LATEST_VERSION_KEY = "latest_version"
-    _DEVELOPMENT_VERSION_KEY = "development_version"
-    _PRODUCTION_VERSION_KEY = "production_version"
-
-    @abstractmethod
-    def _set_latest_version(self, version_number):
-        raise NotImplementedError
-
-    @abstractmethod
-    def _get_latest_version(self):
-        raise NotImplementedError
-
-    @abstractmethod
-    def _set_development_version(self, version_number):
-        raise NotImplementedError
-
-    @abstractmethod
-    def _get_development_version(self):
-        raise NotImplementedError
-
-    @abstractmethod
-    def _set_production_version(self, version_number):
-        raise NotImplementedError
-
-    @abstractmethod
-    def _get_production_versions(self):
-        raise NotImplementedError
-
-    @abstractmethod
-    def _delete_production_version(self, version_number):
-        raise NotImplementedError

+ 0 - 9
taipy/core/config/__init__.py

@@ -25,7 +25,6 @@ from .checkers._task_config_checker import _TaskConfigChecker
 from .core_section import CoreSection
 from .core_section import CoreSection
 from .data_node_config import DataNodeConfig
 from .data_node_config import DataNodeConfig
 from .job_config import JobConfig
 from .job_config import JobConfig
-from .migration_config import MigrationConfig
 from .scenario_config import ScenarioConfig
 from .scenario_config import ScenarioConfig
 from .task_config import TaskConfig
 from .task_config import TaskConfig
 
 
@@ -75,13 +74,6 @@ _inject_section(
         ("set_default_scenario_configuration", ScenarioConfig._set_default_configuration),
         ("set_default_scenario_configuration", ScenarioConfig._set_default_configuration),
     ],
     ],
 )
 )
-_inject_section(
-    MigrationConfig,
-    "migration_functions",
-    MigrationConfig.default_config(),
-    [("add_migration_function", MigrationConfig._add_migration_function)],
-    add_to_unconflicted_sections=True,
-)
 _inject_section(
 _inject_section(
     CoreSection,
     CoreSection,
     "core",
     "core",
@@ -94,6 +86,5 @@ _Checker.add_checker(_ConfigIdChecker)
 _Checker.add_checker(_CoreSectionChecker)
 _Checker.add_checker(_CoreSectionChecker)
 _Checker.add_checker(_DataNodeConfigChecker)
 _Checker.add_checker(_DataNodeConfigChecker)
 _Checker.add_checker(_JobConfigChecker)
 _Checker.add_checker(_JobConfigChecker)
-# We don't need to add _MigrationConfigChecker because it is run only when the Core service is run.
 _Checker.add_checker(_TaskConfigChecker)
 _Checker.add_checker(_TaskConfigChecker)
 _Checker.add_checker(_ScenarioConfigChecker)
 _Checker.add_checker(_ScenarioConfigChecker)

+ 0 - 66
taipy/core/config/checkers/_migration_config_checker.py

@@ -1,66 +0,0 @@
-# Copyright 2021-2024 Avaiga Private Limited
-#
-# 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.
-
-from taipy.config._config import _Config
-from taipy.config.checker._checkers._config_checker import _ConfigChecker
-from taipy.config.checker.issue_collector import IssueCollector
-
-from ..._version._version_manager_factory import _VersionManagerFactory
-from ..migration_config import MigrationConfig
-
-
-class _MigrationConfigChecker(_ConfigChecker):
-    def __init__(self, config: _Config, collector: IssueCollector):
-        super().__init__(config, collector)
-
-    def _check(self) -> IssueCollector:
-        if migration_config := self._config._unique_sections.get(MigrationConfig.name):
-            self._check_if_entity_property_key_used_is_predefined(migration_config)
-
-            migration_fcts = migration_config.migration_fcts
-
-            for target_version, migration_functions in migration_config.migration_fcts.items():  # type: ignore[union-attr]
-                for config_id, migration_function in migration_functions.items():
-                    self._check_callable(target_version, config_id, migration_function)
-
-            self._check_valid_production_version(migration_fcts)
-            self._check_migration_from_productions_to_productions_exist(migration_fcts)
-
-        return self._collector
-
-    def _check_callable(self, target_version, config_id, migration_function):
-        if not callable(migration_function):
-            self._error(
-                MigrationConfig._MIGRATION_FCTS_KEY,
-                migration_function,
-                f"The migration function of config `{config_id}` from version {target_version}"
-                f" must be populated with Callable value.",
-            )
-
-    def _check_valid_production_version(self, migration_fcts):
-        for target_version in migration_fcts.keys():
-            if target_version not in _VersionManagerFactory._build_manager()._get_production_versions():
-                self._error(
-                    MigrationConfig._MIGRATION_FCTS_KEY,
-                    target_version,
-                    "The target version for a migration function must be a production version.",
-                )
-
-    def _check_migration_from_productions_to_productions_exist(self, migration_fcts):
-        production_versions = _VersionManagerFactory._build_manager()._get_production_versions()
-        for source_version, target_version in zip(production_versions[:-1], production_versions[1:]):
-            if not migration_fcts.get(target_version):
-                self._info(
-                    "target_version",
-                    None,
-                    f'There is no migration function from production version "{source_version}"'
-                    f' to version "{target_version}".',
-                )

+ 6 - 7
taipy/core/config/core_section.py

@@ -39,8 +39,8 @@ class CoreSection(UniqueSection):
         read_entity_retry (int): Number of retries to read an entity from the repository before return failure.
         read_entity_retry (int): Number of retries to read an entity from the repository before return failure.
             The default value is 3.
             The default value is 3.
         mode (str): The Taipy operating mode. By default, the `Core^` service runs in "development" mode.
         mode (str): The Taipy operating mode. By default, the `Core^` service runs in "development" mode.
-            An "experiment" and a "production" mode are also available. Please refer to the
-            [Versioning management](../../userman/versioning/index.md) documentation page for more details.
+            Please refer to the [Versioning management](../../userman/versioning/index.md)
+            documentation page for more details.
         version_number (str)): The identifier of the user application version. Please refer to the
         version_number (str)): The identifier of the user application version. Please refer to the
             [Versioning management](../../userman/versioning/index.md) documentation page for more details.
             [Versioning management](../../userman/versioning/index.md) documentation page for more details.
         force (bool): If True, force the application run even if there are some conflicts in the
         force (bool): If True, force the application run even if there are some conflicts in the
@@ -69,10 +69,7 @@ class CoreSection(UniqueSection):
     _DEFAULT_READ_ENTITY_RETRY = 1
     _DEFAULT_READ_ENTITY_RETRY = 1
 
 
     _MODE_KEY = "mode"
     _MODE_KEY = "mode"
-    _DEVELOPMENT_MODE = "development"
-    _EXPERIMENT_MODE = "experiment"
-    _PRODUCTION_MODE = "production"
-    _DEFAULT_MODE = _DEVELOPMENT_MODE
+    _DEFAULT_MODE = "development"
 
 
     _VERSION_NUMBER_KEY = "version_number"
     _VERSION_NUMBER_KEY = "version_number"
     _DEFAULT_VERSION_NUMBER = ""
     _DEFAULT_VERSION_NUMBER = ""
@@ -366,7 +363,9 @@ class CoreSection(UniqueSection):
             read_entity_retry (Optional[int]): Number of retries to read an entity from the repository
             read_entity_retry (Optional[int]): Number of retries to read an entity from the repository
                 before return failure. The default value is 3.
                 before return failure. The default value is 3.
             mode (Optional[str]): Indicates the mode of the version management system.
             mode (Optional[str]): Indicates the mode of the version management system.
-                Possible values are *"development"*, *"experiment"*, or *"production"*.
+                Possible values are *"development"* or *"experiment"*. On Enterprise edition of Taipy,
+                *production* mode is also available. Please refer to the
+                [Versioning management](../../userman/versioning/index.md) documentation page for more details.
             version_number (Optional[str]): The string identifier of the version.
             version_number (Optional[str]): The string identifier of the version.
                  In development mode, the version number is ignored.
                  In development mode, the version number is ignored.
             force (Optional[bool]): If True, Taipy will override a version even if the configuration
             force (Optional[bool]): If True, Taipy will override a version even if the configuration

+ 0 - 113
taipy/core/config/migration_config.py

@@ -1,113 +0,0 @@
-# Copyright 2021-2024 Avaiga Private Limited
-#
-# 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 collections.abc
-from copy import deepcopy
-from typing import Any, Callable, Dict, Optional, Union
-
-from taipy.config._config import _Config
-from taipy.config.common._template_handler import _TemplateHandler as _tpl
-from taipy.config.config import Config
-from taipy.config.section import Section
-from taipy.config.unique_section import UniqueSection
-
-
-class MigrationConfig(UniqueSection):
-    """
-    Configuration fields needed to register migration functions from an old version to newer one.
-
-    Attributes:
-        migration_fcts (Dict[str, Dict[str, Callable]]): A dictionary that maps the version that entities are
-            migrated from to the migration functions.
-        **properties (dict[str, Any]): A dictionary of additional properties.
-    """
-
-    name = "VERSION_MIGRATION"
-
-    _MIGRATION_FCTS_KEY = "migration_fcts"
-
-    def __init__(
-        self,
-        migration_fcts: Dict[str, Dict[str, Callable]],
-        **properties,
-    ):
-        self.migration_fcts = migration_fcts
-
-        super().__init__(**properties)
-
-    def __copy__(self):
-        return MigrationConfig(
-            deepcopy(self.migration_fcts),
-            **deepcopy(self._properties),
-        )
-
-    def _clean(self):
-        self.migration_fcts.clear()
-        self._properties.clear()
-
-    def __getattr__(self, item: str) -> Optional[Any]:
-        return _tpl._replace_templates(self._properties.get(item))  # type: ignore
-
-    @classmethod
-    def default_config(cls):
-        return MigrationConfig({})
-
-    def _to_dict(self):
-        return {
-            self._MIGRATION_FCTS_KEY: self.migration_fcts,
-            **self._properties,
-        }
-
-    @classmethod
-    def _from_dict(cls, as_dict: Dict[str, Any], id: str, config: Optional[_Config]):
-        return MigrationConfig(**as_dict)
-
-    def _update(self, as_dict, default_section=None):
-        def deep_update(d, u):
-            for k, v in u.items():
-                if isinstance(v, collections.abc.Mapping):
-                    d[k] = deep_update(d.get(k, {}), v)
-                else:
-                    d[k] = v
-            return d
-
-        migration_fcts = as_dict.pop(self._MIGRATION_FCTS_KEY)
-        deep_update(self.migration_fcts, migration_fcts)
-
-        self._properties.update(as_dict)
-
-    @staticmethod
-    def _add_migration_function(
-        target_version: str,
-        config: Union[Section, str],
-        migration_fct: Callable,
-        **properties,
-    ):
-        """Add a migration function for a Configuration to migrate entities to the target version.
-
-        Parameters:
-            target_version (str): The production version that entities are migrated to.
-            config (Union[Section, str]): The configuration or the `id` of the config that needs to migrate.
-            migration_fct (Callable): Migration function that takes an entity as input and returns a new entity
-                that is compatible with the target production version.
-            **properties (Dict[str, Any]): A keyworded variable length list of additional arguments.
-        Returns:
-            `MigrationConfig^`: The Migration configuration.
-        """
-        config_id = config if isinstance(config, str) else config.id
-        migration_fcts = {target_version: {config_id: migration_fct}}
-
-        section = MigrationConfig(
-            migration_fcts,
-            **properties,
-        )
-        Config._register(section)
-        return Config.unique_sections[MigrationConfig.name]

+ 1 - 3
taipy/core/data/_data_converter.py

@@ -14,7 +14,6 @@ from datetime import datetime, timedelta
 from pydoc import locate
 from pydoc import locate
 
 
 from .._repository._abstract_converter import _AbstractConverter
 from .._repository._abstract_converter import _AbstractConverter
-from .._version._utils import _migrate_entity
 from ..common._utils import _load_fct
 from ..common._utils import _load_fct
 from ..data._data_model import _DataNodeModel
 from ..data._data_model import _DataNodeModel
 from ..data.data_node import DataNode
 from ..data.data_node import DataNode
@@ -299,7 +298,7 @@ class _DataNodeConverter(_AbstractConverter):
             validity_period = timedelta(days=model.validity_days, seconds=model.validity_seconds)
             validity_period = timedelta(days=model.validity_days, seconds=model.validity_seconds)
 
 
         exp_date = datetime.fromisoformat(model.editor_expiration_date) if model.editor_expiration_date else None
         exp_date = datetime.fromisoformat(model.editor_expiration_date) if model.editor_expiration_date else None
-        datanode = DataNode._class_map()[model.storage_type](
+        return DataNode._class_map()[model.storage_type](
             config_id=model.config_id,
             config_id=model.config_id,
             scope=model.scope,
             scope=model.scope,
             id=model.id,
             id=model.id,
@@ -314,4 +313,3 @@ class _DataNodeConverter(_AbstractConverter):
             editor_expiration_date=exp_date,
             editor_expiration_date=exp_date,
             properties=data_node_properties,
             properties=data_node_properties,
         )
         )
-        return _migrate_entity(datanode)

+ 6 - 2
taipy/core/exceptions/exceptions.py

@@ -346,8 +346,12 @@ class NonExistingVersion(Exception):
         self.message = f"Version '{version_number}' does not exist."
         self.message = f"Version '{version_number}' does not exist."
 
 
 
 
-class VersionIsNotProductionVersion(Exception):
-    """Raised if the version is not a production version."""
+class VersionAlreadyExistsAsDevelopment(Exception):
+    """Raised if a version already exists as the development version."""
+
+    def __init__(self, version_number: str):
+        self.message = f"Version number {version_number} already exists as the development version."
+        self.message += " Please choose a different name for this experiment."
 
 
 
 
 class ConflictedConfigurationError(Exception):
 class ConflictedConfigurationError(Exception):

+ 1 - 3
taipy/core/scenario/_scenario_converter.py

@@ -13,7 +13,6 @@ from datetime import datetime
 from typing import Dict, List, Optional, Set, Union
 from typing import Dict, List, Optional, Set, Union
 
 
 from .._repository._abstract_converter import _AbstractConverter
 from .._repository._abstract_converter import _AbstractConverter
-from .._version._utils import _migrate_entity
 from ..common import _utils
 from ..common import _utils
 from ..cycle._cycle_manager_factory import _CycleManagerFactory
 from ..cycle._cycle_manager_factory import _CycleManagerFactory
 from ..cycle.cycle import Cycle, CycleId
 from ..cycle.cycle import Cycle, CycleId
@@ -67,7 +66,7 @@ class _ScenarioConverter(_AbstractConverter):
                         for it in subscribers
                         for it in subscribers
                     ]
                     ]
 
 
-        scenario = Scenario(
+        return Scenario(
             scenario_id=model.id,
             scenario_id=model.id,
             config_id=model.config_id,
             config_id=model.config_id,
             tasks=tasks,
             tasks=tasks,
@@ -84,7 +83,6 @@ class _ScenarioConverter(_AbstractConverter):
             version=model.version,
             version=model.version,
             sequences=model.sequences,
             sequences=model.sequences,
         )
         )
-        return _migrate_entity(scenario)
 
 
     @staticmethod
     @staticmethod
     def __to_cycle(cycle_id: Optional[CycleId] = None) -> Optional[Cycle]:
     def __to_cycle(cycle_id: Optional[CycleId] = None) -> Optional[Cycle]:

+ 7 - 24
taipy/core/taipy.py

@@ -36,12 +36,7 @@ from .cycle.cycle_id import CycleId
 from .data._data_manager_factory import _DataManagerFactory
 from .data._data_manager_factory import _DataManagerFactory
 from .data.data_node import DataNode
 from .data.data_node import DataNode
 from .data.data_node_id import DataNodeId
 from .data.data_node_id import DataNodeId
-from .exceptions.exceptions import (
-    DataNodeConfigIsNotGlobal,
-    ModelNotFound,
-    NonExistingVersion,
-    VersionIsNotProductionVersion,
-)
+from .exceptions.exceptions import DataNodeConfigIsNotGlobal, ModelNotFound, NonExistingVersion
 from .job._job_manager_factory import _JobManagerFactory
 from .job._job_manager_factory import _JobManagerFactory
 from .job.job import Job
 from .job.job import Job
 from .job.job_id import JobId
 from .job.job_id import JobId
@@ -967,19 +962,14 @@ def clean_all_entities_by_version(version_number=None) -> bool:
 
 
 def clean_all_entities(version_number: str) -> bool:
 def clean_all_entities(version_number: str) -> bool:
     """Deletes all entities associated with the specified version.
     """Deletes all entities associated with the specified version.
+    This function cleans all entities, including jobs, submissions, scenarios, cycles, sequences, tasks, and data nodes.
 
 
     Parameters:
     Parameters:
-        version_number (str): The version number of the entities to be deleted.
-            The version_number should not be a production version.
+        version_number (str): The version number of the entities to be deleted.<br/>
+            - If the specified version does not exist, the operation will be aborted, and False will be returned.
 
 
     Returns:
     Returns:
         True if the operation succeeded, False otherwise.
         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.
-        - 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()
     version_manager = _VersionManagerFactory._build_manager()
     try:
     try:
@@ -988,10 +978,9 @@ def clean_all_entities(version_number: str) -> bool:
         __logger.warning(f"{e.message} Abort cleaning the entities of version '{version_number}'.")
         __logger.warning(f"{e.message} Abort cleaning the entities of version '{version_number}'.")
         return False
         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."
-        )
+    if not version_manager._is_deletable(version_number):
+        reason_collection = version_manager._is_deletable(version_number)
+        __logger.warning(f"Abort cleaning the entities of version '{version_number}'. {reason_collection.reasons}.")
         return False
         return False
 
 
     _JobManagerFactory._build_manager()._delete_by_version(version_number)
     _JobManagerFactory._build_manager()._delete_by_version(version_number)
@@ -1000,14 +989,8 @@ def clean_all_entities(version_number: str) -> bool:
     _SequenceManagerFactory._build_manager()._delete_by_version(version_number)
     _SequenceManagerFactory._build_manager()._delete_by_version(version_number)
     _TaskManagerFactory._build_manager()._delete_by_version(version_number)
     _TaskManagerFactory._build_manager()._delete_by_version(version_number)
     _DataManagerFactory._build_manager()._delete_by_version(version_number)
     _DataManagerFactory._build_manager()._delete_by_version(version_number)
-
     version_manager._delete(version_number)
     version_manager._delete(version_number)
 
 
-    try:
-        version_manager._delete_production_version(version_number)
-    except VersionIsNotProductionVersion:
-        pass
-
     return True
     return True
 
 
 
 

+ 1 - 4
taipy/core/task/_task_converter.py

@@ -9,9 +9,7 @@
 # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 # 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.
 # specific language governing permissions and limitations under the License.
 
 
-
 from .._repository._abstract_converter import _AbstractConverter
 from .._repository._abstract_converter import _AbstractConverter
-from .._version._utils import _migrate_entity
 from ..common._utils import _load_fct
 from ..common._utils import _load_fct
 from ..data._data_manager_factory import _DataManagerFactory
 from ..data._data_manager_factory import _DataManagerFactory
 from ..exceptions import NonExistingDataNode
 from ..exceptions import NonExistingDataNode
@@ -39,7 +37,7 @@ class _TaskConverter(_AbstractConverter):
 
 
     @classmethod
     @classmethod
     def _model_to_entity(cls, model: _TaskModel) -> Task:
     def _model_to_entity(cls, model: _TaskModel) -> Task:
-        task = Task(
+        return Task(
             id=TaskId(model.id),
             id=TaskId(model.id),
             owner_id=model.owner_id,
             owner_id=model.owner_id,
             parent_ids=set(model.parent_ids),
             parent_ids=set(model.parent_ids),
@@ -51,7 +49,6 @@ class _TaskConverter(_AbstractConverter):
             skippable=model.skippable,
             skippable=model.skippable,
             properties=model.properties,
             properties=model.properties,
         )
         )
-        return _migrate_entity(task)
 
 
     @staticmethod
     @staticmethod
     def __to_ids(data_nodes):
     def __to_ids(data_nodes):

+ 1 - 8
tests/conftest.py

@@ -21,7 +21,7 @@ from taipy.config._serializer._toml_serializer import _TomlSerializer
 from taipy.config.checker._checker import _Checker
 from taipy.config.checker._checker import _Checker
 from taipy.config.checker.issue_collector import IssueCollector
 from taipy.config.checker.issue_collector import IssueCollector
 from taipy.config.config import Config
 from taipy.config.config import Config
-from taipy.core.config import CoreSection, DataNodeConfig, JobConfig, MigrationConfig, ScenarioConfig, TaskConfig
+from taipy.core.config import CoreSection, DataNodeConfig, JobConfig, ScenarioConfig, TaskConfig
 
 
 
 
 def pytest_addoption(parser):
 def pytest_addoption(parser):
@@ -137,12 +137,5 @@ def inject_core_sections():
                 ("set_default_scenario_configuration", ScenarioConfig._set_default_configuration),
                 ("set_default_scenario_configuration", ScenarioConfig._set_default_configuration),
             ],
             ],
         )
         )
-        _inject_section(
-            MigrationConfig,
-            "migration_functions",
-            MigrationConfig.default_config(),
-            [("add_migration_function", MigrationConfig._add_migration_function)],
-            True,
-        )
 
 
     return _inject_core_sections
     return _inject_core_sections

+ 10 - 0
tests/core/_version/__init__.py

@@ -0,0 +1,10 @@
+# Copyright 2021-2024 Avaiga Private Limited
+#
+# 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.

+ 0 - 0
tests/core/version/dataset_2.0/cycles/CYCLE_Frequency.DAILY_2023-01-18T172525.892619_8956558e-d108-4ac4-8684-60f3e5ef9e8f.json → tests/core/_version/dataset_2.0/cycles/CYCLE_Frequency.DAILY_2023-01-18T172525.892619_8956558e-d108-4ac4-8684-60f3e5ef9e8f.json


+ 0 - 0
tests/core/version/dataset_2.0/data_nodes/DATANODE_d1_3d65c33b-b188-4402-8d2c-3b26d98b9a9e.json → tests/core/_version/dataset_2.0/data_nodes/DATANODE_d1_3d65c33b-b188-4402-8d2c-3b26d98b9a9e.json


+ 0 - 0
tests/core/version/dataset_2.0/data_nodes/DATANODE_d2_bd8ee43e-6fa9-4832-b2e7-c0c9516b1e1c.json → tests/core/_version/dataset_2.0/data_nodes/DATANODE_d2_bd8ee43e-6fa9-4832-b2e7-c0c9516b1e1c.json


+ 0 - 0
tests/core/version/dataset_2.0/scenarios/SCENARIO_my_scenario_c4307ae8-d2ce-4802-8b16-8307baa7cff1.json → tests/core/_version/dataset_2.0/scenarios/SCENARIO_my_scenario_c4307ae8-d2ce-4802-8b16-8307baa7cff1.json


+ 0 - 0
tests/core/version/dataset_2.0/sequences/SEQUENCE_my_sequence_1b97a539-ca51-4eb8-aa64-c232269618c6.json → tests/core/_version/dataset_2.0/sequences/SEQUENCE_my_sequence_1b97a539-ca51-4eb8-aa64-c232269618c6.json


+ 0 - 0
tests/core/version/dataset_2.0/tasks/TASK_my_task_53cf9993-047f-4220-9c03-e28fa250f6b3.json → tests/core/_version/dataset_2.0/tasks/TASK_my_task_53cf9993-047f-4220-9c03-e28fa250f6b3.json


+ 0 - 0
tests/core/version/test_version.py → tests/core/_version/test_version.py


+ 23 - 99
tests/core/version/test_version_cli.py → tests/core/_version/test_version_cli.py

@@ -19,7 +19,7 @@ from taipy.config.common.frequency import Frequency
 from taipy.config.common.scope import Scope
 from taipy.config.common.scope import Scope
 from taipy.config.config import Config
 from taipy.config.config import Config
 from taipy.core import Core
 from taipy.core import Core
-from taipy.core._version._cli._version_cli import _VersionCLI
+from taipy.core._version._cli._version_cli_factory import _VersionCLIFactory
 from taipy.core._version._version_manager import _VersionManager
 from taipy.core._version._version_manager import _VersionManager
 from taipy.core.data._data_manager import _DataManager
 from taipy.core.data._data_manager import _DataManager
 from taipy.core.job._job_manager import _JobManager
 from taipy.core.job._job_manager import _JobManager
@@ -59,11 +59,6 @@ def test_delete_version(caplog):
         _ScenarioManager._submit(scenario)
         _ScenarioManager._submit(scenario)
         core.stop()
         core.stop()
 
 
-    with patch("sys.argv", ["prog", "--production", "1.1"]):
-        core = Core()
-        core.run()
-        core.stop()
-
     with patch("sys.argv", ["prog", "--experiment", "2.0"]):
     with patch("sys.argv", ["prog", "--experiment", "2.0"]):
         core = Core()
         core = Core()
         core.run()
         core.run()
@@ -71,61 +66,28 @@ def test_delete_version(caplog):
         _ScenarioManager._submit(scenario)
         _ScenarioManager._submit(scenario)
         core.stop()
         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()]
     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 len(all_versions) == 4
     assert "1.0" in all_versions
     assert "1.0" in all_versions
-    assert "1.1" in all_versions and "1.1" in production_version
+    assert "1.1" in all_versions
     assert "2.0" in all_versions
     assert "2.0" in all_versions
-    assert "2.1" in all_versions and "2.1" in production_version
 
 
-    _VersionCLI.create_parser()
+    _VersionCLIFactory._build_cli().create_parser()
     with pytest.raises(SystemExit):
     with pytest.raises(SystemExit):
         with patch("sys.argv", ["prog", "manage-versions", "--delete", "1.0"]):
         with patch("sys.argv", ["prog", "manage-versions", "--delete", "1.0"]):
-            _VersionCLI.handle_command()
+            _VersionCLIFactory._build_cli().handle_command()
 
 
     assert "Successfully delete version 1.0." in caplog.text
     assert "Successfully delete version 1.0." in caplog.text
     all_versions = [version.id for version in _VersionManager._get_all()]
     all_versions = [version.id for version in _VersionManager._get_all()]
-    assert len(all_versions) == 4
+    assert len(all_versions) == 3
     assert "1.0" not in all_versions
     assert "1.0" not in all_versions
 
 
     # Test delete a non-existed version
     # Test delete a non-existed version
     with pytest.raises(SystemExit):
     with pytest.raises(SystemExit):
         with patch("sys.argv", ["prog", "manage-versions", "--delete", "non_exist_version"]):
         with patch("sys.argv", ["prog", "manage-versions", "--delete", "non_exist_version"]):
-            _VersionCLI.handle_command()
+            _VersionCLIFactory._build_cli().handle_command()
     assert "Version 'non_exist_version' does not exist." in caplog.text
     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.handle_command()
-
-    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.handle_command()
-
-    assert str(e.value) == "Version 'non_exist_version' is not a production version."
-
 
 
 def test_list_versions(capsys):
 def test_list_versions(capsys):
     with patch("sys.argv", ["prog", "--development"]):
     with patch("sys.argv", ["prog", "--development"]):
@@ -138,45 +100,23 @@ def test_list_versions(capsys):
         core.run()
         core.run()
         core.stop()
         core.stop()
     sleep(0.05)
     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"]):
     with patch("sys.argv", ["prog", "--experiment", "2.0"]):
         core = Core()
         core = Core()
         core.run()
         core.run()
         core.stop()
         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()
+    _VersionCLIFactory._build_cli().create_parser()
     with pytest.raises(SystemExit):
     with pytest.raises(SystemExit):
         with patch("sys.argv", ["prog", "manage-versions", "--list"]):
         with patch("sys.argv", ["prog", "manage-versions", "--list"]):
-            _VersionCLI.handle_command()
+            _VersionCLIFactory._build_cli().handle_command()
 
 
     out, _ = capsys.readouterr()
     out, _ = capsys.readouterr()
     version_list = str(out).strip().split("\n")
     version_list = str(out).strip().split("\n")
-    assert len(version_list) == 6  # 5 versions with the header
+    assert len(version_list) == 4  # 3 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[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]
+    assert all(column in version_list[1] for column in ["2.0", "Experiment", "latest"])
+    assert all(column in version_list[2] for column in ["1.0", "Experiment"]) and "latest" not in version_list[2]
+    assert "Development" in version_list[3] and "latest" not in version_list[3]
 
 
 
 
 def test_rename_version(caplog):
 def test_rename_version(caplog):
@@ -189,7 +129,7 @@ def test_rename_version(caplog):
         _ScenarioManager._submit(scenario)
         _ScenarioManager._submit(scenario)
         core.stop()
         core.stop()
 
 
-    with patch("sys.argv", ["prog", "--production", "2.0"]):
+    with patch("sys.argv", ["prog", "--experiment", "2.0"]):
         core = Core()
         core = Core()
         core.run()
         core.run()
         scenario = _ScenarioManager._create(scenario_config)
         scenario = _ScenarioManager._create(scenario_config)
@@ -198,24 +138,22 @@ def test_rename_version(caplog):
 
 
     dev_ver = _VersionManager._get_development_version()
     dev_ver = _VersionManager._get_development_version()
 
 
-    _VersionCLI.create_parser()
+    _VersionCLIFactory._build_cli().create_parser()
     with pytest.raises(SystemExit):
     with pytest.raises(SystemExit):
         with patch("sys.argv", ["prog", "manage-versions", "--rename", "non_exist_version", "1.1"]):
         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
             # This should raise an exception since version "non_exist_version" does not exist
-            _VersionCLI.handle_command()
+            _VersionCLIFactory._build_cli().handle_command()
     assert "Version 'non_exist_version' does not exist." in caplog.text
     assert "Version 'non_exist_version' does not exist." in caplog.text
 
 
-    _VersionCLI.create_parser()
     with pytest.raises(SystemExit):
     with pytest.raises(SystemExit):
         with patch("sys.argv", ["prog", "manage-versions", "--rename", "1.0", "2.0"]):
         with patch("sys.argv", ["prog", "manage-versions", "--rename", "1.0", "2.0"]):
             # This should raise an exception since 2.0 already exists
             # This should raise an exception since 2.0 already exists
-            _VersionCLI.handle_command()
+            _VersionCLIFactory._build_cli().handle_command()
     assert "Version name '2.0' is already used." in caplog.text
     assert "Version name '2.0' is already used." in caplog.text
 
 
-    _VersionCLI.create_parser()
     with pytest.raises(SystemExit):
     with pytest.raises(SystemExit):
         with patch("sys.argv", ["prog", "manage-versions", "--rename", "1.0", "1.1"]):
         with patch("sys.argv", ["prog", "manage-versions", "--rename", "1.0", "1.1"]):
-            _VersionCLI.handle_command()
+            _VersionCLIFactory._build_cli().handle_command()
     assert _VersionManager._get("1.0") is None
     assert _VersionManager._get("1.0") is None
     assert [version.id for version in _VersionManager._get_all()].sort() == [dev_ver, "1.1", "2.0"].sort()
     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
     # All entities are assigned to the new version
@@ -225,20 +163,6 @@ def test_rename_version(caplog):
     assert len(_ScenarioManager._get_all("1.1")) == 1
     assert len(_ScenarioManager._get_all("1.1")) == 1
     assert len(_JobManager._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.handle_command()
-    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")) == 1
-    assert len(_ScenarioManager._get_all("2.1")) == 1
-    assert len(_JobManager._get_all("2.1")) == 1
-
 
 
 def test_compare_version_config(caplog, init_config):
 def test_compare_version_config(caplog, init_config):
     scenario_config_1 = config_scenario()
     scenario_config_1 = config_scenario()
@@ -262,27 +186,27 @@ def test_compare_version_config(caplog, init_config):
         _ScenarioManager._submit(scenario)
         _ScenarioManager._submit(scenario)
         core.stop()
         core.stop()
 
 
-    _VersionCLI.create_parser()
+    _VersionCLIFactory._build_cli().create_parser()
     with pytest.raises(SystemExit):
     with pytest.raises(SystemExit):
         with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "non_exist_version", "2.0"]):
         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
             # This should raise an exception since version "non_exist_version" does not exist
-            _VersionCLI.handle_command()
+            _VersionCLIFactory._build_cli().handle_command()
     assert "Version 'non_exist_version' does not exist." in caplog.text
     assert "Version 'non_exist_version' does not exist." in caplog.text
 
 
     with pytest.raises(SystemExit):
     with pytest.raises(SystemExit):
         with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "non_exist_version"]):
         with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "non_exist_version"]):
             # This should raise an exception since 2.0 already exists
             # This should raise an exception since 2.0 already exists
-            _VersionCLI.handle_command()
+            _VersionCLIFactory._build_cli().handle_command()
     assert "Version 'non_exist_version' does not exist." in caplog.text
     assert "Version 'non_exist_version' does not exist." in caplog.text
 
 
     with pytest.raises(SystemExit):
     with pytest.raises(SystemExit):
         with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "1.0"]):
         with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "1.0"]):
-            _VersionCLI.handle_command()
+            _VersionCLIFactory._build_cli().handle_command()
     assert "There is no difference between version 1.0 Configuration and version 1.0 Configuration." in caplog.text
     assert "There is no difference between version 1.0 Configuration and version 1.0 Configuration." in caplog.text
 
 
     with pytest.raises(SystemExit):
     with pytest.raises(SystemExit):
         with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "2.0"]):
         with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "2.0"]):
-            _VersionCLI.handle_command()
+            _VersionCLIFactory._build_cli().handle_command()
     expected_message = """Differences between version 1.0 Configuration and version 2.0 Configuration:
     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"""
 \tDATA_NODE "d2" has attribute "default_path" modified: foo.csv -> bar.csv"""
     assert expected_message in caplog.text
     assert expected_message in caplog.text

+ 0 - 0
tests/core/version/test_version_manager.py → tests/core/_version/test_version_manager.py


+ 0 - 0
tests/core/version/test_version_repositories.py → tests/core/_version/test_version_repositories.py


+ 0 - 132
tests/core/config/checkers/test_migration_config_checker.py

@@ -1,132 +0,0 @@
-# Copyright 2021-2024 Avaiga Private Limited
-#
-# 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.
-
-from unittest.mock import patch
-
-import pytest
-
-from taipy.config.config import Config
-from taipy.core import Core
-from taipy.core._version._version_manager import _VersionManager
-from taipy.core.config import MigrationConfig
-
-
-def mock_func():
-    pass
-
-
-def test_check_if_entity_property_key_used_is_predefined(caplog):
-    Config.unique_sections[MigrationConfig.name]._properties["_entity_owner"] = None
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        with pytest.raises(SystemExit):
-            core = Core()
-            core.run()
-        core.stop()
-    assert (
-        "Properties of MigrationConfig `VERSION_MIGRATION` cannot have `_entity_owner` as its property." in caplog.text
-    )
-
-    caplog.clear()
-
-    Config.unique_sections[MigrationConfig.name]._properties["_entity_owner"] = "entity_owner"
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        with pytest.raises(SystemExit):
-            core = Core()
-            core.run()
-        core.stop()
-    expected_error_message = (
-        "Properties of MigrationConfig `VERSION_MIGRATION` cannot have `_entity_owner` as its property."
-        ' Current value of property `_entity_owner` is "entity_owner".'
-    )
-    assert expected_error_message in caplog.text
-
-
-def test_check_valid_version(caplog):
-    data_nodes1 = Config.configure_data_node("data_nodes1", "pickle")
-
-    Config.add_migration_function("2.0", data_nodes1, mock_func)
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        with pytest.raises(SystemExit):
-            core = Core()
-            core.run()
-        core.stop()
-    assert "The target version for a migration function must be a production version." in caplog.text
-
-    caplog.clear()
-    Config.unblock_update()
-
-    with patch("sys.argv", ["prog", "--production", "2.0"]):
-        # No SystemExit should be raised
-        core = Core()
-        core.run()
-    core.stop()
-
-
-def test_check_callable_function(caplog):
-    data_nodes1 = Config.configure_data_node("data_nodes1", "pickle")
-    Config.add_migration_function("1.0", data_nodes1, 1)
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        with pytest.raises(SystemExit):
-            core = Core()
-            core.run()
-        core.stop()
-    expected_error_message = (
-        "The migration function of config `data_nodes1` from version 1.0 must be populated with"
-        " Callable value. Current value of property `migration_fcts` is 1."
-    )
-    assert expected_error_message in caplog.text
-
-    caplog.clear()
-    Config.unblock_update()
-
-    Config.add_migration_function("1.0", data_nodes1, "bar")
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        with pytest.raises(SystemExit):
-            core = Core()
-            core.run()
-        core.stop()
-    expected_error_message = (
-        "The migration function of config `data_nodes1` from version 1.0 must be populated with"
-        ' Callable value. Current value of property `migration_fcts` is "bar".'
-    )
-    assert expected_error_message in caplog.text
-
-    caplog.clear()
-    Config.unblock_update()
-
-    Config.add_migration_function("1.0", data_nodes1, mock_func)
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        core = Core()
-        core.run()
-        core.stop()
-
-
-def test_check_migration_from_productions_to_productions_exist(caplog):
-    _VersionManager._set_production_version("1.0", True)
-    _VersionManager._set_production_version("1.1", True)
-    _VersionManager._set_production_version("1.2", True)
-
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        core = Core()
-        core.run()
-        core.stop()
-    assert 'There is no migration function from production version "1.0" to version "1.1".' in caplog.text
-    assert 'There is no migration function from production version "1.1" to version "1.2".' in caplog.text
-
-    caplog.clear()
-    Config.unblock_update()
-
-    Config.add_migration_function("1.2", "data_nodes1", mock_func)
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        core = Core()
-        core.run()
-        core.stop()
-    assert 'There is no migration function from production version "1.0" to version "1.1".' in caplog.text

+ 5 - 35
tests/core/config/test_config_serialization.py

@@ -16,7 +16,7 @@ from taipy.config import Config
 from taipy.config._serializer._json_serializer import _JsonSerializer
 from taipy.config._serializer._json_serializer import _JsonSerializer
 from taipy.config.common.frequency import Frequency
 from taipy.config.common.frequency import Frequency
 from taipy.config.common.scope import Scope
 from taipy.config.common.scope import Scope
-from taipy.core.config import CoreSection, DataNodeConfig, JobConfig, MigrationConfig, ScenarioConfig, TaskConfig
+from taipy.core.config import CoreSection, DataNodeConfig, JobConfig, ScenarioConfig, TaskConfig
 from tests.core.utils.named_temporary_file import NamedTemporaryFile
 from tests.core.utils.named_temporary_file import NamedTemporaryFile
 
 
 
 
@@ -102,8 +102,6 @@ def config_test_scenario():
     )
     )
     test_scenario_cfg.add_sequences({"sequence1": [test_task_cfg]})
     test_scenario_cfg.add_sequences({"sequence1": [test_task_cfg]})
 
 
-    Config.add_migration_function("1.0", test_csv_dn_cfg, migrate_csv_path)
-
     return test_scenario_cfg
     return test_scenario_cfg
 
 
 
 
@@ -172,9 +170,6 @@ tasks = [ "test_task:SECTION",]
 additional_data_nodes = [ "test_pickle_dn:SECTION",]
 additional_data_nodes = [ "test_pickle_dn:SECTION",]
 frequency = "DAILY:FREQUENCY"
 frequency = "DAILY:FREQUENCY"
 
 
-[VERSION_MIGRATION.migration_fcts."1.0"]
-test_csv_dn = "tests.core.config.test_config_serialization.migrate_csv_path:function"
-
 [SCENARIO.default.comparators]
 [SCENARIO.default.comparators]
 
 
 [SCENARIO.default.sequences]
 [SCENARIO.default.sequences]
@@ -201,13 +196,11 @@ sequence1 = [ "test_task:SECTION",]
     assert actual_config_2 == expected_toml_config
     assert actual_config_2 == expected_toml_config
 
 
     assert Config.unique_sections is not None
     assert Config.unique_sections is not None
-    assert len(Config.unique_sections) == 3
+    assert len(Config.unique_sections) == 2
 
 
     assert Config.unique_sections[JobConfig.name].mode == "development"
     assert Config.unique_sections[JobConfig.name].mode == "development"
     assert Config.unique_sections[JobConfig.name].max_nb_of_workers is None
     assert Config.unique_sections[JobConfig.name].max_nb_of_workers is None
 
 
-    assert Config.unique_sections[MigrationConfig.name].migration_fcts["1.0"] == {"test_csv_dn": migrate_csv_path}
-
     assert Config.sections is not None
     assert Config.sections is not None
     assert len(Config.sections) == 3
     assert len(Config.sections) == 3
 
 
@@ -300,13 +293,6 @@ def test_read_write_json_configuration_file():
 """
 """
         + """
         + """
 },
 },
-"VERSION_MIGRATION": {
-"migration_fcts": {
-"1.0": {
-"test_csv_dn": "tests.core.config.test_config_serialization.migrate_csv_path:function"
-}
-}
-},
 "DATA_NODE": {
 "DATA_NODE": {
 "default": {
 "default": {
 "storage_type": "pickle",
 "storage_type": "pickle",
@@ -402,13 +388,11 @@ def test_read_write_json_configuration_file():
     assert actual_config_2 == expected_json_config
     assert actual_config_2 == expected_json_config
 
 
     assert Config.unique_sections is not None
     assert Config.unique_sections is not None
-    assert len(Config.unique_sections) == 3
+    assert len(Config.unique_sections) == 2
 
 
     assert Config.unique_sections[JobConfig.name].mode == "development"
     assert Config.unique_sections[JobConfig.name].mode == "development"
     assert Config.unique_sections[JobConfig.name].max_nb_of_workers is None
     assert Config.unique_sections[JobConfig.name].max_nb_of_workers is None
 
 
-    assert Config.unique_sections[MigrationConfig.name].migration_fcts["1.0"] == {"test_csv_dn": migrate_csv_path}
-
     assert Config.sections is not None
     assert Config.sections is not None
     assert len(Config.sections) == 3
     assert len(Config.sections) == 3
 
 
@@ -531,9 +515,6 @@ tasks = [ "test_task:SECTION",]
 sequences.test_sequence = [ "test_task:SECTION",]
 sequences.test_sequence = [ "test_task:SECTION",]
 frequency = "DAILY:FREQUENCY"
 frequency = "DAILY:FREQUENCY"
 
 
-[VERSION_MIGRATION.migration_fcts."1.0"]
-test_csv_dn = "tests.core.config.test_config_serialization.migrate_csv_path:function"
-
 [SCENARIO.default.comparators]
 [SCENARIO.default.comparators]
 
 
 [SCENARIO.test_scenario.comparators]
 [SCENARIO.test_scenario.comparators]
@@ -548,7 +529,7 @@ test_json_dn = [ "tests.core.config.test_config_serialization.compare_function:f
     Config.restore(tf.filename)
     Config.restore(tf.filename)
 
 
     assert Config.unique_sections is not None
     assert Config.unique_sections is not None
-    assert len(Config.unique_sections) == 3
+    assert len(Config.unique_sections) == 2
 
 
     assert Config.unique_sections[CoreSection.name].root_folder == "./taipy/"
     assert Config.unique_sections[CoreSection.name].root_folder == "./taipy/"
     assert Config.unique_sections[CoreSection.name].storage_folder == ".data/"
     assert Config.unique_sections[CoreSection.name].storage_folder == ".data/"
@@ -561,8 +542,6 @@ test_json_dn = [ "tests.core.config.test_config_serialization.compare_function:f
     assert Config.unique_sections[JobConfig.name].mode == "development"
     assert Config.unique_sections[JobConfig.name].mode == "development"
     assert Config.unique_sections[JobConfig.name].max_nb_of_workers == 1
     assert Config.unique_sections[JobConfig.name].max_nb_of_workers == 1
 
 
-    assert Config.unique_sections[MigrationConfig.name].migration_fcts["1.0"] == {"test_csv_dn": migrate_csv_path}
-
     assert Config.sections is not None
     assert Config.sections is not None
     assert len(Config.sections) == 3
     assert len(Config.sections) == 3
 
 
@@ -643,13 +622,6 @@ def test_read_write_json_configuration_file_migrate_sequence_in_scenario():
 "version_number": "",
 "version_number": "",
 "force": "False:bool"
 "force": "False:bool"
 },
 },
-"VERSION_MIGRATION": {
-"migration_fcts": {
-"1.0": {
-"test_csv_dn": "tests.core.config.test_config_serialization.migrate_csv_path:function"
-}
-}
-},
 "DATA_NODE": {
 "DATA_NODE": {
 "default": {
 "default": {
 "storage_type": "pickle",
 "storage_type": "pickle",
@@ -724,7 +696,7 @@ def test_read_write_json_configuration_file_migrate_sequence_in_scenario():
     Config.restore(tf.filename)
     Config.restore(tf.filename)
 
 
     assert Config.unique_sections is not None
     assert Config.unique_sections is not None
-    assert len(Config.unique_sections) == 3
+    assert len(Config.unique_sections) == 2
 
 
     assert Config.unique_sections[CoreSection.name].root_folder == "./taipy/"
     assert Config.unique_sections[CoreSection.name].root_folder == "./taipy/"
     assert Config.unique_sections[CoreSection.name].storage_folder == ".data/"
     assert Config.unique_sections[CoreSection.name].storage_folder == ".data/"
@@ -737,8 +709,6 @@ def test_read_write_json_configuration_file_migrate_sequence_in_scenario():
     assert Config.unique_sections[JobConfig.name].mode == "development"
     assert Config.unique_sections[JobConfig.name].mode == "development"
     assert Config.unique_sections[JobConfig.name].max_nb_of_workers == 1
     assert Config.unique_sections[JobConfig.name].max_nb_of_workers == 1
 
 
-    assert Config.unique_sections[MigrationConfig.name].migration_fcts["1.0"] == {"test_csv_dn": migrate_csv_path}
-
     assert Config.sections is not None
     assert Config.sections is not None
     assert len(Config.sections) == 3
     assert len(Config.sections) == 3
 
 

+ 2 - 2
tests/core/config/test_core_section.py

@@ -45,7 +45,7 @@ def test_core_section():
 [TAIPY]
 [TAIPY]
 
 
 [CORE]
 [CORE]
-mode = "production"
+mode = "experiment"
 version_number = "test_num_2"
 version_number = "test_num_2"
 force = "true:bool"
 force = "true:bool"
         """
         """
@@ -54,7 +54,7 @@ force = "true:bool"
     with patch("sys.argv", ["prog"]):
     with patch("sys.argv", ["prog"]):
         core = Core()
         core = Core()
         core.run()
         core.run()
-    assert Config.core.mode == "production"
+    assert Config.core.mode == "experiment"
     assert Config.core.version_number == "test_num_2"
     assert Config.core.version_number == "test_num_2"
     assert Config.core.force
     assert Config.core.force
     core.stop()
     core.stop()

+ 0 - 5
tests/core/config/test_core_version.py

@@ -81,8 +81,6 @@ class TestCoreVersionInCoreSectionConfig:
             version_number = ""
             version_number = ""
             force = "False:bool"
             force = "False:bool"
             core_version = "{core_version}"
             core_version = "{core_version}"
-
-            [VERSION_MIGRATION.migration_fcts]
             """
             """
         )
         )
         if is_compatible:
         if is_compatible:
@@ -111,8 +109,6 @@ class TestCoreVersionInCoreSectionConfig:
             version_number = ""
             version_number = ""
             force = "False:bool"
             force = "False:bool"
             core_version = "{core_version}"
             core_version = "{core_version}"
-
-            [VERSION_MIGRATION.migration_fcts]
             """
             """
         )
         )
         if is_compatible:
         if is_compatible:
@@ -137,7 +133,6 @@ class TestCoreVersionInCoreSectionConfig:
             mode = "development"
             mode = "development"
             version_number = ""
             version_number = ""
             force = "False:bool"
             force = "False:bool"
-            [VERSION_MIGRATION.migration_fcts]
             """
             """
         )
         )
         Config.load(file_config.filename)
         Config.load(file_config.filename)

+ 1 - 12
tests/core/config/test_default_config.py

@@ -15,7 +15,6 @@ from taipy.config.global_app.global_app_config import GlobalAppConfig
 from taipy.core.config import CoreSection
 from taipy.core.config import CoreSection
 from taipy.core.config.data_node_config import DataNodeConfig
 from taipy.core.config.data_node_config import DataNodeConfig
 from taipy.core.config.job_config import JobConfig
 from taipy.core.config.job_config import JobConfig
-from taipy.core.config.migration_config import MigrationConfig
 from taipy.core.config.scenario_config import ScenarioConfig
 from taipy.core.config.scenario_config import ScenarioConfig
 from taipy.core.config.task_config import TaskConfig
 from taipy.core.config.task_config import TaskConfig
 
 
@@ -70,12 +69,6 @@ def _test_default_scenario_config(scenario_config: ScenarioConfig):
     assert len(scenario_config.properties) == 0  # type: ignore
     assert len(scenario_config.properties) == 0  # type: ignore
 
 
 
 
-def _test_default_version_migration_config(version_migration_config: MigrationConfig):
-    assert version_migration_config is not None
-    assert version_migration_config.migration_fcts == {}
-    assert len(version_migration_config.properties) == 0  # type: ignore
-
-
 def _test_default_global_app_config(global_config: GlobalAppConfig):
 def _test_default_global_app_config(global_config: GlobalAppConfig):
     assert global_config is not None
     assert global_config is not None
     assert not global_config.notification
     assert not global_config.notification
@@ -90,17 +83,13 @@ def test_default_configuration():
     _test_default_global_app_config(GlobalAppConfig().default_config())
     _test_default_global_app_config(GlobalAppConfig().default_config())
 
 
     assert default_config._unique_sections is not None
     assert default_config._unique_sections is not None
-    assert len(default_config._unique_sections) == 3
+    assert len(default_config._unique_sections) == 2
     assert len(default_config._sections) == 3
     assert len(default_config._sections) == 3
 
 
     _test_default_job_config(default_config._unique_sections[JobConfig.name])
     _test_default_job_config(default_config._unique_sections[JobConfig.name])
     _test_default_job_config(Config.job_config)
     _test_default_job_config(Config.job_config)
     _test_default_job_config(JobConfig().default_config())
     _test_default_job_config(JobConfig().default_config())
 
 
-    _test_default_version_migration_config(default_config._unique_sections[MigrationConfig.name])
-    _test_default_version_migration_config(Config.migration_functions)
-    _test_default_version_migration_config(MigrationConfig.default_config())
-
     _test_default_core_section(default_config._unique_sections[CoreSection.name])
     _test_default_core_section(default_config._unique_sections[CoreSection.name])
     _test_default_core_section(Config.core)
     _test_default_core_section(Config.core)
     _test_default_core_section(CoreSection().default_config())
     _test_default_core_section(CoreSection().default_config())

+ 0 - 2
tests/core/config/test_file_config.py

@@ -40,8 +40,6 @@ version_number = ""
 force = "False:bool"
 force = "False:bool"
 core_version = "{CoreSection._CURRENT_CORE_VERSION}"
 core_version = "{CoreSection._CURRENT_CORE_VERSION}"
 
 
-[VERSION_MIGRATION.migration_fcts]
-
 [DATA_NODE.default]
 [DATA_NODE.default]
 storage_type = "in_memory"
 storage_type = "in_memory"
 scope = "SCENARIO:SCOPE"
 scope = "SCENARIO:SCOPE"

+ 0 - 65
tests/core/config/test_migration_config.py

@@ -1,65 +0,0 @@
-# Copyright 2021-2024 Avaiga Private Limited
-#
-# 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.
-
-from taipy.config.config import Config
-
-
-def migrate_pickle_path(dn):
-    dn.path = "s1.pkl"
-
-
-def migrate_skippable(task):
-    task.skippable = True
-
-
-def test_migration_config():
-    assert Config.migration_functions.migration_fcts == {}
-
-    data_nodes1 = Config.configure_data_node("data_nodes1", "pickle")
-
-    migration_cfg = Config.add_migration_function(
-        target_version="1.0",
-        config=data_nodes1,
-        migration_fct=migrate_pickle_path,
-    )
-
-    assert migration_cfg.migration_fcts == {"1.0": {"data_nodes1": migrate_pickle_path}}
-    assert migration_cfg.properties == {}
-
-    data_nodes2 = Config.configure_data_node("data_nodes2", "pickle")
-
-    migration_cfg = Config.add_migration_function(
-        target_version="1.0",
-        config=data_nodes2,
-        migration_fct=migrate_pickle_path,
-    )
-    assert migration_cfg.migration_fcts == {
-        "1.0": {"data_nodes1": migrate_pickle_path, "data_nodes2": migrate_pickle_path}
-    }
-
-
-def test_clean_config():
-    assert Config.migration_functions.migration_fcts == {}
-
-    data_nodes1 = Config.configure_data_node("data_nodes1", "pickle")
-    migration_cfg = Config.add_migration_function(
-        target_version="1.0",
-        config=data_nodes1,
-        migration_fct=migrate_pickle_path,
-    )
-
-    assert migration_cfg.migration_fcts == {"1.0": {"data_nodes1": migrate_pickle_path}}
-    assert migration_cfg.properties == {}
-
-    migration_cfg._clean()
-
-    assert migration_cfg.migration_fcts == {}
-    assert migration_cfg._properties == {}

+ 0 - 1
tests/core/conftest.py

@@ -350,7 +350,6 @@ def init_config(reset_configuration_singleton, inject_core_sections):
         _Checker.add_checker(_CoreSectionChecker)
         _Checker.add_checker(_CoreSectionChecker)
         _Checker.add_checker(_DataNodeConfigChecker)
         _Checker.add_checker(_DataNodeConfigChecker)
         _Checker.add_checker(_JobConfigChecker)
         _Checker.add_checker(_JobConfigChecker)
-        # We don't need to add _MigrationConfigChecker because it is run only when the Core service is run.
         _Checker.add_checker(_TaskConfigChecker)
         _Checker.add_checker(_TaskConfigChecker)
         _Checker.add_checker(_ScenarioConfigChecker)
         _Checker.add_checker(_ScenarioConfigChecker)
 
 

+ 0 - 136
tests/core/test_core_cli.py

@@ -88,16 +88,6 @@ def test_core_cli_experiment_mode_with_force_version(init_config):
         core.stop()
         core.stop()
 
 
 
 
-def test_core_cli_production_mode():
-    with patch("sys.argv", ["prog", "--production"]):
-        core = Core()
-        core.run()
-        assert Config.core.mode == "production"
-        assert Config.core.version_number == _VersionManagerFactory._build_manager()._get_latest_version()
-        assert not Config.core.force
-        core.stop()
-
-
 def test_dev_mode_clean_all_entities_of_the_latest_version():
 def test_dev_mode_clean_all_entities_of_the_latest_version():
     scenario_config = config_scenario()
     scenario_config = config_scenario()
 
 
@@ -268,28 +258,6 @@ def test_version_number_when_switching_mode():
         assert len(_VersionManager._get_all()) == 4
         assert len(_VersionManager._get_all()) == 4
         core.stop()
         core.stop()
 
 
-    # When run with production mode, the latest version is used as production
-    with patch("sys.argv", ["prog", "--production"]):
-        core = Core()
-        core.run()
-        ver_6 = _VersionManager._get_latest_version()
-        production_versions = _VersionManager._get_production_versions()
-        assert ver_6 == ver_5
-        assert production_versions == [ver_6]
-        assert len(_VersionManager._get_all()) == 4
-        core.stop()
-
-    # When run with production mode, the "2.1" version is used as production
-    with patch("sys.argv", ["prog", "--production", "2.1"]):
-        core = Core()
-        core.run()
-        ver_7 = _VersionManager._get_latest_version()
-        production_versions = _VersionManager._get_production_versions()
-        assert ver_7 == "2.1"
-        assert production_versions == [ver_6, ver_7]
-        assert len(_VersionManager._get_all()) == 4
-        core.stop()
-
     # Run with dev mode, the version number is the same as the first dev version to override it
     # Run with dev mode, the version number is the same as the first dev version to override it
     with patch("sys.argv", ["prog", "--development"]):
     with patch("sys.argv", ["prog", "--development"]):
         core = Core()
         core = Core()
@@ -300,56 +268,6 @@ def test_version_number_when_switching_mode():
         core.stop()
         core.stop()
 
 
 
 
-def test_production_mode_load_all_entities_from_previous_production_version():
-    scenario_config = config_scenario()
-
-    with patch("sys.argv", ["prog", "--development"]):
-        core = Core()
-        core.run()
-        scenario = _ScenarioManager._create(scenario_config)
-        taipy.submit(scenario)
-        core.stop()
-
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        core = Core()
-        core.run()
-        production_ver_1 = _VersionManager._get_latest_version()
-        assert _VersionManager._get_production_versions() == [production_ver_1]
-        # When run production mode on a new app, a dev version is created alongside
-        assert _VersionManager._get_development_version() not in _VersionManager._get_production_versions()
-        assert len(_VersionManager._get_all()) == 2
-
-        scenario = _ScenarioManager._create(scenario_config)
-        taipy.submit(scenario)
-
-        assert len(_DataManager._get_all()) == 2
-        assert len(_TaskManager._get_all()) == 1
-        assert len(_SequenceManager._get_all()) == 1
-        assert len(_ScenarioManager._get_all()) == 1
-        assert len(_CycleManager._get_all()) == 1
-        assert len(_JobManager._get_all()) == 1
-        core.stop()
-
-    with patch("sys.argv", ["prog", "--production", "2.0"]):
-        core = Core()
-        core.run()
-        production_ver_2 = _VersionManager._get_latest_version()
-        assert _VersionManager._get_production_versions() == [production_ver_1, production_ver_2]
-        assert len(_VersionManager._get_all()) == 3
-
-        # All entities from previous production version should be saved
-        scenario = _ScenarioManager._create(scenario_config)
-        taipy.submit(scenario)
-
-        assert len(_DataManager._get_all()) == 4
-        assert len(_TaskManager._get_all()) == 2
-        assert len(_SequenceManager._get_all()) == 2
-        assert len(_ScenarioManager._get_all()) == 2
-        assert len(_CycleManager._get_all()) == 1
-        assert len(_JobManager._get_all()) == 2
-        core.stop()
-
-
 def test_force_override_experiment_version():
 def test_force_override_experiment_version():
     scenario_config = config_scenario()
     scenario_config = config_scenario()
 
 
@@ -402,60 +320,6 @@ def test_force_override_experiment_version():
         core.stop()
         core.stop()
 
 
 
 
-def test_force_override_production_version():
-    scenario_config = config_scenario()
-
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        core = Core()
-        core.run()
-        ver_1 = _VersionManager._get_latest_version()
-        production_versions = _VersionManager._get_production_versions()
-        assert ver_1 == "1.0"
-        assert production_versions == ["1.0"]
-        # When create new production version, a development version entity is also created as a placeholder
-        assert len(_VersionManager._get_all()) == 2  # 2 version include 1 production 1 development
-
-        scenario = _ScenarioManager._create(scenario_config)
-        taipy.submit(scenario)
-
-        assert len(_DataManager._get_all()) == 2
-        assert len(_TaskManager._get_all()) == 1
-        assert len(_SequenceManager._get_all()) == 1
-        assert len(_ScenarioManager._get_all()) == 1
-        assert len(_CycleManager._get_all()) == 1
-        assert len(_JobManager._get_all()) == 1
-        core.stop()
-
-    Config.configure_global_app(foo="bar")
-
-    # Without --taipy-force parameter, a SystemExit will be raised
-    with pytest.raises(SystemExit):
-        with patch("sys.argv", ["prog", "--production", "1.0"]):
-            core = Core()
-            core.run()
-    core.stop()
-
-    # With --taipy-force parameter
-    with patch("sys.argv", ["prog", "--production", "1.0", "--taipy-force"]):
-        core = Core()
-        core.run()
-        ver_2 = _VersionManager._get_latest_version()
-        assert ver_2 == "1.0"
-        assert len(_VersionManager._get_all()) == 2  # 2 version include 1 production 1 development
-
-        # All entities from previous submit should be saved
-        scenario = _ScenarioManager._create(scenario_config)
-        taipy.submit(scenario)
-
-        assert len(_DataManager._get_all()) == 4
-        assert len(_TaskManager._get_all()) == 2
-        assert len(_SequenceManager._get_all()) == 2
-        assert len(_ScenarioManager._get_all()) == 2
-        assert len(_CycleManager._get_all()) == 1
-        assert len(_JobManager._get_all()) == 2
-        core.stop()
-
-
 def test_modified_job_configuration_dont_block_application_run(caplog, init_config):
 def test_modified_job_configuration_dont_block_application_run(caplog, init_config):
     _ = config_scenario()
     _ = config_scenario()
 
 

+ 0 - 280
tests/core/version/test_production_version_migration.py

@@ -1,280 +0,0 @@
-# Copyright 2021-2024 Avaiga Private Limited
-#
-# 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.
-
-from unittest.mock import patch
-
-import pytest
-
-from taipy.config.config import Config
-from taipy.core import Core, taipy
-from taipy.core.data._data_manager import _DataManager
-from taipy.core.scenario._scenario_manager import _ScenarioManager
-from tests.core.utils import assert_true_after_time
-
-
-def twice(a):
-    return a * 2
-
-
-def triple(a):
-    return a * 3
-
-
-def migrate_pickle_path(dn):
-    dn.path = "bar.pkl"
-    return dn
-
-
-def migrate_skippable_task(task):
-    task.skippable = True
-    return task
-
-
-def migrate_foo_scenario(scenario):
-    scenario.properties["foo"] = "bar"
-    return scenario
-
-
-def test_migrate_datanode(init_config):
-    scenario_v1 = submit_v1()
-
-    init_config()
-    Config.add_migration_function("2.0", "d1", migrate_pickle_path)
-
-    submit_v2()
-    v1 = taipy.get(scenario_v1.id)
-    assert v1.d1.version == "2.0"
-    assert v1.d1.path == "bar.pkl"
-
-
-@pytest.mark.standalone
-def test_migrate_datanode_in_standalone_mode(init_config):
-    scenario_v1 = submit_v1()
-
-    init_config()
-    Config.configure_job_executions(mode="standalone", max_nb_of_workers=2)
-    Config.add_migration_function("2.0", "d1", migrate_pickle_path)
-
-    scenario_cfg_v2 = config_scenario_v2()
-    with patch("sys.argv", ["prog", "--production", "2.0"]):
-        core = Core()
-        core.run()
-        scenario_v2 = _ScenarioManager._create(scenario_cfg_v2)
-        jobs = _ScenarioManager._submit(scenario_v2).jobs
-        v1 = taipy.get(scenario_v1.id)
-        assert v1.d1.version == "2.0"
-        assert v1.d1.path == "bar.pkl"
-        assert_true_after_time(jobs[0].is_completed)
-        core.stop()
-
-
-def test_migrate_task(init_config):
-    scenario_v1 = submit_v1()
-
-    init_config()
-    Config.add_migration_function("2.0", "my_task", migrate_skippable_task)
-
-    submit_v2()
-    v1 = taipy.get(scenario_v1.id)
-    assert v1.my_task.version == "2.0"
-    assert v1.my_task.skippable is True
-
-
-@pytest.mark.standalone
-def test_migrate_task_in_standalone_mode(init_config):
-    scenario_v1 = submit_v1()
-
-    init_config()
-    Config.configure_job_executions(mode="standalone", max_nb_of_workers=2)
-    Config.add_migration_function("2.0", "my_task", migrate_skippable_task)
-
-    scenario_cfg_v2 = config_scenario_v2()
-    with patch("sys.argv", ["prog", "--production", "2.0"]):
-        core = Core()
-        core.run()
-        scenario_v2 = _ScenarioManager._create(scenario_cfg_v2)
-        jobs = _ScenarioManager._submit(scenario_v2).jobs
-        v1 = taipy.get(scenario_v1.id)
-        assert v1.my_task.version == "2.0"
-        assert v1.my_task.skippable is True
-        assert_true_after_time(jobs[0].is_completed)
-        core.stop()
-
-
-def test_migrate_scenario(init_config):
-    scenario_v1 = submit_v1()
-
-    init_config()
-    Config.add_migration_function("2.0", "my_scenario", migrate_foo_scenario)
-
-    submit_v2()
-    v1 = taipy.get(scenario_v1.id)
-    assert v1.version == "2.0"
-    assert v1.properties["foo"] == "bar"
-
-
-@pytest.mark.standalone
-def test_migrate_scenario_in_standalone_mode(init_config):
-    scenario_v1 = submit_v1()
-
-    init_config()
-    Config.configure_job_executions(mode="standalone", max_nb_of_workers=2)
-    Config.add_migration_function("2.0", "my_scenario", migrate_foo_scenario)
-
-    scenario_cfg_v2 = config_scenario_v2()
-    with patch("sys.argv", ["prog", "--production", "2.0"]):
-        core = Core()
-        core.run()
-        scenario_v2 = _ScenarioManager._create(scenario_cfg_v2)
-        jobs = _ScenarioManager._submit(scenario_v2).jobs
-        v1 = taipy.get(scenario_v1.id)
-        assert v1.version == "2.0"
-        assert v1.properties["foo"] == "bar"
-        assert_true_after_time(jobs[0].is_completed)
-        core.stop()
-
-
-def test_migrate_all_entities(init_config):
-    scenario_v1 = submit_v1()
-
-    init_config()
-    Config.add_migration_function("2.0", "d1", migrate_pickle_path)
-    Config.add_migration_function("2.0", "my_task", migrate_skippable_task)
-    Config.add_migration_function("2.0", "my_scenario", migrate_foo_scenario)
-
-    submit_v2()
-    v1 = taipy.get(scenario_v1.id)
-
-    assert v1.d1.version == "2.0"
-    assert v1.my_task.version == "2.0"
-
-    assert v1.d1.path == "bar.pkl"
-    assert v1.my_task.skippable is True
-    assert v1.properties["foo"] == "bar"
-
-
-@pytest.mark.standalone
-def test_migrate_all_entities_in_standalone_mode(init_config):
-    scenario_v1 = submit_v1()
-
-    init_config()
-    Config.configure_job_executions(mode="standalone", max_nb_of_workers=2)
-    Config.add_migration_function("2.0", "my_scenario", migrate_foo_scenario)
-
-    scenario_cfg_v2 = config_scenario_v2()
-    with patch("sys.argv", ["prog", "--production", "2.0"]):
-        core = Core()
-        core.run()
-        scenario_v2 = _ScenarioManager._create(scenario_cfg_v2)
-        jobs = _ScenarioManager._submit(scenario_v2).jobs
-        v1 = taipy.get(scenario_v1.id)
-        assert v1.version == "2.0"
-        assert v1.properties["foo"] == "bar"
-        assert_true_after_time(jobs[0].is_completed)
-        core.stop()
-
-
-def test_migrate_compatible_version(init_config):
-    scenario_cfg = config_scenario_v1()
-    # Production 1.0
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        core = Core()
-        core.run()
-
-        scenario_v1 = _ScenarioManager._create(scenario_cfg)
-        _ScenarioManager._submit(scenario_v1)
-
-        assert scenario_v1.d2.read() == 2
-        assert len(_DataManager._get_all(version_number="all")) == 2
-        core.stop()
-
-    init_config()
-    scenario_cfg = config_scenario_v1()
-
-    # Production 2.0 is a compatible version
-    with patch("sys.argv", ["prog", "--production", "2.0"]):
-        core = Core()
-        core.run()
-
-        scenario_v2 = _ScenarioManager._create(scenario_cfg)
-        _ScenarioManager._submit(scenario_v2)
-
-        assert scenario_v2.d2.read() == 2
-        assert len(_DataManager._get_all(version_number="all")) == 4
-        core.stop()
-
-    init_config()
-
-    # Production 2.1
-    Config.add_migration_function(
-        target_version="2.1",
-        config="d1",
-        migration_fct=migrate_pickle_path,
-    )
-    scenario_cfg_v2_1 = config_scenario_v2()
-
-    with patch("sys.argv", ["prog", "--production", "2.1"]):
-        core = Core()
-        core.run()
-        scenario_v2_1 = _ScenarioManager._create(scenario_cfg_v2_1)
-        _ScenarioManager._submit(scenario_v2_1)
-        core.stop()
-
-    assert scenario_v2_1.d2.read() == 6
-    assert len(_DataManager._get_all(version_number="all")) == 6
-
-    v1 = taipy.get(scenario_v1.id)
-    assert v1.d1.version == "2.1"
-    assert v1.d1.path == "bar.pkl"
-
-    v2 = taipy.get(scenario_v2.id)
-    assert v2.d1.version == "2.1"
-    assert v2.d1.path == "bar.pkl"
-
-
-def submit_v1():
-    scenario_cfg_v1 = config_scenario_v1()
-    with patch("sys.argv", ["prog", "--production", "1.0"]):
-        core = Core()
-        core.run()
-        scenario_v1 = _ScenarioManager._create(scenario_cfg_v1)
-        _ScenarioManager._submit(scenario_v1)
-        core.stop()
-    return scenario_v1
-
-
-def submit_v2():
-    scenario_cfg_v2 = config_scenario_v2()
-    with patch("sys.argv", ["prog", "--production", "2.0"]):
-        core = Core()
-        core.run()
-        scenario_v2 = _ScenarioManager._create(scenario_cfg_v2)
-        _ScenarioManager._submit(scenario_v2)
-        core.stop()
-    return scenario_v2
-
-
-def config_scenario_v1():
-    dn1 = Config.configure_pickle_data_node(id="d1", default_data=1)
-    dn2 = Config.configure_pickle_data_node(id="d2")
-    task_cfg = Config.configure_task("my_task", twice, dn1, dn2)
-    scenario_cfg = Config.configure_scenario("my_scenario", [task_cfg])
-    scenario_cfg.add_sequences({"my_sequence": [task_cfg]})
-    return scenario_cfg
-
-
-def config_scenario_v2():
-    dn1 = Config.configure_pickle_data_node(id="d1", default_data=2)
-    dn2 = Config.configure_pickle_data_node(id="d2")
-    task_cfg = Config.configure_task("my_task", triple, dn1, dn2)
-    scenario_cfg = Config.configure_scenario("my_scenario", [task_cfg])
-    scenario_cfg.add_sequences({"my_scenario": [task_cfg]})
-    return scenario_cfg