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
Example #2
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
Example #3
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,
            }))
    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,
                }))
    def to_python(self, obj, name, value):
        field_type = obj._schema_store['fields'][name]['type']
        new_value = value

        if type(value) in (str, ):
            if field_type == 'datetime':
                new_value = dateparser.parse(value)
            elif field_type == 'date':
                new_value = dateparser.parse(value).date()
            elif field_type in (
                    'list',
                    'json',
            ):
                new_value = value

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

        obj._fields[name] = new_value
Example #6
0
    def dispatch(self, request_type, request, **kwargs):
        # this needs to be called before method check
        try:
            self.is_authenticated(request)

            response = super(ModelResource, self).dispatch(request_type, request, **kwargs)
        except Exception, e:
            logger.exception(logf({"message": "A fatal error has occurred during processing dispatch", "exception": e}))
            raise e
    def _response(self):
        if self.__response:
            return self.__response

        serializer = slumber.serialize.Serializer(
            default=self.model._main_client._store['format'])

        if self._url is not None:
            logger.debug(
                logf({
                    'message': 'Getting cache...',
                    'key': self._url,
                }))

            cached = cache.get(self._url)
            if cached:
                logger.debug(
                    logf({
                        'message': 'Found in cache.',
                        'key': self._url,
                        'value': cached,
                    }))

                self.refresh(serializer.loads(cached))
                return self.__response

        response = super(Response, self)._response

        if self._url is not None:
            if 'model' in response:
                del (response['model'])

            content = serializer.dumps(response)

            logger.debug(
                logf({
                    'message': 'Setting cache...',
                    'key': self._url,
                    'value': content,
                }))

            cache.set(self._url, content)

        return response
Example #8
0
    def debug(self, request, response, log=logger.debug):
        info = log if log == logger.exception else logger.info

        data = {
            "message": "API called.",
            "user": request.user,
            "method": request.method,
            "status_code": response.status_code,
            "path_info": request.META.get("PATH_INFO"),
            "query_string": request.META.get("QUERY_STRING"),
        }

        info(logf(data))

        if len(request.raw_post_data):
            data["post_data"] = request.raw_post_data.decode("utf-8")

        if len(response.content):
            data["response"] = response.content.decode("utf-8")

        log(logf(data))
    def debug(self, request, response, log=logger.debug):
        info = log if log == logger.exception else logger.info

        data = {
            'message': 'API called.',
            'user': request.user,
            'method': request.method,
            'status_code': response.status_code,
            'path_info': request.META.get('PATH_INFO'),
            'query_string': request.META.get('QUERY_STRING'),
        }

        info(logf(data))

        if len(request.raw_post_data):
            data['post_data'] = request.raw_post_data.decode('utf-8')

        if len(response.content):
            data['response'] = response.content.decode('utf-8')

        log(logf(data))
Example #10
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)
Example #11
0
    def _response(self):
        if self.__response:
            return self.__response

        serializer = slumber.serialize.Serializer(default=self.model._main_client._store['format'])

        if self._url is not None:
            logger.debug(logf({
                'message': 'Getting cache...',
                'key': self._url,
            }))

            cached = cache.get(self._url)
            if cached:
                logger.debug(logf({
                    'message': 'Found in cache.',
                    'key': self._url,
                    'value': cached,
                }))

                self.refresh(serializer.loads(cached))
                return self.__response

        response = super(Response, self)._response

        if self._url is not None:
            if 'model' in response:
                del(response['model'])

            content = serializer.dumps(response)

            logger.debug(logf({
                'message': 'Setting cache...',
                'key': self._url,
                'value': content,
            }))

            cache.set(self._url, content)

        return response
Example #12
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)
    def dispatch(self, request_type, request, **kwargs):
        # this needs to be called before method check
        try:
            self.is_authenticated(request)

            response = super(ModelResource,
                             self).dispatch(request_type, request, **kwargs)
        except Exception, e:
            logger.exception(
                logf({
                    'message':
                    'A fatal error has occurred during processing dispatch',
                    'exception': e,
                }))
            raise e
