Skip to content

Commit

Permalink
Handle unsupported message type errors in client generator (#984)
Browse files Browse the repository at this point in the history
* fix: throw error for all message types and continue client creation for multiple clients

* fix: formatting

* fix: comments

* fix: update error messages and remove continue

* fix: refactor the code by breaking into sub-methods

* fix: revert the code refactor and remove try except in batch mode

* fix: throw error for first failure after iteration duting all mode

* fix: formatting

* fix: update error message
  • Loading branch information
Jotheeswaran-Nandagopal authored Oct 16, 2024
1 parent 3360077 commit a0cf656
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
)


_CLIENT_CREATION_ERROR_MESSAGE = "Client creation failed for '{}'. Possible reason(s): {}"


def _render_template(template_name: str, **template_args: Any) -> bytes:
file_path = str(pathlib.Path(__file__).parent / "templates" / template_name)
template = Template(filename=file_path, input_encoding="utf-8", output_encoding="utf-8")
Expand Down Expand Up @@ -60,6 +63,7 @@ def _create_client(
module_name: str,
class_name: str,
directory_out: pathlib.Path,
generated_modules: List[str],
) -> None:
built_in_import_modules: List[str] = []
custom_import_modules: List[str] = []
Expand Down Expand Up @@ -103,6 +107,7 @@ def _create_client(
+ metadata.measurement_signature.configuration_parameters_message_type,
)

generated_modules.append(module_name)
print(
f"The measurement plug-in client for the service class '{measurement_service_class}' has been successfully created as '{module_name}.py'."
)
Expand All @@ -113,26 +118,39 @@ def _create_all_clients(directory_out: Optional[str]) -> None:
discovery_client = DiscoveryClient(grpc_channel_pool=channel_pool)

generated_modules: List[str] = []
errors: List[str] = []
directory_out_path = resolve_output_directory(directory_out)
measurement_service_classes, _ = get_all_registered_measurement_info(discovery_client)
validate_measurement_service_classes(measurement_service_classes)

for service_class in measurement_service_classes:
base_service_class = extract_base_service_class(service_class)
module_name = create_module_name(base_service_class, generated_modules)
class_name = create_class_name(base_service_class)
validate_identifier(module_name, "module")
validate_identifier(class_name, "class")

_create_client(
channel_pool=channel_pool,
discovery_client=discovery_client,
measurement_service_class=service_class,
module_name=module_name,
class_name=class_name,
directory_out=directory_out_path,
try:
base_service_class = extract_base_service_class(service_class)
module_name = create_module_name(base_service_class, generated_modules)
class_name = create_class_name(base_service_class)
validate_identifier(module_name, "module")
validate_identifier(class_name, "class")

_create_client(
channel_pool=channel_pool,
discovery_client=discovery_client,
measurement_service_class=service_class,
module_name=module_name,
class_name=class_name,
directory_out=directory_out_path,
generated_modules=generated_modules,
)
except Exception as e:
errors.append(_CLIENT_CREATION_ERROR_MESSAGE.format(service_class, e))

if len(errors) == 1:
raise click.ClickException(errors[0])
elif len(errors) > 1:
raise click.ClickException(
"Client creation failed for multiple measurement plug-ins:\n\n{}".format(
"\n\n".join(errors)
)
)
generated_modules.append(module_name)


def _create_clients_interactively() -> None:
Expand Down Expand Up @@ -162,31 +180,34 @@ def _create_clients_interactively() -> None:
int(selection), measurement_service_classes
)

base_service_class = extract_base_service_class(service_class)
default_module_name = create_module_name(base_service_class, generated_modules)
module_name = click.prompt(
"Enter a name for the Python client module, or press Enter to use the default name.",
type=str,
default=default_module_name,
)
validate_identifier(module_name, "module")
default_class_name = create_class_name(base_service_class)
class_name = click.prompt(
"Enter a name for the Python client class, or press Enter to use the default name.",
type=str,
default=default_class_name,
)
validate_identifier(class_name, "class")

_create_client(
channel_pool=channel_pool,
discovery_client=discovery_client,
measurement_service_class=service_class,
module_name=module_name,
class_name=class_name,
directory_out=directory_out_path,
)
generated_modules.append(module_name)
try:
base_service_class = extract_base_service_class(service_class)
default_module_name = create_module_name(base_service_class, generated_modules)
module_name = click.prompt(
"Enter a name for the Python client module, or press Enter to use the default name.",
type=str,
default=default_module_name,
)
validate_identifier(module_name, "module")
default_class_name = create_class_name(base_service_class)
class_name = click.prompt(
"Enter a name for the Python client class, or press Enter to use the default name.",
type=str,
default=default_class_name,
)
validate_identifier(class_name, "class")

_create_client(
channel_pool=channel_pool,
discovery_client=discovery_client,
measurement_service_class=service_class,
module_name=module_name,
class_name=class_name,
directory_out=directory_out_path,
generated_modules=generated_modules,
)
except Exception as e:
click.echo(_CLIENT_CREATION_ERROR_MESSAGE.format(service_class, e))


def _create_clients(
Expand Down Expand Up @@ -217,8 +238,8 @@ def _create_clients(
module_name=module_name,
class_name=class_name,
directory_out=directory_out_path,
generated_modules=generated_modules,
)
generated_modules.append(module_name)


@click.command()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ def get_configuration_and_output_metadata_by_index(
"""Returns the configuration and output metadata of the measurement."""
configuration_parameter_list = []
for configuration in metadata.measurement_signature.configuration_parameters:
if configuration.message_type:
raise click.ClickException(
f"Measurement configurations do not support message data types ({configuration.message_type} is unsupported)."
)

annotations_dict = dict(configuration.annotations.items())
if _is_enum_param(configuration.type):
annotations_dict["ni/enum.values"] = _validate_and_transform_enum_annotations(
Expand All @@ -148,6 +153,11 @@ def get_configuration_and_output_metadata_by_index(

output_parameter_list = []
for output in metadata.measurement_signature.outputs:
if output.message_type and output.message_type != "ni.protobuf.types.DoubleXYData":
raise click.ClickException(
f"Measurement outputs do not support {output.message_type}. Only DoubleXYData is supported."
)

annotations_dict = dict(output.annotations.items())
if _is_enum_param(output.type):
annotations_dict["ni/enum.values"] = _validate_and_transform_enum_annotations(
Expand Down Expand Up @@ -231,11 +241,6 @@ def get_configuration_parameters_with_type_and_default_values(
else:
default_value = f"pathlib.PurePath({default_value})"

if metadata.message_type:
raise click.ClickException(
"Measurement configuration with message datatype is not supported."
)

if metadata.annotations and metadata.annotations.get("ni/type_specialization") == "enum":
enum_type = _get_enum_type(
metadata.display_name, metadata.annotations["ni/enum.values"], enum_values_by_type
Expand Down

0 comments on commit a0cf656

Please sign in to comment.