from typing import Any, Dict, NewType    DataNodeId = NewType("DataNodeId", str)  DataNodeId.__doc__ = """Type that holds a `DataNode^` identifier."""  Edit = NewType("Edit", Dict[str, Any])  Edit.__doc__ = """Type that holds a `DataNode^` edit information."""


#  # 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 .._repository._filesystem_repository import _FileSystemRepository  from ._submission_converter import _SubmissionConverter  from ._submission_model import _SubmissionModel      class _SubmissionFSRepository(_FileSystemRepository):      def __init__(self):          super().__init__(model_type=_SubmissionModel, converter=_SubmissionConverter, dir_name="submission")


from typing import NewType    SubmissionId = NewType("SubmissionId", str)  SubmissionId.__doc__ = """Type that holds a `Submission^` identifier."""


from ..common._repr_enum import _ReprEnum      class SubmissionStatus(_ReprEnum):      """Execution status of a `Submission^`.        It is implemented as an enumeration.        The possible values are:        - `SUBMITTED`: A `SUBMITTED` submission has been submitted for execution but not processed yet by          the orchestrator.        - `UNDEFINED`: AN `UNDEFINED` submission's jobs have been submitted for execution but got some undefined          status changes.        - `PENDING`: A `PENDING` submission has been enqueued by the orchestrator. It is waiting for an executor          to be available for its execution.        - `BLOCKED`: A `BLOCKED` submission has been blocked because it has been finished with a job being blocked.        - `RUNNING`: A `RUNNING` submission has its jobs currently being executed.        - `CANCELED`: A `CANCELED` submission has been submitted but its execution has been canceled.        - `FAILED`: A `FAILED` submission has a job failed during its execution.        - `COMPLETED`: A `COMPLETED` submission has successfully been executed.      """        SUBMITTED = 0      UNDEFINED = 1      BLOCKED = 2      PENDING = 3      RUNNING = 4      CANCELED = 5      FAILED = 6      COMPLETED = 7


from dataclasses import dataclass  from typing import Any, Dict, List, Union    from sqlalchemy import JSON, Column, Enum, String, Table    from .._repository._base_taipy_model import _BaseModel  from .._repository.db._sql_base_model import mapper_registry  from ..job.job_id import JobId  from .submission_status import SubmissionStatus      @mapper_registry.mapped  @dataclass  class _SubmissionModel(_BaseModel):      __table__ = Table(          "submission",          mapper_registry.metadata,          Column("id", String, primary_key=True),          Column("entity_id", String),          Column("entity_type", String),          Column("job_ids", JSON),          Column("creation_date", String),          Column("submission_status", Enum(SubmissionStatus)),          Column("version", String),      )      id: str      entity_id: str      entity_type: str      job_ids: Union[List[JobId], List]      creation_date: str      submission_status: SubmissionStatus      version: str        @staticmethod      def from_dict(data: Dict[str, Any]):          return _SubmissionModel(              id=data["id"],              entity_id=data["entity_id"],              entity_type=data["entity_type"],              job_ids=_BaseModel._deserialize_attribute(data["job_ids"]),              creation_date=data["creation_date"],              submission_status=SubmissionStatus._from_repr(data["submission_status"]),              version=data["version"],          )        def to_list(self):          return [              self.id,              self.entity_id,              self.entity_type,              _BaseModel._serialize_attribute(self.job_ids),              self.creation_date,              repr(self.submission_status),              self.version,          ]


from datetime import datetime    from .._repository._abstract_converter import _AbstractConverter  from ..job.job import Job, JobId  from ..submission._submission_model import _SubmissionModel  from ..submission.submission import Submission  from .submission import SubmissionId      class _SubmissionConverter(_AbstractConverter):      @classmethod      def _entity_to_model(cls, submission: Submission) -> _SubmissionModel:          return _SubmissionModel(              id=submission.id,              entity_id=submission._entity_id,              entity_type=submission.entity_type,              job_ids=[job.id if isinstance(job, Job) else JobId(str(job)) for job in list(submission._jobs)],              creation_date=submission._creation_date.isoformat(),              submission_status=submission._submission_status,              version=submission._version,          )        @classmethod      def _model_to_entity(cls, model: _SubmissionModel) -> Submission:          submission = Submission(              entity_id=model.entity_id,              entity_type=model.entity_type,              id=SubmissionId(model.id),              jobs=model.job_ids,              creation_date=datetime.fromisoformat(model.creation_date),              submission_status=model.submission_status,              version=model.version,          )          return submission


from typing import List, Optional, Union    from .._manager._manager import _Manager  from .._repository._abstract_repository import _AbstractRepository  from .._version._version_mixin import _VersionMixin  from ..notification import EventEntityType, EventOperation, Notifier, _make_event  from ..scenario.scenario import Scenario  from ..sequence.sequence import Sequence  from ..submission.submission import Submission  from ..task.task import Task      class _SubmissionManager(_Manager[Submission], _VersionMixin):      _ENTITY_NAME = Submission.__name__      _repository: _AbstractRepository      _EVENT_ENTITY_TYPE = EventEntityType.SUBMISSION        @classmethod      def _get_all(cls, version_number: Optional[str] = None) -> List[Submission]:          """          Returns all entities.          """          filters = cls._build_filters_with_version(version_number)          return cls._repository._load_all(filters)        @classmethod      def _create(cls, entity_id: str, entity_type: str) -> Submission:          submission = Submission(entity_id=entity_id, entity_type=entity_type)          cls._set(submission)            Notifier.publish(_make_event(submission, EventOperation.CREATION))            return submission        @classmethod      def _get_latest(cls, entity: Union[Scenario, Sequence, Task]) -> Optional[Submission]:          entity_id = entity.id if not isinstance(entity, str) else entity          submissions_of_task = list(filter(lambda submission: submission.entity_id == entity_id, cls._get_all()))          if len(submissions_of_task) == 0:              return None          if len(submissions_of_task) == 1:              return submissions_of_task[0]          else:              return max(submissions_of_task)


import threading  import uuid  from collections.abc import MutableSet  from datetime import datetime  from typing import Any, List, Optional, Union    from .._entity._entity import _Entity  from .._entity._labeled import _Labeled  from .._entity._reload import _self_reload, _self_setter  from .._version._version_manager_factory import _VersionManagerFactory  from ..job._job_manager_factory import _JobManagerFactory  from ..job.job import Job, JobId, Status  from ..notification.event import Event, EventEntityType, EventOperation, _make_event  from .submission_id import SubmissionId  from .submission_status import SubmissionStatus      class Submission(_Entity, _Labeled):      """Hold the jobs and submission status when a Scenario^, Sequence^ or Task^ is submitted.        Attributes:          entity_id (str): The identifier of the entity that was submitted.          id (str): The identifier of the `Submission^` entity.          jobs (Optional[Union[List[Job], List[JobId]]]): A list of jobs.          creation_date (Optional[datetime]): The date of this submission's creation.          submission_status (Optional[SubmissionStatus]): The current status of this submission.          version (Optional[str]): The string indicates the application version of the submission to instantiate.              If not provided, the latest version is used.      """        _ID_PREFIX = "SUBMISSION"      _MANAGER_NAME = "submission"      __SEPARATOR = "_"      lock = threading.Lock()        def __init__(          self,          entity_id: str,          entity_type: str,          id: Optional[str] = None,          jobs: Optional[Union[List[Job], List[JobId]]] = None,          creation_date: Optional[datetime] = None,          submission_status: Optional[SubmissionStatus] = None,          version: Optional[str] = None,      ):          self._entity_id = entity_id          self._entity_type = entity_type          self.id = id or self.__new_id()          self._jobs: Union[List[Job], List[JobId], List] = jobs or []          self._creation_date = creation_date or datetime.now()          self._submission_status = submission_status or SubmissionStatus.SUBMITTED          self._version = version or _VersionManagerFactory._build_manager()._get_latest_version()            self.__abandoned = False          self.__completed = False            self.__is_canceled = False          self.__running_jobs: MutableSet[str] = set()          self.__blocked_jobs: MutableSet[str] = set()          self.__pending_jobs: MutableSet[str] = set()        @staticmethod      def __new_id() -> str:          """Generate a unique Submission identifier."""          return SubmissionId(Submission.__SEPARATOR.join([Submission._ID_PREFIX, str(uuid.uuid4())]))        @property      def entity_id(self) -> str:          return self._entity_id        @property      def entity_type(self) -> str:          return self._entity_type        @property      def creation_date(self):          return self._creation_date        def get_label(self) -> str:          """Returns the submission simple label prefixed by its owner label.            Returns:              The label of the submission as a string.          """          return self._get_label()        def get_simple_label(self) -> str:          """Returns the submission simple label.            Returns:              The simple label of the submission as a string.          """          return self._get_simple_label()        @property  # type: ignore      @_self_reload(_MANAGER_NAME)      def jobs(self) -> List[Job]:          jobs = []          job_manager = _JobManagerFactory._build_manager()            for job in self._jobs:              jobs.append(job_manager._get(job))            return jobs        @jobs.setter  # type: ignore      @_self_setter(_MANAGER_NAME)      def jobs(self, jobs: Union[List[Job], List[JobId]]):          self._jobs = jobs        def __hash__(self):          return hash(self.id)        def __eq__(self, other):          return self.id == other.id        @property  # type: ignore      @_self_reload(_MANAGER_NAME)      def submission_status(self):          return self._submission_status        @submission_status.setter  # type: ignore      @_self_setter(_MANAGER_NAME)      def submission_status(self, submission_status):          self._submission_status = submission_status        def __lt__(self, other):          return self.creation_date.timestamp() < other.creation_date.timestamp()        def __le__(self, other):          return self.creation_date.timestamp() <= other.creation_date.timestamp()        def __gt__(self, other):          return self.creation_date.timestamp() > other.creation_date.timestamp()        def __ge__(self, other):          return self.creation_date.timestamp() >= other.creation_date.timestamp()        def _update_submission_status(self, job: Job):          if self._submission_status == SubmissionStatus.FAILED:              return            job_status = job.status            if job_status == Status.FAILED:              self.submission_status = SubmissionStatus.FAILED  # type: ignore              return            with self.lock:              if job_status == Status.CANCELED:                  self.__is_canceled = True              elif job_status == Status.BLOCKED:                  self.__blocked_jobs.add(job.id)                  self.__pending_jobs.discard(job.id)              elif job_status == Status.PENDING or job_status == Status.SUBMITTED:                  self.__pending_jobs.add(job.id)                  self.__blocked_jobs.discard(job.id)              elif job_status == Status.RUNNING:                  self.__running_jobs.add(job.id)                  self.__pending_jobs.discard(job.id)              elif job_status == Status.COMPLETED or job_status == Status.SKIPPED:                  self.__completed = True                  self.__blocked_jobs.discard(job.id)                  self.__pending_jobs.discard(job.id)                  self.__running_jobs.discard(job.id)              elif job_status == Status.ABANDONED:                  self.__abandoned = True                  self.__running_jobs.discard(job.id)                  self.__blocked_jobs.discard(job.id)                  self.__pending_jobs.discard(job.id)            if self.__is_canceled:              self.submission_status = SubmissionStatus.CANCELED  # type: ignore          elif self.__abandoned:              self.submission_status = SubmissionStatus.UNDEFINED  # type: ignore          elif self.__running_jobs:              self.submission_status = SubmissionStatus.RUNNING  # type: ignore          elif self.__pending_jobs:              self.submission_status = SubmissionStatus.PENDING  # type: ignore          elif self.__blocked_jobs:              self.submission_status = SubmissionStatus.BLOCKED  # type: ignore          elif self.__completed:              self.submission_status = SubmissionStatus.COMPLETED  # type: ignore          else:              self.submission_status = SubmissionStatus.UNDEFINED  # type: ignore      @_make_event.register(Submission)  def _make_event_for_submission(      submission: Submission,      operation: EventOperation,      /,      attribute_name: Optional[str] = None,      attribute_value: Optional[Any] = None,      **kwargs,  ) -> Event:      metadata = {"creation_date": submission.creation_date, "version": submission._version, **kwargs}      return Event(          entity_type=EventEntityType.SUBMISSION,          entity_id=submission.id,          operation=operation,          attribute_name=attribute_name,          attribute_value=attribute_value,          metadata=metadata,      )


