[Checkins] SVN: lovely.flickr/ initial import from Lovely Systems repository

Jodok Batlogg jodok.batlogg at lovelysystems.com
Thu Aug 17 12:49:56 EDT 2006


Log message for revision 69614:
  initial import from Lovely Systems repository

Changed:
  A   lovely.flickr/
  A   lovely.flickr/trunk/
  A   lovely.flickr/trunk/src/
  A   lovely.flickr/trunk/src/lovely/
  A   lovely.flickr/trunk/src/lovely/__init__.py
  A   lovely.flickr/trunk/src/lovely/flickr/
  A   lovely.flickr/trunk/src/lovely/flickr/DEPENDENCIES.cfg
  A   lovely.flickr/trunk/src/lovely/flickr/README.txt
  A   lovely.flickr/trunk/src/lovely/flickr/__init__.py
  A   lovely.flickr/trunk/src/lovely/flickr/auth.py
  A   lovely.flickr/trunk/src/lovely/flickr/auth.txt
  A   lovely.flickr/trunk/src/lovely/flickr/blogs.py
  A   lovely.flickr/trunk/src/lovely/flickr/blogs.txt
  A   lovely.flickr/trunk/src/lovely/flickr/contacts.py
  A   lovely.flickr/trunk/src/lovely/flickr/contacts.txt
  A   lovely.flickr/trunk/src/lovely/flickr/favorites.txt
  A   lovely.flickr/trunk/src/lovely/flickr/flickr.py
  A   lovely.flickr/trunk/src/lovely/flickr/interfaces.py
  A   lovely.flickr/trunk/src/lovely/flickr/online.txt
  A   lovely.flickr/trunk/src/lovely/flickr/photos.py
  A   lovely.flickr/trunk/src/lovely/flickr/photos.txt
  A   lovely.flickr/trunk/src/lovely/flickr/test.py
  A   lovely.flickr/trunk/src/lovely/flickr/test.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/
  A   lovely.flickr/trunk/src/lovely/flickr/tests/__init__.py
  A   lovely.flickr/trunk/src/lovely/flickr/tests/auth.checkToken-1.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/auth.getFrob-1.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/auth.getFullToken-1.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/auth.getToken-1.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/blogs.getList-1.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-1.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-2.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-3.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getPublicList-1.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/photos.search-1.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/photos.search-2.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/success.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/test.echo-1.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/test.echo-2.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/test.login-1.txt
  A   lovely.flickr/trunk/src/lovely/flickr/tests/test_doc.py

-=-
Added: lovely.flickr/trunk/src/lovely/__init__.py
===================================================================


Property changes on: lovely.flickr/trunk/src/lovely/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/DEPENDENCIES.cfg
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/DEPENDENCIES.cfg	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/DEPENDENCIES.cfg	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1 @@
+cElementTree
\ No newline at end of file

Added: lovely.flickr/trunk/src/lovely/flickr/README.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/README.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/README.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,32 @@
+======
+Flickr
+======
+
+Flickr holds millions of photos and provides a rich and powerful API. The API
+definition can be found at 'http://www.flickr.com/services/api/'
+
+this modules follows pretty strictly the API.
+
+  >>> from lovely import flickr
+
+the main areas are:
+
+auth, blogs, contacts, favorites, groups, interestingness, people, photos,
+photosets, reflection, tags, test, urls
+
+To use the Flickr API you need to have an application key. Flickr uses this
+key to track API usage.
+This is Lovely Systems non-commercial key for development:
+
+  >>> API_KEY=u'a8d135acf227a6c9471c5b6d24877080'
+  >>> SHARED_SECRET=u'cf4c77be4d206e6a'
+
+
+If the connection to flickr results in an error, a FlickrError is beeing
+raised.
+
+  >>> flickr.test.echo(api_key=u'bullshit')
+  Traceback (most recent call last):
+  ...
+  FlickrError: Flickr Error 100: Invalid API Key (Key not found)
+


Property changes on: lovely.flickr/trunk/src/lovely/flickr/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/__init__.py
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/__init__.py	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/__init__.py	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,3 @@
+# Make a package.
+
+import auth, test, photos


