kscale 0.0.11__py3-none-any.whl → 0.1.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- kscale/__init__.py +2 -2
- kscale/api.py +3 -6
- kscale/cli.py +32 -0
- kscale/conf.py +6 -3
- kscale/requirements.txt +17 -1
- kscale/utils/checksum.py +41 -0
- kscale/utils/cli.py +28 -0
- kscale/web/api.py +14 -0
- kscale/web/cli/robot.py +100 -0
- kscale/web/cli/robot_class.py +113 -0
- kscale/web/cli/token.py +33 -0
- kscale/web/cli/user.py +33 -0
- kscale/web/clients/__init__.py +0 -0
- kscale/web/clients/base.py +314 -0
- kscale/web/clients/client.py +11 -0
- kscale/web/clients/robot.py +39 -0
- kscale/web/clients/robot_class.py +114 -0
- kscale/web/clients/user.py +10 -0
- kscale/web/gen/__init__.py +0 -0
- kscale/web/gen/api.py +73 -0
- kscale/web/utils.py +31 -0
- {kscale-0.0.11.dist-info → kscale-0.1.0.dist-info}/METADATA +29 -48
- kscale-0.1.0.dist-info/RECORD +36 -0
- {kscale-0.0.11.dist-info → kscale-0.1.0.dist-info}/WHEEL +1 -1
- kscale-0.1.0.dist-info/entry_points.txt +3 -0
- kscale/store/api.py +0 -64
- kscale/store/cli.py +0 -35
- kscale/store/client.py +0 -82
- kscale/store/gen/api.py +0 -397
- kscale/store/pybullet.py +0 -180
- kscale/store/urdf.py +0 -193
- kscale/store/utils.py +0 -33
- kscale-0.0.11.dist-info/RECORD +0 -26
- kscale-0.0.11.dist-info/entry_points.txt +0 -2
- /kscale/{store → web}/__init__.py +0 -0
- /kscale/{store/gen → web/cli}/__init__.py +0 -0
- {kscale-0.0.11.dist-info → kscale-0.1.0.dist-info}/LICENSE +0 -0
- {kscale-0.0.11.dist-info → kscale-0.1.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: kscale
|
3
|
-
Version: 0.0
|
3
|
+
Version: 0.1.0
|
4
4
|
Summary: The kscale project
|
5
5
|
Home-page: https://github.com/kscalelabs/kscale
|
6
6
|
Author: Benjamin Bolte
|
@@ -8,23 +8,35 @@ Requires-Python: >=3.11
|
|
8
8
|
Description-Content-Type: text/markdown
|
9
9
|
License-File: LICENSE
|
10
10
|
Requires-Dist: omegaconf
|
11
|
-
Requires-Dist:
|
11
|
+
Requires-Dist: email_validator
|
12
|
+
Requires-Dist: colorlogging
|
13
|
+
Requires-Dist: aiohttp
|
14
|
+
Requires-Dist: cryptography
|
12
15
|
Requires-Dist: httpx
|
13
|
-
Requires-Dist: requests
|
14
16
|
Requires-Dist: pydantic
|
17
|
+
Requires-Dist: pyjwt
|
18
|
+
Requires-Dist: requests
|
19
|
+
Requires-Dist: yarl
|
20
|
+
Requires-Dist: aiofiles
|
21
|
+
Requires-Dist: click
|
22
|
+
Requires-Dist: tabulate
|
23
|
+
Requires-Dist: async-lru
|
24
|
+
Requires-Dist: krec
|
15
25
|
Provides-Extra: dev
|
16
|
-
Requires-Dist: black
|
17
|
-
Requires-Dist: darglint
|
18
|
-
Requires-Dist: mypy
|
19
|
-
Requires-Dist: pytest
|
20
|
-
Requires-Dist: ruff
|
21
|
-
Requires-Dist: datamodel-code-generator
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
Requires-Dist: black; extra == "dev"
|
27
|
+
Requires-Dist: darglint; extra == "dev"
|
28
|
+
Requires-Dist: mypy; extra == "dev"
|
29
|
+
Requires-Dist: pytest; extra == "dev"
|
30
|
+
Requires-Dist: ruff; extra == "dev"
|
31
|
+
Requires-Dist: datamodel-code-generator; extra == "dev"
|
32
|
+
Dynamic: author
|
33
|
+
Dynamic: description
|
34
|
+
Dynamic: description-content-type
|
35
|
+
Dynamic: home-page
|
36
|
+
Dynamic: provides-extra
|
37
|
+
Dynamic: requires-dist
|
38
|
+
Dynamic: requires-python
|
39
|
+
Dynamic: summary
|
28
40
|
|
29
41
|
<div align="center">
|
30
42
|
|
@@ -43,41 +55,10 @@ Requires-Dist: datamodel-code-generator ; extra == 'dev'
|
|
43
55
|
|
44
56
|
# K-Scale Command Line Interface
|
45
57
|
|
46
|
-
This is a command line tool for interacting with various services provided by K-Scale Labs,
|
47
|
-
|
48
|
-
- [K-Scale Store](https://kscale.store/)
|
58
|
+
This is a command line tool for interacting with various services provided by K-Scale Labs. For more information, see the [documentation](https://docs.kscale.dev/pkg/intro).
|
49
59
|
|
50
60
|
## Installation
|
51
61
|
|
52
62
|
```bash
|
53
63
|
pip install kscale
|
54
64
|
```
|
55
|
-
|
56
|
-
## Usage
|
57
|
-
|
58
|
-
### CLI
|
59
|
-
|
60
|
-
Download a URDF from the K-Scale Store:
|
61
|
-
|
62
|
-
```bash
|
63
|
-
kscale urdf download <artifact_id>
|
64
|
-
```
|
65
|
-
|
66
|
-
Upload a URDF to the K-Scale Store:
|
67
|
-
|
68
|
-
```bash
|
69
|
-
kscale urdf upload <artifact_id> <root_dir>
|
70
|
-
```
|
71
|
-
|
72
|
-
### Python API
|
73
|
-
|
74
|
-
Reference a URDF by ID from the K-Scale Store:
|
75
|
-
|
76
|
-
```python
|
77
|
-
from kscale import KScale
|
78
|
-
|
79
|
-
async def main():
|
80
|
-
kscale = KScale()
|
81
|
-
urdf_dir_path = await kscale.store.urdf("123456")
|
82
|
-
print(urdf_dir_path)
|
83
|
-
```
|
@@ -0,0 +1,36 @@
|
|
1
|
+
kscale/__init__.py,sha256=2jGtLxds4EdX8FEGT3yA74b0VgrkOEBx_PxiWvoh924,172
|
2
|
+
kscale/api.py,sha256=jmiuFurTN_Gj_-k-6asqxw8wp-_bgJUXgMPFgJ4lqHA,230
|
3
|
+
kscale/cli.py,sha256=PMHLKR5UwdbbReVmqHXpJ-K9-mGHv_0I7KQkwxmFcUA,881
|
4
|
+
kscale/conf.py,sha256=i5gDTs8D73l2OvX4pOlPWtT2PC26MmoKw3PPwf8HM7U,1526
|
5
|
+
kscale/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
+
kscale/requirements-dev.txt,sha256=WI7-ea4IRJakmqVMN8QKhOsDGrghwtvk03aIsFaNSIw,130
|
7
|
+
kscale/requirements.txt,sha256=lKDpyebp9nHZ2uHIuS6FQ6SAg7YO_0sDyb67MFmP4h4,214
|
8
|
+
kscale/artifacts/__init__.py,sha256=RK8wdybtCJPgdLLJ8R8-YMi1Ph5ojqAKVJZowHONtgo,232
|
9
|
+
kscale/artifacts/plane.obj,sha256=x59-IIrWpLjhotChiqT2Ul6U8s0RcHkaEeUZb4KXL1c,348
|
10
|
+
kscale/artifacts/plane.urdf,sha256=LCiTk14AyTHjkZ1jvsb0hNaEaJUxDb8Z1JjsgpXu3YM,819
|
11
|
+
kscale/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
|
+
kscale/utils/api_base.py,sha256=Kk_WtRDdJHmOg6NtHmVxVrcfARSUkhfr29ypLch_pO0,112
|
13
|
+
kscale/utils/checksum.py,sha256=jt6QmmQND9zrOEnUtOfZpLYROhgto4Gh3OpdUWk4tZA,1093
|
14
|
+
kscale/utils/cli.py,sha256=JoaY5x5SdUx97KmMM9j5AjRRUqqrTlJ9qVckZptEsYA,827
|
15
|
+
kscale/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
|
+
kscale/web/api.py,sha256=YioIdruq7LCKSBf9SvOGkv914W36_zBmpTzsJqKc0wE,439
|
17
|
+
kscale/web/utils.py,sha256=KFB9lrgn_2BRY38Sfbb_QOKZ8fWyINqIqLPwN0rjbyk,806
|
18
|
+
kscale/web/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
+
kscale/web/cli/robot.py,sha256=rI-A4_0uvJPeA71Apl4Z3mV5fIfWkgmzT9JRmJYxz3A,3307
|
20
|
+
kscale/web/cli/robot_class.py,sha256=ymC5phUqofvOXv5P6f51b9lMK5eRDaavvnzS0x9rDbU,3574
|
21
|
+
kscale/web/cli/token.py,sha256=1rFC8MYKtqbNsQa2KIqwW1tqpaMtFaxuNsallwejXTU,787
|
22
|
+
kscale/web/cli/user.py,sha256=qO0z2K5uA48hEiOOYEzv6BO2nOlCpITTDZFuiNl6d34,817
|
23
|
+
kscale/web/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
|
+
kscale/web/clients/base.py,sha256=NRqRH2JTXjJLUMDM93txKgwFu9bQRYhCYLYy7vE76Ik,11462
|
25
|
+
kscale/web/clients/client.py,sha256=QjBicdHQYNoUG9XRjAYmGu3THae9DzWa_hQox3OO1Gw,214
|
26
|
+
kscale/web/clients/robot.py,sha256=HMfJnkDxaJ_o7X2vdYYS9iob1JRoBG2qiGmQpCQZpAk,1485
|
27
|
+
kscale/web/clients/robot_class.py,sha256=yC0G4pVPDoEskf0QfQLxejyDgHLT8gR1RLJ8ioCGoOM,4236
|
28
|
+
kscale/web/clients/user.py,sha256=9iv8J-ROm_yBIwi-0oqldReLkNBFktdHRv3UCOxBzjY,377
|
29
|
+
kscale/web/gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
|
+
kscale/web/gen/api.py,sha256=SovcII36JFgK9jd2CXlLPMjiUROGB4vEnapOsYMUrkU,2188
|
31
|
+
kscale-0.1.0.dist-info/LICENSE,sha256=HCN2bImAzUOXldAZZI7JZ9PYq6OwMlDAP_PpX1HnuN0,1071
|
32
|
+
kscale-0.1.0.dist-info/METADATA,sha256=EBGeAHNhtgjRQ38M_3n_mQ1LFlaogmA3qgUsVa45zEA,2340
|
33
|
+
kscale-0.1.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
34
|
+
kscale-0.1.0.dist-info/entry_points.txt,sha256=N_0pCpPnwGDYVzOeuaSOrbJkS5L3lS9d8CxpJF1f8UI,62
|
35
|
+
kscale-0.1.0.dist-info/top_level.txt,sha256=C2ynjYwopg6YjgttnI2dJjasyq3EKNmYp-IfQg9Xms4,7
|
36
|
+
kscale-0.1.0.dist-info/RECORD,,
|
kscale/store/api.py
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
"""Defines a common interface for the K-Scale Store API."""
|
2
|
-
|
3
|
-
from pathlib import Path
|
4
|
-
from typing import overload
|
5
|
-
|
6
|
-
from kscale.store.gen.api import UploadArtifactResponse
|
7
|
-
from kscale.store.urdf import download_urdf, upload_urdf
|
8
|
-
from kscale.utils.api_base import APIBase
|
9
|
-
|
10
|
-
|
11
|
-
class StoreAPI(APIBase):
|
12
|
-
def __init__(
|
13
|
-
self,
|
14
|
-
*,
|
15
|
-
api_key: str | None = None,
|
16
|
-
) -> None:
|
17
|
-
super().__init__()
|
18
|
-
|
19
|
-
self.api_key = api_key
|
20
|
-
|
21
|
-
async def artifact_root(self, artifact_id: str) -> Path:
|
22
|
-
return await download_urdf(artifact_id)
|
23
|
-
|
24
|
-
@overload
|
25
|
-
async def urdf_path(self, artifact_id: str) -> Path: ...
|
26
|
-
|
27
|
-
@overload
|
28
|
-
async def urdf_path(self, artifact_id: str, *, throw_if_missing: bool = True) -> Path | None: ...
|
29
|
-
|
30
|
-
async def urdf_path(self, artifact_id: str, *, throw_if_missing: bool = True) -> Path | None:
|
31
|
-
root_dir = await self.artifact_root(artifact_id)
|
32
|
-
urdf_path = next(root_dir.glob("*.urdf"), None)
|
33
|
-
if urdf_path is None and throw_if_missing:
|
34
|
-
raise FileNotFoundError(f"No URDF found for artifact {artifact_id}")
|
35
|
-
return urdf_path
|
36
|
-
|
37
|
-
@overload
|
38
|
-
async def mjcf_path(self, artifact_id: str) -> Path: ...
|
39
|
-
|
40
|
-
@overload
|
41
|
-
async def mjcf_path(self, artifact_id: str, *, throw_if_missing: bool = True) -> Path | None: ...
|
42
|
-
|
43
|
-
async def mjcf_path(self, artifact_id: str, *, throw_if_missing: bool = True) -> Path | None:
|
44
|
-
root_dir = await self.artifact_root(artifact_id)
|
45
|
-
mjcf_path = next(root_dir.glob("*.mjcf"), None)
|
46
|
-
if mjcf_path is None and throw_if_missing:
|
47
|
-
raise FileNotFoundError(f"No MJCF found for artifact {artifact_id}")
|
48
|
-
return mjcf_path
|
49
|
-
|
50
|
-
@overload
|
51
|
-
async def xml_path(self, artifact_id: str) -> Path: ...
|
52
|
-
|
53
|
-
@overload
|
54
|
-
async def xml_path(self, artifact_id: str, *, throw_if_missing: bool = True) -> Path | None: ...
|
55
|
-
|
56
|
-
async def xml_path(self, artifact_id: str, *, throw_if_missing: bool = True) -> Path | None:
|
57
|
-
root_dir = await self.artifact_root(artifact_id)
|
58
|
-
xml_path = next(root_dir.glob("*.xml"), None)
|
59
|
-
if xml_path is None and throw_if_missing:
|
60
|
-
raise FileNotFoundError(f"No XML found for artifact {artifact_id}")
|
61
|
-
return xml_path
|
62
|
-
|
63
|
-
async def upload_urdf(self, listing_id: str, root_dir: Path) -> UploadArtifactResponse:
|
64
|
-
return await upload_urdf(listing_id, root_dir)
|
kscale/store/cli.py
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
"""Defines the top-level KOL CLI."""
|
2
|
-
|
3
|
-
import argparse
|
4
|
-
import asyncio
|
5
|
-
from typing import Sequence
|
6
|
-
|
7
|
-
from kscale.store import pybullet, urdf
|
8
|
-
|
9
|
-
|
10
|
-
async def main(args: Sequence[str] | None = None) -> None:
|
11
|
-
parser = argparse.ArgumentParser(description="K-Scale OnShape Library", add_help=False)
|
12
|
-
parser.add_argument(
|
13
|
-
"subcommand",
|
14
|
-
choices=[
|
15
|
-
"urdf",
|
16
|
-
"pybullet",
|
17
|
-
],
|
18
|
-
help="The subcommand to run",
|
19
|
-
)
|
20
|
-
parsed_args, remaining_args = parser.parse_known_args(args)
|
21
|
-
|
22
|
-
match parsed_args.subcommand:
|
23
|
-
case "urdf":
|
24
|
-
await urdf.main(remaining_args)
|
25
|
-
case "pybullet":
|
26
|
-
await pybullet.main(remaining_args)
|
27
|
-
|
28
|
-
|
29
|
-
def sync_main(args: Sequence[str] | None = None) -> None:
|
30
|
-
asyncio.run(main(args))
|
31
|
-
|
32
|
-
|
33
|
-
if __name__ == "__main__":
|
34
|
-
# python3 -m kscale.store.cli
|
35
|
-
sync_main()
|
kscale/store/client.py
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
"""Defines a typed client for the K-Scale Store API."""
|
2
|
-
|
3
|
-
import logging
|
4
|
-
from pathlib import Path
|
5
|
-
from types import TracebackType
|
6
|
-
from typing import Any, Dict, Type
|
7
|
-
from urllib.parse import urljoin
|
8
|
-
|
9
|
-
import httpx
|
10
|
-
from pydantic import BaseModel
|
11
|
-
|
12
|
-
from kscale.store.gen.api import (
|
13
|
-
NewListingRequest,
|
14
|
-
NewListingResponse,
|
15
|
-
SingleArtifactResponse,
|
16
|
-
UploadArtifactResponse,
|
17
|
-
)
|
18
|
-
from kscale.store.utils import get_api_key, get_api_root
|
19
|
-
|
20
|
-
logger = logging.getLogger(__name__)
|
21
|
-
|
22
|
-
|
23
|
-
class KScaleStoreClient:
|
24
|
-
def __init__(self, base_url: str = get_api_root()) -> None:
|
25
|
-
self.base_url = base_url
|
26
|
-
self.client = httpx.AsyncClient(
|
27
|
-
base_url=self.base_url,
|
28
|
-
headers={"Authorization": f"Bearer {get_api_key()}"},
|
29
|
-
timeout=httpx.Timeout(30.0),
|
30
|
-
)
|
31
|
-
|
32
|
-
async def _request(
|
33
|
-
self,
|
34
|
-
method: str,
|
35
|
-
endpoint: str,
|
36
|
-
*,
|
37
|
-
params: Dict[str, Any] | None = None,
|
38
|
-
data: BaseModel | None = None,
|
39
|
-
files: Dict[str, Any] | None = None,
|
40
|
-
) -> Dict[str, Any]:
|
41
|
-
url = urljoin(self.base_url, endpoint)
|
42
|
-
kwargs: Dict[str, Any] = {"params": params}
|
43
|
-
|
44
|
-
if data:
|
45
|
-
kwargs["json"] = data.dict(exclude_unset=True)
|
46
|
-
if files:
|
47
|
-
kwargs["files"] = files
|
48
|
-
|
49
|
-
response = await self.client.request(method, url, **kwargs)
|
50
|
-
if response.is_error:
|
51
|
-
logger.error(f"Error response from K-Scale Store: {response.text}")
|
52
|
-
response.raise_for_status()
|
53
|
-
return response.json()
|
54
|
-
|
55
|
-
async def get_artifact_info(self, artifact_id: str) -> SingleArtifactResponse:
|
56
|
-
data = await self._request("GET", f"/artifacts/info/{artifact_id}")
|
57
|
-
return SingleArtifactResponse(**data)
|
58
|
-
|
59
|
-
async def upload_artifact(self, listing_id: str, file_path: str) -> UploadArtifactResponse:
|
60
|
-
file_name = Path(file_path).name
|
61
|
-
with open(file_path, "rb") as f:
|
62
|
-
files = {"files": (file_name, f, "application/gzip")}
|
63
|
-
data = await self._request("POST", f"/artifacts/upload/{listing_id}", files=files)
|
64
|
-
return UploadArtifactResponse(**data)
|
65
|
-
|
66
|
-
async def create_listing(self, request: NewListingRequest) -> NewListingResponse:
|
67
|
-
data = await self._request("POST", "/listings", data=request)
|
68
|
-
return NewListingResponse(**data)
|
69
|
-
|
70
|
-
async def close(self) -> None:
|
71
|
-
await self.client.aclose()
|
72
|
-
|
73
|
-
async def __aenter__(self) -> "KScaleStoreClient":
|
74
|
-
return self
|
75
|
-
|
76
|
-
async def __aexit__(
|
77
|
-
self,
|
78
|
-
exc_type: Type[BaseException] | None,
|
79
|
-
exc_val: BaseException | None,
|
80
|
-
exc_tb: TracebackType | None,
|
81
|
-
) -> None:
|
82
|
-
await self.close()
|