kleinkram 0.0.119__py3-none-any.whl → 0.0.121__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 kleinkram might be problematic. Click here for more details.

kleinkram/auth.py CHANGED
@@ -94,7 +94,9 @@ class AuthenticatedClient(httpx.Client):
94
94
  self.tokenfile = TokenFile()
95
95
  self._load_cookies()
96
96
  except Exception as e:
97
- print(f"{self.tokenfile.endpoint} is not authenticated. Please run 'klein login'.")
97
+ print(
98
+ f"{self.tokenfile.endpoint} is not authenticated. Please run 'klein login'."
99
+ )
98
100
 
99
101
  def _load_cookies(self):
100
102
  if self.tokenfile.isCliToken():
@@ -110,7 +112,10 @@ class AuthenticatedClient(httpx.Client):
110
112
  if not refresh_token:
111
113
  print("No refresh token found. Please login again.")
112
114
  raise Exception("No refresh token found.")
113
- self.cookies.set(REFRESH_TOKEN, refresh_token, )
115
+ self.cookies.set(
116
+ REFRESH_TOKEN,
117
+ refresh_token,
118
+ )
114
119
  response = self.post(
115
120
  "/auth/refresh-token",
116
121
  )
@@ -124,16 +129,16 @@ class AuthenticatedClient(httpx.Client):
124
129
  response = super().request(
125
130
  method, self.tokenfile.endpoint + url, *args, **kwargs
126
131
  )
127
- if (
128
- url == "/auth/refresh-token"
129
- ) and response.status_code == 401:
132
+ if (url == "/auth/refresh-token") and response.status_code == 401:
130
133
  print("Refresh token expired. Please login again.")
131
134
  response.status_code = 403
132
135
  exit(1)
133
136
  if response.status_code == 401:
134
137
  print("Token expired, refreshing token...")
135
138
  self.refresh_token()
136
- response = super().request(method, self.tokenfile.endpoint + url, *args, **kwargs)
139
+ response = super().request(
140
+ method, self.tokenfile.endpoint + url, *args, **kwargs
141
+ )
137
142
  return response
138
143
 
139
144
 
@@ -141,8 +146,10 @@ client = AuthenticatedClient()
141
146
 
142
147
 
143
148
  def login(
144
- key: Optional[str] = typer.Option(None, help="CLI Key", hidden=True),
145
- open_browser: Optional[bool] = typer.Option(True, help="Open browser for authentication"),
149
+ key: Optional[str] = typer.Option(None, help="CLI Key", hidden=True),
150
+ open_browser: Optional[bool] = typer.Option(
151
+ True, help="Open browser for authentication"
152
+ ),
146
153
  ):
147
154
  """
148
155
  Login into the currently set endpoint.\n
@@ -175,12 +182,16 @@ def login(
175
182
 
176
183
  return
177
184
 
178
- print(f"Please open the following URL manually in your browser to authenticate: {url + '-no-redirect'}")
185
+ print(
186
+ f"Please open the following URL manually in your browser to authenticate: {url + '-no-redirect'}"
187
+ )
179
188
  print("Enter the authentication token provided after logging in:")
180
189
  manual_auth_token = input("Authentication Token: ")
181
190
  manual_refresh_token = input("Refresh Token: ")
182
191
  if manual_auth_token:
183
- tokenfile.saveTokens({AUTH_TOKEN: manual_auth_token, REFRESH_TOKEN: manual_refresh_token})
192
+ tokenfile.saveTokens(
193
+ {AUTH_TOKEN: manual_auth_token, REFRESH_TOKEN: manual_refresh_token}
194
+ )
184
195
  print("Authentication complete. Tokens saved to tokens.json.")
185
196
  else:
186
197
  print("No authentication token provided.")
@@ -188,7 +199,7 @@ def login(
188
199
 
189
200
 
190
201
  def setEndpoint(
191
- endpoint: Optional[str] = typer.Argument(None, help="API endpoint to use")
202
+ endpoint: Optional[str] = typer.Argument(None, help="API endpoint to use")
192
203
  ):
193
204
  """
194
205
  Set the current endpoint
@@ -220,9 +231,7 @@ def endpoint():
220
231
  print("- " + _endpoint)
221
232
 
222
233
 
