ciocore 9.1.0b2__py2.py3-none-any.whl → 9.1.0rc2__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:
@@ -2,7 +2,6 @@ import datetime
2
2
  import json
3
3
  import logging
4
4
  import os
5
- import pathlib
6
5
  import requests.exceptions
7
6
  import sys
8
7
  import time
@@ -26,12 +25,13 @@ from ciocore import (
26
25
  exceptions,
27
26
  )
28
27
 
29
- from . import thread_queue_job
30
-
31
28
  from .upload_stats import UploadStats
32
29
 
33
30
  logger = logging.getLogger("{}.uploader".format(loggeria.CONDUCTOR_LOGGER_NAME))
34
31
 
32
+ SINGLEPART = "singlepart"
33
+ MULTIPART = "multipart"
34
+
35
35
 
36
36
  class MD5Worker(worker.ThreadWorker):
37
37
  """
@@ -329,61 +329,28 @@ class FileStatWorker(worker.ThreadWorker):
329
329
  """
330
330
 
331
331
  if job:
332
-
333
- kms_key_name = job.get('kmsKeyName')
334
-
335
332
  # iterate through singlepart urls
336
333
  for singlepart_upload in job.get("singlePartURLs", []):
337
334
  path = singlepart_upload["filePath"]
338
335
  file_size = singlepart_upload["fileSize"]
339
336
  upload_url = singlepart_upload["preSignedURL"]
340
- md5 = self.metric_store.get_dict("file_md5s", path)
341
337
 
342
338
  self.metric_store.increment("bytes_to_upload", file_size, path)
343
339
  self.metric_store.increment("num_files_to_upload")
344
340
  logger.debug("Singlepart, adding task %s", path)
345
341
 
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)
342
+ self.put_job((path, file_size, upload_url, SINGLEPART))
356
343
 
357
344
  # iterate through multipart
358
345
  for multipart_upload in job.get("multiPartURLs", []):
359
346
  path = multipart_upload["filePath"]
360
347
  file_size = multipart_upload["fileSize"]
361
348
 
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
-
384
349
  self.metric_store.increment("bytes_to_upload", file_size, path)
385
350
  self.metric_store.increment("num_files_to_upload")
386
-
351
+ logger.debug("Multipart, adding task %s", path)
352
+ self.put_job((path, file_size, multipart_upload, MULTIPART))
353
+
387
354
  # make sure we return None, so no message is automatically added to the out_queue
388
355
  return None
389
356
 
@@ -415,30 +382,45 @@ class UploadWorker(worker.ThreadWorker):
415
382
  self.metric_store.increment("bytes_uploaded", len(data), filename)
416
383
 
417
384
  def do_work(self, job, thread_int):
418
-
419
385
  if job:
420
-
421
- md5 = self.metric_store.get_dict("file_md5s", job.path)
386
+ kms_key_name = None
422
387
 
423
388
  try:
424
- if job.is_multipart():
425
- return self.do_multipart_upload(job)
426
-
427
- else:
428
- return self.do_singlepart_upload(job)
389
+ filename = job[0]
390
+ file_size = job[1]
391
+ upload = job[2]
392
+ upload_type = job[3]
429
393
 
430
- except Exception as err_msg:
431
- real_md5 = common.get_base64_md5(job.path)
394
+ except Exception:
395
+ logger.error("Issue with job (%s): %s", len(job), job)
396
+ raise
397
+
398
+ if len(job) > 4:
399
+ kms_key_name = job[4]
400
+
401
+ md5 = self.metric_store.get_dict("file_md5s", filename)
402
+
403
+ try:
404
+ if upload_type == SINGLEPART:
405
+ return self.do_singlepart_upload(
406
+ upload, filename, file_size, md5, kms_key_name
407
+ )
408
+ elif upload_type == MULTIPART:
409
+ return self.do_multipart_upload(upload, filename, md5)
432
410
 
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
411
+ raise Exception(
412
+ "upload_type is '%s' expected %s or %s"
413
+ % (upload_type, SINGLEPART, MULTIPART)
414
+ )
415
+
416
+ except Exception as err_msg:
417
+ real_md5 = common.get_base64_md5(filename)
436
418
 
437
419
  if isinstance(err_msg, requests.exceptions.HTTPError):
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}')"
420
+ 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}')"
439
421
  else:
440
422
  error_message = (
441
- f"Upload of {job.path} failed. (expected '{job.file_md5}', got '{real_md5}') {str(err_msg)} [{exception_file}-{exception_line_num}]"
423
+ f"Upload of {filename} failed. (expected '{md5}', got '{real_md5}') {str(err_msg)}"
442
424
  )
443
425
 
444
426
  logger.error(error_message)
@@ -447,7 +429,9 @@ class UploadWorker(worker.ThreadWorker):
447
429
  return worker.EMPTY_JOB
