test_scenario.py 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576
  1. # Copyright 2021-2025 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 datetime import datetime, timedelta
  12. from unittest import mock
  13. import pytest
  14. from taipy import Scope
  15. from taipy.common.config import Config
  16. from taipy.common.config.exceptions.exceptions import InvalidConfigurationId
  17. from taipy.core import create_scenario
  18. from taipy.core.common._utils import _Subscriber
  19. from taipy.core.common.frequency import Frequency
  20. from taipy.core.cycle._cycle_manager_factory import _CycleManagerFactory
  21. from taipy.core.cycle.cycle import Cycle, CycleId
  22. from taipy.core.data._data_manager_factory import _DataManagerFactory
  23. from taipy.core.data.in_memory import DataNode, InMemoryDataNode
  24. from taipy.core.data.pickle import PickleDataNode
  25. from taipy.core.exceptions.exceptions import (
  26. AttributeKeyAlreadyExisted,
  27. SequenceAlreadyExists,
  28. SequenceTaskDoesNotExistInScenario,
  29. )
  30. from taipy.core.scenario._scenario_manager_factory import _ScenarioManagerFactory
  31. from taipy.core.scenario.scenario import Scenario
  32. from taipy.core.scenario.scenario_id import ScenarioId
  33. from taipy.core.sequence.sequence import Sequence
  34. from taipy.core.sequence.sequence_id import SequenceId
  35. from taipy.core.task._task_manager_factory import _TaskManagerFactory
  36. from taipy.core.task.task import Task, TaskId
  37. def test_scenario_equals(scenario):
  38. scenario_manager = _ScenarioManagerFactory()._build_manager()
  39. scenario_id = scenario.id
  40. scenario_manager._repository._save(scenario)
  41. # To test if instance is same type
  42. task = Task("task", {}, print, [], [], scenario_id)
  43. scenario_2 = scenario_manager._get(scenario_id)
  44. assert scenario == scenario_2
  45. assert scenario != scenario_id
  46. assert scenario != task
  47. def test_create_primary_scenario(cycle):
  48. scenario = Scenario("foo", set(), {"key": "value"}, is_primary=True, cycle=cycle)
  49. assert scenario.id is not None
  50. assert scenario.config_id == "foo"
  51. assert scenario.tasks == {}
  52. assert scenario.additional_data_nodes == {}
  53. assert scenario.data_nodes == {}
  54. assert scenario.sequences == {}
  55. assert scenario.properties == {"key": "value"}
  56. assert scenario.properties["key"] == "value"
  57. assert scenario.creation_date is not None
  58. assert scenario.is_primary
  59. assert scenario.cycle == cycle
  60. assert scenario.tags == set()
  61. assert scenario.get_simple_label() == scenario.config_id
  62. with mock.patch("taipy.core.get") as get_mck:
  63. class MockOwner:
  64. label = "owner_label"
  65. def get_label(self):
  66. return self.label
  67. get_mck.return_value = MockOwner()
  68. assert scenario.get_label() == "owner_label > " + scenario.config_id
  69. def test_create_scenario_at_time(current_datetime):
  70. scenario = Scenario("bar", set(), {}, set(), ScenarioId("baz"), creation_date=current_datetime)
  71. assert scenario.id == "baz"
  72. assert scenario.config_id == "bar"
  73. assert scenario.tasks == {}
  74. assert scenario.additional_data_nodes == {}
  75. assert scenario.data_nodes == {}
  76. assert scenario.sequences == {}
  77. assert scenario.properties == {}
  78. assert scenario.creation_date == current_datetime
  79. assert not scenario.is_primary
  80. assert scenario.cycle is None
  81. assert scenario.tags == set()
  82. assert scenario.get_simple_label() == scenario.config_id
  83. assert scenario.get_label() == scenario.config_id
  84. def test_create_scenario_with_task_and_additional_dn_and_sequence():
  85. dn_1 = PickleDataNode("xyz", Scope.SCENARIO)
  86. dn_2 = PickleDataNode("abc", Scope.SCENARIO)
  87. task = Task("qux", {}, print, [dn_1])
  88. scenario = Scenario("quux", {task}, {}, {dn_2}, sequences={"acb": {"tasks": [task]}})
  89. sequence = scenario.sequences["acb"]
  90. assert scenario.id is not None
  91. assert scenario.config_id == "quux"
  92. assert len(scenario.tasks) == 1
  93. assert len(scenario.additional_data_nodes) == 1
  94. assert len(scenario.data_nodes) == 2
  95. assert len(scenario.sequences) == 1
  96. assert scenario.qux == task
  97. assert scenario.xyz == dn_1
  98. assert scenario.abc == dn_2
  99. assert scenario.acb == sequence
  100. assert scenario.properties == {}
  101. assert scenario.tags == set()
  102. def test_create_scenario_invalid_config_id():
  103. with pytest.raises(InvalidConfigurationId):
  104. Scenario("foo bar", set(), {})
  105. def test_create_scenario_and_add_sequences():
  106. input_1 = PickleDataNode("input_1", Scope.SCENARIO)
  107. output_1 = PickleDataNode("output_1", Scope.SCENARIO)
  108. output_2 = PickleDataNode("output_2", Scope.SCENARIO)
  109. additional_dn_1 = PickleDataNode("additional_1", Scope.SCENARIO)
  110. additional_dn_2 = PickleDataNode("additional_2", Scope.SCENARIO)
  111. task_1 = Task("task_1", {}, print, [input_1], [output_1], TaskId("task_id_1"))
  112. task_2 = Task("task_2", {}, print, [output_1], [output_2], TaskId("task_id_2"))
  113. data_manager = _DataManagerFactory._build_manager()
  114. task_manager = _TaskManagerFactory._build_manager()
  115. data_manager._repository._save(input_1)
  116. data_manager._repository._save(output_1)
  117. data_manager._repository._save(output_2)
  118. data_manager._repository._save(additional_dn_1)
  119. data_manager._repository._save(additional_dn_2)
  120. task_manager._repository._save(task_1)
  121. task_manager._repository._save(task_2)
  122. scenario = Scenario("scenario", {task_1}, {})
  123. _ScenarioManagerFactory._build_manager()._repository._save(scenario)
  124. scenario.sequences = {"sequence_1": {"tasks": [task_1]}, "sequence_2": {"tasks": []}}
  125. assert scenario.id is not None
  126. assert scenario.config_id == "scenario"
  127. assert len(scenario.tasks) == 1
  128. assert scenario.tasks.keys() == {task_1.config_id}
  129. assert len(scenario.additional_data_nodes) == 0
  130. assert scenario.additional_data_nodes == {}
  131. assert len(scenario.data_nodes) == 2
  132. assert scenario.data_nodes == {
  133. input_1.config_id: input_1,
  134. output_1.config_id: output_1,
  135. }
  136. assert len(scenario.sequences) == 2
  137. assert scenario.sequence_1 == scenario.sequences["sequence_1"]
  138. assert scenario.sequence_2 == scenario.sequences["sequence_2"]
  139. assert scenario.sequences == {"sequence_1": scenario.sequence_1, "sequence_2": scenario.sequence_2}
  140. def test_get_set_attribute():
  141. dn_cfg = Config.configure_data_node("bar")
  142. s_cfg = Config.configure_scenario("foo", additional_data_node_configs=[dn_cfg])
  143. scenario = create_scenario(s_cfg)
  144. scenario.key = "value"
  145. assert scenario.key == "value"
  146. with pytest.raises(AttributeKeyAlreadyExisted):
  147. scenario.bar = "KeyAlreadyUsed"
  148. def test_create_scenario_overlapping_sequences():
  149. input_1 = PickleDataNode("input_1", Scope.SCENARIO)
  150. output_1 = PickleDataNode("output_1", Scope.SCENARIO)
  151. output_2 = PickleDataNode("output_2", Scope.SCENARIO)
  152. additional_dn_1 = PickleDataNode("additional_1", Scope.SCENARIO)
  153. additional_dn_2 = PickleDataNode("additional_2", Scope.SCENARIO)
  154. task_1 = Task("task_1", {}, print, [input_1], [output_1], TaskId("task_id_1"))
  155. task_2 = Task("task_2", {}, print, [output_1], [output_2], TaskId("task_id_2"))
  156. data_manager = _DataManagerFactory._build_manager()
  157. task_manager = _TaskManagerFactory._build_manager()
  158. data_manager._repository._save(input_1)
  159. data_manager._repository._save(output_1)
  160. data_manager._repository._save(output_2)
  161. data_manager._repository._save(additional_dn_1)
  162. data_manager._repository._save(additional_dn_2)
  163. task_manager._repository._save(task_1)
  164. task_manager._repository._save(task_2)
  165. scenario = Scenario("scenario", {task_1, task_2}, {})
  166. _ScenarioManagerFactory._build_manager()._repository._save(scenario)
  167. scenario.add_sequence("sequence_1", [task_1])
  168. scenario.add_sequence("sequence_2", [task_1, task_2])
  169. assert scenario.id is not None
  170. assert scenario.config_id == "scenario"
  171. assert len(scenario.tasks) == 2
  172. assert scenario.tasks.keys() == {task_1.config_id, task_2.config_id}
  173. assert len(scenario.additional_data_nodes) == 0
  174. assert scenario.additional_data_nodes == {}
  175. assert len(scenario.data_nodes) == 3
  176. assert scenario.data_nodes == {
  177. input_1.config_id: input_1,
  178. output_1.config_id: output_1,
  179. output_2.config_id: output_2,
  180. }
  181. sequence_1 = scenario.sequences["sequence_1"]
  182. sequence_2 = scenario.sequences["sequence_2"]
  183. assert scenario.sequences == {"sequence_1": sequence_1, "sequence_2": sequence_2}
  184. scenario.remove_sequences(["sequence_2"])
  185. assert scenario.sequences == {"sequence_1": sequence_1}
  186. scenario.remove_sequences(["sequence_1"])
  187. assert scenario.sequences == {}
  188. def test_create_scenario_one_additional_dn():
  189. input_1 = PickleDataNode("input_1", Scope.SCENARIO)
  190. input_2 = PickleDataNode("input_2", Scope.SCENARIO)
  191. output_1 = PickleDataNode("output_1", Scope.SCENARIO)
  192. output_2 = PickleDataNode("output_2", Scope.SCENARIO)
  193. additional_dn_1 = PickleDataNode("additional_1", Scope.SCENARIO)
  194. additional_dn_2 = PickleDataNode("additional_2", Scope.SCENARIO)
  195. task_1 = Task("task_1", {}, print, [input_1], [output_1], TaskId("task_id_1"))
  196. task_2 = Task("task_2", {}, print, [input_2], [output_2], TaskId("task_id_2"))
  197. data_manager = _DataManagerFactory._build_manager()
  198. task_manager = _TaskManagerFactory._build_manager()
  199. data_manager._repository._save(input_1)
  200. data_manager._repository._save(output_1)
  201. data_manager._repository._save(input_2)
  202. data_manager._repository._save(output_2)
  203. data_manager._repository._save(additional_dn_1)
  204. data_manager._repository._save(additional_dn_2)
  205. task_manager._repository._save(task_1)
  206. task_manager._repository._save(task_2)
  207. scenario = Scenario("scenario", set(), {}, {additional_dn_1})
  208. assert scenario.id is not None
  209. assert scenario.config_id == "scenario"
  210. assert len(scenario.tasks) == 0
  211. assert len(scenario.additional_data_nodes) == 1
  212. assert len(scenario.data_nodes) == 1
  213. assert scenario.tasks == {}
  214. assert scenario.additional_data_nodes == {additional_dn_1.config_id: additional_dn_1}
  215. assert scenario.data_nodes == {additional_dn_1.config_id: additional_dn_1}
  216. def test_create_scenario_wth_additional_dns():
  217. input_1 = PickleDataNode("input_1", Scope.SCENARIO)
  218. input_2 = PickleDataNode("input_2", Scope.SCENARIO)
  219. output_1 = PickleDataNode("output_1", Scope.SCENARIO)
  220. output_2 = PickleDataNode("output_2", Scope.SCENARIO)
  221. additional_dn_1 = PickleDataNode("additional_1", Scope.SCENARIO)
  222. additional_dn_2 = PickleDataNode("additional_2", Scope.SCENARIO)
  223. task_1 = Task("task_1", {}, print, [input_1], [output_1], TaskId("task_id_1"))
  224. task_2 = Task("task_2", {}, print, [input_2], [output_2], TaskId("task_id_2"))
  225. data_manager = _DataManagerFactory._build_manager()
  226. task_manager = _TaskManagerFactory._build_manager()
  227. data_manager._repository._save(input_1)
  228. data_manager._repository._save(output_1)
  229. data_manager._repository._save(input_2)
  230. data_manager._repository._save(output_2)
  231. data_manager._repository._save(additional_dn_1)
  232. data_manager._repository._save(additional_dn_2)
  233. task_manager._repository._save(task_1)
  234. task_manager._repository._save(task_2)
  235. scenario = Scenario("scenario", set(), {}, {additional_dn_1, additional_dn_2})
  236. assert scenario.id is not None
  237. assert scenario.config_id == "scenario"
  238. assert len(scenario.tasks) == 0
  239. assert len(scenario.additional_data_nodes) == 2
  240. assert len(scenario.data_nodes) == 2
  241. assert scenario.tasks == {}
  242. assert scenario.additional_data_nodes == {
  243. additional_dn_1.config_id: additional_dn_1,
  244. additional_dn_2.config_id: additional_dn_2,
  245. }
  246. assert scenario.data_nodes == {
  247. additional_dn_1.config_id: additional_dn_1,
  248. additional_dn_2.config_id: additional_dn_2,
  249. }
  250. scenario_1 = Scenario("scenario_1", {task_1}, {}, {additional_dn_1})
  251. assert scenario_1.id is not None
  252. assert scenario_1.config_id == "scenario_1"
  253. assert len(scenario_1.tasks) == 1
  254. assert len(scenario_1.additional_data_nodes) == 1
  255. assert len(scenario_1.data_nodes) == 3
  256. assert scenario_1.tasks.keys() == {task_1.config_id}
  257. assert scenario_1.additional_data_nodes == {
  258. additional_dn_1.config_id: additional_dn_1,
  259. }
  260. assert scenario_1.data_nodes == {
  261. input_1.config_id: input_1,
  262. output_1.config_id: output_1,
  263. additional_dn_1.config_id: additional_dn_1,
  264. }
  265. scenario_2 = Scenario("scenario_2", {task_1, task_2}, {}, {additional_dn_1, additional_dn_2})
  266. assert scenario_2.id is not None
  267. assert scenario_2.config_id == "scenario_2"
  268. assert len(scenario_2.tasks) == 2
  269. assert len(scenario_2.additional_data_nodes) == 2
  270. assert len(scenario_2.data_nodes) == 6
  271. assert scenario_2.tasks.keys() == {task_1.config_id, task_2.config_id}
  272. assert scenario_2.additional_data_nodes == {
  273. additional_dn_1.config_id: additional_dn_1,
  274. additional_dn_2.config_id: additional_dn_2,
  275. }
  276. assert {dn_config_id: dn.id for dn_config_id, dn in scenario_2.data_nodes.items()} == {
  277. input_1.config_id: input_1.id,
  278. output_1.config_id: output_1.id,
  279. input_2.config_id: input_2.id,
  280. output_2.config_id: output_2.id,
  281. additional_dn_1.config_id: additional_dn_1.id,
  282. additional_dn_2.config_id: additional_dn_2.id,
  283. }
  284. def test_raise_sequence_tasks_not_in_scenario(data_node):
  285. task_1 = Task("task_1", {}, print, output=[data_node])
  286. task_2 = Task("task_2", {}, print, input=[data_node])
  287. with pytest.raises(SequenceTaskDoesNotExistInScenario) as err:
  288. Scenario("scenario", set(), {}, sequences={"sequence": {"tasks": [task_1]}}, scenario_id="SCENARIO_scenario")
  289. assert err.value.args == ([task_1.id], "sequence", "SCENARIO_scenario")
  290. with pytest.raises(SequenceTaskDoesNotExistInScenario) as err:
  291. Scenario(
  292. "scenario",
  293. [task_1],
  294. {},
  295. sequences={"sequence": {"tasks": [task_1, task_2]}},
  296. scenario_id="SCENARIO_scenario",
  297. )
  298. assert err.value.args == ([task_2.id], "sequence", "SCENARIO_scenario")
  299. Scenario("scenario", {task_1}, {}, sequences={"sequence": {"tasks": [task_1]}})
  300. Scenario(
  301. "scenario",
  302. [task_1, task_2],
  303. {},
  304. sequences={"sequence_1": {"tasks": [task_1]}, "sequence_2": {"tasks": [task_1, task_2]}},
  305. )
  306. def test_adding_sequence_raises_tasks_not_in_scenario(data_node):
  307. _DataManagerFactory._build_manager()._repository._save(data_node)
  308. task_1 = Task("task_1", {}, print, output=[data_node])
  309. task_2 = Task("task_2", {}, print, input=[data_node])
  310. scenario = Scenario("scenario", [task_1], {})
  311. scenario_manager = _ScenarioManagerFactory._build_manager()
  312. task_manager = _TaskManagerFactory._build_manager()
  313. scenario_manager._repository._save(scenario)
  314. task_manager._repository._save(task_1)
  315. task_manager._repository._save(task_2)
  316. scenario.add_sequences({"sequence_1": {}})
  317. with pytest.raises(SequenceTaskDoesNotExistInScenario) as err:
  318. scenario.add_sequence("sequence_2", [task_2])
  319. assert err.value.args == ([task_2.id], "sequence_2", scenario.id)
  320. scenario.add_sequence("sequence_3", [task_1])
  321. with pytest.raises(SequenceTaskDoesNotExistInScenario) as err:
  322. scenario.add_sequences({"sequence_4": [task_2]})
  323. assert err.value.args == ([task_2.id], "sequence_4", scenario.id)
  324. with pytest.raises(SequenceTaskDoesNotExistInScenario) as err:
  325. scenario.add_sequences({"sequence_5": [task_1, task_2]})
  326. assert err.value.args == ([task_2.id], "sequence_5", scenario.id)
  327. scenario.tasks = [task_1, task_2]
  328. scenario.add_sequence("sequence_6", [task_1, task_2])
  329. def test_adding_existing_sequence_raises_exception(data_node):
  330. _DataManagerFactory._build_manager()._repository._save(data_node)
  331. task_1 = Task("task_1", {}, print, output=[data_node])
  332. _TaskManagerFactory._build_manager()._repository._save(task_1)
  333. task_2 = Task("task_2", {}, print, input=[data_node])
  334. _TaskManagerFactory._build_manager()._repository._save(task_2)
  335. scenario = Scenario("scenario", tasks={task_1, task_2}, properties={})
  336. _ScenarioManagerFactory._build_manager()._repository._save(scenario)
  337. scenario.add_sequence("sequence_1", [task_1])
  338. with pytest.raises(SequenceAlreadyExists):
  339. scenario.add_sequence("sequence_1", [task_2])
  340. def test_renaming_existing_sequence_raises_exception(data_node):
  341. _DataManagerFactory._build_manager()._repository._save(data_node)
  342. task_1 = Task("task_1", {}, print, output=[data_node])
  343. _TaskManagerFactory._build_manager()._repository._save(task_1)
  344. task_2 = Task("task_2", {}, print, input=[data_node])
  345. _TaskManagerFactory._build_manager()._repository._save(task_2)
  346. scenario = Scenario("scenario", {task_1, task_2}, {})
  347. _ScenarioManagerFactory._build_manager()._repository._save(scenario)
  348. scenario.add_sequence("sequence_1", [task_1])
  349. scenario.add_sequence("sequence_2", [task_2])
  350. with pytest.raises(SequenceAlreadyExists):
  351. scenario.rename_sequence("sequence_1", "sequence_2")
  352. def test_add_rename_and_remove_sequences():
  353. data_node_1 = InMemoryDataNode("foo", Scope.SCENARIO, "s1")
  354. data_node_2 = InMemoryDataNode("bar", Scope.SCENARIO, "s2")
  355. data_node_3 = InMemoryDataNode("qux", Scope.SCENARIO, "s3")
  356. data_node_4 = InMemoryDataNode("quux", Scope.SCENARIO, "s4")
  357. data_node_5 = InMemoryDataNode("quuz", Scope.SCENARIO, "s5")
  358. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_3], TaskId("t1"))
  359. task_2 = Task("garply", {}, print, [data_node_3], id=TaskId("t2"))
  360. task_3 = Task("waldo", {}, print, [data_node_3], None, id=TaskId("t3"))
  361. task_4 = Task("fred", {}, print, [data_node_3], [data_node_4], TaskId("t4"))
  362. task_5 = Task("bob", {}, print, [data_node_5], [data_node_3], TaskId("t5"))
  363. scenario = Scenario("quest", {task_1, task_2, task_3, task_4, task_5}, {}, [], scenario_id=ScenarioId("s1"))
  364. sequence_1 = Sequence({"name": "seq_1"}, [task_1], SequenceId(f"SEQUENCE_seq_1_{scenario.id}"))
  365. sequence_2 = Sequence({"name": "seq_2"}, [task_1, task_2], SequenceId(f"SEQUENCE_seq_2_{scenario.id}"))
  366. new_seq_2 = Sequence({"name": "seq_2"}, [task_1, task_2], SequenceId(f"SEQUENCE_new_seq_2_{scenario.id}"))
  367. seq_3 = Sequence({"name": "seq 3"}, [task_1, task_5, task_3], SequenceId(f"SEQUENCE_seqTPSPACE3_{scenario.id}"))
  368. task_manager = _TaskManagerFactory._build_manager()
  369. data_manager = _DataManagerFactory._build_manager()
  370. scenario_manager = _ScenarioManagerFactory._build_manager()
  371. for dn in [data_node_1, data_node_2, data_node_3, data_node_4, data_node_5]:
  372. data_manager._repository._save(dn)
  373. for t in [task_1, task_2, task_3, task_4, task_5]:
  374. task_manager._repository._save(t)
  375. scenario_manager._repository._save(scenario)
  376. assert scenario.get_inputs() == {data_node_1, data_node_2, data_node_5}
  377. assert scenario._get_set_of_tasks() == {task_1, task_2, task_3, task_4, task_5}
  378. assert len(scenario.sequences) == 0
  379. scenario.sequences = {"seq_1": {"tasks": [task_1]}}
  380. assert scenario.sequences == {"seq_1": sequence_1}
  381. scenario.add_sequences({"seq_2": [task_1, task_2]})
  382. assert scenario.sequences == {"seq_1": sequence_1, "seq_2": sequence_2}
  383. scenario.remove_sequences(["seq_1"])
  384. assert scenario.sequences == {"seq_2": sequence_2}
  385. scenario.add_sequences({"seq_1": [task_1], "seq 3": [task_1, task_5, task_3]})
  386. assert scenario.sequences == {"seq_2": sequence_2, "seq_1": sequence_1, "seq 3": seq_3}
  387. scenario.remove_sequences(["seq_2", "seq 3"])
  388. assert scenario.sequences == {"seq_1": sequence_1}
  389. scenario.add_sequence("seq_2", [task_1, task_2])
  390. assert scenario.sequences == {"seq_1": sequence_1, "seq_2": sequence_2}
  391. scenario.add_sequence("seq 3", [task_1.id, task_5.id, task_3.id])
  392. assert scenario.sequences == {"seq_1": sequence_1, "seq_2": sequence_2, "seq 3": seq_3}
  393. scenario.remove_sequence("seq_1")
  394. assert scenario.sequences == {"seq_2": sequence_2, "seq 3": seq_3}
  395. scenario.rename_sequence("seq_2", "new_seq_2")
  396. assert scenario.sequences == {"new_seq_2": new_seq_2, "seq 3": seq_3}
  397. def test_update_sequence(data_node):
  398. _DataManagerFactory._build_manager()._repository._save(data_node)
  399. task_1 = Task("foo", {}, print, [data_node], [], TaskId("t1"))
  400. task_2 = Task("bar", {}, print, [], [data_node], id=TaskId("t2"))
  401. scenario = Scenario("baz", {task_1, task_2}, {})
  402. _TaskManagerFactory._build_manager()._repository._save(task_1)
  403. _TaskManagerFactory._build_manager()._repository._save(task_2)
  404. _ScenarioManagerFactory._build_manager()._repository._save(scenario)
  405. scenario.add_sequence("seq_1", [task_1])
  406. assert len(scenario.sequences) == 1
  407. assert scenario.sequences["seq_1"].tasks == {"foo": task_1}
  408. assert scenario.sequences["seq_1"].properties["name"] == "seq_1"
  409. scenario.update_sequence("seq_1", [task_2], {"new_key": "new_value"}, [])
  410. assert len(scenario.sequences) == 1
  411. assert scenario.sequences["seq_1"].tasks == {"bar": task_2}
  412. assert scenario.sequences["seq_1"].properties["name"] == "seq_1"
  413. assert scenario.sequences["seq_1"].properties["new_key"] == "new_value"
  414. def test_add_rename_and_remove_sequences_within_context(data_node):
  415. _DataManagerFactory._build_manager()._repository._save(data_node)
  416. task_1 = Task("task_1", {}, print, output=[data_node])
  417. task_2 = Task("task_2", {}, print, input=[data_node])
  418. _TaskManagerFactory._build_manager()._repository._save(task_1)
  419. _TaskManagerFactory._build_manager()._repository._save(task_2)
  420. scenario = Scenario(config_id="scenario", tasks={task_1, task_2}, properties={})
  421. _ScenarioManagerFactory._build_manager()._repository._save(scenario)
  422. with scenario as sc:
  423. sc.add_sequence("seq_name", [task_1])
  424. assert len(scenario.sequences) == 1
  425. assert scenario.sequences["seq_name"].tasks == {"task_1": task_1}
  426. with scenario as sc:
  427. sc.update_sequence("seq_name", [task_2])
  428. assert len(scenario.sequences) == 1
  429. assert scenario.sequences["seq_name"].tasks == {"task_2": task_2}
  430. with scenario as sc:
  431. sc.rename_sequence("seq_name", "seq name")
  432. assert scenario.sequences["seq name"].tasks == {"task_2": task_2}
  433. with scenario as sc:
  434. sc.remove_sequence("seq name")
  435. assert len(scenario.sequences) == 0
  436. def test_add_property_to_scenario():
  437. scenario = Scenario("foo", set(), {"key": "value"})
  438. _ScenarioManagerFactory._build_manager()._repository._save(scenario)
  439. assert scenario.properties == {"key": "value"}
  440. assert scenario.properties["key"] == "value"
  441. scenario.properties["new_key"] = "new_value"
  442. assert scenario.properties == {"key": "value", "new_key": "new_value"}
  443. assert scenario.properties["key"] == "value"
  444. assert scenario.properties["new_key"] == "new_value"
  445. def test_add_cycle_to_scenario(cycle):
  446. scenario = Scenario("foo", set(), {})
  447. _ScenarioManagerFactory._build_manager()._repository._save(scenario)
  448. assert scenario.cycle is None
  449. _CycleManagerFactory._build_manager()._repository._save(cycle)
  450. scenario.cycle = cycle
  451. assert scenario.cycle == cycle
  452. def test_add_and_remove_subscriber():
  453. scenario = Scenario("foo", set(), {})
  454. _ScenarioManagerFactory._build_manager()._repository._save(scenario)
  455. scenario._add_subscriber(print)
  456. assert len(scenario.subscribers) == 1
  457. scenario._remove_subscriber(print)
  458. assert len(scenario.subscribers) == 0
  459. def test_add_and_remove_tag():
  460. scenario = Scenario("foo", set(), {})
  461. assert len(scenario.tags) == 0
  462. scenario._add_tag("tag")
  463. assert len(scenario.tags) == 1
  464. scenario._remove_tag("tag")
  465. assert len(scenario.tags) == 0
  466. def test_auto_update_and_reload(cycle, current_datetime, task, data_node):
  467. scenario_1 = Scenario(
  468. "foo",
  469. set(),
  470. {"name": "bar"},
  471. set(),
  472. creation_date=current_datetime,
  473. is_primary=True,
  474. cycle=None,
  475. )
  476. additional_dn = InMemoryDataNode("additional_dn", Scope.SCENARIO)
  477. example_date = datetime.fromisoformat("2021-11-11T11:11:01.000001")
  478. tmp_cycle = Cycle(
  479. Frequency.WEEKLY,
  480. {},
  481. creation_date=example_date,
  482. start_date=example_date,
  483. end_date=example_date,
  484. name="cc",
  485. id=CycleId("tmp_cc_id"),
  486. )
  487. sequence_1_name = "sequence_1"
  488. sequence_1 = Sequence({}, [], SequenceId(f"SEQUENCE_{sequence_1_name}_{scenario_1.id}"))
  489. tmp_sequence_name = "tmp_sequence"
  490. tmp_sequence = Sequence(
  491. {},
  492. [],
  493. SequenceId(f"SEQUENCE_{tmp_sequence_name}_{scenario_1.id}"),
  494. )
  495. _TaskManagerFactory._build_manager()._repository._save(task)
  496. _DataManagerFactory._build_manager()._repository._save(data_node)
  497. _DataManagerFactory._build_manager()._repository._save(additional_dn)
  498. scenario_manager = _ScenarioManagerFactory._build_manager()
  499. cycle_manager = _CycleManagerFactory._build_manager()
  500. cycle_manager._repository._save(cycle)
  501. cycle_manager._repository._save(tmp_cycle)
  502. scenario_manager._repository._save(scenario_1)
  503. scenario_2 = scenario_manager._get(scenario_1)
  504. assert scenario_1.config_id == "foo"
  505. assert scenario_2.config_id == "foo"
  506. # auto set & reload on name attribute
  507. assert scenario_1.name == "bar"
  508. assert scenario_2.name == "bar"
  509. scenario_1.name = "zab"
  510. assert scenario_1.name == "zab"
  511. assert scenario_2.name == "zab"
  512. scenario_2.name = "baz"
  513. assert scenario_1.name == "baz"
  514. assert scenario_2.name == "baz"
  515. # auto set & reload on sequences attribute
  516. assert len(scenario_1.sequences) == 0
  517. assert len(scenario_2.sequences) == 0
  518. scenario_1.sequences = {tmp_sequence_name: {}}
  519. assert len(scenario_1.sequences) == 1
  520. assert scenario_1.sequences[tmp_sequence_name] == tmp_sequence
  521. assert len(scenario_2.sequences) == 1
  522. assert scenario_2.sequences[tmp_sequence_name] == tmp_sequence
  523. scenario_2.add_sequences({sequence_1_name: []})
  524. assert len(scenario_1.sequences) == 2
  525. assert scenario_1.sequences == {sequence_1_name: sequence_1, tmp_sequence_name: tmp_sequence}
  526. assert len(scenario_2.sequences) == 2
  527. assert scenario_2.sequences == {sequence_1_name: sequence_1, tmp_sequence_name: tmp_sequence}
  528. scenario_2.remove_sequences([tmp_sequence_name])
  529. assert len(scenario_1.sequences) == 1
  530. assert scenario_1.sequences == {sequence_1_name: sequence_1}
  531. assert len(scenario_2.sequences) == 1
  532. assert scenario_2.sequences == {sequence_1_name: sequence_1}
  533. assert len(scenario_1.tasks) == 0
  534. assert len(scenario_1.data_nodes) == 0
  535. scenario_1.tasks = {task}
  536. assert len(scenario_1.tasks) == 1
  537. assert scenario_1.tasks[task.config_id] == task
  538. assert len(scenario_1.data_nodes) == 2
  539. assert len(scenario_2.tasks) == 1
  540. assert scenario_2.tasks[task.config_id] == task
  541. assert len(scenario_2.data_nodes) == 2
  542. assert len(scenario_1.additional_data_nodes) == 0
  543. scenario_1.additional_data_nodes = {additional_dn}
  544. assert len(scenario_1.additional_data_nodes) == 1
  545. assert scenario_1.additional_data_nodes[additional_dn.config_id] == additional_dn
  546. assert len(scenario_1.data_nodes) == 3
  547. assert len(scenario_2.additional_data_nodes) == 1
  548. assert scenario_2.additional_data_nodes[additional_dn.config_id] == additional_dn
  549. assert len(scenario_2.data_nodes) == 3
  550. new_datetime = current_datetime + timedelta(1)
  551. new_datetime_1 = current_datetime + timedelta(2)
  552. # auto set & reload on name attribute
  553. assert scenario_1.creation_date == current_datetime
  554. assert scenario_2.creation_date == current_datetime
  555. scenario_1.creation_date = new_datetime_1
  556. assert scenario_1.creation_date == new_datetime_1
  557. assert scenario_2.creation_date == new_datetime_1
  558. scenario_2.creation_date = new_datetime
  559. assert scenario_1.creation_date == new_datetime
  560. assert scenario_2.creation_date == new_datetime
  561. # auto set & reload on cycle attribute
  562. assert scenario_1.cycle is None
  563. assert scenario_2.cycle is None
  564. scenario_1.cycle = tmp_cycle
  565. assert scenario_1.cycle == tmp_cycle
  566. assert scenario_2.cycle == tmp_cycle
  567. scenario_2.cycle = cycle
  568. assert scenario_1.cycle == cycle
  569. assert scenario_2.cycle == cycle
  570. # auto set & reload on is_primary attribute
  571. assert scenario_1.is_primary
  572. assert scenario_2.is_primary
  573. scenario_1.is_primary = False
  574. assert not scenario_1.is_primary
  575. assert not scenario_2.is_primary
  576. scenario_2.is_primary = True
  577. assert scenario_1.is_primary
  578. assert scenario_2.is_primary
  579. # auto set & reload on subscribers attribute
  580. assert len(scenario_1.subscribers) == 0
  581. assert len(scenario_2.subscribers) == 0
  582. scenario_1.subscribers.append(_Subscriber(print, []))
  583. assert len(scenario_1.subscribers) == 1
  584. assert len(scenario_2.subscribers) == 1
  585. scenario_2.subscribers.append(_Subscriber(print, []))
  586. assert len(scenario_1.subscribers) == 2
  587. assert len(scenario_2.subscribers) == 2
  588. scenario_1.subscribers.clear()
  589. assert len(scenario_1.subscribers) == 0
  590. assert len(scenario_2.subscribers) == 0
  591. scenario_1.subscribers.extend([_Subscriber(print, []), _Subscriber(map, [])])
  592. assert len(scenario_1.subscribers) == 2
  593. assert len(scenario_2.subscribers) == 2
  594. scenario_1.subscribers.remove(_Subscriber(print, []))
  595. assert len(scenario_1.subscribers) == 1
  596. assert len(scenario_2.subscribers) == 1
  597. scenario_1.subscribers + print + len
  598. assert len(scenario_1.subscribers) == 3
  599. assert len(scenario_2.subscribers) == 3
  600. scenario_1.subscribers = []
  601. assert len(scenario_1.subscribers) == 0
  602. assert len(scenario_2.subscribers) == 0
  603. assert len(scenario_1.tags) == 0
  604. scenario_1.tags = {"hi"}
  605. assert len(scenario_1.tags) == 1
  606. assert len(scenario_2.tags) == 1
  607. with scenario_1 as scenario:
  608. assert scenario.config_id == "foo"
  609. assert len(scenario.tasks) == 1
  610. assert len(scenario.sequences) == 1
  611. assert scenario.sequences["sequence_1"] == sequence_1
  612. assert scenario.tasks[task.config_id] == task
  613. assert len(scenario.additional_data_nodes) == 1
  614. assert scenario.additional_data_nodes[additional_dn.config_id] == additional_dn
  615. assert scenario.creation_date == new_datetime
  616. assert scenario.cycle == cycle
  617. assert scenario.is_primary
  618. assert len(scenario.subscribers) == 0
  619. assert len(scenario.tags) == 1
  620. assert scenario._is_in_context
  621. assert scenario.name == "baz"
  622. new_datetime_2 = new_datetime + timedelta(5)
  623. scenario._config_id = "foo"
  624. scenario.tasks = set()
  625. scenario.additional_data_nodes = set()
  626. scenario.remove_sequences([sequence_1_name])
  627. scenario.creation_date = new_datetime_2
  628. scenario.cycle = None
  629. scenario.is_primary = False
  630. scenario.subscribers = [print]
  631. scenario.tags = None
  632. scenario.name = "qux"
  633. assert scenario.config_id == "foo"
  634. assert len(scenario.sequences) == 1
  635. assert scenario.sequences[sequence_1_name] == sequence_1
  636. assert len(scenario.tasks) == 1
  637. assert scenario.tasks[task.config_id] == task
  638. assert len(scenario.additional_data_nodes) == 1
  639. assert scenario.additional_data_nodes[additional_dn.config_id] == additional_dn
  640. assert scenario.creation_date == new_datetime
  641. assert scenario.cycle == cycle
  642. assert scenario.is_primary
  643. assert len(scenario.subscribers) == 0
  644. assert len(scenario.tags) == 1
  645. assert scenario._is_in_context
  646. assert scenario.name == "baz"
  647. assert scenario_1.config_id == "foo"
  648. assert len(scenario_1.sequences) == 0
  649. assert len(scenario_1.tasks) == 0
  650. assert len(scenario_1.additional_data_nodes) == 0
  651. assert scenario_1.tasks == {}
  652. assert scenario_1.additional_data_nodes == {}
  653. assert scenario_1.creation_date == new_datetime_2
  654. assert scenario_1.cycle is None
  655. assert not scenario_1.is_primary
  656. assert len(scenario_1.subscribers) == 1
  657. assert len(scenario_1.tags) == 0
  658. assert not scenario_1._is_in_context
  659. def test_auto_update_and_reload_properties():
  660. scenario_1 = Scenario(
  661. "foo",
  662. set(),
  663. {"name": "baz"},
  664. )
  665. scenario_manager = _ScenarioManagerFactory._build_manager()
  666. scenario_manager._repository._save(scenario_1)
  667. scenario_2 = scenario_manager._get(scenario_1)
  668. # auto set & reload on properties attribute
  669. assert scenario_1.properties == {"name": "baz"}
  670. assert scenario_2.properties == {"name": "baz"}
  671. scenario_1._properties["qux"] = 4
  672. assert scenario_1.properties["qux"] == 4
  673. assert scenario_2.properties["qux"] == 4
  674. assert scenario_1.properties == {"name": "baz", "qux": 4}
  675. assert scenario_2.properties == {"name": "baz", "qux": 4}
  676. scenario_2._properties["qux"] = 5
  677. assert scenario_1.properties["qux"] == 5
  678. assert scenario_2.properties["qux"] == 5
  679. scenario_1.properties["temp_key_1"] = "temp_value_1"
  680. scenario_1.properties["temp_key_2"] = "temp_value_2"
  681. assert scenario_1.properties == {
  682. "name": "baz",
  683. "qux": 5,
  684. "temp_key_1": "temp_value_1",
  685. "temp_key_2": "temp_value_2",
  686. }
  687. assert scenario_2.properties == {
  688. "name": "baz",
  689. "qux": 5,
  690. "temp_key_1": "temp_value_1",
  691. "temp_key_2": "temp_value_2",
  692. }
  693. scenario_1.properties.pop("temp_key_1")
  694. assert "temp_key_1" not in scenario_1.properties.keys()
  695. assert "temp_key_1" not in scenario_1.properties.keys()
  696. assert scenario_1.properties == {
  697. "name": "baz",
  698. "qux": 5,
  699. "temp_key_2": "temp_value_2",
  700. }
  701. assert scenario_2.properties == {
  702. "name": "baz",
  703. "qux": 5,
  704. "temp_key_2": "temp_value_2",
  705. }
  706. scenario_2.properties.pop("temp_key_2")
  707. assert scenario_1.properties == {"name": "baz", "qux": 5}
  708. assert scenario_2.properties == {"name": "baz", "qux": 5}
  709. assert "temp_key_2" not in scenario_1.properties.keys()
  710. assert "temp_key_2" not in scenario_2.properties.keys()
  711. scenario_1.properties["temp_key_3"] = 0
  712. assert scenario_1.properties == {"name": "baz", "qux": 5, "temp_key_3": 0}
  713. assert scenario_2.properties == {"name": "baz", "qux": 5, "temp_key_3": 0}
  714. scenario_1.properties.update({"temp_key_3": 1})
  715. assert scenario_1.properties == {"name": "baz", "qux": 5, "temp_key_3": 1}
  716. assert scenario_2.properties == {"name": "baz", "qux": 5, "temp_key_3": 1}
  717. scenario_1.properties.update({})
  718. assert scenario_1.properties == {"name": "baz", "qux": 5, "temp_key_3": 1}
  719. assert scenario_2.properties == {"name": "baz", "qux": 5, "temp_key_3": 1}
  720. scenario_1.properties["temp_key_4"] = 0
  721. scenario_1.properties["temp_key_5"] = 0
  722. with scenario_1 as scenario:
  723. assert scenario.properties["qux"] == 5
  724. assert scenario.properties["temp_key_3"] == 1
  725. assert scenario.properties["temp_key_4"] == 0
  726. assert scenario.properties["temp_key_5"] == 0
  727. scenario.properties["qux"] = 9
  728. scenario.properties.pop("temp_key_3")
  729. scenario.properties.pop("temp_key_4")
  730. scenario.properties.update({"temp_key_4": 1})
  731. scenario.properties.update({"temp_key_5": 2})
  732. scenario.properties.pop("temp_key_5")
  733. scenario.properties.update({})
  734. assert scenario._is_in_context
  735. assert scenario.properties["qux"] == 5
  736. assert scenario.properties["temp_key_3"] == 1
  737. assert scenario.properties["temp_key_4"] == 0
  738. assert scenario.properties["temp_key_5"] == 0
  739. assert not scenario_1._is_in_context
  740. assert scenario_1.properties["qux"] == 9
  741. assert "temp_key_3" not in scenario_1.properties.keys()
  742. assert scenario_1.properties["temp_key_4"] == 1
  743. assert "temp_key_5" not in scenario_1.properties.keys()
  744. def test_is_deletable():
  745. with mock.patch("taipy.core.scenario._scenario_manager._ScenarioManager._is_deletable") as mock_submit:
  746. scenario = Scenario("foo", set(), {})
  747. scenario.is_deletable()
  748. mock_submit.assert_called_once_with(scenario)
  749. def test_submit_scenario():
  750. with mock.patch("taipy.core.scenario._scenario_manager._ScenarioManager._submit") as mock_submit:
  751. scenario = Scenario("foo", set(), {})
  752. scenario.submit(force=False)
  753. mock_submit.assert_called_once_with(scenario, None, False, False, None)
  754. def test_subscribe_scenario():
  755. with mock.patch("taipy.core.subscribe_scenario") as mock_subscribe:
  756. scenario = Scenario("foo", set(), {})
  757. scenario.subscribe(None)
  758. mock_subscribe.assert_called_once_with(None, None, scenario)
  759. def test_unsubscribe_scenario():
  760. with mock.patch("taipy.core.unsubscribe_scenario") as mock_unsubscribe:
  761. scenario = Scenario("foo", set(), {})
  762. scenario.unsubscribe(None)
  763. mock_unsubscribe.assert_called_once_with(None, None, scenario)
  764. def test_add_tag_scenario():
  765. with mock.patch("taipy.core.tag") as mock_add_tag:
  766. scenario = Scenario("foo", set(), {})
  767. scenario.add_tag("tag")
  768. mock_add_tag.assert_called_once_with(scenario, "tag")
  769. def test_remove_tag_scenario():
  770. with mock.patch("taipy.core.untag") as mock_remove_tag:
  771. scenario = Scenario("foo", set(), {})
  772. scenario.remove_tag("tag")
  773. mock_remove_tag.assert_called_once_with(scenario, "tag")
  774. def test_get_inputs_outputs_intermediate_data_nodes():
  775. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  776. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  777. data_node_3 = DataNode("baz", Scope.SCENARIO, "s3")
  778. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  779. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  780. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  781. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  782. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_3, data_node_4], TaskId("t1"))
  783. task_2 = Task("garply", {}, print, [data_node_3], [data_node_5], TaskId("t2"))
  784. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], [data_node_6], TaskId("t3"))
  785. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  786. scenario = Scenario("scenario", {task_1, task_2, task_3, task_4}, {}, set(), ScenarioId("s1"))
  787. # s1 --- ---> s3 ---> t2 ---> s5 ----
  788. # | | |
  789. # |---> t1 ---| -------------------------> t3 ---> s6
  790. # | | |
  791. # s2 --- ---> s4 ---> t4 ---> s7
  792. assert scenario.get_inputs() == {data_node_1, data_node_2}
  793. assert scenario.get_outputs() == {data_node_6, data_node_7}
  794. assert scenario.get_intermediate() == {data_node_3, data_node_4, data_node_5}
  795. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  796. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  797. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  798. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  799. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  800. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  801. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  802. task_2 = Task("garply", {}, print, None, [data_node_5], TaskId("t2"))
  803. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], [data_node_6], TaskId("t3"))
  804. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  805. scenario = Scenario("scenario", {task_1, task_2, task_3, task_4}, {}, set(), ScenarioId("s1"))
  806. # s1 --- t2 ---> s5 ------
  807. # | |
  808. # |---> t1 ---| -----> t3 ---> s6
  809. # | | |
  810. # s2 --- ---> s4 ---> t4 ---> s7
  811. assert scenario.get_inputs() == {data_node_1, data_node_2}
  812. assert scenario.get_outputs() == {data_node_6, data_node_7}
  813. assert scenario.get_intermediate() == {data_node_4, data_node_5}
  814. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  815. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  816. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  817. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  818. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  819. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  820. data_node_8 = DataNode("d8", Scope.SCENARIO, "s8")
  821. data_node_9 = DataNode("d9", Scope.SCENARIO, "s9")
  822. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  823. task_2 = Task("garply", {}, print, [data_node_6], [data_node_5], TaskId("t2"))
  824. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], id=TaskId("t3"))
  825. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  826. task_5 = Task("t5", {}, print, [data_node_8], [data_node_9], TaskId("t5"))
  827. task_6 = Task("t6", {}, print, [data_node_7, data_node_9], id=TaskId("t6"))
  828. scenario = Scenario("scenario", {task_1, task_2, task_3, task_4, task_5, task_6}, {}, set(), ScenarioId("s1"))
  829. # s1 --- s6 ---> t2 ---> s5
  830. # | |
  831. # |---> t1 ---| -----> t3
  832. # | | |
  833. # s2 --- ---> s4 ---> t4 ---> s7 ---> t6
  834. # |
  835. # s8 -------> t5 -------> s9 ------------------
  836. assert scenario.get_inputs() == {data_node_1, data_node_2, data_node_6, data_node_8}
  837. assert scenario.get_outputs() == set()
  838. assert scenario.get_intermediate() == {data_node_5, data_node_4, data_node_7, data_node_9}
  839. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  840. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  841. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  842. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  843. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  844. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  845. data_node_8 = DataNode("hugh", Scope.SCENARIO, "s8")
  846. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  847. task_2 = Task("garply", {}, print, output=[data_node_5], id=TaskId("t2"))
  848. task_3 = Task("waldo", {}, print, [data_node_4], None, id=TaskId("t3"))
  849. task_4 = Task("fred", {}, print, [data_node_4, data_node_6], [data_node_7], TaskId("t4"))
  850. task_5 = Task("bob", {}, print, [data_node_8], None, TaskId("t5"))
  851. scenario = Scenario("scenario", {task_1, task_2, task_3, task_4, task_5}, {}, set(), ScenarioId("sc1"))
  852. # s1 ---
  853. # |
  854. # |---> t1 ---| -----> t3
  855. # | | |
  856. # s2 --- ---> s4 ---> t4 ---> s7
  857. # t2 ---> s5 |
  858. # s8 ---> t5 s6 --|
  859. assert scenario.get_inputs() == {data_node_1, data_node_2, data_node_8, data_node_6}
  860. assert scenario.get_outputs() == {data_node_5, data_node_7}
  861. assert scenario.get_intermediate() == {data_node_4}
  862. def test_is_ready_to_run():
  863. task_1_id, task_2_id, task_3_id, task_4_id, task_5_id, task_6_id = (
  864. TaskId("TASK_t1"),
  865. TaskId("TASK_t2"),
  866. TaskId("TASK_t3"),
  867. TaskId("TASK_t4"),
  868. TaskId("TASK_t5"),
  869. TaskId("TASK_t6"),
  870. )
  871. sc_id = ScenarioId("SCENARIO_s1")
  872. data_node_1 = PickleDataNode("foo", Scope.SCENARIO, "d1", parent_ids={task_1_id}, properties={"default_data": 1})
  873. data_node_2 = PickleDataNode("bar", Scope.SCENARIO, "d2", parent_ids={task_1_id}, properties={"default_data": 2})
  874. data_node_4 = PickleDataNode(
  875. "qux", Scope.SCENARIO, "d4", parent_ids={task_1_id, task_4_id, task_3_id}, properties={"default_data": 4}
  876. )
  877. data_node_5 = PickleDataNode(
  878. "quux", Scope.SCENARIO, "d5", parent_ids={task_2_id, task_3_id}, properties={"default_data": 5}
  879. )
  880. data_node_6 = PickleDataNode("quuz", Scope.SCENARIO, "d6", parent_ids={task_2_id}, properties={"default_data": 6})
  881. data_node_7 = PickleDataNode(
  882. "corge", Scope.SCENARIO, "d7", parent_ids={task_4_id, task_6_id}, properties={"default_data": 7}
  883. )
  884. data_node_8 = PickleDataNode("d8", Scope.SCENARIO, "d8", parent_ids={task_5_id}, properties={"default_data": 8})
  885. data_node_9 = PickleDataNode(
  886. "d9", Scope.SCENARIO, "d9", parent_ids={task_5_id, task_6_id}, properties={"default_data": 9}
  887. )
  888. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], id=task_1_id, parent_ids={sc_id})
  889. task_2 = Task("garply", {}, print, [data_node_6], [data_node_5], id=task_2_id, parent_ids={sc_id})
  890. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], id=task_3_id, parent_ids={sc_id})
  891. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], id=task_4_id, parent_ids={sc_id})
  892. task_5 = Task("t5", {}, print, [data_node_8], [data_node_9], id=task_5_id, parent_ids={sc_id})
  893. task_6 = Task("t6", {}, print, [data_node_7, data_node_9], id=task_6_id, parent_ids={sc_id})
  894. scenario = Scenario("scenario", {task_1, task_2, task_3, task_4, task_5, task_6}, {}, set(), scenario_id=sc_id)
  895. # d1 --- d6 ---> t2 ---> d5
  896. # | |
  897. # |---> t1 ---| -----> t3
  898. # | | |
  899. # d2 --- ---> d4 ---> t4 ---> d7 ---> t6
  900. # |
  901. # d8 -------> t5 -------> d9 ------------------
  902. assert scenario.get_inputs() == {data_node_1, data_node_2, data_node_6, data_node_8}
  903. data_manager = _DataManagerFactory._build_manager()
  904. data_manager._delete_all()
  905. for dn in [data_node_1, data_node_2, data_node_4, data_node_5, data_node_6, data_node_7, data_node_8, data_node_9]:
  906. data_manager._repository._save(dn)
  907. task_manager = _TaskManagerFactory._build_manager()
  908. for task in [task_1, task_2, task_3, task_4, task_5, task_6]:
  909. task_manager._repository._save(task)
  910. _ScenarioManagerFactory._build_manager()._repository._save(scenario)
  911. assert scenario.is_ready_to_run()
  912. data_node_1.edit_in_progress = True
  913. assert not scenario.is_ready_to_run()
  914. data_node_2.edit_in_progress = True
  915. assert not scenario.is_ready_to_run()
  916. data_node_6.edit_in_progress = True
  917. data_node_8.edit_in_progress = True
  918. assert not scenario.is_ready_to_run()
  919. data_node_1.edit_in_progress = False
  920. data_node_2.edit_in_progress = False
  921. data_node_6.edit_in_progress = False
  922. data_node_8.edit_in_progress = False
  923. assert scenario.is_ready_to_run()
  924. def test_data_nodes_being_edited():
  925. data_node_1 = PickleDataNode("foo", Scope.SCENARIO, "s1", properties={"default_data": 1})
  926. data_node_2 = PickleDataNode("bar", Scope.SCENARIO, "s2", properties={"default_data": 2})
  927. data_node_4 = PickleDataNode("qux", Scope.SCENARIO, "s4", properties={"default_data": 4})
  928. data_node_5 = PickleDataNode("quux", Scope.SCENARIO, "s5", properties={"default_data": 5})
  929. data_node_6 = PickleDataNode("quuz", Scope.SCENARIO, "s6", properties={"default_data": 6})
  930. data_node_7 = PickleDataNode("corge", Scope.SCENARIO, "s7", properties={"default_data": 7})
  931. data_node_8 = PickleDataNode("d8", Scope.SCENARIO, "s8", properties={"default_data": 8})
  932. data_node_9 = PickleDataNode("d9", Scope.SCENARIO, "s9", properties={"default_data": 9})
  933. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  934. task_2 = Task("garply", {}, print, [data_node_6], [data_node_5], TaskId("t2"))
  935. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], id=TaskId("t3"))
  936. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  937. task_5 = Task("t5", {}, print, [data_node_8], [data_node_9], TaskId("t5"))
  938. task_6 = Task("t6", {}, print, [data_node_7, data_node_9], id=TaskId("t6"))
  939. scenario = Scenario("scenario", {task_1, task_2, task_3, task_4, task_5, task_6}, {}, set(), ScenarioId("s1"))
  940. # s1 --- s6 ---> t2 ---> s5
  941. # | |
  942. # |---> t1 ---| -----> t3
  943. # | | |
  944. # s2 --- ---> s4 ---> t4 ---> s7 ---> t6
  945. # |
  946. # s8 -------> t5 -------> s9 ------------------
  947. data_manager = _DataManagerFactory._build_manager()
  948. for dn in [data_node_1, data_node_2, data_node_4, data_node_5, data_node_6, data_node_7, data_node_8, data_node_9]:
  949. data_manager._repository._save(dn)
  950. assert len(scenario.data_nodes_being_edited()) == 0
  951. assert scenario.data_nodes_being_edited() == set()
  952. data_node_1.edit_in_progress = True
  953. assert len(scenario.data_nodes_being_edited()) == 1
  954. assert scenario.data_nodes_being_edited() == {data_node_1}
  955. data_node_2.edit_in_progress = True
  956. data_node_6.edit_in_progress = True
  957. data_node_8.edit_in_progress = True
  958. assert len(scenario.data_nodes_being_edited()) == 4
  959. assert scenario.data_nodes_being_edited() == {data_node_1, data_node_2, data_node_6, data_node_8}
  960. data_node_4.edit_in_progress = True
  961. data_node_5.edit_in_progress = True
  962. data_node_9.edit_in_progress = True
  963. assert len(scenario.data_nodes_being_edited()) == 7
  964. assert scenario.data_nodes_being_edited() == {
  965. data_node_1,
  966. data_node_2,
  967. data_node_4,
  968. data_node_5,
  969. data_node_6,
  970. data_node_8,
  971. data_node_9,
  972. }
  973. data_node_1.edit_in_progress = False
  974. data_node_2.edit_in_progress = False
  975. data_node_6.edit_in_progress = False
  976. data_node_8.edit_in_progress = False
  977. assert len(scenario.data_nodes_being_edited()) == 3
  978. assert scenario.data_nodes_being_edited() == {data_node_4, data_node_5, data_node_9}
  979. data_node_4.edit_in_progress = False
  980. data_node_5.edit_in_progress = False
  981. data_node_7.edit_in_progress = True
  982. assert len(scenario.data_nodes_being_edited()) == 2
  983. assert scenario.data_nodes_being_edited() == {data_node_7, data_node_9}
  984. data_node_7.edit_in_progress = False
  985. data_node_9.edit_in_progress = False
  986. assert len(scenario.data_nodes_being_edited()) == 0
  987. assert scenario.data_nodes_being_edited() == set()
  988. def test_get_tasks():
  989. task_1 = Task("grault", {}, print, id=TaskId("t1"))
  990. task_2 = Task("garply", {}, print, id=TaskId("t2"))
  991. task_3 = Task("waldo", {}, print, id=TaskId("t3"))
  992. task_4 = Task("fred", {}, print, id=TaskId("t4"))
  993. scenario_1 = Scenario("scenario_1", {task_1, task_2, task_3, task_4}, {}, set(), ScenarioId("s1"))
  994. assert scenario_1.tasks == {"grault": task_1, "garply": task_2, "waldo": task_3, "fred": task_4}
  995. task_5 = Task("wallo", {}, print, id=TaskId("t5"))
  996. scenario_2 = Scenario("scenario_2", {task_1, task_2, task_3, task_4, task_5}, {}, set(), ScenarioId("s2"))
  997. assert scenario_2.tasks == {"grault": task_1, "garply": task_2, "waldo": task_3, "fred": task_4, "wallo": task_5}
  998. def test_get_set_of_tasks():
  999. task_1 = Task("grault", {}, print, id=TaskId("t1"))
  1000. task_2 = Task("garply", {}, print, id=TaskId("t2"))
  1001. task_3 = Task("waldo", {}, print, id=TaskId("t3"))
  1002. task_4 = Task("fred", {}, print, id=TaskId("t4"))
  1003. scenario_1 = Scenario("scenario_1", {task_1, task_2, task_3, task_4}, {}, set(), ScenarioId("s1"))
  1004. assert scenario_1._get_set_of_tasks() == {task_1, task_2, task_3, task_4}
  1005. task_5 = Task("wallo", {}, print, id=TaskId("t5"))
  1006. scenario_2 = Scenario("scenario_2", {task_1, task_2, task_3, task_4, task_5}, {}, set(), ScenarioId("s2"))
  1007. assert scenario_2._get_set_of_tasks() == {task_1, task_2, task_3, task_4, task_5}
  1008. def test_get_sorted_tasks():
  1009. def _assert_equal(tasks_a, tasks_b) -> bool:
  1010. if len(tasks_a) != len(tasks_b):
  1011. return False
  1012. for i in range(len(tasks_a)):
  1013. task_a, task_b = tasks_a[i], tasks_b[i]
  1014. if isinstance(task_a, list) and isinstance(task_b, list):
  1015. if not _assert_equal(task_a, task_b):
  1016. return False
  1017. elif isinstance(task_a, list) or isinstance(task_b, list):
  1018. return False
  1019. else:
  1020. index_task_b = tasks_b.index(task_a)
  1021. if any(isinstance(task_b, list) for task_b in tasks_b[i : index_task_b + 1]):
  1022. return False
  1023. return True
  1024. # s1 --- ---> s3 ---> t2 ---> s5 ----
  1025. # | | |
  1026. # |---> t1 ---| -------------------------> t3 ---> s6
  1027. # | | |
  1028. # s2 --- ---> s4 ---> t4 ---> s7
  1029. data_node_1 = InMemoryDataNode("foo", Scope.SCENARIO, "s1")
  1030. data_node_2 = InMemoryDataNode("bar", Scope.SCENARIO, "s2")
  1031. data_node_3 = InMemoryDataNode("baz", Scope.SCENARIO, "s3")
  1032. data_node_4 = InMemoryDataNode("qux", Scope.SCENARIO, "s4")
  1033. data_node_5 = InMemoryDataNode("quux", Scope.SCENARIO, "s5")
  1034. data_node_6 = InMemoryDataNode("quuz", Scope.SCENARIO, "s6")
  1035. data_node_7 = InMemoryDataNode("corge", Scope.SCENARIO, "s7")
  1036. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_3, data_node_4], TaskId("t1"))
  1037. task_2 = Task("garply", {}, print, [data_node_3], [data_node_5], TaskId("t2"))
  1038. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], [data_node_6], TaskId("t3"))
  1039. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  1040. scenario_1 = Scenario("scenario_1", {task_1, task_2, task_3, task_4}, {}, [], ScenarioId("s1"))
  1041. assert scenario_1.get_inputs() == {data_node_1, data_node_2}
  1042. assert scenario_1._get_set_of_tasks() == {task_1, task_2, task_3, task_4}
  1043. _assert_equal(scenario_1._get_sorted_tasks(), [[task_1], [task_2, task_4], [task_3]])
  1044. # s1 --- t2 ---> s5
  1045. # | |
  1046. # |---> t1 ---| -----> t3 ---> s6
  1047. # | | |
  1048. # s2 --- ---> s4 ---> t4 ---> s7
  1049. data_node_1 = InMemoryDataNode("foo", Scope.SCENARIO, "s1")
  1050. data_node_2 = InMemoryDataNode("bar", Scope.SCENARIO, "s2")
  1051. data_node_4 = InMemoryDataNode("qux", Scope.SCENARIO, "s4")
  1052. data_node_5 = InMemoryDataNode("quux", Scope.SCENARIO, "s5")
  1053. data_node_6 = InMemoryDataNode("quuz", Scope.SCENARIO, "s6")
  1054. data_node_7 = InMemoryDataNode("corge", Scope.SCENARIO, "s7")
  1055. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  1056. task_2 = Task("garply", {}, print, None, [data_node_5], TaskId("t2"))
  1057. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], [data_node_6], TaskId("t3"))
  1058. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  1059. scenario_2 = Scenario("scenario_2", {task_1, task_2, task_3, task_4}, {}, [], ScenarioId("s2"))
  1060. assert scenario_2.get_inputs() == {data_node_1, data_node_2}
  1061. assert scenario_2._get_set_of_tasks() == {task_1, task_2, task_3, task_4}
  1062. _assert_equal(scenario_2._get_sorted_tasks(), [[task_1, task_2], [task_3, task_4]])
  1063. # s1 --- s6 ---> t2 ---> s5
  1064. # | |
  1065. # |---> t1 ---| -----> t3
  1066. # | | |
  1067. # s2 --- ---> s4 ---> t4 ---> s7
  1068. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  1069. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  1070. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  1071. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  1072. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  1073. data_node_7 = DataNode("corge", Scope.SCENARIO, "s7")
  1074. task_1 = Task(
  1075. "grault",
  1076. {},
  1077. print,
  1078. [data_node_1, data_node_2],
  1079. [data_node_4],
  1080. TaskId("t1"),
  1081. )
  1082. task_2 = Task("garply", {}, print, [data_node_6], [data_node_5], TaskId("t2"))
  1083. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], id=TaskId("t3"))
  1084. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  1085. scenario_3 = Scenario("quest", [task_4, task_2, task_1, task_3], {}, [], scenario_id=ScenarioId("s3"))
  1086. assert scenario_3.get_inputs() == {data_node_1, data_node_2, data_node_6}
  1087. assert scenario_3._get_set_of_tasks() == {task_1, task_2, task_3, task_4}
  1088. assert _assert_equal(scenario_3._get_sorted_tasks(), [[task_2, task_1], [task_4, task_3]])
  1089. # s1 --- s6 ---> t2 ---> s5
  1090. # | |
  1091. # |---> t1 ---| -----> t3
  1092. # | | |
  1093. # s2 --- ---> s4 ---> t4 ---> s7 ---> t6
  1094. # |
  1095. # s8 -------> t5 -------> s9 ------------------
  1096. data_node_1 = InMemoryDataNode("foo", Scope.SCENARIO, "s1")
  1097. data_node_2 = InMemoryDataNode("bar", Scope.SCENARIO, "s2")
  1098. data_node_4 = InMemoryDataNode("qux", Scope.SCENARIO, "s4")
  1099. data_node_5 = InMemoryDataNode("quux", Scope.SCENARIO, "s5")
  1100. data_node_6 = InMemoryDataNode("quuz", Scope.SCENARIO, "s6")
  1101. data_node_7 = InMemoryDataNode("corge", Scope.SCENARIO, "s7")
  1102. data_node_8 = InMemoryDataNode("d8", Scope.SCENARIO, "s8")
  1103. data_node_9 = InMemoryDataNode("d9", Scope.SCENARIO, "s9")
  1104. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  1105. task_2 = Task("garply", {}, print, [data_node_6], [data_node_5], TaskId("t2"))
  1106. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], id=TaskId("t3"))
  1107. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  1108. task_5 = Task("t5", {}, print, [data_node_8], [data_node_9], TaskId("t5"))
  1109. task_6 = Task("t6", {}, print, [data_node_7, data_node_9], id=TaskId("t6"))
  1110. scenario_4 = Scenario("scenario_3", [task_1, task_2, task_3, task_4, task_5, task_6], {}, [], ScenarioId("s4"))
  1111. assert scenario_4.get_inputs() == {data_node_1, data_node_2, data_node_6, data_node_8}
  1112. assert scenario_4._get_set_of_tasks() == {task_1, task_2, task_3, task_4, task_5, task_6}
  1113. _assert_equal(scenario_4._get_sorted_tasks(), [[task_1, task_2, task_5], [task_3, task_4], [task_6]])
  1114. # s1 ---
  1115. # |
  1116. # |---> t1 ---| -----> t3
  1117. # | | |
  1118. # s2 --- ---> s4 ---> t4 ---> s7
  1119. # t2 ---> s5 |
  1120. # s8 ---> t5 s6 --|
  1121. data_node_1 = InMemoryDataNode("foo", Scope.SCENARIO, "s1")
  1122. data_node_2 = InMemoryDataNode("bar", Scope.SCENARIO, "s2")
  1123. data_node_4 = InMemoryDataNode("qux", Scope.SCENARIO, "s4")
  1124. data_node_5 = InMemoryDataNode("quux", Scope.SCENARIO, "s5")
  1125. data_node_6 = InMemoryDataNode("quuz", Scope.SCENARIO, "s6")
  1126. data_node_7 = InMemoryDataNode("corge", Scope.SCENARIO, "s7")
  1127. data_node_8 = InMemoryDataNode("hugh", Scope.SCENARIO, "s8")
  1128. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  1129. task_2 = Task("garply", {}, print, output=[data_node_5], id=TaskId("t2"))
  1130. task_3 = Task("waldo", {}, print, [data_node_4], None, id=TaskId("t3"))
  1131. task_4 = Task("fred", {}, print, [data_node_4, data_node_6], [data_node_7], TaskId("t4"))
  1132. task_5 = Task("bob", {}, print, [data_node_8], None, TaskId("t5"))
  1133. scenario_5 = Scenario("scenario_4", [task_1, task_2, task_3, task_4, task_5], {}, [], ScenarioId("s5"))
  1134. assert scenario_5.get_inputs() == {data_node_1, data_node_2, data_node_8, data_node_6}
  1135. assert scenario_5._get_set_of_tasks() == {task_1, task_2, task_3, task_4, task_5}
  1136. _assert_equal(scenario_5._get_sorted_tasks(), [[task_1, task_2, task_5], [task_3, task_4]])
  1137. # p1 s1 ---
  1138. # |
  1139. # |---> t1 ---| -----> t3
  1140. # | | |
  1141. # s2 --- ---> s4 ---> t4 ---> s5
  1142. # p2 t2 ---> s4 ---> t3
  1143. # p3 s6 ---> t5
  1144. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  1145. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  1146. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  1147. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  1148. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  1149. task_1 = Task(
  1150. "grault",
  1151. {},
  1152. print,
  1153. [data_node_1, data_node_2],
  1154. [data_node_4],
  1155. TaskId("t1"),
  1156. )
  1157. task_2 = Task("garply", {}, print, output=[data_node_4], id=TaskId("t2"))
  1158. task_3 = Task("waldo", {}, print, [data_node_4], None, id=TaskId("t3"))
  1159. task_4 = Task("fred", {}, print, [data_node_4], [data_node_5], TaskId("t4"))
  1160. task_5 = Task("bob", {}, print, [data_node_6], None, TaskId("t5"))
  1161. scenario_6 = Scenario("quest", [task_1, task_2, task_3, task_4, task_5], {}, [], ScenarioId("s6"))
  1162. assert scenario_6.get_inputs() == {data_node_1, data_node_2, data_node_6}
  1163. assert scenario_6._get_set_of_tasks() == {task_1, task_2, task_3, task_4, task_5}
  1164. _assert_equal(scenario_6._get_sorted_tasks(), [[task_5, task_2, task_1], [task_4, task_3]])
  1165. # p1 s1 ---
  1166. # |
  1167. # |---> t1 ---| -----> t3
  1168. # | | |
  1169. # s2 --- ---> s4 ---> t4 ---> s5
  1170. # p2 t2 ---> s4 ---> t3
  1171. # p3 s6 ---> t5 ---> s4 ---> t4 ---> s5
  1172. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  1173. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  1174. data_node_4 = DataNode("qux", Scope.SCENARIO, "s4")
  1175. data_node_5 = DataNode("quux", Scope.SCENARIO, "s5")
  1176. data_node_6 = DataNode("quuz", Scope.SCENARIO, "s6")
  1177. task_1 = Task(
  1178. "grault",
  1179. {},
  1180. print,
  1181. [data_node_1, data_node_2],
  1182. [data_node_4],
  1183. TaskId("t1"),
  1184. )
  1185. task_2 = Task("garply", {}, print, output=[data_node_4], id=TaskId("t2"))
  1186. task_3 = Task("waldo", {}, print, [data_node_4], None, id=TaskId("t3"))
  1187. task_4 = Task("fred", {}, print, [data_node_4], [data_node_5], TaskId("t4"))
  1188. task_5 = Task("bob", {}, print, [data_node_6], [data_node_4], None, TaskId("t5"))
  1189. scenario_7 = Scenario("quest", [task_4, task_1, task_2, task_3, task_5], {}, [], scenario_id=ScenarioId("s7"))
  1190. assert scenario_7.get_inputs() == {data_node_1, data_node_2, data_node_6}
  1191. assert scenario_7._get_set_of_tasks() == {task_1, task_2, task_3, task_4, task_5}
  1192. _assert_equal(scenario_7._get_sorted_tasks(), [[task_5, task_2, task_1], [task_4, task_3]])
  1193. # p1 s1 ---
  1194. # |
  1195. # |---> t1 ---| -----> t3
  1196. # | | |
  1197. # s2 --- ---> s3 ---> t4 ---> s4
  1198. # p2 t2 ---> s3 ---> t3
  1199. # p3 s5 ---> t5 ---> s3 ---> t4 ---> s4
  1200. # p4 s3 ---> t4 ---> s4
  1201. data_node_1 = DataNode("foo", Scope.SCENARIO, "s1")
  1202. data_node_2 = DataNode("bar", Scope.SCENARIO, "s2")
  1203. data_node_3 = DataNode("qux", Scope.SCENARIO, "s3")
  1204. data_node_4 = DataNode("quux", Scope.SCENARIO, "s4")
  1205. data_node_5 = DataNode("quuz", Scope.SCENARIO, "s5")
  1206. task_1 = Task(
  1207. "grault",
  1208. {},
  1209. print,
  1210. [data_node_1, data_node_2],
  1211. [data_node_3],
  1212. TaskId("t1"),
  1213. )
  1214. task_2 = Task("garply", {}, print, output=[data_node_3], id=TaskId("t2"))
  1215. task_3 = Task("waldo", {}, print, [data_node_3], None, id=TaskId("t3"))
  1216. task_4 = Task("fred", {}, print, [data_node_3], [data_node_4], TaskId("t4"))
  1217. task_5 = Task("bob", {}, print, [data_node_5], [data_node_3], TaskId("t5"))
  1218. scenario_8 = Scenario("quest", [task_1, task_2, task_3, task_4, task_5], {}, [], scenario_id=ScenarioId("s8"))
  1219. assert scenario_8.get_inputs() == {data_node_1, data_node_2, data_node_5}
  1220. assert scenario_8._get_set_of_tasks() == {task_1, task_2, task_3, task_4, task_5}
  1221. _assert_equal(scenario_8._get_sorted_tasks(), [[task_5, task_2, task_1], [task_3, task_4]])
  1222. def test_check_consistency():
  1223. data_node_1 = InMemoryDataNode("foo", Scope.SCENARIO, "s1")
  1224. data_node_2 = InMemoryDataNode("bar", Scope.SCENARIO, "s2")
  1225. data_node_3 = InMemoryDataNode("bar", Scope.SCENARIO, "s3")
  1226. data_node_4 = InMemoryDataNode("qux", Scope.SCENARIO, "s4")
  1227. data_node_5 = InMemoryDataNode("quux", Scope.SCENARIO, "s5")
  1228. data_node_6 = InMemoryDataNode("quuz", Scope.SCENARIO, "s6")
  1229. data_node_7 = InMemoryDataNode("corge", Scope.SCENARIO, "s7")
  1230. data_node_8 = InMemoryDataNode("d8", Scope.SCENARIO, "s8")
  1231. data_node_9 = InMemoryDataNode("d9", Scope.SCENARIO, "s9")
  1232. scenario_0 = Scenario("scenario_0", [], {})
  1233. assert scenario_0._is_consistent()
  1234. task_1 = Task("foo", {}, print, [data_node_1], [data_node_2], TaskId("t1"))
  1235. scenario_1 = Scenario("scenario_1", [task_1], {})
  1236. assert scenario_1._is_consistent()
  1237. # s1 --- ---> s3 ---> t2 ---> s5 ----
  1238. # | | |
  1239. # |---> t1 ---| -------------------------> t3 ---> s6
  1240. # | | |
  1241. # s2 --- ---> s4 ---> t4 ---> s7
  1242. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_3, data_node_4], TaskId("t1"))
  1243. task_2 = Task("garply", {}, print, [data_node_3], [data_node_5], TaskId("t2"))
  1244. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], [data_node_6], TaskId("t3"))
  1245. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  1246. scenario_2 = Scenario("scenario_2", {task_1, task_2, task_3, task_4}, {}, [], ScenarioId("s1"))
  1247. assert scenario_2._is_consistent()
  1248. # s1 --- t2 ---> s5
  1249. # | |
  1250. # |---> t1 ---| -----> t3 ---> s6
  1251. # | | |
  1252. # s2 --- ---> s4 ---> t4 ---> s7
  1253. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  1254. task_2 = Task("garply", {}, print, None, [data_node_5], TaskId("t2"))
  1255. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], [data_node_6], TaskId("t3"))
  1256. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  1257. scenario_3 = Scenario("scenario_3", {task_1, task_2, task_3, task_4}, {}, [], ScenarioId("s2"))
  1258. assert scenario_3._is_consistent()
  1259. # s1 --- s6 ---> t2 ---> s5
  1260. # | |
  1261. # |---> t1 ---| -----> t3
  1262. # | | |
  1263. # s2 --- ---> s4 ---> t4 ---> s7
  1264. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  1265. task_2 = Task("garply", {}, print, [data_node_6], [data_node_5], TaskId("t2"))
  1266. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], id=TaskId("t3"))
  1267. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  1268. scenario_4 = Scenario("scenario_4", [task_4, task_2, task_1, task_3], {}, [], scenario_id=ScenarioId("s3"))
  1269. assert scenario_4._is_consistent()
  1270. # s1 --- s6 ---> t2 ---> s5
  1271. # | |
  1272. # |---> t1 ---| -----> t3
  1273. # | | |
  1274. # s2 --- ---> s4 ---> t4 ---> s7 ---> t6
  1275. # |
  1276. # s8 -------> t5 -------> s9 ------------------
  1277. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  1278. task_2 = Task("garply", {}, print, [data_node_6], [data_node_5], TaskId("t2"))
  1279. task_3 = Task("waldo", {}, print, [data_node_5, data_node_4], id=TaskId("t3"))
  1280. task_4 = Task("fred", {}, print, [data_node_4], [data_node_7], TaskId("t4"))
  1281. task_5 = Task("t5", {}, print, [data_node_8], [data_node_9], TaskId("t5"))
  1282. task_6 = Task("t6", {}, print, [data_node_7, data_node_9], id=TaskId("t6"))
  1283. scenario_5 = Scenario("scenario_5", [task_1, task_2, task_3, task_4, task_5, task_6], {}, [], ScenarioId("s4"))
  1284. assert scenario_5._is_consistent()
  1285. # s1 ---
  1286. # |
  1287. # |---> t1 ---| -----> t3
  1288. # | | |
  1289. # s2 --- ---> s4 ---> t4 ---> s7
  1290. # t2 ---> s5 |
  1291. # s8 ---> t5 s6 --|
  1292. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  1293. task_2 = Task("garply", {}, print, output=[data_node_5], id=TaskId("t2"))
  1294. task_3 = Task("waldo", {}, print, [data_node_4], None, id=TaskId("t3"))
  1295. task_4 = Task("fred", {}, print, [data_node_4, data_node_6], [data_node_7], TaskId("t4"))
  1296. task_5 = Task("bob", {}, print, [data_node_8], None, TaskId("t5"))
  1297. scenario_6 = Scenario("scenario_6", [task_1, task_2, task_3, task_4, task_5], {}, [], ScenarioId("s5"))
  1298. assert scenario_6._is_consistent()
  1299. # p1 s1 ---
  1300. # |
  1301. # |---> t1 ---| -----> t3
  1302. # | | |
  1303. # s2 --- ---> s4 ---> t4 ---> s5
  1304. # p2 t2 ---> s4 ---> t3
  1305. # p3 s6 ---> t5
  1306. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  1307. task_2 = Task("garply", {}, print, output=[data_node_4], id=TaskId("t2"))
  1308. task_3 = Task("waldo", {}, print, [data_node_4], None, id=TaskId("t3"))
  1309. task_4 = Task("fred", {}, print, [data_node_4], [data_node_5], TaskId("t4"))
  1310. task_5 = Task("bob", {}, print, [data_node_6], None, TaskId("t5"))
  1311. scenario_7 = Scenario("scenario_7", [task_1, task_2, task_3, task_4, task_5], {}, [], ScenarioId("s6"))
  1312. assert scenario_7._is_consistent()
  1313. # p1 s1 ---
  1314. # |
  1315. # |---> t1 ---| -----> t3
  1316. # | | |
  1317. # s2 --- ---> s4 ---> t4 ---> s5
  1318. # p2 t2 ---> s4 ---> t3
  1319. # p3 s6 ---> t5 ---> s4 ---> t4 ---> s5
  1320. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_4], TaskId("t1"))
  1321. task_2 = Task("garply", {}, print, output=[data_node_4], id=TaskId("t2"))
  1322. task_3 = Task("waldo", {}, print, [data_node_4], None, id=TaskId("t3"))
  1323. task_4 = Task("fred", {}, print, [data_node_4], [data_node_5], TaskId("t4"))
  1324. task_5 = Task("bob", {}, print, [data_node_6], [data_node_4], None, TaskId("t5"))
  1325. scenario_8 = Scenario("scenario_8", [task_4, task_1, task_2, task_3, task_5], {}, [], scenario_id=ScenarioId("s7"))
  1326. assert scenario_8._is_consistent()
  1327. # p1 s1 ---
  1328. # |
  1329. # |---> t1 ---| -----> t3
  1330. # | | |
  1331. # s2 --- ---> s3 ---> t4 ---> s4
  1332. # p2 t2 ---> s3 ---> t3
  1333. # p3 s5 ---> t5 ---> s3 ---> t4 ---> s4
  1334. # p4 s3 ---> t4 ---> s4
  1335. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [data_node_3], TaskId("t1"))
  1336. task_2 = Task("garply", {}, print, output=[data_node_3], id=TaskId("t2"))
  1337. task_3 = Task("waldo", {}, print, [data_node_3], None, id=TaskId("t3"))
  1338. task_4 = Task("fred", {}, print, [data_node_3], [data_node_4], TaskId("t4"))
  1339. task_5 = Task("bob", {}, print, [data_node_5], [data_node_3], TaskId("t5"))
  1340. scenario_9 = Scenario("scenario_9", [task_1, task_2, task_3, task_4, task_5], {}, [], scenario_id=ScenarioId("s8"))
  1341. assert scenario_9._is_consistent()
  1342. def test_check_inconsistency(caplog):
  1343. class FakeDataNode:
  1344. config_id = "config_id_of_a_fake_dn"
  1345. data_node_1 = InMemoryDataNode("foo", Scope.SCENARIO, "s1")
  1346. data_node_2 = InMemoryDataNode("bar", Scope.SCENARIO, "s2")
  1347. task_1 = Task("grault", {}, print, [data_node_1, data_node_2], [FakeDataNode()], TaskId("t1"))
  1348. task_2 = Task("garply", {}, print, [data_node_1], [data_node_2], id=TaskId("t2"))
  1349. scenario_1 = Scenario("scenario_1", [task_1, task_2], {}, [], scenario_id=ScenarioId("s1"))
  1350. assert not scenario_1._is_consistent()
  1351. assert (
  1352. 'Invalid edge detected in scenario "s1": left node Task "grault" and right node FakeDataNode'
  1353. " must connect a Task and a DataNode" in caplog.text
  1354. )
  1355. task_3 = Task("waldo", {}, print, [data_node_2], [data_node_1], id=TaskId("t3"))
  1356. scenario_2 = Scenario("scenario_2", [task_2, task_3], {}, [], scenario_id=ScenarioId("s2"))
  1357. assert not scenario_2._is_consistent()
  1358. assert 'The DAG of scenario "s2" is not a directed acyclic graph' in caplog.text