diff options
Diffstat (limited to 'lib/upload/flickr.py')
-rw-r--r-- | lib/upload/flickr.py | 889 |
1 files changed, 0 insertions, 889 deletions
diff --git a/lib/upload/flickr.py b/lib/upload/flickr.py deleted file mode 100644 index a4cd224..0000000 --- a/lib/upload/flickr.py +++ /dev/null @@ -1,889 +0,0 @@ -""" - flickr.py - Copyright 2004-6 James Clarke <james@jamesclarke.info> - -THIS SOFTWARE IS SUPPLIED WITHOUT WARRANTY OF ANY KIND, AND MAY BE -COPIED, MODIFIED OR DISTRIBUTED IN ANY WAY, AS LONG AS THIS NOTICE -AND ACKNOWLEDGEMENT OF AUTHORSHIP REMAIN. - -2006-12-19 -Applied patches from Berco Beute and Wolfram Kriesing. -TODO list below is out of date! - -2005-06-10 -TOOD list: -* flickr.blogs.* -* flickr.contacts.getList -* flickr.groups.browse -* flickr.groups.getActiveList -* flickr.people.getOnlineList -* flickr.photos.getContactsPhotos -* flickr.photos.getContactsPublicPhotos -* flickr.photos.getContext -* flickr.photos.getCounts -* flickr.photos.getExif -* flickr.photos.getNotInSet -* flickr.photos.getPerms -* flickr.photos.getRecent -* flickr.photos.getUntagged -* flickr.photos.setDates -* flickr.photos.setPerms -* flickr.photos.licenses.* -* flickr.photos.notes.* -* flickr.photos.transform.* -* flickr.photosets.getContext -* flickr.photosets.orderSets -* flickr.reflection.* (not important) -* flickr.tags.getListPhoto -* flickr.urls.* -""" - -__author__ = "James Clarke <james@jamesclarke.info>" -__version__ = "$Rev$" -__date__ = "$Date$" -__copyright__ = "Copyright 2004-6 James Clarke" - -from urllib import urlencode, urlopen -from xml.dom import minidom - -HOST = 'http://flickr.com' -API = '/services/rest' - -#set these here or using flickr.API_KEY in your application -API_KEY = '' -email = None -password = None - -class FlickrError(Exception): pass - -class Photo(object): - """Represents a Flickr Photo.""" - - __readonly = ['id', 'secret', 'server', 'isfavorite', 'license', 'rotation', - 'owner', 'dateposted', 'datetaken', 'takengranularity', - 'title', 'description', 'ispublic', 'isfriend', 'isfamily', - 'cancomment', 'canaddmeta', 'comments', 'tags', 'permcomment', - 'permaddmeta'] - - #XXX: Hopefully None won't cause problems - def __init__(self, id, owner=None, dateuploaded=None, \ - title=None, description=None, ispublic=None, \ - isfriend=None, isfamily=None, cancomment=None, \ - canaddmeta=None, comments=None, tags=None, secret=None, \ - isfavorite=None, server=None, license=None, rotation=None): - """Must specify id, rest is optional.""" - self.__loaded = False - self.__cancomment = cancomment - self.__canaddmeta = canaddmeta - self.__comments = comments - self.__dateuploaded = dateuploaded - self.__description = description - self.__id = id - self.__license = license - self.__isfamily = isfamily - self.__isfavorite = isfavorite - self.__isfriend = isfriend - self.__ispublic = ispublic - self.__owner = owner - self.__rotation = rotation - self.__secret = secret - self.__server = server - self.__tags = tags - self.__title = title - - self.__dateposted = None - self.__datetaken = None - self.__takengranularity = None - self.__permcomment = None - self.__permaddmeta = None - - def __setattr__(self, key, value): - if key in self.__class__.__readonly: - raise AttributeError("The attribute %s is read-only." % key) - else: - super(Photo, self).__setattr__(key, value) - - def __getattr__(self, key): - if not self.__loaded: - self._load_properties() - if key in self.__class__.__readonly: - return super(Photo, self).__getattribute__("_%s__%s" % (self.__class__.__name__, key)) - else: - return super(Photo, self).__getattribute__(key) - - def _load_properties(self): - """Loads the properties from Flickr.""" - self.__loaded = True - - method = 'flickr.photos.getInfo' - data = _doget(method, photo_id=self.id) - - photo = data.rsp.photo - - self.__secret = photo.secret - self.__server = photo.server - self.__isfavorite = photo.isfavorite - self.__license = photo.license - self.__rotation = photo.rotation - - - - owner = photo.owner - self.__owner = User(owner.nsid, username=owner.username,\ - realname=owner.realname,\ - location=owner.location) - - self.__title = photo.title.text - self.__description = photo.description.text - self.__ispublic = photo.visibility.ispublic - self.__isfriend = photo.visibility.isfriend - self.__isfamily = photo.visibility.isfamily - - self.__dateposted = photo.dates.posted - self.__datetaken = photo.dates.taken - self.__takengranularity = photo.dates.takengranularity - - self.__cancomment = photo.editability.cancomment - self.__canaddmeta = photo.editability.canaddmeta - self.__comments = photo.comments.text - - try: - self.__permcomment = photo.permissions.permcomment - self.__permaddmeta = photo.permissions.permaddmeta - except AttributeError: - self.__permcomment = None - self.__permaddmeta = None - - #TODO: Implement Notes? - if hasattr(photo.tags, "tag"): - if isinstance(photo.tags.tag, list): - self.__tags = [Tag(tag.id, User(tag.author), tag.raw, tag.text) \ - for tag in photo.tags.tag] - else: - tag = photo.tags.tag - self.__tags = [Tag(tag.id, User(tag.author), tag.raw, tag.text)] - - - def __str__(self): - return '<Flickr Photo %s>' % self.id - - - def setTags(self, tags): - """Set the tags for current photo to list tags. - (flickr.photos.settags) - """ - method = 'flickr.photos.setTags' - tags = uniq(tags) - _dopost(method, auth=True, photo_id=self.id, tags=tags) - self._load_properties() - - - def addTags(self, tags): - """Adds the list of tags to current tags. (flickr.photos.addtags) - """ - method = 'flickr.photos.addTags' - if isinstance(tags, list): - tags = uniq(tags) - - _dopost(method, auth=True, photo_id=self.id, tags=tags) - #load properties again - self._load_properties() - - def removeTag(self, tag): - """Remove the tag from the photo must be a Tag object. - (flickr.photos.removeTag) - """ - method = 'flickr.photos.removeTag' - tag_id = '' - try: - tag_id = tag.id - except AttributeError: - raise FlickrError, "Tag object expected" - _dopost(method, auth=True, photo_id=self.id, tag_id=tag_id) - self._load_properties() - - - def setMeta(self, title=None, description=None): - """Set metadata for photo. (flickr.photos.setMeta)""" - method = 'flickr.photos.setMeta' - - if title is None: - title = self.title - if description is None: - description = self.description - - _dopost(method, auth=True, title=title, \ - description=description, photo_id=self.id) - - self.__title = title - self.__description = description - - - def getURL(self, size='Medium', urlType='url'): - """Retrieves a url for the photo. (flickr.photos.getSizes) - - urlType - 'url' or 'source' - 'url' - flickr page of photo - 'source' - image file - """ - method = 'flickr.photos.getSizes' - data = _doget(method, photo_id=self.id) - for psize in data.rsp.sizes.size: - if psize.label == size: - return getattr(psize, urlType) - raise FlickrError, "No URL found" - - def getSizes(self): - """ - Get all the available sizes of the current image, and all available - data about them. - Returns: A list of dicts with the size data. - """ - method = 'flickr.photos.getSizes' - data = _doget(method, photo_id=self.id) - ret = [] - # The given props are those that we return and the according types, since - # return width and height as string would make "75">"100" be True, which - # is just error prone. - props = {'url':str,'width':int,'height':int,'label':str,'source':str,'text':str} - for psize in data.rsp.sizes.size: - d = {} - for prop,convert_to_type in props.items(): - d[prop] = convert_to_type(getattr(psize, prop)) - ret.append(d) - return ret - - #def getExif(self): - #method = 'flickr.photos.getExif' - #data = _doget(method, photo_id=self.id) - #ret = [] - #for exif in data.rsp.photo.exif: - #print exif.label, dir(exif) - ##ret.append({exif.label:exif.}) - #return ret - ##raise FlickrError, "No URL found" - - def getLocation(self): - """ - Return the latitude+longitutde of the picture. - Returns None if no location given for this pic. - """ - method = 'flickr.photos.geo.getLocation' - try: - data = _doget(method, photo_id=self.id) - except FlickrError: # Some other error might have occured too!? - return None - loc = data.rsp.photo.location - return [loc.latitude, loc.longitude] - - -class Photoset(object): - """A Flickr photoset.""" - - def __init__(self, id, title, primary, photos=0, description='', \ - secret='', server=''): - self.__id = id - self.__title = title - self.__primary = primary - self.__description = description - self.__count = photos - self.__secret = secret - self.__server = server - - id = property(lambda self: self.__id) - title = property(lambda self: self.__title) - description = property(lambda self: self.__description) - primary = property(lambda self: self.__primary) - - def __len__(self): - return self.__count - - def __str__(self): - return '<Flickr Photoset %s>' % self.id - - def getPhotos(self): - """Returns list of Photos.""" - method = 'flickr.photosets.getPhotos' - data = _doget(method, photoset_id=self.id) - photos = data.rsp.photoset.photo - p = [] - for photo in photos: - p.append(Photo(photo.id, title=photo.title, secret=photo.secret, \ - server=photo.server)) - return p - - def editPhotos(self, photos, primary=None): - """Edit the photos in this set. - - photos - photos for set - primary - primary photo (if None will used current) - """ - method = 'flickr.photosets.editPhotos' - - if primary is None: - primary = self.primary - - ids = [photo.id for photo in photos] - if primary.id not in ids: - ids.append(primary.id) - - _dopost(method, auth=True, photoset_id=self.id,\ - primary_photo_id=primary.id, - photo_ids=ids) - self.__count = len(ids) - return True - - def addPhoto(self, photo): - """Add a photo to this set. - - photo - the photo - """ - method = 'flickr.photosets.addPhoto' - - _dopost(method, auth=True, photoset_id=self.id, photo_id=photo.id) - - self.__count += 1 - return True - - def removePhoto(self, photo): - """Remove the photo from this set. - - photo - the photo - """ - method = 'flickr.photosets.removePhoto' - - _dopost(method, auth=True, photoset_id=self.id, photo_id=photo.id) - self.__count = self.__count - 1 - return True - - def editMeta(self, title=None, description=None): - """Set metadata for photo. (flickr.photos.setMeta)""" - method = 'flickr.photosets.editMeta' - - if title is None: - title = self.title - if description is None: - description = self.description - - _dopost(method, auth=True, title=title, \ - description=description, photoset_id=self.id) - - self.__title = title - self.__description = description - return True - - #XXX: Delete isn't handled well as the python object will still exist - def delete(self): - """Deletes the photoset. - """ - method = 'flickr.photosets.delete' - - _dopost(method, auth=True, photoset_id=self.id) - return True - - def create(cls, photo, title, description=''): - """Create a new photoset. - - photo - primary photo - """ - if not isinstance(photo, Photo): - raise TypeError, "Photo expected" - - method = 'flickr.photosets.create' - data = _dopost(method, auth=True, title=title,\ - description=description,\ - primary_photo_id=photo.id) - - set = Photoset(data.rsp.photoset.id, title, Photo(photo.id), - photos=1, description=description) - return set - create = classmethod(create) - - -class User(object): - """A Flickr user.""" - - def __init__(self, id, username=None, isadmin=None, ispro=None, \ - realname=None, location=None, firstdate=None, count=None): - """id required, rest optional.""" - self.__loaded = False #so we don't keep loading data - self.__id = id - self.__username = username - self.__isadmin = isadmin - self.__ispro = ispro - self.__realname = realname - self.__location = location - self.__photos_firstdate = firstdate - self.__photos_count = count - - #property fu - id = property(lambda self: self._general_getattr('id')) - username = property(lambda self: self._general_getattr('username')) - isadmin = property(lambda self: self._general_getattr('isadmin')) - ispro = property(lambda self: self._general_getattr('ispro')) - realname = property(lambda self: self._general_getattr('realname')) - location = property(lambda self: self._general_getattr('location')) - photos_firstdate = property(lambda self: \ - self._general_getattr('photos_firstdate')) - photos_firstdatetaken = property(lambda self: \ - self._general_getattr\ - ('photos_firstdatetaken')) - photos_count = property(lambda self: \ - self._general_getattr('photos_count')) - icon_server= property(lambda self: self._general_getattr('icon_server')) - icon_url= property(lambda self: self._general_getattr('icon_url')) - - def _general_getattr(self, var): - """Generic get attribute function.""" - if getattr(self, "_%s__%s" % (self.__class__.__name__, var)) is None \ - and not self.__loaded: - self._load_properties() - return getattr(self, "_%s__%s" % (self.__class__.__name__, var)) - - def _load_properties(self): - """Load User properties from Flickr.""" - method = 'flickr.people.getInfo' - data = _doget(method, user_id=self.__id) - - self.__loaded = True - - person = data.rsp.person - - self.__isadmin = person.isadmin - self.__ispro = person.ispro - self.__icon_server = person.iconserver - if int(person.iconserver) > 0: - self.__icon_url = 'http://photos%s.flickr.com/buddyicons/%s.jpg' \ - % (person.iconserver, self.__id) - else: - self.__icon_url = 'http://www.flickr.com/images/buddyicon.jpg' - - self.__username = person.username.text - self.__realname = person.realname.text - self.__location = person.location.text - self.__photos_firstdate = person.photos.firstdate.text - self.__photos_firstdatetaken = person.photos.firstdatetaken.text - self.__photos_count = person.photos.count.text - - def __str__(self): - return '<Flickr User %s>' % self.id - - def getPhotosets(self): - """Returns a list of Photosets.""" - method = 'flickr.photosets.getList' - data = _doget(method, user_id=self.id) - sets = [] - if isinstance(data.rsp.photosets.photoset, list): - for photoset in data.rsp.photosets.photoset: - sets.append(Photoset(photoset.id, photoset.title.text,\ - Photo(photoset.primary),\ - secret=photoset.secret, \ - server=photoset.server, \ - description=photoset.description.text, - photos=photoset.photos)) - else: - photoset = data.rsp.photosets.photoset - sets.append(Photoset(photoset.id, photoset.title.text,\ - Photo(photoset.primary),\ - secret=photoset.secret, \ - server=photoset.server, \ - description=photoset.description.text, - photos=photoset.photos)) - return sets - - def getPublicFavorites(self, per_page='', page=''): - return favorites_getPublicList(user_id=self.id, per_page=per_page, \ - page=page) - - def getFavorites(self, per_page='', page=''): - return favorites_getList(user_id=self.id, per_page=per_page, \ - page=page) - -class Group(object): - """Flickr Group Pool""" - def __init__(self, id, name=None, members=None, online=None,\ - privacy=None, chatid=None, chatcount=None): - self.__loaded = False - self.__id = id - self.__name = name - self.__members = members - self.__online = online - self.__privacy = privacy - self.__chatid = chatid - self.__chatcount = chatcount - self.__url = None - - id = property(lambda self: self._general_getattr('id')) - name = property(lambda self: self._general_getattr('name')) - members = property(lambda self: self._general_getattr('members')) - online = property(lambda self: self._general_getattr('online')) - privacy = property(lambda self: self._general_getattr('privacy')) - chatid = property(lambda self: self._general_getattr('chatid')) - chatcount = property(lambda self: self._general_getattr('chatcount')) - - def _general_getattr(self, var): - """Generic get attribute function.""" - if getattr(self, "_%s__%s" % (self.__class__.__name__, var)) is None \ - and not self.__loaded: - self._load_properties() - return getattr(self, "_%s__%s" % (self.__class__.__name__, var)) - - def _load_properties(self): - """Loads the properties from Flickr.""" - method = 'flickr.groups.getInfo' - data = _doget(method, group_id=self.id) - - self.__loaded = True - - group = data.rsp.group - - self.__name = photo.name.text - self.__members = photo.members.text - self.__online = photo.online.text - self.__privacy = photo.privacy.text - self.__chatid = photo.chatid.text - self.__chatcount = photo.chatcount.text - - def __str__(self): - return '<Flickr Group %s>' % self.id - - def getPhotos(self, tags='', per_page='', page=''): - """Get a list of photo objects for this group""" - method = 'flickr.groups.pools.getPhotos' - data = _doget(method, group_id=self.id, tags=tags,\ - per_page=per_page, page=page) - photos = [] - for photo in data.rsp.photos.photo: - photos.append(_parse_photo(photo)) - return photos - - def add(self, photo): - """Adds a Photo to the group""" - method = 'flickr.groups.pools.add' - _dopost(method, auth=True, photo_id=photo.id, group_id=self.id) - return True - - def remove(self, photo): - """Remove a Photo from the group""" - method = 'flickr.groups.pools.remove' - _dopost(method, auth=True, photo_id=photo.id, group_id=self.id) - return True - -class Tag(object): - def __init__(self, id, author, raw, text): - self.id = id - self.author = author - self.raw = raw - self.text = text - - def __str__(self): - return '<Flickr Tag %s (%s)>' % (self.id, self.text) - - -#Flickr API methods -#see api docs http://www.flickr.com/services/api/ -#for details of each param - -#XXX: Could be Photo.search(cls) -def photos_search(user_id='', auth=False, tags='', tag_mode='', text='',\ - min_upload_date='', max_upload_date='',\ - min_taken_date='', max_taken_date='', \ - license='', per_page='', page='', sort=''): - """Returns a list of Photo objects. - - If auth=True then will auth the user. Can see private etc - """ - method = 'flickr.photos.search' - - data = _doget(method, auth=auth, user_id=user_id, tags=tags, text=text,\ - min_upload_date=min_upload_date,\ - max_upload_date=max_upload_date, \ - min_taken_date=min_taken_date, \ - max_taken_date=max_taken_date, \ - license=license, per_page=per_page,\ - page=page, sort=sort) - photos = [] - if isinstance(data.rsp.photos.photo, list): - for photo in data.rsp.photos.photo: - photos.append(_parse_photo(photo)) - else: - photos = [_parse_photo(data.rsp.photos.photo)] - return photos - -#XXX: Could be class method in User -def people_findByEmail(email): - """Returns User object.""" - method = 'flickr.people.findByEmail' - data = _doget(method, find_email=email) - user = User(data.rsp.user.id, username=data.rsp.user.username.text) - return user - -def people_findByUsername(username): - """Returns User object.""" - method = 'flickr.people.findByUsername' - data = _doget(method, username=username) - user = User(data.rsp.user.id, username=data.rsp.user.username.text) - return user - -#XXX: Should probably be in User as a list User.public -def people_getPublicPhotos(user_id, per_page='', page=''): - """Returns list of Photo objects.""" - method = 'flickr.people.getPublicPhotos' - data = _doget(method, user_id=user_id, per_page=per_page, page=page) - photos = [] - if hasattr(data.rsp.photos, "photo"): # Check if there are photos at all (may be been paging too far). - if isinstance(data.rsp.photos.photo, list): - for photo in data.rsp.photos.photo: - photos.append(_parse_photo(photo)) - else: - photos = [_parse_photo(data.rsp.photos.photo)] - return photos - -#XXX: These are also called from User -def favorites_getList(user_id='', per_page='', page=''): - """Returns list of Photo objects.""" - method = 'flickr.favorites.getList' - data = _doget(method, auth=True, user_id=user_id, per_page=per_page,\ - page=page) - photos = [] - if isinstance(data.rsp.photos.photo, list): - for photo in data.rsp.photos.photo: - photos.append(_parse_photo(photo)) - else: - photos = [_parse_photo(data.rsp.photos.photo)] - return photos - -def favorites_getPublicList(user_id, per_page='', page=''): - """Returns list of Photo objects.""" - method = 'flickr.favorites.getPublicList' - data = _doget(method, auth=False, user_id=user_id, per_page=per_page,\ - page=page) - photos = [] - if isinstance(data.rsp.photos.photo, list): - for photo in data.rsp.photos.photo: - photos.append(_parse_photo(photo)) - else: - photos = [_parse_photo(data.rsp.photos.photo)] - return photos - -def favorites_add(photo_id): - """Add a photo to the user's favorites.""" - method = 'flickr.favorites.add' - _dopost(method, auth=True, photo_id=photo_id) - return True - -def favorites_remove(photo_id): - """Remove a photo from the user's favorites.""" - method = 'flickr.favorites.remove' - _dopost(method, auth=True, photo_id=photo_id) - return True - -def groups_getPublicGroups(): - """Get a list of groups the auth'd user is a member of.""" - method = 'flickr.groups.getPublicGroups' - data = _doget(method, auth=True) - groups = [] - if isinstance(data.rsp.groups.group, list): - for group in data.rsp.groups.group: - groups.append(Group(group.id, name=group.name)) - else: - group = data.rsp.groups.group - groups = [Group(group.id, name=group.name)] - return groups - -def groups_pools_getGroups(): - """Get a list of groups the auth'd user can post photos to.""" - method = 'flickr.groups.pools.getGroups' - data = _doget(method, auth=True) - groups = [] - if isinstance(data.rsp.groups.group, list): - for group in data.rsp.groups.group: - groups.append(Group(group.id, name=group.name, \ - privacy=group.privacy)) - else: - group = data.rsp.groups.group - groups = [Group(group.id, name=group.name, privacy=group.privacy)] - return groups - - -def tags_getListUser(user_id=''): - """Returns a list of tags for the given user (in string format)""" - method = 'flickr.tags.getListUser' - auth = user_id == '' - data = _doget(method, auth=auth, user_id=user_id) - if isinstance(data.rsp.tags.tag, list): - return [tag.text for tag in data.rsp.tags.tag] - else: - return [data.rsp.tags.tag.text] - -def tags_getListUserPopular(user_id='', count=''): - """Gets the popular tags for a user in dictionary form tag=>count""" - method = 'flickr.tags.getListUserPopular' - auth = user_id == '' - data = _doget(method, auth=auth, user_id=user_id) - result = {} - if isinstance(data.rsp.tags.tag, list): - for tag in data.rsp.tags.tag: - result[tag.text] = tag.count - else: - result[data.rsp.tags.tag.text] = data.rsp.tags.tag.count - return result - -def tags_getrelated(tag): - """Gets the related tags for given tag.""" - method = 'flickr.tags.getRelated' - data = _doget(method, auth=False, tag=tag) - if isinstance(data.rsp.tags.tag, list): - return [tag.text for tag in data.rsp.tags.tag] - else: - return [data.rsp.tags.tag.text] - -def contacts_getPublicList(user_id): - """Gets the contacts (Users) for the user_id""" - method = 'flickr.contacts.getPublicList' - data = _doget(method, auth=False, user_id=user_id) - if isinstance(data.rsp.contacts.contact, list): - return [User(user.nsid, username=user.username) \ - for user in data.rsp.contacts.contact] - else: - user = data.rsp.contacts.contact - return [User(user.nsid, username=user.username)] - -def interestingness(): - method = 'flickr.interestingness.getList' - data = _doget(method) - photos = [] - if isinstance(data.rsp.photos.photo , list): - for photo in data.rsp.photos.photo: - photos.append(_parse_photo(photo)) - else: - photos = [_parse_photo(data.rsp.photos.photo)] - return photos - -def test_login(): - method = 'flickr.test.login' - data = _doget(method, auth=True) - user = User(data.rsp.user.id, username=data.rsp.user.username.text) - return user - -def test_echo(): - method = 'flickr.test.echo' - data = _doget(method) - return data.rsp.stat - - -#useful methods - -def _doget(method, auth=False, **params): - #uncomment to check you aren't killing the flickr server - #print "***** do get %s" % method - - #convert lists to strings with ',' between items - for (key, value) in params.items(): - if isinstance(value, list): - params[key] = ','.join([item for item in value]) - - url = '%s%s/?api_key=%s&method=%s&%s'% \ - (HOST, API, API_KEY, method, urlencode(params)) - if auth: - url = url + '&email=%s&password=%s' % (email, password) - - #another useful debug print statement - #print url - - xml = minidom.parse(urlopen(url)) - data = unmarshal(xml) - if not data.rsp.stat == 'ok': - msg = "ERROR [%s]: %s" % (data.rsp.err.code, data.rsp.err.msg) - raise FlickrError, msg - return data - -def _dopost(method, auth=False, **params): - #uncomment to check you aren't killing the flickr server - #print "***** do post %s" % method - - #convert lists to strings with ',' between items - for (key, value) in params.items(): - if isinstance(value, list): - params[key] = ','.join([item for item in value]) - - url = '%s%s/' % (HOST, API) - - payload = 'api_key=%s&method=%s&%s'% \ - (API_KEY, method, urlencode(params)) - if auth: - payload = payload + '&email=%s&password=%s' % (email, password) - - #another useful debug print statement - #print url - #print payload - - xml = minidom.parse(urlopen(url, payload)) - data = unmarshal(xml) - if not data.rsp.stat == 'ok': - msg = "ERROR [%s]: %s" % (data.rsp.err.code, data.rsp.err.msg) - raise FlickrError, msg - return data - -def _parse_photo(photo): - """Create a Photo object from photo data.""" - owner = User(photo.owner) - title = photo.title - ispublic = photo.ispublic - isfriend = photo.isfriend - isfamily = photo.isfamily - secret = photo.secret - server = photo.server - p = Photo(photo.id, owner=owner, title=title, ispublic=ispublic,\ - isfriend=isfriend, isfamily=isfamily, secret=secret, \ - server=server) - return p - -#stolen methods - -class Bag: pass - -#unmarshal taken and modified from pyamazon.py -#makes the xml easy to work with -def unmarshal(element): - rc = Bag() - if isinstance(element, minidom.Element): - for key in element.attributes.keys(): - setattr(rc, key, element.attributes[key].value) - - childElements = [e for e in element.childNodes \ - if isinstance(e, minidom.Element)] - if childElements: - for child in childElements: - key = child.tagName - if hasattr(rc, key): - if type(getattr(rc, key)) <> type([]): - setattr(rc, key, [getattr(rc, key)]) - setattr(rc, key, getattr(rc, key) + [unmarshal(child)]) - elif isinstance(child, minidom.Element) and \ - (child.tagName == 'Details'): - # make the first Details element a key - setattr(rc,key,[unmarshal(child)]) - #dbg: because otherwise 'hasattr' only tests - #dbg: on the second occurence: if there's a - #dbg: single return to a query, it's not a - #dbg: list. This module should always - #dbg: return a list of Details objects. - else: - setattr(rc, key, unmarshal(child)) - else: - #jec: we'll have the main part of the element stored in .text - #jec: will break if tag <text> is also present - text = "".join([e.data for e in element.childNodes \ - if isinstance(e, minidom.Text)]) - setattr(rc, 'text', text) - return rc - -#unique items from a list from the cookbook -def uniq(alist): # Fastest without order preserving - set = {} - map(set.__setitem__, alist, []) - return set.keys() - -if __name__ == '__main__': - print test_echo() |