supervisely 6.73.212__py3-none-any.whl → 6.73.214__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 supervisely might be problematic. Click here for more details.

@@ -56,7 +56,7 @@ class FigureInfo(NamedTuple):
56
56
  tags: list
57
57
  meta: dict
58
58
  area: str
59
- priority: int
59
+ priority: Optional[int] = None
60
60
 
61
61
  @property
62
62
  def bbox(self) -> Optional[Rectangle]:
@@ -1,5 +1,6 @@
1
- from supervisely import Annotation, Label, PointLocation, Polygon, ProjectMeta, logger, ObjClass
1
+ from supervisely import Annotation, Label, PointLocation, Polygon, ProjectMeta, logger, Rectangle
2
2
  from supervisely.io.json import load_json_file
3
+ from supervisely.convert.image.image_helper import validate_image_bounds
3
4
 
4
5
  COLOR_MAP_FILE_NAME = "class_to_id.json"
5
6
 
@@ -62,8 +63,11 @@ def convert_points(simple_points):
62
63
  return [PointLocation(int(p[1]), int(p[0])) for p in simple_points]
63
64
 
64
65
 
65
- def create_ann_from_file(ann: Annotation, ann_path: str, meta: ProjectMeta, renamed_classes: dict) -> Annotation:
66
+ def create_ann_from_file(
67
+ ann: Annotation, ann_path: str, meta: ProjectMeta, renamed_classes: dict
68
+ ) -> Annotation:
66
69
  ann_data = load_json_file(ann_path)
70
+ labels = []
67
71
  for obj in ann_data["objects"]:
68
72
  class_name = obj["label"]
69
73
  class_name = renamed_classes.get(class_name, class_name)
