356 lines
12 KiB
Python
356 lines
12 KiB
Python
|
# -*-*- encoding: utf-8 -*-*-
|
||
|
#
|
||
|
# This is gdata.photos.media, implementing parts of the MediaRSS spec in gdata structures
|
||
|
#
|
||
|
# $Id: __init__.py 81 2007-10-03 14:41:42Z havard.gulldahl $
|
||
|
#
|
||
|
# Copyright 2007 Håvard Gulldahl
|
||
|
# Portions copyright 2007 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.
|
||
|
|
||
|
|
||
|
"""Essential attributes of photos in Google Photos/Picasa Web Albums are
|
||
|
expressed using elements from the `media' namespace, defined in the
|
||
|
MediaRSS specification[1].
|
||
|
|
||
|
Due to copyright issues, the elements herein are documented sparingly, please
|
||
|
consult with the Google Photos API Reference Guide[2], alternatively the
|
||
|
official MediaRSS specification[1] for details.
|
||
|
(If there is a version conflict between the two sources, stick to the
|
||
|
Google Photos API).
|
||
|
|
||
|
[1]: http://search.yahoo.com/mrss (version 1.1.1)
|
||
|
[2]: http://code.google.com/apis/picasaweb/reference.html#media_reference
|
||
|
|
||
|
Keep in mind that Google Photos only uses a subset of the MediaRSS elements
|
||
|
(and some of the attributes are trimmed down, too):
|
||
|
|
||
|
media:content
|
||
|
media:credit
|
||
|
media:description
|
||
|
media:group
|
||
|
media:keywords
|
||
|
media:thumbnail
|
||
|
media:title
|
||
|
"""
|
||
|
|
||
|
__author__ = u'havard@gulldahl.no'# (Håvard Gulldahl)' #BUG: api chokes on non-ascii chars in __author__
|
||
|
__license__ = 'Apache License v2'
|
||
|
|
||
|
|
||
|
import atom
|
||
|
import gdata
|
||
|
|
||
|
MEDIA_NAMESPACE = 'http://search.yahoo.com/mrss/'
|
||
|
YOUTUBE_NAMESPACE = 'http://gdata.youtube.com/schemas/2007'
|
||
|
|
||
|
|
||
|
class MediaBaseElement(atom.AtomBase):
|
||
|
"""Base class for elements in the MEDIA_NAMESPACE.
|
||
|
To add new elements, you only need to add the element tag name to self._tag
|
||
|
"""
|
||
|
|
||
|
_tag = ''
|
||
|
_namespace = MEDIA_NAMESPACE
|
||
|
_children = atom.AtomBase._children.copy()
|
||
|
_attributes = atom.AtomBase._attributes.copy()
|
||
|
|
||
|
def __init__(self, name=None, extension_elements=None,
|
||
|
extension_attributes=None, text=None):
|
||
|
self.name = name
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
class Content(MediaBaseElement):
|
||
|
"""(attribute container) This element describes the original content,
|
||
|
e.g. an image or a video. There may be multiple Content elements
|
||
|
in a media:Group.
|
||
|
|
||
|
For example, a video may have a
|
||
|
<media:content medium="image"> element that specifies a JPEG
|
||
|
representation of the video, and a <media:content medium="video">
|
||
|
element that specifies the URL of the video itself.
|
||
|
|
||
|
Attributes:
|
||
|
url: non-ambigous reference to online object
|
||
|
width: width of the object frame, in pixels
|
||
|
height: width of the object frame, in pixels
|
||
|
medium: one of `image' or `video', allowing the api user to quickly
|
||
|
determine the object's type
|
||
|
type: Internet media Type[1] (a.k.a. mime type) of the object -- a more
|
||
|
verbose way of determining the media type. To set the type member
|
||
|
in the contructor, use the content_type parameter.
|
||
|
(optional) fileSize: the size of the object, in bytes
|
||
|
|
||
|
[1]: http://en.wikipedia.org/wiki/Internet_media_type
|
||
|
"""
|
||
|
|
||
|
_tag = 'content'
|
||
|
_attributes = atom.AtomBase._attributes.copy()
|
||
|
_attributes['url'] = 'url'
|
||
|
_attributes['width'] = 'width'
|
||
|
_attributes['height'] = 'height'
|
||
|
_attributes['medium'] = 'medium'
|
||
|
_attributes['type'] = 'type'
|
||
|
_attributes['fileSize'] = 'fileSize'
|
||
|
|
||
|
def __init__(self, url=None, width=None, height=None,
|
||
|
medium=None, content_type=None, fileSize=None, format=None,
|
||
|
extension_elements=None, extension_attributes=None, text=None):
|
||
|
MediaBaseElement.__init__(self, extension_elements=extension_elements,
|
||
|
extension_attributes=extension_attributes,
|
||
|
text=text)
|
||
|
self.url = url
|
||
|
self.width = width
|
||
|
self.height = height
|
||
|
self.medium = medium
|
||
|
self.type = content_type
|
||
|
self.fileSize = fileSize
|
||
|
|
||
|
|
||
|
def ContentFromString(xml_string):
|
||
|
return atom.CreateClassFromXMLString(Content, xml_string)
|
||
|
|
||
|
|
||
|
class Credit(MediaBaseElement):
|
||
|
"""(string) Contains the nickname of the user who created the content,
|
||
|
e.g. `Liz Bennet'.
|
||
|
|
||
|
This is a user-specified value that should be used when referring to
|
||
|
the user by name.
|
||
|
|
||
|
Note that none of the attributes from the MediaRSS spec are supported.
|
||
|
"""
|
||
|
|
||
|
_tag = 'credit'
|
||
|
|
||
|
|
||
|
def CreditFromString(xml_string):
|
||
|
return atom.CreateClassFromXMLString(Credit, xml_string)
|
||
|
|
||
|
|
||
|
class Description(MediaBaseElement):
|
||
|
"""(string) A description of the media object.
|
||
|
Either plain unicode text, or entity-encoded html (look at the `type'
|
||
|
attribute).
|
||
|
|
||
|
E.g `A set of photographs I took while vacationing in Italy.'
|
||
|
|
||
|
For `api' projections, the description is in plain text;
|
||
|
for `base' projections, the description is in HTML.
|
||
|
|
||
|
Attributes:
|
||
|
type: either `text' or `html'. To set the type member in the contructor,
|
||
|
use the description_type parameter.
|
||
|
"""
|
||
|
|
||
|
_tag = 'description'
|
||
|
_attributes = atom.AtomBase._attributes.copy()
|
||
|
_attributes['type'] = 'type'
|
||
|
def __init__(self, description_type=None,
|
||
|
extension_elements=None, extension_attributes=None, text=None):
|
||
|
MediaBaseElement.__init__(self, extension_elements=extension_elements,
|
||
|
extension_attributes=extension_attributes,
|
||
|
text=text)
|
||
|
|
||
|
self.type = description_type
|
||
|
|
||
|
|
||
|
def DescriptionFromString(xml_string):
|
||
|
return atom.CreateClassFromXMLString(Description, xml_string)
|
||
|
|
||
|
|
||
|
class Keywords(MediaBaseElement):
|
||
|
"""(string) Lists the tags associated with the entry,
|
||
|
e.g `italy, vacation, sunset'.
|
||
|
|
||
|
Contains a comma-separated list of tags that have been added to the photo, or
|
||
|
all tags that have been added to photos in the album.
|
||
|
"""
|
||
|
|
||
|
_tag = 'keywords'
|
||
|
|
||
|
|
||
|
def KeywordsFromString(xml_string):
|
||
|
return atom.CreateClassFromXMLString(Keywords, xml_string)
|
||
|
|
||
|
|
||
|
class Thumbnail(MediaBaseElement):
|
||
|
"""(attributes) Contains the URL of a thumbnail of a photo or album cover.
|
||
|
|
||
|
There can be multiple <media:thumbnail> elements for a given <media:group>;
|
||
|
for example, a given item may have multiple thumbnails at different sizes.
|
||
|
Photos generally have two thumbnails at different sizes;
|
||
|
albums generally have one cropped thumbnail.
|
||
|
|
||
|
If the thumbsize parameter is set to the initial query, this element points
|
||
|
to thumbnails of the requested sizes; otherwise the thumbnails are the
|
||
|
default thumbnail size.
|
||
|
|
||
|
This element must not be confused with the <gphoto:thumbnail> element.
|
||
|
|
||
|
Attributes:
|
||
|
url: The URL of the thumbnail image.
|
||
|
height: The height of the thumbnail image, in pixels.
|
||
|
width: The width of the thumbnail image, in pixels.
|
||
|
"""
|
||
|
|
||
|
_tag = 'thumbnail'
|
||
|
_attributes = atom.AtomBase._attributes.copy()
|
||
|
_attributes['url'] = 'url'
|
||
|
_attributes['width'] = 'width'
|
||
|
_attributes['height'] = 'height'
|
||
|
def __init__(self, url=None, width=None, height=None,
|
||
|
extension_attributes=None, text=None, extension_elements=None):
|
||
|
MediaBaseElement.__init__(self, extension_elements=extension_elements,
|
||
|
extension_attributes=extension_attributes,
|
||
|
text=text)
|
||
|
self.url = url
|
||
|
self.width = width
|
||
|
self.height = height
|
||
|
|
||
|
|
||
|
def ThumbnailFromString(xml_string):
|
||
|
return atom.CreateClassFromXMLString(Thumbnail, xml_string)
|
||
|
|
||
|
|
||
|
class Title(MediaBaseElement):
|
||
|
"""(string) Contains the title of the entry's media content, in plain text.
|
||
|
|
||
|
Attributes:
|
||
|
type: Always set to plain. To set the type member in the constructor, use
|
||
|
the title_type parameter.
|
||
|
"""
|
||
|
|
||
|
_tag = 'title'
|
||
|
_attributes = atom.AtomBase._attributes.copy()
|
||
|
_attributes['type'] = 'type'
|
||
|
def __init__(self, title_type=None,
|
||
|
extension_attributes=None, text=None, extension_elements=None):
|
||
|
MediaBaseElement.__init__(self, extension_elements=extension_elements,
|
||
|
extension_attributes=extension_attributes,
|
||
|
text=text)
|
||
|
self.type = title_type
|
||
|
|
||
|
|
||
|
def TitleFromString(xml_string):
|
||
|
return atom.CreateClassFromXMLString(Title, xml_string)
|
||
|
|
||
|
|
||
|
class Player(MediaBaseElement):
|
||
|
"""(string) Contains the embeddable player URL for the entry's media content
|
||
|
if the media is a video.
|
||
|
|
||
|
Attributes:
|
||
|
url: Always set to plain
|
||
|
"""
|
||
|
|
||
|
_tag = 'player'
|
||
|
_attributes = atom.AtomBase._attributes.copy()
|
||
|
_attributes['url'] = 'url'
|
||
|
|
||
|
def __init__(self, player_url=None,
|
||
|
extension_attributes=None, extension_elements=None):
|
||
|
MediaBaseElement.__init__(self, extension_elements=extension_elements,
|
||
|
extension_attributes=extension_attributes)
|
||
|
self.url= player_url
|
||
|
|
||
|
|
||
|
class Private(atom.AtomBase):
|
||
|
"""The YouTube Private element"""
|
||
|
_tag = 'private'
|
||
|
_namespace = YOUTUBE_NAMESPACE
|
||
|
|
||
|
|
||
|
class Duration(atom.AtomBase):
|
||
|
"""The YouTube Duration element"""
|
||
|
_tag = 'duration'
|
||
|
_namespace = YOUTUBE_NAMESPACE
|
||
|
_attributes = atom.AtomBase._attributes.copy()
|
||
|
_attributes['seconds'] = 'seconds'
|
||
|
|
||
|
|
||
|
class Category(MediaBaseElement):
|
||
|
"""The mediagroup:category element"""
|
||
|
|
||
|
_tag = 'category'
|
||
|
_attributes = atom.AtomBase._attributes.copy()
|
||
|
_attributes['term'] = 'term'
|
||
|
_attributes['scheme'] = 'scheme'
|
||
|
_attributes['label'] = 'label'
|
||
|
|
||
|
def __init__(self, term=None, scheme=None, label=None, text=None,
|
||
|
extension_elements=None, extension_attributes=None):
|
||
|
"""Constructor for Category
|
||
|
|
||
|
Args:
|
||
|
term: str
|
||
|
scheme: str
|
||
|
label: str
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.term = term
|
||
|
self.scheme = scheme
|
||
|
self.label = label
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
class Group(MediaBaseElement):
|
||
|
"""Container element for all media elements.
|
||
|
The <media:group> element can appear as a child of an album, photo or
|
||
|
video entry."""
|
||
|
|
||
|
_tag = 'group'
|
||
|
_children = atom.AtomBase._children.copy()
|
||
|
_children['{%s}content' % MEDIA_NAMESPACE] = ('content', [Content,])
|
||
|
_children['{%s}credit' % MEDIA_NAMESPACE] = ('credit', Credit)
|
||
|
_children['{%s}description' % MEDIA_NAMESPACE] = ('description', Description)
|
||
|
_children['{%s}keywords' % MEDIA_NAMESPACE] = ('keywords', Keywords)
|
||
|
_children['{%s}thumbnail' % MEDIA_NAMESPACE] = ('thumbnail', [Thumbnail,])
|
||
|
_children['{%s}title' % MEDIA_NAMESPACE] = ('title', Title)
|
||
|
_children['{%s}category' % MEDIA_NAMESPACE] = ('category', [Category,])
|
||
|
_children['{%s}duration' % YOUTUBE_NAMESPACE] = ('duration', Duration)
|
||
|
_children['{%s}private' % YOUTUBE_NAMESPACE] = ('private', Private)
|
||
|
_children['{%s}player' % MEDIA_NAMESPACE] = ('player', Player)
|
||
|
|
||
|
def __init__(self, content=None, credit=None, description=None, keywords=None,
|
||
|
thumbnail=None, title=None, duration=None, private=None,
|
||
|
category=None, player=None, extension_elements=None,
|
||
|
extension_attributes=None, text=None):
|
||
|
|
||
|
MediaBaseElement.__init__(self, extension_elements=extension_elements,
|
||
|
extension_attributes=extension_attributes,
|
||
|
text=text)
|
||
|
self.content=content
|
||
|
self.credit=credit
|
||
|
self.description=description
|
||
|
self.keywords=keywords
|
||
|
self.thumbnail=thumbnail or []
|
||
|
self.title=title
|
||
|
self.duration=duration
|
||
|
self.private=private
|
||
|
self.category=category or []
|
||
|
self.player=player
|
||
|
|
||
|
|
||
|
def GroupFromString(xml_string):
|
||
|
return atom.CreateClassFromXMLString(Group, xml_string)
|