Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions build/helper/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from build.helper.metadata_add_all import add_all_metadata # noqa: F401

from build.helper.metadata_filters import are_complex_parameters_used # noqa: F401
from build.helper.metadata_filters import are_grpc_complex_types_used # noqa: F401
from build.helper.metadata_filters import filter_codegen_attributes # noqa: F401
from build.helper.metadata_filters import filter_codegen_attributes_public_only # noqa: F401
from build.helper.metadata_filters import filter_codegen_enums # noqa: F401
Expand Down
4 changes: 2 additions & 2 deletions build/helper/codegen_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,9 @@ def get_library_interpreter_method_return_snippet(parameters, config, use_numpy_
return ('return ' + ', '.join(snippets)).strip()


def get_grpc_interpreter_method_return_snippet(parameters, config):
def get_grpc_interpreter_method_return_snippet(parameters, config, use_numpy_array=False):
'''Returns a string suitable to use as the return argument of a _gprc.LibraryInterpreter method'''
parameters_to_use = filter_parameters(parameters, ParameterUsageOptions.API_OUTPUT_PARAMETERS)
parameters_to_use = filter_parameters(parameters, ParameterUsageOptions.API_NUMPY_OUTPUT_PARAMETERS if use_numpy_array else ParameterUsageOptions.API_OUTPUT_PARAMETERS)
snippets = [_get_grpc_interpreter_output_param_return_snippet(p, parameters, config) for p in parameters_to_use]
return ('return ' + ', '.join(snippets)).strip()

Expand Down
11 changes: 11 additions & 0 deletions build/helper/metadata_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -499,3 +499,14 @@ def are_complex_parameters_used(functions):
are_complex_parameters_used = True
break
return are_complex_parameters_used


def are_grpc_complex_types_used(functions):
'''Returns bool based on whether any gRPC methods use nidevice complex message types.'''
grpc_complex_original_types = {'NIComplexNumber[]', 'NIComplexNumberF32[]', 'NIComplexI16[]'}
for _, function_metadata in functions.items():
numpy_parameters = filter_parameters(function_metadata['parameters'], ParameterUsageOptions.NUMPY_PARAMETERS)
for parameter in numpy_parameters:
if parameter.get('complex_array_representation') is not None and parameter.get('original_type') in grpc_complex_original_types:
return True
return False
23 changes: 21 additions & 2 deletions build/templates/_grpc_stub_interpreter.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module_name = config['module_name']
proto_name = config.get('proto_name', module_name)
service_class_prefix = config['grpc_service_class_prefix']
functions = helper.filter_codegen_functions(config['functions'])
are_grpc_complex_types_used = helper.are_grpc_complex_types_used(functions)
%>\

import grpc
Expand All @@ -21,9 +22,18 @@ from . import enums as enums # noqa: F401
from . import errors as errors
from . import ${proto_name}_pb2 as grpc_types
from . import ${proto_name}_pb2_grpc as ${module_name}_grpc
% if 'restricted_proto' in config:
from . import ${config['restricted_proto']}_pb2 as restricted_grpc_types
from . import ${config['restricted_proto']}_pb2_grpc as restricted_grpc
% endif
% if are_grpc_complex_types_used:
from . import nidevice_pb2 as grpc_complex_types # noqa: F401
% endif
from . import session_pb2 as session_grpc_types
% for c in config['custom_types']:
% if config['custom_types']:

% endif
% for c in sorted(config['custom_types'], key=lambda custom_type: custom_type['file_name']):
from . import ${c['file_name']} as ${c['file_name']} # noqa: F401
% endfor

Expand All @@ -35,6 +45,9 @@ class GrpcStubInterpreter(object):
self._grpc_options = grpc_options
self._lock = threading.RLock()
self._client = ${module_name}_grpc.${service_class_prefix}Stub(grpc_options.grpc_channel)
% if 'restricted_proto' in config:
self._restricted_client = restricted_grpc.${service_class_prefix}RestrictedStub(grpc_options.grpc_channel)
% endif
self.set_session_handle()

def set_session_handle(self, value=session_grpc_types.Session()):
Expand Down Expand Up @@ -87,7 +100,13 @@ class GrpcStubInterpreter(object):
% for func_name in sorted(functions):
% for method_template in functions[func_name]['method_templates']:
% if method_template['library_interpreter_filename'] != '/none':
<%include file="${'/_grpc_stub_interpreter.py' + method_template['library_interpreter_filename'] + '.py.mako'}" args="f=functions[func_name], config=config, method_template=method_template" />\
<%
# Determine which grpc types and client to use for this function
f = functions[func_name]
grpc_types_var = 'restricted_grpc_types' if f.get('grpc_type') == 'restricted' else 'grpc_types'
grpc_client_var = 'restricted_grpc' if f.get('grpc_type') == 'restricted' else module_name + '_grpc'
%>\
<%include file="${'/_grpc_stub_interpreter.py' + method_template['library_interpreter_filename'] + '.py.mako'}" args="f=f, config=config, method_template=method_template, grpc_types_var=grpc_types_var, grpc_client_var=grpc_client_var" />\
% endif
% endfor
% endfor
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%page args="f, config, method_template"/>\
<%page args="f, config, method_template, grpc_types_var, grpc_client_var"/>\
<%
'''Renders a GrpcStubInterpreter method corresponding to the passed-in function metadata.'''
import build.helper as helper
Expand All @@ -10,14 +10,15 @@
if return_statement == 'return':
return_statement = None
capture_response = 'response = ' if return_statement else ''
client = 'self._restricted_client' if grpc_client_var == 'restricted_grpc' else 'self._client'
included_in_proto = f.get('included_in_proto', True)
%>\

def ${full_func_name}(${method_decl_params}): # noqa: N802
% if included_in_proto:
${capture_response}self._invoke(
self._client.${grpc_name},
grpc_types.${grpc_name}Request(${grpc_request_args}),
${client}.${grpc_name},
${grpc_types_var}.${grpc_name}Request(${grpc_request_args}),
)
% if return_statement:
${return_statement}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%page args="f, config, method_template"/>\
<%page args="f, config, method_template, grpc_types_var, grpc_client_var"/>\
<%
'''Renders a GrpcStubInterpreter initialization method, adding proto-specific fields to the passed-in function metadata.'''

Expand Down
2 changes: 1 addition & 1 deletion build/templates/_grpc_stub_interpreter.py/lock.py.mako
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%page args="f, config, method_template"/>\
<%page args="f, config, method_template, grpc_types_var, grpc_client_var"/>\
<%
import build.helper as helper

Expand Down
2 changes: 1 addition & 1 deletion build/templates/_grpc_stub_interpreter.py/unlock.py.mako
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%page args="f, config, method_template"/>\
<%page args="f, config, method_template, grpc_types_var, grpc_client_var"/>\
<%
import build.helper as helper

Expand Down
12 changes: 11 additions & 1 deletion docs/nirfsg/class.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Session
=======

.. py:class:: Session(self, resource_name, id_query=False, reset_device=False, options={})
.. py:class:: Session(self, resource_name, id_query=False, reset_device=False, options={}, *, grpc_options=None)



Expand Down Expand Up @@ -111,6 +111,16 @@ Session

:type options: dict

:param grpc_options:


MeasurementLink gRPC session options




:type grpc_options: nirfsg.GrpcSessionOptions


Methods
=======
Expand Down
10 changes: 10 additions & 0 deletions docs/nirfsg/errors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ SelfTestError
An error due to a failed self-test


RpcError
--------

.. py:currentmodule:: nirfsg.errors

.. exception:: RpcError

An error specific to sessions to the NI gRPC Device Server


DriverWarning
-------------

Expand Down
91 changes: 91 additions & 0 deletions docs/nirfsg/grpc_session_options.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
gRPC Support
============

Support for using NI-RFSG over gRPC

.. py:currentmodule:: nirfsg



SessionInitializationBehavior
-----------------------------

.. py:class:: SessionInitializationBehavior

.. py:attribute:: SessionInitializationBehavior.AUTO


The NI gRPC Device Server will attach to an existing session with the specified name if it exists,
otherwise the server will initialize a new session.

.. note:: When using the Session as a context manager and the context exits, the behavior depends on what happened when the constructor
was called. If it resulted in a new session being initialized on the NI gRPC Device Server, then it will automatically close the
server session. If it instead attached to an existing session, then it will detach from the server session and leave it open.


.. py:attribute:: SessionInitializationBehavior.INITIALIZE_SERVER_SESSION


Require the NI gRPC Device Server to initialize a new session with the specified name.

.. note:: When using the Session as a context manager and the context exits, it will automatically close the
server session.


.. py:attribute:: SessionInitializationBehavior.ATTACH_TO_SERVER_SESSION


Require the NI gRPC Device Server to attach to an existing session with the specified name.

.. note:: When using the Session as a context manager and the context exits, it will detach from the server session
and leave it open.



GrpcSessionOptions
------------------


.. py:class:: GrpcSessionOptions(self, grpc_channel, session_name, initialization_behavior=SessionInitializationBehavior.AUTO)


Collection of options that specifies session behaviors related to gRPC.

Creates and returns an object you can pass to a Session constructor.


:param grpc_channel:


Specifies the channel to the NI gRPC Device Server.



:type grpc_channel: grpc.Channel


:param session_name:


User-specified name that identifies the driver session on the NI gRPC Device Server.

This is different from the resource name parameter many APIs take as a separate
parameter. Specifying a name makes it easy to share sessions across multiple gRPC clients.
You can use an empty string if you want to always initialize a new session on the server.
To attach to an existing session, you must specify the session name it was initialized with.



:type session_name: str


:param initialization_behavior:


Specifies whether it is acceptable to initialize a new session or attach to an existing one, or if only one of the behaviors is desired.

The driver session exists on the NI gRPC Device Server.



:type initialization_behavior: :py:data:`nirfsg.SessionInitializationBehavior`
1 change: 1 addition & 0 deletions docs/nirfsg/toc.inc
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ API Reference
enums
errors
examples
grpc_session_options

3 changes: 1 addition & 2 deletions generated/nidcpower/nidcpower/_grpc_stub_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
from . import nidcpower_pb2_grpc as nidcpower_grpc
from . import session_pb2 as session_grpc_types

from . import lcr_measurement as lcr_measurement # noqa: F401

from . import lcr_load_compensation_spot as lcr_load_compensation_spot # noqa: F401
from . import lcr_measurement as lcr_measurement # noqa: F401


class GrpcStubInterpreter(object):
Expand Down
2 changes: 0 additions & 2 deletions generated/nidcpower/nidcpower/_library_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,6 @@ def initialize_with_channels(self, resource_name, channels, reset, option_string
errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False)
self._close_on_exit = True
return int(vi_ctype.value)

def initialize_with_independent_channels(self, resource_name, reset, option_string): # noqa: N802
resource_name_ctype = ctypes.create_string_buffer(resource_name.encode(self._encoding)) # case C020
reset_ctype = _visatype.ViBoolean(reset) # case S150
Expand All @@ -484,7 +483,6 @@ def initialize_with_independent_channels(self, resource_name, reset, option_stri
errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False)
self._close_on_exit = True
return int(vi_ctype.value)

def initiate_with_channels(self, channel_name): # noqa: N802
vi_ctype = _visatype.ViSession(self._vi) # case S110
channel_name_ctype = ctypes.create_string_buffer(channel_name.encode(self._encoding)) # case C010
Expand Down
1 change: 0 additions & 1 deletion generated/nidigital/nidigital/_library_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,6 @@ def init_with_options(self, resource_name, id_query, reset_device, option_string
errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False)
self._close_on_exit = True
return int(new_vi_ctype.value)

def initiate(self): # noqa: N802
vi_ctype = _visatype.ViSession(self._vi) # case S110
error_code = self._library.niDigital_Initiate(vi_ctype)
Expand Down
1 change: 0 additions & 1 deletion generated/nidmm/nidmm/_library_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,6 @@ def init_with_options(self, resource_name, id_query, reset_device, option_string
errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False)
self._close_on_exit = True
return int(vi_ctype.value)

def initiate(self): # noqa: N802
vi_ctype = _visatype.ViSession(self._vi) # case S110
error_code = self._library.niDMM_Initiate(vi_ctype)
Expand Down
5 changes: 2 additions & 3 deletions generated/nifake/nifake/_grpc_stub_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@
from . import errors as errors
from . import nifake_pb2 as grpc_types
from . import nifake_pb2_grpc as nifake_grpc
from . import nidevice_pb2 as grpc_complex_types # noqa: F401
from . import session_pb2 as session_grpc_types

from . import custom_struct as custom_struct # noqa: F401

from . import custom_struct_typedef as custom_struct_typedef # noqa: F401

from . import custom_struct_nested_typedef as custom_struct_nested_typedef # noqa: F401
from . import custom_struct_typedef as custom_struct_typedef # noqa: F401


class GrpcStubInterpreter(object):
Expand Down
1 change: 0 additions & 1 deletion generated/nifake/nifake/_library_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,6 @@ def init_with_options(self, resource_name, id_query, reset_device, option_string
errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False)
self._close_on_exit = True
return int(vi_ctype.value)

def initiate(self): # noqa: N802
vi_ctype = _visatype.ViSession(self._vi) # case S110
error_code = self._library.niFake_Initiate(vi_ctype)
Expand Down
1 change: 0 additions & 1 deletion generated/nifgen/nifgen/_library_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,6 @@ def initialize_with_channels(self, resource_name, channel_name, reset_device, op
errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False)
self._close_on_exit = True
return int(vi_ctype.value)

def initiate_generation(self): # noqa: N802
vi_ctype = _visatype.ViSession(self._vi) # case S110
error_code = self._library.niFgen_InitiateGeneration(vi_ctype)
Expand Down
1 change: 1 addition & 0 deletions generated/nirfsg/nirfsg/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from nirfsg.enums import * # noqa: F403,F401,H303
from nirfsg.errors import DriverWarning # noqa: F401
from nirfsg.errors import Error # noqa: F401
from nirfsg.grpc_session_options import * # noqa: F403,F401,H303
from nirfsg.session import Session # noqa: F401


Expand Down
Loading