Example #1
0
    def _iter_recent(self, progress_callback=None):
        """Get the recently updated photos."""

        page, pages = 1, 1

        while page <= pages:
            resp = self.proxy.photos_recentlyUpdated(
                page=page,
                min_date=self.last_update + 1,
                extras=', '.join((
                    'date_upload',
                    'last_update',
                    'o_dims',
                    'original_format',
                    'url_o',
                )))

            photos = resp.find('photos')

            if photos:
                for photo in photos.findall('photo'):
                    yield photo.attrib
            elif photos is None:
                raise FlickrError('No photos in server response.')
            else:
                break

            pages = int(photos.get('pages'))

            if progress_callback:
                progress_callback('photos', (page, pages))

            page = int(photos.get('page')) + 1
Example #2
0
def get_proxy(key=API_KEY, secret=API_SECRET, wait_callback=None):
    """Get a web service proxy to Flickr."""

    # Setup the API proxy.
    perms = 'write'
    proxy = flickrapi.FlickrAPI(key, secret, format='etree')

    try:
        # Authorize.
        auth_response = proxy.get_token_part_one(perms=perms)
    except ExpatError:  # FlickrAPI chokes on non-XML responses.
        raise FlickrError('Non-XML response from Flickr')

    while True:
        try:
            if proxy.get_token_part_two(auth_response):
                break
        except FlickrError as e:
            # Wait for frob confirmation.
            frob_ok = filter(lambda x: x.startswith('Error: 108'), e)
            if frob_ok and wait_callback \
               and not wait_callback(proxy, perms, *auth_response):
                continue
            raise

    return proxy
Example #3
0
    def parse_xmlnode(self, rest_xml):
        '''Parses a REST XML response from Flickr into an XMLNode object.'''

        rsp = XMLNode.parse(rest_xml, store_xml=True)
        if rsp['stat'] == 'ok':
            return rsp

        err = rsp.err[0]
        raise FlickrError(u'Error: %(code)s: %(msg)s' % err)
Example #4
0
    def parse_xmlnode(self, rest_xml):
        u'''Parses a REST XML response from Flickr into an XMLNode object.''' #$NON-NLS-1$

        rsp = XMLNode.parse(rest_xml, store_xml=True)
        if rsp[u'stat'] == u'ok' or not self.fail_on_error: #$NON-NLS-2$ #$NON-NLS-1$
            return rsp
        
        err = rsp.err[0]
        raise FlickrError(u'Error: %(code)s: %(msg)s' % err) #$NON-NLS-1$
Example #5
0
    def parse_etree(self, rest_xml):
        u'''Parses a REST XML response from Flickr into an ElementTree object.''' #$NON-NLS-1$

        # Only import it here, to maintain Python 2.4 compatibility
        import xml.etree.ElementTree

        rsp = xml.etree.ElementTree.fromstring(rest_xml)
        if rsp.attrib[u'stat'] == u'ok' or not self.fail_on_error: #$NON-NLS-2$ #$NON-NLS-1$
            return rsp
        
        err = rsp.find(u'err') #$NON-NLS-1$
        raise FlickrError(u'Error: %s: %s' % ( #$NON-NLS-1$
            err.attrib[u'code'], err.attrib[u'msg'])) #$NON-NLS-2$ #$NON-NLS-1$
Example #6
0
    def test_failure(cls, rsp, exception_on_error=True):
        u"""Exit app if the rsp XMLNode indicates failure.""" #$NON-NLS-1$

        LOG.warn(u"FlickrAPI.test_failure has been deprecated and will be " #$NON-NLS-1$
                 u"removed in FlickrAPI version 1.2.") #$NON-NLS-1$

        if rsp[u'stat'] != u"fail": #$NON-NLS-2$ #$NON-NLS-1$
            return
        
        message = cls.get_printable_error(rsp)
        LOG.error(message)
        
        if exception_on_error:
            raise FlickrError(message)
Example #7
0
    def parse_etree(self, rest_xml):
        '''Parses a REST XML response from Flickr into
           an ElementTree object.'''

        try:
            import xml.etree.ElementTree as ElementTree
        except ImportError:
            # For Python 2.4 compatibility:
            try:
                import elementtree.ElementTree as ElementTree
            except ImportError:
                raise ImportError("You need to install "
                                  "ElementTree for using the etree format")

        rsp = ElementTree.fromstring(rest_xml)
        if rsp.attrib['stat'] == 'ok':
            return rsp

        err = rsp.find('err')
        raise FlickrError(u'Error: %(code)s: %(msg)s' % err.attrib)