223
- def setCliKey(
224
- key: Annotated[str, typer.Argument(help="CLI Key")]
225
- ):
234
+ def setCliKey(key: Annotated[str, typer.Argument(help="CLI Key")]):
226
235
  """
227
236
  Set the CLI key (Actions Only)
228
237
 
kleinkram/consts.py CHANGED
@@ -1,2 +1 @@
1
- API_URL = "http://localhost:3000"
2
- # API_URL = "https://api.datasets.leggedrobotics.com"
1
+ API_URL='https://api.datasets.leggedrobotics.com'
kleinkram/helper.py CHANGED
@@ -56,7 +56,9 @@ def uploadFile(_queue: queue.Queue, paths: Dict[str, str], pbar: tqdm):
56
56
  pbar.update(100) # Update progress for each file
57
57
  client.post("/queue/confirmUpload", json={"uuid": uuid})
58
58
  else:
59
- print(f"Failed to upload {filename}. HTTP status: {response.status_code}")
59
+ print(
60
+ f"Failed to upload {filename}. HTTP status: {response.status_code}"
61
+ )
60
62
  _queue.task_done()
61
63
  except queue.Empty:
62
64
  break
kleinkram/main.py CHANGED
@@ -18,7 +18,7 @@ projects = typer.Typer(name="projects", help="Project operations")
18
18
  missions = typer.Typer(name="missions", help="Mission operations")
19
19
  files = typer.Typer(name="files", help="File operations")
20
20
  topics = typer.Typer(name="topics", help="Topic operations")
21
- queue = typer.Typer(name="queue", help="Queue operations")
21
+ queue = typer.Typer(name="queue", help="Status of files uploading")
22
22
  user = typer.Typer(name="users", help="User operations")
23
23
  tagtypes = typer.Typer(name="tagtypes", help="TagType operations")
24
24
  tag = typer.Typer(name="tag", help="Tag operations")
@@ -40,9 +40,12 @@ app.command(hidden=True)(setCliKey)
40
40
 
41
41
  @files.command("list")
42
42
  def list_files(
43
- project: Optional[str] = typer.Option(None, help="Name of Project"),
44
- mission: Optional[str] = typer.Option(None, help="Name of Mission"),
45
- topics: Optional[List[str]] = typer.Option(None, help="Comma separated list of topics")
43
+ project: Optional[str] = typer.Option(None, help="Name of Project"),
44
+ mission: Optional[str] = typer.Option(None, help="Name of Mission"),
45
+ topics: Optional[str] = typer.Option(
46
+ None, help="Comma separated list of topics"
47
+ ),
48
+ tags: Optional[str] = typer.Option(None, help="Comma separated list of tagtype:tagvalue pairs")
46
49
  ):
47
50
  """
48
51
  List all files with optional filters for project, mission, or topics.