#  # 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 Type    from .._manager._manager_factory import _ManagerFactory  from ..common._utils import _load_fct  from ._submission_fs_repository import _SubmissionFSRepository  from ._submission_manager import _SubmissionManager  from ._submission_sql_repository import _SubmissionSQLRepository      class _SubmissionManagerFactory(_ManagerFactory):        __REPOSITORY_MAP = {"default": _SubmissionFSRepository, "sql": _SubmissionSQLRepository}        @classmethod      def _build_manager(cls) -> Type[_SubmissionManager]:  # type: ignore          if cls._using_enterprise():              submission_manager = _load_fct(                  cls._TAIPY_ENTERPRISE_CORE_MODULE + ".submission._submission_manager", "_SubmissionManager"              )  # type: ignore              build_repository = _load_fct(                  cls._TAIPY_ENTERPRISE_CORE_MODULE + ".submission._submission_manager_factory",                  "_SubmissionManagerFactory",              )._build_repository  # type: ignore          else:              submission_manager = _SubmissionManager              build_repository = cls._build_repository          submission_manager._repository = build_repository()  # type: ignore          return submission_manager  # type: ignore        @classmethod      def _build_repository(cls):          return cls._get_repository_with_repo_map(cls.__REPOSITORY_MAP)()


#  # 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 .._repository._sql_repository import _SQLRepository  from ._submission_converter import _SubmissionConverter  from ._submission_model import _SubmissionModel      class _SubmissionSQLRepository(_SQLRepository):      def __init__(self):          super().__init__(model_type=_SubmissionModel, converter=_SubmissionConverter)


import logging.config  import os  import sys      class _TaipyLogger:      _ENVIRONMENT_VARIABLE_NAME_WITH_LOGGER_CONFIG_PATH = "TAIPY_LOGGER_CONFIG_PATH"        __logger = None        @classmethod      def _get_logger(cls):          cls._ENVIRONMENT_VARIABLE_NAME_WITH_LOGGER_CONFIG_PATH = "TAIPY_LOGGER_CONFIG_PATH"            if cls.__logger:              return cls.__logger            if config_filename := os.environ.get(cls._ENVIRONMENT_VARIABLE_NAME_WITH_LOGGER_CONFIG_PATH):              logging.config.fileConfig(config_filename)              cls.__logger = logging.getLogger("Taipy")          else:              cls.__logger = logging.getLogger("Taipy")              cls.__logger.setLevel(logging.INFO)              ch = logging.StreamHandler(sys.stdout)              ch.setLevel(logging.INFO)              formatter = logging.Formatter("[%(asctime)s][%(name)s][%(levelname)s] %(message)s", "%Y-%m-%d %H:%M:%S")              ch.setFormatter(formatter)              cls.__logger.addHandler(ch)          return cls.__logger


import os  from typing import Dict    from ..logger._taipy_logger import _TaipyLogger  from ._config import _Config  from ._config_comparator._config_comparator import _ConfigComparator  from ._serializer._json_serializer import _JsonSerializer  from ._serializer._toml_serializer import _TomlSerializer  from .checker._checker import _Checker  from .checker.issue_collector import IssueCollector  from .common._classproperty import _Classproperty  from .common._config_blocker import _ConfigBlocker  from .global_app.global_app_config import GlobalAppConfig  from .section import Section  from .unique_section import UniqueSection      class Config:      """Configuration singleton."""        _ENVIRONMENT_VARIABLE_NAME_WITH_CONFIG_PATH = "TAIPY_CONFIG_PATH"      __logger = _TaipyLogger._get_logger()      _default_config = _Config._default_config()      _python_config = _Config()      _file_config = _Config()      _env_file_config = _Config()      _applied_config = _Config()      _collector = IssueCollector()      _serializer = _TomlSerializer()      __json_serializer = _JsonSerializer()      _comparator: _ConfigComparator = _ConfigComparator()        @_Classproperty      def unique_sections(cls) -> Dict[str, UniqueSection]:          """Return all unique sections."""          return cls._applied_config._unique_sections        @_Classproperty      def sections(cls) -> Dict[str, Dict[str, Section]]:          """Return all non unique sections."""          return cls._applied_config._sections        @_Classproperty      def global_config(cls) -> GlobalAppConfig:          """Return configuration values related to the global application as a `GlobalAppConfig^`."""          return cls._applied_config._global_config        @classmethod      @_ConfigBlocker._check()      def load(cls, filename):          """Load a configuration file.            The current Python configuration is replaced and the Config compilation is triggered.            Parameters:              filename (Union[str, Path]): The path of the toml configuration file to load.          """          cls.__logger.info(f"Loading configuration. Filename: '{filename}'")          cls._python_config = cls._serializer._read(filename)          cls._compile_configs()          cls.__logger.info(f"Configuration '{filename}' successfully loaded.")        @classmethod      def export(cls, filename):          """Export a configuration.            The export is done in a toml file.            The exported configuration is taken from the Python code configuration.            Parameters:              filename (Union[str, Path]): The path of the file to export.          Note:              If *filename* already exists, it is overwritten.          """          cls._serializer._write(cls._python_config, filename)        @classmethod      def backup(cls, filename):          """Backup a configuration.            The backup is done in a toml file.            The backed up configuration is a compilation from the three possible methods to configure          the application: the Python code configuration, the file configuration and the environment          configuration.            Parameters:              filename (Union[str, Path]): The path of the file to export.          Note:              If *filename* already exists, it is overwritten.          """          cls._serializer._write(cls._applied_config, filename)        @classmethod      @_ConfigBlocker._check()      def restore(cls, filename):          """Restore a configuration file and replace the current applied configuration.            Parameters:              filename (Union[str, Path]): The path of the toml configuration file to load.          """          cls.__logger.info(f"Restoring configuration. Filename: '{filename}'")          cls._applied_config = cls._serializer._read(filename)          cls.__logger.info(f"Configuration '{filename}' successfully restored.")        @classmethod      @_ConfigBlocker._check()      def override(cls, filename):          """Load a configuration from a file and overrides the current config.            Parameters:              filename (Union[str, Path]): The path of the toml configuration file to load.          """          cls.__logger.info(f"Loading configuration. Filename: '{filename}'")          cls._file_config = cls._serializer._read(filename)          cls.__logger.info("Overriding configuration.'")          cls._compile_configs()          cls.__logger.info(f"Configuration '{filename}' successfully loaded.")        @classmethod      def block_update(cls):          """Block update on the configuration signgleton."""          _ConfigBlocker._block()        @classmethod      def unblock_update(cls):          """Unblock update on the configuration signgleton."""          _ConfigBlocker._unblock()        @classmethod      @_ConfigBlocker._check()      def configure_global_app(cls, **properties) -> GlobalAppConfig:          """Configure the global application.            Parameters:              **properties (Dict[str, Any]): A dictionary of additional properties.          Returns:              The global application configuration.          """          glob_cfg = GlobalAppConfig(**properties)          if cls._python_config._global_config is None:              cls._python_config._global_config = glob_cfg          else:              cls._python_config._global_config._update(glob_cfg._to_dict())          cls._compile_configs()          return cls._applied_config._global_config        @classmethod      def check(cls) -> IssueCollector:          """Check configuration.            This method logs issue messages and returns an issue collector.            Returns:              Collector containing the info, warning and error issues.          """          cls._collector = _Checker._check(cls._applied_config)          cls.__log_message(cls)          return cls._collector        @classmethod      @_ConfigBlocker._check()      def _register_default(cls, default_section: Section):          if isinstance(default_section, UniqueSection):              if cls._default_config._unique_sections.get(default_section.name, None):                  cls._default_config._unique_sections[default_section.name]._update(default_section._to_dict())              else:                  cls._default_config._unique_sections[default_section.name] = default_section          else:              if def_sections := cls._default_config._sections.get(default_section.name, None):                  def_sections[default_section.id] = default_section              else:                  cls._default_config._sections[default_section.name] = {default_section.id: default_section}          cls._serializer._section_class[default_section.name] = default_section.__class__  # type: ignore          cls.__json_serializer._section_class[default_section.name] = default_section.__class__  # type: ignore          cls._compile_configs()        @classmethod      @_ConfigBlocker._check()      def _register(cls, section):          if isinstance(section, UniqueSection):              if cls._python_config._unique_sections.get(section.name, None):                  cls._python_config._unique_sections[section.name]._update(section._to_dict())              else:                  cls._python_config._unique_sections[section.name] = section          else:              if sections := cls._python_config._sections.get(section.name, None):                  if sections.get(section.id, None):                      sections[section.id]._update(section._to_dict())                  else:                      sections[section.id] = section              else:                  cls._python_config._sections[section.name] = {section.id: section}          cls._serializer._section_class[section.name] = section.__class__          cls.__json_serializer._section_class[section.name] = section.__class__          cls._compile_configs()        @classmethod      def _override_env_file(cls):          if config_filename := os.environ.get(cls._ENVIRONMENT_VARIABLE_NAME_WITH_CONFIG_PATH):              cls.__logger.info(f"Loading configuration provided by environment variable. Filename: '{config_filename}'")              cls._env_file_config = cls._serializer._read(config_filename)              cls.__logger.info(f"Configuration '{config_filename}' successfully loaded.")        @classmethod      def _compile_configs(cls):          Config._override_env_file()          cls._applied_config._clean()          if cls._default_config:              cls._applied_config._update(cls._default_config)          if cls._python_config:              cls._applied_config._update(cls._python_config)          if cls._file_config:              cls._applied_config._update(cls._file_config)          if cls._env_file_config:              cls._applied_config._update(cls._env_file_config)        @classmethod      def __log_message(cls, config):          for issue in config._collector._warnings:              cls.__logger.warning(str(issue))          for issue in config._collector._infos:              cls.__logger.info(str(issue))          for issue in config._collector._errors:              cls.__logger.error(str(issue))          if len(config._collector._errors) != 0:              raise SystemExit("Configuration errors found. Please check the error log for more information.")        @classmethod      def _to_json(cls, _config: _Config) -> str:          return cls.__json_serializer._serialize(_config)        @classmethod      def _from_json(cls, config_as_str: str) -> _Config:          return cls.__json_serializer._deserialize(config_as_str)      Config._override_env_file()


