import datetime  import json  import os  from unittest import mock    from src.taipy.config import Config  from src.taipy.config._serializer._json_serializer import _JsonSerializer  from src.taipy.config.common.frequency import Frequency  from src.taipy.config.common.scope import Scope  from tests.config.utils.named_temporary_file import NamedTemporaryFile  from tests.config.utils.section_for_tests import SectionForTest  from tests.config.utils.unique_section_for_tests import UniqueSectionForTest      def add(a, b):      return a + b      class CustomClass:      a = None      b = None      class CustomEncoder(json.JSONEncoder):      def default(self, o):          if isinstance(o, datetime):              result = {"__type__": "Datetime", "__value__": o.isoformat()}          else:              result = json.JSONEncoder.default(self, o)          return result      class CustomDecoder(json.JSONDecoder):      def __init__(self, *args, **kwargs):          json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)        def object_hook(self, source):          if source.get("__type__") == "Datetime":              return datetime.fromisoformat(source.get("__value__"))          else:              return source      def test_write_toml_configuration_file():      expected_toml_config = """  [TAIPY]    [unique_section_name]  attribute = "my_attribute"  prop = "my_prop"  prop_int = "1:int"  prop_bool = "False:bool"  prop_list = [ "p1", "1991-01-01T00:00:00:datetime", "1d0h0m0s:timedelta",]  prop_scope = "SCENARIO:SCOPE"  prop_freq = "QUARTERLY:FREQUENCY"  baz = "ENV[QUX]"  quux = "ENV[QUUZ]:bool"  corge = [ "grault", "ENV[GARPLY]", "ENV[WALDO]:int", "3.0:float",]    [section_name.default]  attribute = "default_attribute"  prop = "default_prop"  prop_int = "0:int"    [section_name.my_id]  attribute = "my_attribute"  prop = "default_prop"  prop_int = "1:int"  prop_bool = "False:bool"  prop_list = [ "unique_section_name:SECTION",]  prop_scope = "SCENARIO"  baz = "ENV[QUX]"      """.strip()      tf = NamedTemporaryFile()      with mock.patch.dict(          os.environ, {"FOO": "in_memory", "QUX": "qux", "QUUZ": "true", "GARPLY": "garply", "WALDO": "17"}      ):          unique_section = Config.configure_unique_section_for_tests(              attribute="my_attribute",              prop="my_prop",              prop_int=1,              prop_bool=False,              prop_list=["p1", datetime.datetime(1991, 1, 1), datetime.timedelta(days=1)],              prop_scope=Scope.SCENARIO,              prop_freq=Frequency.QUARTERLY,              baz="ENV[QUX]",              quux="ENV[QUUZ]:bool",              corge=("grault", "ENV[GARPLY]", "ENV[WALDO]:int", 3.0),          )          Config.configure_section_for_tests(              "my_id",              "my_attribute",              prop_int=1,              prop_bool=False,              prop_list=[unique_section],              prop_scope="SCENARIO",              baz="ENV[QUX]",          )            Config.backup(tf.filename)          actual_config = tf.read().strip()          assert actual_config == expected_toml_config      def test_read_toml_configuration_file():      toml_config = """  [TAIPY]  foo = "bar"    [unique_section_name]  attribute = "my_attribute"  prop = "my_prop"  prop_int = "1:int"  prop_bool = "False:bool"  prop_list = [ "p1", "1991-01-01T00:00:00:datetime", "1d0h0m0s:timedelta",]  prop_scope = "SCENARIO:SCOPE"  prop_freq = "QUARTERLY:FREQUENCY"  baz = "ENV[QUX]"  quux = "ENV[QUUZ]:bool"  corge = [ "grault", "ENV[GARPLY]", "ENV[WALDO]:int", "3.0:float",]    [TAIPY.custom_properties]  bar = "baz"    [section_name.default]  attribute = "default_attribute"  prop = "default_prop"  prop_int = "0:int"    [section_name.my_id]  attribute = "my_attribute"  prop = "default_prop"  prop_int = "1:int"  prop_bool = "False:bool"  prop_list = [ "unique_section_name", "section_name.my_id",]  prop_scope = "SCENARIO:SCOPE"  baz = "ENV[QUX]"      """.strip()      tf = NamedTemporaryFile(toml_config)      with mock.patch.dict(          os.environ, {"FOO": "in_memory", "QUX": "qux", "QUUZ": "true", "GARPLY": "garply", "WALDO": "17"}      ):          Config.override(tf.filename)            assert Config.global_config.foo == "bar"          assert Config.global_config.custom_properties.get("bar") == "baz"            assert Config.unique_sections is not None          assert Config.unique_sections[UniqueSectionForTest.name] is not None          assert Config.unique_sections[UniqueSectionForTest.name].attribute == "my_attribute"          assert Config.unique_sections[UniqueSectionForTest.name].prop == "my_prop"          assert Config.unique_sections[UniqueSectionForTest.name].prop_int == 1          assert Config.unique_sections[UniqueSectionForTest.name].prop_bool is False          assert Config.unique_sections[UniqueSectionForTest.name].prop_list == [              "p1",              datetime.datetime(1991, 1, 1),              datetime.timedelta(days=1),          ]          assert Config.unique_sections[UniqueSectionForTest.name].prop_scope == Scope.SCENARIO          assert Config.unique_sections[UniqueSectionForTest.name].prop_freq == Frequency.QUARTERLY          assert Config.unique_sections[UniqueSectionForTest.name].baz == "qux"          assert Config.unique_sections[UniqueSectionForTest.name].quux is True          assert Config.unique_sections[UniqueSectionForTest.name].corge == [              "grault",              "garply",              17,              3.0,          ]            assert Config.sections is not None          assert len(Config.sections) == 1          assert Config.sections[SectionForTest.name] is not None          assert len(Config.sections[SectionForTest.name]) == 2          assert Config.sections[SectionForTest.name]["default"] is not None          assert Config.sections[SectionForTest.name]["default"].attribute == "default_attribute"          assert Config.sections[SectionForTest.name]["default"].prop == "default_prop"          assert Config.sections[SectionForTest.name]["default"].prop_int == 0          assert Config.sections[SectionForTest.name]["my_id"] is not None          assert Config.sections[SectionForTest.name]["my_id"].attribute == "my_attribute"          assert Config.sections[SectionForTest.name]["my_id"].prop == "default_prop"          assert Config.sections[SectionForTest.name]["my_id"].prop_int == 1          assert Config.sections[SectionForTest.name]["my_id"].prop_bool is False          assert Config.sections[SectionForTest.name]["my_id"].prop_list == ["unique_section_name", "section_name.my_id"]          assert Config.sections[SectionForTest.name]["my_id"].prop_scope == Scope.SCENARIO          assert Config.sections[SectionForTest.name]["my_id"].baz == "qux"            tf2 = NamedTemporaryFile()          Config.backup(tf2.filename)          actual_config_2 = tf2.read().strip()          assert actual_config_2 == toml_config      def test_read_write_toml_configuration_file_with_function_and_class():      expected_toml_config = """  [TAIPY]    [unique_section_name]  attribute = "my_attribute"  prop = "my_prop"  prop_list = [ "tests.config.test_section_serialization.CustomEncoder:class", "tests.config.test_section_serialization.CustomDecoder:class",]    [section_name.default]  attribute = "default_attribute"  prop = "default_prop"  prop_int = "0:int"    [section_name.my_id]  attribute = "my_attribute"  prop = "default_prop"  prop_int = "0:int"  prop_fct_list = [ "tests.config.test_section_serialization.add:function",]  prop_class_list = [ "tests.config.test_section_serialization.CustomClass:class",]    [section_name.my_id_2]  attribute = "my_attribute_2"  prop = "default_prop"  prop_int = "0:int"  prop_fct_list = [ "builtins.print:function", "builtins.pow:function",]      """.strip()        tf = NamedTemporaryFile()      Config.configure_unique_section_for_tests(          attribute="my_attribute",          prop="my_prop",          prop_list=[CustomEncoder, CustomDecoder],      )      Config.configure_section_for_tests(          "my_id",          "my_attribute",          prop_fct_list=[add],          prop_class_list=[CustomClass],      )        Config.configure_section_for_tests(          "my_id_2",          "my_attribute_2",          prop_fct_list=[print, pow],      )        Config.backup(tf.filename)      actual_exported_toml = tf.read().strip()      assert actual_exported_toml == expected_toml_config        Config.override(tf.filename)      tf2 = NamedTemporaryFile()      Config.backup(tf2.filename)        actual_exported_toml_2 = tf2.read().strip()      assert actual_exported_toml_2 == expected_toml_config      def test_write_json_configuration_file():      expected_json_config = """  {  "TAIPY": {},  "unique_section_name": {  "attribute": "my_attribute",  "prop": "my_prop",  "prop_int": "1:int",  "prop_bool": "False:bool",  "prop_list": [  "p1",  "1991-01-01T00:00:00:datetime",  "1d0h0m0s:timedelta"  ],  "prop_scope": "SCENARIO:SCOPE",  "prop_freq": "QUARTERLY:FREQUENCY"  },  "section_name": {  "default": {  "attribute": "default_attribute",  "prop": "default_prop",  "prop_int": "0:int"  },  "my_id": {  "attribute": "my_attribute",  "prop": "default_prop",  "prop_int": "1:int",  "prop_bool": "False:bool",  "prop_list": [  "unique_section_name:SECTION"  ],  "prop_scope": "SCENARIO",  "baz": "ENV[QUX]"  }  }  }      """.strip()      tf = NamedTemporaryFile()      Config._serializer = _JsonSerializer()        unique_section = Config.configure_unique_section_for_tests(          attribute="my_attribute",          prop="my_prop",          prop_int=1,          prop_bool=False,          prop_list=["p1", datetime.datetime(1991, 1, 1), datetime.timedelta(days=1)],          prop_scope=Scope.SCENARIO,          prop_freq=Frequency.QUARTERLY,      )      Config.configure_section_for_tests(          "my_id",          "my_attribute",          prop_int=1,          prop_bool=False,          prop_list=[unique_section],          prop_scope="SCENARIO",          baz="ENV[QUX]",      )      Config.backup(tf.filename)      actual_config = tf.read()      assert actual_config == expected_json_config      def test_read_json_configuration_file():      json_config = """  {  "TAIPY": {  "root_folder": "./taipy/",  "storage_folder": ".data/",  "repository_type": "filesystem"  },  "unique_section_name": {  "attribute": "my_attribute",  "prop": "my_prop",  "prop_int": "1:int",  "prop_bool": "False:bool",  "prop_list": [  "p1",  "1991-01-01T00:00:00:datetime",  "1d0h0m0s:timedelta"  ],  "prop_scope": "SCENARIO:SCOPE",  "prop_freq": "QUARTERLY:FREQUENCY"  },  "section_name": {  "default": {  "attribute": "default_attribute",  "prop": "default_prop",  "prop_int": "0:int"  },  "my_id": {  "attribute": "my_attribute",  "prop": "default_prop",  "prop_int": "1:int",  "prop_bool": "False:bool",  "prop_list": [  "unique_section_name"  ],  "prop_scope": "SCENARIO"  }  }  }      """.strip()      Config._serializer = _JsonSerializer()      tf = NamedTemporaryFile(json_config)        Config.override(tf.filename)        assert Config.unique_sections is not None      assert Config.unique_sections[UniqueSectionForTest.name] is not None      assert Config.unique_sections[UniqueSectionForTest.name].attribute == "my_attribute"      assert Config.unique_sections[UniqueSectionForTest.name].prop == "my_prop"      assert Config.unique_sections[UniqueSectionForTest.name].prop_int == 1      assert Config.unique_sections[UniqueSectionForTest.name].prop_bool is False      assert Config.unique_sections[UniqueSectionForTest.name].prop_list == [          "p1",          datetime.datetime(1991, 1, 1),          datetime.timedelta(days=1),      ]      assert Config.unique_sections[UniqueSectionForTest.name].prop_scope == Scope.SCENARIO      assert Config.unique_sections[UniqueSectionForTest.name].prop_freq == Frequency.QUARTERLY        assert Config.sections is not None      assert len(Config.sections) == 1      assert Config.sections[SectionForTest.name] is not None      assert len(Config.sections[SectionForTest.name]) == 2      assert Config.sections[SectionForTest.name]["default"] is not None      assert Config.sections[SectionForTest.name]["default"].attribute == "default_attribute"      assert Config.sections[SectionForTest.name]["default"].prop == "default_prop"      assert Config.sections[SectionForTest.name]["default"].prop_int == 0      assert Config.sections[SectionForTest.name]["my_id"] is not None      assert Config.sections[SectionForTest.name]["my_id"].attribute == "my_attribute"      assert Config.sections[SectionForTest.name]["my_id"].prop == "default_prop"      assert Config.sections[SectionForTest.name]["my_id"].prop_int == 1      assert Config.sections[SectionForTest.name]["my_id"].prop_bool is False      assert Config.sections[SectionForTest.name]["my_id"].prop_list == ["unique_section_name"]        tf2 = NamedTemporaryFile()      Config.backup(tf2.filename)      actual_config_2 = tf2.read().strip()      assert actual_config_2 == json_config      def test_read_write_json_configuration_file_with_function_and_class():      expected_json_config = """  {  "TAIPY": {},  "unique_section_name": {  "attribute": "my_attribute",  "prop": "my_prop",  "prop_list": [  "tests.config.test_section_serialization.CustomEncoder:class",  "tests.config.test_section_serialization.CustomDecoder:class"  ]  },  "section_name": {  "default": {  "attribute": "default_attribute",  "prop": "default_prop",  "prop_int": "0:int"  },  "my_id": {  "attribute": "my_attribute",  "prop": "default_prop",  "prop_int": "0:int",  "prop_fct_list": [  "tests.config.test_section_serialization.add:function"  ],  "prop_class_list": [  "tests.config.test_section_serialization.CustomClass:class"  ]  },  "my_id_2": {  "attribute": "my_attribute_2",  "prop": "default_prop",  "prop_int": "0:int",  "prop_fct_list": [  "builtins.print:function",  "builtins.pow:function"  ]  }  }  }      """.strip()        Config._serializer = _JsonSerializer()      tf = NamedTemporaryFile()      Config.configure_unique_section_for_tests(          attribute="my_attribute",          prop="my_prop",          prop_list=[CustomEncoder, CustomDecoder],      )      Config.configure_section_for_tests(          "my_id",          "my_attribute",          prop_fct_list=[add],          prop_class_list=[CustomClass],      )      Config.configure_section_for_tests(          "my_id_2",          "my_attribute_2",          prop_fct_list=[print, pow],      )        Config.backup(tf.filename)      actual_exported_json = tf.read().strip()      assert actual_exported_json == expected_json_config        Config.override(tf.filename)      tf2 = NamedTemporaryFile()      Config.backup(tf2.filename)        actual_exported_json_2 = tf2.read().strip()      assert actual_exported_json_2 == expected_json_config


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


