diff --git a/oauth2client/appengine.py b/oauth2client/appengine.py index 8e05d8b..165c9b1 100644 --- a/oauth2client/appengine.py +++ b/oauth2client/appengine.py @@ -31,7 +31,6 @@ from google.appengine.api import app_identity from google.appengine.api import memcache from google.appengine.api import users from google.appengine.ext import db -from google.appengine.ext import ndb from google.appengine.ext import webapp from google.appengine.ext.webapp.util import login_required from google.appengine.ext.webapp.util import run_wsgi_app @@ -49,6 +48,13 @@ from oauth2client.client import Flow from oauth2client.client import OAuth2WebServerFlow from oauth2client.client import Storage +# TODO(dhermes): Resolve import issue. +# This is a temporary fix for a Google internal issue. +try: + from google.appengine.ext import ndb +except ImportError: + ndb = None + logger = logging.getLogger(__name__) OAUTH2CLIENT_NAMESPACE = 'oauth2client#ns' @@ -84,23 +90,23 @@ class SiteXsrfSecretKey(db.Model): """ secret = db.StringProperty() +if ndb is not None: + class SiteXsrfSecretKeyNDB(ndb.Model): + """NDB Model for storage for the sites XSRF secret key. -class SiteXsrfSecretKeyNDB(ndb.Model): - """NDB Model for storage for the sites XSRF secret key. + Since this model uses the same kind as SiteXsrfSecretKey, it can be used + interchangeably. This simply provides an NDB model for interacting with the + same data the DB model interacts with. - Since this model uses the same kind as SiteXsrfSecretKey, it can be used - interchangeably. This simply provides an NDB model for interacting with the - same data the DB model interacts with. + There should only be one instance stored of this model, the one used for the + site. + """ + secret = ndb.StringProperty() - There should only be one instance stored of this model, the one used for the - site. - """ - secret = ndb.StringProperty() - - @classmethod - def _get_kind(cls): - """Return the kind name for this class.""" - return 'SiteXsrfSecretKey' + @classmethod + def _get_kind(cls): + """Return the kind name for this class.""" + return 'SiteXsrfSecretKey' def _generate_new_xsrf_secret_key(): @@ -217,30 +223,31 @@ class FlowProperty(db.Property): return not value -class FlowNDBProperty(ndb.PickleProperty): - """App Engine NDB datastore Property for Flow. +if ndb is not None: + class FlowNDBProperty(ndb.PickleProperty): + """App Engine NDB datastore Property for Flow. - Serves the same purpose as the DB FlowProperty, but for NDB models. Since - PickleProperty inherits from BlobProperty, the underlying representation of - the data in the datastore will be the same as in the DB case. + Serves the same purpose as the DB FlowProperty, but for NDB models. Since + PickleProperty inherits from BlobProperty, the underlying 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 - oauth2client.Flow - """ - - def _validate(self, value): - """Validates a value as a proper Flow object. - - Args: - value: A value to be set on the property. - - Raises: - TypeError if the value is not an instance of Flow. + Utility property that allows easy storage and retrieval of an + oauth2client.Flow """ - logger.info('validate: Got type %s', type(value)) - if value is not None and not isinstance(value, Flow): - raise TypeError('Property %s must be convertible to a flow ' - 'instance; received: %s.' % (self._name, value)) + + def _validate(self, value): + """Validates a value as a proper Flow object. + + Args: + value: A value to be set on the property. + + Raises: + TypeError if the value is not an instance of Flow. + """ + logger.info('validate: Got type %s', type(value)) + if value is not None and not isinstance(value, Flow): + raise TypeError('Property %s must be convertible to a flow ' + 'instance; received: %s.' % (self._name, value)) class CredentialsProperty(db.Property): @@ -289,65 +296,66 @@ class CredentialsProperty(db.Property): return value -# TODO(dhermes): Turn this into a JsonProperty and overhaul the Credentials -# and subclass mechanics to use new_from_dict, to_dict, -# from_dict, etc. -class CredentialsNDBProperty(ndb.BlobProperty): - """App Engine NDB datastore Property for Credentials. +if ndb is not None: + # TODO(dhermes): Turn this into a JsonProperty and overhaul the Credentials + # and subclass mechanics to use new_from_dict, to_dict, + # from_dict, etc. + class CredentialsNDBProperty(ndb.BlobProperty): + """App Engine NDB datastore Property for Credentials. - Serves the same purpose as the DB CredentialsProperty, but for NDB models. - Since CredentialsProperty stores data as a blob and this inherits from - BlobProperty, the data in the datastore will be the same as in the DB case. + Serves the same purpose as the DB CredentialsProperty, but for NDB models. + Since CredentialsProperty stores data as a blob and this 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 - subclasses. - """ - def _validate(self, value): - """Validates a value as a proper credentials object. - - Args: - value: A value to be set on the property. - - Raises: - TypeError if the value is not an instance of Credentials. + Utility property that allows easy storage and retrieval of Credentials and + subclasses. """ - logger.info('validate: Got type %s', type(value)) - if value is not None and not isinstance(value, Credentials): - raise TypeError('Property %s must be convertible to a credentials ' - 'instance; received: %s.' % (self._name, value)) + def _validate(self, value): + """Validates a value as a proper credentials object. - def _to_base_type(self, value): - """Converts our validated value to a JSON serialized string. + Args: + value: A value to be set on the property. - Args: - value: A value to be set in the datastore. + Raises: + TypeError if the value is not an instance of Credentials. + """ + logger.info('validate: Got type %s', type(value)) + if value is not None and not isinstance(value, Credentials): + raise TypeError('Property %s must be convertible to a credentials ' + 'instance; received: %s.' % (self._name, value)) - Returns: - A JSON serialized version of the credential, else '' if value is None. - """ - if value is None: - return '' - else: - return value.to_json() + def _to_base_type(self, value): + """Converts our validated value to a JSON serialized string. - def _from_base_type(self, value): - """Converts our stored JSON string back to the desired type. + Args: + value: A value to be set in the datastore. - Args: - value: A value from the datastore to be converted to the desired type. + Returns: + A JSON serialized version of the credential, else '' if value is None. + """ + if value is None: + return '' + else: + return value.to_json() - Returns: - A deserialized Credentials (or subclass) object, else None if the - value can't be parsed. - """ - if not value: - return None - try: - # Uses the from_json method of the implied class of value - credentials = Credentials.new_from_json(value) - except ValueError: - credentials = None - return credentials + def _from_base_type(self, value): + """Converts our stored JSON string back to the desired type. + + Args: + value: A value from the datastore to be converted to the desired type. + + Returns: + A deserialized Credentials (or subclass) object, else None if the + value can't be parsed. + """ + if not value: + return None + try: + # Uses the from_json method of the implied class of value + credentials = Credentials.new_from_json(value) + except ValueError: + credentials = None + return credentials class StorageByKeyName(Storage): @@ -385,7 +393,7 @@ class StorageByKeyName(Storage): # issubclass will fail if one of the arguments is not a class, only need # worry about new-style classes since ndb and db models are new-style if isinstance(self._model, type): - if issubclass(self._model, ndb.Model): + if ndb is not None and issubclass(self._model, ndb.Model): return True elif issubclass(self._model, db.Model): return False @@ -469,23 +477,24 @@ class CredentialsModel(db.Model): credentials = CredentialsProperty() -class CredentialsNDBModel(ndb.Model): - """NDB Model for storage of OAuth 2.0 Credentials +if ndb is not None: + class CredentialsNDBModel(ndb.Model): + """NDB Model for storage of OAuth 2.0 Credentials - Since this model uses the same kind as CredentialsModel and has a property - which can serialize and deserialize Credentials correctly, it can be used - interchangeably with a CredentialsModel to access, insert and delete the same - entities. This simply provides an NDB model for interacting with the - same data the DB model interacts with. + Since this model uses the same kind as CredentialsModel and has a property + which can serialize and deserialize Credentials correctly, it can be used + interchangeably with a CredentialsModel to access, insert and delete the + same entities. This simply provides an NDB model for interacting with the + same data the DB model interacts with. - Storage of the model is keyed by the user.user_id(). - """ - credentials = CredentialsNDBProperty() + Storage of the model is keyed by the user.user_id(). + """ + credentials = CredentialsNDBProperty() - @classmethod - def _get_kind(cls): - """Return the kind name for this class.""" - return 'CredentialsModel' + @classmethod + def _get_kind(cls): + """Return the kind name for this class.""" + return 'CredentialsModel' def _build_state_value(request_handler, user):