def update(self, id=None, new_data={}, **kwargs):
        """Update an object on the server.

        Args:
            id: ID of the object to update (can be None if not required)
            new_data: the update data for the object
            **kwargs: Extra options to send to the server (e.g. sudo)

        Returns:
            dict: The new object data (*not* a RESTObject)

        Raises:
            GitlabAuthenticationError: If authentication is not correct
            GitlabUpdateError: If the server cannot perform the request
        """

        if id is None:
            path = self.path
        else:
            path = '%s/%s' % (self.path, id)

        self._check_missing_update_attrs(new_data)
        files = {}

        # We get the attributes that need some special transformation
        types = getattr(self, '_types', {})
        if types:
            # Duplicate data to avoid messing with what the user sent us
            new_data = new_data.copy()
            for attr_name, type_cls in types.items():
                if attr_name in new_data.keys():
                    type_obj = type_cls(new_data[attr_name])

                    # if the type if FileAttribute we need to pass the data as
                    # file
                    if issubclass(type_cls, g_types.FileAttribute):
                        k = type_obj.get_file_name(attr_name)
                        files[attr_name] = (k, new_data.pop(attr_name))
                    else:
                        new_data[attr_name] = type_obj.get_for_api()

        http_method = self._get_update_method()
        return http_method(path, post_data=new_data, files=files, **kwargs)