kscale 0.3.7__py3-none-any.whl → 0.3.9__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 CHANGED
@@ -1,6 +1,6 @@
1
1
  """Defines the common interface for the K-Scale Python API."""
2
2
 
3
- __version__ = "0.3.7"
3
+ __version__ = "0.3.9"
4
4
 
5
5
  from pathlib import Path
6
6
 
kscale/cli.py CHANGED
@@ -8,7 +8,6 @@ import colorlogging
8
8
  from kscale.utils.cli import recursive_help
9
9
  from kscale.web.cli.robot import cli as robot_cli
10
10
  from kscale.web.cli.robot_class import cli as robot_class_cli
11
- from kscale.web.cli.token import cli as token_cli
12
11
  from kscale.web.cli.user import cli as user_cli
13
12
 
14
13
 
@@ -22,7 +21,6 @@ def cli() -> None:
22
21
  logging.getLogger("aiohttp.access").setLevel(logging.WARNING)
23
22
 
24
23
 
25
- cli.add_command(token_cli, "token")
26
24
  cli.add_command(user_cli, "user")
27
25
  cli.add_command(robot_class_cli, "robots")
28
26
  cli.add_command(robot_cli, "robot")
@@ -1,5 +1,6 @@
1
1
  """Defines the CLI for getting information about robot classes."""
2
2
 
3
+ import itertools
3
4
  import json
4
5
  import logging
5
6
  import math
@@ -452,19 +453,20 @@ async def run_mujoco(class_name: str, no_cache: bool) -> None:
452
453
  try:
453
454
  import mujoco.viewer
454
455
  except ImportError:
455
- click.echo(
456
- click.style(
457
- "Mujoco and mujoco-python-viewer are required; install with `pip install mujoco`",
458
- fg="red",
459
- )
460
- )
456
+ click.echo(click.style("Mujoco is required; install with `pip install mujoco`", fg="red"))
461
457
  return
462
458
 
463
459
  async with RobotClassClient() as client:
464
460
  extracted_folder = await client.download_and_extract_urdf(class_name, cache=not no_cache)
465
461
 
466
462
  try:
467
- mjcf_file = next(extracted_folder.glob("*.mjcf"))
463
+ mjcf_file = next(
464
+ itertools.chain(
465
+ extracted_folder.glob("*.scene.mjcf"),
466
+ extracted_folder.glob("*.mjcf"),
467
+ extracted_folder.glob("*.xml"),
468
+ )
469
+ )
468
470
  except StopIteration:
469
471
  click.echo(click.style(f"No MJCF file found in {extracted_folder}", fg="red"))
470
472
  return
kscale/web/cli/user.py CHANGED
@@ -45,8 +45,7 @@ async def key() -> None:
45
45
  """Get an API key for the currently-authenticated user."""
46
46
  client = UserClient()
47
47
  api_key = await client.get_api_key()
48
- click.echo("API key:")
49
- click.echo(click.style(api_key, fg="green"))
48
+ click.echo(f"API key: {click.style(api_key, fg='green')}")
50
49
 
51
50
 
52
51
  if __name__ == "__main__":
@@ -5,6 +5,7 @@ import json
5
5
  import logging
6
6
  import os
7
7
  import secrets
8
+ import sys
8
9
  import time
9
10
  import webbrowser
10
11
  from types import TracebackType
@@ -31,6 +32,10 @@ OAUTH_PORT = 16821
31
32
  HEADER_NAME = "x-kscale-api-key"
32
33
 
33
34
 
35
+ def verbose_error() -> bool:
36
+ return os.environ.get("KSCALE_VERBOSE_ERROR", "0") == "1"
37
+
38
+
34
39
  class OAuthCallback:
35
40
  def __init__(self) -> None:
36
41
  self.token_type: str | None = None
@@ -375,8 +380,14 @@ class BaseClient:
375
380
  response = await client.request(method, url, **kwargs)
376
381
 
377
382
  if response.is_error:
