ciocore 5.1.1__py2.py3-none-any.whl → 10.0.0b3__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. ciocore/VERSION +1 -1
  2. ciocore/__init__.py +23 -1
  3. ciocore/api_client.py +655 -160
  4. ciocore/auth/__init__.py +5 -3
  5. ciocore/cli.py +501 -0
  6. ciocore/common.py +15 -13
  7. ciocore/conductor_submit.py +77 -60
  8. ciocore/config.py +127 -13
  9. ciocore/data.py +162 -77
  10. ciocore/docsite/404.html +746 -0
  11. ciocore/docsite/apidoc/api_client/index.html +3605 -0
  12. ciocore/docsite/apidoc/apidoc/index.html +909 -0
  13. ciocore/docsite/apidoc/config/index.html +1652 -0
  14. ciocore/docsite/apidoc/data/index.html +1553 -0
  15. ciocore/docsite/apidoc/hardware_set/index.html +2460 -0
  16. ciocore/docsite/apidoc/package_environment/index.html +1507 -0
  17. ciocore/docsite/apidoc/package_tree/index.html +2386 -0
  18. ciocore/docsite/assets/_mkdocstrings.css +16 -0
  19. ciocore/docsite/assets/images/favicon.png +0 -0
  20. ciocore/docsite/assets/javascripts/bundle.471ce7a9.min.js +29 -0
  21. ciocore/docsite/assets/javascripts/bundle.471ce7a9.min.js.map +7 -0
  22. ciocore/docsite/assets/javascripts/lunr/min/lunr.ar.min.js +1 -0
  23. ciocore/docsite/assets/javascripts/lunr/min/lunr.da.min.js +18 -0
  24. ciocore/docsite/assets/javascripts/lunr/min/lunr.de.min.js +18 -0
  25. ciocore/docsite/assets/javascripts/lunr/min/lunr.du.min.js +18 -0
  26. ciocore/docsite/assets/javascripts/lunr/min/lunr.el.min.js +1 -0
  27. ciocore/docsite/assets/javascripts/lunr/min/lunr.es.min.js +18 -0
  28. ciocore/docsite/assets/javascripts/lunr/min/lunr.fi.min.js +18 -0
  29. ciocore/docsite/assets/javascripts/lunr/min/lunr.fr.min.js +18 -0
  30. ciocore/docsite/assets/javascripts/lunr/min/lunr.he.min.js +1 -0
  31. ciocore/docsite/assets/javascripts/lunr/min/lunr.hi.min.js +1 -0
  32. ciocore/docsite/assets/javascripts/lunr/min/lunr.hu.min.js +18 -0
  33. ciocore/docsite/assets/javascripts/lunr/min/lunr.hy.min.js +1 -0
  34. ciocore/docsite/assets/javascripts/lunr/min/lunr.it.min.js +18 -0
  35. ciocore/docsite/assets/javascripts/lunr/min/lunr.ja.min.js +1 -0
  36. ciocore/docsite/assets/javascripts/lunr/min/lunr.jp.min.js +1 -0
  37. ciocore/docsite/assets/javascripts/lunr/min/lunr.kn.min.js +1 -0
  38. ciocore/docsite/assets/javascripts/lunr/min/lunr.ko.min.js +1 -0
  39. ciocore/docsite/assets/javascripts/lunr/min/lunr.multi.min.js +1 -0
  40. ciocore/docsite/assets/javascripts/lunr/min/lunr.nl.min.js +18 -0
  41. ciocore/docsite/assets/javascripts/lunr/min/lunr.no.min.js +18 -0
  42. ciocore/docsite/assets/javascripts/lunr/min/lunr.pt.min.js +18 -0
  43. ciocore/docsite/assets/javascripts/lunr/min/lunr.ro.min.js +18 -0
  44. ciocore/docsite/assets/javascripts/lunr/min/lunr.ru.min.js +18 -0
  45. ciocore/docsite/assets/javascripts/lunr/min/lunr.sa.min.js +1 -0
  46. ciocore/docsite/assets/javascripts/lunr/min/lunr.stemmer.support.min.js +1 -0
  47. ciocore/docsite/assets/javascripts/lunr/min/lunr.sv.min.js +18 -0
  48. ciocore/docsite/assets/javascripts/lunr/min/lunr.ta.min.js +1 -0
  49. ciocore/docsite/assets/javascripts/lunr/min/lunr.te.min.js +1 -0
  50. ciocore/docsite/assets/javascripts/lunr/min/lunr.th.min.js +1 -0
  51. ciocore/docsite/assets/javascripts/lunr/min/lunr.tr.min.js +18 -0
  52. ciocore/docsite/assets/javascripts/lunr/min/lunr.vi.min.js +1 -0
  53. ciocore/docsite/assets/javascripts/lunr/min/lunr.zh.min.js +1 -0
  54. ciocore/docsite/assets/javascripts/lunr/tinyseg.js +206 -0
  55. ciocore/docsite/assets/javascripts/lunr/wordcut.js +6708 -0
  56. ciocore/docsite/assets/javascripts/workers/search.b8dbb3d2.min.js +42 -0
  57. ciocore/docsite/assets/javascripts/workers/search.b8dbb3d2.min.js.map +7 -0
  58. ciocore/docsite/assets/stylesheets/main.3cba04c6.min.css +1 -0
  59. ciocore/docsite/assets/stylesheets/main.3cba04c6.min.css.map +1 -0
  60. ciocore/docsite/assets/stylesheets/palette.06af60db.min.css +1 -0
  61. ciocore/docsite/assets/stylesheets/palette.06af60db.min.css.map +1 -0
  62. ciocore/docsite/cmdline/docs/index.html +871 -0
  63. ciocore/docsite/cmdline/downloader/index.html +934 -0
  64. ciocore/docsite/cmdline/packages/index.html +878 -0
  65. ciocore/docsite/cmdline/uploader/index.html +995 -0
  66. ciocore/docsite/how-to-guides/index.html +869 -0
  67. ciocore/docsite/index.html +895 -0
  68. ciocore/docsite/logo.png +0 -0
  69. ciocore/docsite/objects.inv +0 -0
  70. ciocore/docsite/search/search_index.json +1 -0
  71. ciocore/docsite/sitemap.xml +3 -0
  72. ciocore/docsite/sitemap.xml.gz +0 -0
  73. ciocore/docsite/stylesheets/extra.css +26 -0
  74. ciocore/docsite/stylesheets/tables.css +167 -0
  75. ciocore/downloader/base_downloader.py +644 -0
  76. ciocore/downloader/download_runner_base.py +47 -0
  77. ciocore/downloader/job_downloader.py +119 -0
  78. ciocore/{downloader.py → downloader/legacy_downloader.py} +12 -9
  79. ciocore/downloader/log.py +73 -0
  80. ciocore/downloader/logging_download_runner.py +87 -0
  81. ciocore/downloader/perpetual_downloader.py +63 -0
  82. ciocore/downloader/registry.py +97 -0
  83. ciocore/downloader/reporter.py +135 -0
  84. ciocore/exceptions.py +8 -2
  85. ciocore/file_utils.py +51 -50
  86. ciocore/hardware_set.py +449 -0
  87. ciocore/loggeria.py +89 -20
  88. ciocore/package_environment.py +110 -48
  89. ciocore/package_query.py +182 -0
  90. ciocore/package_tree.py +319 -258
  91. ciocore/retry.py +0 -0
  92. ciocore/uploader/_uploader.py +547 -364
  93. ciocore/uploader/thread_queue_job.py +176 -0
  94. ciocore/uploader/upload_stats/__init__.py +3 -4
  95. ciocore/uploader/upload_stats/stats_formats.py +10 -4
  96. ciocore/validator.py +34 -2
  97. ciocore/worker.py +174 -151
  98. ciocore-10.0.0b3.dist-info/METADATA +928 -0
  99. ciocore-10.0.0b3.dist-info/RECORD +128 -0
  100. {ciocore-5.1.1.dist-info → ciocore-10.0.0b3.dist-info}/WHEEL +1 -1
  101. ciocore-10.0.0b3.dist-info/entry_points.txt +2 -0
  102. tests/instance_type_fixtures.py +175 -0
  103. tests/package_fixtures.py +205 -0
  104. tests/test_api_client.py +297 -12
  105. tests/test_base_downloader.py +104 -0
  106. tests/test_cli.py +149 -0
  107. tests/test_common.py +1 -7
  108. tests/test_config.py +40 -18
  109. tests/test_data.py +162 -173
  110. tests/test_downloader.py +118 -0
  111. tests/test_hardware_set.py +139 -0
  112. tests/test_job_downloader.py +213 -0
  113. tests/test_package_query.py +38 -0
  114. tests/test_package_tree.py +91 -291
  115. tests/test_submit.py +44 -18
  116. tests/test_uploader.py +1 -4
  117. ciocore/__about__.py +0 -10
  118. ciocore/cli/conductor.py +0 -191
  119. ciocore/compat.py +0 -15
  120. ciocore-5.1.1.data/scripts/conductor +0 -19
  121. ciocore-5.1.1.data/scripts/conductor.bat +0 -13
  122. ciocore-5.1.1.dist-info/METADATA +0 -408
  123. ciocore-5.1.1.dist-info/RECORD +0 -47
  124. tests/mocks/api_client_mock.py +0 -51
  125. /ciocore/{cli → downloader}/__init__.py +0 -0
  126. {ciocore-5.1.1.dist-info → ciocore-10.0.0b3.dist-info}/top_level.txt +0 -0
