cognite-toolkit 0.5.63__py3-none-any.whl → 0.5.64__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.
@@ -4,7 +4,7 @@ default_env = "<DEFAULT_ENV_PLACEHOLDER>"
4
4
  [modules]
5
5
  # This is the version of the modules. It should not be changed manually.
6
6
  # It will be updated by the 'cdf modules upgrade' command.
7
- version = "0.5.63"
7
+ version = "0.5.64"
8
8
 
9
9
 
10
10
  [plugins]
@@ -46,6 +46,7 @@ from cognite_toolkit._cdf_tk.utils import (
46
46
  calculate_secure_hash,
47
47
  )
48
48
  from cognite_toolkit._cdf_tk.utils.cdf import read_auth, try_find_error
49
+ from cognite_toolkit._cdf_tk.utils.text import suffix_description
49
50
 
50
51
  from .auth_loaders import GroupAllScopedLoader
51
52
  from .data_organization_loaders import DataSetsLoader
@@ -464,20 +465,15 @@ class FunctionScheduleLoader(
464
465
  )
465
466
  self.authentication_by_id[identifier] = credentials
466
467
  auth_hash = calculate_secure_hash(credentials.dump(camel_case=True), shorten=True)
467
- extra_str = f" {self._hash_key}: {auth_hash}"
468
- if "description" not in resource:
469
- resource["description"] = extra_str[1:]
470
- elif resource["description"].endswith(extra_str[1:]):
471
- # The hash is already in the description
472
- ...
473
- elif len(resource["description"]) + len(extra_str) < self._description_character_limit:
474
- resource["description"] += f"{extra_str}"
475
- else:
476
- LowSeverityWarning(f"Description is too long for schedule {identifier!r}. Truncating...").print_warning(
477
- console=self.console
478
- )
479
- truncation = self._description_character_limit - len(extra_str) - 3
480
- resource["description"] = f"{resource['description'][:truncation]}...{extra_str}"
468
+ extra_str = f"{self._hash_key}: {auth_hash}"
469
+ resource["description"] = suffix_description(
470
+ extra_str,
471
+ resource.get("description"),
472
+ self._description_character_limit,
473
+ self.get_id(resource),
474
+ self.display_name,
475
+ self.console,
476
+ )
481
477
  return resources
482
478
 
483
479
  def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) -> FunctionScheduleWrite:
@@ -1,5 +1,7 @@
1
+ import json
1
2
  from collections.abc import Hashable, Iterable, Sequence
2
3
  from functools import lru_cache
4
+ from pathlib import Path
3
5
  from typing import Any, cast, final
4
6
 
5
7
  from cognite.client.data_classes import (
@@ -28,7 +30,9 @@ from cognite_toolkit._cdf_tk.exceptions import (
28
30
  )
29
31
  from cognite_toolkit._cdf_tk.loaders._base_loaders import ResourceContainerLoader, ResourceLoader
30
32
  from cognite_toolkit._cdf_tk.resource_classes import TimeSeriesYAML
33
+ from cognite_toolkit._cdf_tk.utils import calculate_hash
31
34
  from cognite_toolkit._cdf_tk.utils.diff_list import diff_list_hashable, diff_list_identifiable, dm_identifier
35
+ from cognite_toolkit._cdf_tk.utils.text import suffix_description
32
36
 
33
37
  from .auth_loaders import GroupAllScopedLoader, SecurityCategoryLoader
34
38
  from .classic_loaders import AssetLoader
@@ -216,6 +220,9 @@ class DatapointSubscriptionLoader(
216
220
  }
217
221
  )
218
222
 
223
+ _hash_key = "cdf-hash"
224
+ _description_character_limit = 1000
225
+
219
226
  @property
220
227
  def display_name(self) -> str:
221
228
  return "timeseries subscriptions"
@@ -325,25 +332,58 @@ class DatapointSubscriptionLoader(
325
332
  ) -> Iterable[DatapointSubscription]:
326
333
  return iter(self.client.time_series.subscriptions)
327
334
 