Property changes on: lovely.flickr/trunk/src/lovely/flickr/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/auth.py
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/auth.py	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/auth.py	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,238 @@
+##############################################################################
+#
+# Copyright (c) 2006 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""This module implements the flickr.auth namespace
+
+http://www.flickr.com/services/api/
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import urllib
+import zope.interface
+from zope.schema import fieldproperty
+from lovely.flickr import interfaces, flickr
+from zope.testbrowser import browser
+from mechanize import Browser
+
+
+class _InternalWebBrowser(Browser):
+    """A special type of mechanize browser.
+
+    This is unfortunately necessary, because the default setup pf the
+    mechanize browser does not work with the "Yahoo! Sin In" page. Oh well.
+
+    We do not provide '_http_error' in ``default_others`` and '_refresh' in
+    ``default_features``.
+    """
+    default_others = ['_http_error', '_http_request_upgrade',
+                      '_http_default_error']
+    default_features = ['_redirect', '_cookies', '_referer', '_refresh',
+                        '_equiv', '_basicauth', '_digestauth', '_seek' ]
+
+    def activateRefreshHandler(self):
+        refresh_handler = self.handler_classes['_refresh']()
+        self._ua_handlers['_refresh'] = refresh_handler
+        self.add_handler(refresh_handler)
+        self.set_handle_refresh(refresh_handler)
+
+    def deactivateRefreshHandler(self):
+        handler = self._ua_handlers['_refresh']
+        self._replace_handler('_refresh')
+        del self._ua_handlers['_refresh']
+
+
+class User(object):
+    zope.interface.implements(interfaces.IUser)
+
+    nsid = fieldproperty.FieldProperty(interfaces.IUser['nsid'])
+    username = fieldproperty.FieldProperty(interfaces.IUser['username'])
+    fullname = fieldproperty.FieldProperty(interfaces.IUser['fullname'])
+
+    def __init__(self, nsid, username, fullname=None):
+        self.nsid = nsid
+        self.username = username
+        if fullname is not None:
+            self.fullname = fullname
+
+    @classmethod
+    def fromElement(self, element):
+        """See interfaces.IBaseFlickrObject"""
+        args = dict([
+            (name, field.fromUnicode(unicode(element.get(name))))
+            for name, field in zope.schema.getFields(interfaces.IUser).items()
+            ])
+        return User(**args)
+
+    def __repr__(self):
+        return '<%s %r - %r>' %(self.__class__.__name__,
+                                self.username, self.fullname)
+
+
+class Auth(object):
+    zope.interface.implements(interfaces.IAuth)
+
+    token = fieldproperty.FieldProperty(interfaces.IAuth['token'])
+    perms = fieldproperty.FieldProperty(interfaces.IAuth['perms'])
+    user = fieldproperty.FieldProperty(interfaces.IAuth['user'])
+
+    def __init__(self, token, perms, user):
+        self.token = token
+        self.perms = perms
+        self.user = user
+
+    @classmethod
+    def fromElement(self, element):
+        """See interfaces.IBaseFlickrObject"""
+        token = unicode(element.find('token').text)
+        perms = [unicode(perm.strip())
+                 for perm in element.find('perms').text.split(',')]
+        user = User.fromElement(element.find('user'))
+        return Auth(token, perms, user)
+
+    def __repr__(self):
+        return '<%s %s>' %(self.__class__.__name__, self.token)
+
+
+class APIAuth(flickr.APIFlickr):
+    """This class provides a pythonic interface to the ``flickr.auth``
+       namespace.
+    """
+    zope.interface.implements(interfaces.IAPIAuth)
+
+    # This can be turned off in tests when dealing with stub implementations
+    _authenticate_for_real = True
+
+    def getAuthenticationURL(self, frob, perms):
+        """See interfaces.IAPIAuth"""
+        params = {'api_key': self.api_key, 'frob': frob,
+                  'perms': ','.join(perms)}
+        self.sign(params)
+        url = 'http://www.flickr.com/services/auth/?%s'% \
+              (urllib.urlencode(params))
+        return url
+
+    def authenticate(self, frob, perms, username, password):
+        """See interfaces.IAPIAuth"""
+        if not self._authenticate_for_real:
+            return
+        # Create a browser that will be used to log into the site.
+        yahoo = browser.Browser(mech_browser=_InternalWebBrowser())
+        yahoo.mech_browser.addheaders = [
+            ("User-agent",
+             "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)")]
+
+        # Go to the login page.
+        yahoo.open('http://www.flickr.com/signin')
+
+        yahoo.mech_browser.deactivateRefreshHandler()
+        yahoo.getLink('Sign in').click()
+
+        # Now log in using the Yahoo! Sign In page.
+        yahoo.getControl('Yahoo! ID').value = username
+        yahoo.getControl('Password').value = password
+        yahoo.mech_browser.activateRefreshHandler()
+        yahoo.getControl('Sign In').click()
+
+        if 'Invalid ID or password' in yahoo.contents:
+            raise ValueError(
+                'Username or password is incorrect. Sometimes the system '
+                'also wants you to verify the user by asking for entering '
+                'strings of an image, which is not supported here. Please '
+                'log in at flickr.com once and retry again.')
+
+        # Now allow the frob.
+        yahoo.open(self.getAuthenticationURL(frob, perms))
+        if 'Success!' not in yahoo.contents:
+            yahoo.getControl("OK, I'LL ALLOW IT").click()
+
+
+    def authenticateCookie(self, frob, perms, cookies):
+        """See interfaces.IAPIAuth"""
+        # Create a browser that will be used to log into the site.
+        yahoo = browser.Browser(mech_browser=_InternalWebBrowser())
+        yahoo.mech_browser.addheaders = [
+            ("User-agent",
+             "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"),
+            ("Cookie", cookies)
+        ]
+        # Now allow the frob.
+        yahoo.open(self.getAuthenticationURL(frob, perms))
+        if 'Success!' not in yahoo.contents:
+            yahoo.getControl("OK, I'LL ALLOW IT").click()
+
+    def getFrob(self):
+        """See interfaces.IAPIAuth"""
+        params = self.initParameters('flickr.auth.getFrob')
+        self.sign(params)
+        rsp = self.execute(params)
+        return rsp.find('frob').text
+
+    def checkToken(self, auth_token):
+        """See interfaces.IAPIAuth"""
+        params = self.initParameters(
+            'flickr.auth.checkToken', auth_token=auth_token)
+        rsp = self.execute(params)
+        return Auth.fromElement(rsp.find('auth'))
+
+    def getToken(self, frob):
+        """See interfaces.IAPIAuth"""
+        params = self.initParameters(
+            'flickr.auth.getToken', frob=frob)
+        self.sign(params)
+        rsp = self.execute(params)
+        return Auth.fromElement(rsp.find('auth'))
+
+    def getFullToken(self, mini_token):
+        """See interfaces.IAPIAuth"""
+        # The API requires the mini-token to be 9 characters long after
+        # optional dashes are removed.
+        mini_token = mini_token.replace('-', '')
+        assert len(mini_token) == 9
+
+        params = self.initParameters(
+            'flickr.auth.getFullToken', mini_token=mini_token)
+        self.sign(params)
+        rsp = self.execute(params)
+        return Auth.fromElement(rsp.find('auth'))
+
+
+def getFrob(api_key, secret):
+    __doc__ = interfaces.IAPIAuth['getFrob'].__doc__
+    return APIAuth(api_key, secret).getFrob()
+
+def checkToken(api_key, auth_token):
+    __doc__ = interfaces.IAPIAuth['checkToken'].__doc__
+    return APIAuth(api_key).checkToken(auth_token)
+
+def getToken(api_key, secret, frob):
+    __doc__ = interfaces.IAPIAuth['checkToken'].__doc__
+    return APIAuth(api_key, secret).getToken(frob)
+
+def getFullToken(api_key, secret, mini_token):
+    __doc__ = interfaces.IAPIAuth['getFullToken'].__doc__
+    return APIAuth(api_key, secret).getFullToken(mini_token)
+
+def getAuthenticationURL(api_key, secret, frob, perms):
+    __doc__ = interfaces.IAPIAuth['getAuthenticationURL'].__doc__
+    return APIAuth(api_key, secret).getAuthenticationURL(frob, perms)
+
+def authenticate(api_key, frob, perms, username, password):
+    __doc__ = interfaces.IAPIAuth['authenticate'].__doc__
+    return APIAuth(api_key, secret).authenticate(
+        frob, perms, username, password)
+
+def authenticateCookie(api_key, frob, perms, cookies):
+    __doc__ = interfaces.IAPIAuth['authenticateCookie'].__doc__
+    return APIAuth(api_key, secret).authenticateCookie(
+        frob, perms, cookies)


Property changes on: lovely.flickr/trunk/src/lovely/flickr/auth.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/auth.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/auth.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/auth.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,103 @@
+=====================
+flickr.auth Namespace
+=====================
+
+This namespace deals with authenticating the user and the requesting client.
+
+  >>> import lovely.flickr.auth
+  >>> from lovely import flickr
+
+As you may know already, this implementation provides an object-oriented and
+procedural implementation of the Flickr API:
+
+  >>> api = flickr.auth.APIAuth(API_KEY, SECRET)
+
+
+``getFrob()``
+-------------
+
+See ``http://www.flickr.com/services/api/flickr.auth.getFrob.html``
+
+Getting the frob is simple:
+
+  >>> frob = flickr.auth.getFrob(API_KEY, SECRET)
+  >>> frob
+  '2572639-8aac54751ebab5a7'
+
+  >>> frob2 = api.getFrob()
+  >>> frob2
+  '2572639-8aac54751ebab5a7'
+
+
+``getAuthenticationURL()`` and ``authenticate()`` [Local]
+---------------------------------------------------------
+
+Before we can continue, we need to authenticate against the Flickr Web site:
+
+  >>> url = flickr.auth.getAuthenticationURL(API_KEY, SECRET, frob, [u'write'])
+  >>> api.getAuthenticationURL(frob, [u'write'])
+  'http://www.flickr.com/services/auth/?...'
+
+This is usually done in a Web browser, but this package allows you to do it
+programmatically as well:
+
+  >>> api.authenticate(frob, [u'write'], 'lovelyflickr', 'pwd123')
+
+
+``getToken()``
+--------------
+
+See ``http://flickr.com/services/api/flickr.auth.getToken.html``
+
+Once you have a frob, you can ask for an authentication token:
+
+  >>> flickr.auth.getToken(API_KEY, SECRET, frob)
+  <Auth 909163-79a56fd4b2ca4a76>
+
+  >>> api.authenticate(frob2, [u'write'], 'lovelyflickr', 'pwd123')
+  >>> auth = api.getToken(frob2)
+  >>> auth.token
+  u'909163-79a56fd4b2ca4a76'
+  >>> auth.perms
+  [u'write']
+  >>> auth.user
+  <User u'lovelyflickr' - u'Lovely Flickr'>
+
+
+``checkToken()``
+----------------
+
+See ``http://flickr.com/services/api/flickr.auth.checkToken.html``
+
+When you have a token, you can verify it at any time:
+
+  >>> flickr.auth.checkToken(API_KEY, auth.token)
+  <Auth 909163-79a56fd4b2ca4a76>
+
+  >>> auth = api.checkToken(auth.token)
+  >>> auth.token
+  u'909163-79a56fd4b2ca4a76'
+  >>> auth.perms
+  [u'write']
+  >>> auth.user
+  <User u'lovelyflickr' - u'Lovely Flickr'>
+
+
+``getFullToken()``
+------------------
+
+See ``http://flickr.com/services/api/flickr.auth.getFullToken.html``
+
+When you have a token, you can verify it at any time:
+
+  >>> flickr.auth.getFullToken(API_KEY, SECRET, '909-a16-3fa')
+  <Auth 909163-79a56fd4b2ca4a76>
+
+  >>> auth2 = api.getFullToken('909-a16-3fa')
+  >>> auth2.token
+  u'909163-79a56fd4b2ca4a76'
+  >>> auth2.perms
+  [u'write']
+  >>> auth2.user
+  <User u'lovelyflickr' - u'Lovely Flickr'>
+


