dtlpy 1.95.6__py3-none-any.whl → 1.96.8__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.
dtlpy/__version__.py CHANGED
@@ -1 +1 @@
1
- version = '1.95.6'
1
+ version = '1.96.8'
dtlpy/entities/filters.py CHANGED
@@ -196,6 +196,8 @@ class Filters:
196
196
  """
197
197
  if method is None:
198
198
  method = self.method
199
+ if 'metadata.system.refs.metadata' in field and self.resource == FiltersResource.ITEM:
200
+ logger.warning('Filtering by metadata.system.refs.metadata may cause incorrect results. please use match operator')
199
201
 
200
202
  # create SingleFilter object and add to self.filter_list
201
203
  if method == FiltersMethod.OR:
dtlpy/entities/model.py CHANGED
@@ -388,13 +388,12 @@ class Model(entities.BaseEntity):
388
388
 
389
389
  @property
390
390
  def id_to_label_map(self):
391
+ # default
391
392
  if 'id_to_label_map' not in self.configuration:
392
- # default
393
- if self.ontology_id == 'null' or self.ontology_id is None:
394
- self.configuration['id_to_label_map'] = {int(idx): lbl for idx, lbl in enumerate(self.labels)}
395
- else:
396
- self.configuration['id_to_label_map'] = {int(idx): lbl.tag for idx, lbl in
397
- enumerate(self.ontology.labels)}
393
+ if not (self.dataset_id == 'null' or self.dataset_id is None):
394
+ self.labels = [label.tag for label in self.dataset.labels]
395
+ self.configuration['id_to_label_map'] = {int(idx): lbl for idx, lbl in enumerate(self.labels)}
396
+ # use existing
398
397
  else:
399
398
  self.configuration['id_to_label_map'] = {int(idx): lbl for idx, lbl in
400
399
  self.configuration['id_to_label_map'].items()}
dtlpy/entities/service.py CHANGED
@@ -567,14 +567,14 @@ class Service(entities.BaseEntity):
567
567
  """
568
568
  return self.services.update(service=self, force=force)
569
569
 
570
- def delete(self):
570
+ def delete(self, force: bool = False):
571
571
  """
572
572
  Delete Service object
573
573
 
574
574
  :return: True
575
575
  :rtype: bool
576
576
  """
577
- return self.services.delete(service_id=self.id)
577
+ return self.services.delete(service_id=self.id, force=force)
578
578
 
579
579
  def status(self):
580
580
  """
@@ -759,6 +759,32 @@ class Service(entities.BaseEntity):
759
759
  wait=wait)
760
760
  return execution
761
761
 
762
+ def rerun_batch(self,
763
+ filters,
764
+ wait=True
765
+ ):
766
+ """
767
+ rerun a executions on an existing service
768
+
769
+ **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a Filter.
770
+
771
+ :param filters: Filters entity for a filtering before rerun
772
+ :param bool wait: wait until create task finish
773
+ :return: rerun command
774
+ :rtype: dtlpy.entities.command.Command
775
+
776
+ **Example**:
777
+
778
+ .. code-block:: python
779
+
780
+ command = service.executions.rerun_batch(
781
+ filters=dl.Filters(field='id', values=['executionId'], operator=dl.FiltersOperations.IN, resource=dl.FiltersResource.EXECUTION))
782
+ """
783
+ execution = self.executions.rerun_batch(service_id=self.id,
784
+ filters=filters,
785
+ wait=wait)
786
+ return execution
787
+
762
788
  def activate_slots(
763
789
  self,
764
790
  project_id: str = None,
@@ -4,6 +4,9 @@ import logging
4
4
  import json
5
5
  import jwt
6
6
  import os
7
+ from PIL import Image
8
+ from io import BytesIO
9
+ import base64
7
10
 
8
11
  from .. import entities, exceptions, miscellaneous, _api_reference
9
12
  from ..services.api_client import ApiClient
@@ -487,12 +490,9 @@ class Annotations:
487
490
  status = True
488
491
  result = w_annotation
489
492
  else:
490
- url_path = '/annotations/{}'.format(annotation_id)
491
- if system_metadata:
492
- url_path += '?system=true'
493
- suc, response = self._client_api.gen_request(req_type='put',
494
- path=url_path,
495
- json_req=json_req)
493
+ suc, response = self._update_annotation_req(annotation_json=json_req,
494
+ system_metadata=system_metadata,
495
+ annotation_id=annotation_id)
496
496
  if suc:
497
497
  result = entities.Annotation.from_json(_json=response.json(),
498
498
  annotations=self,
@@ -507,6 +507,15 @@ class Annotations:
507
507
  result = traceback.format_exc()
508
508
  return status, result
509
509
 
510
+ def _update_annotation_req(self, annotation_json, system_metadata, annotation_id):
511
+ url_path = '/annotations/{}'.format(annotation_id)
512
+ if system_metadata:
513
+ url_path += '?system=true'
514
+ suc, response = self._client_api.gen_request(req_type='put',
515
+ path=url_path,
516
+ json_req=annotation_json)
517
+ return suc, response
518
+
510
519
  @_api_reference.add(path='/annotations/{annotationId}', method='put')
511
520
  def update(self, annotations, system_metadata=False):
512
521
  """
