test_file_config.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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 os
  12. from datetime import timedelta
  13. from unittest import mock
  14. from taipy.config.common.frequency import Frequency
  15. from taipy.config.common.scope import Scope
  16. from taipy.config.config import Config
  17. from taipy.core.config import DataNodeConfig, ScenarioConfig, TaskConfig
  18. from taipy.core.config.core_section import CoreSection
  19. from tests.core.utils.named_temporary_file import NamedTemporaryFile
  20. def test_write_configuration_file():
  21. expected_config = f"""
  22. [TAIPY]
  23. [JOB]
  24. mode = "standalone"
  25. max_nb_of_workers = "2:int"
  26. [CORE]
  27. root_folder = "./taipy/"
  28. storage_folder = "user_data/"
  29. taipy_storage_folder = ".taipy/"
  30. repository_type = "filesystem"
  31. read_entity_retry = "0:int"
  32. mode = "development"
  33. version_number = ""
  34. force = "False:bool"
  35. core_version = "{CoreSection._CURRENT_CORE_VERSION}"
  36. [VERSION_MIGRATION.migration_fcts]
  37. [DATA_NODE.default]
  38. storage_type = "in_memory"
  39. scope = "SCENARIO:SCOPE"
  40. validity_period = "1d0h0m0s:timedelta"
  41. custom = "default_custom_prop"
  42. [DATA_NODE.dn1]
  43. storage_type = "pickle"
  44. scope = "SCENARIO:SCOPE"
  45. validity_period = "1d0h0m0s:timedelta"
  46. custom = "custom property"
  47. default_data = "dn1"
  48. [DATA_NODE.dn2]
  49. storage_type = "ENV[FOO]"
  50. scope = "SCENARIO:SCOPE"
  51. validity_period = "2d0h0m0s:timedelta"
  52. foo = "bar"
  53. default_data = "dn2"
  54. baz = "ENV[QUX]"
  55. quux = "ENV[QUUZ]:bool"
  56. corge = [ "grault", "ENV[GARPLY]", "ENV[WALDO]:int", "3.0:float",]
  57. [DATA_NODE.dn3]
  58. storage_type = "ENV[FOO]"
  59. scope = "SCENARIO:SCOPE"
  60. validity_period = "1d0h0m0s:timedelta"
  61. foo = "bar"
  62. default_data = "dn3"
  63. quux = "ENV[QUUZ]:bool"
  64. [TASK.default]
  65. inputs = []
  66. outputs = []
  67. skippable = "False:bool"
  68. [TASK.t1]
  69. function = "builtins.print:function"
  70. inputs = [ "dn1:SECTION",]
  71. outputs = [ "dn2:SECTION",]
  72. skippable = "False:bool"
  73. description = "t1 description"
  74. [SCENARIO.default]
  75. tasks = []
  76. additional_data_nodes = []
  77. frequency = "QUARTERLY:FREQUENCY"
  78. owner = "Michel Platini"
  79. [SCENARIO.s1]
  80. tasks = [ "t1:SECTION",]
  81. additional_data_nodes = [ "dn3:SECTION",]
  82. frequency = "QUARTERLY:FREQUENCY"
  83. owner = "Raymond Kopa"
  84. [SCENARIO.default.comparators]
  85. [SCENARIO.default.sequences]
  86. [SCENARIO.s1.comparators]
  87. [SCENARIO.s1.sequences]
  88. sequence = [ "t1:SECTION",]
  89. """.strip()
  90. tf = NamedTemporaryFile()
  91. with mock.patch.dict(
  92. os.environ, {"FOO": "in_memory", "QUX": "qux", "QUUZ": "true", "GARPLY": "garply", "WALDO": "17"}
  93. ):
  94. Config.configure_job_executions(mode="standalone", max_nb_of_workers=2)
  95. Config.set_default_data_node_configuration(
  96. storage_type="in_memory",
  97. custom="default_custom_prop",
  98. validity_period=timedelta(1),
  99. )
  100. dn1_cfg_v2 = Config.configure_data_node(
  101. "dn1", storage_type="pickle", scope=Scope.SCENARIO, default_data="dn1", custom="custom property"
  102. )
  103. dn2_cfg_v2 = Config.configure_data_node(
  104. "dn2",
  105. storage_type="ENV[FOO]",
  106. validity_period=timedelta(2),
  107. foo="bar",
  108. default_data="dn2",
  109. baz="ENV[QUX]",
  110. quux="ENV[QUUZ]:bool",
  111. corge=("grault", "ENV[GARPLY]", "ENV[WALDO]:int", 3.0),
  112. )
  113. dn3_cfg_v2 = Config.configure_data_node(
  114. "dn3",
  115. storage_type="ENV[FOO]",
  116. foo="bar",
  117. default_data="dn3",
  118. quux="ENV[QUUZ]:bool",
  119. )
  120. assert dn2_cfg_v2.scope == Scope.SCENARIO
  121. t1_cfg_v2 = Config.configure_task("t1", print, dn1_cfg_v2, dn2_cfg_v2, description="t1 description")
  122. Config.set_default_scenario_configuration([], [], Frequency.QUARTERLY, owner="Michel Platini")
  123. Config.configure_scenario(
  124. "s1",
  125. task_configs=[t1_cfg_v2],
  126. additional_data_node_configs=[dn3_cfg_v2],
  127. frequency=Frequency.QUARTERLY,
  128. owner="Raymond Kopa",
  129. sequences={"sequence": [t1_cfg_v2]},
  130. )
  131. Config.backup(tf.filename)
  132. actual_config = tf.read().strip() # problem here
  133. assert actual_config == expected_config
  134. Config.override(tf.filename)
  135. tf2 = NamedTemporaryFile()
  136. Config.backup(tf2.filename)
  137. actual_config_2 = tf2.read().strip()
  138. assert actual_config_2 == expected_config
  139. def test_read_configuration_file():
  140. file_config = NamedTemporaryFile(
  141. """
  142. [DATA_NODE.default]
  143. has_header = true
  144. [DATA_NODE.my_datanode]
  145. path = "/data/csv"
  146. validity_period = "1d0h0m0s:timedelta"
  147. [DATA_NODE.my_datanode2]
  148. path = "/data2/csv"
  149. [DATA_NODE.my_datanode3]
  150. path = "/data3/csv"
  151. source = "local"
  152. [TASK.my_task]
  153. inputs = ["my_datanode:SECTION"]
  154. outputs = ["my_datanode2:SECTION"]
  155. description = "task description"
  156. [SCENARIO.my_scenario]
  157. tasks = [ "my_task:SECTION"]
  158. additional_data_nodes = ["my_datanode3:SECTION"]
  159. owner = "John Doe"
  160. [SCENARIO.my_scenario.sequences]
  161. sequence = [ "my_task:SECTION",]
  162. """
  163. )
  164. Config.configure_task("my_task", print)
  165. Config.override(file_config.filename)
  166. assert len(Config.data_nodes) == 4
  167. assert type(Config.data_nodes["my_datanode"]) == DataNodeConfig
  168. assert type(Config.data_nodes["my_datanode2"]) == DataNodeConfig
  169. assert type(Config.data_nodes["my_datanode3"]) == DataNodeConfig
  170. assert Config.data_nodes["my_datanode"].path == "/data/csv"
  171. assert Config.data_nodes["my_datanode2"].path == "/data2/csv"
  172. assert Config.data_nodes["my_datanode3"].path == "/data3/csv"
  173. assert Config.data_nodes["my_datanode"].id == "my_datanode"
  174. assert Config.data_nodes["my_datanode2"].id == "my_datanode2"
  175. assert Config.data_nodes["my_datanode3"].id == "my_datanode3"
  176. assert Config.data_nodes["my_datanode"].validity_period == timedelta(1)
  177. assert Config.data_nodes["my_datanode3"].source == "local"
  178. assert len(Config.tasks) == 2
  179. assert type(Config.tasks["my_task"]) == TaskConfig
  180. assert Config.tasks["my_task"].id == "my_task"
  181. assert Config.tasks["my_task"].description == "task description"
  182. assert Config.tasks["my_task"].function == print
  183. assert len(Config.tasks["my_task"].inputs) == 1
  184. assert type(Config.tasks["my_task"].inputs[0]) == DataNodeConfig
  185. assert Config.tasks["my_task"].inputs[0].path == "/data/csv"
  186. assert Config.tasks["my_task"].inputs[0].id == "my_datanode"
  187. assert len(Config.tasks["my_task"].outputs) == 1
  188. assert type(Config.tasks["my_task"].outputs[0]) == DataNodeConfig
  189. assert Config.tasks["my_task"].outputs[0].path == "/data2/csv"
  190. assert Config.tasks["my_task"].outputs[0].id == "my_datanode2"
  191. assert len(Config.scenarios) == 2
  192. assert type(Config.scenarios["my_scenario"]) == ScenarioConfig
  193. assert Config.scenarios["my_scenario"].id == "my_scenario"
  194. assert Config.scenarios["my_scenario"].owner == "John Doe"
  195. assert len(Config.scenarios["my_scenario"].tasks) == 1
  196. assert type(Config.scenarios["my_scenario"].tasks[0]) == TaskConfig
  197. assert len(Config.scenarios["my_scenario"].additional_data_nodes) == 1
  198. assert type(Config.scenarios["my_scenario"].additional_data_nodes[0]) == DataNodeConfig
  199. assert Config.scenarios["my_scenario"].tasks[0].id == "my_task"
  200. assert Config.scenarios["my_scenario"].tasks[0].description == "task description"
  201. assert Config.scenarios["my_scenario"].additional_data_nodes[0].id == "my_datanode3"
  202. assert Config.scenarios["my_scenario"].additional_data_nodes[0].source == "local"
  203. assert [task.id for task in Config.scenarios["my_scenario"].sequences["sequence"]] == [
  204. Config.scenarios["my_scenario"].tasks[0].id
  205. ]