Skip to content

Commit 77b4453

Browse files
author
GitHub Actions
committed
Auto commit from main repo: manual-sync
1 parent 38d5d5a commit 77b4453

10 files changed

Lines changed: 535 additions & 4 deletions

File tree

armis_sdk/clients/data_export_client.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,10 @@ async def main():
100100
raise ArmisError("Only parquet files supported")
101101

102102
for url in data_export.urls:
103-
df: pandas.DataFrame = await asyncio.to_thread(pandas.read_parquet, url)
104-
for _, row in df.iterrows():
103+
data_frame: pandas.DataFrame = await asyncio.to_thread(
104+
pandas.read_parquet, url
105+
)
106+
for _, row in data_frame.iterrows():
105107
yield entity.series_to_model(row)
106108

107109
async def get(self, entity: Type[BaseExportedEntity]) -> DataExport:
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
from typing import AsyncIterator
2+
3+
import universalasync
4+
5+
from armis_sdk.core import response_utils
6+
from armis_sdk.core.armis_error import ArmisError
7+
from armis_sdk.core.base_entity_client import BaseEntityClient
8+
from armis_sdk.entities.device_custom_property import DeviceCustomProperty
9+
10+
11+
@universalasync.wrap
12+
class DeviceCustomPropertiesClient(BaseEntityClient):
13+
"""
14+
A client for interacting with device custom properties.
15+
16+
The primary entity for this client is
17+
[DeviceCustomProperty][armis_sdk.entities.device_custom_property.DeviceCustomProperty].
18+
"""
19+
20+
async def create(self, property_: DeviceCustomProperty) -> DeviceCustomProperty:
21+
# pylint: disable=line-too-long
22+
"""Create a `DeviceCustomProperty`.
23+
24+
Args:
25+
property_: The `DeviceCustomProperty` to create.
26+
27+
Returns:
28+
The same property as the input with the addition of id.
29+
30+
Example:
31+
Example:
32+
```python linenums="1" hl_lines="10"
33+
import asyncio
34+
35+
from armis_sdk.clients.device_custom_properties_client import DeviceCustomPropertiesClient
36+
from armis_sdk.entities.device_custom_property import DeviceCustomProperty
37+
38+
39+
async def main():
40+
client = DeviceCustomPropertiesClient()
41+
property_ = DeviceCustomProperty(name="MyConfig", type="string")
42+
print(await client.create(property_))
43+
44+
asyncio.run(main())
45+
```
46+
Will output:
47+
```python linenums="1"
48+
DeviceCustomPropertiesClient(id=1, name="MyConfig", type="string")
49+
```
50+
"""
51+
if property_.id is not None:
52+
raise ArmisError(
53+
"Can't create a property that already has an id. "
54+
"Did you mean to call `.update(property_)`?",
55+
)
56+
57+
if not property_.name:
58+
raise ArmisError("Can't create a property without a name.")
59+
60+
if not property_.type:
61+
raise ArmisError("Can't create a property without a type.")
62+
63+
payload = property_.model_dump(exclude_none=True)
64+
65+
async with self._armis_client.client() as client:
66+
response = await client.post(
67+
"/v3/settings/device-custom-properties", json=payload
68+
)
69+
data = response_utils.get_data_dict(response)
70+
return DeviceCustomProperty.model_validate(data)
71+
72+
async def delete(self, property_: DeviceCustomProperty):
73+
# pylint: disable=line-too-long
74+
"""Delete a `DeviceCustomProperty`.
75+
76+
Args:
77+
property_: The `DeviceCustomProperty` to delete.
78+
79+
Example:
80+
Example:
81+
```python linenums="1" hl_lines="10"
82+
import asyncio
83+
84+
from armis_sdk.clients.device_custom_properties_client import DeviceCustomPropertiesClient
85+
from armis_sdk.entities.device_custom_property import DeviceCustomProperty
86+
87+
88+
async def main():
89+
client = DeviceCustomPropertiesClient()
90+
property_ = DeviceCustomProperty(id=1, name="MyConfig", type="string")
91+
await client.delete(property_)
92+
93+
asyncio.run(main())
94+
```
95+
"""
96+
if property_.id is None:
97+
raise ArmisError("Can't delete a property without an id.")
98+
99+
async with self._armis_client.client() as client:
100+
response = await client.delete(
101+
f"/v3/settings/device-custom-properties/{property_.id}"
102+
)
103+
response_utils.raise_for_status(response)
104+
105+
async def get(self, property_id: int) -> DeviceCustomProperty:
106+
# pylint: disable=line-too-long
107+
"""Get a `DeviceCustomProperty` by its ID.
108+
109+
Args:
110+
property_id: The ID of the `DeviceCustomProperty` to get.
111+
112+
Returns:
113+
A `DeviceCustomProperty` object.
114+
115+
Example:
116+
Example:
117+
```python linenums="1" hl_lines="8"
118+
import asyncio
119+
120+
from armis_sdk.clients.device_custom_properties_client import DeviceCustomPropertiesClient
121+
122+
123+
async def main():
124+
client = DeviceCustomPropertiesClient()
125+
print(await client.get(1))
126+
127+
asyncio.run(main())
128+
```
129+
Will output:
130+
```python linenums="1"
131+
DeviceCustomPropertiesClient(id=1, name="MyConfig", type="string")
132+
```
133+
"""
134+
async with self._armis_client.client() as client:
135+
response = await client.get(
136+
f"/v3/settings/device-custom-properties/{property_id}"
137+
)
138+
data = response_utils.get_data_dict(response)
139+
return DeviceCustomProperty.model_validate(data)
140+
141+
async def list(self) -> AsyncIterator[DeviceCustomProperty]:
142+
# pylint: disable=line-too-long
143+
"""List all the tenant's `DeviceCustomProperty`s.
144+
This method takes care of pagination, so you don't have to deal with it.
145+
146+
Returns:
147+
An (async) iterator of `DeviceCustomProperty` object.
148+
149+
Example:
150+
```python linenums="1" hl_lines="8"
151+
import asyncio
152+
153+
from armis_sdk.clients.device_custom_properties_client import DeviceCustomPropertiesClient
154+
155+
156+
async def main():
157+
client = DeviceCustomPropertiesClient()
158+
async for property_ in client.list()
159+
print(property_)
160+
161+
asyncio.run(main())
162+
```
163+
Will output:
164+
```python linenums="1"
165+
DeviceCustomPropertiesClient(id=1, name="MyConfig", type="string")
166+
DeviceCustomPropertiesClient(id=1, name="MyOtherConfig", type="integer")
167+
```
168+
"""
169+
170+
async with self._armis_client.client() as client:
171+
# endpoint doesn't support paging
172+
response = await client.get("/v3/settings/device-custom-properties")
173+
data = response_utils.get_data_dict(response)
174+
for item in data["items"]:
175+
yield DeviceCustomProperty.model_validate(item)
176+
177+
async def update(self, property_: DeviceCustomProperty) -> DeviceCustomProperty:
178+
# pylint: disable=line-too-long
179+
"""Update a `DeviceCustomProperty`.
180+
Only `description` and `allowed_values` are updatable.
181+
182+
Args:
183+
property_: The `DeviceCustomProperty` to update.
184+
185+
Raises:
186+
ResponseError: If an error occurs while communicating with the API.
187+
188+
Example:
189+
```python linenums="1" hl_lines="15"
190+
import asyncio
191+
192+
from armis_sdk.clients.device_custom_properties_client import DeviceCustomPropertiesClient
193+
from armis_sdk.entities.device_custom_property import DeviceCustomProperty
194+
195+
196+
async def main():
197+
client = DeviceCustomPropertiesClient()
198+
property_ = DeviceCustomProperty(
199+
id=1,
200+
name="MyConfig",
201+
type="string",
202+
description="New description",
203+
)
204+
await client.update(property_)
205+
206+
asyncio.run(main())
207+
```
208+
"""
209+
if property_.id is None:
210+
raise ArmisError(
211+
"Can't update a property without an id. "
212+
"Did you mean to call `.create(property_)`?",
213+
)
214+
215+
data = property_.model_dump(
216+
exclude={"id", "name", "creation_time", "created_by", "type"},
217+
exclude_none=True,
218+
)
219+
220+
if not data:
221+
return property_
222+
223+
async with self._armis_client.client() as client:
224+
response = await client.patch(
225+
f"/v3/settings/device-custom-properties/{property_.id}",
226+
json=data,
227+
)
228+
response_utils.raise_for_status(response)
229+
230+
return property_

