kleinkram 0.22.2.dev20240924083348__tar.gz → 0.23.1.dev20240925145619__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.

Potentially problematic release.


This version of kleinkram might be problematic. Click here for more details.

Files changed (24) hide show
  1. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/PKG-INFO +1 -1
  2. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/pyproject.toml +1 -1
  3. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/file/file.py +5 -1
  4. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/main.py +7 -4
  5. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/mission/mission.py +65 -8
  6. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/.gitignore +0 -0
  7. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/LICENSE +0 -0
  8. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/README.md +0 -0
  9. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/deploy.sh +0 -0
  10. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/dev.sh +0 -0
  11. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/requirements.txt +0 -0
  12. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/klein.py +0 -0
  13. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/__init__.py +0 -0
  14. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/api_client.py +0 -0
  15. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/auth/auth.py +0 -0
  16. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/consts.py +0 -0
  17. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/endpoint/endpoint.py +0 -0
  18. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/error_handling.py +0 -0
  19. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/helper.py +0 -0
  20. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/project/project.py +0 -0
  21. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/queue/queue.py +0 -0
  22. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/tag/tag.py +0 -0
  23. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/topic/topic.py +0 -0
  24. {kleinkram-0.22.2.dev20240924083348 → kleinkram-0.23.1.dev20240925145619}/src/kleinkram/user/user.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: kleinkram
3
- Version: 0.22.2.dev20240924083348
3
+ Version: 0.23.1.dev20240925145619
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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "kleinkram"
7
- version = "0.22.2-dev20240924083348"
7
+ version = "0.23.1-dev20240925145619"
8
8
  description = "A CLI for the ETH project kleinkram"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.7"
@@ -56,7 +56,11 @@ def list_files(
56
56
  url,
57
57
  params=params,
58
58
  )
59
- response.raise_for_status()
59
+ if response.status_code >= 400:
60
+ raise AccessDeniedException(
61
+ f"Failed to fetch files: {response.json()['message']} ({response.status_code})",
62
+ "Access Denied",
63
+ )
60
64
  data = response.json()
61
65
  missions_by_project_uuid = {}
62
66
  files_by_mission_uuid = {}
@@ -16,7 +16,7 @@ from kleinkram.auth.auth import login, setCliKey, logout
16
16
  from kleinkram.endpoint.endpoint import endpoint
17
17
  from kleinkram.error_handling import ErrorHandledTyper, AccessDeniedException
18
18
  from kleinkram.file.file import file
19
- from kleinkram.mission.mission import mission
19
+ from kleinkram.mission.mission import missionCommands
20
20
  from kleinkram.project.project import project
21
21
  from kleinkram.queue.queue import queue
22
22
  from kleinkram.tag.tag import tag
@@ -33,7 +33,10 @@ class CommandPanel(str, Enum):
33
33
 
34
34
  def version_callback(value: bool):
35
35
  if value:
36
- _version = importlib.metadata.version("kleinkram")
36
+ try:
37
+ _version = importlib.metadata.version("kleinkram")
38
+ except importlib.metadata.PackageNotFoundError:
39
+ _version = "local"
37
40
  typer.echo(f"CLI Version: {_version}")
38
41
  raise typer.Exit()
39
42
 
