ciocore 6.1.0__py2.py3-none-any.whl → 6.3.0__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.
Potentially problematic release.
This version of ciocore might be problematic. Click here for more details.
- ciocore/VERSION +1 -1
- ciocore/hardware_set.py +77 -15
- {ciocore-6.1.0.dist-info → ciocore-6.3.0.dist-info}/METADATA +13 -8
- {ciocore-6.1.0.dist-info → ciocore-6.3.0.dist-info}/RECORD +10 -10
- tests/instance_type_fixtures.py +22 -1
- tests/test_hardware_set.py +28 -14
- {ciocore-6.1.0.data → ciocore-6.3.0.data}/scripts/conductor +0 -0
- {ciocore-6.1.0.data → ciocore-6.3.0.data}/scripts/conductor.bat +0 -0
- {ciocore-6.1.0.dist-info → ciocore-6.3.0.dist-info}/WHEEL +0 -0
- {ciocore-6.1.0.dist-info → ciocore-6.3.0.dist-info}/top_level.txt +0 -0
ciocore/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
6.
|
|
1
|
+
6.3.0
|
ciocore/hardware_set.py
CHANGED
|
@@ -1,31 +1,46 @@
|
|
|
1
1
|
|
|
2
2
|
import copy
|
|
3
|
+
import logging
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
logger = logging.getLogger(__name__)
|
|
5
6
|
|
|
6
7
|
class HardwareSet(object):
|
|
7
8
|
"""A class to manage the categorized instance types.
|
|
8
9
|
|
|
9
10
|
It takes flat instance types array and builds a nested structure where instance types exist in
|
|
10
11
|
categories.
|
|
12
|
+
|
|
13
|
+
If after categorization there is only one category and it is the misc category, then we
|
|
14
|
+
recategorize by cpu and gpu.
|
|
11
15
|
"""
|
|
12
16
|
|
|
13
17
|
def __init__(self, instance_types):
|
|
18
|
+
|
|
14
19
|
self.instance_types = self.build_unique(instance_types)
|
|
15
20
|
self.categories = self.build_categories()
|
|
16
|
-
|
|
21
|
+
|
|
17
22
|
@staticmethod
|
|
18
23
|
def build_unique(instance_types):
|
|
19
24
|
"""Build a dictionary of instance types using name as key.
|
|
20
25
|
|
|
21
26
|
Remove any instance types whose description has already been seen. We can't have duplicate
|
|
22
27
|
descriptions.
|
|
28
|
+
|
|
29
|
+
If categories exist, then remove any instance types that don't have a category. Otherwise,
|
|
30
|
+
since there are no categories, we can't remove any instance types.
|
|
23
31
|
"""
|
|
32
|
+
categories = [category for it in instance_types for category in (it.get("categories") or [])]
|
|
24
33
|
result = {}
|
|
25
34
|
seen_descriptions = set()
|
|
26
35
|
for it in instance_types:
|
|
27
36
|
if it["description"] in seen_descriptions:
|
|
28
37
|
continue
|
|
38
|
+
if categories:
|
|
39
|
+
if it.get("categories") in [[], None]:
|
|
40
|
+
continue
|
|
41
|
+
else:
|
|
42
|
+
# make our own categories GPU/CPU
|
|
43
|
+
it["categories"] = [{'label': 'GPU', 'order': 2}] if "gpu" in it and it["gpu"] else [{'label': 'CPU', 'order': 1}]
|
|
29
44
|
result[it["name"]] = it
|
|
30
45
|
seen_descriptions.add(it["description"])
|
|
31
46
|
return result
|
|
@@ -37,9 +52,7 @@ class HardwareSet(object):
|
|
|
37
52
|
dikt = {}
|
|
38
53
|
for key in self.instance_types:
|
|
39
54
|
it = self.instance_types[key]
|
|
40
|
-
categories = it
|
|
41
|
-
if not categories:
|
|
42
|
-
categories.append({"label": MISC_CATEGORY_LABEL, "order": 999})
|
|
55
|
+
categories = it["categories"]
|
|
43
56
|
for category in categories:
|
|
44
57
|
label = category["label"]
|
|
45
58
|
if label not in dikt:
|
|
@@ -53,29 +66,78 @@ class HardwareSet(object):
|
|
|
53
66
|
result.append(category)
|
|
54
67
|
return sorted(result, key=lambda k: k["order"])
|
|
55
68
|
|
|
56
|
-
|
|
69
|
+
def recategorize(self, partitioner):
|
|
70
|
+
"""Recategorize the instance types.
|
|
71
|
+
|
|
72
|
+
Partitioner is a function that takes an instance type and returns a list of categories.
|
|
73
|
+
|
|
74
|
+
If for example you want to append to the existing categories, then you can use a function like this:
|
|
75
|
+
lambda x: x["categories"] + [{'label': 'Low cores', 'order': 10}] if x["cores"] < 16 else [{'label': 'High cores', 'order': 20}]
|
|
76
|
+
|
|
77
|
+
Rebuilds the categories structure after assigning the new categories.
|
|
78
|
+
"""
|
|
79
|
+
for key in self.instance_types:
|
|
80
|
+
self.instance_types[key]["categories"] = partitioner(self.instance_types[key])
|
|
81
|
+
self.categories = self.build_categories()
|
|
82
|
+
|
|
83
|
+
|
|
57
84
|
def get_model(self, with_misc=False):
|
|
58
|
-
"""Returns the categories structure with
|
|
85
|
+
"""Returns the categories structure with renaming ready for some UI.
|
|
59
86
|
|
|
60
|
-
|
|
87
|
+
NOTE: THIS METHOD WILL BE DEPRECATED. with_misc is no longer used, which means that this
|
|
88
|
+
function just renames a few keys. What's more, the init function ensures that every instance
|
|
89
|
+
type has a (non-misc) category. So this function is no longer needed. Submitters that use
|
|
90
|
+
it will work fine, but should be updated to use the categories structure directly.
|
|
61
91
|
"""
|
|
92
|
+
if with_misc:
|
|
93
|
+
logger.warning("with_misc is no longer used")
|
|
62
94
|
result = []
|
|
63
|
-
should_remove_misc = not with_misc and len( self.categories) > 1
|
|
64
|
-
|
|
65
95
|
for category in self.categories:
|
|
66
|
-
if should_remove_misc and category["label"] == MISC_CATEGORY_LABEL:
|
|
67
|
-
continue
|
|
68
|
-
|
|
69
96
|
result.append({
|
|
70
97
|
"label": category["label"],
|
|
71
|
-
"content":
|
|
98
|
+
"content": [{"label": k["description"], "value": k["name"]} for k in category["content"]]
|
|
72
99
|
})
|
|
73
100
|
|
|
74
101
|
return result
|
|
75
|
-
|
|
102
|
+
|
|
76
103
|
def find(self, name):
|
|
104
|
+
"""Find an instance type by name (sku).
|
|
105
|
+
|
|
106
|
+
Example: find("p3.2xlarge")
|
|
107
|
+
|
|
108
|
+
Returns and instance-type or None if not found.
|
|
109
|
+
"""
|
|
77
110
|
return self.instance_types.get(name)
|
|
78
111
|
|
|
112
|
+
def find_category(self, label):
|
|
113
|
+
"""Find a category by label.
|
|
114
|
+
|
|
115
|
+
Example: find_category("GPU")
|
|
116
|
+
|
|
117
|
+
Returns the entire category and its contents or None if not found.
|
|
118
|
+
"""
|
|
119
|
+
return next((c for c in self.categories if c["label"] == label), None)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def find_all(self, condition):
|
|
123
|
+
"""Find all instance types that match a condition.
|
|
124
|
+
|
|
125
|
+
Example: find_all(lambda x: x["gpu"])
|
|
126
|
+
"""
|
|
127
|
+
result = []
|
|
128
|
+
for key in self.instance_types:
|
|
129
|
+
if condition(self.instance_types[key]):
|
|
130
|
+
result.append(self.instance_types[key])
|
|
131
|
+
return result
|
|
132
|
+
|
|
133
|
+
def find_first(self, condition):
|
|
134
|
+
"""Find the first instance type that matches a condition.
|
|
135
|
+
|
|
136
|
+
Example: find_first(lambda x: x["cores"] == 4)"])
|
|
137
|
+
"""
|
|
138
|
+
return next(iter(self.find_all(condition)), None)
|
|
139
|
+
|
|
79
140
|
def number_of_categories(self):
|
|
141
|
+
"""Return the number of categories in the data."""
|
|
80
142
|
return len(self.categories)
|
|
81
143
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ciocore
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.3.0
|
|
4
4
|
Summary: Core functionality for Conductor's client tools
|
|
5
5
|
Home-page: https://github.com/ConductorTechnologies/ciocore
|
|
6
6
|
Author: conductor
|
|
@@ -26,11 +26,6 @@ Use the command-line uploader and downloader or develop your own tools using the
|
|
|
26
26
|
pip install --upgrade ciocore
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
**To install a specific version, for example 0.1.0.**
|
|
30
|
-
```bash
|
|
31
|
-
pip install --upgrade ciocore==0.1.0
|
|
32
|
-
```
|
|
33
|
-
|
|
34
29
|
Run the conductor command to confirm the package was installed.
|
|
35
30
|
```bash
|
|
36
31
|
conductor --help
|
|
@@ -48,13 +43,23 @@ See [CONTRIBUTING](CONTRIBUTING.md)
|
|
|
48
43
|
|
|
49
44
|
## Changelog
|
|
50
45
|
|
|
46
|
+
## Version:6.3.0 -- 05 Jul 2023
|
|
47
|
+
|
|
48
|
+
* In the absence of instance-type categories provided by the endpoint, the client generates default
|
|
49
|
+
categories CPU and GPU which at least splits the instance types into two groups, thereby making
|
|
50
|
+
dropdown menus more manageable, especially for CoreWeave's array of machines.
|
|
51
|
+
* update circleci config and related documentation
|
|
52
|
+
|
|
51
53
|
## Version:6.1.0 -- 09 Jun 2023
|
|
52
54
|
|
|
53
|
-
Add the ability to specify which platforms to get resources for. This helps consumers of the API to
|
|
55
|
+
Add the ability to specify which platforms to get resources for. This helps consumers of the API to
|
|
56
|
+
avoid fetching resources for Windows when the client is not ready.
|
|
54
57
|
|
|
55
58
|
## Version:6.0.0 -- 07 Jun 2023
|
|
56
59
|
|
|
57
|
-
This is a breaking change due instance types being provided as an instance of HardwareSet with
|
|
60
|
+
This is a breaking change due instance types being provided as an instance of HardwareSet with
|
|
61
|
+
support for categories as opposed to a simple list. Consumers of the API will need to be updated to
|
|
62
|
+
support this change.
|
|
58
63
|
|
|
59
64
|
## Version:6.0.0-rc.4 -- 06 Jun 2023
|
|
60
65
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
ciocore/VERSION,sha256=
|
|
1
|
+
ciocore/VERSION,sha256=AcBmZzP8VI6iOQK01krLRTlT4Tu0al4tBEsVA7A-nUo,5
|
|
2
2
|
ciocore/__about__.py,sha256=nTb4Xx0r9QtGROSFKgwDZ-Mr2LKjm2wVt1OkMQAkRAQ,241
|
|
3
3
|
ciocore/__init__.py,sha256=zB_e7gBW2QloqbrGzcvccfpZhOhd6o9KACnScrwylm8,25
|
|
4
4
|
ciocore/api_client.py,sha256=O9uvtnqgmE2IRkqlP9DoPn6CX_HAIuSLo9je5Om-800,17913
|
|
@@ -11,7 +11,7 @@ ciocore/data.py,sha256=RQZEYGkZrVFgyyPqzBat-L99sq49h-SQUnSdGIPDI18,8938
|
|
|
11
11
|
ciocore/downloader.py,sha256=oRmRePdIx_GdQwM39ipl9_e2c2ZkcGJRanuHOZmqpTM,51147
|
|
12
12
|
ciocore/exceptions.py,sha256=c1K48hWcD8VOORfNoSf5qlQkLLEqwjryH8FUwUYAYU4,1431
|
|
13
13
|
ciocore/file_utils.py,sha256=bAlL31B4YkRgX-yT8kF8UXBFktQlsE1PvxbKqTeAeOU,17174
|
|
14
|
-
ciocore/hardware_set.py,sha256=
|
|
14
|
+
ciocore/hardware_set.py,sha256=txcSLrVSNewRGxKLye-wuM8szGMVloU29ktL8WHdUtM,5401
|
|
15
15
|
ciocore/loggeria.py,sha256=dKKJC8ZtRZdghqD5R5XrA6eDoy8gKacfeTA-zNzXvDE,13482
|
|
16
16
|
ciocore/package_environment.py,sha256=oEbNKXRtPSPzKR-yCoKtvgzu4OCmr-zaqAcNoLAN9Uk,7238
|
|
17
17
|
ciocore/package_tree.py,sha256=kH03HVfjomj7nsaxJJtr-1KSQ_9ZSQY5msG_l9btvg8,16277
|
|
@@ -23,16 +23,16 @@ ciocore/auth/__init__.py,sha256=cdS-xZzMq41yXM5cz8sUlcYgo8CJYh8HcCCWmhbDgf0,606
|
|
|
23
23
|
ciocore/auth/server.py,sha256=8btX9-EokUl6q55V8muDmEV2tvvbTBD0BHeWFbwkzUc,3892
|
|
24
24
|
ciocore/cli/__init__.py,sha256=RmZKWJaMpzNyMdyYc2W3VXglaJiC8vyR2cgUlA-9Qmw,26
|
|
25
25
|
ciocore/cli/conductor.py,sha256=snmlICkMgP94ZPKl6J7g299deB75QwGDWI0oCnZPfSI,10861
|
|
26
|
-
ciocore-6.
|
|
27
|
-
ciocore-6.
|
|
26
|
+
ciocore-6.3.0.data/scripts/conductor,sha256=Nk3QsLQqbUUrtaKDp4b5mr9__4tz-xnssENpQe5vuIo,409
|
|
27
|
+
ciocore-6.3.0.data/scripts/conductor.bat,sha256=T1_9ByheubBczgQZn8_LwfvMtWgE7Bt64EsEScnSXMs,447
|
|
28
28
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
-
tests/instance_type_fixtures.py,sha256=
|
|
29
|
+
tests/instance_type_fixtures.py,sha256=gR6ordfghp34I94oM2eDg6jfIe5HAwE644GKIwspuW8,3469
|
|
30
30
|
tests/package_fixtures.py,sha256=CsJnhB7oYzIxJH7b1tCOPyvnnVSCqEbSPhtCnsHL-nA,5070
|
|
31
31
|
tests/test_api_client.py,sha256=dWOmAIKmX0gLaDGsT9VfAq9Hcs9HIQf2P5IMM_Bt5dE,1284
|
|
32
32
|
tests/test_common.py,sha256=lJpzRdL-7u4McXFbLuwPQQoUnuEOnCVQtZEt6e_dIYs,638
|
|
33
33
|
tests/test_config.py,sha256=nSmpinX2SmDNAprIcxs9UHdB0VakJB0snXaZmAoKJSc,12863
|
|
34
34
|
tests/test_data.py,sha256=YdP1kZJivQ6yb9z96UK6oMDaOfJAl4YMJqzKvlCQaes,5744
|
|
35
|
-
tests/test_hardware_set.py,sha256=
|
|
35
|
+
tests/test_hardware_set.py,sha256=TcBh63rOxf1rKXxKlCPSnHueBFlz7rNP6BcoJjgVvPs,3065
|
|
36
36
|
tests/test_imports_2and3.py,sha256=ehqpRYPVY7djBcb8OT_cnh86iCJJ9wuMWnfSR9RHxmY,507
|
|
37
37
|
tests/test_package_environment.py,sha256=CdiC2PDVSnbcwTb4fsDTWqGYSzs1n5ca2KMoyISckGA,5893
|
|
38
38
|
tests/test_package_tree.py,sha256=xCwNwYUmJrfmgCP2FGoHRFG-L0JPy8s4-66icxAls4o,6780
|
|
@@ -42,7 +42,7 @@ tests/test_validator.py,sha256=2fY66ayNc08PGyj2vTI-V_1yeCWJDngkj2zkUM5TTCI,1526
|
|
|
42
42
|
tests/mocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
43
|
tests/mocks/api_client_mock.py,sha256=Wfv2JPFSZfyHftVqsqxcpXWJn136pEHx26I_esz567E,943
|
|
44
44
|
tests/mocks/glob.py,sha256=J2MH7nqi6NJOHuGdVWxhfeBd700_Ckj6cLh_8jSNkfg,215
|
|
45
|
-
ciocore-6.
|
|
46
|
-
ciocore-6.
|
|
47
|
-
ciocore-6.
|
|
48
|
-
ciocore-6.
|
|
45
|
+
ciocore-6.3.0.dist-info/METADATA,sha256=Jf9qxoQUVb1qnmIgguLei22xyWZTXtoHIEYWBf9pe4w,14285
|
|
46
|
+
ciocore-6.3.0.dist-info/WHEEL,sha256=a-zpFRIJzOq5QfuhBzbhiA1eHTzNCJn8OdRvhdNX0Rk,110
|
|
47
|
+
ciocore-6.3.0.dist-info/top_level.txt,sha256=SvlM5JlqULzAz00JZWfiUhfjhqDzYzSWssA87zdJl0o,14
|
|
48
|
+
ciocore-6.3.0.dist-info/RECORD,,
|
tests/instance_type_fixtures.py
CHANGED
|
@@ -105,7 +105,7 @@ CW_INSTANCE_TYPES = [
|
|
|
105
105
|
"operating_system": "linux",
|
|
106
106
|
"description": "Desc 8 C 32 M F",
|
|
107
107
|
},
|
|
108
|
-
|
|
108
|
+
{
|
|
109
109
|
"cores": 8,
|
|
110
110
|
"memory": 64,
|
|
111
111
|
"name": "g-8-32",
|
|
@@ -114,3 +114,24 @@ CW_INSTANCE_TYPES = [
|
|
|
114
114
|
"description": "Desc 8 C 32 M G",
|
|
115
115
|
},
|
|
116
116
|
]
|
|
117
|
+
|
|
118
|
+
CW_INSTANCE_TYPES_WITH_GPUS = [
|
|
119
|
+
{
|
|
120
|
+
"cores": 8,
|
|
121
|
+
"memory": 64,
|
|
122
|
+
"name": "f-8-32-gpu",
|
|
123
|
+
"categories": [{"label": "high", "order": 3}],
|
|
124
|
+
"operating_system": "linux",
|
|
125
|
+
"description": "Desc 8 C 32 M F gpu",
|
|
126
|
+
"gpu": 1,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"cores": 8,
|
|
130
|
+
"memory": 64,
|
|
131
|
+
"name": "g-8-32-gpu",
|
|
132
|
+
"categories": [{"label": "high", "order": 3}],
|
|
133
|
+
"operating_system": "linux",
|
|
134
|
+
"description": "Desc 8 C 32 M G gpu",
|
|
135
|
+
"gpu": 1,
|
|
136
|
+
},
|
|
137
|
+
] + CW_INSTANCE_TYPES
|
tests/test_hardware_set.py
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import unittest
|
|
6
6
|
from unittest.mock import patch
|
|
7
7
|
|
|
8
|
-
from ciocore.hardware_set import
|
|
8
|
+
from ciocore.hardware_set import HardwareSet
|
|
9
9
|
|
|
10
10
|
PROJECTS = [
|
|
11
11
|
"Deadpool",
|
|
@@ -15,7 +15,7 @@ PROJECTS = [
|
|
|
15
15
|
]
|
|
16
16
|
|
|
17
17
|
from package_fixtures import *
|
|
18
|
-
from instance_type_fixtures import
|
|
18
|
+
from instance_type_fixtures import CW_INSTANCE_TYPES, CW_INSTANCE_TYPES_WITH_GPUS, ALL_INSTANCE_TYPES
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class TestCategorizedInstanceTypes(unittest.TestCase):
|
|
@@ -23,7 +23,7 @@ class TestCategorizedInstanceTypes(unittest.TestCase):
|
|
|
23
23
|
self.hs = HardwareSet(CW_INSTANCE_TYPES)
|
|
24
24
|
|
|
25
25
|
def test_number_of_categories(self):
|
|
26
|
-
self.assertEqual(self.hs.number_of_categories(),
|
|
26
|
+
self.assertEqual(self.hs.number_of_categories(), 4)
|
|
27
27
|
|
|
28
28
|
def test_categories_sorted_on_order(self):
|
|
29
29
|
labels = [i["label"] for i in self.hs.get_model()]
|
|
@@ -39,17 +39,31 @@ class TestCategorizedInstanceTypes(unittest.TestCase):
|
|
|
39
39
|
self.assertIn("a-4-16", low_category_values)
|
|
40
40
|
self.assertIn("a-4-16", extra_category_values)
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
class TestRecategorizeInstanceTypes(unittest.TestCase):
|
|
43
|
+
def setUp(self):
|
|
44
|
+
self.hs = HardwareSet(CW_INSTANCE_TYPES_WITH_GPUS)
|
|
45
|
+
|
|
46
|
+
def test_recategorize_cpu_gpu(self):
|
|
47
|
+
test_func = lambda x: [{'label': 'GPU', 'order': 2}] if "gpu" in x and x["gpu"] else [{'label': 'CPU', 'order': 1}]
|
|
48
|
+
self.hs.recategorize(test_func)
|
|
49
|
+
self.assertEqual(self.hs.number_of_categories(), 2)
|
|
50
|
+
|
|
51
|
+
def test_find_all_by_condition(self):
|
|
52
|
+
test_func = lambda x: "gpu" in x and x["gpu"]
|
|
53
|
+
result = self.hs.find_all(test_func)
|
|
54
|
+
self.assertEqual(len(result), 2)
|
|
55
|
+
|
|
56
|
+
def test_find_first_by_condition(self):
|
|
57
|
+
test_func = lambda x: x[ "memory"] < 32
|
|
58
|
+
result = self.hs.find_first(test_func)
|
|
59
|
+
self.assertTrue(result["memory"] < 32)
|
|
60
|
+
|
|
61
|
+
def test_find_category(self):
|
|
62
|
+
label = "mid"
|
|
63
|
+
result = self.hs.find_category(label)
|
|
64
|
+
self.assertEqual(result["label"] , label)
|
|
65
|
+
self.assertEqual(result["order"] , 2)
|
|
66
|
+
|
|
53
67
|
class TestUncategorizedInstanceTypes(unittest.TestCase):
|
|
54
68
|
def setUp(self):
|
|
55
69
|
self.hs = HardwareSet(ALL_INSTANCE_TYPES)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|