cognite-toolkit 0.7.38__py3-none-any.whl → 0.7.40__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.
- cognite_toolkit/_cdf_tk/client/_toolkit_client.py +3 -1
- cognite_toolkit/_cdf_tk/client/api/assets.py +118 -0
- cognite_toolkit/_cdf_tk/client/api/events.py +79 -0
- cognite_toolkit/_cdf_tk/client/api/infield.py +3 -3
- cognite_toolkit/_cdf_tk/client/api/legacy/extended_functions.py +1 -1
- cognite_toolkit/_cdf_tk/client/api/project.py +1 -1
- cognite_toolkit/_cdf_tk/client/api/streams.py +2 -2
- cognite_toolkit/_cdf_tk/client/api/three_d.py +5 -4
- cognite_toolkit/_cdf_tk/client/api/timeseries.py +85 -0
- cognite_toolkit/_cdf_tk/client/cdf_client/__init__.py +9 -0
- cognite_toolkit/_cdf_tk/client/cdf_client/api.py +220 -0
- cognite_toolkit/_cdf_tk/client/{data_classes/api_classes.py → cdf_client/responses.py} +10 -13
- cognite_toolkit/_cdf_tk/client/data_classes/asset.py +54 -0
- cognite_toolkit/_cdf_tk/client/data_classes/base.py +117 -22
- cognite_toolkit/_cdf_tk/client/data_classes/event.py +40 -0
- cognite_toolkit/_cdf_tk/client/data_classes/identifiers.py +44 -0
- cognite_toolkit/_cdf_tk/client/data_classes/instance_api.py +34 -0
- cognite_toolkit/_cdf_tk/client/data_classes/streams.py +3 -2
- cognite_toolkit/_cdf_tk/client/data_classes/three_d.py +29 -34
- cognite_toolkit/_cdf_tk/client/data_classes/timeseries.py +45 -0
- cognite_toolkit/_cdf_tk/{utils → client}/http_client/__init__.py +4 -4
- cognite_toolkit/_cdf_tk/{utils → client}/http_client/_client.py +10 -10
- cognite_toolkit/_cdf_tk/{utils → client}/http_client/_data_classes.py +2 -2
- cognite_toolkit/_cdf_tk/{utils → client}/http_client/_data_classes2.py +10 -33
- cognite_toolkit/_cdf_tk/client/testing.py +2 -0
- cognite_toolkit/_cdf_tk/commands/_migrate/command.py +1 -1
- cognite_toolkit/_cdf_tk/commands/_migrate/conversion.py +6 -7
- cognite_toolkit/_cdf_tk/commands/_migrate/data_classes.py +6 -5
- cognite_toolkit/_cdf_tk/commands/_migrate/data_mapper.py +6 -4
- cognite_toolkit/_cdf_tk/commands/_migrate/migration_io.py +10 -10
- cognite_toolkit/_cdf_tk/commands/_purge.py +7 -7
- cognite_toolkit/_cdf_tk/commands/_upload.py +1 -1
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/classic.py +43 -47
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/fieldops.py +11 -4
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/file.py +2 -1
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/location.py +3 -2
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/relationship.py +2 -1
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/streams.py +1 -1
- cognite_toolkit/_cdf_tk/cruds/_resource_cruds/timeseries.py +2 -1
- cognite_toolkit/_cdf_tk/data_classes/_module_toml.py +1 -0
- cognite_toolkit/_cdf_tk/storageio/_applications.py +1 -1
- cognite_toolkit/_cdf_tk/storageio/_asset_centric.py +32 -29
- cognite_toolkit/_cdf_tk/storageio/_base.py +1 -1
- cognite_toolkit/_cdf_tk/storageio/_datapoints.py +7 -7
- cognite_toolkit/_cdf_tk/storageio/_file_content.py +7 -7
- cognite_toolkit/_cdf_tk/storageio/_raw.py +1 -1
- cognite_toolkit/_cdf_tk/utils/useful_types.py +4 -7
- cognite_toolkit/_cdf_tk/utils/useful_types2.py +12 -0
- cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml +1 -1
- cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml +1 -1
- cognite_toolkit/_resources/cdf.toml +1 -1
- cognite_toolkit/_version.py +1 -1
- {cognite_toolkit-0.7.38.dist-info → cognite_toolkit-0.7.40.dist-info}/METADATA +1 -1
- {cognite_toolkit-0.7.38.dist-info → cognite_toolkit-0.7.40.dist-info}/RECORD +58 -48
- {cognite_toolkit-0.7.38.dist-info → cognite_toolkit-0.7.40.dist-info}/WHEEL +1 -1
- /cognite_toolkit/_cdf_tk/{utils → client}/http_client/_exception.py +0 -0
- /cognite_toolkit/_cdf_tk/{utils → client}/http_client/_tracker.py +0 -0
- {cognite_toolkit-0.7.38.dist-info → cognite_toolkit-0.7.40.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
3
|
+
from pydantic import JsonValue
|
|
4
|
+
|
|
5
|
+
from cognite_toolkit._cdf_tk.client.data_classes.base import BaseModelObject, RequestUpdateable, ResponseResource
|
|
6
|
+
|
|
7
|
+
from .identifiers import ExternalId
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AssetRequest(RequestUpdateable):
|
|
11
|
+
container_fields = frozenset({"metadata", "labels"})
|
|
12
|
+
non_nullable_fields = frozenset({"parent_id", "parent_external_id"})
|
|
13
|
+
external_id: str | None = None
|
|
14
|
+
name: str
|
|
15
|
+
parent_id: int | None = None
|
|
16
|
+
parent_external_id: str | None = None
|
|
17
|
+
description: str | None = None
|
|
18
|
+
metadata: dict[str, str] | None = None
|
|
19
|
+
data_set_id: int | None = None
|
|
20
|
+
source: str | None = None
|
|
21
|
+
labels: list[dict[Literal["externalId"], str]] | None = None
|
|
22
|
+
geo_location: dict[str, JsonValue] | None = None
|
|
23
|
+
|
|
24
|
+
def as_id(self) -> ExternalId:
|
|
25
|
+
if self.external_id is None:
|
|
26
|
+
raise ValueError("Cannot convert AssetRequest to ExternalId when external_id is None")
|
|
27
|
+
return ExternalId(external_id=self.external_id)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AssetAggregateItem(BaseModelObject):
|
|
31
|
+
child_count: int
|
|
32
|
+
depth: int
|
|
33
|
+
path: list[dict[Literal["id"], int]]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class AssetResponse(ResponseResource[AssetRequest]):
|
|
37
|
+
created_time: int
|
|
38
|
+
last_updated_time: int
|
|
39
|
+
root_id: int
|
|
40
|
+
aggregates: AssetAggregateItem | None = None
|
|
41
|
+
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
|
+
|
|
53
|
+
def as_request_resource(self) -> AssetRequest:
|
|
54
|
+
return AssetRequest.model_validate(self.dump(), extra="ignore")
|
|
@@ -1,55 +1,150 @@
|
|
|
1
1
|
import sys
|
|
2
|
+
import types
|
|
2
3
|
from abc import ABC, abstractmethod
|
|
3
4
|
from collections import UserList
|
|
4
|
-
from typing import
|
|
5
|
+
from typing import Any, ClassVar, Generic, Literal, TypeVar, Union, get_args, get_origin
|
|
5
6
|
|
|
6
|
-
from
|
|
7
|
+
from cognite.client import CogniteClient
|
|
8
|
+
from pydantic import BaseModel, ConfigDict
|
|
7
9
|
from pydantic.alias_generators import to_camel
|
|
8
10
|
|
|
9
|
-
from cognite_toolkit._cdf_tk.utils.http_client._data_classes2 import BaseModelObject, RequestResource
|
|
10
|
-
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
from cognite.client import CogniteClient
|
|
13
|
-
|
|
14
11
|
if sys.version_info >= (3, 11):
|
|
15
12
|
from typing import Self
|
|
16
13
|
else:
|
|
17
14
|
from typing_extensions import Self
|
|
18
15
|
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
class BaseModelObject(BaseModel):
|
|
18
|
+
"""Base class for all object. This includes resources and nested objects."""
|
|
21
19
|
|
|
20
|
+
# We allow extra fields to support forward compatibility.
|
|
21
|
+
model_config = ConfigDict(alias_generator=to_camel, extra="allow")
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def as_request_resource(self) -> T_RequestResource:
|
|
26
|
-
"""Convert the response resource to a request resource."""
|
|
27
|
-
...
|
|
23
|
+
def dump(self, camel_case: bool = True) -> dict[str, Any]:
|
|
24
|
+
"""Dump the resource to a dictionary.
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
"""
|
|
31
|
-
return self.
|
|
26
|
+
This is the default serialization method for request resources.
|
|
27
|
+
"""
|
|
28
|
+
return self.model_dump(mode="json", by_alias=camel_case, exclude_unset=True)
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def _load(cls, resource: dict[str, Any]) -> Self:
|
|
32
|
+
"""Load method to match CogniteResource signature."""
|
|
33
|
+
return cls.model_validate(resource)
|
|
32
34
|
|
|
33
35
|
|
|
34
|
-
class Identifier(
|
|
35
|
-
"""Base class for all identifier
|
|
36
|
+
class Identifier(BaseModelObject):
|
|
37
|
+
"""Base class for all identifier objects typically
|
|
38
|
+
{"externalId": "..."}, {"id": ...}, {"space": "...", "externalId: }."""
|
|
36
39
|
|
|
37
40
|
model_config = ConfigDict(alias_generator=to_camel, extra="ignore", populate_by_name=True, frozen=True)
|
|
38
41
|
|
|
39
|
-
def dump(self, camel_case: bool = True
|
|
42
|
+
def dump(self, camel_case: bool = True) -> dict[str, Any]:
|
|
40
43
|
"""Dump the resource to a dictionary.
|
|
41
44
|
|
|
42
45
|
This is the default serialization method for request resources.
|
|
43
46
|
"""
|
|
44
|
-
return self.model_dump(mode="json", by_alias=camel_case, exclude_unset=
|
|
47
|
+
return self.model_dump(mode="json", by_alias=camel_case, exclude_unset=True)
|
|
48
|
+
|
|
49
|
+
def __str__(self) -> str:
|
|
50
|
+
raise NotImplementedError()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
T_Identifier = TypeVar("T_Identifier", bound=Identifier)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class RequestResource(BaseModelObject, ABC):
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def as_id(self) -> Identifier:
|
|
59
|
+
raise NotImplementedError()
|
|
60
|
+
|
|
61
|
+
def __str__(self) -> str:
|
|
62
|
+
return str(self.as_id())
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
T_RequestResource = TypeVar("T_RequestResource", bound=RequestResource)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class RequestUpdateable(RequestResource, ABC):
|
|
69
|
+
container_fields: ClassVar[frozenset[str]] = frozenset()
|
|
70
|
+
non_nullable_fields: ClassVar[frozenset[str]] = frozenset()
|
|
71
|
+
|
|
72
|
+
def as_update(self, mode: Literal["patch", "replace"]) -> dict[str, Any]:
|
|
73
|
+
"""Convert the request resource to an update item."""
|
|
74
|
+
update_item = self.as_id().dump(camel_case=True)
|
|
75
|
+
update: dict[str, Any] = {}
|
|
76
|
+
field_by_name = {info.alias or field_id: (field_id, info) for field_id, info in type(self).model_fields.items()}
|
|
77
|
+
# When mode is "patch", we only include fields that are set
|
|
78
|
+
exclude_unset = mode == "patch"
|
|
79
|
+
for key, value in self.model_dump(mode="json", by_alias=True, exclude_unset=exclude_unset).items():
|
|
80
|
+
if key in update_item:
|
|
81
|
+
# Skip identifier fields
|
|
82
|
+
continue
|
|
83
|
+
if key not in field_by_name:
|
|
84
|
+
# Skip unknown fields
|
|
85
|
+
continue
|
|
86
|
+
field_id, info = field_by_name[key]
|
|
87
|
+
if field_id in self.container_fields:
|
|
88
|
+
if mode == "patch":
|
|
89
|
+
update[key] = {"add": value}
|
|
90
|
+
elif mode == "replace":
|
|
91
|
+
if value is None:
|
|
92
|
+
origin = _get_annotation_origin(info.annotation)
|
|
93
|
+
if origin is list:
|
|
94
|
+
update[key] = {"set": []}
|
|
95
|
+
elif origin is dict:
|
|
96
|
+
update[key] = {"set": {}}
|
|
97
|
+
else:
|
|
98
|
+
raise NotImplementedError(
|
|
99
|
+
f'Cannot replace container field "{key}" with None when its type is unknown.'
|
|
100
|
+
)
|
|
101
|
+
else:
|
|
102
|
+
update[key] = {"set": value}
|
|
103
|
+
else:
|
|
104
|
+
raise NotImplementedError(f'Update mode "{mode}" is not supported for container fields.')
|
|
105
|
+
elif value is None:
|
|
106
|
+
if field_id not in self.non_nullable_fields:
|
|
107
|
+
update[key] = {"setNull": True}
|
|
108
|
+
else:
|
|
109
|
+
update[key] = {"set": value}
|
|
110
|
+
update_item["update"] = update
|
|
111
|
+
return update_item
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _get_annotation_origin(field_type: Any) -> Any:
|
|
115
|
+
origin = get_origin(field_type)
|
|
116
|
+
args = get_args(field_type)
|
|
117
|
+
|
|
118
|
+
# Check for Union type (both typing.Union and | syntax from Python 3.10+)
|
|
119
|
+
is_union = origin is Union or isinstance(field_type, getattr(types, "UnionType", ()))
|
|
120
|
+
|
|
121
|
+
if is_union:
|
|
122
|
+
# Handle Optional[T] by filtering out NoneType
|
|
123
|
+
none_types = (type(None), types.NoneType)
|
|
124
|
+
non_none_args = [arg for arg in args if arg not in none_types]
|
|
125
|
+
if len(non_none_args) == 1:
|
|
126
|
+
field_type = non_none_args[0]
|
|
127
|
+
origin = get_origin(field_type) or field_type
|
|
128
|
+
return origin
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class ResponseResource(BaseModelObject, Generic[T_RequestResource], ABC):
|
|
132
|
+
@abstractmethod
|
|
133
|
+
def as_request_resource(self) -> T_RequestResource:
|
|
134
|
+
"""Convert the response resource to a request resource."""
|
|
135
|
+
raise NotImplementedError()
|
|
136
|
+
|
|
137
|
+
def as_write(self) -> T_RequestResource:
|
|
138
|
+
"""Alias for as_request_resource to match protocol signature."""
|
|
139
|
+
return self.as_request_resource()
|
|
45
140
|
|
|
46
|
-
def as_id(self) -> Self:
|
|
47
|
-
return self
|
|
48
141
|
|
|
142
|
+
T_ResponseResource = TypeVar("T_ResponseResource", bound=ResponseResource)
|
|
49
143
|
|
|
50
144
|
T_Resource = TypeVar("T_Resource", bound=RequestResource | ResponseResource)
|
|
51
145
|
|
|
52
146
|
|
|
147
|
+
# Todo: Delete this class and use list[T_Resource] directly
|
|
53
148
|
class BaseResourceList(UserList[T_Resource]):
|
|
54
149
|
"""Base class for resource lists."""
|
|
55
150
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from cognite_toolkit._cdf_tk.client.data_classes.base import RequestResource, ResponseResource
|
|
2
|
+
|
|
3
|
+
from .identifiers import ExternalId, InternalOrExternalId
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class EventRequest(RequestResource):
|
|
7
|
+
external_id: str | None = None
|
|
8
|
+
data_set_id: int | None = None
|
|
9
|
+
start_time: int | None = None
|
|
10
|
+
end_time: int | None = None
|
|
11
|
+
type: str | None = None
|
|
12
|
+
subtype: str | None = None
|
|
13
|
+
description: str | None = None
|
|
14
|
+
metadata: dict[str, str] | None = None
|
|
15
|
+
asset_ids: list[int] | None = None
|
|
16
|
+
source: str | None = None
|
|
17
|
+
|
|
18
|
+
def as_id(self) -> InternalOrExternalId:
|
|
19
|
+
if self.external_id is None:
|
|
20
|
+
raise ValueError("Cannot convert EventRequest to ExternalId when external_id is None")
|
|
21
|
+
return ExternalId(external_id=self.external_id)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class EventResponse(ResponseResource[EventRequest]):
|
|
25
|
+
external_id: str | None = None
|
|
26
|
+
data_set_id: int | None = None
|
|
27
|
+
start_time: int | None = None
|
|
28
|
+
end_time: int | None = None
|
|
29
|
+
type: str | None = None
|
|
30
|
+
subtype: str | None = None
|
|
31
|
+
description: str | None = None
|
|
32
|
+
metadata: dict[str, str] | None = None
|
|
33
|
+
asset_ids: list[int] | None = None
|
|
34
|
+
source: str | None = None
|
|
35
|
+
id: int
|
|
36
|
+
created_time: int
|
|
37
|
+
last_updated_time: int
|
|
38
|
+
|
|
39
|
+
def as_request_resource(self) -> EventRequest:
|
|
40
|
+
return EventRequest.model_validate(self.dump())
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from typing import Annotated, Literal
|
|
3
|
+
|
|
4
|
+
from pydantic import Field
|
|
5
|
+
|
|
6
|
+
from cognite_toolkit._cdf_tk.client.data_classes.base import Identifier
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class InternalOrExternalIdDefinition(Identifier):
|
|
10
|
+
type: str
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class InternalId(InternalOrExternalIdDefinition):
|
|
14
|
+
type: Literal["id"] = Field("id", exclude=True)
|
|
15
|
+
id: int
|
|
16
|
+
|
|
17
|
+
@classmethod
|
|
18
|
+
def from_ids(cls, ids: Sequence[int]) -> list["InternalId"]:
|
|
19
|
+
return [cls(id=id_) for id_ in ids]
|
|
20
|
+
|
|
21
|
+
def __str__(self) -> str:
|
|
22
|
+
return f"id={self.id}"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ExternalId(InternalOrExternalIdDefinition):
|
|
26
|
+
type: Literal["externalId"] = Field("externalId", exclude=True)
|
|
27
|
+
external_id: str
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def from_external_ids(cls, external_ids: list[str]) -> list["ExternalId"]:
|
|
31
|
+
return [cls(external_id=ext_id) for ext_id in external_ids]
|
|
32
|
+
|
|
33
|
+
def __str__(self) -> str:
|
|
34
|
+
return f"externalId='{self.external_id}'"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
InternalOrExternalId = Annotated[InternalId | ExternalId, Field(discriminator="type")]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class NameId(Identifier):
|
|
41
|
+
name: str
|
|
42
|
+
|
|
43
|
+
def __str__(self) -> str:
|
|
44
|
+
return f"name='{self.name}'"
|
|
@@ -14,19 +14,38 @@ class TypedInstanceIdentifier(Identifier):
|
|
|
14
14
|
space: str
|
|
15
15
|
external_id: str
|
|
16
16
|
|
|
17
|
+
def __str__(self) -> str:
|
|
18
|
+
return f"Instance({self.instance_type}, {self.space}, {self.external_id})"
|
|
19
|
+
|
|
20
|
+
def dump(self, camel_case: bool = True, include_type: bool = True) -> dict[str, Any]:
|
|
21
|
+
"""Dump the resource to a dictionary.
|
|
22
|
+
|
|
23
|
+
This is the default serialization method for request resources.
|
|
24
|
+
"""
|
|
25
|
+
return self.model_dump(mode="json", by_alias=camel_case, exclude_unset=not include_type)
|
|
26
|
+
|
|
17
27
|
|
|
18
28
|
class TypedNodeIdentifier(TypedInstanceIdentifier):
|
|
19
29
|
instance_type: Literal["node"] = "node"
|
|
20
30
|
|
|
31
|
+
def __str__(self) -> str:
|
|
32
|
+
return f"Node({self.space}, {self.external_id})"
|
|
33
|
+
|
|
21
34
|
|
|
22
35
|
class TypedEdgeIdentifier(TypedInstanceIdentifier):
|
|
23
36
|
instance_type: Literal["edge"] = "edge"
|
|
24
37
|
|
|
38
|
+
def __str__(self) -> str:
|
|
39
|
+
return f"Edge({self.space}, {self.external_id})"
|
|
40
|
+
|
|
25
41
|
|
|
26
42
|
class InstanceIdentifier(Identifier):
|
|
27
43
|
space: str
|
|
28
44
|
external_id: str
|
|
29
45
|
|
|
46
|
+
def __str__(self) -> str:
|
|
47
|
+
return f"Instance({self.space}, {self.external_id})"
|
|
48
|
+
|
|
30
49
|
|
|
31
50
|
class InstanceResult(BaseModelObject):
|
|
32
51
|
instance_type: InstanceType
|
|
@@ -51,6 +70,16 @@ class ViewReference(Identifier):
|
|
|
51
70
|
external_id: str
|
|
52
71
|
version: str
|
|
53
72
|
|
|
73
|
+
def __str__(self) -> str:
|
|
74
|
+
return f"View({self.space}, {self.external_id}, v{self.version})"
|
|
75
|
+
|
|
76
|
+
def dump(self, camel_case: bool = True, include_type: bool = True) -> dict[str, Any]:
|
|
77
|
+
"""Dump the resource to a dictionary.
|
|
78
|
+
|
|
79
|
+
This is the default serialization method for request resources.
|
|
80
|
+
"""
|
|
81
|
+
return self.model_dump(mode="json", by_alias=camel_case, exclude_unset=not include_type)
|
|
82
|
+
|
|
54
83
|
|
|
55
84
|
######################################################
|
|
56
85
|
# The classes below are helper classes for making instances request/responses.
|
|
@@ -160,3 +189,8 @@ class InstanceResponseItem(BaseModelObject):
|
|
|
160
189
|
space=self.space,
|
|
161
190
|
external_id=self.external_id,
|
|
162
191
|
)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class NodeReference(BaseModelObject):
|
|
195
|
+
space: str
|
|
196
|
+
external_id: str
|
|
@@ -7,6 +7,7 @@ from cognite_toolkit._cdf_tk.protocols import (
|
|
|
7
7
|
)
|
|
8
8
|
|
|
9
9
|
from .base import BaseModelObject, BaseResourceList, RequestResource, ResponseResource
|
|
10
|
+
from .identifiers import ExternalId
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class StreamRequest(RequestResource):
|
|
@@ -15,8 +16,8 @@ class StreamRequest(RequestResource):
|
|
|
15
16
|
external_id: str
|
|
16
17
|
settings: dict[Literal["template"], dict[Literal["name"], StreamTemplateName]]
|
|
17
18
|
|
|
18
|
-
def as_id(self) ->
|
|
19
|
-
return self.external_id
|
|
19
|
+
def as_id(self) -> ExternalId:
|
|
20
|
+
return ExternalId(external_id=self.external_id)
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class StreamRequestList(BaseResourceList[StreamRequest], ResourceRequestListProtocol):
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import sys
|
|
2
2
|
from typing import Literal
|
|
3
3
|
|
|
4
4
|
from pydantic import Field
|
|
5
5
|
|
|
6
|
-
from .base import BaseModelObject, RequestResource, ResponseResource
|
|
6
|
+
from .base import BaseModelObject, Identifier, RequestResource, ResponseResource
|
|
7
|
+
from .identifiers import NameId
|
|
8
|
+
from .instance_api import NodeReference
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
if sys.version_info >= (3, 11):
|
|
11
|
+
from typing import Self
|
|
12
|
+
else:
|
|
13
|
+
from typing_extensions import Self
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class RevisionStatus(BaseModelObject):
|
|
@@ -22,17 +24,14 @@ class RevisionStatus(BaseModelObject):
|
|
|
22
24
|
class ThreeDModelRequest(RequestResource):
|
|
23
25
|
name: str
|
|
24
26
|
|
|
25
|
-
def as_id(self) ->
|
|
26
|
-
return self.name
|
|
27
|
+
def as_id(self) -> NameId:
|
|
28
|
+
return NameId(name=self.name)
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
class ThreeDModelClassicRequest(ThreeDModelRequest):
|
|
30
32
|
data_set_id: int | None = None
|
|
31
33
|
metadata: dict[str, str] | None = None
|
|
32
34
|
|
|
33
|
-
def as_id(self) -> str:
|
|
34
|
-
return self.name
|
|
35
|
-
|
|
36
35
|
|
|
37
36
|
class ThreeDModelDMSRequest(ThreeDModelRequest):
|
|
38
37
|
space: str
|
|
@@ -56,24 +55,21 @@ class ThreeDModelResponse(ResponseResource[ThreeDModelRequest]):
|
|
|
56
55
|
return ThreeDModelDMSRequest._load(self.dump())
|
|
57
56
|
|
|
58
57
|
|
|
59
|
-
class AssetMappingDMRequest(RequestResource):
|
|
58
|
+
class AssetMappingDMRequest(RequestResource, Identifier):
|
|
60
59
|
node_id: int
|
|
61
60
|
asset_instance_id: NodeReference
|
|
62
61
|
# These fields are part of the path request and not the body schema.
|
|
63
62
|
model_id: int = Field(exclude=True)
|
|
64
63
|
revision_id: int = Field(exclude=True)
|
|
65
64
|
|
|
66
|
-
def as_id(self) ->
|
|
67
|
-
return
|
|
68
|
-
self.model_id,
|
|
69
|
-
self.revision_id,
|
|
70
|
-
self.node_id,
|
|
71
|
-
self.asset_instance_id.space,
|
|
72
|
-
self.asset_instance_id.external_id,
|
|
73
|
-
)
|
|
65
|
+
def as_id(self) -> Self:
|
|
66
|
+
return self
|
|
74
67
|
|
|
68
|
+
def __str__(self) -> str:
|
|
69
|
+
return f"{self.model_id}_{self.revision_id}_{self.node_id}_{self.asset_instance_id.space}_{self.asset_instance_id.external_id}"
|
|
75
70
|
|
|
76
|
-
|
|
71
|
+
|
|
72
|
+
class AssetMappingClassicRequest(RequestResource, Identifier):
|
|
77
73
|
node_id: int
|
|
78
74
|
asset_id: int | None = None
|
|
79
75
|
asset_instance_id: NodeReference | None = None
|
|
@@ -81,19 +77,18 @@ class AssetMappingClassicRequest(RequestResource):
|
|
|
81
77
|
model_id: int = Field(exclude=True)
|
|
82
78
|
revision_id: int = Field(exclude=True)
|
|
83
79
|
|
|
84
|
-
def as_id(self) ->
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
raise AttributeError("asset_id or asset_instance_id is required")
|
|
80
|
+
def as_id(self) -> Self:
|
|
81
|
+
return self
|
|
82
|
+
|
|
83
|
+
def __str__(self) -> str:
|
|
84
|
+
asset_part = (
|
|
85
|
+
f"assetId:{self.asset_id}"
|
|
86
|
+
if self.asset_id is not None
|
|
87
|
+
else f"assetInstance:{self.asset_instance_id.space}_{self.asset_instance_id.external_id}"
|
|
88
|
+
if self.asset_instance_id is not None
|
|
89
|
+
else "noAsset"
|
|
90
|
+
)
|
|
91
|
+
return f"{self.model_id}_{self.revision_id}_{self.node_id}_{asset_part}"
|
|
97
92
|
|
|
98
93
|
|
|
99
94
|
class AssetMappingResponse(ResponseResource[AssetMappingClassicRequest]):
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from cognite_toolkit._cdf_tk.client.data_classes.base import RequestResource, ResponseResource
|
|
2
|
+
|
|
3
|
+
from .identifiers import ExternalId, InternalOrExternalId
|
|
4
|
+
from .instance_api import NodeReference
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TimeSeriesRequest(RequestResource):
|
|
8
|
+
external_id: str | None = None
|
|
9
|
+
name: str | None = None
|
|
10
|
+
is_sting: bool = False
|
|
11
|
+
metadata: dict[str, str] | None = None
|
|
12
|
+
unit: str | None = None
|
|
13
|
+
unit_external_id: str | None = None
|
|
14
|
+
asset_id: int | None = None
|
|
15
|
+
is_step: bool = False
|
|
16
|
+
description: str | None = None
|
|
17
|
+
security_categories: list[int] | None = None
|
|
18
|
+
data_set_id: int | None = None
|
|
19
|
+
|
|
20
|
+
def as_id(self) -> InternalOrExternalId:
|
|
21
|
+
if self.external_id is None:
|
|
22
|
+
raise ValueError("Cannot convert TimeSeriesRequest to ExternalId when external_id is None")
|
|
23
|
+
return ExternalId(external_id=self.external_id)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class TimeSeriesResponse(ResponseResource[TimeSeriesRequest]):
|
|
27
|
+
id: int
|
|
28
|
+
instance_id: NodeReference | None = None
|
|
29
|
+
external_id: str | None = None
|
|
30
|
+
name: str | None = None
|
|
31
|
+
is_sting: bool
|
|
32
|
+
metadata: dict[str, str] | None = None
|
|
33
|
+
unit: str | None = None
|
|
34
|
+
type: str
|
|
35
|
+
unit_external_id: str | None = None
|
|
36
|
+
asset_id: int | None = None
|
|
37
|
+
is_step: bool
|
|
38
|
+
description: str | None = None
|
|
39
|
+
security_categories: list[int] | None = None
|
|
40
|
+
data_set_id: int | None = None
|
|
41
|
+
created_time: int
|
|
42
|
+
last_updated_time: int
|
|
43
|
+
|
|
44
|
+
def as_request_resource(self) -> TimeSeriesRequest:
|
|
45
|
+
return TimeSeriesRequest.model_validate(self.dump())
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from ._client import HTTPClient
|
|
2
2
|
from ._data_classes import (
|
|
3
|
+
T_COVARIANT_ID,
|
|
3
4
|
DataBodyRequest,
|
|
4
5
|
ErrorDetails,
|
|
5
6
|
FailedRequestItems,
|
|
@@ -10,6 +11,7 @@ from ._data_classes import (
|
|
|
10
11
|
ItemMessage,
|
|
11
12
|
ItemsRequest,
|
|
12
13
|
ParamRequest,
|
|
14
|
+
RequestItem,
|
|
13
15
|
RequestMessage,
|
|
14
16
|
ResponseList,
|
|
15
17
|
ResponseMessage,
|
|
@@ -18,7 +20,6 @@ from ._data_classes import (
|
|
|
18
20
|
SuccessResponseItems,
|
|
19
21
|
)
|
|
20
22
|
from ._data_classes2 import (
|
|
21
|
-
BaseModelObject,
|
|
22
23
|
ErrorDetails2,
|
|
23
24
|
FailedRequest2,
|
|
24
25
|
FailedResponse2,
|
|
@@ -29,13 +30,12 @@ from ._data_classes2 import (
|
|
|
29
30
|
ItemsResultMessage2,
|
|
30
31
|
ItemsSuccessResponse2,
|
|
31
32
|
RequestMessage2,
|
|
32
|
-
RequestResource,
|
|
33
33
|
SuccessResponse2,
|
|
34
34
|
)
|
|
35
35
|
from ._exception import ToolkitAPIError
|
|
36
36
|
|
|
37
37
|
__all__ = [
|
|
38
|
-
"
|
|
38
|
+
"T_COVARIANT_ID",
|
|
39
39
|
"DataBodyRequest",
|
|
40
40
|
"ErrorDetails",
|
|
41
41
|
"ErrorDetails2",
|
|
@@ -56,9 +56,9 @@ __all__ = [
|
|
|
56
56
|
"ItemsResultMessage2",
|
|
57
57
|
"ItemsSuccessResponse2",
|
|
58
58
|
"ParamRequest",
|
|
59
|
+
"RequestItem",
|
|
59
60
|
"RequestMessage",
|
|
60
61
|
"RequestMessage2",
|
|
61
|
-
"RequestResource",
|
|
62
62
|
"ResponseList",
|
|
63
63
|
"ResponseMessage",
|
|
64
64
|
"SimpleBodyRequest",
|
|
@@ -10,9 +10,7 @@ import httpx
|
|
|
10
10
|
from cognite.client import global_config
|
|
11
11
|
from rich.console import Console
|
|
12
12
|
|
|
13
|
-
from cognite_toolkit._cdf_tk.
|
|
14
|
-
from cognite_toolkit._cdf_tk.utils.auxiliary import get_current_toolkit_version, get_user_agent
|
|
15
|
-
from cognite_toolkit._cdf_tk.utils.http_client._data_classes import (
|
|
13
|
+
from cognite_toolkit._cdf_tk.client.http_client._data_classes import (
|
|
16
14
|
BodyRequest,
|
|
17
15
|
DataBodyRequest,
|
|
18
16
|
FailedRequestMessage,
|
|
@@ -23,7 +21,7 @@ from cognite_toolkit._cdf_tk.utils.http_client._data_classes import (
|
|
|
23
21
|
ResponseList,
|
|
24
22
|
ResponseMessage,
|
|
25
23
|
)
|
|
26
|
-
from cognite_toolkit._cdf_tk.
|
|
24
|
+
from cognite_toolkit._cdf_tk.client.http_client._data_classes2 import (
|
|
27
25
|
BaseRequestMessage,
|
|
28
26
|
ErrorDetails2,
|
|
29
27
|
FailedRequest2,
|
|
@@ -38,6 +36,8 @@ from cognite_toolkit._cdf_tk.utils.http_client._data_classes2 import (
|
|
|
38
36
|
RequestMessage2,
|
|
39
37
|
SuccessResponse2,
|
|
40
38
|
)
|
|
39
|
+
from cognite_toolkit._cdf_tk.tk_warnings import HighSeverityWarning
|
|
40
|
+
from cognite_toolkit._cdf_tk.utils.auxiliary import get_current_toolkit_version, get_user_agent
|
|
41
41
|
from cognite_toolkit._cdf_tk.utils.useful_types import PrimitiveType
|
|
42
42
|
|
|
43
43
|
if sys.version_info >= (3, 11):
|
|
@@ -414,7 +414,7 @@ class HTTPClient:
|
|
|
414
414
|
if message.tracker and message.tracker.limit_reached():
|
|
415
415
|
return [
|
|
416
416
|
ItemsFailedRequest2(
|
|
417
|
-
ids=[item
|
|
417
|
+
ids=[str(item) for item in message.items],
|
|
418
418
|
error_message=f"Aborting further splitting of requests after {message.tracker.failed_split_count} failed attempts.",
|
|
419
419
|
)
|
|
420
420
|
]
|
|
@@ -464,7 +464,7 @@ class HTTPClient:
|
|
|
464
464
|
if 200 <= response.status_code < 300:
|
|
465
465
|
return [
|
|
466
466
|
ItemsSuccessResponse2(
|
|
467
|
-
ids=[item
|
|
467
|
+
ids=[str(item) for item in request.items],
|
|
468
468
|
status_code=response.status_code,
|
|
469
469
|
body=response.text,
|
|
470
470
|
content=response.content,
|
|
@@ -480,7 +480,7 @@ class HTTPClient:
|
|
|
480
480
|
if splits[0].tracker and splits[0].tracker.limit_reached():
|
|
481
481
|
return [
|
|
482
482
|
ItemsFailedResponse2(
|
|
483
|
-
ids=[item
|
|
483
|
+
ids=[str(item) for item in request.items],
|
|
484
484
|
status_code=response.status_code,
|
|
485
485
|
body=response.text,
|
|
486
486
|
error=ErrorDetails2.from_response(response),
|
|
@@ -494,7 +494,7 @@ class HTTPClient:
|
|
|
494
494
|
# Permanent failure
|
|
495
495
|
return [
|
|
496
496
|
ItemsFailedResponse2(
|
|
497
|
-
ids=[item
|
|
497
|
+
ids=[str(item) for item in request.items],
|
|
498
498
|
status_code=response.status_code,
|
|
499
499
|
body=response.text,
|
|
500
500
|
error=ErrorDetails2.from_response(response),
|
|
@@ -516,7 +516,7 @@ class HTTPClient:
|
|
|
516
516
|
error_msg = f"Unexpected exception: {e!s}"
|
|
517
517
|
return [
|
|
518
518
|
ItemsFailedRequest2(
|
|
519
|
-
ids=[item
|
|
519
|
+
ids=[str(item) for item in request.items],
|
|
520
520
|
error_message=error_msg,
|
|
521
521
|
)
|
|
522
522
|
]
|
|
@@ -530,7 +530,7 @@ class HTTPClient:
|
|
|
530
530
|
|
|
531
531
|
return [
|
|
532
532
|
ItemsFailedRequest2(
|
|
533
|
-
ids=[item
|
|
533
|
+
ids=[str(item) for item in request.items],
|
|
534
534
|
error_message=error_msg,
|
|
535
535
|
)
|
|
536
536
|
]
|