from src.taipy.config._config import _Config  from src.taipy.config.checker._checker import _Checker      class TestDefaultConfigChecker:      def test_check_default_config(self):          config = _Config._default_config()          collector = _Checker._check(config)          assert len(collector._errors) == 0          assert len(collector._infos) == 0          assert len(collector._warnings) == 0


from src.taipy.config.checker.issue import Issue  from src.taipy.config.checker.issue_collector import IssueCollector      class TestIssueCollector:      def test_add_error(self):          collector = IssueCollector()          assert len(collector.errors) == 0          assert len(collector.warnings) == 0          assert len(collector.infos) == 0          assert len(collector.all) == 0          collector._add_error("field", "value", "message", "checker")          assert len(collector.errors) == 1          assert len(collector.warnings) == 0          assert len(collector.infos) == 0          assert len(collector.all) == 1          assert collector.all[0] == Issue(IssueCollector._ERROR_LEVEL, "field", "value", "message", "checker")          collector._add_error("field", "value", "message", "checker")          assert len(collector.errors) == 2          assert len(collector.warnings) == 0          assert len(collector.infos) == 0          assert len(collector.all) == 2          assert collector.all[0] == Issue(IssueCollector._ERROR_LEVEL, "field", "value", "message", "checker")          assert collector.all[1] == Issue(IssueCollector._ERROR_LEVEL, "field", "value", "message", "checker")        def test_add_warning(self):          collector = IssueCollector()          assert len(collector.errors) == 0          assert len(collector.warnings) == 0          assert len(collector.infos) == 0          assert len(collector.all) == 0          collector._add_warning("field", "value", "message", "checker")          assert len(collector.errors) == 0          assert len(collector.warnings) == 1          assert len(collector.infos) == 0          assert len(collector.all) == 1          assert collector.all[0] == Issue(IssueCollector._WARNING_LEVEL, "field", "value", "message", "checker")          collector._add_warning("field", "value", "message", "checker")          assert len(collector.errors) == 0          assert len(collector.warnings) == 2          assert len(collector.infos) == 0          assert len(collector.all) == 2          assert collector.all[0] == Issue(IssueCollector._WARNING_LEVEL, "field", "value", "message", "checker")          assert collector.all[1] == Issue(IssueCollector._WARNING_LEVEL, "field", "value", "message", "checker")        def test_add_info(self):          collector = IssueCollector()          assert len(collector.errors) == 0          assert len(collector.warnings) == 0          assert len(collector.infos) == 0          assert len(collector.all) == 0          collector._add_info("field", "value", "message", "checker")          assert len(collector.errors) == 0          assert len(collector.warnings) == 0          assert len(collector.infos) == 1          assert len(collector.all) == 1          assert collector.all[0] == Issue(IssueCollector._INFO_LEVEL, "field", "value", "message", "checker")          collector._add_info("field", "value", "message", "checker")          assert len(collector.errors) == 0          assert len(collector.warnings) == 0          assert len(collector.infos) == 2          assert len(collector.all) == 2          assert collector.all[0] == Issue(IssueCollector._INFO_LEVEL, "field", "value", "message", "checker")          assert collector.all[1] == Issue(IssueCollector._INFO_LEVEL, "field", "value", "message", "checker")        def test_all(self):          collector = IssueCollector()          collector._add_info("foo", "bar", "baz", "qux")          assert collector.all[0] == Issue(IssueCollector._INFO_LEVEL, "foo", "bar", "baz", "qux")          collector._add_warning("foo2", "bar2", "baz2", "qux2")          assert collector.all[0] == Issue(IssueCollector._WARNING_LEVEL, "foo2", "bar2", "baz2", "qux2")          assert collector.all[1] == Issue(IssueCollector._INFO_LEVEL, "foo", "bar", "baz", "qux")          collector._add_warning("foo3", "bar3", "baz3", "qux3")          assert collector.all[0] == Issue(IssueCollector._WARNING_LEVEL, "foo2", "bar2", "baz2", "qux2")          assert collector.all[1] == Issue(IssueCollector._WARNING_LEVEL, "foo3", "bar3", "baz3", "qux3")          assert collector.all[2] == Issue(IssueCollector._INFO_LEVEL, "foo", "bar", "baz", "qux")          collector._add_info("field", "value", "message", "checker")          collector._add_error("field", "value", "message", "checker")          assert collector.all[0] == Issue(IssueCollector._ERROR_LEVEL, "field", "value", "message", "checker")          assert collector.all[1] == Issue(IssueCollector._WARNING_LEVEL, "foo2", "bar2", "baz2", "qux2")          assert collector.all[2] == Issue(IssueCollector._WARNING_LEVEL, "foo3", "bar3", "baz3", "qux3")          assert collector.all[3] == Issue(IssueCollector._INFO_LEVEL, "foo", "bar", "baz", "qux")          assert collector.all[4] == Issue(IssueCollector._INFO_LEVEL, "field", "value", "message", "checker")