import json  import os      def _get_version():      with open(f"{os.path.dirname(os.path.abspath(__file__))}{os.sep}version.json") as version_file:          version = json.load(version_file)          version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'          if vext := version.get("ext"):              version_string = f"{version_string}.{vext}"      return version_string


from .common.frequency import Frequency  from .common.scope import Scope  from .config import Config


"""# Taipy Config    The Taipy Config package is a Python library designed to configure a Taipy application.    The main entrypoint is the `Config^` singleton class. It exposes some methods to configure the  Taipy application and some attributes to retrieve the configuration values.    """    from typing import List    from ._init import Config  from .checker.issue import Issue  from .checker.issue_collector import IssueCollector  from .global_app.global_app_config import GlobalAppConfig  from .section import Section  from .unique_section import UniqueSection  from .version import _get_version    __version__ = _get_version()      def _config_doc(func):      def func_with_doc(section, attribute_name, default, configuration_methods, add_to_unconflicted_sections=False):          import os            if os.environ.get("GENERATING_TAIPY_DOC", None) and os.environ["GENERATING_TAIPY_DOC"] == "true":              with open("config_doc.txt", "a") as f:                  from inspect import signature                    for exposed_configuration_method, configuration_method in configuration_methods:                      annotation = "    @staticmethod\n"                      sign = "    def " + exposed_configuration_method + str(signature(configuration_method)) + ":\n"                      doc = '        """' + configuration_method.__doc__ + '"""\n'                      content = "        pass\n\n"                      f.write(annotation + sign + doc + content)          return func(section, attribute_name, default, configuration_methods, add_to_unconflicted_sections)        return func_with_doc      @_config_doc  def _inject_section(      section_clazz,      attribute_name: str,      default: Section,      configuration_methods: List[tuple],      add_to_unconflicted_sections: bool = False,  ):      Config._register_default(default)        if issubclass(section_clazz, UniqueSection):          setattr(Config, attribute_name, Config.unique_sections[section_clazz.name])      elif issubclass(section_clazz, Section):          setattr(Config, attribute_name, Config.sections[section_clazz.name])      else:          raise TypeError        if add_to_unconflicted_sections:          Config._comparator._add_unconflicted_section(section_clazz.name)  # type: ignore        for exposed_configuration_method, configuration_method in configuration_methods:          setattr(Config, exposed_configuration_method, configuration_method)


from abc import abstractmethod  from typing import Any, Dict, Optional    from .common._config_blocker import _ConfigBlocker  from .common._template_handler import _TemplateHandler as _tpl  from .common._validate_id import _validate_id      class Section:      """A Section as a consistent part of the Config.        A section is defined by the section name (representing the type of objects that are configured) and a section id.      """        _DEFAULT_KEY = "default"      _ID_KEY = "id"        def __init__(self, id, **properties):          self.id = _validate_id(id)          self._properties = properties or dict()        @abstractmethod      def __copy__(self):          raise NotImplementedError        @property      @abstractmethod      def name(self):          raise NotImplementedError        @abstractmethod      def _clean(self):          raise NotImplementedError        @abstractmethod      def _to_dict(self):          raise NotImplementedError        @classmethod      @abstractmethod      def _from_dict(cls, config_as_dict: Dict[str, Any], id, config):          raise NotImplementedError        @abstractmethod      def _update(self, config_as_dict, default_section=None):          raise NotImplementedError        def __getattr__(self, item: str) -> Optional[Any]:          return self._replace_templates(self._properties.get(item, None))        @property      def properties(self):          return {k: _tpl._replace_templates(v) for k, v in self._properties.items()}        @properties.setter  # type: ignore      @_ConfigBlocker._check()      def properties(self, val):          self._properties = val        def _replace_templates(self, value):          return _tpl._replace_templates(value)


#!/usr/bin/env python    """The setup script."""  import json  import os    from setuptools import find_namespace_packages, find_packages, setup    with open("README.md") as readme_file:      readme = readme_file.read()    with open(f"src{os.sep}taipy{os.sep}config{os.sep}version.json") as version_file:      version = json.load(version_file)      version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'      if vext := version.get("ext"):          version_string = f"{version_string}.{vext}"    requirements = ["toml>=0.10,<0.11", "deepdiff>=6.2,<6.3"]    test_requirements = ["pytest>=3.8"]    setup(      author="Avaiga",      author_email="dev@taipy.io",      python_requires=">=3.8",      classifiers=[          "Intended Audience :: Developers",          "License :: OSI Approved :: Apache Software License",          "Natural Language :: English",          "Programming Language :: Python :: 3",          "Programming Language :: Python :: 3.8",          "Programming Language :: Python :: 3.9",          "Programming Language :: Python :: 3.10",      ],      description="A Taipy package dedicated to easily configure a Taipy application.",      install_requires=requirements,      long_description=readme,      long_description_content_type="text/markdown",      include_package_data=True,      license="Apache License 2.0",      keywords="taipy-config",      name="taipy-config",      package_dir={"": "src"},      packages=find_namespace_packages(where="src")      + find_packages(include=["taipy", "taipy.config", "taipy.config.*", "taipy.logger", "taipy.logger.*"]),      test_suite="tests",      tests_require=test_requirements,      url="https://github.com/avaiga/taipy-config",      version=version_string,      zip_safe=False,  )


from abc import ABC    from .common._validate_id import _validate_id  from .section import Section      class UniqueSection(Section, ABC):      """A UniqueSection is a configuration `Section^` that can have only one instance.        A UniqueSection is only defined by the section name.      """        def __init__(self, **properties):          super().__init__(self.name, **properties)


from copy import copy  from typing import Dict    from .global_app.global_app_config import GlobalAppConfig  from .section import Section  from .unique_section import UniqueSection      class _Config:      DEFAULT_KEY = "default"        def __init__(self):          self._sections: Dict[str, Dict[str, Section]] = {}          self._unique_sections: Dict[str, UniqueSection] = {}          self._global_config: GlobalAppConfig = GlobalAppConfig()        def _clean(self):          self._global_config._clean()          for unique_section in self._unique_sections.values():              unique_section._clean()          for sections in self._sections.values():              for section in sections.values():                  section._clean()        @classmethod      def _default_config(cls):          config = _Config()          config._global_config = GlobalAppConfig.default_config()          return config        def _update(self, other_config):          self._global_config._update(other_config._global_config._to_dict())          if other_config._unique_sections:              for section_name, other_section in other_config._unique_sections.items():                  if section := self._unique_sections.get(section_name, None):                      section._update(other_section._to_dict())                  else:                      self._unique_sections[section_name] = copy(other_config._unique_sections[section_name])          if other_config._sections:              for section_name, other_non_unique_sections in other_config._sections.items():                  if non_unique_sections := self._sections.get(section_name, None):                      self.__update_sections(non_unique_sections, other_non_unique_sections)                  else:                      self._sections[section_name] = {}                      self.__add_sections(self._sections[section_name], other_non_unique_sections)        def __add_sections(self, entity_config, other_entity_configs):          for cfg_id, sub_config in other_entity_configs.items():              entity_config[cfg_id] = copy(sub_config)              self.__point_nested_section_to_self(sub_config)        def __update_sections(self, entity_config, other_entity_configs):          if self.DEFAULT_KEY in other_entity_configs:              if self.DEFAULT_KEY in entity_config:                  entity_config[self.DEFAULT_KEY]._update(other_entity_configs[self.DEFAULT_KEY]._to_dict())              else:                  entity_config[self.DEFAULT_KEY] = other_entity_configs[self.DEFAULT_KEY]          for cfg_id, sub_config in other_entity_configs.items():              if cfg_id != self.DEFAULT_KEY:                  if cfg_id in entity_config:                      entity_config[cfg_id]._update(sub_config._to_dict(), entity_config.get(self.DEFAULT_KEY))                  else:                      entity_config[cfg_id] = copy(sub_config)                      entity_config[cfg_id]._update(sub_config._to_dict(), entity_config.get(self.DEFAULT_KEY))              self.__point_nested_section_to_self(sub_config)        def __point_nested_section_to_self(self, section):          """Loop through attributes of a Section to find if any attribute has a list of Section as value.          If there is, update each nested Section by the corresponding instance in self.            Args:              section (Section): The Section to search for nested sections.          """          for _, attr_value in vars(section).items():              # ! This will fail if an attribute is a dictionary, or nested list of Sections.              if not isinstance(attr_value, list):                  continue                for index, item in enumerate(attr_value):                  if not isinstance(item, Section):                      continue                    if sub_item := self._sections.get(item.name, {}).get(item.id, None):                      attr_value[index] = sub_item


