unitlab 2.3.46__tar.gz → 2.3.48__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unitlab
3
- Version: 2.3.46
3
+ Version: 2.3.48
4
4
  Home-page: https://github.com/teamunitlab/unitlab-sdk
5
5
  Author: Unitlab Inc.
6
6
  Author-email: team@unitlab.ai
@@ -2,11 +2,11 @@ from setuptools import find_packages, setup
2
2
 
3
3
  setup(
4
4
  name="unitlab",
5
- version="2.3.46",
5
+ version="2.3.48",
6
6
  license="MIT",
7
7
  author="Unitlab Inc.",
8
8
  author_email="team@unitlab.ai",
9
- packages=find_packages("src"),
9
+ packages=find_packages(where="src"),
10
10
  include_package_data=True,
11
11
  package_data={"static": ["*"], "Potato": ["*.so"]},
12
12
  classifiers=[
@@ -113,24 +113,43 @@ class UnitlabClient:
113
113
  def project_members(self, project_id, pretty=0):
114
114
  return self._get(f"/api/sdk/projects/{project_id}/members/?pretty={pretty}")
115
115
 
116
- def project_upload_data(self, project_id, directory, batch_size=100):
116
+ def project_upload_info(self, project_id):
117
+ return self._get(f"/api/sdk/projects/{project_id}/upload-info/")
118
+
119
+ def project_upload_data(
120
+ self,
121
+ project_id,
122
+ directory,
123
+ batch_size=100,
124
+ sentences_per_chunk=10,
125
+ fps=1.0,
126
+ ):
117
127
  if not os.path.isdir(directory):
118
128
  raise ValueError(f"Directory {directory} does not exist")
119
129
 
130
+ upload_info = self.project_upload_info(project_id)
131
+ accepted_formats = upload_info["accepted_formats"]
132
+ max_file_size_bytes = upload_info["max_file_size"]
133
+ generic_type = upload_info["generic_type"]
134
+
120
135
  files = [
121
136
  file
122
137
  for files_list in (
123
- glob.glob(os.path.join(directory, "") + extension)
124
- for extension in ["*jpg", "*png", "*jpeg", "*webp"]
138
+ glob.glob(os.path.join(directory, "") + f"*.{ext}")
139
+ for ext in accepted_formats
125
140
  )
126
141
  for file in files_list
127
142
  ]
143
+
128
144
  filtered_files = []
145
+ max_file_size_mb = max_file_size_bytes / 1024 / 1024
129
146
  for file in files:
130
- file_size = os.path.getsize(file) / 1024 / 1024
131
- if file_size > 6:
147
+ file_size_bytes = os.path.getsize(file)
148
+ if file_size_bytes > max_file_size_bytes:
149
+ file_size_mb = file_size_bytes / 1024 / 1024
132
150
  logger.warning(
133
- f"File {file} is too large ({file_size:.4f} megabytes) skipping, max size is 6 MB"
151
+ f"File {file} is too large ({file_size_mb:.4f} MB) skipping, "
152
+ f"max size is {max_file_size_mb:.2f} MB"
134
153
  )
135
154
  continue
136
155
  filtered_files.append(file)
@@ -141,14 +160,20 @@ class UnitlabClient:
141
160
  async def post_file(session: aiohttp.ClientSession, file: str, project_id: str):
142
161
  async with aiofiles.open(file, "rb") as f:
143
162
  form_data = aiohttp.FormData()
144
- form_data.add_field("project", project_id)
145
163
  form_data.add_field(
146
164
  "file", await f.read(), filename=os.path.basename(file)
147
165
  )
166
+ if generic_type == "text":
167
+ form_data.add_field("sentences_per_chunk", str(sentences_per_chunk))
168
+ elif generic_type == "video":
169
+ form_data.add_field("fps", str(fps))
170
+
148
171
  try:
149
172
  await asyncio.sleep(0.1)
150
173
  async with session.post(
151
- urllib.parse.urljoin(self.api_url, "/api/sdk/upload-data/"),
174
+ urllib.parse.urljoin(
175
+ self.api_url, f"/api/sdk/projects/{project_id}/upload-data/"
176
+ ),
152
177
  data=form_data,
153
178
  ) as response:
154
179
  response.raise_for_status()
@@ -204,16 +229,44 @@ class UnitlabClient:
204
229
  return os.path.abspath(filename)
205
230
 
206
231
  def dataset_download_files(self, dataset_id):
232
+ """Download files from a dataset.
233
+
234
+ Args:
235
+ dataset_id: UUID of the dataset/release to download.
236
+
237
+ Returns:
238
+ Path to the download folder.
239
+ """
207
240
  response = self._post(
208
241
  f"/api/sdk/datasets/{dataset_id}/", data={"download_type": "files"}
209
242
  )
210
- folder = f"dataset-files-{dataset_id}"
211
- os.makedirs(folder, exist_ok=True)
212
- dataset_files = [
213
- dataset_file
214
- for dataset_file in response
215
- if not os.path.isfile(os.path.join(folder, dataset_file["file_name"]))
216
- ]
243
+ base_folder = f"dataset-files-{dataset_id}"
244
+ os.makedirs(base_folder, exist_ok=True)
245
+
246
+ files_to_download = []
247
+ for dataset_file in response:
248
+ file_name = dataset_file["file_name"]
249
+ file_path = os.path.join(base_folder, file_name)
250
+
251
+ parent_dir = os.path.dirname(file_path)
252
+ if parent_dir:
253
+ os.makedirs(parent_dir, exist_ok=True)
254
+
255
+ if "content" in dataset_file:
256
+ if not os.path.isfile(file_path):
257
+ with open(file_path, "w", encoding="utf-8") as f:
258
+ f.write(dataset_file["content"])
259
+ elif "source" in dataset_file and not os.path.isfile(file_path):
260
+ files_to_download.append(
261
+ {
262
+ "file_name": file_name,
263
+ "source": dataset_file["source"],
264
+ "file_path": file_path,
265
+ }
266
+ )
267
+
268
+ if not files_to_download:
269
+ return base_folder
217
270
 
218
271
  async def download_file(session: aiohttp.ClientSession, dataset_file: dict):
219
272
  async with session.get(url=dataset_file["source"]) as r:
@@ -224,21 +277,20 @@ class UnitlabClient:
224
277
  f"Error downloading file {dataset_file['file_name']} - {e}"
225
278
  )
226
279
  return 0
227
- async with aiofiles.open(
228
- os.path.join(folder, dataset_file["file_name"]), "wb"
229
- ) as f:
280
+ async with aiofiles.open(dataset_file["file_path"], "wb") as f:
230
281
  async for chunk in r.content.iter_any():
231
282
  await f.write(chunk)
232
283
  return 1
233
284
 
234
285
  async def main():
235
- with tqdm.tqdm(total=len(dataset_files), ncols=80) as pbar:
286
+ with tqdm.tqdm(total=len(files_to_download), ncols=80) as pbar:
236
287
  async with aiohttp.ClientSession() as session:
237
288
  tasks = [
238
- download_file(session=session, dataset_file=dataset_file)
239
- for dataset_file in dataset_files
289
+ download_file(session=session, dataset_file=df)
290
+ for df in files_to_download
240
291
  ]
241
292
  for f in asyncio.as_completed(tasks):
242
293
  pbar.update(await f)
243
294
 
244
295
  asyncio.run(main())
296
+ return base_folder
@@ -72,8 +72,25 @@ def upload(
72
72
  directory: Annotated[
73
73
  Path, typer.Option(help="Directory containing the data to be uploaded")
74
74
  ],
75
+ sentences_per_chunk: Annotated[
76
+ int,
77
+ typer.Option(
78
+ help="Number of sentences per chunk for text projects (default: 10, range: 3-50)"
79
+ ),
80
+ ] = 10,
81
+ fps: Annotated[
82
+ float,
83
+ typer.Option(
84
+ help="Frames per second for video projects (default: 1.0, min: 0.25)"
85
+ ),
86
+ ] = 1.0,
75
87
  ):
76
- get_client(api_key).project_upload_data(str(pk), directory=directory)
88
+ get_client(api_key).project_upload_data(
89
+ str(pk),
90
+ directory=directory,
91
+ sentences_per_chunk=sentences_per_chunk,
92
+ fps=fps,
93
+ )
77
94
 
78
95
 
79
96
  @dataset_app.command(name="list", help="List datasets")
@@ -105,8 +122,9 @@ def dataset_download(
105
122
  raise typer.BadParameter(
106
123
  "Split type is required when download type is annotation"
107
124
  )
108
- return get_client(api_key).dataset_download(pk, export_type, split_type)
109
- get_client(api_key).dataset_download_files(pk)
125
+ print(get_client(api_key).dataset_download(pk, export_type, split_type))
126
+ else:
127
+ print(get_client(api_key).dataset_download_files(pk))
110
128
 
111
129
 
112
130
  if __name__ == "__main__":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: unitlab
3
- Version: 2.3.46
3
+ Version: 2.3.48
4
4
  Home-page: https://github.com/teamunitlab/unitlab-sdk
5
5
  Author: Unitlab Inc.
6
6
  Author-email: team@unitlab.ai
File without changes
File without changes
File without changes
File without changes