@@ -572,11 +581,12 @@ class Annotations:
572
581
  last_frame = frame
573
582
  return annotation
574
583
 
575
- def _create_batches_for_upload(self, annotations):
584
+ def _create_batches_for_upload(self, annotations, merge=False):
576
585
  """
577
586
  receives a list of annotations and split them into batches to optimize the upload
578
587
 
579
588
  :param annotations: list of all annotations
589
+ :param merge: bool - merge the new binary annotations with the existing annotations
580
590
  :return: batch_annotations: list of list of annotation. each batch with size self._upload_batch_size
581
591
  """
582
592
  annotation_batches = list()
@@ -601,8 +611,107 @@ class Annotations:
601
611
  single_batch = list()
602
612
  if len(single_batch) > 0:
603
613
  annotation_batches.append(single_batch)
614
+ if merge and self.item:
615
+ annotation_batches = self._merge_new_annotations(annotation_batches)
616
+ annotation_batches = self._merge_to_exits_annotations(annotation_batches)
604
617
  return annotation_batches
605
618
 
619
+ def _merge_binary_annotations(self, data_url1, data_url2, item_width, item_height):
620
+ # Decode base64 data
621
+ img_data1 = base64.b64decode(data_url1.split(",")[1])
622
+ img_data2 = base64.b64decode(data_url2.split(",")[1])
623
+
624
+ # Convert binary data to images
625
+ img1 = Image.open(BytesIO(img_data1))
626
+ img2 = Image.open(BytesIO(img_data2))
627
+
628
+ # Create a new image with the target item size
629
+ merged_img = Image.new('RGBA', (item_width, item_height))
630
+
631
+ # Paste both images on the new canvas at their original sizes and positions
632
+ # Adjust positioning logic if needed (assuming top-left corner for both images here)
633
+ merged_img.paste(img1, (0, 0), img1) # Use img1 as a mask to handle transparency
634
+ merged_img.paste(img2, (0, 0), img2) # Overlay img2 at the same position
635
+
636
+ # Save the merged image to a buffer
637
+ buffer = BytesIO()
638
+ merged_img.save(buffer, format="PNG")
639
+ merged_img_data = buffer.getvalue()
640
+
641
+ # Encode the merged image back to a base64 string
642
+ merged_data_url = "data:image/png;base64," + base64.b64encode(merged_img_data).decode()
643
+
644
+ return merged_data_url
645
+
646
+ def _merge_new_annotations(self, annotations_batch):
647
+ """
648
+ Merge the new binary annotations with the existing annotations
649
+ :param annotations_batch: list of list of annotation. each batch with size self._upload_batch_size
650
+ :return: merged_annotations_batch: list of list of annotation. each batch with size self._upload_batch_size
651
+ """
652
+ for annotations in annotations_batch:
653
+ for annotation in annotations:
654
+ if annotation['type'] == 'binary' and not annotation.get('clean', False):
655
+ to_merge = [a for a in annotations if
656
+ not a.get('clean', False) and a.get("metadata", {}).get('system', {}).get('objectId',
657
+ None) ==
658
+ annotation.get("metadata", {}).get('system', {}).get('objectId', None) and a['label'] ==
659
+ annotation['label']]
660
+ if len(to_merge) == 0:
661
+ # no annotation to merge with
662
+ continue
663
+ for a in to_merge:
664
+ if a['coordinates'] == annotation['coordinates']:
665
+ continue
666
+ merged_data_url = self._merge_binary_annotations(a['coordinates'], annotation['coordinates'],
667
+ self.item.width, self.item.height)
668
+ annotation['coordinates'] = merged_data_url
669
+ a['clean'] = True
670
+ return [[a for a in annotations if not a.get('clean', False)] for annotations in annotations_batch]
671
+
672
+ def _merge_to_exits_annotations(self, annotations_batch):
673
+ filters = entities.Filters(resource=entities.FiltersResource.ANNOTATION, field='type', values='binary')
674
+ filters.add(field='itemId', values=self.item.id, method=entities.FiltersMethod.AND)
675
+ exist_annotations = self.list(filters=filters).annotations or list()
676
+ to_delete = list()
677
+ for annotations in annotations_batch:
678
+ for ann in annotations:
679
+ if ann['type'] == 'binary':
680
+ to_merge = [a for a in exist_annotations if
681
+ a.object_id == ann.get("metadata", {}).get('system', {}).get('objectId',
682
+ None) and a.label == ann[
683
+ 'label']]
684
+ if len(to_merge) == 0:
685
+ # no annotation to merge with
686
+ continue
687
+ if to_merge[0].coordinates == ann['coordinates']:
688
+ # same annotation
689
+ continue
690
+ if len(to_merge) > 1:
691
+ raise exceptions.PlatformException('400', 'Multiple annotations with the same label')
692
+ # merge
693
+ exist_annotations.remove(to_merge[0])
694
+ merged_data_url = self._merge_binary_annotations(to_merge[0].coordinates, ann['coordinates'],
695
+ self.item.width, self.item.height)
696
+ json_ann = to_merge[0].to_json()
697
+ json_ann['coordinates'] = merged_data_url
698
+ suc, response = self._update_annotation_req(annotation_json=json_ann,
699
+ system_metadata=True,
700
+ annotation_id=to_merge[0].id)
701
+ if not suc:
702
+ raise exceptions.PlatformException(response)
703
+ if suc:
704
+ result = entities.Annotation.from_json(_json=response.json(),
705
+ annotations=self,
706
+ dataset=self._dataset,
707
+ item=self._item)
708
+ exist_annotations.append(result)
709
+ to_delete.append(ann)
710
+ if len(to_delete) > 0:
711
+ annotations_batch = [[a for a in annotations if a not in to_delete] for annotations in annotations_batch]
712
+
713
+ return annotations_batch
714
+
606
715
  def _upload_single_batch(self, annotation_batch):