tests/test_config.py CHANGED
@@ -6,12 +6,20 @@ import sys
6
6
  import os
7
7
  import logging
8
8
 
9
- try:
10
- from unittest import mock
11
- except ImportError:
12
- import mock
13
-
14
- APIKEY = '{"auth_provider_x509_cert_url": "https://www.exampleapis.com/oauth2/v1/certs", "auth_uri": "https://accounts.example.com/o/oauth2/auth", "client_email": "account-5641301770895360@eloquent-vector-104019.iam.gserviceaccount.com", "client_id": "106815243682887997903", "client_x509_cert_url": "https://www.exampleapis.com/robot/v1/metadata/x509/account-5641301770895360%40eloquent-vector-104019.iam.gserviceaccount.com", "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDcadqRWyd7VpYN\n804fEn07qlqNXU0ihz6g2dfbj9gzZDhHGVCI5QvPFskAQcV91k8cDdFu380m+sh1\nz9wlcdaM/lksRV/DRJiV76qrqyrNi0gSekZUuYhSsyMWUGvG4aSbf5BzVf1j8W4I\nUArH+ht5pgdSjowNc4zQIqmMH2XY+Ntr+NysBBfIv1PI6GoHFgDYOTSzsvz0qFYS\nWuonYGTjzNz4CY9Yh5ki8iq0/ijKzpUWeRUkpK9uF7WBoxrj3EyFFHejtfhVX2l0\n2KxrIF0kkmy5nmxVUck76FqdQ6vyvaHudREd3z/08hgdYogemQUTKFE/0LQmKuBV\nIJipPvORAgMBAAECggEAZvPMozN8LBikC00XstzMgRePp1MqydN5NeG6+TPlrQ+F\nV/RjkSXHT8oZRdTy3dXB6t0rc4n2xdvC0YCvGBBlwkK1vT+EPO2oBfTF99yCKDME\nDZlui3mDyvkgjPYweVuBKx65Bp5mNo4ZMqnMd18EAVxDM9UgZtIPtlJSdoBd7qtk\nyCGr03l+SV0krmvPV+KS9vyDOg/7Km5gMhTMaIveNyS1pG6AmZ0ggQA5djg/P2iF\nxGwYdvfADY5cBzg0OG5ELv9hvyA4CKN6RLfYv3JJS2gbNaMknjmsjaM/p0LtE2HL\n+uFPL0ZjoMwV3BlEFQIHwhNWS63H43ISBa1/2XvGPwKBgQDw4a4kQ9+Ce3edWonz\n3Fm/3no+HrMSVjbv28qphAHMFrSUdbMejQm4QSbNeOW1pEcVvW21u8tYagrJEsaU\ns4DulFXRep36teVDWpc1FrNowWEPPVeC8CO74VfssK1h2Itqis8JPbzXOcNtSH9+\nAg1EvrB9XnyEvJuM6GOGo3juTwKBgQDqP058+H3iSZe6al4P6Ib3g/82nr2dHeN5\n4xxGu1fzTMNX5lopbNji6tQcsMoMVPdOvCQy5c0PEUbvo7mxfZ8fOZwgBjIcXbYg\nzIJkPTSv7nxSE5M5lW5juzLkdq2k5k0qt9ByWuWEA3PSn/DEANa5888phSCoJSw/\nPjpwHhZoHwKBgQDCoQbMxI6e5lYCrToT8PIPhpptAO8dnM2sxoGcsE2ncp0b63H7\n+GdnGjVZBhtMxdyt4y33DjLCUIRAbUxIsDU4EGC67oEhJsGEx3iva5Uwyjc7UgwY\nfyHQV8ZsN2EQUyBqyJd6VwjzOff+n/prfQrthcoisiqYMbDZjJeGHSXEHwKBgAo4\nBsmG4Z78jOTx/PZ+s1ya4ohUdnsjMahAkxw20ghoIeF0yBwkhnWnvucdg0L0dfF2\nXbHmuoJcw5ZyswgeLdHj5n6zJn58TBS0Nz/+N40xPzUpa3PIpA8vvHGhB8Q408b4\nS9yhQH/40pWuqocybiugijoKd7k+HecIZO49MccLAoGBAPDScJHSxKPW6wJKjxDC\nXXWWQ2flbwv4Sja487QV/trWMSRnHJHnCVHqv/F7ThPaoHM+MJSzrJ7wr/CJhk0H\noEt+0Rn6qPd/A36bSjTfXMFLXWi75ovek+IJGKxr7B46jrcS/oe1XIIOlV1+OvOY\nVoO6vgYkPhpMkth2hyZ/luea\n-----END PRIVATE KEY-----\n", "private_key_id": "3dfe3bdc40d4dc431d283bf22feb113c9b622dd3", "project_id": "eloquent-vector-104019", "token_uri": "https://oauth2.exampleapis.com/token", "type": "service_account"}'
9
+ from unittest import mock
10
+
11
+ MOCK_API_KEY = '''{
12
+ "type": "service_account",
13
+ "project_id": "mock-project",
14
+ "private_key_id": "mock-key-id",
15
+ "private_key": "-----BEGIN PRIVATE KEY-----\\nMOCKKEY\\n-----END PRIVATE KEY-----\\n",
16
+ "client_email": "mock@example.com",
17
+ "client_id": "123456789",
18
+ "auth_uri": "https://accounts.example.com/oauth2/auth",
19
+ "token_uri": "https://oauth2.example.com/token",
20
+ "auth_provider_x509_cert_url": "https://www.example.com/oauth2/v1/certs",
21
+ "client_x509_cert_url": "https://www.example.com/robot/v1/metadata/x509/mock%40example.com"
22
+ }'''
15
23
 
