Skip to content

Commit 664dc22

Browse files
andersfyllingclaude
andcommitted
feat(records): add list (filter) endpoint with read data classes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9ecf95c commit 664dc22

50 files changed

Lines changed: 601 additions & 1050 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cognite/client/_api/data_modeling/records.py

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,20 @@
22

33
import asyncio
44
from collections.abc import Sequence
5-
from typing import TYPE_CHECKING, ClassVar, Literal
5+
from typing import TYPE_CHECKING, Any, ClassVar, Literal
66

77
from cognite.client._api_client import APIClient
8-
from cognite.client.data_classes.data_modeling.records import RecordId, RecordIdSequence, RecordWrite
8+
from cognite.client.data_classes.data_modeling.instances import InstanceSort
9+
from cognite.client.data_classes.data_modeling.records import (
10+
Record,
11+
RecordId,
12+
RecordIdSequence,
13+
RecordList,
14+
RecordSourceSelector,
15+
RecordWrite,
16+
TimeRange,
17+
)
18+
from cognite.client.data_classes.filters import Filter
919
from cognite.client.utils._concurrency import RecordsConcurrencyOperation
1020
from cognite.client.utils._experimental import FeaturePreviewWarning
1121
from cognite.client.utils._url import interpolate_and_url_encode
@@ -14,7 +24,6 @@
1424
from cognite.client import AsyncCogniteClient
1525
from cognite.client.config import ClientConfig
1626

17-
1827
class RecordsAPI(APIClient):
1928
def __init__(self, config: ClientConfig, api_version: str | None, cognite_client: AsyncCogniteClient) -> None:
2029
super().__init__(config, api_version, cognite_client)
@@ -23,11 +32,14 @@ def __init__(self, config: ClientConfig, api_version: str | None, cognite_client
2332
)
2433

2534
_OPERATION_TO_RATE_LIMIT: ClassVar[dict[str, RecordsConcurrencyOperation]] = {
35+
"read": RecordsConcurrencyOperation.READ,
2636
"write": RecordsConcurrencyOperation.WRITE,
2737
"delete": RecordsConcurrencyOperation.WRITE,
2838
}
2939

30-
def _get_semaphore(self, operation: Literal["write", "delete"]) -> asyncio.BoundedSemaphore:
40+
def _get_semaphore( # type: ignore[override]
41+
self, operation: Literal["read", "write", "delete"]
42+
) -> asyncio.BoundedSemaphore:
3143
from cognite.client import global_config
3244

