Esempio n. 1
0
    def __init__(self, *args, **kwargs):

        if (self._meta.abstract
                or (models and isinstance(self, models.Model))):
            super(Proxy, self).__init__(*args, **kwargs)
            return

        if not self._meta.api_url:
            raise exceptions.ProxyException(
                _('"API_URL" not found in settings or '
                  '"api_url" not found in kwargs.'))

        self._client = self._meta.client.get(
            self._meta.api_url,
            version=self._meta.version,
            namespace=self._meta.namespace
            or '/'.join(self.__module__.split('.')[1:-1]),
            auth=self._meta.auth if self._meta.auth[0] is not None else None,
            proxy=self)

        try:
            class_name = self.__class__.__name__
            self._resource = getattr(
                self._client, self._meta.resource_name or class_name,
                getattr(self._client, self._meta.resource_name
                        or class_name.lower(), None))
        except AttributeError, e:
            logger.debug(
                logf({
                    'message':
                    'API seems not to have endpoint for the resource.',
                    'resource': class_name,
                }))
Esempio n. 2
0
 def filter(self, *args, **kwargs):
     if 'id__in' in kwargs:
         raise exceptions.ProxyException(
             _('"id__in" is not supported '
               'in ManyToManyManager.'))
     return QuerySet(self.model, query=self._query,
                     response_class=Response).filter(*args, **kwargs)
Esempio n. 3
0
class ProxyMeta(type):
    def __new__(cls, name, bases, attrs):

        declarative = Response not in bases

        if declarative and name in ProxyClient._proxies:
            # returns existing proxy object
            return ProxyClient._proxies[name]

        meta = attrs.pop('Meta', attrs.pop('_meta', None))
        abstract = getattr(meta, 'abstract', False)

        # create new proxy class
        proxy = super(ProxyMeta, cls).__new__(cls, name, bases, attrs)
        proxy._meta = ProxyOptions(meta)
        proxy._meta.abstract = abstract

        if abstract:
            return proxy

        if not proxy._meta.model:
            try:
                proxy._meta.model = getattr(
                    import_module('%s.models' %
                                  proxy.__module__.rpartition('.')[0]), name)
            except Exception, e:
                pass

        if proxy._meta.api_url:
            # return proxy class or object
            return proxy() if declarative else proxy
        else:
            # return model class which implements proxy interfaces
            if name not in ProxyClient._models.keys():
                model = proxy._meta.model

                if not model:
                    raise exceptions.ProxyException(
                        _('Module seems not to be imported '
                          'within django application context '
                          '("%s" model not found). Specify '
                          'proper model in Meta class.') % name)

                # implement proxy mixin
                def __init__(obj, *args, **kwargs):
                    obj.__init__original(*args, **kwargs)
                    mixin(obj.__class__, proxy)
                    obj.__module__ = proxy.__module__
                    obj.__init_proxy__()

                model.__init__original = model.__init__
                model.__init__ = __init__

                ProxyClient._models[name] = model

        return ProxyClient._models[name]
Esempio n. 4
0
    def request(self, url, method='GET'):
        nocache = False

        if method != 'GET':
            logger.debug(logf({
                'message': 'Deleting cache...',
                'key': url,
            }))

            cache.delete(url)
            nocache = True
        else:
            logger.debug(logf({
                'message': 'Getting cache...',
                'key': url,
            }))

            result = cache.get(url)

            if result is not None:
                logger.debug(
                    logf({
                        'message': 'Found in cache.',
                        'key': url,
                        'value': result,
                    }))

                return result

        # override super to handle HTTP response error
        client = self._main_client._store
        url = self._url_gen(url)
        response = client['session'].request(method, url)

        if response.status_code >= 300:
            raise exceptions.ProxyException(
                'Failed to fetch resource (%s, %s %s)' % (
                    url,
                    method,
                    response.status_code,
                ))

        serializer = slumber.serialize.Serializer(default=client['format'])
        result = serializer.loads(response.content)

        if not nocache:
            logger.debug(
                logf({
                    'message': 'Setting cache...',
                    'url': url,
                    'value': result,
                }))

            cache.set(url, result)

        return result
