kscale 0.1.5__py3-none-any.whl → 0.2.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
kscale/__init__.py CHANGED
@@ -1,9 +1,9 @@
1
1
  """Defines the common interface for the K-Scale Python API."""
2
2
 
3
- __version__ = "0.1.5"
3
+ __version__ = "0.2.1"
4
4
 
5
5
  from pathlib import Path
6
6
 
7
- from kscale.api import K
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.download_robot_class_urdf(class_name, cache=not no_cache)
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
  ):
@@ -21,6 +21,8 @@ logger = logging.getLogger(__name__)
21
21
  UPLOAD_TIMEOUT = 300.0
22
22
  DOWNLOAD_TIMEOUT = 60.0
23
23
 
24
+ INFO_FILE_NAME = ".info.json"
25
+
24
26
 
25
27
  class RobotClassClient(BaseClient):
26
28
  async def get_robot_classes(self) -> list[RobotClass]:
@@ -98,7 +100,7 @@ class RobotClassClient(BaseClient):
98
100
  r.raise_for_status()
99
101
  return response
100
102
 
101
- async def download_robot_class_urdf(self, class_name: str, *, cache: bool = True) -> Path:
103
+ async def download_compressed_urdf(self, class_name: str, *, cache: bool = True) -> Path:
102
104
  cache_path = get_robots_dir() / class_name / "robot.tgz"
103
105
  if cache and cache_path.exists() and not should_refresh_file(cache_path):
104
106
  return cache_path
@@ -108,7 +110,7 @@ class RobotClassClient(BaseClient):
108
110
  cache_path.parent.mkdir(parents=True, exist_ok=True)
109
111
 
110
112
  # Checks the md5 hash of the file.
111
- cache_path_info = cache_path.parent / "info.json"
113
+ cache_path_info = cache_path.parent / INFO_FILE_NAME
112
114
  if cache_path_info.exists():
113
115
  with open(cache_path_info, "r") as f:
114
116
  info = json.load(f)
@@ -133,13 +135,42 @@ class RobotClassClient(BaseClient):
133
135
  if hash_value_hex != expected_hash:
134
136
  raise ValueError(f"MD5 hash mismatch: {hash_value_hex} != {expected_hash}")
135
137
 
136
- logger.info("Unpacking downloaded file")
137
- with tarfile.open(cache_path, "r:gz") as tar:
138
- tar.extractall(path=cache_path.parent)
139
-
140
138
  logger.info("Updating downloaded file information")
141
139
  info = {"md5_hash": hash_value_hex}
142
140
  with open(cache_path_info, "w") as f:
143
141
  json.dump(info, f)
144
142
 
145
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: kscale
3
- Version: 0.1.5
3
+ Version: 0.2.1
4
4
  Summary: The kscale project
5
5
  Home-page: https://github.com/kscalelabs/kscale
6
6
  Author: Benjamin Bolte
@@ -1,5 +1,4 @@
1
- kscale/__init__.py,sha256=SnUAXz1ZDSR98-rg2Ne7pAF7YPDh5i3v3EyoZxR3l-4,172
2
- kscale/api.py,sha256=jmiuFurTN_Gj_-k-6asqxw8wp-_bgJUXgMPFgJ4lqHA,230
1
+ kscale/__init__.py,sha256=73uaPK_Lj05TFJYmYf9BjFp9JHB5XKLlMIwORoDZpx0,200
3
2
  kscale/cli.py,sha256=PMHLKR5UwdbbReVmqHXpJ-K9-mGHv_0I7KQkwxmFcUA,881
4
3
  kscale/conf.py,sha256=OLGz2J-9NAaICoWeN9-hCxrOsyf0vpJBNw-UzIsHdwE,1572
5
4
  kscale/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -13,24 +12,23 @@ kscale/utils/api_base.py,sha256=Kk_WtRDdJHmOg6NtHmVxVrcfARSUkhfr29ypLch_pO0,112
13
12
  kscale/utils/checksum.py,sha256=jt6QmmQND9zrOEnUtOfZpLYROhgto4Gh3OpdUWk4tZA,1093
14
13
  kscale/utils/cli.py,sha256=JoaY5x5SdUx97KmMM9j5AjRRUqqrTlJ9qVckZptEsYA,827
15
14
  kscale/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- kscale/web/api.py,sha256=oyW0XLfX96RPe1xNgdf8ejfATdLlNlP0CL1lP0FN1nM,593