import ast  import re  from pathlib import Path  from typing import List      def _get_function_delimiters(initial_line, lines):      begin = end = initial_line      while True:          if lines[begin - 1] == "\n":              break          begin -= 1        if lines[end].endswith("(\n"):          while ":\n" not in lines[end]:              end += 1        if '"""' in lines[end + 1]:          while True:              if '"""\n' in lines[end]:                  break              end += 1      return begin, end + 1      def _get_file_lines(filename: str) -> List[str]:      # Get file lines for later      with open(filename) as f:          return f.readlines()      def _get_file_ast(filename: str):      # Get raw text and build ast      _config = Path(filename)      _tree = _config.read_text()      return ast.parse(_tree)      def _build_base_config_pyi(filename, base_pyi):      lines = _get_file_lines(filename)      tree = _get_file_ast(filename)        class_lineno = [f.lineno for f in ast.walk(tree) if isinstance(f, ast.ClassDef) and f.name == "Config"]      begin_class, end_class = _get_function_delimiters(class_lineno[0] - 1, lines)        base_pyi += "".join(lines[begin_class:end_class])      functions = [f.lineno for f in ast.walk(tree) if isinstance(f, ast.FunctionDef) and not f.name.startswith("__")]        for ln in functions:          begin_line, end_line = _get_function_delimiters(ln - 1, lines)          base_pyi += "".join(lines[begin_line:end_line])            base_pyi = __add_docstring(base_pyi, lines, end_line)          base_pyi += "\n"        return base_pyi      def __add_docstring(base_pyi, lines, end_line):      if '"""' not in lines[end_line - 1]:          base_pyi += '\t\t""""""\n'.replace("\t", "    ")      return base_pyi      def _build_entity_config_pyi(base_pyi, filename, entity_map):      lines = _get_file_lines(filename)      tree = _get_file_ast(filename)      functions = {}        for f in ast.walk(tree):          if isinstance(f, ast.FunctionDef):              if "_configure" in f.name and not f.name.startswith("__"):                  functions[f.name] = f.lineno              elif "_set_default" in f.name and not f.name.startswith("__"):                  functions[f.name] = f.lineno              elif "_add" in f.name and not f.name.startswith("__"):                  functions[f.name] = f.lineno        for k, v in functions.items():          begin_line, end_line = _get_function_delimiters(v - 1, lines)          try:              func = "".join(lines[begin_line:end_line])              func = func if not k.startswith("_") else func.replace(k, entity_map.get(k))              func = __add_docstring(func, lines, end_line) + "\n"              base_pyi += func          except Exception:              print(f"key={k}")              raise        return base_pyi      def _generate_entity_and_property_maps(filename):      entities_map = {}      property_map = {}      entity_tree = _get_file_ast(filename)      functions = [          f for f in ast.walk(entity_tree) if isinstance(f, ast.Call) and getattr(f.func, "id", "") == "_inject_section"      ]        for f in functions:          entity = ast.unparse(f.args[0])          entities_map[entity] = {}          property_map[eval(ast.unparse(f.args[1]))] = entity          # Remove class name from function map          text = ast.unparse(f.args[-1]).replace(f"{entity}.", "")          matches = re.findall(r"\((.*?)\)", text)            for m in matches:              v, k = m.replace("'", "").split(",")              entities_map[entity][k.strip()] = v      return entities_map, property_map      def _generate_acessors(base_pyi, property_map):      for property, cls in property_map.items():          return_template = f"Dict[str, {cls}]" if property != "job_config" else f"{cls}"          template = ("\t@_Classproperty\n" + f'\tdef {property}(cls) -> {return_template}:\n\t\t""""""\n').replace(              "\t", "    "          )          base_pyi += template + "\n"      return base_pyi      def _build_header(filename):      _file = Path(filename)      return _file.read_text() + "\n\n"      if __name__ == "__main__":      header_file = "stubs/pyi_header.py"      config_init = Path("taipy-core/src/taipy/core/config/__init__.py")      base_config = "src/taipy/config/config.py"        dn_filename = "taipy-core/src/taipy/core/config/data_node_config.py"      job_filename = "taipy-core/src/taipy/core/config/job_config.py"      scenario_filename = "taipy-core/src/taipy/core/config/scenario_config.py"      task_filename = "taipy-core/src/taipy/core/config/task_config.py"      migration_filename = "taipy-core/src/taipy/core/config/migration_config.py"      core_filename = "taipy-core/src/taipy/core/config/core_section.py"        entities_map, property_map = _generate_entity_and_property_maps(config_init)      pyi = _build_header(header_file)      pyi = _build_base_config_pyi(base_config, pyi)      pyi = _generate_acessors(pyi, property_map)      pyi = _build_entity_config_pyi(pyi, scenario_filename, entities_map["ScenarioConfig"])      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, 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"])        with open("src/taipy/config/config.pyi", "w") as f:          f.writelines(pyi)


import json  from datetime import timedelta  from typing import Any, Callable, Dict, List, Optional, Union    from taipy.core.config import CoreSection, DataNodeConfig, JobConfig, MigrationConfig, ScenarioConfig, TaskConfig    from .checker.issue_collector import IssueCollector  from .common._classproperty import _Classproperty  from .common._config_blocker import _ConfigBlocker  from .common.frequency import Frequency  from .common.scope import Scope  from .global_app.global_app_config import GlobalAppConfig  from .section import Section  from .unique_section import UniqueSection


import toml  # type: ignore    from .._config import _Config  from ..exceptions.exceptions import LoadingError  from ._base_serializer import _BaseSerializer      class _TomlSerializer(_BaseSerializer):      """Convert configuration from TOML representation to Python Dict and reciprocally."""        @classmethod      def _write(cls, configuration: _Config, filename: str):          with open(filename, "w") as fd:              toml.dump(cls._str(configuration), fd)        @classmethod      def _read(cls, filename: str) -> _Config:          try:              config_as_dict = cls._pythonify(dict(toml.load(filename)))              return cls._from_dict(config_as_dict)          except toml.TomlDecodeError as e:              error_msg = f"Can not load configuration {e}"              raise LoadingError(error_msg)        @classmethod      def _serialize(cls, configuration: _Config) -> str:          return toml.dumps(cls._str(configuration))        @classmethod      def _deserialize(cls, config_as_string: str) -> _Config:          return cls._from_dict(cls._pythonify(dict(toml.loads(config_as_string))))


