supervisely 6.73.220__py3-none-any.whl → 6.73.221__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.

@@ -5,14 +5,15 @@ from __future__ import annotations
5
5
 
6
6
  import mimetypes
7
7
  import os
8
- import re
9
8
  import shutil
10
9
  import tarfile
11
10
  import tempfile
12
11
  import urllib
13
12
  from pathlib import Path
13
+ from time import time
14
14
  from typing import Callable, Dict, List, NamedTuple, Optional, Union
15
15
 
16
+ from dotenv import load_dotenv
16
17
  import requests
17
18
  from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor
18
19
  from tqdm import tqdm
@@ -20,9 +21,8 @@ from typing_extensions import Literal
20
21
 
21
22
  import supervisely.io.env as env
22
23
  import supervisely.io.fs as sly_fs
23
- from supervisely._utils import batched, is_development, rand_str
24
+ from supervisely._utils import batched, rand_str
24
25
  from supervisely.api.module_api import ApiField, ModuleApiBase
25
- from supervisely.imaging.image import get_hash, write_bytes
26
26
  from supervisely.io.fs import (
27
27
  ensure_base_path,
28
28
  get_file_ext,
@@ -36,7 +36,7 @@ from supervisely.io.fs import (
36
36
  from supervisely.io.fs_cache import FileCache
37
37
  from supervisely.io.json import load_json_file
38
38
  from supervisely.sly_logger import logger
39
- from supervisely.task.progress import Progress, handle_original_tqdm, tqdm_sly
39
+ from supervisely.task.progress import Progress
40
40
 
41
41
 
42
42
  class FileInfo(NamedTuple):
@@ -958,9 +958,7 @@ class FileApi(ModuleApiBase):
958
958
  )
959
959
  return
960
960
 
961
- resp = self._api.post(
962
- "file-storage.remove", {ApiField.TEAM_ID: team_id, ApiField.PATH: path}
963
- )
961
+ self._api.post("file-storage.remove", {ApiField.TEAM_ID: team_id, ApiField.PATH: path})
964
962
 
965
963
  def remove_file(self, team_id: int, path: str) -> None:
966
964
  """
@@ -1401,6 +1399,55 @@ class FileApi(ModuleApiBase):
1401
1399
  self.upload_bulk(team_id, local_paths_batch, remote_files_batch, progress_size_cb)
1402
1400
  return res_remote_dir
1403
1401
 
1402
+ def load_dotenv_from_teamfiles(
1403
+ self, remote_path: str = None, team_id: int = None, override: int = False
1404
+ ) -> None:
1405
+ """Loads .env file from Team Files into environment variables.
1406
+ If remote_path or team_id is not specified, it will be taken from environment variables.
1407
+
1408
+ :param remote_path: Path to .env file in Team Files.
1409
+ :type remote_path: str, optional
1410
+ :param team_id: Team ID in Supervisely.
1411
+ :type team_id: int, optional
1412
+ :param override: If True, existing environment variables will be overridden.
1413
+ :type override: bool, optional
1414
+
1415
+ :Usage example:
1416
+
1417
+ .. code-block:: python
1418
+
1419
+ import supervisely as sly
1420
+
1421
+ api = sly.Api.from_env()
1422
+
1423
+ api.file.load_dotenv_from_teamfiles()
1424
+ # All variables from .env file are loaded into environment variables.
1425
+ """
1426
+ # If remote_path or team_id is not specified, it will be taken from environment variables.
1427
+ remote_path = remote_path or env.file(raise_not_found=False)
1428
+ team_id = team_id or env.team_id(raise_not_found=False)
1429
+
1430
+ if not remote_path or not team_id or not remote_path.endswith(".env"):
1431
+ return
1432
+
1433
+ try:
1434
+ file_name = sly_fs.get_file_name(remote_path)
1435
+
1436
+ # Use timestamp to avoid conflicts with existing files.
1437
+ timestamp = int(time())
1438
+ local_save_path = os.path.join(os.getcwd(), f"{file_name}_{timestamp}.env")
1439
+
1440
+ # Download .env file from Team Files.
1441
+ self.download(team_id=team_id, remote_path=remote_path, local_save_path=local_save_path)
1442
+
1443
+ # Load .env file into environment variables and then remove it.
1444
+ load_dotenv(local_save_path, override=override)
1445
+ sly_fs.silent_remove(local_save_path)
1446
+
1447
+ logger.debug(f"Loaded .env file from team files: {remote_path}")
1448
+ except Exception as e:
1449
+ logger.debug(f"Failed to load .env file from team files: {remote_path}. Error: {e}")
1450
+
1404
1451
  def get_json_file_content(self, team_id: int, remote_path: str, download: bool = False) -> dict:
1405
1452
  """
1406
1453
  Get JSON file content.
@@ -1,4 +1,5 @@
1
1
  from supervisely.app.development.development import (
2
2
  supervisely_vpn_network,
3
3
  create_debug_task,
4
+ enable_advanced_debug,
4
5
  )
@@ -6,6 +6,8 @@ from typing import Any, Dict, Optional
6
6
 
7
7
  import requests
8
8
 
9
+ import supervisely.io.env as sly_env
10
+ from supervisely._utils import is_development
9
11
  from supervisely.api.api import Api
10
12
  from supervisely.io.fs import mkdir
11
13
  from supervisely.sly_logger import logger
@@ -154,11 +156,12 @@ def supervisely_vpn_network(
154
156
 
155
157
 
156
158
  def create_debug_task(
157
- team_id: int, port: int = 8000, update_status: bool = True
159
+ team_id: int = None, port: int = 8000, update_status: bool = True
158
160
  ) -> Dict[str, Any]:
159
161
  """Gets or creates a debug task for the current user.
160
162
 
161
- :param team_id: The ID of the team to create the task in.
163
+ :param team_id: The ID of the team to create the task in, if not provided, the function
164
+ will try to obtain it from environment variables. Default is None.
162
165
  :type team_id: int
163
166
  :param port: The port to redirect the requests to. Default is 8000.
164
167
  :type port: int
@@ -167,6 +170,14 @@ def create_debug_task(
167
170
  :return: The task details.
168
171
  :rtype: Dict[str, Any]
169
172
  """
173
+ team_id = team_id or sly_env.team_id()
174
+ if not team_id:
175
+ raise ValueError(
176
+ "Team ID is not provided and cannot be obtained from environment variables."
177
+ "The debug task cannot be created. Please provide the team ID as an argument "
178
+ "or set the TEAM_ID environment variable."
179
+ )
180
+
170
181
  api = Api()
171
182
  me = api.user.get_my_info()
172
183
  session_name = me.login + "-development"
@@ -200,4 +211,87 @@ def create_debug_task(
200
211
  if update_status:
201
212
  logger.info(f"Task status will be updated to STARTED for task with ID: {task['id']}")
202
213
  api.task.update_status(task["id"], api.task.Status.STARTED)
214
+
203
215
  return task
216
+
217
+
218
+ def enable_advanced_debug(
219
+ team_id: int = None,
220
+ port: int = 8000,
221
+ update_status: bool = True,
222
+ vpn_action: Literal["up", "down"] = "up",
223
+ vpn_raise_on_error: bool = True,
224
+ only_for_development: bool = True,
225
+ ) -> Optional[int]:
226
+ """Enables advanced debugging for the app.
227
+ At first, it establishes a WireGuard VPN connection to the Supervisely network.
228
+ And then creates a debug task to redirect requests to the local machine.
229
+
230
+ Please, ensure that the Team ID was provided, or set as TEAM_ID environment variable.
231
+ All other parameters can be omitted if using the default instance settings.
232
+
233
+ :param team_id: The ID of the team to create the task in, if not provided, the function
234
+ will try to obtain it from environment variables. Default is None.
235
+ :type team_id: int
236
+ :param port: The port to redirect the requests to. Default is 8000.
237
+ :type port: int
238
+ :param update_status: If True, the task status will be updated to STARTED.
239
+ :type update_status: bool
240
+ :param vpn_action: The action to perform with the VPN connection, either "up" or "down". Default is "up".
241
+ :type vpn_action: Literal["up", "down"]
242
+ :param vpn_raise_on_error: If True, an exception will be raised if an error occurs while connecting to VPN.
243
+ :type vpn_raise_on_error: bool
244
+ :param only_for_development: If True, the debugging will be started only if the app is running in development mode.
245
+ It's not recommended to set this parameter to False in production environments.
246
+ :type only_for_development: bool
247
+ :return: The task ID of the debug task or None if the debugging was not started.
248
+ :rtype: Optional[int]
249
+
250
+ :Usage example:
251
+
252
+ .. code-block:: python
253
+
254
+ import supervisely as sly
255
+
256
+ os.environ['SERVER_ADDRESS'] = 'https://app.supervisely.com'
257
+ os.environ['API_TOKEN'] = 'Your Supervisely API Token'
258
+ api = sly.Api.from_env()
259
+
260
+ # Ensure that the TEAM_ID environment variable is set.
261
+ # Or provide the team ID as an argument to the function.
262
+ os.environ['TEAM_ID'] = 123456
263
+
264
+ # The task ID can be used to make requests to the app.
265
+ task_id = sly.app.development.enable_advanced_debug()
266
+
267
+ # An example of how to send a request to the app using the task ID.
268
+ data = {"project_id": 789, "force": True}
269
+ api.task.send_request(task_id, "endpoint-name-here", data, skip_response=True)
270
+ """
271
+
272
+ if only_for_development and not is_development():
273
+ logger.debug(
274
+ "Advanced debugging was not started because the app is not running in development mode. "
275
+ "If you need to force the debugging, set the only_for_development argument to False. "
276
+ "Use this parameter with caution, and do not set to False in production environments."
277
+ )
278
+ return None
279
+
280
+ logger.debug(
281
+ "Starting advanced debugging, will create a wireguard VPN connection and create "
282
+ "or use an existing debug task to redirect requests to the local machine. "
283
+ "Learn more about this feature in Supervisely Developer Portal: "
284
+ "https://developer.supervisely.com/app-development/advanced/advanced-debugging"
285
+ )
286
+
287
+ supervisely_vpn_network(action=vpn_action, raise_on_error=vpn_raise_on_error)
288
+ task = create_debug_task(team_id=team_id, port=port, update_status=update_status)
289
+ task_id = task.get("id", None)
290
+
291
+ logger.debug(
292
+ f"Advanced debugging has been started. "
293
+ f"VPN connection has been established and debug task has been create. Task ID: {task_id}. "
294
+ "The metod will return the task ID, you can use it to make requests to the app."
295
+ )
296
+
297
+ return task_id
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import inspect
2
3
  import signal
3
4
  import sys
4
5
  from contextlib import suppress
@@ -1012,11 +1013,15 @@ class Application(metaclass=Singleton):
1012
1013
  self._graceful_stop_event.set()
1013
1014
  return suppress(self.StopException)
1014
1015
 
1015
- def event(self, event: Event) -> Callable:
1016
+ def event(self, event: Event, use_state: bool = False) -> Callable:
1016
1017
  """Decorator to register posts to specific endpoints.
1018
+ Supports both async and sync functions.
1017
1019
 
1018
1020
  :param event: event to register (e.g. `Event.Brush.LeftMouseReleased`)
1019
1021
  :type event: Event
1022
+ :param use_state: if set to True, data will be extracted from request.state.state,
1023
+ otherwise from request.state.context, defaults to False
1024
+ :type use_state: bool, optional
1020
1025
  :return: decorator
1021
1026
  :rtype: Callable
1022
1027
 
@@ -1037,9 +1042,19 @@ class Application(metaclass=Singleton):
1037
1042
  def inner(func: Callable) -> Callable:
1038
1043
  server = self.get_server()
1039
1044
 
1040
- @server.post(event.endpoint)
1041
- def wrapper(request: Request):
1042
- return func(request.state.api, event.from_json(request.state.context))
1045
+ if inspect.iscoroutinefunction(func):
1046
+
1047
+ @server.post(event.endpoint)
1048
+ async def wrapper(request: Request):
1049
+ data = request.state.state if use_state else request.state.context
1050
+ return await func(request.state.api, event.from_json(data))
1051
+
1052
+ else:
1053
+
1054
+ @server.post(event.endpoint)
1055
+ def wrapper(request: Request):
1056
+ data = request.state.state if use_state else request.state.context
1057
+ return func(request.state.api, event.from_json(data))
1043
1058
 
1044
1059
  return wrapper
1045
1060
 
@@ -286,15 +286,23 @@ class BaseConverter:
286
286
  return found_formats[0]
287
287
 
288
288
  def _collect_items_if_format_not_detected(self):
289
+ from supervisely.convert.pointcloud_episodes.pointcloud_episodes_converter import (
290
+ PointcloudEpisodeConverter,
291
+ )
292
+
289
293
  only_modality_items = True
290
294
  unsupported_exts = set()
291
295
  items = []
296
+ is_episode = isinstance(self, PointcloudEpisodeConverter)
292
297
  for root, _, files in os.walk(self._input_data):
293
298
  for file in files:
294
299
  full_path = os.path.join(root, file)
295
300
  ext = get_file_ext(full_path)
296
301
  if ext.lower() in self.allowed_exts: # pylint: disable=no-member
297
- items.append(self.Item(full_path)) # pylint: disable=no-member
302
+ if is_episode:
303
+ items.append(self.Item(full_path, len(items))) # pylint: disable=no-member
304
+ else:
305
+ items.append(self.Item(full_path)) # pylint: disable=no-member
298
306
  continue
299
307
  only_modality_items = False
300
308
  if ext.lower() in self.unsupported_exts:
@@ -71,11 +71,17 @@ class SLYPointcloudEpisodesConverter(PointcloudEpisodeConverter):
71
71
  continue
72
72
 
73
73
  ext = get_file_ext(full_path)
74
+ recognized_ext = imghdr.what(full_path)
74
75
  if file in JUNK_FILES:
75
76
  continue
76
77
  elif ext in self.ann_ext:
77
78
  rimg_json_dict[file] = full_path
78
- elif imghdr.what(full_path):
79
+ elif recognized_ext:
80
+ if ext.lower() == ".pcd":
81
+ logger.warning(
82
+ f"File '{file}' has been recognized as '.{recognized_ext}' format. Skipping."
83
+ )
84
+ continue
79
85
  rimg_dict[file] = full_path
80
86
  if ext not in used_img_ext:
81
87
  used_img_ext.append(ext)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: supervisely
3
- Version: 6.73.220
3
+ Version: 6.73.221
4
4
  Summary: Supervisely Python SDK.
5
5
  Home-page: https://github.com/supervisely/supervisely
6
6
  Author: Supervisely
@@ -25,7 +25,7 @@ supervisely/api/annotation_api.py,sha256=Eps-Jf10_SQFy7DjghUnyiM6DcVJBsamHDViRAX
25
25
  supervisely/api/api.py,sha256=YQ939NaIMDrZSb5ael1W8foKZOIIrB0TC2iTBCvTvWA,37198
26
26
  supervisely/api/app_api.py,sha256=zX3Iy16RuGwtcLZfMs3YfUFc93S9AVGb3W_eINeMjOs,66729
27
27
  supervisely/api/dataset_api.py,sha256=7iwAyz3pmzFG2i072gLdXjczfBGbyj-V_rRl7Tx-V30,37944
28
- supervisely/api/file_api.py,sha256=y8FkE-vx1382cbhNo_rTZs7SobrkxmYQAe79CpvStO4,54279
28
+ supervisely/api/file_api.py,sha256=PfZe01eUpUHMIT_SCS7fac6WvUqNqPnEQ0XJmJ8TJlE,56223
29
29
  supervisely/api/github_api.py,sha256=NIexNjEer9H5rf5sw2LEZd7C1WR-tK4t6IZzsgeAAwQ,623
30
30
  supervisely/api/image_annotation_tool_api.py,sha256=YcUo78jRDBJYvIjrd-Y6FJAasLta54nnxhyaGyanovA,5237
31
31
  supervisely/api/image_api.py,sha256=wnzoCbD5vV8f8joBQsNCbRjoG0jhyAXHe1ZM8YhbCsc,138727
@@ -83,8 +83,8 @@ supervisely/app/import_template.py,sha256=H2jaVekt9GZvz6FdzfrT8sJTS3VJY8JeXTCJiR
83
83
  supervisely/app/jinja2.py,sha256=H3TCoLDCdTfO7Fq3ZDtcBNqfyZBlNr7p8qcKrE88HE8,341
84
84
  supervisely/app/singleton.py,sha256=g8FI4vqt76tXF09tsb05N_N4ouTI0LJGZekrgVkulg0,406
85
85
  supervisely/app/widgets_context.py,sha256=JkAd4o87eqhkGJbai-Yq6YHULiPsbp1VwGOSBRxTOgY,313
86
- supervisely/app/development/__init__.py,sha256=Yx368OqG_YUksH9jayAbMKZwjxMaQi3IBfcx2wODtjY,108
87
- supervisely/app/development/development.py,sha256=p7ikzMTa5Q2uhvH0bZGiJAsRHsOjBmd203js6YNmaNQ,8223
86
+ supervisely/app/development/__init__.py,sha256=f2SpWBcCFPbSEBsJijH25eCAK8NcY2An5NU9vPgCBVo,135
87
+ supervisely/app/development/development.py,sha256=Ij3tn7HmkHr2RRoYxlpK9xkTGnpFjZwy2kArn6ZxVnA,12505
88
88
  supervisely/app/development/sly-net.sh,sha256=-EVburj4NtS7Dw4OiwXXolYu9SXvui83F-c2T8jWm-Y,1105
89
89
  supervisely/app/fastapi/__init__.py,sha256=kNhkaGuBKn9-GNnPOmikIHqhjL-j66xmZaBbjCmXfAo,460
90
90
  supervisely/app/fastapi/custom_static_files.py,sha256=5todaVIvUG9sAt6vu1IujJn8N7zTmFhVUfeCVbuXbvc,3391
@@ -93,7 +93,7 @@ supervisely/app/fastapi/index.html,sha256=4kF8PWYvssCX2iH0jOOq0dCcKxQfndpJbTzUF4
93
93
  supervisely/app/fastapi/no_html_main.html,sha256=NhQP7noyORBx72lFh1CQKgBRupkWjiq6Gaw-9Hkvg7c,37
94
94
  supervisely/app/fastapi/offline.py,sha256=CwMMkJ1frD6wiZS-SEoNDtQ1UJcJe1Ob6ohE3r4CQL8,7414
95
95
  supervisely/app/fastapi/request.py,sha256=NU7rKmxJ1pfkDZ7_yHckRcRAueJRQIqCor11UO2OHr8,766
96
- supervisely/app/fastapi/subapp.py,sha256=uZNRG-mX8tPdN-adVAWgv4wKr-4D3uqqMJWKikCSQtU,42706
96
+ supervisely/app/fastapi/subapp.py,sha256=kvycQ2NSsitbdWxaSzGPjzNzvplONqi9UbNnfeAWryw,43411
97
97
  supervisely/app/fastapi/templating.py,sha256=3JO4WmQKfPMmb8xhSuV5knWCen3gTgfdqWpIx4RSJlg,2330
98
98
  supervisely/app/fastapi/utils.py,sha256=GZuTWLcVRGVx8TL3jVEYUOZIT2FawbwIe2kAOBLw9ho,398
99
99
  supervisely/app/fastapi/websocket.py,sha256=TlRSPOAhRItTv1HGvdukK1ZvhRjMUxRa-lJlsRR9rJw,1308
@@ -554,7 +554,7 @@ supervisely/collection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
554
554
  supervisely/collection/key_indexed_collection.py,sha256=x2UVlkprspWhhae9oLUzjTWBoIouiWY9UQSS_MozfH0,37643
555
555
  supervisely/collection/str_enum.py,sha256=Zp29yFGvnxC6oJRYNNlXhO2lTSdsriU1wiGHj6ahEJE,1250
556
556
  supervisely/convert/__init__.py,sha256=gRTV93OYJPI3FNfy78HO2SfR59qQ3FFKFSy_jw1adJ8,2571
557
- supervisely/convert/base_converter.py,sha256=F5oCwQZ_w7XlIIQnW-y-2scvA9sC8vCJL2XMP3DtPZg,14343
557
+ supervisely/convert/base_converter.py,sha256=6HAiKPuwHS-aP7id4JCb650k9fjYrMJc_xILcO1BUwI,14717
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=6GC8-erDTIJnjkcDvaxs8VAItBNsJrMHaZtOcOsphew,9537
@@ -620,7 +620,7 @@ supervisely/convert/pointcloud_episodes/pointcloud_episodes_converter.py,sha256=
620
620
  supervisely/convert/pointcloud_episodes/bag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
621
621
  supervisely/convert/pointcloud_episodes/bag/bag_converter.py,sha256=jzWKXoFUWu11d5WlPfT1hphCubYpq_lhQZmhh07xZdQ,1659
622
622
  supervisely/convert/pointcloud_episodes/sly/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
623
- supervisely/convert/pointcloud_episodes/sly/sly_pointcloud_episodes_converter.py,sha256=JD733jWyLXSljRNRAij5OTriaPrnPB6aIdQgQcUc_pg,5889
623
+ supervisely/convert/pointcloud_episodes/sly/sly_pointcloud_episodes_converter.py,sha256=7ONcZMOUJCNpmc0tmMX6FnNG0lu8Nj9K2SSTQHaSXFM,6188
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
626
  supervisely/convert/video/video_converter.py,sha256=ZMvZfrzglh5GsSp7fbtQwNsijDqPRrVmPxwAlGVAqOk,10648
@@ -997,9 +997,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
997
997
  supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
998
998
  supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
999
999
  supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
1000
- supervisely-6.73.220.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1001
- supervisely-6.73.220.dist-info/METADATA,sha256=FBTFB3GBrRDD6WPzIBQXWG1jgBIaxwFoIjaYJuFJUSk,33090
1002
- supervisely-6.73.220.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1003
- supervisely-6.73.220.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1004
- supervisely-6.73.220.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1005
- supervisely-6.73.220.dist-info/RECORD,,
1000
+ supervisely-6.73.221.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1001
+ supervisely-6.73.221.dist-info/METADATA,sha256=2F4Io8Yd8IAMGT1n7eNXEzMTvqAyH53k420bqxMBh2Q,33090
1002
+ supervisely-6.73.221.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1003
+ supervisely-6.73.221.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1004
+ supervisely-6.73.221.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1005
+ supervisely-6.73.221.dist-info/RECORD,,