@@ -88,7 +91,7 @@ def version(
88
91
 
89
92
 
90
93
  app.add_typer(project, rich_help_panel=CommandPanel.Commands)
91
- app.add_typer(mission, rich_help_panel=CommandPanel.Commands)
94
+ app.add_typer(missionCommands, rich_help_panel=CommandPanel.Commands)
92
95
 
93
96
  app.add_typer(topic, rich_help_panel=CommandPanel.Commands)
94
97
  app.add_typer(file, rich_help_panel=CommandPanel.Commands)
@@ -223,7 +226,7 @@ def upload(
223
226
  for _file in filenames:
224
227
  if not _file in confirmed_files.keys():
225
228
  raise Exception(
226
- "Could not upload File '" + file + "'. Is the filename unique? "
229
+ "Could not upload File '" + _file + "'. Is the filename unique? "
227
230
  )
228
231
  confirmed_files[_file]["filepath"] = filepaths[_file]
229
232
  if len(confirmed_files.keys()) > 0:
@@ -9,8 +9,9 @@ from rich.table import Table
9
9
 
10
10
  from kleinkram.api_client import AuthenticatedClient
11
11
  from kleinkram.error_handling import AccessDeniedException
12
+ from kleinkram.helper import expand_and_match, uploadFiles
12
13
 
13
- mission = typer.Typer(
14
+ missionCommands = typer.Typer(
14
15
  name="mission",
15
16
  help="Mission operations",
16
17
  no_args_is_help=True,
@@ -18,7 +19,7 @@ mission = typer.Typer(
18
19
  )
19
20
 
20
21
 
21
- @mission.command("tag")
22
+ @missionCommands.command("tag")
22
23
  def addTag(
23
24
  mission_uuid: Annotated[str, typer.Argument()],
24
25
  tagtype_uuid: Annotated[str, typer.Argument()],
@@ -43,7 +44,7 @@ def addTag(
43
44
  raise e
44
45
 
45
46
 
46
- @mission.command("list")
47
+ @missionCommands.command("list")
47
48
  def list_missions(
48
49
  project: Optional[str] = typer.Option(None, help="Name of Project"),
49
50
  verbose: Optional[bool] = typer.Option(
@@ -111,7 +112,7 @@ def list_missions(
111
112
  console.print(table)
112
113
 
113
114
 
114
- @mission.command("byUUID")
115
+ @missionCommands.command("byUUID")
115
116
  def mission_by_uuid(
116
117
  uuid: Annotated[str, typer.Argument()],
117
118
  json: Optional[bool] = typer.Option(False, help="Output as JSON"),
@@ -123,7 +124,7 @@ def mission_by_uuid(
123
124
 
124
125
  Can be run with API Key or with login.
125
126
  """
126
- url = "/mission/byUUID"
127
+ url = "/mission/one"
127
128
  client = AuthenticatedClient()
128
129
  response = client.get(url, params={"uuid": uuid})
129
130
 
@@ -131,7 +132,7 @@ def mission_by_uuid(
131
132
  response.raise_for_status()
132
133
  except httpx.HTTPError:
133
134
  raise AccessDeniedException(
134
- f"Failed to fetch mission."
135
+ f"Failed to fetch mission. "
135
136
  f"Consider using the following command to list all missions: 'klein mission list --verbose'\n",
136
137
  f"{response.json()['message']} ({response.status_code})",
137
138
  )
@@ -151,7 +152,7 @@ def mission_by_uuid(
151
152
  console.print(table)
152
153
 
153
154
 
154
- @mission.command("download")
155
+ @missionCommands.command("download")
155
156
  def download(
156
157
  mission_uuid: Annotated[str, typer.Argument()],
157
158
  local_path: Annotated[str, typer.Argument()],
@@ -169,7 +170,7 @@ def download(
169
170
  raise ValueError(f"Local path '{local_path}' is not empty, but must be empty.")
170
171
 
171
172
  client = AuthenticatedClient()
172
- response = client.get("/file/downloadWithToken", params={"uuid": mission_uuid})
173
+ response = client.get("/mission/download", params={"uuid": mission_uuid})
173
174
 
174
175
  try:
175
176
  response.raise_for_status()
@@ -197,3 +198,59 @@ def download(
197
198
  if chunk: # Filter out keep-alive new chunks
198
199
  f.write(chunk)
199
200
  print(f" Downloaded {filename}")
201
+
202
+ @missionCommands.command("upload")
203
+ def upload(
204
+ path: Annotated[
205
+ str, typer.Option(prompt=True, help="Path to files to upload, Regex supported")
206
+ ],
207
+ mission: Annotated[
208
+ str, typer.Option(prompt=True, help="UUID of Mission to create")
209
+ ],
210
+ ):
211
+ """
212
+ Upload files matching the path to a mission in a project.
213
+
214
+ The mission name must be unique within the project and already created.\n
215
+ Examples:\n
216
+ - 'klein upload --path "~/data/**/*.bag" --project "Project 1" --mission "Mission 1" '\n
217
+
218
+ """
219
+ files = expand_and_match(path)
220
+ filenames = list(
221
+ map(lambda x: x.split("/")[-1], filter(lambda x: not os.path.isdir(x), files))
222
+ )
223
+ if not filenames:
224
+ raise ValueError("No files found matching the given path.")
225
+
226
+ print(
227
+ f"Uploading the following files to mission '{mission}':"
228
+ )
229
+ filepaths = {}
230
+ for path in files:
231
+ if not os.path.isdir(path):
232
+ filepaths[path.split("/")[-1]] = path
233
+ typer.secho(f" - {path}", fg=typer.colors.RESET)
234
+
235
+ try:
236
+ client = AuthenticatedClient()
237
+ res = client.post("/file/temporaryAccess", json={"missionUUID": mission, "filenames": filenames})
238
+ if res.status_code >= 400:
239
+ raise ValueError("Failed to get temporary access. Status code: " + str(res.status_code) + " Message: " + res.json()['message'])
240
+
241
+ temp_credentials = res.json()
242
+ credential = temp_credentials["credentials"]
243
+ confirmed_files = temp_credentials["files"]
244
+ for _file in filenames:
245
+ if not _file in confirmed_files.keys():
246
+ raise Exception(
247
+ "Could not upload File '" + _file + "'. Is the filename unique? "
248
+ )
249
+ confirmed_files[_file]["filepath"] = filepaths[_file]
250
+ if len(confirmed_files.keys()) > 0:
251
+ uploadFiles(confirmed_files, credential, 4)
252
+ except Exception as e:
253
+ print(e)
254
+ print("Failed to upload files")
255
+ raise e
256
+