Example #14
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.'))
Example #15
0
    def schema(self, model_name=None):
        path = '.'.join(self._base_url.replace(self._api_url,
                                               '').split('/')[:-1])

        if model_name is None:
            model_name = path
            url = self._base_url
        else:
            url = self._url_gen('%s/schema/' % model_name)

        if model_name not in ProxyClient._schemas:
            try:
                self._schema_store[model_name] = self.request(url)
                ProxyClient._schemas[model_name] = self._schema_store[model_name]
            except Exception, e:
                logger.debug(logf({
                    'message': 'Couldn\'t fetch the schema definition for some reason.',
                    'schema': model_name,
                }))
Example #16
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.'))
Example #17
0
    def schema(self, model_name=None):
        path = '.'.join(
            self._base_url.replace(self._api_url, '').split('/')[:-1])

        if model_name is None:
            model_name = path
            url = self._base_url
        else:
            url = self._url_gen('%s/schema/' % model_name)

        if model_name not in ProxyClient._schemas:
            try:
                self._schema_store[model_name] = self.request(url)
                ProxyClient._schemas[model_name] = self._schema_store[
                    model_name]
            except Exception, e:
                logger.debug(
                    logf({
                        'message':
                        'Couldn\'t fetch the schema definition for some reason.',
                        'schema': model_name,
                    }))
Example #18
0
    def is_authenticated(self, request):
        super(ModelResource, self).is_authenticated(request)

        # allow superuser all operations dynamically
        if request.user.is_superuser:

            logger.debug(
                logf(
                    {
                        "message": "Hello superuser you can do anything with this resource.",
                        "resource": request.META["PATH_INFO"],
                    }
                )
            )

            self._meta.list_allowed_methods = ALL_METHODS
            self._meta.detail_allowed_methods = ALL_METHODS

            for field in self._meta.excludes:
                self.fields[field] = fields.CharField(attribute=field, blank=True, null=True, readonly=True)

            self._meta.excludes = []
Example #19
0
    def to_python(self, obj, name, value):
        field_type = obj._schema_store['fields'][name]['type']
        new_value = value

        if type(value) in (str,):
            if field_type == 'datetime':
                new_value = dateparser.parse(value)
            elif field_type == 'date':
                new_value = dateparser.parse(value).date()
            elif field_type in ('list', 'json',):
                new_value = value

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

        obj._fields[name] = new_value
    def is_authenticated(self, request):
        super(ModelResource, self).is_authenticated(request)

        # allow superuser all operations dynamically
        if request.user.is_superuser:

            logger.debug(
                logf({
                    'message':
                    'Hello superuser you can do anything with this resource.',
                    'resource': request.META['PATH_INFO'],
                }))

            self._meta.list_allowed_methods = ALL_METHODS
            self._meta.detail_allowed_methods = ALL_METHODS

            for field in self._meta.excludes:
                self.fields[field] = fields.CharField(attribute=field,
                                                      blank=True,
                                                      null=True,
                                                      readonly=True)

            self._meta.excludes = []
Example #21
0
        # 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)

        logger.debug(
            logf({
                'message':
                'Need namespace schema.',
                'attribute':
                name,
                'resource_uri':
                self._response[name],
                'client_key':
                ProxyClient.build_client_key(
                    base_client._api_url, **{
                        'version': base_client._version,
                        'namespace': namespace,
                        'auth': base_client._auth,
                    }),
            }))

        proxy_client = ProxyClient.get(base_client._api_url,
                                       version=base_client._version,
                                       namespace=namespace,
                                       auth=base_client._auth)
        proxy_client.schema()

        model = proxy_client._model_gen(resource_name)
Example #22
0
        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)

        logger.debug(logf({
            'message': 'Need namespace schema.',
            'attribute': name,
            'resource_uri': self._response[name],
            'client_key': ProxyClient.build_client_key(base_client._api_url, **{
                'version': base_client._version,
                'namespace': namespace,
                'auth': base_client._auth,
            }),
        }))

        proxy_client = ProxyClient.get(base_client._api_url,
                                       version=base_client._version,
                                       namespace=namespace,
                                       auth=base_client._auth)
        proxy_client.schema()

        model = proxy_client._model_gen(resource_name)

        # set manager alias
        if name is not resource_name:
Example #23
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)