cognite-toolkit 0.6.97__py3-none-any.whl → 0.7.30__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 (136) hide show
  1. cognite_toolkit/_cdf.py +16 -17
  2. cognite_toolkit/_cdf_tk/apps/__init__.py +2 -0
  3. cognite_toolkit/_cdf_tk/apps/_core_app.py +13 -5
  4. cognite_toolkit/_cdf_tk/apps/_data_app.py +1 -1
  5. cognite_toolkit/_cdf_tk/apps/_dev_app.py +86 -0
  6. cognite_toolkit/_cdf_tk/apps/_download_app.py +692 -24
  7. cognite_toolkit/_cdf_tk/apps/_dump_app.py +43 -101
  8. cognite_toolkit/_cdf_tk/apps/_landing_app.py +18 -4
  9. cognite_toolkit/_cdf_tk/apps/_migrate_app.py +249 -9
  10. cognite_toolkit/_cdf_tk/apps/_modules_app.py +0 -3
  11. cognite_toolkit/_cdf_tk/apps/_purge.py +15 -43
  12. cognite_toolkit/_cdf_tk/apps/_run.py +11 -0
  13. cognite_toolkit/_cdf_tk/apps/_upload_app.py +45 -6
  14. cognite_toolkit/_cdf_tk/builders/__init__.py +2 -2
  15. cognite_toolkit/_cdf_tk/builders/_base.py +28 -42
  16. cognite_toolkit/_cdf_tk/cdf_toml.py +20 -1
  17. cognite_toolkit/_cdf_tk/client/_toolkit_client.py +23 -3
  18. cognite_toolkit/_cdf_tk/client/api/extended_functions.py +6 -9
  19. cognite_toolkit/_cdf_tk/client/api/infield.py +93 -1
  20. cognite_toolkit/_cdf_tk/client/api/migration.py +175 -1
  21. cognite_toolkit/_cdf_tk/client/api/streams.py +84 -0
  22. cognite_toolkit/_cdf_tk/client/api/three_d.py +50 -0
  23. cognite_toolkit/_cdf_tk/client/data_classes/base.py +25 -1
  24. cognite_toolkit/_cdf_tk/client/data_classes/canvas.py +46 -3
  25. cognite_toolkit/_cdf_tk/client/data_classes/charts.py +3 -3
  26. cognite_toolkit/_cdf_tk/client/data_classes/charts_data.py +95 -213
  27. cognite_toolkit/_cdf_tk/client/data_classes/infield.py +32 -18
  28. cognite_toolkit/_cdf_tk/client/data_classes/migration.py +10 -2
  29. cognite_toolkit/_cdf_tk/client/data_classes/streams.py +90 -0
  30. cognite_toolkit/_cdf_tk/client/data_classes/three_d.py +47 -0
  31. cognite_toolkit/_cdf_tk/client/testing.py +18 -2
  32. cognite_toolkit/_cdf_tk/commands/__init__.py +6 -6
  33. cognite_toolkit/_cdf_tk/commands/_changes.py +3 -42
  34. cognite_toolkit/_cdf_tk/commands/_download.py +21 -11
  35. cognite_toolkit/_cdf_tk/commands/_migrate/__init__.py +0 -2
  36. cognite_toolkit/_cdf_tk/commands/_migrate/command.py +22 -20
  37. cognite_toolkit/_cdf_tk/commands/_migrate/conversion.py +133 -91
  38. cognite_toolkit/_cdf_tk/commands/_migrate/data_classes.py +73 -22
  39. cognite_toolkit/_cdf_tk/commands/_migrate/data_mapper.py +311 -43
  40. cognite_toolkit/_cdf_tk/commands/_migrate/default_mappings.py +5 -5
  41. cognite_toolkit/_cdf_tk/commands/_migrate/issues.py +33 -0
  42. cognite_toolkit/_cdf_tk/commands/_migrate/migration_io.py +157 -8
  43. cognite_toolkit/_cdf_tk/commands/_migrate/selectors.py +9 -4
  44. cognite_toolkit/_cdf_tk/commands/_purge.py +27 -28
  45. cognite_toolkit/_cdf_tk/commands/_questionary_style.py +16 -0
  46. cognite_toolkit/_cdf_tk/commands/_upload.py +109 -86
  47. cognite_toolkit/_cdf_tk/commands/about.py +221 -0
  48. cognite_toolkit/_cdf_tk/commands/auth.py +19 -12
  49. cognite_toolkit/_cdf_tk/commands/build_cmd.py +15 -61
  50. cognite_toolkit/_cdf_tk/commands/clean.py +63 -16
  51. cognite_toolkit/_cdf_tk/commands/deploy.py +20 -17
  52. cognite_toolkit/_cdf_tk/commands/dump_resource.py +6 -4
  53. cognite_toolkit/_cdf_tk/commands/init.py +225 -3
  54. cognite_toolkit/_cdf_tk/commands/modules.py +20 -44
  55. cognite_toolkit/_cdf_tk/commands/pull.py +6 -19
  56. cognite_toolkit/_cdf_tk/commands/resources.py +179 -0
  57. cognite_toolkit/_cdf_tk/constants.py +20 -1
  58. cognite_toolkit/_cdf_tk/cruds/__init__.py +19 -5
  59. cognite_toolkit/_cdf_tk/cruds/_base_cruds.py +14 -70
  60. cognite_toolkit/_cdf_tk/cruds/_data_cruds.py +8 -17
  61. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/__init__.py +4 -1
  62. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/agent.py +11 -9
  63. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/auth.py +4 -14
  64. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/classic.py +44 -43
  65. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/configuration.py +4 -11
  66. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/data_organization.py +4 -13
  67. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/datamodel.py +205 -66
  68. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/extraction_pipeline.py +5 -17
  69. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/fieldops.py +116 -27
  70. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/file.py +6 -27
  71. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/function.py +9 -28
  72. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/hosted_extractors.py +12 -30
  73. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/industrial_tool.py +3 -7
  74. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/location.py +3 -15
  75. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/migration.py +4 -12
  76. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/raw.py +4 -10
  77. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/relationship.py +3 -8
  78. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/robotics.py +15 -44
  79. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/streams.py +94 -0
  80. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/three_d_model.py +3 -7
  81. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/timeseries.py +5 -15
  82. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/transformation.py +39 -31
  83. cognite_toolkit/_cdf_tk/cruds/_resource_cruds/workflow.py +20 -40
  84. cognite_toolkit/_cdf_tk/cruds/_worker.py +24 -36
  85. cognite_toolkit/_cdf_tk/feature_flags.py +16 -36
  86. cognite_toolkit/_cdf_tk/plugins.py +2 -1
  87. cognite_toolkit/_cdf_tk/resource_classes/__init__.py +4 -0
  88. cognite_toolkit/_cdf_tk/resource_classes/capabilities.py +12 -0
  89. cognite_toolkit/_cdf_tk/resource_classes/functions.py +3 -1
  90. cognite_toolkit/_cdf_tk/resource_classes/infield_cdm_location_config.py +109 -0
  91. cognite_toolkit/_cdf_tk/resource_classes/migration.py +8 -17
  92. cognite_toolkit/_cdf_tk/resource_classes/streams.py +29 -0
  93. cognite_toolkit/_cdf_tk/storageio/__init__.py +9 -21
  94. cognite_toolkit/_cdf_tk/storageio/_annotations.py +19 -16
  95. cognite_toolkit/_cdf_tk/storageio/_applications.py +338 -26
  96. cognite_toolkit/_cdf_tk/storageio/_asset_centric.py +67 -104
  97. cognite_toolkit/_cdf_tk/storageio/_base.py +61 -29
  98. cognite_toolkit/_cdf_tk/storageio/_datapoints.py +276 -20
  99. cognite_toolkit/_cdf_tk/storageio/_file_content.py +436 -0
  100. cognite_toolkit/_cdf_tk/storageio/_instances.py +34 -2
  101. cognite_toolkit/_cdf_tk/storageio/_raw.py +26 -0
  102. cognite_toolkit/_cdf_tk/storageio/selectors/__init__.py +62 -4
  103. cognite_toolkit/_cdf_tk/storageio/selectors/_base.py +14 -2
  104. cognite_toolkit/_cdf_tk/storageio/selectors/_canvas.py +14 -0
  105. cognite_toolkit/_cdf_tk/storageio/selectors/_charts.py +14 -0
  106. cognite_toolkit/_cdf_tk/storageio/selectors/_datapoints.py +23 -3
  107. cognite_toolkit/_cdf_tk/storageio/selectors/_file_content.py +164 -0
  108. cognite_toolkit/_cdf_tk/tk_warnings/other.py +4 -0
  109. cognite_toolkit/_cdf_tk/tracker.py +2 -2
  110. cognite_toolkit/_cdf_tk/utils/dtype_conversion.py +9 -3
  111. cognite_toolkit/_cdf_tk/utils/fileio/__init__.py +2 -0
  112. cognite_toolkit/_cdf_tk/utils/fileio/_base.py +5 -1
  113. cognite_toolkit/_cdf_tk/utils/fileio/_readers.py +112 -20
  114. cognite_toolkit/_cdf_tk/utils/fileio/_writers.py +15 -15
  115. cognite_toolkit/_cdf_tk/utils/http_client/_client.py +284 -18
  116. cognite_toolkit/_cdf_tk/utils/http_client/_data_classes.py +50 -4
  117. cognite_toolkit/_cdf_tk/utils/http_client/_data_classes2.py +187 -0
  118. cognite_toolkit/_cdf_tk/utils/interactive_select.py +9 -14
  119. cognite_toolkit/_cdf_tk/utils/sql_parser.py +2 -3
  120. cognite_toolkit/_cdf_tk/utils/useful_types.py +6 -2
  121. cognite_toolkit/_cdf_tk/validation.py +79 -1
  122. cognite_toolkit/_repo_files/GitHub/.github/workflows/deploy.yaml +1 -1
  123. cognite_toolkit/_repo_files/GitHub/.github/workflows/dry-run.yaml +1 -1
  124. cognite_toolkit/_resources/cdf.toml +5 -4
  125. cognite_toolkit/_version.py +1 -1
  126. cognite_toolkit/config.dev.yaml +13 -0
  127. {cognite_toolkit-0.6.97.dist-info → cognite_toolkit-0.7.30.dist-info}/METADATA +24 -24
  128. {cognite_toolkit-0.6.97.dist-info → cognite_toolkit-0.7.30.dist-info}/RECORD +153 -143
  129. cognite_toolkit-0.7.30.dist-info/WHEEL +4 -0
  130. {cognite_toolkit-0.6.97.dist-info → cognite_toolkit-0.7.30.dist-info}/entry_points.txt +1 -0
  131. cognite_toolkit/_cdf_tk/commands/_migrate/canvas.py +0 -201
  132. cognite_toolkit/_cdf_tk/commands/dump_data.py +0 -489
  133. cognite_toolkit/_cdf_tk/commands/featureflag.py +0 -27
  134. cognite_toolkit/_cdf_tk/utils/table_writers.py +0 -434
  135. cognite_toolkit-0.6.97.dist-info/WHEEL +0 -4
  136. cognite_toolkit-0.6.97.dist-info/licenses/LICENSE +0 -18