@@ -64,6 +67,11 @@ def list_files(
64
67
  params["missionName"] = mission
65
68
  if topics:
66
69
  params["topics"] = topics
70
+ if tags:
71
+ params["tags"] = {}
72
+ for tag in tags.split(","):
73
+ tagtype, tagvalue = tag.split("§")
74
+ params['tags'][tagtype] = tagvalue
67
75
  response = client.get(
68
76
  url,
69
77
  params=params,
@@ -115,12 +123,13 @@ def list_projects():
115
123
 
116
124
  @missions.command("list")
117
125
  def list_missions(
118
- project: Optional[str] = typer.Option(None, help="Name of Project"),
119
- verbose: Optional[bool] = typer.Option(False, help="Outputs a table with more information"),
126
+ project: Optional[str] = typer.Option(None, help="Name of Project"),
127
+ verbose: Optional[bool] = typer.Option(
128
+ False, help="Outputs a table with more information"
129
+ ),
120
130
  ):
121
131
  """
122
132
  List all missions with optional filter for project.
123
-
124
133
  """
125
134
  try:
126
135
  url = "/mission"
@@ -141,7 +150,9 @@ def list_missions(
141
150
  print("missions by Project:")
142
151
  if not verbose:
143
152
  for project_uuid, missions in missions_by_project_uuid.items():
144
- print(f"* {missions_by_project_uuid[project_uuid][0]['project']['name']}")
153
+ print(
154
+ f"* {missions_by_project_uuid[project_uuid][0]['project']['name']}"
155
+ )
145
156
  for mission in missions:
146
157
  print(f" - {mission['name']}")
147
158
  else:
@@ -163,8 +174,8 @@ def list_missions(
163
174
 
164
175
  @missions.command("byUUID")
165
176
  def mission_by_uuid(
166
- uuid: Annotated[str, typer.Argument()],
167
- json: Optional[bool] = typer.Option(False, help="Output as JSON"),
177
+ uuid: Annotated[str, typer.Argument()],
178
+ json: Optional[bool] = typer.Option(False, help="Output as JSON"),
168
179
  ):
169
180
  """
170
181
  Get mission name, project name, creator and table of its files given a Mission UUID
@@ -194,14 +205,16 @@ def mission_by_uuid(
194
205
 
195
206
  @topics.command("list")
196
207
  def topics(
197
- file: Annotated[str, typer.Option(help="Name of File")],
198
- full: Annotated[bool, typer.Option(help="As a table with additional parameters")] = False,
199
- # Todo add mission / project as optional argument as filenames are not unique
208
+ file: Annotated[str, typer.Option(help="Name of File")],
209
+ full: Annotated[
210
+ bool, typer.Option(help="As a table with additional parameters")
211
+ ] = False,
212
+ # Todo add mission / project as optional argument as filenames are not unique or handle multiple files
200
213
  ):
201
214
  """
202
215
  List topics for a file
203
216
 
204
- Only makes sense with MCAP files as we don't associate topics with BAGs.
217
+ Only makes sense with MCAP files as we don't associate topics with BAGs as that would be redundant.
205
218
  """
206
219
  if file.endswith(".bag"):
207
220
  print("BAG files generally do not have topics")
@@ -231,18 +244,22 @@ def topics(
231
244
 
232
245
  @projects.command("create")
233
246
  def create_project(
234
- name: Annotated[str, typer.Option(help="Name of Project")],
235
- description: Annotated[str, typer.Option(help="Description of Project")],
247
+ name: Annotated[str, typer.Option(help="Name of Project")],
248
+ description: Annotated[str, typer.Option(help="Description of Project")],
236
249
  ):
237
250
  """
238
251
  Create a new project
239
252
  """
253
+ # Todo add required tags as option.
240
254
  try:
241
255
  url = "/project/create"
242
- response = client.post(url, json={"name": name, "description": description, "requiredTags": []}) # TODO: Add required tags as option
256
+ response = client.post(
257
+ url, json={"name": name, "description": description, "requiredTags": []}
258
+ ) # TODO: Add required tags as option
243
259
  if response.status_code >= 400:
244
260
  response_json = response.json()
245
- print(f"Failed to create project: {response_json["message"]}")
261
+ response_text = response_json["message"]
262
+ print(f"Failed to create project: {response_text}")
246
263
  return
247
264
  print("Project created")
248
265
 
@@ -252,9 +269,13 @@ def create_project(
252
269
 
253
270
  @app.command("upload")
254
271
  def upload(
255
- path: Annotated[str, typer.Option(prompt=True, help="Path to files to upload, Regex supported")],
256
- project: Annotated[str, typer.Option(prompt=True, help="Name of Project")],
257
- mission: Annotated[str, typer.Option(prompt=True, help="Name of Mission to create")],
272
+ path: Annotated[
273
+ str, typer.Option(prompt=True, help="Path to files to upload, Regex supported")
274
+ ],
275
+ project: Annotated[str, typer.Option(prompt=True, help="Name of Project")],
276
+ mission: Annotated[
277
+ str, typer.Option(prompt=True, help="Name of Mission to create")
278
+ ],
258
279
  ):
259
280
  """
260
281
  Upload files matching the path to a mission in a project.
@@ -265,7 +286,9 @@ def upload(
265
286
 
266
287
  """
267
288
  files = expand_and_match(path)
268
- filenames = list(map(lambda x: x.split("/")[-1], filter(lambda x: not os.path.isdir(x),files)))
289
+ filenames = list(
290
+ map(lambda x: x.split("/")[-1], filter(lambda x: not os.path.isdir(x), files))
291
+ )
269
292
  if not filenames:
270
293
  print("No files found")
271
294
  return
@@ -300,7 +323,8 @@ def upload(
300
323
 
301
324
  create_mission_url = "/mission/create"
302
325
  new_mission = client.post(
303
- create_mission_url, json={"name": mission, "projectUUID": project_json["uuid"], "tags": []}
326
+ create_mission_url,
327
+ json={"name": mission, "projectUUID": project_json["uuid"], "tags": []},
304
328
  )
305
329
  new_mission.raise_for_status()
306
330
  new_mission_data = new_mission.json()
@@ -466,7 +490,7 @@ def demote(email: Annotated[str, typer.Option()]):
466
490
 
467
491
  @files.command("download")
468
492
  def download(
469
- missionuuid: Annotated[str, typer.Argument()],
493
+ missionuuid: Annotated[str, typer.Argument()],
470
494
  ):
471
495
  """Download file"""
472
496
  try:
@@ -476,15 +500,19 @@ def download(
476
500
  except:
477
501
  print("Failed to download file")
478
502
 
479
- @missions.command('tag')
503
+
504
+ @missions.command("tag")
480
505
  def addTag(
481
- missionuuid: Annotated[str, typer.Argument()],
482
- tagtypeuuid: Annotated[str, typer.Argument()],
483
- value: Annotated[str, typer.Argument()],
506
+ missionuuid: Annotated[str, typer.Argument()],
507
+ tagtypeuuid: Annotated[str, typer.Argument()],
508
+ value: Annotated[str, typer.Argument()],
484
509
  ):
485
510
  """Tag a mission"""
486
511
  try:
487
- response = client.post("/tag/addTag", json={"mission": missionuuid, "tagType": tagtypeuuid, "value": value})
512
+ response = client.post(
513
+ "/tag/addTag",
514
+ json={"mission": missionuuid, "tagType": tagtypeuuid, "value": value},
515
+ )
488
516
  if response.status_code < 400:
489
517
  print("Tagged mission")
490
518
  else:
@@ -496,9 +524,9 @@ def addTag(
496
524
  sys.exit(1)
497
525
 
498
526
 
499
- @tagtypes.command('list')
527
+ @tagtypes.command("list")
500
528
  def tagTypes(
501
- verbose: Annotated[bool, typer.Option()] = False,
529
+ verbose: Annotated[bool, typer.Option()] = False,
502
530
  ):
503
531
  """List all tagtypes"""
504
532
  try:
@@ -506,7 +534,7 @@ def tagTypes(
506
534
  response.raise_for_status()
507
535
  data = response.json()
508
536
  if verbose:
509
- table = Table("UUID","Name", "Datatype")
537
+ table = Table("UUID", "Name", "Datatype")
510
538
  for tagtype in data:
511
539
  table.add_row(tagtype["uuid"], tagtype["name"], tagtype["datatype"])
512
540
  else:
@@ -517,9 +545,10 @@ def tagTypes(
517
545
  except:
518
546
  print("Failed to fetch tagtypes")
519
547
 
520
- @tag.command('delete')
548
+
549
+ @tag.command("delete")
521
550
  def deleteTag(
522
- taguuid: Annotated[str, typer.Argument()],
551
+ taguuid: Annotated[str, typer.Argument()],
523
552
  ):
524
553
  """Delete a tag"""
525
554
  try:
@@ -530,8 +559,7 @@ def deleteTag(
530
559
  print(response)
531
560
  print("Failed to delete tag")
532
561
  except:
533
- print("Failed to delete tag"
534
- )
562
+ print("Failed to delete tag")
535
563
 
536
564
 
537
565
  if __name__ == "__main__":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: kleinkram
3
- Version: 0.0.119
3
+ Version: 0.0.121
4
4
  Summary: A CLI for the ETH project kleinkram
5
5
  Project-URL: Homepage, https://github.com/leggedrobotics/kleinkram
6
6
  Project-URL: Issues, https://github.com/leggedrobotics/kleinkram/issues
@@ -0,0 +1,10 @@
1
+ kleinkram/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ kleinkram/auth.py,sha256=-XxVw3qLbWHT5Pv-yFyyxagu01RP8FlFLY-P274inYc,7739
3
+ kleinkram/consts.py,sha256=pm_6OuQcO-tYcRhwauTtyRRsuYY0y0yb6EGuIl49LnI,50
4
+ kleinkram/helper.py,sha256=5JbDBgaWjfenCHsRbNSdVZo7XfDaJ8VK_it7edi0ERU,2252
5
+ kleinkram/main.py,sha256=-fW92VMubBAryGWXNskW-X2Chza6Ay79mtW5C1t5WHs,18654
6
+ kleinkram-0.0.121.dist-info/METADATA,sha256=CxBUCrJCcK706BKz5z9IxYcFdUE2CFUsHLTeEQPeiYQ,733
7
+ kleinkram-0.0.121.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
8
+ kleinkram-0.0.121.dist-info/entry_points.txt,sha256=RHXtRzcreVHImatgjhQwZQ6GdJThElYjHEWcR1BPXUI,45
9
+ kleinkram-0.0.121.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
10
+ kleinkram-0.0.121.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- kleinkram/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- kleinkram/auth.py,sha256=s6Lek1vLRs2cXSwfGmEWuuzmszMhaTAJbh9icxWPSkQ,7628
3
- kleinkram/consts.py,sha256=8kCOeSdMqEyB89hT55w5yd1fksUwbj52a2nYkZTZI_0,88
4
- kleinkram/helper.py,sha256=mP6AohHWU8kckAi1Oevgs0gfGPH1Qzkp0f7jiQF9u5I,2198
5
- kleinkram/main.py,sha256=NuBeWg_vykRWf7TLgYidyKQ5us_8WHc7tcutTjbukx4,18113
6
- kleinkram-0.0.119.dist-info/METADATA,sha256=jE5GOIwBPIMaF_2EAeixcwsRq894O0JITOZC-tgR0J8,733
7
- kleinkram-0.0.119.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
8
- kleinkram-0.0.119.dist-info/entry_points.txt,sha256=RHXtRzcreVHImatgjhQwZQ6GdJThElYjHEWcR1BPXUI,45
9
- kleinkram-0.0.119.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
10
- kleinkram-0.0.119.dist-info/RECORD,,