448
430
 
449
431
  @common.DecRetry(retry_exceptions=api_client.CONNECTION_EXCEPTIONS, tries=5)
450
- def do_singlepart_upload(self, job):
432
+ def do_singlepart_upload(
433
+ self, upload_url, filename, file_size, md5, kms_key_name=None
434
+ ):
451
435
  """
452
436
  Note that for GCS we don't rely on the make_request's own retry mechanism because we need to
453
437
  recreate the chunked_reader generator before retrying the request. Instead, we wrap this
@@ -457,23 +441,19 @@ class UploadWorker(worker.ThreadWorker):
457
441
  headers that S3 does not accept.
458
442
  """
459
443
 
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():
444
+ if ("amazonaws" in upload_url) or ("coreweave" in upload_url):
465
445
  # must declare content-length ourselves due to zero byte bug in requests library.
466
446
  # api_client.make_prepared_request docstring.
467
447
  headers = {
468
448
  "Content-Type": "application/octet-stream",
469
- "Content-Length": str(job.file_size),
449
+ "Content-Length": str(file_size),
470
450
  }
471
451
 
472
- with open(job.path, "rb") as fh:
452
+ with open(filename, "rb") as fh:
473
453
  # TODO: support chunked
474
454
  response = self.api_client.make_prepared_request(
475
455
  verb="PUT",
476
- url=job.presigned_url,
456
+ url=upload_url,
477
457
  headers=headers,
478
458
  params=None,
479
459
  data=fh,
@@ -487,26 +467,25 @@ class UploadWorker(worker.ThreadWorker):
487
467
  response.close()
488
468
 
489
469
  # report upload progress
490
- self.metric_store.increment("bytes_uploaded", job.file_size, job.path)
491
-
470
+ self.metric_store.increment("bytes_uploaded", file_size, filename)
471
+
472
+ return response
492
473
  else:
493
474
  headers = {"Content-MD5": md5, "Content-Type": "application/octet-stream"}
494
475
 
495
- if job.kms_key_name is not None:
496
- headers["x-goog-encryption-kms-key-name"] = job.kms_key_name
476
+ if kms_key_name:
477
+ headers["x-goog-encryption-kms-key-name"] = kms_key_name
497
478
 
498
- self.api_client.make_request(
499
- conductor_url=job.presigned_url,
479
+ return self.api_client.make_request(
480
+ conductor_url=upload_url,
500
481
  headers=headers,
501
- data=self.chunked_reader(job.path),
482
+ data=self.chunked_reader(filename),
502
483
  verb="PUT",
503
484
  tries=1,
504
485
  use_api_key=True,
505
486
  )
506
-
507
- return tq_job
508
487
 
509
- def do_multipart_upload(self, job):
488
+ def do_multipart_upload(self, upload, filename, md5):
510
489
  """
511
490
  Files will be split into partSize returned by the FileAPI and hydrated once all parts are
512
491
  uploaded. On successful part upload, response headers will contain an ETag. This value must
@@ -514,32 +493,42 @@ class UploadWorker(worker.ThreadWorker):
514
493
  """
515
494
  uploads = []
516
495
  complete_payload = {
517
- "uploadID": job.upload_id,
518
- "hash": job.file_md5,
496
+ "uploadID": upload["uploadID"],
497
+ "hash": md5,
519
498
  "completedParts": [],
520
499
  "project": self.project,
521
500
  }
522
501
 
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
502
+ # iterate over parts and upload
503
+ for part in upload["parts"]:
504
+ resp_headers = self._do_multipart_upload(
505
+ upload_url=part["url"],
506
+ filename=filename,
507
+ part_number=part["partNumber"],
508
+ part_size=upload["partSize"],
509
+ )
529
510
 
511
+ if resp_headers:
512
+ uploads.append(upload["uploadID"])
513
+ completed_part = {
514
+ "partNumber": part["partNumber"],
515
+ "etag": resp_headers["ETag"].strip('"'),
516
+ }
517
+ complete_payload["completedParts"].append(completed_part)
530
518
 
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,
519
+ # Complete multipart upload in order to hydrate file for availability
520
+ uri_path = "/api/v2/files/multipart/complete"
521
+ headers = {"Content-Type": "application/json"}
522
+ self.api_client.make_request(
523
+ uri_path=uri_path,
524
+ verb="POST",
525
+ headers=headers,
526
+ data=json.dumps(complete_payload),
527
+ raise_on_error=True,
528
+ use_api_key=True,
536
529
  )
537
530
 
538
- if resp_headers:
539
- tq_job.part = job.part_index
540
- tq_job.etag = resp_headers["ETag"].strip('"')
541
-
542
- return tq_job
531
+ return uploads
543
532
 
544
533
  @common.DecRetry(retry_exceptions=api_client.CONNECTION_EXCEPTIONS, tries=5)
545
534
  def _do_multipart_upload(self, upload_url, filename, part_number, part_size):
@@ -574,73 +563,6 @@ class UploadWorker(worker.ThreadWorker):
574
563
 
575
564
  return response.headers
576
565
 
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
-
644
566
  def is_complete(self):
645
567
  # Get the number of files already uploaded as they are not passed to the Upload
646
568
  # worker
@@ -658,11 +580,11 @@ class MultiPartSiphonWorker(worker.ThreadWorker):
658
580
  self.task_count,
659
581
  )
660
582
 
661
- return (queue_size) >= self.task_count
583
+ return (queue_size + already_completed_uploads) >= self.task_count
662
584
 
663
585
  else:
664
586
  logger.debug("Is complete?: files not initialized yet")
665
- return False
587
+ return False
666
588
 
667
589
 
668
590
  class Uploader(object):
@@ -716,7 +638,6 @@ class Uploader(object):
716
638
  ),
