cognite-toolkit 0.7.42__py3-none-any.whl → 0.7.44__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.
Files changed (72) hide show
  1. cognite_toolkit/_cdf_tk/client/_toolkit_client.py +7 -1
  2. cognite_toolkit/_cdf_tk/client/api/events.py +20 -2
  3. cognite_toolkit/_cdf_tk/client/api/filemetadata.py +145 -0
  4. cognite_toolkit/_cdf_tk/client/api/raw.py +174 -0
  5. cognite_toolkit/_cdf_tk/client/api/simulator_models.py +118 -0
  6. cognite_toolkit/_cdf_tk/client/api/simulators.py +8 -0
  7. cognite_toolkit/_cdf_tk/client/api/timeseries.py +20 -2
  8. cognite_toolkit/_cdf_tk/client/cdf_client/__init__.py +2 -1
  9. cognite_toolkit/_cdf_tk/client/cdf_client/api.py +40 -6
  10. cognite_toolkit/_cdf_tk/client/data_classes/agent.py +6 -9
  11. cognite_toolkit/_cdf_tk/client/data_classes/annotation.py +79 -0
  12. cognite_toolkit/_cdf_tk/client/data_classes/asset.py +7 -14
  13. cognite_toolkit/_cdf_tk/client/data_classes/base.py +15 -5
  14. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/__init__.py +164 -0
  15. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_constraints.py +37 -0
  16. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_container.py +50 -0
  17. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_data_model.py +73 -0
  18. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_data_types.py +116 -0
  19. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_indexes.py +26 -0
  20. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_instance.py +143 -0
  21. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_references.py +86 -0
  22. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_space.py +26 -0
  23. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_view.py +143 -0
  24. cognite_toolkit/_cdf_tk/client/data_classes/data_modeling/_view_property.py +152 -0
  25. cognite_toolkit/_cdf_tk/client/data_classes/dataset.py +35 -0
  26. cognite_toolkit/_cdf_tk/client/data_classes/event.py +12 -15
  27. cognite_toolkit/_cdf_tk/client/data_classes/extraction_pipeline.py +59 -0
  28. cognite_toolkit/_cdf_tk/client/data_classes/filemetadata.py +15 -19
  29. cognite_toolkit/_cdf_tk/client/data_classes/hosted_extractor_destination.py +34 -0
  30. cognite_toolkit/_cdf_tk/client/data_classes/hosted_extractor_job.py +134 -0
  31. cognite_toolkit/_cdf_tk/client/data_classes/hosted_extractor_mapping.py +72 -0
  32. cognite_toolkit/_cdf_tk/client/data_classes/hosted_extractor_source/__init__.py +63 -0
  33. cognite_toolkit/_cdf_tk/client/data_classes/hosted_extractor_source/_auth.py +63 -0
  34. cognite_toolkit/_cdf_tk/client/data_classes/hosted_extractor_source/_base.py +26 -0
  35. cognite_toolkit/_cdf_tk/client/data_classes/hosted_extractor_source/_certificate.py +20 -0
  36. cognite_toolkit/_cdf_tk/client/data_classes/hosted_extractor_source/_eventhub.py +31 -0
  37. cognite_toolkit/_cdf_tk/client/data_classes/hosted_extractor_source/_kafka.py +53 -0
  38. cognite_toolkit/_cdf_tk/client/data_classes/hosted_extractor_source/_mqtt.py +36 -0
  39. cognite_toolkit/_cdf_tk/client/data_classes/hosted_extractor_source/_rest.py +49 -0
  40. cognite_toolkit/_cdf_tk/client/data_classes/identifiers.py +8 -0
  41. cognite_toolkit/_cdf_tk/client/data_classes/label.py +27 -0
  42. cognite_toolkit/_cdf_tk/client/data_classes/raw.py +3 -2
  43. cognite_toolkit/_cdf_tk/client/data_classes/securitycategory.py +24 -0
  44. cognite_toolkit/_cdf_tk/client/data_classes/sequence.py +45 -0
  45. cognite_toolkit/_cdf_tk/client/data_classes/simulator_model.py +50 -0
  46. cognite_toolkit/_cdf_tk/client/data_classes/timeseries.py +15 -18
  47. cognite_toolkit/_cdf_tk/client/data_classes/transformation.py +140 -0
  48. cognite_toolkit/_cdf_tk/client/data_classes/workflow.py +27 -0
  49. cognite_toolkit/_cdf_tk/client/data_classes/workflow_trigger.py +63 -0
  50. cognite_toolkit/_cdf_tk/client/data_classes/workflow_version.py +155 -0
  51. cognite_toolkit/_cdf_tk/client/testing.py +6 -1
  52. cognite_toolkit/_cdf_tk/commands/_migrate/conversion.py +10 -7
  53. cognite_toolkit/_cdf_tk/commands/_migrate/data_mapper.py +4 -4
  54. cognite_toolkit/_cdf_tk/cruds/_data_cruds.py +7 -3
  55. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/auth.py +5 -1
  56. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/classic.py +40 -39
  57. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/file.py +56 -59
  58. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/relationship.py +3 -3
  59. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/timeseries.py +48 -47
  60. cognite_toolkit/_cdf_tk/resource_classes/__init__.py +2 -0
  61. cognite_toolkit/_cdf_tk/resource_classes/simulator_model.py +17 -0
  62. cognite_toolkit/_cdf_tk/storageio/_asset_centric.py +84 -71
  63. cognite_toolkit/_cdf_tk/storageio/_file_content.py +22 -19
  64. cognite_toolkit/_cdf_tk/utils/useful_types2.py +5 -3
  65. cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml +1 -1
  66. cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml +1 -1
  67. cognite_toolkit/_resources/cdf.toml +1 -1
  68. cognite_toolkit/_version.py +1 -1
  69. {cognite_toolkit-0.7.42.dist-info → cognite_toolkit-0.7.44.dist-info}/METADATA +11 -1
  70. {cognite_toolkit-0.7.42.dist-info → cognite_toolkit-0.7.44.dist-info}/RECORD +72 -34
  71. {cognite_toolkit-0.7.42.dist-info → cognite_toolkit-0.7.44.dist-info}/WHEEL +1 -1
  72. {cognite_toolkit-0.7.42.dist-info → cognite_toolkit-0.7.44.dist-info}/entry_points.txt +0 -0
