nominal 1.111.1__py3-none-any.whl → 1.112.0__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.
- CHANGELOG.md +14 -0
- nominal/experimental/migration/migration_resources.py +3 -2
- nominal/experimental/migration/migration_utils.py +10 -4
- nominal/thirdparty/polars/polars_export_handler.py +27 -2
- {nominal-1.111.1.dist-info → nominal-1.112.0.dist-info}/METADATA +2 -2
- {nominal-1.111.1.dist-info → nominal-1.112.0.dist-info}/RECORD +9 -9
- {nominal-1.111.1.dist-info → nominal-1.112.0.dist-info}/WHEEL +0 -0
- {nominal-1.111.1.dist-info → nominal-1.112.0.dist-info}/entry_points.txt +0 -0
- {nominal-1.111.1.dist-info → nominal-1.112.0.dist-info}/licenses/LICENSE +0 -0
CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.112.0](https://github.com/nominal-io/nominal-client/compare/v1.111.2...v1.112.0) (2026-02-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add option for standalone template cloning in migration_utils ([#605](https://github.com/nominal-io/nominal-client/issues/605)) ([d12a290](https://github.com/nominal-io/nominal-client/commit/d12a2908559f1f3f655981c247b67e9b07c4ce4c))
|
|
9
|
+
|
|
10
|
+
## [1.111.2](https://github.com/nominal-io/nominal-client/compare/v1.111.1...v1.111.2) (2026-02-04)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* prevent decimated exports from bricking polars export handler ([#596](https://github.com/nominal-io/nominal-client/issues/596)) ([8106f74](https://github.com/nominal-io/nominal-client/commit/8106f74dbc985c3f62946dbc4861eefa8e064964))
|
|
16
|
+
|
|
3
17
|
## [1.111.1](https://github.com/nominal-io/nominal-client/compare/v1.111.0...v1.111.1) (2026-01-29)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import Sequence
|
|
4
|
+
from typing import Mapping, Sequence
|
|
5
5
|
|
|
6
6
|
from nominal.core.asset import Asset
|
|
7
7
|
from nominal.core.workbook_template import WorkbookTemplate
|
|
@@ -15,4 +15,5 @@ class AssetResources:
|
|
|
15
15
|
|
|
16
16
|
@dataclass(frozen=True)
|
|
17
17
|
class MigrationResources:
|
|
18
|
-
source_assets:
|
|
18
|
+
source_assets: Mapping[str, AssetResources]
|
|
19
|
+
source_standalone_templates: Sequence[WorkbookTemplate]
|
|
@@ -1027,7 +1027,8 @@ def copy_resources_to_destination_client(
|
|
|
1027
1027
|
dataset_config: MigrationDatasetConfig | None = None,
|
|
1028
1028
|
) -> tuple[Sequence[tuple[str, Dataset]], Sequence[Asset], Sequence[WorkbookTemplate], Sequence[Workbook]]:
|
|
1029
1029
|
"""Based on a list of assets and workbook templates, copy resources to destination client, creating
|
|
1030
|
-
new datasets, datafiles, and workbooks along the way.
|
|
1030
|
+
new datasets, datafiles, and workbooks along the way. Standalone templates are cloned without
|
|
1031
|
+
creating workbooks.
|
|
1031
1032
|
|
|
1032
1033
|
Args:
|
|
1033
1034
|
destination_client (NominalClient): client of the tenant/workspace to copy resources to.
|
|
@@ -1050,9 +1051,10 @@ def copy_resources_to_destination_client(
|
|
|
1050
1051
|
new_workbooks = []
|
|
1051
1052
|
|
|
1052
1053
|
new_data_scopes_and_datasets: list[tuple[str, Dataset]] = []
|
|
1053
|
-
for
|
|
1054
|
+
for asset_resources in migration_resources.source_assets.values():
|
|
1055
|
+
source_asset = asset_resources.asset
|
|
1054
1056
|
new_asset = copy_asset_from(
|
|
1055
|
-
source_asset
|
|
1057
|
+
source_asset,
|
|
1056
1058
|
destination_client,
|
|
1057
1059
|
dataset_config=dataset_config,
|
|
1058
1060
|
include_events=True,
|
|
@@ -1062,7 +1064,7 @@ def copy_resources_to_destination_client(
|
|
|
1062
1064
|
new_assets.append(new_asset)
|
|
1063
1065
|
new_data_scopes_and_datasets.extend(new_asset.list_datasets())
|
|
1064
1066
|
|
|
1065
|
-
for source_workbook_template in
|
|
1067
|
+
for source_workbook_template in asset_resources.source_workbook_templates:
|
|
1066
1068
|
new_template = clone_workbook_template(source_workbook_template, destination_client)
|
|
1067
1069
|
new_templates.append(new_template)
|
|
1068
1070
|
new_workbook = new_template.create_workbook(
|
|
@@ -1077,6 +1079,10 @@ def copy_resources_to_destination_client(
|
|
|
1077
1079
|
extra=log_extras,
|
|
1078
1080
|
)
|
|
1079
1081
|
new_workbooks.append(new_workbook)
|
|
1082
|
+
|
|
1083
|
+
for source_template in migration_resources.source_standalone_templates:
|
|
1084
|
+
new_template = clone_workbook_template(source_template, destination_client)
|
|
1085
|
+
new_templates.append(new_template)
|
|
1080
1086
|
finally:
|
|
1081
1087
|
file_handler.close()
|
|
1082
1088
|
logger.removeHandler(file_handler)
|
|
@@ -42,6 +42,10 @@ DEFAULT_POINTS_PER_DATAFRAME = 25_000_000
|
|
|
42
42
|
# Maximum number of channels to get data for within a single request to Nominal
|
|
43
43
|
DEFAULT_CHANNELS_PER_REQUEST = 25
|
|
44
44
|
|
|
45
|
+
# Maximum number of buckets / decimated points exported per compute query.
|
|
46
|
+
# TODO(drake) raise 1000 limit once backend limit is raised
|
|
47
|
+
MAX_NUM_BUCKETS = 1000
|
|
48
|
+
|
|
45
49
|
DEFAULT_EXPORTED_TIMESTAMP_COL_NAME = "timestamp"
|
|
46
50
|
_INTERNAL_TS_COL = "__nmnl_ts__" # internal join key, chosen to avoid collision with channel names
|
|
47
51
|
|
|
@@ -133,8 +137,8 @@ def _batch_channel_points_per_second(
|
|
|
133
137
|
if not channels:
|
|
134
138
|
logger.warning("No channels given!")
|
|
135
139
|
return {}
|
|
136
|
-
elif num_buckets >
|
|
137
|
-
raise ValueError("num_buckets must be <=
|
|
140
|
+
elif num_buckets > MAX_NUM_BUCKETS:
|
|
141
|
+
raise ValueError(f"num_buckets ({num_buckets}) must be <= {MAX_NUM_BUCKETS}")
|
|
138
142
|
|
|
139
143
|
# For each channel that has data with the given tags within the provided time range, add a
|
|
140
144
|
# compute expression to later retrieve decimated bucket stats
|
|
@@ -683,6 +687,27 @@ class PolarsExportHandler:
|
|
|
683
687
|
if None not in (buckets, resolution):
|
|
684
688
|
raise ValueError("Cannot export data decimated with both buckets and resolution")
|
|
685
689
|
|
|
690
|
+
if resolution is not None:
|
|
691
|
+
# If the batch duration is higher than this number, and data is actually downsampled with the
|
|
692
|
+
# given resolution, then it would error today if the batch duration is any larger than this.
|
|
693
|
+
computed_batch_duration = datetime.timedelta(seconds=(resolution * MAX_NUM_BUCKETS) / 1e9)
|
|
694
|
+
if batch_duration is None:
|
|
695
|
+
logger.info(
|
|
696
|
+
"Manually setting batch_duration to %fs (resolution=%dns)",
|
|
697
|
+
computed_batch_duration.total_seconds(),
|
|
698
|
+
resolution,
|
|
699
|
+
)
|
|
700
|
+
batch_duration = computed_batch_duration
|
|
701
|
+
elif computed_batch_duration < batch_duration:
|
|
702
|
+
logger.warning(
|
|
703
|
+
"Configured batch_duration of %fs would result in failing exports with resolution=%dns. "
|
|
704
|
+
"Setting batch_duration to %fs instead.",
|
|
705
|
+
batch_duration.total_seconds(),
|
|
706
|
+
resolution,
|
|
707
|
+
computed_batch_duration.total_seconds(),
|
|
708
|
+
)
|
|
709
|
+
batch_duration = computed_batch_duration
|
|
710
|
+
|
|
686
711
|
# Determine download schedule
|
|
687
712
|
export_jobs = self._compute_export_jobs(
|
|
688
713
|
channels, _TimeRange(start, end), timestamp_type, tags or {}, buckets, resolution, batch_duration
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nominal
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.112.0
|
|
4
4
|
Summary: Automate Nominal workflows in Python
|
|
5
5
|
Project-URL: Homepage, https://nominal.io
|
|
6
6
|
Project-URL: Documentation, https://docs.nominal.io
|
|
@@ -21,7 +21,7 @@ Requires-Dist: click<9,>=8
|
|
|
21
21
|
Requires-Dist: conjure-python-client<4,>=3.1.0
|
|
22
22
|
Requires-Dist: ffmpeg-python>=0.2.0
|
|
23
23
|
Requires-Dist: nominal-api==0.1079.0
|
|
24
|
-
Requires-Dist: nominal-streaming==0.
|
|
24
|
+
Requires-Dist: nominal-streaming==0.7.12; platform_python_implementation == 'CPython' and python_version >= '3.10' and ((sys_platform == 'win32' and platform_machine == 'AMD64') or (sys_platform == 'darwin' and platform_machine == 'arm64') or (sys_platform == 'linux' and (platform_machine == 'x86_64' or platform_machine == 'armv7l' or platform_machine == 'aarch64' or platform_machine == 'arm64')))
|
|
25
25
|
Requires-Dist: openpyxl>=0.0.0
|
|
26
26
|
Requires-Dist: pandas>=0.0.0
|
|
27
27
|
Requires-Dist: polars>=0.0.0
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
CHANGELOG.md,sha256=
|
|
1
|
+
CHANGELOG.md,sha256=mPkM7Gb3inSDt6u9dSj18fMbVB6JgaiF4NuzRIaFHvc,92757
|
|
2
2
|
LICENSE,sha256=zEGHG9mjDjaIS3I79O8mweQo-yiTbqx8jJvUPppVAwk,1067
|
|
3
3
|
README.md,sha256=KKe0dxh_pHXCtB7I9G4qWGQYvot_BZU8yW6MJyuyUHM,311
|
|
4
4
|
nominal/__init__.py,sha256=rbraORnXUrNn1hywLXM0XwSQCd9UmQt20PDYlsBalfE,2167
|
|
@@ -93,8 +93,8 @@ nominal/experimental/logging/nominal_log_handler.py,sha256=hyTxyjsvFnE7vtyrDJpun
|
|
|
93
93
|
nominal/experimental/logging/rich_log_handler.py,sha256=8yz_VtxNgJg2oiesnXz2iXoBvQrUP5pAsYkxknOXgXA,1231
|
|
94
94
|
nominal/experimental/migration/__init__.py,sha256=E2IgWJLwJ5bN6jbl8k5nHECKFx5aT11jKAzVYcyXn3o,460
|
|
95
95
|
nominal/experimental/migration/migration_data_config.py,sha256=sPwZjyLmL-_pHvDZvQspxrfW6yNZhEsQjDVwKA8IaXM,522
|
|
96
|
-
nominal/experimental/migration/migration_resources.py,sha256=
|
|
97
|
-
nominal/experimental/migration/migration_utils.py,sha256=
|
|
96
|
+
nominal/experimental/migration/migration_resources.py,sha256=LP1ishD3GoZgv0W-3EHcuJ4Vyt3w7oBjy0jRnhWb58o,488
|
|
97
|
+
nominal/experimental/migration/migration_utils.py,sha256=vWzbATE6QJoUKo39F2fCiykpuEI1voYcbfRnoWjRo4s,42764
|
|
98
98
|
nominal/experimental/rust_streaming/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
99
99
|
nominal/experimental/rust_streaming/rust_write_stream.py,sha256=oQ6ixwm8ct8ZDc_qNB7AucDt8o5-_aBVlW2fFCQ_nmA,1541
|
|
100
100
|
nominal/experimental/stream_v2/__init__.py,sha256=W39vK46pssx5sXvmsImMuJiEPs7iGtwrbYBI0bWnXCY,2313
|
|
@@ -109,12 +109,12 @@ nominal/thirdparty/matlab/_matlab.py,sha256=qtrO_wP_o9J2oqiwhriSfL0LYO7rBzssoHyg
|
|
|
109
109
|
nominal/thirdparty/pandas/__init__.py,sha256=wnPcbvZrTCNM5cphvwn198dCn7Dcp1QJFDK12mcdd8w,361
|
|
110
110
|
nominal/thirdparty/pandas/_pandas.py,sha256=QcM1tk-Z5W8bKd9oYz5rD6M3qIHZ0N5uUe_UOVOQC08,16367
|
|
111
111
|
nominal/thirdparty/polars/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
112
|
-
nominal/thirdparty/polars/polars_export_handler.py,sha256=
|
|
112
|
+
nominal/thirdparty/polars/polars_export_handler.py,sha256=1XjdOYWpiU2ilSU5tcjNpoLoRw1GrgrhtcgwR8Cobxo,34301
|
|
113
113
|
nominal/thirdparty/tdms/__init__.py,sha256=6n2ImFr2Wiil6JM1P5Q7Mpr0VzLcnDkmup_ftNpPq-s,142
|
|
114
114
|
nominal/thirdparty/tdms/_tdms.py,sha256=m4gxbpxB9MTLi2FuYvGlbUGSyDAZKFxbM3ia2x1wIz0,8746
|
|
115
115
|
nominal/ts/__init__.py,sha256=hmd0ENvDhxRnzDKGLxIub6QG8LpcxCgcyAct029CaEs,21442
|
|
116
|
-
nominal-1.
|
|
117
|
-
nominal-1.
|
|
118
|
-
nominal-1.
|
|
119
|
-
nominal-1.
|
|
120
|
-
nominal-1.
|
|
116
|
+
nominal-1.112.0.dist-info/METADATA,sha256=QRY9hFafvibV--dN3xxIcD1EGDCnj-vfzdTG7K933N4,2372
|
|
117
|
+
nominal-1.112.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
118
|
+
nominal-1.112.0.dist-info/entry_points.txt,sha256=-mCLhxgg9R_lm5efT7vW9wuBH12izvY322R0a3TYxbE,66
|
|
119
|
+
nominal-1.112.0.dist-info/licenses/LICENSE,sha256=zEGHG9mjDjaIS3I79O8mweQo-yiTbqx8jJvUPppVAwk,1067
|
|
120
|
+
nominal-1.112.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|