import os  from unittest import mock  from unittest.mock import MagicMock    from src.taipy.config import Config  from src.taipy.config.checker._checker import _Checker  from src.taipy.config.checker.issue_collector import IssueCollector  from tests.config.utils.checker_for_tests import CheckerForTest      def test_register_checker():      checker = CheckerForTest      checker._check = MagicMock()      _Checker.add_checker(checker)      Config.check()      checker._check.assert_called_once()


import logging  from unittest import mock    from src.taipy.config._config import _Config  from src.taipy.config.checker._checkers._config_checker import _ConfigChecker  from src.taipy.config.checker.issue import Issue  from src.taipy.config.checker.issue_collector import IssueCollector      class MyCustomChecker(_ConfigChecker):      def _check(self) -> IssueCollector:          pass      def test__error():      with mock.patch.object(logging.Logger, "error"):          collector = IssueCollector()          assert len(collector.all) == 0          _ConfigChecker(_Config(), collector)._error("field", 17, "my message")          assert len(collector.all) == 1          assert len(collector.errors) == 1          assert len(collector.warnings) == 0          assert len(collector.infos) == 0          assert collector.errors[0] == Issue(IssueCollector._ERROR_LEVEL, "field", 17, "my message", "_ConfigChecker")            MyCustomChecker(_Config(), collector)._error("foo", "bar", "baz")          assert len(collector.all) == 2          assert len(collector.errors) == 2          assert len(collector.warnings) == 0          assert len(collector.infos) == 0          assert collector.errors[0] == Issue(IssueCollector._ERROR_LEVEL, "field", 17, "my message", "_ConfigChecker")          assert collector.errors[1] == Issue(IssueCollector._ERROR_LEVEL, "foo", "bar", "baz", "MyCustomChecker")      def test__warning():      collector = IssueCollector()      assert len(collector.all) == 0      _ConfigChecker(_Config(), collector)._warning("field", 17, "my message")      assert len(collector.all) == 1      assert len(collector.warnings) == 1      assert len(collector.errors) == 0      assert len(collector.infos) == 0      assert collector.warnings[0] == Issue(IssueCollector._WARNING_LEVEL, "field", 17, "my message", "_ConfigChecker")        MyCustomChecker(_Config(), collector)._warning("foo", "bar", "baz")      assert len(collector.all) == 2      assert len(collector.warnings) == 2      assert len(collector.errors) == 0      assert len(collector.infos) == 0      assert collector.warnings[0] == Issue(IssueCollector._WARNING_LEVEL, "field", 17, "my message", "_ConfigChecker")      assert collector.warnings[1] == Issue(IssueCollector._WARNING_LEVEL, "foo", "bar", "baz", "MyCustomChecker")      def test__info():      collector = IssueCollector()      assert len(collector.all) == 0      _ConfigChecker(_Config(), collector)._info("field", 17, "my message")      assert len(collector.all) == 1      assert len(collector.infos) == 1      assert len(collector.errors) == 0      assert len(collector.warnings) == 0      assert collector.infos[0] == Issue(IssueCollector._INFO_LEVEL, "field", 17, "my message", "_ConfigChecker")        MyCustomChecker(_Config(), collector)._info("foo", "bar", "baz")      assert len(collector.all) == 2      assert len(collector.infos) == 2      assert len(collector.errors) == 0      assert len(collector.warnings) == 0      assert collector.infos[0] == Issue(IssueCollector._INFO_LEVEL, "field", 17, "my message", "_ConfigChecker")      assert collector.infos[1] == Issue(IssueCollector._INFO_LEVEL, "foo", "bar", "baz", "MyCustomChecker")


