2

I'm trying use Google APIs Client Library for Python to rename drive file, here is the rename function:

def rename_file(service, file_id, new_title):
"""Rename a file.

Args:
    service: Drive API service instance.
    file_id: ID of the file to rename.
    new_title: New title for the file.
Returns:
    Updated file metadata if successful, None otherwise.
"""
try:
    file = {'title': new_title}
    # Rename the file.
    updated_file = service.files().patch(
            fileId=file_id,
            body=file,
            fields='title').execute()
    return updated_file
except errors.HttpError, error:
    logging.error('An error occurred: %s' % error)
    return None

But get errors, here is the trackback:

    Traceback (most recent call last):
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1535, in __call__
    rv = self.handle_exception(request, response, e)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1529, in __call__
    rv = self.router.dispatch(request, response)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/myproduct/libs/oauth2client/appengine.py", line 469, in check_oauth
    return method(request_handler, *args, **kwargs)
  File "/myproduct/main.py", line 31, in get
    new_title="file new name")
  File "/myproduct/gapi.py", line 148, in rename_file
    fields='title').execute()
  File "/myproduct/libs/oauth2client/util.py", line 120, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/myproduct/libs/apiclient/http.py", line 676, in execute
    headers=self.headers)
  File "/myproduct/libs/oauth2client/util.py", line 120, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/myproduct/libs/oauth2client/client.py", line 420, in new_request
    redirections, connection_type)
  File "/myproduct/libs/httplib2/__init__.py", line 1588, in request
    (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey)
  File "/myproduct/libs/httplib2/__init__.py", line 1336, in _request
    (response, content) = self._conn_request(conn, request_uri, method, body, headers)
  File "/myproduct/libs/httplib2/__init__.py", line 1273, in _conn_request
    conn.request(method, request_uri, body, headers)
  File "/myproduct/libs/httplib2/__init__.py", line 1112, in request
    validate_certificate=self.validate_certificate)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/urlfetch.py", line 265, in fetch
    allow_truncated, follow_redirects, validate_certificate)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/api/urlfetch.py", line 286, in make_fetch_call
    raise InvalidMethodError('Invalid method %s.' % str(method))
InvalidMethodError: Invalid method PATCH.

So what should I do to use the rename_file function directly?

2
  • minor nitpick; logging an exception, at the "error" log level, is spelled logger.error("msg", exc_info=True) or logging.exception("msg", level=logging.ERROR), and related, use log.info("msg %", arg) not log.info("msg %" % arg), since logging will interpolate for you (or not, if the message is below the threshold) Commented Jan 1, 2013 at 1:55
  • What is the service parameter that you are passing to the function? It should be a fully built and authorized drive service as described at: developers.google.com/drive/… Commented Jan 2, 2013 at 1:11

1 Answer 1

3

As the error message indicates, PATCH is not yet supported by urlfetch, but an issue has been filed with the App Engine team and the issue is acknowledged.

In the meantime, you can patch httplib2 to send an X-HTTP-METHOD-OVERRIDE header instead of using the PATCH method, as is indicated in a patch filed against httplib2.

As that patch references some old code, I have provided the relevant snippet here:

UNAUTHORIZED_METHODS = ['patch']
HTTP_METHOD_OVERRIDE_HEADER = 'X-HTTP-Method-Override'
HTTP_OVERRIDE_METHOD = 'POST'

class AppEngineHttpConnection(httplib.HTTPConnection):
  ...
  def request(self, method, url, body=None, headers={}):
    if method.lower() in UNAUTHORIZED_METHODS:
      # No side-effects on provided headers.
      new_headers = {}
      new_headers.update(headers)
      new_headers[HTTP_METHOD_OVERRIDE_HEADER] = method
      method = HTTP_OVERRIDE_METHOD
      headers = new_headers
    super(AppEngineHttpConnection, self).request(method, url, body, headers)

Since request is now simply the one defined in httplib.HTTPConnection, we can just re-use it while changing the one header we need.

A similar override will be needed for the HTTPS version since it does not inherit from AppEngineHttpConnection.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.