kscale 0.2.0__tar.gz → 0.2.1__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {kscale-0.2.0/kscale.egg-info → kscale-0.2.1}/PKG-INFO +1 -1
- {kscale-0.2.0 → kscale-0.2.1}/kscale/__init__.py +2 -2
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/cli/robot_class.py +1 -1
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/client.py +4 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/robot_class.py +38 -2
- {kscale-0.2.0 → kscale-0.2.1/kscale.egg-info}/PKG-INFO +1 -1
- {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/SOURCES.txt +0 -2
- kscale-0.2.0/kscale/api.py +0 -11
- kscale-0.2.0/kscale/web/api.py +0 -18
- {kscale-0.2.0 → kscale-0.2.1}/LICENSE +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/MANIFEST.in +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/README.md +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/artifacts/__init__.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/artifacts/plane.obj +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/artifacts/plane.urdf +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/cli.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/conf.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/py.typed +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/requirements-dev.txt +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/requirements.txt +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/utils/__init__.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/utils/api_base.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/utils/checksum.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/utils/cli.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/__init__.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/cli/__init__.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/cli/robot.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/cli/token.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/cli/user.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/__init__.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/base.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/robot.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/user.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/gen/__init__.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/gen/api.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale/web/utils.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/dependency_links.txt +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/entry_points.txt +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/not-zip-safe +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/requires.txt +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/top_level.txt +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/pyproject.toml +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/setup.cfg +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/setup.py +0 -0
- {kscale-0.2.0 → kscale-0.2.1}/tests/test_dummy.py +0 -0
@@ -1,9 +1,9 @@
|
|
1
1
|
"""Defines the common interface for the K-Scale Python API."""
|
2
2
|
|
3
|
-
__version__ = "0.2.
|
3
|
+
__version__ = "0.2.1"
|
4
4
|
|
5
5
|
from pathlib import Path
|
6
6
|
|
7
|
-
from kscale.
|
7
|
+
from kscale.web.clients.client import WWWClient as K
|
8
8
|
|
9
9
|
ROOT_DIR = Path(__file__).parent
|
@@ -105,7 +105,7 @@ async def upload(class_name: str, urdf_file: str) -> None:
|
|
105
105
|
async def download(class_name: str, no_cache: bool) -> None:
|
106
106
|
"""Downloads a URDF file from a robot class."""
|
107
107
|
async with RobotClassClient() as client:
|
108
|
-
urdf_file = await client.
|
108
|
+
urdf_file = await client.download_compressed_urdf(class_name, cache=not no_cache)
|
109
109
|
click.echo(f"URDF downloaded: {click.style(urdf_file, fg='green')}")
|
110
110
|
|
111
111
|
|
@@ -1,10 +1,14 @@
|
|
1
1
|
"""Defines a unified client for the K-Scale WWW API."""
|
2
2
|
|
3
3
|
from kscale.web.clients.base import BaseClient
|
4
|
+
from kscale.web.clients.robot import RobotClient
|
5
|
+
from kscale.web.clients.robot_class import RobotClassClient
|
4
6
|
from kscale.web.clients.user import UserClient
|
5
7
|
|
6
8
|
|
7
9
|
class WWWClient(
|
10
|
+
RobotClient,
|
11
|
+
RobotClassClient,
|
8
12
|
UserClient,
|
9
13
|
BaseClient,
|
10
14
|
):
|
@@ -3,6 +3,7 @@
|
|
3
3
|
import hashlib
|
4
4
|
import json
|
5
5
|
import logging
|
6
|
+
import tarfile
|
6
7
|
from pathlib import Path
|
7
8
|
|
8
9
|
import httpx
|
@@ -20,6 +21,8 @@ logger = logging.getLogger(__name__)
|
|
20
21
|
UPLOAD_TIMEOUT = 300.0
|
21
22
|
DOWNLOAD_TIMEOUT = 60.0
|
22
23
|
|
24
|
+
INFO_FILE_NAME = ".info.json"
|
25
|
+
|
23
26
|
|
24
27
|
class RobotClassClient(BaseClient):
|
25
28
|
async def get_robot_classes(self) -> list[RobotClass]:
|
@@ -97,7 +100,7 @@ class RobotClassClient(BaseClient):
|
|
97
100
|
r.raise_for_status()
|
98
101
|
return response
|
99
102
|
|
100
|
-
async def
|
103
|
+
async def download_compressed_urdf(self, class_name: str, *, cache: bool = True) -> Path:
|
101
104
|
cache_path = get_robots_dir() / class_name / "robot.tgz"
|
102
105
|
if cache and cache_path.exists() and not should_refresh_file(cache_path):
|
103
106
|
return cache_path
|
@@ -107,7 +110,7 @@ class RobotClassClient(BaseClient):
|
|
107
110
|
cache_path.parent.mkdir(parents=True, exist_ok=True)
|
108
111
|
|
109
112
|
# Checks the md5 hash of the file.
|
110
|
-
cache_path_info = cache_path.parent /
|
113
|
+
cache_path_info = cache_path.parent / INFO_FILE_NAME
|
111
114
|
if cache_path_info.exists():
|
112
115
|
with open(cache_path_info, "r") as f:
|
113
116
|
info = json.load(f)
|
@@ -138,3 +141,36 @@ class RobotClassClient(BaseClient):
|
|
138
141
|
json.dump(info, f)
|
139
142
|
|
140
143
|
return cache_path
|
144
|
+
|
145
|
+
async def download_and_extract_urdf(self, class_name: str, *, cache: bool = True) -> Path:
|
146
|
+
cache_path = await self.download_compressed_urdf(class_name, cache=cache)
|
147
|
+
|
148
|
+
# Reads the MD5 hash from the info file.
|
149
|
+
cache_path_info = cache_path.parent / INFO_FILE_NAME
|
150
|
+
with open(cache_path_info, "r") as f:
|
151
|
+
info = json.load(f)
|
152
|
+
expected_hash = info["md5_hash"]
|
153
|
+
|
154
|
+
# Unpacks the file if requested.
|
155
|
+
unpack_path = cache_path.parent / "robot"
|
156
|
+
unpack_path.mkdir(parents=True, exist_ok=True)
|
157
|
+
unpacked_path_info = unpack_path / INFO_FILE_NAME
|
158
|
+
|
159
|
+
# If the file has already been unpacked, return the path.
|
160
|
+
if unpacked_path_info.exists():
|
161
|
+
with open(unpacked_path_info, "r") as f:
|
162
|
+
info = json.load(f)
|
163
|
+
if info["md5_hash"] == expected_hash:
|
164
|
+
unpack_path.touch()
|
165
|
+
return unpack_path
|
166
|
+
|
167
|
+
logger.info("Unpacking URDF file")
|
168
|
+
with tarfile.open(cache_path, "r:gz") as tar:
|
169
|
+
tar.extractall(path=unpack_path)
|
170
|
+
|
171
|
+
logger.info("Updating downloaded file information")
|
172
|
+
info = {"md5_hash": expected_hash}
|
173
|
+
with open(unpacked_path_info, "w") as f:
|
174
|
+
json.dump(info, f)
|
175
|
+
|
176
|
+
return unpack_path
|
@@ -4,7 +4,6 @@ README.md
|
|
4
4
|
pyproject.toml
|
5
5
|
setup.py
|
6
6
|
kscale/__init__.py
|
7
|
-
kscale/api.py
|
8
7
|
kscale/cli.py
|
9
8
|
kscale/conf.py
|
10
9
|
kscale/py.typed
|
@@ -25,7 +24,6 @@ kscale/utils/api_base.py
|
|
25
24
|
kscale/utils/checksum.py
|
26
25
|
kscale/utils/cli.py
|
27
26
|
kscale/web/__init__.py
|
28
|
-
kscale/web/api.py
|
29
27
|
kscale/web/utils.py
|
30
28
|
kscale/web/cli/__init__.py
|
31
29
|
kscale/web/cli/robot.py
|
kscale-0.2.0/kscale/api.py
DELETED
kscale-0.2.0/kscale/web/api.py
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
"""Defines a common interface for the K-Scale WWW API."""
|
2
|
-
|
3
|
-
from kscale.utils.api_base import APIBase
|
4
|
-
from kscale.web.clients.client import WWWClient
|
5
|
-
from kscale.web.gen.api import ProfileResponse
|
6
|
-
|
7
|
-
|
8
|
-
class WebAPI(APIBase):
|
9
|
-
async def www_client(self) -> WWWClient:
|
10
|
-
return WWWClient()
|
11
|
-
|
12
|
-
async def get_profile_info(self) -> ProfileResponse:
|
13
|
-
client = await self.www_client()
|
14
|
-
return await client.get_profile_info()
|
15
|
-
|
16
|
-
async def get_api_key(self, num_hours: int = 24) -> str:
|
17
|
-
client = await self.www_client()
|
18
|
-
return await client.get_api_key(num_hours)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|