from src.taipy.config import IssueCollector  from src.taipy.config.checker._checkers._config_checker import _ConfigChecker      class CheckerForTest(_ConfigChecker):        def _check(self) -> IssueCollector:          return self._collector


from copy import copy  from typing import Any, Dict, List, Optional    from src.taipy.config import Config, Section  from src.taipy.config._config import _Config  from src.taipy.config.common._config_blocker import _ConfigBlocker    from .section_for_tests import SectionForTest      class SectionOfSectionsListForTest(Section):        name = "list_section_name"      _MY_ATTRIBUTE_KEY = "attribute"      _SECTIONS_LIST_KEY = "sections_list"        def __init__(self, id: str, attribute: Any = None, sections_list: List = None, **properties):          self._attribute = attribute          self._sections_list = sections_list if sections_list else []          super().__init__(id, **properties)        def __copy__(self):          return SectionOfSectionsListForTest(              self.id, self._attribute, copy(self._sections_list), **copy(self._properties)          )        @property      def attribute(self):          return self._replace_templates(self._attribute)        @attribute.setter  # type: ignore      @_ConfigBlocker._check()      def attribute(self, val):          self._attribute = val        @property      def sections_list(self):          return list(self._sections_list)        @sections_list.setter  # type: ignore      @_ConfigBlocker._check()      def sections_list(self, val):          self._sections_list = val        def _clean(self):          self._attribute = None          self._sections_list = []          self._properties.clear()        def _to_dict(self):          as_dict = {}          if self._attribute is not None:              as_dict[self._MY_ATTRIBUTE_KEY] = self._attribute          if self._sections_list:              as_dict[self._SECTIONS_LIST_KEY] = self._sections_list          as_dict.update(self._properties)          return as_dict        @classmethod      def _from_dict(cls, as_dict: Dict[str, Any], id: str, config: Optional[_Config] = None):          as_dict.pop(cls._ID_KEY, id)          attribute = as_dict.pop(cls._MY_ATTRIBUTE_KEY, None)          section_configs = config._sections.get(SectionForTest.name, None) or []  # type: ignore          sections_list = []          if inputs_as_str := as_dict.pop(cls._SECTIONS_LIST_KEY, None):              for section_id in inputs_as_str:                  if section_id in section_configs:                      sections_list.append(section_configs[section_id])                  else:                      sections_list.append(section_id)          return SectionOfSectionsListForTest(id=id, attribute=attribute, sections_list=sections_list, **as_dict)        def _update(self, as_dict: Dict[str, Any], default_section=None):          self._attribute = as_dict.pop(self._MY_ATTRIBUTE_KEY, self._attribute)          if self._attribute is None and default_section:              self._attribute = default_section._attribute          self._sections_list = as_dict.pop(self._SECTIONS_LIST_KEY, self._sections_list)          if self._sections_list is None and default_section:              self._sections_list = default_section._sections_list          self._properties.update(as_dict)          if default_section:              self._properties = {**default_section.properties, **self._properties}        @staticmethod      def _configure(id: str, attribute: str, sections_list: List = None, **properties):          section = SectionOfSectionsListForTest(id, attribute, sections_list, **properties)          Config._register(section)          return Config.sections[SectionOfSectionsListForTest.name][id]