armis_sdk/clients/sites_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ async def create(self, site: Site) -> Site:
2222
"""Create a `Site`.
2323
2424
Args:
25-
site: The site to delete.
25+
site: The site to create.
2626
2727
Returns:
2828
The same site as the input with the addition of id.

armis_sdk/core/armis_sdk.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from typing import Optional
22

33
from armis_sdk.clients.data_export_client import DataExportClient
4+
from armis_sdk.clients.device_custom_properties_client import (
5+
DeviceCustomPropertiesClient,
6+
)
47
from armis_sdk.clients.sites_client import SitesClient
58
from armis_sdk.core.armis_client import ArmisClient
69
from armis_sdk.core.client_credentials import ClientCredentials
@@ -15,6 +18,7 @@ class ArmisSdk: # pylint: disable=too-few-public-methods
1518
Attributes:
1619
client (ArmisClient): An instance of [ArmisClient][armis_sdk.core.armis_client.ArmisClient]
1720
data_export (DataExportClient): An instance of [DataExportClient][armis_sdk.clients.data_export_client.DataExportClient]
21+
device_custom_properties (DeviceCustomPropertiesClient): An instance of [DeviceCustomPropertiesClient][armis_sdk.clients.device_custom_properties_client.DeviceCustomPropertiesClient]
1822
sites (SitesClient): An instance of [SitesClient][armis_sdk.clients.sites_client.SitesClient]
1923
2024
Example:
@@ -36,4 +40,7 @@ async def main():
3640
def __init__(self, credentials: Optional[ClientCredentials] = None):
3741
self.client: ArmisClient = ArmisClient(credentials=credentials)
3842
self.data_export: DataExportClient = DataExportClient(self.client)
43+
self.device_custom_properties: DeviceCustomPropertiesClient = (
44+
DeviceCustomPropertiesClient(self.client)
45+
)
3946
self.sites: SitesClient = SitesClient(self.client)

armis_sdk/entities/data_export/data_export.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from typing import Optional
44

55
from pydantic import BaseModel
6+
from pydantic import Field
67

78

89
class DataExport(BaseModel):
@@ -23,5 +24,5 @@ class DataExport(BaseModel):
2324
urls: list[str]
2425
"""URLs to the files that contain the exported data."""
2526

26-
urls_creation_time: Optional[datetime.datetime]
27+
urls_creation_time: Optional[datetime.datetime] = Field(strict=False)
2728
"""The creation time of the URLs."""
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import datetime
2+
from typing import Literal
3+
from typing import Optional
4+
5+
from pydantic import Field
6+
7+
from armis_sdk.core.base_entity import BaseEntity
8+
9+
10+
class DeviceCustomProperty(BaseEntity):
11+
id: Optional[int] = None
12+
"""The id of the property."""
13+
14+
name: str = Field(max_length=40, pattern=r"^[\w_]*$")
15+
"""
16+
The name of the property.
17+
18+
Example: `Size`
19+
"""
20+
21+
description: Optional[str] = Field(max_length=250, default=None)
22+
"""
23+
The description of the property.
24+
25+
Example: `The size of the device`
26+
"""
27+
28+
type: Literal[
29+
"boolean",
30+
"enum",
31+
"externalLink",
32+
"integer",
33+
"string",
34+
"timestamp",
35+
]
36+
"""
37+
The type of the property.
38+
39+
Example: `enum`
40+
"""
41+
42+
allowed_values: Optional[list[str]] = None
43+
"""
44+
The allowed values of the property when the 'type' is 'enum'.
45+
46+
Example: `["s", "m", "l"]`
47+
"""
48+
49+
created_by: Optional[str] = Field(max_length=50, default=None)
50+
"""Who / what created the property."""
51+
52+
creation_time: Optional[datetime.datetime] = Field(strict=False, default=None)
53+
"""The creation time of the property."""
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
::: armis_sdk.clients.device_custom_properties_client.DeviceCustomPropertiesClient
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
::: armis_sdk.entities.device_custom_property.DeviceCustomProperty

mkdocs.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ nav:
1111
- DataExport: entities/data_export/DataExport.md
1212
- RiskFactor: entities/data_export/RiskFactor.md
1313
- Vulnerability: entities/data_export/Vulnerability.md
14+
- DeviceCustomProperty: entities/DeviceCustomProperty.md
1415
- Site: entities/Site.md
1516
- Clients:
1617
- DataExportClient: clients/DataExportClient.md
18+
- DeviceCustomPropertiesClient: clients/DeviceCustomPropertiesClient.md
1719
- SitesClient: clients/SitesClient.md
1820
- Core:
1921
- ArmisClient: core/ArmisClient.md

0 commit comments

Comments
 (0)