test_sequence.py 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  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.core.common._utils import _Subscriber
  15. from taipy.core.data._data_manager_factory import _DataManagerFactory
  16. from taipy.core.data.data_node import DataNode
  17. from taipy.core.data.in_memory import InMemoryDataNode
  18. from taipy.core.data.pickle import PickleDataNode
  19. from taipy.core.scenario._scenario_manager import _ScenarioManager
  20. from taipy.core.scenario.scenario import Scenario
  21. from taipy.core.sequence._sequence_manager import _SequenceManager
  22. from taipy.core.sequence.sequence import Sequence
  23. from taipy.core.sequence.sequence_id import SequenceId
  24. from taipy.core.task._task_manager import _TaskManager
  25. from taipy.core.task.task import Task, TaskId
  26. def test_create_sequence():
  27. input = InMemoryDataNode("foo", Scope.SCENARIO)
  28. output = InMemoryDataNode("bar", Scope.SCENARIO)
  29. task = Task("baz", {}, print, [input], [output], TaskId("task_id"))
  30. sequence = Sequence({"description": "description"}, [task], sequence_id=SequenceId("name_1"))
  31. assert sequence.id == "name_1"
  32. assert sequence.owner_id is None
  33. assert sequence.description == "description"
  34. assert sequence.foo == input
  35. assert sequence.bar == output
  36. assert sequence.baz.id == task.id
  37. assert sequence.tasks == {task.config_id: task}
  38. assert sequence.data_nodes == {"foo": input, "bar": output}
  39. assert sequence.parent_ids == set()
  40. with pytest.raises(AttributeError):
  41. _ = sequence.qux
  42. assert sequence.get_label() == sequence.id
  43. assert sequence.get_simple_label() == sequence.id
  44. input_1 = InMemoryDataNode("input", Scope.SCENARIO)
  45. output_1 = InMemoryDataNode("output", Scope.SCENARIO)
  46. task_1 = Task("task_1", {}, print, [input_1], [output_1], TaskId("task_id_1"))
  47. sequence_1 = Sequence(
  48. {"description": "description"},
  49. [task_1],
  50. owner_id="owner_id",
  51. parent_ids={"scenario_id"},
  52. sequence_id=SequenceId("name_1"),
  53. )
  54. assert sequence_1.id == "name_1"
  55. assert sequence_1.owner_id == "owner_id"
  56. assert sequence_1.description == "description"
  57. assert sequence_1.input == input_1
  58. assert sequence_1.output == output_1
  59. assert sequence_1.task_1 == task_1
  60. assert sequence_1.tasks == {task_1.config_id: task_1}
  61. assert sequence_1.data_nodes == {"input": input_1, "output": output_1}
  62. assert sequence_1.parent_ids == {"scenario_id"}
  63. assert sequence_1.id is not None
  64. with mock.patch("taipy.core.get") as get_mck:
  65. class MockOwner:
  66. label = "owner_label"
  67. def get_label(self):
  68. return self.label
  69. get_mck.return_value = MockOwner()
  70. assert sequence_1.get_label() == "owner_label > " + sequence_1.id
  71. assert sequence_1.get_simple_label() == sequence_1.id
  72. sequence_2 = Sequence(
  73. {"description": "description", "name": "Name"},
  74. [task, task_1],
  75. owner_id="owner_id",
  76. parent_ids={"parent_id_1", "parent_id_2"},
  77. sequence_id=SequenceId("name_2"),
  78. )
  79. assert sequence_2.owner_id == "owner_id"
  80. assert sequence_2.id == "name_2"
  81. assert sequence_2.description == "description"
  82. assert sequence_2.tasks == {task.config_id: task, task_1.config_id: task_1}
  83. assert sequence_2.data_nodes == {"foo": input, "bar": output, "input": input_1, "output": output_1}
  84. assert sequence_2.parent_ids == {"parent_id_1", "parent_id_2"}
  85. with mock.patch("taipy.core.get") as get_mck:
  86. class MockOwner:
  87. label = "owner_label"
  88. def get_label(self):
  89. return self.label
  90. get_mck.return_value = MockOwner()
  91. assert sequence_2.get_label() == "owner_label > " + sequence_2.name
  92. assert sequence_2.get_simple_label() == sequence_2.name
  93. def test_check_consistency():
  94. sequence_1 = Sequence({}, [], "name_1")
  95. assert sequence_1._is_consistent()
  96. input_2 = InMemoryDataNode("foo", Scope.SCENARIO)
  97. output_2 = InMemoryDataNode("bar", Scope.SCENARIO)
  98. task_2 = Task("tfoo", {}, print, [input_2], [output_2], TaskId("task_id_2"))
  99. sequence_2 = Sequence({}, [task_2], "name_2")
  100. assert sequence_2._is_consistent()
  101. data_node_3 = InMemoryDataNode("foo", Scope.SCENARIO)
  102. task_3 = Task("tfoo", {}, print, [data_node_3], [data_node_3], TaskId("task_id_3"))
  103. sequence_3 = Sequence({}, [task_3], "name_3")
  104. assert not sequence_3._is_consistent() # Not a dag
  105. input_4 = InMemoryDataNode("foo", Scope.SCENARIO)
  106. output_4 = InMemoryDataNode("bar", Scope.SCENARIO)
  107. task_4_1 = Task("tfoo", {}, print, [input_4], [output_4], TaskId("task_id_4_1"))
  108. task_4_2 = Task("tbar", {}, print, [output_4], [input_4], TaskId("task_id_4_2"))
  109. sequence_4 = Sequence({}, [task_4_1, task_4_2], "name_4")
  110. assert not sequence_4._is_consistent() # Not a Dag
  111. class FakeDataNode:
  112. config_id = "config_id_of_a_fake_dn"
  113. input_6 = DataNode("foo", Scope.SCENARIO, "input_id_5")
  114. output_6 = DataNode("bar", Scope.SCENARIO, "output_id_5")
  115. task_6_1 = Task("tfoo", {}, print, [input_6], [output_6], TaskId("task_id_5_1"))
  116. task_6_2 = Task("tbar", {}, print, [output_6], [FakeDataNode()], TaskId("task_id_5_2"))
  117. sequence_6 = Sequence({}, [task_6_1, task_6_2], "name_5")
  118. assert not sequence_6._is_consistent() # Not a DataNode
  119. intermediate_7 = DataNode("foo", Scope.SCENARIO, "intermediate_id_7")
  120. output_7 = DataNode("bar", Scope.SCENARIO, "output_id_7")
  121. task_7_1 = Task("tfoo", {}, print, [], [intermediate_7], TaskId("task_id_7_1"))
  122. task_7_2 = Task("tbar", {}, print, [intermediate_7], [output_7], TaskId("task_id_7_2"))
  123. sequence_7 = Sequence({}, [task_7_1, task_7_2], "name_7")
  124. assert sequence_7._is_consistent()
  125. input_8 = DataNode("foo", Scope.SCENARIO, "output_id_8")
  126. intermediate_8 = DataNode("bar", Scope.SCENARIO, "intermediate_id_8")
  127. task_8_1 = Task("tfoo", {}, print, [input_8], [intermediate_8], TaskId("task_id_8_1"))
  128. task_8_2 = Task("tbar", {}, print, [intermediate_8], [], TaskId("task_id_8_2"))
  129. sequence_8 = Sequence({}, [task_8_1, task_8_2], "name_8")
  130. assert sequence_8._is_consistent()
  131. input_9_1 = DataNode("foo", Scope.SCENARIO, "input_id_9_1")
  132. output_9_1 = DataNode("bar", Scope.SCENARIO, "output_id_9_1")
  133. input_9_2 = DataNode("baz", Scope.SCENARIO, "input_id_9_2")
  134. output_9_2 = DataNode("qux", Scope.SCENARIO, "output_id_9_2")
  135. task_9_1 = Task("tfoo", {}, print, [input_9_1], [output_9_1], TaskId("task_id_9_1"))
  136. task_9_2 = Task("tbar", {}, print, [input_9_2], [output_9_2], TaskId("task_id_9_2"))
  137. sequence_9 = Sequence({}, [task_9_1, task_9_2], "name_9")
  138. assert not sequence_9._is_consistent() # Not connected
  139. input_10_1 = DataNode("foo", Scope.SCENARIO, "output_id_10_1")
  140. intermediate_10_1 = DataNode("bar", Scope.SCENARIO, "intermediate_id_10_1")
  141. intermediate_10_2 = DataNode("baz", Scope.SCENARIO, "intermediate_id_10_2")
  142. output_10 = DataNode("qux", Scope.SCENARIO, "output_id_10")
  143. post_10 = DataNode("quux", Scope.SCENARIO, "post_id_10")
  144. task_10_1 = Task("tfoo", {}, print, [input_10_1], [intermediate_10_1], TaskId("task_id_10_1"))
  145. task_10_2 = Task("tbar", {}, print, [], [intermediate_10_2], TaskId("task_id_10_2"))
  146. task_10_3 = Task("tbaz", {}, print, [intermediate_10_1, intermediate_10_2], [output_10], TaskId("task_id_10_3"))
  147. task_10_4 = Task("tqux", {}, print, [output_10], [post_10], TaskId("task_id_10_4"))
  148. task_10_5 = Task("tquux", {}, print, [output_10], [], TaskId("task_id_10_5"))
  149. sequence_10 = Sequence({}, [task_10_1, task_10_2, task_10_3, task_10_4, task_10_5], "name_10")
  150. assert sequence_10._is_consistent()
  151. def test_get_sorted_tasks():
  152. def assert_equal(tasks_a, tasks_b) -> bool:
  153. if len(tasks_a) != len(tasks_b):
  154. return False
  155. for i in range(len(tasks_a)):
  156. task_a, task_b = tasks_a[i], tasks_b[i]
  157. if isinstance(task_a, list) and isinstance(task_b, list):
  158. if not assert_equal(task_a, task_b):
  159. return False
  160. elif isinstance(task_a, list) or isinstance(task_b, list):
  161. return False
  162. else:
  163. index_task_b = tasks_b.index(task_a)
  164. if any(isinstance(task_b, list) for task_b in tasks_b[i : index_task_b + 1]):
  165. return False
  166. return True
  167. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  168. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  169. data_node_3 = DataNode("baz", Scope.SCENARIO, "s3")
  170. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  171. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  172. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  173. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  174. task_1 = Task(
  175. "grault",
  176. {},
  177. print,
  178. [data_node_1, data_node_2],
  179. [data_node_3, data_node_4],
  180. TaskId("t1"),
  181. )
  182. task_2 = Task("garply", {}, print, [data_node_3], [data_node_5], TaskId("t2"))
  183. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], [data_node_6], TaskId("t3"))
  184. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  185. sequence = Sequence({}, [task_4, task_2, task_1, task_3], SequenceId("p1"))
  186. # s1 --- ---> s3 ---> t2 ---> s5 ----
  187. # | | |
  188. # |---> t1 ---| -------------------------> t3 ---> s6
  189. # | | |
  190. # s2 --- ---> s4 ---> t4 ---> s7
  191. assert assert_equal(sequence._get_sorted_tasks(), [[task_1], [task_2, task_4], [task_3]])
  192. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  193. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  194. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  195. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  196. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  197. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  198. task_1 = Task(
  199. "grault",
  200. {},
  201. print,
  202. [data_node_1, data_node_2],
  203. [data_node_4],
  204. TaskId("t1"),
  205. )
  206. task_2 = Task("garply", {}, print, None, [data_node_5], TaskId("t2"))
  207. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], [data_node_6], TaskId("t3"))
  208. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  209. sequence = Sequence({}, [task_4, task_2, task_1, task_3], SequenceId("p1"))
  210. # s1 --- t2 ---> s5 ------
  211. # | |
  212. # |---> t1 ---| -----> t3 ---> s6
  213. # | | |
  214. # s2 --- ---> s4 ---> t4 ---> s7
  215. assert assert_equal(sequence._get_sorted_tasks(), [[task_2, task_1], [task_4, task_3]])
  216. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  217. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  218. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  219. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  220. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  221. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  222. task_1 = Task(
  223. "grault",
  224. {},
  225. print,
  226. [data_node_1, data_node_2],
  227. [data_node_4],
  228. TaskId("t1"),
  229. )
  230. task_2 = Task("garply", {}, print, [data_node_6], [data_node_5], TaskId("t2"))
  231. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], id=TaskId("t3"))
  232. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  233. sequence = Sequence({}, [task_4, task_2, task_1, task_3], SequenceId("p1"))
  234. # s1 --- s6 ---> t2 ---> s5
  235. # | |
  236. # |---> t1 ---| -----> t3
  237. # | | |
  238. # s2 --- ---> s4 ---> t4 ---> s7
  239. assert assert_equal(sequence._get_sorted_tasks(), [[task_2, task_1], [task_4, task_3]])
  240. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  241. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  242. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  243. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  244. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  245. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  246. task_1 = Task(
  247. "grault",
  248. {},
  249. print,
  250. [data_node_1, data_node_2],
  251. [data_node_4],
  252. TaskId("t1"),
  253. )
  254. task_2 = Task("garply", {}, print, output=[data_node_5], id=TaskId("t2"))
  255. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], None, id=TaskId("t3"))
  256. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  257. sequence = Sequence({}, [task_4, task_2, task_1, task_3], SequenceId("p1"))
  258. # s1 --- t2 ---> s5
  259. # | |
  260. # |---> t1 ---| -----> t3
  261. # | | |
  262. # s2 --- ---> s4 ---> t4 ---> s7
  263. assert assert_equal(sequence._get_sorted_tasks(), [[task_2, task_1], [task_4, task_3]])
  264. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  265. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  266. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  267. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  268. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  269. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  270. data_node_8 = DataNode("hugh", Scope.SCENARIO, "s8")
  271. task_1 = Task(
  272. "grault",
  273. {},
  274. print,
  275. [data_node_1, data_node_2],
  276. [data_node_4],
  277. TaskId("t1"),
  278. )
  279. task_2 = Task("garply", {}, print, output=[data_node_5], id=TaskId("t2"))
  280. task_3 = Task("waldo", {}, print, [data_node_4], None, id=TaskId("t3"))
  281. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  282. task_5 = Task("bob", {}, print, [data_node_8], None, TaskId("t5"))
  283. sequence = Sequence({}, [task_5, task_4, task_2, task_1, task_3], SequenceId("p1"))
  284. # s1 ---
  285. # |
  286. # |---> t1 ---| -----> t3
  287. # | | |
  288. # s2 --- ---> s4 ---> t4 ---> s7
  289. # t2 ---> s5
  290. # s8 ---> t5
  291. assert assert_equal(sequence._get_sorted_tasks(), [[task_5, task_2, task_1], [task_4, task_3]])
  292. def test_get_inputs():
  293. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  294. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  295. data_node_3 = DataNode("baz", Scope.SCENARIO, "s3")
  296. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  297. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  298. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  299. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  300. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_3, data_node_4], TaskId("t1"))
  301. task_2 = Task("garply", {}, print, [data_node_3], [data_node_5], TaskId("t2"))
  302. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], [data_node_6], TaskId("t3"))
  303. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  304. sequence = Sequence({}, [task_4, task_2, task_1, task_3], SequenceId("p1"))
  305. # s1 --- ---> s3 ---> t2 ---> s5 ----
  306. # | | |
  307. # |---> t1 ---| -------------------------> t3 ---> s6
  308. # | | |
  309. # s2 --- ---> s4 ---> t4 ---> s7
  310. assert sequence.get_inputs() == {data_node_1, data_node_2}
  311. assert sequence.get_outputs() == {data_node_6, data_node_7}
  312. assert sequence.get_intermediate() == {data_node_3, data_node_4, data_node_5}
  313. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  314. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  315. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  316. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  317. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  318. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  319. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  320. task_2 = Task("garply", {}, print, None, [data_node_5], TaskId("t2"))
  321. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], [data_node_6], TaskId("t3"))
  322. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  323. sequence = Sequence({}, [task_4, task_2, task_1, task_3], SequenceId("p1"))
  324. # s1 --- t2 ---> s5 ------
  325. # | |
  326. # |---> t1 ---| -----> t3 ---> s6
  327. # | | |
  328. # s2 --- ---> s4 ---> t4 ---> s7
  329. assert sequence.get_inputs() == {data_node_1, data_node_2}
  330. assert sequence.get_outputs() == {data_node_6, data_node_7}
  331. assert sequence.get_intermediate() == {data_node_4, data_node_5}
  332. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  333. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  334. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  335. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  336. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  337. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  338. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  339. task_2 = Task("garply", {}, print, [data_node_6], [data_node_5], TaskId("t2"))
  340. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], id=TaskId("t3"))
  341. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  342. sequence = Sequence({}, [task_4, task_2, task_1, task_3], SequenceId("p1"))
  343. # s1 --- s6 ---> t2 ---> s5
  344. # | |
  345. # |---> t1 ---| -----> t3
  346. # | | |
  347. # s2 --- ---> s4 ---> t4 ---> s7
  348. assert sequence.get_inputs() == {data_node_1, data_node_2, data_node_6}
  349. assert sequence.get_outputs() == {data_node_7}
  350. assert sequence.get_intermediate() == {data_node_4, data_node_5}
  351. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  352. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  353. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  354. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  355. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  356. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  357. data_node_8 = DataNode("hugh", Scope.SCENARIO, "s8")
  358. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  359. task_2 = Task("garply", {}, print, output=[data_node_5], id=TaskId("t2"))
  360. task_3 = Task("waldo", {}, print, [data_node_4], None, id=TaskId("t3"))
  361. task_4 = Task("fred", {}, print, [data_node_4, data_node_6], [data_node_7], TaskId("t4"))
  362. task_5 = Task("bob", {}, print, [data_node_8], None, TaskId("t5"))
  363. sequence = Sequence({}, [task_5, task_4, task_2, task_1, task_3], SequenceId("p1"))
  364. # s1 ---
  365. # |
  366. # |---> t1 ---| -----> t3
  367. # | | |
  368. # s2 --- ---> s4 ---> t4 ---> s7
  369. # t2 ---> s5 |
  370. # s8 ---> t5 s6 --|
  371. assert sequence.get_inputs() == {data_node_1, data_node_2, data_node_8, data_node_6}
  372. assert sequence.get_outputs() == {data_node_5, data_node_7}
  373. assert sequence.get_intermediate() == {data_node_4}
  374. def test_is_ready_to_run():
  375. data_node_1 = PickleDataNode("foo", Scope.SCENARIO, "s1", properties={"default_data": 1})
  376. data_node_2 = PickleDataNode("bar", Scope.SCENARIO, "s2", properties={"default_data": 2})
  377. data_node_4 = PickleDataNode("qux", Scope.SCENARIO, "s4", properties={"default_data": 4})
  378. data_node_5 = PickleDataNode("quux", Scope.SCENARIO, "s5", properties={"default_data": 5})
  379. data_node_6 = PickleDataNode("quuz", Scope.SCENARIO, "s6", properties={"default_data": 6})
  380. data_node_7 = PickleDataNode("corge", Scope.SCENARIO, "s7", properties={"default_data": 7})
  381. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  382. task_2 = Task("garply", {}, print, [data_node_6], [data_node_5], TaskId("t2"))
  383. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], id=TaskId("t3"))
  384. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  385. sequence = Sequence({}, [task_4, task_2, task_1, task_3], SequenceId("p1"))
  386. # s1 --- s6 ---> t2 ---> s5
  387. # | |
  388. # |---> t1 ---| -----> t3
  389. # | | |
  390. # s2 --- ---> s4 ---> t4 ---> s7
  391. data_manager = _DataManagerFactory._build_manager()
  392. for dn in [data_node_1, data_node_2, data_node_4, data_node_5, data_node_6, data_node_7]:
  393. data_manager._set(dn)
  394. assert sequence.is_ready_to_run()
  395. data_node_1.edit_in_progress = True
  396. assert not sequence.is_ready_to_run()
  397. data_node_2.edit_in_progress = True
  398. data_node_6.edit_in_progress = True
  399. assert not sequence.is_ready_to_run()
  400. data_node_1.edit_in_progress = False
  401. data_node_2.edit_in_progress = False
  402. data_node_6.edit_in_progress = False
  403. assert sequence.is_ready_to_run()
  404. def test_data_nodes_being_edited():
  405. data_node_1 = PickleDataNode("foo", Scope.SCENARIO, "s1", properties={"default_data": 1})
  406. data_node_2 = PickleDataNode("bar", Scope.SCENARIO, "s2", properties={"default_data": 2})
  407. data_node_4 = PickleDataNode("qux", Scope.SCENARIO, "s4", properties={"default_data": 4})
  408. data_node_5 = PickleDataNode("quux", Scope.SCENARIO, "s5", properties={"default_data": 5})
  409. data_node_6 = PickleDataNode("quuz", Scope.SCENARIO, "s6", properties={"default_data": 6})
  410. data_node_7 = PickleDataNode("corge", Scope.SCENARIO, "s7", properties={"default_data": 7})
  411. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  412. task_2 = Task("garply", {}, print, [data_node_6], [data_node_5], TaskId("t2"))
  413. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], id=TaskId("t3"))
  414. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  415. sequence = Sequence({}, [task_4, task_2, task_1, task_3], SequenceId("p1"))
  416. # s1 --- s6 ---> t2 ---> s5
  417. # | |
  418. # |---> t1 ---| -----> t3
  419. # | | |
  420. # s2 --- ---> s4 ---> t4 ---> s7
  421. data_manager = _DataManagerFactory._build_manager()
  422. for dn in [data_node_1, data_node_2, data_node_4, data_node_5, data_node_6, data_node_7]:
  423. data_manager._set(dn)
  424. assert len(sequence.data_nodes_being_edited()) == 0
  425. assert sequence.data_nodes_being_edited() == set()
  426. data_node_1.edit_in_progress = True
  427. assert len(sequence.data_nodes_being_edited()) == 1
  428. assert sequence.data_nodes_being_edited() == {data_node_1}
  429. data_node_2.edit_in_progress = True
  430. data_node_6.edit_in_progress = True
  431. assert len(sequence.data_nodes_being_edited()) == 3
  432. assert sequence.data_nodes_being_edited() == {data_node_1, data_node_2, data_node_6}
  433. data_node_4.edit_in_progress = True
  434. data_node_5.edit_in_progress = True
  435. assert len(sequence.data_nodes_being_edited()) == 5
  436. assert sequence.data_nodes_being_edited() == {data_node_1, data_node_2, data_node_4, data_node_5, data_node_6}
  437. data_node_1.edit_in_progress = False
  438. data_node_2.edit_in_progress = False
  439. data_node_6.edit_in_progress = False
  440. assert len(sequence.data_nodes_being_edited()) == 2
  441. assert sequence.data_nodes_being_edited() == {data_node_4, data_node_5}
  442. data_node_4.edit_in_progress = False
  443. data_node_5.edit_in_progress = False
  444. data_node_7.edit_in_progress = True
  445. assert len(sequence.data_nodes_being_edited()) == 1
  446. assert sequence.data_nodes_being_edited() == {data_node_7}
  447. data_node_7.edit_in_progress = False
  448. assert len(sequence.data_nodes_being_edited()) == 0
  449. assert sequence.data_nodes_being_edited() == set()
  450. def test_get_tasks():
  451. task_1 = Task("grault", {}, print, id=TaskId("t1"))
  452. task_2 = Task("garply", {}, print, id=TaskId("t2"))
  453. task_3 = Task("waldo", {}, print, id=TaskId("t3"))
  454. sequence_1 = Sequence({}, [task_1, task_2, task_3], SequenceId("p1"))
  455. assert sequence_1.tasks == {"grault": task_1, "garply": task_2, "waldo": task_3}
  456. def test_get_set_of_tasks():
  457. task_1 = Task("grault", {}, print, id=TaskId("t1"))
  458. task_2 = Task("garply", {}, print, id=TaskId("t2"))
  459. task_3 = Task("waldo", {}, print, id=TaskId("t3"))
  460. sequence_1 = Sequence({}, [task_1, task_2, task_3], SequenceId("p1"))
  461. assert sequence_1._get_set_of_tasks() == {task_1, task_2, task_3}
  462. def test_auto_set_and_reload(task):
  463. tmp_task = Task("tmp_task_config_id", {}, print, list(task.output.values()), [], TaskId("tmp_task_id"))
  464. scenario = Scenario("scenario", [task, tmp_task], {}, sequences={"foo": {}})
  465. _TaskManager._set(task)
  466. _TaskManager._set(tmp_task)
  467. _ScenarioManager._set(scenario)
  468. sequence_1 = scenario.sequences["foo"]
  469. sequence_2 = _SequenceManager._get(sequence_1)
  470. # auto set & reload on tasks attribute
  471. assert len(sequence_1.tasks) == 0
  472. assert len(sequence_2.tasks) == 0
  473. sequence_1.tasks = [tmp_task]
  474. assert len(sequence_1.tasks) == 1
  475. assert sequence_1.tasks[tmp_task.config_id].id == tmp_task.id
  476. assert len(sequence_2.tasks) == 1
  477. assert sequence_2.tasks[tmp_task.config_id].id == tmp_task.id
  478. sequence_2.tasks = [task]
  479. assert len(sequence_1.tasks) == 1
  480. assert sequence_1.tasks[task.config_id].id == task.id
  481. assert len(sequence_2.tasks) == 1
  482. assert sequence_2.tasks[task.config_id].id == task.id
  483. assert sequence_1.owner_id == scenario.id
  484. assert sequence_2.owner_id == scenario.id
  485. # auto set & reload on subscribers attribute
  486. assert len(sequence_1.subscribers) == 0
  487. assert len(sequence_2.subscribers) == 0
  488. sequence_1.subscribers.append(print)
  489. assert len(sequence_1.subscribers) == 1
  490. assert len(sequence_2.subscribers) == 1
  491. sequence_2.subscribers.append(print)
  492. assert len(sequence_1.subscribers) == 2
  493. assert len(sequence_2.subscribers) == 2
  494. sequence_1.subscribers.clear()
  495. assert len(sequence_1.subscribers) == 0
  496. assert len(sequence_2.subscribers) == 0
  497. sequence_1.subscribers.extend([print, map])
  498. assert len(sequence_1.subscribers) == 2
  499. assert len(sequence_2.subscribers) == 2
  500. sequence_1.subscribers.remove(_Subscriber(print, []))
  501. assert len(sequence_1.subscribers) == 1
  502. assert len(sequence_2.subscribers) == 1
  503. sequence_2.subscribers.clear()
  504. assert len(sequence_1.subscribers) == 0
  505. assert len(sequence_2.subscribers) == 0
  506. sequence_1.subscribers + print + len
  507. assert len(sequence_1.subscribers) == 2
  508. assert len(sequence_2.subscribers) == 2
  509. sequence_1.subscribers = []
  510. assert len(sequence_1.subscribers) == 0
  511. assert len(sequence_2.subscribers) == 0
  512. with sequence_1 as sequence:
  513. assert len(sequence.tasks) == 1
  514. assert sequence.tasks[task.config_id].id == task.id
  515. assert len(sequence.subscribers) == 0
  516. assert sequence._is_in_context
  517. sequence.tasks = []
  518. sequence.subscribers = [print]
  519. assert len(sequence.tasks) == 1
  520. assert sequence.tasks[task.config_id].id == task.id
  521. assert len(sequence.subscribers) == 0
  522. assert sequence._is_in_context
  523. assert len(sequence_1.tasks) == 0
  524. assert len(sequence_1.subscribers) == 1
  525. assert not sequence_1._is_in_context
  526. def test_auto_set_and_reload_properties():
  527. scenario = Scenario("scenario", [], {}, sequences={"foo": {}})
  528. _ScenarioManager._set(scenario)
  529. sequence_1 = scenario.sequences["foo"]
  530. sequence_2 = _SequenceManager._get(sequence_1)
  531. # auto set & reload on properties attribute
  532. assert sequence_1.properties == {"name": "foo"}
  533. assert sequence_2.properties == {"name": "foo"}
  534. sequence_1.properties["qux"] = 4
  535. assert sequence_1.properties["qux"] == 4
  536. assert sequence_2.properties["qux"] == 4
  537. sequence_2.properties["qux"] = 5
  538. assert sequence_1.properties["qux"] == 5
  539. assert sequence_2.properties["qux"] == 5
  540. sequence_1.properties["temp_key_1"] = "temp_value_1"
  541. sequence_1.properties["temp_key_2"] = "temp_value_2"
  542. assert sequence_1.properties == {
  543. "qux": 5,
  544. "name": "foo",
  545. "temp_key_1": "temp_value_1",
  546. "temp_key_2": "temp_value_2",
  547. }
  548. assert sequence_2.properties == {
  549. "qux": 5,
  550. "name": "foo",
  551. "temp_key_1": "temp_value_1",
  552. "temp_key_2": "temp_value_2",
  553. }
  554. sequence_1.properties.pop("temp_key_1")
  555. assert "temp_key_1" not in sequence_1.properties.keys()
  556. assert "temp_key_1" not in sequence_1.properties.keys()
  557. assert sequence_1.properties == {
  558. "qux": 5,
  559. "name": "foo",
  560. "temp_key_2": "temp_value_2",
  561. }
  562. assert sequence_2.properties == {
  563. "qux": 5,
  564. "name": "foo",
  565. "temp_key_2": "temp_value_2",
  566. }
  567. sequence_2.properties.pop("temp_key_2")
  568. assert sequence_1.properties == {"name": "foo", "qux": 5}
  569. assert sequence_2.properties == {"name": "foo", "qux": 5}
  570. assert "temp_key_2" not in sequence_1.properties.keys()
  571. assert "temp_key_2" not in sequence_2.properties.keys()
  572. sequence_1.properties["temp_key_3"] = 0
  573. assert sequence_1.properties == {"name": "foo", "qux": 5, "temp_key_3": 0}
  574. assert sequence_2.properties == {"name": "foo", "qux": 5, "temp_key_3": 0}
  575. sequence_1.properties.update({"temp_key_3": 1})
  576. assert sequence_1.properties == {"name": "foo", "qux": 5, "temp_key_3": 1}
  577. assert sequence_2.properties == {"name": "foo", "qux": 5, "temp_key_3": 1}
  578. sequence_1.properties.update(dict())
  579. assert sequence_1.properties == {"name": "foo", "qux": 5, "temp_key_3": 1}
  580. assert sequence_2.properties == {"name": "foo", "qux": 5, "temp_key_3": 1}
  581. sequence_1.properties["temp_key_4"] = 0
  582. sequence_1.properties["temp_key_5"] = 0
  583. with sequence_1 as sequence:
  584. assert sequence._is_in_context
  585. assert sequence.properties["qux"] == 5
  586. assert sequence.properties["temp_key_3"] == 1
  587. assert sequence.properties["temp_key_4"] == 0
  588. assert sequence.properties["temp_key_5"] == 0
  589. sequence.properties["qux"] = 9
  590. sequence.properties.pop("temp_key_3")
  591. sequence.properties.pop("temp_key_4")
  592. sequence.properties.update({"temp_key_4": 1})
  593. sequence.properties.update({"temp_key_5": 2})
  594. sequence.properties.pop("temp_key_5")
  595. sequence.properties.update(dict())
  596. assert sequence._is_in_context
  597. assert sequence.properties["qux"] == 5
  598. assert sequence.properties["temp_key_3"] == 1
  599. assert sequence.properties["temp_key_4"] == 0
  600. assert sequence.properties["temp_key_5"] == 0
  601. assert not sequence_1._is_in_context
  602. assert sequence_1.properties["qux"] == 9
  603. assert "temp_key_3" not in sequence_1.properties.keys()
  604. assert sequence_1.properties["temp_key_4"] == 1
  605. assert "temp_key_5" not in sequence_1.properties.keys()
  606. def test_get_parents(sequence):
  607. with mock.patch("taipy.core.get_parents") as mck:
  608. sequence.get_parents()
  609. mck.assert_called_once_with(sequence)
  610. def test_subscribe_sequence():
  611. with mock.patch("taipy.core.subscribe_sequence") as mck:
  612. sequence = Sequence({}, [], "id")
  613. sequence.subscribe(None)
  614. mck.assert_called_once_with(None, None, sequence)
  615. def test_unsubscribe_sequence():
  616. with mock.patch("taipy.core.unsubscribe_sequence") as mck:
  617. sequence = Sequence({}, [], "id")
  618. sequence.unsubscribe(None)
  619. mck.assert_called_once_with(None, None, sequence)
  620. def test_submit_sequence():
  621. with mock.patch("taipy.core.sequence._sequence_manager._SequenceManager._submit") as mck:
  622. sequence = Sequence({}, [], "id")
  623. sequence.submit(None, False)
  624. mck.assert_called_once_with(sequence, None, False, False, None)