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.
Files changed (45) hide show
  1. {kscale-0.2.0/kscale.egg-info → kscale-0.2.1}/PKG-INFO +1 -1
  2. {kscale-0.2.0 → kscale-0.2.1}/kscale/__init__.py +2 -2
  3. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/cli/robot_class.py +1 -1
  4. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/client.py +4 -0
  5. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/robot_class.py +38 -2
  6. {kscale-0.2.0 → kscale-0.2.1/kscale.egg-info}/PKG-INFO +1 -1
  7. {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/SOURCES.txt +0 -2
  8. kscale-0.2.0/kscale/api.py +0 -11
  9. kscale-0.2.0/kscale/web/api.py +0 -18
  10. {kscale-0.2.0 → kscale-0.2.1}/LICENSE +0 -0
  11. {kscale-0.2.0 → kscale-0.2.1}/MANIFEST.in +0 -0
  12. {kscale-0.2.0 → kscale-0.2.1}/README.md +0 -0
  13. {kscale-0.2.0 → kscale-0.2.1}/kscale/artifacts/__init__.py +0 -0
  14. {kscale-0.2.0 → kscale-0.2.1}/kscale/artifacts/plane.obj +0 -0
  15. {kscale-0.2.0 → kscale-0.2.1}/kscale/artifacts/plane.urdf +0 -0
  16. {kscale-0.2.0 → kscale-0.2.1}/kscale/cli.py +0 -0
  17. {kscale-0.2.0 → kscale-0.2.1}/kscale/conf.py +0 -0
  18. {kscale-0.2.0 → kscale-0.2.1}/kscale/py.typed +0 -0
  19. {kscale-0.2.0 → kscale-0.2.1}/kscale/requirements-dev.txt +0 -0
  20. {kscale-0.2.0 → kscale-0.2.1}/kscale/requirements.txt +0 -0
  21. {kscale-0.2.0 → kscale-0.2.1}/kscale/utils/__init__.py +0 -0
  22. {kscale-0.2.0 → kscale-0.2.1}/kscale/utils/api_base.py +0 -0
  23. {kscale-0.2.0 → kscale-0.2.1}/kscale/utils/checksum.py +0 -0
  24. {kscale-0.2.0 → kscale-0.2.1}/kscale/utils/cli.py +0 -0
  25. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/__init__.py +0 -0
  26. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/cli/__init__.py +0 -0
  27. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/cli/robot.py +0 -0
  28. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/cli/token.py +0 -0
  29. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/cli/user.py +0 -0
  30. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/__init__.py +0 -0
  31. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/base.py +0 -0
  32. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/robot.py +0 -0
  33. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/clients/user.py +0 -0
  34. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/gen/__init__.py +0 -0
  35. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/gen/api.py +0 -0
  36. {kscale-0.2.0 → kscale-0.2.1}/kscale/web/utils.py +0 -0
  37. {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/dependency_links.txt +0 -0
  38. {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/entry_points.txt +0 -0
  39. {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/not-zip-safe +0 -0
  40. {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/requires.txt +0 -0
  41. {kscale-0.2.0 → kscale-0.2.1}/kscale.egg-info/top_level.txt +0 -0
  42. {kscale-0.2.0 → kscale-0.2.1}/pyproject.toml +0 -0
  43. {kscale-0.2.0 → kscale-0.2.1}/setup.cfg +0 -0
  44. {kscale-0.2.0 → kscale-0.2.1}/setup.py +0 -0
  45. {kscale-0.2.0 → kscale-0.2.1}/tests/test_dummy.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: kscale
3
- Version: 0.2.0
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,9 +1,9 @@
1
1
  """Defines the common interface for the K-Scale Python API."""
2
2
 
3
- __version__ = "0.2.0"
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
  ):
@@ -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 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:
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 / "info.json"
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: kscale
3
- Version: 0.2.0
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
@@ -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
@@ -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."""
@@ -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