@@ -83,5 +87,7 @@ def create_ann_from_file(ann: Annotation, ann_path: str, meta: ProjectMeta, rena
83
87
  interiors = [convert_points(interior) for interior in interiors]
84
88
  polygon = Polygon(convert_points(polygon), interiors)
85
89
  obj_class = meta.get_obj_class(class_name)
86
- ann = ann.add_label(Label(polygon, obj_class))
90
+ labels.append(Label(polygon, obj_class))
91
+ labels = validate_image_bounds(labels, Rectangle.from_size(ann.img_size))
92
+ ann = ann.add_labels(labels)
87
93
  return ann
@@ -7,7 +7,6 @@ from typing import List
7
7
  import cv2
8
8
  import numpy as np
9
9
 
10
-
11
10
  class HiddenCocoPrints:
12
11
  def __enter__(self):
13
12
  self._original_stdout = sys.stdout
@@ -37,10 +36,10 @@ from supervisely import (
37
36
  from supervisely.convert.image.image_converter import ImageConverter
38
37
  from supervisely.geometry.graph import KeypointsTemplate
39
38
  from supervisely.imaging.color import generate_rgb
39
+ from supervisely.convert.image.image_helper import validate_image_bounds
40
40
 
41
41
  conflict_classes = []
42
42
 
43
-
44
43
  # COCO Convert funcs
45
44
  def create_supervisely_annotation(
46
45
  item: ImageConverter.Item,
@@ -149,6 +148,7 @@ def create_supervisely_annotation(
149
148
  Rectangle(y, x, y + h, x + w), obj_class_rectangle, binding_key=key
150
149
  )
151
150
  labels.append(rectangle)
151
+ labels = validate_image_bounds(labels, Rectangle.from_size(item.shape))
152
152
  return Annotation(item.shape, labels=labels, img_tags=imag_tags)
153
153
 
154
154
 
@@ -4,9 +4,9 @@ from pathlib import Path
4
4
  import magic
5
5
  import numpy as np
6
6
  from PIL import Image
7
- from typing import Union
7
+ from typing import Union, List
8
8
 
9
- from supervisely import logger
9
+ from supervisely import Rectangle, Label, logger
10
10
  from supervisely.imaging.image import read, write
11
11
  from supervisely.io.fs import (
12
12
  get_file_ext,
@@ -98,4 +98,16 @@ def read_tiff_image(path: str) -> Union[np.ndarray, None]:
98
98
  f"{name}: transposed shape from {tiff_shape} to {image.shape}"
99
99
  )
100
100
 
101
- return image
101
+ return image
102
+
103
+
104
+ def validate_image_bounds(labels: List[Label], img_rect: Rectangle) -> List[Label]:
105
+ """
106
+ Check if labels are localed inside the image canvas, print a warning and skip them if not.
107
+ """
108
+ new_labels = [label for label in labels if img_rect.contains(label.geometry.to_bbox())]
109
+ if new_labels != labels:
110
+ logger.warning(
111
+ f"{len(labels) - len(new_labels)} annotation objects are out of image bounds. Skipping..."
112
+ )
113
+ return new_labels
@@ -21,6 +21,7 @@ from supervisely.io.fs import file_exists
21
21
  from supervisely.io.json import dump_json_file, load_json_file
22
22
  from supervisely.project.project_meta import ProjectMeta
23
23
  from supervisely.sly_logger import logger
24
+ from supervisely.convert.image.image_helper import validate_image_bounds
24
25
 
25
26
  labelme_shape_types_to_sly_map = {
26
27
  "polygon": Polygon,
@@ -221,6 +222,7 @@ def create_supervisely_annotation(
221
222
  label = convert_labelme_to_sly(shape, obj_class)
222
223
  if label is not None:
223
224
  labels.append(label)
225
+ labels = validate_image_bounds(labels, Rectangle.from_size(ann.img_size))
224
226
  ann = ann.add_labels(labels)
225
227
 
226
228
  return ann
@@ -17,6 +17,7 @@ from supervisely.geometry.polygon import Polygon
17
17
  from supervisely.geometry.rectangle import Rectangle
18
18
  from supervisely.project.project_meta import ProjectMeta
19
19
  from supervisely.sly_logger import logger
20
+ from supervisely.convert.image.image_helper import validate_image_bounds
20
21
 
21
22
  POSSIBLE_SHAPE_TYPES = ["polygonlabels", "rectanglelabels", "brushlabels"]
22
23
  POSSIBLE_TAGS_TYPES = ["choices"]
@@ -211,5 +212,6 @@ def create_supervisely_annotation(image_path: str, ann: Dict, meta: ProjectMeta)
211
212
  for labels in key_label_map.values():
212
213
  res_labels.extend(labels)
213
214
 
215
+ res_labels = validate_image_bounds(res_labels, Rectangle.from_size(sly_ann.img_size))
214
216
  sly_ann = sly_ann.clone(labels=res_labels, img_tags=img_tags)
215
217
  return sly_ann, meta
@@ -2,13 +2,21 @@ import os
2
2
  from typing import Dict, Optional, Union
3
3
 
4
4
  import supervisely.convert.image.masks.image_with_masks_helper as helper
5
- from supervisely import Annotation, ProjectMeta, logger, ObjClass, Bitmap, ObjClassCollection
5
+ from supervisely import (
6
+ Annotation,
7
+ ProjectMeta,
8
+ logger,
9
+ ObjClass,
10
+ Bitmap,
11
+ ObjClassCollection,
12
+ Rectangle,
13
+ )
6
14
  from supervisely.convert.base_converter import AvailableImageConverters
7
15
  from supervisely.convert.image.image_converter import ImageConverter
8
16
  from supervisely.io.fs import file_exists, dirs_with_marker, dir_exists, get_file_name, list_files, dirs_filter, remove_junk_from_dir, get_file_ext
9
17
  from supervisely.io.json import load_json_file
10
18
  from supervisely.project.project_settings import LabelingInterface
11
-
19
+ from supervisely.convert.image.image_helper import validate_image_bounds
12
20
 
13
21
  class ImagesWithMasksConverter(ImageConverter):
14
22
  def __init__(
@@ -59,7 +67,7 @@ class ImagesWithMasksConverter(ImageConverter):
59
67
  return False
60
68
  self._meta = key_file_result
61
69
 
62
- # possible_dss
70
+ # possible_dss
63
71
  def _search_for_dss(dir_path):
64
72
  if any([d in os.listdir(dir_path) for d in helper.MASK_DIRS]):
65
73
  return True
@@ -142,8 +150,11 @@ class ImagesWithMasksConverter(ImageConverter):
142
150
  instance_labels = helper.read_instance_labels(
143
151
  instance_masks_paths, meta.obj_classes, renamed_classes
144
152
  )
153
+ all_labels = validate_image_bounds(
154
+ semantic_labels + instance_labels, Rectangle.from_size(item.shape)
155
+ )
145
156
 
146
- ann = ann.add_labels(labels=semantic_labels + instance_labels)
157
+ ann = ann.add_labels(labels=all_labels)
147
158
 
148
159
  return ann
149
160
  except Exception as e:
@@ -2,7 +2,7 @@ import os
2
2
  from typing import List, Tuple
3
3
 
4
4
  import numpy as np
5
-
5
+ from supervisely.convert.image.image_helper import validate_image_bounds
6
6
  from supervisely import (
7
7
  Annotation,
8
8
  Label,
@@ -87,7 +87,6 @@ def read_colors(colors_file: str) -> Tuple[ObjClassCollection, dict]:
87
87
  color2class_name = {v: k for k, v in cls2col.items()}
88
88
  return obj_classes, color2class_name
89
89
 
90
-
91
90
  def get_ann(
92
91
  item,
93
92
  color2class_name: dict,
@@ -97,11 +96,13 @@ def get_ann(
97
96
  ) -> Annotation:
98
97
  segm_path, inst_path = item.segm_path, item.inst_path
99
98
  height, width = item.shape
100
-
99
+ img_rect = Rectangle.from_size(item.shape)
101
100
  ann = Annotation(img_size=(height, width))
102
101
 
103
102
  if item.ann_data is not None:
104
- bbox_labels = xml_to_sly_labels(item.ann_data, meta, bbox_classes_map, renamed_classes)
103
+ bbox_labels = xml_to_sly_labels(
104
+ item.ann_data, meta, bbox_classes_map, img_rect, renamed_classes
105
+ )
105
106
  ann = ann.add_labels(bbox_labels)
106
107
 
107
108
  if segm_path is None:
@@ -136,15 +137,18 @@ def get_ann(
136
137
  cls_name = renamed_classes[cls_name]
137
138
  curr_col2cls[color] = cls_name
138
139
 
140
+ labels = []
139
141
  for color, class_name in curr_col2cls.items():
140
142
  mask = np.all(colored_img == color, axis=2) # exact match (3-channel img & rgb color)
141
143
  bitmap = Bitmap(data=mask)
142
144
  obj_class = ObjClass(name=class_name, geometry_type=Bitmap)
143
-
144
- ann = ann.add_label(Label(bitmap, obj_class))
145
+ labels.append(Label(bitmap, obj_class))
145
146
  # clear used pixels in mask to check missing colors, see below
146
147
  colored_img[mask] = (0, 0, 0)
147
148
 
149
+ labels = validate_image_bounds(labels, img_rect)
150
+ ann = ann.add_labels(labels)
151
+
148
152
  if np.sum(colored_img) > 0:
149
153
  logger.warn(
150
154
  f"Not all objects or classes are captured from source segmentation: {item.name}"
@@ -157,6 +161,7 @@ def xml_to_sly_labels(
157
161
  xml_path: str,
158
162
  meta: ProjectMeta,
159
163
  bbox_classes_map: dict,
164
+ img_rect: Rectangle,
160
165
  renamed_classes=None,
161
166
  ) -> List[Label]:
162
167
  import xml.etree.ElementTree as ET
@@ -180,6 +185,7 @@ def xml_to_sly_labels(
180
185
  bbox = Rectangle(*bbox_coords)
181
186
  label = Label(bbox, obj_cls)
182
187
  labels.append(label)
188
+ labels = validate_image_bounds(labels, img_rect)
183
189
 
184
190
  return labels
185
191
 
@@ -1,11 +1,21 @@
1
1
  import os
2
2
 
3
- from supervisely import Annotation, Api, ProjectMeta, batched, is_development, logger
3
+ from supervisely import (
4
+ Annotation,
5
+ Api,
6
+ ProjectMeta,
7
+ Label,
8
+ Rectangle,
9
+ batched,
10
+ is_development,
11
+ logger,
12
+ )
4
13
  from supervisely.convert.image.sly.sly_image_converter import SLYImageConverter
5
14
  import supervisely.convert.image.sly.sly_image_helper as helper
6
15
  from supervisely.convert.image.image_converter import ImageConverter
7
16
  from supervisely.io.fs import get_file_ext
8
17
  from supervisely.io.json import load_json_file
18
+ from supervisely.convert.image.image_helper import validate_image_bounds
9
19
 
10
20
 
11
21
  class FastSlyImageConverter(SLYImageConverter, ImageConverter):
@@ -40,7 +50,6 @@ class FastSlyImageConverter(SLYImageConverter, ImageConverter):
40
50
  self._meta = meta
41
51
  return detected_ann_cnt > 0
42
52
 
43
-
44
53
  def to_supervisely(
45
54
  self,
46
55
  item: ImageConverter.Item,
@@ -58,12 +67,16 @@ class FastSlyImageConverter(SLYImageConverter, ImageConverter):
58
67
  ann_json = ann_json["annotation"]
59
68
  if renamed_classes or renamed_tags:
60
69
  ann_json = helper.rename_in_json(ann_json, renamed_classes, renamed_tags)
61
- return Annotation.from_json(ann_json, meta)
70
+ img_size = list(ann_json["size"].values())
71
+ labels = validate_image_bounds(
72
+ [Label.from_json(obj, meta) for obj in ann_json["objects"]],
73
+ Rectangle.from_size(img_size),
74
+ )
75
+ return Annotation.from_json(ann_json, meta).clone(labels=labels)
62
76
  except Exception as e:
63
77
  logger.warn(f"Failed to convert annotation: {repr(e)}")
64
78
  return None
65
79
 
66
-
67
80
  def upload_dataset(
68
81
  self,
69
82
  api: Api,
@@ -2,7 +2,17 @@ import os
2
2
  from typing import Dict, Optional
3
3
 
4
4
  import supervisely.convert.image.sly.sly_image_helper as sly_image_helper
5
- from supervisely import Annotation, Dataset, OpenMode, Project, ProjectMeta, logger
5
+ from supervisely.convert.image.image_helper import validate_image_bounds
6
+ from supervisely import (
7
+ Annotation,
8
+ Dataset,
9
+ OpenMode,
10
+ Project,
11
+ ProjectMeta,
12
+ Rectangle,
13
+ Label,
14
+ logger,
15
+ )
6
16
  from supervisely._utils import generate_free_name
7
17
  from supervisely.api.api import Api
8
18
  from supervisely.convert.base_converter import AvailableImageConverters
@@ -134,7 +144,12 @@ class SLYImageConverter(ImageConverter):
134
144
  ann_json = ann_json["annotation"]
135
145
  if renamed_classes or renamed_tags:
136
146
  ann_json = sly_image_helper.rename_in_json(ann_json, renamed_classes, renamed_tags)
137
- return Annotation.from_json(ann_json, meta)
147
+ img_size = list(ann_json["size"].values())
148
+ labels = validate_image_bounds(
149
+ [Label.from_json(obj, meta) for obj in ann_json["objects"]],
150
+ Rectangle.from_size(img_size),
151
+ )
152
+ return Annotation.from_json(ann_json, meta).clone(labels=labels)
138
153
  except Exception as e:
139
154
  logger.warn(f"Failed to convert annotation: {repr(e)}")
140
155
  return item.create_empty_annotation()
@@ -283,5 +283,5 @@ class VideoConverter(BaseConverter):
283
283
  )
284
284
  )
285
285
  upload_progress[0].set_current_value(monitor)
286
-
286
+
287
287
  return lambda m: _print_progress(m, upload_progress)
@@ -1,14 +1,17 @@
1
1
  # coding: utf-8
2
2
 
3
+ import time
3
4
  import traceback
5
+
4
6
  import requests
5
- import time
6
7
 
7
- CONNECTION_ERROR = 'Temporary connection error, please wait ...'
8
- AGENT_CONNECTION_ERROR = 'Temporary connection error (agent ping), please wait ...'
8
+ CONNECTION_ERROR = "Temporary connection error, please wait ..."
9
+ AGENT_CONNECTION_ERROR = "Temporary connection error (agent ping), please wait ..."
9
10
 
10
- REQUEST_FAILED = 'Request has failed. This may be due to connection problems or invalid requests. '
11
- SPECIAL_RECONNECT_ERROR = "Agent should call AgentConnected or AgentPing before attempting any other request"
11
+ REQUEST_FAILED = "Request has failed. This may be due to connection problems or invalid requests. "
12
+ SPECIAL_RECONNECT_ERROR = (
13
+ "Agent should call AgentConnected or AgentPing before attempting any other request"
14
+ )
12
15
  RETRY_STATUS_CODES = {
13
16
  408, # Request Timeout
14
17
  429, # Too Many Requests
@@ -19,51 +22,100 @@ RETRY_STATUS_CODES = {
19
22
  504, # Gateway Timeout
20
23
  509, # Bandwidth Limit Exceeded (Apache)
21
24
  598, # Network read timeout error
22
- 599 # Network connect timeout error
25
+ 599, # Network connect timeout error
23
26
  }
24
27
 
25
28
 
26
- def process_requests_exception(external_logger, exc, api_method_name, url,
27
- verbose=True, swallow_exc=False, sleep_sec=None, response=None, retry_info=None):
28
- is_connection_error = isinstance(exc, (requests.exceptions.ConnectionError,
29
- requests.exceptions.Timeout,
30
- requests.exceptions.TooManyRedirects,
31
- requests.exceptions.ChunkedEncodingError))
32
-
33
- is_server_retryable_error = isinstance(exc, requests.exceptions.HTTPError) and \
34
- hasattr(exc, 'response') and \
35
- (exc.response.status_code in RETRY_STATUS_CODES)
29
+ def process_requests_exception(
30
+ external_logger,
31
+ exc,
32
+ api_method_name,
33
+ url,
34
+ verbose=True,
35
+ swallow_exc=False,
36
+ sleep_sec=None,
37
+ response=None,
38
+ retry_info=None,
39
+ ):
40
+ is_connection_error = isinstance(
41
+ exc,
42
+ (
43
+ requests.exceptions.ConnectionError,
44
+ requests.exceptions.Timeout,
45
+ requests.exceptions.TooManyRedirects,
46
+ requests.exceptions.ChunkedEncodingError,
47
+ ),
48
+ )
49
+
50
+ is_server_retryable_error = (
51
+ isinstance(exc, requests.exceptions.HTTPError)
52
+ and hasattr(exc, "response")
53
+ and (exc.response.status_code in RETRY_STATUS_CODES)
54
+ )
36
55
 
37
56
  is_need_ping_error = False
38
- if isinstance(exc, requests.exceptions.HTTPError) and hasattr(exc, 'response') and (exc.response.status_code == 400):
57
+ if (
58
+ isinstance(exc, requests.exceptions.HTTPError)
59
+ and hasattr(exc, "response")
60
+ and (exc.response.status_code == 400)
61
+ ):
39
62
  try:
40
63
  server_explanation = exc.response.json()
41
- is_need_ping_error = (server_explanation.get('error', None) == SPECIAL_RECONNECT_ERROR)
64
+ is_need_ping_error = server_explanation.get("error", None) == SPECIAL_RECONNECT_ERROR
42
65
  except (AttributeError, ValueError):
43
66
  pass
44
67
 
45
68
  if is_connection_error or is_server_retryable_error:
46
- process_retryable_request(external_logger, exc, api_method_name, url,
47
- CONNECTION_ERROR,
48
- verbose=verbose, swallow_exc=swallow_exc, sleep_sec=sleep_sec, retry_info=retry_info)
69
+ process_retryable_request(
70
+ external_logger,
71
+ exc,
72
+ api_method_name,
73
+ url,
74
+ CONNECTION_ERROR,
75
+ verbose=verbose,
76
+ swallow_exc=swallow_exc,
77
+ sleep_sec=sleep_sec,
78
+ retry_info=retry_info,
79
+ )
49
80
  elif is_need_ping_error:
50
- process_retryable_request(external_logger, exc, api_method_name, url,
51
- AGENT_CONNECTION_ERROR,
52
- verbose=verbose, swallow_exc=swallow_exc, sleep_sec=sleep_sec, retry_info=retry_info)
81
+ process_retryable_request(
82
+ external_logger,
83
+ exc,
84
+ api_method_name,
85
+ url,
86
+ AGENT_CONNECTION_ERROR,
87
+ verbose=verbose,
88
+ swallow_exc=swallow_exc,
89
+ sleep_sec=sleep_sec,
90
+ retry_info=retry_info,
91
+ )
92
+ elif response is None:
93
+ process_unhandled_request(external_logger, exc)
53
94
  elif isinstance(exc, requests.exceptions.HTTPError):
54
95
  process_invalid_request(external_logger, exc, response, verbose)
55
96
  else:
56
97
  process_unhandled_request(external_logger, exc)
57
98
 
58
99
 
59
- def process_retryable_request(external_logger, exc, api_method_name, url, user_message,
60
- verbose=True, swallow_exc=False, sleep_sec=None, retry_info=None):
100
+ def process_retryable_request(
101
+ external_logger,
102
+ exc,
103
+ api_method_name,
104
+ url,
105
+ user_message,
106
+ verbose=True,
107
+ swallow_exc=False,
108
+ sleep_sec=None,
109
+ retry_info=None,
110
+ ):
61
111
  if retry_info is not None:
62
112
  retry_idx = retry_info["retry_idx"]
63
113
  retry_limit = retry_info["retry_limit"]
64
114
  user_message = "{}: Retrying ({}/{}).".format(user_message, retry_idx, retry_limit)
65
115
  if verbose:
66
- external_logger.warn(user_message, extra={'method': api_method_name, 'url': url, 'details': str(exc)})
116
+ external_logger.warn(
117
+ user_message, extra={"method": api_method_name, "url": url, "details": str(exc)}
118
+ )
67
119
 
68
120
  if sleep_sec is not None:
69
121
  time.sleep(sleep_sec)
@@ -74,13 +126,18 @@ def process_retryable_request(external_logger, exc, api_method_name, url, user_m
74
126
 
75
127
  def process_invalid_request(external_logger, exc, response, verbose=True):
76
128
  if verbose:
77
- external_logger.warn(REQUEST_FAILED, extra={'reason': response.content.decode('utf-8'),
78
- 'status_code': response.status_code,
79
- 'url': response.url})
129
+ external_logger.warn(
130
+ REQUEST_FAILED,
131
+ extra={
132
+ "reason": response.content.decode("utf-8"),
133
+ "status_code": response.status_code,
134
+ "url": response.url,
135
+ },
136
+ )
80
137
  raise exc
81
138
 
82
139
 
83
140
  def process_unhandled_request(external_logger, exc):
84
141
  exc_str = str(exc)
85
- external_logger.error(traceback.format_exc(), exc_info=True, extra={'exc_str': exc_str})
86
- raise RuntimeError(REQUEST_FAILED + 'Last failure: {!r}'.format(exc_str))
142
+ external_logger.error(traceback.format_exc(), exc_info=True, extra={"exc_str": exc_str})
143
+ raise RuntimeError(REQUEST_FAILED + "Last failure: {!r}".format(exc_str))
@@ -1,18 +1,18 @@
1
1
  import json
2
2
  import os
3
3
  import shutil
4
+ from concurrent.futures import ThreadPoolExecutor
4
5
  from enum import Enum
5
6
  from logging import Logger
6
7
  from pathlib import Path
7
8
  from threading import Lock, Thread
8
- from concurrent.futures import ThreadPoolExecutor
9
9
  from time import sleep
10
10
  from typing import Any, Callable, Generator, List, Optional, Tuple, Union
11
11
 
12
12
  import cv2
13
13
  import numpy as np
14
14
  from cacheout import Cache as CacheOut
15
- from cachetools import Cache, LRUCache, TTLCache, _Link
15
+ from cachetools import Cache, LRUCache, TTLCache
16
16
  from fastapi import BackgroundTasks, FastAPI, Form, Request, UploadFile
17
17
 
18
18
  import supervisely as sly
@@ -83,7 +83,10 @@ class PersistentImageTTLCache(TTLCache):
83
83
  # pylint: disable=no-member
84
84
  link = self._TTLCache__getlink(key)
85
85
  # pylint: disable=no-member
86
- link.expire = self._TTLCache__timer() + self._TTLCache__ttl
86
+ if hasattr(link, "expire"):
87
+ link.expire = self.timer() + self._TTLCache__ttl
88
+ else:
89
+ link.expires = self.timer() + self._TTLCache__ttl
87
90
  except KeyError:
88
91
  return
89
92
 
@@ -626,11 +629,11 @@ class InferenceImageCache:
626
629
  pos_by_name[name] = pos
627
630
  elif return_images is True:
628
631
  items.append((pos, name))
629
-
632
+
630
633
  def get_one_image(item):
631
634
  pos, name = item
632
635
  return pos, self._cache.get_image(name)
633
-
636
+
634
637
  if len(items) > 0:
635
638
  with ThreadPoolExecutor(min(64, len(items))) as executor:
636
639
  for pos, image in executor.map(get_one_image, items):
@@ -399,11 +399,12 @@ class DataVersion(ModuleApiBase):
399
399
  updated_at = self.versions[str(version_id)]["updated_at"]
400
400
  backup_files = self.versions[str(version_id)]["path"]
401
401
 
402
- if updated_at == self.project_info.updated_at:
403
- logger.warning(
404
- f"Project is already on version {version_num} with the same updated_at timestamp"
405
- )
406
- return
402
+ # turn off this check for now (treating this as a project clone operation)
403
+ # if updated_at == self.project_info.updated_at:
404
+ # logger.warning(
405
+ # f"Project is already on version {version_num} with the same updated_at timestamp"
406
+ # )
407
+ # return
407
408
 
408
409
  if backup_files is None:
409
410
  logger.warning(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: supervisely
3
- Version: 6.73.212
3
+ Version: 6.73.214
4
4
  Summary: Supervisely Python SDK.
5
5
  Home-page: https://github.com/supervisely/supervisely
6
6
  Author: Supervisely
@@ -20,7 +20,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
20
  Requires-Python: >=3.8
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: cachetools<5.0.0,>=4.2.3
23
+ Requires-Dist: cachetools<=5.5.0,>=4.2.3
24
24
  Requires-Dist: numpy<2.0.0,>=1.19
25
25
  Requires-Dist: opencv-python<5.0.0.0,>=4.5.5.62
26
26
  Requires-Dist: PTable<1.0.0,>=0.9.2
@@ -38,12 +38,12 @@ Requires-Dist: SimpleITK<3.0.0.0,>=2.1.1.2
38
38
  Requires-Dist: pydicom<3.0.0,>=2.3.0
39
39
  Requires-Dist: stringcase<2.0.0,>=1.2.0
40
40
  Requires-Dist: python-magic<1.0.0,>=0.4.25
41
- Requires-Dist: trimesh<4.0.0,>=3.11.2
41
+ Requires-Dist: trimesh<=4.5.0,>=3.11.2
42
42
  Requires-Dist: uvicorn[standard]<1.0.0,>=0.18.2
43
43
  Requires-Dist: pydantic<=2.8.2,>=1.7.4
44
44
  Requires-Dist: anyio<=4.2.0,>=3.7.1
45
45
  Requires-Dist: fastapi<=0.109.0,>=0.79.0
46
- Requires-Dist: websockets<11.0,>=10.3
46
+ Requires-Dist: websockets<=13.1,>=10.3
47
47
  Requires-Dist: jinja2<4.0.0,>=3.0.3
48
48
  Requires-Dist: psutil<6.0.0,>=5.9.0
49
49
  Requires-Dist: jsonpatch<2.0,>=1.32
@@ -71,7 +71,7 @@ Requires-Dist: zstd
71
71
  Provides-Extra: apps
72
72
  Requires-Dist: uvicorn[standard]<1.0.0,>=0.18.2; extra == "apps"
73
73
  Requires-Dist: fastapi<1.0.0,>=0.79.0; extra == "apps"
74
- Requires-Dist: websockets<11.0,>=10.3; extra == "apps"
74
+ Requires-Dist: websockets<=13.1,>=10.3; extra == "apps"
75
75
  Requires-Dist: jinja2<4.0.0,>=3.0.3; extra == "apps"
76
76
  Requires-Dist: psutil<6.0.0,>=5.9.0; extra == "apps"
77
77
  Requires-Dist: jsonpatch<2.0,>=1.32; extra == "apps"
@@ -49,7 +49,7 @@ supervisely/api/video_annotation_tool_api.py,sha256=Uy1MvT-M7vjC6y-0-V4wFCO-fZt8
49
49
  supervisely/api/workspace_api.py,sha256=5KAxpI9DKBmgF_pyQaXHpGT30HZ9wRtR6DP3FoYFZtY,9228
50
50
  supervisely/api/entity_annotation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
51
  supervisely/api/entity_annotation/entity_annotation_api.py,sha256=K79KdDyepQv4FiNQHBj9V4-zLIemxK9WG1ig1bfBKb8,3083
52
- supervisely/api/entity_annotation/figure_api.py,sha256=fFACK0NNVnYjhTq4RmUQyVUBug0WUYK1fjJG7ANdFzs,20500
52
+ supervisely/api/entity_annotation/figure_api.py,sha256=ZO2W2Px4XNHqgEOFhvw-HGsUJpK5Pek5azbNxDOJ47o,20517
53
53
  supervisely/api/entity_annotation/object_api.py,sha256=gbcNvN_KY6G80Me8fHKQgryc2Co7VU_kfFd1GYILZ4E,8875
54
54
  supervisely/api/entity_annotation/tag_api.py,sha256=jA6q5XuvJ6qAalM9ktGbscbNM07xw4Qo3odkkstvNKY,10882
55
55
  supervisely/api/pointcloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -558,14 +558,14 @@ supervisely/convert/base_converter.py,sha256=F5oCwQZ_w7XlIIQnW-y-2scvA9sC8vCJL2X
558
558
  supervisely/convert/converter.py,sha256=0F93xZmyprua63C6KxIeh0AbaFab81LiWqlkOVrkaYU,8672
559
559
  supervisely/convert/image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
560
560
  supervisely/convert/image/image_converter.py,sha256=Er-QX6qyVO4p72iJ3ae0YMF9gSfm_SUimoH6id0MIIs,9446
561
- supervisely/convert/image/image_helper.py,sha256=21cpHiSzHS7brQpP15MAkrGh1lj7pOWh9Z976cObyIw,3145
561
+ supervisely/convert/image/image_helper.py,sha256=RkBAyxxXmDG1Z5WFuO9kBDK8MN1Kl7Z25DX9-CwZ7OI,3647
562
562
  supervisely/convert/image/cityscapes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
563
563
  supervisely/convert/image/cityscapes/cityscapes_converter.py,sha256=msmsR2W-Xiod06dwn-MzmkbrEmQQqlKh7zyfTrW6YQw,7854
564
- supervisely/convert/image/cityscapes/cityscapes_helper.py,sha256=mIgc-wjKJskYY8XfDZueadEilPmjxee091fIPUege88,2787
564
+ supervisely/convert/image/cityscapes/cityscapes_helper.py,sha256=in5nR7__q_u5dCkVtZmynfZ_ZuvsIAHrTzyTG4EvNgU,2988
565
565
  supervisely/convert/image/coco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
566
566
  supervisely/convert/image/coco/coco_anntotation_converter.py,sha256=79rhAy_nkudxEgJDLW0BziUz808-fSqTOnlUeN-kvn8,6603
567
567
  supervisely/convert/image/coco/coco_converter.py,sha256=7czTd4I1we_HxEc9diQiXPC2pXAtnoqSnFSVCtNOmP4,5431
568
- supervisely/convert/image/coco/coco_helper.py,sha256=ZjHlQIF7RReNROVGo5ZUANGv5iR3K-MrsyAC76sm9fI,13193
568
+ supervisely/convert/image/coco/coco_helper.py,sha256=lRr9TcqRVphF_Hlw37-vgJClJBQ-THmCW5xHPYhkxPg,13340
569
569
  supervisely/convert/image/csv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
570
570
  supervisely/convert/image/csv/csv_converter.py,sha256=iLyc2PAVtlsAq7blnGH4iS1_D7Ai6-4UsdI_RlDVB9Q,11677
571
571
  supervisely/convert/image/csv/csv_helper.py,sha256=-nR192IfMU0vTlNRoKXu5FS6tTs9fENqySyeKKyemRs,8409
@@ -574,13 +574,13 @@ supervisely/convert/image/high_color/high_color_depth.py,sha256=t1LsOnEwhSmXUWxs
574
574
  supervisely/convert/image/high_color/high_color_helper.py,sha256=bD5Jl6lmKbiNG_8Bpy-WvIYjSJqwdaVmXrHGVZT6o2w,1630
575
575
  supervisely/convert/image/label_me/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
576
576
  supervisely/convert/image/label_me/label_me_converter.py,sha256=E8epO8METLslVLy51AW7FoZto1jrPSFUZHDwzOnHbTk,3081
577
- supervisely/convert/image/label_me/label_me_helper.py,sha256=_JO-IS2iiGVcWBHFoC8-LDBW4deJ_Rt4s3Sl5rFjXFg,8279
577
+ supervisely/convert/image/label_me/label_me_helper.py,sha256=qysfNlGyUG8dAEn9dS66AfxTSC6S5fTSTg7JMtVA2OU,8430
578
578
  supervisely/convert/image/label_studio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
579
579
  supervisely/convert/image/label_studio/label_studio_converter.py,sha256=eP7Lch9QxTzN29sF71rIJyffeXQdXXaUmoLUPBuC6JM,5117
580
- supervisely/convert/image/label_studio/label_studio_helper.py,sha256=TsE-Qx0nrOcStYEgT4uxJVO5vPmU3fLClyNPTeFJmLI,7845
580
+ supervisely/convert/image/label_studio/label_studio_helper.py,sha256=aSAvhZnkqqVtGKxSDrw9slLIe-cNte7G1FeH8Tu3yRY,8008
581
581
  supervisely/convert/image/masks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
582
582
  supervisely/convert/image/masks/image_with_masks_helper.py,sha256=TSHiAIH3qlYdjR-9HteDcbJQbvJLM7NfWqoaW5BNTX4,2233
583
- supervisely/convert/image/masks/images_with_masks_converter.py,sha256=6r3rSKiWJVJJY7XjhRhnUpbpNVFKTgFYt2jJambUhEo,6629
583
+ supervisely/convert/image/masks/images_with_masks_converter.py,sha256=Won5LihYXZZmimgaJHmK0_rVmOadWYk21OHKri21R08,6866
584
584
  supervisely/convert/image/medical2d/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
585
585
  supervisely/convert/image/medical2d/medical2d_converter.py,sha256=cYEaRfr8YFxEG_Pv-_SVMxrqZudi3kWbGQ3aArL2mds,8156
586
586
  supervisely/convert/image/medical2d/medical2d_helper.py,sha256=pfLRCSFbFa5EIhmbB7kdmdWRu01OwIEDPXeNHzAeagg,12329
@@ -590,13 +590,13 @@ supervisely/convert/image/multispectral/__init__.py,sha256=47DEQpj8HBSa-_TImW-5J
590
590
  supervisely/convert/image/multispectral/multispectral_converter.py,sha256=T3etYVNI0AUUrQsQhxw_r85NthXrqhqmdZQfz8kUY0g,5194
591
591
  supervisely/convert/image/pascal_voc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
592
592
  supervisely/convert/image/pascal_voc/pascal_voc_converter.py,sha256=h5Q3qW4riUCXPo5535wuKGurlLvPfKbWGML0RGnMxyg,7648
593
- supervisely/convert/image/pascal_voc/pascal_voc_helper.py,sha256=6m0UeeL14vlY_lFRJR84Rfcblh4o-bOgRlEXv-FW1rc,7682
593
+ supervisely/convert/image/pascal_voc/pascal_voc_helper.py,sha256=Brpyet_FRnKAJSTaXrI5wLZLc9yIt3VAAkC6SYUCm1Y,8005
594
594
  supervisely/convert/image/pdf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
595
595
  supervisely/convert/image/pdf/pdf_converter.py,sha256=LKvVng9jPp0cSIjYEjKLOb48wtdOdB7LXS2gjmOdZhE,2442
596
596
  supervisely/convert/image/pdf/pdf_helper.py,sha256=IDwLEvsVy8lu-KC1lXvSRkZZ9BCC6ylebnNEtLQU5L4,1288
597
597
  supervisely/convert/image/sly/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
598
- supervisely/convert/image/sly/fast_sly_image_converter.py,sha256=iKozfi9BNpei67IQ0YucF0aaXNX_y3EYZSA7EGPNrUs,4924
599
- supervisely/convert/image/sly/sly_image_converter.py,sha256=zNp2-sU313UgtEGNTOiu4juJfKdTULUt6V3FZ5N1a8k,11624
598
+ supervisely/convert/image/sly/fast_sly_image_converter.py,sha256=bmJTA-ty_P6oU4SBiiUi5PUzX7OfwX8OBXN8XHiSJmw,5308
599
+ supervisely/convert/image/sly/sly_image_converter.py,sha256=Qxp8F_loZMpzLFRiQw1RC4ZWsZeyQ4c3n_ldlBiZZE8,12010
600
600
  supervisely/convert/image/sly/sly_image_helper.py,sha256=5Ri8fKb5dzh5b3v8AJ5u8xVFOQfAtoWqZ7HktPsCjTI,7373
601
601
  supervisely/convert/image/yolo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
602
602
  supervisely/convert/image/yolo/yolo_converter.py,sha256=cg5___X5MzvR-rZbNLmaKtr0MdRnyqtEzbBq5UBnYZ0,11171
@@ -623,7 +623,7 @@ supervisely/convert/pointcloud_episodes/sly/__init__.py,sha256=47DEQpj8HBSa-_TIm
623
623
  supervisely/convert/pointcloud_episodes/sly/sly_pointcloud_episodes_converter.py,sha256=JD733jWyLXSljRNRAij5OTriaPrnPB6aIdQgQcUc_pg,5889
624
624
  supervisely/convert/pointcloud_episodes/sly/sly_pointcloud_episodes_helper.py,sha256=h4WvNH6cEHtjxxhCnU7Hs2vkyJMye0qwabqXNYVTywE,3570
625
625
  supervisely/convert/video/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
626
- supervisely/convert/video/video_converter.py,sha256=V4uq3fYNOwfwQvitAGvTTYHD-HW7jWwZxhi3qTasopM,10656
626
+ supervisely/convert/video/video_converter.py,sha256=ZMvZfrzglh5GsSp7fbtQwNsijDqPRrVmPxwAlGVAqOk,10648
627
627
  supervisely/convert/video/davis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
628
628
  supervisely/convert/video/davis/davis_converter.py,sha256=zaPsJdN6AvyPT7fVnswuPbgrz5T-X2RFbHEdkuMhWGk,415
629
629
  supervisely/convert/video/mot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -689,7 +689,7 @@ supervisely/io/fs_cache.py,sha256=UvG27YGuLHOahY-cVchYXciTZNEM2aJfh0TAnP_xeeQ,57
689
689
  supervisely/io/github_utils.py,sha256=jGmvQJ5bjtACuSFABzrxL0jJdh14SezovrHp8T-9y8g,1779
690
690
  supervisely/io/json.py,sha256=7RGAk72FpPtlHYcyo7-uWZf5IAvQJg_nM09RpXBpaNo,7588
691
691
  supervisely/io/multipart_stream_decoder.py,sha256=rCheeSCAGdw2tNyaWEYa4dvoIDuldXOxH86RVB82c78,14417
692
- supervisely/io/network_exceptions.py,sha256=Zy9INsRk0eZL73LW6e_Gs3mIYzGXW1BJqNkBxTuPRzg,3952
692
+ supervisely/io/network_exceptions.py,sha256=ka5ce-L4brzqnzARFpma5zmVZaq1ojgVZcfxzWQPTJ8,4126
693
693
  supervisely/labeling_jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
694
694
  supervisely/labeling_jobs/constants.py,sha256=GF_pwF9fC9_DGbpD3cAk3llifskAxpDmyuXwxM1f3Hw,104
695
695
  supervisely/labeling_jobs/utils.py,sha256=XOGF2cbnTGbXFdT5jGL1LIPQfiCEJgRkmKNIjTlFois,22656
@@ -776,7 +776,7 @@ supervisely/nn/benchmark/visualization/vis_metrics/recall_vs_precision.py,sha256
776
776
  supervisely/nn/benchmark/visualization/vis_metrics/reliability_diagram.py,sha256=Vxta2s0RTTcV0GCcMiF8CykCtZYryLTwGjW9vVUrK3I,3107
777
777
  supervisely/nn/benchmark/visualization/vis_metrics/what_is.py,sha256=MDnYR-o7Mj-YE1Jwu9EcLUEPcu6rLknRx7LvV4nnUBo,842
778
778
  supervisely/nn/inference/__init__.py,sha256=mtEci4Puu-fRXDnGn8RP47o97rv3VTE0hjbYO34Zwqg,1622
779
- supervisely/nn/inference/cache.py,sha256=vjFYIkoV-txzAl_C_WKvS5odccBU8GHFY8iTxxnSqLU,25619
779
+ supervisely/nn/inference/cache.py,sha256=WylgHgPQRIoA_RDks8FyKgHqeZZ_YFoyddxkVvOX2YQ,25713
780
780
  supervisely/nn/inference/inference.py,sha256=pwTh6_EQ-sJNXTBD08eUMdOH8VoNF2uJUTr_P1-BuN0,114983
781
781
  supervisely/nn/inference/session.py,sha256=jmkkxbe2kH-lEgUU6Afh62jP68dxfhF5v6OGDfLU62E,35757
782
782
  supervisely/nn/inference/video_inference.py,sha256=8Bshjr6rDyLay5Za8IB8Dr6FURMO2R_v7aELasO8pR4,5746
@@ -891,7 +891,7 @@ supervisely/pointcloud_annotation/pointcloud_tag_collection.py,sha256=j_TAN23GkT
891
891
  supervisely/pointcloud_episodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
892
892
  supervisely/pointcloud_episodes/pointcloud_episodes.py,sha256=NqUkVdHBSIplB2wvzL6a8z8EuGNpAJuOn1j5UrmSrQw,3421
893
893
  supervisely/project/__init__.py,sha256=hlzdj9Pgy53Q3qdP8LMtGTChvZHQuuShdtui2eRUQeE,2601
894
- supervisely/project/data_version.py,sha256=a2eKJsPLjPYFnO7hFyQMNGsFERoCwA-yJ5I2pX549zM,19177
894
+ supervisely/project/data_version.py,sha256=nknaWJSUCwoDyNG9_d1KA-GjzidhV9zd9Cn8cg15DOU,19270
895
895
  supervisely/project/download.py,sha256=HtprYsqdzx0AgBmMlvigerFjhMQDtTGuCE1aQ9LBqN0,19704
896
896
  supervisely/project/pointcloud_episode_project.py,sha256=fcaFAaHVn_VvdiIfHl4IyEFE5-Q3VFGfo7_YoxEma0I,41341
897
897
  supervisely/project/pointcloud_project.py,sha256=Y8Xhi6Hg-KyztwFncezuDfKTt2FILss96EU_LdXzmrA,49172
@@ -957,9 +957,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
957
957
  supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
958
958
  supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
959
959
  supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
960
- supervisely-6.73.212.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
961
- supervisely-6.73.212.dist-info/METADATA,sha256=iToYzdSTy2-0TOu9UbwsqvC_A_UEbTohLp4GndImxq0,33086
962
- supervisely-6.73.212.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
963
- supervisely-6.73.212.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
964
- supervisely-6.73.212.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
965
- supervisely-6.73.212.dist-info/RECORD,,
960
+ supervisely-6.73.214.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
961
+ supervisely-6.73.214.dist-info/METADATA,sha256=eiPzbAzdjKq2Ni6e1iFqKqPdKouyzo9fONMZqs_Rx2A,33090
962
+ supervisely-6.73.214.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
963
+ supervisely-6.73.214.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
964
+ supervisely-6.73.214.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
965
+ supervisely-6.73.214.dist-info/RECORD,,