Skip to content
This repository has been archived by the owner on Jul 21, 2021. It is now read-only.

Latest commit

 

History

History
155 lines (89 loc) · 3.82 KB

proto-mapping.rst

File metadata and controls

155 lines (89 loc) · 3.82 KB

Proto Mapping in Detail

A :py~mercator.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 :py~mercator.ProtoMapping must declare a proto attribute that points to a valid :py~google.protobuf.message.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 :pySyntaxError

__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 :pytype.

The section SQLAlchemy Support for more information on how to use the __source_input_type__ attribute.

Field mappings

Field mappings are either :py~mercator.ProtoKey or :py~mercator.ProtoList class-attributes defined in the body of your :py~mercator.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 :pymercator.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: :pystr, :pyint, :pyfloat, :pylong, :pydict, :pylist

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)