607
716
  try:
608
717
  suc, response = self._client_api.gen_request(req_type='post',
@@ -650,14 +759,15 @@ class Annotations:
650
759
  logger.info('Annotation/s uploaded successfully. num: {}'.format(len(uploaded_annotations)))
651
760
  return uploaded_annotations
652
761
 
653
- async def _async_upload_annotations(self, annotations):
762
+ async def _async_upload_annotations(self, annotations, merge=False):
654
763
  """
655
764
  Async function to run from the uploader. will use asyncio to not break the async
656
- :param annotations:
765
+ :param annotations: list of all annotations
766
+ :param merge: bool - merge the new binary annotations with the existing annotations
657
767
  :return:
658
768
  """
659
769
  async with self._client_api.event_loop.semaphore('annotations.upload'):
660
- annotation_batch = self._create_batches_for_upload(annotations=annotations)
770
+ annotation_batch = self._create_batches_for_upload(annotations=annotations, merge=merge)
661
771
  output_annotations = list()
662
772
  for annotations_list in annotation_batch:
663
773
  success, response = await self._client_api.gen_async_request(req_type='post',
@@ -679,7 +789,7 @@ class Annotations:
679
789
  return result
680
790
 
681
791
  @_api_reference.add(path='/items/{itemId}/annotations', method='post')
682
- def upload(self, annotations) -> entities.AnnotationCollection:
792
+ def upload(self, annotations, merge=False) -> entities.AnnotationCollection:
683
793
  """
684
794
  Upload a new annotation/annotations. You must first create the annotation using the annotation *builder* method.
685
795
 
@@ -687,6 +797,7 @@ class Annotations:
687
797
 
688
798
  :param List[dtlpy.entities.annotation.Annotation] or dtlpy.entities.annotation.Annotation annotations: list or
689
799
  single annotation of type Annotation
800
+ :param bool merge: optional - merge the new binary annotations with the existing annotations
690
801
  :return: list of annotation objects
691
802
  :rtype: entities.AnnotationCollection
692
803
 
@@ -718,7 +829,7 @@ class Annotations:
718
829
  logger.warning('Annotation upload receives 0 annotations. Not doing anything')
719
830
  out_annotations = list()
720
831
  else:
721
- annotation_batches = self._create_batches_for_upload(annotations=annotations)
832
+ annotation_batches = self._create_batches_for_upload(annotations=annotations, merge=merge)
722
833
  out_annotations = self._upload_annotations_batches(annotation_batches=annotation_batches)
723
834
  out_annotations = entities.AnnotationCollection.from_json(_json=out_annotations,
724
835
  item=self.item)
@@ -1,6 +1,8 @@
1
1
  import threading
2
2
  import logging
3
3
  import time
4
+ from copy import deepcopy
5
+
4
6
  import numpy as np
5
7
 
6
8
  from .. import exceptions, entities, repositories, miscellaneous, _api_reference
@@ -351,6 +353,58 @@ class Executions:
351
353
  command = command.wait(timeout=0)
352
354
  return command
353
355
 
356
+ @_api_reference.add(path='/executions/rerun', method='post')
357
+ def rerun_batch(self,
358
+ filters,
359
+ service_id: str = None,
360
+ wait=True
361
+ ):
362
+ """
363
+ rerun a executions on an existing service
364
+
365
+ **Prerequisites**: You must be in the role of an *owner* or *developer*. You must have a Filter.
366
+
367
+ :param filters: Filters entity for a filtering before rerun
368
+ :param str service_id: service id to rerun on
369
+ :param bool wait: wait until create task finish
370
+ :return: rerun command
371
+ :rtype: dtlpy.entities.command.Command
372
+
373
+ **Example**:
374
+
375
+ .. code-block:: python
376
+
377
+ command = service.executions.rerun_batch(
378
+ filters=dl.Filters(field='id', values=['executionId'], operator=dl.FiltersOperations.IN, resource=dl.FiltersResource.EXECUTION))
379
+ """
380
+ url_path = '/executions/rerun'
381
+
382
+ if filters is None:
383
+ raise exceptions.PlatformException('400', 'Please provide filter')
384
+
385
+ if filters.resource != entities.FiltersResource.EXECUTION:
386
+ raise exceptions.PlatformException(
387
+ error='400',
388
+ message='Filters resource must to be FiltersResource.EXECUTION. Got: {!r}'.format(filters.resource))
389
+
390
+ if service_id is not None and not filters.has_field('serviceId'):
391
+ filters = deepcopy(filters)
392
+ filters.add(field='serviceId', values=service_id, method=entities.FiltersMethod.AND)
393
+
394
+ success, response = self._client_api.gen_request(req_type='post',
395
+ path=url_path,
396
+ json_req={'query': filters.prepare()['filter']})
397
+ # exception handling
398
+ if not success:
399
+ raise exceptions.PlatformException(response)
400
+
401
+ response_json = response.json()
402
+ command = entities.Command.from_json(_json=response_json,
403
+ client_api=self._client_api)
404
+ if wait:
405
+ command = command.wait(timeout=0)
406
+ return command
407
+
354
408
  def _list(self, filters: entities.Filters):
355
409
  """
356
410
  List service executions
@@ -638,11 +638,6 @@ class Items:
638
638
  item_metadata={'Hellow': 'Word'}
639
639
  )
640
640
  """
641
- # fix remote path
642
- if remote_path is not None:
643
- if not remote_path.startswith('/'):
644
- remote_path = '/' + remote_path
645
-
646
641
  # initiate and use uploader
647
642
  uploader = repositories.Uploader(items_repository=self, output_entity=output_entity, no_output=no_output)
648
643
  return uploader.upload(
@@ -642,10 +642,19 @@ class Tasks:
642
642
  if filters is None and items is None:
643
643
  query = entities.Filters().prepare()
644
644
  elif filters is None:
645
- if not isinstance(items, list):
646
- items = [items]
645
+ item_list = list()
646
+ if isinstance(items, entities.PagedEntities):
647
+ for page in items:
648
+ for item in page:
649
+ item_list.append(item)
650
+ elif isinstance(items, list):
651
+ item_list = items
652
+ elif isinstance(items, entities.Item):
653
+ item_list.append(items)
654
+ else:
655
+ raise exceptions.PlatformException('400', 'Unknown items type')
647
656
  query = entities.Filters(field='id',
648
- values=[item.id for item in items],
657
+ values=[item.id for item in item_list],
649
658
  operator=entities.FiltersOperations.IN,
650
659
  use_defaults=False).prepare()
651
660
  else:
@@ -133,11 +133,13 @@ class Uploader:
133
133
  item_metadata,
134
134
  export_version: str = entities.ExportVersion.V1,
135
135
  item_description=None):
136
-
136
+ # fix remote path
137
137
  if remote_path is None:
138
- remote_path = '/'
138
+ remote_path = "/"
139
+ if not remote_path.startswith('/'):
140
+ remote_path = f"/{remote_path}"
139
141
  if not remote_path.endswith("/"):
140
- remote_path += "/"
142
+ remote_path = f"{remote_path}/"
141
143
  if file_types is not None and not isinstance(file_types, list):
142
144
  msg = '"file_types" should be a list of file extension. e.g [".jpg", ".png"]'
143
145
  raise PlatformException(error="400", message=msg)
@@ -74,8 +74,6 @@ class PlatformError(Exception):
74
74
  super().__init__(msg)
75
75
 
76
76
 
77
-
78
-
79
77
  class Callbacks:
80
78
  def __init__(self):
81
79
  self._callbacks = {}
@@ -1172,7 +1170,12 @@ class ApiClient:
1172
1170
  def callback(bytes_read):
1173
1171
  pass
1174
1172
 
1175
- timeout = aiohttp.ClientTimeout(total=2 * 60)
1173
+ timeout = aiohttp.ClientTimeout(
1174
+ total=None, # Disable overall timeout
1175
+ connect=2 * 60, # Set connect timeout (in seconds)
1176
+ sock_read=10 * 60, # Set read timeout for socket read operations
1177
+ sock_connect=2 * 60 # Set timeout for connection setup
1178
+ )
1176
1179
  async with aiohttp.ClientSession(headers=headers, timeout=timeout) as session:
1177
1180
  try:
1178
1181
  form = aiohttp.FormData({})
@@ -1634,6 +1637,30 @@ class ApiClient:
1634
1637
  self._send_login_event(user_type='human', login_type='refresh')
1635
1638
  return res
1636
1639
 
1640
+ def generate_api_key(self, description: str = None, login: bool = False):
1641
+ """
1642
+ Generate an API key for a user
1643
+ :param description: description for the API key
1644
+ :param login: if True, login with the new API key
1645
+ :return: User token
1646
+ """
1647
+ user_email = self.info()['user_email']
1648
+ payload = {
1649
+ 'userId': user_email
1650
+ }
1651
+ if description:
1652
+ if not isinstance(description, str):
1653
+ raise ValueError('description should be a string')
1654
+ payload['description'] = description
1655
+ success, response = self.gen_request(req_type='post', path='/apiKeys', json_req=payload)
1656
+ if not success:
1657
+ raise exceptions.PlatformException(response)
1658
+ if login:
1659
+ self.login_api_key(response.json()['jwt'])
1660
+ return True
1661
+
1662
+ return response.json()['jwt']
1663
+
1637
1664
  def _renew_token_with_refresh_token(self):
1638
1665
  renewed = False
1639
1666
  if self.refresh_token_active is False:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dtlpy
3
- Version: 1.95.6
3
+ Version: 1.96.8
4
4
  Summary: SDK and CLI for Dataloop platform
5
5
  Home-page: https://github.com/dataloop-ai/dtlpy
6
6
  Author: Dataloop Team
@@ -1,5 +1,5 @@
1
1
  dtlpy/__init__.py,sha256=nE2SN0AD2rZ_ekF_kD7OzZbSE32H8zV5UM6t_E0LzTw,20647
2
- dtlpy/__version__.py,sha256=3OtkFGDOCL5-ZRo52dswwfcY5vYhh114MOzr2lJhEAA,19
2
+ dtlpy/__version__.py,sha256=8A7-aAEwSxpoFoUNMO139i-077CC5W2bPhNdC-ARCAI,19
3
3
  dtlpy/exceptions.py,sha256=EQCKs3pwhwZhgMByQN3D3LpWpdxwcKPEEt-bIaDwURM,2871
4
4
  dtlpy/new_instance.py,sha256=ORhXmIsc8Kut2M1jekKL3dG_adRp7axK-25B4zJNqMU,10091
5
5
  dtlpy/assets/__init__.py,sha256=D_hAa6NM8Zoy32sF_9b7m0b7I-BQEyBFg8-9Tg2WOeo,976
@@ -64,13 +64,13 @@ dtlpy/entities/driver.py,sha256=O_QdK1EaLjQyQkmvKsmkNgmvmMb1mPjKnJGxK43KrOA,7197
64
64
  dtlpy/entities/execution.py,sha256=WBiAws-6wZnQQ3y9wyvOeexA3OjxfaRdwDu5dSFYL1g,13420
65
65
  dtlpy/entities/feature.py,sha256=9fFjD0W57anOVSAVU55ypxN_WTCsWTG03Wkc3cAAj78,3732
66
66
  dtlpy/entities/feature_set.py,sha256=niw4MkmrDbD_LWQu1X30uE6U4DCzmFhPTaYeZ6VZDB0,4443
67
- dtlpy/entities/filters.py,sha256=tA-A0dS8nhMbnkHIo-INK6UuKzEPMyCdTs51K1-Vl9Y,22441
67
+ dtlpy/entities/filters.py,sha256=x0SZqhguQ7CWfBZPWmoTU7MrDLO6c8iN5a6gI_ar224,22664
68
68
  dtlpy/entities/integration.py,sha256=CA5F1eQCGE_4c_Kry4nWRdeyjHctNnvexcDXg_M5HLU,5734
69
69
  dtlpy/entities/item.py,sha256=G6VVcVCudqeShWigZmNIuKD4OkvTRJ05CeXFXNe3Jk8,29691
70
70
  dtlpy/entities/label.py,sha256=ycDYavIgKhz806plIX-64c07_TeHpDa-V7LnfFVe4Rg,3869
71
71
  dtlpy/entities/links.py,sha256=FAmEwHtsrqKet3c0UHH9u_gHgG6_OwF1-rl4xK7guME,2516
72
72
  dtlpy/entities/message.py,sha256=ApJuaKEqxATpXjNYUjGdYPu3ibQzEMo8-LtJ_4xAcPI,5865
73
- dtlpy/entities/model.py,sha256=LEot0PHOxPSeK9SCzAT6pofbLrbfybFYmr6v9YsiuB4,24927
73
+ dtlpy/entities/model.py,sha256=UKtai_V8ckTNPlhzflmJNHXJvH6BH9UYOwCMWXNZueU,24822
74
74
  dtlpy/entities/node.py,sha256=yPPYDLtNMc6vZbbf4FIffY86y7tkaTvYm42Jb7k3Ofk,39617
75
75
  dtlpy/entities/ontology.py,sha256=ok4p3sLBc_SS5hs2gZr5-gbblrveM7qSIX4z67QSKeQ,31967
76
76
  dtlpy/entities/organization.py,sha256=AMkx8hNIIIjnu5pYlNjckMRuKt6H3lnOAqtEynkr7wg,9893
@@ -87,7 +87,7 @@ dtlpy/entities/prompt_item.py,sha256=Kmvguz3f0sGtkKZS9OEA_-Yi4aQRCgdg1GBkaLQyyTg
87
87
  dtlpy/entities/recipe.py,sha256=Q1HtYgind3bEe-vnDZWhw6H-rcIAGhkGHPRWtLIkPSE,11917
88
88
  dtlpy/entities/reflect_dict.py,sha256=2NaSAL-CO0T0FYRYFQlaSpbsoLT2Q18AqdHgQSLX5Y4,3273
89
89
  dtlpy/entities/resource_execution.py,sha256=1HuVV__U4jAUOtOkWlWImnM3Yts8qxMSAkMA9sBhArY,5033
90
- dtlpy/entities/service.py,sha256=ZV3HhBbafs0N_lSIWxu4CNJ39WThd7z5GAd0fCvSnFg,32462
90
+ dtlpy/entities/service.py,sha256=3A_kcEUCbaS-Qx31rfNyThYK7OxUrzHiE6shT0Oxh60,33467
91
91
  dtlpy/entities/setting.py,sha256=uXagJHtcCR3nJYClR_AUGZjz_kx3TejPcUZ8ginHFIA,8561
92
92
  dtlpy/entities/task.py,sha256=XHiEqZYFlrDCtmw1MXsysjoBLdIzAk7coMrVk8bNIiE,19534
93
93
  dtlpy/entities/time_series.py,sha256=336jWNckjuSn0G29WJFetB7nBoFAKqs4VH9_IB4m4FE,4017
@@ -153,7 +153,7 @@ dtlpy/ml/summary_writer.py,sha256=dehDi8zmGC1sAGyy_3cpSWGXoGQSiQd7bL_Thoo8yIs,27
153
153
  dtlpy/ml/train_utils.py,sha256=R-BHKRfqDoLLhFyLzsRFyJ4E-8iedj9s9oZqy3IO2rg,2404
154
154
  dtlpy/repositories/__init__.py,sha256=aBWg6mayTAy6CtfSPLxyT_Uae7hQyNTILI7sRLKNEPU,1996
155
155
  dtlpy/repositories/analytics.py,sha256=dQPCYTPAIuyfVI_ppR49W7_GBj0033feIm9Gd7LW1V0,2966
156
- dtlpy/repositories/annotations.py,sha256=E7iHo8UwDAhdulqh0lGr3fGQ-TSwZXXGsEXZA-WJ_NA,35780
156
+ dtlpy/repositories/annotations.py,sha256=Vly9htqoH79s6uDB1HMiM-uG1EvguzsGS2BoaAjKReI,42387
157
157
  dtlpy/repositories/apps.py,sha256=J-PDCPWVtvTLmzzkABs2-8zo9hGLk_z_sNR2JB1mB0c,15752
158
158
  dtlpy/repositories/artifacts.py,sha256=Ke2ustTNw-1eQ0onLsWY7gL2aChjXPAX5p1uQ_EzMbo,19081
159
159
  dtlpy/repositories/assignments.py,sha256=1VwJZ7ctQe1iaDDDpeYDgoj2G-TCgzolVLUEqUocd2w,25506
@@ -166,11 +166,11 @@ dtlpy/repositories/datasets.py,sha256=rDpJXNyxOlJwDQB-wNkM-JIqOGH10q9nujnAl6y8_x
166
166
  dtlpy/repositories/downloader.py,sha256=pNwL7Nid8xmOyYNiv4DB_WY4RoKlxQ-U9nG2V99Gyr8,41342
167
167
  dtlpy/repositories/dpks.py,sha256=mj3QPvfzj_jZAscwIgpKUfa7fLxptc3OJQ_RrSfgYxo,17487
168
168
  dtlpy/repositories/drivers.py,sha256=fF0UuHCyBzop8pHfryex23mf0kVFAkqzNdOmwBbaWxY,10204
169
- dtlpy/repositories/executions.py,sha256=M84nhpFPPZq4fQeJ2m_sv6JT4NE2WDRMOXWr451J0bU,30403
169
+ dtlpy/repositories/executions.py,sha256=4UoU6bnB3kl5cMuF1eJvDecfZCaB06gKWxPfv6_g1_k,32598
170
170
  dtlpy/repositories/feature_sets.py,sha256=UowMDAl_CRefRB5oZzubnsjU_OFgiPPdQXn8q2j4Kuw,9666
171
171
  dtlpy/repositories/features.py,sha256=7xA2ihEuNgZD7HBQMMGLWpsS2V_3PgieKW2YAk1OeUU,9712
172
172
  dtlpy/repositories/integrations.py,sha256=Wi-CpT2PH36GFu3znWP5Uf2CmkqWBUYyOdwvatGD_eM,11798
173
- dtlpy/repositories/items.py,sha256=DqJ3g9bc4OLMm9KqI-OebXbr-zcEiohO1wGZJ1uE2Lg,37874
173
+ dtlpy/repositories/items.py,sha256=wZL438X49lGcLcQjREqzjr-7JzBFriZmdKBOzI_C1mI,37715
174
174
  dtlpy/repositories/messages.py,sha256=zYcoz8Us6j8Tb5Z7luJuvtO9xSRTuOCS7pl-ztt97Ac,3082
175
175
  dtlpy/repositories/models.py,sha256=GdVWHJ6kOIxM01wH7RVQ3CVaR4OmGurWJdQVHZezLDM,34789
176
176
  dtlpy/repositories/nodes.py,sha256=xXJm_YA0vDUn0dVvaGeq6ORM0vI3YXvfjuylvGRtkxo,3061
@@ -185,15 +185,15 @@ dtlpy/repositories/resource_executions.py,sha256=PyzsbdJxz6jf17Gx13GZmqdu6tZo3TT
185
185
  dtlpy/repositories/schema.py,sha256=kTKDrbwm7BfQnBAK81LpAl9ChNFdyUweSLNazlJJhjk,3953
186
186
  dtlpy/repositories/services.py,sha256=8hu6CgIyGQHOOlBmZmmM-oY8i-adU_99lSN46FGvvkc,67421
187
187
  dtlpy/repositories/settings.py,sha256=pvqNse0ANCdU3NSLJEzHco-PZq__OIsPSPVJveB9E4I,12296
188
- dtlpy/repositories/tasks.py,sha256=nA3rODvS8Q361xDmPXII-VPzktzoxbAApxTkzC5wv4M,48601
188
+ dtlpy/repositories/tasks.py,sha256=v09S2pYGkKx_vBG7SWigJeuMhp0GsefKo3Td7ImrWb0,49039
189
189
  dtlpy/repositories/times_series.py,sha256=m-bKFEgiZ13yQNelDjBfeXMUy_HgsPD_JAHj1GVx9fU,11420
190
190
  dtlpy/repositories/triggers.py,sha256=izdNyCN1gDc5uo7AXntso0HSMTDIzGFUp-dSEz8cn_U,21990
191
191
  dtlpy/repositories/upload_element.py,sha256=4CDZRKLubanOP0ZyGwxAHTtl6GLzwAyRAIm-PLYt0ck,10140
192
- dtlpy/repositories/uploader.py,sha256=iOlDYWIMy_h1Rbd7Mfug1I0e93dBJ0SxqP_BOwqYQPQ,30697
192
+ dtlpy/repositories/uploader.py,sha256=Flqd3gxHoTNIoTVpLGOt-EO5AYWydPiHwkYJ1461d3w,30823
193
193
  dtlpy/repositories/webhooks.py,sha256=IIpxOJ-7KeQp1TY9aJZz-FuycSjAoYx0TDk8z86KAK8,9033
194
194
  dtlpy/services/__init__.py,sha256=VfVJy2otIrDra6i7Sepjyez2ujiE6171ChQZp-YgxsM,904
195
195
  dtlpy/services/aihttp_retry.py,sha256=tgntZsAY0dW9v08rkjX1T5BLNDdDd8svtgn7nH8DSGU,5022
196
- dtlpy/services/api_client.py,sha256=DBelaW5qpZoX7vQXjgLL2xTcTwUqJodZ901g0C3Panw,68331
196
+ dtlpy/services/api_client.py,sha256=htIy5RN7gJ7k1ddXJ8X1Im6Y1fl2fvs825rF8bvJi1U,69484
197
197
  dtlpy/services/api_reference.py,sha256=cW-B3eoi9Xs3AwI87_Kr6GV_E6HPoC73aETFaGz3A-0,1515
198
198
  dtlpy/services/async_utils.py,sha256=lfpkTkRUvQoMTxaRZBHbPt5e43qdvpCGDe_-KcY2Jps,2810
199
199
  dtlpy/services/calls_counter.py,sha256=gr0io5rIsO5-7Cgc8neA1vK8kUtYhgFPmDQ2jXtiZZs,1036
@@ -221,9 +221,9 @@ dtlpy/utilities/reports/report.py,sha256=3nEsNnIWmdPEsd21nN8vMMgaZVcPKn9iawKTTeO
221
221
  dtlpy/utilities/videos/__init__.py,sha256=SV3w51vfPuGBxaMeNemx6qEMHw_C4lLpWNGXMvdsKSY,734
222
222
  dtlpy/utilities/videos/video_player.py,sha256=LCxg0EZ_DeuwcT7U_r7MRC6Q19s0xdFb7x5Gk39PRms,24072
223
223
  dtlpy/utilities/videos/videos.py,sha256=Dj916B4TQRIhI7HZVevl3foFrCsPp0eeWwvGbgX3-_A,21875
224
- dtlpy-1.95.6.data/scripts/dlp,sha256=-F0vSCWuSOOtgERAtsPMPyMmzitjhB7Yeftg_PDlDjw,10
225
- dtlpy-1.95.6.data/scripts/dlp.bat,sha256=QOvx8Dlx5dUbCTMpwbhOcAIXL1IWmgVRSboQqDhIn3A,37
226
- dtlpy-1.95.6.data/scripts/dlp.py,sha256=tEokRaDINISXnq8yNx_CBw1qM5uwjYiZoJOYGqWB3RU,4267
224
+ dtlpy-1.96.8.data/scripts/dlp,sha256=-F0vSCWuSOOtgERAtsPMPyMmzitjhB7Yeftg_PDlDjw,10
225
+ dtlpy-1.96.8.data/scripts/dlp.bat,sha256=QOvx8Dlx5dUbCTMpwbhOcAIXL1IWmgVRSboQqDhIn3A,37
226
+ dtlpy-1.96.8.data/scripts/dlp.py,sha256=tEokRaDINISXnq8yNx_CBw1qM5uwjYiZoJOYGqWB3RU,4267
227
227
  tests/assets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
228
228
  tests/assets/models_flow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
229
229
  tests/assets/models_flow/failedmain.py,sha256=n8F4eu_u7JPrJ1zedbJPvv9e3lHb3ihoErqrBIcseEc,1847
@@ -231,9 +231,9 @@ tests/assets/models_flow/main.py,sha256=87O3-JaWcC6m_kA39sqPhX70_VCBzzbLWmX2YQFi
231
231
  tests/assets/models_flow/main_model.py,sha256=Hl_tv7Q6KaRL3yLkpUoLMRqu5-ab1QsUYPL6RPEoamw,2042
232
232
  tests/features/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
233
233
  tests/features/environment.py,sha256=V23cUx_p4VpNk9kc2I0BDZJHO_xcJBFJq8m3JlYCooc,16736
234
- dtlpy-1.95.6.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
235
- dtlpy-1.95.6.dist-info/METADATA,sha256=gwEWuQCr9AOla7PZkit6MzkeFa6pW626gXqni3GPKVM,3002
236
- dtlpy-1.95.6.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
237
- dtlpy-1.95.6.dist-info/entry_points.txt,sha256=C4PyKthCs_no88HU39eioO68oei64STYXC2ooGZTc4Y,43
238
- dtlpy-1.95.6.dist-info/top_level.txt,sha256=ZWuLmQGUOtWAdgTf4Fbx884w1o0vBYq9dEc1zLv9Mig,12
239
- dtlpy-1.95.6.dist-info/RECORD,,
234
+ dtlpy-1.96.8.dist-info/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
235
+ dtlpy-1.96.8.dist-info/METADATA,sha256=disS6SF9AJSCxx0jFfo2PrNCo1LBMmHHpAQbfyXz5OU,3002
236
+ dtlpy-1.96.8.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
237
+ dtlpy-1.96.8.dist-info/entry_points.txt,sha256=C4PyKthCs_no88HU39eioO68oei64STYXC2ooGZTc4Y,43
238
+ dtlpy-1.96.8.dist-info/top_level.txt,sha256=ZWuLmQGUOtWAdgTf4Fbx884w1o0vBYq9dEc1zLv9Mig,12
239
+ dtlpy-1.96.8.dist-info/RECORD,,
File without changes
File without changes
File without changes
File without changes