Esempio n. 5
0
 def metadata(self):
     try:
         meta = getattr(import_module(self.__module__),
                        self.meta_type_display)
     except Exception, e:
         logger.exception(
             logf({
                 'message': 'No metadata model found.',
                 'meta_type': self.meta_type_display,
                 'exception': e,
             }))
         raise exceptions.ProxyException('No metadata model for '
                                         '%s found.' %
                                         self.meta_type_display)
Esempio n. 6
0
 def delete(obj):
     break_cache(obj)
     try:
         model.delete_original(obj)
     except KeyError, e:
         try:
             obj._client(get_pk(obj)).delete()
             obj._clear_fields()
         except Exception, e:
             raise exceptions.ProxyException(
                 _('Failed to delete an object (%s): %s' % (
                     obj,
                     e,
                 )))
Esempio n. 7
0
    def to_serializable(self, obj, name):
        field_type = obj._schema_store['fields'][name]['type']
        value = new_value = obj._fields[name]

        if field_type == 'date' and type(value) not in (str, ):
            new_value = value.isoformat()

        if value != new_value:
            logger.debug(
                logf({
                    'message': 'Serializing from python...',
                    'field': name,
                    'type': field_type,
                    'from': value.__repr__(),
                    'to': new_value.__repr__()
                }))
            return new_value

        raise exceptions.ProxyException(_('Raise to call super.'))
Esempio n. 8
0
class Response(client.Response):
    def __init__(self, model, response=None, url=None, **kwargs):
        # implement proxy mixin
        model_name = model._model_name.lower()
        if model_name in ProxyClient._proxies:
            proxy = ProxyClient._proxies[model_name].__class__
            extend(self, proxy, proxy.__dict__.copy())
            self.__init_proxy__()

        super(Response, self).__init__(model, response, url, **kwargs)

        # the magic
        dir(self)

    def __repr__(self):
        if hasattr(self, 'resource_uri'):
            return self.resource_uri
        return '<%s: None>' % self.model._model_name.title()

    def __getattr__(self, name):
        """
        Overrides to support api namespace and to_one class diversity.
        """
        try:
            if name not in self._response:
                raise AttributeError(name)

            elif 'related_type' not in self._schema['fields'][name]:
                return self.__getitem__(name)

        except AttributeError, e:
            if name in PK_ID:
                return get_pk(self)

            return getattr(self.model, name)

        # resolves foreign key references in another api namespace
        # expects to be called with detail url like /api/v1/<resource>/<id>|schema/
        #
        # CAVEAT: resource_uri of referred resource has to have the same version
        base_client = self.model._base_client

        if name in self._schema['fields']:
            schema = self._schema['fields'][name]

            if ('related_type' in schema and schema['related_type'] in (
                    'to_one',
                    'to_many',
            )):
                if schema.get('schema'):
                    schema_uri = schema.get('schema')
                else:
                    try:
                        schema_uri = self._response[name]
                        schema_uri = schema_uri[0] if (isinstance(
                            schema_uri, list)) else schema_uri
                        schema_uri = schema_uri['resource_uri'] if (isinstance(
                            schema_uri, dict)) else schema_uri

                        logger.debug(
                            logf({
                                'message':
                                'Trying to guess schema info from '
                                'schema_uri.',
                                'schema_uri':
                                schema_uri,
                            }))
                    except Exception, e:
                        raise exceptions.ProxyException(
                            _('Couldn\'t identify related '
                              'field schema (%s).') % name)
Esempio n. 9
0
                        logger.debug(
                            logf({
                                'message':
                                'Trying to guess schema info from '
                                'schema_uri.',
                                'schema_uri':
                                schema_uri,
                            }))
                    except Exception, e:
                        raise exceptions.ProxyException(
                            _('Couldn\'t identify related '
                              'field schema (%s).') % name)
        else:
            raise exceptions.ProxyException(
                _('The field seems not to be defined '
                  'in the schema (%s).') % name)

        api_url = base_client._api_url
        version = base_client._version
        paths = filter(
            None,
            schema_uri.replace(base_client._api_path, '').split('/'))

        # strip <id> or ``schema`` part and extract resource_name
        paths.pop()
        resource_name = paths.pop()

        if version in paths: paths.remove(version)
        namespace = '/'.join(paths)