kscale 0.3.0__py3-none-any.whl → 0.3.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  """Defines the common interface for the K-Scale Python API."""
2
2
 
3
- __version__ = "0.3.0"
3
+ __version__ = "0.3.2"
4
4
 
5
5
  from pathlib import Path
6
6
 
@@ -16,6 +16,11 @@ from kscale.web.gen.api import RobotURDFMetadataInput
16
16
  logger = logging.getLogger(__name__)
17
17
 
18
18
 
19
+ class RobotURDFMetadataInputStrict(RobotURDFMetadataInput):
20
+ class Config:
21
+ extra = "forbid"
22
+
23
+
19
24
  @click.group()
20
25
  def cli() -> None:
21
26
  """Get information about robot classes."""
@@ -83,7 +88,7 @@ async def update_metadata(name: str, json_path: str) -> None:
83
88
  """Updates the metadata of a robot class."""
84
89
  with open(json_path, "r", encoding="utf-8") as f:
85
90
  raw_metadata = json.load(f)
86
- metadata = RobotURDFMetadataInput.model_validate(raw_metadata)
91
+ metadata = RobotURDFMetadataInputStrict.model_validate(raw_metadata)
87
92
  async with RobotClassClient() as client:
88
93
  robot_class = await client.update_robot_class(name, new_metadata=metadata)
89
94
  click.echo("Robot class metadata updated:")
@@ -91,6 +96,25 @@ async def update_metadata(name: str, json_path: str) -> None:
91
96
  click.echo(f" Name: {click.style(robot_class.class_name, fg='green')}")
92
97
 
93
98
 
99
+ @cli.command()
100
+ @click.argument("name")
101
+ @click.option("--json-path", type=click.Path(exists=False))
102
+ @coro
103
+ async def get_metadata(name: str, json_path: str | None = None) -> None:
104
+ """Gets the metadata of a robot class."""
105
+ async with RobotClassClient() as client:
106
+ robot_class = await client.get_robot_class(name)
107
+ metadata = robot_class.metadata
108
+ if metadata is None:
109
+ click.echo(click.style("No metadata found", fg="red"))
110
+ return
111
+ if json_path is None:
112
+ click.echo(metadata.model_dump_json(indent=2))
113
+ else:
114
+ with open(json_path, "w", encoding="utf-8") as f:
115
+ json.dump(metadata.model_dump(), f)
116
+
117
+
94
118
  @cli.command()
95
119
  @click.argument("name")
96
120
  @coro
@@ -35,6 +35,14 @@ class RobotClassClient(BaseClient):
35
35
  )
36
36
  return [RobotClass.model_validate(item) for item in data]
37
37
 
38
+ async def get_robot_class(self, class_name: str) -> RobotClass:
39
+ data = await self._request(
40
+ "GET",
41
+ f"/robots/name/{class_name}",
42
+ auth=True,
43
+ )
44
+ return RobotClass.model_validate(data)
45
+
38
46
  async def create_robot_class(self, class_name: str, description: str | None = None) -> RobotClass:
39
47
  data = {}
40
48
  if description is not None:
kscale/web/gen/api.py CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # generated by datamodel-codegen:
4
4
  # filename: openapi.json
5
- # timestamp: 2025-01-21T07:10:22+00:00
5
+ # timestamp: 2025-01-22T04:20:37+00:00
6
6
 
7
7
  from __future__ import annotations
8
8
 
@@ -11,6 +11,10 @@ from typing import Dict, List, Optional, Union
11
11
  from pydantic import BaseModel, Field
12
12
 
13
13
 
14
+ class APIKeyRequest(BaseModel):
15
+ num_hours: Optional[int] = Field(24, title="Num Hours")
16
+
17
+
14
18
  class APIKeyResponse(BaseModel):
15
19
  api_key: str = Field(..., title="Api Key")
16
20
 
@@ -29,8 +33,7 @@ class JointMetadataInput(BaseModel):
29
33
  kp: Optional[Union[float, str]] = Field(None, title="Kp")
30
34
  kd: Optional[Union[float, str]] = Field(None, title="Kd")
31
35
  offset: Optional[Union[float, str]] = Field(None, title="Offset")
32
- lower_limit: Optional[Union[float, str]] = Field(None, title="Lower Limit")
33
- upper_limit: Optional[Union[float, str]] = Field(None, title="Upper Limit")
36
+ flipped: Optional[bool] = Field(None, title="Flipped")
34
37
 
35
38
 
36
39
  class JointMetadataOutput(BaseModel):
@@ -38,8 +41,7 @@ class JointMetadataOutput(BaseModel):
38
41
  kp: Optional[str] = Field(None, title="Kp")
39
42
  kd: Optional[str] = Field(None, title="Kd")
40
43
  offset: Optional[str] = Field(None, title="Offset")