import inspect  import re  import types  from abc import abstractmethod  from datetime import datetime, timedelta  from typing import Any, Dict, Optional    from .._config import _Config  from ..common._template_handler import _TemplateHandler  from ..common._validate_id import _validate_id  from ..common.frequency import Frequency  from ..common.scope import Scope  from ..exceptions.exceptions import LoadingError  from ..global_app.global_app_config import GlobalAppConfig  from ..section import Section  from ..unique_section import UniqueSection      class _BaseSerializer(object):      """Base serializer class for taipy configuration."""        _GLOBAL_NODE_NAME = "TAIPY"      _section_class = {_GLOBAL_NODE_NAME: GlobalAppConfig}        @classmethod      @abstractmethod      def _write(cls, configuration: _Config, filename: str):          raise NotImplementedError        @classmethod      def _str(cls, configuration: _Config):          config_as_dict = {cls._GLOBAL_NODE_NAME: configuration._global_config._to_dict()}          for u_sect_name, u_sect in configuration._unique_sections.items():              config_as_dict[u_sect_name] = u_sect._to_dict()          for sect_name, sections in configuration._sections.items():              config_as_dict[sect_name] = cls._to_dict(sections)          return cls._stringify(config_as_dict)        @classmethod      def _to_dict(cls, sections: Dict[str, Any]):          return {section_id: section._to_dict() for section_id, section in sections.items()}        @classmethod      def _stringify(cls, as_dict):          if as_dict is None:              return None          if isinstance(as_dict, Section):              return as_dict.id + ":SECTION"          if isinstance(as_dict, Scope):              return as_dict.name + ":SCOPE"          if isinstance(as_dict, Frequency):              return as_dict.name + ":FREQUENCY"          if isinstance(as_dict, bool):              return str(as_dict) + ":bool"          if isinstance(as_dict, int):              return str(as_dict) + ":int"          if isinstance(as_dict, float):              return str(as_dict) + ":float"          if isinstance(as_dict, datetime):              return as_dict.isoformat() + ":datetime"          if isinstance(as_dict, timedelta):              return cls._timedelta_to_str(as_dict) + ":timedelta"          if inspect.isfunction(as_dict) or isinstance(as_dict, types.BuiltinFunctionType):              return as_dict.__module__ + "." + as_dict.__name__ + ":function"          if inspect.isclass(as_dict):              return as_dict.__module__ + "." + as_dict.__qualname__ + ":class"          if isinstance(as_dict, dict):              return {str(key): cls._stringify(val) for key, val in as_dict.items()}          if isinstance(as_dict, list):              return [cls._stringify(val) for val in as_dict]          if isinstance(as_dict, tuple):              return [cls._stringify(val) for val in as_dict]          return as_dict        @staticmethod      def _extract_node(config_as_dict, cls_config, node, config: Optional[Any]) -> Dict[str, Section]:          res = {}          for key, value in config_as_dict.get(node, {}).items():  # my_task, {input=[], output=[my_data_node], ...}              key = _validate_id(key)              res[key] = cls_config._from_dict(value, key, config)  # if config is None else cls_config._from_dict(key,              # value, config)          return res        @classmethod      def _from_dict(cls, as_dict) -> _Config:          config = _Config()          config._global_config = GlobalAppConfig._from_dict(as_dict.get(cls._GLOBAL_NODE_NAME, {}))          for section_name, sect_as_dict in as_dict.items():              if section_class := cls._section_class.get(section_name, None):                  if issubclass(section_class, UniqueSection):                      config._unique_sections[section_name] = section_class._from_dict(                          sect_as_dict, None, None                      )  # type: ignore                  elif issubclass(section_class, Section):                      config._sections[section_name] = cls._extract_node(as_dict, section_class, section_name, config)          return config        @classmethod      def _pythonify(cls, val):          match = re.fullmatch(_TemplateHandler._PATTERN, str(val))          if not match:              if isinstance(val, str):                  TYPE_PATTERN = (                      r"^(.+):(\bbool\b|\bstr\b|\bint\b|\bfloat\b|\bdatetime\b||\btimedelta\b|"                      r"\bfunction\b|\bclass\b|\bSCOPE\b|\bFREQUENCY\b|\bSECTION\b)?$"                  )                  match = re.fullmatch(TYPE_PATTERN, str(val))                  if match:                      actual_val = match.group(1)                      dynamic_type = match.group(2)                      if dynamic_type == "SECTION":                          return actual_val                      if dynamic_type == "FREQUENCY":                          return Frequency[actual_val]                      if dynamic_type == "SCOPE":                          return Scope[actual_val]                      if dynamic_type == "bool":                          return _TemplateHandler._to_bool(actual_val)                      elif dynamic_type == "int":                          return _TemplateHandler._to_int(actual_val)                      elif dynamic_type == "float":                          return _TemplateHandler._to_float(actual_val)                      elif dynamic_type == "datetime":                          return _TemplateHandler._to_datetime(actual_val)                      elif dynamic_type == "timedelta":                          return _TemplateHandler._to_timedelta(actual_val)                      elif dynamic_type == "function":                          return _TemplateHandler._to_function(actual_val)                      elif dynamic_type == "class":                          return _TemplateHandler._to_class(actual_val)                      elif dynamic_type == "str":                          return actual_val                      else:                          error_msg = f"Error loading toml configuration at {val}. {dynamic_type} type is not supported."                          raise LoadingError(error_msg)              if isinstance(val, dict):                  return {str(k): cls._pythonify(v) for k, v in val.items()}              if isinstance(val, list):                  return [cls._pythonify(v) for v in val]          return val        @classmethod      def _timedelta_to_str(cls, obj: timedelta) -> str:          total_seconds = obj.total_seconds()          return (              f"{int(total_seconds // 86400)}d"              f"{int(total_seconds % 86400 // 3600)}h"              f"{int(total_seconds % 3600 // 60)}m"              f"{int(total_seconds % 60)}s"          )


import json  # type: ignore    from .._config import _Config  from ..exceptions.exceptions import LoadingError  from ._base_serializer import _BaseSerializer      class _JsonSerializer(_BaseSerializer):      """Convert configuration from JSON representation to Python Dict and reciprocally."""        @classmethod      def _write(cls, configuration: _Config, filename: str):          with open(filename, "w") as fd:              json.dump(cls._str(configuration), fd, ensure_ascii=False, indent=0, check_circular=False)        @classmethod      def _read(cls, filename: str) -> _Config:          try:              with open(filename) as f:                  config_as_dict = cls._pythonify(json.load(f))              return cls._from_dict(config_as_dict)          except json.JSONDecodeError as e:              error_msg = f"Can not load configuration {e}"              raise LoadingError(error_msg)        @classmethod      def _serialize(cls, configuration: _Config) -> str:          return json.dumps(cls._str(configuration), ensure_ascii=False, indent=0, check_circular=False)        @classmethod      def _deserialize(cls, config_as_string: str) -> _Config:          return cls._from_dict(cls._pythonify(dict(json.loads(config_as_string))))


#  # 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 Any, List    from .issue import Issue      class IssueCollector:      """      A collection of issues (instances of class `Issue^`).        Attributes:          errors (List[Issue^]): List of ERROR issues collected.          warnings (List[Issue^]): List WARNING issues collected.          infos (List[Issue^]): List INFO issues collected.          all (List[Issue^]): List of all issues collected ordered by decreasing level (ERROR, WARNING and INFO).      """        _ERROR_LEVEL = "ERROR"      _WARNING_LEVEL = "WARNING"      _INFO_LEVEL = "INFO"        def __init__(self):          self._errors: List[Issue] = []          self._warnings: List[Issue] = []          self._infos: List[Issue] = []        @property      def all(self) -> List[Issue]:          return self._errors + self._warnings + self._infos        @property      def infos(self) -> List[Issue]:          return self._infos        @property      def warnings(self) -> List[Issue]:          return self._warnings        @property      def errors(self) -> List[Issue]:          return self._errors        def _add_error(self, field: str, value: Any, message: str, checker_name: str):          self._errors.append(Issue(self._ERROR_LEVEL, field, value, message, checker_name))        def _add_warning(self, field: str, value: Any, message: str, checker_name: str):          self._warnings.append(Issue(self._WARNING_LEVEL, field, value, message, checker_name))        def _add_info(self, field: str, value: Any, message: str, checker_name: str):          self._infos.append(Issue(self._INFO_LEVEL, field, value, message, checker_name))


from dataclasses import dataclass  from typing import Any, Optional      @dataclass  class Issue:      """      An issue detected in the configuration.        Attributes:          level (str): Level of the issue among ERROR, WARNING, INFO.          field (str): Configuration field on which the issue has been detected.          value (Any): Value of the field on which the issue has been detected.          message (str): Human readable message to help the user fix the issue.          tag (Optional[str]): Optional tag to be used to filter issues.      """        level: str      field: str      value: Any      message: str      tag: Optional[str]        def __str__(self) -> str:          message = self.message            if self.value:              current_value_str = f'"{self.value}"' if isinstance(self.value, str) else f"{self.value}"              message += f" Current value of property `{self.field}` is {current_value_str}."            return message


from typing import List    from ._checkers._config_checker import _ConfigChecker  from .issue_collector import IssueCollector      class _Checker:      """Holds the various checkers to perform on the config."""        _checkers: List[_ConfigChecker] = []        @classmethod      def _check(cls, _applied_config):          collector = IssueCollector()          for checker in cls._checkers:              checker(_applied_config, collector)._check()          return collector        @classmethod      def add_checker(cls, checker_class: _ConfigChecker):          cls._checkers.append(checker_class)


import abc  from typing import Any, List, Optional, Set    from ..._config import _Config  from ..issue_collector import IssueCollector      class _ConfigChecker:      _PREDEFINED_PROPERTIES_KEYS = ["_entity_owner"]        def __init__(self, config: _Config, collector):          self._collector = collector          self._config = config        @abc.abstractmethod      def _check(self) -> IssueCollector:          raise NotImplementedError        def _error(self, field: str, value: Any, message: str):          self._collector._add_error(field, value, message, self.__class__.__name__)        def _warning(self, field: str, value: Any, message: str):          self._collector._add_warning(field, value, message, self.__class__.__name__)        def _info(self, field: str, value: Any, message: str):          self._collector._add_info(field, value, message, self.__class__.__name__)        def _check_children(          self,          parent_config_class,          config_id: str,          config_key: str,          config_value,          child_config_class,          can_be_empty: Optional[bool] = False,      ):          if not config_value and not can_be_empty:              self._warning(                  config_key,                  config_value,                  f"{config_key} field of {parent_config_class.__name__} `{config_id}` is empty.",              )          else:              if not (                  (isinstance(config_value, List) or isinstance(config_value, Set))                  and all(map(lambda x: isinstance(x, child_config_class), config_value))              ):                  self._error(                      config_key,                      config_value,                      f"{config_key} field of {parent_config_class.__name__} `{config_id}` must be populated with a list "                      f"of {child_config_class.__name__} objects.",                  )        def _check_existing_config_id(self, config):          if not config.id:              self._error(                  "config_id",                  config.id,                  f"config_id of {config.__class__.__name__} `{config.id}` is empty.",              )        def _check_if_entity_property_key_used_is_predefined(self, config):          for key, value in config._properties.items():              if key in self._PREDEFINED_PROPERTIES_KEYS:                  self._error(                      key,                      value,                      f"Properties of {config.__class__.__name__} `{config.id}` cannot have `{key}` as its property.",                  )


