nominal 1.95.0__tar.gz → 1.96.0__tar.gz
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.
- {nominal-1.95.0 → nominal-1.96.0}/CHANGELOG.md +9 -0
- {nominal-1.95.0 → nominal-1.96.0}/PKG-INFO +2 -2
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/__init__.py +1 -2
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/auth.py +2 -13
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/dataset.py +2 -2
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/util/click_log_handler.py +6 -3
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/util/global_decorators.py +6 -48
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/client.py +5 -24
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/data_review.py +5 -2
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/dataset.py +27 -38
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/event.py +1 -6
- nominal-1.96.0/nominal/core/exceptions.py +78 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/run.py +148 -148
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/workbook.py +5 -8
- {nominal-1.95.0 → nominal-1.96.0}/nominal/nominal.py +4 -3
- {nominal-1.95.0 → nominal-1.96.0}/pyproject.toml +2 -2
- nominal-1.95.0/nominal/core/exceptions.py +0 -39
- {nominal-1.95.0 → nominal-1.96.0}/.gitignore +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/LICENSE +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/README.md +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/__main__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/_utils/README.md +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/_utils/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/_utils/dataclass_tools.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/_utils/deprecation_tools.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/_utils/iterator_tools.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/_utils/streaming_tools.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/_utils/timing_tools.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/__main__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/attachment.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/config.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/download.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/mis.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/run.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/util/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/cli/util/verify_connection.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/config/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/config/_config.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_clientsbunch.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_constants.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_stream/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_stream/batch_processor.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_stream/batch_processor_proto.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_stream/write_stream.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_stream/write_stream_base.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_utils/README.md +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_utils/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_utils/api_tools.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_utils/multipart.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_utils/multipart_downloader.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_utils/networking.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_utils/pagination_tools.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_utils/query_tools.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/_utils/queueing.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/asset.py +176 -176
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/attachment.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/bounds.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/channel.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/checklist.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/connection.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/containerized_extractors.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/dataset_file.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/datasource.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/filetype.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/log.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/secret.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/unit.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/user.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/video.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/video_file.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/workbook_template.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/core/workspace.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/exceptions/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/compute/README.md +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/compute/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/compute/_buckets.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/compute/dsl/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/compute/dsl/_enum_expr_impls.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/compute/dsl/_numeric_expr_impls.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/compute/dsl/_range_expr_impls.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/compute/dsl/exprs.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/compute/dsl/params.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/logging/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/logging/click_log_handler.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/logging/nominal_log_handler.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/logging/rich_log_handler.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/rust_streaming/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/rust_streaming/rust_write_stream.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/stream_v2/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/stream_v2/_serializer.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/stream_v2/_write_stream.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/video_processing/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/video_processing/resolution.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/experimental/video_processing/video_conversion.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/py.typed +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/thirdparty/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/thirdparty/matlab/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/thirdparty/matlab/_matlab.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/thirdparty/pandas/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/thirdparty/pandas/_pandas.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/thirdparty/polars/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/thirdparty/polars/polars_export_handler.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/thirdparty/tdms/__init__.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/thirdparty/tdms/_tdms.py +0 -0
- {nominal-1.95.0 → nominal-1.96.0}/nominal/ts/__init__.py +0 -0
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.96.0](https://github.com/nominal-io/nominal-client/compare/v1.95.0...v1.96.0) (2025-12-03)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add tags to dataflash apis ([#534](https://github.com/nominal-io/nominal-client/issues/534)) ([00cd79f](https://github.com/nominal-io/nominal-client/commit/00cd79fdb84e299a4013b69ce9639cfc75644b32))
|
|
9
|
+
* remove deprecated fields, methods, files ([#525](https://github.com/nominal-io/nominal-client/issues/525)) ([e11175d](https://github.com/nominal-io/nominal-client/commit/e11175de0e303d97d91efa7eaf6ee6010d6b08ef))
|
|
10
|
+
* reorder methods in run and asset class ([#530](https://github.com/nominal-io/nominal-client/issues/530)) ([5813157](https://github.com/nominal-io/nominal-client/commit/58131574bd85a82d36f7e76f18279c8c7cfaf1a8))
|
|
11
|
+
|
|
3
12
|
## [1.95.0](https://github.com/nominal-io/nominal-client/compare/v1.94.0...v1.95.0) (2025-11-19)
|
|
4
13
|
|
|
5
14
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nominal
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.96.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
|
|
@@ -20,7 +20,7 @@ Requires-Dist: cachetools>=6.1.0
|
|
|
20
20
|
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
|
-
Requires-Dist: nominal-api==0.
|
|
23
|
+
Requires-Dist: nominal-api==0.1019.0
|
|
24
24
|
Requires-Dist: nominal-streaming==0.5.8
|
|
25
25
|
Requires-Dist: openpyxl>=0.0.0
|
|
26
26
|
Requires-Dist: pandas>=0.0.0
|
|
@@ -2,7 +2,7 @@ import importlib.metadata
|
|
|
2
2
|
|
|
3
3
|
import click
|
|
4
4
|
|
|
5
|
-
from nominal.cli import attachment,
|
|
5
|
+
from nominal.cli import attachment, config, dataset, download, mis, run
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
@click.group(context_settings={"show_default": True, "help_option_names": ("-h", "--help")})
|
|
@@ -12,7 +12,6 @@ def nom() -> None:
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
nom.add_command(attachment.attachment_cmd)
|
|
15
|
-
nom.add_command(auth.auth_cmd)
|
|
16
15
|
nom.add_command(config.config_cmd)
|
|
17
16
|
nom.add_command(dataset.dataset_cmd)
|
|
18
17
|
nom.add_command(download.download_cmd)
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import warnings
|
|
4
|
-
|
|
5
3
|
import click
|
|
6
4
|
|
|
7
5
|
from nominal.cli.util.global_decorators import global_options
|
|
8
|
-
from nominal.
|
|
9
|
-
from nominal.config import _config as _deprecated_config
|
|
6
|
+
from nominal.core.exceptions import NominalMethodRemovedError
|
|
10
7
|
|
|
11
8
|
|
|
12
9
|
@click.group(name="auth")
|
|
@@ -25,12 +22,4 @@ def set_token(token: str, base_url: str) -> None:
|
|
|
25
22
|
|
|
26
23
|
Update the token for a given URL in the (deprecated) Nominal config file
|
|
27
24
|
"""
|
|
28
|
-
|
|
29
|
-
"`nom auth set-token` is deprecated, use `nom config profile add` instead",
|
|
30
|
-
UserWarning,
|
|
31
|
-
stacklevel=2,
|
|
32
|
-
)
|
|
33
|
-
path = _deprecated_config._DEFAULT_NOMINAL_CONFIG_PATH
|
|
34
|
-
validate_token_url(token, base_url, None)
|
|
35
|
-
_deprecated_config.set_token(base_url, token)
|
|
36
|
-
click.secho(f"Successfully set token for '{base_url}' in {path}", fg="green")
|
|
25
|
+
raise NominalMethodRemovedError("nominal auth set-token", "use 'nominal config profile add' instead")
|
|
@@ -70,7 +70,7 @@ def upload_csv(
|
|
|
70
70
|
description=description,
|
|
71
71
|
prefix_tree_delimiter=channel_name_delimiter,
|
|
72
72
|
)
|
|
73
|
-
dataset.add_tabular_data(
|
|
73
|
+
dataset_file = dataset.add_tabular_data(
|
|
74
74
|
file,
|
|
75
75
|
timestamp_column=timestamp_column,
|
|
76
76
|
timestamp_type=timestamp_type,
|
|
@@ -78,7 +78,7 @@ def upload_csv(
|
|
|
78
78
|
|
|
79
79
|
# block until ingestion completed, if requested
|
|
80
80
|
if wait:
|
|
81
|
-
|
|
81
|
+
dataset_file.poll_until_ingestion_completed()
|
|
82
82
|
|
|
83
83
|
click.echo(dataset)
|
|
84
84
|
|
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
|
|
5
5
|
from typing_extensions import deprecated
|
|
6
6
|
|
|
7
|
-
from nominal.
|
|
7
|
+
from nominal.core.exceptions import NominalMethodRemovedError
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@deprecated(
|
|
@@ -20,7 +20,10 @@ def install_log_handler(level: int = logging.WARNING, no_color: bool = False) ->
|
|
|
20
20
|
no_color: If true, prevents log messages from being stylized by severity level
|
|
21
21
|
|
|
22
22
|
"""
|
|
23
|
-
|
|
23
|
+
raise NominalMethodRemovedError(
|
|
24
|
+
"nominal.cli.util.install_log_handler",
|
|
25
|
+
"use nominal.experimental.logging.install_click_log_handler instead",
|
|
26
|
+
)
|
|
24
27
|
|
|
25
28
|
|
|
26
|
-
__all__ = ["
|
|
29
|
+
__all__ = ["install_log_handler"]
|
|
@@ -8,7 +8,6 @@ import typing
|
|
|
8
8
|
|
|
9
9
|
import click
|
|
10
10
|
|
|
11
|
-
from nominal.config._config import _DEFAULT_NOMINAL_CONFIG_PATH, get_token
|
|
12
11
|
from nominal.core.client import NominalClient
|
|
13
12
|
from nominal.experimental.logging import install_click_log_handler
|
|
14
13
|
|
|
@@ -105,14 +104,14 @@ def client_options(func: typing.Callable[Param, T]) -> typing.Callable[..., T]:
|
|
|
105
104
|
"""Decorator to add click options to a click command for dynamically creating and injecting an instance of the
|
|
106
105
|
NominalClient into commands based on user-provided flags to configure its creation.
|
|
107
106
|
|
|
108
|
-
This will add
|
|
109
|
-
configurations before spawning a NominalClient.
|
|
107
|
+
This will add an option --profile which perform the aforementioned configurations before spawning a NominalClient.
|
|
110
108
|
|
|
111
109
|
NOTE: any click command utilizing this decorator MUST accept a key-value argument pair named client of type
|
|
112
110
|
NominalClient.
|
|
113
111
|
"""
|
|
114
112
|
profile_option = click.option(
|
|
115
113
|
"--profile",
|
|
114
|
+
required=True,
|
|
116
115
|
help=(
|
|
117
116
|
"If provided, use the given named config profile for instantiating a Nominal Client. "
|
|
118
117
|
"This is the preferred mechanism for instantiating a client today-- see `nom config profile add` "
|
|
@@ -120,26 +119,6 @@ def client_options(func: typing.Callable[Param, T]) -> typing.Callable[..., T]:
|
|
|
120
119
|
"--base-url."
|
|
121
120
|
),
|
|
122
121
|
)
|
|
123
|
-
url_option = click.option(
|
|
124
|
-
"--base-url",
|
|
125
|
-
default="https://api.gov.nominal.io/api",
|
|
126
|
-
show_default=True,
|
|
127
|
-
help="Base URL of the Nominal API to hit. Useful for hitting other clusters, e.g., staging for internal users.",
|
|
128
|
-
)
|
|
129
|
-
token_path_option = click.option(
|
|
130
|
-
"--token-path",
|
|
131
|
-
default=_DEFAULT_NOMINAL_CONFIG_PATH,
|
|
132
|
-
type=click.Path(dir_okay=False, resolve_path=True, path_type=pathlib.Path),
|
|
133
|
-
show_default=True,
|
|
134
|
-
help="Path to the yaml file containing the Nominal access token for authenticating with the API",
|
|
135
|
-
)
|
|
136
|
-
token_option = click.option(
|
|
137
|
-
"--token",
|
|
138
|
-
help=(
|
|
139
|
-
"API Access token to use when creating the nominal client. "
|
|
140
|
-
"If provided, takes precedence over --token-path and --base-url"
|
|
141
|
-
),
|
|
142
|
-
)
|
|
143
122
|
trust_store_option = click.option(
|
|
144
123
|
"--trust-store-path",
|
|
145
124
|
type=click.Path(dir_okay=False, exists=True, resolve_path=True, path_type=pathlib.Path),
|
|
@@ -154,35 +133,14 @@ def client_options(func: typing.Callable[Param, T]) -> typing.Callable[..., T]:
|
|
|
154
133
|
*args: Param.args,
|
|
155
134
|
**kwargs: Param.kwargs,
|
|
156
135
|
) -> T:
|
|
157
|
-
profile: str
|
|
158
|
-
base_url: str = kwargs.pop("base_url", "") # type: ignore[assignment]
|
|
159
|
-
token: str | None = kwargs.pop("token") # type: ignore[assignment]
|
|
160
|
-
token_path: pathlib.Path = kwargs.pop("token_path") # type: ignore[assignment]
|
|
136
|
+
profile: str = kwargs.pop("profile") # type: ignore[assignment]
|
|
161
137
|
trust_store_path: pathlib.Path | None = kwargs.pop("trust_store_path") # type: ignore[assignment]
|
|
162
138
|
|
|
163
139
|
trust_store_str = str(trust_store_path) if trust_store_path else None
|
|
164
140
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
client = NominalClient.from_profile(profile, trust_store_path=trust_store_str)
|
|
168
|
-
kwargs["client"] = client
|
|
169
|
-
return func(*args, **kwargs)
|
|
170
|
-
|
|
171
|
-
logger.warning(
|
|
172
|
-
"Creating a Nominal Client without using '--profile' is deprecated! "
|
|
173
|
-
"See 'https://docs.nominal.io/core/sdk/python-client/authentication' for details..."
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
if token is None:
|
|
177
|
-
if token_path.exists():
|
|
178
|
-
token = get_token(base_url, token_path)
|
|
179
|
-
else:
|
|
180
|
-
raise ValueError(
|
|
181
|
-
f"Cannot instantiate client: no token provided and token path {token_path} does not exist."
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
client = NominalClient.create(base_url, token=token, trust_store_path=trust_store_str)
|
|
141
|
+
logger.info("Instantiating client from profile '%s'", profile)
|
|
142
|
+
client = NominalClient.from_profile(profile, trust_store_path=trust_store_str)
|
|
185
143
|
kwargs["client"] = client
|
|
186
144
|
return func(*args, **kwargs)
|
|
187
145
|
|
|
188
|
-
return profile_option(
|
|
146
|
+
return profile_option(trust_store_option(wrapped_function))
|
|
@@ -31,7 +31,6 @@ from nominal_api import (
|
|
|
31
31
|
from typing_extensions import Self, deprecated
|
|
32
32
|
|
|
33
33
|
from nominal import ts
|
|
34
|
-
from nominal._utils.deprecation_tools import warn_on_deprecated_argument
|
|
35
34
|
from nominal.config import NominalConfig, _config
|
|
36
35
|
from nominal.core._clientsbunch import ClientsBunch
|
|
37
36
|
from nominal.core._constants import DEFAULT_API_BASE_URL
|
|
@@ -94,7 +93,7 @@ from nominal.core.dataset import (
|
|
|
94
93
|
)
|
|
95
94
|
from nominal.core.datasource import DataSource
|
|
96
95
|
from nominal.core.event import Event, EventType
|
|
97
|
-
from nominal.core.exceptions import NominalConfigError, NominalError, NominalIngestError
|
|
96
|
+
from nominal.core.exceptions import NominalConfigError, NominalError, NominalIngestError, NominalMethodRemovedError
|
|
98
97
|
from nominal.core.filetype import FileType, FileTypes
|
|
99
98
|
from nominal.core.run import Run
|
|
100
99
|
from nominal.core.secret import Secret
|
|
@@ -338,10 +337,6 @@ class NominalClient:
|
|
|
338
337
|
for raw_dataset in search_datasets_paginated(self._clients.catalog, self._clients.auth_header, query):
|
|
339
338
|
yield Dataset._from_conjure(self._clients, raw_dataset)
|
|
340
339
|
|
|
341
|
-
@warn_on_deprecated_argument(
|
|
342
|
-
"workspace_rid",
|
|
343
|
-
"`workspace_rid` has been deprecated and will be removed in a future version. Use `workspace` instead.",
|
|
344
|
-
)
|
|
345
340
|
def search_datasets(
|
|
346
341
|
self,
|
|
347
342
|
*,
|
|
@@ -351,7 +346,6 @@ class NominalClient:
|
|
|
351
346
|
properties: Mapping[str, str] | None = None,
|
|
352
347
|
before: str | datetime | IntegralNanosecondsUTC | None = None,
|
|
353
348
|
after: str | datetime | IntegralNanosecondsUTC | None = None,
|
|
354
|
-
workspace_rid: Workspace | str | None = None,
|
|
355
349
|
workspace: WorkspaceSearchT = WorkspaceSearchType.ALL,
|
|
356
350
|
archived: bool | None = None,
|
|
357
351
|
) -> Sequence[Dataset]:
|
|
@@ -365,7 +359,6 @@ class NominalClient:
|
|
|
365
359
|
properties: A mapping of key-value pairs that must ALL be present on a secret to be included.
|
|
366
360
|
before: Searches for datasets created before some time (inclusive).
|
|
367
361
|
after: Searches for datasets created before after time (inclusive).
|
|
368
|
-
workspace_rid: deprecated. use `workspace` instead.
|
|
369
362
|
workspace: Filters search to given workspace.
|
|
370
363
|
archived: Filters results to either archived or unarchived datasets.
|
|
371
364
|
|
|
@@ -377,12 +370,6 @@ class NominalClient:
|
|
|
377
370
|
Returns:
|
|
378
371
|
All datasets which match all of the provided conditions
|
|
379
372
|
"""
|
|
380
|
-
if workspace is not None and workspace_rid is not None:
|
|
381
|
-
raise ValueError("Both `workspace` and `workspace_rid` provided-- must use one or the other.")
|
|
382
|
-
|
|
383
|
-
if workspace_rid is not None:
|
|
384
|
-
workspace = workspace_rid
|
|
385
|
-
|
|
386
373
|
query = create_search_datasets_query(
|
|
387
374
|
exact_match=exact_match,
|
|
388
375
|
search_text=search_text,
|
|
@@ -1477,7 +1464,7 @@ class NominalClient:
|
|
|
1477
1464
|
|
|
1478
1465
|
@deprecated(
|
|
1479
1466
|
"Calling `NominalClient.create_workbook_from_template` is deprecated and will be removed "
|
|
1480
|
-
"in a future release. Use `
|
|
1467
|
+
"in a future release. Use `WorkbookTemplate.create_workbook` instead"
|
|
1481
1468
|
)
|
|
1482
1469
|
def create_workbook_from_template(
|
|
1483
1470
|
self,
|
|
@@ -1487,13 +1474,7 @@ class NominalClient:
|
|
|
1487
1474
|
description: str | None = None,
|
|
1488
1475
|
is_draft: bool = False,
|
|
1489
1476
|
) -> Workbook:
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
"""
|
|
1494
|
-
template = self.get_workbook_template(template_rid)
|
|
1495
|
-
return template.create_workbook(
|
|
1496
|
-
title=title,
|
|
1497
|
-
description=description,
|
|
1498
|
-
run=run_rid,
|
|
1477
|
+
raise NominalMethodRemovedError(
|
|
1478
|
+
"nominal.core.NominalClient.create_workbook_from_template",
|
|
1479
|
+
"use 'nominal.core.WorkbookTemplate.create_workbook' instead",
|
|
1499
1480
|
)
|
|
@@ -21,6 +21,7 @@ from typing_extensions import Self, deprecated
|
|
|
21
21
|
from nominal.core import checklist, event
|
|
22
22
|
from nominal.core._clientsbunch import HasScoutParams
|
|
23
23
|
from nominal.core._utils.api_tools import HasRid
|
|
24
|
+
from nominal.core.exceptions import NominalMethodRemovedError
|
|
24
25
|
from nominal.ts import IntegralNanosecondsUTC, _SecondsNanos
|
|
25
26
|
|
|
26
27
|
|
|
@@ -75,8 +76,10 @@ class DataReview(HasRid):
|
|
|
75
76
|
)
|
|
76
77
|
def get_violations(self) -> Sequence[CheckViolation]:
|
|
77
78
|
"""Retrieves the list of check violations for the data review."""
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
raise NominalMethodRemovedError(
|
|
80
|
+
"nominal.core.DataReview.get_violations",
|
|
81
|
+
"use 'nominal.core.DataReview.get_events()' instead",
|
|
82
|
+
)
|
|
80
83
|
|
|
81
84
|
def get_events(self) -> Sequence[event.Event]:
|
|
82
85
|
"""Retrieves the list of events for the data review."""
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
import time
|
|
5
4
|
from dataclasses import dataclass
|
|
6
5
|
from datetime import timedelta
|
|
7
6
|
from io import TextIOBase
|
|
@@ -20,7 +19,7 @@ from nominal.core.bounds import Bounds
|
|
|
20
19
|
from nominal.core.containerized_extractors import ContainerizedExtractor
|
|
21
20
|
from nominal.core.dataset_file import DatasetFile
|
|
22
21
|
from nominal.core.datasource import DataSource
|
|
23
|
-
from nominal.core.exceptions import NominalIngestError,
|
|
22
|
+
from nominal.core.exceptions import NominalIngestError, NominalIngestMultiError, NominalMethodRemovedError
|
|
24
23
|
from nominal.core.filetype import FileType, FileTypes
|
|
25
24
|
from nominal.core.log import LogPoint, _write_logs
|
|
26
25
|
from nominal.ts import (
|
|
@@ -55,38 +54,12 @@ class Dataset(DataSource, RefreshableMixin[scout_catalog.EnrichedDataset]):
|
|
|
55
54
|
"obtained when ingesting files or by calling `dataset.list_files()`."
|
|
56
55
|
)
|
|
57
56
|
def poll_until_ingestion_completed(self, interval: timedelta = timedelta(seconds=1)) -> Self:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
NominalIngestError: if the ingest status is not known
|
|
65
|
-
|
|
66
|
-
"""
|
|
67
|
-
while True:
|
|
68
|
-
progress = self._clients.catalog.get_ingest_progress_v2(self._clients.auth_header, self.rid)
|
|
69
|
-
if progress.ingest_status.type == "success":
|
|
70
|
-
break
|
|
71
|
-
elif progress.ingest_status.type == "inProgress": # "type" strings are camelCase
|
|
72
|
-
pass
|
|
73
|
-
elif progress.ingest_status.type == "error":
|
|
74
|
-
error = progress.ingest_status.error
|
|
75
|
-
if error is not None:
|
|
76
|
-
raise NominalIngestFailed(
|
|
77
|
-
f"ingest failed for dataset {self.rid!r}: {error.message} ({error.error_type})"
|
|
78
|
-
)
|
|
79
|
-
raise NominalIngestError(
|
|
80
|
-
f"ingest status type marked as 'error' but with no instance for dataset {self.rid!r}"
|
|
81
|
-
)
|
|
82
|
-
else:
|
|
83
|
-
raise NominalIngestError(
|
|
84
|
-
f"unhandled ingest status {progress.ingest_status.type!r} for dataset {self.rid!r}"
|
|
85
|
-
)
|
|
86
|
-
time.sleep(interval.total_seconds())
|
|
87
|
-
|
|
88
|
-
# Update metadata now that data has successfully ingested
|
|
89
|
-
return self.refresh()
|
|
57
|
+
raise NominalMethodRemovedError(
|
|
58
|
+
"nominal.core.Dataset.poll_until_ingestion_completed",
|
|
59
|
+
"poll for ingestion completion on individual 'nominal.core.DatasetFile's, "
|
|
60
|
+
"which are obtained when ingesting files or by calling "
|
|
61
|
+
"'nominal.core.Dataset.list_files()' etc.",
|
|
62
|
+
)
|
|
90
63
|
|
|
91
64
|
def update(
|
|
92
65
|
self,
|
|
@@ -339,8 +312,14 @@ class Dataset(DataSource, RefreshableMixin[scout_catalog.EnrichedDataset]):
|
|
|
339
312
|
def add_ardupilot_dataflash(
|
|
340
313
|
self,
|
|
341
314
|
path: Path | str,
|
|
315
|
+
tags: Mapping[str, str] | None = None,
|
|
342
316
|
) -> DatasetFile:
|
|
343
|
-
"""Add a Dataflash file to an existing dataset.
|
|
317
|
+
"""Add a Dataflash file to an existing dataset.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
path: Path to the Dataflash file to add to this dataset.
|
|
321
|
+
tags: key-value pairs to apply as tags to all data uniformly in the file.
|
|
322
|
+
"""
|
|
344
323
|
dataflash_path = Path(path)
|
|
345
324
|
s3_path = upload_multipart_file(
|
|
346
325
|
self._clients.auth_header,
|
|
@@ -352,7 +331,7 @@ class Dataset(DataSource, RefreshableMixin[scout_catalog.EnrichedDataset]):
|
|
|
352
331
|
target = ingest_api.DatasetIngestTarget(
|
|
353
332
|
existing=ingest_api.ExistingDatasetIngestDestination(dataset_rid=self.rid)
|
|
354
333
|
)
|
|
355
|
-
request = _create_dataflash_ingest_request(s3_path, target)
|
|
334
|
+
request = _create_dataflash_ingest_request(s3_path, target, tags)
|
|
356
335
|
resp = self._clients.ingest.ingest(self._clients.auth_header, request)
|
|
357
336
|
return self._handle_ingest_response(resp)
|
|
358
337
|
|
|
@@ -548,6 +527,10 @@ class Dataset(DataSource, RefreshableMixin[scout_catalog.EnrichedDataset]):
|
|
|
548
527
|
)
|
|
549
528
|
|
|
550
529
|
|
|
530
|
+
@deprecated(
|
|
531
|
+
"poll_until_ingestion_completed() is deprecated and will be removed in a future release. "
|
|
532
|
+
"Instead, call poll_until_ingestion_completed() on individual DatasetFiles."
|
|
533
|
+
)
|
|
551
534
|
def poll_until_ingestion_completed(datasets: Iterable[Dataset], interval: timedelta = timedelta(seconds=1)) -> None:
|
|
552
535
|
"""Block until all dataset ingestions have completed (succeeded or failed).
|
|
553
536
|
|
|
@@ -562,7 +545,8 @@ def poll_until_ingestion_completed(datasets: Iterable[Dataset], interval: timede
|
|
|
562
545
|
errors = {}
|
|
563
546
|
for dataset in datasets:
|
|
564
547
|
try:
|
|
565
|
-
dataset.
|
|
548
|
+
for dataset_file in dataset.list_files():
|
|
549
|
+
dataset_file.poll_until_ingestion_completed(interval=interval)
|
|
566
550
|
except NominalIngestError as e:
|
|
567
551
|
errors[dataset.rid] = e
|
|
568
552
|
if errors:
|
|
@@ -611,12 +595,17 @@ def _create_dataset(
|
|
|
611
595
|
return client.create_dataset(auth_header, request)
|
|
612
596
|
|
|
613
597
|
|
|
614
|
-
def _create_dataflash_ingest_request(
|
|
598
|
+
def _create_dataflash_ingest_request(
|
|
599
|
+
s3_path: str,
|
|
600
|
+
target: ingest_api.DatasetIngestTarget,
|
|
601
|
+
tags: Mapping[str, str] | None = None,
|
|
602
|
+
) -> ingest_api.IngestRequest:
|
|
615
603
|
return ingest_api.IngestRequest(
|
|
616
604
|
ingest_api.IngestOptions(
|
|
617
605
|
dataflash=ingest_api.DataflashOpts(
|
|
618
606
|
source=ingest_api.IngestSource(s3=ingest_api.S3IngestSource(path=s3_path)),
|
|
619
607
|
target=target,
|
|
608
|
+
additional_file_tags={**tags} if tags else None,
|
|
620
609
|
)
|
|
621
610
|
),
|
|
622
611
|
)
|
|
@@ -7,7 +7,7 @@ from enum import Enum
|
|
|
7
7
|
from typing import Iterable, Mapping, Protocol, Sequence
|
|
8
8
|
|
|
9
9
|
from nominal_api import event
|
|
10
|
-
from typing_extensions import Self
|
|
10
|
+
from typing_extensions import Self
|
|
11
11
|
|
|
12
12
|
from nominal.core._clientsbunch import HasScoutParams
|
|
13
13
|
from nominal.core._utils.api_tools import HasRid, RefreshableMixin, rid_from_instance_or_string
|
|
@@ -45,11 +45,6 @@ class Event(HasRid, RefreshableMixin[event.Event]):
|
|
|
45
45
|
|
|
46
46
|
return resp[0]
|
|
47
47
|
|
|
48
|
-
@property
|
|
49
|
-
@deprecated("The uuid field of an event is deprecated and will be removed in a future release")
|
|
50
|
-
def uuid(self) -> str:
|
|
51
|
-
return self._uuid
|
|
52
|
-
|
|
53
48
|
def update(
|
|
54
49
|
self,
|
|
55
50
|
*,
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from typing import Mapping
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class NominalError(Exception):
|
|
5
|
+
"""Base class for Nominal exceptions."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class NominalIngestError(NominalError):
|
|
9
|
+
"""An error occurred during ingest."""
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class NominalIngestMultiError(NominalError):
|
|
13
|
+
"""Error(s) occurred during ingest.
|
|
14
|
+
|
|
15
|
+
Attributes:
|
|
16
|
+
----------
|
|
17
|
+
errors: A mapping of dataset RIDs to the errors that occurred during ingest.
|
|
18
|
+
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, rids_to_errors: Mapping[str, NominalIngestError]) -> None:
|
|
22
|
+
"""Initialize multi-error with the rids to error on."""
|
|
23
|
+
self.errors = rids_to_errors
|
|
24
|
+
|
|
25
|
+
def __str__(self) -> str:
|
|
26
|
+
"""String repr."""
|
|
27
|
+
return f"{len(self.errors)} errors occurred during ingest: {self.errors}"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class NominalIngestFailed(NominalIngestError):
|
|
31
|
+
"""The ingest failed."""
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class NominalMultipartUploadFailed(NominalError):
|
|
35
|
+
"""The multipart upload failed."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class NominalConfigError(NominalError):
|
|
39
|
+
"""An error occurred reading or writing the configuration."""
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class NominalMethodRemovedError(NominalError):
|
|
43
|
+
"""An error raised when a method has been deprecated and now removed.
|
|
44
|
+
Error informs users of the new method to use instead.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(self, original_method: str, instructions: str | None = None):
|
|
48
|
+
"""Initialize error with the method removed and method to use instead."""
|
|
49
|
+
self._original_method = original_method
|
|
50
|
+
self._instructions = instructions
|
|
51
|
+
|
|
52
|
+
def __str__(self) -> str:
|
|
53
|
+
"""String repr."""
|
|
54
|
+
base_msg = f"'{self._original_method}' was deprecated and has now been removed."
|
|
55
|
+
if self._instructions is None:
|
|
56
|
+
return f"{base_msg} Contact your Nominal Representative if you need this functionality."
|
|
57
|
+
else:
|
|
58
|
+
return f"{base_msg} To fix: {self._instructions}"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class NominalParameterRemovedError(NominalError):
|
|
62
|
+
"""An error raised when an parameter has been deprecated and now removed."""
|
|
63
|
+
|
|
64
|
+
def __init__(self, method_name: str, parameter_name: str, instructions: str | None = None):
|
|
65
|
+
"""Initialize error with the method removed and method to use instead."""
|
|
66
|
+
self._method_name = method_name
|
|
67
|
+
self._parameter_name = parameter_name
|
|
68
|
+
self._instructions = instructions
|
|
69
|
+
|
|
70
|
+
def __str__(self) -> str:
|
|
71
|
+
"""String repr."""
|
|
72
|
+
base_msg = (
|
|
73
|
+
f"Parameter '{self._parameter_name}' was deprecated and has now been removed from '{self._method_name}'."
|
|
74
|
+
)
|
|
75
|
+
if self._instructions is None:
|
|
76
|
+
return f"{base_msg} Contact your Nominal Representative if you need this functionality."
|
|
77
|
+
else:
|
|
78
|
+
return f"{base_msg} To fix: {self._instructions}"
|