Property changes on: lovely.flickr/trunk/src/lovely/flickr/auth.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/blogs.py
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/blogs.py	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/blogs.py	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,98 @@
+##############################################################################
+#
+# Copyright (c) 2006 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""This module implements the flickr.blogs namespace
+
+http://www.flickr.com/services/api/
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import zope.interface
+from zope.schema import fieldproperty
+from lovely.flickr import interfaces, flickr
+
+
+class Blogs(list):
+    zope.interface.implements(interfaces.IBlogs)
+
+    @classmethod
+    def fromElement(self, element):
+        """See interfaces.IBaseFlickrObject"""
+        blogs = Blogs()
+        for child in element.getchildren():
+            blogs.append(Blog.fromElement(child))
+        return blogs
+
+
+class Blog(object):
+    zope.interface.implements(interfaces.IBlog)
+
+    id = fieldproperty.FieldProperty(interfaces.IBlog['id'])
+    name = fieldproperty.FieldProperty(interfaces.IBlog['name'])
+    needspassword = fieldproperty.FieldProperty(
+        interfaces.IBlog['needspassword'])
+    url = fieldproperty.FieldProperty(interfaces.IBlog['url'])
+
+    def __init__(self, id, name, needspassword, url):
+        self.id = id
+        self.name = name
+        self.needspassword = needspassword
+        self.url = url
+
+    @classmethod
+    def fromElement(self, element):
+        """See interfaces.IBaseFlickrObject"""
+        args = dict([
+            (name, field.fromUnicode(unicode(element.get(name))))
+            for name, field in zope.schema.getFields(interfaces.IBlog).items()
+            ])
+        return Blog(**args)
+
+    def __repr__(self):
+        return '<%s %i - %r>' %(self.__class__.__name__, self.id, self.name)
+
+
+class APIBlogs(flickr.APIFlickr):
+    """This class provides a pythonic interface to the ``flickr.blogs``
+       namespace.
+    """
+    zope.interface.implements(interfaces.IAPIBlogs)
+
+    def getList(self):
+        """See interfaces.IAPIBlogs"""
+        params = self.initParameters('flickr.blogs.getList')
+        self.addAuthToken(params)
+        self.sign(params)
+        elem = self.execute(params)
+        return Blogs.fromElement(elem.getchildren()[0])
+
+    def postPhoto(self, blog_id, photo_id, title, description,
+                  blog_password=None):
+        """See interfaces.IAPIBlogs"""
+        params = self.initParameters(
+            'flickr.blogs.postPhoto', blog_id=blog_id, photo_id=photo_id,
+            title=title, description=description)
+        if blog_password is not None:
+            params['blog_password'] = blog_password
+        self.addAuthToken(params)
+        self.sign(params)
+        self.execute(params, 'POST')
+
+def getList(api_key, secret, auth_token):
+    __doc__ = interfaces.IAPIBlogs['getList'].__doc__
+    return APIBlogs(api_key, secret, auth_token).getList()
+
+def postPhoto(api_key, secret, auth_token, *args, **kw):
+    __doc__ = interfaces.IAPIBlogs['postPhoto'].__doc__
+    return APIBlogs(api_key, secret, auth_token).postPhoto(*args, **kw)


Property changes on: lovely.flickr/trunk/src/lovely/flickr/blogs.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/blogs.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/blogs.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/blogs.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,42 @@
+======================
+flickr.blogs Namespace
+======================
+
+This namespace allows to connect photos with blogs.
+
+  >>> import lovely.flickr.blogs
+  >>> from lovely import flickr
+
+As you may know already, this implementation provides an object-oriented and
+procedural implementation of the Flickr API. For this namespace we need an
+authentication token, so get it.
+
+  >>> api = flickr.blogs.APIBlogs(API_KEY, SECRET, TOKEN)
+
+
+``getList()``
+-------------
+
+See ``http://flickr.com/services/api/flickr.blogs.getList.html``
+
+You can get a list of all your blogs:
+
+  >>> flickr.blogs.getList(API_KEY, SECRET, TOKEN)
+  [<Blog 73 - u'Bloxus test'>, <Blog 74 - u'Manila Test'>]
+
+  >>> api.getList()
+  [<Blog 73 - u'Bloxus test'>, <Blog 74 - u'Manila Test'>]
+
+
+``postPhoto()``
+------------------
+
+See ``http://flickr.com/services/api/flickr.blogs.postPhoto.html``
+
+You can now add a photo to a blog:
+
+  >>> flickr.blogs.postPhoto(API_KEY, SECRET, TOKEN,
+  ...     73, 2633, 'At Lovely Systems', 'Last week I was at ...')
+
+  >>> api.postPhoto(74, 2633, 'At Lovely Systems', 'Last week I was at ...')
+


Property changes on: lovely.flickr/trunk/src/lovely/flickr/blogs.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/contacts.py
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/contacts.py	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/contacts.py	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,107 @@
+##############################################################################
+#
+# Copyright (c) 2006 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""this module implements the flickr.contacts namespace
+
+http://www.flickr.com/services/api/
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import zope.interface
+import zope.schema
+from zope.schema import fieldproperty
+from lovely.flickr import interfaces, flickr
+
+
+class Contacts(list):
+    zope.interface.implements(interfaces.IContacts)
+
+    @classmethod
+    def fromElement(self, element):
+        """See interfaces.IBaseFlickrObject"""
+        contacts = Contacts()
+        for child in element.getchildren():
+            contacts.append(Contact.fromElement(child))
+        return contacts
+
+    def __repr__(self):
+        return '<%s entries=%i>' %(self.__class__.__name__, len(self))
+
+class Contact(object):
+    zope.interface.implements(interfaces.IContact)
+
+    nsid = fieldproperty.FieldProperty(interfaces.IContact['nsid'])
+    username = fieldproperty.FieldProperty(interfaces.IContact['username'])
+    iconserver = fieldproperty.FieldProperty(interfaces.IContact['iconserver'])
+    realname = fieldproperty.FieldProperty(interfaces.IContact['realname'])
+    friend = fieldproperty.FieldProperty(interfaces.IContact['friend'])
+    family = fieldproperty.FieldProperty(interfaces.IContact['family'])
+    ignored = fieldproperty.FieldProperty(interfaces.IContact['ignored'])
+
+    def __init__(self, nsid, username, iconserver, ignored, realname=None,
+                 friend=None, family=None):
+        self.nsid = nsid
+        self.username = username
+        self.iconserver = iconserver
+        self.realname = realname
+        self.friend = friend
+        self.family = family
+        self.ignored = ignored
+
+    @classmethod
+    def fromElement(self, element):
+        """See interfaces.IBaseFlickrObject"""
+        args = dict([
+            (name, field.fromUnicode(unicode(element.get(name))))
+            for name, field in zope.schema.getFields(interfaces.IContact).items()
+            if element.get(name) is not None
+            ])
+        return Contact(**args)
+
+    def __repr__(self):
+        return '<%s %s>' %(self.__class__.__name__, self.nsid)
+
+
+class APIContacts(flickr.APIFlickr):
+    zope.interface.implements(interfaces.IAPIContacts)
+
+    def getList(self, filter=None):
+        """See interfaces.IAPIContacts"""
+        params = self.initParameters('flickr.contacts.getList')
+        if filter is not None:
+            assert filter in ['friends', 'family', 'both', 'neither']
+            params['filter'] = filter
+        self.addAuthToken(params)
+        self.sign(params)
+        elem = self.execute(params)
+        return Contacts.fromElement(elem.getchildren()[0])
+
+    def getPublicList(self, user_name):
+        """See interfaces.IAPIContacts"""
+        params = self.initParameters('flickr.contacts.getPublicList',
+                                     user_name=user_name)
+        elem = self.execute(params)
+        return Contacts.fromElement(elem.getchildren()[0])
+
+
+def getList(api_key, auth_token, **kw):
+    __doc__ = interfaces.IAPIContacts['getList'].__doc__
+
+    return APIContacts(api_key, secret, auth_token).getList(**kw)
+
+def getPublicList(api_key, **kw):
+    __doc__ = interfaces.IAPIContacts['getPublicList'].__doc__
+
+    return APIContacts(api_key).getPublicList(**kw)


