{"id":15686025,"url":"https://github.com/theacodes/protopigeon","last_synced_at":"2025-05-07T18:22:19.730Z","repository":{"id":21512371,"uuid":"24831451","full_name":"theacodes/Protopigeon","owner":"theacodes","description":"Helpers for datastore models and protorpc messages","archived":false,"fork":false,"pushed_at":"2015-01-14T15:54:48.000Z","size":220,"stargazers_count":9,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-25T04:48:09.727Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"sonata-nfv/son-gui","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theacodes.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-06T02:06:45.000Z","updated_at":"2023-05-15T13:08:38.000Z","dependencies_parsed_at":"2022-08-21T16:20:57.778Z","dependency_job_id":null,"html_url":"https://github.com/theacodes/Protopigeon","commit_stats":null,"previous_names":["jonparrott/protopigeon"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theacodes%2FProtopigeon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theacodes%2FProtopigeon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theacodes%2FProtopigeon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theacodes%2FProtopigeon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theacodes","download_url":"https://codeload.github.com/theacodes/Protopigeon/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252931883,"owners_count":21827181,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-03T17:34:54.825Z","updated_at":"2025-05-07T18:22:19.706Z","avatar_url":"https://github.com/theacodes.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"Protopigeon\n===========\n\nProtopigeon provides utilities for generating [protorpc Messages](https://cloud.google.com/appengine/docs/python/tools/protorpc/#Working_with_Messages) from [ndb Models](https://cloud.google.com/appengine/docs/python/ndb/). It can generate Message classes from Models, translate entities to message instances and vice-versa. It can also compose multiple message classes together.\n\n\nUsage\n=====\n\nGenerating message classes from a model\n---------------------------------------\n\nIf you have a model:\n\n```python\nclass Actor(ndb.Model)\n    name = ndb.StringProperty()\n    shows = ndb.StringProperty(repeated=True)\n    rating = ndb.IntegerProperty()\n```\n\nYou can easily generate a message class:\n\n```python\nActorMessage = protopigeon.model_message(Actor)\n```\n\nYou can also exclude fields, or specify which particular fields:\n\n```python\nActorWithoutRatingMessage = protopigeon.model_message(Action, exclude=('rating',))\nActorRatingMessage = protopigeon.model_message(Action, only=('rating',))\n```\n\nTranslating between entities and messages\n-----------------------------------------\n\nPlaying on the previous example, if you have an entity (an instance of a Model) and want to make a message:\n\n```python\ndoctor = Actor(name='Matt Smith', shows=('Doctor Who', 'Moses Jones'), rating=90)\n\ndoctor_message = protopigeon.to_message(doctor, ActorMessage)\ndoctor_no_rating = protopigeon.to_message(doctor, ActorWithoutRatingMessage)\ndoctor_rating = protopigeon.to_message(doctor, ActorRatingMessage)\n```\n\nIf you have an instance of a message and you want an entity:\n\n```python\ndoctor = protopigeon.to_entity(doctor_message, Actor)\n```\n\nYou can even use this to update an existing entity (this works vice-versa with existing message instances too):\n\n```python\nnew_doctor = protopigeon.to_entity(doctor_no_rating, Actor)  # all fields but rating populated\nprotopigeon.to_entity(doctor_rating, new_doctor) # rating has been populated now, it's a complete entity.\n```\n\nComposing messages\n------------------\n\nIf you have two or more messages classes that you'd like to combine into one message, we can do that too.\n\n```python\nclass Origin(Message)\n    year = IntegerField(1)\n    location = StringField(2)\n\nclass Traveler(Message):\n    name = StringField(1)\n    species = StringField(1)\n\nclass Tag(Message)\n    urlsafe = StringField(1)\n\nTravelerWithOriginAndTag = protopigeon.compose(Origin, Destination, Tag)\n\ninstance = TravelerWithOriginAndTag(\n    name='The Doctor',\n    year=2013,\n    location='Gallifrey'\n    species='Time Lord',\n    urlsafe='the_doctor'\n)\n```\n\nThings that don't work\n======================\n\nAt 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.\n\nIn the meantime it's pretty easy to fill in the data yourself using the above method of composing messages.\n\n\nInstallation\n============\n\nYou can install easily with pip:\n\n    pip install --target lib protopigeon\n\n\nContributing\n============\n\nI graciously accept bugs and pull requests.\n\n\nLicense\n=======\n\nApache License, Version 2.0\n\n\nThanks\n======\n\nSpecial thanks to Danny Hermes and his [endpoints-proto-datastore](https://github.com/GoogleCloudPlatform/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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheacodes%2Fprotopigeon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheacodes%2Fprotopigeon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheacodes%2Fprotopigeon/lists"}