Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "suz-sdk"
version = "1.2.0"
version = "1.3.0"
description = "Python SDK for СУЗ API 3.0 (СУЗ-Облако 4.0)"
readme = "README.md"
requires-python = ">=3.11"
Expand Down
2 changes: 1 addition & 1 deletion src/suz_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,4 @@
"RetryConfig",
]

__version__ = "1.2.0"
__version__ = "1.3.0"
26 changes: 25 additions & 1 deletion src/suz_sdk/api/async_integration.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""Async IntegrationApi — registration endpoint (§9.2)."""

import json
from collections.abc import Awaitable, Callable
from collections.abc import AsyncIterator, Awaitable, Callable
from typing import Any

from suz_sdk.api.integration import (
ConnectionInfo,
DeleteConnectionResponse,
IntegrationApi,
ListConnectionsResponse,
Expand Down Expand Up @@ -113,6 +114,29 @@ async def list_connections(
total=body["total"],
)

async def aiter_connections(self, *, page_size: int = 100) -> AsyncIterator[ConnectionInfo]:
"""Iterate over all registered integration connections across pages."""
if page_size <= 0:
raise ValueError("page_size must be greater than 0")

offset = 0
yielded = 0

while True:
resp = await self.list_connections(limit=page_size, offset=offset)
batch = resp.oms_connection_infos
if not batch:
return

for item in batch:
yield item
yielded += len(batch)

if yielded >= resp.total or len(batch) < page_size:
return

offset += page_size

async def delete_connection(self, oms_connection: str) -> DeleteConnectionResponse:
"""Delete a registered integration connection.

Expand Down
35 changes: 34 additions & 1 deletion src/suz_sdk/api/async_orders.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Async OrdersApi — KM emission orders (§4.4)."""

import json
from collections.abc import Awaitable, Callable
from collections.abc import AsyncIterator, Awaitable, Callable
from typing import Any, cast

from suz_sdk.api.orders import (
Expand Down Expand Up @@ -134,6 +134,11 @@ async def list_orders(self) -> ListOrdersResponse:
],
)

async def aiter_orders(self, *, page_size: int = 100) -> AsyncIterator[OrderSummaryInfo]:
"""Iterate over all orders using paginated search requests."""
async for item in self.aiter_search_orders(filter=None, page_size=page_size):
yield item

async def get_codes(
self,
order_id: str,
Expand Down Expand Up @@ -290,6 +295,34 @@ async def search_orders(
],
)

async def aiter_search_orders(
self,
filter: OrderFilter | None = None,
*,
page_size: int = 100,
) -> AsyncIterator[OrderSummaryInfo]:
"""Iterate over all search results across pages."""
if page_size <= 0:
raise ValueError("page_size must be greater than 0")

page = 0
yielded = 0

while True:
resp = await self.search_orders(filter=filter, limit=page_size, page=page)
batch = resp.results
if not batch:
return

for item in batch:
yield item
yielded += len(batch)

if yielded >= resp.total_count or len(batch) < page_size:
return

page += 1

async def close(
self,
order_id: str,
Expand Down
61 changes: 60 additions & 1 deletion src/suz_sdk/api/documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
sign_document() POST /api/v3/documents/sign
"""

from collections.abc import Awaitable, Callable
from collections.abc import AsyncIterator, Awaitable, Callable, Iterator
from dataclasses import dataclass
from typing import Any

Expand Down Expand Up @@ -166,6 +166,33 @@ def search_documents(
results=body.get("results", []),
)

def iter_documents(
self,
document_type: str,
*,
page_size: int = 100,
) -> Iterator[dict[str, Any]]:
"""Iterate over all matching documents across pages."""
if page_size <= 0:
raise ValueError("page_size must be greater than 0")

skip = 0
yielded = 0

while True:
resp = self.search_documents(document_type=document_type, limit=page_size, skip=skip)
batch = resp.results
if not batch:
return

yield from batch
yielded += len(batch)

if yielded >= resp.total_count or len(batch) < page_size:
return

skip += page_size

