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.

Binary file
ciocore/package_tree.py CHANGED
@@ -290,10 +290,6 @@ class PackageTree(object):
290
290
  def __bool__(self):
291
291
  return True if self._tree["children"] else False
292
292
 
293
- def __nonzero__(self):
294
- # Python 2.7
295
- return self.__bool__()
296
-
297
293
  def as_dict(self):
298
294
  """
299
295
  Returns:
@@ -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
- self.put_job((path, file_size, upload_url, SINGLEPART))
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
- logger.debug("Multipart, adding task %s", path)
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
- kms_key_name = None
420
+
421
+ md5 = self.metric_store.get_dict("file_md5s", job.path)
388
422
 
389
423
  try:
390
- filename = job[0]
391
- file_size = job[1]
392
- upload = job[2]
393
- upload_type = job[3]
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(filename)
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 {filename} failed with a response code {err_msg.response.status_code} ({err_msg.response.reason}) (expected '{md5}', got '{real_md5}')"
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 {filename} failed. (expected '{md5}', got '{real_md5}') {str(err_msg)}"
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
- if ("amazonaws" in upload_url) or ("coreweave" in upload_url):
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(filename, "rb") as fh:
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=upload_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, filename)
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
- return self.api_client.make_request(
481
- conductor_url=upload_url,
498
+ self.api_client.make_request(
499
+ conductor_url=job.presigned_url,
482
500
  headers=headers,
483
- data=self.chunked_reader(filename),
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, upload, filename, md5):
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": upload["uploadID"],
498
- "hash": md5,
517
+ "uploadID": job.upload_id,
518
+ "hash": job.file_md5,
499
519
  "completedParts": [],
500
520
  "project": self.project,
501
521
  }
502
522
 
503
- # iterate over parts and upload
504
- for part in upload["parts"]:
505
- resp_headers = self._do_multipart_upload(
506
- upload_url=part["url"],
507
- filename=filename,
508
- part_number=part["partNumber"],
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
- # Complete multipart upload in order to hydrate file for availability
521
- uri_path = "/api/v2/files/multipart/complete"
522
- headers = {"Content-Type": "application/json"}
523
- self.api_client.make_request(
524
- uri_path=uri_path,
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
- return uploads
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 + already_completed_uploads) >= self.task_count
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
- # thread.isAlive() was renamed to is_alive() in Python 3.9
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.0b1
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[use_chardet_on_py3]==2.28.1
13
- Requires-Dist: pyjwt==1.7.1
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
- ## Unreleased:
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=TCUlj36m9-VV6atKK8EETx-2I8BQY_6CSKTVDGTHeqo,12
1
+ ciocore/VERSION,sha256=ax2aQwModu65ZstFnKm4dTChIjzu_0ljZcaKGDaGkSA,10
2
2
  ciocore/__init__.py,sha256=aTP7LeeosQA8BZE67gDV4jgfTK5zxmwZRjiTRu_ZWj0,646
3
- ciocore/api_client.py,sha256=SBxEwAiwn2XtH7T_ipefUbWhczXjoNdNbQBur1RV-Bw,32810
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=Ji0qUk8nJXBNakoHSqBiVx8O58SbZXyt273SHlEDn3U,7027
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=vkORKXxQ7dO8l0_96eFwm-5AUVL0rP9bhgWYhW_v3lo,15649
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=YnE0mGqkky9uxPMyDRmvdt1p1ER_GN39AeZPIGw6f4U,21832
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=mThGdpcFPBqhVOOM7T3lZOZMuSVSoDrSjqxs4psAmeY,127
30
- ciocore/docsite/apidoc/api_client/index.html,sha256=TvoSl4iqdXhBVfesDxe_sBPA6G-Jt1-gpWA40xXspa0,188372
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=vjC5u7wcm2ryOW28GctA9ZG6dXgBTkMJLLomJ9Kqxo0,50850
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=60Ir6X1Q9k17bQCqozXzuMAcSVuu6DuC5zGfBk4LLnw,109393
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=vBLU-rkC0pxOPX0O3MNKXRKGfgsaS1-91KsV17Gf9SY,189092
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=Xz1sos76FK-BKsgPuErlKQ8HsCAtBKp3pLbCtRVrr9E,38250
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/project_fixtures.py,sha256=iBm_th_JtAw76vlNu7Jjhh9tLH4oOaNi-MgtPzCV7yQ,138
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=tY_-SY-JmJX09UehFs9RIDqZ785AmhfTl6eVKJeIUFY,763
111
- tests/test_config.py,sha256=-_G682Ss3Zr1FmcMkjla1zAZprX2tQKpKc5_wD28rII,13340
112
- tests/test_data.py,sha256=NIBXpCjG3Os3vpc1CkiVONrebro8D_jqQyJ0N3kbucU,5433
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=ppijBcpLXeHUZh7UXyClxLalSV6cTfKb6Ygw5zXQPKo,5836
121
- tests/test_uploader.py,sha256=B1llTJt_fqR6e_V_Jxfw9z73QgkFlEPU87xLYGzt-TQ,2914
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.0b1.dist-info/METADATA,sha256=jd_61cbX9eiHy2SgX19hXCdf-gqvcvaOJP_gOwZVG-M,19085
126
- ciocore-9.1.0b1.dist-info/WHEEL,sha256=qUzzGenXXuJTzyjFah76kDVqDvnk-YDzY00svnrl84w,109
127
- ciocore-9.1.0b1.dist-info/entry_points.txt,sha256=cCqcALMYbC4d8545V9w0Zysfg9MVuKWhzDQ2er4UfGE,47
128
- ciocore-9.1.0b1.dist-info/top_level.txt,sha256=SvlM5JlqULzAz00JZWfiUhfjhqDzYzSWssA87zdJl0o,14
129
- ciocore-9.1.0b1.dist-info/RECORD,,
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
@@ -7,10 +7,7 @@ import json
7
7
  import sys
8
8
  import unittest
9
9
 
10
- try:
11
- from unittest import mock
12
- except ImportError:
13
- import mock
10
+ from unittest import mock
14
11
 
15
12
  from ciocore import api_client
16
13
 
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
- try:
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