Esempio n. 1
0
    def refresh(self, client=None):
        """Refresh this resource instance with the latest data from the server.

        :param client: The client that should be used (if None, the global fetchcore client is used).
        :raise ConnectionError: Thrown if a connection to fetchcore cannot be made.
        :raise DoesNotExist: Thrown if the resource longer exists on the server (updates only).
        :raise InternalServerError: Thrown if the server responds with an error.
        """
        # Check if we are using the global client
        if client is None:
            client = configuration.__GLOBAL_CLIENT__
        self.__validate_client(client)

        try:
            # TODO: check if ID is set

            response = client.get(self.endpoint, getattr(self, self.pk)) or {}
            # Save back the data we got
            for key, value in response.iteritems():
                self.set_values(key, value)
                self.__set_since_update.discard(key)
        # TODO: add exceptions and such for unauthed states when we add in more permissions
        except exceptions.NotFound:
            # Cleanup internally
            self._set('id', None)
            raise exceptions.DoesNotExist(
                "Resource no longer exists on the server.")
        except exceptions.MethodNotAllowed:
            raise exceptions.UnsupportedOperation(
                "Loading of the current data is unsupported by fetchcore.")
Esempio n. 2
0
    def update(self, client=None):
        """
        Update the resource on the server with fields changed for the current resource since the last update call.

        This method includes extra logic for handling Map's image. It also does some pretty nasty method calls due
        to ssid mangling, but it's necessary for function.

        :param client: The client that should be used (if None, the global fetchcore client is used).
        :raise fetchcore.exceptions.ConnectionError: Thrown if a connection to fetchcore cannot be made.
        :raise fetchcore.exceptions.ValidationError: Thrown if there was an issue validating the data on the server.
        :raise fetchcore.exceptions.DoesNotExist: Thrown if the resource does not exist on the server (updates only).
        :raise fetchcore.exceptions.UnsupportedOperation: Thrown if the saves are not supported for this resource.
        :raise fetchcore.exceptions.InternalServerError: Thrown if the server responds with an error.
        """
        # Check if we are using the global client
        if client is None:
            client = configuration.__GLOBAL_CLIENT__
        self._Resource__validate_client(client)

        request_kwargs = self._get_request_args_from_dict()

        try:
            # First, check if we are creating a new instance
            if not self.is_set('id'):
                raise exceptions.DoesNotExist(
                    "You cannot update a resource that is not on the server.")
            else:
                # Generate minimal PATCH update
                patch_data = {}
                data_key = 'data' if len(request_kwargs) == 2 else 'json'
                json_data = request_kwargs.get(data_key)

                if 'aggregate_image' in self._Resource__set_since_update:
                    # Base image has changed, so just discard it from the set (it should already be in request_kwargs)
                    self._Resource__set_since_update.discard('aggregate_image')
                else:
                    # Base image hasn't changed, so just remove it safely (if it exists)
                    request_kwargs.pop('files', None)

                for field in list(self._Resource__set_since_update):
                    patch_data[field] = json_data[field]
                    self._Resource__set_since_update.discard(field)

                request_kwargs[data_key] = patch_data

                client.patch(self.endpoint, getattr(self, self.pk),
                             **request_kwargs)

        # TODO: add exceptions and such for unauthed states when we add in more permissions
        except exceptions.NotFound:
            # Cleanup internally
            self._set('id', None)
            raise exceptions.DoesNotExist(
                "Resource no longer exists on the server.")
        except exceptions.BadRequest as e:
            raise exceptions.ValidationError(e.message)
        except exceptions.MethodNotAllowed:
            raise exceptions.UnsupportedOperation(
                "Deleting the current data is unsupported by fetchcore.")
Esempio n. 3
0
    def delete(self, _=None):
        """Overwrites base class delete. Sounds are immutable and cannot be deleted on the server.

        :param _: Unused client parameter.
        :raise: fetchcore.exceptions.UnsupportedOperation
        """
        raise exceptions.UnsupportedOperation(
            "Sounds are immutable and cannot be deleted on the server.")
Esempio n. 4
0
    def update(self, client=None):
        """Update the resource on the server with fields changed for the current resource since the last update call.

        :param client: The client that should be used (if None, the global fetchcore client is used).
        :raise ConnectionError: Thrown if a connection to fetchcore cannot be made.
        :raise ValidationError: Thrown if there was an issue validating the data on the server.
        :raise DoesNotExist: Thrown if the resource does not exist on the server (updates only).
        :raise UnsupportedOperation: Thrown if the saves are not supported for this resource.
        :raise InternalServerError: Thrown if the server responds with an error.
        """
        # Check if we are using the global client
        if client is None:
            client = configuration.__GLOBAL_CLIENT__
        self.__validate_client(client)

        try:
            # First, check if we are creating a new instance
            if not self.is_set('id'):
                raise exceptions.DoesNotExist(
                    "You cannot update a resource that is not on the server.")
            elif self.__set_since_update:
                # Generate minimal PATCH update iff we've changed fields since the last update
                patch_data = {}
                actual_set = self.__set_since_update.copy()
                json_data = self.to_json_dict()
                for field in list(actual_set):
                    patch_data[field] = json_data[field]
                    actual_set.discard(field)
                self.__set_since_update = actual_set
                # Check if we have anything to send
                if patch_data:
                    return client.patch(self.endpoint, getattr(self, self.pk),
                                        patch_data)
                else:
                    # We should just update in that case
                    self.refresh(client=client)
                    return self.to_json_dict()

        # TODO: add exceptions and such for unauthed states when we add in more permissions
        except exceptions.NotFound:
            # Cleanup internally
            self._set('id', None)
            raise exceptions.DoesNotExist(
                "Resource no longer exists on the server.")
        except exceptions.BadRequest as e:
            raise exceptions.ValidationError(e.message)
        except exceptions.MethodNotAllowed:
            raise exceptions.UnsupportedOperation(
                "Deleting the current data is unsupported by fetchcore.")
