Esempio n. 1
0
 def __init__(self,
              service_url,
              auth=None,
              params=None,
              serializer=None,
              verify=False):
     self._auth = auth
     self._params = params
     self._verify = verify
     self._service = Service(service_url)
     self._serializer = JsonSerializer() if serializer is None \
                                 else serializer
     self._endpoints = self._get()  # The API endpoint should return
Esempio n. 2
0
 def __init__(self, service_url, auth=None, serializer=None, endpoints=None):
     self._auth = auth
     self._service = Service(service_url)
     self._serializer = JsonSerializer() if serializer is None \
                                 else serializer
     # The API endpoint should return resource endpoints list.
     self._endpoints = endpoints if endpoints is not None else self._get()
Esempio n. 3
0
 def __init__(self, service_url, auth=None, params=None, serializer=None, verify=False):
     self._auth = auth
     self._params = params
     self._verify = verify
     self._service = Service(service_url)
     self._serializer = JsonSerializer() if serializer is None \
                                 else serializer
     self._endpoints = self._get() # The API endpoint should return 
Esempio n. 4
0
class Api(object):
    """The TastyPie client"""

    def __init__(self, service_url, auth=None, serializer=None):
        self._auth = auth
        self._service = Service(service_url)
        self._serializer = JsonSerializer() if serializer is None \
                                    else serializer
        self._endpoints = self._get() # The API endpoint should return 
                                      # resource endpoints list.

    def __repr__(self):
        return '<Api: %s>' % self._service.url

    def __getattr__(self, attr):
        """
        Some magic to enable us to dynamically resolves the endpoints names on
        on the Api object.
        
        For example :
            Api('http://localhost:1337/').poney.find(name__startswith='D')
        Generates an HTTP GET request on this URL :
            http://localhost:1337/poney/?name__startswith=D
        """
        if attr in self._endpoints:
            return EndpointProxy(self, self._endpoints[attr]['list_endpoint'],
                                       self._endpoints[attr]['schema'])
        else:
            raise AttributeError(attr)

    def _get_url(self, resource=None, id=None, **kw):
        """Generate an URL
        
        1. The service URL is used as the base string (eg. "/api/1/")
        2. If a `resource` is given, it is appended (eg. "/api/1/country/")
            2.1. If an `id` is given, it is appended (eg. "/api/1/country/2/")
        3. If keyword arguments are given, construct a query string and append
           it :
           kw = dict(foo=42, bar='test')
           => '/api/1/resource/?foo=42&bar=test
        """
        url = self._service.url
        if resource is not None:
            url += '%s/' % resource
            if id is not None:
                url += '%s/' % id
        if kw:
            for key, value in kw.items():
                if isinstance(value, basestring):
                    kw[key] = value.encode('utf-8')
            url += '?' + urllib.urlencode(kw)
        return url

    def _parse_resource(self, resource):
        """Parses a raw resource as returned by the service, replace related
           resource URLs with ResourceProxy objects.
        """

        url = resource['resource_uri']
        del resource['resource_uri']

        for attr, value in resource.items():
            if self._service.is_resource_url(value):
                resource[attr] = ResourceProxy(value, self._service, self)
            elif isinstance(value, list):
                resource[attr] = ListProxy(value, self._service, self)

        type_, id_ = self._service.parse_resource_url(url)
        return Resource(resource, type_, id_, url)

    def _parse_resources(self, resources):
        return map(self._parse_resource, resources)

    def _get(self, type=None, id=None, **kw):
        """Do a HTTP GET request"""

        url = self._get_url(type, id, **kw)
        response = requests.get(url, auth=self._auth)
        if response.status_code != 200:
            raise BadHttpStatus(response)
        raw_data = response.content
        data = self._serializer.decode(raw_data)
        return data

    def __call__(self, type=None, id=None, proxy=None, **kw):
        """Get a resource by its ID or a search filter

        Get an entry by its ID ::

            api.entry(42)

        Finds an entry by it's title ::

            api.entry(title='foo!')

        Find an entry by it's name, case insensitive ::

            api.entry(name__iexact='FOO!')
        """

        if proxy:
            if proxy._resource:
                return proxy._resource
            type = proxy._type
            id = proxy._id
        elif type is None:
            raise ResourceTypeMissing

        if id is None:
            if not kw:
                raise ResourceIdMissing
            response = self.find(type, **kw)
            if len(response) != 1:
                raise TooManyResources
            return response[0]
        else:
            response = self._get(type, id, **kw)
            resource = self._parse_resource(response)
            if proxy:
                proxy._resource = resource
            return resource

    def many(self, type, *ids, **kw):
        """Get multiple resources (of the same type) with an unique request

        Returns a list of `Resource` objects.

        Example:
            api.entry.many(17, 41)
        """
        id = 'set/' + ';'.join(map(str, ids))
        response = self._get(type, id, **kw)
        resources = self._parse_resources(response['objects'])
        # Transform a list of Resource in a dict using resource ID as key
        resources = dict([ (r.id, r) for r in resources ])
        # Add not found IDs to the dict
        if 'not_found' in response:
            for id in response['not_found']:
                resources[int(id)] = None
        return resources

    def find(self, type, **kw):
        """Find resources based on a search filter"""
        response = self._get(type, **kw)
        meta = response['meta']
        resources = self._parse_resources(response['objects'])
        return SearchResponse(self, type, meta, resources, kw)
