kleinkram 0.0.119__py3-none-any.whl → 0.0.121.dev20240731104925__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,11 @@ 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[List[str]] = typer.Option(
46
+ None, help="Comma separated list of topics"
47
+ ),
46
48
  ):
47
49
  """
48
50
  List all files with optional filters for project, mission, or topics.
@@ -115,12 +117,13 @@ def list_projects():
115
117
 
116
118
  @missions.command("list")
117
119
  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"),
120
+ project: Optional[str] = typer.Option(None, help="Name of Project"),
121
+ verbose: Optional[bool] = typer.Option(
122
+ False, help="Outputs a table with more information"
123
+ ),
120
124
  ):
121
125
  """
122
126
  List all missions with optional filter for project.
123
-
124
127
  """
125
128
  try:
126
129
  url = "/mission"
@@ -141,7 +144,9 @@ def list_missions(
141
144
  print("missions by Project:")
142
145
  if not verbose:
143
146
  for project_uuid, missions in missions_by_project_uuid.items():
144
- print(f"* {missions_by_project_uuid[project_uuid][0]['project']['name']}")
147
+ print(
148
+ f"* {missions_by_project_uuid[project_uuid][0]['project']['name']}"
149
+ )
145
150
  for mission in missions:
146
151
  print(f" - {mission['name']}")
147
152
  else:
@@ -163,8 +168,8 @@ def list_missions(
163
168
 
164
169
  @missions.command("byUUID")
165
170
  def mission_by_uuid(
166
- uuid: Annotated[str, typer.Argument()],
167
- json: Optional[bool] = typer.Option(False, help="Output as JSON"),
171
+ uuid: Annotated[str, typer.Argument()],
172
+ json: Optional[bool] = typer.Option(False, help="Output as JSON"),
168
173
  ):
169
174
  """
170
175
  Get mission name, project name, creator and table of its files given a Mission UUID
@@ -194,14 +199,16 @@ def mission_by_uuid(
194
199
 
195
200
  @topics.command("list")
196
201
  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
202
+ file: Annotated[str, typer.Option(help="Name of File")],
203
+ full: Annotated[
204
+ bool, typer.Option(help="As a table with additional parameters")
205
+ ] = False,
206
+ # Todo add mission / project as optional argument as filenames are not unique or handle multiple files
200
207
  ):
201
208
  """
202
209
  List topics for a file
203
210
 
204
- Only makes sense with MCAP files as we don't associate topics with BAGs.
211
+ Only makes sense with MCAP files as we don't associate topics with BAGs as that would be redundant.
205
212
  """
206
213
  if file.endswith(".bag"):
207
214
  print("BAG files generally do not have topics")