41
- lower_limit: Optional[str] = Field(None, title="Lower Limit")
42
- upper_limit: Optional[str] = Field(None, title="Upper Limit")
44
+ flipped: Optional[bool] = Field(None, title="Flipped")
43
45
 
44
46
 
45
47
  class OICDInfo(BaseModel):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: kscale
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: The kscale project
5
5
  Home-page: https://github.com/kscalelabs/kscale
6
6
  Author: Benjamin Bolte
@@ -1,4 +1,4 @@
1
- kscale/__init__.py,sha256=ApqkdyLhaMQ1u0TopxCm4T5hZTDoweO2b2gUg0djui8,200
1
+ kscale/__init__.py,sha256=kd5GppaQJl10D1iD73gCLOi5akkQ1_cWXXdlx4NMGD8,200
2
2
  kscale/cli.py,sha256=PMHLKR5UwdbbReVmqHXpJ-K9-mGHv_0I7KQkwxmFcUA,881
3
3
  kscale/conf.py,sha256=dm35XSnzJp93St-ixVtYN4Nvqvb5upPGBrWkSI6Yb-4,1743
4
4
  kscale/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -15,20 +15,20 @@ 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=Za5WZmyySgpY-hhR1BqyF1k1wr9bGbXLAE6uFlTOZkk,16706
18
+ kscale/web/cli/robot_class.py,sha256=Gvfg_TsSC0MRUhBIx0yDVXOf8P4kyDbR_glFv5svuDA,17481
19
19
  kscale/web/cli/token.py,sha256=1rFC8MYKtqbNsQa2KIqwW1tqpaMtFaxuNsallwejXTU,787
20
20
  kscale/web/cli/user.py,sha256=aaJJCL1P5lfhK6ZC9OwOHXKA-I3MWqVZ_k7TYnx33CY,1303
21
21
  kscale/web/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  kscale/web/clients/base.py,sha256=A70BF9ZnHEBds0RKrowbeUNsX_WwsgV349csUlM4iMc,15174
23
23
  kscale/web/clients/client.py,sha256=rzW2s8T7bKVuybOSQ65-ghl02rcXBoOxnx_nUDwgEPw,362
24
24
  kscale/web/clients/robot.py,sha256=PI8HHkU-4Re9I5rLpp6dGbekRE-rBNVfXZxR_mO2MqE,1485
25
- kscale/web/clients/robot_class.py,sha256=_oAEUglLmNXCspnACC40XLclLL3Z2rF88o1p0tk-JUM,6588
25
+ kscale/web/clients/robot_class.py,sha256=G8Nk6V7LGJE9Wpg9tyyCkIfz1fRTsxXQRgHtleiUVqo,6834
26
26
  kscale/web/clients/user.py,sha256=jsa1_s6qXRM-AGBbHlPhd1NierUtynjY9tVAPNr6_Os,568
27
27
  kscale/web/gen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- kscale/web/gen/api.py,sha256=7Uyzy4V2Ovh70M5lLSaJhwKkBr5SYyTfrNjr180JQhY,4304
29
- kscale-0.3.0.dist-info/LICENSE,sha256=HCN2bImAzUOXldAZZI7JZ9PYq6OwMlDAP_PpX1HnuN0,1071
30
- kscale-0.3.0.dist-info/METADATA,sha256=H3CQZAwUTZBfScRQVKAArLadR62aw-rWhFMUBkTby84,2340
31
- kscale-0.3.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
32
- kscale-0.3.0.dist-info/entry_points.txt,sha256=N_0pCpPnwGDYVzOeuaSOrbJkS5L3lS9d8CxpJF1f8UI,62
33
- kscale-0.3.0.dist-info/top_level.txt,sha256=C2ynjYwopg6YjgttnI2dJjasyq3EKNmYp-IfQg9Xms4,7
34
- kscale-0.3.0.dist-info/RECORD,,
28
+ kscale/web/gen/api.py,sha256=PMxBujxwL65yTFL8YIfZXWvcTRsENG0xkmG7kcmfRlw,4224
29
+ kscale-0.3.2.dist-info/LICENSE,sha256=HCN2bImAzUOXldAZZI7JZ9PYq6OwMlDAP_PpX1HnuN0,1071
30
+ kscale-0.3.2.dist-info/METADATA,sha256=PxUN_QjnqP3Md5VOo6u9apGvEm8pytJmR2sDYfKZ2Qs,2340
31
+ kscale-0.3.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
32
+ kscale-0.3.2.dist-info/entry_points.txt,sha256=N_0pCpPnwGDYVzOeuaSOrbJkS5L3lS9d8CxpJF1f8UI,62
33
+ kscale-0.3.2.dist-info/top_level.txt,sha256=C2ynjYwopg6YjgttnI2dJjasyq3EKNmYp-IfQg9Xms4,7
34
+ kscale-0.3.2.dist-info/RECORD,,
File without changes