kleinkram 0.21.7.dev20240919182750__tar.gz → 0.21.9.dev20240920112301__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.
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/PKG-INFO +1 -1
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/pyproject.toml +1 -1
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/helper.py +48 -1
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/main.py +39 -23
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/.gitignore +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/LICENSE +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/README.md +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/deploy.sh +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/dev.sh +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/requirements.txt +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/klein.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/__init__.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/api_client.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/auth/auth.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/consts.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/endpoint/endpoint.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/error_handling.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/file/file.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/mission/mission.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/project/project.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/queue/queue.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/tag/tag.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/topic/topic.py +0 -0
- {kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/user/user.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: kleinkram
|
|
3
|
-
Version: 0.21.
|
|
3
|
+
Version: 0.21.9.dev20240920112301
|
|
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
|
{kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/helper.py
RENAMED
|
@@ -2,7 +2,11 @@ import glob
|
|
|
2
2
|
import os
|
|
3
3
|
import queue
|
|
4
4
|
import threading
|
|
5
|
+
from datetime import datetime
|
|
5
6
|
from functools import partial
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
from botocore.config import Config
|
|
6
10
|
from typing_extensions import Dict
|
|
7
11
|
import boto3
|
|
8
12
|
|
|
@@ -114,7 +118,12 @@ def uploadFiles(files: Dict[str, str], credentials: Dict[str, str], nrThreads: i
|
|
|
114
118
|
minio_endpoint = "http://localhost:9000"
|
|
115
119
|
else:
|
|
116
120
|
minio_endpoint = api_endpoint.replace("api", "minio")
|
|
117
|
-
|
|
121
|
+
|
|
122
|
+
config = Config(retries={
|
|
123
|
+
'max_attempts': 10,
|
|
124
|
+
'mode': 'standard'
|
|
125
|
+
})
|
|
126
|
+
s3 = session.resource("s3", endpoint_url=minio_endpoint, config=config)
|
|
118
127
|
|
|
119
128
|
_queue = queue.Queue()
|
|
120
129
|
for file in files.items():
|
|
@@ -162,6 +171,44 @@ def uploadFile(_queue: queue.Queue, s3: BaseClient, transferCallback: TransferCa
|
|
|
162
171
|
_queue.task_done()
|
|
163
172
|
|
|
164
173
|
|
|
174
|
+
def canUploadMission(client: AuthenticatedClient, project_uuid: str):
|
|
175
|
+
permissions = client.get("/user/permissions")
|
|
176
|
+
permissions.raise_for_status()
|
|
177
|
+
permissions_json = permissions.json()
|
|
178
|
+
for_project = filter(lambda x: x["uuid"] == project_uuid, permissions_json["projects"])
|
|
179
|
+
max_for_project = max(map(lambda x: x["access"], for_project))
|
|
180
|
+
return max_for_project >= 10
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def promptForTags(setTags: Dict[str, str], requiredTags: Dict[str, str]):
|
|
184
|
+
for required_tag in requiredTags:
|
|
185
|
+
if required_tag["name"] not in setTags:
|
|
186
|
+
while True:
|
|
187
|
+
if required_tag["datatype"] in ["LOCATION", "STRING", "LINK"]:
|
|
188
|
+
tag_value = typer.prompt("Provide value for required tag " + required_tag["name"])
|
|
189
|
+
if tag_value != "":
|
|
190
|
+
break
|
|
191
|
+
elif required_tag["datatype"] == "BOOLEAN":
|
|
192
|
+
tag_value = typer.confirm("Provide (y/N) for required tag " + required_tag["name"])
|
|
193
|
+
break
|
|
194
|
+
elif required_tag["datatype"] == "NUMBER":
|
|
195
|
+
tag_value = typer.prompt("Provide number for required tag " + required_tag["name"])
|
|
196
|
+
try:
|
|
197
|
+
tag_value = float(tag_value)
|
|
198
|
+
break
|
|
199
|
+
except ValueError:
|
|
200
|
+
typer.echo("Invalid number format. Please provide a number.")
|
|
201
|
+
elif required_tag["datatype"] == "DATE":
|
|
202
|
+
tag_value = typer.prompt("Provide date for required tag " + required_tag["name"])
|
|
203
|
+
try:
|
|
204
|
+
tag_value = datetime.strptime(tag_value, "%Y-%m-%d %H:%M:%S")
|
|
205
|
+
break
|
|
206
|
+
except ValueError:
|
|
207
|
+
print("Invalid date format. Please use 'YYYY-MM-DD HH:MM:SS'")
|
|
208
|
+
|
|
209
|
+
setTags[required_tag["uuid"]] = tag_value
|
|
210
|
+
|
|
211
|
+
|
|
165
212
|
if __name__ == "__main__":
|
|
166
213
|
res = expand_and_match(
|
|
167
214
|
"~/Downloads/dodo_mission_2024_02_08-20240408T074313Z-003/**.bag"
|
{kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/main.py
RENAMED
|
@@ -9,7 +9,7 @@ from rich import print
|
|
|
9
9
|
from rich.table import Table
|
|
10
10
|
from typer.core import TyperGroup
|
|
11
11
|
from typer.models import Context
|
|
12
|
-
from typing_extensions import Annotated, List
|
|
12
|
+
from typing_extensions import Annotated, List, Optional
|
|
13
13
|
|
|
14
14
|
from kleinkram.api_client import AuthenticatedClient
|
|
15
15
|
from kleinkram.auth.auth import login, setCliKey, logout
|
|
@@ -22,7 +22,7 @@ from kleinkram.queue.queue import queue
|
|
|
22
22
|
from kleinkram.tag.tag import tag
|
|
23
23
|
from kleinkram.topic.topic import topic
|
|
24
24
|
from kleinkram.user.user import user
|
|
25
|
-
from .helper import uploadFiles, expand_and_match
|
|
25
|
+
from .helper import uploadFiles, expand_and_match, canUploadMission, promptForTags
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class CommandPanel(str, Enum):
|
|
@@ -75,14 +75,14 @@ app = ErrorHandledTyper(
|
|
|
75
75
|
|
|
76
76
|
@app.callback()
|
|
77
77
|
def version(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
78
|
+
version: bool = typer.Option(
|
|
79
|
+
None,
|
|
80
|
+
"--version",
|
|
81
|
+
"-v",
|
|
82
|
+
callback=version_callback,
|
|
83
|
+
is_eager=True,
|
|
84
|
+
help="Print the version and exit",
|
|
85
|
+
)
|
|
86
86
|
):
|
|
87
87
|
pass
|
|
88
88
|
|
|
@@ -109,20 +109,21 @@ def download():
|
|
|
109
109
|
|
|
110
110
|
@app.command("upload", rich_help_panel=CommandPanel.CoreCommands)
|
|
111
111
|
def upload(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
112
|
+
path: Annotated[
|
|
113
|
+
str, typer.Option(prompt=True, help="Path to files to upload, Regex supported")
|
|
114
|
+
],
|
|
115
|
+
project: Annotated[str, typer.Option(prompt=True, help="Name of Project")],
|
|
116
|
+
mission: Annotated[
|
|
117
|
+
str, typer.Option(prompt=True, help="Name of Mission to create")
|
|
118
|
+
],
|
|
119
|
+
tags: Annotated[Optional[List[str]], typer.Option(prompt=False, help="Tags to add to the mission")] = None,
|
|
119
120
|
):
|
|
120
121
|
"""
|
|
121
122
|
Upload files matching the path to a mission in a project.
|
|
122
123
|
|
|
123
124
|
The mission name must be unique within the project and not yet created.\n
|
|
124
125
|
Examples:\n
|
|
125
|
-
- 'klein upload --path "~/data/**/*.bag" --project "Project 1" --mission "Mission 1"'\n
|
|
126
|
+
- 'klein upload --path "~/data/**/*.bag" --project "Project 1" --mission "Mission 1" --tags "0700946d-1d6a-4520-b263-0e177f49c35b:LEE-H" --tags "1565118d-593c-4517-8c2d-9658452d9319:Dodo"'\n
|
|
126
127
|
|
|
127
128
|
"""
|
|
128
129
|
files = expand_and_match(path)
|
|
@@ -147,7 +148,6 @@ def upload(
|
|
|
147
148
|
get_project_url = "/project/byName"
|
|
148
149
|
project_response = client.get(get_project_url, params={"name": project})
|
|
149
150
|
if project_response.status_code >= 400:
|
|
150
|
-
|
|
151
151
|
raise AccessDeniedException(
|
|
152
152
|
f"The project '{project}' does not exist or you do not have access to it.\n"
|
|
153
153
|
f"Consider using the following command to create a project: 'klein project create'\n",
|
|
@@ -159,6 +159,17 @@ def upload(
|
|
|
159
159
|
print(f"Project not found: '{project}'")
|
|
160
160
|
return
|
|
161
161
|
|
|
162
|
+
can_upload = canUploadMission(client, project_json['uuid'])
|
|
163
|
+
if not can_upload:
|
|
164
|
+
raise AccessDeniedException(
|
|
165
|
+
f"You do not have the required permissions to upload to project '{project}'\n", "Access Denied")
|
|
166
|
+
|
|
167
|
+
if not tags:
|
|
168
|
+
tags = []
|
|
169
|
+
tags_dict = {item.split(":")[0]: item.split(":")[1] for item in tags}
|
|
170
|
+
|
|
171
|
+
promptForTags(tags_dict, project_json["requiredTags"])
|
|
172
|
+
|
|
162
173
|
get_mission_url = "/mission/byName"
|
|
163
174
|
mission_response = client.get(get_mission_url, params={"name": mission})
|
|
164
175
|
mission_response.raise_for_status()
|
|
@@ -174,18 +185,23 @@ def upload(
|
|
|
174
185
|
create_mission_url = "/mission/create"
|
|
175
186
|
new_mission = client.post(
|
|
176
187
|
create_mission_url,
|
|
177
|
-
json={"name": mission, "projectUUID": project_json["uuid"], "tags":
|
|
188
|
+
json={"name": mission, "projectUUID": project_json["uuid"], "tags": tags_dict},
|
|
178
189
|
)
|
|
179
|
-
new_mission.
|
|
190
|
+
if new_mission.status_code >= 400:
|
|
191
|
+
raise ValueError(
|
|
192
|
+
"Failed to create mission. Status Code: " + str(new_mission.status_code) + "\n" + new_mission.json()[
|
|
193
|
+
"message"])
|
|
180
194
|
new_mission_data = new_mission.json()
|
|
181
195
|
|
|
182
196
|
get_temporary_credentials = "/file/temporaryAccess"
|
|
183
|
-
|
|
184
197
|
response_2 = client.post(
|
|
185
198
|
get_temporary_credentials,
|
|
186
199
|
json={"filenames": filenames, "missionUUID": new_mission_data["uuid"]},
|
|
187
200
|
)
|
|
188
|
-
response_2.
|
|
201
|
+
if response_2.status_code >= 400:
|
|
202
|
+
raise ValueError(
|
|
203
|
+
"Failed to get temporary credentials. Status Code: " + str(response_2.status_code) + "\n" + response_2.json()[
|
|
204
|
+
"message"])
|
|
189
205
|
temp_credentials = response_2.json()
|
|
190
206
|
credential = temp_credentials["credentials"]
|
|
191
207
|
confirmed_files = temp_credentials["files"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/auth/auth.py
RENAMED
|
File without changes
|
{kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/consts.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/file/file.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/tag/tag.py
RENAMED
|
File without changes
|
|
File without changes
|
{kleinkram-0.21.7.dev20240919182750 → kleinkram-0.21.9.dev20240920112301}/src/kleinkram/user/user.py
RENAMED
|
File without changes
|