from ..._config import _Config  from ..issue_collector import IssueCollector  from ._config_checker import _ConfigChecker      class _AuthConfigChecker(_ConfigChecker):      def __init__(self, config: _Config, collector: IssueCollector):          super().__init__(config, collector)        def _check(self) -> IssueCollector:          auth_config = self._config._auth_config  # type: ignore          self._check_predefined_protocol(auth_config)          return self._collector        def _check_predefined_protocol(self, auth_config):          if auth_config.protocol == auth_config._PROTOCOL_LDAP:              self.__check_ldap(auth_config)          if auth_config.protocol == auth_config._PROTOCOL_TAIPY:              self.__check_taipy(auth_config)        def __check_taipy(self, auth_config):          if auth_config._TAIPY_ROLES not in auth_config.properties:              self._error(                  "properties",                  auth_config._LDAP_SERVER,                  f"`{auth_config._LDAP_SERVER}` property must be populated when {auth_config._PROTOCOL_LDAP} is used.",              )          if auth_config._TAIPY_PWD not in auth_config.properties:              self._warning(                  "properties",                  auth_config._TAIPY_PWD,                  f"`In order to protect authentication with passwords using {auth_config._PROTOCOL_TAIPY} protocol,"                  f" {auth_config._TAIPY_PWD}` property can be populated.",              )        def __check_ldap(self, auth_config):          if auth_config._LDAP_SERVER not in auth_config.properties:              self._error(                  "properties",                  auth_config._LDAP_SERVER,                  f"`{auth_config._LDAP_SERVER}` attribute must be populated when {auth_config._PROTOCOL_LDAP} is used.",              )          if auth_config._LDAP_BASE_DN not in auth_config.properties:              self._error(                  "properties",                  auth_config._LDAP_BASE_DN,                  f"`{auth_config._LDAP_BASE_DN}` field must be populated when {auth_config._PROTOCOL_LDAP} is used.",              )


# 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 .exceptions import *


class LoadingError(Exception):      """Raised if an error occurs while loading the configuration file."""      class InconsistentEnvVariableError(Exception):      """Inconsistency value has been detected in an environment variable referenced by the configuration."""      class MissingEnvVariableError(Exception):      """Environment variable referenced in configuration is missing."""      class InvalidConfigurationId(Exception):      """Configuration id is not valid."""      class ConfigurationUpdateBlocked(Exception):      """The configuration is being blocked from update by other Taipy services."""


from ..common._repr_enum import _ReprEnum      class Frequency(_ReprEnum):      """Frequency of the recurrence of `Cycle^` and `Scenario^` objects.        The frequency must be provided in the `ScenarioConfig^`.        Each recurrent scenario is attached to the cycle corresponding to the creation date and the      frequency. In other words, each cycle represents an iteration and contains the various scenarios      created during this iteration.        For instance, when scenarios have a _MONTHLY_ frequency, one cycle will be created for each      month (January, February, March, etc.). A new scenario created on February 10th, gets      attached to the _February_ cycle.        The frequency is implemented as an enumeration with the following possible values:        - With a _DAILY_ frequency, a new cycle is created for each day.        - With a _WEEKLY_ frequency, a new cycle is created for each week (from Monday to Sunday).        - With a _MONTHLY_ frequency, a new cycle is created for each month.        - With a _QUARTERLY_ frequency, a new cycle is created for each quarter.        - With a _YEARLY_ frequency, a new cycle is created for each year.      """        DAILY = 1      WEEKLY = 2      MONTHLY = 3      QUARTERLY = 4      YEARLY = 5


class _Classproperty(object):      def __init__(self, f):          self.f = f        def __get__(self, obj, owner):          return self.f(owner)


import functools  from enum import Enum      class _ReprEnum(Enum):      @classmethod      @functools.lru_cache      def _from_repr(cls, repr_: str):          return next(filter(lambda e: repr(e) == repr_, cls))  # type: ignore


import keyword    from ..exceptions.exceptions import InvalidConfigurationId    __INVALID_TAIPY_ID_TERMS = ["CYCLE", "SCENARIO", "SEQUENCE", "TASK", "DATANODE"]      def _validate_id(name: str):      for invalid_taipy_id_term in __INVALID_TAIPY_ID_TERMS:          if invalid_taipy_id_term in name:              raise InvalidConfigurationId(f"{name} is not a valid identifier. {invalid_taipy_id_term} is restricted.")        if name.isidentifier() and not keyword.iskeyword(name):          return name        raise InvalidConfigurationId(f"{name} is not a valid identifier.")


import functools    from ...logger._taipy_logger import _TaipyLogger  from ..exceptions.exceptions import ConfigurationUpdateBlocked      class _ConfigBlocker:      """Configuration blocker singleton."""        __logger = _TaipyLogger._get_logger()      __block_config_update = False        @classmethod      def _block(cls):          cls.__block_config_update = True        @classmethod      def _unblock(cls):          cls.__block_config_update = False        @classmethod      def _check(cls):          def inner(f):              @functools.wraps(f)              def _check_if_is_blocking(*args, **kwargs):                  if cls.__block_config_update:                      error_message = (                          "The Core service should be stopped by running core.stop() before"                          " modifying the Configuration. For more information, please refer to:"                          " https://docs.taipy.io/en/latest/manuals/running_services/#running-core."                      )                      cls.__logger.error("ConfigurationUpdateBlocked: " + error_message)                      raise ConfigurationUpdateBlocked(error_message)                    return f(*args, **kwargs)                return _check_if_is_blocking            return inner


from ..common._repr_enum import _ReprEnum      class _OrderedEnum(_ReprEnum):      def __ge__(self, other):          if self.__class__ is other.__class__:              return self.value >= other.value          return NotImplemented        def __gt__(self, other):          if self.__class__ is other.__class__:              return self.value > other.value          return NotImplemented        def __le__(self, other):          if self.__class__ is other.__class__:              return self.value <= other.value          return NotImplemented        def __lt__(self, other):          if self.__class__ is other.__class__:              return self.value < other.value          return NotImplemented      class Scope(_OrderedEnum):      """Scope of a `DataNode^`.        This enumeration can have the following values:        - `GLOBAL`      - `CYCLE`      - `SCENARIO`      """        GLOBAL = 3      CYCLE = 2      SCENARIO = 1


import os  import re  from collections import UserDict  from datetime import datetime, timedelta  from importlib import import_module  from operator import attrgetter  from pydoc import locate    from ..exceptions.exceptions import InconsistentEnvVariableError, MissingEnvVariableError  from .frequency import Frequency  from .scope import Scope      class _TemplateHandler:      """Factory to handle actions related to config value templating."""        _PATTERN = r"^ENV\[([a-zA-Z_]\w*)\](:(\bbool\b|\bstr\b|\bfloat\b|\bint\b))?$"        @classmethod      def _replace_templates(cls, template, type=str, required=True, default=None):          if isinstance(template, tuple):              return tuple(cls._replace_template(item, type, required, default) for item in template)          if isinstance(template, list):              return [cls._replace_template(item, type, required, default) for item in template]          if isinstance(template, dict):              return {str(k): cls._replace_template(v, type, required, default) for k, v in template.items()}          if isinstance(template, UserDict):              return {str(k): cls._replace_template(v, type, required, default) for k, v in template.items()}          return cls._replace_template(template, type, required, default)        @classmethod      def _replace_template(cls, template, type, required, default):          if "ENV" not in str(template):              return template          match = re.fullmatch(cls._PATTERN, str(template))          if match:              var = match.group(1)              dynamic_type = match.group(3)              val = os.environ.get(var)              if val is None:                  if required:                      raise MissingEnvVariableError(f"Environment variable {var} is not set.")                  return default              if type == bool:                  return cls._to_bool(val)              elif type == int:                  return cls._to_int(val)              elif type == float:                  return cls._to_float(val)              elif type == Scope:                  return cls._to_scope(val)              elif type == Frequency:                  return cls._to_frequency(val)              else:                  if dynamic_type == "bool":                      return cls._to_bool(val)                  elif dynamic_type == "int":                      return cls._to_int(val)                  elif dynamic_type == "float":                      return cls._to_float(val)                  return val          return template        @staticmethod      def _to_bool(val: str) -> bool:          possible_values = ["true", "false"]          if str.lower(val) not in possible_values:              raise InconsistentEnvVariableError("{val} is not a Boolean.")          return str.lower(val) == "true" or not (str.lower(val) == "false")        @staticmethod      def _to_int(val: str) -> int:          try:              return int(val)          except ValueError:              raise InconsistentEnvVariableError(f"{val} is not an integer.")        @staticmethod      def _to_float(val: str) -> float:          try:              return float(val)          except ValueError:              raise InconsistentEnvVariableError(f"{val} is not a float.")        @staticmethod      def _to_datetime(val: str) -> datetime:          try:              return datetime.fromisoformat(val)          except ValueError:              raise InconsistentEnvVariableError(f"{val} is not a valid datetime.")        @staticmethod      def _to_timedelta(val: str) -> timedelta:          """          Parse a time string e.g. (2h13m) into a timedelta object.            :param timedelta_str: A string identifying a duration.  (eg. 2h13m)          :return datetime.timedelta: A datetime.timedelta object          """          regex = re.compile(              r"^((?P<days>[\.\d]+?)d)? *"              r"((?P<hours>[\.\d]+?)h)? *"              r"((?P<minutes>[\.\d]+?)m)? *"              r"((?P<seconds>[\.\d]+?)s)?$"          )          parts = regex.match(val)          if not parts:              raise InconsistentEnvVariableError(f"{val} is not a valid timedelta.")          time_params = {name: float(param) for name, param in parts.groupdict().items() if param}          return timedelta(**time_params)  # type: ignore        @staticmethod      def _to_scope(val: str) -> Scope:          try:              return Scope[str.upper(val)]          except Exception:              raise InconsistentEnvVariableError(f"{val} is not a valid scope.")        @staticmethod      def _to_frequency(val: str) -> Frequency:          try:              return Frequency[str.upper(val)]          except Exception:              raise InconsistentEnvVariableError(f"{val} is not a valid frequency.")        @staticmethod      def _to_function(val: str):          module_name, fct_name = val.rsplit(".", 1)          try:              module = import_module(module_name)              return attrgetter(fct_name)(module)          except Exception:              raise InconsistentEnvVariableError(f"{val} is not a valid function.")        @staticmethod      def _to_class(val: str):          try:              return locate(val)          except Exception:              raise InconsistentEnvVariableError(f"{val} is not a valid class.")