Esempio n. 5
0
class Api(object):
    """The TastyPie client"""
    def __init__(self,
                 service_url,
                 auth=None,
                 params=None,
                 serializer=None,
                 verify=False):
        self._auth = auth
        self._params = params
        self._verify = verify
        self._service = Service(service_url)
        self._serializer = JsonSerializer() if serializer is None \
                                    else serializer
        self._endpoints = self._get()  # The API endpoint should return
        # resource endpoints list.

    def __repr__(self):
        return '<Api: %s>' % self._service.url

    def __getattr__(self, attr):
        """
        Some magic to enable us to dynamically resolves the endpoints names on
        on the Api object.
        
        For example :
            Api('http://localhost:1337/').poney.find(name__startswith='D')
        Generates an HTTP GET request on this URL :
            http://localhost:1337/poney/?name__startswith=D
        """
        if attr in self._endpoints:
            return EndpointProxy(self, self._endpoints[attr]['list_endpoint'],
                                 self._endpoints[attr]['schema'])
        else:
            raise AttributeError(attr)

    def _get_url(self, resource=None, id=None, **kw):
        """Generate an URL
        
        1. The service URL is used as the base string (eg. "/api/1/")
        2. If a `resource` is given, it is appended (eg. "/api/1/country/")
            2.1. If an `id` is given, it is appended (eg. "/api/1/country/2/")
        3. If keyword arguments are given, construct a query string and append
           it :
           kw = dict(foo=42, bar='test')
           => '/api/1/resource/?foo=42&bar=test
        """
        url = self._service.url
        if resource is not None:
            url += '%s/' % resource
            if id is not None:
                url += '%s/' % id
        if kw:
            for key, value in kw.items():
                if isinstance(value, basestring):
                    kw[key] = value.encode('utf-8')
            url += '?' + urllib.urlencode(kw)
        return url

    def _parse_resource(self, resource):
        """Parses a raw resource as returned by the service, replace related
           resource URLs with ResourceProxy objects.
        """

        url = resource['resource_uri']
        del resource['resource_uri']

        for attr, value in resource.items():
            if self._service.is_resource_url(value):
                resource[attr] = ResourceProxy(value, self._service, self)
            elif isinstance(value, list):
                resource[attr] = ListProxy(value, self._service, self)

        type_, id_ = self._service.parse_resource_url(url)
        return Resource(resource, type_, id_, url)

    def _parse_resources(self, resources):
        return map(self._parse_resource, resources)

    def _get(self, type=None, id=None, timeout=None, **kw):
        """Do a HTTP GET request"""

        url = self._get_url(type, id, **kw)
        if timeout:
            response = requests.get(url,
                                    auth=self._auth,
                                    params=self._params,
                                    verify=self._verify,
                                    timeout=timeout)
        else:
            response = requests.get(url,
                                    auth=self._auth,
                                    params=self._params,
                                    verify=self._verify)

        if response.status_code != 200:
            raise BadHttpStatus(response)
        raw_data = response.content
        data = self._serializer.decode(raw_data)
        return data

    def __call__(self, type=None, id=None, proxy=None, **kw):
        """Get a resource by its ID or a search filter

        Get an entry by its ID ::

            api.entry(42)

        Finds an entry by it's title ::

            api.entry(title='foo!')

        Find an entry by it's name, case insensitive ::

            api.entry(name__iexact='FOO!')
        """

        if proxy:
            if proxy._resource:
                return proxy._resource
            type = proxy._type
            id = proxy._id
        elif type is None:
            raise ResourceTypeMissing

        if id is None:
            if not kw:
                raise ResourceIdMissing
            response = self.find(type, **kw)
            if len(response) != 1:
                raise TooManyResources
            return response[0]
        else:
            response = self._get(type, id, **kw)
            resource = self._parse_resource(response)
            if proxy:
                proxy._resource = resource
            return resource

    def many(self, type, *ids, **kw):
        """Get multiple resources (of the same type) with an unique request

        Returns a list of `Resource` objects.

        Example:
            api.entry.many(17, 41)
        """
        id = 'set/' + ';'.join(map(str, ids))
        response = self._get(type, id, **kw)
        resources = self._parse_resources(response['objects'])
        # Transform a list of Resource in a dict using resource ID as key
        resources = dict([(r.id, r) for r in resources])
        # Add not found IDs to the dict
        if 'not_found' in response:
            for id in response['not_found']:
                resources[int(id)] = None
        return resources

    def find(self, type, **kw):
        """Find resources based on a search filter"""
        response = self._get(type, **kw)
        meta = response['meta']
        resources = self._parse_resources(response['objects'])
        return SearchResponse(self, type, meta, resources, kw)