Property changes on: lovely.flickr/trunk/src/lovely/flickr/contacts.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/contacts.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/contacts.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/contacts.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,72 @@
+=========================
+flickr.contacts Namespace
+=========================
+
+This namespace allows to view your contacts.
+
+  >>> import lovely.flickr.contacts
+  >>> from lovely import flickr
+
+As you may know already, this implementation provides an object-oriented and
+procedural implementation of the Flickr API. For this namespace we need an
+authentication token, so get it.
+
+  >>> api = flickr.contacts.APIContacts(API_KEY, SECRET, TOKEN)
+
+
+``getList()``
+------------
+
+See ``http://www.flickr.com/services/api/flickr.contacts.getList.html``
+
+Get a list of all my contacts:
+
+  >>> contacts = api.getList()
+  >>> contacts
+  <Contacts entries=3>
+
+
+A contact itself has the following properties
+
+  >>> contact = contacts[0]
+  >>> contact
+  <Contact 12037949629 at N01>
+
+  >>> contact.nsid
+  u'12037949629 at N01'
+  >>> contact.username
+  u'Eric'
+  >>> contact.iconserver
+  1
+  >>> contact.realname
+  u'Eric Costello'
+  >>> contact.friend
+  1
+  >>> contact.family
+  0
+  >>> contact.ignored
+  1
+
+Show my friends only:
+
+  >>> api.getList('friends')
+  <Contacts entries=2>
+
+Now show my family only:
+
+  >>> api.getList('family')
+  <Contacts entries=1>
+
+
+``getPublicList()``
+-------------------
+
+See ``http://www.flickr.com/services/api/flickr.contacts.getPublicList.html``
+
+  >>> contacts = api.getPublicList('lovelyflickr')
+  >>> contacts
+  <Contacts entries=3>
+
+  >>> contact = contacts[0]
+  >>> contact
+  <Contact 12037949629 at N01>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/contacts.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/favorites.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/favorites.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/favorites.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,111 @@
+==========================
+flickr.favorites Namespace
+==========================
+
+This namespace allows to view and manage your favorite photos.
+
+  >>> import lovely.flickr.favorites
+  >>> from lovely import flickr
+
+As you may know already, this implementation provides an object-oriented and
+procedural implementation of the Flickr API. For this namespace we need an
+authentication token, so get it.
+
+  >>> api = flickr.favorites.APIFavorites(API_KEY, SECRET, TOKEN)
+
+
+``getPublicList()``
+-------------------
+
+See ``http://www.flickr.com/services/api/flickr.favorites.getPublicList.html``
+
+Get the public list of your favorite photos:
+
+  >>> photos = api.getPublicList('47058503995 at N01')
+  >>> photos
+  <Photos entries=4>
+
+  >>> photo = photos[0]
+  >>> photo
+  <Photo 2636>
+
+Of course you can also just call the API Function:
+
+  >>> flickr.favorites.getPublicList(API_KEY, '47058503995 at N01')
+  <Photos entries=4>
+
+
+``getList()``
+------------
+
+See ``http://www.flickr.com/services/api/flickr.favorites.getList.html``
+
+Get a list of all my contacts:
+
+  >>> photos = api.getList('47058503995 at N01')
+  >>> photos
+  <Photos entries=3>
+
+  >>> photo = photos[0]
+  >>> photo
+  <Photo 2635>
+
+You can also specify the list of extra meta data that you would like to
+receive:
+
+  >>> photos = photos = api.getList(
+  ...     '47058503995 at N01',
+  ...     extra=['license', 'date_upload', 'date_taken', 'owner_name',
+  ...            'icon_server', 'original_format', 'last_update'])
+
+  >>> photos
+
+  >>> photo = photos[0]
+  >>> photo.license
+
+  >>> photo.date_upload
+
+  >>> photo.date_taken
+
+  >>> photo.owner_name
+
+  >>> photo.icon_server
+
+  >>> photo.original_format
+
+  >>> photo.last_update
+
+Of course you can also just call the API Function:
+
+  >>> flickr.favorites.getList(API_KEY, SECRET, TOKEN, '47058503995 at N01')
+  <Photos entries=3>
+
+
+``add()``
+---------
+
+See ``http://www.flickr.com/services/api/flickr.favorites.add.html``
+
+Add a photo to the list of favorites:
+
+  >>> api.add('3000')
+
+
+Of course you can also just call the API Function:
+
+  >>> flickr.favorites.add(API_KEY, SECRET, TOKEN, '3001')
+
+
+``remove()``
+------------
+
+See ``http://www.flickr.com/services/api/flickr.favorites.remove.html``
+
+Remove a photo from the list of favorites:
+
+  >>> api.remove('3000')
+
+
+Of course you can also just call the API Function:
+
+  >>> flickr.favorites.remove(API_KEY, SECRET, TOKEN, '3001')


Property changes on: lovely.flickr/trunk/src/lovely/flickr/favorites.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/flickr.py
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/flickr.py	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/flickr.py	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,92 @@
+##############################################################################
+#
+# Copyright (c) 2006 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Flickr Base Class
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import cElementTree
+import md5
+import urllib
+from zope.schema import fieldproperty
+from lovely.flickr import interfaces
+
+
+class APIFlickr(object):
+    """This is the base class for all Flickr API classes.
+    """
+    api_key = fieldproperty.FieldProperty(interfaces.IAPIFlickr['api_key'])
+    url = fieldproperty.FieldProperty(interfaces.IAPIFlickr['url'])
+
+    # Tests can use this hooks to allow for stub testing.
+    _urlopen = urllib.urlopen
+
+    def __init__(self, api_key, secret=None, auth_token=None, url=None):
+        self.api_key = api_key
+        self.secret = secret
+        self.auth_token = auth_token
+        if url is not None:
+            self.url = url
+
+    def initParameters(self, method, **params):
+        params['api_key'] = self.api_key
+        params['method'] = method
+        return params
+
+    def addAuthToken(self, params):
+        '''Add the authentication token to the paramter list'''
+        params['auth_token'] = self.auth_token
+
+    def sign(self, params):
+        """Sign the Flickr request.
+
+        See http://www.flickr.com/services/api/auth.spec.html, Section 8
+        """
+        # Step 1: Sort your argument list into alphabetical order based on
+        #         the parameter name.
+        plist = sorted(params.items())
+        # Step 2: Concatenate the shared secret and argument name-value pairs.
+        sig = u''.join([name+unicode(value) for name, value in plist])
+        sig = self.secret + sig
+        # Step 3: Calculate the md5() hash of this string.
+        sig_hex = md5.md5(sig).hexdigest()
+        # The signature is now complete; add it to the parameter list
+        params['api_sig'] = sig_hex
+
+    def execute(self, params, http='GET'):
+        """See interfaces.IAPIFlickr"""
+        params = dict([(name, unicode(value).encode('UTF-8'))
+                       for name, value in params.items()])
+
+        # The function had been converted to a method :-(
+        urlopen = self._urlopen.im_func
+
+        if http == 'GET':
+            url = '%s/?%s' % (self.url, urllib.urlencode(params))
+            rsp = urlopen(url)
+        elif http == 'POST':
+            rsp = urlopen(self.url, urllib.urlencode(params))
+        else:
+            raise ValueError('HTTP Verb not recognized')
+
+        tree = cElementTree.parse(rsp).getroot()
+
+        stat = tree.get('stat')
+        if stat != 'ok':
+            err = tree.find('err')
+            raise interfaces.FlickrError(
+                code=int(err.get('code')), msg=unicode(err.get('msg')))
+
+        return tree


