Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 91 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions protos/ni/protobuf/types/scalar.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
syntax = "proto3";

package ni.protobuf.types;

option csharp_namespace = "NationalInstruments.Protobuf.Types";
option go_package = "types";
option java_multiple_files = true;
option java_outer_classname = "ScalarProto";
option java_package = "com.ni.protobuf.types";
option objc_class_prefix = "NIPT";
option php_namespace = "NI\\PROTOBUF\\TYPES";
option ruby_package = "NI::Protobuf::Types";

message ScalarData {
string units = 1;

oneof value {
double double_value = 2;
int32 int32_value = 3;
bool bool_value = 4;
string string_value = 5;
}
}
6 changes: 4 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ protobuf = {version=">=4.21"}
ni-measurement-plugin-sdk = {version=">=2.3"}
typing-extensions = ">=4.13.2"
streamlit = ">=1.24"
# Temporary dependency until ni-apis-python is available.
nitypes = ">=0.1.0dev1"

[tool.poetry.group.dev.dependencies]
types-grpcio = ">=1.0"
Expand Down Expand Up @@ -52,10 +54,10 @@ requires = ["poetry-core>=1.8.0"]
build-backend = "poetry.core.masonry.api"

[tool.ni-python-styleguide]
extend_exclude = ".tox,docs,src/ni/pythonpanel/v1"
extend_exclude = ".tox,docs,src/ni/pythonpanel/v1,src/ni/protobuf/types/"

[tool.black]
extend-exclude = '\.tox/|docs/|src/ni/pythonpanel/v1/'
extend-exclude = '\.tox/|docs/|src/ni/pythonpanel/v1/|src/ni/protobuf/types/'
line-length = 100

[tool.mypy]
Expand Down
26 changes: 26 additions & 0 deletions src/ni/protobuf/types/scalar_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions src/ni/protobuf/types/scalar_pb2.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""

import builtins
import google.protobuf.descriptor
import google.protobuf.message
import typing

DESCRIPTOR: google.protobuf.descriptor.FileDescriptor

@typing.final
class ScalarData(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor

UNITS_FIELD_NUMBER: builtins.int
DOUBLE_VALUE_FIELD_NUMBER: builtins.int
INT32_VALUE_FIELD_NUMBER: builtins.int
BOOL_VALUE_FIELD_NUMBER: builtins.int
STRING_VALUE_FIELD_NUMBER: builtins.int
units: builtins.str
double_value: builtins.float
int32_value: builtins.int
bool_value: builtins.bool
string_value: builtins.str
def __init__(
self,
*,
units: builtins.str = ...,
double_value: builtins.float = ...,
int32_value: builtins.int = ...,
bool_value: builtins.bool = ...,
string_value: builtins.str = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["bool_value", b"bool_value", "double_value", b"double_value", "int32_value", b"int32_value", "string_value", b"string_value", "value", b"value"]) -> builtins.bool: ...
def ClearField(self, field_name: typing.Literal["bool_value", b"bool_value", "double_value", b"double_value", "int32_value", b"int32_value", "string_value", b"string_value", "units", b"units", "value", b"value"]) -> None: ...
def WhichOneof(self, oneof_group: typing.Literal["value", b"value"]) -> typing.Literal["double_value", "int32_value", "bool_value", "string_value"] | None: ...

global___ScalarData = ScalarData
4 changes: 4 additions & 0 deletions src/ni/protobuf/types/scalar_pb2_grpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc

17 changes: 17 additions & 0 deletions src/ni/protobuf/types/scalar_pb2_grpc.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""
@generated by mypy-protobuf. Do not edit manually!
isort:skip_file
"""

import abc
import collections.abc
import grpc
import grpc.aio
import typing

_T = typing.TypeVar("_T")

class _MaybeAsyncIterator(collections.abc.AsyncIterator[_T], collections.abc.Iterator[_T], metaclass=abc.ABCMeta): ...

class _ServicerContext(grpc.ServicerContext, grpc.aio.ServicerContext): # type: ignore[misc, type-arg]
...
56 changes: 56 additions & 0 deletions src/nipanel/converters/protobuf_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""Classes to convert between measurement specific protobuf types and containers."""

from typing import Any, Type

from ni.protobuf.types import scalar_pb2
from nitypes.scalar import Scalar

from nipanel.converters import Converter


class ScalarConverter(Converter[Scalar[Any], scalar_pb2.ScalarData]):
"""A converter for Scalar objects."""

@property
def python_typename(self) -> str:
"""The Python type that this converter handles."""
return Scalar.__name__

@property
def protobuf_message(self) -> Type[scalar_pb2.ScalarData]:
"""The type-specific protobuf message for the Python type."""
return scalar_pb2.ScalarData

def to_protobuf_message(self, python_value: Scalar[Any]) -> scalar_pb2.ScalarData:
"""Convert the Python Scalar to a protobuf scalar_pb2.ScalarData."""
message = self.protobuf_message()
message.units = python_value.units
if isinstance(python_value.value, bool):
message.bool_value = python_value.value
elif isinstance(python_value.value, int):
message.int32_value = python_value.value
elif isinstance(python_value.value, float):
message.double_value = python_value.value
elif isinstance(python_value.value, str):
message.string_value = python_value.value
else:
raise TypeError(f"Unexpected type for python_value.value: {type(python_value.value)}")

return message

def to_python_value(self, protobuf_value: scalar_pb2.ScalarData) -> Scalar[Any]:
"""Convert the protobuf message to a Python Scalar."""
if protobuf_value.units is None:
raise ValueError("protobuf.units cannot be None.")

pb_type = protobuf_value.WhichOneof("value")
if pb_type == "bool_value":
return Scalar(protobuf_value.bool_value, protobuf_value.units)
elif pb_type == "int32_value":
return Scalar(protobuf_value.int32_value, protobuf_value.units)
elif pb_type == "double_value":
return Scalar(protobuf_value.double_value, protobuf_value.units)
elif pb_type == "string_value":
return Scalar(protobuf_value.string_value, protobuf_value.units)
else:
raise ValueError(f"Unexpected value for protobuf_value.WhichOneOf: {pb_type}")
Loading