import os  import tempfile      class NamedTemporaryFile:      def __init__(self, content=None):          with tempfile.NamedTemporaryFile("w", delete=False) as fd:              if content:                  fd.write(content)              self.filename = fd.name        def read(self):          with open(self.filename, "r") as fp:              return fp.read()        def __del__(self):          os.unlink(self.filename)


from copy import copy  from typing import Any, Dict, Optional    from src.taipy.config import Config, Section  from src.taipy.config._config import _Config  from src.taipy.config.common._config_blocker import _ConfigBlocker      class SectionForTest(Section):        name = "section_name"      _MY_ATTRIBUTE_KEY = "attribute"        def __init__(self, id: str, attribute: Any = None, **properties):          self._attribute = attribute          super().__init__(id, **properties)        def __copy__(self):          return SectionForTest(self.id, self._attribute, **copy(self._properties))        @property      def attribute(self):          return self._replace_templates(self._attribute)        @attribute.setter  # type: ignore      @_ConfigBlocker._check()      def attribute(self, val):          self._attribute = val        def _clean(self):          self._attribute = None          self._properties.clear()        def _to_dict(self):          as_dict = {}          if self._attribute is not None:              as_dict[self._MY_ATTRIBUTE_KEY] = self._attribute          as_dict.update(self._properties)          return as_dict        @classmethod      def _from_dict(cls, as_dict: Dict[str, Any], id: str, config: Optional[_Config] = None):          as_dict.pop(cls._ID_KEY, id)          attribute = as_dict.pop(cls._MY_ATTRIBUTE_KEY, None)          return SectionForTest(id=id, attribute=attribute, **as_dict)        def _update(self, as_dict: Dict[str, Any], default_section=None):          self._attribute = as_dict.pop(self._MY_ATTRIBUTE_KEY, self._attribute)          if self._attribute is None and default_section:              self._attribute = default_section._attribute          self._properties.update(as_dict)          if default_section:              self._properties = {**default_section.properties, **self._properties}        @staticmethod      def _configure(id: str, attribute: str, **properties):          section = SectionForTest(id, attribute, **properties)          Config._register(section)          return Config.sections[SectionForTest.name][id]


from copy import copy  from typing import Any, Dict, Optional    from src.taipy.config import Config  from src.taipy.config._config import _Config  from src.taipy.config.common._config_blocker import _ConfigBlocker  from src.taipy.config.unique_section import UniqueSection      class UniqueSectionForTest(UniqueSection):        name = "unique_section_name"      _MY_ATTRIBUTE_KEY = "attribute"        def __init__(self, attribute: str = None, **properties):          self._attribute = attribute          super().__init__(**properties)        def __copy__(self):          return UniqueSectionForTest(self._attribute, **copy(self._properties))        @property      def attribute(self):          return self._replace_templates(self._attribute)        @attribute.setter  # type: ignore      @_ConfigBlocker._check()      def attribute(self, val):          self._attribute = val        def _clean(self):          self._attribute = None          self._properties.clear()        def _to_dict(self):          as_dict = {}          if self._attribute is not None:              as_dict[self._MY_ATTRIBUTE_KEY] = self._attribute          as_dict.update(self._properties)          return as_dict        @classmethod      def _from_dict(cls, as_dict: Dict[str, Any], id=None, config: Optional[_Config] = None):          as_dict.pop(cls._ID_KEY, None)          attribute = as_dict.pop(cls._MY_ATTRIBUTE_KEY, None)          return UniqueSectionForTest(attribute=attribute, **as_dict)        def _update(self, as_dict: Dict[str, Any], default_section=None):          self._attribute = as_dict.pop(self._MY_ATTRIBUTE_KEY, self._attribute)          if self._attribute is None and default_section:              self._attribute = default_section._attribute          self._properties.update(as_dict)          if default_section:              self._properties = {**default_section.properties, **self._properties}        @staticmethod      def _configure(attribute: str, **properties):          section = UniqueSectionForTest(attribute, **properties)          Config._register(section)          return Config.unique_sections[UniqueSectionForTest.name]