378
- logger.error("Error response from K-Scale: %s", response.text)
379
- response.raise_for_status()
383
+ logger.error("Got %d error K-Scale: %s", response.status_code, response.text)
384
+ if verbose_error():
385
+ response.raise_for_status()
386
+ else:
387
+ logger.error("Use KSCALE_VERBOSE_ERROR=1 to see the full error message")
388
+ logger.error("If this persists, please create an issue here: https://github.com/kscalelabs/kscale")
389
+ sys.exit(1)
390
+
380
391
  return response.json()
381
392
 
382
393
  async def close(self) -> None:
kscale/web/gen/api.py CHANGED
@@ -36,6 +36,7 @@ class JointMetadataInput(BaseModel):
36
36
  friction: Optional[Union[float, str]] = Field(None, title="Friction")
37
37
  offset: Optional[Union[float, str]] = Field(None, title="Offset")
38
38
  flipped: Optional[bool] = Field(None, title="Flipped")
39
+ actuator_type: Optional[str] = Field(None, title="Actuator Type")
39
40
 
40
41
 
41
42
  class JointMetadataOutput(BaseModel):
@@ -46,6 +47,7 @@ class JointMetadataOutput(BaseModel):
46
47
  friction: Optional[str] = Field(None, title="Friction")
47
48
  offset: Optional[str] = Field(None, title="Offset")
48
49
  flipped: Optional[bool] = Field(None, title="Flipped")
50
+ actuator_type: Optional[str] = Field(None, title="Actuator Type")
49
51
 
50
52
 
51
53
  class OICDInfo(BaseModel):
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: kscale
3
- Version: 0.3.7
3
+ Version: 0.3.9
4
4
  Summary: The kscale project
5
5
  Home-page: https://github.com/kscalelabs/kscale
6
6
  Author: Benjamin Bolte
@@ -32,6 +32,7 @@ Dynamic: author
32
32
  Dynamic: description
33
33
  Dynamic: description-content-type
34
34
  Dynamic: home-page
35
+ Dynamic: license-file
35
36
  Dynamic: provides-extra
36
37
  Dynamic: requires-dist
37
38
  Dynamic: requires-python
@@ -1,5 +1,5 @@
1
- kscale/__init__.py,sha256=JXk1-68D39Xj5C7awsV8wBXSDoj4Zds3jDuQP0VvMyY,200
2
- kscale/cli.py,sha256=PMHLKR5UwdbbReVmqHXpJ-K9-mGHv_0I7KQkwxmFcUA,881
1
+ kscale/__init__.py,sha256=Cy-vvz6K5u5eWHpZ4Ia6rH75rLZxjsRF9FGJDItTADs,200
2
+ kscale/cli.py,sha256=JvaPtmWvF7s0D4I3K98eZAItf3oOi2ULsn5aPGxDcu4,795
3
3
  kscale/conf.py,sha256=dm35XSnzJp93St-ixVtYN4Nvqvb5upPGBrWkSI6Yb-4,1743
4
4
  kscale/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  kscale/requirements-dev.txt,sha256=WI7-ea4IRJakmqVMN8QKhOsDGrghwtvk03aIsFaNSIw,130
@@ -15,20 +15,19 @@ kscale/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  kscale/web/utils.py,sha256=Mme-FAQ0_zbjjOQeX8wyq8F4kL4i9fH7ytri16U6qOA,1046
16
16
  kscale/web/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  kscale/web/cli/robot.py,sha256=rI-A4_0uvJPeA71Apl4Z3mV5fIfWkgmzT9JRmJYxz3A,3307
18
- kscale/web/cli/robot_class.py,sha256=QjE65uw2lSaerrdFr_zZzN9_W5w4Rx4exWZkijpDzmQ,18892
19
- kscale/web/cli/token.py,sha256=1rFC8MYKtqbNsQa2KIqwW1tqpaMtFaxuNsallwejXTU,787
20
- kscale/web/cli/user.py,sha256=aaJJCL1P5lfhK6ZC9OwOHXKA-I3MWqVZ_k7TYnx33CY,1303
18
+ kscale/web/cli/robot_class.py,sha256=DLB5ok69JAeUUeA7Yy80VmyZGFt9dKf8kD0vSBMmqP8,18987
19
+ kscale/web/cli/user.py,sha256=9IGsJBPyhjsmT04mZ2RGOs35ePfqB2RltYP0Ty5zF5o,1290
21
20
  kscale/web/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- kscale/web/clients/base.py,sha256=A70BF9ZnHEBds0RKrowbeUNsX_WwsgV349csUlM4iMc,15174