@@ -0,0 +1,109 @@
1
+ from typing import Any
2
+
3
+ from .base import BaseModelResource, ToolkitResource
4
+
5
+
6
+ class FeatureToggles(BaseModelResource):
7
+ """Feature toggles for InField location configuration."""
8
+
9
+ three_d: bool | None = None
10
+ trends: bool | None = None
11
+ documents: bool | None = None
12
+ workorders: bool | None = None
13
+ notifications: bool | None = None
14
+ media: bool | None = None
15
+ template_checklist_flow: bool | None = None
16
+
17
+
18
+ class AccessManagement(BaseModelResource):
19
+ """Access management configuration."""
20
+
21
+ template_admins: list[str] | None = None # list of CDF group external IDs
22
+ checklist_admins: list[str] | None = None # list of CDF group external IDs
23
+
24
+
25
+ class DataFilterPath(BaseModelResource):
26
+ """Path reference for data filters."""
27
+
28
+ space: str
29
+ external_id: str
30
+
31
+
32
+ class DataFilter(BaseModelResource):
33
+ """Data filter configuration for a resource type."""
34
+
35
+ path: DataFilterPath | None = None
36
+ instance_spaces: list[str] | None = None
37
+
38
+
39
+ class DataFilters(BaseModelResource):
40
+ """Data filters configuration."""
41
+
42
+ files: DataFilter | None = None
43
+ assets: DataFilter | None = None
44
+ operations: DataFilter | None = None
45
+ time_series: DataFilter | None = None
46
+ notifications: DataFilter | None = None
47
+ maintenance_orders: DataFilter | None = None
48
+
49
+
50
+ class DataStorage(BaseModelResource):
51
+ """Data storage configuration."""
52
+
53
+ root_location: DataFilterPath | None = None
54
+ app_instance_space: str | None = None
55
+
56
+
57
+ class ViewMapping(BaseModelResource):
58
+ """View mapping configuration."""
59
+
60
+ space: str
61
+ version: str
62
+ external_id: str
63
+
64
+
65
+ class ViewMappings(BaseModelResource):
66
+ """View mappings configuration."""
67
+
68
+ asset: ViewMapping | None = None
69
+ operation: ViewMapping | None = None
70
+ notification: ViewMapping | None = None
71
+ maintenance_order: ViewMapping | None = None
72
+
73
+
74
+ class Discipline(BaseModelResource):
75
+ """Discipline configuration."""
76
+
77
+ name: str
78
+ external_id: str
79
+
80
+
81
+ class InFieldCDMLocationConfigYAML(ToolkitResource):
82
+ """Properties for InFieldCDMLocationConfig node.
83
+
84
+ Fields:
85
+ - space: The space of the InField CDM location configuration
86
+ - external_id: The external ID of the InField CDM location configuration
87
+ - name: The name of the location configuration
88
+ - description: The description of the location configuration
89
+ - feature_toggles: Feature toggles configuration
90
+ - access_management: Access management configuration
91
+ - data_filters: Data filters configuration for various resource types
92
+ - data_storage: Data storage configuration
93
+ - view_mappings: View mappings configuration
94
+ - disciplines: List of disciplines
95
+ - data_exploration_config: Data exploration configuration
96
+ """
97
+
98
+ space: str
99
+ external_id: str
100
+
101
+ name: str | None = None
102
+ description: str | None = None
103
+ feature_toggles: FeatureToggles | None = None
104
+ access_management: AccessManagement | None = None
105
+ data_filters: DataFilters | None = None
106
+ data_storage: DataStorage | None = None
107
+ view_mappings: ViewMappings | None = None
108
+ disciplines: list[Discipline] | None = None
109
+ data_exploration_config: dict[str, Any] | None = None
@@ -1,19 +1,20 @@
1
- import re
2
1
  from typing import Literal
