AssistagroAPI 0.1.0__tar.gz

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.
Files changed (28) hide show
  1. assistagroapi-0.1.0/PKG-INFO +79 -0
  2. assistagroapi-0.1.0/README.md +63 -0
  3. assistagroapi-0.1.0/pyproject.toml +32 -0
  4. assistagroapi-0.1.0/setup.cfg +4 -0
  5. assistagroapi-0.1.0/src/AssistagroAPI.egg-info/PKG-INFO +79 -0
  6. assistagroapi-0.1.0/src/AssistagroAPI.egg-info/SOURCES.txt +26 -0
  7. assistagroapi-0.1.0/src/AssistagroAPI.egg-info/dependency_links.txt +1 -0
  8. assistagroapi-0.1.0/src/AssistagroAPI.egg-info/requires.txt +4 -0
  9. assistagroapi-0.1.0/src/AssistagroAPI.egg-info/top_level.txt +1 -0
  10. assistagroapi-0.1.0/src/assistagro_client/__init__.py +17 -0
  11. assistagroapi-0.1.0/src/assistagro_client/api/__init__.py +1 -0
  12. assistagroapi-0.1.0/src/assistagro_client/api/v1/__init__.py +1 -0
  13. assistagroapi-0.1.0/src/assistagro_client/api/v1/accounts.py +53 -0
  14. assistagroapi-0.1.0/src/assistagro_client/api/v1/companies.py +39 -0
  15. assistagroapi-0.1.0/src/assistagro_client/api/v1/dictionaries.py +69 -0
  16. assistagroapi-0.1.0/src/assistagro_client/api/v1/fields.py +62 -0
  17. assistagroapi-0.1.0/src/assistagro_client/api/v1/meteostations.py +31 -0
  18. assistagroapi-0.1.0/src/assistagro_client/api/v1/reports.py +67 -0
  19. assistagroapi-0.1.0/src/assistagro_client/api/v1/structures.py +30 -0
  20. assistagroapi-0.1.0/src/assistagro_client/api/v1/tasks.py +93 -0
  21. assistagroapi-0.1.0/src/assistagro_client/api/v1/techmaps.py +83 -0
  22. assistagroapi-0.1.0/src/assistagro_client/auth.py +100 -0
  23. assistagroapi-0.1.0/src/assistagro_client/client.py +218 -0
  24. assistagroapi-0.1.0/src/assistagro_client/config.py +14 -0
  25. assistagroapi-0.1.0/src/assistagro_client/exceptions.py +27 -0
  26. assistagroapi-0.1.0/src/assistagro_client/models/__init__.py +1 -0
  27. assistagroapi-0.1.0/tests/test_auth.py +112 -0
  28. assistagroapi-0.1.0/tests/test_client.py +80 -0
