ciocore 8.0.0b32__py2.py3-none-any.whl → 8.0.1__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/cli.py +18 -14
- ciocore/docsite/404.html +1 -1
- ciocore/docsite/apidoc/api_client/index.html +1 -1
- ciocore/docsite/apidoc/apidoc/index.html +1 -1
- ciocore/docsite/apidoc/config/index.html +1 -1
- ciocore/docsite/apidoc/data/index.html +1 -1
- ciocore/docsite/apidoc/hardware_set/index.html +1 -1
- ciocore/docsite/apidoc/package_environment/index.html +1 -1
- ciocore/docsite/apidoc/package_tree/index.html +1 -1
- ciocore/docsite/cmdline/docs/index.html +1 -1
- ciocore/docsite/cmdline/downloader/index.html +1 -1
- ciocore/docsite/cmdline/packages/index.html +1 -1
- ciocore/docsite/cmdline/uploader/index.html +1 -1
- ciocore/docsite/how-to-guides/index.html +1 -1
- ciocore/docsite/index.html +1 -1
- ciocore/docsite/sitemap.xml.gz +0 -0
- ciocore/docsite/stylesheets/extra.css +2 -2
- ciocore/docsite/stylesheets/tables.css +0 -3
- ciocore/downloader/legacy_downloader.py +22 -51
- ciocore/file_utils.py +3 -3
- ciocore/uploader/_uploader.py +8 -7
- ciocore/worker.py +10 -5
- {ciocore-8.0.0b32.dist-info → ciocore-8.0.1.dist-info}/METADATA +6 -3
- {ciocore-8.0.0b32.dist-info → ciocore-8.0.1.dist-info}/RECORD +29 -30
- tests/test_cli.py +0 -14
- ciocore/dev_inst_tagger.py +0 -120
- {ciocore-8.0.0b32.dist-info → ciocore-8.0.1.dist-info}/WHEEL +0 -0
- {ciocore-8.0.0b32.dist-info → ciocore-8.0.1.dist-info}/entry_points.txt +0 -0
- {ciocore-8.0.0b32.dist-info → ciocore-8.0.1.dist-info}/top_level.txt +0 -0
ciocore/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
8.0.
|
|
1
|
+
8.0.1
|
ciocore/cli.py
CHANGED
|
@@ -118,9 +118,11 @@ def _set_logging(log_level, log_to_console=True, log_dir=None, log_filename=None
|
|
|
118
118
|
log_filename=log_filename,
|
|
119
119
|
console_formatter=loggeria.FORMATTER_VERBOSE,
|
|
120
120
|
disable_console_logging= not log_to_console,
|
|
121
|
-
use_system_log=
|
|
121
|
+
use_system_log=True,
|
|
122
122
|
)
|
|
123
123
|
|
|
124
|
+
print("Logging to %s" % loggeria.LOG_PATH)
|
|
125
|
+
|
|
124
126
|
def _register(client):
|
|
125
127
|
api_client.ApiClient.register_client(
|
|
126
128
|
client_name=client.CLIENT_NAME, client_version=VERSION
|
|
@@ -131,7 +133,15 @@ def _register(client):
|
|
|
131
133
|
@click.pass_context
|
|
132
134
|
@click.option("-v", "--version", is_flag=True, help="Print the version and exit.")
|
|
133
135
|
def main(ctx, version):
|
|
134
|
-
"""
|
|
136
|
+
"""
|
|
137
|
+
Conductor Command-line interface.
|
|
138
|
+
|
|
139
|
+
To get help on subcommands, use the --help flag after the subcommand.
|
|
140
|
+
|
|
141
|
+
Example:
|
|
142
|
+
conductor download --help
|
|
143
|
+
|
|
144
|
+
"""
|
|
135
145
|
if not ctx.invoked_subcommand:
|
|
136
146
|
if version:
|
|
137
147
|
click.echo(VERSION)
|
|
@@ -158,7 +168,7 @@ def main(ctx, version):
|
|
|
158
168
|
default=DEFAULT_CONFIG_LOG_LEVEL,
|
|
159
169
|
)
|
|
160
170
|
@click.option("-ld", "--log_dir", help=LOG_DIR_HELP)
|
|
161
|
-
@click.option("-lcl", "--log_to_console", is_flag=True, help=LOG_TO_CONSOLE_HELP, default=
|
|
171
|
+
@click.option("-lcl", "--log_to_console", is_flag=True, help=LOG_TO_CONSOLE_HELP, default=False)
|
|
162
172
|
@click.option(
|
|
163
173
|
"-tc",
|
|
164
174
|
"--thread_count",
|
|
@@ -181,15 +191,13 @@ def upload(
|
|
|
181
191
|
Example:
|
|
182
192
|
conductor upload file1 file2 file3
|
|
183
193
|
"""
|
|
184
|
-
|
|
185
|
-
_set_logging(log_level, log_to_console=log_to_console, log_dir=log_dir)
|
|
194
|
+
|
|
195
|
+
_set_logging(log_level, log_to_console=log_to_console, log_dir=log_dir, log_filename="conductor_uploader.log")
|
|
186
196
|
|
|
187
197
|
args_dict = {
|
|
188
198
|
"database_filepath": database_filepath,
|
|
189
199
|
"location": location,
|
|
190
200
|
"md5_caching": md5_caching,
|
|
191
|
-
"log_level": log_level,
|
|
192
|
-
"log_dir": log_dir,
|
|
193
201
|
"thread_count": thread_count,
|
|
194
202
|
}
|
|
195
203
|
|
|
@@ -276,7 +284,7 @@ DEPRECATED_PATHS_HELP = "Specify a list of paths to upload."
|
|
|
276
284
|
help=THREADS_HELP,
|
|
277
285
|
default=DEFAULT_CONFIG_THREAD_COUNT,
|
|
278
286
|
)
|
|
279
|
-
@click.option("-lcl", "--log_to_console", is_flag=True, help=LOG_TO_CONSOLE_HELP, default=
|
|
287
|
+
@click.option("-lcl", "--log_to_console", is_flag=True, help=LOG_TO_CONSOLE_HELP, default=False)
|
|
280
288
|
@click.option("-lc", "--location", help=LOCATION_HELP)
|
|
281
289
|
@click.option(
|
|
282
290
|
"-p",
|
|
@@ -298,14 +306,12 @@ def uploader(
|
|
|
298
306
|
Example:
|
|
299
307
|
conductor upload file1 file2 file3
|
|
300
308
|
"""
|
|
301
|
-
_set_logging(log_level, log_to_console=log_to_console, log_dir=log_dir)
|
|
309
|
+
_set_logging(log_level, log_to_console=log_to_console, log_dir=log_dir, log_filename="conductor_uploader.log")
|
|
302
310
|
|
|
303
311
|
args_dict = {
|
|
304
312
|
"database_filepath": database_filepath,
|
|
305
313
|
"location": location,
|
|
306
314
|
"md5_caching": md5_caching,
|
|
307
|
-
"log_level": log_level,
|
|
308
|
-
"log_dir": log_dir,
|
|
309
315
|
"thread_count": thread_count,
|
|
310
316
|
}
|
|
311
317
|
|
|
@@ -374,11 +380,9 @@ def downloader(
|
|
|
374
380
|
)
|
|
375
381
|
ctx.exit(0)
|
|
376
382
|
|
|
377
|
-
if task_id:
|
|
378
|
-
job_id = job_id + ":" + task_id
|
|
379
|
-
|
|
380
383
|
Downloader.download_jobs(
|
|
381
384
|
(job_id,),
|
|
385
|
+
task_id=task_id,
|
|
382
386
|
thread_count=thread_count,
|
|
383
387
|
output_dir=output,
|
|
384
388
|
)
|
ciocore/docsite/404.html
CHANGED
ciocore/docsite/index.html
CHANGED
ciocore/docsite/sitemap.xml.gz
CHANGED
|
Binary file
|
|
@@ -18,10 +18,10 @@ import time
|
|
|
18
18
|
import threading
|
|
19
19
|
import hashlib
|
|
20
20
|
|
|
21
|
+
import ciocore
|
|
21
22
|
from ciocore import config
|
|
22
23
|
from ciocore import api_client, common, loggeria
|
|
23
24
|
from ciocore.common import CONDUCTOR_LOGGER_NAME
|
|
24
|
-
from cioseq.sequence import Sequence
|
|
25
25
|
|
|
26
26
|
try:
|
|
27
27
|
import Queue as queue
|
|
@@ -291,12 +291,12 @@ class Downloader(object):
|
|
|
291
291
|
downloader.print_uptime()
|
|
292
292
|
|
|
293
293
|
@classmethod
|
|
294
|
-
def download_jobs(cls, job_ids, thread_count=None, output_dir=None):
|
|
294
|
+
def download_jobs(cls, job_ids, task_id=None, thread_count=None, output_dir=None):
|
|
295
295
|
"""
|
|
296
296
|
Run the downloader for explicit jobs, and terminate afterwards.
|
|
297
297
|
"""
|
|
298
298
|
downloader = cls(thread_count=thread_count, output_dir=output_dir)
|
|
299
|
-
downloader.start(job_ids)
|
|
299
|
+
thread_states = downloader.start(job_ids, task_id=task_id)
|
|
300
300
|
while not common.SIGINT_EXIT and (
|
|
301
301
|
not downloader.pending_queue.empty() or not downloader.downloading_queue.empty()
|
|
302
302
|
):
|
|
@@ -306,7 +306,7 @@ class Downloader(object):
|
|
|
306
306
|
downloader._print_download_history()
|
|
307
307
|
downloader.print_uptime()
|
|
308
308
|
|
|
309
|
-
def start(self, job_ids=None, summary_interval=10):
|
|
309
|
+
def start(self, job_ids=None, task_id=None, summary_interval=10):
|
|
310
310
|
# Create new queues
|
|
311
311
|
self.start_time = time.time()
|
|
312
312
|
self.pending_queue = queue.Queue()
|
|
@@ -316,7 +316,7 @@ class Downloader(object):
|
|
|
316
316
|
# If a job id has been specified then only load the queue up with that work
|
|
317
317
|
if job_ids:
|
|
318
318
|
self.history_queue_max = None
|
|
319
|
-
self.get_jobs_downloads(job_ids)
|
|
319
|
+
self.get_jobs_downloads(job_ids, task_id)
|
|
320
320
|
|
|
321
321
|
# otherwise create a queue thread the polls the app for wor
|
|
322
322
|
else:
|
|
@@ -461,12 +461,10 @@ class Downloader(object):
|
|
|
461
461
|
# Wait for the queue to be consumed before querying for more
|
|
462
462
|
self.nap()
|
|
463
463
|
|
|
464
|
-
|
|
465
464
|
def nap(self):
|
|
466
465
|
while not common.SIGINT_EXIT:
|
|
467
466
|
|
|
468
467
|
time.sleep(self.naptime)
|
|
469
|
-
# Pretty sure this return should be unindented!
|
|
470
468
|
return
|
|
471
469
|
|
|
472
470
|
@common.dec_timer_exit(log_level=logging.DEBUG)
|
|
@@ -479,51 +477,23 @@ class Downloader(object):
|
|
|
479
477
|
except Exception as e:
|
|
480
478
|
logger.exception("Could not get next download")
|
|
481
479
|
|
|
482
|
-
def get_jobs_downloads(self, job_ids):
|
|
480
|
+
def get_jobs_downloads(self, job_ids, task_id):
|
|
483
481
|
"""
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
Job ids are padded to 5 digits, and task ids are padded to 3 digits.
|
|
482
|
+
Get each job and optional comma-separated task list.
|
|
487
483
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
for tid in job["tasks"] or [None]:
|
|
500
|
-
downloads = _get_job_download(endpoint, self.api_client, job["job_id"], tid)
|
|
484
|
+
There will only be a task list if there is just one job, due to earlier arg validation.
|
|
485
|
+
|
|
486
|
+
If there is no task list, _get_job_download is called with tid=None (i.e. the whole job)
|
|
487
|
+
"""
|
|
488
|
+
task_ids = [t for t in task_id.split(",") if t] if task_id else [None]
|
|
489
|
+
|
|
490
|
+
for job_id in job_ids:
|
|
491
|
+
endpoint = self.endpoint_downloads_job % job_id
|
|
492
|
+
for tid in task_ids:
|
|
493
|
+
downloads = _get_job_download(endpoint, self.api_client, job_id, tid)
|
|
501
494
|
if downloads:
|
|
502
495
|
for task_download in downloads.get("downloads", []):
|
|
503
|
-
print("putting in queue: %s" % task_download)
|
|
504
496
|
self.pending_queue.put(task_download, block=True)
|
|
505
|
-
|
|
506
|
-
@staticmethod
|
|
507
|
-
def _flatten(job_ids):
|
|
508
|
-
"""Create a list of job objects with keys: job_id and tasks.
|
|
509
|
-
|
|
510
|
-
see: get_jobs_downloads() function see tests/test_downloader.py for examples.
|
|
511
|
-
"""
|
|
512
|
-
result = []
|
|
513
|
-
for job_id in job_ids:
|
|
514
|
-
if ":" in job_id:
|
|
515
|
-
job_id, range_spec = job_id.split(":")
|
|
516
|
-
try:
|
|
517
|
-
seq = Sequence.create(range_spec)
|
|
518
|
-
tasks = seq.expand("###")
|
|
519
|
-
except (ValueError, TypeError):
|
|
520
|
-
tasks = None
|
|
521
|
-
else:
|
|
522
|
-
tasks = None
|
|
523
|
-
result.append({"job_id": job_id.zfill(5), "tasks": tasks})
|
|
524
|
-
return result
|
|
525
|
-
|
|
526
|
-
|
|
527
497
|
|
|
528
498
|
@common.dec_catch_exception(raise_=True)
|
|
529
499
|
def download_target(self, pending_queue, downloading_queue, task_download_state):
|
|
@@ -620,8 +590,8 @@ class Downloader(object):
|
|
|
620
590
|
# account for a render's generated subdirectories
|
|
621
591
|
dirpath = os.path.dirname(local_filepath)
|
|
622
592
|
|
|
623
|
-
# Ensure that the
|
|
624
|
-
logger.debug("Creating
|
|
593
|
+
# Ensure that the destination directory exists and set open permissions
|
|
594
|
+
logger.debug("Creating destination directory if necessary: %s", dirpath)
|
|
625
595
|
file_download_state.status = FileDownloadState.STATE_PREPARING_DIRECTORY
|
|
626
596
|
safe_mkdirs(dirpath)
|
|
627
597
|
|
|
@@ -1268,7 +1238,7 @@ def run_downloader(args):
|
|
|
1268
1238
|
file_formatter=LOG_FORMATTER,
|
|
1269
1239
|
)
|
|
1270
1240
|
|
|
1271
|
-
api_client.ApiClient.register_client(client_name = Downloader.CLIENT_NAME, client_version=__version__)
|
|
1241
|
+
api_client.ApiClient.register_client(client_name = Downloader.CLIENT_NAME, client_version=ciocore.__version__)
|
|
1272
1242
|
|
|
1273
1243
|
logger.debug("Downloader args: %s", args)
|
|
1274
1244
|
|
|
@@ -1278,6 +1248,7 @@ def run_downloader(args):
|
|
|
1278
1248
|
if job_ids:
|
|
1279
1249
|
Downloader.download_jobs(
|
|
1280
1250
|
job_ids,
|
|
1251
|
+
task_id=args.get("task_id"),
|
|
1281
1252
|
thread_count=thread_count,
|
|
1282
1253
|
output_dir=args.get("output"),
|
|
1283
1254
|
)
|
|
@@ -1306,6 +1277,6 @@ def report_error(self, download_id, error_message):
|
|
|
1306
1277
|
resp_str, resp_code = self.api_helper.make_request(
|
|
1307
1278
|
"/downloads/%s/fail" % download_id, data=error_message, verb="POST", use_api_key=True
|
|
1308
1279
|
)
|
|
1309
|
-
except:
|
|
1280
|
+
except e:
|
|
1310
1281
|
pass
|
|
1311
1282
|
return True
|
ciocore/file_utils.py
CHANGED
|
@@ -256,13 +256,13 @@ def get_common_dirpath(paths):
|
|
|
256
256
|
|
|
257
257
|
|
|
258
258
|
def _is_valid_path(path_str):
|
|
259
|
-
"""
|
|
259
|
+
r"""
|
|
260
260
|
This is dirty/inaccurate helper function to determine whether the given "path" is considered
|
|
261
261
|
valid. If so, return True.
|
|
262
262
|
|
|
263
263
|
If the given path_str is any of the following characters, then it's to be considered invalid:
|
|
264
264
|
|
|
265
|
-
On linux
|
|
265
|
+
On linux/mac:
|
|
266
266
|
/
|
|
267
267
|
//
|
|
268
268
|
lettered drive (e.g. x:\)
|
|
@@ -453,7 +453,7 @@ def get_tx_path(filepath, existing_only=False):
|
|
|
453
453
|
|
|
454
454
|
|
|
455
455
|
def strip_drive_letter(filepath):
|
|
456
|
-
"""
|
|
456
|
+
r"""
|
|
457
457
|
If the given filepath has a drive letter, remove it and return the rest of the path
|
|
458
458
|
|
|
459
459
|
C:\cat.txt --> \cat.txt
|
ciocore/uploader/_uploader.py
CHANGED
|
@@ -640,8 +640,7 @@ class Uploader(object):
|
|
|
640
640
|
(UploadWorker, [], {"thread_count": self.args["thread_count"]}),
|
|
641
641
|
]
|
|
642
642
|
|
|
643
|
-
manager = worker.JobManager(job_description)
|
|
644
|
-
manager.start()
|
|
643
|
+
manager = worker.JobManager(job_description)
|
|
645
644
|
return manager
|
|
646
645
|
|
|
647
646
|
@common.dec_catch_exception(raise_=True)
|
|
@@ -744,7 +743,7 @@ class Uploader(object):
|
|
|
744
743
|
return True
|
|
745
744
|
|
|
746
745
|
def mark_upload_failed(self, error_message, upload_id):
|
|
747
|
-
logger.error("Upload failed:
|
|
746
|
+
logger.error("Upload failed: %s", error_message)
|
|
748
747
|
|
|
749
748
|
# report error_message to the app
|
|
750
749
|
self.api_client.make_request(
|
|
@@ -793,6 +792,7 @@ class Uploader(object):
|
|
|
793
792
|
|
|
794
793
|
# create worker pools
|
|
795
794
|
self.manager = self.create_manager(project)
|
|
795
|
+
self.manager.start()
|
|
796
796
|
|
|
797
797
|
# create reporters
|
|
798
798
|
logger.debug("creating report status thread...")
|
|
@@ -931,16 +931,17 @@ class Uploader(object):
|
|
|
931
931
|
|
|
932
932
|
if error_messages:
|
|
933
933
|
self.mark_upload_failed(
|
|
934
|
-
error_message="\n".join(error_messages),
|
|
934
|
+
error_message="Uploader ERROR: {}".format("\n".join(error_messages)),
|
|
935
|
+
upload_id=upload_id
|
|
935
936
|
)
|
|
936
937
|
|
|
937
938
|
log_file = loggeria.LOG_PATH
|
|
938
|
-
sys.stderr.write("
|
|
939
|
+
sys.stderr.write("\nError uploading files:\n")
|
|
939
940
|
|
|
940
941
|
for err_msg in error_messages:
|
|
941
|
-
sys.stderr.write("\t
|
|
942
|
+
sys.stderr.write("\t{}\n".format(err_msg))
|
|
942
943
|
|
|
943
|
-
sys.stderr.write("\nSee log
|
|
944
|
+
sys.stderr.write("\nSee log {} for more details\n\n".format(log_file))
|
|
944
945
|
|
|
945
946
|
self.error_messages = []
|
|
946
947
|
|
ciocore/worker.py
CHANGED
|
@@ -252,7 +252,7 @@ class ThreadWorker(object):
|
|
|
252
252
|
return
|
|
253
253
|
|
|
254
254
|
# don't to anything if we were not provided an out_queue
|
|
255
|
-
logger.debug("Attempting to put job to out_queue (%s -> %s)", job,
|
|
255
|
+
logger.debug("Attempting to put job to out_queue (%s -> %s)", job, self.out_queue)
|
|
256
256
|
|
|
257
257
|
if not self.out_queue:
|
|
258
258
|
return
|
|
@@ -261,7 +261,7 @@ class ThreadWorker(object):
|
|
|
261
261
|
if not WORKING:
|
|
262
262
|
return
|
|
263
263
|
|
|
264
|
-
logger.debug("Adding job to out_queue (%s -> %s)", job,
|
|
264
|
+
logger.debug("Adding job to out_queue (%s -> %s)", job, self.out_queue)
|
|
265
265
|
|
|
266
266
|
# add item to job
|
|
267
267
|
self.out_queue.put(job)
|
|
@@ -491,10 +491,15 @@ class JobManager():
|
|
|
491
491
|
while not self.error_handler_stop:
|
|
492
492
|
|
|
493
493
|
try:
|
|
494
|
-
error = self.error_queue.get(True,
|
|
494
|
+
error = self.error_queue.get(True, 0.5)
|
|
495
495
|
|
|
496
496
|
except queue.Empty:
|
|
497
|
-
|
|
497
|
+
|
|
498
|
+
if self.error:
|
|
499
|
+
break
|
|
500
|
+
|
|
501
|
+
else:
|
|
502
|
+
continue
|
|
498
503
|
|
|
499
504
|
logger.error('Got something from the error queue: %s', error)
|
|
500
505
|
self.error.append(error)
|
|
@@ -503,7 +508,7 @@ class JobManager():
|
|
|
503
508
|
except ValueError:
|
|
504
509
|
pass
|
|
505
510
|
|
|
506
|
-
|
|
511
|
+
self.stop_work(force=True)
|
|
507
512
|
|
|
508
513
|
def start_error_handler(self):
|
|
509
514
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ciocore
|
|
3
|
-
Version: 8.0.
|
|
3
|
+
Version: 8.0.1
|
|
4
4
|
Summary: Core functionality for Conductor's client tools
|
|
5
5
|
Home-page: https://github.com/ConductorTechnologies/ciocore
|
|
6
6
|
Author: conductor
|
|
@@ -51,11 +51,14 @@ See [CONTRIBUTING](CONTRIBUTING.md)
|
|
|
51
51
|
|
|
52
52
|
## Changelog
|
|
53
53
|
|
|
54
|
-
## Version:
|
|
54
|
+
## Version:8.0.1 -- 22 Apr 2024
|
|
55
55
|
|
|
56
|
+
* The uploader now sends all error messages to the dashboard - not just the first error.
|
|
57
|
+
* Fixed a bug where --log-to-console was not not working as expected in the command line upload subcommand.
|
|
58
|
+
* Fixed some errors in DEBUG-level logging messages.
|
|
56
59
|
|
|
57
|
-
Major Updates in Version 8.0.0
|
|
58
60
|
|
|
61
|
+
## Version:8.0.0 -- 07 Apr 2024
|
|
59
62
|
|
|
60
63
|
* The `conductor` commandline interface (CLI) has undergone a complete overhaul to improve its functionality and performance. It is now installed as a Python console script, which simplifies the installation process on all platforms and ensures that the tool is always accessible. In addition, this standardized installation allows for better integration into our Companion application and potentially customers' own proprietary tools.
|
|
61
64
|
* The commandline downloader has been rewritten to improve its performance and reliability. In previous versions, the downloader would fetch all download URLs from the server before starting any downloads. This approach was inefficient and would lead to performance issues when handling jobs with large numbers of tasks. The new downloader fetches tasks in small batches, which allows the download to start almost immediately, regardless of the number of tasks. It provides several new commandline flags, such as filtering based on filenames, and better logging, giving users more control and visibility over the download process. In addition, the new downloader has been written as an event based system that can be seamlessly integrated into other pipeline tools and GUIs. Pipeline TDs need only to register handlers to any of the events that the downloader emits.
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
ciocore/VERSION,sha256=
|
|
1
|
+
ciocore/VERSION,sha256=NUqt24vsbMosc7cU07CLlLBV2gAdKgs8roFBqy0xjlA,5
|
|
2
2
|
ciocore/__init__.py,sha256=aTP7LeeosQA8BZE67gDV4jgfTK5zxmwZRjiTRu_ZWj0,646
|
|
3
3
|
ciocore/api_client.py,sha256=TyHXGmK4uTmKV93O_IpAvttZhbexIIZTGP-IVn_WyWM,24599
|
|
4
|
-
ciocore/cli.py,sha256=
|
|
4
|
+
ciocore/cli.py,sha256=jZ1lOKQiUcrMhsVmD9SVmPMFwHtgDF4SaoAf2-PBS54,15449
|
|
5
5
|
ciocore/client_db.py,sha256=tTz3bl2xeDPPcYSDS3g3QgV_xYihJMx0Kj6OeN2klK0,12978
|
|
6
6
|
ciocore/common.py,sha256=mBIS6KiYoQsjWe6aIFUGRRvCMl8BIN2kmLZ4J8icap8,14982
|
|
7
7
|
ciocore/compat.py,sha256=5uEXPSog_jxsDMaHBswAKEtfyXT25VgU6WNGIhz9PHU,256
|
|
8
8
|
ciocore/conductor_submit.py,sha256=ONE0LsA5hGavTJIOXXYx8qzl8_vBPADwhd6Ytq_0E0c,9382
|
|
9
9
|
ciocore/config.py,sha256=rCL7kaFn1tYgSglN8q9Wx6SwMpoXTq0BMQGwPRVwVIg,8973
|
|
10
10
|
ciocore/data.py,sha256=Ji0qUk8nJXBNakoHSqBiVx8O58SbZXyt273SHlEDn3U,7027
|
|
11
|
-
ciocore/dev_inst_tagger.py,sha256=bPfoFbE7IPCpDbtbVHxW7IlMwvspdnJhPuNq-u4fJN4,3497
|
|
12
11
|
ciocore/exceptions.py,sha256=4Oq-WX-qiN6kPUdBCHvvd6mtSQ0nCkDbJxWt2CNtpv8,1504
|
|
13
|
-
ciocore/file_utils.py,sha256=
|
|
12
|
+
ciocore/file_utils.py,sha256=swA7th9WhDEloW69YViRTKB-oeC9UmNdEGegfH1r-Gw,17176
|
|
14
13
|
ciocore/hardware_set.py,sha256=FlRQiGCLRcSW7Oko_gzgVK8ZqJ_J92eT8e_AleAbS2E,17047
|
|
15
14
|
ciocore/loggeria.py,sha256=2xdQRFb9NyXynU2O_pSOszJWcpoHgPwTUWJvERg7ODY,15251
|
|
16
15
|
ciocore/package_environment.py,sha256=MEHV7jfs3NJIEYCIaW8JfJdBmelvPHZMmBzPlXETiRo,7808
|
|
@@ -19,22 +18,22 @@ ciocore/package_tree.py,sha256=vkORKXxQ7dO8l0_96eFwm-5AUVL0rP9bhgWYhW_v3lo,15649
|
|
|
19
18
|
ciocore/post_install.py,sha256=zu5Ctz2ANbKD-f5G2ODLIhKkWENBi4F3UKKu50OEWrg,1000
|
|
20
19
|
ciocore/retry.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
20
|
ciocore/validator.py,sha256=f_K7gxz122W_i5AxVx6dKhckOygl8TnmQiVj7tyX5zw,2344
|
|
22
|
-
ciocore/worker.py,sha256=
|
|
21
|
+
ciocore/worker.py,sha256=YnE0mGqkky9uxPMyDRmvdt1p1ER_GN39AeZPIGw6f4U,21832
|
|
23
22
|
ciocore/auth/__init__.py,sha256=cdS-xZzMq41yXM5cz8sUlcYgo8CJYh8HcCCWmhbDgf0,606
|
|
24
23
|
ciocore/auth/server.py,sha256=8btX9-EokUl6q55V8muDmEV2tvvbTBD0BHeWFbwkzUc,3892
|
|
25
|
-
ciocore/docsite/404.html,sha256=
|
|
26
|
-
ciocore/docsite/index.html,sha256=
|
|
24
|
+
ciocore/docsite/404.html,sha256=zUCnDe9r5yFZh8MXcTmzDaFyYBuRHz1gvuyJS2rYiTI,17207
|
|
25
|
+
ciocore/docsite/index.html,sha256=xz215H_KHWBYI1HT7IRpAZ4d1ptUiO8Y4DlOmbEPgPk,20945
|
|
27
26
|
ciocore/docsite/logo.png,sha256=gArgFFWdw8w985-0TkuGIgU_pW9sziEMZdqytXb5WLo,2825
|
|
28
27
|
ciocore/docsite/objects.inv,sha256=s2FKStLlVIQbfG7U2-nw-7rz4unvd1W0u00YtLBxAKo,758
|
|
29
28
|
ciocore/docsite/sitemap.xml,sha256=M_V85zl0y2adRvzJAnoCxlZH_Hl7TLnIb1A-6l_xGmI,109
|
|
30
|
-
ciocore/docsite/sitemap.xml.gz,sha256=
|
|
31
|
-
ciocore/docsite/apidoc/api_client/index.html,sha256=
|
|
32
|
-
ciocore/docsite/apidoc/apidoc/index.html,sha256=
|
|
33
|
-
ciocore/docsite/apidoc/config/index.html,sha256=
|
|
34
|
-
ciocore/docsite/apidoc/data/index.html,sha256=
|
|
35
|
-
ciocore/docsite/apidoc/hardware_set/index.html,sha256=
|
|
36
|
-
ciocore/docsite/apidoc/package_environment/index.html,sha256=
|
|
37
|
-
ciocore/docsite/apidoc/package_tree/index.html,sha256=
|
|
29
|
+
ciocore/docsite/sitemap.xml.gz,sha256=mBXMN84utPFOOhXBKJnq47kV3Zp6NvUz5Xxy7lDOxq8,127
|
|
30
|
+
ciocore/docsite/apidoc/api_client/index.html,sha256=0AdyUY-LmL5ZqUeqxIjjzmoZDbupNcImCWf7RFeO5-o,170218
|
|
31
|
+
ciocore/docsite/apidoc/apidoc/index.html,sha256=KGsHBY6GBF380w338GfOIMWnwAyyLvw2i1RQFORdwlE,26171
|
|
32
|
+
ciocore/docsite/apidoc/config/index.html,sha256=n3koKPRUza5-uHUt8hK8H8XyH6HG_U2CsGobdaN4KfY,72559
|
|
33
|
+
ciocore/docsite/apidoc/data/index.html,sha256=QhqiXUd_3qk_jGRYB5JiqlJTem8Jg7aKa5mPPDT1978,50850
|
|
34
|
+
ciocore/docsite/apidoc/hardware_set/index.html,sha256=4GEBYy5uLVlJqvdG71RdyrN7sKKuxszxipgmRi_NCbM,123042
|
|
35
|
+
ciocore/docsite/apidoc/package_environment/index.html,sha256=1d4hVlBXPy4bldkBH1GsRjVd-bxdYANmB-Mg7xIAC_4,69248
|
|
36
|
+
ciocore/docsite/apidoc/package_tree/index.html,sha256=7GaOHXeM_oKH8Db25f2-h5kUI1R6pcp0bXxW1COCJxs,109393
|
|
38
37
|
ciocore/docsite/assets/_mkdocstrings.css,sha256=K3bqYEmxlOHQ3-M11JNbBWHCBDBLarkFRm8HuEYrAG4,341
|
|
39
38
|
ciocore/docsite/assets/images/favicon.png,sha256=AjhUxD_Eslt5XuSVHIAZ494Fk__rb5GLXR8qm0elfP4,1870
|
|
40
39
|
ciocore/docsite/assets/javascripts/bundle.4e31edb1.min.js,sha256=vMxCR_BtNIcbmbPV6j8Z-YDLQ9ckt4RzvGuzCTg034s,97250
|
|
@@ -77,26 +76,26 @@ ciocore/docsite/assets/stylesheets/main.83068744.min.css,sha256=gwaHRErdgDoSsYab
|
|
|
77
76
|
ciocore/docsite/assets/stylesheets/main.83068744.min.css.map,sha256=q8dWQkgGSfCcYT2Le1J0Tmxpcqxol5kZKaokp9d8Af0,42278
|
|
78
77
|
ciocore/docsite/assets/stylesheets/palette.ecc896b0.min.css,sha256=7MiWsGpIt19TLduugHr1OQv1TJ9rEsndnkc2V8D9VjM,12245
|
|
79
78
|
ciocore/docsite/assets/stylesheets/palette.ecc896b0.min.css.map,sha256=T8ZT8Mw8ws4vxyx_b1QAwyC9_pnv7r0KVaUdu2ST7ug,3639
|
|
80
|
-
ciocore/docsite/cmdline/docs/index.html,sha256=
|
|
81
|
-
ciocore/docsite/cmdline/downloader/index.html,sha256=
|
|
82
|
-
ciocore/docsite/cmdline/packages/index.html,sha256=
|
|
83
|
-
ciocore/docsite/cmdline/uploader/index.html,sha256=
|
|
84
|
-
ciocore/docsite/how-to-guides/index.html,sha256=
|
|
79
|
+
ciocore/docsite/cmdline/docs/index.html,sha256=Vte3vd2TtRY34Ft6cKvUREeQrWEI9jgdTkQ0XzjZuss,20051
|
|
80
|
+
ciocore/docsite/cmdline/downloader/index.html,sha256=917XE3waukGnIXI9qxl0zYEf3vHVIQPdY3ZybmABAqc,23171
|
|
81
|
+
ciocore/docsite/cmdline/packages/index.html,sha256=Ssb2R7eSubBNR824oc3jjhJfrG3JKOPojA-uiAczgeQ,20923
|
|
82
|
+
ciocore/docsite/cmdline/uploader/index.html,sha256=TtLbHNlu4ofZ4bQBqam87RelWdHnVDSL7_rw_YqBbC8,25123
|
|
83
|
+
ciocore/docsite/how-to-guides/index.html,sha256=rF-DMyk4k_jGUJRF3dKtMMiOgXS8OvBqAn-zxWy3AGs,20100
|
|
85
84
|
ciocore/docsite/search/search_index.json,sha256=ZMAbHLAlwOTujgA32XJTA7SHogRYh9i-ioPFOxjjJ0s,182633
|
|
86
|
-
ciocore/docsite/stylesheets/extra.css,sha256=
|
|
87
|
-
ciocore/docsite/stylesheets/tables.css,sha256=
|
|
85
|
+
ciocore/docsite/stylesheets/extra.css,sha256=_Cxe9Dhg1BBi6Kqaz_iZD9z9VyqxA9vtONRjP4PVic0,354
|
|
86
|
+
ciocore/docsite/stylesheets/tables.css,sha256=LE_zwGRxGcdPIy-9QiVPecOzlEBSqZb_WP5vDkFE0ZM,3235
|
|
88
87
|
ciocore/downloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
89
88
|
ciocore/downloader/base_downloader.py,sha256=9PVmP1qy-dop4MbVsmLFvf5W6LKQLUKHPDYE6AEt71g,25784
|
|
90
89
|
ciocore/downloader/download_runner_base.py,sha256=cWTWKhFX5FLG84Wh8_s7xpk3n0nmQ4fDiD2rYV6a3u0,1612
|
|
91
90
|
ciocore/downloader/job_downloader.py,sha256=HAhr95RyCsj3KTp5W58Znc4JmqHY-mrM5b8vo6kRIJ0,5697
|
|
92
|
-
ciocore/downloader/legacy_downloader.py,sha256=
|
|
91
|
+
ciocore/downloader/legacy_downloader.py,sha256=LIbT3BxuY56lq_UW_io9FSgK_2VIKwFVMENyF-5KllA,51158
|
|
93
92
|
ciocore/downloader/log.py,sha256=WCRNx0LObx8JBO5MQucNHQGBXMgSBLGdH0VALN8dFDo,2105
|
|
94
93
|
ciocore/downloader/logging_download_runner.py,sha256=iOuW8OvfAYW5MpP9zpUXh94qkWLC0GeG4PDGH7JSqJM,2865
|
|
95
94
|
ciocore/downloader/perpetual_downloader.py,sha256=cD7lnBH75-c-ZVVPHZc1vSnDhgJOnGlPT85zn7IjGgA,2105
|
|
96
95
|
ciocore/downloader/registry.py,sha256=_JIOuqpWkJkgJGN33nt-DCvqN9Gw3xeFhzPq4RUxIoE,2903
|
|
97
96
|
ciocore/downloader/reporter.py,sha256=p1NK9k6iQ-jt7lRvZR0xFz0cGb2yo8tQcjlvYKR9SWM,4501
|
|
98
97
|
ciocore/uploader/__init__.py,sha256=hxRFJf5Lo86rtRObFXSjjot8nybQd-SebSfYCbgZwow,24
|
|
99
|
-
ciocore/uploader/_uploader.py,sha256=
|
|
98
|
+
ciocore/uploader/_uploader.py,sha256=40nzqO5DuFi4sx31VvjWxZPNkrWsWqM9jtFVxs_-o3o,37479
|
|
100
99
|
ciocore/uploader/upload_stats/__init__.py,sha256=Lg1y4zq1i0cwc6Hh2K1TAQDYymLff49W-uIo1xjcvdI,5309
|
|
101
100
|
ciocore/uploader/upload_stats/stats_formats.py,sha256=giNirtObU66VALWghPFSRhg3q_vw5MvESsnXhb_I3y8,2402
|
|
102
101
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -106,7 +105,7 @@ tests/package_fixtures.py,sha256=CsJnhB7oYzIxJH7b1tCOPyvnnVSCqEbSPhtCnsHL-nA,507
|
|
|
106
105
|
tests/project_fixtures.py,sha256=iBm_th_JtAw76vlNu7Jjhh9tLH4oOaNi-MgtPzCV7yQ,138
|
|
107
106
|
tests/test_api_client.py,sha256=tnYkIYvDILGJRatZM0nrtr83x8yBJstMP0Rt151U2gI,6757
|
|
108
107
|
tests/test_base_downloader.py,sha256=SS7tWKv2ZZhpUDk4UCg1TkrNrpntjSewgzLl1mEubSE,3603
|
|
109
|
-
tests/test_cli.py,sha256=
|
|
108
|
+
tests/test_cli.py,sha256=_WTs2SWlEgd6wtg1hmOBlFnbWVdFLvqp0KqNhy-y2e8,5532
|
|
110
109
|
tests/test_common.py,sha256=tY_-SY-JmJX09UehFs9RIDqZ785AmhfTl6eVKJeIUFY,763
|
|
111
110
|
tests/test_config.py,sha256=-_G682Ss3Zr1FmcMkjla1zAZprX2tQKpKc5_wD28rII,13340
|
|
112
111
|
tests/test_data.py,sha256=NIBXpCjG3Os3vpc1CkiVONrebro8D_jqQyJ0N3kbucU,5433
|
|
@@ -121,8 +120,8 @@ tests/test_uploader.py,sha256=B1llTJt_fqR6e_V_Jxfw9z73QgkFlEPU87xLYGzt-TQ,2914
|
|
|
121
120
|
tests/test_validator.py,sha256=2fY66ayNc08PGyj2vTI-V_1yeCWJDngkj2zkUM5TTCI,1526
|
|
122
121
|
tests/mocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
123
122
|
tests/mocks/glob.py,sha256=J2MH7nqi6NJOHuGdVWxhfeBd700_Ckj6cLh_8jSNkfg,215
|
|
124
|
-
ciocore-8.0.
|
|
125
|
-
ciocore-8.0.
|
|
126
|
-
ciocore-8.0.
|
|
127
|
-
ciocore-8.0.
|
|
128
|
-
ciocore-8.0.
|
|
123
|
+
ciocore-8.0.1.dist-info/METADATA,sha256=798KBccoox0YMHAcd09zV7pIzVkXN_GNoBWhckmK4D4,18440
|
|
124
|
+
ciocore-8.0.1.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
|
|
125
|
+
ciocore-8.0.1.dist-info/entry_points.txt,sha256=cCqcALMYbC4d8545V9w0Zysfg9MVuKWhzDQ2er4UfGE,47
|
|
126
|
+
ciocore-8.0.1.dist-info/top_level.txt,sha256=SvlM5JlqULzAz00JZWfiUhfjhqDzYzSWssA87zdJl0o,14
|
|
127
|
+
ciocore-8.0.1.dist-info/RECORD,,
|
tests/test_cli.py
CHANGED
|
@@ -13,8 +13,6 @@ class CliTestUploaderOptions(unittest.TestCase):
|
|
|
13
13
|
"database_filepath": None,
|
|
14
14
|
"location": None,
|
|
15
15
|
"md5_caching": True,
|
|
16
|
-
"log_level": "INFO",
|
|
17
|
-
"log_dir": None,
|
|
18
16
|
"thread_count": mock.ANY,
|
|
19
17
|
}
|
|
20
18
|
init_patcher = mock.patch("ciocore.cli.Uploader.__init__", autospec=True)
|
|
@@ -43,18 +41,6 @@ class CliTestUploaderOptions(unittest.TestCase):
|
|
|
43
41
|
expected.update({"md5_caching": False})
|
|
44
42
|
self.mock_init.assert_called_once_with(mock.ANY, expected)
|
|
45
43
|
|
|
46
|
-
def test_log_level_arg(self):
|
|
47
|
-
self.runner.invoke(cli_upload, ["--log_level", "DEBUG"])
|
|
48
|
-
expected = self.default_args
|
|
49
|
-
expected.update({"log_level": "DEBUG"})
|
|
50
|
-
self.mock_init.assert_called_once_with(mock.ANY, expected)
|
|
51
|
-
|
|
52
|
-
def test_log_dir_arg(self):
|
|
53
|
-
self.runner.invoke(cli_upload, ["--log_dir", "foo"])
|
|
54
|
-
expected = self.default_args
|
|
55
|
-
expected.update({"log_dir": "foo"})
|
|
56
|
-
self.mock_init.assert_called_once_with(mock.ANY, expected)
|
|
57
|
-
|
|
58
44
|
def test_thread_count_arg(self):
|
|
59
45
|
self.runner.invoke(cli_upload, ["--thread_count", 4])
|
|
60
46
|
expected = self.default_args
|
ciocore/dev_inst_tagger.py
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
DEV only. This module is used to request instance types from the inst-tagger service. We try to isolate the cod so it can be easily removed.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import os
|
|
6
|
-
import requests
|
|
7
|
-
from ciocore import api_client
|
|
8
|
-
|
|
9
|
-
USE_INST_TAGGER = int(os.environ.get("CIO_FEATURE_USE_INST_TAGGER", 0))
|
|
10
|
-
SUPABASE_URL = os.environ.get("CIO_FEATURE_INST_TAGGER_SUPABASE_URL")
|
|
11
|
-
SUPABASE_KEY = os.environ.get("CIO_FEATURE_INST_TAGGER_SUPABASE_KEY")
|
|
12
|
-
|
|
13
|
-
def request_supabase_data(table_name):
|
|
14
|
-
HEADERS = {
|
|
15
|
-
"Authorization": f"Bearer {SUPABASE_KEY}",
|
|
16
|
-
"apikey": SUPABASE_KEY,
|
|
17
|
-
"Content-Type": "application/json",
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
response = requests.get(
|
|
21
|
-
f"{SUPABASE_URL}/rest/v1/{table_name}", headers=HEADERS, timeout=5
|
|
22
|
-
)
|
|
23
|
-
if response.status_code == 200:
|
|
24
|
-
return response.json()
|
|
25
|
-
else:
|
|
26
|
-
print("Error:", response.status_code, response.text)
|
|
27
|
-
return None
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def get_cloud(cio_inst_types):
|
|
31
|
-
if not cio_inst_types:
|
|
32
|
-
return None
|
|
33
|
-
if cio_inst_types[0]["name"].startswith("cw-"):
|
|
34
|
-
return "cw"
|
|
35
|
-
elif "." in cio_inst_types[0]["name"]:
|
|
36
|
-
return "aws"
|
|
37
|
-
return "gcp"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def normalize_sb_inst_types(sb_inst_types):
|
|
41
|
-
result = []
|
|
42
|
-
for inst_type in sb_inst_types:
|
|
43
|
-
el = inst_type["instance_type"].copy()
|
|
44
|
-
el["id"] = inst_type["id"]
|
|
45
|
-
result.append(el)
|
|
46
|
-
return result
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def to_id_dict(thelist):
|
|
50
|
-
return {d["id"]: d for d in thelist}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def valid_inst_types():
|
|
54
|
-
sb_inst_types = request_supabase_data("instance_types")
|
|
55
|
-
sb_inst_types = normalize_sb_inst_types(sb_inst_types)
|
|
56
|
-
|
|
57
|
-
cio_inst_types = api_client.request_instance_types()
|
|
58
|
-
# print(json.dumps(cio_inst_types, indent=2))
|
|
59
|
-
|
|
60
|
-
cloud = get_cloud(cio_inst_types)
|
|
61
|
-
|
|
62
|
-
# filter out instance types that are not in the cloud
|
|
63
|
-
|
|
64
|
-
sb_inst_types = [
|
|
65
|
-
inst_type for inst_type in sb_inst_types if inst_type["cloud"] == cloud
|
|
66
|
-
]
|
|
67
|
-
for it in sb_inst_types:
|
|
68
|
-
it["cores"] = it["total_cpu"]
|
|
69
|
-
it["memory"] = it["total_memory_gb"]
|
|
70
|
-
|
|
71
|
-
cores = it["cores"]
|
|
72
|
-
mem = it["memory_gb"]
|
|
73
|
-
cpu_desc = f"{cores} cores, {mem} GB RAM"
|
|
74
|
-
gpu_desc = ""
|
|
75
|
-
if it["gpu"]:
|
|
76
|
-
gpu_count = it["gpu"]["gpu_count"]
|
|
77
|
-
gpu_model = it["gpu"]["gpu_model"]
|
|
78
|
-
gpu_arch = it["gpu"]["gpu_architecture"]
|
|
79
|
-
gpu_mem = it["gpu"]["total_gpu_memory"]
|
|
80
|
-
gpu_desc = f" ({gpu_count}x {gpu_model} ({gpu_arch}) {gpu_mem} GB)"
|
|
81
|
-
|
|
82
|
-
desc = f"{cpu_desc}{gpu_desc}"
|
|
83
|
-
it["description"] = desc
|
|
84
|
-
|
|
85
|
-
return sb_inst_types
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def request_instance_types():
|
|
89
|
-
"""
|
|
90
|
-
Request instance types from the inst-tagger service.
|
|
91
|
-
|
|
92
|
-
Returns:
|
|
93
|
-
list(dict): A list of instance types.
|
|
94
|
-
"""
|
|
95
|
-
if not USE_INST_TAGGER:
|
|
96
|
-
return None
|
|
97
|
-
|
|
98
|
-
inst_types = valid_inst_types()
|
|
99
|
-
|
|
100
|
-
tags = request_supabase_data("tags")
|
|
101
|
-
tag_ids = [tag["id"] for tag in tags]
|
|
102
|
-
tags_dict = to_id_dict(tags)
|
|
103
|
-
|
|
104
|
-
assignments = request_supabase_data("assignments")
|
|
105
|
-
assignments = [a for a in assignments if a["tag_id"] in tag_ids]
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
# assign tags to instance types
|
|
109
|
-
for inst_type in inst_types:
|
|
110
|
-
inst_type["categories"] = []
|
|
111
|
-
# find assignments relating to this instance type
|
|
112
|
-
these_assignments = [
|
|
113
|
-
a for a in assignments if a["instance_type_id"] == inst_type["id"]
|
|
114
|
-
]
|
|
115
|
-
|
|
116
|
-
for assignment in these_assignments:
|
|
117
|
-
tag = tags_dict[assignment["tag_id"]]
|
|
118
|
-
inst_type["categories"].append({"label": tag["label"], "order": tag["order"]})
|
|
119
|
-
|
|
120
|
-
return inst_types
|
|
File without changes
|
|
File without changes
|
|
File without changes
|