prkumar/uplink-protobuf

View on GitHub
uplink_protobuf/json_options.py

Summary

Maintainability
A
0 mins
Test Coverage
# Third party imports
from google.protobuf import json_format
from uplink import decorators

# Local imports
from uplink_protobuf import helpers

__all__ = [
    "include_default_value_fields",
    "preserve_proto_field_names",
    "use_integers_for_enums",
    "ignore_unknown_fields"
]


class _DecodeOption(decorators.MethodAnnotation):
    @property
    def options(self):  # pragma: no cover
        raise NotImplementedError


class _EncodeOption(decorators.MethodAnnotation):
    @property
    def options(self):  # pragma: no cover
        raise NotImplementedError


# noinspection PyPep8Naming
class include_default_value_fields(_EncodeOption):
    """
    Indicates that the JSON output should include fields with their
    default values.

    By default, these fields are omitted if not set.
    """
    _can_be_static = True
    __options = {"including_default_value_fields": True}

    @property
    def options(self):
        return self.__options


# noinspection PyPep8Naming
class preserve_proto_field_names(_EncodeOption):
    """
    Indicates that the JSON output should use the proto field name as
    the JSON name.

    By default, the JSON printer converts the proto field names to
    lowerCamelCase and uses that as the JSON name.
    """
    _can_be_static = True
    __options = {"preserving_proto_field_name": True}

    @property
    def options(self):
        return self.__options


# noinspection PyPep8Naming
class use_integers_for_enums(_EncodeOption):
    """
    Indicates that the JSON output should use the numerical value of a
    proto enum value, instead of the name of the enum value.

    By default, the name of an enum value is used in the JSON
    output.
    """
    _can_be_static = True
    __options = {"use_integers_for_enums": True}

    @property
    def options(self):
        return self.__options


# noinspection PyPep8Naming
class ignore_unknown_fields(_DecodeOption):
    """
    Indicates that the JSON parser should ignore unknown fields in
    parsing.
    """
    _can_be_static = True
    __options = {"ignore_unknown_fields": True}

    @property
    def options(self):
        return self.__options


def parse_json(message_cls, request_definition, body):
    method_annotations = request_definition.method_annotations
    parsing_options = {}
    for opt in helpers.get_values_of_type(method_annotations, _DecodeOption):
        parsing_options.update(opt.options)

    message = message_cls()
    return json_format.ParseDict(body, message, **parsing_options)


def convert_message_to_dict(_, request_definition, message):
    method_annotations = request_definition.method_annotations
    printing_options = {}

    for opt in helpers.get_values_of_type(method_annotations, _EncodeOption):
        printing_options.update(opt.options)

    return json_format.MessageToDict(message, **printing_options)