ciocore 9.1.0b1__py2.py3-none-any.whl → 9.1.0rc1__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/api_client.py +10 -6
- ciocore/data.py +4 -2
- ciocore/docsite/apidoc/api_client/index.html +17 -6
- ciocore/docsite/apidoc/data/index.html +11 -3
- ciocore/docsite/apidoc/package_tree/index.html +0 -5
- ciocore/docsite/search/search_index.json +1 -1
- ciocore/docsite/sitemap.xml.gz +0 -0
- ciocore/package_tree.py +0 -4
- ciocore/uploader/_uploader.py +161 -83
- ciocore/worker.py +1 -5
- {ciocore-9.1.0b1.dist-info → ciocore-9.1.0rc1.dist-info}/METADATA +10 -5
- {ciocore-9.1.0b1.dist-info → ciocore-9.1.0rc1.dist-info}/RECORD +22 -25
- tests/test_api_client.py +1 -4
- tests/test_common.py +1 -11
- tests/test_config.py +1 -4
- tests/test_data.py +167 -157
- tests/test_submit.py +1 -4
- tests/test_uploader.py +1 -4
- ciocore/compat.py +0 -15
- tests/extra_env_fixtures.py +0 -57
- tests/project_fixtures.py +0 -8
- {ciocore-9.1.0b1.dist-info → ciocore-9.1.0rc1.dist-info}/WHEEL +0 -0
- {ciocore-9.1.0b1.dist-info → ciocore-9.1.0rc1.dist-info}/entry_points.txt +0 -0
- {ciocore-9.1.0b1.dist-info → ciocore-9.1.0rc1.dist-info}/top_level.txt +0 -0
ciocore/docsite/sitemap.xml.gz
CHANGED
|
Binary file
|
ciocore/package_tree.py
CHANGED
ciocore/uploader/_uploader.py
CHANGED
|
@@ -26,13 +26,12 @@ from ciocore import (
|
|
|
26
26
|
exceptions,
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
+
from . import thread_queue_job
|
|
30
|
+
|
|
29
31
|
from .upload_stats import UploadStats
|
|
30
32
|
|
|
31
33
|
logger = logging.getLogger("{}.uploader".format(loggeria.CONDUCTOR_LOGGER_NAME))
|
|
32
34
|
|
|
33
|
-
SINGLEPART = "singlepart"
|
|
34
|
-
MULTIPART = "multipart"
|
|
35
|
-
|
|
36
35
|
|
|
37
36
|
class MD5Worker(worker.ThreadWorker):
|
|
38
37
|
"""
|
|
@@ -330,28 +329,61 @@ class FileStatWorker(worker.ThreadWorker):
|
|
|
330
329
|
"""
|
|
331
330
|
|
|
332
331
|
if job:
|
|
332
|
+
|
|
333
|
+
kms_key_name = job.get('kmsKeyName')
|
|
334
|
+
|
|
333
335
|
# iterate through singlepart urls
|
|
334
336
|
for singlepart_upload in job.get("singlePartURLs", []):
|
|
335
337
|
path = singlepart_upload["filePath"]
|
|
336
338
|
file_size = singlepart_upload["fileSize"]
|
|
337
339
|
upload_url = singlepart_upload["preSignedURL"]
|
|
340
|
+
md5 = self.metric_store.get_dict("file_md5s", path)
|
|
338
341
|
|
|
339
342
|
self.metric_store.increment("bytes_to_upload", file_size, path)
|
|
340
343
|
self.metric_store.increment("num_files_to_upload")
|
|
341
344
|
logger.debug("Singlepart, adding task %s", path)
|
|
342
345
|
|
|
343
|
-
|
|
346
|
+
upload_tq_job = thread_queue_job.UploadThreadQueueJob(path,
|
|
347
|
+
file_size,
|
|
348
|
+
presigned_url=upload_url,
|
|
349
|
+
file_md5=md5,
|
|
350
|
+
upload_id=None,
|
|
351
|
+
part_size=file_size,
|
|
352
|
+
part_index=1,
|
|
353
|
+
kms_key_name=kms_key_name)
|
|
354
|
+
|
|
355
|
+
self.put_job(upload_tq_job)
|
|
344
356
|
|
|
345
357
|
# iterate through multipart
|
|
346
358
|
for multipart_upload in job.get("multiPartURLs", []):
|
|
347
359
|
path = multipart_upload["filePath"]
|
|
348
360
|
file_size = multipart_upload["fileSize"]
|
|
349
361
|
|
|
362
|
+
part = multipart_upload
|
|
363
|
+
total_parts = len(multipart_upload['parts'])
|
|
364
|
+
md5 = self.metric_store.get_dict("file_md5s", path)
|
|
365
|
+
|
|
366
|
+
for chunk in multipart_upload['parts']:
|
|
367
|
+
logger.debug("Multipart, adding task %s (part %s)", path, chunk['partNumber'])
|
|
368
|
+
|
|
369
|
+
upload_tq_job = thread_queue_job.UploadThreadQueueJob(
|
|
370
|
+
path=path,
|
|
371
|
+
file_size=file_size,
|
|
372
|
+
presigned_url=chunk['url'],
|
|
373
|
+
file_md5=md5,
|
|
374
|
+
upload_id=multipart_upload['uploadID'],
|
|
375
|
+
part_size=multipart_upload['partSize'],
|
|
376
|
+
total_parts=total_parts,
|
|
377
|
+
part_index=chunk['partNumber'],
|
|
378
|
+
kms_key_name=kms_key_name)
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
part['parts'] = chunk
|
|
382
|
+
self.put_job(upload_tq_job)
|
|
383
|
+
|
|
350
384
|
self.metric_store.increment("bytes_to_upload", file_size, path)
|
|
351
385
|
self.metric_store.increment("num_files_to_upload")
|
|
352
|
-
|
|
353
|
-
self.put_job((path, file_size, multipart_upload, MULTIPART))
|
|
354
|
-
|
|
386
|
+
|
|
355
387
|
# make sure we return None, so no message is automatically added to the out_queue
|
|
356
388
|
return None
|
|
357
389
|
|
|
@@ -383,45 +415,30 @@ class UploadWorker(worker.ThreadWorker):
|
|
|
383
415
|
self.metric_store.increment("bytes_uploaded", len(data), filename)
|
|
384
416
|
|
|
385
417
|
def do_work(self, job, thread_int):
|
|
418
|
+
|
|
386
419
|
if job:
|
|
387
|
-
|
|
420
|
+
|
|
421
|
+
md5 = self.metric_store.get_dict("file_md5s", job.path)
|
|
388
422
|
|
|
389
423
|
try:
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
except Exception:
|
|
396
|
-
logger.error("Issue with job (%s): %s", len(job), job)
|
|
397
|
-
raise
|
|
398
|
-
|
|
399
|
-
if len(job) > 4:
|
|
400
|
-
kms_key_name = job[4]
|
|
401
|
-
|
|
402
|
-
md5 = self.metric_store.get_dict("file_md5s", filename)
|
|
403
|
-
|
|
404
|
-
try:
|
|
405
|
-
if upload_type == SINGLEPART:
|
|
406
|
-
return self.do_singlepart_upload(
|
|
407
|
-
upload, filename, file_size, md5, kms_key_name
|
|
408
|
-
)
|
|
409
|
-
elif upload_type == MULTIPART:
|
|
410
|
-
return self.do_multipart_upload(upload, filename, md5)
|
|
411
|
-
|
|
412
|
-
raise Exception(
|
|
413
|
-
"upload_type is '%s' expected %s or %s"
|
|
414
|
-
% (upload_type, SINGLEPART, MULTIPART)
|
|
415
|
-
)
|
|
424
|
+
if job.is_multipart():
|
|
425
|
+
return self.do_multipart_upload(job)
|
|
426
|
+
|
|
427
|
+
else:
|
|
428
|
+
return self.do_singlepart_upload(job)
|
|
416
429
|
|
|
417
430
|
except Exception as err_msg:
|
|
418
|
-
real_md5 = common.get_base64_md5(
|
|
431
|
+
real_md5 = common.get_base64_md5(job.path)
|
|
432
|
+
|
|
433
|
+
exc_tb = sys.exc_info()[2]
|
|
434
|
+
exception_line_num = exc_tb.tb_lineno
|
|
435
|
+
exception_file = pathlib.Path(exc_tb.tb_frame.f_code.co_filename).name
|
|
419
436
|
|
|
420
437
|
if isinstance(err_msg, requests.exceptions.HTTPError):
|
|
421
|
-
error_message = f"Upload of {
|
|
438
|
+
error_message = f"Upload of {job.path} failed with a response code {err_msg.response.status_code} ({err_msg.response.reason}) (expected '{job.md5}', got '{real_md5}')"
|
|
422
439
|
else:
|
|
423
440
|
error_message = (
|
|
424
|
-
f"Upload of {
|
|
441
|
+
f"Upload of {job.path} failed. (expected '{job.file_md5}', got '{real_md5}') {str(err_msg)} [{exception_file}-{exception_line_num}]"
|
|
425
442
|
)
|
|
426
443
|
|
|
427
444
|
logger.error(error_message)
|
|
@@ -430,9 +447,7 @@ class UploadWorker(worker.ThreadWorker):
|
|
|
430
447
|
return worker.EMPTY_JOB
|
|
431
448
|
|
|
432
449
|
@common.DecRetry(retry_exceptions=api_client.CONNECTION_EXCEPTIONS, tries=5)
|
|
433
|
-
def do_singlepart_upload(
|
|
434
|
-
self, upload_url, filename, file_size, md5, kms_key_name=None
|
|
435
|
-
):
|
|
450
|
+
def do_singlepart_upload(self, job):
|
|
436
451
|
"""
|
|
437
452
|
Note that for GCS we don't rely on the make_request's own retry mechanism because we need to
|
|
438
453
|
recreate the chunked_reader generator before retrying the request. Instead, we wrap this
|
|
@@ -442,19 +457,23 @@ class UploadWorker(worker.ThreadWorker):
|
|
|
442
457
|
headers that S3 does not accept.
|
|
443
458
|
"""
|
|
444
459
|
|
|
445
|
-
|
|
460
|
+
tq_job = thread_queue_job.MultiPartThreadQueueJob( md5=job.file_md5,
|
|
461
|
+
path=job.path,
|
|
462
|
+
total_parts=job.total_parts)
|
|
463
|
+
|
|
464
|
+
if job.is_vendor_aws() or job.is_vendor_cw():
|
|
446
465
|
# must declare content-length ourselves due to zero byte bug in requests library.
|
|
447
466
|
# api_client.make_prepared_request docstring.
|
|
448
467
|
headers = {
|
|
449
468
|
"Content-Type": "application/octet-stream",
|
|
450
|
-
"Content-Length": str(file_size),
|
|
469
|
+
"Content-Length": str(job.file_size),
|
|
451
470
|
}
|
|
452
471
|
|
|
453
|
-
with open(
|
|
472
|
+
with open(job.path, "rb") as fh:
|
|
454
473
|
# TODO: support chunked
|
|
455
474
|
response = self.api_client.make_prepared_request(
|
|
456
475
|
verb="PUT",
|
|
457
|
-
url=
|
|
476
|
+
url=job.presigned_url,
|
|
458
477
|
headers=headers,
|
|
459
478
|
params=None,
|
|
460
479
|
data=fh,
|
|
@@ -468,25 +487,26 @@ class UploadWorker(worker.ThreadWorker):
|
|
|
468
487
|
response.close()
|
|
469
488
|
|
|
470
489
|
# report upload progress
|
|
471
|
-
self.metric_store.increment("bytes_uploaded", file_size,
|
|
472
|
-
|
|
473
|
-
return response
|
|
490
|
+
self.metric_store.increment("bytes_uploaded", job.file_size, job.path)
|
|
491
|
+
|
|
474
492
|
else:
|
|
475
493
|
headers = {"Content-MD5": md5, "Content-Type": "application/octet-stream"}
|
|
476
494
|
|
|
477
|
-
if kms_key_name:
|
|
478
|
-
headers["x-goog-encryption-kms-key-name"] = kms_key_name
|
|
495
|
+
if job.kms_key_name is not None:
|
|
496
|
+
headers["x-goog-encryption-kms-key-name"] = job.kms_key_name
|
|
479
497
|
|
|
480
|
-
|
|
481
|
-
conductor_url=
|
|
498
|
+
self.api_client.make_request(
|
|
499
|
+
conductor_url=job.presigned_url,
|
|
482
500
|
headers=headers,
|
|
483
|
-
data=self.chunked_reader(
|
|
501
|
+
data=self.chunked_reader(job.path),
|
|
484
502
|
verb="PUT",
|
|
485
503
|
tries=1,
|
|
486
504
|
use_api_key=True,
|
|
487
505
|
)
|
|
506
|
+
|
|
507
|
+
return tq_job
|
|
488
508
|
|
|
489
|
-
def do_multipart_upload(self,
|
|
509
|
+
def do_multipart_upload(self, job):
|
|
490
510
|
"""
|
|
491
511
|
Files will be split into partSize returned by the FileAPI and hydrated once all parts are
|
|
492
512
|
uploaded. On successful part upload, response headers will contain an ETag. This value must
|
|
@@ -494,42 +514,32 @@ class UploadWorker(worker.ThreadWorker):
|
|
|
494
514
|
"""
|
|
495
515
|
uploads = []
|
|
496
516
|
complete_payload = {
|
|
497
|
-
"uploadID":
|
|
498
|
-
"hash":
|
|
517
|
+
"uploadID": job.upload_id,
|
|
518
|
+
"hash": job.file_md5,
|
|
499
519
|
"completedParts": [],
|
|
500
520
|
"project": self.project,
|
|
501
521
|
}
|
|
502
522
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
part_size=upload["partSize"],
|
|
510
|
-
)
|
|
523
|
+
tq_job = thread_queue_job.MultiPartThreadQueueJob(path=job.path,
|
|
524
|
+
md5=job.file_md5,
|
|
525
|
+
total_parts=job.total_parts,
|
|
526
|
+
part_index=job.part_index)
|
|
527
|
+
tq_job.upload_id = job.upload_id
|
|
528
|
+
tq_job.project = self.project
|
|
511
529
|
|
|
512
|
-
if resp_headers:
|
|
513
|
-
uploads.append(upload["uploadID"])
|
|
514
|
-
completed_part = {
|
|
515
|
-
"partNumber": part["partNumber"],
|
|
516
|
-
"etag": resp_headers["ETag"].strip('"'),
|
|
517
|
-
}
|
|
518
|
-
complete_payload["completedParts"].append(completed_part)
|
|
519
530
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
verb="POST",
|
|
526
|
-
headers=headers,
|
|
527
|
-
data=json.dumps(complete_payload),
|
|
528
|
-
raise_on_error=True,
|
|
529
|
-
use_api_key=True,
|
|
531
|
+
resp_headers = self._do_multipart_upload(
|
|
532
|
+
upload_url=job.presigned_url,
|
|
533
|
+
filename=job.path,
|
|
534
|
+
part_number=job.part_index,
|
|
535
|
+
part_size=job.part_size,
|
|
530
536
|
)
|
|
531
537
|
|
|
532
|
-
|
|
538
|
+
if resp_headers:
|
|
539
|
+
tq_job.part = job.part_index
|
|
540
|
+
tq_job.etag = resp_headers["ETag"].strip('"')
|
|
541
|
+
|
|
542
|
+
return tq_job
|
|
533
543
|
|
|
534
544
|
@common.DecRetry(retry_exceptions=api_client.CONNECTION_EXCEPTIONS, tries=5)
|
|
535
545
|
def _do_multipart_upload(self, upload_url, filename, part_number, part_size):
|
|
@@ -564,6 +574,73 @@ class UploadWorker(worker.ThreadWorker):
|
|
|
564
574
|
|
|
565
575
|
return response.headers
|
|
566
576
|
|
|
577
|
+
|
|
578
|
+
class MultiPartSiphonWorker(worker.ThreadWorker):
|
|
579
|
+
def __init__(self, *args, **kwargs):
|
|
580
|
+
super(MultiPartSiphonWorker, self).__init__(*args, **kwargs)
|
|
581
|
+
|
|
582
|
+
self.api_client = api_client.ApiClient()
|
|
583
|
+
self.multipart_siphon = {}
|
|
584
|
+
|
|
585
|
+
def do_work(self, job, thread_int):
|
|
586
|
+
"""
|
|
587
|
+
Process files that have already been uploaded.
|
|
588
|
+
|
|
589
|
+
If it's a single-part file, add the job to the out queue, so that it can
|
|
590
|
+
be used to determine if the Upload entity is complete.
|
|
591
|
+
|
|
592
|
+
If it's a multi-part upload, collect all the parts together. Once all the
|
|
593
|
+
parts have been accumulated, mark it as complete and add the file to the
|
|
594
|
+
out queue.
|
|
595
|
+
"""
|
|
596
|
+
|
|
597
|
+
if job:
|
|
598
|
+
|
|
599
|
+
if not job.is_multipart():
|
|
600
|
+
logger.debug("Job is not multipart (%s, %s)", job.total_parts, job.part_index)
|
|
601
|
+
|
|
602
|
+
else:
|
|
603
|
+
|
|
604
|
+
if job.md5 not in self.multipart_siphon:
|
|
605
|
+
self.multipart_siphon[job.md5] = []
|
|
606
|
+
|
|
607
|
+
# Add to the task count for this worker.
|
|
608
|
+
# -1 because a task has already been added for a single file
|
|
609
|
+
# but not all its parts.
|
|
610
|
+
old_task_count = self.task_count
|
|
611
|
+
self.task_count += job.total_parts - 1
|
|
612
|
+
logger.debug("Incrementing task count to %s from %s", self.task_count, old_task_count)
|
|
613
|
+
|
|
614
|
+
self.multipart_siphon[job.md5].append(job)
|
|
615
|
+
|
|
616
|
+
if len(self.multipart_siphon[job.md5]) == job.total_parts:
|
|
617
|
+
|
|
618
|
+
complete_payload = {
|
|
619
|
+
"uploadID": job.upload_id,
|
|
620
|
+
"hash": job.md5,
|
|
621
|
+
"completedParts": thread_queue_job.MultiPartThreadQueueJob.aggregate_parts(self.multipart_siphon[job.md5]),
|
|
622
|
+
"project": job.project,
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
# Complete multipart upload in order to hydrate file for availability
|
|
626
|
+
uri_path = "/api/v2/files/multipart/complete"
|
|
627
|
+
headers = {"Content-Type": "application/json"}
|
|
628
|
+
self.api_client.make_request(
|
|
629
|
+
uri_path=uri_path,
|
|
630
|
+
verb="POST",
|
|
631
|
+
headers=headers,
|
|
632
|
+
data=json.dumps(complete_payload),
|
|
633
|
+
raise_on_error=True,
|
|
634
|
+
use_api_key=True,
|
|
635
|
+
)
|
|
636
|
+
|
|
637
|
+
logger.debug("JSON payload: '%s'", json.dumps(complete_payload))
|
|
638
|
+
|
|
639
|
+
return job
|
|
640
|
+
|
|
641
|
+
# make sure we return None, so no message is automatically added to the out_queue
|
|
642
|
+
return None
|
|
643
|
+
|
|
567
644
|
def is_complete(self):
|
|
568
645
|
# Get the number of files already uploaded as they are not passed to the Upload
|
|
569
646
|
# worker
|
|
@@ -581,11 +658,11 @@ class UploadWorker(worker.ThreadWorker):
|
|
|
581
658
|
self.task_count,
|
|
582
659
|
)
|
|
583
660
|
|
|
584
|
-
return (queue_size
|
|
661
|
+
return (queue_size) >= self.task_count
|
|
585
662
|
|
|
586
663
|
else:
|
|
587
664
|
logger.debug("Is complete?: files not initialized yet")
|
|
588
|
-
return False
|
|
665
|
+
return False
|
|
589
666
|
|
|
590
667
|
|
|
591
668
|
class Uploader(object):
|
|
@@ -639,6 +716,7 @@ class Uploader(object):
|
|
|
639
716
|
),
|
|
640
717
|
(FileStatWorker, [], {"thread_count": 1}),
|
|
641
718
|
(UploadWorker, [], {"thread_count": self.args["thread_count"]}),
|
|
719
|
+
(MultiPartSiphonWorker, [], {"thread_count": 1})
|
|
642
720
|
]
|
|
643
721
|
|
|
644
722
|
manager = worker.JobManager(job_description)
|
ciocore/worker.py
CHANGED
|
@@ -621,11 +621,7 @@ class JobManager():
|
|
|
621
621
|
q_size = self.work_queues[index].qsize()
|
|
622
622
|
worker_threads = self.workers[index].threads
|
|
623
623
|
|
|
624
|
-
|
|
625
|
-
try:
|
|
626
|
-
num_active_threads = len([thd for thd in worker_threads if thd.isAlive()])
|
|
627
|
-
except AttributeError:
|
|
628
|
-
num_active_threads = len([thd for thd in worker_threads if thd.is_alive()])
|
|
624
|
+
num_active_threads = len([thd for thd in worker_threads if thd.is_alive()])
|
|
629
625
|
|
|
630
626
|
msg += '%s \titems in queue: %s' % (q_size, worker_class.__name__)
|
|
631
627
|
msg += '\t\t%s threads' % num_active_threads
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ciocore
|
|
3
|
-
Version: 9.1.
|
|
3
|
+
Version: 9.1.0rc1
|
|
4
4
|
Summary: Core functionality for Conductor's client tools
|
|
5
5
|
Home-page: https://github.com/ConductorTechnologies/ciocore
|
|
6
6
|
Author: conductor
|
|
@@ -9,9 +9,8 @@ Classifier: Operating System :: OS Independent
|
|
|
9
9
|
Classifier: Programming Language :: Python
|
|
10
10
|
Classifier: Topic :: Multimedia :: Graphics :: 3D Rendering
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
|
-
Requires-Dist: requests
|
|
13
|
-
Requires-Dist: pyjwt==
|
|
14
|
-
Requires-Dist: future>=0.18.2
|
|
12
|
+
Requires-Dist: requests>=2.31.0
|
|
13
|
+
Requires-Dist: pyjwt==2.9.0
|
|
15
14
|
Requires-Dist: cioseq<1.0.0,>=0.4.1
|
|
16
15
|
Requires-Dist: Click<9.0.0,>=8.1.3
|
|
17
16
|
Requires-Dist: markdown<4.0.0,>=3.5.2
|
|
@@ -51,12 +50,18 @@ See [CONTRIBUTING](CONTRIBUTING.md)
|
|
|
51
50
|
|
|
52
51
|
## Changelog
|
|
53
52
|
|
|
54
|
-
##
|
|
53
|
+
## Version:9.1.0-rc.1 -- 11 Dec 2024
|
|
54
|
+
|
|
55
55
|
* Adds required changes to parallelize multi-part uploads
|
|
56
56
|
* Cleans up the output when explicit paths are uploaded
|
|
57
57
|
* Fixes logic so managers doesn't erroneously try and call join a second time if cancelled
|
|
58
|
+
* Use the new required jwt parameters
|
|
59
|
+
* Removing py2.7 compatibility
|
|
58
60
|
|
|
61
|
+
## Version:8.3.3 -- 04 Dec 2024
|
|
59
62
|
|
|
63
|
+
* Adds filter option for API data query
|
|
64
|
+
|
|
60
65
|
## Version:8.3.2 -- 01 Oct 2024
|
|
61
66
|
|
|
62
67
|
* Tweak to package order behavior for markdown package query
|
|
@@ -1,24 +1,23 @@
|
|
|
1
|
-
ciocore/VERSION,sha256=
|
|
1
|
+
ciocore/VERSION,sha256=ax2aQwModu65ZstFnKm4dTChIjzu_0ljZcaKGDaGkSA,10
|
|
2
2
|
ciocore/__init__.py,sha256=aTP7LeeosQA8BZE67gDV4jgfTK5zxmwZRjiTRu_ZWj0,646
|
|
3
|
-
ciocore/api_client.py,sha256=
|
|
3
|
+
ciocore/api_client.py,sha256=KKL7TsYygNcfkFZDPPq1CSJsrVN_QLK4PqP44vXsCQg,33101
|
|
4
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
|
-
ciocore/compat.py,sha256=5uEXPSog_jxsDMaHBswAKEtfyXT25VgU6WNGIhz9PHU,256
|
|
8
7
|
ciocore/conductor_submit.py,sha256=bxvzdyNzscAOOOsqTvAYh5DQsTWyCQJNb16Mf-n_F0M,9702
|
|
9
8
|
ciocore/config.py,sha256=rCL7kaFn1tYgSglN8q9Wx6SwMpoXTq0BMQGwPRVwVIg,8973
|
|
10
|
-
ciocore/data.py,sha256=
|
|
9
|
+
ciocore/data.py,sha256=zT3zpkSbHPHHGlLeLDTbwkB8_-Ct6zd8qQ-7U1pDCHM,7215
|
|
11
10
|
ciocore/exceptions.py,sha256=4Oq-WX-qiN6kPUdBCHvvd6mtSQ0nCkDbJxWt2CNtpv8,1504
|
|
12
11
|
ciocore/file_utils.py,sha256=swA7th9WhDEloW69YViRTKB-oeC9UmNdEGegfH1r-Gw,17176
|
|
13
12
|
ciocore/hardware_set.py,sha256=FlRQiGCLRcSW7Oko_gzgVK8ZqJ_J92eT8e_AleAbS2E,17047
|
|
14
13
|
ciocore/loggeria.py,sha256=dk8n899TYFiMTD2gjjj8oiumJkPtCus0a_IY2GORAvU,15251
|
|
15
14
|
ciocore/package_environment.py,sha256=MEHV7jfs3NJIEYCIaW8JfJdBmelvPHZMmBzPlXETiRo,7808
|
|
16
15
|
ciocore/package_query.py,sha256=hWi_JmRieZ8f2Ji5JR7tQnHnm29Ktb88scbIXNsDu-8,6181
|
|
17
|
-
ciocore/package_tree.py,sha256=
|
|
16
|
+
ciocore/package_tree.py,sha256=FDKHxYZS8ZAkz3hpjMYFy-P8hwU1V9w4wA7gNqhruqs,15569
|
|
18
17
|
ciocore/post_install.py,sha256=zu5Ctz2ANbKD-f5G2ODLIhKkWENBi4F3UKKu50OEWrg,1000
|
|
19
18
|
ciocore/retry.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
19
|
ciocore/validator.py,sha256=f_K7gxz122W_i5AxVx6dKhckOygl8TnmQiVj7tyX5zw,2344
|
|
21
|
-
ciocore/worker.py,sha256=
|
|
20
|
+
ciocore/worker.py,sha256=3C4KJuBTdeqvMWdBn3cRnTju5dUjNKG0OGtHp0SZ4l8,21613
|
|
22
21
|
ciocore/auth/__init__.py,sha256=cdS-xZzMq41yXM5cz8sUlcYgo8CJYh8HcCCWmhbDgf0,606
|
|
23
22
|
ciocore/auth/server.py,sha256=8btX9-EokUl6q55V8muDmEV2tvvbTBD0BHeWFbwkzUc,3892
|
|
24
23
|
ciocore/docsite/404.html,sha256=xP-mZwn-87pnlkD-paIYzdXDLQr7DS551KflVdFfrCk,17207
|
|
@@ -26,14 +25,14 @@ ciocore/docsite/index.html,sha256=NEK4HaX2yaetTajVtQuTmS9C5cPnkAtxgeKEj7wQ9t0,20
|
|
|
26
25
|
ciocore/docsite/logo.png,sha256=gArgFFWdw8w985-0TkuGIgU_pW9sziEMZdqytXb5WLo,2825
|
|
27
26
|
ciocore/docsite/objects.inv,sha256=XwmLactPEWWC4fAWqHNPBXGsluRxLLTrwDLQqq51ONY,775
|
|
28
27
|
ciocore/docsite/sitemap.xml,sha256=M_V85zl0y2adRvzJAnoCxlZH_Hl7TLnIb1A-6l_xGmI,109
|
|
29
|
-
ciocore/docsite/sitemap.xml.gz,sha256=
|
|
30
|
-
ciocore/docsite/apidoc/api_client/index.html,sha256=
|
|
28
|
+
ciocore/docsite/sitemap.xml.gz,sha256=5N9BP1xbOEPkbpLHoqTsfzUJD3N4IJB55-_WR8JLfrc,127
|
|
29
|
+
ciocore/docsite/apidoc/api_client/index.html,sha256=kkhKzA7OThkpASLveONRPNS7gGppf8Ot2rxek1lZxHc,189722
|
|
31
30
|
ciocore/docsite/apidoc/apidoc/index.html,sha256=GOSvv6KZPOtgekgshRE4j7aDvJkkaiBQLwA_By9J94g,26171
|
|
32
31
|
ciocore/docsite/apidoc/config/index.html,sha256=WDqy4MLR3EMp9T_2-Z9Op61rTFkvb0aTWmtjiR8sbjA,72559
|
|
33
|
-
ciocore/docsite/apidoc/data/index.html,sha256=
|
|
32
|
+
ciocore/docsite/apidoc/data/index.html,sha256=8ldmfisgelzdWtTqGY8uebvVRcskhbv-reO3hMcIgGI,51627
|
|
34
33
|
ciocore/docsite/apidoc/hardware_set/index.html,sha256=SpYg-lwuCvfLPbNIIM7aQL2jGt-NA5wlVMlIKixGwBo,123042
|
|
35
34
|
ciocore/docsite/apidoc/package_environment/index.html,sha256=V6_ah3V1_4_aOwJbEcITCdwuHxe1vGtfn0maRrbflUs,69248
|
|
36
|
-
ciocore/docsite/apidoc/package_tree/index.html,sha256=
|
|
35
|
+
ciocore/docsite/apidoc/package_tree/index.html,sha256=5_4vV8x_GmpsyWHnMP62gBaAcdzfM7L-mP7uQKh_DH4,109054
|
|
37
36
|
ciocore/docsite/assets/_mkdocstrings.css,sha256=K3bqYEmxlOHQ3-M11JNbBWHCBDBLarkFRm8HuEYrAG4,341
|
|
38
37
|
ciocore/docsite/assets/images/favicon.png,sha256=AjhUxD_Eslt5XuSVHIAZ494Fk__rb5GLXR8qm0elfP4,1870
|
|
39
38
|
ciocore/docsite/assets/javascripts/bundle.4e31edb1.min.js,sha256=vMxCR_BtNIcbmbPV6j8Z-YDLQ9ckt4RzvGuzCTg034s,97250
|
|
@@ -81,7 +80,7 @@ ciocore/docsite/cmdline/downloader/index.html,sha256=nygj-0GQmpD79B5AxHjwzQxOFv8
|
|
|
81
80
|
ciocore/docsite/cmdline/packages/index.html,sha256=_kXB85PBAgrqW09OerYpxnJuyERHMbcLn6qBGRdyHwk,20923
|
|
82
81
|
ciocore/docsite/cmdline/uploader/index.html,sha256=vuQ06Gys9Eoxs87PXlqnM5AgB6Ag00BlDIy6oaprjis,25123
|
|
83
82
|
ciocore/docsite/how-to-guides/index.html,sha256=KifCHl2S3RfPBZhP1UXwUNWuhcXPlPPqM4Gk6rVGhjQ,20100
|
|
84
|
-
ciocore/docsite/search/search_index.json,sha256=
|
|
83
|
+
ciocore/docsite/search/search_index.json,sha256=LP1ck_wuTP9A_dWTyaVF8Fugg22q1O0XS6hGqg2zk0M,189860
|
|
85
84
|
ciocore/docsite/stylesheets/extra.css,sha256=_Cxe9Dhg1BBi6Kqaz_iZD9z9VyqxA9vtONRjP4PVic0,354
|
|
86
85
|
ciocore/docsite/stylesheets/tables.css,sha256=LE_zwGRxGcdPIy-9QiVPecOzlEBSqZb_WP5vDkFE0ZM,3235
|
|
87
86
|
ciocore/downloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -95,21 +94,19 @@ ciocore/downloader/perpetual_downloader.py,sha256=cD7lnBH75-c-ZVVPHZc1vSnDhgJOnG
|
|
|
95
94
|
ciocore/downloader/registry.py,sha256=_JIOuqpWkJkgJGN33nt-DCvqN9Gw3xeFhzPq4RUxIoE,2903
|
|
96
95
|
ciocore/downloader/reporter.py,sha256=p1NK9k6iQ-jt7lRvZR0xFz0cGb2yo8tQcjlvYKR9SWM,4501
|
|
97
96
|
ciocore/uploader/__init__.py,sha256=hxRFJf5Lo86rtRObFXSjjot8nybQd-SebSfYCbgZwow,24
|
|
98
|
-
ciocore/uploader/_uploader.py,sha256=
|
|
97
|
+
ciocore/uploader/_uploader.py,sha256=Kt4toITJHZDMjRLqRyw_lwe_HOoWz2AigMp2k5heHBI,42291
|
|
99
98
|
ciocore/uploader/thread_queue_job.py,sha256=MzOcetttfWtDfwy-M0_ARwUf8_OjaGjyy-dA_WgNTPE,3416
|
|
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
|
|
103
|
-
tests/extra_env_fixtures.py,sha256=8qvU4d8SXGKzRVNR5whVqKCQOwOVMiFVfbKBAjxa2gE,1119
|
|
104
102
|
tests/instance_type_fixtures.py,sha256=uIzQduqKQVgjllMuyXaYnRC-pwqk5lnTx3NY2M5Nujo,4320
|
|
105
103
|
tests/package_fixtures.py,sha256=od7ZHofG8ubpQ3PqlUsrcHBcbmD3qVWih9eiIg1WtSQ,5361
|
|
106
|
-
tests/
|
|
107
|
-
tests/test_api_client.py,sha256=4jhj-YrBPcLj7XZn3ngguau2DPxpCYGMSuqPJ3hW0GQ,14497
|
|
104
|
+
tests/test_api_client.py,sha256=isntMDs3QTyTWdghBa_LbFAiC7ydZD1RWb655oEZo24,14452
|
|
108
105
|
tests/test_base_downloader.py,sha256=SS7tWKv2ZZhpUDk4UCg1TkrNrpntjSewgzLl1mEubSE,3603
|
|
109
106
|
tests/test_cli.py,sha256=_WTs2SWlEgd6wtg1hmOBlFnbWVdFLvqp0KqNhy-y2e8,5532
|
|
110
|
-
tests/test_common.py,sha256=
|
|
111
|
-
tests/test_config.py,sha256
|
|
112
|
-
tests/test_data.py,sha256=
|
|
107
|
+
tests/test_common.py,sha256=5N9xeeGVuwN4kcjIg30eBliUD8PePzCNNLuLipGuTgk,410
|
|
108
|
+
tests/test_config.py,sha256=iiMPwoVA9C3vvGGR6_gKKMbYkSxheNLdljeOA-iPrJU,13295
|
|
109
|
+
tests/test_data.py,sha256=o320GdvOJ2TouWtuA8jcs8Cr_gQWlQ6KxWVSWtmARlY,7614
|
|
113
110
|
tests/test_downloader.py,sha256=hceljsjnuvk5Vk5X4mHgavIEcpbv8ylPwpz7rTwJ-aE,4721
|
|
114
111
|
tests/test_hardware_set.py,sha256=hW7A_suyYdU7WkB7qoHSBPLxaAP2CKqI0i_ULfO5GeY,4408
|
|
115
112
|
tests/test_imports_2and3.py,sha256=ehqpRYPVY7djBcb8OT_cnh86iCJJ9wuMWnfSR9RHxmY,507
|
|
@@ -117,13 +114,13 @@ tests/test_job_downloader.py,sha256=_dZqyLZhc2Bq2n7-skERfodHx1JgFyHw8TamHp6ID9I,
|
|
|
117
114
|
tests/test_package_environment.py,sha256=CdiC2PDVSnbcwTb4fsDTWqGYSzs1n5ca2KMoyISckGA,5893
|
|
118
115
|
tests/test_package_query.py,sha256=LZqvCrGkWs0lMtIMumjDatX0ypeYYvabh_k1R0A6sS0,1451
|
|
119
116
|
tests/test_package_tree.py,sha256=K2kzJwRHCr6ojc4MZHjdH7VtmvG5O97OoH6vzwAE9GQ,6780
|
|
120
|
-
tests/test_submit.py,sha256=
|
|
121
|
-
tests/test_uploader.py,sha256=
|
|
117
|
+
tests/test_submit.py,sha256=v75ciL-C0XjiO7wUFQvYBZj0UoqhYOmTLa8TiUyhKqw,5769
|
|
118
|
+
tests/test_uploader.py,sha256=JGp6GEyqRXRtbQSb-IW-cCX_BzNotWdCbnJnLwZvpUM,2869
|
|
122
119
|
tests/test_validator.py,sha256=2fY66ayNc08PGyj2vTI-V_1yeCWJDngkj2zkUM5TTCI,1526
|
|
123
120
|
tests/mocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
124
121
|
tests/mocks/glob.py,sha256=J2MH7nqi6NJOHuGdVWxhfeBd700_Ckj6cLh_8jSNkfg,215
|
|
125
|
-
ciocore-9.1.
|
|
126
|
-
ciocore-9.1.
|
|
127
|
-
ciocore-9.1.
|
|
128
|
-
ciocore-9.1.
|
|
129
|
-
ciocore-9.1.
|
|
122
|
+
ciocore-9.1.0rc1.dist-info/METADATA,sha256=R_i2XrMj2RbhWLQrczzrbq71Ufz_3Q37WY3d0qIe2m8,19201
|
|
123
|
+
ciocore-9.1.0rc1.dist-info/WHEEL,sha256=qUzzGenXXuJTzyjFah76kDVqDvnk-YDzY00svnrl84w,109
|
|
124
|
+
ciocore-9.1.0rc1.dist-info/entry_points.txt,sha256=cCqcALMYbC4d8545V9w0Zysfg9MVuKWhzDQ2er4UfGE,47
|
|
125
|
+
ciocore-9.1.0rc1.dist-info/top_level.txt,sha256=SvlM5JlqULzAz00JZWfiUhfjhqDzYzSWssA87zdJl0o,14
|
|
126
|
+
ciocore-9.1.0rc1.dist-info/RECORD,,
|
tests/test_api_client.py
CHANGED
tests/test_common.py
CHANGED
|
@@ -9,17 +9,7 @@ FILES_PATH = os.path.join(os.path.dirname(__file__), "files")
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class TestMd5(unittest.TestCase):
|
|
12
|
-
|
|
13
|
-
# def test_get_base64_md5_is_correct_md5(self):
|
|
14
|
-
# from ciocore import common
|
|
15
|
-
# fn1 = os.path.join(FILES_PATH, "one")
|
|
16
|
-
# md5=common.get_base64_md5(fn1)
|
|
17
|
-
# if os.name == "nt":
|
|
18
|
-
# self.assertEqual(md5, "w8F8opHbdwHIozghPc63XA==")
|
|
19
|
-
# else:
|
|
20
|
-
# self.assertEqual(md5, "9iVbsBxkj+lncU1SqJ6OnA==")
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
|
|
23
13
|
def test_get_base64_md5_is_correct_type(self):
|
|
24
14
|
from ciocore import common
|
|
25
15
|
from builtins import str
|
tests/test_config.py
CHANGED
|
@@ -6,10 +6,7 @@ import sys
|
|
|
6
6
|
import os
|
|
7
7
|
import logging
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
from unittest import mock
|
|
11
|
-
except ImportError:
|
|
12
|
-
import mock
|
|
9
|
+
from unittest import mock
|
|
13
10
|
|
|
14
11
|
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"}'
|
|
15
12
|
|