Docstring pass after pep8ify in oauth2client/

This commit is contained in:
Danny Hermes
2015-08-21 08:05:44 -07:00
parent 34c1ff543d
commit 119f5b57fe
19 changed files with 1579 additions and 1504 deletions

View File

@@ -25,10 +25,12 @@ def _parse_pem_key(raw_key_input):
the relevant part of the key if it is. the relevant part of the key if it is.
Args: Args:
raw_key_input: The contents of a private key file (either PEM or PKCS12). raw_key_input: The contents of a private key file (either PEM or
PKCS12).
Returns: Returns:
string, The actual key if the contents are from a PEM file, or else None. string, The actual key if the contents are from a PEM file, or
else None.
""" """
offset = raw_key_input.find(b'-----BEGIN ') offset = raw_key_input.find(b'-----BEGIN ')
if offset != -1: if offset != -1:

View File

@@ -28,7 +28,7 @@ class OpenSSLVerifier(object):
"""Constructor. """Constructor.
Args: Args:
pubkey, OpenSSL.crypto.PKey, The public key to verify with. pubkey: OpenSSL.crypto.PKey, The public key to verify with.
""" """
self._pubkey = pubkey self._pubkey = pubkey
@@ -42,8 +42,8 @@ class OpenSSLVerifier(object):
will be encoded to bytes as utf-8. will be encoded to bytes as utf-8.
Returns: Returns:
True if message was signed by the private key associated with the public True if message was signed by the private key associated with the
key that this object was constructed with. public key that this object was constructed with.
""" """
message = _to_bytes(message, encoding='utf-8') message = _to_bytes(message, encoding='utf-8')
signature = _to_bytes(signature, encoding='utf-8') signature = _to_bytes(signature, encoding='utf-8')
@@ -59,14 +59,14 @@ class OpenSSLVerifier(object):
Args: Args:
key_pem: string, public key in PEM format. key_pem: string, public key in PEM format.
is_x509_cert: bool, True if key_pem is an X509 cert, otherwise it is is_x509_cert: bool, True if key_pem is an X509 cert, otherwise it
expected to be an RSA key in PEM format. is expected to be an RSA key in PEM format.
Returns: Returns:
Verifier instance. Verifier instance.
Raises: Raises:
OpenSSL.crypto.Error if the key_pem can't be parsed. OpenSSL.crypto.Error: if the key_pem can't be parsed.
""" """
if is_x509_cert: if is_x509_cert:
pubkey = crypto.load_certificate(crypto.FILETYPE_PEM, key_pem) pubkey = crypto.load_certificate(crypto.FILETYPE_PEM, key_pem)
@@ -82,7 +82,7 @@ class OpenSSLSigner(object):
"""Constructor. """Constructor.
Args: Args:
pkey, OpenSSL.crypto.PKey (or equiv), The private key to sign with. pkey: OpenSSL.crypto.PKey (or equiv), The private key to sign with.
""" """
self._key = pkey self._key = pkey

View File