import pytest    from src.taipy.config.common._validate_id import _validate_id  from src.taipy.config.exceptions.exceptions import InvalidConfigurationId      class TestId:      def test_validate_id(self):          s = _validate_id("foo")          assert s == "foo"          with pytest.raises(InvalidConfigurationId):              _validate_id("1foo")          with pytest.raises(InvalidConfigurationId):              _validate_id("foo bar")          with pytest.raises(InvalidConfigurationId):              _validate_id("foo/foo$")          with pytest.raises(InvalidConfigurationId):              _validate_id("")          with pytest.raises(InvalidConfigurationId):              _validate_id(" ")          with pytest.raises(InvalidConfigurationId):              _validate_id("class")          with pytest.raises(InvalidConfigurationId):              _validate_id("def")          with pytest.raises(InvalidConfigurationId):              _validate_id("with")          with pytest.raises(InvalidConfigurationId):              _validate_id("CYCLE")          with pytest.raises(InvalidConfigurationId):              _validate_id("SCENARIO")          with pytest.raises(InvalidConfigurationId):              _validate_id("SEQUENCE")          with pytest.raises(InvalidConfigurationId):              _validate_id("TASK")          with pytest.raises(InvalidConfigurationId):              _validate_id("DATANODE")


import pytest    from src.taipy.config.common.scope import Scope      def test_scope():      # Test __ge__ method      assert Scope.GLOBAL >= Scope.GLOBAL      assert Scope.GLOBAL >= Scope.CYCLE      assert Scope.CYCLE >= Scope.CYCLE      assert Scope.GLOBAL >= Scope.SCENARIO      assert Scope.CYCLE >= Scope.SCENARIO      assert Scope.SCENARIO >= Scope.SCENARIO      with pytest.raises(TypeError):          assert Scope.SCENARIO >= "testing string"        # Test __gt__ method      assert Scope.GLOBAL > Scope.CYCLE      assert Scope.GLOBAL > Scope.SCENARIO      assert Scope.CYCLE > Scope.SCENARIO      with pytest.raises(TypeError):          assert Scope.SCENARIO > "testing string"        # Test __le__ method      assert Scope.GLOBAL <= Scope.GLOBAL      assert Scope.CYCLE <= Scope.GLOBAL      assert Scope.CYCLE <= Scope.CYCLE      assert Scope.SCENARIO <= Scope.GLOBAL      assert Scope.SCENARIO <= Scope.CYCLE      assert Scope.SCENARIO <= Scope.SCENARIO      with pytest.raises(TypeError):          assert Scope.SCENARIO <= "testing string"        # Test __lt__ method      assert Scope.SCENARIO < Scope.GLOBAL      assert Scope.SCENARIO < Scope.GLOBAL      assert Scope.SCENARIO < Scope.CYCLE      with pytest.raises(TypeError):          assert Scope.SCENARIO < "testing string"


import argparse  import re  import sys    import pytest    from src.taipy._cli._base_cli import _CLI    if sys.version_info >= (3, 10):      argparse_options_str = "options:"  else:      argparse_options_str = "optional arguments:"      def preprocess_stdout(stdout):      stdout = stdout.replace("\n", " ").replace("\t", " ")      return re.sub(" +", " ", stdout)      def remove_subparser(name: str):      """Remove a subparser from argparse."""      _CLI._sub_taipyparsers.pop(name, None)        if _CLI._subparser_action:          _CLI._subparser_action._name_parser_map.pop(name, None)            for action in _CLI._subparser_action._choices_actions:              if action.dest == name:                  _CLI._subparser_action._choices_actions.remove(action)      @pytest.fixture(autouse=True, scope="function")  def clean_argparser():      _CLI._parser = argparse.ArgumentParser(conflict_handler="resolve")      _CLI._arg_groups = {}      subcommands = list(_CLI._sub_taipyparsers.keys())      for subcommand in subcommands:          remove_subparser(subcommand)        yield      def test_subparser(capfd):      subcommand_1 = _CLI._add_subparser("subcommand_1", help="subcommand_1 help")      subcommand_1.add_argument("--foo", "-f", help="foo help")      subcommand_1.add_argument("--bar", "-b", help="bar help")        subcommand_2 = _CLI._add_subparser("subcommand_2", help="subcommand_2 help")      subcommand_2.add_argument("--doo", "-d", help="doo help")      subcommand_2.add_argument("--baz", "-z", help="baz help")        expected_subcommand_1_help_message = f"""subcommand_1 [-h] [--foo FOO] [--bar BAR]    {argparse_options_str}    -h, --help         show this help message and exit    --foo FOO, -f FOO  foo help    --bar BAR, -b BAR  bar help      """        subcommand_1.print_help()      stdout, _ = capfd.readouterr()      assert preprocess_stdout(expected_subcommand_1_help_message) in preprocess_stdout(stdout)        expected_subcommand_2_help_message = f"""subcommand_2 [-h] [--doo DOO] [--baz BAZ]    {argparse_options_str}    -h, --help         show this help message and exit    --doo DOO, -d DOO  doo help    --baz BAZ, -z BAZ  baz help      """        subcommand_2.print_help()      stdout, _ = capfd.readouterr()      assert preprocess_stdout(expected_subcommand_2_help_message) in preprocess_stdout(stdout)      def test_duplicate_subcommand():      subcommand_1 = _CLI._add_subparser("subcommand_1", help="subcommand_1 help")      subcommand_1.add_argument("--foo", "-f", help="foo help")        subcommand_2 = _CLI._add_subparser("subcommand_1", help="subcommand_2 help")      subcommand_2.add_argument("--bar", "-b", help="bar help")        # The title of subcommand_2 is duplicated with  subcommand_1, and therefore      # there will be no new subcommand created      assert len(_CLI._sub_taipyparsers) == 1      def test_groupparser(capfd):      group_1 = _CLI._add_groupparser("group_1", "group_1 desc")      group_1.add_argument("--foo", "-f", help="foo help")      group_1.add_argument("--bar", "-b", help="bar help")        group_2 = _CLI._add_groupparser("group_2", "group_2 desc")      group_2.add_argument("--doo", "-d", help="doo help")      group_2.add_argument("--baz", "-z", help="baz help")        expected_help_message = """  group_1:    group_1 desc      --foo FOO, -f FOO  foo help    --bar BAR, -b BAR  bar help    group_2:    group_2 desc      --doo DOO, -d DOO  doo help    --baz BAZ, -z BAZ  baz help      """.strip()        _CLI._parser.print_help()      stdout, _ = capfd.readouterr()        assert expected_help_message in stdout      def test_duplicate_group():      group_1 = _CLI._add_groupparser("group_1", "group_1 desc")      group_1.add_argument("--foo", "-f", help="foo help")        group_2 = _CLI._add_groupparser("group_1", "group_2 desc")      group_2.add_argument("--bar", "-b", help="bar help")        # The title of group_2 is duplicated with  group_1, and therefore      # there will be no new group created      assert len(_CLI._arg_groups) == 1


