Proto Mapping in Detail¶
A ProtoMapping
provides syntax sugar to define
ways in which python dictionaries or objects can have its keys or
properties serialized into predefined ProtoBuf messages.
__proto__
¶
Every ProtoMapping
must declare a __proto__ attribute that points to a valid Message
subclass.
Example:¶
from google.protobuf.timestamp_pb2 import Timestamp
from mercator import ProtoMapping
from mercator import ProtoKey
class TimestampMapping(ProtoMapping):
__proto__ = Timestamp
seconds = ProtoKey('seconds', int)
Warning
Failing to declare a valid __proto__ attribute will cause mercator to raise a SyntaxError
__source_input_type__
¶
If declared, this property will be considered as base-class of opaque objects that can have its properties mapped into protobuf.
This feature was primarily designed to support SQLAlchemy ORM models out of the box but supports any opaque python objects, as long as their base classes are defined by this attribute.
from sqlalchemy.ext.declarative import declarative_base
from mercator import ProtoMapping
from mercator import ProtoKey
MySimpleBaseModel = declarative_base()
class User(MySimpleBaseModel):
__tablename__ = 'user'
__table_args__ = {'useexisting': True}
login = sa.Column(sa.String(256))
email = sa.Column(sa.String(256))
password = sa.Column(sa.String(256))
class UserMapping(ProtoMapping):
__proto__ = domain_pb2.User
__source_input_type__ = User
Important
This attribute is optional when declaring proto mappings, but if defined it must be a type
.
See also
The section SQLAlchemy ORM Support for more information on
how to use the __source_input_type__
attribute.
Field mappings¶
Field mappings are either ProtoKey
or
ProtoList
class-attributes defined in the body
of your ProtoMapping
subclass.
This gives you the power to gather data from dictionaries with keys that are different than in the protobuf model.
target_type
¶
Field mappings are subclasses of mercator.meta.FieldMapping
and share its __init__
signature:
FieldMapping(name_at_source: str, target_type: type)
ProtoKey(name_at_source: str, target_type: type)
ProtoList(name_at_source: str, target_type: type)
The target_type
argument is optional, but when given, supports different types.
Let’s dive into the possibilities.
Native python types¶
Ensures that the field value is cast into any python type, namely: str
, int
, float
, long
, dict
, list
Mappings of Mappings¶
Allows recursively translating data into protobuf messages whose members contain sub-messages.
Example¶
from mercator import (
ProtoMapping,
ProtoKey,
)
from . import domain_pb2
from . import sql
class UserMapping(ProtoMapping):
__proto__ = domain_pb2.User
uuid = ProtoKey('id', str)
email = ProtoKey('email', str)
username = ProtoKey('login', str)
class MediaMapping(ProtoMapping):
__proto__ = domain_pb2.UserMedia
author = ProtoKey('owner', UserMapping)
download_url = ProtoKey('link', str)