@@ -5,6 +5,7 @@ that handle CRUD operations for CDF Data Modeling API resources.
5
5
  """
6
6
 
7
7
  from abc import ABC, abstractmethod
8
+ from collections import defaultdict
8
9
  from collections.abc import Callable, Iterable, Sequence
9
10
  from dataclasses import dataclass
10
11
  from functools import partial
@@ -97,9 +98,10 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
97
98
  method: APIMethod,
98
99
  params: dict[str, Any] | None = None,
99
100
  extra_body: dict[str, Any] | None = None,
101
+ endpoint: str | None = None,
100
102
  ) -> list[T_ResponseResource]:
101
103
  response_items: list[T_ResponseResource] = []
102
- for response in self._chunk_requests(items, method, self._serialize_items, params, extra_body):
104
+ for response in self._chunk_requests(items, method, self._serialize_items, params, extra_body, endpoint):
103
105
  response_items.extend(self._page_response(response).items)
104
106
  return response_items
105
107
 
@@ -121,8 +123,9 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
121
123
  method: APIMethod,
122
124
  params: dict[str, Any] | None = None,
123
125
  extra_body: dict[str, Any] | None = None,
126
+ endpoint: str | None = None,
124
127
  ) -> None:
125
- list(self._chunk_requests(items, method, self._serialize_items, params, extra_body))
128
+ list(self._chunk_requests(items, method, self._serialize_items, params, extra_body, endpoint))
126
129
  return None
127
130
 
128
131
  def _chunk_requests(
@@ -132,14 +135,28 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
132
135
  serialization: Callable[[Sequence[_T_BaseModel]], list[dict[str, JsonValue]]],
133
136
  params: dict[str, Any] | None = None,
134
137
  extra_body: dict[str, Any] | None = None,
138
+ endpoint_path: str | None = None,
135
139
  ) -> Iterable[SuccessResponse2]:
140
+ """Send requests in chunks and yield responses.
141
+
142
+ Args:
143
+ items: The items to process.
144
+ method: The API method to use. This is used ot look the up the endpoint.
145
+ serialization: A function to serialize the items to JSON-compatible dicts.
146
+ params: Optional query parameters for the request.
147
+ extra_body: Optional extra body content to include in the request.
148
+ endpoint_path: Optional override for the endpoint path.
149
+
150
+ Yields:
151
+ The successful responses from the API.
152
+ """
136
153
  # Filter out None
137
154
  request_params = self._filter_out_none_values(params)
138
155
  endpoint = self._method_endpoint_map[method]
139
156
 
140
157
  for chunk in chunker_sequence(items, endpoint.item_limit):
141
158
  request = RequestMessage2(
142
- endpoint_url=f"{self._make_url(endpoint.path)}",
159
+ endpoint_url=f"{self._make_url(endpoint_path or endpoint.path)}",
143
160
  method=endpoint.method,
144
161
  body_content={"items": serialization(chunk), **(extra_body or {})}, # type: ignore[dict-item]
145
162
  parameters=request_params,
@@ -154,12 +171,24 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
154
171
  request_params = {k: v for k, v in params.items() if v is not None}
155
172
  return request_params
156
173
 
174
+ @classmethod
175
+ def _group_items_by_text_field(
176
+ cls, items: Sequence[_T_BaseModel], field_name: str
177
+ ) -> dict[str, list[_T_BaseModel]]:
178
+ """Group items by a text field."""
179
+ grouped_items: dict[str, list[_T_BaseModel]] = defaultdict(list)
180
+ for item in items:
181
+ key = str(getattr(item, field_name))
182
+ grouped_items[key].append(item)
183
+ return grouped_items
184
+
157
185
  def _iterate(
158
186
  self,
159
187
  limit: int,
160
188
  cursor: str | None = None,
161
189
  params: dict[str, Any] | None = None,
162
190
  body: dict[str, Any] | None = None,
191
+ endpoint_path: str | None = None,
163
192
  ) -> PagedResponse[T_ResponseResource]:
164
193
  """Fetch a single page of resources.