717
639
  (FileStatWorker, [], {"thread_count": 1}),
718
640
  (UploadWorker, [], {"thread_count": self.args["thread_count"]}),
719
- (MultiPartSiphonWorker, [], {"thread_count": 1})
720
641
  ]
721
642
 
722
643
  manager = worker.JobManager(job_description)
@@ -839,31 +760,6 @@ class Uploader(object):
839
760
  file_map = {path: None for path in processed_filepaths}
840
761
  self.handle_upload_response(project=None, upload_files=file_map)
841
762
 
842
- if common.SIGINT_EXIT or self.cancel:
843
- print("\nUpload cancelled\n")
844
-
845
- else:
846
- print("\nUpload of {} file completed\n".format(len(file_map)))
847
-
848
- error_messages = []
849
-
850
- for exception in self.error_messages:
851
- error_messages.append(str(exception[1]))
852
- print("".join(traceback.format_tb(exception[2])))
853
- logger.error("".join(traceback.format_tb(exception[2])))
854
-
855
- if error_messages:
856
-
857
- log_file = loggeria.LOG_PATH
858
- sys.stderr.write("\nError uploading files:\n")
859
-
860
- for err_msg in error_messages:
861
- sys.stderr.write("\t{}\n".format(err_msg))
862
-
863
- sys.stderr.write("\nSee log {} for more details\n\n".format(log_file))
864
-
865
- self.error_messages = []
866
-
867
763
  def handle_upload_response(self, project, upload_files, upload_id=None):