import datetime  import os  from unittest import mock    import pytest    from src.taipy.config.common.frequency import Frequency  from src.taipy.config.common.scope import Scope  from src.taipy.config.common._template_handler import _TemplateHandler  from src.taipy.config.exceptions.exceptions import InconsistentEnvVariableError      def test_replace_if_template():      assert_does_not_change("123")      assert_does_not_change("foo")      assert_does_not_change("_foo")      assert_does_not_change("_foo_")      assert_does_not_change("foo_")      assert_does_not_change("foo")      assert_does_not_change("foo_1")      assert_does_not_change("1foo_1")      assert_does_not_change("env(foo)")      assert_does_not_change("env<foo>")      assert_does_not_change("env[foo]")      assert_does_not_change("Env[foo]")      assert_does_not_change("ENV[1foo]")        assert_does_not_change("123:bool")      assert_does_not_change("foo:bool")      assert_does_not_change("_foo:bool")      assert_does_not_change("_foo_:bool")      assert_does_not_change("foo_:bool")      assert_does_not_change("foo:bool")      assert_does_not_change("foo_1:bool")      assert_does_not_change("1foo_1:bool")      assert_does_not_change("env(foo):bool")      assert_does_not_change("env<foo>:bool")      assert_does_not_change("env[foo]:bool")      assert_does_not_change("Env[foo]:bool")      assert_does_not_change("ENV[1foo]:bool")        assert_does_not_change("ENV[foo]:")      assert_does_not_change("ENV[_foo]:")      assert_does_not_change("ENV[foo_]:")      assert_does_not_change("ENV[foo0]:")      assert_does_not_change("ENV[foo_0]:")      assert_does_not_change("ENV[_foo_0]:")        assert_does_not_change("ENV[foo]:foo")      assert_does_not_change("ENV[_foo]:foo")      assert_does_not_change("ENV[foo_]:foo")      assert_does_not_change("ENV[foo0]:foo")      assert_does_not_change("ENV[foo_0]:foo")      assert_does_not_change("ENV[_foo_0]:foo")        assert_does_replace("ENV[foo]", "foo", "VALUE", str)      assert_does_replace("ENV[_foo]", "_foo", "VALUE", str)      assert_does_replace("ENV[foo_]", "foo_", "VALUE", str)      assert_does_replace("ENV[foo0]", "foo0", "VALUE", str)      assert_does_replace("ENV[foo_0]", "foo_0", "VALUE", str)      assert_does_replace("ENV[_foo_0]", "_foo_0", "VALUE", str)        assert_does_replace("ENV[foo]:str", "foo", "VALUE", str)      assert_does_replace("ENV[_foo]:str", "_foo", "VALUE", str)      assert_does_replace("ENV[foo_]:str", "foo_", "VALUE", str)      assert_does_replace("ENV[foo0]:str", "foo0", "VALUE", str)      assert_does_replace("ENV[foo_0]:str", "foo_0", "VALUE", str)      assert_does_replace("ENV[_foo_0]:str", "_foo_0", "VALUE", str)        assert_does_replace("ENV[foo]:int", "foo", "1", int)      assert_does_replace("ENV[_foo]:int", "_foo", "1", int)      assert_does_replace("ENV[foo_]:int", "foo_", "1", int)      assert_does_replace("ENV[foo0]:int", "foo0", "1", int)      assert_does_replace("ENV[foo_0]:int", "foo_0", "1", int)      assert_does_replace("ENV[_foo_0]:int", "_foo_0", "1", int)        assert_does_replace("ENV[foo]:float", "foo", "1.", float)      assert_does_replace("ENV[_foo]:float", "_foo", "1.", float)      assert_does_replace("ENV[foo_]:float", "foo_", "1.", float)      assert_does_replace("ENV[foo0]:float", "foo0", "1.", float)      assert_does_replace("ENV[foo_0]:float", "foo_0", "1.", float)      assert_does_replace("ENV[_foo_0]:float", "_foo_0", "1.", float)        assert_does_replace("ENV[foo]:bool", "foo", "True", bool)      assert_does_replace("ENV[_foo]:bool", "_foo", "True", bool)      assert_does_replace("ENV[foo_]:bool", "foo_", "True", bool)      assert_does_replace("ENV[foo0]:bool", "foo0", "True", bool)      assert_does_replace("ENV[foo_0]:bool", "foo_0", "True", bool)      assert_does_replace("ENV[_foo_0]:bool", "_foo_0", "True", bool)      def assert_does_replace(template, env_variable_name, replaced_by, as_type):      with mock.patch.dict(os.environ, {env_variable_name: replaced_by}):          tpl = _TemplateHandler()          assert tpl._replace_templates(template) == as_type(replaced_by)      def assert_does_not_change(template):      tpl = _TemplateHandler()      assert tpl._replace_templates(template) == template      def test_replace_tuple_list_dict():      with mock.patch.dict(os.environ, {"FOO": "true", "BAR": "3", "BAZ": "qux"}):          tpl = _TemplateHandler()          now = datetime.datetime.now()          actual = tpl._replace_templates(("ENV[FOO]:bool", now, "ENV[BAR]:int", "ENV[BAZ]", "quz"))          assert actual == (True, now, 3, "qux", "quz")          actual = tpl._replace_templates(("ENV[FOO]:bool", now, "ENV[BAR]:int", "ENV[BAZ]", "quz"))          assert actual == (True, now, 3, "qux", "quz")      def test_to_bool():      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_bool("okhds")      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_bool("no")      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_bool("tru")      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_bool("tru_e")        assert _TemplateHandler._to_bool("true")      assert _TemplateHandler._to_bool("True")      assert _TemplateHandler._to_bool("TRUE")      assert _TemplateHandler._to_bool("TruE")      assert _TemplateHandler._to_bool("TrUE")        assert not _TemplateHandler._to_bool("false")      assert not _TemplateHandler._to_bool("False")      assert not _TemplateHandler._to_bool("FALSE")      assert not _TemplateHandler._to_bool("FalSE")      assert not _TemplateHandler._to_bool("FalSe")      def test_to_int():      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_int("okhds")      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_int("_45")      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_int("12.5")        assert 12 == _TemplateHandler._to_int("12")      assert 0 == _TemplateHandler._to_int("0")      assert -2 == _TemplateHandler._to_int("-2")      assert 156165 == _TemplateHandler._to_int("156165")      def test_to_float():      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_float("okhds")      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_float("_45")        assert 12.5 == _TemplateHandler._to_float("12.5")      assert 2.0 == _TemplateHandler._to_float("2")      assert 0.0 == _TemplateHandler._to_float("0")      assert -2.1 == _TemplateHandler._to_float("-2.1")      assert 156165.3 == _TemplateHandler._to_float("156165.3")      def test_to_scope():      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_scope("okhds")      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_scope("plop")        assert Scope.GLOBAL == _TemplateHandler._to_scope("global")      assert Scope.GLOBAL == _TemplateHandler._to_scope("GLOBAL")      assert Scope.SCENARIO == _TemplateHandler._to_scope("SCENARIO")      assert Scope.CYCLE == _TemplateHandler._to_scope("cycle")      def test_to_frequency():      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_frequency("okhds")      with pytest.raises(InconsistentEnvVariableError):          _TemplateHandler._to_frequency("plop")        assert Frequency.DAILY == _TemplateHandler._to_frequency("DAILY")      assert Frequency.DAILY == _TemplateHandler._to_frequency("Daily")      assert Frequency.WEEKLY == _TemplateHandler._to_frequency("weekly")      assert Frequency.WEEKLY == _TemplateHandler._to_frequency("WEEKLY")      assert Frequency.MONTHLY == _TemplateHandler._to_frequency("Monthly")      assert Frequency.MONTHLY == _TemplateHandler._to_frequency("MONThLY")      assert Frequency.QUARTERLY == _TemplateHandler._to_frequency("QuaRtERlY")      assert Frequency.YEARLY == _TemplateHandler._to_frequency("Yearly")