Property changes on: lovely.flickr/trunk/src/lovely/flickr/flickr.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/interfaces.py
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/interfaces.py	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/interfaces.py	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,449 @@
+##############################################################################
+#
+# Copyright (c) 2006 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""this module implements the flickr.photos namespace
+
+http://www.flickr.com/services/api/
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import zope.interface
+import zope.schema
+from zope.interface.common import sequence
+
+class FlickrError(Exception):
+    """An error occured while executing a Flickr API method."""
+
+    def __init__(self, code, msg):
+        self.code = code
+        self.msg = msg
+
+    def __str__(self):
+        return 'Flickr Error %i: %s' %(self.code, self.msg.encode('utf-8'))
+
+    def __repr__(self):
+        return '<%s %i, %r>' %(self.__class__.__name__, self.code, self.msg)
+
+
+class IFlickr(zope.interface.Interface):
+    """Flickr toplevel namespace"""
+
+    auth = zope.interface.Attribute('flickr.auth package')
+    blogs = zope.interface.Attribute('flickr.blogs package')
+    photos = zope.interface.Attribute('flickr.photos package')
+    test = zope.interface.Attribute('flickr.test package')
+
+
+class IBaseFlickrObject(zope.interface.Interface):
+    """This interface has to be implemented by all Flickr objects"""
+
+    def fromElement(element):
+        """Create a Flickr object from the ElementTree element.
+
+        This is a classmethod.
+        """
+
+
+class IUser(IBaseFlickrObject):
+    """A Flickr user"""
+
+    nsid = zope.schema.TextLine(
+        title = u'User Id',
+        description = u'The Flickr user id.',
+        required = True
+        )
+
+    username = zope.schema.TextLine(
+        title = u'Username',
+        description = u'The username used to log into Flickr.',
+        required = True
+        )
+
+    fullname = zope.schema.TextLine(
+        title = u'Full name',
+        description = u'The full name of the Flickr user.',
+        required = True
+        )
+
+
+class IAuth(IBaseFlickrObject):
+    """An authentication Response"""
+
+    token = zope.schema.TextLine(
+        title = u'Token',
+        description = u'The authentication token to be used.',
+        required = True
+        )
+
+    perms = zope.schema.List(
+        title = u'Permissions',
+        description = u'A set of permissions for this authentication token.',
+        required = True,
+        value_type = zope.schema.Choice(
+                values=['none', 'read', 'write', 'delete'])
+        )
+
+    user = zope.schema.Object(
+        title = u'User',
+        description = u'The Flickr user for whom the authentication was '
+                      u'granted.',
+        schema = IUser,
+        required = True
+        )
+
+
+class IBlogs(sequence.ISequence):
+    """A list of blog entries."""
+
+
+class IBlog(IBaseFlickrObject):
+    """A blog entry on Flickr."""
+
+    id = zope.schema.Int(
+        title = u'Id',
+        description = u'The Flickr blog id.',
+        required = True
+        )
+
+    name = zope.schema.TextLine(
+        title = u'Name',
+        description = u'The Flickr blog name.',
+        required = True
+        )
+
+    needspassword = zope.schema.Int(
+        title = u'Needs Password',
+        description = u'Whether the blog needs a password to upload a photo.',
+        required = True
+        )
+
+    url = zope.schema.TextLine(
+        title = u'URL',
+        description = u'The Flickr blog URL.',
+        required = True
+        )
+
+
+class IContact(IBaseFlickrObject):
+    """A single contact."""
+
+    nsid = zope.schema.TextLine(
+        title = u'NSID',
+        description = u'The id of the contact.',
+        required = True
+        )
+
+    username = zope.schema.TextLine(
+        title = u'Username',
+        description = u'The username of the contact.',
+        required = True
+        )
+
+    iconserver = zope.schema.Int(
+        title = u'Icon Server',
+        description = u'The id of the server on which the icon is available.',
+        required = True
+        )
+
+    realname = zope.schema.TextLine(
+        title = u'Real Name',
+        description = u'The real name of the contact.',
+        required = False
+        )
+
+    friend = zope.schema.Int(
+        title = u'Friend',
+        description = u'Specifies whether the contact is a friend.',
+        required = False
+        )
+
+    family = zope.schema.Int(
+        title = u'Family',
+        description = u'Specifies whether the contact is a family member.',
+        required = False
+        )
+
+    ignored = zope.schema.Int(
+        title = u'Ignored',
+        description = u'Specifies whether the contact is ignored.',
+        required = True
+        )
+
+
+class IContacts(IBaseFlickrObject):
+    """A collection of contacts."""
+
+
+class IPhoto(IBaseFlickrObject):
+    """A single photo."""
+
+    id = zope.schema.Int(
+        title = u'Id',
+        description = u'The id of the photo.',
+        required = True
+        )
+
+    owner = zope.schema.TextLine(
+        title = u'Owner',
+        description = u'The owner user id of the photo.',
+        required = True
+        )
+
+    secret = zope.schema.TextLine(
+        title = u'Secret',
+        description = u'The secret of the photo.',
+        required = True
+        )
+
+    server = zope.schema.Int(
+        title = u'Server',
+        description = u'The id of the server on which the photo is available.',
+        required = True
+        )
+
+    title = zope.schema.TextLine(
+        title = u'Title',
+        description = u'The title of the photo.',
+        required = True
+        )
+
+    ispublic = zope.schema.Int(
+        title = u'Is Public',
+        description = u'Specifies whether the photo is public.',
+        required = True
+        )
+
+    isfriend = zope.schema.Int(
+        title = u'Is Friend',
+        description = u'Specifies whether the photo is from a friend.',
+        required = True
+        )
+
+    isfamily = zope.schema.Int(
+        title = u'Is Family',
+        description = u'Specifies whether the photo is from a family member.',
+        required = True
+        )
+
+
+class IPhotos(IBaseFlickrObject):
+    """A sub-collection of photos within a larger collection."""
+
+    page = zope.schema.Int(
+        title = u'Page',
+        description = u'The page this photos collection describes.',
+        required = True
+        )
+
+    pages = zope.schema.Int(
+        title = u'Pages',
+        description = u'The total amount of pages available.',
+        required = True
+        )
+
+    perpage = zope.schema.Int(
+        title = u'Per Page',
+        description = u'The amount of photos per page.',
+        required = True
+        )
+
+    total = zope.schema.Int(
+        title = u'Total',
+        description = u'The total amount of photos available.',
+        required = True
+        )
+
+
+class IAPIFlickr(zope.interface.Interface):
+    """This is our base class for all Flickr API classes.
+
+    It provides the basic information to connect to the Flickr services.
+    """
+
+    api_key = zope.schema.TextLine(
+        title = u'Flickr API Key',
+        description = u'Flickr API Key required to use the Flickr API',
+        required = True
+        )
+
+    secret = zope.schema.TextLine(
+        title = u'Flickr Secret',
+        description = u'Flickr API Authentication Secret.',
+        required = True
+        )
+
+    url = zope.schema.TextLine(
+        title = u'Flickr API URL',
+        description = u'The Flickr API URL to use; '
+                      u'usually http://www.flickr.com/services/rest',
+        required = True,
+        default = u'http://www.flickr.com/services/rest',
+        )
+
+    def execute(method, **kw):
+        """Send a request to the Flickr Service endpoint and return the result.
+
+        The method will return an ``ElementTree`` data structure.
+        """
+
+
+class IAPIAuth(IAPIFlickr):
+    """This class provides a pythonic interface to the ``flickr.auth``
+    namespace."""
+
+    def getFrob():
+        """Returns a frob to be used during authentication.
+
+        The result will be the frob string.
+
+        See ``http://flickr.com/services/api/flickr.auth.getFrob.html``
+        """
+
+    def checkToken(auth_token):
+        """Returns the credentials attached to an authentication token.
+
+        The result will be an ``Auth`` instance.
+
+        See ``http://flickr.com/services/api/flickr.auth.checkToken.html``
+        """
+
+    def getToken(frob):
+        """Returns the auth token for the given frob, if one has been attached.
+
+        The result will be an ``Auth`` instance.
+
+        See ``http://flickr.com/services/api/flickr.auth.getToken.html``
+        """
+
+    def getFullToken(mini_token):
+        """Get the full authentication token for a mini-token.
+
+        The result will be an ``Auth`` instance.
+
+        See ``http://flickr.com/services/api/flickr.auth.getFullToken.html``
+        """
+
+    def getAuthenticationURL(self, frob, perms):
+        """Get the Flickr Web site authentication URL.
+
+        The result will be a URL string.
+
+        This is not a Flickr API method. It is provided as a client service.
+        """
+
+    def authenticate(self, frob, perms, username, password):
+        """Try to authenticate against Flickr and allow the frob.
+
+        This is not a Flickr API method. It is provided as a client service.
+        """
+
+    def authenticateCookie(self, frob, perms, cookies):
+        """Try to authenticate against Flickr by using the stored cookie
+
+        This is not a Flickr API method. It is provided as a client service.
+        """
+
+
+class IAPIBlogs(IAPIFlickr):
+    """This class provides a pythonic interface to the ``flickr.blogs``
+    namespace."""
+
+    def getList():
+        """Get a list of configured blogs for the calling user.
+
+        The result will be a ``Blogs`` instance.
+
+        See ``http://flickr.com/services/api/flickr.blogs.getList.html``
+        """
+
+    def postPhoto(blog_id, photo_id, title, description, blog_password=None):
+        """Post a photo on a blog.
+
+        There is no return value.
+
+        See ``http://flickr.com/services/api/flickr.blogs.postPhoto.html``
+        """
+
+class IAPIContacts(IAPIFlickr):
+    """This class provides a pythonic interface to the ``flickr.contacts``
+    namespace."""
+
+    def getList(filter=None):
+        """Get a list of contacts for the calling user.
+
+        The result will be a ``Contacts`` instance (list) and contain
+        ``Contact`` instances
+
+        See ``http://www.flickr.com/services/api/flickr.contacts.getList.html``
+        """
+
+    def getPublicList(user_id):
+        """Get the contact list for the given user.
+
+        The result will be a ``Contacts`` instance (list) and contain
+        ``Contact`` instances
+
+        See ``http://www.flickr.com
+              /services/api/flickr.contacts.getPublicList.html``
+        """
+
+
+class IAPITest(IAPIFlickr):
+    """This class provides a pythonic interface to the ``flickr.test``
+       namespace."""
+
+    def echo(**kw):
+        """Test connectivity to Flickr.
+
+        The result will be an echo of all parameters passed.
+
+        See ``http://www.flickr.com/services/api/flickr.test.echo.html``
+        """
+
+    def login():
+        """A testing method which checks if the caller is logged in then
+        returns their username.
+
+        The result will be an User instance
+
+        See ``http://www.flickr.com/services/api/flickr.test.login.html``
+        """
+
+    def null():
+        """Null test
+
+        There is no return value.
+
+        See ``http://www.flickr.com/services/api/flickr.test.null.html``
+        """
+
+
+class IAPIPhotos(IAPIFlickr):
+    """This class provides a pythonic interface to the ``flickr.photos``
+       namespace."""
+
+    def search(user_id=None, tags=None, tag_mode=None, text=None,
+               min_upload_date=None, max_upload_date=None, min_taken_date=None,
+               max_taken_date=None, license=None, sort=None,
+               privacy_filter=None, extras=None, per_page=None, page=None):
+        """Return a list of photos matching some criteria.
+
+        Only photos visible to the calling user will be returned. To return
+        private or semi-private photos, the caller must be authenticated with
+        'read' permissions, and have permission to view the photos.
+        Unauthenticated calls will only return public photos.
+
+        See ``http://www.flickr.com/services/api/flickr.photos.search.html``
+        """