21
+ kscale/web/clients/base.py,sha256=ThQakuvGh7CquiGQ4wiCyCWAgqmKInsJcANo910X9Uw,15585
23
22
  kscale/web/clients/client.py,sha256=rzW2s8T7bKVuybOSQ65-ghl02rcXBoOxnx_nUDwgEPw,362
24
23
  kscale/web/clients/robot.py,sha256=PI8HHkU-4Re9I5rLpp6dGbekRE-rBNVfXZxR_mO2MqE,1485
25
24
  kscale/web/clients/robot_class.py,sha256=G8Nk6V7LGJE9Wpg9tyyCkIfz1fRTsxXQRgHtleiUVqo,6834
26
25
  kscale/web/clients/user.py,sha256=jsa1_s6qXRM-AGBbHlPhd1NierUtynjY9tVAPNr6_Os,568
27
26
  kscale/web/gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- kscale/web/gen/api.py,sha256=VWlt8TaMZaAhCPPIWhx1d4yE0BRfpVz0-_Cps8hjgAI,4662
29
- kscale-0.3.7.dist-info/LICENSE,sha256=HCN2bImAzUOXldAZZI7JZ9PYq6OwMlDAP_PpX1HnuN0,1071
30
- kscale-0.3.7.dist-info/METADATA,sha256=0hDh7EJaKk94ofN-EfGPVcvlSNs1vfcuVTI5vx9DB6Y,2320
31
- kscale-0.3.7.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
32
- kscale-0.3.7.dist-info/entry_points.txt,sha256=N_0pCpPnwGDYVzOeuaSOrbJkS5L3lS9d8CxpJF1f8UI,62
33
- kscale-0.3.7.dist-info/top_level.txt,sha256=C2ynjYwopg6YjgttnI2dJjasyq3EKNmYp-IfQg9Xms4,7
34
- kscale-0.3.7.dist-info/RECORD,,
27
+ kscale/web/gen/api.py,sha256=GEQpOovAzixZa582d-t_O1dYYoEXrso2_DXXlxn7A48,4802
28
+ kscale-0.3.9.dist-info/licenses/LICENSE,sha256=HCN2bImAzUOXldAZZI7JZ9PYq6OwMlDAP_PpX1HnuN0,1071
29
+ kscale-0.3.9.dist-info/METADATA,sha256=ZaPRFJfJ8YKHaK7pmQSEXNWZLkmqV2IHt3m2Vz3gY74,2342
30
+ kscale-0.3.9.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
31
+ kscale-0.3.9.dist-info/entry_points.txt,sha256=N_0pCpPnwGDYVzOeuaSOrbJkS5L3lS9d8CxpJF1f8UI,62
32
+ kscale-0.3.9.dist-info/top_level.txt,sha256=C2ynjYwopg6YjgttnI2dJjasyq3EKNmYp-IfQg9Xms4,7
33
+ kscale-0.3.9.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
kscale/web/cli/token.py DELETED
@@ -1,33 +0,0 @@
1
- """Defines the CLI for interacting with K-Scale's OpenID Connect server."""
2
-
3
- import logging
4
-
5
- import click
6
-
7
- from kscale.utils.cli import coro
8
- from kscale.web.clients.base import BaseClient
9
-
10
- logger = logging.getLogger(__name__)
11
-
12
-
13
- @click.group()
14
- def cli() -> None:
15
- """Retrieve an OICD token from the K-Scale authentication server."""
16
- pass
17
-
18
-
19
- @cli.command()
20
- @coro
21
- async def get() -> None:
22
- """Get a bearer token from OpenID Connect."""
23
- logging.getLogger("aiohttp.access").setLevel(logging.WARNING)
24
- async with BaseClient() as client:
25
- try:
26
- token = await client.get_bearer_token()
27
- logger.info("Bearer token: %s", token)
28
- except Exception:
29
- logger.exception("Error getting bearer token")
30
-
31
-
32
- if __name__ == "__main__":
33
- cli()