Protopigeon provides utilities for generating protorpc Messages from ndb Models. It can generate Message classes from Models, translate entities to message instances and vice-versa. It can also compose multiple message classes together.
If you have a model:
class Actor(ndb.Model)
name = ndb.StringProperty()
shows = ndb.StringProperty(repeated=True)
rating = ndb.IntegerProperty()You can easily generate a message class:
ActorMessage = protopigeon.model_message(Actor)You can also exclude fields, or specify which particular fields:
ActorWithoutRatingMessage = protopigeon.model_message(Action, exclude=('rating',))
ActorRatingMessage = protopigeon.model_message(Action, only=('rating',))Playing on the previous example, if you have an entity (an instance of a Model) and want to make a message:
doctor = Actor(name='Matt Smith', shows=('Doctor Who', 'Moses Jones'), rating=90)
doctor_message = protopigeon.to_message(doctor, ActorMessage)
doctor_no_rating = protopigeon.to_message(doctor, ActorWithoutRatingMessage)
doctor_rating = protopigeon.to_message(doctor, ActorRatingMessage)If you have an instance of a message and you want an entity:
doctor = protopigeon.to_entity(doctor_message, Actor)You can even use this to update an existing entity (this works vice-versa with existing message instances too):
new_doctor = protopigeon.to_entity(doctor_no_rating, Actor) # all fields but rating populated
protopigeon.to_entity(doctor_rating, new_doctor) # rating has been populated now, it's a complete entity.If you have two or more messages classes that you'd like to combine into one message, we can do that too.
class Origin(Message)
year = IntegerField(1)
location = StringField(2)
class Traveler(Message):
name = StringField(1)
species = StringField(1)
class Tag(Message)
urlsafe = StringField(1)
TravelerWithOriginAndTag = protopigeon.compose(Origin, Destination, Tag)
instance = TravelerWithOriginAndTag(
name='The Doctor',
year=2013,
location='Gallifrey'
species='Time Lord',
urlsafe='the_doctor'
)At the moment, I do not have a clever solution for supporting computed properties. I may take the approach seen in the endpoints-proto-datastore and add a TypedComputedProperty. However, my goal was to not modify any Model classes if I didn't absolutely have to. I'm open to suggestions on this.
In the meantime it's pretty easy to fill in the data yourself using the above method of composing messages.
You can install easily with pip:
pip install --target lib protopigeon
I graciously accept bugs and pull requests.
Apache License, Version 2.0
Special thanks to Danny Hermes and his endpoints-proto-datastore library, which helped me figure out a few quirky bits of ndb-to-message mapping. It's a much more comprehensive library and great if you want a more direct and magical approach to integrating protorpc, ndb, and endpoints.