Property changes on: lovely.flickr/trunk/src/lovely/flickr/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/online.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/online.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/online.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,37 @@
+=====================
+flickr.auth Namespace
+=====================
+
+Usually we test offline as the Yahoo! fraud protection mechanisms block us
+after some testing. :)
+
+  >>> from lovely import flickr
+
+This test connects online to flickr. We need a key and a shared secret:
+
+  >>> API_KEY = u'a8d135acf227a6c9471c5b6d24877080'
+  >>> SECRET = u'cf4c77be4d206e6a'
+
+Furthermore, we use the cookies from a previous authenticated flickr session
+to log into flickr.com:
+
+  >>> COOKIES = u'cookie_accid=3948774; ' + \
+  ...           u'cookie_epass=3ea9f1eecf2886fe8adab2f65884bf1c'
+
+Let's now use this information to authenticate against flickr and retrieve an
+authentication token:
+
+  >>> import lovely.flickr.auth
+  >>> api = flickr.auth.APIAuth(API_KEY, SECRET)
+  >>> frob = flickr.auth.getFrob(API_KEY, SECRET)
+  >>> api.authenticateCookie(frob, [u'write'], COOKIES)
+  >>> token = api.getToken(frob).token
+
+Now that we are logged in, let's ask some interesting questions; for example a
+list of contacts:
+
+  >>> import lovely.flickr.contacts
+  >>> contacts = lovely.flickr.contacts.APIContacts(API_KEY, SECRET, token)
+
+  >>> contacts.getList()
+  <Contacts entries=3>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/online.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/photos.py
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/photos.py	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/photos.py	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,109 @@
+##############################################################################
+#
+# Copyright (c) 2006 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""this module implements the flickr.photos namespace
+
+http://www.flickr.com/services/api/
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import zope.interface
+import zope.schema
+from zope.schema import fieldproperty
+from lovely.flickr import interfaces, flickr
+
+
+class Photos(list):
+    zope.interface.implements(interfaces.IPhotos)
+
+    page = fieldproperty.FieldProperty(interfaces.IPhotos['page'])
+    pages = fieldproperty.FieldProperty(interfaces.IPhotos['pages'])
+    perpage = fieldproperty.FieldProperty(interfaces.IPhotos['perpage'])
+    total = fieldproperty.FieldProperty(interfaces.IPhotos['total'])
+
+    def __init__(self, page, pages, perpage, total):
+        super(Photos, self).__init__()
+        self.page = page
+        self.pages = pages
+        self.perpage = perpage
+        self.total = total
+
+    @classmethod
+    def fromElement(self, element):
+        """See interfaces.IBaseFlickrObject"""
+        args = dict([
+            (name, field.fromUnicode(element.get(name)))
+            for name, field in zope.schema.getFields(interfaces.IPhotos).items()
+            ])
+        photos = Photos(**args)
+        for child in element.getchildren():
+            photos.append(Photo.fromElement(child))
+        return photos
+
+    def __repr__(self):
+        return '<%s entries=%i>' %(self.__class__.__name__, len(self))
+
+class Photo(object):
+    zope.interface.implements(interfaces.IPhoto)
+
+    id = fieldproperty.FieldProperty(interfaces.IPhoto['id'])
+    owner = fieldproperty.FieldProperty(interfaces.IPhoto['owner'])
+    secret = fieldproperty.FieldProperty(interfaces.IPhoto['secret'])
+    server = fieldproperty.FieldProperty(interfaces.IPhoto['server'])
+    title = fieldproperty.FieldProperty(interfaces.IPhoto['title'])
+    ispublic = fieldproperty.FieldProperty(interfaces.IPhoto['ispublic'])
+    isfriend = fieldproperty.FieldProperty(interfaces.IPhoto['isfriend'])
+    isfamily = fieldproperty.FieldProperty(interfaces.IPhoto['isfamily'])
+
+    def __init__(self, id, owner, secret, server, title,
+                 ispublic, isfriend, isfamily):
+        self.id = id
+        self.owner = owner
+        self.secret = secret
+        self.server = server
+        self.title = title
+        self.ispublic = ispublic
+        self.isfriend = isfriend
+        self.isfamily = isfamily
+
+    @classmethod
+    def fromElement(self, element):
+        """See interfaces.IBaseFlickrObject"""
+        args = dict([
+            (name, field.fromUnicode(unicode(element.get(name))))
+            for name, field in zope.schema.getFields(interfaces.IPhoto).items()
+            ])
+        return Photo(**args)
+
+    def __repr__(self):
+        return '<%s %i>' %(self.__class__.__name__, self.id)
+
+class APIPhotos(flickr.APIFlickr):
+    zope.interface.implements(interfaces.IAPIPhotos)
+
+    def search(self, **kw):
+        """See interfaces.IAPIPhotos"""
+        args = interfaces.IAPIPhotos['search'].getSignatureInfo()['optional']
+        params = dict([(arg, kw.get(arg)) for arg in args
+                       if kw.get(arg, None) is not None])
+        params = self.initParameters('flickr.photos.search', **params)
+        elem = self.execute(params)
+        return Photos.fromElement(elem.getchildren()[0])
+
+
+def search(api_key, **kw):
+    __doc__ = interfaces.IAPIPhotos['search'].__doc__
+
+    return APIPhotos(api_key).search(**kw)