165
194
 
@@ -171,8 +200,11 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
171
200
  - space: Filter by space
172
201
  - includeGlobal: Whether to include global resources
173
202
  body : Body content for the request, if applicable.
203
+ limit: Maximum number of items to return in the page.
204
+ cursor: Cursor for pagination.
174
205
  limit: Maximum number of items to return in the page.
175
206
  cursor: Cursor for pagination.
207
+
176
208
  Returns:
177
209
  A Page containing the items and the cursor for the next page.
178
210
  """
@@ -194,7 +226,7 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
194
226
  raise NotImplementedError(f"Unsupported method {endpoint.method} for pagination.")
195
227
 
196
228
  request = RequestMessage2(
197
- endpoint_url=self._make_url(endpoint.path),
229
+ endpoint_url=self._make_url(endpoint_path or endpoint.path),
198
230
  method=endpoint.method,
199
231
  parameters=request_params,
200
232
  body_content=body,
@@ -203,7 +235,9 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
203
235
  response = result.get_success_or_raise()
204
236
  return self._page_response(response)
205
237
 
206
- def _list(self, limit: int | None = None, params: dict[str, Any] | None = None) -> list[T_ResponseResource]:
238
+ def _list(
239
+ self, limit: int | None = None, params: dict[str, Any] | None = None, endpoint_path: str | None = None
240
+ ) -> list[T_ResponseResource]:
207
241
  """List all resources, handling pagination automatically."""
208
242
  all_items: list[T_ResponseResource] = []
209
243
  next_cursor: str | None = None
@@ -211,7 +245,7 @@ class CDFResourceAPI(Generic[T_Identifier, T_RequestResource, T_ResponseResource
211
245
  endpoint = self._method_endpoint_map["list"]
212
246
  while True:
213
247
  page_limit = endpoint.item_limit if limit is None else min(limit - total, endpoint.item_limit)
214
- page = self._iterate(limit=page_limit, cursor=next_cursor, params=params)
248
+ page = self._iterate(limit=page_limit, cursor=next_cursor, params=params, endpoint_path=endpoint_path)
215
249
  all_items.extend(page.items)
216
250
  total += len(page.items)
217
251
  if page.next_cursor is None or (limit is not None and total >= limit):
@@ -98,29 +98,26 @@ AgentTool = Annotated[
98
98
  ]
99
99
 
100
100
 
101
- class AgentRequest(RequestResource):
101
+ class Agent(BaseModelObject):
102
102
  external_id: str
103
103
  name: str
104
104
  description: str | None = None
105
105
  instructions: str | None = None
106
106
  model: str = "azure/gpt-4o-mini"
107
107
  tools: list[AgentTool] | None = None
108
- runtime_version: str | None = None
109
108
 
110
109
  def as_id(self) -> ExternalId:
111
110
  return ExternalId(external_id=self.external_id)
112
111
 
113
112
 
114
- class AgentResponse(ResponseResource[AgentRequest]):
113
+ class AgentRequest(Agent, RequestResource):
114
+ runtime_version: str | None = None
115
+
116
+
117
+ class AgentResponse(Agent, ResponseResource[AgentRequest]):
115
118
  created_time: int
116
119
  last_updated_time: int
117
120
  owner_id: str
118
- external_id: str
119
- name: str
120
- description: str | None = None
121
- instructions: str | None = None
122
- model: str = "azure/gpt-4o-mini"
123
- tools: list[AgentTool] | None = None
124
121
  runtime_version: str
125
122
 
126
123
  def as_request_resource(self) -> AgentRequest:
@@ -0,0 +1,79 @@
1
+ from typing import Any, Literal, TypeAlias
2
+
3
+ from pydantic import Field, JsonValue
4
+
5
+ from cognite_toolkit._cdf_tk.client.data_classes.base import BaseModelObject, RequestUpdateable, ResponseResource
6
+
7
+ from .identifiers import InternalId
8
+
9
+ AnnotationStatus: TypeAlias = Literal["suggested", "rejected", "approved"]
10
+ AnnotationType: TypeAlias = Literal[
11
+ "diagrams.AssetLink",
12
+ "diagrams.FileLink",
13
+ "diagrams.InstanceLink",
14
+ "diagrams.Junction",
15
+ "diagrams.Line",
16
+ "diagrams.UnhandledSymbolObject",
17
+ "diagrams.UnhandledTextObject",
18
+ "documents.ExtractedText",
19
+ "forms.Detection",
20
+ "images.AssetLink",
21
+ "images.Classification",
22
+ "images.InstanceLink",
23
+ "images.KeypointCollection",
24
+ "images.ObjectDetection",
25
+ "images.TextRegion",
26
+ "isoplan.IsoPlanAnnotation",
27
+ "pointcloud.BoundingVolume",
28
+ ]
29
+
30
+
31
+ class Annotation(BaseModelObject):
32
+ annotated_resource_type: str
33
+ annotated_resource_id: int
34
+ annotation_type: AnnotationType
35
+ creating_app: str
36
+ creating_app_version: str
37
+ creating_user: str | None
38
+ data: dict[str, JsonValue]
39
+ status: AnnotationStatus
40
+
41
+
42
+ class AnnotationRequest(Annotation, RequestUpdateable):
43
+ """Request data class for annotations."""
44
+
45
+ # The 'id' field is not part of the request when creating a new resource,
46
+ # but is needed when updating an existing resource.
47
+ id: int | None = Field(default=None, exclude=True)
48
+
49
+ def as_id(self) -> InternalId:
50
+ if self.id is None:
51
+ raise ValueError("Cannot convert AnnotationRequest to InternalId when id is None")
52
+ return InternalId(id=self.id)
53
+
54
+ def as_update(self, mode: Literal["patch", "replace"]) -> dict[str, Any]:
55
+ """Converts the request to an update payload for the API."""
56
+ if self.id is None:
57
+ raise ValueError("id must be provided to create an update dictionary")
58
+ return {
59
+ "id": self.id,
60
+ "update": {
61
+ "annotationType": {"set": self.annotation_type},
62
+ "data": {"set": self.data},
63
+ "status": {"set": self.status},
64
+ },
65
+ }
66
+
67
+
68
+ class AnnotationResponse(Annotation, ResponseResource[AnnotationRequest]):
69
+ """Response data class for annotations."""
70
+
71
+ id: int
72
+ created_time: int
73
+ last_updated_time: int
74
+
75
+ def as_id(self) -> InternalId:
76
+ return InternalId(id=self.id)
77
+
78
+ def as_request_resource(self) -> AnnotationRequest:
79
+ return AnnotationRequest.model_validate(self.dump(), extra="ignore")
@@ -7,9 +7,7 @@ from cognite_toolkit._cdf_tk.client.data_classes.base import BaseModelObject, Re
7
7
  from .identifiers import ExternalId
8
8
 
9
9
 
10
- class AssetRequest(RequestUpdateable):
11
- container_fields: ClassVar[frozenset[str]] = frozenset({"metadata", "labels"})
12
- non_nullable_fields: ClassVar[frozenset[str]] = frozenset({"parent_id", "parent_external_id"})
10
+ class Asset(BaseModelObject):
13
11
  external_id: str | None = None
14
12
  name: str
15
13
  parent_id: int | None = None
@@ -27,28 +25,23 @@ class AssetRequest(RequestUpdateable):
27
25
  return ExternalId(external_id=self.external_id)
28
26
 
29
27
 
28
+ class AssetRequest(Asset, RequestUpdateable):
29
+ container_fields: ClassVar[frozenset[str]] = frozenset({"metadata", "labels"})
30
+ non_nullable_fields: ClassVar[frozenset[str]] = frozenset({"parent_id", "parent_external_id"})
31
+
32
+
30
33
  class AssetAggregateItem(BaseModelObject):
31
34
  child_count: int
32
35
  depth: int
33
36
  path: list[dict[Literal["id"], int]]
34
37
 
35
38
 
36
- class AssetResponse(ResponseResource[AssetRequest]):
39
+ class AssetResponse(Asset, ResponseResource[AssetRequest]):
37
40
  created_time: int
38
41
  last_updated_time: int
39
42
  root_id: int
40
43
  aggregates: AssetAggregateItem | None = None
41
44
  id: int
42
- external_id: str | None = None
43
- name: str
44
- parent_id: int | None = None
45
- parent_external_id: str | None = None
46
- description: str | None = None
47
- metadata: dict[str, str] | None = None
48
- data_set_id: int | None = None
49
- source: str | None = None
50
- labels: list[dict[Literal["externalId"], str]] | None = None
51
- geo_location: dict[str, JsonValue] | None = None
52
45
 
53
46
  def as_request_resource(self) -> AssetRequest:
54
47
  return AssetRequest.model_validate(self.dump(), extra="ignore")
@@ -18,19 +18,29 @@ class BaseModelObject(BaseModel):
18
18
  """Base class for all object. This includes resources and nested objects."""
19
19
 
20
20
  # We allow extra fields to support forward compatibility.
21
- model_config = ConfigDict(alias_generator=to_camel, extra="allow")
21
+ model_config = ConfigDict(alias_generator=to_camel, extra="allow", populate_by_name=True)
22
22
 
23
- def dump(self, camel_case: bool = True) -> dict[str, Any]:
23
+ def dump(self, camel_case: bool = True, exclude_extra: bool = False) -> dict[str, Any]:
24
24
  """Dump the resource to a dictionary.