@@ -0,0 +1,79 @@
1
+ Metadata-Version: 2.4
2
+ Name: AssistagroAPI
3
+ Version: 0.1.0
4
+ Summary: Async HTTP client for AssistAgro API
5
+ Author-email: Dmitriy Kazakov <dmitriyfile@yandex.ru>
6
+ License: MIT
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.13
10
+ Requires-Python: >=3.13
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: httpx>=0.28.1
13
+ Requires-Dist: pydantic>=2.12.5
14
+ Requires-Dist: pydantic-settings>=2.13.1
15
+ Requires-Dist: python-dateutil>=2.9.0.post0
16
+
17
+ # AssistAgro API Client
18
+
19
+ Асинхронный HTTP-клиент для AssistAgro API.
20
+
21
+ ## Установка
22
+
23
+ ```bash
24
+ pip install assistagro-client
25
+ ```
26
+
27
+ ## Использование
28
+
29
+ ```python
30
+ import asyncio
31
+ from assistagro_client import AssistAgroClient
32
+
33
+ async def main():
34
+ async with AssistAgroClient(base_url="https://dev-gateway-frontend.agroassist.ru") as client:
35
+ tokens = await client.auth.sign_in(
36
+ email="user@example.com",
37
+ password="password123"
38
+ )
39
+ print(f"Access token: {tokens.access_token[:20]}...")
40
+
41
+ fields = await client.fields.list_()
42
+ print(f"Найдено полей: {len(fields)}")
43
+
44
+ tasks = await client.tasks.list_(limit=10)
45
+ print(f"Найдено задач: {len(tasks)}")
46
+
47
+ if __name__ == "__main__":
48
+ asyncio.run(main())
49
+ ```
50
+
51
+ ## API эндпоинты
52
+
53
+ - **auth** - Аутентификация (sign_in, refresh_tokens, logout)
54
+ - **accounts** - Профили пользователей и аккаунты
55
+ - **companies** - Управление компаниями
56
+ - **fields** - Поля и контуры
57
+ - **tasks** - Управление задачами
58
+ - **techmaps** - Технологические карты
59
+ - **reports** - Отчёты
60
+ - **dictionaries** - Справочники (культуры, пестициды и т.д.)
61
+ - **meteostations** - Метеостанции
62
+ - **structures** - Структуры
63
+
64
+ ## Разработка
65
+
66
+ ```bash
67
+ # Установить зависимости
68
+ uv sync
69
+
70
+ # Запустить тесты
71
+ uv run pytest
72
+
73
+ # Запустить линтер
74
+ uv run ruff check .
75
+ ```
76
+
77
+ ## Лицензия
78
+
79
+ MIT
@@ -0,0 +1,63 @@
1
+ # AssistAgro API Client
2
+
3
+ Асинхронный HTTP-клиент для AssistAgro API.
4
+
5
+ ## Установка
6
+
7
+ ```bash
8
+ pip install assistagro-client
9
+ ```
10
+
11
+ ## Использование
12
+
13
+ ```python
14
+ import asyncio
15
+ from assistagro_client import AssistAgroClient
16
+
17
+ async def main():
18
+ async with AssistAgroClient(base_url="https://dev-gateway-frontend.agroassist.ru") as client:
19
+ tokens = await client.auth.sign_in(
20
+ email="user@example.com",
21
+ password="password123"
22
+ )
23
+ print(f"Access token: {tokens.access_token[:20]}...")
24
+
25
+ fields = await client.fields.list_()
26
+ print(f"Найдено полей: {len(fields)}")
27
+
28
+ tasks = await client.tasks.list_(limit=10)
29
+ print(f"Найдено задач: {len(tasks)}")
30
+
31
+ if __name__ == "__main__":
32
+ asyncio.run(main())
33
+ ```
34
+
35
+ ## API эндпоинты
36
+
37
+ - **auth** - Аутентификация (sign_in, refresh_tokens, logout)
38
+ - **accounts** - Профили пользователей и аккаунты
39
+ - **companies** - Управление компаниями
40
+ - **fields** - Поля и контуры
41
+ - **tasks** - Управление задачами
42
+ - **techmaps** - Технологические карты
43
+ - **reports** - Отчёты
44
+ - **dictionaries** - Справочники (культуры, пестициды и т.д.)
45
+ - **meteostations** - Метеостанции
46
+ - **structures** - Структуры
47
+
48
+ ## Разработка
49
+
50
+ ```bash
51
+ # Установить зависимости
52
+ uv sync
53
+
54
+ # Запустить тесты
55
+ uv run pytest
56
+
57
+ # Запустить линтер
58
+ uv run ruff check .
59
+ ```
60
+
61
+ ## Лицензия
62
+
63
+ MIT
@@ -0,0 +1,32 @@
1
+ [project]
2
+ name = "AssistagroAPI"
3
+ version = "0.1.0"
4
+ description = "Async HTTP client for AssistAgro API"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ license = {text = "MIT"}
8
+ authors = [
9
+ {name = "Dmitriy Kazakov", email = "dmitriyfile@yandex.ru"},
10
+ ]
11
+ classifiers = [
12
+ "License :: OSI Approved :: MIT License",
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3.13",
15
+ ]
16
+ dependencies = [
17
+ "httpx>=0.28.1",
18
+ "pydantic>=2.12.5",
19
+ "pydantic-settings>=2.13.1",
20
+ "python-dateutil>=2.9.0.post0",
21
+ ]
22
+
23
+ [dependency-groups]
24
+ dev = [
25
+ "pytest>=9.0.2",
26
+ "pytest-asyncio>=1.3.0",
27
+ "ruff>=0.9.0",
28
+ "mypy>=1.15.0",
29
+ ]
30
+
31
+ [tool.setuptools.packages.find]
32
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,79 @@
1
+ Metadata-Version: 2.4
2
+ Name: AssistagroAPI
3
+ Version: 0.1.0
4
+ Summary: Async HTTP client for AssistAgro API
5
+ Author-email: Dmitriy Kazakov <dmitriyfile@yandex.ru>
6
+ License: MIT
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.13
10
+ Requires-Python: >=3.13
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: httpx>=0.28.1
13
+ Requires-Dist: pydantic>=2.12.5
14
+ Requires-Dist: pydantic-settings>=2.13.1
15
+ Requires-Dist: python-dateutil>=2.9.0.post0
16
+
17
+ # AssistAgro API Client
18
+
19
+ Асинхронный HTTP-клиент для AssistAgro API.
20
+
21
+ ## Установка
22
+
23
+ ```bash
24
+ pip install assistagro-client
25
+ ```
26
+
27
+ ## Использование
28
+
29
+ ```python
30
+ import asyncio
31
+ from assistagro_client import AssistAgroClient
32
+
33
+ async def main():
34
+ async with AssistAgroClient(base_url="https://dev-gateway-frontend.agroassist.ru") as client:
35
+ tokens = await client.auth.sign_in(
36
+ email="user@example.com",
37
+ password="password123"
38
+ )
39
+ print(f"Access token: {tokens.access_token[:20]}...")
40
+
41
+ fields = await client.fields.list_()
42
+ print(f"Найдено полей: {len(fields)}")
43
+
44
+ tasks = await client.tasks.list_(limit=10)
45
+ print(f"Найдено задач: {len(tasks)}")
46
+
47
+ if __name__ == "__main__":
48
+ asyncio.run(main())
49
+ ```
50
+
51
+ ## API эндпоинты
52
+
53
+ - **auth** - Аутентификация (sign_in, refresh_tokens, logout)
54
+ - **accounts** - Профили пользователей и аккаунты
55
+ - **companies** - Управление компаниями
56
+ - **fields** - Поля и контуры
57
+ - **tasks** - Управление задачами
58
+ - **techmaps** - Технологические карты
59
+ - **reports** - Отчёты
60
+ - **dictionaries** - Справочники (культуры, пестициды и т.д.)
61
+ - **meteostations** - Метеостанции
62
+ - **structures** - Структуры
63
+
64
+ ## Разработка
65
+
66
+ ```bash
67
+ # Установить зависимости
68
+ uv sync
69
+
70
+ # Запустить тесты
71
+ uv run pytest
72
+
73
+ # Запустить линтер
74
+ uv run ruff check .
75
+ ```
76
+
77
+ ## Лицензия
78
+
79
+ MIT
@@ -0,0 +1,26 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/AssistagroAPI.egg-info/PKG-INFO
4
+ src/AssistagroAPI.egg-info/SOURCES.txt
5
+ src/AssistagroAPI.egg-info/dependency_links.txt
6
+ src/AssistagroAPI.egg-info/requires.txt
7
+ src/AssistagroAPI.egg-info/top_level.txt
8
+ src/assistagro_client/__init__.py
9
+ src/assistagro_client/auth.py
10
+ src/assistagro_client/client.py
11
+ src/assistagro_client/config.py
12
+ src/assistagro_client/exceptions.py
13
+ src/assistagro_client/api/__init__.py
14
+ src/assistagro_client/api/v1/__init__.py
15
+ src/assistagro_client/api/v1/accounts.py
16
+ src/assistagro_client/api/v1/companies.py
17
+ src/assistagro_client/api/v1/dictionaries.py
18
+ src/assistagro_client/api/v1/fields.py
19
+ src/assistagro_client/api/v1/meteostations.py
20
+ src/assistagro_client/api/v1/reports.py
21
+ src/assistagro_client/api/v1/structures.py
22
+ src/assistagro_client/api/v1/tasks.py
23
+ src/assistagro_client/api/v1/techmaps.py
24
+ src/assistagro_client/models/__init__.py
25
+ tests/test_auth.py
26
+ tests/test_client.py
@@ -0,0 +1,4 @@
1
+ httpx>=0.28.1
2
+ pydantic>=2.12.5
3
+ pydantic-settings>=2.13.1
4
+ python-dateutil>=2.9.0.post0
@@ -0,0 +1 @@
1
+ assistagro_client
@@ -0,0 +1,17 @@
1
+ """AssistAgro API Client."""
2
+
3
+ from .client import AssistAgroClient
4
+ from .auth import Auth, AuthTokens, SignInRequest, OTPResponse
5
+ from .exceptions import AssistAgroError, AuthenticationError, APIError, TimeoutError
6
+
7
+ __all__ = [
8
+ "AssistAgroClient",
9
+ "Auth",
10
+ "AuthTokens",
11
+ "SignInRequest",
12
+ "OTPResponse",
13
+ "AssistAgroError",
14
+ "AuthenticationError",
15
+ "APIError",
16
+ "TimeoutError",
17
+ ]
@@ -0,0 +1 @@
1
+ """API v1 endpoints."""
@@ -0,0 +1 @@
1
+ """API v1 endpoints."""
@@ -0,0 +1,53 @@
1
+ """Accounts API endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+ from uuid import UUID
7
+
8
+ from pydantic import BaseModel
9
+
10
+ if TYPE_CHECKING:
11
+ from .client import AssistAgroClient
12
+
13
+
14
+ class Company(BaseModel):
15
+ guid: UUID
16
+ name: str
17
+ parent_guid: UUID | None = None
18
+
19
+
20
+ class UserProfile(BaseModel):
21
+ company: Company
22
+ user_guid: UUID
23
+ permissions: list[str]
24
+ is_current: bool
25
+ is_confirmed: bool
26
+
27
+
28
+ class AccountsAPI:
29
+ """Accounts API endpoints."""
30
+
31
+ def __init__(self, client: AssistAgroClient):
32
+ self._client = client
33
+
34
+ async def get_users(self, account_guid: UUID | None = None) -> list[UserProfile]:
35
+ """Get user profiles."""
36
+ params = {}
37
+ if account_guid:
38
+ params["account_guid"] = str(account_guid)
39
+ response = await self._client.get("/account/users", params=params)
40
+ response.raise_for_status()
41
+ return [UserProfile(**item) for item in response.json()]
42
+
43
+ async def get_current_user(self) -> dict:
44
+ """Get current user info."""
45
+ response = await self._client.get("/account/users/current")
46
+ response.raise_for_status()
47
+ return response.json()
48
+
49
+ async def get_user(self, user_guid: UUID) -> dict:
50
+ """Get user by GUID."""
51
+ response = await self._client.get(f"/account/users/{user_guid}")
52
+ response.raise_for_status()
53
+ return response.json()
@@ -0,0 +1,39 @@
1
+ """Companies API endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import date
6
+ from typing import TYPE_CHECKING
7
+ from uuid import UUID
8
+
9
+ from pydantic import BaseModel
10
+
11
+ if TYPE_CHECKING:
12
+ from .client import AssistAgroClient
13
+
14
+
15
+ class License(BaseModel):
16
+ begin_date: date
17
+ end_date: date
18
+ modules: list[int]
19
+
20
+
21
+ class Company(BaseModel):
22
+ guid: UUID
23
+ name: str
24
+ user_count: int
25
+ active_flag: bool
26
+ license: License
27
+
28
+
29
+ class CompaniesAPI:
30
+ """Companies API endpoints."""
31
+
32
+ def __init__(self, client: AssistAgroClient):
33
+ self._client = client
34
+
35
+ async def list_(self) -> list[Company]:
36
+ """Get all companies."""
37
+ response = await self._client.get("/companies")
38
+ response.raise_for_status()
39
+ return [Company(**item) for item in response.json()]
@@ -0,0 +1,69 @@
1
+ """Dictionaries API endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ if TYPE_CHECKING:
8
+ from .client import AssistAgroClient
9
+
10
+
11
+ class DictionariesAPI:
12
+ """Dictionaries API endpoints."""
13
+
14
+ def __init__(self, client: AssistAgroClient):
15
+ self._client = client
16
+
17
+ async def get_crops(self) -> list[dict[str, Any]]:
18
+ """Get crops dictionary."""
19
+ response = await self._client.get("/dictionaries/crops")
20
+ response.raise_for_status()
21
+ return response.json()
22
+
23
+ async def get_crop_products(self) -> list[dict[str, Any]]:
24
+ """Get crop products dictionary."""
25
+ response = await self._client.get("/dictionaries/crop_products")
26
+ response.raise_for_status()
27
+ return response.json()
28
+
29
+ async def get_techoperations(self) -> list[dict[str, Any]]:
30
+ """Get techoperations dictionary."""
31
+ response = await self._client.get("/dictionaries/techoperations")
32
+ response.raise_for_status()
33
+ return response.json()
34
+
35
+ async def get_machine_models(self) -> list[dict[str, Any]]:
36
+ """Get machine models dictionary."""
37
+ response = await self._client.get("/dictionaries/machine_models")
38
+ response.raise_for_status()
39
+ return response.json()
40
+
41
+ async def get_pesticides(self) -> list[dict[str, Any]]:
42
+ """Get pesticides dictionary."""
43
+ response = await self._client.get("/dictionaries/pesticides")
44
+ response.raise_for_status()
45
+ return response.json()
46
+
47
+ async def get_fertilizers(self) -> list[dict[str, Any]]:
48
+ """Get fertilizers dictionary."""
49
+ response = await self._client.get("/dictionaries/fertilizers")
50
+ response.raise_for_status()
51
+ return response.json()
52
+
53
+ async def get_varieties(self) -> list[dict[str, Any]]:
54
+ """Get varieties dictionary."""
55
+ response = await self._client.get("/dictionaries/varieties")
56
+ response.raise_for_status()
57
+ return response.json()
58
+
59
+ async def get_meteostations(self) -> list[dict[str, Any]]:
60
+ """Get meteostations."""
61
+ response = await self._client.get("/meteostations")
62
+ response.raise_for_status()
63
+ return response.json()
64
+
65
+ async def get_notifications_channels(self) -> list[dict[str, Any]]:
66
+ """Get notification channels."""
67
+ response = await self._client.get("/notifications/channels")
68
+ response.raise_for_status()
69
+ return response.json()
@@ -0,0 +1,62 @@
1
+ """Fields API endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from typing import TYPE_CHECKING
7
+ from uuid import UUID
8
+
9
+ from pydantic import BaseModel
10
+
11
+ if TYPE_CHECKING:
12
+ from .client import AssistAgroClient
13
+
14
+
15
+ class FieldContour(BaseModel):
16
+ contour_guid: UUID
17
+ field_guid: UUID
18
+ superfield_guid: UUID
19
+ contour: str
20
+ area_fact_hectare: float
21
+ area_etalon_hectare: float
22
+ start_datetime: datetime
23
+ author_guid: UUID
24
+ editor_guid: UUID
25
+ created_at: datetime
26
+ updated_at: datetime
27
+
28
+
29
+ class FieldListItem(BaseModel):
30
+ guid: UUID
31
+ name: str
32
+ company_guid: UUID
33
+ area_fact_hectare: float
34
+ area_etalon_hectare: float
35
+
36
+
37
+ class FieldsAPI:
38
+ """Fields API endpoints."""
39
+
40
+ def __init__(self, client: AssistAgroClient):
41
+ self._client = client
42
+
43
+ async def get_contours(self, field_guid: UUID) -> list[FieldContour]:
44
+ """Get field contours."""
45
+ response = await self._client.get(
46
+ "/fields/contours",
47
+ params={"field_guid": str(field_guid)},
48
+ )
49
+ response.raise_for_status()
50
+ return [FieldContour(**item) for item in response.json()]
51
+
52
+ async def list_(self) -> list[FieldListItem]:
53
+ """List all fields."""
54
+ response = await self._client.get("/fields/list")
55
+ response.raise_for_status()
56
+ return [FieldListItem(**item) for item in response.json()]
57
+
58
+ async def list_meta(self) -> dict:
59
+ """List fields with metadata."""
60
+ response = await self._client.get("/fields/list_meta")
61
+ response.raise_for_status()
62
+ return response.json()
@@ -0,0 +1,31 @@
1
+ """Meteostations API endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+ from uuid import UUID
7
+
8
+ from pydantic import BaseModel
9
+
10
+ if TYPE_CHECKING:
11
+ from .client import AssistAgroClient
12
+
13
+
14
+ class Meteostation(BaseModel):
15
+ guid: UUID
16
+ name: str
17
+ latitude: float
18
+ longitude: float
19
+
20
+
21
+ class MeteostationsAPI:
22
+ """Meteostations API endpoints."""
23
+
24
+ def __init__(self, client: AssistAgroClient):
25
+ self._client = client
26
+
27
+ async def list_(self) -> list[Meteostation]:
28
+ """List all meteostations."""
29
+ response = await self._client.get("/meteostations")
30
+ response.raise_for_status()
31
+ return [Meteostation(**item) for item in response.json()]
@@ -0,0 +1,67 @@
1
+ """Reports API endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from typing import TYPE_CHECKING, Any
7
+ from uuid import UUID
8
+
9
+ from pydantic import BaseModel
10
+
11
+ if TYPE_CHECKING:
12
+ from .client import AssistAgroClient
13
+
14
+
15
+ class Report(BaseModel):
16
+ guid: UUID
17
+ task_guid: UUID | None = None
18
+ season_id: int
19
+ entity_guid: UUID | None = None
20
+ entity_type: str | None = None
21
+ status_id: int
22
+ name: str
23
+ created_at: datetime
24
+ updated_at: datetime
25
+
26
+
27
+ class ReportCreateRequest(BaseModel):
28
+ task_guid: UUID | None = None
29
+ season_id: int
30
+ entity_guid: UUID | None = None
31
+ entity_type: str | None = None
32
+ entity_data: dict[str, Any]
33
+ datetimes: dict
34
+ history: list[dict]
35
+
36
+
37
+ class ReportsAPI:
38
+ """Reports API endpoints."""
39
+
40
+ def __init__(self, client: AssistAgroClient):
41
+ self._client = client
42
+
43
+ async def create(
44
+ self,
45
+ season_id: int,
46
+ entity_data: dict[str, Any],
47
+ datetimes: dict,
48
+ history: list[dict],
49
+ task_guid: UUID | None = None,
50
+ entity_guid: UUID | None = None,
51
+ entity_type: str | None = None,
52
+ ) -> Report:
53
+ """Create a report."""
54
+ response = await self._client.post(
55
+ "/reports",
56
+ json={
57
+ "task_guid": str(task_guid) if task_guid else None,
58
+ "season_id": season_id,
59
+ "entity_guid": str(entity_guid) if entity_guid else None,
60
+ "entity_type": entity_type,
61
+ "entity_data": entity_data,
62
+ "datetimes": datetimes,
63
+ "history": history,
64
+ },
65
+ )
66
+ response.raise_for_status()
67
+ return Report(**response.json())
@@ -0,0 +1,30 @@
1
+ """Structures API endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+ from uuid import UUID
7
+
8
+ from pydantic import BaseModel
9
+
10
+ if TYPE_CHECKING:
11
+ from .client import AssistAgroClient
12
+
13
+
14
+ class Structure(BaseModel):
15
+ guid: UUID
16
+ name: str
17
+ company_guid: UUID
18
+
19
+
20
+ class StructuresAPI:
21
+ """Structures API endpoints."""
22
+
23
+ def __init__(self, client: AssistAgroClient):
24
+ self._client = client
25
+
26
+ async def list_(self) -> list[Structure]:
27
+ """List structures."""
28
+ response = await self._client.get("/structures")
29
+ response.raise_for_status()
30
+ return [Structure(**item) for item in response.json()]