kscale 0.0.5__py3-none-any.whl → 0.0.7__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.
- kscale/__init__.py +1 -1
- kscale/store/api.py +5 -1
- kscale/store/client.py +6 -3
- kscale/store/pybullet.py +4 -1
- kscale/store/urdf.py +26 -9
- kscale/store/utils.py +15 -1
- {kscale-0.0.5.dist-info → kscale-0.0.7.dist-info}/METADATA +6 -5
- kscale-0.0.7.dist-info/RECORD +21 -0
- {kscale-0.0.5.dist-info → kscale-0.0.7.dist-info}/WHEEL +1 -1
- kscale-0.0.5.dist-info/RECORD +0 -21
- {kscale-0.0.5.dist-info → kscale-0.0.7.dist-info}/LICENSE +0 -0
- {kscale-0.0.5.dist-info → kscale-0.0.7.dist-info}/entry_points.txt +0 -0
- {kscale-0.0.5.dist-info → kscale-0.0.7.dist-info}/top_level.txt +0 -0
kscale/__init__.py
CHANGED
kscale/store/api.py
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
from pathlib import Path
|
4
4
|
|
5
|
-
from kscale.store.
|
5
|
+
from kscale.store.gen.api import UploadArtifactResponse
|
6
|
+
from kscale.store.urdf import download_urdf, upload_urdf
|
6
7
|
from kscale.utils.api_base import APIBase
|
7
8
|
|
8
9
|
|
@@ -18,3 +19,6 @@ class StoreAPI(APIBase):
|
|
18
19
|
|
19
20
|
async def urdf(self, artifact_id: str) -> Path:
|
20
21
|
return await download_urdf(artifact_id)
|
22
|
+
|
23
|
+
async def upload_urdf(self, listing_id: str, root_dir: Path) -> UploadArtifactResponse:
|
24
|
+
return await upload_urdf(listing_id, root_dir)
|
kscale/store/client.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
"""Defines a typed client for the K-Scale Store API."""
|
2
2
|
|
3
3
|
import logging
|
4
|
+
from pathlib import Path
|
4
5
|
from types import TracebackType
|
5
6
|
from typing import Any, Dict, Type
|
6
7
|
from urllib.parse import urljoin
|
@@ -14,17 +15,18 @@ from kscale.store.gen.api import (
|
|
14
15
|
SingleArtifactResponse,
|
15
16
|
UploadArtifactResponse,
|
16
17
|
)
|
17
|
-
from kscale.store.utils import
|
18
|
+
from kscale.store.utils import get_api_key, get_api_root
|
18
19
|
|
19
20
|
logger = logging.getLogger(__name__)
|
20
21
|
|
21
22
|
|
22
23
|
class KScaleStoreClient:
|
23
|
-
def __init__(self, base_url: str =
|
24
|
+
def __init__(self, base_url: str = get_api_root()) -> None:
|
24
25
|
self.base_url = base_url
|
25
26
|
self.client = httpx.AsyncClient(
|
26
27
|
base_url=self.base_url,
|
27
28
|
headers={"Authorization": f"Bearer {get_api_key()}"},
|
29
|
+
timeout=httpx.Timeout(30.0),
|
28
30
|
)
|
29
31
|
|
30
32
|
async def _request(
|
@@ -55,8 +57,9 @@ class KScaleStoreClient:
|
|
55
57
|
return SingleArtifactResponse(**data)
|
56
58
|
|
57
59
|
async def upload_artifact(self, listing_id: str, file_path: str) -> UploadArtifactResponse:
|
60
|
+
file_name = Path(file_path).name
|
58
61
|
with open(file_path, "rb") as f:
|
59
|
-
files = {"files": (
|
62
|
+
files = {"files": (file_name, f, "application/gzip")}
|
60
63
|
data = await self._request("POST", f"/artifacts/upload/{listing_id}", files=files)
|
61
64
|
return UploadArtifactResponse(**data)
|
62
65
|
|
kscale/store/pybullet.py
CHANGED
@@ -27,7 +27,10 @@ async def main(args: Sequence[str] | None = None) -> None:
|
|
27
27
|
parsed_args = parser.parse_args(args)
|
28
28
|
|
29
29
|
# Gets the URDF path.
|
30
|
-
|
30
|
+
urdf_dir = await download_urdf(parsed_args.listing_id)
|
31
|
+
urdf_path = next(urdf_dir.glob("*.urdf"), None)
|
32
|
+
if urdf_path is None:
|
33
|
+
raise ValueError(f"No URDF found in {urdf_dir}")
|
31
34
|
|
32
35
|
try:
|
33
36
|
import pybullet as p # type: ignore[import-not-found]
|
kscale/store/urdf.py
CHANGED
@@ -14,13 +14,24 @@ import requests
|
|
14
14
|
|
15
15
|
from kscale.conf import Settings
|
16
16
|
from kscale.store.client import KScaleStoreClient
|
17
|
-
from kscale.store.gen.api import SingleArtifactResponse
|
17
|
+
from kscale.store.gen.api import SingleArtifactResponse, UploadArtifactResponse
|
18
18
|
from kscale.store.utils import get_api_key
|
19
19
|
|
20
20
|
# Set up logging
|
21
21
|
logging.basicConfig(level=logging.INFO)
|
22
22
|
logger = logging.getLogger(__name__)
|
23
23
|
|
24
|
+
ALLOWED_SUFFIXES = {
|
25
|
+
".urdf",
|
26
|
+
".mjcf",
|
27
|
+
".stl",
|
28
|
+
".obj",
|
29
|
+
".dae",
|
30
|
+
".png",
|
31
|
+
".jpg",
|
32
|
+
".jpeg",
|
33
|
+
}
|
34
|
+
|
24
35
|
|
25
36
|
def get_cache_dir() -> Path:
|
26
37
|
return Path(Settings.load().store.cache_dir).expanduser().resolve()
|
@@ -75,7 +86,7 @@ def create_tarball(folder_path: Path, output_filename: str, cache_dir: Path) ->
|
|
75
86
|
tarball_path = cache_dir / output_filename
|
76
87
|
with tarfile.open(tarball_path, "w:gz") as tar:
|
77
88
|
for file_path in folder_path.rglob("*"):
|
78
|
-
if file_path.is_file() and file_path.suffix.lower() in
|
89
|
+
if file_path.is_file() and file_path.suffix.lower() in ALLOWED_SUFFIXES:
|
79
90
|
tar.add(file_path, arcname=file_path.relative_to(folder_path))
|
80
91
|
logger.info("Added %s to tarball", file_path)
|
81
92
|
else:
|
@@ -128,18 +139,24 @@ async def remove_local_urdf(artifact_id: str) -> None:
|
|
128
139
|
raise
|
129
140
|
|
130
141
|
|
131
|
-
async def upload_urdf(listing_id: str,
|
132
|
-
parser = argparse.ArgumentParser(description="K-Scale URDF Store", add_help=False)
|
133
|
-
parser.add_argument("root_dir", type=Path, help="The path to the root directory to upload")
|
134
|
-
parsed_args = parser.parse_args(args)
|
135
|
-
|
136
|
-
root_dir = parsed_args.root_dir
|
142
|
+
async def upload_urdf(listing_id: str, root_dir: Path) -> UploadArtifactResponse:
|
137
143
|
tarball_path = create_tarball(root_dir, "robot.tgz", get_artifact_dir(listing_id))
|
138
144
|
|
139
145
|
async with KScaleStoreClient() as client:
|
140
146
|
response = await client.upload_artifact(listing_id, str(tarball_path))
|
141
147
|
|
142
148
|
logger.info("Uploaded artifacts: %s", [artifact.artifact_id for artifact in response.artifacts])
|
149
|
+
return response
|
150
|
+
|
151
|
+
|
152
|
+
async def upload_urdf_cli(listing_id: str, args: Sequence[str]) -> UploadArtifactResponse:
|
153
|
+
parser = argparse.ArgumentParser(description="K-Scale URDF Store", add_help=False)
|
154
|
+
parser.add_argument("root_dir", type=Path, help="The path to the root directory to upload")
|
155
|
+
parsed_args = parser.parse_args(args)
|
156
|
+
|
157
|
+
root_dir = parsed_args.root_dir
|
158
|
+
response = await upload_urdf(listing_id, root_dir)
|
159
|
+
return response
|
143
160
|
|
144
161
|
|
145
162
|
Command = Literal["download", "info", "upload", "remove-local"]
|
@@ -165,7 +182,7 @@ async def main(args: Sequence[str] | None = None) -> None:
|
|
165
182
|
await remove_local_urdf(id)
|
166
183
|
|
167
184
|
case "upload":
|
168
|
-
await
|
185
|
+
await upload_urdf_cli(id, remaining_args)
|
169
186
|
|
170
187
|
case _:
|
171
188
|
logger.error("Invalid command")
|
kscale/store/utils.py
CHANGED
@@ -4,10 +4,24 @@ import os
|
|
4
4
|
|
5
5
|
from kscale.conf import Settings
|
6
6
|
|
7
|
-
|
7
|
+
|
8
|
+
def get_api_root() -> str:
|
9
|
+
"""Returns the base URL for the K-Scale Store API.
|
10
|
+
|
11
|
+
This can be overridden when targetting a different server.
|
12
|
+
|
13
|
+
Returns:
|
14
|
+
The base URL for the K-Scale Store API.
|
15
|
+
"""
|
16
|
+
return os.getenv("KSCALE_API_ROOT", "https://api.kscale.store")
|
8
17
|
|
9
18
|
|
10
19
|
def get_api_key() -> str:
|
20
|
+
"""Returns the API key for the K-Scale Store API.
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
The API key for the K-Scale Store API.
|
24
|
+
"""
|
11
25
|
api_key = Settings.load().store.api_key
|
12
26
|
if api_key is None:
|
13
27
|
api_key = os.getenv("KSCALE_API_KEY")
|
@@ -1,16 +1,17 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: kscale
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.7
|
4
4
|
Summary: The kscale project
|
5
5
|
Home-page: https://github.com/kscalelabs/kscale
|
6
6
|
Author: Benjamin Bolte
|
7
7
|
Requires-Python: >=3.11
|
8
8
|
Description-Content-Type: text/markdown
|
9
9
|
License-File: LICENSE
|
10
|
-
Requires-Dist: omegaconf
|
11
|
-
Requires-Dist: email-validator
|
12
|
-
Requires-Dist: httpx
|
13
|
-
Requires-Dist: requests
|
10
|
+
Requires-Dist: omegaconf
|
11
|
+
Requires-Dist: email-validator
|
12
|
+
Requires-Dist: httpx
|
13
|
+
Requires-Dist: requests
|
14
|
+
Requires-Dist: pydantic
|
14
15
|
Provides-Extra: dev
|
15
16
|
Requires-Dist: black ; extra == 'dev'
|
16
17
|
Requires-Dist: darglint ; extra == 'dev'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
kscale/__init__.py,sha256=3DfIJ5zf1Jokj7wyBCtRldKZFvBMVODE8CoieJr1Zo4,117
|
2
|
+
kscale/api.py,sha256=xBtKj8rgZ400r1Xx9LRY0AzSgIIttoXdejmhHhdVGS0,333
|
3
|
+
kscale/conf.py,sha256=9fShFaYTbnrm_eiGjmy8ZtC4Q4m6PQkWPyoF3eNyov8,1424
|
4
|
+
kscale/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
+
kscale/store/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
+
kscale/store/api.py,sha256=rydanYGg8zlc_cNuWo9YBG_WVtPKMxFgp6fpec-B8M0,671
|
7
|
+
kscale/store/cli.py,sha256=8ygg_1tZzOOHJotEIgSN9pfumcriPmA31sI_FCFQiTo,859
|
8
|
+
kscale/store/client.py,sha256=R1IDnf2J4ojAcP8nmUUHfXhcHUt4zP0-mxtVI7MIC5U,2664
|
9
|
+
kscale/store/pybullet.py,sha256=WzA1FVAc19JMY9nUar0go9kcy9BvU8W1lnT9eT1W1LI,7638
|
10
|
+
kscale/store/urdf.py,sha256=5x8tK2BYv901S_yYWYPWEnHv-3T0ALBQMdDwb70EZFw,6395
|
11
|
+
kscale/store/utils.py,sha256=rFXGkem2oAttAf3bhWmFEhxrqYnaVvlVJsC268IMw6Y,906
|
12
|
+
kscale/store/gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
+
kscale/store/gen/api.py,sha256=82D41J6pg9KWdgD0lx7NggLcNS32SpnN8DqE3Md6ON0,9559
|
14
|
+
kscale/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
+
kscale/utils/api_base.py,sha256=Kk_WtRDdJHmOg6NtHmVxVrcfARSUkhfr29ypLch_pO0,112
|
16
|
+
kscale-0.0.7.dist-info/LICENSE,sha256=HCN2bImAzUOXldAZZI7JZ9PYq6OwMlDAP_PpX1HnuN0,1071
|
17
|
+
kscale-0.0.7.dist-info/METADATA,sha256=JzwigJrhRpaJNCYKDzgam_allQTuY6G10nR4TU31an0,2504
|
18
|
+
kscale-0.0.7.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
19
|
+
kscale-0.0.7.dist-info/entry_points.txt,sha256=PaVs1ivqB0BBdGUsiFkxGUYjGLz05VqagxwRVwi4yV4,54
|
20
|
+
kscale-0.0.7.dist-info/top_level.txt,sha256=C2ynjYwopg6YjgttnI2dJjasyq3EKNmYp-IfQg9Xms4,7
|
21
|
+
kscale-0.0.7.dist-info/RECORD,,
|
kscale-0.0.5.dist-info/RECORD
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
kscale/__init__.py,sha256=e1NdSlxsBKi5qyOIjXC3vAPQXleZwh2hyVlLHcKQsq8,117
|
2
|
-
kscale/api.py,sha256=xBtKj8rgZ400r1Xx9LRY0AzSgIIttoXdejmhHhdVGS0,333
|
3
|
-
kscale/conf.py,sha256=9fShFaYTbnrm_eiGjmy8ZtC4Q4m6PQkWPyoF3eNyov8,1424
|
4
|
-
kscale/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
kscale/store/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
kscale/store/api.py,sha256=L-QZMDeOsNo8ovIRjwfBlidYKD510hdoKrmrue7C5Wk,454
|
7
|
-
kscale/store/cli.py,sha256=8ygg_1tZzOOHJotEIgSN9pfumcriPmA31sI_FCFQiTo,859
|
8
|
-
kscale/store/client.py,sha256=HEyTzgCOXdLCQKdFKwNglvTBtXVipul7cxbdjz53Pb4,2544
|
9
|
-
kscale/store/pybullet.py,sha256=viTQCE2jT72miPKZpFKj4f4zGLLYtjhRFxGqzxd2Z8M,7504
|
10
|
-
kscale/store/urdf.py,sha256=zMUfJNNpZkoLf-SnhMO28f8Qj39hmZrA0vqLL3sZSqE,6069
|
11
|
-
kscale/store/utils.py,sha256=vQSFd9fByDUUSD0dAA65T_WI5R55vY-HOQjIJg_u2jw,536
|
12
|
-
kscale/store/gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
-
kscale/store/gen/api.py,sha256=82D41J6pg9KWdgD0lx7NggLcNS32SpnN8DqE3Md6ON0,9559
|
14
|
-
kscale/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
-
kscale/utils/api_base.py,sha256=Kk_WtRDdJHmOg6NtHmVxVrcfARSUkhfr29ypLch_pO0,112
|
16
|
-
kscale-0.0.5.dist-info/LICENSE,sha256=HCN2bImAzUOXldAZZI7JZ9PYq6OwMlDAP_PpX1HnuN0,1071
|
17
|
-
kscale-0.0.5.dist-info/METADATA,sha256=jAkpxXCrUa8b30BY32OaW6eIoR0VFHQzKgzO26EDFGM,2514
|
18
|
-
kscale-0.0.5.dist-info/WHEEL,sha256=uCRv0ZEik_232NlR4YDw4Pv3Ajt5bKvMH13NUU7hFuI,91
|
19
|
-
kscale-0.0.5.dist-info/entry_points.txt,sha256=PaVs1ivqB0BBdGUsiFkxGUYjGLz05VqagxwRVwi4yV4,54
|
20
|
-
kscale-0.0.5.dist-info/top_level.txt,sha256=C2ynjYwopg6YjgttnI2dJjasyq3EKNmYp-IfQg9Xms4,7
|
21
|
-
kscale-0.0.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|