def get_document_content(self, doc_id: str) -> dict[str, Any]:
"""Retrieve the content of a document by its doc ID.

Expand Down Expand Up @@ -360,6 +387,38 @@ async def search_documents(
results=body.get("results", []),
)

async def aiter_documents(
self,
document_type: str,
*,
page_size: int = 100,
) -> AsyncIterator[dict[str, Any]]:
"""Iterate over all matching documents across pages."""
if page_size <= 0:
raise ValueError("page_size must be greater than 0")

skip = 0
yielded = 0

while True:
resp = await self.search_documents(
document_type=document_type,
limit=page_size,
skip=skip,
)
batch = resp.results
if not batch:
return

for item in batch:
yield item
yielded += len(batch)

if yielded >= resp.total_count or len(batch) < page_size:
return

skip += page_size

async def get_document_content(self, doc_id: str) -> dict[str, Any]:
"""Retrieve the content of a document by its doc ID.

Expand Down
30 changes: 26 additions & 4 deletions src/suz_sdk/api/integration.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Integration registration API client (§9.2).

Implements "Регистрация установки экземпляра интеграционного решения" —
the method for registering an integration installation with СУЗ and
obtaining an ``omsConnection`` UUID.
Implements "Регистрация установки экземпляра интеграционного
решения" — the method for registering an integration installation with СУЗ
and obtaining an ``omsConnection`` UUID.

API specification (§9.2.1, Table 360–364):
Method: POST
Expand Down Expand Up @@ -34,7 +34,7 @@
"""

import json
from collections.abc import Callable
from collections.abc import Callable, Iterator
from dataclasses import dataclass, field
from typing import Any

Expand Down Expand Up @@ -240,6 +240,28 @@ def list_connections(
total=body["total"],
)

def iter_connections(self, *, page_size: int = 100) -> Iterator[ConnectionInfo]:
"""Iterate over all registered integration connections across pages."""
if page_size <= 0:
raise ValueError("page_size must be greater than 0")

offset = 0
yielded = 0

while True:
resp = self.list_connections(limit=page_size, offset=offset)
batch = resp.oms_connection_infos
if not batch:
return

yield from batch
yielded += len(batch)

if yielded >= resp.total or len(batch) < page_size:
return

offset += page_size

def delete_connection(self, oms_connection: str) -> DeleteConnectionResponse:
"""Delete a registered integration connection.

Expand Down
50 changes: 49 additions & 1 deletion src/suz_sdk/api/orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"""

import json
from collections.abc import Callable
from collections.abc import Callable, Iterator
from dataclasses import dataclass, field
from typing import Any, cast

Expand Down Expand Up @@ -311,6 +311,19 @@ def list_orders(self) -> ListOrdersResponse:
],
)

def iter_orders(self, *, page_size: int = 100) -> Iterator[OrderSummaryInfo]:
"""Iterate over all orders using paginated search requests.

This helper provides memory-efficient iteration over order summaries.

Args:
page_size: Number of records requested per page.

Yields:
OrderSummaryInfo items across all available pages.
"""
yield from self.iter_search_orders(filter=None, page_size=page_size)

def get_codes(
self,
order_id: str,
Expand Down Expand Up @@ -504,6 +517,41 @@ def search_orders(
results=[self._parse_order_summary_info(item) for item in body.get("results", [])],
)

def iter_search_orders(
self,
filter: OrderFilter | None = None,
*,
page_size: int = 100,
) -> Iterator[OrderSummaryInfo]:
"""Iterate over all search results across pages.

Args:
filter: Optional OrderFilter criteria.
page_size: Number of records requested per page.

Yields:
OrderSummaryInfo items from all result pages.
"""
if page_size <= 0:
raise ValueError("page_size must be greater than 0")

page = 0
yielded = 0

while True:
resp = self.search_orders(filter=filter, limit=page_size, page=page)
batch = resp.results
if not batch:
return

yield from batch
yielded += len(batch)

if yielded >= resp.total_count or len(batch) < page_size:
return

page += 1

def close(
self,
order_id: str,
Expand Down
Loading