def as_proto_cls(proto_cls):
  """Simulate proto inheritance.

  By default, protobuf do not support direct inheritance, so this decorator
  simulates inheritance to the class to which it is applied.

  Example:

  ```
  @as_proto_class(proto.MyProto)
  class A(object):
    def custom_method(self):
      return self.proto_field * 10

  p = proto.MyProto(proto_field=123)

  a = A()
  a.CopyFrom(p)  # a is like a proto object
  assert a.proto_field == 123
  a.custom_method()  # But has additional methods

  ```

  Args:
    proto_cls: The protobuf class to inherit from

  Returns:
    decorated_cls: The decorated class
  """

  def decorator(cls):
    """Decorator applied to the class."""

    class ProtoCls(object):
      """Base class simulating the protobuf."""

      def __init__(self, *args, **kwargs):
        super(ProtoCls, self).__setattr__(
            "_ProtoCls__proto",
            proto_cls(*args, **kwargs),
        )

      def __getattr__(self, attr_name):
        return getattr(self.__proto, attr_name)

      def __setattr__(self, attr_name, new_value):
        try:
          return setattr(self.__proto, attr_name, new_value)
        except AttributeError:
          return super(ProtoCls, self).__setattr__(attr_name, new_value)

      def __eq__(self, other):
        return self.__proto, other.get_proto()

      def get_proto(self):
        return self.__proto

      def __repr__(self):
        return "<{cls_name}\n{proto_repr}\n>".format(
            cls_name=cls.__name__, proto_repr=repr(self.__proto))

    decorator_cls = type(cls.__name__, (cls, ProtoCls), {
        "__doc__": cls.__doc__,
    })
    return decorator_cls
  return decorator
def as_proto_cls ( proto_cls ) : def decorator ( cls ) : class ProtoCls ( object ) : def __init__ ( self , * args , ** kwargs ) : super ( ProtoCls , self ) . __setattr__ ( "_ProtoCls__proto" , proto_cls ( * args , ** kwargs ) , ) def __getattr__ ( self , attr_name ) : return getattr ( self . __proto , attr_name ) def __setattr__ ( self , attr_name , new_value ) : try : return setattr ( self . __proto , attr_name , new_value ) except AttributeError : return super ( ProtoCls , self ) . __setattr__ ( attr_name , new_value ) def __eq__ ( self , other ) : return self . __proto , other . get_proto ( ) def get_proto ( self ) : return self . __proto def __repr__ ( self ) : return "<{cls_name}\n{proto_repr}\n>" . format ( cls_name = cls . __name__ , proto_repr = repr ( self . __proto ) ) decorator_cls = type ( cls . __name__ , ( cls , ProtoCls ) , { "__doc__" : cls . __doc__ , } ) return decorator_cls return decorator
Simulate proto inheritance.

  By default, protobuf do not support direct inheritance, so this decorator
  simulates inheritance to the class to which it is applied.

  Example:

  ```
  @as_proto_class(proto.MyProto)
  class A(object):
    def custom_method(self):
      return self.proto_field * 10

  p = proto.MyProto(proto_field=123)

  a = A()
  a.CopyFrom(p)  # a is like a proto object
  assert a.proto_field == 123
  a.custom_method()  # But has additional methods

  ```

  Args:
    proto_cls: The protobuf class to inherit from

  Returns:
    decorated_cls: The decorated class