@@ -231,18 +238,22 @@ def topics(
231
238
 
232
239
  @projects.command("create")
233
240
  def create_project(
234
- name: Annotated[str, typer.Option(help="Name of Project")],
235
- description: Annotated[str, typer.Option(help="Description of Project")],
241
+ name: Annotated[str, typer.Option(help="Name of Project")],
242
+ description: Annotated[str, typer.Option(help="Description of Project")],
236
243
  ):
237
244
  """
238
245
  Create a new project
239
246
  """
247
+ #Todo add required tags as option.
240
248
  try:
241
249
  url = "/project/create"
242
- response = client.post(url, json={"name": name, "description": description, "requiredTags": []}) # TODO: Add required tags as option
250
+ response = client.post(
251
+ url, json={"name": name, "description": description, "requiredTags": []}
252
+ ) # TODO: Add required tags as option
243
253
  if response.status_code >= 400:
244
254
  response_json = response.json()
245
- print(f"Failed to create project: {response_json["message"]}")
255
+ response_text = response_json["message"]
256
+ print(f"Failed to create project: {response_text}")
246
257
  return
247
258
  print("Project created")
248
259
 
@@ -252,9 +263,13 @@ def create_project(
252
263
 
253
264
  @app.command("upload")
254
265
  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")],
266
+ path: Annotated[
267
+ str, typer.Option(prompt=True, help="Path to files to upload, Regex supported")
268
+ ],
269
+ project: Annotated[str, typer.Option(prompt=True, help="Name of Project")],
270
+ mission: Annotated[
271
+ str, typer.Option(prompt=True, help="Name of Mission to create")
272
+ ],
258
273
  ):
259
274
  """
260
275
  Upload files matching the path to a mission in a project.
@@ -265,7 +280,9 @@ def upload(
265
280
 
266
281
  """
267
282
  files = expand_and_match(path)
268
- filenames = list(map(lambda x: x.split("/")[-1], filter(lambda x: not os.path.isdir(x),files)))
283
+ filenames = list(
284
+ map(lambda x: x.split("/")[-1], filter(lambda x: not os.path.isdir(x), files))
285
+ )
269
286
  if not filenames:
270
287
  print("No files found")
271
288
  return
@@ -300,7 +317,8 @@ def upload(
300
317
 
301
318
  create_mission_url = "/mission/create"
302
319
  new_mission = client.post(
303
- create_mission_url, json={"name": mission, "projectUUID": project_json["uuid"], "tags": []}
320
+ create_mission_url,
321
+ json={"name": mission, "projectUUID": project_json["uuid"], "tags": []},
304
322
  )
305
323
  new_mission.raise_for_status()
306
324
  new_mission_data = new_mission.json()
@@ -466,7 +484,7 @@ def demote(email: Annotated[str, typer.Option()]):
466
484
 
467
485
  @files.command("download")
468
486
  def download(
469
- missionuuid: Annotated[str, typer.Argument()],
487
+ missionuuid: Annotated[str, typer.Argument()],
470
488
  ):
471
489
  """Download file"""
472
490
  try:
@@ -476,15 +494,19 @@ def download(
476
494
  except:
477
495
  print("Failed to download file")
478
496
 
479
- @missions.command('tag')
497
+
498
+ @missions.command("tag")
480
499
  def addTag(
481
- missionuuid: Annotated[str, typer.Argument()],
482
- tagtypeuuid: Annotated[str, typer.Argument()],
483
- value: Annotated[str, typer.Argument()],
500
+ missionuuid: Annotated[str, typer.Argument()],
501
+ tagtypeuuid: Annotated[str, typer.Argument()],
502
+ value: Annotated[str, typer.Argument()],
484
503
  ):
485
504
  """Tag a mission"""
486
505
  try:
487
- response = client.post("/tag/addTag", json={"mission": missionuuid, "tagType": tagtypeuuid, "value": value})
506
+ response = client.post(
507
+ "/tag/addTag",
508
+ json={"mission": missionuuid, "tagType": tagtypeuuid, "value": value},
509
+ )
488
510
  if response.status_code < 400:
489
511
  print("Tagged mission")
490
512
  else:
@@ -496,9 +518,9 @@ def addTag(
496
518
  sys.exit(1)
497
519
 
498
520
 
499
- @tagtypes.command('list')
521
+ @tagtypes.command("list")
500
522
  def tagTypes(
501
- verbose: Annotated[bool, typer.Option()] = False,
523
+ verbose: Annotated[bool, typer.Option()] = False,
502
524
  ):
503
525
  """List all tagtypes"""
504
526
  try:
@@ -506,7 +528,7 @@ def tagTypes(
506
528
  response.raise_for_status()
507
529
  data = response.json()
508
530
  if verbose:
509
- table = Table("UUID","Name", "Datatype")
531
+ table = Table("UUID", "Name", "Datatype")
510
532
  for tagtype in data:
511
533
  table.add_row(tagtype["uuid"], tagtype["name"], tagtype["datatype"])
512
534
  else:
@@ -517,9 +539,10 @@ def tagTypes(
517
539
  except:
518
540
  print("Failed to fetch tagtypes")
519
541
 
520
- @tag.command('delete')
542
+
543
+ @tag.command("delete")
521
544
  def deleteTag(
522
- taguuid: Annotated[str, typer.Argument()],
545
+ taguuid: Annotated[str, typer.Argument()],
523
546
  ):
524
547
  """Delete a tag"""
525
548
  try:
@@ -530,8 +553,7 @@ def deleteTag(
530
553
  print(response)
531
554
  print("Failed to delete tag")
532
555
  except:
533
- print("Failed to delete tag"
534
- )
556
+ print("Failed to delete tag")
535
557
 
536
558
 
537
559
  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.dev20240731104925
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=-T6Qx8OIRHbf4_DMd1IGaDaBEcXui6UYk-88rrPKAg0,18367
6
+ kleinkram-0.0.121.dev20240731104925.dist-info/METADATA,sha256=-FTioIAlssf9o_2yTC4yeX4mPVgv6AzBOGrYBfhUgJY,751
7
+ kleinkram-0.0.121.dev20240731104925.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
8
+ kleinkram-0.0.121.dev20240731104925.dist-info/entry_points.txt,sha256=RHXtRzcreVHImatgjhQwZQ6GdJThElYjHEWcR1BPXUI,45
9
+ kleinkram-0.0.121.dev20240731104925.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
10
+ kleinkram-0.0.121.dev20240731104925.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,,