thirdparty/google_appengine/google/appengine/ext/db/__init__.py
changeset 109 620f9b141567
child 149 f2e327a7c5de
equal deleted inserted replaced
108:261778de26ff 109:620f9b141567
       
     1 #!/usr/bin/env python
       
     2 #
       
     3 # Copyright 2007 Google Inc.
       
     4 #
       
     5 # Licensed under the Apache License, Version 2.0 (the "License");
       
     6 # you may not use this file except in compliance with the License.
       
     7 # You may obtain a copy of the License at
       
     8 #
       
     9 #     http://www.apache.org/licenses/LICENSE-2.0
       
    10 #
       
    11 # Unless required by applicable law or agreed to in writing, software
       
    12 # distributed under the License is distributed on an "AS IS" BASIS,
       
    13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    14 # See the License for the specific language governing permissions and
       
    15 # limitations under the License.
       
    16 #
       
    17 
       
    18 """Simple, schema-based database abstraction layer for the datastore.
       
    19 
       
    20 Modeled after Django's abstraction layer on top of SQL databases,
       
    21 http://www.djangoproject.com/documentation/mode_api/. Ours is a little simpler
       
    22 and a lot less code because the datastore is so much simpler than SQL
       
    23 databases.
       
    24 
       
    25 The programming model is to declare Python subclasses of the Model class,
       
    26 declaring datastore properties as class members of that class. So if you want to
       
    27 publish a story with title, body, and created date, you would do it like this:
       
    28 
       
    29     class Story(db.Model):
       
    30       title = db.StringProperty()
       
    31       body = db.TextProperty()
       
    32       created = db.DateTimeProperty(auto_now_add=True)
       
    33 
       
    34 You can create a new Story in the datastore with this usage pattern:
       
    35 
       
    36     story = Story(title='My title')
       
    37     story.body = 'My body'
       
    38     story.put()
       
    39 
       
    40 You query for Story entities using built in query interfaces that map directly
       
    41 to the syntax and semantics of the datastore:
       
    42 
       
    43     stories = Story.all().filter('date >=', yesterday).order('-date')
       
    44     for story in stories:
       
    45       print story.title
       
    46 
       
    47 The Property declarations enforce types by performing validation on assignment.
       
    48 For example, the DateTimeProperty enforces that you assign valid datetime
       
    49 objects, and if you supply the "required" option for a property, you will not
       
    50 be able to assign None to that property.
       
    51 
       
    52 We also support references between models, so if a story has comments, you
       
    53 would represent it like this:
       
    54 
       
    55     class Comment(db.Model):
       
    56       story = db.ReferenceProperty(Story)
       
    57       body = db.TextProperty()
       
    58 
       
    59 When you get a story out of the datastore, the story reference is resolved
       
    60 automatically the first time it is referenced, which makes it easy to use
       
    61 model instances without performing additional queries by hand:
       
    62 
       
    63     comment = Comment.get(key)
       
    64     print comment.story.title
       
    65 
       
    66 Likewise, you can access the set of comments that refer to each story through
       
    67 this property through a reverse reference called comment_set, which is a Query
       
    68 preconfigured to return all matching comments:
       
    69 
       
    70     story = Story.get(key)
       
    71     for comment in story.comment_set:
       
    72        print comment.body
       
    73 
       
    74 """
       
    75 
       
    76 
       
    77 
       
    78 
       
    79 
       
    80 
       
    81 import datetime
       
    82 import logging
       
    83 import time
       
    84 import urlparse
       
    85 
       
    86 from google.appengine.api import datastore
       
    87 from google.appengine.api import datastore_errors
       
    88 from google.appengine.api import datastore_types
       
    89 from google.appengine.api import users
       
    90 
       
    91 Error = datastore_errors.Error
       
    92 BadValueError = datastore_errors.BadValueError
       
    93 BadPropertyError = datastore_errors.BadPropertyError
       
    94 BadRequestError = datastore_errors.BadRequestError
       
    95 EntityNotFoundError = datastore_errors.EntityNotFoundError
       
    96 BadArgumentError = datastore_errors.BadArgumentError
       
    97 QueryNotFoundError = datastore_errors.QueryNotFoundError
       
    98 TransactionNotFoundError = datastore_errors.TransactionNotFoundError
       
    99 Rollback = datastore_errors.Rollback
       
   100 TransactionFailedError = datastore_errors.TransactionFailedError
       
   101 BadFilterError = datastore_errors.BadFilterError
       
   102 BadQueryError = datastore_errors.BadQueryError
       
   103 BadKeyError = datastore_errors.BadKeyError
       
   104 InternalError = datastore_errors.InternalError
       
   105 NeedIndexError = datastore_errors.NeedIndexError
       
   106 Timeout = datastore_errors.Timeout
       
   107 
       
   108 ValidationError = BadValueError
       
   109 
       
   110 Key = datastore_types.Key
       
   111 Category = datastore_types.Category
       
   112 Link = datastore_types.Link
       
   113 Email = datastore_types.Email
       
   114 GeoPt = datastore_types.GeoPt
       
   115 IM = datastore_types.IM
       
   116 PhoneNumber = datastore_types.PhoneNumber
       
   117 PostalAddress = datastore_types.PostalAddress
       
   118 Rating = datastore_types.Rating
       
   119 Text = datastore_types.Text
       
   120 Blob = datastore_types.Blob
       
   121 
       
   122 _kind_map = {}
       
   123 
       
   124 _SELF_REFERENCE = object()
       
   125 
       
   126 
       
   127 _RESERVED_WORDS = set(['key_name'])
       
   128 
       
   129 
       
   130 
       
   131 
       
   132 class NotSavedError(Error):
       
   133   """Raised when a saved-object action is performed on a non-saved object."""
       
   134 
       
   135 
       
   136 class KindError(BadValueError):
       
   137   """Raised when an entity is used with incorrect Model."""
       
   138 
       
   139 
       
   140 class PropertyError(Error):
       
   141   """Raised when non-existent property is referenced."""
       
   142 
       
   143 
       
   144 class DuplicatePropertyError(Error):
       
   145   """Raised when a property is duplicated in a model definition."""
       
   146 
       
   147 
       
   148 class ConfigurationError(Error):
       
   149   """Raised when a property is improperly configured."""
       
   150 
       
   151 
       
   152 class ReservedWordError(Error):
       
   153   """Raised when a property is defined for a reserved word."""
       
   154 
       
   155 
       
   156 _ALLOWED_PROPERTY_TYPES = set([
       
   157     basestring,
       
   158     str,
       
   159     unicode,
       
   160     bool,
       
   161     int,
       
   162     long,
       
   163     float,
       
   164     Key,
       
   165     datetime.datetime,
       
   166     datetime.date,
       
   167     datetime.time,
       
   168     Blob,
       
   169     Text,
       
   170     users.User,
       
   171     Category,
       
   172     Link,
       
   173     Email,
       
   174     GeoPt,
       
   175     IM,
       
   176     PhoneNumber,
       
   177     PostalAddress,
       
   178     Rating,
       
   179     ])
       
   180 
       
   181 _ALLOWED_EXPANDO_PROPERTY_TYPES = set(_ALLOWED_PROPERTY_TYPES)
       
   182 _ALLOWED_EXPANDO_PROPERTY_TYPES.update((list, tuple, type(None)))
       
   183 
       
   184 
       
   185 def class_for_kind(kind):
       
   186   """Return base-class responsible for implementing kind.
       
   187 
       
   188   Necessary to recover the class responsible for implementing provided
       
   189   kind.
       
   190 
       
   191   Args:
       
   192     kind: Entity kind string.
       
   193 
       
   194   Returns:
       
   195     Class implementation for kind.
       
   196 
       
   197   Raises:
       
   198     KindError when there is no implementation for kind.
       
   199   """
       
   200   try:
       
   201     return _kind_map[kind]
       
   202   except KeyError:
       
   203     raise KindError('No implementation for kind \'%s\'' % kind)
       
   204 
       
   205 
       
   206 def check_reserved_word(attr_name):
       
   207   """Raise an exception if attribute name is a reserved word.
       
   208 
       
   209   Args:
       
   210     attr_name: Name to check to see if it is a reserved word.
       
   211 
       
   212   Raises:
       
   213     ReservedWordError when attr_name is determined to be a reserved word.
       
   214   """
       
   215   if datastore_types.RESERVED_PROPERTY_NAME.match(attr_name):
       
   216     raise ReservedWordError(
       
   217         "Cannot define property.  All names both beginning and "
       
   218         "ending with '__' are reserved.")
       
   219 
       
   220   if attr_name in _RESERVED_WORDS or attr_name in dir(Model):
       
   221     raise ReservedWordError(
       
   222         "Cannot define property using reserved word '%(attr_name)s'. "
       
   223         "If you would like to use this name in the datastore consider "
       
   224         "using a different name like %(attr_name)s_ and adding "
       
   225         "name='%(attr_name)s' to the parameter list of the property "
       
   226         "definition." % locals())
       
   227 
       
   228 
       
   229 class PropertiedClass(type):
       
   230   """Meta-class for initializing Model classes properties.
       
   231 
       
   232   Used for initializing Properties defined in the context of a model.
       
   233   By using a meta-class much of the configuration of a Property
       
   234   descriptor becomes implicit.  By using this meta-class, descriptors
       
   235   that are of class Model are notified about which class they
       
   236   belong to and what attribute they are associated with and can
       
   237   do appropriate initialization via __property_config__.
       
   238 
       
   239   Duplicate properties are not permitted.
       
   240   """
       
   241 
       
   242   def __init__(cls, name, bases, dct):
       
   243     """Initializes a class that might have property definitions.
       
   244 
       
   245     This method is called when a class is created with the PropertiedClass
       
   246     meta-class.
       
   247 
       
   248     Loads all properties for this model and its base classes in to a dictionary
       
   249     for easy reflection via the 'properties' method.
       
   250 
       
   251     Configures each property defined in the new class.
       
   252 
       
   253     Duplicate properties, either defined in the new class or defined separately
       
   254     in two base classes are not permitted.
       
   255 
       
   256     Properties may not assigned to names which are in the list of
       
   257     _RESERVED_WORDS.  It is still possible to store a property using a reserved
       
   258     word in the datastore by using the 'name' keyword argument to the Property
       
   259     constructor.
       
   260 
       
   261     Args:
       
   262       cls: Class being initialized.
       
   263       name: Name of new class.
       
   264       bases: Base classes of new class.
       
   265       dct: Dictionary of new definitions for class.
       
   266 
       
   267     Raises:
       
   268       DuplicatePropertyError when a property is duplicated either in the new
       
   269         class or separately in two base classes.
       
   270       ReservedWordError when a property is given a name that is in the list of
       
   271         reserved words, attributes of Model and names of the form '__.*__'.
       
   272     """
       
   273     super(PropertiedClass, cls).__init__(name, bases, dct)
       
   274 
       
   275     cls._properties = {}
       
   276     defined = set()
       
   277     for base in bases:
       
   278       if hasattr(base, '_properties'):
       
   279         property_keys = base._properties.keys()
       
   280         duplicate_properties = defined.intersection(property_keys)
       
   281         if duplicate_properties:
       
   282           raise DuplicatePropertyError(
       
   283               'Duplicate properties in base class %s already defined: %s' %
       
   284               (base.__name__, list(duplicate_properties)))
       
   285         defined.update(property_keys)
       
   286         cls._properties.update(base._properties)
       
   287 
       
   288     for attr_name in dct.keys():
       
   289       attr = dct[attr_name]
       
   290       if isinstance(attr, Property):
       
   291         check_reserved_word(attr_name)
       
   292         if attr_name in defined:
       
   293           raise DuplicatePropertyError('Duplicate property: %s' % attr_name)
       
   294         defined.add(attr_name)
       
   295         cls._properties[attr_name] = attr
       
   296         attr.__property_config__(cls, attr_name)
       
   297 
       
   298     _kind_map[cls.kind()] = cls
       
   299 
       
   300 
       
   301 class Property(object):
       
   302   """A Property is an attribute of a Model.
       
   303 
       
   304   It defines the type of the attribute, which determines how it is stored
       
   305   in the datastore and how the property values are validated. Different property
       
   306   types support different options, which change validation rules, default
       
   307   values, etc.  The simplest example of a property is a StringProperty:
       
   308 
       
   309      class Story(db.Model):
       
   310        title = db.StringProperty()
       
   311   """
       
   312 
       
   313   creation_counter = 0
       
   314 
       
   315   def __init__(self, verbose_name=None, name=None, default=None,
       
   316                required=False, validator=None, choices=None):
       
   317     """Initializes this Property with the given options.
       
   318 
       
   319     Args:
       
   320       verbose_name: User friendly name of property.
       
   321       name: Storage name for property.  By default, uses attribute name
       
   322         as it is assigned in the Model sub-class.
       
   323       default: Default value for property if none is assigned.
       
   324       required: Whether property is required.
       
   325       validator: User provided method used for validation.
       
   326       choices: User provided set of valid property values.
       
   327     """
       
   328     self.verbose_name = verbose_name
       
   329     self.name = name
       
   330     self.default = default
       
   331     self.required = required
       
   332     self.validator = validator
       
   333     self.choices = choices
       
   334     self.creation_counter = Property.creation_counter
       
   335     Property.creation_counter += 1
       
   336 
       
   337   def __property_config__(self, model_class, property_name):
       
   338     """Configure property, connecting it to its model.
       
   339 
       
   340     Configure the property so that it knows its property name and what class
       
   341     it belongs to.
       
   342 
       
   343     Args:
       
   344       model_class: Model class which Property will belong to.
       
   345       property_name: Name of property within Model instance to store property
       
   346         values in.  By default this will be the property name preceded by
       
   347         an underscore, but may change for different subclasses.
       
   348     """
       
   349     self.model_class = model_class
       
   350     if self.name is None:
       
   351       self.name = property_name
       
   352 
       
   353   def __get__(self, model_instance, model_class):
       
   354     """Returns the value for this property on the given model instance.
       
   355 
       
   356     See http://docs.python.org/ref/descriptors.html for a description of
       
   357     the arguments to this class and what they mean."""
       
   358     if model_instance is None:
       
   359       return self
       
   360 
       
   361     try:
       
   362       return getattr(model_instance, self._attr_name())
       
   363     except AttributeError:
       
   364       return None
       
   365 
       
   366   def __set__(self, model_instance, value):
       
   367     """Sets the value for this property on the given model instance.
       
   368 
       
   369     See http://docs.python.org/ref/descriptors.html for a description of
       
   370     the arguments to this class and what they mean.
       
   371     """
       
   372     value = self.validate(value)
       
   373     setattr(model_instance, self._attr_name(), value)
       
   374 
       
   375   def default_value(self):
       
   376     """Default value for unassigned values.
       
   377 
       
   378     Returns:
       
   379       Default value as provided by __init__(default).
       
   380     """
       
   381     return self.default
       
   382 
       
   383   def validate(self, value):
       
   384     """Assert that provided value is compatible with this property.
       
   385 
       
   386     Args:
       
   387       value: Value to validate against this Property.
       
   388 
       
   389     Returns:
       
   390       A valid value, either the input unchanged or adapted to the
       
   391       required type.
       
   392 
       
   393     Raises:
       
   394       BadValueError if the value is not appropriate for this
       
   395       property in any way.
       
   396     """
       
   397     if self.empty(value):
       
   398       if self.required:
       
   399         raise BadValueError('Property %s is required' % self.name)
       
   400     else:
       
   401       if self.choices:
       
   402         match = False
       
   403         for choice in self.choices:
       
   404           if choice == value:
       
   405             match = True
       
   406         if not match:
       
   407           raise BadValueError('Property %s is %r; must be one of %r' %
       
   408                               (self.name, value, self.choices))
       
   409     if self.validator is not None:
       
   410       self.validator(value)
       
   411     return value
       
   412 
       
   413   def empty(self, value):
       
   414     """Determine if value is empty in the context of this property.
       
   415 
       
   416     For most kinds, this is equivalent to "not value", but for kinds like
       
   417     bool, the test is more subtle, so subclasses can override this method
       
   418     if necessary.
       
   419 
       
   420     Args:
       
   421       value: Value to validate against this Property.
       
   422 
       
   423     Returns:
       
   424       True if this value is considered empty in the context of this Property
       
   425       type, otherwise False.
       
   426     """
       
   427     return not value
       
   428 
       
   429   def get_value_for_datastore(self, model_instance):
       
   430     """Datastore representation of this property.
       
   431 
       
   432     Looks for this property in the given model instance, and returns the proper
       
   433     datastore representation of the value that can be stored in a datastore
       
   434     entity.  Most critically, it will fetch the datastore key value for
       
   435     reference properties.
       
   436 
       
   437     Args:
       
   438       model_instance: Instance to fetch datastore value from.
       
   439 
       
   440     Returns:
       
   441       Datastore representation of the model value in a form that is
       
   442       appropriate for storing in the datastore.
       
   443     """
       
   444     return self.__get__(model_instance, model_instance.__class__)
       
   445 
       
   446   def make_value_from_datastore(self, value):
       
   447     """Native representation of this property.
       
   448 
       
   449     Given a value retrieved from a datastore entity, return a value,
       
   450     possibly converted, to be stored on the model instance.  Usually
       
   451     this returns the value unchanged, but a property class may
       
   452     override this when it uses a different datatype on the model
       
   453     instance than on the entity.
       
   454 
       
   455     This API is not quite symmetric with get_value_for_datastore(),
       
   456     because the model instance on which to store the converted value
       
   457     may not exist yet -- we may be collecting values to be passed to a
       
   458     model constructor.
       
   459 
       
   460     Args:
       
   461       value: value retrieved from the datastore entity.
       
   462 
       
   463     Returns:
       
   464       The value converted for use as a model instance attribute.
       
   465     """
       
   466     return value
       
   467 
       
   468   def _attr_name(self):
       
   469     """Attribute name we use for this property in model instances."""
       
   470     return '_' + self.name
       
   471 
       
   472   data_type = str
       
   473 
       
   474   def datastore_type(self):
       
   475     """Deprecated backwards-compatible accessor method for self.data_type."""
       
   476     return self.data_type
       
   477 
       
   478 
       
   479 class Model(object):
       
   480   """Model is the superclass of all object entities in the datastore.
       
   481 
       
   482   The programming model is to declare Python subclasses of the Model class,
       
   483   declaring datastore properties as class members of that class. So if you want
       
   484   to publish a story with title, body, and created date, you would do it like
       
   485   this:
       
   486 
       
   487     class Story(db.Model):
       
   488       title = db.StringProperty()
       
   489       body = db.TextProperty()
       
   490       created = db.DateTimeProperty(auto_now_add=True)
       
   491 
       
   492   A model instance can have a single parent.  Model instances without any
       
   493   parent are root entities.  It is possible to efficiently query for
       
   494   instances by their shared parent.  All descendents of a single root
       
   495   instance also behave as a transaction group.  This means that when you
       
   496   work one member of the group within a transaction all descendents of that
       
   497   root join the transaction.  All operations within a transaction on this
       
   498   group are ACID.
       
   499   """
       
   500 
       
   501   __metaclass__ = PropertiedClass
       
   502 
       
   503   def __init__(self, parent=None, key_name=None, _app=None, **kwds):
       
   504     """Creates a new instance of this model.
       
   505 
       
   506     To create a new entity, you instantiate a model and then call save(),
       
   507     which saves the entity to the datastore:
       
   508 
       
   509        person = Person()
       
   510        person.name = 'Bret'
       
   511        person.save()
       
   512 
       
   513     You can initialize properties in the model in the constructor with keyword
       
   514     arguments:
       
   515 
       
   516        person = Person(name='Bret')
       
   517 
       
   518     We initialize all other properties to the default value (as defined by the
       
   519     properties in the model definition) if they are not provided in the
       
   520     constructor.
       
   521 
       
   522     Args:
       
   523       parent: Parent instance for this instance or None, indicating a top-
       
   524         level instance.
       
   525       key_name: Name for new model instance.
       
   526       _app: Intentionally undocumented.
       
   527       args: Keyword arguments mapping to properties of model.
       
   528     """
       
   529     if key_name == '':
       
   530       raise BadKeyError('Name cannot be empty.')
       
   531     elif key_name is not None and not isinstance(key_name, basestring):
       
   532       raise BadKeyError('Name must be string type, not %s' %
       
   533                         key_name.__class__.__name__)
       
   534 
       
   535     if parent is not None:
       
   536       if not isinstance(parent, Model):
       
   537         raise TypeError('Expected Model type; received %s (is %s)' %
       
   538                         (parent, parent.__class__.__name__))
       
   539       if not parent.is_saved():
       
   540         raise BadValueError(
       
   541             "%s instance must be saved before it can be used as a "
       
   542             "parent." % parent.kind())
       
   543 
       
   544     self._parent = parent
       
   545     self._entity = None
       
   546     self._key_name = key_name
       
   547     self._app = _app
       
   548 
       
   549     properties = self.properties()
       
   550     for prop in self.properties().values():
       
   551       if prop.name in kwds:
       
   552         value = kwds[prop.name]
       
   553       else:
       
   554         value = prop.default_value()
       
   555       prop.__set__(self, value)
       
   556 
       
   557   def key(self):
       
   558     """Unique key for this entity.
       
   559 
       
   560     This property is only available if this entity is already stored in the
       
   561     datastore, so it is available if this entity was fetched returned from a
       
   562     query, or after save() is called the first time for new entities.
       
   563 
       
   564     Returns:
       
   565       Datastore key of persisted entity.
       
   566 
       
   567     Raises:
       
   568       NotSavedError when entity is not persistent.
       
   569     """
       
   570     if self.is_saved():
       
   571       return self._entity.key()
       
   572     else:
       
   573       raise NotSavedError()
       
   574 
       
   575   def _to_entity(self, entity):
       
   576     """Copies information from this model to provided entity.
       
   577 
       
   578     Args:
       
   579       entity: Entity to save information on.
       
   580     """
       
   581     for prop in self.properties().values():
       
   582       datastore_value = prop.get_value_for_datastore(self)
       
   583       if datastore_value == []:
       
   584         try:
       
   585           del entity[prop.name]
       
   586         except KeyError:
       
   587           pass
       
   588       else:
       
   589         entity[prop.name] = datastore_value
       
   590 
       
   591   def _populate_internal_entity(self, _entity_class=datastore.Entity):
       
   592     """Populates self._entity, saving its state to the datastore.
       
   593 
       
   594     After this method is called, calling is_saved() will return True.
       
   595 
       
   596     Returns:
       
   597       Populated self._entity
       
   598     """
       
   599     self._entity = self._populate_entity(_entity_class=_entity_class)
       
   600     if hasattr(self, '_key_name'):
       
   601       del self._key_name
       
   602     return self._entity
       
   603 
       
   604   def put(self):
       
   605     """Writes this model instance to the datastore.
       
   606 
       
   607     If this instance is new, we add an entity to the datastore.
       
   608     Otherwise, we update this instance, and the key will remain the
       
   609     same.
       
   610 
       
   611     Returns:
       
   612       The key of the instance (either the existing key or a new key).
       
   613 
       
   614     Raises:
       
   615       TransactionFailedError if the data could not be committed.
       
   616     """
       
   617     self._populate_internal_entity()
       
   618     return datastore.Put(self._entity)
       
   619 
       
   620   save = put
       
   621 
       
   622   def _populate_entity(self, _entity_class=datastore.Entity):
       
   623     """Internal helper -- Populate self._entity or create a new one
       
   624     if that one does not exist.  Does not change any state of the instance
       
   625     other than the internal state of the entity.
       
   626 
       
   627     This method is separate from _populate_internal_entity so that it is
       
   628     possible to call to_xml without changing the state of an unsaved entity
       
   629     to saved.
       
   630 
       
   631     Returns:
       
   632       self._entity or a new Entity which is not stored on the instance.
       
   633     """
       
   634     if self.is_saved():
       
   635       entity = self._entity
       
   636     else:
       
   637       if self._parent is not None:
       
   638         entity = _entity_class(self.kind(),
       
   639                                parent=self._parent._entity,
       
   640                                name=self._key_name,
       
   641                                _app=self._app)
       
   642       else:
       
   643         entity = _entity_class(self.kind(),
       
   644                                name=self._key_name,
       
   645                                _app=self._app)
       
   646 
       
   647     self._to_entity(entity)
       
   648     return entity
       
   649 
       
   650   def delete(self):
       
   651     """Deletes this entity from the datastore.
       
   652 
       
   653     Raises:
       
   654       TransactionFailedError if the data could not be committed.
       
   655     """
       
   656     datastore.Delete(self.key())
       
   657     self._entity = None
       
   658 
       
   659 
       
   660   def is_saved(self):
       
   661     """Determine if entity is persisted in the datastore.
       
   662 
       
   663     New instances of Model do not start out saved in the data.  Objects which
       
   664     are saved to or loaded from the Datastore will have a True saved state.
       
   665 
       
   666     Returns:
       
   667       True if object has been persisted to the datastore, otherwise False.
       
   668     """
       
   669     return self._entity is not None
       
   670 
       
   671   def dynamic_properties(self):
       
   672     """Returns a list of all dynamic properties defined for instance."""
       
   673     return []
       
   674 
       
   675   def instance_properties(self):
       
   676     """Alias for dyanmic_properties."""
       
   677     return self.dynamic_properties()
       
   678 
       
   679   def parent(self):
       
   680     """Get the parent of the model instance.
       
   681 
       
   682     Returns:
       
   683       Parent of contained entity or parent provided in constructor, None if
       
   684       instance has no parent.
       
   685     """
       
   686     if (self._parent is None and
       
   687         self._entity is not None and
       
   688         self._entity.parent() is not None):
       
   689       self._parent = get(self._entity.parent())
       
   690     return self._parent
       
   691 
       
   692   def parent_key(self):
       
   693     """Get the parent's key.
       
   694 
       
   695     This method is useful for avoiding a potential fetch from the datastore
       
   696     but still get information about the instances parent.
       
   697 
       
   698     Returns:
       
   699       Parent key of entity, None if there is no parent.
       
   700     """
       
   701     if self._parent is not None:
       
   702       return self._parent.key()
       
   703     elif self._entity is not None:
       
   704       return self._entity.parent()
       
   705     else:
       
   706       return None
       
   707 
       
   708   def to_xml(self, _entity_class=datastore.Entity):
       
   709     """Generate an XML representation of this model instance.
       
   710 
       
   711     atom and gd:namespace properties are converted to XML according to their
       
   712     respective schemas. For more information, see:
       
   713 
       
   714       http://www.atomenabled.org/developers/syndication/
       
   715       http://code.google.com/apis/gdata/common-elements.html
       
   716     """
       
   717     entity = self._populate_entity(_entity_class)
       
   718     return entity.ToXml()
       
   719 
       
   720   @classmethod
       
   721   def get(cls, keys):
       
   722     """Fetch instance from the datastore of a specific Model type using key.
       
   723 
       
   724     We support Key objects and string keys (we convert them to Key objects
       
   725     automatically).
       
   726 
       
   727     Useful for ensuring that specific instance types are retrieved from the
       
   728     datastore.  It also helps that the source code clearly indicates what
       
   729     kind of object is being retreived.  Example:
       
   730 
       
   731       story = Story.get(story_key)
       
   732 
       
   733     Args:
       
   734       keys: Key within datastore entity collection to find; or string key;
       
   735         or list of Keys or string keys.
       
   736 
       
   737     Returns:
       
   738       If a single key was given: a Model instance associated with key
       
   739       for provided class if it exists in the datastore, otherwise
       
   740       None; if a list of keys was given: a list whose items are either
       
   741       a Model instance or None.
       
   742 
       
   743     Raises:
       
   744       KindError if any of the retreived objects are not instances of the
       
   745       type associated with call to 'get'.
       
   746     """
       
   747     results = get(keys)
       
   748     if results is None:
       
   749       return None
       
   750 
       
   751     if isinstance(results, Model):
       
   752       instances = [results]
       
   753     else:
       
   754       instances = results
       
   755 
       
   756     for instance in instances:
       
   757       if not(instance is None or isinstance(instance, cls)):
       
   758         raise KindError('Kind %r is not a subclass of kind %r' %
       
   759                         (instance.kind(), cls.kind()))
       
   760 
       
   761     return results
       
   762 
       
   763   @classmethod
       
   764   def get_by_key_name(cls, key_names, parent=None):
       
   765     """Get instance of Model class by its key's name.
       
   766 
       
   767     Args:
       
   768       key_names: A single key-name or a list of key-names.
       
   769       parent: Parent of instances to get.  Can be a model or key.
       
   770     """
       
   771     if isinstance(parent, Model):
       
   772       parent = parent.key()
       
   773     key_names, multiple = datastore.NormalizeAndTypeCheck(key_names, basestring)
       
   774     keys = [datastore.Key.from_path(cls.kind(), name, parent=parent)
       
   775             for name in key_names]
       
   776     if multiple:
       
   777       return get(keys)
       
   778     else:
       
   779       return get(*keys)
       
   780 
       
   781   @classmethod
       
   782   def get_by_id(cls, ids, parent=None):
       
   783     """Get instance of Model class by id.
       
   784 
       
   785     Args:
       
   786       key_names: A single id or a list of ids.
       
   787       parent: Parent of instances to get.  Can be a model or key.
       
   788     """
       
   789     if isinstance(parent, Model):
       
   790       parent = parent.key()
       
   791     ids, multiple = datastore.NormalizeAndTypeCheck(ids, (int, long))
       
   792     keys = [datastore.Key.from_path(cls.kind(), id, parent=parent)
       
   793             for id in ids]
       
   794     if multiple:
       
   795       return get(keys)
       
   796     else:
       
   797       return get(*keys)
       
   798 
       
   799   @classmethod
       
   800   def get_or_insert(cls, key_name, **kwds):
       
   801     """Transactionally retrieve or create an instance of Model class.
       
   802 
       
   803     This acts much like the Python dictionary setdefault() method, where we
       
   804     first try to retrieve a Model instance with the given key name and parent.
       
   805     If it's not present, then we create a new instance (using the *kwds
       
   806     supplied) and insert that with the supplied key name.
       
   807 
       
   808     Subsequent calls to this method with the same key_name and parent will
       
   809     always yield the same entity (though not the same actual object instance),
       
   810     regardless of the *kwds supplied. If the specified entity has somehow
       
   811     been deleted separately, then the next call will create a new entity and
       
   812     return it.
       
   813 
       
   814     If the 'parent' keyword argument is supplied, it must be a Model instance.
       
   815     It will be used as the parent of the new instance of this Model class if
       
   816     one is created.
       
   817 
       
   818     This method is especially useful for having just one unique entity for
       
   819     a specific identifier. Insertion/retrieval is done transactionally, which
       
   820     guarantees uniqueness.
       
   821 
       
   822     Example usage:
       
   823 
       
   824       class WikiTopic(db.Model):
       
   825         creation_date = db.DatetimeProperty(auto_now_add=True)
       
   826         body = db.TextProperty(required=True)
       
   827 
       
   828       # The first time through we'll create the new topic.
       
   829       wiki_word = 'CommonIdioms'
       
   830       topic = WikiTopic.get_or_insert(wiki_word,
       
   831                                       body='This topic is totally new!')
       
   832       assert topic.key().name() == 'CommonIdioms'
       
   833       assert topic.body == 'This topic is totally new!'
       
   834 
       
   835       # The second time through will just retrieve the entity.
       
   836       overwrite_topic = WikiTopic.get_or_insert(wiki_word,
       
   837                                       body='A totally different message!')
       
   838       assert topic.key().name() == 'CommonIdioms'
       
   839       assert topic.body == 'This topic is totally new!'
       
   840 
       
   841     Args:
       
   842       key_name: Key name to retrieve or create.
       
   843       **kwds: Keyword arguments to pass to the constructor of the model class
       
   844         if an instance for the specified key name does not already exist. If
       
   845         an instance with the supplied key_name and parent already exists, the
       
   846         rest of these arguments will be discarded.
       
   847 
       
   848     Returns:
       
   849       Existing instance of Model class with the specified key_name and parent
       
   850       or a new one that has just been created.
       
   851 
       
   852     Raises:
       
   853       TransactionFailedError if the specified Model instance could not be
       
   854       retrieved or created transactionally (due to high contention, etc).
       
   855     """
       
   856     def txn():
       
   857       entity = cls.get_by_key_name(key_name, parent=kwds.get('parent'))
       
   858       if entity is None:
       
   859         entity = cls(key_name=key_name, **kwds)
       
   860         entity.put()
       
   861       return entity
       
   862     return run_in_transaction(txn)
       
   863 
       
   864   @classmethod
       
   865   def all(cls):
       
   866     """Returns a query over all instances of this model from the datastore.
       
   867 
       
   868     Returns:
       
   869       Query that will retrieve all instances from entity collection.
       
   870     """
       
   871     return Query(cls)
       
   872 
       
   873   @classmethod
       
   874   def gql(cls, query_string, *args, **kwds):
       
   875     """Returns a query using GQL query string.
       
   876 
       
   877     See appengine/ext/gql for more information about GQL.
       
   878 
       
   879     Args:
       
   880       query_string: properly formatted GQL query string with the
       
   881         'SELECT * FROM <entity>' part omitted
       
   882       *args: rest of the positional arguments used to bind numeric references
       
   883         in the query.
       
   884       **kwds: dictionary-based arguments (for named parameters).
       
   885     """
       
   886     return GqlQuery('SELECT * FROM %s %s' % (cls.kind(), query_string),
       
   887                     *args, **kwds)
       
   888 
       
   889   @classmethod
       
   890   def _load_entity_values(cls, entity):
       
   891     """Load dynamic properties from entity.
       
   892 
       
   893     Loads attributes which are not defined as part of the entity in
       
   894     to the model instance.
       
   895 
       
   896     Args:
       
   897       entity: Entity which contain values to search dyanmic properties for.
       
   898     """
       
   899     entity_values = {}
       
   900     for prop in cls.properties().values():
       
   901       if prop.name in entity:
       
   902         try:
       
   903           value = prop.make_value_from_datastore(entity[prop.name])
       
   904           entity_values[prop.name] = value
       
   905         except KeyError:
       
   906           entity_values[prop.name] = []
       
   907 
       
   908     return entity_values
       
   909 
       
   910   @classmethod
       
   911   def from_entity(cls, entity):
       
   912     """Converts the entity representation of this model to an instance.
       
   913 
       
   914     Converts datastore.Entity instance to an instance of cls.
       
   915 
       
   916     Args:
       
   917       entity: Entity loaded directly from datastore.
       
   918 
       
   919     Raises:
       
   920       KindError when cls is incorrect model for entity.
       
   921     """
       
   922     if cls.kind() != entity.kind():
       
   923       raise KindError('Class %s cannot handle kind \'%s\'' %
       
   924                       (repr(cls), entity.kind()))
       
   925 
       
   926     entity_values = cls._load_entity_values(entity)
       
   927     instance = cls(None, **entity_values)
       
   928     instance._entity = entity
       
   929     del instance._key_name
       
   930     return instance
       
   931 
       
   932   @classmethod
       
   933   def kind(cls):
       
   934     """Returns the datastore kind we use for this model.
       
   935 
       
   936     We just use the name of the model for now, ignoring potential collisions.
       
   937     """
       
   938     return cls.__name__
       
   939 
       
   940   @classmethod
       
   941   def entity_type(cls):
       
   942     """Soon to be removed alias for kind."""
       
   943     return cls.kind()
       
   944 
       
   945   @classmethod
       
   946   def properties(cls):
       
   947     """Returns a dictionary of all the properties defined for this model."""
       
   948     return dict(cls._properties)
       
   949 
       
   950   @classmethod
       
   951   def fields(cls):
       
   952     """Soon to be removed alias for properties."""
       
   953     return cls.properties()
       
   954 
       
   955 
       
   956 def get(keys):
       
   957   """Fetch the specific Model instance with the given key from the datastore.
       
   958 
       
   959   We support Key objects and string keys (we convert them to Key objects
       
   960   automatically).
       
   961 
       
   962   Args:
       
   963     keys: Key within datastore entity collection to find; or string key;
       
   964       or list of Keys or string keys.
       
   965 
       
   966     Returns:
       
   967       If a single key was given: a Model instance associated with key
       
   968       for if it exists in the datastore, otherwise None; if a list of
       
   969       keys was given: a list whose items are either a Model instance or
       
   970       None.
       
   971   """
       
   972   keys, multiple = datastore.NormalizeAndTypeCheckKeys(keys)
       
   973   try:
       
   974     entities = datastore.Get(keys)
       
   975   except datastore_errors.EntityNotFoundError:
       
   976     assert not multiple
       
   977     return None
       
   978   models = []
       
   979   for entity in entities:
       
   980     if entity is None:
       
   981       model = None
       
   982     else:
       
   983       cls1 = class_for_kind(entity.kind())
       
   984       model = cls1.from_entity(entity)
       
   985     models.append(model)
       
   986   if multiple:
       
   987     return models
       
   988   assert len(models) == 1
       
   989   return models[0]
       
   990 
       
   991 
       
   992 def put(models):
       
   993   """Store one or more Model instances.
       
   994 
       
   995   Args:
       
   996     models: Model instance or list of Model instances.
       
   997 
       
   998   Returns:
       
   999     A Key or a list of Keys (corresponding to the argument's plurality).
       
  1000 
       
  1001   Raises:
       
  1002     TransactionFailedError if the data could not be committed.
       
  1003   """
       
  1004   models, multiple = datastore.NormalizeAndTypeCheck(models, Model)
       
  1005   entities = [model._populate_internal_entity() for model in models]
       
  1006   keys = datastore.Put(entities)
       
  1007   if multiple:
       
  1008     return keys
       
  1009   assert len(keys) == 1
       
  1010   return keys[0]
       
  1011 
       
  1012 save = put
       
  1013 
       
  1014 
       
  1015 def delete(models):
       
  1016   """Delete one or more Model instances.
       
  1017 
       
  1018   Args:
       
  1019     models: Model instance or list of Model instances.
       
  1020 
       
  1021   Raises:
       
  1022     TransactionFailedError if the data could not be committed.
       
  1023   """
       
  1024   models, multiple = datastore.NormalizeAndTypeCheck(models, Model)
       
  1025   entities = [model.key() for model in models]
       
  1026   keys = datastore.Delete(entities)
       
  1027 
       
  1028 
       
  1029 class Expando(Model):
       
  1030   """Dynamically expandable model.
       
  1031 
       
  1032   An Expando does not require (but can still benefit from) the definition
       
  1033   of any properties before it can be used to store information in the
       
  1034   datastore.  Properties can be added to an expando object by simply
       
  1035   performing an assignment.  The assignment of properties is done on
       
  1036   an instance by instance basis, so it is possible for one object of an
       
  1037   expando type to have different properties from another or even the same
       
  1038   properties with different types.  It is still possible to define
       
  1039   properties on an expando, allowing those properties to behave the same
       
  1040   as on any other model.
       
  1041 
       
  1042   Example:
       
  1043     import datetime
       
  1044 
       
  1045     class Song(db.Expando):
       
  1046       title = db.StringProperty()
       
  1047 
       
  1048     crazy = Song(title='Crazy like a diamond',
       
  1049                  author='Lucy Sky',
       
  1050                  publish_date='yesterday',
       
  1051                  rating=5.0)
       
  1052 
       
  1053     hoboken = Song(title='The man from Hoboken',
       
  1054                    author=['Anthony', 'Lou'],
       
  1055                    publish_date=datetime.datetime(1977, 5, 3))
       
  1056 
       
  1057     crazy.last_minute_note=db.Text('Get a train to the station.')
       
  1058 
       
  1059   Possible Uses:
       
  1060 
       
  1061     One use of an expando is to create an object without any specific
       
  1062     structure and later, when your application mature and it in the right
       
  1063     state, change it to a normal model object and define explicit properties.
       
  1064 
       
  1065   Additional exceptions for expando:
       
  1066 
       
  1067     Protected attributes (ones whose names begin with '_') cannot be used
       
  1068     as dynamic properties.  These are names that are reserved for protected
       
  1069     transient (non-persisted) attributes.
       
  1070 
       
  1071   Order of lookup:
       
  1072 
       
  1073     When trying to set or access an attribute value, any other defined
       
  1074     properties, such as methods and other values in __dict__ take precedence
       
  1075     over values in the datastore.
       
  1076 
       
  1077     1 - Because it is not possible for the datastore to know what kind of
       
  1078         property to store on an undefined expando value, setting a property to
       
  1079         None is the same as deleting it form the expando.
       
  1080 
       
  1081     2 - Persistent variables on Expando must not begin with '_'.  These
       
  1082         variables considered to be 'protected' in Python, and are used
       
  1083         internally.
       
  1084 
       
  1085     3 - Expando's dynamic properties are not able to store empty lists.
       
  1086         Attempting to assign an empty list to a dynamic property will raise
       
  1087         ValueError.  Static properties on Expando can still support empty
       
  1088         lists but like normal Model properties is restricted from using
       
  1089         None.
       
  1090   """
       
  1091 
       
  1092   _dynamic_properties = None
       
  1093 
       
  1094   def __init__(self, parent=None, key_name=None, _app=None, **kwds):
       
  1095     """Creates a new instance of this expando model.
       
  1096 
       
  1097     Args:
       
  1098       parent: Parent instance for this instance or None, indicating a top-
       
  1099         level instance.
       
  1100       key_name: Name for new model instance.
       
  1101       _app: Intentionally undocumented.
       
  1102       args: Keyword arguments mapping to properties of model.
       
  1103     """
       
  1104     super(Expando, self).__init__(parent, key_name, _app, **kwds)
       
  1105     self._dynamic_properties = {}
       
  1106     for prop, value in kwds.iteritems():
       
  1107       if prop not in self.properties() and value is not None:
       
  1108         setattr(self, prop, value)
       
  1109 
       
  1110   def __setattr__(self, key, value):
       
  1111     """Dynamically set field values that are not defined.
       
  1112 
       
  1113     Tries to set the value on the object normally, but failing that
       
  1114     sets the value on the contained entity.
       
  1115 
       
  1116     Args:
       
  1117       key: Name of attribute.
       
  1118       value: Value to set for attribute.  Must be compatible with
       
  1119         datastore.
       
  1120 
       
  1121     Raises:
       
  1122       ValueError on attempt to assign empty list.
       
  1123     """
       
  1124     check_reserved_word(key)
       
  1125     if key[:1] != '_' and key not in self.properties():
       
  1126       if value == []:
       
  1127         raise ValueError('Cannot store empty list to dynamic property %s' %
       
  1128                          key)
       
  1129       if type(value) not in _ALLOWED_EXPANDO_PROPERTY_TYPES:
       
  1130         raise TypeError("Expando cannot accept values of type '%s'." %
       
  1131                         type(value).__name__)
       
  1132       if self._dynamic_properties is None:
       
  1133         self._dynamic_properties = {}
       
  1134       self._dynamic_properties[key] = value
       
  1135     else:
       
  1136       Model.__setattr__(self, key, value)
       
  1137 
       
  1138   def __getattr__(self, key):
       
  1139     """If no explicit attribute defined, retrieve value from entity.
       
  1140 
       
  1141     Tries to get the value on the object normally, but failing that
       
  1142     retrieves value from contained entity.
       
  1143 
       
  1144     Args:
       
  1145       key: Name of attribute.
       
  1146 
       
  1147     Raises:
       
  1148       AttributeError when there is no attribute for key on object or
       
  1149         contained entity.
       
  1150     """
       
  1151     if self._dynamic_properties and key in self._dynamic_properties:
       
  1152       return self._dynamic_properties[key]
       
  1153     else:
       
  1154       return getattr(super(Expando, self), key)
       
  1155 
       
  1156   def __delattr__(self, key):
       
  1157     """Remove attribute from expando.
       
  1158 
       
  1159     Expando is not like normal entities in that undefined fields
       
  1160     can be removed.
       
  1161 
       
  1162     Args:
       
  1163       key: Dynamic property to be deleted.
       
  1164     """
       
  1165     if self._dynamic_properties and key in self._dynamic_properties:
       
  1166       del self._dynamic_properties[key]
       
  1167     else:
       
  1168       object.__delattr__(self, key)
       
  1169 
       
  1170   def dynamic_properties(self):
       
  1171     """Determine which properties are particular to instance of entity.
       
  1172 
       
  1173     Returns:
       
  1174       Set of names which correspond only to the dynamic properties.
       
  1175     """
       
  1176     if self._dynamic_properties is None:
       
  1177       return []
       
  1178     return self._dynamic_properties.keys()
       
  1179 
       
  1180   def _to_entity(self, entity):
       
  1181     """Store to entity, deleting dynamic properties that no longer exist.
       
  1182 
       
  1183     When the expando is saved, it is possible that a given property no longer
       
  1184     exists.  In this case, the property will be removed from the saved instance.
       
  1185 
       
  1186     Args:
       
  1187       entity: Entity which will receive dynamic properties.
       
  1188     """
       
  1189     super(Expando, self)._to_entity(entity)
       
  1190 
       
  1191     if self._dynamic_properties is None:
       
  1192       self._dynamic_properties = {}
       
  1193 
       
  1194     for key, value in self._dynamic_properties.iteritems():
       
  1195       entity[key] = value
       
  1196 
       
  1197     all_properties = set(self._dynamic_properties.iterkeys())
       
  1198     all_properties.update(self.properties().iterkeys())
       
  1199     for key in entity.keys():
       
  1200       if key not in all_properties:
       
  1201         del entity[key]
       
  1202 
       
  1203   @classmethod
       
  1204   def _load_entity_values(cls, entity):
       
  1205     """Load dynamic properties from entity.
       
  1206 
       
  1207     Expando needs to do a second pass to add the entity values which were
       
  1208     ignored by Model because they didn't have an corresponding predefined
       
  1209     property on the model.
       
  1210 
       
  1211     Args:
       
  1212       entity: Entity which contain values to search dyanmic properties for.
       
  1213     """
       
  1214     entity_values = Model._load_entity_values(entity)
       
  1215     for key, value in entity.iteritems():
       
  1216       if key not in entity_values:
       
  1217         entity_values[str(key)] = value
       
  1218     return entity_values
       
  1219 
       
  1220 
       
  1221 class _BaseQuery(object):
       
  1222   """Base class for both Query and GqlQuery."""
       
  1223 
       
  1224   def __init__(self, model_class):
       
  1225     """Constructor."
       
  1226 
       
  1227       Args:
       
  1228         model_class: Model class from which entities are constructed.
       
  1229     """
       
  1230     self._model_class = model_class
       
  1231 
       
  1232   def _get_query(self):
       
  1233     """Subclass must override (and not call their super method).
       
  1234 
       
  1235     Returns:
       
  1236       A datastore.Query instance representing the query.
       
  1237     """
       
  1238     raise NotImplementedError
       
  1239 
       
  1240   def run(self):
       
  1241     """Iterator for this query.
       
  1242 
       
  1243     If you know the number of results you need, consider fetch() instead,
       
  1244     or use a GQL query with a LIMIT clause. It's more efficient.
       
  1245 
       
  1246     Returns:
       
  1247       Iterator for this query.
       
  1248     """
       
  1249     return _QueryIterator(self._model_class, iter(self._get_query().Run()))
       
  1250 
       
  1251   def __iter__(self):
       
  1252     """Iterator for this query.
       
  1253 
       
  1254     If you know the number of results you need, consider fetch() instead,
       
  1255     or use a GQL query with a LIMIT clause. It's more efficient.
       
  1256     """
       
  1257     return self.run()
       
  1258 
       
  1259   def get(self):
       
  1260     """Get first result from this.
       
  1261 
       
  1262     Beware: get() ignores the LIMIT clause on GQL queries.
       
  1263 
       
  1264     Returns:
       
  1265       First result from running the query if there are any, else None.
       
  1266     """
       
  1267     results = self.fetch(1)
       
  1268     try:
       
  1269       return results[0]
       
  1270     except IndexError:
       
  1271       return None
       
  1272 
       
  1273   def count(self, limit=None):
       
  1274     """Number of entities this query fetches.
       
  1275 
       
  1276     Beware: count() ignores the LIMIT clause on GQL queries.
       
  1277 
       
  1278     Args:
       
  1279       limit, a number. If there are more results than this, stop short and
       
  1280       just return this number. Providing this argument makes the count
       
  1281       operation more efficient.
       
  1282 
       
  1283     Returns:
       
  1284       Number of entities this query fetches.
       
  1285     """
       
  1286     return self._get_query().Count(limit=limit)
       
  1287 
       
  1288   def fetch(self, limit, offset=0):
       
  1289     """Return a list of items selected using SQL-like limit and offset.
       
  1290 
       
  1291     Whenever possible, use fetch() instead of iterating over the query
       
  1292     results with run() or __iter__() . fetch() is more efficient.
       
  1293 
       
  1294     Beware: fetch() ignores the LIMIT clause on GQL queries.
       
  1295 
       
  1296     Args:
       
  1297       limit: Maximum number of results to return.
       
  1298       offset: Optional number of results to skip first; default zero.
       
  1299 
       
  1300     Returns:
       
  1301       A list of db.Model instances.  There may be fewer than 'limit'
       
  1302       results if there aren't enough results to satisfy the request.
       
  1303     """
       
  1304     accepted = (int, long)
       
  1305     if not (isinstance(limit, accepted) and isinstance(offset, accepted)):
       
  1306       raise TypeError('Arguments to fetch() must be integers')
       
  1307     if limit < 0 or offset < 0:
       
  1308       raise ValueError('Arguments to fetch() must be >= 0')
       
  1309     if limit == 0:
       
  1310       return []
       
  1311     raw = self._get_query().Get(limit, offset)
       
  1312     return map(self._model_class.from_entity, raw)
       
  1313 
       
  1314   def __getitem__(self, arg):
       
  1315     """Support for query[index] and query[start:stop].
       
  1316 
       
  1317     Beware: this ignores the LIMIT clause on GQL queries.
       
  1318 
       
  1319     Args:
       
  1320       arg: Either a single integer, corresponding to the query[index]
       
  1321         syntax, or a Python slice object, corresponding to the
       
  1322         query[start:stop] or query[start:stop:step] syntax.
       
  1323 
       
  1324     Returns:
       
  1325       A single Model instance when the argument is a single integer.
       
  1326       A list of Model instances when the argument is a slice.
       
  1327     """
       
  1328     if isinstance(arg, slice):
       
  1329       start, stop, step = arg.start, arg.stop, arg.step
       
  1330       if start is None:
       
  1331         start = 0
       
  1332       if stop is None:
       
  1333         raise ValueError('Open-ended slices are not supported')
       
  1334       if step is None:
       
  1335         step = 1
       
  1336       if start < 0 or stop < 0 or step != 1:
       
  1337         raise ValueError(
       
  1338             'Only slices with start>=0, stop>=0, step==1 are supported')
       
  1339       limit = stop - start
       
  1340       if limit < 0:
       
  1341         return []
       
  1342       return self.fetch(limit, start)
       
  1343     elif isinstance(arg, (int, long)):
       
  1344       if arg < 0:
       
  1345         raise ValueError('Only indices >= 0 are supported')
       
  1346       results = self.fetch(1, arg)
       
  1347       if results:
       
  1348         return results[0]
       
  1349       else:
       
  1350         raise IndexError('The query returned fewer than %d results' % (arg+1))
       
  1351     else:
       
  1352       raise TypeError('Only integer indices and slices are supported')
       
  1353 
       
  1354 
       
  1355 class _QueryIterator(object):
       
  1356   """Wraps the datastore iterator to return Model instances.
       
  1357 
       
  1358   The datastore returns entities. We wrap the datastore iterator to
       
  1359   return Model instances instead.
       
  1360   """
       
  1361 
       
  1362   def __init__(self, model_class, datastore_iterator):
       
  1363     """Iterator constructor
       
  1364 
       
  1365     Args:
       
  1366       model_class: Model class from which entities are constructed.
       
  1367       datastore_iterator: Underlying datastore iterator.
       
  1368     """
       
  1369     self.__model_class = model_class
       
  1370     self.__iterator = datastore_iterator
       
  1371 
       
  1372   def __iter__(self):
       
  1373     """Iterator on self.
       
  1374 
       
  1375     Returns:
       
  1376       Self.
       
  1377     """
       
  1378     return self
       
  1379 
       
  1380   def next(self):
       
  1381     """Get next Model instance in query results.
       
  1382 
       
  1383     Returns:
       
  1384       Next model instance.
       
  1385 
       
  1386     Raises:
       
  1387       StopIteration when there are no more results in query.
       
  1388     """
       
  1389     return self.__model_class.from_entity(self.__iterator.next())
       
  1390 
       
  1391 
       
  1392 def _normalize_query_parameter(value):
       
  1393   """Make any necessary type conversions to a query parameter.
       
  1394 
       
  1395   The following conversions are made:
       
  1396     - Model instances are converted to Key instances.  This is necessary so
       
  1397       that querying reference properties will work.
       
  1398     - datetime.date objects are converted to datetime.datetime objects (see
       
  1399       _date_to_datetime for details on this conversion).  This is necessary so
       
  1400       that querying date properties with date objects will work.
       
  1401     - datetime.time objects are converted to datetime.datetime objects (see
       
  1402       _time_to_datetime for details on this conversion).  This is necessary so
       
  1403       that querying time properties with time objects will work.
       
  1404 
       
  1405   Args:
       
  1406     value: The query parameter value.
       
  1407 
       
  1408   Returns:
       
  1409     The input value, or a converted value if value matches one of the
       
  1410     conversions specified above.
       
  1411   """
       
  1412   if isinstance(value, Model):
       
  1413     value = value.key()
       
  1414   if (isinstance(value, datetime.date) and
       
  1415       not isinstance(value, datetime.datetime)):
       
  1416     value = _date_to_datetime(value)
       
  1417   elif isinstance(value, datetime.time):
       
  1418     value = _time_to_datetime(value)
       
  1419   return value
       
  1420 
       
  1421 
       
  1422 class Query(_BaseQuery):
       
  1423   """A Query instance queries over instances of Models.
       
  1424 
       
  1425   You construct a query with a model class, like this:
       
  1426 
       
  1427      class Story(db.Model):
       
  1428        title = db.StringProperty()
       
  1429        date = db.DateTimeProperty()
       
  1430 
       
  1431      query = Query(Story)
       
  1432 
       
  1433   You modify a query with filters and orders like this:
       
  1434 
       
  1435      query.filter('title =', 'Foo')
       
  1436      query.order('-date')
       
  1437      query.ancestor(key_or_model_instance)
       
  1438 
       
  1439   Every query can return an iterator, so you access the results of a query
       
  1440   by iterating over it:
       
  1441 
       
  1442      for story in query:
       
  1443        print story.title
       
  1444 
       
  1445   For convenience, all of the filtering and ordering methods return "self",
       
  1446   so the easiest way to use the query interface is to cascade all filters and
       
  1447   orders in the iterator line like this:
       
  1448 
       
  1449      for story in Query(story).filter('title =', 'Foo').order('-date'):
       
  1450        print story.title
       
  1451   """
       
  1452 
       
  1453   def __init__(self, model_class):
       
  1454     """Constructs a query over instances of the given Model.
       
  1455 
       
  1456     Args:
       
  1457       model_class: Model class to build query for.
       
  1458     """
       
  1459     super(Query, self).__init__(model_class)
       
  1460     self.__query_set = {}
       
  1461     self.__orderings = []
       
  1462     self.__ancestor = None
       
  1463 
       
  1464   def _get_query(self, _query_class=datastore.Query):
       
  1465     query = _query_class(self._model_class.kind(), self.__query_set)
       
  1466     if self.__ancestor is not None:
       
  1467       query.Ancestor(self.__ancestor)
       
  1468     query.Order(*self.__orderings)
       
  1469     return query
       
  1470 
       
  1471   def filter(self, property_operator, value):
       
  1472     """Add filter to query.
       
  1473 
       
  1474     Args:
       
  1475       property_operator: string with the property and operator to filter by.
       
  1476       value: the filter value.
       
  1477 
       
  1478     Returns:
       
  1479       Self to support method chaining.
       
  1480     """
       
  1481     if isinstance(value, (list, tuple)):
       
  1482       raise BadValueError('Filtering on lists is not supported')
       
  1483 
       
  1484     value = _normalize_query_parameter(value)
       
  1485     datastore._AddOrAppend(self.__query_set, property_operator, value)
       
  1486     return self
       
  1487 
       
  1488   def order(self, property):
       
  1489     """Set order of query result.
       
  1490 
       
  1491     To use descending order, prepend '-' (minus) to the property name, e.g.,
       
  1492     '-date' rather than 'date'.
       
  1493 
       
  1494     Args:
       
  1495       property: Property to sort on.
       
  1496 
       
  1497     Returns:
       
  1498       Self to support method chaining.
       
  1499 
       
  1500     Raises:
       
  1501       PropertyError if invalid property name is provided.
       
  1502     """
       
  1503     if property.startswith('-'):
       
  1504       property = property[1:]
       
  1505       order = datastore.Query.DESCENDING
       
  1506     else:
       
  1507       order = datastore.Query.ASCENDING
       
  1508 
       
  1509     if not issubclass(self._model_class, Expando):
       
  1510       if property not in self._model_class.properties():
       
  1511         raise PropertyError('Invalid property name \'%s\'' % property)
       
  1512 
       
  1513     self.__orderings.append((property, order))
       
  1514     return self
       
  1515 
       
  1516   def ancestor(self, ancestor):
       
  1517     """Sets an ancestor for this query.
       
  1518 
       
  1519     This restricts the query to only return results that descend from
       
  1520     a given model instance. In other words, all of the results will
       
  1521     have the ancestor as their parent, or parent's parent, etc.  The
       
  1522     ancestor itself is also a possible result!
       
  1523 
       
  1524     Args:
       
  1525       ancestor: Model or Key (that has already been saved)
       
  1526 
       
  1527     Returns:
       
  1528       Self to support method chaining.
       
  1529 
       
  1530     Raises:
       
  1531       TypeError if the argument isn't a Key or Model; NotSavedError
       
  1532       if it is, but isn't saved yet.
       
  1533     """
       
  1534     if isinstance(ancestor, datastore.Key):
       
  1535       if ancestor.has_id_or_name():
       
  1536         self.__ancestor = ancestor
       
  1537       else:
       
  1538         raise NotSavedError()
       
  1539     elif isinstance(ancestor, Model):
       
  1540       if ancestor.is_saved():
       
  1541         self.__ancestor = ancestor.key()
       
  1542       else:
       
  1543         raise NotSavedError()
       
  1544     else:
       
  1545       raise TypeError('ancestor should be Key or Model')
       
  1546     return self
       
  1547 
       
  1548 
       
  1549 class GqlQuery(_BaseQuery):
       
  1550   """A Query class that uses GQL query syntax instead of .filter() etc."""
       
  1551 
       
  1552   def __init__(self, query_string, *args, **kwds):
       
  1553     """Constructor.
       
  1554 
       
  1555     Args:
       
  1556       query_string: Properly formatted GQL query string.
       
  1557       *args: Positional arguments used to bind numeric references in the query.
       
  1558       **kwds: Dictionary-based arguments for named references.
       
  1559     """
       
  1560     from google.appengine.ext import gql
       
  1561     app = kwds.pop('_app', None)
       
  1562     self._proto_query = gql.GQL(query_string, _app=app)
       
  1563     super(GqlQuery, self).__init__(class_for_kind(self._proto_query._entity))
       
  1564     self.bind(*args, **kwds)
       
  1565 
       
  1566   def bind(self, *args, **kwds):
       
  1567     """Bind arguments (positional or keyword) to the query.
       
  1568 
       
  1569     Note that you can also pass arguments directly to the query
       
  1570     constructor.  Each time you call bind() the previous set of
       
  1571     arguments is replaced with the new set.  This is useful because
       
  1572     the hard work in in parsing the query; so if you expect to be
       
  1573     using the same query with different sets of arguments, you should
       
  1574     hold on to the GqlQuery() object and call bind() on it each time.
       
  1575 
       
  1576     Args:
       
  1577       *args: Positional arguments used to bind numeric references in the query.
       
  1578       **kwds: Dictionary-based arguments for named references.
       
  1579     """
       
  1580     self._args = []
       
  1581     for arg in args:
       
  1582       self._args.append(_normalize_query_parameter(arg))
       
  1583     self._kwds = {}
       
  1584     for name, arg in kwds.iteritems():
       
  1585       self._kwds[name] = _normalize_query_parameter(arg)
       
  1586 
       
  1587   def run(self):
       
  1588     """Override _BaseQuery.run() so the LIMIT clause is handled properly."""
       
  1589     query_run = self._proto_query.Run(*self._args, **self._kwds)
       
  1590     return _QueryIterator(self._model_class, iter(query_run))
       
  1591 
       
  1592   def _get_query(self):
       
  1593     return self._proto_query.Bind(self._args, self._kwds)
       
  1594 
       
  1595 
       
  1596 class TextProperty(Property):
       
  1597   """A string that can be longer than 500 bytes.
       
  1598 
       
  1599   This type should be used for large text values to make sure the datastore
       
  1600   has good performance for queries.
       
  1601   """
       
  1602 
       
  1603   def validate(self, value):
       
  1604     """Validate text property.
       
  1605 
       
  1606     Returns:
       
  1607       A valid value.
       
  1608 
       
  1609     Raises:
       
  1610       BadValueError if property is not instance of 'Text'.
       
  1611     """
       
  1612     if value is not None and not isinstance(value, Text):
       
  1613       try:
       
  1614         value = Text(value)
       
  1615       except TypeError, err:
       
  1616         raise BadValueError('Property %s must be convertible '
       
  1617                             'to a Text instance (%s)' % (self.name, err))
       
  1618     value = super(TextProperty, self).validate(value)
       
  1619     if value is not None and not isinstance(value, Text):
       
  1620       raise BadValueError('Property %s must be a Text instance' % self.name)
       
  1621     return value
       
  1622 
       
  1623   data_type = Text
       
  1624 
       
  1625 
       
  1626 class StringProperty(Property):
       
  1627   """A textual property, which can be multi- or single-line."""
       
  1628 
       
  1629   def __init__(self, verbose_name=None, multiline=False, **kwds):
       
  1630     """Construct string property.
       
  1631 
       
  1632     Args:
       
  1633       verbose_name: Verbose name is always first parameter.
       
  1634       multi-line: Carriage returns permitted in property.
       
  1635     """
       
  1636     super(StringProperty, self).__init__(verbose_name, **kwds)
       
  1637     self.multiline = multiline
       
  1638 
       
  1639   def validate(self, value):
       
  1640     """Validate string property.
       
  1641 
       
  1642     Returns:
       
  1643       A valid value.
       
  1644 
       
  1645     Raises:
       
  1646       BadValueError if property is not multi-line but value is.
       
  1647     """
       
  1648     value = super(StringProperty, self).validate(value)
       
  1649     if value is not None and not isinstance(value, basestring):
       
  1650       raise BadValueError(
       
  1651           'Property %s must be a str or unicode instance, not a %s'
       
  1652           % (self.name, type(value).__name__))
       
  1653     if not self.multiline and value and value.find('\n') != -1:
       
  1654       raise BadValueError('Property %s is not multi-line' % self.name)
       
  1655     return value
       
  1656 
       
  1657   data_type = basestring
       
  1658 
       
  1659 
       
  1660 class _CoercingProperty(Property):
       
  1661   """A Property subclass that extends validate() to coerce to self.data_type."""
       
  1662 
       
  1663   def validate(self, value):
       
  1664     """Coerce values (except None) to self.data_type.
       
  1665 
       
  1666     Args:
       
  1667       value: The value to be validated and coerced.
       
  1668 
       
  1669     Returns:
       
  1670       The coerced and validated value.  It is guaranteed that this is
       
  1671       either None or an instance of self.data_type; otherwise an exception
       
  1672       is raised.
       
  1673 
       
  1674     Raises:
       
  1675       BadValueError if the value could not be validated or coerced.
       
  1676     """
       
  1677     value = super(_CoercingProperty, self).validate(value)
       
  1678     if value is not None and not isinstance(value, self.data_type):
       
  1679       value = self.data_type(value)
       
  1680     return value
       
  1681 
       
  1682 
       
  1683 class CategoryProperty(_CoercingProperty):
       
  1684   """A property whose values are Category instances."""
       
  1685 
       
  1686   data_type = Category
       
  1687 
       
  1688 
       
  1689 class LinkProperty(_CoercingProperty):
       
  1690   """A property whose values are Link instances."""
       
  1691 
       
  1692   def validate(self, value):
       
  1693     value = super(LinkProperty, self).validate(value)
       
  1694     if value is not None:
       
  1695       scheme, netloc, path, query, fragment = urlparse.urlsplit(value)
       
  1696       if not scheme or not netloc:
       
  1697         raise BadValueError('Property %s must be a full URL (\'%s\')' %
       
  1698                             (self.name, value))
       
  1699     return value
       
  1700 
       
  1701   data_type = Link
       
  1702 
       
  1703 URLProperty = LinkProperty
       
  1704 
       
  1705 
       
  1706 class EmailProperty(_CoercingProperty):
       
  1707   """A property whose values are Email instances."""
       
  1708 
       
  1709   data_type = Email
       
  1710 
       
  1711 
       
  1712 class GeoPtProperty(_CoercingProperty):
       
  1713   """A property whose values are GeoPt instances."""
       
  1714 
       
  1715   data_type = GeoPt
       
  1716 
       
  1717 
       
  1718 class IMProperty(_CoercingProperty):
       
  1719   """A property whose values are IM instances."""
       
  1720 
       
  1721   data_type = IM
       
  1722 
       
  1723 
       
  1724 class PhoneNumberProperty(_CoercingProperty):
       
  1725   """A property whose values are PhoneNumber instances."""
       
  1726 
       
  1727   data_type = PhoneNumber
       
  1728 
       
  1729 
       
  1730 class PostalAddressProperty(_CoercingProperty):
       
  1731   """A property whose values are PostalAddress instances."""
       
  1732 
       
  1733   data_type = PostalAddress
       
  1734 
       
  1735 
       
  1736 class BlobProperty(Property):
       
  1737   """A string that can be longer than 500 bytes.
       
  1738 
       
  1739   This type should be used for large binary values to make sure the datastore
       
  1740   has good performance for queries.
       
  1741   """
       
  1742 
       
  1743   def validate(self, value):
       
  1744     """Validate blob property.
       
  1745 
       
  1746     Returns:
       
  1747       A valid value.
       
  1748 
       
  1749     Raises:
       
  1750       BadValueError if property is not instance of 'Blob'.
       
  1751     """
       
  1752     if value is not None and not isinstance(value, Blob):
       
  1753       try:
       
  1754         value = Blob(value)
       
  1755       except TypeError, err:
       
  1756         raise BadValueError('Property %s must be convertible '
       
  1757                             'to a Blob instance (%s)' % (self.name, err))
       
  1758     value = super(BlobProperty, self).validate(value)
       
  1759     if value is not None and not isinstance(value, Blob):
       
  1760       raise BadValueError('Property %s must be a Blob instance' % self.name)
       
  1761     return value
       
  1762 
       
  1763   data_type = Blob
       
  1764 
       
  1765 
       
  1766 class DateTimeProperty(Property):
       
  1767   """The base class of all of our date/time properties.
       
  1768 
       
  1769   We handle common operations, like converting between time tuples and
       
  1770   datetime instances.
       
  1771   """
       
  1772 
       
  1773   def __init__(self, verbose_name=None, auto_now=False, auto_now_add=False,
       
  1774                **kwds):
       
  1775     """Construct a DateTimeProperty
       
  1776 
       
  1777     Args:
       
  1778       verbose_name: Verbose name is always first parameter.
       
  1779       auto_now: Date/time property is updated with the current time every time
       
  1780         it is saved to the datastore.  Useful for properties that want to track
       
  1781         the modification time of an instance.
       
  1782       auto_now_add: Date/time is set to the when its instance is created.
       
  1783         Useful for properties that record the creation time of an entity.
       
  1784     """
       
  1785     super(DateTimeProperty, self).__init__(verbose_name, **kwds)
       
  1786     self.auto_now = auto_now
       
  1787     self.auto_now_add = auto_now_add
       
  1788 
       
  1789   def validate(self, value):
       
  1790     """Validate datetime.
       
  1791 
       
  1792     Returns:
       
  1793       A valid value.
       
  1794 
       
  1795     Raises:
       
  1796       BadValueError if property is not instance of 'datetime'.
       
  1797     """
       
  1798     value = super(DateTimeProperty, self).validate(value)
       
  1799     if value and not isinstance(value, self.data_type):
       
  1800       raise BadValueError('Property %s must be a %s' %
       
  1801                           (self.name, self.data_type.__name__))
       
  1802     return value
       
  1803 
       
  1804   def default_value(self):
       
  1805     """Default value for datetime.
       
  1806 
       
  1807     Returns:
       
  1808       value of now() as appropriate to the date-time instance if auto_now
       
  1809       or auto_now_add is set, else user configured default value implementation.
       
  1810     """
       
  1811     if self.auto_now or self.auto_now_add:
       
  1812       return self.now()
       
  1813     return Property.default_value(self)
       
  1814 
       
  1815   def get_value_for_datastore(self, model_instance):
       
  1816     """Get value from property to send to datastore.
       
  1817 
       
  1818     Returns:
       
  1819       now() as appropriate to the date-time instance in the odd case where
       
  1820       auto_now is set to True, else the default implementation.
       
  1821     """
       
  1822     if self.auto_now:
       
  1823       return self.now()
       
  1824     else:
       
  1825       return super(DateTimeProperty,
       
  1826                    self).get_value_for_datastore(model_instance)
       
  1827 
       
  1828   data_type = datetime.datetime
       
  1829 
       
  1830   @staticmethod
       
  1831   def now():
       
  1832     """Get now as a full datetime value.
       
  1833 
       
  1834     Returns:
       
  1835       'now' as a whole timestamp, including both time and date.
       
  1836     """
       
  1837     return datetime.datetime.now()
       
  1838 
       
  1839 
       
  1840 def _date_to_datetime(value):
       
  1841   """Convert a date to a datetime for datastore storage.
       
  1842 
       
  1843   Args:
       
  1844     value: A datetime.date object.
       
  1845 
       
  1846   Returns:
       
  1847     A datetime object with time set to 0:00.
       
  1848   """
       
  1849   assert isinstance(value, datetime.date)
       
  1850   return datetime.datetime(value.year, value.month, value.day)
       
  1851 
       
  1852 
       
  1853 def _time_to_datetime(value):
       
  1854   """Convert a time to a datetime for datastore storage.
       
  1855 
       
  1856   Args:
       
  1857     value: A datetime.time object.
       
  1858 
       
  1859   Returns:
       
  1860     A datetime object with date set to 1970-01-01.
       
  1861   """
       
  1862   assert isinstance(value, datetime.time)
       
  1863   return datetime.datetime(1970, 1, 1,
       
  1864                            value.hour, value.minute, value.second,
       
  1865                            value.microsecond)
       
  1866 
       
  1867 
       
  1868 class DateProperty(DateTimeProperty):
       
  1869   """A date property, which stores a date without a time."""
       
  1870 
       
  1871 
       
  1872   @staticmethod
       
  1873   def now():
       
  1874     """Get now as a date datetime value.
       
  1875 
       
  1876     Returns:
       
  1877       'date' part of 'now' only.
       
  1878     """
       
  1879     return datetime.datetime.now().date()
       
  1880 
       
  1881   def validate(self, value):
       
  1882     """Validate date.
       
  1883 
       
  1884     Returns:
       
  1885       A valid value.
       
  1886 
       
  1887     Raises:
       
  1888       BadValueError if property is not instance of 'date',
       
  1889       or if it is an instance of 'datetime' (which is a subclass
       
  1890       of 'date', but for all practical purposes a different type).
       
  1891     """
       
  1892     value = super(DateProperty, self).validate(value)
       
  1893     if isinstance(value, datetime.datetime):
       
  1894       raise BadValueError('Property %s must be a %s, not a datetime' %
       
  1895                           (self.name, self.data_type.__name__))
       
  1896     return value
       
  1897 
       
  1898   def get_value_for_datastore(self, model_instance):
       
  1899     """Get value from property to send to datastore.
       
  1900 
       
  1901     We retrieve a datetime.date from the model instance and return a
       
  1902     datetime.datetime instance with the time set to zero.
       
  1903 
       
  1904     See base class method documentation for details.
       
  1905     """
       
  1906     value = super(DateProperty, self).get_value_for_datastore(model_instance)
       
  1907     if value is not None:
       
  1908       assert isinstance(value, datetime.date)
       
  1909       value = _date_to_datetime(value)
       
  1910     return value
       
  1911 
       
  1912   def make_value_from_datastore(self, value):
       
  1913     """Native representation of this property.
       
  1914 
       
  1915     We receive a datetime.datetime retrieved from the entity and return
       
  1916     a datetime.date instance representing its date portion.
       
  1917 
       
  1918     See base class method documentation for details.
       
  1919     """
       
  1920     if value is not None:
       
  1921       assert isinstance(value, datetime.datetime)
       
  1922       value = value.date()
       
  1923     return value
       
  1924 
       
  1925   data_type = datetime.date
       
  1926 
       
  1927 
       
  1928 class TimeProperty(DateTimeProperty):
       
  1929   """A time property, which stores a time without a date."""
       
  1930 
       
  1931 
       
  1932   @staticmethod
       
  1933   def now():
       
  1934     """Get now as a time datetime value.
       
  1935 
       
  1936     Returns:
       
  1937       'time' part of 'now' only.
       
  1938     """
       
  1939     return datetime.datetime.now().time()
       
  1940 
       
  1941   def get_value_for_datastore(self, model_instance):
       
  1942     """Get value from property to send to datastore.
       
  1943 
       
  1944     We retrieve a datetime.time from the model instance and return a
       
  1945     datetime.datetime instance with the date set to 1/1/1970.
       
  1946 
       
  1947     See base class method documentation for details.
       
  1948     """
       
  1949     value = super(TimeProperty, self).get_value_for_datastore(model_instance)
       
  1950     if value is not None:
       
  1951       assert isinstance(value, datetime.time), repr(value)
       
  1952       value = _time_to_datetime(value)
       
  1953     return value
       
  1954 
       
  1955   def make_value_from_datastore(self, value):
       
  1956     """Native representation of this property.
       
  1957 
       
  1958     We receive a datetime.datetime retrieved from the entity and return
       
  1959     a datetime.date instance representing its time portion.
       
  1960 
       
  1961     See base class method documentation for details.
       
  1962     """
       
  1963     if value is not None:
       
  1964       assert isinstance(value, datetime.datetime)
       
  1965       value = value.time()
       
  1966     return value
       
  1967 
       
  1968   data_type = datetime.time
       
  1969 
       
  1970 
       
  1971 class IntegerProperty(Property):
       
  1972   """An integer property."""
       
  1973 
       
  1974   def validate(self, value):
       
  1975     """Validate integer property.
       
  1976 
       
  1977     Returns:
       
  1978       A valid value.
       
  1979 
       
  1980     Raises:
       
  1981       BadValueError if value is not an integer or long instance.
       
  1982     """
       
  1983     value = super(IntegerProperty, self).validate(value)
       
  1984     if value is None:
       
  1985       return value
       
  1986     if not isinstance(value, (int, long)) or isinstance(value, bool):
       
  1987       raise BadValueError('Property %s must be an int or long, not a %s'
       
  1988                           % (self.name, type(value).__name__))
       
  1989     if value < -0x8000000000000000 or value > 0x7fffffffffffffff:
       
  1990       raise BadValueError('Property %s must fit in 64 bits' % self.name)
       
  1991     return value
       
  1992 
       
  1993   data_type = int
       
  1994 
       
  1995   def empty(self, value):
       
  1996     """Is integer property empty.
       
  1997 
       
  1998     0 is not an empty value.
       
  1999 
       
  2000     Returns:
       
  2001       True if value is None, else False.
       
  2002     """
       
  2003     return value is None
       
  2004 
       
  2005 
       
  2006 class RatingProperty(_CoercingProperty, IntegerProperty):
       
  2007   """A property whose values are Rating instances."""
       
  2008 
       
  2009   data_type = Rating
       
  2010 
       
  2011 
       
  2012 class FloatProperty(Property):
       
  2013   """A float property."""
       
  2014 
       
  2015   def validate(self, value):
       
  2016     """Validate float.
       
  2017 
       
  2018     Returns:
       
  2019       A valid value.
       
  2020 
       
  2021     Raises:
       
  2022       BadValueError if property is not instance of 'float'.
       
  2023     """
       
  2024     value = super(FloatProperty, self).validate(value)
       
  2025     if value is not None and not isinstance(value, float):
       
  2026       raise BadValueError('Property %s must be a float' % self.name)
       
  2027     return value
       
  2028 
       
  2029   data_type = float
       
  2030 
       
  2031   def empty(self, value):
       
  2032     """Is float property empty.
       
  2033 
       
  2034     0.0 is not an empty value.
       
  2035 
       
  2036     Returns:
       
  2037       True if value is None, else False.
       
  2038     """
       
  2039     return value is None
       
  2040 
       
  2041 
       
  2042 class BooleanProperty(Property):
       
  2043   """A boolean property."""
       
  2044 
       
  2045   def validate(self, value):
       
  2046     """Validate boolean.
       
  2047 
       
  2048     Returns:
       
  2049       A valid value.
       
  2050 
       
  2051     Raises:
       
  2052       BadValueError if property is not instance of 'bool'.
       
  2053     """
       
  2054     value = super(BooleanProperty, self).validate(value)
       
  2055     if value is not None and not isinstance(value, bool):
       
  2056       raise BadValueError('Property %s must be a bool' % self.name)
       
  2057     return value
       
  2058 
       
  2059   data_type = bool
       
  2060 
       
  2061   def empty(self, value):
       
  2062     """Is boolean property empty.
       
  2063 
       
  2064     False is not an empty value.
       
  2065 
       
  2066     Returns:
       
  2067       True if value is None, else False.
       
  2068     """
       
  2069     return value is None
       
  2070 
       
  2071 
       
  2072 class UserProperty(Property):
       
  2073   """A user property."""
       
  2074 
       
  2075   def __init__(self, verbose_name=None, name=None,
       
  2076                required=False, validator=None, choices=None):
       
  2077     """Initializes this Property with the given options.
       
  2078 
       
  2079     Do not assign user properties a default value.
       
  2080 
       
  2081     Args:
       
  2082       verbose_name: User friendly name of property.
       
  2083       name: Storage name for property.  By default, uses attribute name
       
  2084         as it is assigned in the Model sub-class.
       
  2085       default: Default value for property if none is assigned.
       
  2086       required: Whether property is required.
       
  2087       validator: User provided method used for validation.
       
  2088       choices: User provided set of valid property values.
       
  2089     """
       
  2090     super(UserProperty, self).__init__(verbose_name, name,
       
  2091                                        required=required,
       
  2092                                        validator=validator,
       
  2093                                        choices=choices)
       
  2094 
       
  2095   def validate(self, value):
       
  2096     """Validate user.
       
  2097 
       
  2098     Returns:
       
  2099       A valid value.
       
  2100 
       
  2101     Raises:
       
  2102       BadValueError if property is not instance of 'User'.
       
  2103     """
       
  2104     value = super(UserProperty, self).validate(value)
       
  2105     if value is not None and not isinstance(value, users.User):
       
  2106       raise BadValueError('Property %s must be a User' % self.name)
       
  2107     return value
       
  2108 
       
  2109   data_type = users.User
       
  2110 
       
  2111 
       
  2112 
       
  2113 class ListProperty(Property):
       
  2114   """A property that stores a list of things.
       
  2115 
       
  2116   This is a parameterized property; the parameter must be a valid
       
  2117   non-list data type, and all items must conform to this type.
       
  2118   """
       
  2119 
       
  2120   def __init__(self, item_type, verbose_name=None, default=None, **kwds):
       
  2121     """Construct ListProperty.
       
  2122 
       
  2123     Args:
       
  2124       item_type: Type for the list items; must be one of the allowed property
       
  2125         types.
       
  2126       verbose_name: Optional verbose name.
       
  2127       default: Optional default value; if omitted, an empty list is used.
       
  2128       **kwds: Optional additional keyword arguments, passed to base class.
       
  2129 
       
  2130     Note that the only permissible value for 'required' is True.
       
  2131     """
       
  2132     if not isinstance(item_type, type):
       
  2133       raise TypeError('Item type should be a type object')
       
  2134     if item_type not in _ALLOWED_PROPERTY_TYPES:
       
  2135       raise ValueError('Item type %s is not acceptable' % item_type.__name__)
       
  2136     if 'required' in kwds and kwds['required'] is not True:
       
  2137       raise ValueError('List values must be required')
       
  2138     if default is None:
       
  2139       default = []
       
  2140     self.item_type = item_type
       
  2141     super(ListProperty, self).__init__(verbose_name,
       
  2142                                        required=True,
       
  2143                                        default=default,
       
  2144                                        **kwds)
       
  2145 
       
  2146   def validate(self, value):
       
  2147     """Validate list.
       
  2148 
       
  2149     Returns:
       
  2150       A valid value.
       
  2151 
       
  2152     Raises:
       
  2153       BadValueError if property is not a list whose items are instances of
       
  2154       the item_type given to the constructor.
       
  2155     """
       
  2156     value = super(ListProperty, self).validate(value)
       
  2157     if value is not None:
       
  2158       if not isinstance(value, list):
       
  2159         raise BadValueError('Property %s must be a list' % self.name)
       
  2160 
       
  2161       if self.item_type in (int, long):
       
  2162         item_type = (int, long)
       
  2163       else:
       
  2164         item_type = self.item_type
       
  2165 
       
  2166       for item in value:
       
  2167         if not isinstance(item, item_type):
       
  2168           if item_type == (int, long):
       
  2169             raise BadValueError('Items in the %s list must all be integers.' %
       
  2170                                 self.name)
       
  2171           else:
       
  2172             raise BadValueError(
       
  2173                 'Items in the %s list must all be %s instances' %
       
  2174                 (self.name, self.item_type.__name__))
       
  2175     return value
       
  2176 
       
  2177   def empty(self, value):
       
  2178     """Is list property empty.
       
  2179 
       
  2180     [] is not an empty value.
       
  2181 
       
  2182     Returns:
       
  2183       True if value is None, else false.
       
  2184     """
       
  2185     return value is None
       
  2186 
       
  2187   data_type = list
       
  2188 
       
  2189   def default_value(self):
       
  2190     """Default value for list.
       
  2191 
       
  2192     Because the property supplied to 'default' is a static value,
       
  2193     that value must be shallow copied to prevent all fields with
       
  2194     default values from sharing the same instance.
       
  2195 
       
  2196     Returns:
       
  2197       Copy of the default value.
       
  2198     """
       
  2199     return list(super(ListProperty, self).default_value())
       
  2200 
       
  2201 
       
  2202 def StringListProperty(verbose_name=None, default=None, **kwds):
       
  2203   """A shorthand for the most common type of ListProperty.
       
  2204 
       
  2205   Args:
       
  2206     verbose_name: Optional verbose name.
       
  2207     default: Optional default value; if omitted, an empty list is used.
       
  2208     **kwds: Optional additional keyword arguments, passed to ListProperty().
       
  2209 
       
  2210   Returns:
       
  2211     A ListProperty instance whose item type is basestring and whose other
       
  2212     arguments are whatever was passed here.
       
  2213   """
       
  2214   return ListProperty(basestring, verbose_name, default, **kwds)
       
  2215 
       
  2216 
       
  2217 class ReferenceProperty(Property):
       
  2218   """A property that represents a many-to-one reference to another model.
       
  2219 
       
  2220   For example, a reference property in model A that refers to model B forms
       
  2221   a many-to-one relationship from A to B: every instance of A refers to a
       
  2222   single B instance, and every B instance can have many A instances refer
       
  2223   to it.
       
  2224   """
       
  2225 
       
  2226   def __init__(self,
       
  2227                reference_class=None,
       
  2228                verbose_name=None,
       
  2229                collection_name=None,
       
  2230                **attrs):
       
  2231     """Construct ReferenceProperty.
       
  2232 
       
  2233     Args:
       
  2234       reference_class: Which model class this property references.
       
  2235       verbose_name: User friendly name of property.
       
  2236       collection_name: If provided, alternate name of collection on
       
  2237         reference_class to store back references.  Use this to allow
       
  2238         a Model to have multiple fields which refer to the same class.
       
  2239     """
       
  2240     super(ReferenceProperty, self).__init__(verbose_name, **attrs)
       
  2241 
       
  2242     self.collection_name = collection_name
       
  2243 
       
  2244     if reference_class is None:
       
  2245       reference_class = Model
       
  2246     if not ((isinstance(reference_class, type) and
       
  2247              issubclass(reference_class, Model)) or
       
  2248             reference_class is _SELF_REFERENCE):
       
  2249       raise KindError('reference_class must be Model or _SELF_REFERENCE')
       
  2250     self.reference_class = self.data_type = reference_class
       
  2251 
       
  2252   def __property_config__(self, model_class, property_name):
       
  2253     """Loads all of the references that point to this model.
       
  2254 
       
  2255     We need to do this to create the ReverseReferenceProperty properties for
       
  2256     this model and create the <reference>_set attributes on the referenced
       
  2257     model, e.g.:
       
  2258 
       
  2259        class Story(db.Model):
       
  2260          title = db.StringProperty()
       
  2261        class Comment(db.Model):
       
  2262          story = db.ReferenceProperty(Story)
       
  2263        story = Story.get(id)
       
  2264        print [c for c in story.comment_set]
       
  2265 
       
  2266     In this example, the comment_set property was created based on the reference
       
  2267     from Comment to Story (which is inherently one to many).
       
  2268 
       
  2269     Args:
       
  2270       model_class: Model class which will have its reference properties
       
  2271         initialized.
       
  2272       property_name: Name of property being configured.
       
  2273 
       
  2274     Raises:
       
  2275       DuplicatePropertyError if referenced class already has the provided
       
  2276         collection name as a property.
       
  2277     """
       
  2278     super(ReferenceProperty, self).__property_config__(model_class,
       
  2279                                                        property_name)
       
  2280 
       
  2281     if self.reference_class is _SELF_REFERENCE:
       
  2282       self.reference_class = self.data_type = model_class
       
  2283 
       
  2284     if self.collection_name is None:
       
  2285       self.collection_name = '%s_set' % (model_class.__name__.lower())
       
  2286     if hasattr(self.reference_class, self.collection_name):
       
  2287       raise DuplicatePropertyError('Class %s already has property %s'
       
  2288                                    % (self.reference_class.__name__,
       
  2289                                       self.collection_name))
       
  2290     setattr(self.reference_class,
       
  2291             self.collection_name,
       
  2292             _ReverseReferenceProperty(model_class, property_name))
       
  2293 
       
  2294   def __get__(self, model_instance, model_class):
       
  2295     """Get reference object.
       
  2296 
       
  2297     This method will fetch unresolved entities from the datastore if
       
  2298     they are not already loaded.
       
  2299 
       
  2300     Returns:
       
  2301       ReferenceProperty to Model object if property is set, else None.
       
  2302     """
       
  2303     if model_instance is None:
       
  2304       return self
       
  2305     if hasattr(model_instance, self.__id_attr_name()):
       
  2306       reference_id = getattr(model_instance, self.__id_attr_name())
       
  2307     else:
       
  2308       reference_id = None
       
  2309     if reference_id is not None:
       
  2310       resolved = getattr(model_instance, self.__resolved_attr_name())
       
  2311       if resolved is not None:
       
  2312         return resolved
       
  2313       else:
       
  2314         instance = get(reference_id)
       
  2315         if instance is None:
       
  2316           raise Error('ReferenceProperty failed to be resolved')
       
  2317         setattr(model_instance, self.__resolved_attr_name(), instance)
       
  2318         return instance
       
  2319     else:
       
  2320       return None
       
  2321 
       
  2322   def __set__(self, model_instance, value):
       
  2323     """Set reference."""
       
  2324     value = self.validate(value)
       
  2325     if value is not None:
       
  2326       if isinstance(value, datastore.Key):
       
  2327         setattr(model_instance, self.__id_attr_name(), value)
       
  2328         setattr(model_instance, self.__resolved_attr_name(), None)
       
  2329       else:
       
  2330         setattr(model_instance, self.__id_attr_name(), value.key())
       
  2331         setattr(model_instance, self.__resolved_attr_name(), value)
       
  2332     else:
       
  2333       setattr(model_instance, self.__id_attr_name(), None)
       
  2334       setattr(model_instance, self.__resolved_attr_name(), None)
       
  2335 
       
  2336   def get_value_for_datastore(self, model_instance):
       
  2337     """Get key of reference rather than reference itself."""
       
  2338     return getattr(model_instance, self.__id_attr_name())
       
  2339 
       
  2340   def validate(self, value):
       
  2341     """Validate reference.
       
  2342 
       
  2343     Returns:
       
  2344       A valid value.
       
  2345 
       
  2346     Raises:
       
  2347       BadValueError for the following reasons:
       
  2348         - Value is not saved.
       
  2349         - Object not of correct model type for reference.
       
  2350     """
       
  2351     if isinstance(value, datastore.Key):
       
  2352       return value
       
  2353 
       
  2354     if value is not None and not value.is_saved():
       
  2355       raise BadValueError(
       
  2356           '%s instance must be saved before it can be stored as a '
       
  2357           'reference' % self.reference_class.kind())
       
  2358 
       
  2359     value = super(ReferenceProperty, self).validate(value)
       
  2360 
       
  2361     if value is not None and not isinstance(value, self.reference_class):
       
  2362       raise KindError('Property %s must be an instance of %s' %
       
  2363                             (self.name, self.reference_class.kind()))
       
  2364 
       
  2365     return value
       
  2366 
       
  2367   def __id_attr_name(self):
       
  2368     """Get attribute of referenced id.
       
  2369 
       
  2370     Returns:
       
  2371       Attribute where to store id of referenced entity.
       
  2372     """
       
  2373     return self._attr_name()
       
  2374 
       
  2375   def __resolved_attr_name(self):
       
  2376     """Get attribute of resolved attribute.
       
  2377 
       
  2378     The resolved attribute is where the actual loaded reference instance is
       
  2379     stored on the referring model instance.
       
  2380 
       
  2381     Returns:
       
  2382       Attribute name of where to store resolved reference model instance.
       
  2383     """
       
  2384     return '_RESOLVED' + self._attr_name()
       
  2385 
       
  2386 
       
  2387 Reference = ReferenceProperty
       
  2388 
       
  2389 
       
  2390 def SelfReferenceProperty(verbose_name=None, collection_name=None, **attrs):
       
  2391   """Create a self reference.
       
  2392 
       
  2393   Function for declaring a self referencing property on a model.
       
  2394 
       
  2395   Example:
       
  2396     class HtmlNode(db.Model):
       
  2397       parent = db.SelfReferenceProperty('Parent', 'children')
       
  2398 
       
  2399   Args:
       
  2400     verbose_name: User friendly name of property.
       
  2401     collection_name: Name of collection on model.
       
  2402 
       
  2403   Raises:
       
  2404     ConfigurationError if reference_class provided as parameter.
       
  2405   """
       
  2406   if 'reference_class' in attrs:
       
  2407     raise ConfigurationError(
       
  2408         'Do not provide reference_class to self-reference.')
       
  2409   return ReferenceProperty(_SELF_REFERENCE,
       
  2410                            verbose_name,
       
  2411                            collection_name,
       
  2412                            **attrs)
       
  2413 
       
  2414 
       
  2415 SelfReference = SelfReferenceProperty
       
  2416 
       
  2417 
       
  2418 class _ReverseReferenceProperty(Property):
       
  2419   """The inverse of the Reference property above.
       
  2420 
       
  2421   We construct reverse references automatically for the model to which
       
  2422   the Reference property is pointing to create the one-to-many property for
       
  2423   that model.  For example, if you put a Reference property in model A that
       
  2424   refers to model B, we automatically create a _ReverseReference property in
       
  2425   B called a_set that can fetch all of the model A instances that refer to
       
  2426   that instance of model B.
       
  2427   """
       
  2428 
       
  2429   def __init__(self, model, prop):
       
  2430     """Constructor for reverse reference.
       
  2431 
       
  2432     Constructor does not take standard values of other property types.
       
  2433 
       
  2434     Args:
       
  2435       model: Model that this property is a collection of.
       
  2436       property: Foreign property on referred model that points back to this
       
  2437         properties entity.
       
  2438     """
       
  2439     self.__model = model
       
  2440     self.__property = prop
       
  2441 
       
  2442   def __get__(self, model_instance, model_class):
       
  2443     """Fetches collection of model instances of this collection property."""
       
  2444     if model_instance is not None:
       
  2445       query = Query(self.__model)
       
  2446       return query.filter(self.__property + ' =', model_instance.key())
       
  2447     else:
       
  2448       return self
       
  2449 
       
  2450   def __set__(self, model_instance, value):
       
  2451     """Not possible to set a new collection."""
       
  2452     raise BadValueError('Virtual property is read-only')
       
  2453 
       
  2454 
       
  2455 run_in_transaction = datastore.RunInTransaction
       
  2456 
       
  2457 RunInTransaction = run_in_transaction