from __future__ import annotations    from typing import Any, Dict, Optional, Union    from ..common._config_blocker import _ConfigBlocker  from ..common._template_handler import _TemplateHandler as _tpl      class GlobalAppConfig:      """      Configuration fields related to the global application.        Attributes:          **properties (Dict[str, Any]): A dictionary of additional properties.      """        def __init__(self, **properties):          self._properties = properties        @property      def properties(self):          return {k: _tpl._replace_templates(v) for k, v in self._properties.items()}        @properties.setter  # type: ignore      @_ConfigBlocker._check()      def properties(self, val):          self._properties = val        def __getattr__(self, item: str) -> Optional[Any]:          return _tpl._replace_templates(self._properties.get(item))        @classmethod      def default_config(cls) -> GlobalAppConfig:          return GlobalAppConfig()        def _clean(self):          self._properties.clear()        def _to_dict(self):          as_dict = {}          as_dict.update(self._properties)          return as_dict        @classmethod      def _from_dict(cls, config_as_dict: Dict[str, Any]):          config = GlobalAppConfig()          config._properties = config_as_dict          return config        def _update(self, config_as_dict):          self._properties.update(config_as_dict)


import re  from typing import Dict, List, Set    from .._serializer._json_serializer import _JsonSerializer      class _ComparatorResult(dict):      ADDED_ITEMS_KEY = "added_items"      REMOVED_ITEMS_KEY = "removed_items"      MODIFIED_ITEMS_KEY = "modified_items"        CONFLICTED_SECTION_KEY = "conflicted_sections"      UNCONFLICTED_SECTION_KEY = "unconflicted_sections"        def __init__(self, unconflicted_sections: Set[str]):          super().__init__()            self._unconflicted_sections = unconflicted_sections        def _sort_by_section(self):          if self.get(self.CONFLICTED_SECTION_KEY):              for key in self[self.CONFLICTED_SECTION_KEY].keys():                  self[self.CONFLICTED_SECTION_KEY][key].sort(key=lambda x: x[0][0])            if self.get(self.UNCONFLICTED_SECTION_KEY):              for key in self[self.UNCONFLICTED_SECTION_KEY].keys():                  self[self.UNCONFLICTED_SECTION_KEY][key].sort(key=lambda x: x[0][0])        def _check_added_items(self, config_deepdiff, new_json_config):          if dictionary_item_added := config_deepdiff.get("dictionary_item_added"):              for item_added in dictionary_item_added:                  section_name, config_id, attribute = self.__get_changed_entity_attribute(item_added)                  diff_sections = self.__get_section(section_name)                    if attribute:                      value_added = new_json_config[section_name][config_id][attribute]                  elif config_id:                      value_added = new_json_config[section_name][config_id]                  else:                      value_added = new_json_config[section_name]                    section_name = self.__rename_global_node_name(section_name)                  self.__create_or_append_list(                      diff_sections,                      self.ADDED_ITEMS_KEY,                      ((section_name, config_id, attribute), (value_added)),                  )        def _check_removed_items(self, config_deepdiff, old_json_config):          if dictionary_item_removed := config_deepdiff.get("dictionary_item_removed"):              for item_removed in dictionary_item_removed:                  section_name, config_id, attribute = self.__get_changed_entity_attribute(item_removed)                  diff_sections = self.__get_section(section_name)                    if attribute:                      value_removed = old_json_config[section_name][config_id][attribute]                  elif config_id:                      value_removed = old_json_config[section_name][config_id]                  else:                      value_removed = old_json_config[section_name]                    section_name = self.__rename_global_node_name(section_name)                  self.__create_or_append_list(                      diff_sections,                      self.REMOVED_ITEMS_KEY,                      ((section_name, config_id, attribute), (value_removed)),                  )        def _check_modified_items(self, config_deepdiff, old_json_config, new_json_config):          if values_changed := config_deepdiff.get("values_changed"):              for item_changed, value_changed in values_changed.items():                  section_name, config_id, attribute = self.__get_changed_entity_attribute(item_changed)                  diff_sections = self.__get_section(section_name)                    section_name = self.__rename_global_node_name(section_name)                  self.__create_or_append_list(                      diff_sections,                      self.MODIFIED_ITEMS_KEY,                      ((section_name, config_id, attribute), (value_changed["old_value"], value_changed["new_value"])),                  )            # Iterable item added will be considered a modified item          if iterable_item_added := config_deepdiff.get("iterable_item_added"):              self.__check_modified_iterable(iterable_item_added, old_json_config, new_json_config)            # Iterable item removed will be considered a modified item          if iterable_item_removed := config_deepdiff.get("iterable_item_removed"):              self.__check_modified_iterable(iterable_item_removed, old_json_config, new_json_config)        def __check_modified_iterable(self, iterable_items, old_json_config, new_json_config):          for item in iterable_items:              section_name, config_id, attribute = self.__get_changed_entity_attribute(item)              diff_sections = self.__get_section(section_name)                if attribute:                  new_value = new_json_config[section_name][config_id][attribute]                  old_value = old_json_config[section_name][config_id][attribute]              else:                  new_value = new_json_config[section_name][config_id]                  old_value = old_json_config[section_name][config_id]                section_name = self.__rename_global_node_name(section_name)              modified_value = ((section_name, config_id, attribute), (old_value, new_value))                if (                  not diff_sections.get(self.MODIFIED_ITEMS_KEY)                  or modified_value not in diff_sections[self.MODIFIED_ITEMS_KEY]              ):                  self.__create_or_append_list(                      diff_sections,                      self.MODIFIED_ITEMS_KEY,                      modified_value,                  )        def __get_section(self, section_name: str) -> Dict[str, List]:          if section_name in self._unconflicted_sections:              if not self.get(self.UNCONFLICTED_SECTION_KEY):                  self[self.UNCONFLICTED_SECTION_KEY] = {}              return self[self.UNCONFLICTED_SECTION_KEY]            if not self.get(self.CONFLICTED_SECTION_KEY):              self[self.CONFLICTED_SECTION_KEY] = {}          return self[self.CONFLICTED_SECTION_KEY]        def __create_or_append_list(self, diff_dict, key, value):          if diff_dict.get(key):              diff_dict[key].append(value)          else:              diff_dict[key] = [value]        def __get_changed_entity_attribute(self, attribute_bracket_notation):          """Split the section name, the config id (if exists), and the attribute name (if exists)          from JSON bracket notation.          """          try:              section_name, config_id, attribute = re.findall(r"\[\'(.*?)\'\]", attribute_bracket_notation)          except ValueError:              try:                  section_name, config_id = re.findall(r"\[\'(.*?)\'\]", attribute_bracket_notation)                  attribute = None              except ValueError:                  section_name = re.findall(r"\[\'(.*?)\'\]", attribute_bracket_notation)[0]                  config_id = None                  attribute = None            return section_name, config_id, attribute        def __rename_global_node_name(self, node_name):          if node_name == _JsonSerializer._GLOBAL_NODE_NAME:              return "Global Configuration"          return node_name