25
25
 
26
- This is the default serialization method for request resources.
26
+ Args:
27
+ camel_case (bool): Whether to use camelCase for the keys. Default is True.
28
+ exclude_extra (bool): Whether to exclude extra fields not defined in the model. Default is False.
29
+
27
30
  """
31
+ if exclude_extra:
32
+ return self.model_dump(
33
+ mode="json",
34
+ by_alias=camel_case,
35
+ exclude_unset=True,
36
+ exclude=set(self.__pydantic_extra__) if self.__pydantic_extra__ else None,
37
+ )
28
38
  return self.model_dump(mode="json", by_alias=camel_case, exclude_unset=True)
29
39
 
30
40
  @classmethod
31
41
  def _load(cls, resource: dict[str, Any]) -> Self:
32
42
  """Load method to match CogniteResource signature."""
33
- return cls.model_validate(resource)
43
+ return cls.model_validate(resource, by_alias=True)
34
44
 
35
45
 
36
46
  class Identifier(BaseModelObject):
@@ -39,7 +49,7 @@ class Identifier(BaseModelObject):
39
49
 
40
50
  model_config = ConfigDict(alias_generator=to_camel, extra="ignore", populate_by_name=True, frozen=True)
41
51
 
42
- def dump(self, camel_case: bool = True) -> dict[str, Any]:
52
+ def dump(self, camel_case: bool = True, exclude_extra: bool = False) -> dict[str, Any]:
43
53
  """Dump the resource to a dictionary.
