test_version_cli.py 12 KB

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