Esempio n. 5
0
    def save(self, client=None):
        """
        Save the current resource to the server. If the resource does not yet exist, it will be created. If it already
        exists all fields on the server will be overwritten with the current values.

        This method has extra behaviors for dealing with the Map's image field. It does some pretty nasty method
        calls due to ssid mangling in parent methods, but it's necessary to function.

        :param client: The client that should be used (if None, the global fetchcore client is used).
        :raise fetchcore.exceptions.ConnectionError: Thrown if a connection to fetchcore cannot be made.
        :raise fetchcore.exceptions.ValidationError: Thrown if there was an issue validating the data on the server.
        :raise fetchcore.exceptions.DoesNotExist: Thrown if the resource longer exists on the server (updates only).
        :raise fetchcore.exceptions.UnsupportedOperation: Thrown if the saves are not supported for this resource.
        :raise fetchcore.exceptions.InternalServerError: Thrown if the server responds with an error.
        """
        # Check if we are using the global client
        if client is None:
            client = configuration.__GLOBAL_CLIENT__
        self._Resource__validate_client(client)

        request_kwargs = self._get_request_args_from_dict()

        try:
            # First, check if we are creating a new instance
            if not self.is_set('id'):
                # TODO if map add 'format' argument
                response = client.post(self.endpoint, **request_kwargs)
            else:
                response = client.put(self.endpoint, getattr(self, self.pk),
                                      **request_kwargs)
            # Save back the data we got
            for key, value in response.iteritems():
                self.set_values(key, value)
                self._Resource__set_since_update.discard(key)
            if 'files' in request_kwargs:
                self._Resource__set_since_update.discard('aggregate_image')
        # TODO: add exceptions and such for unauthed states when we add in more permissions
        except exceptions.NotFound:
            # Cleanup internally
            self._set('id', None)
            raise exceptions.DoesNotExist(
                "Resource no longer exists on the server.")
        except exceptions.BadRequest as e:
            raise exceptions.ValidationError(e.message)
        except exceptions.MethodNotAllowed:
            raise exceptions.UnsupportedOperation(
                "Saving or updating of the current data is unsupported by fetchcore."
            )
Esempio n. 6
0
    def save(self, client=None):
        """Save the current resource to the server. If the resource does not yet exist, it will be created. If it
        already exists all fields on the server will be overwritten with the current values.

        :param client: The client that should be used (if None, the global fetchcore client is used).
        :raise ConnectionError: Thrown if a connection to fetchcore cannot be made.
        :raise ValidationError: Thrown if there was an issue validating the data on the server.
        :raise DoesNotExist: Thrown if the resource longer exists on the server (updates only).
        :raise UnsupportedOperation: Thrown if the saves are not supported for this resource.
        :raise InternalServerError: Thrown if the server responds with an error.
        """
        # Check if we are using the global client
        if client is None:
            client = configuration.__GLOBAL_CLIENT__
        self.__validate_client(client)

        try:
            # First, check if we are creating a new instance
            if not self.is_set('id'):
                # TODO if map add 'format' argument
                response = client.post(self.endpoint,
                                       self.to_json_dict()) or {}
            else:
                response = client.put(self.endpoint, getattr(self, self.pk),
                                      self.to_json_dict()) or {}
            # Save back the data we got
            for key, value in response.iteritems():
                self.set_values(key, value)
                self.__set_since_update.discard(key)
            return response
        # TODO: add exceptions and such for unauthed states when we add in more permissions
        except exceptions.NotFound:
            # Cleanup internally
            self._set('id', None)
            raise exceptions.DoesNotExist(
                "Resource no longer exists on the server.")
        except exceptions.BadRequest as e:
            raise exceptions.ValidationError(e.message)
        except exceptions.MethodNotAllowed:
            raise exceptions.UnsupportedOperation(
                "Saving or updating of the current data is unsupported by fetchcore."
            )
Esempio n. 7
0
    def delete(self, client=None):
        """Delete this resource from the server. The resource's ID must be set for this operation to work.

        :param client: The client that should be used (if None, the global fetchcore client is used).
        :raise ConnectionError: Thrown if a connection to fetchcore cannot be made.
        :raise ValidationError: Thrown if there was an issue validating the data on the server.
        :raise DoesNotExist: Thrown if the resource longer exists on the server (updates only).
        :raise UnsupportedOperation: Thrown if DELETE is not allowed or the resource doesn't exist.
        :raise InternalServerError: Thrown if the server responds with an error.
        """

        # Check if we are using the global client
        if client is None:
            client = configuration.__GLOBAL_CLIENT__
        self.__validate_client(client)

        try:
            # First, check if we are creating a new instance
            if not self.is_set('id'):
                raise exceptions.DoesNotExist(
                    "You cannot delete a resource that is not on the server.")

            client.delete(self.endpoint, getattr(self, self.pk))
        # TODO: add exceptions and such for unauthed states when we add in more permissions
        except exceptions.NotFound:
            # Cleanup internally
            self._set('id', None)
            raise exceptions.DoesNotExist(
                "Resource no longer exists on the server.")
        except exceptions.BadRequest as e:
            raise exceptions.ValidationError(e.message)
        except exceptions.MethodNotAllowed:
            raise exceptions.UnsupportedOperation(
                "Deleting the current data is unsupported by fetchcore.")

            # TODO: Add actual destructor? I don't think it's necessary or done in most modules anyway
        # Safe removal of ID
        self._pop('id')