test_file_config.py 8.0 KB

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