#  # 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 json  from copy import copy  from typing import Optional, Set, Union    from deepdiff import DeepDiff    from ...logger._taipy_logger import _TaipyLogger  from .._config import _Config  from .._serializer._json_serializer import _JsonSerializer  from ._comparator_result import _ComparatorResult      class _ConfigComparator:      def __init__(self):          self._unconflicted_sections: Set[str] = set()          self.__logger = _TaipyLogger._get_logger()        def _add_unconflicted_section(self, section_name: Union[str, Set[str]]):          if isinstance(section_name, str):              section_name = {section_name}            self._unconflicted_sections.update(section_name)        def _find_conflict_config(          self,          old_config: _Config,          new_config: _Config,          old_version_number: Optional[str] = None,          new_version_number: Optional[str] = None,      ):          """Compare between 2 _Config object to check for compatibility.            Args:              old_config (_Config): The old _Config.              new_config (_Config): The new _Config.              old_version_number (str, optional): The old version number for logging. Defaults to None.              new_version_number (str, optional): The new version number for logging. Defaults to None.            Returns:              _ComparatorResult: Return a _ComparatorResult dictionary with the following format:          ```python          {              "added_items": [                  ((section_name_1, config_id_1, attribute_1), added_object_1),                  ((section_name_2, config_id_2, attribute_2), added_object_2),              ],              "removed_items": [                  ((section_name_1, config_id_1, attribute_1), removed_object_1),                  ((section_name_2, config_id_2, attribute_2), removed_object_2),              ],              "modified_items": [                  ((section_name_1, config_id_1, attribute_1), (old_value_1, new_value_1)),                  ((section_name_2, config_id_2, attribute_2), (old_value_2, new_value_2)),              ],          }          ```          """          comparator_result = self.__get_config_diff(old_config, new_config)          self.__log_find_conflict_message(comparator_result, old_version_number, new_version_number)          return comparator_result        def _compare(          self,          config_1: _Config,          config_2: _Config,          version_number_1: str,          version_number_2: str,      ):          """Compare between 2 _Config object to check for compatibility.            Args:              config_1 (_Config): The old _Config.              config_2 (_Config): The new _Config.              version_number_1 (str): The old version number for logging.              version_number_2 (str): The new version number for logging.          """          comparator_result = self.__get_config_diff(config_1, config_2)          self.__log_comparison_message(comparator_result, version_number_1, version_number_2)            return comparator_result        def __get_config_diff(self, config_1, config_2):          json_config_1 = json.loads(_JsonSerializer._serialize(config_1))          json_config_2 = json.loads(_JsonSerializer._serialize(config_2))            config_deepdiff = DeepDiff(json_config_1, json_config_2, ignore_order=True)            comparator_result = _ComparatorResult(copy(self._unconflicted_sections))            comparator_result._check_added_items(config_deepdiff, json_config_2)          comparator_result._check_removed_items(config_deepdiff, json_config_1)          comparator_result._check_modified_items(config_deepdiff, json_config_1, json_config_2)          comparator_result._sort_by_section()            return comparator_result        def __log_comparison_message(          self,          comparator_result: _ComparatorResult,          version_number_1: str,          version_number_2: str,      ):          config_str_1 = f"version {version_number_1} Configuration"          config_str_2 = f"version {version_number_2} Configuration"            diff_messages = []          for _, sections in comparator_result.items():              diff_messages = self.__get_messages(sections)            if diff_messages:              self.__logger.info(                  f"Differences between {config_str_1} and {config_str_2}:\n\t" + "\n\t".join(diff_messages)              )          else:              self.__logger.info(f"There is no difference between {config_str_1} and {config_str_2}.")        def __log_find_conflict_message(          self,          comparator_result: _ComparatorResult,          old_version_number: Optional[str] = None,          new_version_number: Optional[str] = None,      ):          old_config_str = (              f"configuration for version {old_version_number}" if old_version_number else "current configuration"          )          new_config_str = (              f"configuration for version {new_version_number}" if new_version_number else "current configuration"          )            if unconflicted_sections := comparator_result.get(_ComparatorResult.UNCONFLICTED_SECTION_KEY):              unconflicted_messages = self.__get_messages(unconflicted_sections)              self.__logger.info(                  f"There are non-conflicting changes between the {old_config_str}"                  f" and the {new_config_str}:\n\t" + "\n\t".join(unconflicted_messages)              )            if conflicted_sections := comparator_result.get(_ComparatorResult.CONFLICTED_SECTION_KEY):              conflicted_messages = self.__get_messages(conflicted_sections)              self.__logger.error(                  f"The {old_config_str} conflicts with the {new_config_str}:\n\t" + "\n\t".join(conflicted_messages)              )        def __get_messages(self, diff_sections):          dq = '"'          messages = []            if added_items := diff_sections.get(_ComparatorResult.ADDED_ITEMS_KEY):              for diff in added_items:                  ((section_name, config_id, attribute), added_object) = diff                  messages.append(                      f"{section_name} {dq}{config_id}{dq} "                      f"{f'has attribute {dq}{attribute}{dq}' if attribute else 'was'} added: {added_object}"                  )            if removed_items := diff_sections.get(_ComparatorResult.REMOVED_ITEMS_KEY):              for diff in removed_items:                  ((section_name, config_id, attribute), removed_object) = diff                  messages.append(                      f"{section_name} {dq}{config_id}{dq} "                      f"{f'has attribute {dq}{attribute}{dq}' if attribute else 'was'} removed"                  )            if modified_items := diff_sections.get(_ComparatorResult.MODIFIED_ITEMS_KEY):              for diff in modified_items:                  ((section_name, config_id, attribute), (old_value, new_value)) = diff                  messages.append(                      f"{section_name} {dq}{config_id}{dq} "                      f"{f'has attribute {dq}{attribute}{dq}' if attribute else 'was'} modified: "                      f"{old_value} -> {new_value}"                  )            return messages


import pathlib  import sys    from cookiecutter.main import cookiecutter    import taipy  from taipy._cli._base_cli import _CLI      class _ScaffoldCLI:      __TAIPY_PATH = pathlib.Path(taipy.__file__).parent.resolve() / "templates"        _TEMPLATE_MAP = {str(x.name): str(x) for x in __TAIPY_PATH.iterdir() if x.is_dir()}        @classmethod      def create_parser(cls):          create_parser = _CLI._add_subparser("create", help="Create a new Taipy application.")          create_parser.add_argument(              "--template",              choices=list(cls._TEMPLATE_MAP.keys()),              default="default",              help="The Taipy template to create new application.",          )        @classmethod      def parse_arguments(cls):          args = _CLI._parse()            if getattr(args, "which", None) == "create":              cookiecutter(cls._TEMPLATE_MAP[args.template])              sys.exit(0)


import subprocess  import sys    from taipy._cli._base_cli import _CLI      class _RunCLI:      @classmethod      def create_parser(cls):          run_parser = _CLI._add_subparser("run", help="Run a Taipy application.")          run_parser.add_argument(              "application_main_file",          )            sub_run_parser = run_parser.add_subparsers(title="subcommands")          sub_run_parser.add_parser(              "external-args",              help="""                  Arguments defined after this keyword will be considered as external arguments                  to be passed to the application              """,          )        @classmethod      def parse_arguments(cls):          args = _CLI._parse()            if getattr(args, "which", None) == "run":              all_args = sys.argv[3:]  # First 3 args are always (1) Python executable, (2) run, (3) Python file                external_args = []              try:                  external_args_index = all_args.index("external-args")              except ValueError:                  pass              else:                  external_args.extend(all_args[external_args_index + 1 :])                  all_args = all_args[:external_args_index]                taipy_args = [f"--taipy-{arg[2:]}" if arg.startswith("--") else arg for arg in all_args]                subprocess.run(                  [sys.executable, args.application_main_file, *(external_args + taipy_args)],                  stdout=sys.stdout,                  stderr=sys.stdout,              )                sys.exit(0)


import sys    from taipy._cli._base_cli import _CLI  from taipy.logger._taipy_logger import _TaipyLogger      class _HelpCLI:      __logger = _TaipyLogger._get_logger()        @classmethod      def create_parser(cls):          create_parser = _CLI._add_subparser("help", help="Show the Taipy help message.", add_help=False)          create_parser.add_argument(              "command", nargs="?", type=str, const="", default="", help="Show the help message of the command."          )        @classmethod      def parse_arguments(cls):          args = _CLI._parse()            if getattr(args, "which", None) == "help":              if args.command:                  if args.command in _CLI._sub_taipyparsers.keys():                      _CLI._sub_taipyparsers.get(args.command).print_help()                  else:                      cls.__logger.error(f"{args.command} is not a valid command.")              else:                  _CLI._parser.print_help()                sys.exit(0)


import argparse  from typing import Dict      class _CLI:      """Argument parser for Taipy application."""        # The conflict_handler is set to "resolve" to override conflict arguments      _subparser_action = None      _parser = argparse.ArgumentParser(conflict_handler="resolve")        _sub_taipyparsers: Dict[str, argparse.ArgumentParser] = {}      _arg_groups: Dict[str, argparse._ArgumentGroup] = {}        @classmethod      def _add_subparser(cls, name: str, **kwargs) -> argparse.ArgumentParser:          """Create a new subparser and return a argparse handler."""          if subparser := cls._sub_taipyparsers.get(name):              return subparser            if not cls._subparser_action:              cls._subparser_action = cls._parser.add_subparsers()            subparser = cls._subparser_action.add_parser(              name=name,              conflict_handler="resolve",              **kwargs,          )          cls._sub_taipyparsers[name] = subparser          subparser.set_defaults(which=name)          return subparser        @classmethod      def _add_groupparser(cls, title: str, description: str = "") -> argparse._ArgumentGroup:          """Create a new group for arguments and return a argparser handler."""          if groupparser := cls._arg_groups.get(title):              return groupparser            groupparser = cls._parser.add_argument_group(title=title, description=description)          cls._arg_groups[title] = groupparser          return groupparser        @classmethod      def _parse(cls):          """Parse and return only known arguments."""          args, _ = cls._parser.parse_known_args()          return args        @classmethod      def _remove_argument(cls, arg: str):          """Remove an argument from the parser. Note that the `arg` must be without --.            Source: https://stackoverflow.com/questions/32807319/disable-remove-argument-in-argparse          """          for action in cls._parser._actions:              opts = action.option_strings              if (opts and opts[0] == arg) or action.dest == arg:                  cls._parser._remove_action(action)                  break            for argument_group in cls._parser._action_groups:              for group_action in argument_group._group_actions:                  opts = group_action.option_strings                  if (opts and opts[0] == arg) or group_action.dest == arg:                      argument_group._group_actions.remove(group_action)                      return


from ._cli import _CLI


import typing as t      class Icon:      """Small image in the User Interface.        Icons are typically used in controls like [button](../gui/viselements/button.md)      or items in a [menu](../gui/viselements/menu.md).        Attributes:          path (str): The path to the image file.          text (Optional[str]): The text associated to the image or None if there is none.          svg (Optional[bool]): True if the image is svg.        If a text is associated to an icon, it is rendered by the visual elements that      uses this Icon.      """        @staticmethod      def get_dict_or(value: t.Union[str, t.Any]) -> t.Union[str, dict]:          return value._to_dict() if isinstance(value, Icon) else value        def __init__(          self,          path: str,          text: t.Optional[str] = None,          light_path: t.Optional[bool] = None,          dark_path: t.Optional[bool] = None,      ) -> None:          """Initialize a new Icon.            Arguments:              path (str): The path to an image file.
                  This path must be relative to and inside the root directory of the                  application (where the Python file that created the `Gui` instance                  is located).
                  In situations where the image file is located outside the application                  directory, a _path mapping_ must be used: the _path_mapping_ parameter                  of the `Gui^` constructor makes it possible to access a resource anywhere                  on the server filesystem, as if it were located in a subdirectory of                  the application directory.              text (Optional[str]): The text associated to the image. If *text* is None,                  there is no text associated to this image.              light_path (Optional[str]): The path to the light theme image (fallback to *path* if not defined).              dark_path (Optional[str]): The path to the dark theme image (fallback to *path* if not defined).          """          self.path = path          self.text = text          if light_path is not None:              self.light_path = light_path          if dark_path is not None:              self.dark_path = dark_path        def _to_dict(self, a_dict: t.Optional[dict] = None) -> dict:          if a_dict is None:              a_dict = {}          a_dict["path"] = self.path          if self.text is not None:              a_dict["text"] = self.text          if hasattr(self, "light_path") and self.light_path is not None:              a_dict["lightPath"] = self.light_path          if hasattr(self, "dark_path") and self.dark_path is not None:              a_dict["darkPath"] = self.dark_path          return a_dict