16
24
  PY3 = sys.version_info >= (3, 0)
17
25
  BUILTIN_OPEN = "builtins.open" if PY3 else "__builtin__.open"
@@ -29,7 +37,7 @@ class ConfigInitTest(unittest.TestCase):
29
37
  It Mocks the 2 api_key functions, the multiprocessing package, and the os environment.
30
38
  """
31
39
  self.cpu_count_patcher = mock.patch(
32
- "multiprocessing.cpu_count", return_value=overrides.get("cpu_count", 4)
40
+ "os.cpu_count", return_value=overrides.get("cpu_count", 4)
33
41
  )
34
42
  self.mock_cpu_count = self.cpu_count_patcher.start()
35
43
  if overrides.get("cpu_count_raise", False):
@@ -64,23 +72,37 @@ class ConfigInitTest(unittest.TestCase):
64
72
  cfg = config.Config()
65
73
  self.assertEqual(cfg.__class__.__name__, "Config")
66
74
 
75
+ # DOWNLOADER PAGE SIZE
76
+ def test_downloader_page_size_default_to_50(self):
77
+ self.up()
78
+ cfg = config.Config()
79
+ self.assertEqual(cfg.config["downloader_page_size"], 50)
80
+ self.down()
81
+
82
+ def test_downloader_page_size_variable_overrides_default(self):
83
+ self.up(env={"CONDUCTOR_DOWNLOADER_PAGE_SIZE": "10"})
84
+ cfg = config.Config()
85
+ self.assertEqual(cfg.config["downloader_page_size"], 10)
86
+ self.down()
87
+
88
+
67
89
  # THREAD COUNT
68
- def test_thread_count_is_double_cpu_count(self):
69
- self.up(cpu_count=2)
90
+ def test_thread_count_is_cpu_count_minus_one(self):
91
+ self.up(cpu_count=4)
70
92
  cfg = config.Config()
71
- self.assertEqual(cfg.config["thread_count"], 4)
93
+ self.assertEqual(cfg.config["thread_count"], 3)
72
94
  self.down()
73
95
 
74
- def test_thread_count_is_max_16(self):
75
- self.up(cpu_count=12)
96
+ def test_thread_count_is_max_15(self):
97
+ self.up(cpu_count=20)
76
98
  cfg = config.Config()
77
- self.assertEqual(cfg.config["thread_count"], 16)
99
+ self.assertEqual(cfg.config["thread_count"], 15)
78
100
  self.down()
79
101
 
80
- def test_thread_count_is_16_if_an_exception_is_thrown(self):
102
+ def test_thread_count_is_15_if_an_exception_is_thrown(self):
81
103
  self.up(cpu_count_raise=True)
82
104
  cfg = config.Config()
83
- self.assertEqual(cfg.config["thread_count"], 16)
105
+ self.assertEqual(cfg.config["thread_count"], 15)
84
106
  self.down()
85
107
 
86
108
  def test_thread_count_variable_overrides_default(self):
@@ -253,7 +275,7 @@ class ApiKeyFromVariableTest(unittest.TestCase):
253
275
  self.down()
254
276
 
255
277
  def test_returns_dict_if_key_is_b64encoded(self):
256
- key = APIKEY
278
+ key = MOCK_API_KEY
257
279
  if sys.version_info < (3, 0):
258
280
  self.up(env={"CONDUCTOR_API_KEY": base64.b64encode(key)})
259
281
  else:
@@ -288,7 +310,7 @@ class ApiKeyFromFileTest(unittest.TestCase):
288
310
  self.assertEqual(result, None)
289
311
  self.down()
290
312
 
291
- @mock.patch(BUILTIN_OPEN, new_callable=mock.mock_open, read_data=APIKEY, create=True)
313
+ @mock.patch(BUILTIN_OPEN, new_callable=mock.mock_open, read_data=MOCK_API_KEY, create=True)
292
314
  def test_open_called_with_api_key_path(self, mock_file_open):
293
315
  self.up(env={"CONDUCTOR_API_KEY_PATH": "path/to/api_key"})
294
316
  config.Config.get_api_key_from_file()
@@ -302,7 +324,7 @@ class ApiKeyFromFileTest(unittest.TestCase):
302
324
  config.Config.get_api_key_from_file()
303
325
  self.down()
304
326
 
305
- @mock.patch(BUILTIN_OPEN, new_callable=mock.mock_open, read_data=APIKEY, create=True)
327
+ @mock.patch(BUILTIN_OPEN, new_callable=mock.mock_open, read_data=MOCK_API_KEY, create=True)
306
328
  def test_returns_dict_if_key_is_valid_json(self, mock_file_open):
307
329
  self.up(env={"CONDUCTOR_API_KEY_PATH": "path/to/api_key"})
308
330
  result = config.Config.get_api_key_from_file()
tests/test_data.py CHANGED
@@ -1,184 +1,173 @@
1
- """ test data
2
-
3
- isort:skip_file
4
- """
5
- import json
6
- import os
7
- import sys
8
1
  import unittest
9
- from mock import patch
10
- from ciocore import data
11
-
12
- PROJECTS = [
13
- "Deadpool",
14
- "Harry Potter & the chamber of secrets",
15
- "Captain Corelli's Mandolin",
16
- "Gone with the Wind"
17
- ]
18
-
19
- LIN_INSTANCE_TYPES = [
20
- {
21
- "cores": 8,
22
- "memory": 30.0,
23
- "description": "8 core, 30GB Mem",
24
- "name": "n1-standard-8",
25
- "operating_system": "linux"
26
- },
27
- {
28
- "cores": 64,
29
- "memory": 416.0,
30
- "description": "64 core, 416GB Mem",
31
- "name": "n1-highmem-64",
32
- "operating_system": "linux"
33
- },
34
- {
35
- "cores": 4,
36
- "memory": 26.0,
37
- "description": "4 core, 26GB Mem",
38
- "name": "n1-highmem-4",
39
- "operating_system": "linux"
40
- },
41
- {
42
- "cores": 32,
43
- "memory": 208.0,
44
- "description": "32 core, 208GB Mem",
45
- "name": "n1-highmem-32",
46
- "operating_system": "linux"
47
- }
48
- ]
49
-
50
- WIN_INSTANCE_TYPES = [
51
- {
52
- "cores": 64,
53
- "memory": 416.0,
54
- "description": "64 core, 416GB Mem",
55
- "name": "n1-highmem-64-w",
56
- "operating_system": "windows"
57
- },
58
- {
59
- "cores": 4,
60
- "memory": 26.0,
61
- "description": "4 core, 26GB Mem",
62
- "name": "n1-highmem-4-w",
63
- "operating_system": "windows"
64
- },
65
- {
66
- "cores": 32,
67
- "memory": 208.0,
68
- "description": "32 core, 208GB Mem",
69
- "name": "n1-highmem-32-w",
70
- "operating_system": "windows"
71
- }
72
- ]
73
-
74
- ALL_INSTANCE_TYPES = WIN_INSTANCE_TYPES+LIN_INSTANCE_TYPES
75
-
76
- with open(os.path.join(os.path.dirname(__file__), "fixtures", "sw_packages.json"), 'r') as content:
77
- SOFTWARE = json.load(content)["data"]
78
-
79
-
80
- class TestDataSingleton(unittest.TestCase):
81
-
82
- def setUp(self):
83
- projects_patcher = patch('ciocore.api_client.request_projects', return_value=PROJECTS)
84
- software_packages_patcher = patch('ciocore.api_client.request_software_packages', return_value=SOFTWARE)
85
-
86
- self.mock_projects = projects_patcher.start()
87
- self.mock_software_packages = software_packages_patcher.start()
88
-
89
- self.addCleanup(projects_patcher.stop)
90
- self.addCleanup(software_packages_patcher.stop)
91
- data.__data__ = {}
92
- data.__product__ = None
93
-
94
- class TestDataAllInstanceTypes(TestDataSingleton):
2
+ from unittest.mock import patch
3
+ from ciocore import data as coredata
95
4
 
5
+ class TestCoreData(unittest.TestCase):
96
6
  def setUp(self):
97
- super(TestDataAllInstanceTypes, self).setUp()
98
- instance_types_patcher = patch('ciocore.api_client.request_instance_types', return_value=ALL_INSTANCE_TYPES)
99
- self.mock_instance_types = instance_types_patcher.start()
100
- self.addCleanup(instance_types_patcher.stop)
101
-
102
- def test_init_sets_project_global(self):
103
- data.init("all")
104
- self.assertEqual(data.product(), "all")
105
-
106
- def test_init_raises_if_product_falsy(self):
107
- with self.assertRaises(ValueError):
108
- data.init()
7
+ """Set up test fixtures before each test method."""
8
+ self.mock_api_responses = {
9
+ 'projects': ['ProjectA', 'ProjectB'],
10
+ 'instance_types': [
11
+ {'operating_system': 'windows', 'name': 'win_machine', 'cores': 1, 'memory': '1024'},
12
+ {'operating_system': 'linux', 'name': 'linux_machine', 'cores': 1, 'memory': '1024'}
13
+ ],
14
+ 'software': [ # Added package_id to each package
15
+ {
16
+ 'name': 'maya-io',
17
+ 'version': '2022',
18
+ 'platform': 'windows',
19
+ 'product': 'maya-io',
20
+ 'package_id': '123456789'
21
+ },
22
+ {
23
+ 'name': 'maya-io',
24
+ 'version': '2022',
25
+ 'platform': 'linux',
26
+ 'product': 'maya-io',
27
+ 'package_id': '123456780'
28
+ },
29
+ {
30
+ 'name': 'nuke',
31
+ 'version': '13.0',
32
+ 'platform': 'linux',
33
+ 'product': 'nuke',
34
+ 'package_id': '123456781'
35
+ }
36
+ ],
37
+ 'extra_env': ['PATH=/custom/path', 'LICENSE_SERVER=1234']
38
+ }
39
+ # Clear data before each test
40
+ coredata.clear()
41
+
42
+ def tearDown(self):
43
+ """Clean up after each test method."""
44
+ coredata.clear()
45
+
46
+ def test_init_with_single_product(self):
47
+ """Test initializing with a single product"""
48
+ coredata.init("maya-io")
49
+ self.assertEqual(coredata.products(), ["maya-io"])
50
+ self.assertEqual(coredata.platforms(), set(["windows", "linux"]))
51
+
52
+ def test_init_with_multiple_products(self):
53
+ """Test initializing with multiple products"""
54
+ coredata.init("maya-io", "nuke")
55
+ self.assertEqual(coredata.products(), ["maya-io", "nuke"])
56
+
57
+ def test_init_with_deprecated_product(self):
58
+ """Test initializing with deprecated product kwarg"""
59
+ coredata.init(product="maya-io")
60
+ self.assertEqual(coredata.products(), ["maya-io"])
61
+
62
+ def test_init_with_all_products(self):
63
+ """Test initializing with 'all' products"""
64
+ coredata.init(product="all")
65
+ self.assertEqual(coredata.products(), [])
66
+
67
+ def test_init_conflict_raises_error(self):
68
+ """Test that using both products arg and product kwarg raises error"""
109
69
  with self.assertRaises(ValueError):
110
- data.init("")
70
+ coredata.init("maya-io", product="nuke")
111
71
 
112
- def test_data_raises_if_not_initialized(self):
72
+ def test_data_requires_init(self):
73
+ """Test that data() raises error if not initialized"""
113
74
  with self.assertRaises(ValueError):
114
- data.data()
115
-
116
- def test_valid(self):
117
- self.assertEqual(data.valid(), False)
118
- data.init("all")
119
- data.data()
120
- self.assertEqual(data.valid(), True)
121
-
122
- def test_clear(self):
123
- data.init("all")
124
- data.data()
125
- self.assertEqual(data.valid(), True)
126
- data.clear()
127
- self.assertEqual(data.valid(), False)
128
-
129
- def test_does_not_refresh_if_not_force(self):
130
- data.init("all")
131
- p1 = data.data()["projects"]
132
- self.assertEqual(len(p1), 4)
133
- self.mock_projects.return_value = ["a", "b"]
134
- p2 = data.data()["projects"]
135
- self.assertEqual(p2, p1)
136
-
137
- def test_does_refresh_if_force_all(self):
138
- data.init("all")
139
- p1 = data.data()["projects"]
140
- self.assertEqual(len(p1), 4)
141
- self.mock_projects.return_value = ["a", "b"]
142
- p2 = data.data(force=True)["projects"]
143
- self.assertNotEqual(p2, p1)
144
- self.assertEqual(len(p2), 2)
75
+ coredata.data()
76
+
77
+ @patch('ciocore.data.api_client')
78
+ def test_data_fetching(self, mock_client):
79
+ """Test fetching data through the data() function"""
80
+ # Setup mock responses
81
+ mock_client.request_projects.return_value = self.mock_api_responses['projects']
82
+ mock_client.request_instance_types.return_value = self.mock_api_responses['instance_types']
83
+ mock_client.request_software_packages.return_value = self.mock_api_responses['software']
84
+ mock_client.request_extra_environment.return_value = self.mock_api_responses['extra_env']
85
+
86
+ coredata.init("maya-io")
87
+ result = coredata.data()
145
88
 
146
- def test_get_data_for_one_product(self):
147
- data.init(product="cinema4d")
148
- inst = data.data()["instance_types"]
149
- sw = data.data()["software"]
150
- self.assertEqual(len(sw.supported_host_names()), 2)
151
-
152
- def test_auto_filter_instance_types_based_on_software_plaforms(self):
153
- data.init(product="maya-io")
154
- inst = data.data()["instance_types"]
155
- self.assertEqual(len(inst), 4)
156
-
157
-
158
-
159
- class TestDataHomogenousInstanceTypes(TestDataSingleton):
89
+ self.assertIn("projects", result)
90
+ self.assertIn("instance_types", result)
91
+ self.assertIn("software", result)
92
+ self.assertIn("extra_environment", result)
93
+
94
+ self.assertEqual(result["projects"], self.mock_api_responses["projects"])
95
+ self.assertIsInstance(result["instance_types"], coredata.HardwareSet)
96
+ self.assertIsInstance(result["software"], coredata.PackageTree)
97
+
98
+ @patch('ciocore.data.api_client')
99
+ def test_force_refresh(self, mock_client):
100
+ """Test forcing data refresh"""
101
+ # Setup mock responses
102
+ mock_client.request_projects.return_value = self.mock_api_responses['projects']
103
+ mock_client.request_instance_types.return_value = self.mock_api_responses['instance_types']
104
+ mock_client.request_software_packages.return_value = self.mock_api_responses['software']
105
+ mock_client.request_extra_environment.return_value = self.mock_api_responses['extra_env']
106
+
107
+ coredata.init("maya-io")
108
+ first_data = coredata.data()
109
+
110
+ # Second call without force should not make new API calls
111
+ mock_client.request_projects.reset_mock()
112
+ second_data = coredata.data()
113
+ mock_client.request_projects.assert_not_called()
114
+
115
+ # Call with force=True should make new API calls
116
+ third_data = coredata.data(force=True)
117
+ mock_client.request_projects.assert_called_once()
160
118
 
161
- def setUp(self):
162
- super(TestDataHomogenousInstanceTypes, self).setUp()
163
- instance_types_patcher = patch('ciocore.api_client.request_instance_types', return_value=LIN_INSTANCE_TYPES)
164
- self.mock_instance_types = instance_types_patcher.start()
165
- self.addCleanup(instance_types_patcher.stop)
166
-
167
- def test_linux_only_instance_types(self):
168
- data.init(product="all")
169
- it = data.data()["instance_types"]
170
- self.assertEqual(len(it), 4)
171
-
172
- def test_linux_only_packages_when_linux_only_instance_types(self):
173
- data.init(product="cinema4d")
174
- sw = data.data()["software"]
175
- print(sw.supported_host_names())
176
- self.assertEqual(len(sw.supported_host_names()), 1)
177
-
178
- def test_platforms_method_only_linux(self):
179
- data.init(product="cinema4d")
180
- data.data()
181
- self.assertEqual({"linux"}, data.platforms())
119
+ def test_valid_state(self):
120
+ """Test valid() function behavior"""
121
+ self.assertFalse(coredata.valid()) # Should be invalid before initialization
122
+
123
+ coredata.init("maya-io")
124
+ self.assertFalse(coredata.valid()) # Should be invalid before data is fetched
125
+
126
+ with patch('ciocore.data.api_client') as mock_client:
127
+ # Setup mock responses
128
+ mock_client.request_projects.return_value = self.mock_api_responses['projects']
129
+ mock_client.request_instance_types.return_value = self.mock_api_responses['instance_types']
130
+ mock_client.request_software_packages.return_value = self.mock_api_responses['software']
131
+ mock_client.request_extra_environment.return_value = self.mock_api_responses['extra_env']
132
+
133
+ coredata.data() # Fetch data
134
+ self.assertTrue(coredata.valid()) # Should be valid after data is fetched
135
+
136
+ coredata.clear()
137
+ self.assertFalse(coredata.valid()) # Should be invalid after clear
138
+
139
+ @patch('ciocore.data.api_client')
140
+ def test_platforms_filtering(self, mock_client):
141
+ """Test platform filtering based on instance types and software"""
142
+ # Setup mock responses
143
+ mock_client.request_projects.return_value = self.mock_api_responses['projects']
144
+ mock_client.request_instance_types.return_value = self.mock_api_responses['instance_types']
145
+ mock_client.request_software_packages.return_value = self.mock_api_responses['software']
146
+ mock_client.request_extra_environment.return_value = self.mock_api_responses['extra_env']
147
+
148
+ coredata.init("nuke") # nuke only supports linux
149
+ coredata.data()
150
+
151
+ # Should only have linux instance types since nuke only supports linux
152
+ self.assertEqual(coredata.platforms(), {"linux"})
153
+
154
+ @patch('ciocore.data.api_client')
155
+ def test_instances_filter(self, mock_client):
156
+ """Testing that instance_types is passed correctly to api_client"""
157
+ # Set up mock response
158
+ mock_client.request_instance_types.return_value = self.mock_api_responses['instance_types']
159
+ coredata.init("maya-io")
160
+
161
+ # Test with no filter
162
+ coredata.data()
163
+ mock_client.request_instance_types.assert_called_with(filter_param="")
182
164
 
165
+ # Test with filter and force=True
166
+ mock_client.request_instance_types.reset_mock()
183
167
 
168
+ instances_filter = "gpu.gpu_count=gte:1:int"
169
+ coredata.data(force=True, instances_filter=instances_filter)
170
+ mock_client.request_instance_types.assert_called_with(filter_param=instances_filter)
184
171
 
172
+ if __name__ == '__main__':
173
+ unittest.main()
@@ -0,0 +1,118 @@
1
+
2
+ from ciocore.downloader.job_downloader import JobDownloader, flatten
3
+ import unittest
4
+ from unittest import mock
5
+ from ciocore.downloader.base_downloader import temp_file
6
+ import tempfile
7
+ import shutil
8
+ import os
9
+ import stat
10
+ import contextlib
11
+
12
+ class TempFileTests(unittest.TestCase):
13
+
14
+ def test_temp_file_creation(self):
15
+ # Create a temporary file and test if it exists
16
+ with temp_file("tests/files/file.txt") as temp_path:
17
+ self.assertTrue(os.path.exists(temp_path))
18
+ self.assertTrue(os.access(temp_path, os.W_OK & os.R_OK))
19
+
20
+ def test_temp_file_overwrite_existing(self):
21
+ # Test if existing file is overwritten by the temporary file
22
+ # Create a dummy file at the specified path
23
+ os.makedirs("tests/files", exist_ok=True)
24
+ with open("tests/files/file.txt", "w") as f:
25
+ f.write("dummy content")
26
+
27
+ # Replace the file with a temporary file and check the content
28
+ with temp_file("tests/files/file.txt") as temp_path:
29
+ with open(temp_path, "r") as tf:
30
+ content = tf.read()
31
+ self.assertEqual(content, "")
32
+
33
+ def test_temp_file_cleanup(self):
34
+ with temp_file("tests/files/file.txt") as temp_path:
35
+ pass # Do nothing
36
+ self.assertFalse(os.path.exists(temp_path))
37
+
38
+ class TestJobDownloaderFlatten(unittest.TestCase):
39
+
40
+ def test_pad_job_id(self):
41
+ input = ("1234",)
42
+ result = flatten(input)
43
+ self.assertEqual(result, [{"job_id": "01234", "task_ids":None}])
44
+
45
+ def test_several_job_ids(self):
46
+ input = ("1234","1235","1236")
47
+ result = flatten(input)
48
+ self.assertEqual(result, [
49
+ {"job_id": "01234", "task_ids":None},
50
+ {"job_id": "01235", "task_ids":None},
51
+ {"job_id": "01236", "task_ids":None}
52
+ ])
53
+
54
+ def test_job_and_tasks(self):
55
+ input = ("1234:1-7x2,10",)
56
+ result = flatten(input)
57
+ self.assertEqual(result, [{"job_id": "01234", "task_ids":["001","003","005","007","010"]}])
58
+
59
+ def test_several_job_and_tasks(self):
60
+ input = ("1234:1-7x2,10","1235:12-15")
61
+ result = flatten(input)
62
+ self.assertEqual(result, [
63
+ {"job_id": "01234", "task_ids":["001","003","005","007","010"]},
64
+ {"job_id": "01235", "task_ids":["012","013","014","015"]}
65
+ ])
66
+
67
+ def test_mix_job_and_job_with_tasks(self):
68
+ input = ("1234","1235:12-15")
69
+ result = flatten(input)
70
+ self.assertEqual(result, [
71
+ {"job_id": "01234", "task_ids":None},
72
+ {"job_id": "01235", "task_ids":["012","013","014","015"]}
73
+ ])
74
+
75
+ def test_invalid_range_downloads_whole_job(self):
76
+ # Someone might have a bunch of stuff queued up and made a mistake and left for the night.
77
+ # We should download the whole job in this case so they don't have to restart the dl in the
78
+ # morning.
79
+ input = ("1234:badrange",)
80
+ result = flatten(input)
81
+ self.assertEqual(result, [
82
+ {"job_id": "01234", "task_ids":None}
83
+ ])
84
+
85
+ class TestJobDownloaderGetSomeTasks(unittest.TestCase):
86
+ def setUp(self):
87
+ # Create a mock instance of JobDownloader
88
+ self.obj = JobDownloader(jobs=["00000"])
89
+
90
+ @mock.patch("ciocore.downloader.job_downloader.logger.error")
91
+ def test_get_some_tasks_error(self, mock_error):
92
+ # Mock the api client to return an error
93
+ mock_api_client = mock.Mock()
94
+ response = '{"error": "some error message"}'
95
+ code = 404
96
+ mock_api_client.make_request.return_value = (response, code)
97
+ self.obj.client = mock_api_client
98
+ # call get_some_tasks
99
+ tasks, locator = self.obj.get_some_tasks({})
100
+
101
+ self.assertEqual(tasks, [])
102
+ self.assertIsNone(locator)
103
+ mock_error.assert_called_with(
104
+ 'Error fetching download info for job ID: %s : %s : %s', '00000', '/jobs/00000/downloads', mock.ANY)
105
+
106
+ def test_get_some_tasks_success(self):
107
+ mock_api_client = mock.Mock()
108
+ # Mock the api client to return a batch of tasks and a next cursor
109
+ response = '{"downloads": [{"id": 1, "name": "task1"}, {"id": 2, "name": "task2"}], "next_cursor": "1234"}'
110
+ code = 201
111
+ mock_api_client.make_request.return_value = (response, code)
112
+ self.obj.client = mock_api_client
113
+ self.obj.jobs = [{"job_id": "00000", "task_ids": [1, 2]}]
114
+ # call get_some_tasks with a locator
115
+ tasks, locator = self.obj.get_some_tasks({"job_index": 0, "cursor": None})
116
+
117
+ self.assertEqual(tasks, [{"id": 1, "name": "task1"}, {"id": 2, "name": "task2"}])
118
+ self.assertEqual(locator, {"job_index": 0, "cursor": "1234"})