17
15
  kscale/web/utils.py,sha256=Mme-FAQ0_zbjjOQeX8wyq8F4kL4i9fH7ytri16U6qOA,1046
18
16
  kscale/web/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
17
  kscale/web/cli/robot.py,sha256=rI-A4_0uvJPeA71Apl4Z3mV5fIfWkgmzT9JRmJYxz3A,3307
20
- kscale/web/cli/robot_class.py,sha256=ymC5phUqofvOXv5P6f51b9lMK5eRDaavvnzS0x9rDbU,3574
18
+ kscale/web/cli/robot_class.py,sha256=8igY6oWUDafb644QzmqC5cX6Az0rNJau_jvLr7YkCd0,3573
21
19
  kscale/web/cli/token.py,sha256=1rFC8MYKtqbNsQa2KIqwW1tqpaMtFaxuNsallwejXTU,787
22
20
  kscale/web/cli/user.py,sha256=aaJJCL1P5lfhK6ZC9OwOHXKA-I3MWqVZ_k7TYnx33CY,1303
23
21
  kscale/web/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
22
  kscale/web/clients/base.py,sha256=uovIxtkotRxrIFL0PhLYDIhhfXrIGjXxNY2FLVO3L18,15110
25
- kscale/web/clients/client.py,sha256=QjBicdHQYNoUG9XRjAYmGu3THae9DzWa_hQox3OO1Gw,214
23
+ kscale/web/clients/client.py,sha256=rzW2s8T7bKVuybOSQ65-ghl02rcXBoOxnx_nUDwgEPw,362
26
24
  kscale/web/clients/robot.py,sha256=HMfJnkDxaJ_o7X2vdYYS9iob1JRoBG2qiGmQpCQZpAk,1485
27
- kscale/web/clients/robot_class.py,sha256=O_6lAKAcdNGFVtojuiQlgPCVP5MQlYPZG5Z-awwauho,5206
25
+ kscale/web/clients/robot_class.py,sha256=zCFL-Y_jIfO9_qOwzBAHzfgFxzpltMte4LM5haCC24U,6385
28
26
  kscale/web/clients/user.py,sha256=jsa1_s6qXRM-AGBbHlPhd1NierUtynjY9tVAPNr6_Os,568
29
27
  kscale/web/gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
28
  kscale/web/gen/api.py,sha256=SovcII36JFgK9jd2CXlLPMjiUROGB4vEnapOsYMUrkU,2188
31
- kscale-0.1.5.dist-info/LICENSE,sha256=HCN2bImAzUOXldAZZI7JZ9PYq6OwMlDAP_PpX1HnuN0,1071
32
- kscale-0.1.5.dist-info/METADATA,sha256=kTsVXOA7Zh2m_eqBm2iaxanfL92BNpPadsC-vasZ018,2340
33
- kscale-0.1.5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
34
- kscale-0.1.5.dist-info/entry_points.txt,sha256=N_0pCpPnwGDYVzOeuaSOrbJkS5L3lS9d8CxpJF1f8UI,62
35
- kscale-0.1.5.dist-info/top_level.txt,sha256=C2ynjYwopg6YjgttnI2dJjasyq3EKNmYp-IfQg9Xms4,7
36
- kscale-0.1.5.dist-info/RECORD,,
29
+ kscale-0.2.1.dist-info/LICENSE,sha256=HCN2bImAzUOXldAZZI7JZ9PYq6OwMlDAP_PpX1HnuN0,1071
30
+ kscale-0.2.1.dist-info/METADATA,sha256=IeSxq7ApAKrn48Xep-kRu-wQpOq14y_M3GbUgcpHbJE,2340
31
+ kscale-0.2.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
32
+ kscale-0.2.1.dist-info/entry_points.txt,sha256=N_0pCpPnwGDYVzOeuaSOrbJkS5L3lS9d8CxpJF1f8UI,62
33
+ kscale-0.2.1.dist-info/top_level.txt,sha256=C2ynjYwopg6YjgttnI2dJjasyq3EKNmYp-IfQg9Xms4,7
34
+ kscale-0.2.1.dist-info/RECORD,,
kscale/api.py DELETED
@@ -1,11 +0,0 @@
1
- """Defines common functionality for the K-Scale API."""
2
-
3
- from kscale.utils.api_base import APIBase
4
- from kscale.web.api import WebAPI
5
-
6
-
7
- class K(
8
- WebAPI,
9
- APIBase,
10
- ):
11
- """Defines a common interface for the K-Scale API."""
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