def testMedia2(self): # Create media & metadata ms = gdata.MediaSource() ms.setFile(test_image_location, 'image/jpeg') new_media_entry = gdata.GDataEntry() new_media_entry.title = atom.Title(text='testimage1.jpg') new_media_entry.summary = atom.Summary(text='Test Image') new_media_entry.category.append( atom.Category(scheme='http://schemas.google.com/g/2005#kind', term='http://schemas.google.com/photos/2007#photo')) media_entry = self.gd_client.Post(new_media_entry, self.album_entry.GetFeedLink().href, media_source=ms) self.assertTrue(media_entry is not None) self.assertTrue(isinstance(media_entry, gdata.GDataEntry)) self.assertTrue(media_entry.IsMedia()) self.assertTrue(media_entry.summary.text == 'Test Image') # Update media only ms = gdata.MediaSource() ms.setFile(test_image_location, 'image/jpeg') media_entry = self.gd_client.Put(None, media_entry.GetEditMediaLink().href, media_source=ms) self.assertTrue(media_entry is not None) self.assertTrue(isinstance(media_entry, gdata.GDataEntry)) self.assertTrue(media_entry.IsMedia()) # Delete entry response = self.gd_client.Delete(media_entry.GetEditLink().href) self.assertTrue(response)
def testMedia1(self): # Create media-only ms = gdata.MediaSource() ms.setFile(test_image_location, 'image/jpeg') media_entry = self.gd_client.Post(None, self.album_entry.GetFeedLink().href, media_source=ms) self.assertTrue(media_entry is not None) self.assertTrue(isinstance(media_entry, gdata.GDataEntry)) self.assertTrue(media_entry.IsMedia()) # Update media & metadata ms = gdata.MediaSource() ms.setFile(test_image_location, 'image/jpeg') media_entry.summary = atom.Summary(text='Test Image') media_entry2 = self.gd_client.Put(media_entry, media_entry.GetEditLink().href, media_source=ms) self.assertTrue(media_entry2 is not None) self.assertTrue(isinstance(media_entry2, gdata.GDataEntry)) self.assertTrue(media_entry2.IsMedia()) self.assertTrue(media_entry2.summary.text == 'Test Image') # Read media binary imageSource = self.gd_client.GetMedia(media_entry2.GetMediaURL()) self.assertTrue(isinstance(imageSource, gdata.MediaSource)) self.assertTrue(imageSource.content_type == 'image/jpeg') self.assertTrue(imageSource.content_length) imageData = imageSource.file_handle.read() self.assertTrue(imageData) # Delete entry response = self.gd_client.Delete(media_entry2.GetEditLink().href) self.assertTrue(response)
def InsertVideo(self, album_or_uri, video, filename_or_handle, content_type='image/jpeg'): """Copy of InsertPhoto which removes protections since it *should* work""" try: assert(isinstance(video, VideoEntry)) except AssertionError: raise GooglePhotosException({'status':GPHOTOS_INVALID_ARGUMENT, 'body':'`video` must be a gdata.photos.VideoEntry instance', 'reason':'Found %s, not PhotoEntry' % type(video) }) try: majtype, mintype = content_type.split('/') #assert(mintype in SUPPORTED_UPLOAD_TYPES) except (ValueError, AssertionError): raise GooglePhotosException({'status':GPHOTOS_INVALID_CONTENT_TYPE, 'body':'This is not a valid content type: %s' % content_type, 'reason':'Accepted content types:' }) if isinstance(filename_or_handle, (str, unicode)) and \ os.path.exists(filename_or_handle): # it's a file name mediasource = gdata.MediaSource() mediasource.setFile(filename_or_handle, content_type) elif hasattr(filename_or_handle, 'read'):# it's a file-like resource if hasattr(filename_or_handle, 'seek'): filename_or_handle.seek(0) # rewind pointer to the start of the file # gdata.MediaSource needs the content length, so read the whole image file_handle = StringIO.StringIO(filename_or_handle.read()) name = 'image' if hasattr(filename_or_handle, 'name'): name = filename_or_handle.name mediasource = gdata.MediaSource(file_handle, content_type, content_length=file_handle.len, file_name=name) else: #filename_or_handle is not valid raise GooglePhotosException({'status':GPHOTOS_INVALID_ARGUMENT, 'body':'`filename_or_handle` must be a path name or a file-like object', 'reason':'Found %s, not path name or object with a .read() method' % \ type(filename_or_handle) }) if isinstance(album_or_uri, (str, unicode)): # it's a uri feed_uri = album_or_uri elif hasattr(album_or_uri, 'GetFeedLink'): # it's a AlbumFeed object feed_uri = album_or_uri.GetFeedLink().href try: return self.Post(video, uri=feed_uri, media_source=mediasource, converter=None) except gdata.service.RequestError as e: raise GooglePhotosException(e.args[0])
def _save_keyring(self, keyring_dict): """Helper to actually write the keyring to Google""" import gdata result = self.OK file_contents = base64.urlsafe_b64encode(pickle.dumps(keyring_dict)) try: if self.docs_entry: extra_headers = {'Content-Type': 'text/plain', 'Content-Length': len(file_contents)} self.docs_entry = self.client.Put( file_contents, self.docs_entry.GetEditMediaLink().href, extra_headers=extra_headers ) else: from gdata.docs.service import DocumentQuery # check for existence of folder, create if required folder_query = DocumentQuery(categories=['folder']) folder_query['title'] = self.collection folder_query['title-exact'] = 'true' docs = self.client.QueryDocumentListFeed(folder_query.ToUri()) if docs.entry: folder_entry = docs.entry[0] else: folder_entry = self.client.CreateFolder(self.collection) file_handle = io.BytesIO(file_contents) media_source = gdata.MediaSource( file_handle=file_handle, content_type='text/plain', content_length=len(file_contents), file_name='temp') self.docs_entry = self.client.Upload( media_source, self._get_doc_title(), folder_or_uri=folder_entry ) except gdata.service.RequestError as ex: try: if ex.message['reason'].lower().find('conflict') != -1: result = self.CONFLICT else: # Google docs has a bug when updating a shared document # using PUT from any account other that the owner. # It returns an error 400 "Sorry, there was an error saving # the file. Please try again" # *despite* actually updating the document! # Workaround by re-reading to see if it actually updated msg = 'Sorry, there was an error saving the file' if ex.message['body'].find(msg) != -1: new_docs_entry, new_keyring_dict = self._read() if new_keyring_dict == keyring_dict: result = self.OK else: result = self.FAIL else: result = self.FAIL except Exception: result = self.FAIL return result
def write_gdata(self, name, username, password, auth_token=None): try: import gdata import gdata.docs.service except ImportError: raise Exception( "Must install package 'gdata' to use write_gdata()") tmp_file, tmp_file_path = tempfile.mkstemp() self.write(tmp_file_path) gd_client = gdata.docs.service.DocsService() gd_client.ssl = True if not auth_token: gd_client.ClientLogin(username, password, "marmir-1.0") else: #TODO: use the token raise Exception("oauth not yet supported") ms = gdata.MediaSource(file_path=tmp_file_path, content_type='application/vnd.ms-excel') entry = gd_client.Upload(ms, name) # NOQA #cleanup os.unlink(tmp_file_path) return gd_client.GetClientLoginToken()
def testMediaConstructorDefaults(self): ms = gdata.MediaSource() ms.setFile(test_image_location, 'image/jpeg') self.assertTrue(ms is not None) self.assertTrue(isinstance(ms, gdata.MediaSource)) self.assertEqual(ms.file_name, test_image_name) self.assertEqual(ms.content_type, 'image/jpeg')
def testMediaConstructorWithFilePath(self): ms = gdata.MediaSource(file_path=test_image_location, content_type='image/jpeg') self.assertTrue(ms is not None) self.assertTrue(isinstance(ms, gdata.MediaSource)) self.assertEqual(ms.file_name, test_image_name) self.assertEqual(ms.content_type, 'image/jpeg')
def GetMedia(self, uri, extra_headers=None): """Returns a MediaSource containing media and its metadata from the given URI string. """ connection = atom.service.AtomService._CreateConnection(self, uri, 'GET', extra_headers) response_handle = connection.getresponse() return gdata.MediaSource(response_handle, response_handle.getheader('Content-Type'), response_handle.getheader('Content-Length'))
def ChangePhoto(self, media, contact_entry_or_url, content_type=None, content_length=None): """Change the photo for the contact by uploading a new photo. Performs a PUT against the photo edit URL to send the binary data for the photo. Args: media: filename, file-like-object, or a gdata.MediaSource object to send. contact_entry_or_url: ContactEntry or str If it is a ContactEntry, this method will search for an edit photo link URL and perform a PUT to the URL. content_type: str (optional) the mime type for the photo data. This is necessary if media is a file or file name, but if media is a MediaSource object then the media object can contain the mime type. If media_type is set, it will override the mime type in the media object. content_length: int or str (optional) Specifying the content length is only required if media is a file-like object. If media is a filename, the length is determined using os.path.getsize. If media is a MediaSource object, it is assumed that it already contains the content length. """ if isinstance(contact_entry_or_url, gdata.contacts.ContactEntry): url = contact_entry_or_url.GetPhotoEditLink().href else: url = contact_entry_or_url if isinstance(media, gdata.MediaSource): payload = media # If the media object is a file-like object, then use it as the file # handle in the in the MediaSource. elif hasattr(media, 'read'): payload = gdata.MediaSource(file_handle=media, content_type=content_type, content_length=content_length) # Assume that the media object is a file name. else: payload = gdata.MediaSource(content_type=content_type, content_length=content_length, file_path=media) return self.Put(payload, url)
def testMediaConstructorWithFileHandle(self): fh = open(test_image_location, 'r') len = os.path.getsize(test_image_location) ms = gdata.MediaSource(fh, 'image/jpeg', len, file_name=test_image_location) self.assert_(ms is not None) self.assert_(isinstance(ms, gdata.MediaSource)) self.assertEquals(ms.file_name, test_image_location) self.assertEquals(ms.content_type, 'image/jpeg')
def GetMedia(self, uri, extra_headers=None): """Returns a MediaSource containing media and its metadata from the given URI string. """ response_handle = self.handler.HttpRequest(self, 'GET', None, uri, extra_headers=extra_headers) return gdata.MediaSource(response_handle, response_handle.getheader('Content-Type'), response_handle.getheader('Content-Length'))
def save_gdata(self): print "logging in" self.client.ProgrammaticLogin() self.feed = self.client.Query(self.q.ToUri()) print "fetched feed!" self.entry = self.feed.entry[0] ms = gdata.MediaSource( file_path=self.file, content_type=gdata.docs.service.SUPPORTED_FILETYPES['TXT']) self.entry.title.text = self.name updated_entry = self.client.Put(ms, self.entry.GetEditMediaLink().href) print "Numbers Updated!"
def CreateDatabase(self, name): """Creates a new Google Spreadsheet with the desired name. Args: name: str The title for the spreadsheet. Returns: A Database instance representing the new spreadsheet. """ # Create a Google Spreadsheet to form the foundation of this database. # Spreadsheet is created by uploading a file to the Google Documents # List API. virtual_csv_file = StringIO.StringIO(',,,') virtual_media_source = gdata.MediaSource(file_handle=virtual_csv_file, content_type='text/csv', content_length=3) db_entry = self.__docs_client.UploadSpreadsheet(virtual_media_source, name) return Database(spreadsheet_entry=db_entry, database_client=self)
def upload_result(file_name, title, username, password): message = 'ok' try: gd_client = gdata.docs.service.DocsService( source='yourCo-yourAppName-v1') gd_client.ClientLogin(username, password) except: return "Wrong email or password!", "" try: ms = gdata.MediaSource( file_path=FILE_GENERATE_PATH + '/' + file_name, content_type=gdata.docs.service.SUPPORTED_FILETYPES['XLS']) entry = gd_client.Upload(ms, 'Report result of ' + title) output_link = entry.GetAlternateLink().href except: return "Invalid file!", "" return message, output_link
def uploadPhoto(self, file, description=""): ms = gdata.MediaSource() try: ms.setFile(file, 'image/jpeg') metadata_entry = gdata.GDataEntry() name = os.path.basename(file) metadata_entry.title = atom.Title(text=name) metadata_entry.summary = atom.Summary(text=description) metadata_entry.category.append( atom.Category( scheme='http://schemas.google.com/g/2005#kind', term='http://schemas.google.com/photos/2007#photo')) link = self.__ae.link[ 0].href # self.__ae.GetFeedLink().href on created album media_entry = self.__gd.Post(metadata_entry, link, media_source=ms) return True except gdata.service.RequestError: return False
def UpdatePhotoBlob(self, photo_or_uri, filename_or_handle, content_type='image/jpeg'): """Update a photo's binary data. Needs authentication, see self.ClientLogin() Arguments: photo_or_uri: a gdata.photos.PhotoEntry that will be updated, or a `edit-media' uri pointing to it filename_or_handle: A file-like object or file name where the image/video will be read from content_type (optional): Internet media type (a.k.a. mime type) of media object. Currently Google Photos supports these types: o image/bmp o image/gif o image/jpeg o image/png Images will be converted to jpeg on upload. Defaults to `image/jpeg' Returns: The modified gdata.photos.PhotoEntry Example: p = GetFeed(PhotoUri) p = UpdatePhotoBlob(p, '/tmp/newPic.jpg') It is important that you don't keep the old object around, once it has been updated. See http://code.google.com/apis/gdata/reference.html#Optimistic-concurrency """ try: majtype, mintype = content_type.split('/') assert (mintype in SUPPORTED_UPLOAD_TYPES) except (ValueError, AssertionError): raise GooglePhotosException({'status':GPHOTOS_INVALID_CONTENT_TYPE, 'body':'This is not a valid content type: %s' % content_type, 'reason':'Accepted content types: %s' % \ ['image/'+t for t in SUPPORTED_UPLOAD_TYPES] }) if isinstance(filename_or_handle, (str, unicode)) and \ os.path.exists(filename_or_handle): # it's a file name photoblob = gdata.MediaSource() photoblob.setFile(filename_or_handle, content_type) elif hasattr(filename_or_handle, 'read'): # it's a file-like resource if hasattr(filename_or_handle, 'seek'): filename_or_handle.seek( 0) # rewind pointer to the start of the file # gdata.MediaSource needs the content length, so read the whole image file_handle = StringIO.StringIO(filename_or_handle.read()) name = 'image' if hasattr(filename_or_handle, 'name'): name = filename_or_handle.name mediasource = gdata.MediaSource(file_handle, content_type, content_length=file_handle.len, file_name=name) else: #filename_or_handle is not valid raise GooglePhotosException({'status':GPHOTOS_INVALID_ARGUMENT, 'body':'`filename_or_handle` must be a path name or a file-like object', 'reason':'Found %s, not path name or an object with .read() method' % \ type(filename_or_handle) }) if isinstance(photo_or_uri, (str, unicode)): entry_uri = photo_or_uri # it's a uri elif hasattr(photo_or_uri, 'GetEditMediaLink'): entry_uri = photo_or_uri.GetEditMediaLink().href try: return self.Put(photoblob, entry_uri, converter=gdata.photos.PhotoEntryFromString) except gdata.service.RequestError, e: raise GooglePhotosException(e.args[0])
def InsertPhoto(self, album_or_uri, photo, filename_or_handle, content_type='image/jpeg'): """Add a PhotoEntry Needs authentication, see self.ClientLogin() Arguments: album_or_uri: AlbumFeed or uri of the album where the photo should go photo: PhotoEntry to add filename_or_handle: A file-like object or file name where the image/video will be read from content_type (optional): Internet media type (a.k.a. mime type) of media object. Currently Google Photos supports these types: o image/bmp o image/gif o image/jpeg o image/png Images will be converted to jpeg on upload. Defaults to `image/jpeg' """ try: assert (isinstance(photo, gdata.photos.PhotoEntry)) except AssertionError: raise GooglePhotosException({ 'status': GPHOTOS_INVALID_ARGUMENT, 'body': '`photo` must be a gdata.photos.PhotoEntry instance', 'reason': 'Found %s, not PhotoEntry' % type(photo) }) try: majtype, mintype = content_type.split('/') assert (mintype in SUPPORTED_UPLOAD_TYPES) except (ValueError, AssertionError): raise GooglePhotosException({'status':GPHOTOS_INVALID_CONTENT_TYPE, 'body':'This is not a valid content type: %s' % content_type, 'reason':'Accepted content types: %s' % \ ['image/'+t for t in SUPPORTED_UPLOAD_TYPES] }) if isinstance(filename_or_handle, (str, unicode)) and \ os.path.exists(filename_or_handle): # it's a file name mediasource = gdata.MediaSource() mediasource.setFile(filename_or_handle, content_type) elif hasattr(filename_or_handle, 'read'): # it's a file-like resource if hasattr(filename_or_handle, 'seek'): filename_or_handle.seek( 0) # rewind pointer to the start of the file # gdata.MediaSource needs the content length, so read the whole image file_handle = StringIO.StringIO(filename_or_handle.read()) name = 'image' if hasattr(filename_or_handle, 'name'): name = filename_or_handle.name mediasource = gdata.MediaSource(file_handle, content_type, content_length=file_handle.len, file_name=name) else: #filename_or_handle is not valid raise GooglePhotosException({'status':GPHOTOS_INVALID_ARGUMENT, 'body':'`filename_or_handle` must be a path name or a file-like object', 'reason':'Found %s, not path name or object with a .read() method' % \ type(filename_or_handle) }) if isinstance(album_or_uri, (str, unicode)): # it's a uri feed_uri = album_or_uri elif hasattr(album_or_uri, 'GetFeedLink'): # it's a AlbumFeed object feed_uri = album_or_uri.GetFeedLink().href try: return self.Post(photo, uri=feed_uri, media_source=mediasource, converter=gdata.photos.PhotoEntryFromString) except gdata.service.RequestError, e: raise GooglePhotosException(e.args[0])