__init__.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. # Copyright 2021-2025 Avaiga Private Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  4. # the License. You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  9. # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  10. # specific language governing permissions and limitations under the License.
  11. """The `taipy.common.config` package provides features to configure a Taipy application.
  12. Its main class is the `Config^` singleton. It exposes various static methods
  13. and attributes to configure the Taipy application and retrieve the configuration values.
  14. !!! example "Standard usage"
  15. ```python
  16. from taipy.common.config import Config
  17. from taipy.common.config import Frequency
  18. from taipy.common.config import Scope
  19. data_node_cfg = Config.configure_data_node("my_data_node", scope=Scope.SCENARIO)
  20. Config.configure_scenario("my_scenario", additional_data_node_configs=[data_node_cfg], frequency=Frequency.DAILY)
  21. Config.configure_core(repository_type="filesystem", storage_folder="my/storage/folder")
  22. Config.configure_authentication(protocol="taipy",roles={"user1": ["role1", "TAIPY_READER"]})
  23. print(Config.data_nodes["my_data_node"].scope) # Output: SCENARIO
  24. print(len(Config.scenarios["my_scenario"].data_nodes)) # Output: 1
  25. ```
  26. In this example, the static methods of the `Config^` singleton are used to configure
  27. a Taipy application. The application has one data node configuration and one scenario
  28. configuration.
  29. We also configure the application to use a filesystem repository and set up authentication.
  30. !!! note "`Frequency^` and `Scope^` for scenario and data nodes configurations"
  31. Besides the `Config^` class which is the main entrypoint, the `taipy.common.config` package exposes
  32. the `Frequency^` and `Scope^` enums that are frequently used to configure data nodes and
  33. scenarios.
  34. The three objects are exposed in the `taipy^` package directly for convenience.
  35. """
  36. import os
  37. from inspect import signature
  38. from typing import List
  39. from ._init import Config
  40. from .global_app.global_app_config import GlobalAppConfig
  41. from .section import Section
  42. from .unique_section import UniqueSection
  43. def __write_method_to_doc(configuration_methods):
  44. if os.environ.get("GENERATING_TAIPY_DOC", None) and os.environ["GENERATING_TAIPY_DOC"] == "true":
  45. with open("config_doc.txt", "a") as f:
  46. from inspect import signature
  47. # Add the documentation for configure methods
  48. for exposed_configuration_method, configuration_method in configuration_methods:
  49. annotation = " @staticmethod\n"
  50. sign = " def " + exposed_configuration_method + str(signature(configuration_method)) + ":\n"
  51. doc = ' """' + configuration_method.__doc__ + '"""\n'
  52. content = " pass\n\n"
  53. f.write(annotation + sign + doc + content)
  54. def __write_section_to_doc(section, attr_name):
  55. if os.environ.get("GENERATING_TAIPY_DOC", None) and os.environ["GENERATING_TAIPY_DOC"] == "true":
  56. with open("config_doc.txt", "a") as f:
  57. # Add the documentation for the attribute
  58. annotation = " @property\n"
  59. sign = f" def {attr_name} (self) -> {section.__name__}:\n"
  60. if issubclass(section, UniqueSection):
  61. doc = f' """The configured {section.__name__} section."""\n'
  62. elif issubclass(section, Section):
  63. doc = f' """The configured {section.__name__} sections ."""\n'
  64. else:
  65. print(f" ERROR - Invalid section class: {section.__name__}") # noqa: T201
  66. return
  67. content = " pass\n\n"
  68. f.write(annotation + sign + doc + content)
  69. def _config_doc_for_section(func):
  70. def func_with_doc(section, attribute_name, default, configuration_methods, add_to_unconflicted_sections=False):
  71. __write_section_to_doc(section, attribute_name)
  72. __write_method_to_doc(configuration_methods)
  73. return func(section, attribute_name, default, configuration_methods, add_to_unconflicted_sections)
  74. return func_with_doc
  75. def _config_doc_for_method(func):
  76. def func_with_doc(configuration_methods):
  77. __write_method_to_doc(configuration_methods)
  78. return func(configuration_methods)
  79. return func_with_doc
  80. @_config_doc_for_section
  81. def _inject_section(
  82. section_clazz,
  83. attribute_name: str,
  84. default: Section,
  85. configuration_methods: List[tuple],
  86. add_to_unconflicted_sections: bool = False,
  87. ):
  88. Config._register_default(default)
  89. if issubclass(section_clazz, UniqueSection):
  90. setattr(Config, attribute_name, Config.unique_sections[section_clazz.name])
  91. elif issubclass(section_clazz, Section):
  92. setattr(Config, attribute_name, Config.sections[section_clazz.name])
  93. else:
  94. raise TypeError
  95. if add_to_unconflicted_sections:
  96. Config._comparator._add_unconflicted_section(section_clazz.name) # type: ignore[attr-defined]
  97. for exposed_configuration_method, configuration_method in configuration_methods:
  98. setattr(Config, exposed_configuration_method, configuration_method)
  99. @_config_doc_for_method
  100. def _inject_method(configuration_methods: List[tuple]):
  101. for exposed_configuration_method, configuration_method in configuration_methods:
  102. setattr(Config, exposed_configuration_method, configuration_method)