Flows no longer need to be saved between uses.

Also introduces util.positional declarations.

Reviewed in http://codereview.appspot.com/6441056/.

Fixes issue #136.
diff --git a/apiclient/discovery.py b/apiclient/discovery.py
index cf83530..16683e7 100644
--- a/apiclient/discovery.py
+++ b/apiclient/discovery.py
@@ -57,6 +57,7 @@
 from apiclient.schema import Schemas
 from email.mime.multipart import MIMEMultipart
 from email.mime.nonmultipart import MIMENonMultipart
+from oauth2client import util
 from oauth2client.anyjson import simplejson
 
 logger = logging.getLogger(__name__)
@@ -139,6 +140,7 @@
   return ''.join(result)
 
 
+@util.positional(2)
 def build(serviceName,
           version,
           http=None,
@@ -194,7 +196,7 @@
     raise UnknownApiNameOrVersion("name: %s  version: %s" % (serviceName,
                                                             version))
   if resp.status >= 400:
-    raise HttpError(resp, content, requested_url)
+    raise HttpError(resp, content, uri=requested_url)
 
   try:
     service = simplejson.loads(content)
@@ -202,10 +204,11 @@
     logger.error('Failed to parse as JSON: ' + content)
     raise InvalidJsonError()
 
-  return build_from_document(content, discoveryServiceUrl, http=http,
+  return build_from_document(content, base=discoveryServiceUrl, http=http,
       developerKey=developerKey, model=model, requestBuilder=requestBuilder)
 
 
+@util.positional(1)
 def build_from_document(
     service,
     base=None,
@@ -529,7 +532,8 @@
             raise UnknownFileType(media_filename)
           if not mimeparse.best_match([media_mime_type], ','.join(accept)):
             raise UnacceptableMimeTypeError(media_mime_type)
-          media_upload = MediaFileUpload(media_filename, media_mime_type)
+          media_upload = MediaFileUpload(media_filename,
+                                         mimetype=media_mime_type)
         elif isinstance(media_filename, MediaUpload):
           media_upload = media_filename
         else:
diff --git a/apiclient/errors.py b/apiclient/errors.py
index e744519..938d8d1 100644
--- a/apiclient/errors.py
+++ b/apiclient/errors.py
@@ -23,6 +23,7 @@
 __author__ = 'jcgregorio@google.com (Joe Gregorio)'
 
 
+from oauth2client import util
 from oauth2client.anyjson import simplejson
 
 
@@ -34,6 +35,7 @@
 class HttpError(Error):
   """HTTP data was invalid or unexpected."""
 
+  @util.positional(3)
   def __init__(self, resp, content, uri=None):
     self.resp = resp
     self.content = content
@@ -92,6 +94,7 @@
 class BatchError(HttpError):
   """Error occured during batch operations."""
 
+  @util.positional(2)
   def __init__(self, reason, resp=None, content=None):
     self.resp = resp
     self.content = content
@@ -106,6 +109,7 @@
 class UnexpectedMethodError(Error):
   """Exception raised by RequestMockBuilder on unexpected calls."""
 
+  @util.positional(1)
   def __init__(self, methodId=None):
     """Constructor for an UnexpectedMethodError."""
     super(UnexpectedMethodError, self).__init__(
diff --git a/apiclient/http.py b/apiclient/http.py
index 753dd09..4331cc2 100644
--- a/apiclient/http.py
+++ b/apiclient/http.py
@@ -43,6 +43,7 @@
 from errors import UnexpectedBodyError
 from errors import UnexpectedMethodError
 from model import JsonModel
+from oauth2client import util
 from oauth2client.anyjson import simplejson
 
 
@@ -162,6 +163,7 @@
     """
     raise NotImplementedError()
 
+  @util.positional(1)
   def _to_json(self, strip=None):
     """Utility function for creating a JSON representation of a MediaUpload.
 
@@ -226,6 +228,7 @@
         media_body=media).execute()
   """
 
+  @util.positional(2)
   def __init__(self, filename, mimetype=None, chunksize=DEFAULT_CHUNK_SIZE, resumable=False):
     """Constructor.
 
@@ -302,13 +305,13 @@
        string, a JSON representation of this instance, suitable to pass to
        from_json().
     """
-    return self._to_json(['_fd'])
+    return self._to_json(strip=['_fd'])
 
   @staticmethod
   def from_json(s):
     d = simplejson.loads(s)
-    return MediaFileUpload(
-        d['_filename'], d['_mimetype'], d['_chunksize'], d['_resumable'])
+    return MediaFileUpload(d['_filename'], mimetype=d['_mimetype'],
+                           chunksize=d['_chunksize'], resumable=d['_resumable'])
 
 
 class MediaIoBaseUpload(MediaUpload):
@@ -326,6 +329,7 @@
         media_body=media).execute()
   """
 
+  @util.positional(3)
   def __init__(self, fd, mimetype, chunksize=DEFAULT_CHUNK_SIZE,
       resumable=False):
     """Constructor.
@@ -414,6 +418,7 @@
   method.
   """
 
+  @util.positional(2)
   def __init__(self, body, mimetype='application/octet-stream',
                chunksize=DEFAULT_CHUNK_SIZE, resumable=False):
     """Create a new MediaBytesUpload.
@@ -496,8 +501,9 @@
   def from_json(s):
     d = simplejson.loads(s)
     return MediaInMemoryUpload(base64.b64decode(d['_b64body']),
-                               d['_mimetype'], d['_chunksize'],
-                               d['_resumable'])
+                               mimetype=d['_mimetype'],
+                               chunksize=d['_chunksize'],
+                               resumable=d['_resumable'])
 
 
 class MediaIoBaseDownload(object):
@@ -520,6 +526,7 @@
     print "Download Complete!"
   """
 
+  @util.positional(3)
   def __init__(self, fd, request, chunksize=DEFAULT_CHUNK_SIZE):
     """Constructor.
 
@@ -574,12 +581,13 @@
         self._done = True
       return MediaDownloadProgress(self._progress, self._total_size), self._done
     else:
-      raise HttpError(resp, content, self._uri)
+      raise HttpError(resp, content, uri=self._uri)
 
 
 class HttpRequest(object):
   """Encapsulates a single HTTP request."""
 
+  @util.positional(4)
   def __init__(self, http, postproc, uri,
                method='GET',
                body=None,
@@ -623,6 +631,7 @@
     # The bytes that have been uploaded.
     self.resumable_progress = 0
 
+  @util.positional(1)
   def execute(self, http=None):
     """Execute the request.
 
@@ -643,7 +652,7 @@
     if self.resumable:
       body = None
       while body is None:
-        _, body = self.next_chunk(http)
+        _, body = self.next_chunk(http=http)
       return body
     else:
       if 'content-length' not in self.headers:
@@ -661,13 +670,14 @@
         self.body = parsed.query
         self.headers['content-length'] = str(len(self.body))
 
-      resp, content = http.request(self.uri, self.method,
+      resp, content = http.request(self.uri, method=self.method,
                                    body=self.body,
                                    headers=self.headers)
       if resp.status >= 300:
-        raise HttpError(resp, content, self.uri)
+        raise HttpError(resp, content, uri=self.uri)
     return self.postproc(resp, content)
 
+  @util.positional(1)
   def next_chunk(self, http=None):
     """Execute the next step of a resumable upload.
 
@@ -782,7 +792,7 @@
         self.resumable_uri = resp['location']
     else:
       self._in_error_state = True
-      raise HttpError(resp, content, self.uri)
+      raise HttpError(resp, content, uri=self.uri)
 
     return (MediaUploadProgress(self.resumable_progress, self.resumable.size()),
             None)
@@ -844,9 +854,10 @@
 
     batch.add(service.animals().list(), list_animals)
     batch.add(service.farmers().list(), list_farmers)
-    batch.execute(http)
+    batch.execute(http=http)
   """
 
+  @util.positional(1)
   def __init__(self, callback=None, batch_uri=None):
     """Constructor for a BatchHttpRequest.
 
@@ -1042,6 +1053,7 @@
       self._last_auto_id += 1
     return str(self._last_auto_id)
 
+  @util.positional(2)
   def add(self, request, callback=None, request_id=None):
     """Add a new request.
 
@@ -1119,7 +1131,7 @@
                                  headers=headers)
 
     if resp.status >= 300:
-      raise HttpError(resp, content, self._batch_uri)
+      raise HttpError(resp, content, uri=self._batch_uri)
 
     # Now break out the individual responses and store each one.
     boundary, _ = content.split(None, 1)
@@ -1133,14 +1145,15 @@
     mime_response = parser.close()
 
     if not mime_response.is_multipart():
-      raise BatchError("Response not in multipart/mixed format.", resp,
-          content)
+      raise BatchError("Response not in multipart/mixed format.", resp=resp,
+                       content=content)
 
     for part in mime_response.get_payload():
       request_id = self._header_to_id(part['Content-ID'])
       response, content = self._deserialize_response(part.get_payload())
       self._responses[request_id] = (response, content)
 
+  @util.positional(1)
   def execute(self, http=None):
     """Execute all the requests as a single batched HTTP request.
 
@@ -1200,7 +1213,7 @@
       exception = None
       try:
         if resp.status >= 300:
-          raise HttpError(resp, content, request.uri)
+          raise HttpError(resp, content, uri=request.uri)
         response = request.postproc(resp, content)
       except HttpError, e:
         exception = e
@@ -1310,7 +1323,7 @@
           raise UnexpectedBodyError(expected_body, body)
       return HttpRequestMock(resp, content, postproc)
     elif self.check_unexpected:
-      raise UnexpectedMethodError(methodId)
+      raise UnexpectedMethodError(methodId=methodId)
     else:
       model = JsonModel(False)
       return HttpRequestMock(None, '{}', model.response)
diff --git a/apiclient/schema.py b/apiclient/schema.py
index cfed7de..d076a86 100644
--- a/apiclient/schema.py
+++ b/apiclient/schema.py
@@ -62,6 +62,8 @@
 __author__ = 'jcgregorio@google.com (Joe Gregorio)'
 
 import copy
+
+from oauth2client import util
 from oauth2client.anyjson import simplejson
 
 
@@ -80,6 +82,7 @@
     # Cache of pretty printed schemas.
     self.pretty = {}
 
+  @util.positional(2)
   def _prettyPrintByName(self, name, seen=None, dent=0):
     """Get pretty printed object prototype from the schema name.
 
@@ -102,7 +105,7 @@
 
     if name not in self.pretty:
       self.pretty[name] = _SchemaToStruct(self.schemas[name],
-          seen, dent).to_str(self._prettyPrintByName)
+          seen, dent=dent).to_str(self._prettyPrintByName)
 
     seen.pop()
 
@@ -121,6 +124,7 @@
     # Return with trailing comma and newline removed.
     return self._prettyPrintByName(name, seen=[], dent=1)[:-2]
 
+  @util.positional(2)
   def _prettyPrintSchema(self, schema, seen=None, dent=0):
     """Get pretty printed object prototype of schema.
 
@@ -136,7 +140,7 @@
     if seen is None:
       seen = []
 
-    return _SchemaToStruct(schema, seen, dent).to_str(self._prettyPrintByName)
+    return _SchemaToStruct(schema, seen, dent=dent).to_str(self._prettyPrintByName)
 
   def prettyPrintSchema(self, schema):
     """Get pretty printed object prototype of schema.
@@ -163,6 +167,7 @@
 class _SchemaToStruct(object):
   """Convert schema to a prototype object."""
 
+  @util.positional(3)
   def __init__(self, schema, seen, dent=0):
     """Constructor.
 
@@ -256,7 +261,7 @@
     elif '$ref' in schema:
       schemaName = schema['$ref']
       description = schema.get('description', '')
-      s = self.from_cache(schemaName, self.seen)
+      s = self.from_cache(schemaName, seen=self.seen)
       parts = s.splitlines()
       self.emitEnd(parts[0], description)
       for line in parts[1:]: