| Index: tools/telemetry/third_party/gsutilz/third_party/protorpc/demos/tunes_db/server/tunes_db.py
|
| diff --git a/tools/telemetry/third_party/gsutilz/third_party/protorpc/demos/tunes_db/server/tunes_db.py b/tools/telemetry/third_party/gsutilz/third_party/protorpc/demos/tunes_db/server/tunes_db.py
|
| deleted file mode 100755
|
| index 0d62cb7ce9a7bdbc69bc629b946168854b6713de..0000000000000000000000000000000000000000
|
| --- a/tools/telemetry/third_party/gsutilz/third_party/protorpc/demos/tunes_db/server/tunes_db.py
|
| +++ /dev/null
|
| @@ -1,539 +0,0 @@
|
| -#!/usr/bin/env python
|
| -#
|
| -# Copyright 2010 Google Inc.
|
| -#
|
| -# Licensed under the Apache License, Version 2.0 (the "License");
|
| -# you may not use this file except in compliance with the License.
|
| -# You may obtain a copy of the License at
|
| -#
|
| -# http://www.apache.org/licenses/LICENSE-2.0
|
| -#
|
| -# Unless required by applicable law or agreed to in writing, software
|
| -# distributed under the License is distributed on an "AS IS" BASIS,
|
| -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -# See the License for the specific language governing permissions and
|
| -# limitations under the License.
|
| -#
|
| -
|
| -"""Tunes DB service implementation.
|
| -
|
| -This module contains all the protocol buffer and service definitions
|
| -necessary for the Tunes DB service.
|
| -"""
|
| -
|
| -import base64
|
| -import sys
|
| -
|
| -from google.appengine.ext import db
|
| -
|
| -from protorpc import descriptor
|
| -from protorpc import message_types
|
| -from protorpc import messages
|
| -from protorpc import protobuf
|
| -from protorpc import remote
|
| -
|
| -import model
|
| -
|
| -
|
| -class Artist(messages.Message):
|
| - """Musician or music group responsible for music production.
|
| -
|
| - Fields:
|
| - artist_id: Unique opaque identifier for artist.
|
| - name: User friendly name of artist.
|
| - album_count: Number of albums produced by artist.
|
| - """
|
| -
|
| - artist_id = messages.StringField(1, required=True)
|
| - name = messages.StringField(2, required=True)
|
| -
|
| - album_count = messages.IntegerField(3)
|
| -
|
| -
|
| -class Album(messages.Message):
|
| - """Album produced by a musician or music group.
|
| -
|
| - Fields:
|
| - album_id: Unique opaque identifier for artist.
|
| - artist_id: Artist id of musician or music group that produced album.
|
| - name: Name of album.
|
| - released: Year when album was released.
|
| - """
|
| -
|
| - album_id = messages.StringField(1, required=True)
|
| - artist_id = messages.StringField(2, required=True)
|
| - name = messages.StringField(3, required=True)
|
| - released = messages.IntegerField(4)
|
| -
|
| -
|
| -class AddArtistRequest(messages.Message):
|
| - """Request to add a new Artist to library.
|
| -
|
| - Fields:
|
| - name: User friendly name of artist.
|
| - """
|
| -
|
| - name = messages.StringField(1, required=True)
|
| -
|
| -
|
| -class AddArtistResponse(messages.Message):
|
| - """Response sent after creation of new artist in library.
|
| -
|
| - Fields:
|
| - artist_id: Unique opaque ID of new artist.
|
| - """
|
| -
|
| - artist_id = messages.StringField(1, required=True)
|
| -
|
| -
|
| -class UpdateArtistRequest(messages.Message):
|
| - """Update an existing artist.
|
| -
|
| - Fields:
|
| - artist: Complete information about artist to update.
|
| - """
|
| -
|
| - artist = messages.MessageField(Artist, 1, required=True)
|
| -
|
| -
|
| -class UpdateArtistResponse(messages.Message):
|
| - """Artist update response.
|
| -
|
| - Fields:
|
| - artist_updated: Artist was found and updated.
|
| - """
|
| -
|
| - artist_updated = messages.BooleanField(1, required=True)
|
| -
|
| -
|
| -class DeleteArtistRequest(messages.Message):
|
| - """Delete artist from library.
|
| -
|
| - Fields:
|
| - artist_id: Unique opaque ID of artist to delete.
|
| - """
|
| -
|
| - artist_id = messages.StringField(1, required=True)
|
| -
|
| -
|
| -class DeleteArtistResponse(messages.Message):
|
| - """Artist deletion response.
|
| -
|
| - Fields:
|
| - artist_deleted: Artist was found and deleted.
|
| - """
|
| -
|
| - artist_deleted = messages.BooleanField(1, default=True)
|
| -
|
| -
|
| -class FetchArtistRequest(messages.Message):
|
| - """Fetch an artist from the library.
|
| -
|
| - Fields:
|
| - artist_id: Unique opaque ID of artist to fetch.
|
| - """
|
| -
|
| - artist_id = messages.StringField(1, required=True)
|
| -
|
| -
|
| -class FetchArtistResponse(messages.Message):
|
| - """Fetched artist from library.
|
| -
|
| - Fields:
|
| - artist: Artist found in library.
|
| - """
|
| -
|
| - artist = messages.MessageField(Artist, 1)
|
| -
|
| -
|
| -class SearchArtistsRequest(messages.Message):
|
| - """Artist search request.
|
| -
|
| - Fields:
|
| - continuation: Continuation from the response of a previous call to
|
| - search_artists remote method.
|
| - fetch_size: Maximum number of records to retrieve.
|
| - name_prefix: Name prefix of artists to search. If none provided and
|
| - no continuation provided, search will be of all artists in library.
|
| - If continuation is provided, name_prefix should be empty, if not, value
|
| - is ignored.
|
| - """
|
| -
|
| - continuation = messages.StringField(1)
|
| - fetch_size = messages.IntegerField(2, default=10)
|
| - name_prefix = messages.StringField(3, default=u'')
|
| -
|
| -
|
| -class SearchArtistsResponse(messages.Message):
|
| - """Response from searching artists.
|
| -
|
| - Fields:
|
| - artists: Artists found from search up to fetch_size.
|
| - continuation: Opaque string that can be used with a new search request
|
| - that will continue finding new artists where this response left off.
|
| - Will not be set if there were no results from the search or fewer
|
| - artists were returned in the response than requested, indicating the end
|
| - of the query.
|
| - """
|
| -
|
| - artists = messages.MessageField(Artist, 1, repeated=True)
|
| - continuation = messages.StringField(2)
|
| -
|
| -
|
| -class AddAlbumRequest(messages.Message):
|
| - """Request to add a new album to library.
|
| -
|
| - Fields:
|
| - name: User friendly name of album.
|
| - artist_id: Artist id of artist that produced record.
|
| - released: Year album was released.
|
| - """
|
| -
|
| - name = messages.StringField(1, required=True)
|
| - artist_id = messages.StringField(2, required=True)
|
| - released = messages.IntegerField(3)
|
| -
|
| -
|
| -class AddAlbumResponse(messages.Message):
|
| - """Response sent after creation of new album in library.
|
| -
|
| - Fields:
|
| - album_id: Unique opaque ID of new album.
|
| - """
|
| -
|
| - album_id = messages.StringField(1, required=True)
|
| -
|
| -
|
| -class UpdateAlbumRequest(messages.Message):
|
| - """Update an existing album.
|
| -
|
| - Fields:
|
| - album: Complete information about album to update.
|
| - """
|
| -
|
| - album = messages.MessageField(Album, 1, required=True)
|
| -
|
| -
|
| -class UpdateAlbumResponse(messages.Message):
|
| - """Album update response.
|
| -
|
| - Fields:
|
| - album_updated: Album was found and updated.
|
| - """
|
| -
|
| - album_updated = messages.BooleanField(1, required=True)
|
| -
|
| -
|
| -class DeleteAlbumRequest(messages.Message):
|
| - """Delete album from library.
|
| -
|
| - Fields:
|
| - album_id: Unique opaque ID of album to delete.
|
| - """
|
| -
|
| - album_id = messages.StringField(1, required=True)
|
| -
|
| -
|
| -class DeleteAlbumResponse(messages.Message):
|
| - """Album deletion response.
|
| -
|
| - Fields:
|
| - album_deleted: Album was found and deleted.
|
| - """
|
| -
|
| - album_deleted = messages.BooleanField(1, default=True)
|
| -
|
| -
|
| -class FetchAlbumRequest(messages.Message):
|
| - """Fetch an album from the library.
|
| -
|
| - Fields:
|
| - album_id: Unique opaque ID of album to fetch.
|
| - """
|
| -
|
| - album_id = messages.StringField(1, required=True)
|
| -
|
| -
|
| -class FetchAlbumResponse(messages.Message):
|
| - """Fetched album from library.
|
| -
|
| - Fields:
|
| - album: Album found in library.
|
| - """
|
| -
|
| - album = messages.MessageField(Album, 1)
|
| -
|
| -
|
| -class SearchAlbumsRequest(messages.Message):
|
| - """Album search request.
|
| -
|
| - Fields:
|
| - continuation: Continuation from the response of a previous call to
|
| - search_albums remote method.
|
| - fetch_size: Maximum number of records to retrieve.
|
| - name_prefix: Name prefix of albms to search. If none provided and
|
| - no continuation provided, search will be of all albums in library.
|
| - If continuation is provided, name_prefix should be empty, if not, value
|
| - is ignored.
|
| - artist_id: Restrict search to albums of single artist.
|
| - """
|
| -
|
| - continuation = messages.StringField(1)
|
| - fetch_size = messages.IntegerField(2, default=10)
|
| - name_prefix = messages.StringField(3, default=u'')
|
| - artist_id = messages.StringField(4)
|
| -
|
| -
|
| -class SearchAlbumsResponse(messages.Message):
|
| - """Response from searching artists.
|
| -
|
| - Fields:
|
| - albums: Albums found from search up to fetch_size.
|
| - continuation: Opaque string that can be used with a new search request
|
| - that will continue finding new albums where this response left off.
|
| - Will not be set if there were no results from the search or fewer
|
| - albums were returned in the response than requested, indicating the end
|
| - of the query.
|
| - """
|
| -
|
| - albums = messages.MessageField(Album, 1, repeated=True)
|
| - continuation = messages.StringField(2)
|
| -
|
| -
|
| -class MusicLibraryService(remote.Service):
|
| - """Music library service."""
|
| -
|
| - __file_set = None
|
| -
|
| - def __artist_from_model(self, artist_model):
|
| - """Helper that copies an Artist model to an Artist message.
|
| -
|
| - Args:
|
| - artist_model: model.ArtistInfo instance to convert in to an Artist
|
| - message.
|
| -
|
| - Returns:
|
| - New Artist message with contents of artist_model copied in to it.
|
| - """
|
| - return Artist(artist_id=unicode(artist_model.key()),
|
| - name=artist_model.name,
|
| - album_count=artist_model.album_count)
|
| -
|
| - def __album_from_model(self, album_model):
|
| - """Helper that copies an Album model to an Album message.
|
| -
|
| - Args:
|
| - album_model: model.AlbumInfo instance to convert in to an Album
|
| - message.
|
| -
|
| - Returns:
|
| - New Album message with contents of album_model copied in to it.
|
| - """
|
| - artist_id = model.AlbumInfo.artist.get_value_for_datastore(album_model)
|
| -
|
| - return Album(album_id=unicode(album_model.key()),
|
| - artist_id=unicode(artist_id),
|
| - name=album_model.name,
|
| - released=album_model.released or None)
|
| -
|
| - @classmethod
|
| - def __search_info(cls,
|
| - request,
|
| - info_class,
|
| - model_to_message,
|
| - customize_query=None):
|
| - """Search over an Info subclass.
|
| -
|
| - Since all search request classes are very similar, it's possible to
|
| - generalize how to do searches over them.
|
| -
|
| - Args:
|
| - request: Search request received from client.
|
| - info_class: The model.Info subclass to search.
|
| - model_to_method: Function (model) -> message that transforms an instance
|
| - of info_class in to the appropriate messages.Message subclass.
|
| - customize_query: Function (request, query) -> None that adds additional
|
| - filters to Datastore query based on specifics of that search message.
|
| -
|
| - Returns:
|
| - Tuple (results, continuation):
|
| - results: A list of messages satisfying the parameters of the request.
|
| - None if there are no results.
|
| - continuation: Continuation string for response if there are more
|
| - results available. None if there are no more results available.
|
| - """
|
| - # TODO(rafek): fetch_size from this request should take priority
|
| - # over what is stored in continuation.
|
| - if request.continuation:
|
| - encoded_search, continuation = request.continuation.split(':', 1)
|
| - decoded_search = base64.urlsafe_b64decode(encoded_search.encode('utf-8'))
|
| - request = protobuf.decode_message(type(request), decoded_search)
|
| - else:
|
| - continuation = None
|
| - encoded_search = unicode(base64.urlsafe_b64encode(
|
| - protobuf.encode_message(request)))
|
| -
|
| - name_prefix = request.name_prefix
|
| -
|
| - query = info_class.search(name_prefix)
|
| - query.order('name')
|
| - if customize_query:
|
| - customize_query(request, query)
|
| -
|
| - if continuation:
|
| - # TODO(rafek): Pure query cursors are not safe for model with
|
| - # query restrictions. Would technically need to be encrypted.
|
| - query.with_cursor(continuation)
|
| -
|
| - fetch_size = request.fetch_size
|
| -
|
| - model_instance = query.fetch(fetch_size)
|
| - results = None
|
| - continuation = None
|
| - if model_instance:
|
| - results = [model_to_message(i) for i in model_instance]
|
| - if len(model_instance) == fetch_size:
|
| - cursor = query.cursor()
|
| - continuation = u'%s:%s' % (encoded_search, query.cursor())
|
| -
|
| - return results, continuation
|
| -
|
| -
|
| - @remote.method(AddArtistRequest, AddArtistResponse)
|
| - def add_artist(self, request):
|
| - """Add artist to library."""
|
| - artist_name = request.name
|
| - def do_add():
|
| - artist = model.ArtistInfo(name=artist_name)
|
| - artist.put()
|
| - return artist
|
| - artist = db.run_in_transaction(do_add)
|
| -
|
| - return AddArtistResponse(artist_id = unicode(artist.key()))
|
| -
|
| - @remote.method(UpdateArtistRequest, UpdateArtistResponse)
|
| - def update_artist(self, request):
|
| - """Update artist from library."""
|
| - def do_deletion():
|
| - artist = model.ArtistInfo.get(request.artist.artist_id)
|
| - if artist:
|
| - artist.name = request.artist.name
|
| - artist.put()
|
| - return True
|
| - else:
|
| - return False
|
| - return UpdateArtistResponse(
|
| - artist_updated=db.run_in_transaction(do_deletion))
|
| -
|
| - @remote.method(DeleteArtistRequest, DeleteArtistResponse)
|
| - def delete_artist(self, request):
|
| - """Delete artist from library."""
|
| - def do_deletion():
|
| - artist = model.ArtistInfo.get(request.artist_id)
|
| - if artist:
|
| - db.delete(model.Info.all(keys_only=True).ancestor(artist))
|
| - return True
|
| - else:
|
| - return False
|
| - return DeleteArtistResponse(
|
| - artist_deleted = db.run_in_transaction(do_deletion))
|
| -
|
| - @remote.method(FetchArtistRequest, FetchArtistResponse)
|
| - def fetch_artist(self, request):
|
| - """Fetch artist from library."""
|
| - artist_model = model.ArtistInfo.get(request.artist_id)
|
| - if isinstance(artist_model, model.ArtistInfo):
|
| - artist = self.__artist_from_model(artist_model)
|
| - else:
|
| - artist = None
|
| - return FetchArtistResponse(artist=artist)
|
| -
|
| -
|
| - @remote.method(SearchArtistsRequest, SearchArtistsResponse)
|
| - def search_artists(self, request):
|
| - """Search library for artists."""
|
| - results, continuation = self.__search_info(request,
|
| - model.ArtistInfo,
|
| - self.__artist_from_model)
|
| - return SearchArtistsResponse(artists=results or [],
|
| - continuation=continuation or None)
|
| -
|
| - @remote.method(AddAlbumRequest, AddAlbumResponse)
|
| - def add_album(self, request):
|
| - """Add album to library."""
|
| - def create_album():
|
| - if not request.artist_id:
|
| - raise ValueError('Request does not have artist-id.')
|
| - artist = model.ArtistInfo.get(request.artist_id)
|
| - if not artist:
|
| - raise ValueError('No artist found for %s.' % request.artist_id)
|
| - artist.album_count += 1
|
| - artist.put()
|
| -
|
| - album = model.AlbumInfo(name=request.name,
|
| - released=request.released,
|
| - artist=artist,
|
| - parent=artist)
|
| - album.put()
|
| -
|
| - return album
|
| - album = db.run_in_transaction(create_album)
|
| -
|
| - return AddAlbumResponse(album_id=unicode(album.key()))
|
| -
|
| - @remote.method(UpdateAlbumRequest, UpdateAlbumResponse)
|
| - def update_album(self, request):
|
| - """Update album from library."""
|
| - def do_deletion():
|
| - album = model.AlbumInfo.get(request.album.album_id)
|
| - if album:
|
| - album.name = request.album.name
|
| - album.released = request.album.released
|
| - album.put()
|
| - return True
|
| - else:
|
| - return False
|
| - return UpdateAlbumResponse(album_updated=db.run_in_transaction(do_deletion))
|
| -
|
| - @remote.method(DeleteAlbumRequest, DeleteAlbumResponse)
|
| - def delete_album(self, request):
|
| - """Delete album from library."""
|
| - def do_deletion():
|
| - album = model.AlbumInfo.get(request.album_id)
|
| -
|
| - artist = album.artist
|
| - artist.album_count -= 1
|
| - artist.put()
|
| -
|
| - if album:
|
| - db.delete(model.Info.all(keys_only=True).ancestor(album))
|
| - return True
|
| - else:
|
| - return False
|
| -
|
| - return DeleteAlbumResponse(album_deleted=db.run_in_transaction(do_deletion))
|
| -
|
| - @remote.method(FetchAlbumRequest, FetchAlbumResponse)
|
| - def fetch_album(self, request):
|
| - """Fetch album from library."""
|
| - album_model = model.AlbumInfo.get(request.album_id)
|
| - if isinstance(album_model, model.AlbumInfo):
|
| - album = self.__album_from_model(album_model)
|
| - else:
|
| - album = None
|
| - return FetchAlbumResponse(album=album)
|
| -
|
| - @remote.method(SearchAlbumsRequest, SearchAlbumsResponse)
|
| - def search_albums(self, request):
|
| - """Search library for albums."""
|
| - def customize_query(request, query):
|
| - if request.artist_id:
|
| - query.filter('artist', db.Key(request.artist_id))
|
| -
|
| - response = SearchAlbumsResponse()
|
| - results, continuation = self.__search_info(request,
|
| - model.AlbumInfo,
|
| - self.__album_from_model,
|
| - customize_query)
|
| - return SearchAlbumsResponse(albums=results or [],
|
| - continuation=continuation or None)
|
|
|