3345
return global_config.concurrency_settings.records._semaphore_factory(
@@ -76,6 +88,7 @@ async def delete(
7688
identifiers=RecordIdSequence.load(items),
7789
wrap_ids=True,
7890
resource_path=self._records_url(stream_id),
91+
override_semaphore=self._get_semaphore("delete"),
7992
)
8093

8194
async def ingest(
@@ -128,6 +141,7 @@ async def ingest(
128141
items=item_list,
129142
resource_path=self._records_url(stream_id),
130143
no_response=True,
144+
override_semaphore=self._get_semaphore("write"),
131145
)
132146

133147
async def upsert(
@@ -182,4 +196,73 @@ async def upsert(
182196
items=item_list,
183197
resource_path=self._records_url(stream_id, "/upsert"),
184198
no_response=True,
199+
override_semaphore=self._get_semaphore("write"),
200+
)
201+
202+
async def list(
203+
self,
204+
stream_id: str,
205+
*,
206+
last_updated_time: TimeRange | None = None,
207+
filter: Filter | None = None,
208+
sources: Sequence[RecordSourceSelector] | None = None,
209+
sort: Sequence[InstanceSort] | InstanceSort | None = None,
210+
limit: int = 10,
211+
include_typing: bool = False,
212+
) -> RecordList:
213+
"""`Filter records in a stream <https://api-docs.cognite.com/20230101/tag/Records/operation/filterRecords>`_.
214+
215+
Returns records matching the given filters, sorted by ``lastUpdatedTime`` unless a custom
216+
``sort`` is given.
217+
218+
Args:
219+
stream_id (str): External ID of the stream to query.
220+
last_updated_time (TimeRange | None): Filter by last-updated time. **Required for
221+
immutable streams** (must include a lower bound).
222+
filter (Filter | None): Filter expression (see :mod:`cognite.client.data_classes.filters`).
223+
sources (Sequence[RecordSourceSelector] | None): Which container properties to return.
224+
sort (Sequence[InstanceSort] | InstanceSort | None): Sort specification(s); up to 5.
225+
limit (int): Maximum number of records to return (1-1000). Defaults to 10.
226+
include_typing (bool): If True, include property type information on the returned
227+
list's ``typing`` attribute.
228+
229+
Returns:
230+
RecordList: The matching records.
231+
232+
Examples:
233+
234+
List records updated since a given timestamp:
235+
236+
>>> from cognite.client import CogniteClient
237+
>>> from cognite.client.data_classes.data_modeling.records import TimeRange
238+
>>> client = CogniteClient()
239+
>>> res = client.data_modeling.records.list(
240+
... stream_id="my-stream",
241+
... last_updated_time=TimeRange(gt=1705341600000),
242+
... limit=100,
243+
... )
244+
"""
245+
self._warning.warn()
246+
other_params: dict[str, Any] = {}
247+
if last_updated_time is not None:
248+
other_params["lastUpdatedTime"] = last_updated_time.dump()
249+
if sources is not None:
250+
other_params["sources"] = [source.dump() for source in sources]
251+
if sort is not None:
252+
sort_list = [sort] if isinstance(sort, InstanceSort) else list(sort)
253+
other_params["sort"] = [spec.dump() for spec in sort_list]
254+
if include_typing:
255+
other_params["includeTyping"] = True
256+
257+
return await self._list(
258+
list_cls=RecordList,
259+
resource_cls=Record,
260+
method="POST",
261+
resource_path=self._records_url(stream_id),
262+
url_path=self._records_url(stream_id, "/filter"),
263+
limit=limit,
264+
filter=filter.dump(camel_case_property=False) if isinstance(filter, Filter) else filter,
265+
other_params=other_params,
266+
settings_forcing_raw_response_loading=[f"{include_typing=}"] if include_typing else None,
267+
override_semaphore=self._get_semaphore("read"),
185268
)

cognite/client/_api/hosted_extractors/destinations.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ async def __call__(
6565
yield item
6666

6767
@overload
68-
async def retrieve(self, external_ids: str, ignore_unknown_ids: bool = False) -> Destination | None: ...
68+
async def retrieve(self, external_ids: str, ignore_unknown_ids: bool = False) -> Destination: ...
6969

7070
@overload
7171
async def retrieve(
@@ -74,15 +74,16 @@ async def retrieve(
7474

7575
async def retrieve(
7676
self, external_ids: str | SequenceNotStr[str], ignore_unknown_ids: bool = False
77-
) -> Destination | DestinationList | None:
77+
) -> Destination | DestinationList:
7878
"""`Retrieve one or more destinations <https://api-docs.cognite.com/20230101/tag/Destinations/operation/retrieve_destinations>`_.
7979
8080
Args:
8181
external_ids (str | SequenceNotStr[str]): The external ID provided by the client. Must be unique for the resource type.
8282
ignore_unknown_ids (bool): Ignore external IDs that are not found
8383
84+
8485
Returns:
85-
Destination | DestinationList | None: Requested destinations
86+
Destination | DestinationList: Requested destinations
8687
8788
Examples:
8889

cognite/client/_api/hosted_extractors/jobs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,15 @@ async def retrieve(self, external_ids: SequenceNotStr[str], ignore_unknown_ids:
7575

7676
async def retrieve(
7777
self, external_ids: str | SequenceNotStr[str], ignore_unknown_ids: bool = False
78-
) -> Job | JobList | None:
78+
) -> Job | None | JobList:
7979
"""`Retrieve one or more jobs <https://api-docs.cognite.com/20230101/tag/Jobs/operation/retrieve_jobs>`_.
8080
8181
Args:
8282
external_ids (str | SequenceNotStr[str]): The external ID provided by the client. Must be unique for the job type.
8383
ignore_unknown_ids (bool): Ignore external IDs that are not found
8484
8585
Returns:
86-
Job | JobList | None: Requested jobs
86+
Job | None | JobList: Requested jobs
8787
8888
Examples:
8989

cognite/client/_api/hosted_extractors/mappings.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,22 +60,23 @@ async def __call__(
6060
yield item
6161

6262
@overload
63-
async def retrieve(self, external_ids: str, ignore_unknown_ids: bool = False) -> Mapping | None: ...
63+
async def retrieve(self, external_ids: str, ignore_unknown_ids: bool = False) -> Mapping: ...
6464

6565
@overload
6666
async def retrieve(self, external_ids: SequenceNotStr[str], ignore_unknown_ids: bool = False) -> MappingList: ...
6767

6868
async def retrieve(
6969
self, external_ids: str | SequenceNotStr[str], ignore_unknown_ids: bool = False
70-
) -> Mapping | MappingList | None:
70+
) -> Mapping | MappingList:
7171
"""`Retrieve one or more mappings <https://api-docs.cognite.com/20230101/tag/Mappings/operation/retrieve_mappings>`_.
7272
7373
Args:
7474
external_ids (str | SequenceNotStr[str]): The external ID provided by the client. Must be unique for the resource type.
7575
ignore_unknown_ids (bool): Ignore external IDs that are not found
7676
77+
7778
Returns:
78-
Mapping | MappingList | None: Requested mappings
79+
Mapping | MappingList: Requested mappings
7980
8081
Examples:
8182

cognite/client/_api/hosted_extractors/sources.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,22 @@ async def __call__(
6161
yield item
6262

6363
@overload
64-
async def retrieve(self, external_ids: str, ignore_unknown_ids: bool = False) -> Source | None: ...
64+
async def retrieve(self, external_ids: str, ignore_unknown_ids: bool = False) -> Source: ...
6565

6666
@overload
6767
async def retrieve(self, external_ids: SequenceNotStr[str], ignore_unknown_ids: bool = False) -> SourceList: ...
6868

6969
async def retrieve(
7070
self, external_ids: str | SequenceNotStr[str], ignore_unknown_ids: bool = False
71-
) -> Source | SourceList | None:
71+
) -> Source | SourceList:
7272
"""`Retrieve one or more sources <https://api-docs.cognite.com/20230101/tag/Sources/operation/retrieve_sources>`_.
7373
7474
Args:
7575
external_ids (str | SequenceNotStr[str]): The external ID provided by the client. Must be unique for the resource type.
7676
ignore_unknown_ids (bool): Ignore external IDs that are not found rather than throw an exception.
7777
7878
Returns:
79-
Source | SourceList | None: Requested sources
79+
Source | SourceList: Requested sources
8080
8181
Examples:
8282

cognite/client/_api/limits.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ async def retrieve(self, id: str) -> Limit | None:
5050
"""
5151
self._warning.warn()
5252

53-
headers = self._alpha_version_header()
53+
headers = {"cdf-version": f"{self._config.api_subversion}-alpha"}
5454

5555
return await self._retrieve(
5656
identifier=LimitId(id),
@@ -87,7 +87,7 @@ async def list(self, filter: Prefix | None = None, limit: int | None = DEFAULT_L
8787
"""
8888
self._warning.warn()
8989

90-
headers = self._alpha_version_header()
90+
headers = {"cdf-version": f"{self._config.api_subversion}-alpha"}
9191

9292
return await self._list(
9393
method="GET" if filter is None else "POST",

0 commit comments

Comments
 (0)