test_sequence.py 34 KB

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