44
54
 
45
55
  This is the default serialization method for request resources.
@@ -0,0 +1,164 @@
1
+ from ._constraints import (
2
+ Constraint,
3
+ ConstraintAdapter,
4
+ ConstraintDefinition,
5
+ RequiresConstraintDefinition,
6
+ UniquenessConstraintDefinition,
7
+ )
8
+ from ._container import (
9
+ Container,
10
+ ContainerPropertyDefinition,
11
+ ContainerRequest,
12
+ ContainerResponse,
13
+ )
14
+ from ._data_model import DataModelRequest, DataModelResponse
15
+ from ._data_types import (
16
+ BooleanProperty,
17
+ DataType,
18
+ DataTypeAdapter,
19
+ DateProperty,
20
+ DirectNodeRelation,
21
+ EnumProperty,
22
+ EnumValue,
23
+ FileCDFExternalIdReference,
24
+ Float32Property,
25
+ Float64Property,
26
+ FloatProperty,
27
+ Int32Property,
28
+ Int64Property,
29
+ JSONProperty,
30
+ ListablePropertyTypeDefinition,
31
+ PropertyTypeDefinition,
32
+ SequenceCDFExternalIdReference,
33
+ TextProperty,
34
+ TimeseriesCDFExternalIdReference,
35
+ TimestampProperty,
36
+ Unit,
37
+ )
38
+ from ._indexes import (
39
+ BtreeIndex,
40
+ Index,
41
+ IndexAdapter,
42
+ IndexDefinition,
43
+ InvertedIndex,
44
+ )
45
+ from ._instance import (
46
+ EdgeRequest,
47
+ EdgeResponse,
48
+ InstanceDefinition,
49
+ InstanceResponseDefinition,
50
+ InstanceSource,
51
+ NodeRequest,
52
+ NodeResponse,
53
+ )
54
+ from ._references import (
55
+ ContainerConstraintReference,
56
+ ContainerDirectReference,
57
+ ContainerIndexReference,
58
+ ContainerReference,
59
+ DataModelReference,
60
+ NodeReference,
61
+ SpaceReference,
62
+ ViewDirectReference,
63
+ ViewReference,
64
+ )
65
+ from ._space import Space, SpaceRequest, SpaceResponse
66
+ from ._view import View, ViewRequest, ViewResponse
67
+ from ._view_property import (
68
+ ConnectionPropertyDefinition,
69
+ ConstraintOrIndexState,
70
+ EdgeProperty,
71
+ MultiEdgeProperty,
72
+ MultiReverseDirectRelationPropertyRequest,
73
+ MultiReverseDirectRelationPropertyResponse,
74
+ ReverseDirectRelationProperty,
75
+ SingleEdgeProperty,
76
+ SingleReverseDirectRelationPropertyRequest,
77
+ SingleReverseDirectRelationPropertyResponse,
78
+ ViewCoreProperty,
79
+ ViewCorePropertyRequest,
80
+ ViewCorePropertyResponse,
81
+ ViewPropertyDefinition,
82
+ ViewRequestProperty,
83
+ ViewRequestPropertyAdapter,
84
+ ViewResponseProperty,
85
+ )
86
+
87
+ __all__ = [
88
+ "BooleanProperty",
89
+ "BtreeIndex",
90
+ "ConnectionPropertyDefinition",
91
+ "Constraint",
92
+ "ConstraintAdapter",
93
+ "ConstraintDefinition",
94
+ "ConstraintOrIndexState",
95
+ "Container",
96
+ "ContainerConstraintReference",
97
+ "ContainerDirectReference",
98
+ "ContainerIndexReference",
99
+ "ContainerPropertyDefinition",
100
+ "ContainerReference",
101
+ "ContainerRequest",
102
+ "ContainerResponse",
103
+ "DataModelReference",
104
+ "DataModelRequest",
105
+ "DataModelResponse",
106
+ "DataType",
107
+ "DataTypeAdapter",
108
+ "DateProperty",
109
+ "DirectNodeRelation",
110
+ "EdgeProperty",
111
+ "EdgeRequest",
112
+ "EdgeResponse",
113
+ "EnumProperty",
114
+ "EnumValue",
115
+ "FileCDFExternalIdReference",
116
+ "Float32Property",
117
+ "Float64Property",
118
+ "FloatProperty",
119
+ "Index",
120
+ "IndexAdapter",
121
+ "IndexDefinition",
122
+ "InstanceDefinition",
123
+ "InstanceResponseDefinition",
124
+ "InstanceSource",
125
+ "Int32Property",
126
+ "Int64Property",
127
+ "InvertedIndex",
128
+ "JSONProperty",
129
+ "ListablePropertyTypeDefinition",
130
+ "MultiEdgeProperty",
131
+ "MultiReverseDirectRelationPropertyRequest",
132
+ "MultiReverseDirectRelationPropertyResponse",
133
+ "NodeReference",
134
+ "NodeRequest",
135
+ "NodeResponse",
136
+ "PropertyTypeDefinition",
137
+ "RequiresConstraintDefinition",
138
+ "ReverseDirectRelationProperty",
139
+ "SequenceCDFExternalIdReference",
140
+ "SingleEdgeProperty",
141
+ "SingleReverseDirectRelationPropertyRequest",
142
+ "SingleReverseDirectRelationPropertyResponse",
143
+ "Space",
144
+ "SpaceReference",
145
+ "SpaceRequest",
146
+ "SpaceResponse",
147
+ "TextProperty",
148
+ "TimeseriesCDFExternalIdReference",
149
+ "TimestampProperty",
150
+ "UniquenessConstraintDefinition",
151
+ "Unit",
152
+ "View",
153
+ "ViewCoreProperty",
154
+ "ViewCorePropertyRequest",
155
+ "ViewCorePropertyResponse",
156
+ "ViewDirectReference",
157
+ "ViewPropertyDefinition",
158
+ "ViewReference",
159
+ "ViewRequest",
160
+ "ViewRequestProperty",
161
+ "ViewRequestPropertyAdapter",
162
+ "ViewResponse",
163
+ "ViewResponseProperty",
164
+ ]
@@ -0,0 +1,37 @@
1
+ from abc import ABC
2
+ from typing import Annotated, Any, Literal
3
+
4
+ from pydantic import Field, TypeAdapter, field_serializer
5
+ from pydantic_core.core_schema import FieldSerializationInfo
6
+
7
+ from cognite_toolkit._cdf_tk.client.data_classes.base import BaseModelObject
8
+
9
+ from ._references import ContainerReference
10
+
11
+
12
+ class ConstraintDefinition(BaseModelObject, ABC):
13
+ constraint_type: str
14
+
15
+
16
+ class UniquenessConstraintDefinition(ConstraintDefinition):
17
+ constraint_type: Literal["uniqueness"] = "uniqueness"
18
+ properties: list[str]
19
+ by_space: bool | None = None
20
+
21
+
22
+ class RequiresConstraintDefinition(ConstraintDefinition):
23
+ constraint_type: Literal["requires"] = "requires"
24
+ require: ContainerReference
25
+
26
+ @field_serializer("require", mode="plain")
27
+ @classmethod
28
+ def serialize_require(cls, require: ContainerReference, info: FieldSerializationInfo) -> dict[str, Any]:
29
+ return {**require.model_dump(**vars(info)), "type": "container"}
30
+
31
+
32
+ Constraint = Annotated[
33
+ UniquenessConstraintDefinition | RequiresConstraintDefinition,
34
+ Field(discriminator="constraint_type"),
35
+ ]
36
+
37
+ ConstraintAdapter: TypeAdapter[Constraint] = TypeAdapter(Constraint)
@@ -0,0 +1,50 @@
1
+ from abc import ABC
2
+ from typing import Literal
3
+
4
+ from pydantic import JsonValue
5
+
6
+ from cognite_toolkit._cdf_tk.client.data_classes.base import BaseModelObject, RequestResource, ResponseResource
7
+
8
+ from ._constraints import Constraint
9
+ from ._data_types import DataType
10
+ from ._indexes import Index
11
+ from ._references import ContainerReference
12
+
13
+
14
+ class ContainerPropertyDefinition(BaseModelObject):
15
+ immutable: bool | None = None
16
+ nullable: bool | None = None
17
+ auto_increment: bool | None = None
18
+ default_value: str | int | float | bool | dict[str, JsonValue] | None = None
19
+ description: str | None = None
20
+ name: str | None = None
21
+ type: DataType
22
+
23
+
24
+ class Container(BaseModelObject, ABC):
25
+ space: str
26
+ external_id: str
27
+ name: str | None = None
28
+ description: str | None = None
29
+ used_for: Literal["node", "edge", "all"] | None = None
30
+ properties: dict[str, ContainerPropertyDefinition]
31
+ constraints: dict[str, Constraint] | None = None
32
+ indexes: dict[str, Index] | None = None
33
+
34
+ def as_id(self) -> ContainerReference:
35
+ return ContainerReference(
36
+ space=self.space,
37
+ external_id=self.external_id,
38
+ )
39
+
40
+
41
+ class ContainerRequest(Container, RequestResource): ...
42
+
43
+
44
+ class ContainerResponse(Container, ResponseResource[ContainerRequest]):
45
+ created_time: int
46
+ last_updated_time: int
47
+ is_global: bool
48
+
49
+ def as_request_resource(self) -> "ContainerRequest":
50
+ return ContainerRequest.model_validate(self.model_dump(by_alias=True))
@@ -0,0 +1,73 @@
1
+ from abc import ABC
2
+ from typing import Any
3
+
4
+ from pydantic import field_serializer
5
+ from pydantic_core.core_schema import FieldSerializationInfo
6
+
7
+ from cognite_toolkit._cdf_tk.client.data_classes.base import BaseModelObject, RequestResource, ResponseResource
8
+
9
+ from ._references import DataModelReference, ViewReference
10
+ from ._view import ViewResponse
11
+
12
+
13
+ class DataModel(BaseModelObject, ABC):
14
+ """Cognite Data Model resource.
15
+
16
+ Data models group and structure views into reusable collections.
17
+ A data model contains a set of views where the node types can
18
+ refer to each other with direct relations and edges.
19
+ """
20
+
21
+ space: str
22
+ external_id: str
23
+ version: str
24
+ description: str | None = None
25
+
26
+ def as_id(self) -> DataModelReference:
27
+ return DataModelReference(
28
+ space=self.space,
29
+ external_id=self.external_id,
30
+ version=self.version,
31
+ )
32
+
33
+
34
+ class DataModelRequest(DataModel, RequestResource):
35
+ views: list[ViewReference] | None = None
36
+
37
+ @field_serializer("views", mode="plain")
38
+ @classmethod
39
+ def serialize_views(
40
+ cls, views: list[ViewReference] | None, info: FieldSerializationInfo
41
+ ) -> list[dict[str, Any]] | None:
42
+ if views is None:
43
+ return None
44
+ return [{**view.model_dump(**vars(info)), "type": "view"} for view in views]
45
+
46
+
47
+ class DataModelResponse(DataModel, ResponseResource[DataModelRequest]):
48
+ views: list[ViewReference] | None = None
49
+ created_time: int
50
+ last_updated_time: int
51
+ is_global: bool
52
+
53
+ def as_request_resource(self) -> DataModelRequest:
54
+ return DataModelRequest.model_validate(self.model_dump(by_alias=True), extra="ignore")
55
+
56
+ @field_serializer("views", mode="plain")
57
+ @classmethod
58
+ def serialize_views(
59
+ cls, views: list[ViewReference] | None, info: FieldSerializationInfo
60
+ ) -> list[dict[str, Any]] | None:
61
+ if views is None:
62
+ return None
63
+ return [{**view.model_dump(**vars(info)), "type": "view"} for view in views]
64
+
65
+
66
+ class DataModelResponseWithViews(DataModel, ResponseResource[DataModelRequest]):
67
+ views: list[ViewResponse] | None = None
68
+ created_time: int
69
+ last_updated_time: int
70
+ is_global: bool
71
+
72
+ def as_request_resource(self) -> DataModelRequest:
73
+ return DataModelRequest.model_validate(self.model_dump(by_alias=True), extra="ignore")