Property changes on: lovely.flickr/trunk/src/lovely/flickr/photos.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/photos.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/photos.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/photos.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,66 @@
+=======================
+flickr.photos Namespace
+=======================
+
+This namespace allows to deal with photos. Tag, search,...
+
+  >>> import lovely.flickr.photos
+  >>> from lovely import flickr
+
+Here are the API key and shared secret required to execute the API calls:
+
+  >>> api = flickr.photos.APIPhotos(API_KEY)
+
+
+``search()``
+------------
+
+See ``http://www.flickr.com/services/api/flickr.photos.search.html``
+
+  >>> photos = api.search(tags='dornbirn')
+
+the ``Photos`` object contains a list of single ``Photo`` objects.
+
+  >>> photos
+  <Photos entries=4>
+  >>> photos.page
+  2
+  >>> photos.pages
+  89
+  >>> photos.perpage
+  10
+  >>> photos.total
+  881
+
+A photo itself has some properties too:
+
+  >>> photo = photos[0]
+  >>> photo
+  <Photo 2636>
+  >>> photo.id
+  2636
+  >>> photo.owner
+  u'47058503995 at N01'
+  >>> photo.secret
+  u'a123456'
+  >>> photo.server
+  2
+  >>> photo.title
+  u'test_04'
+  >>> photo.ispublic
+  1
+  >>> photo.isfriend
+  0
+  >>> photo.isfamily
+  0
+
+of course we can pass unicode characters too :)
+
+  >>> api.search(tags=u'Österreich')
+  <Photos entries=1>
+
+You can use the non-pythonic way to query photos too, the result to a query
+is the same:
+
+  >>> flickr.photos.search(API_KEY, tags='dornbirn')
+  <Photos entries=4>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/photos.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/test.py
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/test.py	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/test.py	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,67 @@
+##############################################################################
+#
+# Copyright (c) 2006 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""This module implements the flickr.test namespace
+
+http://www.flickr.com/services/api/
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+
+import zope.interface
+from zope.schema import fieldproperty
+from lovely.flickr import interfaces, flickr, auth
+
+class APITest(flickr.APIFlickr):
+    """This class provides a pythonic interface to the ``flickr.test``
+       namespace.
+    """
+    zope.interface.implements(interfaces.IAPITest)
+
+    def echo(self, **kw):
+        """See interfaces.IAPITest"""
+        params = self.initParameters('flickr.test.echo', **kw)
+        rsp = self.execute(params)
+        return dict([(item.tag, item.text) for item in rsp.getchildren()])
+
+    def login(self):
+        """See interfaces.IAPITest"""
+        params = self.initParameters('flickr.test.login')
+        self.addAuthToken(params)
+        self.sign(params)
+        rsp = self.execute(params)
+        user = rsp.find('user')
+        return auth.User(unicode(user.get('id')),
+                         unicode(user.find('username').text))
+
+    def null(self):
+        """See interfaces.IAPITest"""
+        params = self.initParameters('flickr.test.null')
+        self.addAuthToken(params)
+        self.sign(params)
+        self.execute(params)
+
+
+def echo(api_key, **kw):
+    __doc__ = interfaces.IAPITest['echo'].__doc__
+    return APITest(api_key).echo(**kw)
+
+def login(api_key, secret, auth_token):
+    __doc__ = interfaces.IAPITest['login'].__doc__
+    return APITest(api_key, secret, auth_token).login()
+
+def null(api_key, secret, auth_token):
+    __doc__ = interfaces.IAPITest['null'].__doc__
+    return APITest(api_key, secret, auth_token).null()


Property changes on: lovely.flickr/trunk/src/lovely/flickr/test.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/test.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/test.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/test.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,54 @@
+======================
+flickr.test Namespace
+======================
+
+This namespace allows to connect photos with blogs.
+
+  >>> import lovely.flickr.test
+  >>> from lovely import flickr
+
+As you may know already, this implementation provides an object-oriented and
+procedural implementation of the Flickr API. For this namespace we need an
+authentication token, so get it.
+
+  >>> api = flickr.test.APITest(API_KEY, SECRET, TOKEN)
+
+
+``echo()``
+----------
+
+See ``http://flickr.com/services/api/flickr.test.echo.html``
+
+Echo the server to make sure it is alive.
+
+  >>> flickr.test.echo(api_key=API_KEY, foo='bar')
+  {'api_key': 'ffd1eeacf227a6c9471c5b6d24ad77099', 'method': 'flickr.test.echo',
+   'foo': 'bar'}
+
+  >>> api.echo(foo='bar')
+  {'api_key': 'ffd1eeacf227a6c9471c5b6d24ad77099', 'method': 'flickr.test.echo',
+   'foo': 'bar'}
+
+
+``login()``
+----------
+
+See ``http://flickr.com/services/api/flickr.test.login.html``
+
+Provide all necessary authentication information and login to the service:
+
+  >>> flickr.test.login(API_KEY, SECRET, TOKEN)
+  <User u'lovelyflickr' - None>
+  >>> api.login()
+  <User u'lovelyflickr' - None>
+
+``null()``
+----------
+
+See ``http://flickr.com/services/api/flickr.test.null.html``
+
+Connect to the service with all credentials and return nothing:
+
+  >>> flickr.test.null(API_KEY, SECRET, TOKEN)
+
+  >>> api.null()


