diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b0a6003..ac2a2df 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -31,8 +31,8 @@ jobs: - name: Run linting run: | - uvx ruff format --check - uvx ruff check + uvx ruff format --check --exclude "docs/**" + uvx ruff check --exclude "docs/**" - name: Run tests run: | @@ -45,7 +45,7 @@ jobs: - name: Run docs generation run: | - uv run python docs-render.py + uv run python docs/render.py if [ -n "$(git status --porcelain docs/index.md)" ]; then echo "Error: docs/index.md has uncommitted changes after running render.py" echo "Please run 'python render.py' locally and commit the changes" diff --git a/README.md b/README.md index 4b4ec6d..b1d41af 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The `nortech-python` library is the official Python client for interacting with The `Nortech` class serves as the primary entry point for the library. It encapsulates the core functionalities and provides a unified interface to interact with the Nortech API. It has 3 main components: -- **Metadata**: Access and manage metadata such as workspaces, assets, divisions, units, devices, and signals. +- **Metadata**: Access and manage metadata such as workspaces, assets, divisions, units and signals. - **Datatools**: Fetch and manipulate signal data, supporting both Pandas and Polars DataFrames, time window queries, and signal filtering. - **Derivers**: Create and manage derivers, which allow computation of new signals based on existing ones. This includes creating deriver schemas, deploying derivers, managing configurations, and testing locally. @@ -89,145 +89,4 @@ These functions return a `PaginatedResponse` object containing 3 functions: `PaginatedResponse` also has a `next_pagination_options` method that returns a `PaginationOptions`, which can also be used to fetch the next page. -## Examples - -### nortech.datatools - -To get a DataFrame with the requested signals: - -1. Go to your `Signal Search` interface. -2. Select the desired signals. -3. Select the `DataTools` exported columns and copy the resulting `search_json`. -4. Use the `signals` field and speficy a `TimeWindow` as in the examples bellow. - -##### Pandas DataFrame - -In order to get a [pandas](https://pandas.pydata.org/docs/) DataFrame use the `get_df` handler: - -```python -from datetime import datetime - -from nortech import Nortech -from nortech.core.values.signal import SignalInput, SignalInputDict -from nortech.datatools.values.windowing import TimeWindow - -# Initialize the Nortech client -nortech = Nortech() - -# Define signals to download -signal1: SignalInputDict = { - "workspace": "workspace1", - "asset": "asset1", - "division": "division1", - "unit": "unit1", - "signal": "signal1", -} -signal2 = 789 # Signal ID -signal3 = SignalInput(workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2") - -# Define the time window for data download -my_time_window = TimeWindow(start=datetime(2023, 1, 1), end=datetime(2023, 1, 31)) - -# Call the get_df function -df = nortech.datatools.pandas.get_df( - signals=[signal1, signal2, signal3], - time_window=my_time_window, -) - -print(df.columns) -# Output -# [ -# 'timestamp', -# 'workspace_1/asset_1/division_1/unit_1/signal_1', -# 'workspace_1/asset_1/division_1/unit_1/signal_2', -# 'workspace_2/asset_2/division_2/unit_2/signal_3' -# ] -``` - -##### Polars DataFrame - -In order to get a [polars](https://pola-rs.github.io/polars/py-polars/html/reference/) DataFrame use the `get_df`: - -```python -from datetime import datetime - -from nortech import Nortech -from nortech.core.values.signal import SignalInput, SignalInputDict -from nortech.datatools.values.windowing import TimeWindow - -# Initialize the Nortech client -nortech = Nortech() - -# Define signals to download -signal1: SignalInputDict = { - "workspace": "workspace1", - "asset": "asset1", - "division": "division1", - "unit": "unit1", - "signal": "signal1", -} -signal2 = 789 # Signal ID -signal3 = SignalInput(workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2") - -# Define the time window for data download -my_time_window = TimeWindow(start=datetime(2023, 1, 1), end=datetime(2023, 1, 31)) - -# Call the get_df function -polars_df = nortech.datatools.polars.get_df( - signals=[signal1, signal2, signal3], - time_window=my_time_window, -) - -print(polars_df.columns) -# Output: -# [ -# 'timestamp', -# 'workspace_1/asset_1/division_1/unit_1/signal_1', -# 'workspace_1/asset_1/division_1/unit_1/signal_2', -# 'workspace_2/asset_2/division_2/unit_2/signal_3' -# ] -``` - -##### Polars LazyFrame - -In order to get a [polars](https://pola-rs.github.io/polars/py-polars/html/reference/) LazyFrame use the `get_lazy_df`: - -```python -from datetime import datetime - -from nortech import Nortech -from nortech.core.values.signal import SignalInput, SignalInputDict -from nortech.datatools.values.windowing import TimeWindow - -# Initialize the Nortech client -nortech = Nortech() - -# Define signals to download -signal1: SignalInputDict = { - "workspace": "workspace1", - "asset": "asset1", - "division": "division1", - "unit": "unit1", - "signal": "signal1", -} -signal2 = 789 # Signal ID -signal3 = SignalInput(workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2") - -# Define the time window for data download -my_time_window = TimeWindow(start=datetime(2023, 1, 1), end=datetime(2023, 1, 31)) - -# Call the get_lazy_df function -lazy_polars_df = nortech.datatools.polars.get_lazy_df( - signals=[signal1, signal2, signal3], - time_window=my_time_window, -) - -print(lazy_polars_df.columns) -# Output: -# [ -# 'timestamp', -# 'workspace_1/asset_1/division_1/unit_1/signal_1', -# 'workspace_1/asset_1/division_1/unit_1/signal_2', -# 'workspace_2/asset_2/division_2/unit_2/signal_3' -# ] -``` +For comprehensive documentation including all available methods, parameters, and detailed examples, see the [Documentation](docs/index.md). diff --git a/docs/examples/datatools/Download/download_data.py b/docs/examples/datatools/Download/download_data.py new file mode 100644 index 0000000..c0e79c6 --- /dev/null +++ b/docs/examples/datatools/Download/download_data.py @@ -0,0 +1,38 @@ +from datetime import datetime + +from nortech import Nortech +from nortech.datatools.values.windowing import TimeWindow +from nortech.metadata.values.signal import SignalInput, SignalInputDict + +# Initialize the Nortech client +nortech = Nortech() + +# Define signals to download +signal1: SignalInputDict = { + "workspace": "workspace1", + "asset": "asset1", + "division": "division1", + "unit": "unit1", + "signal": "signal1", +} +signal2 = 789 # Signal ID +signal3 = SignalInput(workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2") + +fetched_signals = nortech.metadata.signal.list( # Fetched signals + {"workspace": "workspace3", "asset": "asset3", "division": "division3", "unit": "unit3"} +).data + +# Define the time window for data download +my_time_window = TimeWindow(start=datetime(2023, 1, 1), end=datetime(2023, 1, 31)) + +# Specify the output path and file format +output_path = "path/to/output" +file_format = "parquet" + +# Call the download_data function with manually defined signals or fetched signals +nortech.datatools.download.download_data( + signals=[signal1, signal2, signal3] + fetched_signals, + time_window=my_time_window, + output_path=output_path, + file_format=file_format, +) diff --git a/docs/examples/datatools/Pandas/get_df.py b/docs/examples/datatools/Pandas/get_df.py new file mode 100644 index 0000000..124c6be --- /dev/null +++ b/docs/examples/datatools/Pandas/get_df.py @@ -0,0 +1,42 @@ +from datetime import datetime + +from nortech import Nortech +from nortech.datatools.values.windowing import TimeWindow +from nortech.metadata.values.signal import SignalInput, SignalInputDict + +# Initialize the Nortech client +nortech = Nortech() + +# Define signals to download +signal1: SignalInputDict = { + "workspace": "workspace1", + "asset": "asset1", + "division": "division1", + "unit": "unit1", + "signal": "signal1", +} +signal2 = 789 # Signal ID +signal3 = SignalInput(workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2") + +fetched_signals = nortech.metadata.signal.list( # Fetched signals + {"workspace": "workspace3", "asset": "asset3", "division": "division3", "unit": "unit3"} +).data + +# Define the time window for data download +my_time_window = TimeWindow(start=datetime(2023, 1, 1), end=datetime(2023, 1, 31)) + +# Call the get_df function with manually defined signals or fetched signals +df = nortech.datatools.pandas.get_df( + signals=[signal1, signal2, signal3] + fetched_signals, + time_window=my_time_window, +) + +print(df.columns) +# [ +# "timestamp", +# "workspace_1/asset_1/division_1/unit_1/signal_1", +# "workspace_1/asset_1/division_1/unit_1/signal_2", +# "workspace_2/asset_2/division_2/unit_2/signal_3", +# "workspace_3/asset_3/division_3/unit_3/signal_4", +# "workspace_3/asset_3/division_3/unit_3/signal_5", +# ] diff --git a/docs/examples/datatools/Polars/get_df.py b/docs/examples/datatools/Polars/get_df.py new file mode 100644 index 0000000..80cea8c --- /dev/null +++ b/docs/examples/datatools/Polars/get_df.py @@ -0,0 +1,42 @@ +from datetime import datetime + +from nortech import Nortech +from nortech.datatools.values.windowing import TimeWindow +from nortech.metadata.values.signal import SignalInput, SignalInputDict + +# Initialize the Nortech client +nortech = Nortech() + +# Define signals to download +signal1: SignalInputDict = { + "workspace": "workspace1", + "asset": "asset1", + "division": "division1", + "unit": "unit1", + "signal": "signal1", +} +signal2 = 789 # Signal ID +signal3 = SignalInput(workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2") + +fetched_signals = nortech.metadata.signal.list( # Fetched signals + {"workspace": "workspace3", "asset": "asset3", "division": "division3", "unit": "unit3"} +).data + +# Define the time window for data download +my_time_window = TimeWindow(start=datetime(2023, 1, 1), end=datetime(2023, 1, 31)) + +# Call the get_df function with manually defined signals or fetched signals +df = nortech.datatools.polars.get_df( + signals=[signal1, signal2, signal3] + fetched_signals, + time_window=my_time_window, +) + +print(df.columns) +# [ +# "timestamp", +# "workspace_1/asset_1/division_1/unit_1/signal_1", +# "workspace_1/asset_1/division_1/unit_1/signal_2", +# "workspace_2/asset_2/division_2/unit_2/signal_3", +# "workspace_3/asset_3/division_3/unit_3/signal_4", +# "workspace_3/asset_3/division_3/unit_3/signal_5", +# ] diff --git a/docs/examples/datatools/Polars/get_lazy_df.py b/docs/examples/datatools/Polars/get_lazy_df.py new file mode 100644 index 0000000..1ce81ec --- /dev/null +++ b/docs/examples/datatools/Polars/get_lazy_df.py @@ -0,0 +1,42 @@ +from datetime import datetime + +from nortech import Nortech +from nortech.datatools.values.windowing import TimeWindow +from nortech.metadata.values.signal import SignalInput, SignalInputDict + +# Initialize the Nortech client +nortech = Nortech() + +# Define signals to download +signal1: SignalInputDict = { + "workspace": "workspace1", + "asset": "asset1", + "division": "division1", + "unit": "unit1", + "signal": "signal1", +} +signal2 = 789 # Signal ID +signal3 = SignalInput(workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2") + +fetched_signals = nortech.metadata.signal.list( # Fetched signals + {"workspace": "workspace3", "asset": "asset3", "division": "division3", "unit": "unit3"} +).data + +# Define the time window for data download +my_time_window = TimeWindow(start=datetime(2023, 1, 1), end=datetime(2023, 1, 31)) + +# Call the get_df function with manually defined signals or fetched signals +df = nortech.datatools.polars.get_lazy_df( + signals=[signal1, signal2, signal3] + fetched_signals, + time_window=my_time_window, +) + +print(df.columns) +# [ +# "timestamp", +# "workspace_1/asset_1/division_1/unit_1/signal_1", +# "workspace_1/asset_1/division_1/unit_1/signal_2", +# "workspace_2/asset_2/division_2/unit_2/signal_3", +# "workspace_3/asset_3/division_3/unit_3/signal_4", +# "workspace_3/asset_3/division_3/unit_3/signal_5", +# ] diff --git a/docs/examples/derivers/Derivers/__init__.py b/docs/examples/derivers/Derivers/__init__.py new file mode 100644 index 0000000..d0c2427 --- /dev/null +++ b/docs/examples/derivers/Derivers/__init__.py @@ -0,0 +1,55 @@ +# To define a deriver, you need to create a class that inherits from the Deriver class. +# The class must have two inner classes: Inputs and Outputs. +# The Inputs class must inherit from DeriverInputs and the Outputs class must inherit from DeriverOutputs. +# The Inputs class must define the inputs of the deriver. +# The Outputs class must define the outputs of the deriver. +# The run method must be defined and return a bytewax stream. + +from __future__ import annotations + +import bytewax.operators as op + +from nortech.derivers import Deriver, DeriverInput, DeriverInputs, DeriverOutput, DeriverOutputs + + +class MyDeriver(Deriver): + class Inputs(DeriverInputs): + input_1: float | None = DeriverInput( + workspace="workspace1", asset="asset1", division="division1", unit="unit1", signal="signal1" + ) + input_2: float | None = DeriverInput( + workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2" + ) + + class Outputs(DeriverOutputs): + output_1: float = DeriverOutput( + workspace="workspace1", + asset="asset1", + division="division1", + unit="unit1", + signal="new_signal1", + description="output_1", + long_description="output_1_long_description", + physical_unit="m/s", + ) + output_2: str = DeriverOutput( + workspace="workspace2", + asset="asset2", + division="division2", + unit="unit2", + signal="new_signal2", + description="output_2", + long_description="output_2_long_description", + physical_unit="m/s", + ) + + def run(self, inputs: op.Stream[Inputs]) -> op.Stream[Outputs]: + return op.map( + "", + inputs, + lambda _input: self.Outputs( + timestamp=_input.timestamp, + output_1=_input.input_1 or 0, + output_2=str(_input.input_2), + ), + ) diff --git a/docs/examples/derivers/Derivers/create.py b/docs/examples/derivers/Derivers/create.py new file mode 100644 index 0000000..cc49a36 --- /dev/null +++ b/docs/examples/derivers/Derivers/create.py @@ -0,0 +1,75 @@ +from datetime import datetime, timezone + +from nortech import Nortech +from nortech.derivers import Deriver + + +# Define Deriver +class MyDeriver(Deriver): ... + + +nortech = Nortech() + +derivers = nortech.derivers.create(MyDeriver, start_at=datetime.now(timezone.utc), description="my-description") +print(derivers) +# DeployedDeriver( +# deriver=MyDeriver, +# description="my-description", +# start_at=None, +# inputs=[ +# SignalOutput( +# id=1, +# name="input_1", +# description="input_1", +# long_description="input_1_long_description", +# data_type="float", +# physical_unit="m/s", +# created_at="2025-01-01T12:00:00Z", +# updated_at="2025-01-01T12:00:00Z", +# workspace=MetadataOutput( +# id=1, +# name="workspace1", +# ), +# asset=MetadataOutput( +# id=1, +# name="asset1", +# ), +# division=MetadataOutput( +# id=1, +# name="division1", +# ), +# unit=MetadataOutput( +# id=1, +# name="unit1", +# ), +# ), +# ], +# outputs=[ +# SignalOutput( +# id=2, +# name="output_1", +# description="output_1", +# long_description="output_1_long_description", +# data_type="float", +# physical_unit="m/s", +# created_at="2025-01-01T12:00:00Z", +# updated_at="2025-01-01T12:00:00Z", +# workspace=MetadataOutput( +# id=1, +# name="workspace1", +# ), +# asset=MetadataOutput( +# id=1, +# name="asset1", +# ), +# division=MetadataOutput( +# id=1, +# name="division1", +# ), +# unit=MetadataOutput( +# id=1, +# name="unit1", +# ), +# ), +# ] +# ) diff --git a/docs/examples/derivers/Derivers/get.py b/docs/examples/derivers/Derivers/get.py new file mode 100644 index 0000000..bf279b2 --- /dev/null +++ b/docs/examples/derivers/Derivers/get.py @@ -0,0 +1,76 @@ +from nortech import Nortech +from nortech.derivers import Deriver + + +# Define Deriver +class MyDeriver(Deriver): ... + + +nortech = Nortech() + +# Get deriver by class or class name +derivers = nortech.derivers.get(MyDeriver) +derivers = nortech.derivers.get("MyDeriver") + +print(derivers) +# DeployedDeriver( +# deriver=MyDeriver, +# description="my-description", +# start_at="2025-01-01T12:00:00Z", +# inputs=[ +# SignalOutput( +# id=1, +# name="input_1", +# description="input_1", +# long_description="input_1_long_description", +# data_type="float", +# physical_unit="m/s", +# created_at="2025-01-01T12:00:00Z", +# updated_at="2025-01-01T12:00:00Z", +# workspace=MetadataOutput( +# id=1, +# name="workspace1", +# ), +# asset=MetadataOutput( +# id=1, +# name="asset1", +# ), +# division=MetadataOutput( +# id=1, +# name="division1", +# ), +# unit=MetadataOutput( +# id=1, +# name="unit1", +# ), +# ), +# ], +# outputs=[ +# SignalOutput( +# id=2, +# name="output_1", +# description="output_1", +# long_description="output_1_long_description", +# data_type="float", +# physical_unit="m/s", +# created_at="2025-01-01T12:00:00Z", +# updated_at="2025-01-01T12:00:00Z", +# workspace=MetadataOutput( +# id=1, +# name="workspace1", +# ), +# asset=MetadataOutput( +# id=1, +# name="asset1", +# ), +# division=MetadataOutput( +# id=1, +# name="division1", +# ), +# unit=MetadataOutput( +# id=1, +# name="unit1", +# ), +# ), +# ] +# ) diff --git a/docs/examples/derivers/Derivers/list.py b/docs/examples/derivers/Derivers/list.py new file mode 100644 index 0000000..9b2dd00 --- /dev/null +++ b/docs/examples/derivers/Derivers/list.py @@ -0,0 +1,23 @@ +from nortech import Nortech +from nortech.derivers import Deriver + + +# Define Deriver +class MyDeriver(Deriver): ... + + +nortech = Nortech() + +derivers = nortech.derivers.list() +print(derivers) +# PaginatedResponse( +# size=1, +# next=None, +# data=[ +# DeployedDeriverList( +# deriver=MyDeriver, +# description="my-description", +# start_at=None, +# ) +# ], +# ) diff --git a/docs/examples/derivers/Derivers/run_locally_with_df.py b/docs/examples/derivers/Derivers/run_locally_with_df.py new file mode 100644 index 0000000..d2043b2 --- /dev/null +++ b/docs/examples/derivers/Derivers/run_locally_with_df.py @@ -0,0 +1,38 @@ +from datetime import timezone + +import pandas as pd + +from nortech import Nortech +from nortech.derivers import Deriver + + +class MyDeriver(Deriver): ... + + +nortech = Nortech() + +# Create input DataFrame +df = pd.DataFrame( + { + "timestamp": pd.date_range(start="2023-01-01", periods=100, freq="s", tz=timezone.utc), + "input_signal": [float(i) for i in range(100)], + } +).set_index("timestamp") + +# Run the deriver locally +result_df = nortech.derivers.run_locally_with_df(MyDeriver, df, batch_size=5000) + +print(result_df) +# output_signal +# timestamp +# 2023-01-01 00:00:00+00:00 0.0 +# 2023-01-01 00:00:01+00:00 2.0 +# 2023-01-01 00:00:02+00:00 4.0 +# 2023-01-01 00:00:03+00:00 6.0 +# 2023-01-01 00:00:04+00:00 8.0 +# ... ... +# 2023-01-01 00:01:35+00:00 190.0 +# 2023-01-01 00:01:36+00:00 192.0 +# 2023-01-01 00:01:37+00:00 194.0 +# 2023-01-01 00:01:38+00:00 196.0 +# 2023-01-01 00:01:39+00:00 198.0 diff --git a/docs/examples/derivers/Derivers/run_locally_with_source_data.py b/docs/examples/derivers/Derivers/run_locally_with_source_data.py new file mode 100644 index 0000000..00e3087 --- /dev/null +++ b/docs/examples/derivers/Derivers/run_locally_with_source_data.py @@ -0,0 +1,40 @@ +from datetime import datetime, timezone + +import pandas as pd + +from nortech import Nortech +from nortech.derivers import Deriver, TimeWindow + + +class MyDeriver(Deriver): ... + + +nortech = Nortech() + +# Create input DataFrame or use nortech.datatools to get data +df = pd.DataFrame( + { + "timestamp": pd.date_range(start="2023-01-01", periods=100, freq="s", tz=timezone.utc), + "input_signal": [float(i) for i in range(100)], + } +).set_index("timestamp") + +# Run the deriver locally +result_df = nortech.derivers.run_locally_with_source_data( + MyDeriver, time_window=TimeWindow(start=datetime.now(timezone.utc), end=datetime.now(timezone.utc)) +) + +print(result_df) +# output_signal +# timestamp +# 2023-01-01 00:00:00+00:00 0.0 +# 2023-01-01 00:00:01+00:00 2.0 +# 2023-01-01 00:00:02+00:00 4.0 +# 2023-01-01 00:00:03+00:00 6.0 +# 2023-01-01 00:00:04+00:00 8.0 +# ... ... +# 2023-01-01 00:01:35+00:00 190.0 +# 2023-01-01 00:01:36+00:00 192.0 +# 2023-01-01 00:01:37+00:00 194.0 +# 2023-01-01 00:01:38+00:00 196.0 +# 2023-01-01 00:01:39+00:00 198.0 diff --git a/docs/examples/derivers/Derivers/update.py b/docs/examples/derivers/Derivers/update.py new file mode 100644 index 0000000..31f91f6 --- /dev/null +++ b/docs/examples/derivers/Derivers/update.py @@ -0,0 +1,75 @@ +from datetime import datetime, timezone + +from nortech import Nortech +from nortech.derivers import Deriver + + +# Define Deriver +class MyDeriver(Deriver): ... + + +nortech = Nortech() + +derivers = nortech.derivers.update(MyDeriver, start_at=datetime.now(timezone.utc), description="my-description") +print(derivers) +# DeployedDeriver( +# deriver=MyDeriver, +# description="my-description", +# start_at=None, +# inputs=[ +# SignalOutput( +# id=1, +# name="input_1", +# description="input_1", +# long_description="input_1_long_description", +# data_type="float", +# physical_unit="m/s", +# created_at="2025-01-01T12:00:00Z", +# updated_at="2025-01-01T12:00:00Z", +# workspace=MetadataOutput( +# id=1, +# name="workspace1", +# ), +# asset=MetadataOutput( +# id=1, +# name="asset1", +# ), +# division=MetadataOutput( +# id=1, +# name="division1", +# ), +# unit=MetadataOutput( +# id=1, +# name="unit1", +# ), +# ), +# ], +# outputs=[ +# SignalOutput( +# id=2, +# name="output_1", +# description="output_1", +# long_description="output_1_long_description", +# data_type="float", +# physical_unit="m/s", +# created_at="2025-01-01T12:00:00Z", +# updated_at="2025-01-01T12:00:00Z", +# workspace=MetadataOutput( +# id=1, +# name="workspace1", +# ), +# asset=MetadataOutput( +# id=1, +# name="asset1", +# ), +# division=MetadataOutput( +# id=1, +# name="division1", +# ), +# unit=MetadataOutput( +# id=1, +# name="unit1", +# ), +# ), +# ] +# ) diff --git a/docs/examples/metadata/Asset/get.py b/docs/examples/metadata/Asset/get.py new file mode 100644 index 0000000..f239390 --- /dev/null +++ b/docs/examples/metadata/Asset/get.py @@ -0,0 +1,26 @@ +from nortech import Nortech +from nortech.metadata.values.asset import AssetInput + +nortech = Nortech() + +# Get by ID +asset = nortech.metadata.asset.get(123) + +# Get by input dict +asset = nortech.metadata.asset.get({"workspace": "my-workspace", "asset": "my-asset"}) + +# Get by AssetInput pydantic object +asset = nortech.metadata.asset.get(AssetInput(workspace="my-workspace", asset="my-asset")) + +print(asset) +# AssetOutput( +# id=123, +# name="my-asset", +# description="my-description", +# created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), +# updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), +# workspace=MetadataOutput( +# id=123, +# name="my-workspace", +# ) +# ) diff --git a/docs/examples/metadata/Asset/list.py b/docs/examples/metadata/Asset/list.py new file mode 100644 index 0000000..4c8410b --- /dev/null +++ b/docs/examples/metadata/Asset/list.py @@ -0,0 +1,38 @@ +from nortech import Nortech +from nortech.metadata.values.pagination import PaginationOptions +from nortech.metadata.values.workspace import WorkspaceInput + +nortech = Nortech() + +# List all assets in a workspace +assets = nortech.metadata.asset.list(123) # using workspace ID + +# List with pagination +assets = nortech.metadata.asset.list( + "my-workspace", # using workspace name + PaginationOptions(size=10, sortBy="name"), +) + +# Using WorkspaceInputDict dictionary +assets = nortech.metadata.asset.list({"workspace": "my-workspace"}) + +# Using WorkspaceInput pydantic object +assets = nortech.metadata.asset.list(WorkspaceInput(workspace="my-workspace")) + +print(assets) +# PaginatedResponse( +# size=2, +# next=None, +# data=[ +# AssetListOutput( +# id=1, +# name="my-asset", +# description="my-description" +# ), +# AssetListOutput( +# id=2, +# name="another-asset", +# description="another-description" +# ) +# ] +# ) diff --git a/docs/examples/metadata/Division/get.py b/docs/examples/metadata/Division/get.py new file mode 100644 index 0000000..b95d3e0 --- /dev/null +++ b/docs/examples/metadata/Division/get.py @@ -0,0 +1,32 @@ +from nortech import Nortech +from nortech.metadata.values.division import DivisionInput + +nortech = Nortech() + +# Get by ID +division = nortech.metadata.division.get(123) + +# Get by input dict +division = nortech.metadata.division.get({"workspace": "my-workspace", "asset": "my-asset", "division": "my-division"}) + +# Get by DivisionInput pydantic object +division = nortech.metadata.division.get( + DivisionInput(workspace="my-workspace", asset="my-asset", division="my-division") +) + +print(division) +# DivisionOutput( +# id=123, +# name="my-division", +# description="my-description", +# created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), +# updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), +# workspace=MetadataOutput( +# id=123, +# name="my-workspace" +# ), +# asset=MetadataOutput( +# id=456, +# name="my-asset" +# ) +# ) diff --git a/docs/examples/metadata/Division/list.py b/docs/examples/metadata/Division/list.py new file mode 100644 index 0000000..664c87a --- /dev/null +++ b/docs/examples/metadata/Division/list.py @@ -0,0 +1,35 @@ +from nortech import Nortech +from nortech.metadata.values.asset import AssetInput +from nortech.metadata.values.pagination import PaginationOptions + +nortech = Nortech() + +# List all divisions in an asset +divisions = nortech.metadata.division.list(123) # using asset ID + +# List with pagination +divisions = nortech.metadata.division.list( + {"workspace": "my-workspace", "asset": "my-asset"}, # using AssetInputDict + PaginationOptions(size=10, sortBy="name"), +) + +# Using AssetInput pydantic object +divisions = nortech.metadata.division.list(AssetInput(workspace="my-workspace", asset="my-asset")) + +print(divisions) +# PaginatedResponse( +# size=2, +# next=None, +# data=[ +# DivisionListOutput( +# id=1, +# name="my-division", +# description="my-description" +# ), +# DivisionListOutput( +# id=2, +# name="another-division", +# description="another-description" +# ) +# ] +# ) diff --git a/docs/examples/metadata/Division/list_by_workspace_id.py b/docs/examples/metadata/Division/list_by_workspace_id.py new file mode 100644 index 0000000..8cb86a0 --- /dev/null +++ b/docs/examples/metadata/Division/list_by_workspace_id.py @@ -0,0 +1,28 @@ +from nortech import Nortech +from nortech.metadata.values.pagination import PaginationOptions + +nortech = Nortech() + +# List all divisions in a workspace +divisions = nortech.metadata.division.list_by_workspace_id(123) + +# List with pagination +divisions = nortech.metadata.division.list_by_workspace_id(123, PaginationOptions(size=10, sortBy="name")) + +print(divisions) +# PaginatedResponse( +# size=2, +# next=None, +# data=[ +# DivisionListOutput( +# id=1, +# name="my-division", +# description="my-description" +# ), +# DivisionListOutput( +# id=2, +# name="another-division", +# description="another-description" +# ) +# ] +# ) diff --git a/docs/examples/metadata/Signal/get.py b/docs/examples/metadata/Signal/get.py new file mode 100644 index 0000000..5db7845 --- /dev/null +++ b/docs/examples/metadata/Signal/get.py @@ -0,0 +1,52 @@ +from nortech import Nortech +from nortech.metadata.values.signal import SignalInput + +nortech = Nortech() + +# Get by ID +signal = nortech.metadata.signal.get(123) + +# Get unit signal by input dict +signal = nortech.metadata.signal.get( + { + "workspace": "my-workspace", + "asset": "my-asset", + "division": "my-division", + "unit": "my-unit", + "signal": "my-signal", + } +) + + +# Get by SignalInput pydantic object +signal = nortech.metadata.signal.get( + SignalInput(workspace="my-workspace", asset="my-asset", division="my-division", unit="my-unit", signal="my-signal") +) + +print(signal) +# SignalOutput( +# id=123, +# name="my-signal", +# physical_unit="°C", +# data_type="float64", +# description="Temperature sensor", +# long_description="Main temperature sensor for the unit", +# created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), +# updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), +# workspace=MetadataOutput( +# id=123, +# name="my-workspace" +# ), +# asset=MetadataOutput( +# id=456, +# name="my-asset" +# ), +# division=MetadataOutput( +# id=789, +# name="my-division" +# ), +# unit=MetadataOutput( +# id=101, +# name="my-unit" +# ) +# ) diff --git a/docs/examples/metadata/Signal/list.py b/docs/examples/metadata/Signal/list.py new file mode 100644 index 0000000..d6530c1 --- /dev/null +++ b/docs/examples/metadata/Signal/list.py @@ -0,0 +1,43 @@ +from nortech import Nortech +from nortech.metadata.values.pagination import PaginationOptions +from nortech.metadata.values.unit import UnitInput + +nortech = Nortech() + +# List all signals in a unit +signals = nortech.metadata.signal.list(123) # using unit ID + +# List unit signals with pagination +signals = nortech.metadata.signal.list( + {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division", "unit": "my-unit"}, + PaginationOptions(size=10, sortBy="name"), +) + +# Using UnitInput pydantic object +signals = nortech.metadata.signal.list( + UnitInput(workspace="my-workspace", asset="my-asset", division="my-division", unit="my-unit") +) + +print(signals) +# PaginatedResponse( +# size=2, +# next=None, +# data=[ +# SignalListOutput( +# id=1, +# name="my-signal", +# physical_unit="°C", +# data_type="float64", +# description="Temperature sensor", +# long_description="Main temperature sensor for the unit" +# ), +# SignalListOutput( +# id=2, +# name="another-signal", +# physical_unit="bar", +# data_type="float64", +# description="Pressure sensor", +# long_description="Main pressure sensor for the unit" +# ) +# ] +# ) diff --git a/docs/examples/metadata/Signal/list_by_asset_id.py b/docs/examples/metadata/Signal/list_by_asset_id.py new file mode 100644 index 0000000..41b55c7 --- /dev/null +++ b/docs/examples/metadata/Signal/list_by_asset_id.py @@ -0,0 +1,34 @@ +from nortech import Nortech +from nortech.metadata.values.pagination import PaginationOptions + +nortech = Nortech() + +# List all signals in an asset +signals = nortech.metadata.signal.list_by_asset_id(123) + +# List with pagination +signals = nortech.metadata.signal.list_by_asset_id(123, PaginationOptions(size=10, sortBy="name")) + +print(signals) +# PaginatedResponse( +# size=2, +# next=None, +# data=[ +# SignalListOutput( +# id=1, +# name="my-signal", +# physical_unit="°C", +# data_type="float64", +# description="Temperature sensor", +# long_description="Main temperature sensor for the unit" +# ), +# SignalListOutput( +# id=2, +# name="another-signal", +# physical_unit="bar", +# data_type="float64", +# description="Pressure sensor", +# long_description="Main pressure sensor for the unit" +# ) +# ] +# ) diff --git a/docs/examples/metadata/Signal/list_by_division_id.py b/docs/examples/metadata/Signal/list_by_division_id.py new file mode 100644 index 0000000..a9e6f67 --- /dev/null +++ b/docs/examples/metadata/Signal/list_by_division_id.py @@ -0,0 +1,34 @@ +from nortech import Nortech +from nortech.metadata.values.pagination import PaginationOptions + +nortech = Nortech() + +# List all signals in a division +signals = nortech.metadata.signal.list_by_division_id(123) + +# List with pagination +signals = nortech.metadata.signal.list_by_division_id(123, PaginationOptions(size=10, sortBy="name")) + +print(signals) +# PaginatedResponse( +# size=2, +# next=None, +# data=[ +# SignalListOutput( +# id=1, +# name="my-signal", +# physical_unit="°C", +# data_type="float64", +# description="Temperature sensor", +# long_description="Main temperature sensor for the unit" +# ), +# SignalListOutput( +# id=2, +# name="another-signal", +# physical_unit="bar", +# data_type="float64", +# description="Pressure sensor", +# long_description="Main pressure sensor for the unit" +# ) +# ] +# ) diff --git a/docs/examples/metadata/Signal/list_by_workspace_id.py b/docs/examples/metadata/Signal/list_by_workspace_id.py new file mode 100644 index 0000000..5d8b537 --- /dev/null +++ b/docs/examples/metadata/Signal/list_by_workspace_id.py @@ -0,0 +1,34 @@ +from nortech import Nortech +from nortech.metadata.values.pagination import PaginationOptions + +nortech = Nortech() + +# List all signals in a workspace +signals = nortech.metadata.signal.list_by_workspace_id(123) + +# List with pagination +signals = nortech.metadata.signal.list_by_workspace_id(123, PaginationOptions(size=10, sortBy="name")) + +print(signals) +# PaginatedResponse( +# size=2, +# next=None, +# data=[ +# SignalListOutput( +# id=1, +# name="my-signal", +# physical_unit="°C", +# data_type="float64", +# description="Temperature sensor", +# long_description="Main temperature sensor for the unit" +# ), +# SignalListOutput( +# id=2, +# name="another-signal", +# physical_unit="bar", +# data_type="float64", +# description="Pressure sensor", +# long_description="Main pressure sensor for the unit" +# ) +# ] +# ) diff --git a/docs/examples/metadata/Unit/get.py b/docs/examples/metadata/Unit/get.py new file mode 100644 index 0000000..b078c0d --- /dev/null +++ b/docs/examples/metadata/Unit/get.py @@ -0,0 +1,37 @@ +from nortech import Nortech +from nortech.metadata.values.unit import UnitInput + +nortech = Nortech() + +# Get by ID +unit = nortech.metadata.unit.get(123) + +# Get by input dict +unit = nortech.metadata.unit.get( + {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division", "unit": "my-unit"} +) + +# Get by UnitInput pydantic object +unit = nortech.metadata.unit.get( + UnitInput(workspace="my-workspace", asset="my-asset", division="my-division", unit="my-unit") +) + +print(unit) +# UnitOutput( +# id=123, +# name="my-unit", +# created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), +# updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), +# workspace=MetadataOutput( +# id=123, +# name="my-workspace" +# ), +# asset=MetadataOutput( +# id=456, +# name="my-asset" +# ), +# division=MetadataOutput( +# id=789, +# name="my-division" +# ) +# ) diff --git a/docs/examples/metadata/Unit/list.py b/docs/examples/metadata/Unit/list.py new file mode 100644 index 0000000..dfff7c2 --- /dev/null +++ b/docs/examples/metadata/Unit/list.py @@ -0,0 +1,33 @@ +from nortech import Nortech +from nortech.metadata.values.division import DivisionInput +from nortech.metadata.values.pagination import PaginationOptions + +nortech = Nortech() + +# List all units in a division +units = nortech.metadata.unit.list(123) # using division ID + +# List with pagination +units = nortech.metadata.unit.list( + {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division"}, # using DivisionInputDict + PaginationOptions(size=10, sortBy="name"), +) + +# Using DivisionInput pydantic object +units = nortech.metadata.unit.list(DivisionInput(workspace="my-workspace", asset="my-asset", division="my-division")) + +print(units) +# PaginatedResponse( +# size=2, +# next=None, +# data=[ +# UnitListOutput( +# id=1, +# name="my-unit" +# ), +# UnitListOutput( +# id=2, +# name="another-unit" +# ) +# ] +# ) diff --git a/docs/examples/metadata/Unit/list_by_asset_id.py b/docs/examples/metadata/Unit/list_by_asset_id.py new file mode 100644 index 0000000..fcaad9a --- /dev/null +++ b/docs/examples/metadata/Unit/list_by_asset_id.py @@ -0,0 +1,26 @@ +from nortech import Nortech +from nortech.metadata.values.pagination import PaginationOptions + +nortech = Nortech() + +# List all units in an asset +units = nortech.metadata.unit.list_by_asset_id(123) + +# List with pagination +units = nortech.metadata.unit.list_by_asset_id(123, PaginationOptions(size=10, sortBy="name")) + +print(units) +# PaginatedResponse( +# size=2, +# next=None, +# data=[ +# UnitListOutput( +# id=1, +# name="my-unit" +# ), +# UnitListOutput( +# id=2, +# name="another-unit" +# ) +# ] +# ) diff --git a/docs/examples/metadata/Unit/list_by_workspace_id.py b/docs/examples/metadata/Unit/list_by_workspace_id.py new file mode 100644 index 0000000..f87bdc5 --- /dev/null +++ b/docs/examples/metadata/Unit/list_by_workspace_id.py @@ -0,0 +1,26 @@ +from nortech import Nortech +from nortech.metadata.values.pagination import PaginationOptions + +nortech = Nortech() + +# List all units in a workspace +units = nortech.metadata.unit.list_by_workspace_id(123) + +# List with pagination +units = nortech.metadata.unit.list_by_workspace_id(123, PaginationOptions(size=10, sortBy="name")) + +print(units) +# PaginatedResponse( +# size=2, +# next=None, +# data=[ +# UnitListOutput( +# id=1, +# name="my-unit" +# ), +# UnitListOutput( +# id=2, +# name="another-unit" +# ) +# ] +# ) diff --git a/docs/examples/metadata/Workspace/get.py b/docs/examples/metadata/Workspace/get.py new file mode 100644 index 0000000..27fa237 --- /dev/null +++ b/docs/examples/metadata/Workspace/get.py @@ -0,0 +1,25 @@ +from nortech import Nortech +from nortech.metadata.values.workspace import WorkspaceInput + +nortech = Nortech() + +# Get by ID +workspace = nortech.metadata.workspace.get(123) + +# Get by name +workspace = nortech.metadata.workspace.get("my-workspace") + +# Get by input dict +workspace = nortech.metadata.workspace.get({"workspace": "my-workspace"}) + +# Get by WorkspaceInput pydantic object +workspace = nortech.metadata.workspace.get(WorkspaceInput(workspace="my-workspace")) + +print(workspace) +# WorkspaceOutput( +# id=123, +# name="my-workspace", +# description="my-description", +# created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), +# updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0) +# ) diff --git a/docs/examples/metadata/Workspace/list.py b/docs/examples/metadata/Workspace/list.py new file mode 100644 index 0000000..666b63a --- /dev/null +++ b/docs/examples/metadata/Workspace/list.py @@ -0,0 +1,28 @@ +from nortech import Nortech +from nortech.metadata.values.pagination import PaginationOptions + +nortech = Nortech() + +# List all workspaces +workspaces = nortech.metadata.workspace.list() + +# List with pagination +workspaces = nortech.metadata.workspace.list(PaginationOptions(size=10, sortBy="name")) + +print(workspaces) +# PaginatedResponse( +# size=2, +# next=None, +# data=[ +# WorkspaceListOutput( +# id=1, +# name="my-workspace", +# description="my-description" +# ), +# WorkspaceListOutput( +# id=2, +# name="my-workspace", +# description="my-description" +# ) +# ] +# ) diff --git a/docs/index.md b/docs/index.md index d017837..0cd4a7e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -78,7 +78,6 @@ Client for interacting with the Nortech Metadata API. - `asset` _Asset_ - Client for interacting with the Nortech Metadata Asset API. - `division` _Division_ - Client for interacting with the Nortech Metadata Division API. - `unit` _Unit_ - Client for interacting with the Nortech Metadata Unit API. -- `device` _Device_ - Client for interacting with the Nortech Metadata Device API. - `signal` _Signal_ - Client for interacting with the Nortech Metadata Signal API. ### Workspace @@ -110,13 +109,12 @@ Get a workspace by ID or name. **Returns**: - `WorkspaceOutput` - The workspace details. - **Example**: ```python from nortech import Nortech -from nortech.core.values.workspace import WorkspaceInput +from nortech.metadata.values.workspace import WorkspaceInput nortech = Nortech() @@ -149,7 +147,8 @@ print(workspace) def list( pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None -) -> PaginatedResponse[WorkspaceListOutput] +) -> PaginatedResponse[WorkspaceListOutput, Literal["id", "name", + "description"]] ``` List all workspaces. @@ -162,13 +161,12 @@ List all workspaces. **Returns**: - `PaginatedResponse[WorkspaceListOutput]` - A paginated list of workspaces. - **Example**: ```python from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions +from nortech.metadata.values.pagination import PaginationOptions nortech = Nortech() @@ -223,13 +221,12 @@ Get an asset by ID or input. **Returns**: - `AssetOutput` - The asset details. - **Example**: ```python from nortech import Nortech -from nortech.core.values.asset import AssetInput +from nortech.metadata.values.asset import AssetInput nortech = Nortech() @@ -265,7 +262,7 @@ def list( | WorkspaceOutput | WorkspaceListOutput, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None -) -> PaginatedResponse[AssetListOutput] +) -> PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]] ``` List all assets in a workspace. @@ -285,14 +282,13 @@ List all assets in a workspace. **Returns**: - `PaginatedResponse[AssetListOutput]` - A paginated list of assets. - **Example**: ```python from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions -from nortech.core.values.workspace import WorkspaceInput +from nortech.metadata.values.pagination import PaginationOptions +from nortech.metadata.values.workspace import WorkspaceInput nortech = Nortech() @@ -357,13 +353,12 @@ Get a division by ID or input. **Returns**: - `DivisionOutput` - The division details. - **Example**: ```python from nortech import Nortech -from nortech.core.values.division import DivisionInput +from nortech.metadata.values.division import DivisionInput nortech = Nortech() @@ -404,7 +399,8 @@ def list( asset: int | AssetInputDict | AssetInput | AssetOutput | AssetListOutput, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None -) -> PaginatedResponse[DivisionListOutput] +) -> PaginatedResponse[DivisionListOutput, Literal["id", "name", + "description"]] ``` List all divisions in an asset. @@ -423,14 +419,13 @@ List all divisions in an asset. **Returns**: - `PaginatedResponse[DivisionListOutput]` - A paginated list of divisions. - **Example**: ```python from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions -from nortech.core.values.asset import AssetInput +from nortech.metadata.values.asset import AssetInput +from nortech.metadata.values.pagination import PaginationOptions nortech = Nortech() @@ -473,7 +468,8 @@ def list_by_workspace_id( workspace_id: int, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None -) -> PaginatedResponse[DivisionListOutput] +) -> PaginatedResponse[DivisionListOutput, Literal["id", "name", + "description"]] ``` List all divisions in a workspace. @@ -487,13 +483,12 @@ List all divisions in a workspace. **Returns**: - `PaginatedResponse[DivisionListOutput]` - A paginated list of divisions. - **Example**: ```python from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions +from nortech.metadata.values.pagination import PaginationOptions nortech = Nortech() @@ -548,13 +543,12 @@ Get a unit by ID or input. **Returns**: - `UnitOutput` - The unit details. - **Example**: ```python from nortech import Nortech -from nortech.core.values.unit import UnitInput +from nortech.metadata.values.unit import UnitInput nortech = Nortech() @@ -600,7 +594,7 @@ def list( division: int | DivisionInputDict | DivisionInput | DivisionOutput | DivisionListOutput, pagination_options: PaginationOptions[Literal["id", "name"]] | None = None -) -> PaginatedResponse[UnitListOutput] +) -> PaginatedResponse[UnitListOutput, Literal["id", "name"]] ``` List all units in a division. @@ -619,14 +613,13 @@ List all units in a division. **Returns**: - `PaginatedResponse[UnitListOutput]` - A paginated list of units. - **Example**: ```python from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions -from nortech.core.values.division import DivisionInput +from nortech.metadata.values.division import DivisionInput +from nortech.metadata.values.pagination import PaginationOptions nortech = Nortech() @@ -666,7 +659,7 @@ print(units) def list_by_workspace_id( workspace_id: int, pagination_options: PaginationOptions[Literal["id", "name"]] | None = None -) -> PaginatedResponse[UnitListOutput] +) -> PaginatedResponse[UnitListOutput, Literal["id", "name"]] ``` List all units in a workspace. @@ -680,13 +673,12 @@ List all units in a workspace. **Returns**: - `PaginatedResponse[UnitListOutput]` - A paginated list of units. - **Example**: ```python from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions +from nortech.metadata.values.pagination import PaginationOptions nortech = Nortech() @@ -720,7 +712,7 @@ print(units) def list_by_asset_id( asset_id: int, pagination_options: PaginationOptions[Literal["id", "name"]] | None = None -) -> PaginatedResponse[UnitListOutput] +) -> PaginatedResponse[UnitListOutput, Literal["id", "name"]] ``` List all units in an asset. @@ -734,13 +726,12 @@ List all units in an asset. **Returns**: - `PaginatedResponse[UnitListOutput]` - A paginated list of units. - **Example**: ```python from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions +from nortech.metadata.values.pagination import PaginationOptions nortech = Nortech() @@ -765,270 +756,6 @@ print(units) # ) # ] # ) -``` - -### Device - -#### get - -```python -def get( - device: int | DeviceInputDict | DeviceInput | DeviceOutput - | DeviceListOutput -) -> DeviceOutput -``` - -Get a device by ID or input. - -**Arguments**: - -- `device` _int | DeviceInputDict | DeviceInput | DeviceOutput | DeviceListOutput_ - The device identifier, which can be: - - *int*: The device "ID". - - [DeviceInputDict](#deviceinputdict): A dictionary representation of a device input. - - [DeviceInput](#deviceinput): A pydantic model representing a device input. - - [DeviceOutput](#deviceoutput): A pydantic model representing a device output. Obtained from requesting a device metadata. - - [DeviceListOutput](#devicelistoutput): A pydantic model representing a listed device output. Obtained from requesting devices metadata. - - -**Returns**: - -- `DeviceOutput` - The device details. - - -**Example**: - -```python -from nortech import Nortech -from nortech.core.values.device import DeviceInput - -nortech = Nortech() - -# Get by ID -device = nortech.metadata.device.get(123) - -# Get by input dict -device = nortech.metadata.device.get( - {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division", "device": "my-device"} -) - -# Get by DeviceInput pydantic object -device = nortech.metadata.device.get( - DeviceInput(workspace="my-workspace", asset="my-asset", division="my-division", device="my-device") -) - -print(device) -# DeviceOutput( -# id=123, -# name="my-device", -# type="my-type", -# onboarded=True, -# created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), -# updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), -# workspace=MetadataOutput( -# id=123, -# name="my-workspace" -# ), -# asset=MetadataOutput( -# id=456, -# name="my-asset" -# ), -# division=MetadataOutput( -# id=789, -# name="my-division" -# ) -# ) - -``` - -#### list - -```python -def list( - division: int | DivisionInputDict | DivisionInput | DivisionOutput - | DivisionListOutput, - pagination_options: PaginationOptions[Literal["id", "name", "type", - "onboarded"]] | None = None -) -> PaginatedResponse[DeviceListOutput] -``` - -List all devices in a division. - -**Arguments**: - -- `division` _int | DivisionInputDict | DivisionInput | DivisionOutput | DivisionListOutput_ - The division identifier, which can be: - - *int*: The division "ID". - - [DivisionInputDict](#divisioninputdict): A dictionary representation of a division input. - - [DivisionInput](#divisioninput): A pydantic model representing a division input. - - [DivisionOutput](#divisionoutput): A pydantic model representing a division output. - - [DivisionListOutput](#divisionlistoutput): A pydantic model representing a listed division output. -- `pagination_options` _PaginationOptions, optional_ - Pagination settings. - - -**Returns**: - -- `PaginatedResponse[DeviceListOutput]` - A paginated list of devices. - - -**Example**: - -```python -from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions -from nortech.core.values.division import DivisionInput - -nortech = Nortech() - -# List all devices in a division -devices = nortech.metadata.device.list(123) # using division ID - -# List with pagination -devices = nortech.metadata.device.list( - {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division"}, # using DivisionInputDict - PaginationOptions(size=10, sortBy="name"), -) - -# Using DivisionInput pydantic object -devices = nortech.metadata.device.list( - DivisionInput(workspace="my-workspace", asset="my-asset", division="my-division") -) - -print(devices) -# PaginatedResponse( -# size=2, -# next=None, -# data=[ -# DeviceListOutput( -# id=1, -# name="my-device", -# type="my-type", -# onboarded=True -# ), -# DeviceListOutput( -# id=2, -# name="another-device", -# type="another-type", -# onboarded=False -# ) -# ] -# ) - -``` - -#### list\_by\_workspace\_id - -```python -def list_by_workspace_id( - workspace_id: int, - pagination_options: PaginationOptions[Literal["id", "name", "type", - "onboarded"]] | None = None -) -> PaginatedResponse[DeviceListOutput] -``` - -List all devices in a workspace. - -**Arguments**: - -- `workspace_id` _int_ - The workspace ID. -- `pagination_options` _PaginationOptions, optional_ - Pagination settings. - - -**Returns**: - -- `PaginatedResponse[DeviceListOutput]` - A paginated list of devices. - - -**Example**: - -```python -from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions - -nortech = Nortech() - -# List all devices in a workspace -devices = nortech.metadata.device.list_by_workspace_id(123) - -# List with pagination -devices = nortech.metadata.device.list_by_workspace_id(123, PaginationOptions(size=10, sortBy="name")) - -print(devices) -# PaginatedResponse( -# size=2, -# next=None, -# data=[ -# DeviceListOutput( -# id=1, -# name="my-device", -# type="my-type", -# onboarded=True -# ), -# DeviceListOutput( -# id=2, -# name="another-device", -# type="another-type", -# onboarded=False -# ) -# ] -# ) - -``` - -#### list\_by\_asset\_id - -```python -def list_by_asset_id( - asset_id: int, - pagination_options: PaginationOptions[Literal["id", "name", "type", - "onboarded"]] | None = None -) -> PaginatedResponse[DeviceListOutput] -``` - -List all devices in an asset. - -**Arguments**: - -- `asset_id` _int_ - The asset ID. -- `pagination_options` _PaginationOptions, optional_ - Pagination settings. - - -**Returns**: - -- `PaginatedResponse[DeviceListOutput]` - A paginated list of devices. - - -**Example**: - -```python -from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions - -nortech = Nortech() - -# List all devices in an asset -devices = nortech.metadata.device.list_by_asset_id(123) - -# List with pagination -devices = nortech.metadata.device.list_by_asset_id(123, PaginationOptions(size=10, sortBy="name")) - -print(devices) -# PaginatedResponse( -# size=2, -# next=None, -# data=[ -# DeviceListOutput( -# id=1, -# name="my-device", -# type="my-type", -# onboarded=True -# ), -# DeviceListOutput( -# id=2, -# name="another-device", -# type="another-type", -# onboarded=False -# ) -# ] -# ) ``` @@ -1038,13 +765,8 @@ print(devices) ```python def get( - signal: int - | SignalInputDict - | SignalInput - | SignalOutput + signal: int | SignalInputDict | SignalInput | SignalOutput | SignalListOutput - | SignalDeviceInputDict - | SignalDeviceInput ) -> SignalOutput ``` @@ -1052,26 +774,23 @@ Get a signal by ID or input. **Arguments**: -- `signal` _int | SignalInputDict | SignalInput | SignalOutput | SignalListOutput | SignalDeviceInputDict | SignalDeviceInput_ - The signal identifier, which can be: +- `signal` _int | SignalInputDict | SignalInput | SignalOutput | SignalListOutput_ - The signal identifier, which can be: - *int*: The signal "ID". - [SignalInputDict](#signalinputdict): A dictionary representation of a signal input. - [SignalInput](#signalinput): A pydantic model representing a signal input. - [SignalOutput](#signaloutput): A pydantic model representing a signal output. Obtained from requesting a signal metadata. - [SignalListOutput](#signallistoutput): A pydantic model representing a listed signal output. Obtained from requesting signals metadata. - - [SignalDeviceInputDict](#signaldeviceinputdict): A dictionary representation of a device signal input. - - [SignalDeviceInput](#signaldeviceinput): A pydantic model representing a device signal input. **Returns**: - `SignalOutput` - The signal details. - **Example**: ```python from nortech import Nortech -from nortech.core.values.signal import SignalDeviceInput, SignalInput +from nortech.metadata.values.signal import SignalInput nortech = Nortech() @@ -1089,29 +808,10 @@ signal = nortech.metadata.signal.get( } ) -# Get device signal by input dict -signal = nortech.metadata.signal.get( - { - "workspace": "my-workspace", - "asset": "my-asset", - "division": "my-division", - "device": "my-device", - "signal": "my-signal", - } -) # Get by SignalInput pydantic object signal = nortech.metadata.signal.get( - SignalInput( - workspace="my-workspace", asset="my-asset", division="my-division", unit="my-unit", signal="my-signal" - ) -) - -# Get by SignalDeviceInput pydantic object -signal = nortech.metadata.signal.get( -SignalDeviceInput( - workspace="my-workspace", asset="my-asset", division="my-division", device="my-device", signal="my-signal" - ) + SignalInput(workspace="my-workspace", asset="my-asset", division="my-division", unit="my-unit", signal="my-signal") ) print(signal) @@ -1140,10 +840,6 @@ print(signal) # id=101, # name="my-unit" # ) -# device=MetadataOutput( -# id=101, -# name="my-device" -# ) # ) ``` @@ -1152,8 +848,7 @@ print(signal) ```python def list( - unit_or_device: int | UnitInputDict | UnitInput | UnitOutput - | DeviceInputDict | DeviceInput | DeviceOutput, + unit: int | UnitInputDict | UnitInput | UnitOutput, pagination_options: PaginationOptions[Literal[ "id", "name", @@ -1163,36 +858,33 @@ def list( "long_description", ]] | None = None -) -> PaginatedResponse[SignalListOutput] +) -> PaginatedResponse[SignalListOutput, + Literal["id", "name", "physical_unit", "data_type", + "description", "long_description"]] ``` -List all signals in a unit or device. +List all signals in a unit. **Arguments**: -- `unit_or_device` _int | UnitInputDict | UnitInput | UnitOutput | DeviceInputDict | DeviceInput | DeviceOutput_ - The unit or device identifier, which can be: - - *int*: The unit/device "ID". +- `unit` _int | UnitInputDict | UnitInput | UnitOutput_ - The unit identifier, which can be: + - *int*: The unit "ID". - [UnitInputDict](#unitinputdict): A dictionary representation of a unit input. - [UnitInput](#unitinput): A pydantic model representing a unit input. - [UnitOutput](#unitoutput): A pydantic model representing a unit output. - - [DeviceInputDict](#deviceinputdict): A dictionary representation of a device input. - - [DeviceInput](#deviceinput): A pydantic model representing a device input. - - [DeviceOutput](#deviceoutput): A pydantic model representing a device output. - `pagination_options` _PaginationOptions, optional_ - Pagination settings. **Returns**: - `PaginatedResponse[SignalListOutput]` - A paginated list of signals. - **Example**: ```python from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions -from nortech.core.values.device import DeviceInput -from nortech.core.values.unit import UnitInput +from nortech.metadata.values.pagination import PaginationOptions +from nortech.metadata.values.unit import UnitInput nortech = Nortech() @@ -1205,22 +897,11 @@ signals = nortech.metadata.signal.list( PaginationOptions(size=10, sortBy="name"), ) -# List device signals with pagination -signals = nortech.metadata.signal.list( - {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division", "device": "my-device"}, - PaginationOptions(size=10, sortBy="name"), -) - # Using UnitInput pydantic object signals = nortech.metadata.signal.list( UnitInput(workspace="my-workspace", asset="my-asset", division="my-division", unit="my-unit") ) -# Using DeviceInput pydantic object -signals = nortech.metadata.signal.list( - DeviceInput(workspace="my-workspace", asset="my-asset", division="my-division", device="my-device") -) - print(signals) # PaginatedResponse( # size=2, @@ -1261,7 +942,9 @@ def list_by_workspace_id( "long_description", ]] | None = None -) -> PaginatedResponse[SignalListOutput] +) -> PaginatedResponse[SignalListOutput, + Literal["id", "name", "physical_unit", "data_type", + "description", "long_description"]] ``` List all signals in a workspace. @@ -1275,13 +958,12 @@ List all signals in a workspace. **Returns**: - `PaginatedResponse[SignalListOutput]` - A paginated list of signals. - **Example**: ```python from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions +from nortech.metadata.values.pagination import PaginationOptions nortech = Nortech() @@ -1331,7 +1013,9 @@ def list_by_asset_id( "long_description", ]] | None = None -) -> PaginatedResponse[SignalListOutput] +) -> PaginatedResponse[SignalListOutput, + Literal["id", "name", "physical_unit", "data_type", + "description", "long_description"]] ``` List all signals in an asset. @@ -1345,13 +1029,12 @@ List all signals in an asset. **Returns**: - `PaginatedResponse[SignalListOutput]` - A paginated list of signals. - **Example**: ```python from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions +from nortech.metadata.values.pagination import PaginationOptions nortech = Nortech() @@ -1385,7 +1068,6 @@ print(signals) # ] # ) - ``` #### list\_by\_division\_id @@ -1402,7 +1084,9 @@ def list_by_division_id( "long_description", ]] | None = None -) -> PaginatedResponse[SignalListOutput] +) -> PaginatedResponse[SignalListOutput, + Literal["id", "name", "physical_unit", "data_type", + "description", "long_description"]] ``` List all signals in a division. @@ -1416,13 +1100,12 @@ List all signals in a division. **Returns**: - `PaginatedResponse[SignalListOutput]` - A paginated list of signals. - **Example**: ```python from nortech import Nortech -from nortech.gateways.nortech_api import PaginationOptions +from nortech.metadata.values.pagination import PaginationOptions nortech = Nortech() @@ -1456,7 +1139,6 @@ print(signals) # ] # ) - ``` @@ -1492,7 +1174,6 @@ Download data for the specified signals within the given time window. If experim **Raises**: - `NotImplementedError` - If the time window corresponds to hot storage, which is not yet supported. - **Example**: @@ -1500,8 +1181,8 @@ Download data for the specified signals within the given time window. If experim from datetime import datetime from nortech import Nortech -from nortech.core.values.signal import SignalInput, SignalInputDict from nortech.datatools.values.windowing import TimeWindow +from nortech.metadata.values.signal import SignalInput, SignalInputDict # Initialize the Nortech client nortech = Nortech() @@ -1570,7 +1251,6 @@ Retrieve a pandas DataFrame for the specified signals within the given time wind - `NoSignalsRequestedError` - Raised when no signals are requested. - `InvalidTimeWindow` - Raised when the start date is after the end date. - **Example**: @@ -1578,8 +1258,8 @@ Retrieve a pandas DataFrame for the specified signals within the given time wind from datetime import datetime from nortech import Nortech -from nortech.core.values.signal import SignalInput, SignalInputDict from nortech.datatools.values.windowing import TimeWindow +from nortech.metadata.values.signal import SignalInput, SignalInputDict # Initialize the Nortech client nortech = Nortech() @@ -1652,7 +1332,6 @@ Retrieve a polars LazyFrame for the specified signals within the given time wind - `NoSignalsRequestedError` - Raised when no signals are requested. - `InvalidTimeWindow` - Raised when the start date is after the end date. - **Example**: @@ -1660,8 +1339,8 @@ Retrieve a polars LazyFrame for the specified signals within the given time wind from datetime import datetime from nortech import Nortech -from nortech.core.values.signal import SignalInput, SignalInputDict from nortech.datatools.values.windowing import TimeWindow +from nortech.metadata.values.signal import SignalInput, SignalInputDict # Initialize the Nortech client nortech = Nortech() @@ -1732,7 +1411,6 @@ Retrieve a polars DataFrame for the specified signals within the given time wind - `NoSignalsRequestedError` - Raised when no signals are requested. - `InvalidTimeWindow` - Raised when the start date is after the end date. - **Example**: @@ -1740,8 +1418,8 @@ Retrieve a polars DataFrame for the specified signals within the given time wind from datetime import datetime from nortech import Nortech -from nortech.core.values.signal import SignalInput, SignalInputDict from nortech.datatools.values.windowing import TimeWindow +from nortech.metadata.values.signal import SignalInput, SignalInputDict # Initialize the Nortech client nortech = Nortech() @@ -1793,18 +1471,19 @@ Client for interacting with the Nortech Derivers API. **Attributes**: - `nortech_api` _NortechAPI_ - The Nortech API client. - **Example**: - To define a deriver, you need to create a class that inherits from the Deriver class. - The class must have two inner classes: Inputs and Outputs. - The Inputs class must inherit from DeriverInputs and the Outputs class must inherit from DeriverOutputs. - The Inputs class must define the inputs of the deriver. - The Outputs class must define the outputs of the deriver. - The run method must be defined and return a bytewax stream. - ```python +# To define a deriver, you need to create a class that inherits from the Deriver class. +# The class must have two inner classes: Inputs and Outputs. +# The Inputs class must inherit from DeriverInputs and the Outputs class must inherit from DeriverOutputs. +# The Inputs class must define the inputs of the deriver. +# The Outputs class must define the outputs of the deriver. +# The run method must be defined and return a bytewax stream. + +from __future__ import annotations + import bytewax.operators as op from nortech.derivers import Deriver, DeriverInput, DeriverInputs, DeriverOutput, DeriverOutputs @@ -1851,6 +1530,7 @@ class MyDeriver(Deriver): output_2=str(_input.input_2), ), ) + ``` #### list @@ -1871,17 +1551,20 @@ List derivers. **Returns**: - `PaginatedResponse[DeployedDeriver]` - Paginated response of derivers. - **Example**: ```python +from nortech import Nortech +from nortech.derivers import Deriver + + # Define Deriver -class MyDeriver(Deriver): - ... +class MyDeriver(Deriver): ... nortech = Nortech() + derivers = nortech.derivers.list() print(derivers) # PaginatedResponse( @@ -1895,6 +1578,7 @@ print(derivers) # ) # ], # ) + ``` #### get @@ -1913,24 +1597,31 @@ Get a deriver. **Returns**: - `DeployedDeriver` - Deployed deriver. - **Example**: ```python +from nortech import Nortech +from nortech.derivers import Deriver + + # Define Deriver -class MyDeriver(Deriver): - ... +class MyDeriver(Deriver): ... + nortech = Nortech() + +# Get deriver by class or class name derivers = nortech.derivers.get(MyDeriver) +derivers = nortech.derivers.get("MyDeriver") + print(derivers) # DeployedDeriver( # deriver=MyDeriver, # description="my-description", # start_at="2025-01-01T12:00:00Z", # inputs=[ -# SignalOutputNoDevice( +# SignalOutput( # id=1, # name="input_1", # description="input_1", @@ -1958,7 +1649,7 @@ print(derivers) # ), # ], # outputs=[ -# SignalOutputNoDevice( +# SignalOutput( # id=2, # name="output_1", # description="output_1", @@ -1986,6 +1677,7 @@ print(derivers) # ), # ] # ) + ``` #### create @@ -2010,16 +1702,22 @@ Create a deriver. **Returns**: - `DeployedDeriver` - Deployed deriver. - **Example**: ```python +from datetime import datetime, timezone + +from nortech import Nortech +from nortech.derivers import Deriver + + # Define Deriver -class MyDeriver(Deriver): - ... +class MyDeriver(Deriver): ... + nortech = Nortech() + derivers = nortech.derivers.create(MyDeriver, start_at=datetime.now(timezone.utc), description="my-description") print(derivers) # DeployedDeriver( @@ -2027,7 +1725,7 @@ print(derivers) # description="my-description", # start_at=None, # inputs=[ -# SignalOutputNoDevice( +# SignalOutput( # id=1, # name="input_1", # description="input_1", @@ -2055,7 +1753,7 @@ print(derivers) # ), # ], # outputs=[ -# SignalOutputNoDevice( +# SignalOutput( # id=2, # name="output_1", # description="output_1", @@ -2083,6 +1781,7 @@ print(derivers) # ), # ] # ) + ``` #### update @@ -2109,16 +1808,22 @@ Update a deriver. **Returns**: - `DeployedDeriver` - Deployed deriver. - **Example**: ```python +from datetime import datetime, timezone + +from nortech import Nortech +from nortech.derivers import Deriver + + # Define Deriver -class MyDeriver(Deriver): - ... +class MyDeriver(Deriver): ... + nortech = Nortech() + derivers = nortech.derivers.update(MyDeriver, start_at=datetime.now(timezone.utc), description="my-description") print(derivers) # DeployedDeriver( @@ -2126,7 +1831,7 @@ print(derivers) # description="my-description", # start_at=None, # inputs=[ -# SignalOutputNoDevice( +# SignalOutput( # id=1, # name="input_1", # description="input_1", @@ -2154,7 +1859,7 @@ print(derivers) # ), # ], # outputs=[ -# SignalOutputNoDevice( +# SignalOutput( # id=2, # name="output_1", # description="output_1", @@ -2182,6 +1887,7 @@ print(derivers) # ), # ] # ) + ``` #### run\_locally\_with\_df @@ -2204,18 +1910,20 @@ Run a deriver locally on a DataFrame. The dataframe must have a timestamp index **Returns**: - `DataFrame` - The processed DataFrame with derived signals. - **Example**: ```python -from datetime import datetime, timezone +from datetime import timezone + +import pandas as pd from nortech import Nortech -from nortech.derivers import Deriver, TimeWindow +from nortech.derivers import Deriver + + +class MyDeriver(Deriver): ... -class MyDeriver(Deriver): - ... nortech = Nortech() @@ -2244,6 +1952,7 @@ print(result_df) # 2023-01-01 00:01:37+00:00 194.0 # 2023-01-01 00:01:38+00:00 196.0 # 2023-01-01 00:01:39+00:00 198.0 + ``` #### run\_locally\_with\_source\_data @@ -2266,18 +1975,20 @@ Run a deriver locally by fetching its inputs signal data for a given time window **Returns**: - `DataFrame` - The processed DataFrame with derived signals. - **Example**: ```python from datetime import datetime, timezone +import pandas as pd + from nortech import Nortech from nortech.derivers import Deriver, TimeWindow -class MyDeriver(Deriver): - ... + +class MyDeriver(Deriver): ... + nortech = Nortech() @@ -2290,7 +2001,9 @@ df = pd.DataFrame( ).set_index("timestamp") # Run the deriver locally -result_df = nortech.derivers.run_locally_with_source_data(MyDeriver, time_window=TimeWindow(start=datetime.now(timezone.utc), end=datetime.now(timezone.utc))) +result_df = nortech.derivers.run_locally_with_source_data( + MyDeriver, time_window=TimeWindow(start=datetime.now(timezone.utc), end=datetime.now(timezone.utc)) +) print(result_df) # output_signal @@ -2306,6 +2019,7 @@ print(result_df) # 2023-01-01 00:01:37+00:00 194.0 # 2023-01-01 00:01:38+00:00 196.0 # 2023-01-01 00:01:39+00:00 198.0 + ``` @@ -2561,67 +2275,6 @@ Detailed output model for a single unit. -## metadata.values.device - -Module containing all schemas related with Devices. - -### DeviceInputDict - -Dictionary representation of Device input data. - -**Attributes**: - -- `workspace` _str_ - The name of the Workspace. -- `asset` _str_ - The name of the Asset. -- `division` _str_ - The name of the Division. -- `device` _str_ - The name of the Device. - -### DeviceInput - -Pydantic model for Device input data. - -**Attributes**: - -- `workspace` _str_ - The name of the Workspace. -- `asset` _str_ - The name of the Asset. -- `division` _str_ - The name of the Division. -- `device` _str_ - The name of the Device. - -### DeviceListOutput - -Output model for device list entries. - -**Attributes**: - -- `id` _int_ - Id of the Device. -- `name` _str_ - Name of the Device. -- `type` _str_ - The type of the Device. -- `onboarded` _bool_ - Whether the Device is onboarded. - -### DeviceOutput - -Detailed output model for a single device. - -**Attributes**: - -- `id` _int_ - Id of the Device. -- `name` _str_ - Name of the Device. -- `type` _str_ - The type of the Device. -- `onboarded` _bool_ - Whether the Device is onboarded. -- `created_at` _datetime_ - Timestamp of when the Device was created. -- `updated_at` _datetime_ - Timestamp of when the Device was last updated. -- `workspace` - Metadata about the Workspace containing the Device. - - id (int): Id of the Workspace. - - name (str): Name of the Workspace. -- `asset` - Metadata about the Asset containing the Device. - - id (int): Id of the Asset. - - name (str): Name of the Asset. -- `division` - Metadata about the Division containing the Device. - - id (int): Id of the Division. - - name (str): Name of the Division. - - - ## metadata.values.signal Module containing all schemas related with Signals. @@ -2650,30 +2303,6 @@ Pydantic model for Signal input data. - `unit` _str_ - The name of the Unit. - `signal` _str_ - The name of the Signal. -### SignalDeviceInputDict - -Dictionary representation of SignalDevice input data. - -**Attributes**: - -- `workspace` _str_ - The name of the Workspace. -- `asset` _str_ - The name of the Asset. -- `division` _str_ - The name of the Division. -- `device` _str_ - The name of the Device. -- `signal` _str_ - The name of the Signal. - -### SignalDeviceInput - -Pydantic model for SignalDevice input data. - -**Attributes**: - -- `workspace` _str_ - The name of the Workspace. -- `asset` _str_ - The name of the Asset. -- `division` _str_ - The name of the Division. -- `device` _str_ - The name of the Device. -- `signal` _str_ - The name of the Signal. - ### SignalListOutput Output model for signal list entries. @@ -2687,29 +2316,3 @@ Output model for signal list entries. - `description` _str_ - A description of the Signal. - `long_description` _str_ - A long description of the Signal. -### SignalOutput - -Detailed output model for a single signal. - -**Attributes**: - -- `id` _int_ - Id of the Signal. -- `name` _str_ - Name of the Signal. -- `created_at` _datetime_ - Timestamp of when the Signal was created. -- `updated_at` _datetime_ - Timestamp of when the Signal was last updated. -- `workspace` - Metadata about the Workspace containing the Signal. - - id (int): Id of the Workspace. - - name (str): Name of the Workspace. -- `asset` - Metadata about the Asset containing the Signal. - - id (int): Id of the Asset. - - name (str): Name of the Asset. -- `division` - Metadata about the Division containing the Signal. - - id (int): Id of the Division. - - name (str): Name of the Division. -- `unit` - Metadata about the Unit containing the Signal. - - id (int): Id of the Unit. - - name (str): Name of the Unit. -- `device` - Metadata about the Device containing the Signal. - - id (int): Id of the Device. - - name (str): Name of the Device. - diff --git a/docs-render.py b/docs/render.py similarity index 53% rename from docs-render.py rename to docs/render.py index 4b740c0..16ac1f9 100644 --- a/docs-render.py +++ b/docs/render.py @@ -3,6 +3,7 @@ import shutil from pathlib import Path +from docspec import ApiObject, Docstring, HasMembers, Module from pydoc_markdown import PydocMarkdown from pydoc_markdown.contrib.loaders.python import PythonLoader from pydoc_markdown.contrib.processors.crossref import CrossrefProcessor @@ -12,24 +13,65 @@ CustomizedMarkdownRenderer, DocusaurusRenderer, ) +from pydoc_markdown.interfaces import Processor, Resolver -DOCS_PREFIX = "docs" +DOCS_PATH = Path(__file__).parent +REPO_ROOT = DOCS_PATH.parent / "nortech" +EXAMPLES_PATH = DOCS_PATH / "examples" BASE_FILE = "index.md" -def render_doc(path: Path, output_dir: Path): +def add_examples_to_modules(modules: list[ApiObject], examples_path: Path = EXAMPLES_PATH): + for path in examples_path.iterdir(): + if path.is_file() and path.name == "__init__.py": + module = modules[0].parent + if module and module.name == path.parent.name and module.docstring: + module.docstring = Docstring( + location=module.docstring.location, + content=module.docstring.content.rstrip() + + "\n\n**Example**:\n\n```python\n" + + path.read_text() + + "\n```", + ) + + else: + module = next((m for m in modules if m.name == path.stem), None) + if not module: + continue + + if path.is_file(): + if module and module.docstring: + module.docstring = Docstring( + location=module.docstring.location, + content=module.docstring.content.rstrip() + + "\n\n**Example**:\n\n```python\n" + + path.read_text() + + "\n```", + ) + else: + if isinstance(module, HasMembers): + add_examples_to_modules(list(module.members), path) + + +class ExampleProcessor(Processor): + def process(self, modules: list[Module], resolver: Resolver | None = None) -> None: + add_examples_to_modules(list(modules)) + + +def render_doc(): config = PydocMarkdown( - loaders=[PythonLoader(search_path=[str(path)])], + loaders=[PythonLoader(search_path=[str(REPO_ROOT)])], processors=[ FilterProcessor(skip_empty_modules=True), CrossrefProcessor(), GoogleProcessor(), + ExampleProcessor(), ], renderer=DocusaurusRenderer( - docs_base_path=str(output_dir), - relative_output_path=str(output_dir), - relative_sidebar_path=str(output_dir / "sidebar.json"), - sidebar_top_level_module_label=DOCS_PREFIX, + docs_base_path=str(DOCS_PATH), + relative_output_path=str(DOCS_PATH), + relative_sidebar_path=str(DOCS_PATH / "sidebar.json"), + sidebar_top_level_module_label="Docs", sidebar_top_level_label="Reference", markdown=CustomizedMarkdownRenderer( classdef_code_block=False, @@ -48,13 +90,14 @@ def render_doc(path: Path, output_dir: Path): ), ), ) - modules = config.load_modules() + + modules: list[Module] = config.load_modules() config.process(modules) config.render(modules) -def format_files(docs_path: Path): - for path in docs_path.rglob("*"): +def format_files(): + for path in DOCS_PATH.rglob("*"): if path.is_dir() and path.name == "__init__": init_file = path / "__init__.md" if init_file.exists(): @@ -64,32 +107,32 @@ def format_files(docs_path: Path): path.rename(path.parent / BASE_FILE) -def format_md_contents(docs_path: Path): - for path in docs_path.rglob("*.md"): +def format_md_contents(): + for path in DOCS_PATH.rglob("*.md"): content = path.read_text() content = content.replace("#### \\_\\_init\\_\\_", "#### constructor") content = content.replace("# \\_\\_init\\_\\_", "") path.write_text(content) -def group_files(docs_path: Path, file_order: list[str] | None = None): +def group_files(file_order: list[str] | None = None): """Append contents of files to BASE_FILE in specified order.""" - index_path = docs_path / BASE_FILE + index_path = DOCS_PATH / BASE_FILE # Get all markdown files - md_files = list(docs_path.rglob("*.md")) + md_files = list(DOCS_PATH.rglob("*.md")) # Filter out BASE_FILE in root docs path only - md_files = [f for f in md_files if not (f.parent == docs_path and f.name == BASE_FILE)] + md_files = [f for f in md_files if not (f.parent == DOCS_PATH and f.name == BASE_FILE)] if file_order: # Sort files according to specified order - ordered_files = [] + ordered_files: list[Path] = [] remaining_files = md_files.copy() for ordered_path in file_order: for file in md_files: - if str(file.relative_to(docs_path)) == ordered_path: + if str(file.relative_to(DOCS_PATH)) == ordered_path: ordered_files.append(file) remaining_files.remove(file) break @@ -104,24 +147,22 @@ def group_files(docs_path: Path, file_order: list[str] | None = None): index.write("\n\n" + content) -def delete_extra_files(docs_path: Path): - for path in docs_path.rglob("*"): - if path.is_file() and path.name != BASE_FILE: - path.unlink() - elif path.is_dir(): - shutil.rmtree(path) +def delete_extra_files(): + for item in DOCS_PATH.iterdir(): + if item in [EXAMPLES_PATH, DOCS_PATH / BASE_FILE, Path(__file__)]: + continue + if item.is_file(): + item.unlink() + elif item.is_dir(): + shutil.rmtree(item) def main(): - base_path = Path(__file__).parent - repo_root = base_path / "nortech" - docs_path = base_path / DOCS_PREFIX - docs_path.mkdir(exist_ok=True, parents=True) - render_doc(repo_root, docs_path) - format_files(docs_path) - format_md_contents(docs_path) + DOCS_PATH.mkdir(exist_ok=True, parents=True) + render_doc() + format_files() + format_md_contents() group_files( - docs_path, [ "metadata/index.md", "datatools/index.md", @@ -132,14 +173,13 @@ def main(): "metadata/values/asset.md", "metadata/values/division.md", "metadata/values/unit.md", - "metadata/values/device.md", "metadata/values/signal.md", "derivers/values/schema.md", "derivers/values/instance.md", "derivers/values/physical_units_schema.md", ], ) - delete_extra_files(docs_path) + delete_extra_files() if __name__ == "__main__": diff --git a/nortech/datatools/__init__.py b/nortech/datatools/__init__.py index a864a01..113b3de 100644 --- a/nortech/datatools/__init__.py +++ b/nortech/datatools/__init__.py @@ -55,49 +55,6 @@ def download_data( Raises: NotImplementedError: If the time window corresponds to hot storage, which is not yet supported. - Example: - ```python - from datetime import datetime - - from nortech import Nortech - from nortech.core.values.signal import SignalInput, SignalInputDict - from nortech.datatools.values.windowing import TimeWindow - - # Initialize the Nortech client - nortech = Nortech() - - # Define signals to download - signal1: SignalInputDict = { - "workspace": "workspace1", - "asset": "asset1", - "division": "division1", - "unit": "unit1", - "signal": "signal1", - } - signal2 = 789 # Signal ID - signal3 = SignalInput(workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2") - - fetched_signals = nortech.metadata.signal.list( # Fetched signals - {"workspace": "workspace3", "asset": "asset3", "division": "division3", "unit": "unit3"} - ).data - - # Define the time window for data download - my_time_window = TimeWindow(start=datetime(2023, 1, 1), end=datetime(2023, 1, 31)) - - # Specify the output path and file format - output_path = "path/to/output" - file_format = "parquet" - - # Call the download_data function with manually defined signals or fetched signals - nortech.datatools.download.download_data( - signals=[signal1, signal2, signal3] + fetched_signals, - time_window=my_time_window, - output_path=output_path, - file_format=file_format, - ) - - ``` - """ return download_handlers.download_data(self.nortech_api, signals, time_window, output_path, file_format) @@ -130,53 +87,6 @@ def get_df( NoSignalsRequestedError: Raised when no signals are requested. InvalidTimeWindow: Raised when the start date is after the end date. - Example: - ```python - from datetime import datetime - - from nortech import Nortech - from nortech.core.values.signal import SignalInput, SignalInputDict - from nortech.datatools.values.windowing import TimeWindow - - # Initialize the Nortech client - nortech = Nortech() - - # Define signals to download - signal1: SignalInputDict = { - "workspace": "workspace1", - "asset": "asset1", - "division": "division1", - "unit": "unit1", - "signal": "signal1", - } - signal2 = 789 # Signal ID - signal3 = SignalInput(workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2") - - fetched_signals = nortech.metadata.signal.list( # Fetched signals - {"workspace": "workspace3", "asset": "asset3", "division": "division3", "unit": "unit3"} - ).data - - # Define the time window for data download - my_time_window = TimeWindow(start=datetime(2023, 1, 1), end=datetime(2023, 1, 31)) - - # Call the get_df function with manually defined signals or fetched signals - df = nortech.datatools.pandas.get_df( - signals=[signal1, signal2, signal3] + fetched_signals, - time_window=my_time_window, - ) - - print(df.columns) - # [ - # "timestamp", - # "workspace_1/asset_1/division_1/unit_1/signal_1", - # "workspace_1/asset_1/division_1/unit_1/signal_2", - # "workspace_2/asset_2/division_2/unit_2/signal_3", - # "workspace_3/asset_3/division_3/unit_3/signal_4", - # "workspace_3/asset_3/division_3/unit_3/signal_5", - # ] - - ``` - """ return pandas_handlers.get_df(self.nortech_api, signals, time_window) @@ -209,53 +119,6 @@ def get_lazy_df( NoSignalsRequestedError: Raised when no signals are requested. InvalidTimeWindow: Raised when the start date is after the end date. - Example: - ```python - from datetime import datetime - - from nortech import Nortech - from nortech.core.values.signal import SignalInput, SignalInputDict - from nortech.datatools.values.windowing import TimeWindow - - # Initialize the Nortech client - nortech = Nortech() - - # Define signals to download - signal1: SignalInputDict = { - "workspace": "workspace1", - "asset": "asset1", - "division": "division1", - "unit": "unit1", - "signal": "signal1", - } - signal2 = 789 # Signal ID - signal3 = SignalInput(workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2") - - fetched_signals = nortech.metadata.signal.list( # Fetched signals - {"workspace": "workspace3", "asset": "asset3", "division": "division3", "unit": "unit3"} - ).data - - # Define the time window for data download - my_time_window = TimeWindow(start=datetime(2023, 1, 1), end=datetime(2023, 1, 31)) - - # Call the get_df function with manually defined signals or fetched signals - df = nortech.datatools.polars.get_lazy_df( - signals=[signal1, signal2, signal3] + fetched_signals, - time_window=my_time_window, - ) - - print(df.columns) - # [ - # "timestamp", - # "workspace_1/asset_1/division_1/unit_1/signal_1", - # "workspace_1/asset_1/division_1/unit_1/signal_2", - # "workspace_2/asset_2/division_2/unit_2/signal_3", - # "workspace_3/asset_3/division_3/unit_3/signal_4", - # "workspace_3/asset_3/division_3/unit_3/signal_5", - # ] - - ``` - """ return polars_handlers.get_lazy_polars_df(self.nortech_api, signals, time_window) @@ -283,53 +146,6 @@ def get_df( NoSignalsRequestedError: Raised when no signals are requested. InvalidTimeWindow: Raised when the start date is after the end date. - Example: - ```python - from datetime import datetime - - from nortech import Nortech - from nortech.core.values.signal import SignalInput, SignalInputDict - from nortech.datatools.values.windowing import TimeWindow - - # Initialize the Nortech client - nortech = Nortech() - - # Define signals to download - signal1: SignalInputDict = { - "workspace": "workspace1", - "asset": "asset1", - "division": "division1", - "unit": "unit1", - "signal": "signal1", - } - signal2 = 789 # Signal ID - signal3 = SignalInput(workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2") - - fetched_signals = nortech.metadata.signal.list( # Fetched signals - {"workspace": "workspace3", "asset": "asset3", "division": "division3", "unit": "unit3"} - ).data - - # Define the time window for data download - my_time_window = TimeWindow(start=datetime(2023, 1, 1), end=datetime(2023, 1, 31)) - - # Call the get_df function with manually defined signals or fetched signals - df = nortech.datatools.polars.get_df( - signals=[signal1, signal2, signal3] + fetched_signals, - time_window=my_time_window, - ) - - print(df.columns) - # [ - # "timestamp", - # "workspace_1/asset_1/division_1/unit_1/signal_1", - # "workspace_1/asset_1/division_1/unit_1/signal_2", - # "workspace_2/asset_2/division_2/unit_2/signal_3", - # "workspace_3/asset_3/division_3/unit_3/signal_4", - # "workspace_3/asset_3/division_3/unit_3/signal_5", - # ] - - ``` - """ return polars_handlers.get_polars_df(self.nortech_api, signals, time_window) diff --git a/nortech/derivers/__init__.py b/nortech/derivers/__init__.py index d062e5d..6282964 100644 --- a/nortech/derivers/__init__.py +++ b/nortech/derivers/__init__.py @@ -34,62 +34,6 @@ class Derivers: Attributes: nortech_api (NortechAPI): The Nortech API client. - Example: - To define a deriver, you need to create a class that inherits from the Deriver class. - The class must have two inner classes: Inputs and Outputs. - The Inputs class must inherit from DeriverInputs and the Outputs class must inherit from DeriverOutputs. - The Inputs class must define the inputs of the deriver. - The Outputs class must define the outputs of the deriver. - The run method must be defined and return a bytewax stream. - - ```python - import bytewax.operators as op - - from nortech.derivers import Deriver, DeriverInput, DeriverInputs, DeriverOutput, DeriverOutputs - - - class MyDeriver(Deriver): - class Inputs(DeriverInputs): - input_1: float | None = DeriverInput( - workspace="workspace1", asset="asset1", division="division1", unit="unit1", signal="signal1" - ) - input_2: float | None = DeriverInput( - workspace="workspace2", asset="asset2", division="division2", unit="unit2", signal="signal2" - ) - - class Outputs(DeriverOutputs): - output_1: float = DeriverOutput( - workspace="workspace1", - asset="asset1", - division="division1", - unit="unit1", - signal="new_signal1", - description="output_1", - long_description="output_1_long_description", - physical_unit="m/s", - ) - output_2: str = DeriverOutput( - workspace="workspace2", - asset="asset2", - division="division2", - unit="unit2", - signal="new_signal2", - description="output_2", - long_description="output_2_long_description", - physical_unit="m/s", - ) - - def run(self, inputs: op.Stream[Inputs]) -> op.Stream[Outputs]: - return op.map( - "", - inputs, - lambda _input: self.Outputs( - timestamp=_input.timestamp, - output_1=_input.input_1 or 0, - output_2=str(_input.input_2), - ), - ) - ``` """ @@ -109,28 +53,6 @@ def list( Returns: PaginatedResponse[DeployedDeriver]: Paginated response of derivers. - Example: - ```python - # Define Deriver - class MyDeriver(Deriver): - ... - - - nortech = Nortech() - derivers = nortech.derivers.list() - print(derivers) - # PaginatedResponse( - # size=1, - # next=None, - # data=[ - # DeployedDeriverList( - # deriver=MyDeriver, - # description="my-description", - # start_at=None, - # ) - # ], - # ) - ``` """ return list_derivers(self.nortech_api, pagination_options) @@ -148,78 +70,6 @@ def get( Returns: DeployedDeriver: Deployed deriver. - Example: - ```python - # Define Deriver - class MyDeriver(Deriver): - ... - - nortech = Nortech() - derivers = nortech.derivers.get(MyDeriver) - print(derivers) - # DeployedDeriver( - # deriver=MyDeriver, - # description="my-description", - # start_at="2025-01-01T12:00:00Z", - # inputs=[ - # SignalOutputNoDevice( - # id=1, - # name="input_1", - # description="input_1", - # long_description="input_1_long_description", - # data_type="float", - # physical_unit="m/s", - # created_at="2025-01-01T12:00:00Z", - # updated_at="2025-01-01T12:00:00Z", - # workspace=MetadataOutput( - # id=1, - # name="workspace1", - # ), - # asset=MetadataOutput( - # id=1, - # name="asset1", - # ), - # division=MetadataOutput( - # id=1, - # name="division1", - # ), - # unit=MetadataOutput( - # id=1, - # name="unit1", - # ), - # ), - # ], - # outputs=[ - # SignalOutputNoDevice( - # id=2, - # name="output_1", - # description="output_1", - # long_description="output_1_long_description", - # data_type="float", - # physical_unit="m/s", - # created_at="2025-01-01T12:00:00Z", - # updated_at="2025-01-01T12:00:00Z", - # workspace=MetadataOutput( - # id=1, - # name="workspace1", - # ), - # asset=MetadataOutput( - # id=1, - # name="asset1", - # ), - # division=MetadataOutput( - # id=1, - # name="division1", - # ), - # unit=MetadataOutput( - # id=1, - # name="unit1", - # ), - # ), - # ] - # ) - ``` - """ return get_deriver(self.nortech_api, deriver) @@ -242,78 +92,6 @@ def create( Returns: DeployedDeriver: Deployed deriver. - Example: - ```python - # Define Deriver - class MyDeriver(Deriver): - ... - - nortech = Nortech() - derivers = nortech.derivers.create(MyDeriver, start_at=datetime.now(timezone.utc), description="my-description") - print(derivers) - # DeployedDeriver( - # deriver=MyDeriver, - # description="my-description", - # start_at=None, - # inputs=[ - # SignalOutputNoDevice( - # id=1, - # name="input_1", - # description="input_1", - # long_description="input_1_long_description", - # data_type="float", - # physical_unit="m/s", - # created_at="2025-01-01T12:00:00Z", - # updated_at="2025-01-01T12:00:00Z", - # workspace=MetadataOutput( - # id=1, - # name="workspace1", - # ), - # asset=MetadataOutput( - # id=1, - # name="asset1", - # ), - # division=MetadataOutput( - # id=1, - # name="division1", - # ), - # unit=MetadataOutput( - # id=1, - # name="unit1", - # ), - # ), - # ], - # outputs=[ - # SignalOutputNoDevice( - # id=2, - # name="output_1", - # description="output_1", - # long_description="output_1_long_description", - # data_type="float", - # physical_unit="m/s", - # created_at="2025-01-01T12:00:00Z", - # updated_at="2025-01-01T12:00:00Z", - # workspace=MetadataOutput( - # id=1, - # name="workspace1", - # ), - # asset=MetadataOutput( - # id=1, - # name="asset1", - # ), - # division=MetadataOutput( - # id=1, - # name="division1", - # ), - # unit=MetadataOutput( - # id=1, - # name="unit1", - # ), - # ), - # ] - # ) - ``` - """ return create_deriver(self.nortech_api, deriver, start_at, description, create_parents) @@ -338,77 +116,6 @@ def update( Returns: DeployedDeriver: Deployed deriver. - Example: - ```python - # Define Deriver - class MyDeriver(Deriver): - ... - - nortech = Nortech() - derivers = nortech.derivers.update(MyDeriver, start_at=datetime.now(timezone.utc), description="my-description") - print(derivers) - # DeployedDeriver( - # deriver=MyDeriver, - # description="my-description", - # start_at=None, - # inputs=[ - # SignalOutputNoDevice( - # id=1, - # name="input_1", - # description="input_1", - # long_description="input_1_long_description", - # data_type="float", - # physical_unit="m/s", - # created_at="2025-01-01T12:00:00Z", - # updated_at="2025-01-01T12:00:00Z", - # workspace=MetadataOutput( - # id=1, - # name="workspace1", - # ), - # asset=MetadataOutput( - # id=1, - # name="asset1", - # ), - # division=MetadataOutput( - # id=1, - # name="division1", - # ), - # unit=MetadataOutput( - # id=1, - # name="unit1", - # ), - # ), - # ], - # outputs=[ - # SignalOutputNoDevice( - # id=2, - # name="output_1", - # description="output_1", - # long_description="output_1_long_description", - # data_type="float", - # physical_unit="m/s", - # created_at="2025-01-01T12:00:00Z", - # updated_at="2025-01-01T12:00:00Z", - # workspace=MetadataOutput( - # id=1, - # name="workspace1", - # ), - # asset=MetadataOutput( - # id=1, - # name="asset1", - # ), - # division=MetadataOutput( - # id=1, - # name="division1", - # ), - # unit=MetadataOutput( - # id=1, - # name="unit1", - # ), - # ), - # ] - # ) - ``` """ return update_deriver(self.nortech_api, deriver, start_at, description, create_parents, keep_data=keep_data) @@ -430,45 +137,6 @@ def run_locally_with_df( Returns: DataFrame: The processed DataFrame with derived signals. - Example: - ```python - from datetime import datetime, timezone - - from nortech import Nortech - from nortech.derivers import Deriver, TimeWindow - - class MyDeriver(Deriver): - ... - - nortech = Nortech() - - # Create input DataFrame - df = pd.DataFrame( - { - "timestamp": pd.date_range(start="2023-01-01", periods=100, freq="s", tz=timezone.utc), - "input_signal": [float(i) for i in range(100)], - } - ).set_index("timestamp") - - # Run the deriver locally - result_df = nortech.derivers.run_locally_with_df(MyDeriver, df, batch_size=5000) - - print(result_df) - # output_signal - # timestamp - # 2023-01-01 00:00:00+00:00 0.0 - # 2023-01-01 00:00:01+00:00 2.0 - # 2023-01-01 00:00:02+00:00 4.0 - # 2023-01-01 00:00:03+00:00 6.0 - # 2023-01-01 00:00:04+00:00 8.0 - # ... ... - # 2023-01-01 00:01:35+00:00 190.0 - # 2023-01-01 00:01:36+00:00 192.0 - # 2023-01-01 00:01:37+00:00 194.0 - # 2023-01-01 00:01:38+00:00 196.0 - # 2023-01-01 00:01:39+00:00 198.0 - ``` - """ validate_deriver(deriver) return run_deriver_locally_with_df( @@ -494,45 +162,6 @@ def run_locally_with_source_data( Returns: DataFrame: The processed DataFrame with derived signals. - Example: - ```python - from datetime import datetime, timezone - - from nortech import Nortech - from nortech.derivers import Deriver, TimeWindow - - class MyDeriver(Deriver): - ... - - nortech = Nortech() - - # Create input DataFrame or use nortech.datatools to get data - df = pd.DataFrame( - { - "timestamp": pd.date_range(start="2023-01-01", periods=100, freq="s", tz=timezone.utc), - "input_signal": [float(i) for i in range(100)], - } - ).set_index("timestamp") - - # Run the deriver locally - result_df = nortech.derivers.run_locally_with_source_data(MyDeriver, time_window=TimeWindow(start=datetime.now(timezone.utc), end=datetime.now(timezone.utc))) - - print(result_df) - # output_signal - # timestamp - # 2023-01-01 00:00:00+00:00 0.0 - # 2023-01-01 00:00:01+00:00 2.0 - # 2023-01-01 00:00:02+00:00 4.0 - # 2023-01-01 00:00:03+00:00 6.0 - # 2023-01-01 00:00:04+00:00 8.0 - # ... ... - # 2023-01-01 00:01:35+00:00 190.0 - # 2023-01-01 00:01:36+00:00 192.0 - # 2023-01-01 00:01:37+00:00 194.0 - # 2023-01-01 00:01:38+00:00 196.0 - # 2023-01-01 00:01:39+00:00 198.0 - ``` - """ validate_deriver(deriver) return run_deriver_locally_with_source_data( diff --git a/nortech/derivers/handlers/deriver.py b/nortech/derivers/handlers/deriver.py index 3f6ebba..05fd482 100644 --- a/nortech/derivers/handlers/deriver.py +++ b/nortech/derivers/handlers/deriver.py @@ -86,14 +86,14 @@ def run_deriver_locally_with_df( ): validate_deriver(deriver) - if not isinstance(df.index, DatetimeIndex): + if not isinstance(df.index, DatetimeIndex): # type: ignore raise ValueError("df must have a datetime index") df_timezone = df.index.tz df.index = df.index.tz_convert("UTC") def df_to_inputs(df: DataFrame): - for deriver_input in df.reset_index().to_dict("records"): + for deriver_input in df.reset_index().to_dict("records"): # type: ignore input_with_none = {k: (None if isna(v) else v) for k, v in deriver_input.items()} yield deriver.Inputs.model_validate(input_with_none) @@ -110,7 +110,7 @@ def df_to_inputs(df: DataFrame): df_out = DataFrame([output.model_dump(by_alias=True) for output in output_list]) if "timestamp" in df_out.columns: - df_out = df_out.set_index("timestamp").tz_convert(df_timezone) + df_out = df_out.set_index("timestamp").tz_convert(df_timezone) # type: ignore return df_out diff --git a/nortech/derivers/services/nortech_api.py b/nortech/derivers/services/nortech_api.py index 0f7289f..7dfba6e 100644 --- a/nortech/derivers/services/nortech_api.py +++ b/nortech/derivers/services/nortech_api.py @@ -15,7 +15,7 @@ PaginatedResponse, PaginationOptions, ) -from nortech.metadata.values.signal import SignalOutputNoDevice +from nortech.metadata.values.signal import SignalOutput class DeployedDeriverList(BaseModel): @@ -31,8 +31,8 @@ def convert_deriver_string(cls, v: str): class DeployedDeriver(DeployedDeriverList): - inputs: list[SignalOutputNoDevice] - outputs: list[SignalOutputNoDevice] + inputs: list[SignalOutput] + outputs: list[SignalOutput] class Log(BaseModel): @@ -53,14 +53,14 @@ def __str__(self) -> str: def list_derivers( nortech_api: NortechAPI, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None, -): +) -> PaginatedResponse[DeployedDeriverList, Literal["id", "name", "description"]]: response = nortech_api.get( url="/api/v1/derivers", params=pagination_options.model_dump(by_alias=True) if pagination_options else None, ) validate_response(response, [200], "Failed to list Derivers.") - return PaginatedResponse[DeployedDeriverList].model_validate(response.json()) + return PaginatedResponse[DeployedDeriverList, Literal["id", "name", "description"]].model_validate(response.json()) def get_deriver(nortech_api: NortechAPI, deriver: str): diff --git a/nortech/gateways/nortech_api.py b/nortech/gateways/nortech_api.py index ab3ac66..f6cac7b 100644 --- a/nortech/gateways/nortech_api.py +++ b/nortech/gateways/nortech_api.py @@ -65,6 +65,7 @@ def request( ) -> Response: url_str = url.decode() if isinstance(url, bytes) else str(url) joined_url = urljoin(self.settings.URL, url_str) + print("requesting", joined_url, self.settings) return super().request( method, joined_url, diff --git a/nortech/logger.py b/nortech/logger.py index 3014e20..0ad0ea3 100644 --- a/nortech/logger.py +++ b/nortech/logger.py @@ -42,7 +42,7 @@ def get_logger( logger = structlog.stdlib.get_logger(nortech_sdk=True) logger.addHandler(handler) - logger.setLevel(logging.getLevelName(level)) + logger.setLevel(getattr(logging, level)) return logger diff --git a/nortech/metadata/__init__.py b/nortech/metadata/__init__.py index 8fa2504..0b1562c 100644 --- a/nortech/metadata/__init__.py +++ b/nortech/metadata/__init__.py @@ -3,7 +3,6 @@ from typing import Literal import nortech.metadata.services.asset as asset_service -import nortech.metadata.services.device as device_service import nortech.metadata.services.division as division_service import nortech.metadata.services.signal as signal_service import nortech.metadata.services.unit as unit_service @@ -16,12 +15,6 @@ AssetOutput, ) from nortech.metadata.values.common import MetadataOutput -from nortech.metadata.values.device import ( - DeviceInput, - DeviceInputDict, - DeviceListOutput, - DeviceOutput, -) from nortech.metadata.values.division import ( DivisionInput, DivisionInputDict, @@ -34,8 +27,6 @@ PaginationOptions, ) from nortech.metadata.values.signal import ( - SignalDeviceInput, - SignalDeviceInputDict, SignalInput, SignalInputDict, SignalListOutput, @@ -64,7 +55,6 @@ class Metadata: asset (Asset): Client for interacting with the Nortech Metadata Asset API. division (Division): Client for interacting with the Nortech Metadata Division API. unit (Unit): Client for interacting with the Nortech Metadata Unit API. - device (Device): Client for interacting with the Nortech Metadata Device API. signal (Signal): Client for interacting with the Nortech Metadata Signal API. """ @@ -74,7 +64,6 @@ def __init__(self, nortech_api: NortechAPI): self.asset = Asset(nortech_api) self.division = Division(nortech_api) self.unit = Unit(nortech_api) - self.device = Device(nortech_api) self.signal = Signal(nortech_api) @@ -103,43 +92,13 @@ def get( Returns: WorkspaceOutput: The workspace details. - Example: - ```python - from nortech import Nortech - from nortech.core.values.workspace import WorkspaceInput - - nortech = Nortech() - - # Get by ID - workspace = nortech.metadata.workspace.get(123) - - # Get by name - workspace = nortech.metadata.workspace.get("my-workspace") - - # Get by input dict - workspace = nortech.metadata.workspace.get({"workspace": "my-workspace"}) - - # Get by WorkspaceInput pydantic object - workspace = nortech.metadata.workspace.get(WorkspaceInput(workspace="my-workspace")) - - print(workspace) - # WorkspaceOutput( - # id=123, - # name="my-workspace", - # description="my-description", - # created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), - # updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0) - # ) - - ``` - """ return workspace_service.get_workspace(self.nortech_api, workspace) def list( self, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None, - ) -> PaginatedResponse[WorkspaceListOutput]: + ) -> PaginatedResponse[WorkspaceListOutput, Literal["id", "name", "description"]]: """ List all workspaces. @@ -149,38 +108,6 @@ def list( Returns: PaginatedResponse[WorkspaceListOutput]: A paginated list of workspaces. - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - - nortech = Nortech() - - # List all workspaces - workspaces = nortech.metadata.workspace.list() - - # List with pagination - workspaces = nortech.metadata.workspace.list(PaginationOptions(size=10, sortBy="name")) - - print(workspaces) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # WorkspaceListOutput( - # id=1, - # name="my-workspace", - # description="my-description" - # ), - # WorkspaceListOutput( - # id=2, - # name="my-workspace", - # description="my-description" - # ) - # ] - # ) - - ``` """ return workspace_service.list_workspaces(self.nortech_api, pagination_options) @@ -205,36 +132,6 @@ def get(self, asset: int | AssetInputDict | AssetInput | AssetOutput | AssetList Returns: AssetOutput: The asset details. - Example: - ```python - from nortech import Nortech - from nortech.core.values.asset import AssetInput - - nortech = Nortech() - - # Get by ID - asset = nortech.metadata.asset.get(123) - - # Get by input dict - asset = nortech.metadata.asset.get({"workspace": "my-workspace", "asset": "my-asset"}) - - # Get by AssetInput pydantic object - asset = nortech.metadata.asset.get(AssetInput(workspace="my-workspace", asset="my-asset")) - - print(asset) - # AssetOutput( - # id=123, - # name="my-asset", - # description="my-description", - # created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), - # updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), - # workspace=MetadataOutput( - # id=123, - # name="my-workspace", - # ) - # ) - - ``` """ return asset_service.get_workspace_asset(self.nortech_api, asset) @@ -243,7 +140,7 @@ def list( self, workspace: int | str | WorkspaceInputDict | WorkspaceInput | WorkspaceOutput | WorkspaceListOutput, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None, - ) -> PaginatedResponse[AssetListOutput]: + ) -> PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]]: """ List all assets in a workspace. @@ -260,49 +157,6 @@ def list( Returns: PaginatedResponse[AssetListOutput]: A paginated list of assets. - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - from nortech.core.values.workspace import WorkspaceInput - - nortech = Nortech() - - # List all assets in a workspace - assets = nortech.metadata.asset.list(123) # using workspace ID - - # List with pagination - assets = nortech.metadata.asset.list( - "my-workspace", # using workspace name - PaginationOptions(size=10, sortBy="name"), - ) - - # Using WorkspaceInputDict dictionary - assets = nortech.metadata.asset.list({"workspace": "my-workspace"}) - - # Using WorkspaceInput pydantic object - assets = nortech.metadata.asset.list(WorkspaceInput(workspace="my-workspace")) - - print(assets) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # AssetListOutput( - # id=1, - # name="my-asset", - # description="my-description" - # ), - # AssetListOutput( - # id=2, - # name="another-asset", - # description="another-description" - # ) - # ] - # ) - - ``` - """ return asset_service.list_workspace_assets(self.nortech_api, workspace, pagination_options) @@ -329,43 +183,6 @@ def get( Returns: DivisionOutput: The division details. - Example: - ```python - from nortech import Nortech - from nortech.core.values.division import DivisionInput - - nortech = Nortech() - - # Get by ID - division = nortech.metadata.division.get(123) - - # Get by input dict - division = nortech.metadata.division.get({"workspace": "my-workspace", "asset": "my-asset", "division": "my-division"}) - - # Get by DivisionInput pydantic object - division = nortech.metadata.division.get( - DivisionInput(workspace="my-workspace", asset="my-asset", division="my-division") - ) - - print(division) - # DivisionOutput( - # id=123, - # name="my-division", - # description="my-description", - # created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), - # updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), - # workspace=MetadataOutput( - # id=123, - # name="my-workspace" - # ), - # asset=MetadataOutput( - # id=456, - # name="my-asset" - # ) - # ) - - ``` - """ return division_service.get_workspace_asset_division(self.nortech_api, division) @@ -373,7 +190,7 @@ def list( self, asset: int | AssetInputDict | AssetInput | AssetOutput | AssetListOutput, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None, - ) -> PaginatedResponse[DivisionListOutput]: + ) -> PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]]: """ List all divisions in an asset. @@ -389,46 +206,6 @@ def list( Returns: PaginatedResponse[DivisionListOutput]: A paginated list of divisions. - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - from nortech.core.values.asset import AssetInput - - nortech = Nortech() - - # List all divisions in an asset - divisions = nortech.metadata.division.list(123) # using asset ID - - # List with pagination - divisions = nortech.metadata.division.list( - {"workspace": "my-workspace", "asset": "my-asset"}, # using AssetInputDict - PaginationOptions(size=10, sortBy="name"), - ) - - # Using AssetInput pydantic object - divisions = nortech.metadata.division.list(AssetInput(workspace="my-workspace", asset="my-asset")) - - print(divisions) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # DivisionListOutput( - # id=1, - # name="my-division", - # description="my-description" - # ), - # DivisionListOutput( - # id=2, - # name="another-division", - # description="another-description" - # ) - # ] - # ) - - ``` - """ return division_service.list_workspace_asset_divisions(self.nortech_api, asset, pagination_options) @@ -436,7 +213,7 @@ def list_by_workspace_id( self, workspace_id: int, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None, - ) -> PaginatedResponse[DivisionListOutput]: + ) -> PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]]: """ List all divisions in a workspace. @@ -447,39 +224,6 @@ def list_by_workspace_id( Returns: PaginatedResponse[DivisionListOutput]: A paginated list of divisions. - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - - nortech = Nortech() - - # List all divisions in a workspace - divisions = nortech.metadata.division.list_by_workspace_id(123) - - # List with pagination - divisions = nortech.metadata.division.list_by_workspace_id(123, PaginationOptions(size=10, sortBy="name")) - - print(divisions) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # DivisionListOutput( - # id=1, - # name="my-division", - # description="my-description" - # ), - # DivisionListOutput( - # id=2, - # name="another-division", - # description="another-description" - # ) - # ] - # ) - - ``` - """ return division_service.list_workspace_divisions(self.nortech_api, workspace_id, pagination_options) @@ -503,48 +247,6 @@ def get(self, unit: int | UnitInputDict | UnitInput | UnitOutput | UnitListOutpu Returns: UnitOutput: The unit details. - Example: - ```python - from nortech import Nortech - from nortech.core.values.unit import UnitInput - - nortech = Nortech() - - # Get by ID - unit = nortech.metadata.unit.get(123) - - # Get by input dict - unit = nortech.metadata.unit.get( - {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division", "unit": "my-unit"} - ) - - # Get by UnitInput pydantic object - unit = nortech.metadata.unit.get( - UnitInput(workspace="my-workspace", asset="my-asset", division="my-division", unit="my-unit") - ) - - print(unit) - # UnitOutput( - # id=123, - # name="my-unit", - # created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), - # updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), - # workspace=MetadataOutput( - # id=123, - # name="my-workspace" - # ), - # asset=MetadataOutput( - # id=456, - # name="my-asset" - # ), - # division=MetadataOutput( - # id=789, - # name="my-division" - # ) - # ) - - ``` - """ return unit_service.get_workspace_asset_division_unit(self.nortech_api, unit) @@ -552,7 +254,7 @@ def list( self, division: int | DivisionInputDict | DivisionInput | DivisionOutput | DivisionListOutput, pagination_options: PaginationOptions[Literal["id", "name"]] | None = None, - ) -> PaginatedResponse[UnitListOutput]: + ) -> PaginatedResponse[UnitListOutput, Literal["id", "name"]]: """ List all units in a division. @@ -568,44 +270,6 @@ def list( Returns: PaginatedResponse[UnitListOutput]: A paginated list of units. - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - from nortech.core.values.division import DivisionInput - - nortech = Nortech() - - # List all units in a division - units = nortech.metadata.unit.list(123) # using division ID - - # List with pagination - units = nortech.metadata.unit.list( - {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division"}, # using DivisionInputDict - PaginationOptions(size=10, sortBy="name"), - ) - - # Using DivisionInput pydantic object - units = nortech.metadata.unit.list(DivisionInput(workspace="my-workspace", asset="my-asset", division="my-division")) - - print(units) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # UnitListOutput( - # id=1, - # name="my-unit" - # ), - # UnitListOutput( - # id=2, - # name="another-unit" - # ) - # ] - # ) - - ``` - """ return unit_service.list_workspace_asset_division_units(self.nortech_api, division, pagination_options) @@ -613,7 +277,7 @@ def list_by_workspace_id( self, workspace_id: int, pagination_options: PaginationOptions[Literal["id", "name"]] | None = None, - ) -> PaginatedResponse[UnitListOutput]: + ) -> PaginatedResponse[UnitListOutput, Literal["id", "name"]]: """ List all units in a workspace. @@ -624,37 +288,6 @@ def list_by_workspace_id( Returns: PaginatedResponse[UnitListOutput]: A paginated list of units. - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - - nortech = Nortech() - - # List all units in a workspace - units = nortech.metadata.unit.list_by_workspace_id(123) - - # List with pagination - units = nortech.metadata.unit.list_by_workspace_id(123, PaginationOptions(size=10, sortBy="name")) - - print(units) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # UnitListOutput( - # id=1, - # name="my-unit" - # ), - # UnitListOutput( - # id=2, - # name="another-unit" - # ) - # ] - # ) - - ``` - """ return unit_service.list_workspace_units(self.nortech_api, workspace_id, pagination_options) @@ -662,7 +295,7 @@ def list_by_asset_id( self, asset_id: int, pagination_options: PaginationOptions[Literal["id", "name"]] | None = None, - ) -> PaginatedResponse[UnitListOutput]: + ) -> PaginatedResponse[UnitListOutput, Literal["id", "name"]]: """ List all units in an asset. @@ -673,408 +306,38 @@ def list_by_asset_id( Returns: PaginatedResponse[UnitListOutput]: A paginated list of units. - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - - nortech = Nortech() - - # List all units in an asset - units = nortech.metadata.unit.list_by_asset_id(123) - - # List with pagination - units = nortech.metadata.unit.list_by_asset_id(123, PaginationOptions(size=10, sortBy="name")) - - print(units) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # UnitListOutput( - # id=1, - # name="my-unit" - # ), - # UnitListOutput( - # id=2, - # name="another-unit" - # ) - # ] - # ) - ``` - """ return unit_service.list_asset_units(self.nortech_api, asset_id, pagination_options) -class Device: - def __init__(self, nortech_api: NortechAPI): - self.nortech_api = nortech_api - - def get( - self, - device: int | DeviceInputDict | DeviceInput | DeviceOutput | DeviceListOutput, - ) -> DeviceOutput: - """ - Get a device by ID or input. - - Args: - device (int | DeviceInputDict | DeviceInput | DeviceOutput | DeviceListOutput): The device identifier, which can be: - - *int*: The device "ID". - - [DeviceInputDict](#deviceinputdict): A dictionary representation of a device input. - - [DeviceInput](#deviceinput): A pydantic model representing a device input. - - [DeviceOutput](#deviceoutput): A pydantic model representing a device output. Obtained from requesting a device metadata. - - [DeviceListOutput](#devicelistoutput): A pydantic model representing a listed device output. Obtained from requesting devices metadata. - - Returns: - DeviceOutput: The device details. - - Example: - ```python - from nortech import Nortech - from nortech.core.values.device import DeviceInput - - nortech = Nortech() - - # Get by ID - device = nortech.metadata.device.get(123) - - # Get by input dict - device = nortech.metadata.device.get( - {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division", "device": "my-device"} - ) - - # Get by DeviceInput pydantic object - device = nortech.metadata.device.get( - DeviceInput(workspace="my-workspace", asset="my-asset", division="my-division", device="my-device") - ) - - print(device) - # DeviceOutput( - # id=123, - # name="my-device", - # type="my-type", - # onboarded=True, - # created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), - # updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), - # workspace=MetadataOutput( - # id=123, - # name="my-workspace" - # ), - # asset=MetadataOutput( - # id=456, - # name="my-asset" - # ), - # division=MetadataOutput( - # id=789, - # name="my-division" - # ) - # ) - - ``` - - """ - return device_service.get_workspace_asset_division_device(self.nortech_api, device) - - def list( - self, - division: int | DivisionInputDict | DivisionInput | DivisionOutput | DivisionListOutput, - pagination_options: PaginationOptions[Literal["id", "name", "type", "onboarded"]] | None = None, - ) -> PaginatedResponse[DeviceListOutput]: - """ - List all devices in a division. - - Args: - division (int | DivisionInputDict | DivisionInput | DivisionOutput | DivisionListOutput): The division identifier, which can be: - - *int*: The division "ID". - - [DivisionInputDict](#divisioninputdict): A dictionary representation of a division input. - - [DivisionInput](#divisioninput): A pydantic model representing a division input. - - [DivisionOutput](#divisionoutput): A pydantic model representing a division output. - - [DivisionListOutput](#divisionlistoutput): A pydantic model representing a listed division output. - pagination_options (PaginationOptions, optional): Pagination settings. - - Returns: - PaginatedResponse[DeviceListOutput]: A paginated list of devices. - - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - from nortech.core.values.division import DivisionInput - - nortech = Nortech() - - # List all devices in a division - devices = nortech.metadata.device.list(123) # using division ID - - # List with pagination - devices = nortech.metadata.device.list( - {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division"}, # using DivisionInputDict - PaginationOptions(size=10, sortBy="name"), - ) - - # Using DivisionInput pydantic object - devices = nortech.metadata.device.list( - DivisionInput(workspace="my-workspace", asset="my-asset", division="my-division") - ) - - print(devices) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # DeviceListOutput( - # id=1, - # name="my-device", - # type="my-type", - # onboarded=True - # ), - # DeviceListOutput( - # id=2, - # name="another-device", - # type="another-type", - # onboarded=False - # ) - # ] - # ) - - ``` - - """ - return device_service.list_workspace_asset_division_devices(self.nortech_api, division, pagination_options) - - def list_by_workspace_id( - self, - workspace_id: int, - pagination_options: PaginationOptions[Literal["id", "name", "type", "onboarded"]] | None = None, - ) -> PaginatedResponse[DeviceListOutput]: - """ - List all devices in a workspace. - - Args: - workspace_id (int): The workspace ID. - pagination_options (PaginationOptions, optional): Pagination settings. - - Returns: - PaginatedResponse[DeviceListOutput]: A paginated list of devices. - - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - - nortech = Nortech() - - # List all devices in a workspace - devices = nortech.metadata.device.list_by_workspace_id(123) - - # List with pagination - devices = nortech.metadata.device.list_by_workspace_id(123, PaginationOptions(size=10, sortBy="name")) - - print(devices) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # DeviceListOutput( - # id=1, - # name="my-device", - # type="my-type", - # onboarded=True - # ), - # DeviceListOutput( - # id=2, - # name="another-device", - # type="another-type", - # onboarded=False - # ) - # ] - # ) - - ``` - - """ - return device_service.list_workspace_devices(self.nortech_api, workspace_id, pagination_options) - - def list_by_asset_id( - self, - asset_id: int, - pagination_options: PaginationOptions[Literal["id", "name", "type", "onboarded"]] | None = None, - ) -> PaginatedResponse[DeviceListOutput]: - """ - List all devices in an asset. - - Args: - asset_id (int): The asset ID. - pagination_options (PaginationOptions, optional): Pagination settings. - - Returns: - PaginatedResponse[DeviceListOutput]: A paginated list of devices. - - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - - nortech = Nortech() - - # List all devices in an asset - devices = nortech.metadata.device.list_by_asset_id(123) - - # List with pagination - devices = nortech.metadata.device.list_by_asset_id(123, PaginationOptions(size=10, sortBy="name")) - - print(devices) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # DeviceListOutput( - # id=1, - # name="my-device", - # type="my-type", - # onboarded=True - # ), - # DeviceListOutput( - # id=2, - # name="another-device", - # type="another-type", - # onboarded=False - # ) - # ] - # ) - - ``` - - """ - return device_service.list_asset_devices(self.nortech_api, asset_id, pagination_options) - - class Signal: def __init__(self, nortech_api: NortechAPI): self.nortech_api = nortech_api - def get( - self, - signal: int - | SignalInputDict - | SignalInput - | SignalOutput - | SignalListOutput - | SignalDeviceInputDict - | SignalDeviceInput, - ) -> SignalOutput: + def get(self, signal: int | SignalInputDict | SignalInput | SignalOutput | SignalListOutput) -> SignalOutput: """ Get a signal by ID or input. Args: - signal (int | SignalInputDict | SignalInput | SignalOutput | SignalListOutput | SignalDeviceInputDict | SignalDeviceInput): The signal identifier, which can be: + signal (int | SignalInputDict | SignalInput | SignalOutput | SignalListOutput): The signal identifier, which can be: - *int*: The signal "ID". - [SignalInputDict](#signalinputdict): A dictionary representation of a signal input. - [SignalInput](#signalinput): A pydantic model representing a signal input. - [SignalOutput](#signaloutput): A pydantic model representing a signal output. Obtained from requesting a signal metadata. - [SignalListOutput](#signallistoutput): A pydantic model representing a listed signal output. Obtained from requesting signals metadata. - - [SignalDeviceInputDict](#signaldeviceinputdict): A dictionary representation of a device signal input. - - [SignalDeviceInput](#signaldeviceinput): A pydantic model representing a device signal input. Returns: SignalOutput: The signal details. - Example: - ```python - from nortech import Nortech - from nortech.core.values.signal import SignalDeviceInput, SignalInput - - nortech = Nortech() - - # Get by ID - signal = nortech.metadata.signal.get(123) - - # Get unit signal by input dict - signal = nortech.metadata.signal.get( - { - "workspace": "my-workspace", - "asset": "my-asset", - "division": "my-division", - "unit": "my-unit", - "signal": "my-signal", - } - ) - - # Get device signal by input dict - signal = nortech.metadata.signal.get( - { - "workspace": "my-workspace", - "asset": "my-asset", - "division": "my-division", - "device": "my-device", - "signal": "my-signal", - } - ) - - # Get by SignalInput pydantic object - signal = nortech.metadata.signal.get( - SignalInput( - workspace="my-workspace", asset="my-asset", division="my-division", unit="my-unit", signal="my-signal" - ) - ) - - # Get by SignalDeviceInput pydantic object - signal = nortech.metadata.signal.get( - SignalDeviceInput( - workspace="my-workspace", asset="my-asset", division="my-division", device="my-device", signal="my-signal" - ) - ) - - print(signal) - # SignalOutput( - # id=123, - # name="my-signal", - # physical_unit="°C", - # data_type="float64", - # description="Temperature sensor", - # long_description="Main temperature sensor for the unit", - # created_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), - # updated_at=datetime.datetime(2024, 1, 1, 0, 0, 0, 0), - # workspace=MetadataOutput( - # id=123, - # name="my-workspace" - # ), - # asset=MetadataOutput( - # id=456, - # name="my-asset" - # ), - # division=MetadataOutput( - # id=789, - # name="my-division" - # ), - # unit=MetadataOutput( - # id=101, - # name="my-unit" - # ) - # device=MetadataOutput( - # id=101, - # name="my-device" - # ) - # ) - - ``` - """ if isinstance(signal, dict): - if "device" in signal: - signal = SignalDeviceInput.model_validate(signal) - else: - signal = SignalInput.model_validate(signal) - - if isinstance(signal, SignalDeviceInput): - return signal_service.get_workspace_asset_division_device_signal(self.nortech_api, signal) + signal = SignalInput.model_validate(signal) return signal_service.get_workspace_asset_division_unit_signal(self.nortech_api, signal) def list( self, - unit_or_device: int | UnitInputDict | UnitInput | UnitOutput | DeviceInputDict | DeviceInput | DeviceOutput, + unit: int | UnitInputDict | UnitInput | UnitOutput, pagination_options: PaginationOptions[ Literal[ "id", @@ -1086,99 +349,29 @@ def list( ] ] | None = None, - ) -> PaginatedResponse[SignalListOutput]: + ) -> PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ]: """ - List all signals in a unit or device. + List all signals in a unit. Args: - unit_or_device (int | UnitInputDict | UnitInput | UnitOutput | DeviceInputDict | DeviceInput | DeviceOutput): The unit or device identifier, which can be: - - *int*: The unit/device "ID". + unit (int | UnitInputDict | UnitInput | UnitOutput): The unit identifier, which can be: + - *int*: The unit "ID". - [UnitInputDict](#unitinputdict): A dictionary representation of a unit input. - [UnitInput](#unitinput): A pydantic model representing a unit input. - [UnitOutput](#unitoutput): A pydantic model representing a unit output. - - [DeviceInputDict](#deviceinputdict): A dictionary representation of a device input. - - [DeviceInput](#deviceinput): A pydantic model representing a device input. - - [DeviceOutput](#deviceoutput): A pydantic model representing a device output. pagination_options (PaginationOptions, optional): Pagination settings. Returns: PaginatedResponse[SignalListOutput]: A paginated list of signals. - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - from nortech.core.values.device import DeviceInput - from nortech.core.values.unit import UnitInput - - nortech = Nortech() - - # List all signals in a unit - signals = nortech.metadata.signal.list(123) # using unit ID - - # List unit signals with pagination - signals = nortech.metadata.signal.list( - {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division", "unit": "my-unit"}, - PaginationOptions(size=10, sortBy="name"), - ) - - # List device signals with pagination - signals = nortech.metadata.signal.list( - {"workspace": "my-workspace", "asset": "my-asset", "division": "my-division", "device": "my-device"}, - PaginationOptions(size=10, sortBy="name"), - ) - - # Using UnitInput pydantic object - signals = nortech.metadata.signal.list( - UnitInput(workspace="my-workspace", asset="my-asset", division="my-division", unit="my-unit") - ) - - # Using DeviceInput pydantic object - signals = nortech.metadata.signal.list( - DeviceInput(workspace="my-workspace", asset="my-asset", division="my-division", device="my-device") - ) - - print(signals) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # SignalListOutput( - # id=1, - # name="my-signal", - # physical_unit="°C", - # data_type="float64", - # description="Temperature sensor", - # long_description="Main temperature sensor for the unit" - # ), - # SignalListOutput( - # id=2, - # name="another-signal", - # physical_unit="bar", - # data_type="float64", - # description="Pressure sensor", - # long_description="Main pressure sensor for the unit" - # ) - # ] - # ) - - ``` """ - if isinstance(unit_or_device, dict): - if "device" in unit_or_device: - unit_or_device = DeviceInput.model_validate(unit_or_device) - else: - unit_or_device = UnitInput.model_validate(unit_or_device) - - if isinstance(unit_or_device, DeviceInput) or isinstance(unit_or_device, DeviceOutput): - return signal_service.list_workspace_asset_division_device_signals( - self.nortech_api, unit_or_device, pagination_options - ) + if isinstance(unit, dict): + unit = UnitInput.model_validate(unit) - return signal_service.list_workspace_asset_division_unit_signals( - self.nortech_api, unit_or_device, pagination_options - ) + return signal_service.list_workspace_asset_division_unit_signals(self.nortech_api, unit, pagination_options) def list_by_workspace_id( self, @@ -1194,7 +387,9 @@ def list_by_workspace_id( ] ] | None = None, - ) -> PaginatedResponse[SignalListOutput]: + ) -> PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ]: """ List all signals in a workspace. @@ -1205,44 +400,6 @@ def list_by_workspace_id( Returns: PaginatedResponse[SignalListOutput]: A paginated list of signals. - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - - nortech = Nortech() - - # List all signals in a workspace - signals = nortech.metadata.signal.list_by_workspace_id(123) - - # List with pagination - signals = nortech.metadata.signal.list_by_workspace_id(123, PaginationOptions(size=10, sortBy="name")) - - print(signals) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # SignalListOutput( - # id=1, - # name="my-signal", - # physical_unit="°C", - # data_type="float64", - # description="Temperature sensor", - # long_description="Main temperature sensor for the unit" - # ), - # SignalListOutput( - # id=2, - # name="another-signal", - # physical_unit="bar", - # data_type="float64", - # description="Pressure sensor", - # long_description="Main pressure sensor for the unit" - # ) - # ] - # ) - - ``` """ return signal_service.list_workspace_signals(self.nortech_api, workspace_id, pagination_options) @@ -1261,7 +418,9 @@ def list_by_asset_id( ] ] | None = None, - ) -> PaginatedResponse[SignalListOutput]: + ) -> PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ]: """ List all signals in an asset. @@ -1272,45 +431,6 @@ def list_by_asset_id( Returns: PaginatedResponse[SignalListOutput]: A paginated list of signals. - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - - nortech = Nortech() - - # List all signals in an asset - signals = nortech.metadata.signal.list_by_asset_id(123) - - # List with pagination - signals = nortech.metadata.signal.list_by_asset_id(123, PaginationOptions(size=10, sortBy="name")) - - print(signals) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # SignalListOutput( - # id=1, - # name="my-signal", - # physical_unit="°C", - # data_type="float64", - # description="Temperature sensor", - # long_description="Main temperature sensor for the unit" - # ), - # SignalListOutput( - # id=2, - # name="another-signal", - # physical_unit="bar", - # data_type="float64", - # description="Pressure sensor", - # long_description="Main pressure sensor for the unit" - # ) - # ] - # ) - - - ``` """ return signal_service.list_asset_signals(self.nortech_api, asset_id, pagination_options) @@ -1329,7 +449,9 @@ def list_by_division_id( ] ] | None = None, - ) -> PaginatedResponse[SignalListOutput]: + ) -> PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ]: """ List all signals in a division. @@ -1340,45 +462,6 @@ def list_by_division_id( Returns: PaginatedResponse[SignalListOutput]: A paginated list of signals. - Example: - ```python - from nortech import Nortech - from nortech.gateways.nortech_api import PaginationOptions - - nortech = Nortech() - - # List all signals in a division - signals = nortech.metadata.signal.list_by_division_id(123) - - # List with pagination - signals = nortech.metadata.signal.list_by_division_id(123, PaginationOptions(size=10, sortBy="name")) - - print(signals) - # PaginatedResponse( - # size=2, - # next=None, - # data=[ - # SignalListOutput( - # id=1, - # name="my-signal", - # physical_unit="°C", - # data_type="float64", - # description="Temperature sensor", - # long_description="Main temperature sensor for the unit" - # ), - # SignalListOutput( - # id=2, - # name="another-signal", - # physical_unit="bar", - # data_type="float64", - # description="Pressure sensor", - # long_description="Main pressure sensor for the unit" - # ) - # ] - # ) - - - ``` """ return signal_service.list_division_signals(self.nortech_api, division_id, pagination_options) diff --git a/nortech/metadata/services/asset.py b/nortech/metadata/services/asset.py index 687a500..8f07d26 100644 --- a/nortech/metadata/services/asset.py +++ b/nortech/metadata/services/asset.py @@ -30,7 +30,7 @@ def list_workspace_assets( nortech_api: NortechAPI, workspace: WorkspaceInputDict | WorkspaceInput | WorkspaceOutput | WorkspaceListOutput | int | str, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None, -): +) -> PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]]: workspace_input = parse_workspace_input(workspace) response = nortech_api.get( url=f"/api/v1/workspaces/{workspace_input}/assets", @@ -38,7 +38,7 @@ def list_workspace_assets( ) validate_response(response) - resp = PaginatedResponse[AssetListOutput].model_validate( + resp = PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]].model_validate( {**response.json(), "pagination_options": pagination_options} ) diff --git a/nortech/metadata/services/device.py b/nortech/metadata/services/device.py deleted file mode 100644 index 9d8019c..0000000 --- a/nortech/metadata/services/device.py +++ /dev/null @@ -1,169 +0,0 @@ -from __future__ import annotations - -from typing import Literal - -from nortech.gateways.nortech_api import ( - NortechAPI, - validate_response, -) -from nortech.metadata.services.division import ( - DivisionInput, - DivisionInputDict, - DivisionListOutput, - DivisionOutput, - parse_division_input, -) -from nortech.metadata.values.device import ( - DeviceInput, - DeviceInputDict, - DeviceListOutput, - DeviceOutput, - parse_device_input, -) -from nortech.metadata.values.pagination import ( - PaginatedResponse, - PaginationOptions, -) - - -def list_workspace_asset_division_devices( - nortech_api: NortechAPI, - division: int | DivisionInputDict | DivisionInput | DivisionOutput | DivisionListOutput, - pagination_options: PaginationOptions[Literal["id", "name", "type", "onboarded"]] | None = None, -): - if isinstance(division, int): - return list_division_devices(nortech_api, division, pagination_options) - if isinstance(division, DivisionListOutput): - return list_division_devices(nortech_api, division.id, pagination_options) - - division_input = parse_division_input(division) - response = nortech_api.get( - url=f"/api/v1/workspaces/{division_input.workspace}/assets/{division_input.asset}/divisions/{division_input.division}/devices", - params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, - ) - validate_response(response) - - resp = PaginatedResponse[DeviceListOutput].model_validate( - {**response.json(), "pagination_options": pagination_options} - ) - - if nortech_api.ignore_pagination and resp.next and resp.next.token: - next_resp = list_workspace_asset_division_devices(nortech_api, division, resp.next_pagination_options()) - return resp.model_copy( - update={ - "data": resp.data + next_resp.data, - "size": resp.size + next_resp.size, - "next": next_resp.next, - } - ) - - return resp - - -def get_workspace_asset_division_device( - nortech_api: NortechAPI, - device: int | DeviceInputDict | DeviceInput | DeviceOutput | DeviceListOutput, -): - if isinstance(device, int): - return get_device(nortech_api, device) - if isinstance(device, DeviceListOutput): - return get_device(nortech_api, device.id) - - device_input = parse_device_input(device) - response = nortech_api.get( - url=f"/api/v1/workspaces/{device_input.workspace}/assets/{device_input.asset}/divisions/{device_input.division}/devices/{device_input.device}", - ) - validate_response(response) - return DeviceOutput.model_validate(response.json()) - - -def list_workspace_devices( - nortech_api: NortechAPI, - workspace_id: int, - pagination_options: PaginationOptions[Literal["id", "name", "type", "onboarded"]] | None = None, -): - response = nortech_api.get( - url=f"/api/v1/workspaces/{workspace_id}/devices", - params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, - ) - validate_response(response) - - resp = PaginatedResponse[DeviceListOutput].model_validate( - {**response.json(), "pagination_options": pagination_options} - ) - - if nortech_api.ignore_pagination and resp.next and resp.next.token: - next_resp = list_workspace_devices(nortech_api, workspace_id, resp.next_pagination_options()) - return resp.model_copy( - update={ - "data": resp.data + next_resp.data, - "size": resp.size + next_resp.size, - "next": next_resp.next, - } - ) - - return resp - - -def list_asset_devices( - nortech_api: NortechAPI, - asset_id: int, - pagination_options: PaginationOptions[Literal["id", "name", "type", "onboarded"]] | None = None, -): - response = nortech_api.get( - url=f"/api/v1/assets/{asset_id}/devices", - params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, - ) - validate_response(response) - - resp = PaginatedResponse[DeviceListOutput].model_validate( - {**response.json(), "pagination_options": pagination_options} - ) - - if nortech_api.ignore_pagination and resp.next and resp.next.token: - next_resp = list_asset_devices(nortech_api, asset_id, resp.next_pagination_options()) - return resp.model_copy( - update={ - "data": resp.data + next_resp.data, - "size": resp.size + next_resp.size, - "next": next_resp.next, - } - ) - - return resp - - -def list_division_devices( - nortech_api: NortechAPI, - division_id: int, - pagination_options: PaginationOptions[Literal["id", "name", "type", "onboarded"]] | None = None, -): - response = nortech_api.get( - url=f"/api/v1/divisions/{division_id}/devices", - params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, - ) - validate_response(response) - - resp = PaginatedResponse[DeviceListOutput].model_validate( - {**response.json(), "pagination_options": pagination_options} - ) - - if nortech_api.ignore_pagination and resp.next and resp.next.token: - next_resp = list_division_devices(nortech_api, division_id, resp.next_pagination_options()) - return resp.model_copy( - update={ - "data": resp.data + next_resp.data, - "size": resp.size + next_resp.size, - "next": next_resp.next, - } - ) - - return resp - - -def get_device(nortech_api: NortechAPI, device_id: int): - response = nortech_api.get( - url=f"/api/v1/devices/{device_id}", - ) - validate_response(response) - return DeviceOutput.model_validate(response.json()) diff --git a/nortech/metadata/services/division.py b/nortech/metadata/services/division.py index 6c1c3f4..64e8d72 100644 --- a/nortech/metadata/services/division.py +++ b/nortech/metadata/services/division.py @@ -30,7 +30,7 @@ def list_workspace_asset_divisions( nortech_api: NortechAPI, asset: int | AssetInputDict | AssetInput | AssetOutput | AssetListOutput, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None, -): +) -> PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]]: if isinstance(asset, int): return list_asset_divisions(nortech_api, asset, pagination_options) if isinstance(asset, AssetListOutput): @@ -43,7 +43,7 @@ def list_workspace_asset_divisions( ) validate_response(response) - resp = PaginatedResponse[DivisionListOutput].model_validate( + resp = PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]].model_validate( {**response.json(), "pagination_options": pagination_options} ) @@ -81,14 +81,14 @@ def list_workspace_divisions( nortech_api: NortechAPI, workspace_id: int, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None, -): +) -> PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]]: response = nortech_api.get( url=f"/api/v1/workspaces/{workspace_id}/divisions", params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, ) validate_response(response) - resp = PaginatedResponse[DivisionListOutput].model_validate( + resp = PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]].model_validate( {**response.json(), "pagination_options": pagination_options} ) @@ -109,14 +109,14 @@ def list_asset_divisions( nortech_api: NortechAPI, asset_id: int, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None, -): +) -> PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]]: response = nortech_api.get( url=f"/api/v1/assets/{asset_id}/divisions", params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, ) validate_response(response) - resp = PaginatedResponse[DivisionListOutput].model_validate( + resp = PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]].model_validate( {**response.json(), "pagination_options": pagination_options} ) diff --git a/nortech/metadata/services/signal.py b/nortech/metadata/services/signal.py index e4a5ba6..a530cf2 100644 --- a/nortech/metadata/services/signal.py +++ b/nortech/metadata/services/signal.py @@ -6,13 +6,6 @@ NortechAPI, validate_response, ) -from nortech.metadata.services.device import ( - DeviceInput, - DeviceInputDict, - DeviceListOutput, - DeviceOutput, - parse_device_input, -) from nortech.metadata.services.unit import ( UnitInput, UnitInputDict, @@ -25,13 +18,10 @@ PaginationOptions, ) from nortech.metadata.values.signal import ( - SignalDeviceInput, - SignalDeviceInputDict, SignalInput, SignalInputDict, SignalListOutput, SignalOutput, - parse_signal_device_input, parse_signal_input, ) @@ -63,9 +53,9 @@ def list_workspace_asset_division_unit_signals( ) validate_response(response) - resp = PaginatedResponse[SignalListOutput].model_validate( - {**response.json(), "pagination_options": pagination_options} - ) + resp = PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ].model_validate({**response.json(), "pagination_options": pagination_options}) if nortech_api.ignore_pagination and resp.next and resp.next.token: next_resp = list_workspace_asset_division_unit_signals(nortech_api, unit, resp.next_pagination_options()) @@ -97,63 +87,6 @@ def get_workspace_asset_division_unit_signal( return SignalOutput.model_validate(response.json()) -def list_workspace_asset_division_device_signals( - nortech_api: NortechAPI, - device: DeviceInputDict | DeviceInput | DeviceOutput | DeviceListOutput, - pagination_options: PaginationOptions[ - Literal[ - "id", - "name", - "physical_unit", - "data_type", - "description", - "long_description", - ] - ] - | None = None, -): - if isinstance(device, DeviceListOutput): - return list_device_signals(nortech_api, device.id, pagination_options) - - device_input = parse_device_input(device) - response = nortech_api.get( - url=f"/api/v1/workspaces/{device_input.workspace}/assets/{device_input.asset}/divisions/{device_input.division}/devices/{device_input.device}/signals", - params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, - ) - validate_response(response) - - resp = PaginatedResponse[SignalListOutput].model_validate( - {**response.json(), "pagination_options": pagination_options} - ) - - if nortech_api.ignore_pagination and resp.next and resp.next.token: - next_resp = list_workspace_asset_division_device_signals(nortech_api, device, resp.next_pagination_options()) - return resp.model_copy( - update={ - "data": resp.data + next_resp.data, - "size": resp.size + next_resp.size, - "next": next_resp.next, - } - ) - - return resp - - -def get_workspace_asset_division_device_signal( - nortech_api: NortechAPI, - signal: SignalDeviceInputDict | SignalDeviceInput | SignalOutput | SignalListOutput, -): - if isinstance(signal, SignalListOutput): - return get_signal(nortech_api, signal.id) - - signal_input = parse_signal_device_input(signal) - response = nortech_api.get( - url=f"/api/v1/workspaces/{signal_input.workspace}/assets/{signal_input.asset}/divisions/{signal_input.division}/devices/{signal_input.device}/signals/{signal_input.signal}", - ) - validate_response(response) - return SignalOutput.model_validate(response.json()) - - def list_workspace_signals( nortech_api: NortechAPI, workspace_id: int, @@ -175,9 +108,9 @@ def list_workspace_signals( ) validate_response(response) - resp = PaginatedResponse[SignalListOutput].model_validate( - {**response.json(), "pagination_options": pagination_options} - ) + resp = PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ].model_validate({**response.json(), "pagination_options": pagination_options}) if nortech_api.ignore_pagination and resp.next and resp.next.token: next_resp = list_workspace_signals(nortech_api, workspace_id, resp.next_pagination_options()) @@ -206,16 +139,18 @@ def list_asset_signals( ] ] | None = None, -): +) -> PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] +]: response = nortech_api.get( url=f"/api/v1/assets/{asset_id}/signals", params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, ) validate_response(response) - resp = PaginatedResponse[SignalListOutput].model_validate( - {**response.json(), "pagination_options": pagination_options} - ) + resp = PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ].model_validate({**response.json(), "pagination_options": pagination_options}) if nortech_api.ignore_pagination and resp.next and resp.next.token: next_resp = list_asset_signals(nortech_api, asset_id, resp.next_pagination_options()) @@ -244,16 +179,18 @@ def list_division_signals( ] ] | None = None, -): +) -> PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] +]: response = nortech_api.get( url=f"/api/v1/divisions/{division_id}/signals", params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, ) validate_response(response) - resp = PaginatedResponse[SignalListOutput].model_validate( - {**response.json(), "pagination_options": pagination_options} - ) + resp = PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ].model_validate({**response.json(), "pagination_options": pagination_options}) if nortech_api.ignore_pagination and resp.next and resp.next.token: next_resp = list_division_signals(nortech_api, division_id, resp.next_pagination_options()) @@ -282,16 +219,18 @@ def list_unit_signals( ] ] | None = None, -): +) -> PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] +]: response = nortech_api.get( url=f"/api/v1/units/{unit_id}/signals", params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, ) validate_response(response) - resp = PaginatedResponse[SignalListOutput].model_validate( - {**response.json(), "pagination_options": pagination_options} - ) + resp = PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ].model_validate({**response.json(), "pagination_options": pagination_options}) if nortech_api.ignore_pagination and resp.next and resp.next.token: next_resp = list_unit_signals(nortech_api, unit_id, resp.next_pagination_options()) @@ -306,44 +245,6 @@ def list_unit_signals( return resp -def list_device_signals( - nortech_api: NortechAPI, - device_id: int, - pagination_options: PaginationOptions[ - Literal[ - "id", - "name", - "physical_unit", - "data_type", - "description", - "long_description", - ] - ] - | None = None, -): - response = nortech_api.get( - url=f"/api/v1/devices/{device_id}/signals", - params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, - ) - validate_response(response) - - resp = PaginatedResponse[SignalListOutput].model_validate( - {**response.json(), "pagination_options": pagination_options} - ) - - if nortech_api.ignore_pagination and resp.next and resp.next.token: - next_resp = list_device_signals(nortech_api, device_id, resp.next_pagination_options()) - return resp.model_copy( - update={ - "data": resp.data + next_resp.data, - "size": resp.size + next_resp.size, - "next": next_resp.next, - } - ) - - return resp - - def get_signal(nortech_api: NortechAPI, signal_id: int): response = nortech_api.get( url=f"/api/v1/signals/{signal_id}", diff --git a/nortech/metadata/services/unit.py b/nortech/metadata/services/unit.py index c673515..8a6f9b4 100644 --- a/nortech/metadata/services/unit.py +++ b/nortech/metadata/services/unit.py @@ -30,7 +30,7 @@ def list_workspace_asset_division_units( nortech_api: NortechAPI, division: int | DivisionInputDict | DivisionInput | DivisionOutput | DivisionListOutput, pagination_options: PaginationOptions[Literal["id", "name"]] | None = None, -): +) -> PaginatedResponse[UnitListOutput, Literal["id", "name"]]: if isinstance(division, int): return list_division_units(nortech_api, division, pagination_options) if isinstance(division, DivisionListOutput): @@ -43,7 +43,7 @@ def list_workspace_asset_division_units( ) validate_response(response) - resp = PaginatedResponse[UnitListOutput].model_validate( + resp = PaginatedResponse[UnitListOutput, Literal["id", "name"]].model_validate( {**response.json(), "pagination_options": pagination_options} ) @@ -81,14 +81,14 @@ def list_workspace_units( nortech_api: NortechAPI, workspace_id: int, pagination_options: PaginationOptions[Literal["id", "name"]] | None = None, -): +) -> PaginatedResponse[UnitListOutput, Literal["id", "name"]]: response = nortech_api.get( url=f"/api/v1/workspaces/{workspace_id}/units", params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, ) validate_response(response) - resp = PaginatedResponse[UnitListOutput].model_validate( + resp = PaginatedResponse[UnitListOutput, Literal["id", "name"]].model_validate( {**response.json(), "pagination_options": pagination_options} ) @@ -109,14 +109,14 @@ def list_asset_units( nortech_api: NortechAPI, asset_id: int, pagination_options: PaginationOptions[Literal["id", "name"]] | None = None, -): +) -> PaginatedResponse[UnitListOutput, Literal["id", "name"]]: response = nortech_api.get( url=f"/api/v1/assets/{asset_id}/units", params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, ) validate_response(response) - resp = PaginatedResponse[UnitListOutput].model_validate( + resp = PaginatedResponse[UnitListOutput, Literal["id", "name"]].model_validate( {**response.json(), "pagination_options": pagination_options} ) @@ -137,14 +137,14 @@ def list_division_units( nortech_api: NortechAPI, division_id: int, pagination_options: PaginationOptions[Literal["id", "name"]] | None = None, -): +) -> PaginatedResponse[UnitListOutput, Literal["id", "name"]]: response = nortech_api.get( url=f"/api/v1/divisions/{division_id}/units", params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, ) validate_response(response) - resp = PaginatedResponse[UnitListOutput].model_validate( + resp = PaginatedResponse[UnitListOutput, Literal["id", "name"]].model_validate( {**response.json(), "pagination_options": pagination_options} ) diff --git a/nortech/metadata/services/workspace.py b/nortech/metadata/services/workspace.py index add74e6..8730108 100644 --- a/nortech/metadata/services/workspace.py +++ b/nortech/metadata/services/workspace.py @@ -22,14 +22,14 @@ def list_workspaces( nortech_api: NortechAPI, pagination_options: PaginationOptions[Literal["id", "name", "description"]] | None = None, -) -> PaginatedResponse[WorkspaceListOutput]: +) -> PaginatedResponse[WorkspaceListOutput, Literal["id", "name", "description"]]: response = nortech_api.get( url="/api/v1/workspaces", params=pagination_options.model_dump(exclude_none=True, by_alias=True) if pagination_options else None, ) validate_response(response) - resp = PaginatedResponse[WorkspaceListOutput].model_validate( + resp = PaginatedResponse[WorkspaceListOutput, Literal["id", "name", "description"]].model_validate( {**response.json(), "pagination_options": pagination_options} ) diff --git a/nortech/metadata/values/__init__.py b/nortech/metadata/values/__init__.py index b17739e..0a9dce4 100644 --- a/nortech/metadata/values/__init__.py +++ b/nortech/metadata/values/__init__.py @@ -5,12 +5,6 @@ AssetOutput, ) from nortech.metadata.values.common import MetadataOutput -from nortech.metadata.values.device import ( - DeviceInput, - DeviceInputDict, - DeviceListOutput, - DeviceOutput, -) from nortech.metadata.values.division import ( DivisionInput, DivisionInputDict, @@ -23,8 +17,6 @@ PaginationOptions, ) from nortech.metadata.values.signal import ( - SignalDeviceInput, - SignalDeviceInputDict, SignalInput, SignalInputDict, SignalListOutput, @@ -49,10 +41,6 @@ "AssetInputDict", "AssetListOutput", "AssetOutput", - "DeviceInput", - "DeviceInputDict", - "DeviceListOutput", - "DeviceOutput", "DivisionInput", "DivisionInputDict", "DivisionListOutput", @@ -61,8 +49,6 @@ "NextRef", "PaginatedResponse", "PaginationOptions", - "SignalDeviceInput", - "SignalDeviceInputDict", "SignalInput", "SignalInputDict", "SignalListOutput", diff --git a/nortech/metadata/values/device.py b/nortech/metadata/values/device.py deleted file mode 100644 index 19ee831..0000000 --- a/nortech/metadata/values/device.py +++ /dev/null @@ -1,88 +0,0 @@ -"""Module containing all schemas related with Devices.""" - -from __future__ import annotations - -from nortech.metadata.values.division import DivisionInput, DivisionInputDict - -from .common import MetadataOutput, MetadataTimestamps - - -class DeviceInputDict(DivisionInputDict): - """ - Dictionary representation of Device input data. - - Attributes: - workspace (str): The name of the Workspace. - asset (str): The name of the Asset. - division (str): The name of the Division. - device (str): The name of the Device. - - """ - - device: str - - -class DeviceInput(DivisionInput): - """ - Pydantic model for Device input data. - - Attributes: - workspace (str): The name of the Workspace. - asset (str): The name of the Asset. - division (str): The name of the Division. - device (str): The name of the Device. - - """ - - device: str - - -def parse_device_input(device_input: DeviceInput | DeviceInputDict): # noqa: D103 - if isinstance(device_input, DeviceInput): - return device_input - else: - return DeviceInput.model_validate(device_input) - - -class DeviceListOutput(MetadataOutput): - """ - Output model for device list entries. - - Attributes: - id (int): Id of the Device. - name (str): Name of the Device. - type (str): The type of the Device. - onboarded (bool): Whether the Device is onboarded. - - """ - - type: str - onboarded: bool - - -class DeviceOutput(DeviceListOutput, MetadataTimestamps): - """ - Detailed output model for a single device. - - Attributes: - id (int): Id of the Device. - name (str): Name of the Device. - type (str): The type of the Device. - onboarded (bool): Whether the Device is onboarded. - created_at (datetime): Timestamp of when the Device was created. - updated_at (datetime): Timestamp of when the Device was last updated. - workspace: Metadata about the Workspace containing the Device. - - id (int): Id of the Workspace. - - name (str): Name of the Workspace. - asset: Metadata about the Asset containing the Device. - - id (int): Id of the Asset. - - name (str): Name of the Asset. - division: Metadata about the Division containing the Device. - - id (int): Id of the Division. - - name (str): Name of the Division. - - """ - - workspace: MetadataOutput - asset: MetadataOutput - division: MetadataOutput diff --git a/nortech/metadata/values/pagination.py b/nortech/metadata/values/pagination.py index 06c70b4..a56fce3 100644 --- a/nortech/metadata/values/pagination.py +++ b/nortech/metadata/values/pagination.py @@ -34,7 +34,7 @@ class NextRef(BaseModel): Resp = TypeVar("Resp") -class PaginatedResponse(BaseModel, Generic[Resp]): +class PaginatedResponse(BaseModel, Generic[Resp, SortBy]): """ Paginated response from list endpoints. @@ -48,9 +48,9 @@ class PaginatedResponse(BaseModel, Generic[Resp]): size: int data: list[Resp] next: NextRef | None = None - pagination_options: PaginationOptions | None = None + pagination_options: PaginationOptions[SortBy] | None = None - def next_pagination_options(self) -> PaginationOptions | None: + def next_pagination_options(self) -> PaginationOptions[SortBy] | None: if not self.next: return None if self.pagination_options: diff --git a/nortech/metadata/values/signal.py b/nortech/metadata/values/signal.py index 5be8766..e50f4dd 100644 --- a/nortech/metadata/values/signal.py +++ b/nortech/metadata/values/signal.py @@ -7,7 +7,6 @@ from pydantic import BaseModel, ConfigDict, Field -from nortech.metadata.values.device import DeviceInput, DeviceInputDict from nortech.metadata.values.unit import UnitInput, UnitInputDict from .common import MetadataOutput, MetadataTimestamps @@ -51,7 +50,7 @@ def path(self) -> str: # noqa: D102 def hash(self) -> str: # noqa: D102 return hashlib.sha256(self.model_dump_json().encode()).hexdigest() - def model_dump_with_rename(self) -> dict: # noqa: D102 + def model_dump_with_rename(self) -> dict[str, str]: # noqa: D102 return { "rename": self.hash(), **self.model_dump(by_alias=True), @@ -65,46 +64,6 @@ def parse_signal_input(signal_input: SignalInput | SignalInputDict) -> SignalInp return SignalInput.model_validate(signal_input) -class SignalDeviceInputDict(DeviceInputDict): - """ - Dictionary representation of SignalDevice input data. - - Attributes: - workspace (str): The name of the Workspace. - asset (str): The name of the Asset. - division (str): The name of the Division. - device (str): The name of the Device. - signal (str): The name of the Signal. - - """ - - signal: str - - -class SignalDeviceInput(DeviceInput): - """ - Pydantic model for SignalDevice input data. - - Attributes: - workspace (str): The name of the Workspace. - asset (str): The name of the Asset. - division (str): The name of the Division. - device (str): The name of the Device. - signal (str): The name of the Signal. - - """ - - signal: str - - -def parse_signal_device_input( # noqa: D103 - signal_device_input: SignalDeviceInput | SignalDeviceInputDict | SignalOutput, -) -> SignalDeviceInput: - if isinstance(signal_device_input, SignalDeviceInput): - return signal_device_input - return SignalDeviceInput.model_validate(signal_device_input) - - class SignalSpecs(BaseModel): model_config = ConfigDict(populate_by_name=True) @@ -134,7 +93,7 @@ class SignalListOutput(SignalSpecs): name: str -class SignalOutputNoDevice(SignalListOutput, MetadataTimestamps): +class SignalOutput(SignalListOutput, MetadataTimestamps): workspace: MetadataOutput asset: MetadataOutput division: MetadataOutput @@ -150,35 +109,5 @@ def to_signal_input(self) -> SignalInput: ) -class SignalOutput(SignalOutputNoDevice): - """ - Detailed output model for a single signal. - - Attributes: - id (int): Id of the Signal. - name (str): Name of the Signal. - created_at (datetime): Timestamp of when the Signal was created. - updated_at (datetime): Timestamp of when the Signal was last updated. - workspace: Metadata about the Workspace containing the Signal. - - id (int): Id of the Workspace. - - name (str): Name of the Workspace. - asset: Metadata about the Asset containing the Signal. - - id (int): Id of the Asset. - - name (str): Name of the Asset. - division: Metadata about the Division containing the Signal. - - id (int): Id of the Division. - - name (str): Name of the Division. - unit: Metadata about the Unit containing the Signal. - - id (int): Id of the Unit. - - name (str): Name of the Unit. - device: Metadata about the Device containing the Signal. - - id (int): Id of the Device. - - name (str): Name of the Device. - - """ - - device: MetadataOutput - - class CreateSignalInput(SignalInput, SignalSpecs): group_key: Optional[str] = Field(alias="groupKey", default=None) diff --git a/pyproject.toml b/pyproject.toml index 313f7bf..1bdb443 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "nortech" -version = "0.10.0" +version = "0.11.0" description = "Nortech Python SDK" readme = "README.md" requires-python = ">=3.9" @@ -70,6 +70,5 @@ ignore = [ "D203", # Incorrect black line before class "D212", # Multi line summary first line "E501", # Line too long - "PD901", # Using the generic variable name `df` for DataFrames "S101" # Use of `assert` detected ] diff --git a/tests/integration/datatools/conftest.py b/tests/integration/datatools/conftest.py index 2678bcb..04b5ac4 100644 --- a/tests/integration/datatools/conftest.py +++ b/tests/integration/datatools/conftest.py @@ -40,7 +40,6 @@ def data_signal_output_fixture() -> SignalOutput: asset=MetadataOutput(id=1, name="test_asset"), division=MetadataOutput(id=1, name="test_division"), unit=MetadataOutput(id=1, name="test_unit"), - device=MetadataOutput(id=1, name="test_device"), createdAt=datetime.now(), updatedAt=datetime.now(), ) @@ -59,7 +58,6 @@ def data_signal_output_id_1_fixture() -> SignalOutput: asset=MetadataOutput(id=1, name="test_asset"), division=MetadataOutput(id=1, name="test_division"), unit=MetadataOutput(id=1, name="test_unit"), - device=MetadataOutput(id=1, name="test_device"), createdAt=datetime.now(), updatedAt=datetime.now(), ) @@ -78,7 +76,6 @@ def data_signal_output_id_2_fixture() -> SignalOutput: asset=MetadataOutput(id=1, name="test_asset"), division=MetadataOutput(id=1, name="test_division"), unit=MetadataOutput(id=1, name="test_unit"), - device=MetadataOutput(id=1, name="test_device"), createdAt=datetime.now(), updatedAt=datetime.now(), ) diff --git a/tests/unit/metadata/conftest.py b/tests/unit/metadata/conftest.py index b6d7456..8c8a873 100644 --- a/tests/unit/metadata/conftest.py +++ b/tests/unit/metadata/conftest.py @@ -1,4 +1,5 @@ from datetime import datetime +from typing import Literal import pytest @@ -7,10 +8,6 @@ AssetInputDict, AssetListOutput, AssetOutput, - DeviceInput, - DeviceInputDict, - DeviceListOutput, - DeviceOutput, DivisionInput, DivisionInputDict, DivisionListOutput, @@ -56,8 +53,8 @@ def workspace_list_output_fixture() -> list[WorkspaceListOutput]: @pytest.fixture(scope="session", name="paginated_workspace_list_output") def paginated_workspace_list_output_fixture( workspace_list_output: list[WorkspaceListOutput], -) -> PaginatedResponse[WorkspaceListOutput]: - return PaginatedResponse[WorkspaceListOutput]( +) -> PaginatedResponse[WorkspaceListOutput, Literal["id", "name", "description"]]: + return PaginatedResponse[WorkspaceListOutput, Literal["id", "name", "description"]]( size=len(workspace_list_output), data=workspace_list_output, next=None, @@ -67,8 +64,8 @@ def paginated_workspace_list_output_fixture( @pytest.fixture(scope="session", name="paginated_workspace_list_output_first_page") def paginated_workspace_list_output_first_page_fixture( workspace_list_output: list[WorkspaceListOutput], -) -> PaginatedResponse[WorkspaceListOutput]: - return PaginatedResponse[WorkspaceListOutput]( +) -> PaginatedResponse[WorkspaceListOutput, Literal["id", "name", "description"]]: + return PaginatedResponse[WorkspaceListOutput, Literal["id", "name", "description"]]( size=2, data=workspace_list_output[:2], next=NextRef(token="test_token"), # noqa: S106 @@ -78,8 +75,8 @@ def paginated_workspace_list_output_first_page_fixture( @pytest.fixture(scope="session", name="paginated_workspace_list_output_second_page") def paginated_workspace_list_output_second_page_fixture( workspace_list_output: list[WorkspaceListOutput], -) -> PaginatedResponse[WorkspaceListOutput]: - return PaginatedResponse[WorkspaceListOutput]( +) -> PaginatedResponse[WorkspaceListOutput, Literal["id", "name", "description"]]: + return PaginatedResponse[WorkspaceListOutput, Literal["id", "name", "description"]]( size=2, data=workspace_list_output[2:], next=None, @@ -115,8 +112,8 @@ def asset_list_output_fixture() -> AssetListOutput: @pytest.fixture(scope="session", name="paginated_asset_list_output") def paginated_asset_list_output_fixture( asset_list_output: AssetListOutput, -) -> PaginatedResponse[AssetListOutput]: - return PaginatedResponse[AssetListOutput]( +) -> PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]]: + return PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]]( size=1, data=[asset_list_output], next=None, @@ -153,8 +150,8 @@ def division_list_output_fixture() -> DivisionListOutput: @pytest.fixture(scope="session", name="paginated_division_list_output") def paginated_division_list_output_fixture( division_list_output: DivisionListOutput, -) -> PaginatedResponse[DivisionListOutput]: - return PaginatedResponse[DivisionListOutput]( +) -> PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]]: + return PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]]( size=1, data=[division_list_output], next=None, @@ -197,8 +194,8 @@ def unit_list_output_fixture() -> UnitListOutput: @pytest.fixture(scope="session", name="paginated_unit_list_output") def paginated_unit_list_output_fixture( unit_list_output: UnitListOutput, -) -> PaginatedResponse[UnitListOutput]: - return PaginatedResponse[UnitListOutput]( +) -> PaginatedResponse[UnitListOutput, Literal["id", "name"]]: + return PaginatedResponse[UnitListOutput, Literal["id", "name"]]( size=1, data=[unit_list_output], next=None, @@ -218,57 +215,6 @@ def unit_output_fixture() -> UnitOutput: ) -@pytest.fixture(scope="session", name="device_input") -def device_input_fixture() -> DeviceInput: - return DeviceInput( - device="test_device", - division="test_division", - asset="test_asset", - workspace="test_workspace", - ) - - -@pytest.fixture(scope="session", name="device_input_dict") -def device_input_dict_fixture() -> DeviceInputDict: - return { - "device": "test_device", - "division": "test_division", - "asset": "test_asset", - "workspace": "test_workspace", - } - - -@pytest.fixture(scope="session", name="device_list_output") -def device_list_output_fixture() -> DeviceListOutput: - return DeviceListOutput(id=1, name="test_device", type="test_type", onboarded=True) - - -@pytest.fixture(scope="session", name="paginated_device_list_output") -def paginated_device_list_output_fixture( - device_list_output: DeviceListOutput, -) -> PaginatedResponse[DeviceListOutput]: - return PaginatedResponse[DeviceListOutput]( - size=1, - data=[device_list_output], - next=None, - ) - - -@pytest.fixture(scope="session", name="device_output") -def device_output_fixture() -> DeviceOutput: - return DeviceOutput( - id=1, - name="test_device", - type="test_type", - onboarded=True, - workspace=MetadataOutput(id=1, name="test_workspace"), - asset=MetadataOutput(id=1, name="test_asset"), - division=MetadataOutput(id=1, name="test_division"), - created_at=datetime.now(), # type: ignore - updated_at=datetime.now(), # type: ignore - ) - - @pytest.fixture(scope="session", name="signal_input") def signal_input_fixture() -> SignalInput: return SignalInput( @@ -306,8 +252,12 @@ def signal_list_output_fixture() -> SignalListOutput: @pytest.fixture(scope="session", name="paginated_signal_list_output") def paginated_signal_list_output_fixture( signal_list_output: SignalListOutput, -) -> PaginatedResponse[SignalListOutput]: - return PaginatedResponse[SignalListOutput]( +) -> PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] +]: + return PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ]( size=1, data=[signal_list_output], next=None, @@ -327,7 +277,6 @@ def signal_output_fixture() -> SignalOutput: asset=MetadataOutput(id=1, name="test_asset"), division=MetadataOutput(id=1, name="test_division"), unit=MetadataOutput(id=1, name="test_unit"), - device=MetadataOutput(id=1, name="test_device"), createdAt=datetime.now(), updatedAt=datetime.now(), ) diff --git a/tests/unit/metadata/test_asset.py b/tests/unit/metadata/test_asset.py index 05902c6..363fc3f 100644 --- a/tests/unit/metadata/test_asset.py +++ b/tests/unit/metadata/test_asset.py @@ -1,3 +1,5 @@ +from typing import Literal + import pytest from requests_mock import Mocker @@ -9,7 +11,7 @@ def test_list_workspace_assets_from_id( nortech: Nortech, asset_list_output: AssetListOutput, - paginated_asset_list_output: PaginatedResponse[AssetListOutput], + paginated_asset_list_output: PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -24,7 +26,7 @@ def test_list_workspace_assets_from_id( def test_list_workspace_assets_from_name( nortech: Nortech, asset_list_output: AssetListOutput, - paginated_asset_list_output: PaginatedResponse[AssetListOutput], + paginated_asset_list_output: PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -39,7 +41,7 @@ def test_list_workspace_assets_from_name( def test_list_workspace_assets_from_input( nortech: Nortech, asset_list_output: AssetListOutput, - paginated_asset_list_output: PaginatedResponse[AssetListOutput], + paginated_asset_list_output: PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -54,7 +56,7 @@ def test_list_workspace_assets_from_input( def test_list_workspace_assets_from_input_dict( nortech: Nortech, asset_list_output: AssetListOutput, - paginated_asset_list_output: PaginatedResponse[AssetListOutput], + paginated_asset_list_output: PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -70,7 +72,7 @@ def test_list_workspace_assets_from_output( nortech: Nortech, workspace_output: WorkspaceOutput, asset_list_output: AssetListOutput, - paginated_asset_list_output: PaginatedResponse[AssetListOutput], + paginated_asset_list_output: PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -86,7 +88,7 @@ def test_list_workspace_assets_from_list_output( nortech: Nortech, workspace_list_output: list[WorkspaceListOutput], asset_list_output: AssetListOutput, - paginated_asset_list_output: PaginatedResponse[AssetListOutput], + paginated_asset_list_output: PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -101,7 +103,7 @@ def test_list_workspace_assets_from_list_output( def test_list_workspace_assets_from_int( nortech: Nortech, asset_list_output: AssetListOutput, - paginated_asset_list_output: PaginatedResponse[AssetListOutput], + paginated_asset_list_output: PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -116,7 +118,7 @@ def test_list_workspace_assets_from_int( def test_list_workspace_assets_from_str( nortech: Nortech, asset_list_output: AssetListOutput, - paginated_asset_list_output: PaginatedResponse[AssetListOutput], + paginated_asset_list_output: PaginatedResponse[AssetListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -142,7 +144,7 @@ def test_list_workspace_assets_error( def test_get_workspace_asset_with_input( nortech: Nortech, asset_output: AssetOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset", @@ -156,7 +158,7 @@ def test_get_workspace_asset_with_input( def test_get_workspace_asset_with_input_dict( nortech: Nortech, asset_output: AssetOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset", @@ -170,7 +172,7 @@ def test_get_workspace_asset_with_input_dict( def test_get_workspace_asset_with_output( nortech: Nortech, asset_output: AssetOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/assets/1", @@ -185,7 +187,7 @@ def test_get_workspace_asset_with_list_output( nortech: Nortech, asset_output: AssetOutput, asset_list_output: AssetListOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/assets/1", text=asset_output.model_dump_json(by_alias=True)) @@ -210,7 +212,7 @@ def test_get_workspace_asset_error( def test_get_asset( nortech: Nortech, asset_output: AssetOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/assets/1", @@ -223,7 +225,7 @@ def test_get_asset( def test_get_asset_error( nortech: Nortech, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/assets/1", status_code=404) diff --git a/tests/unit/metadata/test_device.py b/tests/unit/metadata/test_device.py deleted file mode 100644 index 505c123..0000000 --- a/tests/unit/metadata/test_device.py +++ /dev/null @@ -1,280 +0,0 @@ -import pytest -from requests_mock import Mocker - -from nortech import Nortech -from nortech.metadata import DeviceInput, DeviceListOutput, DeviceOutput, DivisionInput, PaginatedResponse -from nortech.metadata.values.division import DivisionListOutput, DivisionOutput - - -def test_list_workspace_asset_division_devices_from_input( - nortech: Nortech, - device_list_output: DeviceListOutput, - paginated_device_list_output: PaginatedResponse[DeviceOutput], - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/devices", - text=paginated_device_list_output.model_dump_json(by_alias=True), - ) - - divisions = nortech.metadata.device.list( - DivisionInput(workspace="test_workspace", asset="test_asset", division="test_division"), - ) - assert divisions.data == [device_list_output] - - -def test_list_workspace_asset_division_devices_from_input_dict( - nortech: Nortech, - device_list_output: DeviceListOutput, - paginated_device_list_output: PaginatedResponse[DeviceOutput], - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/devices", - text=paginated_device_list_output.model_dump_json(by_alias=True), - ) - - divisions = nortech.metadata.device.list( - {"workspace": "test_workspace", "asset": "test_asset", "division": "test_division"}, - ) - assert divisions.data == [device_list_output] - - -def test_list_workspace_asset_division_devices_from_output( - nortech: Nortech, - device_list_output: DeviceListOutput, - division_output: DivisionOutput, - paginated_device_list_output: PaginatedResponse[DeviceOutput], - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/divisions/1/devices", - text=paginated_device_list_output.model_dump_json(by_alias=True), - ) - - divisions = nortech.metadata.device.list(division_output) - assert divisions.data == [device_list_output] - - -def test_list_workspace_asset_division_devices_from_list_output( - nortech: Nortech, - device_list_output: DeviceListOutput, - division_list_output: DivisionListOutput, - paginated_device_list_output: PaginatedResponse[DeviceOutput], - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/divisions/1/devices", - text=paginated_device_list_output.model_dump_json(by_alias=True), - ) - - divisions = nortech.metadata.device.list(division_list_output) - assert divisions.data == [device_list_output] - - -def test_list_workspace_asset_division_devices_error( - nortech: Nortech, - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/devices", - status_code=404, - ) - - with pytest.raises(AssertionError) as err: - nortech.metadata.device.list( - DivisionInput(workspace="test_workspace", asset="test_asset", division="test_division"), - ) - assert "Fetch failed." in str(err.value) - - -def test_get_workspace_asset_division_device_with_input( - nortech: Nortech, - device_output: DeviceOutput, - requests_mock, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/devices/test_device", - text=device_output.model_dump_json(by_alias=True), - ) - - division = nortech.metadata.device.get( - DeviceInput( - workspace="test_workspace", - asset="test_asset", - division="test_division", - device="test_device", - ), - ) - assert division == device_output - - -def test_get_workspace_asset_division_device_with_input_dict( - nortech: Nortech, - device_output: DeviceOutput, - requests_mock, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/devices/test_device", - text=device_output.model_dump_json(by_alias=True), - ) - - division = nortech.metadata.device.get( - { - "workspace": "test_workspace", - "asset": "test_asset", - "division": "test_division", - "device": "test_device", - }, - ) - assert division == device_output - - -def test_get_workspace_asset_division_device_with_output( - nortech: Nortech, - device_output: DeviceOutput, - requests_mock, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/devices/1", - text=device_output.model_dump_json(by_alias=True), - ) - - division = nortech.metadata.device.get(device_output) - assert division == device_output - - -def test_get_workspace_asset_division_device_with_list_output( - nortech: Nortech, - device_output: DeviceOutput, - device_list_output: DeviceListOutput, - requests_mock, -): - requests_mock.get(f"{nortech.settings.URL}/api/v1/devices/1", text=device_output.model_dump_json(by_alias=True)) - - division = nortech.metadata.device.get(device_list_output) - assert division == device_output - - -def test_get_workspace_asset_division_device_error( - nortech: Nortech, - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/devices/test_device", - status_code=404, - ) - - with pytest.raises(AssertionError) as err: - nortech.metadata.device.get( - DeviceInput( - workspace="test_workspace", - asset="test_asset", - division="test_division", - device="test_device", - ), - ) - assert "Fetch failed." in str(err.value) - - -def test_list_workspace_devices( - nortech: Nortech, - device_list_output: DeviceListOutput, - paginated_device_list_output: PaginatedResponse[DeviceOutput], - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/1/devices", - text=paginated_device_list_output.model_dump_json(by_alias=True), - ) - - divisions = nortech.metadata.device.list_by_workspace_id(1) - assert divisions.data == [device_list_output] - - -def test_list_workspace_devices_error( - nortech: Nortech, - requests_mock: Mocker, -): - requests_mock.get(f"{nortech.settings.URL}/api/v1/workspaces/1/devices", status_code=404) - - with pytest.raises(AssertionError) as err: - nortech.metadata.device.list_by_workspace_id(1) - assert "Fetch failed." in str(err.value) - - -def test_list_asset_devices( - nortech: Nortech, - device_list_output: DeviceListOutput, - paginated_device_list_output: PaginatedResponse[DeviceOutput], - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/assets/1/devices", - text=paginated_device_list_output.model_dump_json(by_alias=True), - ) - - divisions = nortech.metadata.device.list_by_asset_id(1) - assert divisions.data == [device_list_output] - - -def test_list_asset_devices_error( - nortech: Nortech, - requests_mock: Mocker, -): - requests_mock.get(f"{nortech.settings.URL}/api/v1/assets/1/devices", status_code=404) - - with pytest.raises(AssertionError) as err: - nortech.metadata.device.list_by_asset_id(1) - assert "Fetch failed." in str(err.value) - - -def test_list_division_devices( - nortech: Nortech, - device_list_output: DeviceListOutput, - paginated_device_list_output: PaginatedResponse[DeviceOutput], - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/divisions/1/devices", - text=paginated_device_list_output.model_dump_json(by_alias=True), - ) - - divisions = nortech.metadata.device.list(division=1) - assert divisions.data == [device_list_output] - - -def test_list_division_devices_error( - nortech: Nortech, - requests_mock: Mocker, -): - requests_mock.get(f"{nortech.settings.URL}/api/v1/divisions/1/devices", status_code=404) - - with pytest.raises(AssertionError) as err: - nortech.metadata.device.list(division=1) - assert "Fetch failed." in str(err.value) - - -def test_get_device( - nortech: Nortech, - device_output: DeviceOutput, - requests_mock, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/devices/1", - text=device_output.model_dump_json(by_alias=True), - ) - - division = nortech.metadata.device.get(device=1) - assert division == device_output - - -def test_get_device_error( - nortech: Nortech, - requests_mock, -): - requests_mock.get(f"{nortech.settings.URL}/api/v1/devices/1", status_code=404) - - with pytest.raises(AssertionError) as err: - nortech.metadata.device.get(device=1) - assert "Fetch failed." in str(err.value) diff --git a/tests/unit/metadata/test_division.py b/tests/unit/metadata/test_division.py index 12063c9..8fe5c17 100644 --- a/tests/unit/metadata/test_division.py +++ b/tests/unit/metadata/test_division.py @@ -1,3 +1,5 @@ +from typing import Literal + import pytest from requests_mock import Mocker @@ -14,7 +16,7 @@ def test_list_workspace_asset_divisions_from_input( nortech: Nortech, division_list_output: DivisionListOutput, - paginated_division_list_output: PaginatedResponse[DivisionOutput], + paginated_division_list_output: PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -31,7 +33,7 @@ def test_list_workspace_asset_divisions_from_input( def test_list_workspace_asset_divisions_from_input_dict( nortech: Nortech, division_list_output: DivisionListOutput, - paginated_division_list_output: PaginatedResponse[DivisionOutput], + paginated_division_list_output: PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -63,7 +65,7 @@ def test_list_workspace_asset_division_error( def test_get_workspace_asset_division_with_input( nortech: Nortech, division_output: DivisionOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division", @@ -79,7 +81,7 @@ def test_get_workspace_asset_division_with_input( def test_get_workspace_asset_division_with_input_dict( nortech: Nortech, division_output: DivisionOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division", @@ -95,7 +97,7 @@ def test_get_workspace_asset_division_with_input_dict( def test_get_workspace_asset_division_with_output( nortech: Nortech, division_output: DivisionOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/divisions/1", @@ -110,7 +112,7 @@ def test_get_workspace_asset_division_with_list_output( nortech: Nortech, division_output: DivisionOutput, division_list_output: DivisionListOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/divisions/1", @@ -140,7 +142,7 @@ def test_get_workspace_asset_division_error( def test_list_workspace_divisions( nortech: Nortech, division_list_output: DivisionListOutput, - paginated_division_list_output: PaginatedResponse[DivisionOutput], + paginated_division_list_output: PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -166,7 +168,7 @@ def test_list_workspace_divisions_error( def test_list_asset_divisions( nortech: Nortech, division_list_output: DivisionListOutput, - paginated_division_list_output: PaginatedResponse[DivisionOutput], + paginated_division_list_output: PaginatedResponse[DivisionListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -192,7 +194,7 @@ def test_list_asset_divisions_error( def test_get_division( nortech: Nortech, division_output: DivisionOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/divisions/1", @@ -205,7 +207,7 @@ def test_get_division( def test_get_division_error( nortech: Nortech, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/divisions/1", status_code=404) diff --git a/tests/unit/metadata/test_signal.py b/tests/unit/metadata/test_signal.py index 035615c..edca3ce 100644 --- a/tests/unit/metadata/test_signal.py +++ b/tests/unit/metadata/test_signal.py @@ -1,26 +1,30 @@ +from typing import Literal + import pytest from requests_mock import Mocker from nortech import Nortech from nortech.metadata import ( - DeviceInput, PaginatedResponse, - SignalDeviceInput, SignalInput, SignalInputDict, SignalListOutput, SignalOutput, UnitInput, ) -from nortech.metadata.services.signal import _get_signals, parse_signal_input_or_output_or_id_union_to_signal_input -from nortech.metadata.values.device import DeviceOutput +from nortech.metadata.services.signal import ( + _get_signals, # type: ignore + parse_signal_input_or_output_or_id_union_to_signal_input, +) from nortech.metadata.values.unit import UnitOutput def test_list_workspace_asset_division_unit_signals_from_input( nortech: Nortech, signal_list_output: SignalListOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], + paginated_signal_list_output: PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ], requests_mock: Mocker, ): requests_mock.get( @@ -42,7 +46,9 @@ def test_list_workspace_asset_division_unit_signals_from_input( def test_list_workspace_asset_division_unit_signals_from_input_dict( nortech: Nortech, signal_list_output: SignalListOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], + paginated_signal_list_output: PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ], requests_mock: Mocker, ): requests_mock.get( @@ -65,7 +71,9 @@ def test_list_workspace_asset_division_unit_signals_from_output( nortech: Nortech, signal_list_output: SignalListOutput, unit_output: UnitOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], + paginated_signal_list_output: PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ], requests_mock: Mocker, ): requests_mock.get( @@ -81,7 +89,9 @@ def test_list_workspace_asset_division_unit_signals_from_output_list( nortech: Nortech, signal_list_output: SignalListOutput, unit_output: UnitOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], + paginated_signal_list_output: PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ], requests_mock: Mocker, ): requests_mock.get( @@ -96,7 +106,7 @@ def test_list_workspace_asset_division_unit_signals_from_output_list( def test_list_workspace_asset_division_unit_signals_error( nortech: Nortech, unit_output: UnitOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/units/1/signals", status_code=404) @@ -105,98 +115,10 @@ def test_list_workspace_asset_division_unit_signals_error( assert "Fetch failed." in str(err.value) -def test_list_workspace_asset_division_device_signals_from_input( - nortech: Nortech, - signal_list_output: SignalListOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/devices/test_device/signals", - text=paginated_signal_list_output.model_dump_json(by_alias=True), - ) - - signals = nortech.metadata.signal.list( - DeviceInput( - workspace="test_workspace", - asset="test_asset", - division="test_division", - device="test_device", - ), - ) - assert signals.data == [signal_list_output] - - -def test_list_workspace_asset_division_device_signals_from_input_dict( - nortech: Nortech, - signal_list_output: SignalListOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/devices/test_device/signals", - text=paginated_signal_list_output.model_dump_json(by_alias=True), - ) - - signals = nortech.metadata.signal.list( - { - "workspace": "test_workspace", - "asset": "test_asset", - "division": "test_division", - "device": "test_device", - }, - ) - assert signals.data == [signal_list_output] - - -def test_list_workspace_asset_division_device_signals_from_output( - nortech: Nortech, - signal_list_output: SignalListOutput, - device_output: DeviceOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/devices/1/signals", - text=paginated_signal_list_output.model_dump_json(by_alias=True), - ) - - signals = nortech.metadata.signal.list(device_output) - assert signals.data == [signal_list_output] - - -def test_list_workspace_asset_division_device_signals_from_output_list( - nortech: Nortech, - signal_list_output: SignalListOutput, - device_output: DeviceOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], - requests_mock: Mocker, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/devices/1/signals", - text=paginated_signal_list_output.model_dump_json(by_alias=True), - ) - - signals = nortech.metadata.signal.list(device_output) - assert signals.data == [signal_list_output] - - -def test_list_workspace_asset_division_device_signals_error( - nortech: Nortech, - device_output: DeviceOutput, - requests_mock, -): - requests_mock.get(f"{nortech.settings.URL}/api/v1/devices/1/signals", status_code=404) - - with pytest.raises(AssertionError) as err: - nortech.metadata.signal.list(device_output) - assert "Fetch failed." in str(err.value) - - def test_get_workspace_asset_division_unit_signal_with_input( nortech: Nortech, signal_output: SignalOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/units/test_unit/signals/test_signal", @@ -218,7 +140,7 @@ def test_get_workspace_asset_division_unit_signal_with_input( def test_get_workspace_asset_division_unit_signal_with_input_dict( nortech: Nortech, signal_output: SignalOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/units/test_unit/signals/test_signal", @@ -240,7 +162,7 @@ def test_get_workspace_asset_division_unit_signal_with_input_dict( def test_get_workspace_asset_division_unit_signal_with_output( nortech: Nortech, signal_output: SignalOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/signals/1", text=signal_output.model_dump_json(by_alias=True)) @@ -251,7 +173,7 @@ def test_get_workspace_asset_division_unit_signal_with_output( def test_get_workspace_asset_division_unit_signal_with_output_list( nortech: Nortech, signal_output: SignalOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/signals/1", text=signal_output.model_dump_json(by_alias=True)) @@ -281,98 +203,12 @@ def test_get_workspace_asset_division_unit_signal_error( assert "Fetch failed." in str(err.value) -def test_get_workspace_asset_division_device_signal_with_input( - nortech: Nortech, - signal_output: SignalOutput, - requests_mock, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/devices/test_device/signals/test_signal", - text=signal_output.model_dump_json(by_alias=True), - ) - - signal = nortech.metadata.signal.get( - SignalDeviceInput( - workspace="test_workspace", - asset="test_asset", - division="test_division", - device="test_device", - signal="test_signal", - ), - ) - assert signal == signal_output - - -def test_get_workspace_asset_division_device_signal_with_input_dict( - nortech: Nortech, - signal_output: SignalOutput, - requests_mock, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/devices/test_device/signals/test_signal", - text=signal_output.model_dump_json(by_alias=True), - ) - - signal = nortech.metadata.signal.get( - { - "workspace": "test_workspace", - "asset": "test_asset", - "division": "test_division", - "device": "test_device", - "signal": "test_signal", - }, - ) - assert signal == signal_output - - -def test_get_workspace_asset_division_device_signal_with_output( - nortech: Nortech, - signal_output: SignalOutput, - requests_mock, -): - requests_mock.get(f"{nortech.settings.URL}/api/v1/signals/1", text=signal_output.model_dump_json(by_alias=True)) - - signal = nortech.metadata.signal.get(signal_output) - assert signal == signal_output - - -def test_get_workspace_asset_division_device_signal_with_output_list( - nortech: Nortech, - signal_output: SignalOutput, - requests_mock, -): - requests_mock.get(f"{nortech.settings.URL}/api/v1/signals/1", text=signal_output.model_dump_json(by_alias=True)) - - signal = nortech.metadata.signal.get(signal_output) - assert signal == signal_output - - -def test_get_workspace_asset_division_device_signal_error( - nortech: Nortech, - requests_mock, -): - requests_mock.get( - f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/devices/test_device/signals/test_signal", - status_code=404, - ) - - with pytest.raises(AssertionError) as err: - nortech.metadata.signal.get( - SignalDeviceInput( - workspace="test_workspace", - asset="test_asset", - division="test_division", - device="test_device", - signal="test_signal", - ), - ) - assert "Fetch failed." in str(err.value) - - def test_list_workspace_signals( nortech: Nortech, signal_list_output: SignalListOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], + paginated_signal_list_output: PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ], requests_mock: Mocker, ): requests_mock.get( @@ -386,7 +222,7 @@ def test_list_workspace_signals( def test_list_workspace_signals_error( nortech: Nortech, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/workspaces/1/signals", status_code=404) @@ -398,7 +234,9 @@ def test_list_workspace_signals_error( def test_list_asset_signals( nortech: Nortech, signal_list_output: SignalListOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], + paginated_signal_list_output: PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ], requests_mock: Mocker, ): requests_mock.get( @@ -412,7 +250,7 @@ def test_list_asset_signals( def test_list_asset_signals_error( nortech: Nortech, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/assets/1/signals", status_code=404) @@ -424,7 +262,9 @@ def test_list_asset_signals_error( def test_list_division_signals( nortech: Nortech, signal_list_output: SignalListOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], + paginated_signal_list_output: PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ], requests_mock: Mocker, ): requests_mock.get( @@ -438,7 +278,7 @@ def test_list_division_signals( def test_list_division_signals_error( nortech: Nortech, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/divisions/1/signals", status_code=404) @@ -450,7 +290,9 @@ def test_list_division_signals_error( def test_list_signals( nortech: Nortech, signal_list_output: SignalListOutput, - paginated_signal_list_output: PaginatedResponse[SignalOutput], + paginated_signal_list_output: PaginatedResponse[ + SignalListOutput, Literal["id", "name", "physical_unit", "data_type", "description", "long_description"] + ], requests_mock: Mocker, ): requests_mock.get( @@ -464,7 +306,7 @@ def test_list_signals( def test_list_signals_error( nortech: Nortech, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/units/1/signals", status_code=404) @@ -476,7 +318,7 @@ def test_list_signals_error( def test_get_signal( nortech: Nortech, signal_output: SignalOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/signals/1", @@ -489,7 +331,7 @@ def test_get_signal( def test_get_signal_error( nortech: Nortech, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/signals/1", status_code=404) diff --git a/tests/unit/metadata/test_unit.py b/tests/unit/metadata/test_unit.py index 471a8e9..23481f3 100644 --- a/tests/unit/metadata/test_unit.py +++ b/tests/unit/metadata/test_unit.py @@ -1,3 +1,5 @@ +from typing import Literal + import pytest from requests_mock import Mocker @@ -15,7 +17,7 @@ def test_list_workspace_asset_division_units_from_input( nortech: Nortech, unit_list_output: UnitListOutput, - paginated_unit_list_output: PaginatedResponse[UnitOutput], + paginated_unit_list_output: PaginatedResponse[UnitListOutput, Literal["id", "name"]], requests_mock: Mocker, ): requests_mock.get( @@ -32,7 +34,7 @@ def test_list_workspace_asset_division_units_from_input( def test_list_workspace_asset_division_units_from_input_dict( nortech: Nortech, unit_list_output: UnitListOutput, - paginated_unit_list_output: PaginatedResponse[UnitOutput], + paginated_unit_list_output: PaginatedResponse[UnitListOutput, Literal["id", "name"]], requests_mock: Mocker, ): requests_mock.get( @@ -50,7 +52,7 @@ def test_list_workspace_asset_division_units_from_output( nortech: Nortech, unit_list_output: UnitListOutput, division_output: DivisionOutput, - paginated_unit_list_output: PaginatedResponse[UnitOutput], + paginated_unit_list_output: PaginatedResponse[UnitListOutput, Literal["id", "name"]], requests_mock: Mocker, ): requests_mock.get( @@ -66,7 +68,7 @@ def test_list_workspace_asset_division_units_from_list_output( nortech: Nortech, unit_list_output: UnitListOutput, division_list_output: DivisionListOutput, - paginated_unit_list_output: PaginatedResponse[UnitOutput], + paginated_unit_list_output: PaginatedResponse[UnitListOutput, Literal["id", "name"]], requests_mock: Mocker, ): requests_mock.get( @@ -92,7 +94,7 @@ def test_list_workspace_asset_division_units_error( def test_get_workspace_asset_division_unit_with_input( nortech: Nortech, unit_output: UnitOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/units/test_unit", @@ -113,7 +115,7 @@ def test_get_workspace_asset_division_unit_with_input( def test_get_workspace_asset_division_unit_with_input_dict( nortech: Nortech, unit_output: UnitOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/workspaces/test_workspace/assets/test_asset/divisions/test_division/units/test_unit", @@ -134,7 +136,7 @@ def test_get_workspace_asset_division_unit_with_input_dict( def test_get_workspace_asset_division_unit_with_output( nortech: Nortech, unit_output: UnitOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/units/1", @@ -149,7 +151,7 @@ def test_get_workspace_asset_division_unit_with_list_output( nortech: Nortech, unit_output: UnitOutput, unit_list_output: UnitListOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/units/1", text=unit_output.model_dump_json(by_alias=True)) @@ -181,7 +183,7 @@ def test_get_workspace_asset_division_unit_error( def test_list_workspace_units( nortech: Nortech, unit_list_output: UnitListOutput, - paginated_unit_list_output: PaginatedResponse[UnitOutput], + paginated_unit_list_output: PaginatedResponse[UnitListOutput, Literal["id", "name"]], requests_mock: Mocker, ): requests_mock.get( @@ -207,7 +209,7 @@ def test_list_workspace_units_error( def test_list_asset_units( nortech: Nortech, unit_list_output: UnitListOutput, - paginated_unit_list_output: PaginatedResponse[UnitOutput], + paginated_unit_list_output: PaginatedResponse[UnitListOutput, Literal["id", "name"]], requests_mock: Mocker, ): requests_mock.get( @@ -233,7 +235,7 @@ def test_list_asset_units_error( def test_list_division_units( nortech: Nortech, unit_list_output: UnitListOutput, - paginated_unit_list_output: PaginatedResponse[UnitOutput], + paginated_unit_list_output: PaginatedResponse[UnitListOutput, Literal["id", "name"]], requests_mock: Mocker, ): requests_mock.get( @@ -259,7 +261,7 @@ def test_list_division_units_error( def test_get_unit( nortech: Nortech, unit_output: UnitOutput, - requests_mock, + requests_mock: Mocker, ): requests_mock.get( f"{nortech.settings.URL}/api/v1/units/1", @@ -272,7 +274,7 @@ def test_get_unit( def test_get_unit_error( nortech: Nortech, - requests_mock, + requests_mock: Mocker, ): requests_mock.get(f"{nortech.settings.URL}/api/v1/units/1", status_code=404) diff --git a/tests/unit/metadata/test_workspace.py b/tests/unit/metadata/test_workspace.py index a086244..b7e4a36 100644 --- a/tests/unit/metadata/test_workspace.py +++ b/tests/unit/metadata/test_workspace.py @@ -1,3 +1,5 @@ +from typing import Literal + import pytest from requests_mock import Mocker @@ -8,7 +10,7 @@ def test_list_workspaces( nortech: Nortech, workspace_list_output: list[WorkspaceListOutput], - paginated_workspace_list_output: PaginatedResponse[WorkspaceListOutput], + paginated_workspace_list_output: PaginatedResponse[WorkspaceListOutput, Literal["id", "name", "description"]], requests_mock: Mocker, ): requests_mock.get( @@ -23,8 +25,12 @@ def test_list_workspaces( def test_list_workspaces_ignore_pagination( nortech: Nortech, workspace_list_output: list[WorkspaceListOutput], - paginated_workspace_list_output_first_page: PaginatedResponse[WorkspaceListOutput], - paginated_workspace_list_output_second_page: PaginatedResponse[WorkspaceListOutput], + paginated_workspace_list_output_first_page: PaginatedResponse[ + WorkspaceListOutput, Literal["id", "name", "description"] + ], + paginated_workspace_list_output_second_page: PaginatedResponse[ + WorkspaceListOutput, Literal["id", "name", "description"] + ], requests_mock: Mocker, ): requests_mock.register_uri( @@ -51,7 +57,9 @@ def test_list_workspaces_ignore_pagination( def test_list_workspaces_with_pagination( nortech: Nortech, workspace_list_output: list[WorkspaceListOutput], - paginated_workspace_list_output_first_page: PaginatedResponse[WorkspaceListOutput], + paginated_workspace_list_output_first_page: PaginatedResponse[ + WorkspaceListOutput, Literal["id", "name", "description"] + ], requests_mock: Mocker, ): nortech.api.ignore_pagination = False diff --git a/uv.lock b/uv.lock index 1fdac1c..823141e 100644 --- a/uv.lock +++ b/uv.lock @@ -912,7 +912,7 @@ wheels = [ [[package]] name = "nortech" -version = "0.10.0" +version = "0.11.0" source = { virtual = "." } dependencies = [ { name = "bytewax" },