868
764
  """
869
765
  This is a really confusing method and should probably be split into to clear logic
@@ -922,7 +818,8 @@ class Uploader(object):
922
818
  time.sleep(5)
923
819
 
924
820
  # Shutdown the manager once all jobs are done
925
- if not (self.cancel or self.manager.error or common.SIGINT_EXIT):
821
+ if not self.cancel and not self.manager.error:
822
+ logger.debug("Waiting for Manager to join")
926
823
  self.manager.join()
927
824
 
928
825
  upload_stats = UploadStats.create(
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.0b2
3
+ Version: 9.1.0rc2
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,11 +50,14 @@ See [CONTRIBUTING](CONTRIBUTING.md)
51
50
 
52
51
  ## Changelog
53
52
 
54
- ## Unreleased:
55
- * Adds required changes to parallelize multi-part uploads
56
- * Cleans up the output when explicit paths are uploaded
57
- * Fixes logic so managers doesn't erroneously try and call join a second time if cancelled
53
+ ## Version:9.1.0-rc.2 -- 12 Dec 2024
58
54
 
55
+ * Use the new required jwt parameters
56
+ * Removing py2.7 compatibility
57
+
58
+ ## Version:8.3.3 -- 04 Dec 2024
59
+
60
+ * Adds filter option for API data query
59
61
 
60
62
  ## Version:8.3.2 -- 01 Oct 2024
61
63
 
@@ -1,24 +1,23 @@
1
- ciocore/VERSION,sha256=V-Kb1TSOiqU51Ac0b71EzlP2Ib7nl3rdmaEL7bhM4iY,12
1
+ ciocore/VERSION,sha256=rK2e-XPKebjaWLwloD4dWey9U5CMdVkZh1nVx-IOI3s,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,18 @@ 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=Kt4toITJHZDMjRLqRyw_lwe_HOoWz2AigMp2k5heHBI,42291
99
- ciocore/uploader/thread_queue_job.py,sha256=MzOcetttfWtDfwy-M0_ARwUf8_OjaGjyy-dA_WgNTPE,3416
97
+ ciocore/uploader/_uploader.py,sha256=40nzqO5DuFi4sx31VvjWxZPNkrWsWqM9jtFVxs_-o3o,37479
100
98
  ciocore/uploader/upload_stats/__init__.py,sha256=Lg1y4zq1i0cwc6Hh2K1TAQDYymLff49W-uIo1xjcvdI,5309
101
99
  ciocore/uploader/upload_stats/stats_formats.py,sha256=giNirtObU66VALWghPFSRhg3q_vw5MvESsnXhb_I3y8,2402
102
100
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
103
- tests/extra_env_fixtures.py,sha256=8qvU4d8SXGKzRVNR5whVqKCQOwOVMiFVfbKBAjxa2gE,1119
104
101
  tests/instance_type_fixtures.py,sha256=uIzQduqKQVgjllMuyXaYnRC-pwqk5lnTx3NY2M5Nujo,4320
105
102
  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
103
+ tests/test_api_client.py,sha256=isntMDs3QTyTWdghBa_LbFAiC7ydZD1RWb655oEZo24,14452
108
104
  tests/test_base_downloader.py,sha256=SS7tWKv2ZZhpUDk4UCg1TkrNrpntjSewgzLl1mEubSE,3603
109
105
  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
106
+ tests/test_common.py,sha256=5N9xeeGVuwN4kcjIg30eBliUD8PePzCNNLuLipGuTgk,410
107
+ tests/test_config.py,sha256=iiMPwoVA9C3vvGGR6_gKKMbYkSxheNLdljeOA-iPrJU,13295
108
+ tests/test_data.py,sha256=o320GdvOJ2TouWtuA8jcs8Cr_gQWlQ6KxWVSWtmARlY,7614
113
109
  tests/test_downloader.py,sha256=hceljsjnuvk5Vk5X4mHgavIEcpbv8ylPwpz7rTwJ-aE,4721
114
110
  tests/test_hardware_set.py,sha256=hW7A_suyYdU7WkB7qoHSBPLxaAP2CKqI0i_ULfO5GeY,4408
115
111
  tests/test_imports_2and3.py,sha256=ehqpRYPVY7djBcb8OT_cnh86iCJJ9wuMWnfSR9RHxmY,507
@@ -117,13 +113,13 @@ tests/test_job_downloader.py,sha256=_dZqyLZhc2Bq2n7-skERfodHx1JgFyHw8TamHp6ID9I,
117
113
  tests/test_package_environment.py,sha256=CdiC2PDVSnbcwTb4fsDTWqGYSzs1n5ca2KMoyISckGA,5893
118
114
  tests/test_package_query.py,sha256=LZqvCrGkWs0lMtIMumjDatX0ypeYYvabh_k1R0A6sS0,1451
119
115
  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
116
+ tests/test_submit.py,sha256=v75ciL-C0XjiO7wUFQvYBZj0UoqhYOmTLa8TiUyhKqw,5769
117
+ tests/test_uploader.py,sha256=JGp6GEyqRXRtbQSb-IW-cCX_BzNotWdCbnJnLwZvpUM,2869
122
118
  tests/test_validator.py,sha256=2fY66ayNc08PGyj2vTI-V_1yeCWJDngkj2zkUM5TTCI,1526
123
119
  tests/mocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
124
120
  tests/mocks/glob.py,sha256=J2MH7nqi6NJOHuGdVWxhfeBd700_Ckj6cLh_8jSNkfg,215
125
- ciocore-9.1.0b2.dist-info/METADATA,sha256=g67y_5StIUtJ3HXVWUsECxrGN5X6LrT8NU96amgI_fg,19085
126
- ciocore-9.1.0b2.dist-info/WHEEL,sha256=qUzzGenXXuJTzyjFah76kDVqDvnk-YDzY00svnrl84w,109
127
- ciocore-9.1.0b2.dist-info/entry_points.txt,sha256=cCqcALMYbC4d8545V9w0Zysfg9MVuKWhzDQ2er4UfGE,47
128
- ciocore-9.1.0b2.dist-info/top_level.txt,sha256=SvlM5JlqULzAz00JZWfiUhfjhqDzYzSWssA87zdJl0o,14
129
- ciocore-9.1.0b2.dist-info/RECORD,,
121
+ ciocore-9.1.0rc2.dist-info/METADATA,sha256=5ckG7OoC_iQTAE6keOl-Sc3GgfEihq4xc-2BvA10ZnU,18999
122
+ ciocore-9.1.0rc2.dist-info/WHEEL,sha256=qUzzGenXXuJTzyjFah76kDVqDvnk-YDzY00svnrl84w,109
123
+ ciocore-9.1.0rc2.dist-info/entry_points.txt,sha256=cCqcALMYbC4d8545V9w0Zysfg9MVuKWhzDQ2er4UfGE,47
124
+ ciocore-9.1.0rc2.dist-info/top_level.txt,sha256=SvlM5JlqULzAz00JZWfiUhfjhqDzYzSWssA87zdJl0o,14
125
+ ciocore-9.1.0rc2.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