335
+ def load_resource_file(
336
+ self, filepath: Path, environment_variables: dict[str, str | None] | None = None
337
+ ) -> list[dict[str, Any]]:
338
+ resources = super().load_resource_file(filepath, environment_variables)
339
+ for resource in resources:
340
+ if "timeSeriesIds" not in resource and "instanceIds" not in resource:
341
+ continue
342
+ # If the timeSeriesIds or instanceIds is set, we need to add the auth hash to the description.
343
+ # such that we can detect if the subscription has changed.
344
+ content: dict[str, object] = {}
345
+ if "timeSeriesIds" in resource:
346
+ content["timeSeriesIds"] = resource["timeSeriesIds"]
347
+ if "instanceIds" in resource:
348
+ content["instanceIds"] = resource["instanceIds"]
349
+ timeseries_hash = calculate_hash(json.dumps(content), shorten=True)
350
+ extra_str = f"{self._hash_key}: {timeseries_hash}"
351
+ resource["description"] = suffix_description(
352
+ extra_str,
353
+ resource.get("description"),
354
+ self._description_character_limit,
355
+ self.get_id(resource),
356
+ self.display_name,
357
+ self.console,
358
+ )
359
+
360
+ return resources
361
+
328
362
  def load_resource(self, resource: dict[str, Any], is_dry_run: bool = False) -> DataPointSubscriptionWrite:
329
363
  if ds_external_id := resource.pop("dataSetExternalId", None):
330
364
  resource["dataSetId"] = self.client.lookup.data_sets.id(ds_external_id, is_dry_run)
331
365
  return DataPointSubscriptionWrite._load(resource)
332
366
 
333
367
  def dump_resource(self, resource: DatapointSubscription, local: dict[str, Any] | None = None) -> dict[str, Any]:
334
- dumped = resource.as_write().dump()
368
+ if resource.filter is not None:
369
+ dumped = resource.as_write().dump()
370
+ else:
371
+ # If filter is not set, the subscription uses explicit timeSeriesIds, which are not returned in the
372
+ # response. Calling .as_write() in this case raises ValueError because either filter or
373
+ # timeSeriesIds must be set.
374
+ dumped = resource.dump()
375
+ for server_prop in ("createdTime", "lastUpdatedTime", "timeSeriesCount"):
376
+ dumped.pop(server_prop, None)
335
377
  local = local or {}
336
378
  if data_set_id := dumped.pop("dataSetId", None):
337
379
  dumped["dataSetExternalId"] = self.client.lookup.data_sets.external_id(data_set_id)
338
- if "timeSeriesIds" not in dumped:
339
- return dumped
340
- # Sorting the timeSeriesIds in the local order
341
- # Sorting in the same order as the local file.
342
- ts_order_by_id = {ts_id: no for no, ts_id in enumerate(local.get("timeSeriesIds", []))}
343
- end_of_list = len(ts_order_by_id)
344
- dumped["timeSeriesIds"] = sorted(
345
- dumped["timeSeriesIds"], key=lambda ts_id: ts_order_by_id.get(ts_id, end_of_list)
346
- )
380
+ # timeSeriesIds and instanceIds are not returned in the response, so we need to add them
381
+ # to the dumped resource if they are set in the local resource. If there is a discrepancy between
382
+ # the local and dumped resource, th hash added to the description will change.
383
+ if "timeSeriesIds" in local:
384
+ dumped["timeSeriesIds"] = local["timeSeriesIds"]
385
+ if "instanceIds" in local:
386
+ dumped["instanceIds"] = local["instanceIds"]
347
387
  return dumped
348
388
 
