test_version_cli.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  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 time import sleep
  12. from unittest.mock import patch
  13. import pytest
  14. from taipy._entrypoint import _entrypoint
  15. from taipy.config.common.frequency import Frequency
  16. from taipy.config.common.scope import Scope
  17. from taipy.config.config import Config
  18. from taipy.core import Core
  19. from taipy.core._version._cli._version_cli import _VersionCLI
  20. from taipy.core._version._version_manager import _VersionManager
  21. from taipy.core.data._data_manager import _DataManager
  22. from taipy.core.job._job_manager import _JobManager
  23. from taipy.core.scenario._scenario_manager import _ScenarioManager
  24. from taipy.core.sequence._sequence_manager import _SequenceManager
  25. from taipy.core.task._task_manager import _TaskManager
  26. def test_version_cli_with_wrong_arguments(caplog):
  27. with patch("sys.argv", ["prog", "manage-versions", "--lits"]):
  28. with pytest.raises(SystemExit):
  29. _entrypoint()
  30. assert "Unknown arguments: --lits. Did you mean: --list?" in caplog.text
  31. def test_delete_version(caplog):
  32. scenario_config = config_scenario()
  33. with patch("sys.argv", ["prog", "--development"]):
  34. core = Core()
  35. core.run()
  36. scenario = _ScenarioManager._create(scenario_config)
  37. _ScenarioManager._submit(scenario)
  38. core.stop()
  39. with patch("sys.argv", ["prog", "--experiment", "1.0"]):
  40. core = Core()
  41. core.run()
  42. scenario = _ScenarioManager._create(scenario_config)
  43. _ScenarioManager._submit(scenario)
  44. core.stop()
  45. with patch("sys.argv", ["prog", "--experiment", "1.1"]):
  46. core = Core()
  47. core.run()
  48. scenario = _ScenarioManager._create(scenario_config)
  49. _ScenarioManager._submit(scenario)
  50. core.stop()
  51. with patch("sys.argv", ["prog", "--production", "1.1"]):
  52. core = Core()
  53. core.run()
  54. core.stop()
  55. with patch("sys.argv", ["prog", "--experiment", "2.0"]):
  56. core = Core()
  57. core.run()
  58. scenario = _ScenarioManager._create(scenario_config)
  59. _ScenarioManager._submit(scenario)
  60. core.stop()
  61. with patch("sys.argv", ["prog", "--experiment", "2.1"]):
  62. core = Core()
  63. core.run()
  64. scenario = _ScenarioManager._create(scenario_config)
  65. _ScenarioManager._submit(scenario)
  66. core.stop()
  67. with patch("sys.argv", ["prog", "--production", "2.1"]):
  68. core = Core()
  69. core.run()
  70. core.stop()
  71. all_versions = [version.id for version in _VersionManager._get_all()]
  72. production_version = _VersionManager._get_production_versions()
  73. assert len(all_versions) == 5
  74. assert len(production_version) == 2
  75. assert "1.0" in all_versions
  76. assert "1.1" in all_versions and "1.1" in production_version
  77. assert "2.0" in all_versions
  78. assert "2.1" in all_versions and "2.1" in production_version
  79. _VersionCLI.create_parser()
  80. with pytest.raises(SystemExit):
  81. with patch("sys.argv", ["prog", "manage-versions", "--delete", "1.0"]):
  82. _VersionCLI.handle_command()
  83. assert "Successfully delete version 1.0." in caplog.text
  84. all_versions = [version.id for version in _VersionManager._get_all()]
  85. assert len(all_versions) == 4
  86. assert "1.0" not in all_versions
  87. # Test delete a non-existed version
  88. with pytest.raises(SystemExit):
  89. with patch("sys.argv", ["prog", "manage-versions", "--delete", "non_exist_version"]):
  90. _VersionCLI.handle_command()
  91. assert "Version 'non_exist_version' does not exist." in caplog.text
  92. # Test delete production version will change the version from production to experiment
  93. with pytest.raises(SystemExit):
  94. with patch("sys.argv", ["prog", "manage-versions", "--delete-production", "1.1"]):
  95. _VersionCLI.handle_command()
  96. assert "Successfully delete version 1.1 from the production version list." in caplog.text
  97. all_versions = [version.id for version in _VersionManager._get_all()]
  98. production_version = _VersionManager._get_production_versions()
  99. assert len(all_versions) == 4
  100. assert "1.1" in all_versions and "1.1" not in production_version
  101. # Test delete a non-existed production version
  102. with pytest.raises(SystemExit) as e:
  103. with patch("sys.argv", ["prog", "manage-versions", "--delete-production", "non_exist_version"]):
  104. _VersionCLI.handle_command()
  105. assert str(e.value) == "Version 'non_exist_version' is not a production version."
  106. def test_list_versions(capsys):
  107. with patch("sys.argv", ["prog", "--development"]):
  108. core = Core()
  109. core.run()
  110. core.stop()
  111. sleep(0.05)
  112. with patch("sys.argv", ["prog", "--experiment", "1.0"]):
  113. core = Core()
  114. core.run()
  115. core.stop()
  116. sleep(0.05)
  117. with patch("sys.argv", ["prog", "--experiment", "1.1"]):
  118. core = Core()
  119. core.run()
  120. core.stop()
  121. sleep(0.05)
  122. with patch("sys.argv", ["prog", "--production", "1.1"]):
  123. core = Core()
  124. core.run()
  125. core.stop()
  126. sleep(0.05)
  127. with patch("sys.argv", ["prog", "--experiment", "2.0"]):
  128. core = Core()
  129. core.run()
  130. core.stop()
  131. sleep(0.05)
  132. with patch("sys.argv", ["prog", "--experiment", "2.1"]):
  133. core = Core()
  134. core.run()
  135. core.stop()
  136. sleep(0.05)
  137. with patch("sys.argv", ["prog", "--production", "2.1"]):
  138. core = Core()
  139. core.run()
  140. core.stop()
  141. _VersionCLI.create_parser()
  142. with pytest.raises(SystemExit):
  143. with patch("sys.argv", ["prog", "manage-versions", "--list"]):
  144. _VersionCLI.handle_command()
  145. out, _ = capsys.readouterr()
  146. version_list = str(out).strip().split("\n")
  147. assert len(version_list) == 6 # 5 versions with the header
  148. assert all(column in version_list[0] for column in ["Version number", "Mode", "Creation date"])
  149. assert all(column in version_list[1] for column in ["2.1", "Production", "latest"])
  150. assert all(column in version_list[2] for column in ["2.0", "Experiment"]) and "latest" not in version_list[2]
  151. assert all(column in version_list[3] for column in ["1.1", "Production"]) and "latest" not in version_list[3]
  152. assert all(column in version_list[4] for column in ["1.0", "Experiment"]) and "latest" not in version_list[4]
  153. assert "Development" in version_list[5] and "latest" not in version_list[5]
  154. def test_rename_version(caplog):
  155. scenario_config = config_scenario()
  156. with patch("sys.argv", ["prog", "--experiment", "1.0"]):
  157. core = Core()
  158. core.run()
  159. scenario = _ScenarioManager._create(scenario_config)
  160. _ScenarioManager._submit(scenario)
  161. core.stop()
  162. with patch("sys.argv", ["prog", "--production", "2.0"]):
  163. core = Core()
  164. core.run()
  165. scenario = _ScenarioManager._create(scenario_config)
  166. _ScenarioManager._submit(scenario)
  167. core.stop()
  168. dev_ver = _VersionManager._get_development_version()
  169. _VersionCLI.create_parser()
  170. with pytest.raises(SystemExit):
  171. with patch("sys.argv", ["prog", "manage-versions", "--rename", "non_exist_version", "1.1"]):
  172. # This should raise an exception since version "non_exist_version" does not exist
  173. _VersionCLI.handle_command()
  174. assert "Version 'non_exist_version' does not exist." in caplog.text
  175. _VersionCLI.create_parser()
  176. with pytest.raises(SystemExit):
  177. with patch("sys.argv", ["prog", "manage-versions", "--rename", "1.0", "2.0"]):
  178. # This should raise an exception since 2.0 already exists
  179. _VersionCLI.handle_command()
  180. assert "Version name '2.0' is already used." in caplog.text
  181. _VersionCLI.create_parser()
  182. with pytest.raises(SystemExit):
  183. with patch("sys.argv", ["prog", "manage-versions", "--rename", "1.0", "1.1"]):
  184. _VersionCLI.handle_command()
  185. assert _VersionManager._get("1.0") is None
  186. assert [version.id for version in _VersionManager._get_all()].sort() == [dev_ver, "1.1", "2.0"].sort()
  187. # All entities are assigned to the new version
  188. assert len(_DataManager._get_all("1.1")) == 2
  189. assert len(_TaskManager._get_all("1.1")) == 1
  190. assert len(_SequenceManager._get_all("1.1")) == 1
  191. assert len(_ScenarioManager._get_all("1.1")) == 1
  192. assert len(_JobManager._get_all("1.1")) == 1
  193. _VersionCLI.create_parser()
  194. with pytest.raises(SystemExit):
  195. with patch("sys.argv", ["prog", "manage-versions", "--rename", "2.0", "2.1"]):
  196. _VersionCLI.handle_command()
  197. assert _VersionManager._get("2.0") is None
  198. assert [version.id for version in _VersionManager._get_all()].sort() == [dev_ver, "1.1", "2.1"].sort()
  199. assert _VersionManager._get_production_versions() == ["2.1"]
  200. # All entities are assigned to the new version
  201. assert len(_DataManager._get_all("2.1")) == 2
  202. assert len(_TaskManager._get_all("2.1")) == 1
  203. assert len(_SequenceManager._get_all("2.1")) == 1
  204. assert len(_ScenarioManager._get_all("2.1")) == 1
  205. assert len(_JobManager._get_all("2.1")) == 1
  206. def test_compare_version_config(caplog, init_config):
  207. scenario_config_1 = config_scenario()
  208. with patch("sys.argv", ["prog", "--experiment", "1.0"]):
  209. core = Core()
  210. core.run()
  211. scenario = _ScenarioManager._create(scenario_config_1)
  212. _ScenarioManager._submit(scenario)
  213. core.stop()
  214. init_config()
  215. scenario_config_2 = config_scenario()
  216. Config.configure_data_node(id="d2", storage_type="csv", default_path="bar.csv")
  217. with patch("sys.argv", ["prog", "--experiment", "2.0"]):
  218. core = Core()
  219. core.run()
  220. scenario = _ScenarioManager._create(scenario_config_2)
  221. _ScenarioManager._submit(scenario)
  222. core.stop()
  223. _VersionCLI.create_parser()
  224. with pytest.raises(SystemExit):
  225. with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "non_exist_version", "2.0"]):
  226. # This should raise an exception since version "non_exist_version" does not exist
  227. _VersionCLI.handle_command()
  228. assert "Version 'non_exist_version' does not exist." in caplog.text
  229. with pytest.raises(SystemExit):
  230. with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "non_exist_version"]):
  231. # This should raise an exception since 2.0 already exists
  232. _VersionCLI.handle_command()
  233. assert "Version 'non_exist_version' does not exist." in caplog.text
  234. with pytest.raises(SystemExit):
  235. with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "1.0"]):
  236. _VersionCLI.handle_command()
  237. assert "There is no difference between version 1.0 Configuration and version 1.0 Configuration." in caplog.text
  238. with pytest.raises(SystemExit):
  239. with patch("sys.argv", ["prog", "manage-versions", "--compare-config", "1.0", "2.0"]):
  240. _VersionCLI.handle_command()
  241. expected_message = """Differences between version 1.0 Configuration and version 2.0 Configuration:
  242. \tDATA_NODE "d2" has attribute "default_path" modified: foo.csv -> bar.csv"""
  243. assert expected_message in caplog.text
  244. def twice(a):
  245. return a * 2
  246. def config_scenario():
  247. data_node_1_config = Config.configure_data_node(
  248. id="d1", storage_type="pickle", default_data="abc", scope=Scope.SCENARIO
  249. )
  250. data_node_2_config = Config.configure_data_node(id="d2", storage_type="csv", default_path="foo.csv")
  251. task_config = Config.configure_task("my_task", twice, data_node_1_config, data_node_2_config)
  252. scenario_config = Config.configure_scenario("my_scenario", [task_config], frequency=Frequency.DAILY)
  253. scenario_config.add_sequences({"my_sequence": [task_config]})
  254. return scenario_config