3
2
 
4
- from pydantic import Field, field_validator
3
+ from pydantic import Field
5
4
 
6
- from cognite_toolkit._cdf_tk.utils import humanize_collection
5
+ from cognite_toolkit._cdf_tk.constants import INSTANCE_EXTERNAL_ID_PATTERN
7
6
 
8
7
  from .base import ToolkitResource
9
8
  from .view_field_definitions import ViewReference
10
9
 
11
- JSON_PATH_PATTERN = re.compile(
12
- r"^([a-zA-Z_][a-zA-Z0-9_]*|\[\d+\])(\.[a-zA-Z_][a-zA-Z0-9_]*|\[\d+\]|\[\'[^\']*\'\]|\[\"[^\"]*\"\])*$"
13
- )
14
-
15
10
 
16
11
  class ResourceViewMappingYAML(ToolkitResource):
12
+ external_id: str = Field(
13
+ description="External-id of the mapping.",
14
+ min_length=1,
15
+ max_length=256,
16
+ pattern=INSTANCE_EXTERNAL_ID_PATTERN,
17
+ )
17
18
  resource_type: Literal["asset", "event", "file", "timeSeries", "sequence", "assetAnnotation", "fileAnnotation"] = (
18
19
  Field(
19
20
  description="The type of the resource to map to the view.",
@@ -25,13 +26,3 @@ class ResourceViewMappingYAML(ToolkitResource):
25
26
  property_mapping: dict[str, str] = Field(
26
27
  description="A dictionary mapping from resource property to view property.",
27
28
  )
28
-
29
- @field_validator("property_mapping")
30
- @classmethod
31
- def validate_json_paths(cls, value: dict[str, str]) -> dict[str, str]:
32
- if not isinstance(value, dict):
33
- return value
34
- not_matching_keys = [k for k in value.keys() if not re.match(JSON_PATH_PATTERN, k)]
35
- if not_matching_keys:
36
- raise ValueError(f"Invalid JSON paths: {humanize_collection(not_matching_keys)}")
37
- return value
@@ -0,0 +1,29 @@
1
+ from typing import Literal
2
+
3
+ from pydantic import Field
4
+
5
+ from cognite_toolkit._cdf_tk.constants import StreamTemplateName
6
+
7
+ from .base import BaseModelResource, ToolkitResource
8
+
9
+
10
+ class StreamSettings(BaseModelResource):
11
+ """Stream settings resource class."""
12
+
13
+ template: dict[Literal["name"], StreamTemplateName] = Field(
14
+ description="Reference to a template which should be used to define initial settings for the stream."
15
+ )
16
+
17
+
18
+ class StreamYAML(ToolkitResource):
19
+ """Stream YAML resource class."""
20
+
21
+ external_id: str = Field(
22
+ description="The external ID of the stream.",
23
+ min_length=1,
24
+ max_length=100,
25
+ pattern="^[a-z]([a-z0-9_-]{0,98}[a-z0-9])?$",
26
+ )
27
+ settings: StreamSettings = Field(
28
+ description="Stream settings which should be applied to a stream.",
29
+ )
@@ -1,13 +1,10 @@
1
- from pathlib import Path
2
-
3
1
  from cognite_toolkit._cdf_tk.utils._auxiliary import get_concrete_subclasses
4
- from cognite_toolkit._cdf_tk.utils.fileio import COMPRESSION_BY_SUFFIX
5
2
 
6
- from ._annotations import FileAnnotationIO
3
+ from ._annotations import AnnotationIO
7
4
  from ._applications import CanvasIO, ChartIO
8
5
  from ._asset_centric import (
6
+ AssetCentricIO,
9
7
  AssetIO,
10
- BaseAssetCentricIO,
11
8
  EventIO,
12
9
  FileMetadataIO,
13
10
  HierarchyIO,
@@ -25,6 +22,7 @@ from ._base import (
25
22
  )
26
23
  from ._data_classes import InstanceIdCSVList, InstanceIdRow, ModelList
27
24
  from ._datapoints import DatapointsIO
25
+ from ._file_content import FileContentIO
28
26
  from ._instances import InstanceIO
29
27
  from ._raw import RawIO
30
28
  from .selectors._base import DataSelector
@@ -34,33 +32,24 @@ STORAGE_IO_CLASSES = get_concrete_subclasses(StorageIO) # type: ignore[type-abs
34
32
  UPLOAD_IO_CLASSES = get_concrete_subclasses(UploadableStorageIO) # type: ignore[type-abstract]
35
33
 
36
34
 
37
- def get_upload_io(selector_cls: type[DataSelector], kind: str | Path) -> type[UploadableStorageIO]:
35
+ def get_upload_io(selector: DataSelector) -> type[UploadableStorageIO]:
38
36
  """Get the appropriate UploadableStorageIO class based on the type of the provided selector."""
39
37
  for cls in UPLOAD_IO_CLASSES:
40
- if issubclass(selector_cls, cls.BASE_SELECTOR) and are_same_kind(cls.KIND, kind):
38
+ if isinstance(selector, cls.BASE_SELECTOR) and selector.kind == cls.KIND:
41
39
  return cls
42
- raise ValueError(f"No UploadableStorageIO found for selector of type {selector_cls.__name__}")
43
-
44
-
45
- def are_same_kind(kind: str, kind_or_path: str | Path, /) -> bool:
46
- """Check if two kinds are the same, ignoring case and compression suffixes."""
47
- if not isinstance(kind_or_path, Path):
48
- return kind.casefold() == kind_or_path.casefold()
49
- stem = kind_or_path.stem
50
- if kind_or_path.suffix in COMPRESSION_BY_SUFFIX:
51
- stem = Path(stem).stem
52
- return stem.lower().endswith(kind.casefold())
40
+ raise ValueError(f"No UploadableStorageIO found for selector of type {type(selector).__name__}")
53
41
 
54
42
 
55
43
  __all__ = [
44
+ "AnnotationIO",
45
+ "AssetCentricIO",
56
46
  "AssetIO",
57
- "BaseAssetCentricIO",
58
47
  "CanvasIO",
59
48
  "ChartIO",
60
49
  "ConfigurableStorageIO",
61
50
  "DatapointsIO",
62
51
  "EventIO",
63
- "FileAnnotationIO",
52
+ "FileContentIO",
64
53
  "FileMetadataIO",
65
54
  "HierarchyIO",
66
55
  "InstanceIO",
@@ -76,6 +65,5 @@ __all__ = [
76
65
  "TimeSeriesIO",
77
66
  "UploadItem",
78
67
  "UploadableStorageIO",
79
- "are_same_kind",
80
68
  "get_upload_io",
81
69
  ]
@@ -11,7 +11,7 @@ from ._base import Page, StorageIO
11
11
  from .selectors import AssetCentricSelector
12
12
 
13
13
 
14
- class FileAnnotationIO(StorageIO[AssetCentricSelector, Annotation]):
14
+ class AnnotationIO(StorageIO[AssetCentricSelector, Annotation]):
15
15
  SUPPORTED_DOWNLOAD_FORMATS = frozenset({".ndjson"})
16
16
  SUPPORTED_COMPRESSIONS = frozenset({".gz"})
17
17
  CHUNK_SIZE = 1000
@@ -23,24 +23,27 @@ class FileAnnotationIO(StorageIO[AssetCentricSelector, Annotation]):
23
23
  project = item._cognite_client.config.project
24
24
  return f"INTERNAL_ID_project_{project}_{item.id!s}"
25
25
 
26
- def stream_data(self, selector: AssetCentricSelector, limit: int | None = None) -> Iterable[Page]:
26
+ def stream_data(self, selector: AssetCentricSelector, limit: int | None = None) -> Iterable[Page[Annotation]]:
27
27
  total = 0
28
28
  for file_chunk in FileMetadataIO(self.client).stream_data(selector, None):
29
- # Todo Support pagination. This is missing in the SDK.
30
- results = self.client.annotations.list(
31
- filter=AnnotationFilter(
32
- annotated_resource_type="file",
33
- annotated_resource_ids=[{"id": file_metadata.id} for file_metadata in file_chunk.items],
29
+ for annotation_type in ["diagrams.AssetLink", "diagrams.FileLink"]:
30
+ # Todo Support pagination. This is missing in the SDK.
31
+ results = self.client.annotations.list(
32
+ filter=AnnotationFilter(
33
+ annotated_resource_type="file",
34
+ annotated_resource_ids=[{"id": file_metadata.id} for file_metadata in file_chunk.items],
35
+ annotation_type=annotation_type,
36
+ ),
37
+ limit=-1,
34
38
  )
35
- )
36
- if limit is not None and total + len(results) > limit:
37
- results = results[: limit - total]
38
-
39
- for chunk in chunker_sequence(results, self.CHUNK_SIZE):
40
- yield Page(worker_id="main", items=chunk)
41
- total += len(chunk)
42
- if limit is not None and total >= limit:
43
- break
39
+ if limit is not None and total + len(results) > limit:
40
+ results = results[: limit - total]
41
+
42
+ for chunk in chunker_sequence(results, self.CHUNK_SIZE):
43
+ yield Page(worker_id="main", items=chunk)
44
+ total += len(chunk)
45
+ if limit is not None and total >= limit:
46
+ break
44
47
 
45
48
  def count(self, selector: AssetCentricSelector) -> int | None:
46
49
  """There is no efficient way to count annotations in CDF."""