Example #8
0
    def __extract_upload_response_format(self, kwargs):
        '''Returns the response format given in kwargs['format'], or
        the default format if there is no such key.

        If kwargs contains 'format', it is removed from kwargs.

        If the format isn't compatible with Flickr's upload response
        type, a FlickrError exception is raised.
        '''

        # Figure out the response format
        format = kwargs.get('format', self.default_format)
        if format not in rest_parsers and format != 'rest':
            raise FlickrError('Format %s not supported for uploading '
                              'photos' % format)

        # The format shouldn't be used in the request to Flickr.
        if 'format' in kwargs:
            del kwargs['format']

        return format
def build_flickr_call(module,
                      method,
                      response_format="json",
                      quiet=False,
                      context=None):
    """
    A builder to flickr api call.
    """
    flickr = get_flickr_object()
    context = context or {}
    call = "%s.%s" % (module, method)
    command = getattr(flickr, call)

    # add context bases
    context['format'] = response_format
    context['user_id'] = settings.USER_ID

    try:
        return command(**context)
    except FlickrError as e:
        if not quiet:
            raise FlickrError(e.message)
Example #10
0
    def get_token_part_one(self, perms="read", auth_callback=None):
        """Get a token either from the cache, or make a new one from
        the frob.

        This first attempts to find a token in the user's token cache
        on disk. If that token is present and valid, it is returned by
        the method.

        If that fails (or if the token is no longer valid based on
        flickr.auth.checkToken) a new frob is acquired. If an auth_callback
        method has been specified it will be called. Otherwise the frob is
        validated by having the user log into flickr (with a browser).

        To get a proper token, follow these steps:
            - Store the result value of this method call
            - Give the user a way to signal the program that he/she
              has authorized it, for example show a button that can be
              pressed.
            - Wait for the user to signal the program that the
              authorization was performed, but only if there was no
              cached token.
            - Call flickrapi.get_token_part_two(...) and pass it the
              result value you stored.

        The newly minted token is then cached locally for the next
        run.

        perms
            "read", "write", or "delete"
        auth_callback
            method to be called if authorization is needed. When not
            passed, ``self.validate_frob(...)`` is called. You can
            call this method yourself from the callback method too.

            If authorization should be blocked, pass
            ``auth_callback=False``.

            The auth_callback method should take ``(frob, perms)`` as
            parameters.

        An example::

            (token, frob) = flickr.get_token_part_one(perms='write')
            if not token:
                raw_input("Press ENTER after you authorized this program")
            flickr.get_token_part_two((token, frob))

        Also take a look at ``authenticate_console(perms)``.
        """

        # Check our auth_callback parameter for correctness before we
        # do anything
        authenticate = self.validate_frob
        if auth_callback is not None:
            if hasattr(auth_callback, '__call__'):
                # use the provided callback function
                authenticate = auth_callback
            elif auth_callback is False:
                authenticate = None
            else:
                # Any non-callable non-False value is invalid
                raise ValueError('Invalid value for auth_callback: %s' %
                                 auth_callback)

        # see if we have a saved token
        token = self.token_cache.token
        frob = None

        # see if it's valid
        if token:
            LOG.debug("Trying cached token '%s'" % token)
            try:
                rsp = self.auth_checkToken(auth_token=token, format='xmlnode')

                # see if we have enough permissions
                tokenPerms = rsp.auth[0].perms[0].text
                if tokenPerms == "read" and perms != "read":
                    token = None
                elif tokenPerms == "write" and perms == "delete":
                    token = None
            except FlickrError:
                LOG.debug("Cached token invalid")
                self.token_cache.forget()
                token = None

        # get a new token if we need one
        if not token:
            # If we can't authenticate, it's all over.
            if not authenticate:
                raise FlickrError('Authentication required but '
                                  'blocked using auth_callback=False')

            # get the frob
            LOG.debug("Getting frob for new token")
            rsp = self.auth_getFrob(auth_token=None, format='xmlnode')

            frob = rsp.frob[0].text
            authenticate(frob, perms)

        return (token, frob)