core_section.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. # Copyright 2021-2024 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. import re
  12. from copy import copy
  13. from typing import Any, Dict, Optional, Union
  14. from taipy.config import Config, UniqueSection
  15. from taipy.config._config import _Config
  16. from taipy.config.common._config_blocker import _ConfigBlocker
  17. from taipy.config.common._template_handler import _TemplateHandler as _tpl
  18. from .._init_version import _read_version
  19. from ..exceptions.exceptions import ConfigCoreVersionMismatched
  20. class CoreSection(UniqueSection):
  21. """
  22. Configuration parameters for running the `Core^` service.
  23. Attributes:
  24. root_folder (str): Path of the base folder for the taipy application. The default value is "./taipy/"
  25. storage_folder (str): Folder name used to store user data. The default value is "user_data/". The default
  26. path is "user_data/".
  27. taipy_storage_folder (str): Folder name used to store Taipy data. The default value is ".taipy/". The default
  28. path is "./taipy/".
  29. repository_type (str): Type of the repository to be used to store Taipy data. The default value is
  30. "filesystem".
  31. repository_properties (Dict[str, Union[str, int]]): A dictionary of additional properties to be used by the
  32. repository.
  33. read_entity_retry (int): Number of retries to read an entity from the repository before return failure.
  34. The default value is 3.
  35. mode (str): The Taipy operating mode. By default, the `Core^` service runs in "development" mode.
  36. An "experiment" and a "production" mode are also available. Please refer to the
  37. [Versioning management](../core/versioning/index.md) documentation page for more details.
  38. version_number (str)): The identifier of the user application version. Please refer to the
  39. [Versioning management](../core/versioning/index.md) documentation page for more details.
  40. force (bool): If True, force the application run even if there are some conflicts in the
  41. configuration.
  42. core_version (str): The Taipy Core package version.
  43. **properties (dict[str, any]): A dictionary of additional properties.
  44. """
  45. name = "CORE"
  46. _ROOT_FOLDER_KEY = "root_folder"
  47. _DEFAULT_ROOT_FOLDER = "./taipy/"
  48. _STORAGE_FOLDER_KEY = "storage_folder"
  49. _DEFAULT_STORAGE_FOLDER = "user_data/"
  50. _STORAGE_FOLDER_TP_KEY = "taipy_storage_folder"
  51. _DEFAULT_STORAGE_FOLDER_TP = ".taipy/"
  52. _REPOSITORY_TYPE_KEY = "repository_type"
  53. _DEFAULT_REPOSITORY_TYPE = "filesystem"
  54. _REPOSITORY_PROPERTIES_KEY = "repository_properties"
  55. _DEFAULT_REPOSITORY_PROPERTIES: Dict = dict()
  56. _READ_ENTITY_RETRY_KEY = "read_entity_retry"
  57. _DEFAULT_READ_ENTITY_RETRY = 1
  58. _MODE_KEY = "mode"
  59. _DEVELOPMENT_MODE = "development"
  60. _EXPERIMENT_MODE = "experiment"
  61. _PRODUCTION_MODE = "production"
  62. _DEFAULT_MODE = _DEVELOPMENT_MODE
  63. _VERSION_NUMBER_KEY = "version_number"
  64. _DEFAULT_VERSION_NUMBER = ""
  65. _FORCE_KEY = "force"
  66. _DEFAULT_FORCE = False
  67. _CORE_VERSION_KEY = "core_version"
  68. _CURRENT_CORE_VERSION = _read_version()
  69. def __init__(
  70. self,
  71. root_folder: Optional[str] = None,
  72. storage_folder: Optional[str] = None,
  73. taipy_storage_folder: Optional[str] = None,
  74. repository_type: Optional[str] = None,
  75. repository_properties: Optional[Dict[str, Union[str, int]]] = None,
  76. read_entity_retry: Optional[int] = None,
  77. mode: Optional[str] = None,
  78. version_number: Optional[str] = None,
  79. force: Optional[bool] = None,
  80. core_version: Optional[str] = None,
  81. **properties,
  82. ):
  83. self._root_folder = root_folder
  84. self._storage_folder = storage_folder
  85. self._taipy_storage_folder = taipy_storage_folder
  86. self._repository_type = repository_type
  87. self._repository_properties = repository_properties or {}
  88. self._read_entity_retry = (
  89. read_entity_retry if read_entity_retry is not None else self._DEFAULT_READ_ENTITY_RETRY
  90. )
  91. self._mode = mode
  92. self._version_number = version_number
  93. self._force = force
  94. self._check_compatibility(core_version)
  95. self._core_version = core_version
  96. super().__init__(**properties)
  97. def __copy__(self):
  98. return CoreSection(
  99. self.root_folder,
  100. self.storage_folder,
  101. self.taipy_storage_folder,
  102. self.repository_type,
  103. self.repository_properties,
  104. self.read_entity_retry,
  105. self.mode,
  106. self.version_number,
  107. self.force,
  108. self._core_version,
  109. **copy(self._properties),
  110. )
  111. @property
  112. def storage_folder(self):
  113. return _tpl._replace_templates(self._storage_folder)
  114. @storage_folder.setter # type: ignore
  115. @_ConfigBlocker._check()
  116. def storage_folder(self, val):
  117. self._storage_folder = val
  118. @property
  119. def taipy_storage_folder(self):
  120. return _tpl._replace_templates(self._taipy_storage_folder)
  121. @taipy_storage_folder.setter # type: ignore
  122. @_ConfigBlocker._check()
  123. def taipy_storage_folder(self, val):
  124. self._taipy_storage_folder = val
  125. @property
  126. def root_folder(self):
  127. return _tpl._replace_templates(self._root_folder)
  128. @root_folder.setter # type: ignore
  129. @_ConfigBlocker._check()
  130. def root_folder(self, val):
  131. self._root_folder = val
  132. @property
  133. def repository_type(self):
  134. return _tpl._replace_templates(self._repository_type)
  135. @repository_type.setter # type: ignore
  136. @_ConfigBlocker._check()
  137. def repository_type(self, val):
  138. self._repository_type = val
  139. @property
  140. def repository_properties(self):
  141. return (
  142. {k: _tpl._replace_templates(v) for k, v in self._repository_properties.items()}
  143. if self._repository_properties
  144. else self._DEFAULT_REPOSITORY_PROPERTIES.copy()
  145. )
  146. @repository_properties.setter # type: ignore
  147. @_ConfigBlocker._check()
  148. def repository_properties(self, val):
  149. self._repository_properties = val
  150. @property
  151. def read_entity_retry(self):
  152. return _tpl._replace_templates(self._read_entity_retry)
  153. @read_entity_retry.setter # type: ignore
  154. @_ConfigBlocker._check()
  155. def read_entity_retry(self, val):
  156. self._read_entity_retry = val
  157. @property
  158. def mode(self):
  159. return _tpl._replace_templates(self._mode)
  160. @mode.setter # type: ignore
  161. @_ConfigBlocker._check()
  162. def mode(self, val):
  163. self._mode = val
  164. @property
  165. def version_number(self):
  166. return _tpl._replace_templates(self._version_number)
  167. @version_number.setter # type: ignore
  168. @_ConfigBlocker._check()
  169. def version_number(self, val):
  170. self._version_number = val
  171. @property
  172. def force(self):
  173. return _tpl._replace_templates(self._force)
  174. @force.setter # type: ignore
  175. @_ConfigBlocker._check()
  176. def force(self, val):
  177. self._force = val
  178. @classmethod
  179. def default_config(cls):
  180. return CoreSection(
  181. cls._DEFAULT_ROOT_FOLDER,
  182. cls._DEFAULT_STORAGE_FOLDER,
  183. cls._DEFAULT_STORAGE_FOLDER_TP,
  184. cls._DEFAULT_REPOSITORY_TYPE,
  185. cls._DEFAULT_REPOSITORY_PROPERTIES,
  186. cls._DEFAULT_READ_ENTITY_RETRY,
  187. cls._DEFAULT_MODE,
  188. cls._DEFAULT_VERSION_NUMBER,
  189. cls._DEFAULT_FORCE,
  190. cls._CURRENT_CORE_VERSION,
  191. )
  192. def _clean(self):
  193. self._root_folder = self._DEFAULT_ROOT_FOLDER
  194. self._storage_folder = self._DEFAULT_STORAGE_FOLDER
  195. self._taipy_storage_folder = self._DEFAULT_STORAGE_FOLDER
  196. self._repository_type = self._DEFAULT_REPOSITORY_TYPE
  197. self._repository_properties = self._DEFAULT_REPOSITORY_PROPERTIES.copy()
  198. self._read_entity_retry = self._DEFAULT_READ_ENTITY_RETRY
  199. self.mode = self._DEFAULT_MODE
  200. self.version_number = self._DEFAULT_VERSION_NUMBER
  201. self.force = self._DEFAULT_FORCE
  202. self._core_version = self._CURRENT_CORE_VERSION
  203. self._properties.clear()
  204. def _to_dict(self):
  205. as_dict = {}
  206. if self._root_folder:
  207. as_dict[self._ROOT_FOLDER_KEY] = self._root_folder
  208. if self._storage_folder:
  209. as_dict[self._STORAGE_FOLDER_KEY] = self._storage_folder
  210. if self._taipy_storage_folder:
  211. as_dict[self._STORAGE_FOLDER_TP_KEY] = self._taipy_storage_folder
  212. if self._repository_type:
  213. as_dict[self._REPOSITORY_TYPE_KEY] = self._repository_type
  214. if self._repository_properties:
  215. as_dict[self._REPOSITORY_PROPERTIES_KEY] = self._repository_properties
  216. if self._read_entity_retry is not None:
  217. as_dict[self._READ_ENTITY_RETRY_KEY] = self._read_entity_retry
  218. if self.mode is not None:
  219. as_dict[self._MODE_KEY] = self.mode
  220. if self.version_number is not None:
  221. as_dict[self._VERSION_NUMBER_KEY] = self.version_number
  222. if self.force is not None:
  223. as_dict[self._FORCE_KEY] = self.force
  224. if self._core_version is not None:
  225. as_dict[self._CORE_VERSION_KEY] = self._core_version
  226. as_dict.update(self._properties)
  227. return as_dict
  228. @classmethod
  229. def _from_dict(cls, as_dict: Dict[str, Any], id=None, config: Optional[_Config] = None):
  230. root_folder = as_dict.pop(cls._ROOT_FOLDER_KEY, None)
  231. storage_folder = as_dict.pop(cls._STORAGE_FOLDER_KEY, None)
  232. taipy_storage_folder = as_dict.pop(cls._STORAGE_FOLDER_TP_KEY, None)
  233. repository_type = as_dict.pop(cls._REPOSITORY_TYPE_KEY, None)
  234. repository_properties = as_dict.pop(cls._REPOSITORY_PROPERTIES_KEY, None)
  235. read_entity_retry = as_dict.pop(cls._READ_ENTITY_RETRY_KEY, None)
  236. mode = as_dict.pop(cls._MODE_KEY, None)
  237. version_nb = as_dict.pop(cls._VERSION_NUMBER_KEY, None)
  238. force = as_dict.pop(cls._FORCE_KEY, None)
  239. core_version = as_dict.pop(cls._CORE_VERSION_KEY, None)
  240. return CoreSection(
  241. root_folder,
  242. storage_folder,
  243. taipy_storage_folder,
  244. repository_type,
  245. repository_properties,
  246. read_entity_retry,
  247. mode,
  248. version_nb,
  249. force,
  250. core_version,
  251. **as_dict,
  252. )
  253. def _update(self, as_dict: Dict[str, Any], default_section=None):
  254. self._root_folder = as_dict.pop(self._ROOT_FOLDER_KEY, self._root_folder)
  255. self._storage_folder = as_dict.pop(self._STORAGE_FOLDER_KEY, self._storage_folder)
  256. self._taipy_storage_folder = as_dict.pop(self._STORAGE_FOLDER_TP_KEY, self._taipy_storage_folder)
  257. self._repository_type = as_dict.pop(self._REPOSITORY_TYPE_KEY, self._repository_type)
  258. self._repository_properties.update(as_dict.pop(self._REPOSITORY_PROPERTIES_KEY, self._repository_properties))
  259. self._read_entity_retry = as_dict.pop(self._READ_ENTITY_RETRY_KEY, self._read_entity_retry)
  260. self._mode = as_dict.pop(self._MODE_KEY, self.mode)
  261. self._version_number = as_dict.pop(self._VERSION_NUMBER_KEY, self.version_number)
  262. self._force = as_dict.pop(self._FORCE_KEY, self.force)
  263. core_version = as_dict.pop(self._CORE_VERSION_KEY, None)
  264. self._check_compatibility(core_version)
  265. self._properties.update(as_dict)
  266. @classmethod
  267. def _check_compatibility(cls, core_version):
  268. if not core_version:
  269. return
  270. version_pattern = r"^(\d+)\.(\d+)\.(\d+)$"
  271. dev_version_pattern = r"^(\d+)\.(\d+)\.(\d+).(\w*)$"
  272. installed_match = re.match(version_pattern, cls._CURRENT_CORE_VERSION) or re.match(
  273. dev_version_pattern, cls._CURRENT_CORE_VERSION
  274. )
  275. required_match = re.match(version_pattern, core_version) or re.match(dev_version_pattern, core_version)
  276. if required_match and installed_match:
  277. installed_group = installed_match.groups()
  278. required_group = required_match.groups()
  279. installed_major, installed_minor = installed_group[0], installed_group[1]
  280. required_major, required_minor = required_group[0], required_group[1]
  281. if required_major != installed_major or required_minor != installed_minor:
  282. raise ConfigCoreVersionMismatched(core_version, cls._CURRENT_CORE_VERSION)
  283. @staticmethod
  284. def _configure(
  285. root_folder: Optional[str] = None,
  286. storage_folder: Optional[str] = None,
  287. repository_type: Optional[str] = None,
  288. repository_properties: Optional[Dict[str, Union[str, int]]] = None,
  289. read_entity_retry: Optional[int] = None,
  290. mode: Optional[str] = None,
  291. version_number: Optional[str] = None,
  292. force: Optional[bool] = None,
  293. **properties,
  294. ) -> "CoreSection":
  295. """Configure the Core service.
  296. Parameters:
  297. root_folder (Optional[str]): Path of the base folder for the taipy application.
  298. The default value is "./taipy/"
  299. storage_folder (str): Folder name used to store user data. The default value is "user_data/". It is used in
  300. conjunction with the *root_folder* attribute. That means the storage path is
  301. <root_folder><storage_folder> (The default path is "./taipy/user_data/").
  302. taipy_storage_folder (str): Folder name used to store Taipy data. The default value is ".taipy/". It is
  303. used in conjunction with the *root_folder* attribute. That means the storage path is
  304. <root_folder><storage_folder> (The default path is "./taipy/.taipy/").
  305. repository_type (Optional[str]): The type of the repository to be used to store Taipy data.
  306. The default value is "filesystem".
  307. repository_properties (Optional[Dict[str, Union[str, int]]]): A dictionary of additional properties
  308. to be used by the repository.
  309. read_entity_retry (Optional[int]): Number of retries to read an entity from the repository
  310. before return failure. The default value is 3.
  311. mode (Optional[str]): Indicates the mode of the version management system.
  312. Possible values are *"development"*, *"experiment"*, or *"production"*.
  313. version_number (Optional[str]): The string identifier of the version.
  314. In development mode, the version number is ignored.
  315. force (Optional[bool]): If True, Taipy will override a version even if the configuration
  316. has changed and run the application.
  317. **properties (Dict[str, Any]): A keyworded variable length list of additional arguments configure the
  318. behavior of the `Core^` service.
  319. Returns:
  320. The Core configuration.
  321. """
  322. section = CoreSection(
  323. root_folder=root_folder,
  324. storage_folder=storage_folder,
  325. repository_type=repository_type,
  326. repository_properties=repository_properties,
  327. read_entity_retry=read_entity_retry,
  328. mode=mode,
  329. version_number=version_number,
  330. force=force,
  331. core_version=_read_version(),
  332. **properties,
  333. )
  334. Config._register(section)
  335. return Config.unique_sections[CoreSection.name]