Property changes on: lovely.flickr/trunk/src/lovely/flickr/test.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/__init__.py
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/__init__.py	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/__init__.py	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1 @@
+# Make a package


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/auth.checkToken-1.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/auth.checkToken-1.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/auth.checkToken-1.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<auth>
+  <token>909163-79a56fd4b2ca4a76</token>
+  <perms>write</perms>
+  <user nsid="97713796 at N00" username="lovelyflickr" fullname="Lovely Flickr" />
+</auth>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/auth.checkToken-1.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/auth.getFrob-1.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/auth.getFrob-1.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/auth.getFrob-1.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<frob>2572639-8aac54751ebab5a7</frob>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/auth.getFrob-1.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/auth.getFullToken-1.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/auth.getFullToken-1.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/auth.getFullToken-1.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<auth>
+  <token>909163-79a56fd4b2ca4a76</token>
+  <perms>write</perms>
+  <user nsid="97713796 at N00" username="lovelyflickr" fullname="Lovely Flickr" />
+</auth>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/auth.getFullToken-1.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/auth.getToken-1.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/auth.getToken-1.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/auth.getToken-1.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<auth>
+  <token>909163-79a56fd4b2ca4a76</token>
+  <perms>write</perms>
+  <user nsid="97713796 at N00" username="lovelyflickr" fullname="Lovely Flickr" />
+</auth>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/auth.getToken-1.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/blogs.getList-1.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/blogs.getList-1.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/blogs.getList-1.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<blogs>
+  <blog id="73" name="Bloxus test" needspassword="0"
+        url="http://remote.bloxus.com/" />
+  <blog id="74" name="Manila Test" needspassword="1"
+        url="http://flickrtest1.userland.com/" />
+</blogs>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/blogs.getList-1.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-1.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-1.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-1.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<contacts>
+  <contact nsid="12037949629 at N01" username="Eric" iconserver="1"
+           realname="Eric Costello"
+           friend="1" family="0" ignored="1" />
+  <contact nsid="12037949631 at N01" username="neb" iconserver="1"
+           realname="Ben Cerveny"
+           friend="0" family="0" ignored="0" />
+  <contact nsid="41578656547 at N01" username="cal_abc" iconserver="1"
+           realname="Cal Henderson"
+           friend="1" family="1" ignored="0" />
+</contacts>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-1.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-2.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-2.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-2.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<contacts>
+  <contact nsid="12037949629 at N01" username="Eric" iconserver="1"
+           realname="Eric Costello"
+           friend="1" family="0" ignored="1" />
+  <contact nsid="41578656547 at N01" username="cal_abc" iconserver="1"
+           realname="Cal Henderson"
+           friend="1" family="1" ignored="0" />
+</contacts>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-2.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-3.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-3.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-3.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<contacts>
+  <contact nsid="41578656547 at N01" username="cal_abc" iconserver="1"
+           realname="Cal Henderson"
+           friend="1" family="1" ignored="0" />
+</contacts>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getList-3.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getPublicList-1.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getPublicList-1.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getPublicList-1.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<contacts>
+  <contact nsid="12037949629 at N01" username="Eric" iconserver="1"
+           ignored="1" />
+  <contact nsid="12037949631 at N01" username="neb" iconserver="1"
+           ignored="0" />
+  <contact nsid="41578656547 at N01" username="cal_abc" iconserver="1"
+           ignored="0" />
+</contacts></rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/contacts.getPublicList-1.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/photos.search-1.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/photos.search-1.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/photos.search-1.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<photos page="2" pages="89" perpage="10" total="881">
+  <photo id="2636" owner="47058503995 at N01"
+         secret="a123456" server="2" title="test_04"
+         ispublic="1" isfriend="0" isfamily="0" />
+  <photo id="2635" owner="47058503995 at N01"
+         secret="b123456" server="2" title="test_03"
+         ispublic="0" isfriend="1" isfamily="1" />
+  <photo id="2633" owner="47058503995 at N01"
+         secret="c123456" server="2" title="test_01"
+         ispublic="1" isfriend="0" isfamily="0" />
+  <photo id="2610" owner="12037949754 at N01"
+         secret="d123456" server="2" title="00_tall"
+         ispublic="1" isfriend="0" isfamily="0" />
+</photos>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/photos.search-1.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/photos.search-2.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/photos.search-2.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/photos.search-2.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<photos page="2" pages="89" perpage="10" total="881">
+  <photo id="2636" owner="47058503995 at N01"
+         secret="a123456" server="2" title="test_04"
+         ispublic="1" isfriend="0" isfamily="0" />
+</photos>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/photos.search-2.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/success.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/success.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/success.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/success.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/test.echo-1.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/test.echo-1.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/test.echo-1.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<api_key>ffd1eeacf227a6c9471c5b6d24ad77099</api_key>
+<method>flickr.test.echo</method>
+<foo>bar</foo>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/test.echo-1.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/test.echo-2.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/test.echo-2.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/test.echo-2.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,3 @@
+<rsp stat="err">
+<err code="100" msg="Invalid API Key (Key not found)" />
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/test.echo-2.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/test.login-1.txt
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/test.login-1.txt	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/test.login-1.txt	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<rsp stat="ok">
+<user id="97713796 at N00">
+  <username>lovelyflickr</username>
+</user>
+</rsp>


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/test.login-1.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: lovely.flickr/trunk/src/lovely/flickr/tests/test_doc.py
===================================================================
--- lovely.flickr/trunk/src/lovely/flickr/tests/test_doc.py	2006-08-17 15:55:52 UTC (rev 69613)
+++ lovely.flickr/trunk/src/lovely/flickr/tests/test_doc.py	2006-08-17 16:49:55 UTC (rev 69614)
@@ -0,0 +1,155 @@
+# -*- coding: latin-1 -*-
+##############################################################################
+#
+# Copyright (c) 2006 Lovely Systems and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Tag test setup
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+
+import cgi
+import cStringIO
+import doctest
+import os
+import unittest
+import urllib
+
+try:
+    from zope.testing.doctestunit import DocFileSuite
+except ImportError:
+    from doctest import DocFileSuite
+
+API_KEY = u'ffd1eeacf227a6c9471c5b6d24ad77099'
+SECRET = u'ff4cffbe4d209ec4'
+FROB = u'2572639-8aac54751ebab5a7'
+TOKEN = u'909163-79a56fd4b2ca4a76'
+MINI_TOKEN = u'909-a16-3fa'
+
+responses = {
+    # flickr.auth
+    ('auth.getFrob', ('api_key='+API_KEY,)): 'auth.getFrob-1.txt',
+    ('auth.getToken', ('api_key='+API_KEY, 'frob='+FROB)):
+        'auth.getToken-1.txt',
+    ('auth.checkToken', ('api_key='+API_KEY, 'auth_token='+TOKEN)):
+        'auth.checkToken-1.txt',
+    ('auth.getFullToken', ('api_key='+API_KEY, 'mini_token=909a163fa')):
+        'auth.getFullToken-1.txt',
+
+    # flickr.blogs
+    ('blogs.getList', ('api_key='+API_KEY, 'auth_token='+TOKEN)):
+        'blogs.getList-1.txt',
+
+    # flickr.contacts
+    ('contacts.getList', ('api_key='+API_KEY, 'auth_token='+TOKEN)):
+        'contacts.getList-1.txt',
+    ('contacts.getList',
+     ('api_key='+API_KEY, 'auth_token='+TOKEN, 'filter=friends')):
+        'contacts.getList-2.txt',
+    ('contacts.getList',
+     ('api_key='+API_KEY, 'auth_token='+TOKEN, 'filter=family')):
+        'contacts.getList-3.txt',
+    ('contacts.getPublicList', ('api_key='+API_KEY, 'user_name=lovelyflickr')):
+        'contacts.getPublicList-1.txt',
+
+    # flickr.favorites
+
+    # flickr.photos
+    ('photos.search', ('api_key='+API_KEY, u'tags=dornbirn')):
+        'photos.search-1.txt',
+    ('photos.search', ('api_key='+API_KEY, u'tags=Österreich')):
+        'photos.search-2.txt',
+
+    # flickr.test
+    ('test.echo', ('api_key='+API_KEY, 'foo=bar')): 'test.echo-1.txt',
+    ('test.echo', ('api_key=bullshit',)): 'test.echo-2.txt',
+    ('test.login', ('api_key='+API_KEY, 'auth_token='+TOKEN)):
+        'test.login-1.txt',
+    }
+
+def urlopen(url, data=None):
+    if '?' in url and not url.endswith('?'):
+        qs = url.split('?')[1]
+        key = dict([
+            (name, value[0])
+            for (name, value) in cgi.parse_qs(qs).items() ])
+    else:
+        fs = cgi.FieldStorage(
+            cStringIO.StringIO(data), environ={'REQUEST_METHOD': 'POST'})
+        key = dict([(field.name, field.value) for field in fs.list])
+
+    method = key['method'][7:]
+    del key['method']
+    if 'api_sig' in key:
+        del key['api_sig']
+    key = ['='.join(item) for item in sorted(key.items())]
+    fn = responses.get((method, tuple(key)), 'success.txt')
+    # For testing
+    if fn == 'success.txt':
+        sig = (method, tuple(key))
+        #import pdb; pdb.set_trace()
+        pass
+    fn = os.path.join(os.path.dirname(__file__), fn)
+    return open(fn, 'r')
+
+def setUp(test):
+    from lovely.flickr import auth, flickr
+    auth.APIAuth._authenticate_for_real = False
+    flickr.APIFlickr._urlopen = urlopen
+    test.globs.update(
+        {'API_KEY': API_KEY, 'SECRET': SECRET, 'FROB': FROB, 'TOKEN': TOKEN})
+
+def tearDown(test):
+    from lovely.flickr import auth, flickr
+    auth.APIAuth._authenticate_for_real = True
+    flickr.APIFlickr._urlopen = urllib.urlopen
+
+
+
+def test_suite():
+    return unittest.TestSuite((
+        DocFileSuite('../README.txt',
+                     setUp=setUp, tearDown=tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        DocFileSuite('../auth.txt',
+                     setUp=setUp, tearDown=tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        DocFileSuite('../online.txt',
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        DocFileSuite('../blogs.txt',
+                     setUp=setUp, tearDown=tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        DocFileSuite('../contacts.txt',
+                     setUp=setUp, tearDown=tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        #DocFileSuite('../favorites.txt',
+        #             setUp=setUp, tearDown=tearDown,
+        #             optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+        #             ),
+        DocFileSuite('../photos.txt',
+                     setUp=setUp, tearDown=tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        DocFileSuite('../test.txt',
+                     setUp=setUp, tearDown=tearDown,
+                     optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                     ),
+        ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')


Property changes on: lovely.flickr/trunk/src/lovely/flickr/tests/test_doc.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native



More information about the Checkins mailing list