test_task.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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. from unittest import mock
  12. import pytest
  13. from taipy.config.common.scope import Scope
  14. from taipy.config.config import Config
  15. from taipy.config.exceptions.exceptions import InvalidConfigurationId
  16. from taipy.core.config.data_node_config import DataNodeConfig
  17. from taipy.core.data._data_manager import _DataManager
  18. from taipy.core.data.csv import CSVDataNode
  19. from taipy.core.data.data_node import DataNode
  20. from taipy.core.data.in_memory import InMemoryDataNode
  21. from taipy.core.task._task_manager import _TaskManager
  22. from taipy.core.task._task_manager_factory import _TaskManagerFactory
  23. from taipy.core.task.task import Task
  24. @pytest.fixture
  25. def output():
  26. return [DataNode("name_1"), DataNode("name_2"), DataNode("name_3")]
  27. @pytest.fixture
  28. def output_config():
  29. return [DataNodeConfig("name_1"), DataNodeConfig("name_2"), DataNodeConfig("name_3")]
  30. @pytest.fixture
  31. def input():
  32. return [DataNode("input_name_1"), DataNode("input_name_2"), DataNode("input_name_3")]
  33. @pytest.fixture
  34. def input_config():
  35. return [DataNodeConfig("input_name_1"), DataNodeConfig("input_name_2"), DataNodeConfig("input_name_3")]
  36. def test_task_equals(task):
  37. task_manager = _TaskManagerFactory()._build_manager()
  38. task_id = task.id
  39. task_manager._set(task)
  40. # To test if instance is same type
  41. dn = CSVDataNode("foo_bar", Scope.SCENARIO, task_id)
  42. task_2 = task_manager._get(task_id)
  43. assert task == task_2
  44. assert task != task_id
  45. assert task != dn
  46. def test_create_task():
  47. name = "name_1"
  48. task = Task(name, {}, print, [], [])
  49. assert f"TASK_{name}_" in task.id
  50. assert task.config_id == "name_1"
  51. with pytest.raises(InvalidConfigurationId):
  52. Task("foo bar", {}, print, [], [])
  53. path = "my/csv/path"
  54. foo_dn = CSVDataNode("foo", Scope.SCENARIO, properties={"path": path, "has_header": True})
  55. task = Task("name_1", {}, print, [foo_dn], [])
  56. assert task.config_id == "name_1"
  57. assert task.id is not None
  58. assert task.owner_id is None
  59. assert task.parent_ids == set()
  60. assert task.foo == foo_dn
  61. assert task.foo.path == path
  62. with pytest.raises(AttributeError):
  63. _ = task.bar
  64. task = Task("name_1", {}, print, [foo_dn], [], parent_ids={"parent_id"})
  65. assert task.parent_ids == {"parent_id"}
  66. path = "my/csv/path"
  67. abc_dn = InMemoryDataNode("name_1ea", Scope.SCENARIO, properties={"path": path})
  68. task = Task("name_1ea", {}, print, [abc_dn], [], owner_id="owner_id", parent_ids={"parent_id_1", "parent_id_2"})
  69. assert task.config_id == "name_1ea"
  70. assert task.id is not None
  71. assert task.owner_id == "owner_id"
  72. assert task.parent_ids == {"parent_id_1", "parent_id_2"}
  73. assert task.name_1ea == abc_dn
  74. assert task.name_1ea.path == path
  75. with pytest.raises(AttributeError):
  76. _ = task.bar
  77. with mock.patch("taipy.core.get") as get_mck:
  78. class MockOwner:
  79. label = "owner_label"
  80. def get_label(self):
  81. return self.label
  82. get_mck.return_value = MockOwner()
  83. assert task.get_label() == "owner_label > " + task.config_id
  84. assert task.get_simple_label() == task.config_id
  85. def test_can_not_change_task_output(output):
  86. task = Task("name_1", {}, print, output=output)
  87. with pytest.raises(AttributeError):
  88. task.output = {}
  89. assert list(task.output.values()) == output
  90. output.append(output[0])
  91. assert list(task.output.values()) != output
  92. def test_can_not_change_task_input(input):
  93. task = Task("name_1", {}, print, input=input)
  94. with pytest.raises(AttributeError):
  95. task.input = {}
  96. assert list(task.input.values()) == input
  97. input.append(input[0])
  98. assert list(task.input.values()) != input
  99. def test_can_not_change_task_config_output(output_config):
  100. task_config = Config.configure_task("name_1", print, [], output=output_config)
  101. assert task_config.output_configs == output_config
  102. with pytest.raises(AttributeError):
  103. task_config.output_configs = []
  104. output_config.append(output_config[0])
  105. assert task_config._output != output_config
  106. def test_can_not_update_task_output_values(output_config):
  107. data_node_cfg = Config.configure_data_node("data_node_cfg")
  108. task_config = Config.configure_task("name_1", print, [], output=output_config)
  109. task_config.output_configs.append(data_node_cfg)
  110. assert task_config.output_configs == output_config
  111. task_config.output_configs[0] = data_node_cfg
  112. assert task_config.output_configs[0] != data_node_cfg
  113. def test_can_not_update_task_input_values(input_config):
  114. data_node_config = DataNodeConfig("data_node")
  115. task_config = Config.configure_task("name_1", print, input=input_config, output=[])
  116. task_config.input_configs.append(data_node_config)
  117. assert task_config.input_configs == input_config
  118. task_config.input_configs[0] = data_node_config
  119. assert task_config.input_configs[0] != data_node_config
  120. def mock_func():
  121. pass
  122. def test_auto_set_and_reload(data_node):
  123. task_1 = Task(
  124. config_id="foo", properties={}, function=print, input=None, output=None, owner_id=None, skippable=False
  125. )
  126. _DataManager._set(data_node)
  127. _TaskManager._set(task_1)
  128. task_2 = _TaskManager._get(task_1)
  129. # auto set & reload on function attribute
  130. assert task_1.function == print
  131. assert task_2.function == print
  132. task_1.function = sum
  133. assert task_1.function == sum
  134. assert task_2.function == sum
  135. task_2.function = mock_func
  136. assert task_1.function == mock_func
  137. assert task_2.function == mock_func
  138. # auto set & reload on skippable attribute
  139. assert not task_1.skippable
  140. assert not task_2.skippable
  141. task_1.skippable = True
  142. assert task_1.skippable
  143. assert task_2.skippable
  144. task_2.skippable = False
  145. assert not task_1.skippable
  146. assert not task_2.skippable
  147. # auto set & reload on parent_ids attribute (set() object does not have auto set yet)
  148. assert task_1.parent_ids == set()
  149. assert task_2.parent_ids == set()
  150. task_1._parent_ids.update(["sc2"])
  151. _TaskManager._set(task_1)
  152. assert task_1.parent_ids == {"sc2"}
  153. assert task_2.parent_ids == {"sc2"}
  154. task_2._parent_ids.clear()
  155. task_2._parent_ids.update(["sc1"])
  156. _TaskManager._set(task_2)
  157. assert task_1.parent_ids == {"sc1"}
  158. assert task_2.parent_ids == {"sc1"}
  159. with task_1 as task:
  160. assert task.config_id == "foo"
  161. assert task.owner_id is None
  162. assert task.function == mock_func
  163. assert not task.skippable
  164. assert task._is_in_context
  165. task.function = print
  166. task.skippable = True
  167. assert task.config_id == "foo"
  168. assert task.owner_id is None
  169. assert task.function == mock_func
  170. assert not task.skippable
  171. assert task._is_in_context
  172. assert task_1.config_id == "foo"
  173. assert task_1.owner_id is None
  174. assert task_1.function == print
  175. assert task.skippable
  176. assert not task_1._is_in_context
  177. def test_auto_set_and_reload_properties():
  178. task_1 = Task(
  179. config_id="foo", properties={}, function=print, input=None, output=None, owner_id=None, skippable=False
  180. )
  181. _TaskManager._set(task_1)
  182. task_2 = _TaskManager._get(task_1)
  183. # auto set & reload on properties attribute
  184. assert task_1.properties == {}
  185. assert task_2.properties == {}
  186. task_1._properties["qux"] = 4
  187. assert task_1.properties["qux"] == 4
  188. assert task_2.properties["qux"] == 4
  189. assert task_1.properties == {"qux": 4}
  190. assert task_2.properties == {"qux": 4}
  191. task_2._properties["qux"] = 5
  192. assert task_1.properties["qux"] == 5
  193. assert task_2.properties["qux"] == 5
  194. task_1.properties["temp_key_1"] = "temp_value_1"
  195. task_1.properties["temp_key_2"] = "temp_value_2"
  196. assert task_1.properties == {
  197. "qux": 5,
  198. "temp_key_1": "temp_value_1",
  199. "temp_key_2": "temp_value_2",
  200. }
  201. assert task_2.properties == {
  202. "qux": 5,
  203. "temp_key_1": "temp_value_1",
  204. "temp_key_2": "temp_value_2",
  205. }
  206. task_1.properties.pop("temp_key_1")
  207. assert "temp_key_1" not in task_1.properties.keys()
  208. assert "temp_key_1" not in task_1.properties.keys()
  209. assert task_1.properties == {
  210. "qux": 5,
  211. "temp_key_2": "temp_value_2",
  212. }
  213. assert task_2.properties == {
  214. "qux": 5,
  215. "temp_key_2": "temp_value_2",
  216. }
  217. task_2.properties.pop("temp_key_2")
  218. assert task_1.properties == {"qux": 5}
  219. assert task_2.properties == {"qux": 5}
  220. assert "temp_key_2" not in task_1.properties.keys()
  221. assert "temp_key_2" not in task_2.properties.keys()
  222. task_1.properties["temp_key_3"] = 0
  223. assert task_1.properties == {"qux": 5, "temp_key_3": 0}
  224. assert task_2.properties == {"qux": 5, "temp_key_3": 0}
  225. task_1.properties.update({"temp_key_3": 1})
  226. assert task_1.properties == {"qux": 5, "temp_key_3": 1}
  227. assert task_2.properties == {"qux": 5, "temp_key_3": 1}
  228. task_1.properties.update({})
  229. assert task_1.properties == {"qux": 5, "temp_key_3": 1}
  230. assert task_2.properties == {"qux": 5, "temp_key_3": 1}
  231. task_1.properties["temp_key_4"] = 0
  232. task_1.properties["temp_key_5"] = 0
  233. with task_1 as task:
  234. assert task._is_in_context
  235. assert task.properties["qux"] == 5
  236. assert task.properties["temp_key_3"] == 1
  237. assert task.properties["temp_key_4"] == 0
  238. assert task.properties["temp_key_5"] == 0
  239. task.properties["qux"] = 9
  240. task.properties.pop("temp_key_3")
  241. task.properties.pop("temp_key_4")
  242. task.properties.update({"temp_key_4": 1})
  243. task.properties.update({"temp_key_5": 2})
  244. task.properties.pop("temp_key_5")
  245. task.properties.update({})
  246. assert task._is_in_context
  247. assert task.properties["qux"] == 5
  248. assert task.properties["temp_key_3"] == 1
  249. assert task.properties["temp_key_4"] == 0
  250. assert task.properties["temp_key_5"] == 0
  251. assert not task_1._is_in_context
  252. assert task_1.properties["qux"] == 9
  253. assert "temp_key_3" not in task_1.properties.keys()
  254. assert task_1.properties["temp_key_4"] == 1
  255. assert "temp_key_5" not in task_1.properties.keys()
  256. def test_get_parents(task):
  257. with mock.patch("taipy.core.get_parents") as mck:
  258. task.get_parents()
  259. mck.assert_called_once_with(task)
  260. def test_submit_task(task: Task):
  261. with mock.patch("taipy.core.task._task_manager._TaskManager._submit") as mock_submit:
  262. task.submit([], True)
  263. mock_submit.assert_called_once_with(task, [], True, False, None)