@@ -31,7 +31,8 @@ class PyCryptoVerifier(object):
"""Constructor. """Constructor.
Args: Args:
pubkey, OpenSSL.crypto.PKey (or equiv), The public key to verify with. pubkey: OpenSSL.crypto.PKey (or equiv), The public key to verify
with.
""" """
self._pubkey = pubkey self._pubkey = pubkey
@@ -44,8 +45,8 @@ class PyCryptoVerifier(object):
signature: string or bytes, The signature on the message. signature: string or bytes, The signature on the message.
Returns: Returns:
True if message was signed by the private key associated with the public True if message was signed by the private key associated with the
key that this object was constructed with. public key that this object was constructed with.
""" """
message = _to_bytes(message, encoding='utf-8') message = _to_bytes(message, encoding='utf-8')
return PKCS1_v1_5.new(self._pubkey).verify( return PKCS1_v1_5.new(self._pubkey).verify(
@@ -106,7 +107,8 @@ class PyCryptoSigner(object):
Args: Args:
key: string, private key in PEM format. key: string, private key in PEM format.
password: string, password for private key file. Unused for PEM files. password: string, password for private key file. Unused for PEM
files.
Returns: Returns:
Signer instance. Signer instance.

View File

@@ -94,12 +94,12 @@ if ndb is not None:
class SiteXsrfSecretKeyNDB(ndb.Model): class SiteXsrfSecretKeyNDB(ndb.Model):
"""NDB Model for storage for the sites XSRF secret key. """NDB Model for storage for the sites XSRF secret key.
Since this model uses the same kind as SiteXsrfSecretKey, it can be used Since this model uses the same kind as SiteXsrfSecretKey, it can be
interchangeably. This simply provides an NDB model for interacting with the used interchangeably. This simply provides an NDB model for interacting
same data the DB model interacts with. with the same data the DB model interacts with.
There should only be one instance stored of this model, the one used for the There should only be one instance stored of this model, the one used
site. for the site.
""" """
secret = ndb.StringProperty() secret = ndb.StringProperty()
@@ -110,8 +110,7 @@ if ndb is not None:
def _generate_new_xsrf_secret_key(): def _generate_new_xsrf_secret_key():
"""Returns a random XSRF secret key. """Returns a random XSRF secret key."""
"""
return os.urandom(16).encode("hex") return os.urandom(16).encode("hex")
@@ -140,14 +139,14 @@ def xsrf_secret_key():
class AppAssertionCredentials(AssertionCredentials): class AppAssertionCredentials(AssertionCredentials):
"""Credentials object for App Engine Assertion Grants """Credentials object for App Engine Assertion Grants
This object will allow an App Engine application to identify itself to Google This object will allow an App Engine application to identify itself to
and other OAuth 2.0 servers that can verify assertions. It can be used for the Google and other OAuth 2.0 servers that can verify assertions. It can be
purpose of accessing data stored under an account assigned to the App Engine used for the purpose of accessing data stored under an account assigned to
application itself. the App Engine application itself.
This credential does not require a flow to instantiate because it represents This credential does not require a flow to instantiate because it
a two legged flow, and therefore has all of the required information to represents a two legged flow, and therefore has all of the required
generate and refresh its own access tokens. information to generate and refresh its own access tokens.
""" """
@util.positional(2) @util.positional(2)
@@ -155,11 +154,12 @@ class AppAssertionCredentials(AssertionCredentials):
"""Constructor for AppAssertionCredentials """Constructor for AppAssertionCredentials
Args: Args:
scope: string or iterable of strings, scope(s) of the credentials being scope: string or iterable of strings, scope(s) of the credentials
requested. being requested.
**kwargs: optional keyword args, including: **kwargs: optional keyword args, including:
service_account_id: service account id of the application. If None or service_account_id: service account id of the application. If None
unspecified, the default service account for the app is used. or unspecified, the default service account for
the app is used.
""" """
self.scope = util.scopes_to_string(scope) self.scope = util.scopes_to_string(scope)
self._kwargs = kwargs self._kwargs = kwargs
@@ -176,13 +176,14 @@ class AppAssertionCredentials(AssertionCredentials):
def _refresh(self, http_request): def _refresh(self, http_request):
"""Refreshes the access_token. """Refreshes the access_token.
Since the underlying App Engine app_identity implementation does its own Since the underlying App Engine app_identity implementation does its
caching we can skip all the storage hoops and just to a refresh using the own caching we can skip all the storage hoops and just to a refresh
API. using the API.
Args: Args:
http_request: callable, a callable that matches the method signature of http_request: callable, a callable that matches the method
httplib2.Http.request, used to make the refresh request. signature of httplib2.Http.request, used to make the
refresh request.
Raises: Raises:
AccessTokenRefreshError: When the refresh fails. AccessTokenRefreshError: When the refresh fails.
@@ -210,7 +211,8 @@ class FlowProperty(db.Property):
"""App Engine datastore Property for Flow. """App Engine datastore Property for Flow.
Utility property that allows easy storage and retrieval of an Utility property that allows easy storage and retrieval of an
oauth2client.Flow""" oauth2client.Flow
"""
# Tell what the user type is. # Tell what the user type is.
data_type = Flow data_type = Flow
@@ -242,9 +244,10 @@ if ndb is not None:
class FlowNDBProperty(ndb.PickleProperty): class FlowNDBProperty(ndb.PickleProperty):
"""App Engine NDB datastore Property for Flow. """App Engine NDB datastore Property for Flow.
Serves the same purpose as the DB FlowProperty, but for NDB models. Since Serves the same purpose as the DB FlowProperty, but for NDB models.
PickleProperty inherits from BlobProperty, the underlying representation of Since PickleProperty inherits from BlobProperty, the underlying
the data in the datastore will be the same as in the DB case. representation of the data in the datastore will be the same as in the
DB case.
Utility property that allows easy storage and retrieval of an Utility property that allows easy storage and retrieval of an
oauth2client.Flow oauth2client.Flow
@@ -320,12 +323,13 @@ if ndb is not None:
class CredentialsNDBProperty(ndb.BlobProperty): class CredentialsNDBProperty(ndb.BlobProperty):
"""App Engine NDB datastore Property for Credentials. """App Engine NDB datastore Property for Credentials.
Serves the same purpose as the DB CredentialsProperty, but for NDB models. Serves the same purpose as the DB CredentialsProperty, but for NDB
Since CredentialsProperty stores data as a blob and this inherits from models. Since CredentialsProperty stores data as a blob and this
BlobProperty, the data in the datastore will be the same as in the DB case. inherits from BlobProperty, the data in the datastore will be the same
as in the DB case.
Utility property that allows easy storage and retrieval of Credentials and Utility property that allows easy storage and retrieval of Credentials
subclasses. and subclasses.
""" """
def _validate(self, value): def _validate(self, value):
@@ -349,7 +353,8 @@ if ndb is not None:
value: A value to be set in the datastore. value: A value to be set in the datastore.
Returns: Returns:
A JSON serialized version of the credential, else '' if value is None. A JSON serialized version of the credential, else '' if value
is None.
""" """
if value is None: if value is None:
return '' return ''
@@ -360,11 +365,12 @@ if ndb is not None:
"""Converts our stored JSON string back to the desired type. """Converts our stored JSON string back to the desired type.
Args: Args:
value: A value from the datastore to be converted to the desired type. value: A value from the datastore to be converted to the
desired type.
Returns: Returns:
A deserialized Credentials (or subclass) object, else None if the A deserialized Credentials (or subclass) object, else None if
value can't be parsed. the value can't be parsed.
""" """
if not value: if not value:
return None return None
@@ -380,8 +386,8 @@ class StorageByKeyName(Storage):
"""Store and retrieve a credential to and from the App Engine datastore. """Store and retrieve a credential to and from the App Engine datastore.
This Storage helper presumes the Credentials have been stored as a This Storage helper presumes the Credentials have been stored as a
CredentialsProperty or CredentialsNDBProperty on a datastore model class, and CredentialsProperty or CredentialsNDBProperty on a datastore model class,
that entities are stored by key_name. and that entities are stored by key_name.
""" """
@util.positional(4) @util.positional(4)
@@ -391,11 +397,12 @@ class StorageByKeyName(Storage):
Args: Args:
model: db.Model or ndb.Model, model class model: db.Model or ndb.Model, model class
key_name: string, key name for the entity that has the credentials key_name: string, key name for the entity that has the credentials
property_name: string, name of the property that is a CredentialsProperty property_name: string, name of the property that is a
or CredentialsNDBProperty. CredentialsProperty or CredentialsNDBProperty.
cache: memcache, a write-through cache to put in front of the datastore. cache: memcache, a write-through cache to put in front of the
If the model you are using is an NDB model, using a cache will be datastore. If the model you are using is an NDB model, using
redundant since the model uses an instance cache and memcache for you. a cache will be redundant since the model uses an instance
cache and memcache for you.
user: users.User object, optional. Can be used to grab user ID as a user: users.User object, optional. Can be used to grab user ID as a
key_name if no key name is specified. key_name if no key name is specified.
""" """
@@ -442,8 +449,8 @@ class StorageByKeyName(Storage):
def _delete_entity(self): def _delete_entity(self):
"""Delete entity from datastore. """Delete entity from datastore.
Attempts to delete using the key_name stored on the object, whether or not Attempts to delete using the key_name stored on the object, whether or
the given key is in the datastore. not the given key is in the datastore.
""" """
if self._is_ndb(): if self._is_ndb():
ndb.Key(self._model, self._key_name).delete() ndb.Key(self._model, self._key_name).delete()
@@ -509,11 +516,11 @@ if ndb is not None:
class CredentialsNDBModel(ndb.Model): class CredentialsNDBModel(ndb.Model):
"""NDB Model for storage of OAuth 2.0 Credentials """NDB Model for storage of OAuth 2.0 Credentials
Since this model uses the same kind as CredentialsModel and has a property Since this model uses the same kind as CredentialsModel and has a
which can serialize and deserialize Credentials correctly, it can be used property which can serialize and deserialize Credentials correctly, it
interchangeably with a CredentialsModel to access, insert and delete the can be used interchangeably with a CredentialsModel to access, insert
same entities. This simply provides an NDB model for interacting with the and delete the same entities. This simply provides an NDB model for
same data the DB model interacts with. interacting with the same data the DB model interacts with.
Storage of the model is keyed by the user.user_id(). Storage of the model is keyed by the user.user_id().
""" """
@@ -584,8 +591,8 @@ class OAuth2Decorator(object):
@decorator.oauth_required @decorator.oauth_required
def get(self): def get(self):
http = decorator.http() http = decorator.http()
# http is authorized with the user's Credentials and can be used # http is authorized with the user's Credentials and can be
# in API calls # used in API calls
""" """
@@ -596,9 +603,9 @@ class OAuth2Decorator(object):
"""A thread local Credentials object. """A thread local Credentials object.
Returns: Returns:
A client.Credentials object, or None if credentials hasn't been set in A client.Credentials object, or None if credentials hasn't been set
this thread yet, which may happen when calling has_credentials inside in this thread yet, which may happen when calling has_credentials
oauth_aware. inside oauth_aware.
""" """
return getattr(self._tls, 'credentials', None) return getattr(self._tls, 'credentials', None)
@@ -611,9 +618,9 @@ class OAuth2Decorator(object):
"""A thread local Flow object. """A thread local Flow object.
Returns: Returns:
A credentials.Flow object, or None if the flow hasn't been set in this A credentials.Flow object, or None if the flow hasn't been set in
thread yet, which happens in _create_flow() since Flows are created this thread yet, which happens in _create_flow() since Flows are
lazily. created lazily.
""" """
return getattr(self._tls, 'flow', None) return getattr(self._tls, 'flow', None)
@@ -638,38 +645,48 @@ class OAuth2Decorator(object):
Args: Args:
client_id: string, client identifier. client_id: string, client identifier.
client_secret: string client secret. client_secret: string client secret.
scope: string or iterable of strings, scope(s) of the credentials being scope: string or iterable of strings, scope(s) of the credentials
requested. being requested.
auth_uri: string, URI for authorization endpoint. For convenience auth_uri: string, URI for authorization endpoint. For convenience
defaults to Google's endpoints but any OAuth 2.0 provider can be used. defaults to Google's endpoints but any OAuth 2.0 provider
token_uri: string, URI for token endpoint. For convenience can be used.
defaults to Google's endpoints but any OAuth 2.0 provider can be used. token_uri: string, URI for token endpoint. For convenience defaults
to Google's endpoints but any OAuth 2.0 provider can be
used.
revoke_uri: string, URI for revoke endpoint. For convenience revoke_uri: string, URI for revoke endpoint. For convenience
defaults to Google's endpoints but any OAuth 2.0 provider can be used. defaults to Google's endpoints but any OAuth 2.0
user_agent: string, User agent of your application, default to None. provider can be used.
user_agent: string, User agent of your application, default to
None.
message: Message to display if there are problems with the OAuth 2.0 message: Message to display if there are problems with the OAuth 2.0
configuration. The message may contain HTML and will be presented on the configuration. The message may contain HTML and will be
web interface for any method that uses the decorator. presented on the web interface for any method that uses
callback_path: string, The absolute path to use as the callback URI. Note the decorator.
that this must match up with the URI given when registering the callback_path: string, The absolute path to use as the callback
application in the APIs Console. URI. Note that this must match up with the URI given
when registering the application in the APIs Console.
token_response_param: string. If provided, the full JSON response token_response_param: string. If provided, the full JSON response
to the access token request will be encoded and included in this query to the access token request will be encoded
parameter in the callback URI. This is useful with providers (e.g. and included in this query parameter in the
wordpress.com) that include extra fields that the client may want. callback URI. This is useful with providers
_storage_class: "Protected" keyword argument not typically provided to (e.g. wordpress.com) that include extra
this constructor. A storage class to aid in storing a Credentials object fields that the client may want.
for a user in the datastore. Defaults to StorageByKeyName. _storage_class: "Protected" keyword argument not typically provided
_credentials_class: "Protected" keyword argument not typically provided to to this constructor. A storage class to aid in
this constructor. A db or ndb Model class to hold credentials. Defaults storing a Credentials object for a user in the
to CredentialsModel. datastore. Defaults to StorageByKeyName.
_credentials_property_name: "Protected" keyword argument not typically _credentials_class: "Protected" keyword argument not typically
provided to this constructor. A string indicating the name of the field provided to this constructor. A db or ndb Model
on the _credentials_class where a Credentials object will be stored. class to hold credentials. Defaults to
CredentialsModel.
_credentials_property_name: "Protected" keyword argument not
typically provided to this constructor.
A string indicating the name of the
field on the _credentials_class where a
Credentials object will be stored.
Defaults to 'credentials'. Defaults to 'credentials'.
**kwargs: dict, Keyword arguments are passed along as kwargs to **kwargs: dict, Keyword arguments are passed along as kwargs to
the OAuth2WebServerFlow constructor. the OAuth2WebServerFlow constructor.
""" """
self._tls = threading.local() self._tls = threading.local()
self.flow = None self.flow = None
@@ -833,8 +850,8 @@ class OAuth2Decorator(object):
"""The absolute path where the callback will occur. """The absolute path where the callback will occur.
Note this is the absolute path, not the absolute URI, that will be Note this is the absolute path, not the absolute URI, that will be
calculated by the decorator at runtime. See callback_handler() for how this calculated by the decorator at runtime. See callback_handler() for how
should be used. this should be used.
Returns: Returns:
The callback path as a string. The callback path as a string.
@@ -890,8 +907,8 @@ class OAuth2Decorator(object):
def callback_application(self): def callback_application(self):
"""WSGI application for handling the OAuth 2.0 redirect callback. """WSGI application for handling the OAuth 2.0 redirect callback.
If you need finer grained control use `callback_handler` which returns just If you need finer grained control use `callback_handler` which returns
the webapp.RequestHandler. just the webapp.RequestHandler.
Returns: Returns:
A webapp.WSGIApplication that handles the redirect back from the A webapp.WSGIApplication that handles the redirect back from the
@@ -918,8 +935,8 @@ class OAuth2DecoratorFromClientSecrets(OAuth2Decorator):
@decorator.oauth_required @decorator.oauth_required
def get(self): def get(self):
http = decorator.http() http = decorator.http()
# http is authorized with the user's Credentials and can be used # http is authorized with the user's Credentials and can be
# in API calls # used in API calls
""" """
@@ -929,13 +946,14 @@ class OAuth2DecoratorFromClientSecrets(OAuth2Decorator):
Args: Args:
filename: string, File name of client secrets. filename: string, File name of client secrets.
scope: string or iterable of strings, scope(s) of the credentials being scope: string or iterable of strings, scope(s) of the credentials
requested. being requested.
message: string, A friendly string to display to the user if the message: string, A friendly string to display to the user if the
clientsecrets file is missing or invalid. The message may contain HTML clientsecrets file is missing or invalid. The message may
and will be presented on the web interface for any method that uses the contain HTML and will be presented on the web interface
decorator. for any method that uses the decorator.
cache: An optional cache service client that implements get() and set() cache: An optional cache service client that implements get() and
set()
methods. See clientsecrets.loadfile() for details. methods. See clientsecrets.loadfile() for details.
**kwargs: dict, Keyword arguments are passed along as kwargs to **kwargs: dict, Keyword arguments are passed along as kwargs to
the OAuth2WebServerFlow constructor. the OAuth2WebServerFlow constructor.
@@ -973,14 +991,13 @@ def oauth2decorator_from_clientsecrets(filename, scope,
scope: string or list of strings, scope(s) of the credentials being scope: string or list of strings, scope(s) of the credentials being
requested. requested.
message: string, A friendly string to display to the user if the message: string, A friendly string to display to the user if the
clientsecrets file is missing or invalid. The message may contain HTML and clientsecrets file is missing or invalid. The message may
will be presented on the web interface for any method that uses the contain HTML and will be presented on the web interface for
decorator. any method that uses the decorator.
cache: An optional cache service client that implements get() and set() cache: An optional cache service client that implements get() and set()
methods. See clientsecrets.loadfile() for details. methods. See clientsecrets.loadfile() for details.
Returns: An OAuth2Decorator Returns: An OAuth2Decorator
""" """
return OAuth2DecoratorFromClientSecrets(filename, scope, return OAuth2DecoratorFromClientSecrets(filename, scope,
message=message, cache=cache) message=message, cache=cache)

View File

@@ -180,11 +180,11 @@ class MemoryCache(object):
class Credentials(object): class Credentials(object):
"""Base class for all Credentials objects. """Base class for all Credentials objects.
Subclasses must define an authorize() method that applies the credentials to Subclasses must define an authorize() method that applies the credentials
an HTTP transport. to an HTTP transport.
Subclasses must also specify a classmethod named 'from_json' that takes a JSON Subclasses must also specify a classmethod named 'from_json' that takes a
string as input and returns an instantiated Credentials object. JSON string as input and returns an instantiated Credentials object.
""" """
NON_SERIALIZED_MEMBERS = ['store'] NON_SERIALIZED_MEMBERS = ['store']
@@ -193,8 +193,8 @@ class Credentials(object):
"""Take an httplib2.Http instance (or equivalent) and authorizes it. """Take an httplib2.Http instance (or equivalent) and authorizes it.
Authorizes it for the set of credentials, usually by replacing Authorizes it for the set of credentials, usually by replacing
http.request() with a method that adds in the appropriate headers and then http.request() with a method that adds in the appropriate headers and
delegates to the original Http.request() method. then delegates to the original Http.request() method.
Args: Args:
http: httplib2.Http, an http object to be used to make the refresh http: httplib2.Http, an http object to be used to make the refresh
@@ -232,7 +232,8 @@ class Credentials(object):
"""Utility function that creates JSON repr. of a Credentials object. """Utility function that creates JSON repr. of a Credentials object.
Args: Args:
strip: array, An array of names of members to not include in the JSON. strip: array, An array of names of members to not include in the
JSON.
Returns: Returns:
string, a JSON representation of this instance, suitable to pass to string, a JSON representation of this instance, suitable to pass to
@@ -411,8 +412,8 @@ class Storage(object):
def clean_headers(headers): def clean_headers(headers):
"""Forces header keys and values to be strings, i.e not unicode. """Forces header keys and values to be strings, i.e not unicode.
The httplib module just concats the header keys and values in a way that may The httplib module just concats the header keys and values in a way that
make the message header a unicode string, which, if it then tries to may make the message header a unicode string, which, if it then tries to
contatenate to a binary request body may result in a unicode decode error. contatenate to a binary request body may result in a unicode decode error.
Args: Args:
@@ -477,16 +478,18 @@ class OAuth2Credentials(Credentials):
refresh_token: string, refresh token. refresh_token: string, refresh token.
token_expiry: datetime, when the access_token expires. token_expiry: datetime, when the access_token expires.
token_uri: string, URI of token endpoint. token_uri: string, URI of token endpoint.
user_agent: string, The HTTP User-Agent to provide for this application. user_agent: string, The HTTP User-Agent to provide for this
revoke_uri: string, URI for revoke endpoint. Defaults to None; a token application.
can't be revoked if this is None. revoke_uri: string, URI for revoke endpoint. Defaults to None; a
token can't be revoked if this is None.
id_token: object, The identity of the resource owner. id_token: object, The identity of the resource owner.
token_response: dict, the decoded response to the token request. None token_response: dict, the decoded response to the token request.
if a token hasn't been requested yet. Stored because some providers None if a token hasn't been requested yet. Stored
(e.g. wordpress.com) include extra fields that clients may want. because some providers (e.g. wordpress.com) include
extra fields that clients may want.
scopes: list, authorized scopes for these credentials. scopes: list, authorized scopes for these credentials.
token_info_uri: string, the URI for the token info endpoint. Defaults to token_info_uri: string, the URI for the token info endpoint. Defaults
None; scopes can not be refreshed if this is None. to None; scopes can not be refreshed if this is None.
Notes: Notes:
store: callable, A callable that when passed a Credential store: callable, A callable that when passed a Credential
@@ -515,11 +518,12 @@ class OAuth2Credentials(Credentials):
def authorize(self, http): def authorize(self, http):
"""Authorize an httplib2.Http instance with these credentials. """Authorize an httplib2.Http instance with these credentials.
The modified http.request method will add authentication headers to each The modified http.request method will add authentication headers to
request and will refresh access_tokens when a 401 is received on a each request and will refresh access_tokens when a 401 is received on a
request. In addition the http.request method has a credentials property, request. In addition the http.request method has a credentials property,
http.request.credentials, which is the Credentials object that authorized http.request.credentials, which is the Credentials object that
it. authorized it.
Args: Args:
http: An instance of ``httplib2.Http`` or something that acts http: An instance of ``httplib2.Http`` or something that acts
@@ -538,7 +542,6 @@ class OAuth2Credentials(Credentials):
signing. So instead we have to overload 'request' with a closure signing. So instead we have to overload 'request' with a closure
that adds in the Authorization header and then calls the original that adds in the Authorization header and then calls the original
version of 'request()'. version of 'request()'.
""" """
request_orig = http.request request_orig = http.request
@@ -627,25 +630,26 @@ class OAuth2Credentials(Credentials):
def has_scopes(self, scopes): def has_scopes(self, scopes):
"""Verify that the credentials are authorized for the given scopes. """Verify that the credentials are authorized for the given scopes.
Returns True if the credentials authorized scopes contain all of the scopes Returns True if the credentials authorized scopes contain all of the
given. scopes given.
Args: Args:
scopes: list or string, the scopes to check. scopes: list or string, the scopes to check.
Notes: Notes:
There are cases where the credentials are unaware of which scopes are There are cases where the credentials are unaware of which scopes
authorized. Notably, credentials obtained and stored before this code was are authorized. Notably, credentials obtained and stored before
added will not have scopes, AccessTokenCredentials do not have scopes. In this code was added will not have scopes, AccessTokenCredentials do
both cases, you can use refresh_scopes() to obtain the canonical set of not have scopes. In both cases, you can use refresh_scopes() to
scopes. obtain the canonical set of scopes.
""" """
scopes = util.string_to_scopes(scopes) scopes = util.string_to_scopes(scopes)
return set(scopes).issubset(self.scopes) return set(scopes).issubset(self.scopes)
def retrieve_scopes(self, http): def retrieve_scopes(self, http):
"""Retrieves the canonical list of scopes for this access token from the """Retrieves the canonical list of scopes for this access token.
OAuth2 provider.
Gets the scopes from the OAuth2 provider.
Args: Args:
http: httplib2.Http, an http object to be used to make the refresh http: httplib2.Http, an http object to be used to make the refresh
@@ -662,8 +666,9 @@ class OAuth2Credentials(Credentials):
@classmethod @classmethod
def from_json(cls, s): def from_json(cls, s):
"""Instantiate a Credentials object from a JSON description of it. The JSON """Instantiate a Credentials object from a JSON description of it.
should have been produced by calling .to_json() on the object.
The JSON should have been produced by calling .to_json() on the object.
Args: Args:
data: dict, A deserialized JSON object. data: dict, A deserialized JSON object.
@@ -745,9 +750,10 @@ class OAuth2Credentials(Credentials):
If token_expiry is in the past, this method will return 0, meaning the If token_expiry is in the past, this method will return 0, meaning the
token has already expired. token has already expired.
If token_expiry is None, this method will return None. Note that returning
0 in such a case would not be fair: the token may still be valid; If token_expiry is None, this method will return None. Note that
we just don't know anything about it. returning 0 in such a case would not be fair: the token may still be
valid; we just don't know anything about it.
""" """
if self.token_expiry: if self.token_expiry:
now = datetime.datetime.utcnow() now = datetime.datetime.utcnow()
@@ -803,8 +809,9 @@ class OAuth2Credentials(Credentials):
refresh is completed. refresh is completed.
Args: Args:
http_request: callable, a callable that matches the method signature of http_request: callable, a callable that matches the method
httplib2.Http.request, used to make the refresh request. signature of httplib2.Http.request, used to make the
refresh request.
Raises: Raises:
AccessTokenRefreshError: When the refresh fails. AccessTokenRefreshError: When the refresh fails.
@@ -830,8 +837,9 @@ class OAuth2Credentials(Credentials):
"""Refresh the access_token using the refresh_token. """Refresh the access_token using the refresh_token.
Args: Args:
http_request: callable, a callable that matches the method signature of http_request: callable, a callable that matches the method
httplib2.Http.request, used to make the refresh request. signature of httplib2.Http.request, used to make the
refresh request.
Raises: Raises:
AccessTokenRefreshError: When the refresh fails. AccessTokenRefreshError: When the refresh fails.
@@ -880,8 +888,9 @@ class OAuth2Credentials(Credentials):
"""Revokes this credential and deletes the stored copy (if it exists). """Revokes this credential and deletes the stored copy (if it exists).
Args: Args:
http_request: callable, a callable that matches the method signature of http_request: callable, a callable that matches the method
httplib2.Http.request, used to make the revoke request. signature of httplib2.Http.request, used to make the
revoke request.
""" """
self._do_revoke(http_request, self.refresh_token or self.access_token) self._do_revoke(http_request, self.refresh_token or self.access_token)
@@ -889,13 +898,15 @@ class OAuth2Credentials(Credentials):
"""Revokes this credential and deletes the stored copy (if it exists). """Revokes this credential and deletes the stored copy (if it exists).
Args: Args:
http_request: callable, a callable that matches the method signature of http_request: callable, a callable that matches the method
httplib2.Http.request, used to make the refresh request. signature of httplib2.Http.request, used to make the
refresh request.
token: A string used as the token to be revoked. Can be either an token: A string used as the token to be revoked. Can be either an
access_token or refresh_token. access_token or refresh_token.
Raises: Raises:
TokenRevokeError: If the revoke request does not return with a 200 OK. TokenRevokeError: If the revoke request does not return with a
200 OK.
""" """
logger.info('Revoking token') logger.info('Revoking token')
query_params = {'token': token} query_params = {'token': token}
@@ -920,8 +931,9 @@ class OAuth2Credentials(Credentials):
"""Retrieves the list of authorized scopes from the OAuth2 provider. """Retrieves the list of authorized scopes from the OAuth2 provider.
Args: Args:
http_request: callable, a callable that matches the method signature of http_request: callable, a callable that matches the method
httplib2.Http.request, used to make the revoke request. signature of httplib2.Http.request, used to make the
revoke request.
""" """
self._do_retrieve_scopes(http_request, self.access_token) self._do_retrieve_scopes(http_request, self.access_token)
@@ -929,13 +941,15 @@ class OAuth2Credentials(Credentials):
"""Retrieves the list of authorized scopes from the OAuth2 provider. """Retrieves the list of authorized scopes from the OAuth2 provider.
Args: Args:
http_request: callable, a callable that matches the method signature of http_request: callable, a callable that matches the method
httplib2.Http.request, used to make the refresh request. signature of httplib2.Http.request, used to make the
token: A string used as the token to identify the credentials to the refresh request.
provider. token: A string used as the token to identify the credentials to
the provider.
Raises: Raises:
Error: When refresh fails, indicating the the access token is invalid. Error: When refresh fails, indicating the the access token is
invalid.
""" """
logger.info('Refreshing scopes') logger.info('Refreshing scopes')
query_params = {'access_token': token, 'fields': 'scope'} query_params = {'access_token': token, 'fields': 'scope'}
@@ -978,8 +992,8 @@ class AccessTokenCredentials(OAuth2Credentials):
http = credentials.authorize(http) http = credentials.authorize(http)
Raises: Raises:
AccessTokenCredentialsExpired: raised when the access_token expires or is AccessTokenCredentialsExpired: raised when the access_token expires or
revoked. is revoked.
""" """
def __init__(self, access_token, user_agent, revoke_uri=None): def __init__(self, access_token, user_agent, revoke_uri=None):
@@ -990,9 +1004,10 @@ class AccessTokenCredentials(OAuth2Credentials):
Args: Args:
access_token: string, access token. access_token: string, access token.
user_agent: string, The HTTP User-Agent to provide for this application. user_agent: string, The HTTP User-Agent to provide for this
revoke_uri: string, URI for revoke endpoint. Defaults to None; a token application.
can't be revoked if this is None. revoke_uri: string, URI for revoke endpoint. Defaults to None; a
token can't be revoked if this is None.
""" """
super(AccessTokenCredentials, self).__init__( super(AccessTokenCredentials, self).__init__(
access_token, access_token,
@@ -1020,8 +1035,9 @@ class AccessTokenCredentials(OAuth2Credentials):
"""Revokes the access_token and deletes the store if available. """Revokes the access_token and deletes the store if available.
Args: Args:
http_request: callable, a callable that matches the method signature of http_request: callable, a callable that matches the method
httplib2.Http.request, used to make the revoke request. signature of httplib2.Http.request, used to make the
revoke request.
""" """
self._do_revoke(http_request, self.access_token) self._do_revoke(http_request, self.access_token)
@@ -1030,7 +1046,8 @@ def _detect_gce_environment(urlopen=None):
"""Determine if the current environment is Compute Engine. """Determine if the current environment is Compute Engine.
Args: Args:
urlopen: Optional argument. Function used to open a connection to a URL. urlopen: Optional argument. Function used to open a connection to a
URL.
Returns: Returns:
Boolean indicating whether or not the current environment is Google Boolean indicating whether or not the current environment is Google
@@ -1083,7 +1100,8 @@ def _in_gce_environment(urlopen=None):
"""Detect if the code is running in the Compute Engine environment. """Detect if the code is running in the Compute Engine environment.
Args: Args:
urlopen: Optional argument. Function used to open a connection to a URL. urlopen: Optional argument. Function used to open a connection to a
URL.
Returns: Returns:
True if running in the GCE environment, False otherwise. True if running in the GCE environment, False otherwise.
@@ -1106,7 +1124,7 @@ class GoogleCredentials(OAuth2Credentials):
https://developers.google.com/accounts/docs/application-default-credentials https://developers.google.com/accounts/docs/application-default-credentials
Here is an example of how to use the Application Default Credentials for a Here is an example of how to use the Application Default Credentials for a
service that requires authentication: service that requires authentication::
from googleapiclient.discovery import build from googleapiclient.discovery import build
from oauth2client.client import GoogleCredentials from oauth2client.client import GoogleCredentials
@@ -1139,9 +1157,11 @@ class GoogleCredentials(OAuth2Credentials):
refresh_token: string, refresh token. refresh_token: string, refresh token.
token_expiry: datetime, when the access_token expires. token_expiry: datetime, when the access_token expires.
token_uri: string, URI of token endpoint. token_uri: string, URI of token endpoint.
user_agent: string, The HTTP User-Agent to provide for this application. user_agent: string, The HTTP User-Agent to provide for this
revoke_uri: string, URI for revoke endpoint. application.
Defaults to GOOGLE_REVOKE_URI; a token can't be revoked if this is None. revoke_uri: string, URI for revoke endpoint. Defaults to
GOOGLE_REVOKE_URI; a token can't be revoked if this
is None.
""" """
super(GoogleCredentials, self).__init__( super(GoogleCredentials, self).__init__(
access_token, client_id, client_secret, refresh_token, token_expiry, access_token, client_id, client_secret, refresh_token, token_expiry,
@@ -1164,7 +1184,7 @@ class GoogleCredentials(OAuth2Credentials):
@property @property
def serialization_data(self): def serialization_data(self):
"""Get the fields and their values identifying the current credentials.""" """Get the fields and values identifying the current credentials."""
return { return {
'type': 'authorized_user', 'type': 'authorized_user',
'client_id': self.client_id, 'client_id': self.client_id,
@@ -1181,7 +1201,8 @@ class GoogleCredentials(OAuth2Credentials):
current environment. current environment.
Returns: Returns:
None, if not in GAE, else an appengine.AppAssertionCredentials object. None, if not in GAE, else an appengine.AppAssertionCredentials
object.
""" """
if not _in_gae_environment(): if not _in_gae_environment():
return None return None
@@ -1192,9 +1213,9 @@ class GoogleCredentials(OAuth2Credentials):
def _implicit_credentials_from_gce(): def _implicit_credentials_from_gce():
"""Attempts to get implicit credentials in Google Compute Engine env. """Attempts to get implicit credentials in Google Compute Engine env.
If the current environment is not detected as Compute Engine, returns None, If the current environment is not detected as Compute Engine, returns
indicating no Google Compute Engine credentials can be detected from the None, indicating no Google Compute Engine credentials can be detected
current environment. from the current environment.
Returns: Returns:
None, if not in GCE, else a gce.AppAssertionCredentials object. None, if not in GCE, else a gce.AppAssertionCredentials object.
@@ -1213,10 +1234,11 @@ class GoogleCredentials(OAuth2Credentials):
"well known" file) associated with the 'gcloud' command line tool. "well known" file) associated with the 'gcloud' command line tool.
Returns: Returns:
Credentials object associated with the GOOGLE_APPLICATION_CREDENTIALS Credentials object associated with the
file or the "well known" file if either exist. If neither file is GOOGLE_APPLICATION_CREDENTIALS file or the "well known" file if
define, returns None, indicating no credentials from a file can either exist. If neither file is define, returns None, indicating
detected from the current environment. no credentials from a file can detected from the current
environment.
""" """
credentials_filename = _get_environment_variable_file() credentials_filename = _get_environment_variable_file()
if not credentials_filename: if not credentials_filename:
@@ -1254,10 +1276,9 @@ class GoogleCredentials(OAuth2Credentials):
- Google Compute Engine production environment. - Google Compute Engine production environment.
Raises: Raises:
ApplicationDefaultCredentialsError: raised when the credentials fail ApplicationDefaultCredentialsError: raised when the credentials
to be retrieved. fail to be retrieved.
""" """
# Environ checks (in order). # Environ checks (in order).
environ_checkers = [ environ_checkers = [
cls._implicit_credentials_from_gae, cls._implicit_credentials_from_gae,
@@ -1278,26 +1299,25 @@ class GoogleCredentials(OAuth2Credentials):
"""Get the Application Default Credentials for the current environment. """Get the Application Default Credentials for the current environment.
Raises: Raises:
ApplicationDefaultCredentialsError: raised when the credentials fail ApplicationDefaultCredentialsError: raised when the credentials
to be retrieved. fail to be retrieved.
""" """
return GoogleCredentials._get_implicit_credentials() return GoogleCredentials._get_implicit_credentials()
@staticmethod @staticmethod
def from_stream(credential_filename): def from_stream(credential_filename):
"""Create a Credentials object by reading the information from a given file. """Create a Credentials object by reading information from a file.
It returns an object of type GoogleCredentials. It returns an object of type GoogleCredentials.
Args: Args:
credential_filename: the path to the file from where the credentials credential_filename: the path to the file from where the
are to be read credentials are to be read
Raises: Raises:
ApplicationDefaultCredentialsError: raised when the credentials fail ApplicationDefaultCredentialsError: raised when the credentials
to be retrieved. fail to be retrieved.
""" """
if credential_filename and os.path.isfile(credential_filename): if credential_filename and os.path.isfile(credential_filename):
try: try:
return _get_application_default_credential_from_file( return _get_application_default_credential_from_file(
@@ -1332,12 +1352,11 @@ def save_to_well_known_file(credentials, well_known_file=None):
"""Save the provided GoogleCredentials to the well known file. """Save the provided GoogleCredentials to the well known file.
Args: Args:
credentials: credentials: the credentials to be saved to the well known file;
the credentials to be saved to the well known file;
it should be an instance of GoogleCredentials it should be an instance of GoogleCredentials
well_known_file: well_known_file: the name of the file where the credentials are to be
the name of the file where the credentials are to be saved; saved; this parameter is supposed to be used for
this parameter is supposed to be used for testing only testing only
""" """
# TODO(orestica): move this method to tools.py # TODO(orestica): move this method to tools.py
# once the argparse import gets fixed (it is not present in Python 2.6) # once the argparse import gets fixed (it is not present in Python 2.6)
@@ -1481,11 +1500,13 @@ class AssertionCredentials(GoogleCredentials):
"""Constructor for AssertionFlowCredentials. """Constructor for AssertionFlowCredentials.
Args: Args:
assertion_type: string, assertion type that will be declared to the auth assertion_type: string, assertion type that will be declared to the
server auth server
user_agent: string, The HTTP User-Agent to provide for this application. user_agent: string, The HTTP User-Agent to provide for this
token_uri: string, URI for token endpoint. For convenience application.
defaults to Google's endpoints but any OAuth 2.0 provider can be used. token_uri: string, URI for token endpoint. For convenience defaults
to Google's endpoints but any OAuth 2.0 provider can be
used.
revoke_uri: string, URI for revoke endpoint. revoke_uri: string, URI for revoke endpoint.
""" """
super(AssertionCredentials, self).__init__( super(AssertionCredentials, self).__init__(
@@ -1510,17 +1531,16 @@ class AssertionCredentials(GoogleCredentials):
return body return body
def _generate_assertion(self): def _generate_assertion(self):
"""Generate the assertion string that will be used in the access token """Generate assertion string to be used in the access token request."""
request.
"""
_abstract() _abstract()
def _revoke(self, http_request): def _revoke(self, http_request):
"""Revokes the access_token and deletes the store if available. """Revokes the access_token and deletes the store if available.
Args: Args:
http_request: callable, a callable that matches the method signature of http_request: callable, a callable that matches the method
httplib2.Http.request, used to make the revoke request. signature of httplib2.Http.request, used to make the
revoke request.
""" """
self._do_revoke(http_request, self.access_token) self._do_revoke(http_request, self.access_token)
@@ -1563,15 +1583,18 @@ class SignedJwtAssertionCredentials(AssertionCredentials):
"""Constructor for SignedJwtAssertionCredentials. """Constructor for SignedJwtAssertionCredentials.
Args: Args:
service_account_name: string, id for account, usually an email address. service_account_name: string, id for account, usually an email
address.
private_key: string, private key in PKCS12 or PEM format. private_key: string, private key in PKCS12 or PEM format.
scope: string or iterable of strings, scope(s) of the credentials being scope: string or iterable of strings, scope(s) of the credentials
requested. being requested.
private_key_password: string, password for private_key, unused if private_key_password: string, password for private_key, unused if
private_key is in PEM format. private_key is in PEM format.
user_agent: string, HTTP User-Agent to provide for this application. user_agent: string, HTTP User-Agent to provide for this
token_uri: string, URI for token endpoint. For convenience application.
defaults to Google's endpoints but any OAuth 2.0 provider can be used. token_uri: string, URI for token endpoint. For convenience defaults
to Google's endpoints but any OAuth 2.0 provider can be
used.
revoke_uri: string, URI for revoke endpoint. revoke_uri: string, URI for revoke endpoint.
kwargs: kwargs, Additional parameters to add to the JWT token, for kwargs: kwargs, Additional parameters to add to the JWT token, for
example sub=joe@xample.org. example sub=joe@xample.org.
@@ -1737,17 +1760,21 @@ def credentials_from_code(client_id, client_secret, scope, code,
scope: string or iterable of strings, scope(s) to request. scope: string or iterable of strings, scope(s) to request.
code: string, An authorization code, most likely passed down from code: string, An authorization code, most likely passed down from
the client the client
redirect_uri: string, this is generally set to 'postmessage' to match the redirect_uri: string, this is generally set to 'postmessage' to match
redirect_uri that the client specified the redirect_uri that the client specified
http: httplib2.Http, optional http instance to use to do the fetch http: httplib2.Http, optional http instance to use to do the fetch
token_uri: string, URI for token endpoint. For convenience token_uri: string, URI for token endpoint. For convenience defaults
defaults to Google's endpoints but any OAuth 2.0 provider can be used. to Google's endpoints but any OAuth 2.0 provider can be
used.
auth_uri: string, URI for authorization endpoint. For convenience auth_uri: string, URI for authorization endpoint. For convenience
defaults to Google's endpoints but any OAuth 2.0 provider can be used. defaults to Google's endpoints but any OAuth 2.0 provider
can be used.
revoke_uri: string, URI for revoke endpoint. For convenience revoke_uri: string, URI for revoke endpoint. For convenience
defaults to Google's endpoints but any OAuth 2.0 provider can be used. defaults to Google's endpoints but any OAuth 2.0 provider
device_uri: string, URI for device authorization endpoint. For convenience can be used.
defaults to Google's endpoints but any OAuth 2.0 provider can be used. device_uri: string, URI for device authorization endpoint. For
convenience defaults to Google's endpoints but any OAuth
2.0 provider can be used.
Returns: Returns:
An OAuth2Credentials object. An OAuth2Credentials object.
@@ -1775,8 +1802,9 @@ def credentials_from_clientsecrets_and_code(filename, scope, code,
device_uri=None): device_uri=None):
"""Returns OAuth2Credentials from a clientsecrets file and an auth code. """Returns OAuth2Credentials from a clientsecrets file and an auth code.
Will create the right kind of Flow based on the contents of the clientsecrets Will create the right kind of Flow based on the contents of the
file or will raise InvalidClientSecretsError for unknown types of Flows. clientsecrets file or will raise InvalidClientSecretsError for unknown
types of Flows.
Args: Args:
filename: string, File name of clientsecrets. filename: string, File name of clientsecrets.
@@ -1784,11 +1812,12 @@ def credentials_from_clientsecrets_and_code(filename, scope, code,
code: string, An authorization code, most likely passed down from code: string, An authorization code, most likely passed down from
the client the client
message: string, A friendly string to display to the user if the message: string, A friendly string to display to the user if the
clientsecrets file is missing or invalid. If message is provided then clientsecrets file is missing or invalid. If message is
sys.exit will be called in the case of an error. If message in not provided then sys.exit will be called in the case of an error.
provided then clientsecrets.InvalidClientSecretsError will be raised. If message in not provided then
redirect_uri: string, this is generally set to 'postmessage' to match the clientsecrets.InvalidClientSecretsError will be raised.
redirect_uri that the client specified redirect_uri: string, this is generally set to 'postmessage' to match
the redirect_uri that the client specified
http: httplib2.Http, optional http instance to use to do the fetch http: httplib2.Http, optional http instance to use to do the fetch
cache: An optional cache service client that implements get() and set() cache: An optional cache service client that implements get() and set()
methods. See clientsecrets.loadfile() for details. methods. See clientsecrets.loadfile() for details.
@@ -1798,10 +1827,11 @@ def credentials_from_clientsecrets_and_code(filename, scope, code,
An OAuth2Credentials object. An OAuth2Credentials object.
Raises: Raises:
FlowExchangeError if the authorization code cannot be exchanged for an FlowExchangeError: if the authorization code cannot be exchanged for an
access token access token
UnknownClientSecretsFlowError if the file describes an unknown kind of Flow. UnknownClientSecretsFlowError: if the file describes an unknown kind
clientsecrets.InvalidClientSecretsError if the clientsecrets file is of Flow.
clientsecrets.InvalidClientSecretsError: if the clientsecrets file is
invalid. invalid.
""" """
flow = flow_from_clientsecrets(filename, scope, message=message, cache=cache, flow = flow_from_clientsecrets(filename, scope, message=message, cache=cache,
@@ -1878,26 +1908,32 @@ class OAuth2WebServerFlow(Flow):
Args: Args:
client_id: string, client identifier. client_id: string, client identifier.
client_secret: string client secret. client_secret: string client secret.
scope: string or iterable of strings, scope(s) of the credentials being scope: string or iterable of strings, scope(s) of the credentials
requested. being requested.
redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob' for redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob'
a non-web-based application, or a URI that handles the callback from for a non-web-based application, or a URI that
the authorization server. handles the callback from the authorization server.
user_agent: string, HTTP User-Agent to provide for this application. user_agent: string, HTTP User-Agent to provide for this application.
auth_uri: string, URI for authorization endpoint. For convenience auth_uri: string, URI for authorization endpoint. For convenience
defaults to Google's endpoints but any OAuth 2.0 provider can be used. defaults to Google's endpoints but any OAuth 2.0 provider
can be used.
token_uri: string, URI for token endpoint. For convenience token_uri: string, URI for token endpoint. For convenience
defaults to Google's endpoints but any OAuth 2.0 provider can be used. defaults to Google's endpoints but any OAuth 2.0
provider can be used.
revoke_uri: string, URI for revoke endpoint. For convenience revoke_uri: string, URI for revoke endpoint. For convenience
defaults to Google's endpoints but any OAuth 2.0 provider can be used. defaults to Google's endpoints but any OAuth 2.0
login_hint: string, Either an email address or domain. Passing this hint provider can be used.
will either pre-fill the email box on the sign-in form or select the login_hint: string, Either an email address or domain. Passing this
proper multi-login session, thereby simplifying the login flow. hint will either pre-fill the email box on the sign-in
device_uri: string, URI for device authorization endpoint. For convenience form or select the proper multi-login session, thereby
defaults to Google's endpoints but any OAuth 2.0 provider can be used. simplifying the login flow.
device_uri: string, URI for device authorization endpoint. For
convenience defaults to Google's endpoints but any
OAuth 2.0 provider can be used.
authorization_header: string, For use with OAuth 2.0 providers that authorization_header: string, For use with OAuth 2.0 providers that
require a client to authenticate using a header value instead of passing require a client to authenticate using a
client_secret in the POST body. header value instead of passing client_secret
in the POST body.
**kwargs: dict, The keyword arguments are all optional and required **kwargs: dict, The keyword arguments are all optional and required
parameters for the OAuth calls. parameters for the OAuth calls.
""" """
@@ -1928,15 +1964,18 @@ class OAuth2WebServerFlow(Flow):
"""Returns a URI to redirect to the provider. """Returns a URI to redirect to the provider.
Args: Args:
redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob' for redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob'
a non-web-based application, or a URI that handles the callback from for a non-web-based application, or a URI that
the authorization server. This parameter is deprecated, please move to handles the callback from the authorization server.
passing the redirect_uri in via the constructor. This parameter is deprecated, please move to passing
state: string, Opaque state string which is passed through the OAuth2 flow the redirect_uri in via the constructor.
and returned to the client as a query parameter in the callback. state: string, Opaque state string which is passed through the
OAuth2 flow and returned to the client as a query parameter
in the callback.
Returns: Returns:
A URI as a string to redirect the user to begin the authorization flow. A URI as a string to redirect the user to begin the authorization
flow.
""" """
if redirect_uri is not None: if redirect_uri is not None:
logger.warning(( logger.warning((
@@ -2012,7 +2051,6 @@ class OAuth2WebServerFlow(Flow):
"""Exchanges a code for OAuth2Credentials. """Exchanges a code for OAuth2Credentials.
Args: Args:
code: string, a dict-like object, or None. For a non-device code: string, a dict-like object, or None. For a non-device
flow, this is either the response code as a string, or a flow, this is either the response code as a string, or a
dictionary of query parameters to the redirect_uri. For a dictionary of query parameters to the redirect_uri. For a
@@ -2030,7 +2068,6 @@ class OAuth2WebServerFlow(Flow):
refresh_token. refresh_token.
ValueError: if code and device_flow_info are both provided or both ValueError: if code and device_flow_info are both provided or both
missing. missing.
""" """
if code is None and device_flow_info is None: if code is None and device_flow_info is None:
raise ValueError('No code or device_flow_info provided.') raise ValueError('No code or device_flow_info provided.')
@@ -2113,33 +2150,38 @@ def flow_from_clientsecrets(filename, scope, redirect_uri=None,
device_uri=None): device_uri=None):
"""Create a Flow from a clientsecrets file. """Create a Flow from a clientsecrets file.
Will create the right kind of Flow based on the contents of the clientsecrets Will create the right kind of Flow based on the contents of the
file or will raise InvalidClientSecretsError for unknown types of Flows. clientsecrets file or will raise InvalidClientSecretsError for unknown
types of Flows.
Args: Args:
filename: string, File name of client secrets. filename: string, File name of client secrets.
scope: string or iterable of strings, scope(s) to request. scope: string or iterable of strings, scope(s) to request.
redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob' for redirect_uri: string, Either the string 'urn:ietf:wg:oauth:2.0:oob' for
a non-web-based application, or a URI that handles the callback from a non-web-based application, or a URI that handles the
the authorization server. callback from the authorization server.
message: string, A friendly string to display to the user if the message: string, A friendly string to display to the user if the
clientsecrets file is missing or invalid. If message is provided then clientsecrets file is missing or invalid. If message is
sys.exit will be called in the case of an error. If message in not provided then sys.exit will be called in the case of an error.
provided then clientsecrets.InvalidClientSecretsError will be raised. If message in not provided then
clientsecrets.InvalidClientSecretsError will be raised.
cache: An optional cache service client that implements get() and set() cache: An optional cache service client that implements get() and set()
methods. See clientsecrets.loadfile() for details. methods. See clientsecrets.loadfile() for details.
login_hint: string, Either an email address or domain. Passing this hint login_hint: string, Either an email address or domain. Passing this
will either pre-fill the email box on the sign-in form or select the hint will either pre-fill the email box on the sign-in form
proper multi-login session, thereby simplifying the login flow. or select the proper multi-login session, thereby
device_uri: string, URI for device authorization endpoint. For convenience simplifying the login flow.
defaults to Google's endpoints but any OAuth 2.0 provider can be used. device_uri: string, URI for device authorization endpoint. For
convenience defaults to Google's endpoints but any
OAuth 2.0 provider can be used.
Returns: Returns:
A Flow object. A Flow object.
Raises: Raises:
UnknownClientSecretsFlowError if the file describes an unknown kind of Flow. UnknownClientSecretsFlowError: if the file describes an unknown kind of
clientsecrets.InvalidClientSecretsError if the clientsecrets file is Flow.
clientsecrets.InvalidClientSecretsError: if the clientsecrets file is
invalid. invalid.
""" """
try: try:

View File

@@ -91,13 +91,14 @@ def _SendRecv():
class DevshellCredentials(client.GoogleCredentials): class DevshellCredentials(client.GoogleCredentials):
"""Credentials object for Google Developer Shell environment. """Credentials object for Google Developer Shell environment.
This object will allow a Google Developer Shell session to identify its user This object will allow a Google Developer Shell session to identify its
to Google and other OAuth 2.0 servers that can verify assertions. It can be user to Google and other OAuth 2.0 servers that can verify assertions. It
used for the purpose of accessing data stored under the user account. can be used for the purpose of accessing data stored under the user
account.
This credential does not require a flow to instantiate because it represents This credential does not require a flow to instantiate because it
a two legged flow, and therefore has all of the required information to represents a two legged flow, and therefore has all of the required
generate and refresh its own access tokens. information to generate and refresh its own access tokens.
""" """
def __init__(self, user_agent=None): def __init__(self, user_agent=None):

View File

@@ -79,8 +79,7 @@ class FlowField(models.Field):
class Storage(BaseStorage): class Storage(BaseStorage):
"""Store and retrieve a single credential to and from """Store and retrieve a single credential to and from the datastore.
the datastore.
This Storage helper presumes the Credentials This Storage helper presumes the Credentials
have been stored as a CredenialsField have been stored as a CredenialsField
@@ -94,7 +93,8 @@ class Storage(BaseStorage):
model: db.Model, model class model: db.Model, model class
key_name: string, key name for the entity that has the credentials key_name: string, key name for the entity that has the credentials
key_value: string, key value for the entity that has the credentials key_value: string, key value for the entity that has the credentials
property_name: string, name of the property that is an CredentialsProperty property_name: string, name of the property that is an
CredentialsProperty
""" """
self.model_class = model_class self.model_class = model_class
self.key_name = key_name self.key_name = key_name
@@ -122,8 +122,8 @@ class Storage(BaseStorage):
Args: Args:
credentials: Credentials, the credentials to store. credentials: Credentials, the credentials to store.
overwrite: Boolean, indicates whether you would like these credentials to overwrite: Boolean, indicates whether you would like these
overwrite any existing stored credentials. credentials to overwrite any existing stored credentials.
""" """
args = {self.key_name: self.key_value} args = {self.key_name: self.key_value}

View File

@@ -46,7 +46,8 @@ class Storage(BaseStorage):
def acquire_lock(self): def acquire_lock(self):
"""Acquires any lock necessary to access this Storage. """Acquires any lock necessary to access this Storage.
This lock is not reentrant.""" This lock is not reentrant.
"""
self._lock.acquire() self._lock.acquire()
def release_lock(self): def release_lock(self):
@@ -105,7 +106,6 @@ class Storage(BaseStorage):
Raises: Raises:
CredentialsFileSymbolicLinkError if the file is a symbolic link. CredentialsFileSymbolicLinkError if the file is a symbolic link.
""" """
self._create_file_if_needed() self._create_file_if_needed()
self._validate_file() self._validate_file()
f = open(self._filename, 'w') f = open(self._filename, 'w')
@@ -118,5 +118,4 @@ class Storage(BaseStorage):
Args: Args:
credentials: Credentials, the credentials to store. credentials: Credentials, the credentials to store.
""" """
os.unlink(self._filename) os.unlink(self._filename)

View File

@@ -337,8 +337,10 @@ class UserOAuth2(object):
return bp return bp
def authorize_view(self): def authorize_view(self):
"""Flask view that starts the authorization flow by redirecting the """Flask view that starts the authorization flow.
user to the OAuth2 provider."""
Starts flow by redirecting the user to the OAuth2 provider.
"""
args = request.args.to_dict() args = request.args.to_dict()
# Scopes will be passed as mutliple args, and to_dict() will only # Scopes will be passed as mutliple args, and to_dict() will only
@@ -355,9 +357,11 @@ class UserOAuth2(object):
return redirect(auth_url) return redirect(auth_url)
def callback_view(self): def callback_view(self):
"""Flask view that handles the user's return from the OAuth2 provider """Flask view that handles the user's return from OAuth2 provider.
and exchanges the authorization code for credentials and stores the
credentials.""" On return, exchanges the authorization code for credentials and stores
the credentials.
"""
if 'error' in request.args: if 'error' in request.args:
reason = request.args.get( reason = request.args.get(
'error_description', request.args.get('error', '')) 'error_description', request.args.get('error', ''))
@@ -429,8 +433,9 @@ class UserOAuth2(object):
@property @property
def user_id(self): def user_id(self):
"""Returns the a unique identifier for the user or None if there are no """Returns the a unique identifier for the user
credentials.
Returns None if there are no credentials.
The id is provided by the current credentials' id_token. The id is provided by the current credentials' id_token.
""" """

View File

@@ -39,9 +39,9 @@ class AppAssertionCredentials(AssertionCredentials):
"""Credentials object for Compute Engine Assertion Grants """Credentials object for Compute Engine Assertion Grants
This object will allow a Compute Engine instance to identify itself to This object will allow a Compute Engine instance to identify itself to
Google and other OAuth 2.0 servers that can verify assertions. It can be used Google and other OAuth 2.0 servers that can verify assertions. It can be
for the purpose of accessing data stored under an account assigned to the used for the purpose of accessing data stored under an account assigned to
Compute Engine instance itself. the Compute Engine instance itself.
This credential does not require a flow to instantiate because it represents This credential does not require a flow to instantiate because it represents
a two legged flow, and therefore has all of the required information to a two legged flow, and therefore has all of the required information to
@@ -53,8 +53,8 @@ class AppAssertionCredentials(AssertionCredentials):
"""Constructor for AppAssertionCredentials """Constructor for AppAssertionCredentials
Args: Args:
scope: string or iterable of strings, scope(s) of the credentials being scope: string or iterable of strings, scope(s) of the credentials
requested. being requested.
""" """
self.scope = util.scopes_to_string(scope) self.scope = util.scopes_to_string(scope)
self.kwargs = kwargs self.kwargs = kwargs
@@ -73,8 +73,9 @@ class AppAssertionCredentials(AssertionCredentials):
Skip all the storage hoops and just refresh using the API. Skip all the storage hoops and just refresh using the API.
Args: Args:
http_request: callable, a callable that matches the method signature of http_request: callable, a callable that matches the method signature
httplib2.Http.request, used to make the refresh request. of httplib2.Http.request, used to make the refresh
request.
Raises: Raises:
AccessTokenRefreshError: When the refresh fails. AccessTokenRefreshError: When the refresh fails.

View File

@@ -31,16 +31,18 @@ class Storage(BaseStorage):
"""Store and retrieve a single credential to and from the keyring. """Store and retrieve a single credential to and from the keyring.
To use this module you must have the keyring module installed. See To use this module you must have the keyring module installed. See
<http://pypi.python.org/pypi/keyring/>. This is an optional module and is not <http://pypi.python.org/pypi/keyring/>. This is an optional module and is
installed with oauth2client by default because it does not work on all the not installed with oauth2client by default because it does not work on all
platforms that oauth2client supports, such as Google App Engine. the platforms that oauth2client supports, such as Google App Engine.
The keyring module <http://pypi.python.org/pypi/keyring/> is a cross-platform The keyring module <http://pypi.python.org/pypi/keyring/> is a
library for access the keyring capabilities of the local system. The user will cross-platform library for access the keyring capabilities of the local
be prompted for their keyring password when this module is used, and the system. The user will be prompted for their keyring password when this
manner in which the user is prompted will vary per platform. module is used, and the manner in which the user is prompted will vary per
platform.
Usage::
Usage:
from oauth2client.keyring_storage import Storage from oauth2client.keyring_storage import Storage
s = Storage('name_of_application', 'user1') s = Storage('name_of_application', 'user1')
@@ -52,8 +54,8 @@ class Storage(BaseStorage):
"""Constructor. """Constructor.
Args: Args:
service_name: string, The name of the service under which the credentials service_name: string, The name of the service under which the
are stored. credentials are stored.
user_name: string, The name of the user to store credentials for. user_name: string, The name of the user to store credentials for.
""" """
self._service_name = service_name self._service_name = service_name
@@ -63,7 +65,8 @@ class Storage(BaseStorage):
def acquire_lock(self): def acquire_lock(self):
"""Acquires any lock necessary to access this Storage. """Acquires any lock necessary to access this Storage.
This lock is not reentrant.""" This lock is not reentrant.
"""
self._lock.acquire() self._lock.acquire()
def release_lock(self): def release_lock(self):

View File

@@ -265,7 +265,8 @@ try:
Raises: Raises:
AlreadyLockedException: if the lock is already acquired. AlreadyLockedException: if the lock is already acquired.
IOError: if the open fails. IOError: if the open fails.
CredentialsFileSymbolicLinkError if the file is a symbolic link. CredentialsFileSymbolicLinkError: if the file is a symbolic
link.
""" """
if self._locked: if self._locked:
raise AlreadyLockedException('File %s is already locked' % raise AlreadyLockedException('File %s is already locked' %
@@ -337,7 +338,8 @@ class LockedFile(object):
filename: string, The path of the file to open. filename: string, The path of the file to open.
mode: string, The mode to try to open the file with. mode: string, The mode to try to open the file with.
fallback_mode: string, The mode to use if locking fails. fallback_mode: string, The mode to use if locking fails.
use_native_locking: bool, Whether or not fcntl/win32 locking is used. use_native_locking: bool, Whether or not fcntl/win32 locking is
used.
""" """
opener = None opener = None
if not opener and use_native_locking: if not opener and use_native_locking:

View File

@@ -128,9 +128,9 @@ def get_credential_storage_custom_key(
Args: Args:
filename: The JSON file storing a set of credentials filename: The JSON file storing a set of credentials
key_dict: A dictionary to use as the key for storing this credential. There key_dict: A dictionary to use as the key for storing this credential.
is no ordering of the keys in the dictionary. Logically equivalent There is no ordering of the keys in the dictionary. Logically
dictionaries will produce equivalent storage keys. equivalent dictionaries will produce equivalent storage keys.
warn_on_readonly: if True, log a warning if the store is readonly warn_on_readonly: if True, log a warning if the store is readonly
Returns: Returns:
@@ -151,9 +151,9 @@ def get_all_credential_keys(filename, warn_on_readonly=True):
warn_on_readonly: if True, log a warning if the store is readonly warn_on_readonly: if True, log a warning if the store is readonly
Returns: Returns:
A list of the credential keys present in the file. They are returned as A list of the credential keys present in the file. They are returned
dictionaries that can be passed into get_credential_storage_custom_key to as dictionaries that can be passed into
get the actual credentials. get_credential_storage_custom_key to get the actual credentials.
""" """
multistore = _get_multistore(filename, warn_on_readonly=warn_on_readonly) multistore = _get_multistore(filename, warn_on_readonly=warn_on_readonly)
multistore._lock() multistore._lock()
@@ -348,8 +348,8 @@ class _MultiStore(object):
The multistore must be locked when this is called. The multistore must be locked when this is called.
Raises: Raises:
NewerCredentialStoreError: Raised when a newer client has written the NewerCredentialStoreError: Raised when a newer client has written
store. the store.
""" """
self._data = {} self._data = {}
try: try:
@@ -418,7 +418,8 @@ class _MultiStore(object):
"""Gets all the registered credential keys in the multistore. """Gets all the registered credential keys in the multistore.
Returns: Returns:
A list of dictionaries corresponding to all the keys currently registered A list of dictionaries corresponding to all the keys currently
registered
""" """
return [dict(key) for key in self._data.keys()] return [dict(key) for key in self._data.keys()]

View File

@@ -133,16 +133,15 @@ def run_flow(flow, storage, flags, http=None):
of values. of values.
``--[no]auth_local_webserver`` (boolean, default: ``True``) ``--[no]auth_local_webserver`` (boolean, default: ``True``)
Run a local web server to handle redirects during OAuth authorization. Run a local web server to handle redirects during OAuth
authorization.
The tools module defines an ``ArgumentParser`` the already contains the flag The tools module defines an ``ArgumentParser`` the already contains the flag
definitions that ``run()`` requires. You can pass that ``ArgumentParser`` to your definitions that ``run()`` requires. You can pass that ``ArgumentParser`` to
``ArgumentParser`` constructor:: your ``ArgumentParser`` constructor::
parser = argparse.ArgumentParser(description=__doc__, parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter, formatter_class=argparse.RawDescriptionHelpFormatter,
parents=[tools.argparser]) parents=[tools.argparser])
flags = parser.parse_args(argv) flags = parser.parse_args(argv)

View File

@@ -72,8 +72,8 @@ def positional(max_positional_args):
def fn(pos1, kwonly1=None, kwonly2=None): def fn(pos1, kwonly1=None, kwonly2=None):
... ...
If no default value is provided to a keyword argument, it becomes a required If no default value is provided to a keyword argument, it becomes a
keyword argument:: required keyword argument::
@positional(0) @positional(0)
def fn(required_kw): def fn(required_kw):
@@ -107,17 +107,18 @@ def positional(max_positional_args):
Args: Args:
max_positional_arguments: Maximum number of positional arguments. All max_positional_arguments: Maximum number of positional arguments. All
parameters after the this index must be keyword only. parameters after the this index must be
keyword only.
Returns: Returns:
A decorator that prevents using arguments after max_positional_args from A decorator that prevents using arguments after max_positional_args
being used as positional parameters. from being used as positional parameters.
Raises: Raises:
TypeError if a key-word only argument is provided as a positional TypeError: if a key-word only argument is provided as a positional
parameter, but only if util.positional_parameters_enforcement is set to parameter, but only if
util.positional_parameters_enforcement is set to
POSITIONAL_EXCEPTION. POSITIONAL_EXCEPTION.
""" """
def positional_decorator(wrapped): def positional_decorator(wrapped):
@@ -187,8 +188,8 @@ def string_to_scopes(scopes):
def dict_to_tuple_key(dictionary): def dict_to_tuple_key(dictionary):
"""Converts a dictionary to a tuple that can be used as an immutable key. """Converts a dictionary to a tuple that can be used as an immutable key.
The resulting key is always sorted so that logically equivalent dictionaries The resulting key is always sorted so that logically equivalent
always produce an identical tuple for a key. dictionaries always produce an identical tuple for a key.
Args: Args:
dictionary: the dictionary to use as the key. dictionary: the dictionary to use as the key.