349
389
  def diff_list(
@@ -0,0 +1,42 @@
1
+ from collections.abc import Hashable
2
+
3
+ from rich.console import Console
4
+
5
+ from cognite_toolkit._cdf_tk.tk_warnings import LowSeverityWarning
6
+
7
+
8
+ def suffix_description(
9
+ suffix: str,
10
+ description: str | None,
11
+ description_character_limit: int,
12
+ identifier: Hashable,
13
+ resource_type: str,
14
+ console: Console | None = None,
15
+ ) -> str:
16
+ """Appends a suffix to a description if it is not already present.
17
+ If the description is too long after appending the suffix, it will be truncated to fit within the character limit.
18
+
19
+ Args:
20
+ suffix: The suffix to append to the description.
21
+ description: The original description to which the suffix will be appended.
22
+ description_character_limit: The maximum number of characters allowed in the description after appending the suffix.
23
+ identifier: Hashable identifier for the resource, used in warnings.
24
+ resource_type: Type of the resource, used in warnings.
25
+ console: Console object for printing warnings.
26
+
27
+ Returns:
28
+ str: The modified description with the suffix appended, or truncated if necessary.
29
+ """
30
+ if description is None or description == "":
31
+ return suffix
32
+ elif description.endswith(suffix):
33
+ # The suffix is already in the description
34
+ return description
35
+ elif len(description) + len(suffix) + 1 < description_character_limit:
36
+ return f"{description} {suffix}"
37
+ else:
38
+ LowSeverityWarning(f"Description is too long for {resource_type} {identifier!r}. Truncating...").print_warning(
39
+ console=console
40
+ )
41
+ truncation = description_character_limit - len(suffix) - 3
42
+ return f"{description[:truncation]}...{suffix}"
@@ -12,7 +12,7 @@ jobs:
12
12
  environment: dev
13
13
  name: Deploy
14
14
  container:
15
- image: cognite/toolkit:0.5.63
15
+ image: cognite/toolkit:0.5.64
16
16
  env:
17
17
  CDF_CLUSTER: ${{ vars.CDF_CLUSTER }}
18
18
  CDF_PROJECT: ${{ vars.CDF_PROJECT }}
@@ -10,7 +10,7 @@ jobs:
10
10
  environment: dev
11
11
  name: Deploy Dry Run
12
12
  container:
13
- image: cognite/toolkit:0.5.63
13
+ image: cognite/toolkit:0.5.64
14
14
  env:
15
15
  CDF_CLUSTER: ${{ vars.CDF_CLUSTER }}
16
16
  CDF_PROJECT: ${{ vars.CDF_PROJECT }}
@@ -1 +1 @@
1
- __version__ = "0.5.63"
1
+ __version__ = "0.5.64"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cognite_toolkit
3
- Version: 0.5.63
3
+ Version: 0.5.64
4
4
  Summary: Official Cognite Data Fusion tool for project templates and configuration deployment
5
5
  Project-URL: Homepage, https://docs.cognite.com/cdf/deploy/cdf_toolkit/
6
6
  Project-URL: Changelog, https://github.com/cognitedata/toolkit/releases
@@ -1,10 +1,10 @@
1
1
  cognite_toolkit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  cognite_toolkit/_cdf.py,sha256=WWMslI-y2VbIYDMH19wnINebGwlOvAeYr-qkPRC1f68,5834
3
- cognite_toolkit/_version.py,sha256=NZyB_3d5nSrSdmUTR1qURqDAEzDzElqs5VAFoKfX_F8,23
3
+ cognite_toolkit/_version.py,sha256=YmQRiPOhelComYapMsMGUkwpYKgzkePjx8U_IXrWTZ4,23
4
4
  cognite_toolkit/config.dev.yaml,sha256=CIDmi1OGNOJ-70h2BNCozZRmhvU5BfpZoh6Q04b8iMs,109
5
5
  cognite_toolkit/_builtin_modules/README.md,sha256=roU3G05E6ogP5yhw4hdIvVDKV831zCh2pzt9BVddtBg,307
6
6
  cognite_toolkit/_builtin_modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- cognite_toolkit/_builtin_modules/cdf.toml,sha256=kjIlSaM6fJ5C09gRiWydBtFY7C2IuoHBUMue1zv7y_I,273
7
+ cognite_toolkit/_builtin_modules/cdf.toml,sha256=cNxARlcrmEJ3CEAaRbEy-M9jxKukb_uZ6slnSAO2hI4,273
8
8
  cognite_toolkit/_builtin_modules/packages.toml,sha256=RdY44Sxvh6sUtAkgp1dHID1mtqkOTzP_rbZL2Q27fYw,1147
9
9
  cognite_toolkit/_builtin_modules/bootcamp/README.md,sha256=iTVqoy3PLpC-xPi5pbuMIAEHILBSfWTGLexwa1AltpY,211
10
10
  cognite_toolkit/_builtin_modules/bootcamp/default.config.yaml,sha256=MqYTcRiz03bow4LT8E3jumnd_BsqC5SvjgYOVVkHGE0,93
@@ -615,7 +615,7 @@ cognite_toolkit/_cdf_tk/loaders/_resource_loaders/datamodel_loaders.py,sha256=xK
615
615
  cognite_toolkit/_cdf_tk/loaders/_resource_loaders/extraction_pipeline_loaders.py,sha256=zqNPiIX1xvYV8alpxPKMqyy4QlH6oqDYNtrITC7ZKdo,18188
616
616
  cognite_toolkit/_cdf_tk/loaders/_resource_loaders/fieldops_loaders.py,sha256=pzjOjnxaJRXId-b0GZ31a6Mab8BdNnKXx3zUiBaxB0E,12203
617
617
  cognite_toolkit/_cdf_tk/loaders/_resource_loaders/file_loader.py,sha256=49uHmkYA5dzL7fyXYRIeZCkYnB5laclO-6Pis_qhVes,17633
618
- cognite_toolkit/_cdf_tk/loaders/_resource_loaders/function_loaders.py,sha256=tO5i_xf1MBt_eQ6VUFJi6VZvusq16Xr33zqirp-Jers,26356
618
+ cognite_toolkit/_cdf_tk/loaders/_resource_loaders/function_loaders.py,sha256=5_p3G0Kuz08saJs_4T6hD26BwHsVvvFG20IhAPZlZbw,25937
619
619
  cognite_toolkit/_cdf_tk/loaders/_resource_loaders/group_scoped_loader.py,sha256=Rerw0Y6tY6Nle3vmyl4nhX5lRsVkUVcnp39qZ3R_tDs,1830
620
620
  cognite_toolkit/_cdf_tk/loaders/_resource_loaders/hosted_extractors.py,sha256=lZuq_dj7_r0O3BcM6xnAenAXAtcJ3ke_LO1IguRKCiE,17527
621
621
  cognite_toolkit/_cdf_tk/loaders/_resource_loaders/industrial_tool_loaders.py,sha256=j1FsynrFk_iPIAsHuqjXmtbMM7ZM6RVlpQkxCH9ATO0,8493
@@ -624,7 +624,7 @@ cognite_toolkit/_cdf_tk/loaders/_resource_loaders/raw_loaders.py,sha256=RM-zxDX6
624
624
  cognite_toolkit/_cdf_tk/loaders/_resource_loaders/relationship_loader.py,sha256=KRWGHk11vRWhFiQUF0vChv95ElGY-E_VGQNCHkuY5Y4,7219
625
625
  cognite_toolkit/_cdf_tk/loaders/_resource_loaders/robotics_loaders.py,sha256=tgPdVA4B8gNfHeHlEMzDgBaWs2jj-FSZAm1O1r5Uzrc,17224
626
626
  cognite_toolkit/_cdf_tk/loaders/_resource_loaders/three_d_model_loaders.py,sha256=IcnZ9wyW6Dpl83nlOdAM44UyrMfgum2hLdqi1u2AEuw,8288
627
- cognite_toolkit/_cdf_tk/loaders/_resource_loaders/timeseries_loaders.py,sha256=Xy6Wu4JU4kDVCbiVV3Y0GXBcix6Y-snLDwtj6g33vow,15281
627
+ cognite_toolkit/_cdf_tk/loaders/_resource_loaders/timeseries_loaders.py,sha256=PU2gRi-9EQKooZ8BLpKnQOtg3lNQ0lRBW0C26BU8r_0,17288
628
628
  cognite_toolkit/_cdf_tk/loaders/_resource_loaders/transformation_loaders.py,sha256=D0iD7jWPetiUM35JKQ1M_By086k4n5co9RaA8-VfF_A,35304
629
629
  cognite_toolkit/_cdf_tk/loaders/_resource_loaders/workflow_loaders.py,sha256=KmqDOIg6ttVqL_7widJgW5rNjs4eipd28AcLDs_bwDc,28427
630
630
  cognite_toolkit/_cdf_tk/prototypes/import_app.py,sha256=7dy852cBlHI2RQF1MidSmxl0jPBxekGWXnd2VtI7QFI,1899
@@ -693,17 +693,18 @@ cognite_toolkit/_cdf_tk/utils/sentry_utils.py,sha256=YWQdsePeFpT214-T-tZ8kEsUyC8
693
693
  cognite_toolkit/_cdf_tk/utils/sql_parser.py,sha256=RhUPWjVjwb9RBv1fixmG7bKvAb4JT_CC0O7Aqnx5Pgg,6196
694
694
  cognite_toolkit/_cdf_tk/utils/table_writers.py,sha256=wEBVlfCFv5bLLy836UiXQubwSxo8kUlSFZeQxnHrTX4,17932
695
695
  cognite_toolkit/_cdf_tk/utils/tarjan.py,sha256=mr3gMzlrkDadn1v7u7-Uzao81KKiM3xfXlZ185HL__A,1359
696
+ cognite_toolkit/_cdf_tk/utils/text.py,sha256=gBl3o60dXRlEBsg8izdnOmuLo86jr35pQFZcxnKdNSY,1715
696
697
  cognite_toolkit/_repo_files/.env.tmpl,sha256=UmgKZVvIp-OzD8oOcYuwb_6c7vSJsqkLhuFaiVgK7RI,972
697
698
  cognite_toolkit/_repo_files/.gitignore,sha256=3exydcQPCJTldGFJoZy1RPHc1horbAprAoaShU8sYnM,5262
698
699
  cognite_toolkit/_repo_files/AzureDevOps/.devops/README.md,sha256=OLA0D7yCX2tACpzvkA0IfkgQ4_swSd-OlJ1tYcTBpsA,240
699
700
  cognite_toolkit/_repo_files/AzureDevOps/.devops/deploy-pipeline.yml,sha256=KVBxW8urCRDtVlJ6HN-kYmw0NCpW6c4lD-nlxz9tZsQ,692
700
701
  cognite_toolkit/_repo_files/AzureDevOps/.devops/dry-run-pipeline.yml,sha256=Cp4KYraeWPjP8SnnEIbJoJnjmrRUwc982DPjOOzy2iM,722
701
- cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml,sha256=kPSbNvw3tI5xsGHKjUDkCMebY6HuTTMwJk7Q3yR7EB4,667
702
- cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml,sha256=_5mG5DphhCXHAScbPTnIaTkJ9tYTSKtyXVlO6aeQyQo,2430
702
+ cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml,sha256=lxYJqdd3aR0ZHU-Xwf4r0tk8vh_yDZABoLHYozuJatA,667
703
+ cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml,sha256=pJjrtZvQ_1iIuKom7FAAGa4QxiwRwTSifrdNON5oLMs,2430
703
704
  cognite_toolkit/demo/__init__.py,sha256=-m1JoUiwRhNCL18eJ6t7fZOL7RPfowhCuqhYFtLgrss,72
704
705
  cognite_toolkit/demo/_base.py,sha256=63nWYI_MHU5EuPwEX_inEAQxxiD5P6k8IAmlgl4CxpE,8082
705
- cognite_toolkit-0.5.63.dist-info/METADATA,sha256=o1oTTOVyWL8Lzlm-3ho6SMvBuN57paaH0UJJmfdRSeQ,4410
706
- cognite_toolkit-0.5.63.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
707
- cognite_toolkit-0.5.63.dist-info/entry_points.txt,sha256=JlR7MH1_UMogC3QOyN4-1l36VbrCX9xUdQoHGkuJ6-4,83
708
- cognite_toolkit-0.5.63.dist-info/licenses/LICENSE,sha256=CW0DRcx5tL-pCxLEN7ts2S9g2sLRAsWgHVEX4SN9_Mc,752
709
- cognite_toolkit-0.5.63.dist-info/RECORD,,
706
+ cognite_toolkit-0.5.64.dist-info/METADATA,sha256=PulESZBXZQdjGl-QJlNBp0VFkJ6HgMlHjxKykzoREu8,4410
707
+ cognite_toolkit-0.5.64.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
708
+ cognite_toolkit-0.5.64.dist-info/entry_points.txt,sha256=JlR7MH1_UMogC3QOyN4-1l36VbrCX9xUdQoHGkuJ6-4,83
709
+ cognite_toolkit-0.5.64.dist-info/licenses/LICENSE,sha256=CW0DRcx5tL-pCxLEN7ts2S9g2sLRAsWgHVEX4SN9_Mc,752
710
+ cognite_toolkit-0.5.64.dist-info/RECORD,,