import pytest    from src.taipy.config.common._classproperty import _Classproperty      class TestClassProperty:      def test_class_property(self):          class TestClass:              @_Classproperty              def test_property(cls):                  return "test_property"            assert TestClass.test_property == "test_property"          assert TestClass().test_property == "test_property"          with pytest.raises(TypeError):              TestClass.test_property()


import os  from unittest import mock    import pytest    from src.taipy.config.config import Config  from src.taipy.config.exceptions.exceptions import ConfigurationUpdateBlocked      def test_global_config_with_env_variable_value():      with mock.patch.dict(os.environ, {"FOO": "bar", "BAZ": "qux"}):          Config.configure_global_app(foo="ENV[FOO]", bar="ENV[BAZ]")          assert Config.global_config.foo == "bar"          assert Config.global_config.bar == "qux"      def test_default_global_app_config():      global_config = Config.global_config      assert global_config is not None      assert not global_config.notification      assert len(global_config.properties) == 0      def test_block_update_global_app_config():      Config.block_update()        with pytest.raises(ConfigurationUpdateBlocked):          Config.configure_global_app(foo="bar")        with pytest.raises(ConfigurationUpdateBlocked):          Config.global_config.properties = {"foo": "bar"}        # Test if the global_config stay as default      assert Config.global_config.foo is None      assert len(Config.global_config.properties) == 0


from importlib.util import find_spec    if find_spec("taipy"):      if find_spec("taipy.config"):          from taipy.config._init import *  # type: ignore        if find_spec("taipy.gui"):          from taipy.gui._init import *  # type: ignore        if find_spec("taipy.core"):          from taipy.core._init import *  # type: ignore        if find_spec("taipy.rest"):          from taipy.rest._init import *  # type: ignore        if find_spec("taipy.gui_core"):          from taipy.gui_core._init import *  # type: ignore        if find_spec("taipy.enterprise"):          from taipy.enterprise._init import *  # type: ignore        if find_spec("taipy._run"):          from taipy._run import _run as run  # type: ignore


#  # 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 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 .config import Config  from .common.frequency import Frequency  from .common.scope import Scope


"""# 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 ._init import *    from typing import List  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)        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)


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 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))))


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          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.


# 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)