kscale 0.1.0__py3-none-any.whl → 0.1.2__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/conf.py +1 -0
- kscale/requirements.txt +1 -1
- kscale/web/clients/robot_class.py +27 -4
- kscale/web/utils.py +6 -0
- {kscale-0.1.0.dist-info → kscale-0.1.2.dist-info}/METADATA +2 -2
- {kscale-0.1.0.dist-info → kscale-0.1.2.dist-info}/RECORD +11 -11
- {kscale-0.1.0.dist-info → kscale-0.1.2.dist-info}/LICENSE +0 -0
- {kscale-0.1.0.dist-info → kscale-0.1.2.dist-info}/WHEEL +0 -0
- {kscale-0.1.0.dist-info → kscale-0.1.2.dist-info}/entry_points.txt +0 -0
- {kscale-0.1.0.dist-info → kscale-0.1.2.dist-info}/top_level.txt +0 -0
kscale/__init__.py
CHANGED
kscale/conf.py
CHANGED
kscale/requirements.txt
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
"""Defines the client for interacting with the K-Scale robot class endpoints."""
|
2
2
|
|
3
3
|
import hashlib
|
4
|
+
import json
|
4
5
|
import logging
|
5
6
|
from pathlib import Path
|
6
7
|
|
@@ -8,10 +9,13 @@ import httpx
|
|
8
9
|
|
9
10
|
from kscale.web.clients.base import BaseClient
|
10
11
|
from kscale.web.gen.api import RobotClass, RobotDownloadURDFResponse, RobotUploadURDFResponse
|
11
|
-
from kscale.web.utils import get_cache_dir
|
12
|
+
from kscale.web.utils import get_cache_dir, should_refresh_file
|
12
13
|
|
13
14
|
logger = logging.getLogger(__name__)
|
14
15
|
|
16
|
+
UPLOAD_TIMEOUT = 300.0
|
17
|
+
DOWNLOAD_TIMEOUT = 60.0
|
18
|
+
|
15
19
|
|
16
20
|
class RobotClassClient(BaseClient):
|
17
21
|
async def get_robot_classes(self) -> list[RobotClass]:
|
@@ -77,7 +81,9 @@ class RobotClassClient(BaseClient):
|
|
77
81
|
auth=True,
|
78
82
|
)
|
79
83
|
response = RobotUploadURDFResponse.model_validate(data)
|
80
|
-
async with httpx.AsyncClient(
|
84
|
+
async with httpx.AsyncClient(
|
85
|
+
timeout=httpx.Timeout(UPLOAD_TIMEOUT),
|
86
|
+
) as client:
|
81
87
|
async with client.stream(
|
82
88
|
"PUT",
|
83
89
|
response.url,
|
@@ -89,15 +95,26 @@ class RobotClassClient(BaseClient):
|
|
89
95
|
|
90
96
|
async def download_robot_class_urdf(self, class_name: str, *, cache: bool = True) -> Path:
|
91
97
|
cache_path = get_cache_dir() / class_name / "robot.tgz"
|
92
|
-
if cache and cache_path.exists():
|
98
|
+
if cache and cache_path.exists() and not should_refresh_file(cache_path):
|
93
99
|
return cache_path
|
94
100
|
data = await self._request("GET", f"/robots/urdf/{class_name}", auth=True)
|
95
101
|
response = RobotDownloadURDFResponse.model_validate(data)
|
96
102
|
expected_hash = response.md5_hash
|
97
103
|
cache_path.parent.mkdir(parents=True, exist_ok=True)
|
98
104
|
|
105
|
+
# Checks the md5 hash of the file.
|
106
|
+
cache_path_info = cache_path.parent / "info.json"
|
107
|
+
if cache_path_info.exists():
|
108
|
+
with open(cache_path_info, "r") as f:
|
109
|
+
info = json.load(f)
|
110
|
+
if info["md5_hash"] == expected_hash:
|
111
|
+
cache_path.touch()
|
112
|
+
return cache_path
|
113
|
+
|
99
114
|
logger.info("Downloading URDF file from %s", response.url)
|
100
|
-
async with httpx.AsyncClient(
|
115
|
+
async with httpx.AsyncClient(
|
116
|
+
timeout=httpx.Timeout(DOWNLOAD_TIMEOUT),
|
117
|
+
) as client:
|
101
118
|
with open(cache_path, "wb") as file:
|
102
119
|
hash_value = hashlib.md5()
|
103
120
|
async with client.stream("GET", response.url) as r:
|
@@ -111,4 +128,10 @@ class RobotClassClient(BaseClient):
|
|
111
128
|
if hash_value_hex != expected_hash:
|
112
129
|
raise ValueError(f"MD5 hash mismatch: {hash_value_hex} != {expected_hash}")
|
113
130
|
|
131
|
+
# Updates the info file.
|
132
|
+
logger.info("Updating downloaded file information")
|
133
|
+
info = {"md5_hash": hash_value_hex}
|
134
|
+
with open(cache_path_info, "w") as f:
|
135
|
+
json.dump(info, f)
|
136
|
+
|
114
137
|
return cache_path
|
kscale/web/utils.py
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
import functools
|
4
4
|
import logging
|
5
|
+
import time
|
5
6
|
from pathlib import Path
|
6
7
|
|
7
8
|
from kscale.conf import Settings
|
@@ -17,6 +18,11 @@ def get_cache_dir() -> Path:
|
|
17
18
|
return Path(Settings.load().www.cache_dir).expanduser().resolve()
|
18
19
|
|
19
20
|
|
21
|
+
def should_refresh_file(file: Path) -> bool:
|
22
|
+
"""Returns whether the file should be refreshed."""
|
23
|
+
return file.exists() and file.stat().st_mtime < time.time() - Settings.load().www.refresh_interval_minutes * 60
|
24
|
+
|
25
|
+
|
20
26
|
@functools.lru_cache
|
21
27
|
def get_artifact_dir(artifact_id: str) -> Path:
|
22
28
|
"""Returns the directory for a specific artifact."""
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: kscale
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.2
|
4
4
|
Summary: The kscale project
|
5
5
|
Home-page: https://github.com/kscalelabs/kscale
|
6
6
|
Author: Benjamin Bolte
|
@@ -9,7 +9,6 @@ Description-Content-Type: text/markdown
|
|
9
9
|
License-File: LICENSE
|
10
10
|
Requires-Dist: omegaconf
|
11
11
|
Requires-Dist: email_validator
|
12
|
-
Requires-Dist: colorlogging
|
13
12
|
Requires-Dist: aiohttp
|
14
13
|
Requires-Dist: cryptography
|
15
14
|
Requires-Dist: httpx
|
@@ -19,6 +18,7 @@ Requires-Dist: requests
|
|
19
18
|
Requires-Dist: yarl
|
20
19
|
Requires-Dist: aiofiles
|
21
20
|
Requires-Dist: click
|
21
|
+
Requires-Dist: colorlogging
|
22
22
|
Requires-Dist: tabulate
|
23
23
|
Requires-Dist: async-lru
|
24
24
|
Requires-Dist: krec
|
@@ -1,10 +1,10 @@
|
|
1
|
-
kscale/__init__.py,sha256=
|
1
|
+
kscale/__init__.py,sha256=Do_oyhXSMNLURbvLDeTx4nJqgYgPhuREBynKDoeJyX4,172
|
2
2
|
kscale/api.py,sha256=jmiuFurTN_Gj_-k-6asqxw8wp-_bgJUXgMPFgJ4lqHA,230
|
3
3
|
kscale/cli.py,sha256=PMHLKR5UwdbbReVmqHXpJ-K9-mGHv_0I7KQkwxmFcUA,881
|
4
|
-
kscale/conf.py,sha256=
|
4
|
+
kscale/conf.py,sha256=x9jJ8pmSweUsLScN741B21SySCrnRZioV-1ZkhmERbI,1585
|
5
5
|
kscale/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
6
|
kscale/requirements-dev.txt,sha256=WI7-ea4IRJakmqVMN8QKhOsDGrghwtvk03aIsFaNSIw,130
|
7
|
-
kscale/requirements.txt,sha256=
|
7
|
+
kscale/requirements.txt,sha256=_BGbnKTQaXKx0bNEG0wguod9swsiCb2mF6rLm7sFJ2Q,214
|
8
8
|
kscale/artifacts/__init__.py,sha256=RK8wdybtCJPgdLLJ8R8-YMi1Ph5ojqAKVJZowHONtgo,232
|
9
9
|
kscale/artifacts/plane.obj,sha256=x59-IIrWpLjhotChiqT2Ul6U8s0RcHkaEeUZb4KXL1c,348
|
10
10
|
kscale/artifacts/plane.urdf,sha256=LCiTk14AyTHjkZ1jvsb0hNaEaJUxDb8Z1JjsgpXu3YM,819
|
@@ -14,7 +14,7 @@ kscale/utils/checksum.py,sha256=jt6QmmQND9zrOEnUtOfZpLYROhgto4Gh3OpdUWk4tZA,1093
|
|
14
14
|
kscale/utils/cli.py,sha256=JoaY5x5SdUx97KmMM9j5AjRRUqqrTlJ9qVckZptEsYA,827
|
15
15
|
kscale/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
16
|
kscale/web/api.py,sha256=YioIdruq7LCKSBf9SvOGkv914W36_zBmpTzsJqKc0wE,439
|
17
|
-
kscale/web/utils.py,sha256=
|
17
|
+
kscale/web/utils.py,sha256=l_m8GETCThhnXbHfXq53j1b-E__uZ5GuUbsQ8HR0WA0,1037
|
18
18
|
kscale/web/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
19
|
kscale/web/cli/robot.py,sha256=rI-A4_0uvJPeA71Apl4Z3mV5fIfWkgmzT9JRmJYxz3A,3307
|
20
20
|
kscale/web/cli/robot_class.py,sha256=ymC5phUqofvOXv5P6f51b9lMK5eRDaavvnzS0x9rDbU,3574
|
@@ -24,13 +24,13 @@ kscale/web/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
|
|
24
24
|
kscale/web/clients/base.py,sha256=NRqRH2JTXjJLUMDM93txKgwFu9bQRYhCYLYy7vE76Ik,11462
|
25
25
|
kscale/web/clients/client.py,sha256=QjBicdHQYNoUG9XRjAYmGu3THae9DzWa_hQox3OO1Gw,214
|
26
26
|
kscale/web/clients/robot.py,sha256=HMfJnkDxaJ_o7X2vdYYS9iob1JRoBG2qiGmQpCQZpAk,1485
|
27
|
-
kscale/web/clients/robot_class.py,sha256=
|
27
|
+
kscale/web/clients/robot_class.py,sha256=vFXlvwQBmt7zEOixAI-mByBEkXCMZIW5OZjiESMavps,5050
|
28
28
|
kscale/web/clients/user.py,sha256=9iv8J-ROm_yBIwi-0oqldReLkNBFktdHRv3UCOxBzjY,377
|
29
29
|
kscale/web/gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
30
|
kscale/web/gen/api.py,sha256=SovcII36JFgK9jd2CXlLPMjiUROGB4vEnapOsYMUrkU,2188
|
31
|
-
kscale-0.1.
|
32
|
-
kscale-0.1.
|
33
|
-
kscale-0.1.
|
34
|
-
kscale-0.1.
|
35
|
-
kscale-0.1.
|
36
|
-
kscale-0.1.
|
31
|
+
kscale-0.1.2.dist-info/LICENSE,sha256=HCN2bImAzUOXldAZZI7JZ9PYq6OwMlDAP_PpX1HnuN0,1071
|
32
|
+
kscale-0.1.2.dist-info/METADATA,sha256=YEcA0zqZwXvW9BnfZn51PrTXcwemCxMuolC1jB7NG-g,2340
|
33
|
+
kscale-0.1.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
34
|
+
kscale-0.1.2.dist-info/entry_points.txt,sha256=N_0pCpPnwGDYVzOeuaSOrbJkS5L3lS9d8CxpJF1f8UI,62
|
35
|
+
kscale-0.1.2.dist-info/top_level.txt,sha256=C2ynjYwopg6YjgttnI2dJjasyq3EKNmYp-IfQg9Xms4,7
|
36
|
+
kscale-0.1.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|