app/reflistprop/__init__.py
changeset 328 275a47dd0ac8
parent 326 4a4474944dee
child 386 33942ff6e71b
--- a/app/reflistprop/__init__.py	Tue Oct 14 21:06:23 2008 +0000
+++ b/app/reflistprop/__init__.py	Tue Oct 14 21:33:57 2008 +0000
@@ -1,17 +1,17 @@
 #!/usr/bin/python2.5
 #
-# Copyright 2007 Ken Tidwell 
+# Copyright 2007 Ken Tidwell
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License. 
-# You may obtain a copy of the License at 
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
 #
-#     http://www.apache.org/licenses/LICENSE-2.0 
+#     http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software 
 # distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-# See the License for the specific language governing permissions and 
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
 # limitations under the License.
 # 
 """Simple property for storing ordered lists of Model objects.
@@ -23,54 +23,52 @@
  
 A quick usage example:
         class Bit(db.Model):
-                name = db.StringProperty(required=True)\ 
+                name = db.StringProperty(required=True)
         class Holder(db.Model):
-                bits = reflistprop.ReferenceListProperty(Bit, default=None) 
-        b1 = Bit(name="first") 
-        b1.put() # need to put it so that it is a valid reference object 
-        h1 = holder() 
-        h1.bits.append(b1) 
+                bits = reflistprop.ReferenceListProperty(Bit, default=None)
+        b1 = Bit(name="first")
+        b1.put() # need to put it so that it is a valid reference object
+        h1 = holder()
+        h1.bits.append(b1)
         h1.put()
          
-These also work: 
+These also work:
         h1.bits = [b1]
          
-This throws a db.BadValueError because a string is not an instance of 
+This throws a db.BadValueError because a string is not an instance of
 Bit: 
         h1.bits = ["nasty evil string"]
          
-This is not good but gets no complaint at assignment time (same 
-behaviour as ListProperty)
-but we will throw a db.BadValueError if you try to put it into the 
-datastore. (Maybe ListProperty
-wants to do the same? Or should I be waiting for the datastore 
-internal entity construction to
-notice the problem and throw?):
+This is not good but gets no complaint at assignment time (same behaviour
+as ListProperty) but we will throw a db.BadValueError if you try to put it
+into the datastore. (Maybe ListProperty wants to do the same? Or should I be
+waiting for the datastore internal entity construction to notice the problem
+and throw?):
         h1.bits.append("nasty evil string")
 
-Yes, of course you can query them. The important bit to understand is 
-that the list is stored as a list of keys in the datastore. So you use 
-the key of the entity in question in your query. (Seems like it would be 
-nice if the property could get involved and do that coercion for you but 
+Yes, of course you can query them. The important bit to understand is
+that the list is stored as a list of keys in the datastore. So you use
+the key of the entity in question in your query. (Seems like it would be
+nice if the property could get involved and do that coercion for you but
 I don't think it can right now...).
  
 Here's a little example:
-        class Thang(db.Model): 
-            name = db.StringProperty(required=True) 
-        class Holder(db.Model): 
-            thangs = langutils.ReferenceListProperty(Thang, default=None) 
-        holder1 = Holder() 
-        holder1.put() 
-        foo = Thang(name="foo") 
-        foo.put() 
-        holder1.thangs.append(foo) 
-        holder1.put() 
-        hq = db.GqlQuery("SELECT * FROM Holder where thangs = :1", foo.key()) 
-        holders = hq.fetch(10) 
+        class Thang(db.Model):
+            name = db.StringProperty(required=True)
+        class Holder(db.Model):
+            thangs = langutils.ReferenceListProperty(Thang, default=None)
+        holder1 = Holder()
+        holder1.put()
+        foo = Thang(name="foo")
+        foo.put()
+        holder1.thangs.append(foo)
+        holder1.put()
+        hq = db.GqlQuery("SELECT * FROM Holder where thangs = :1", foo.key())
+        holders = hq.fetch(10)
         print "Holders =", holders
         
 Obtained from:
-  http://groups.google.com/group/google-appengine/msg/d203cc1b93ee22d7 
+  http://groups.google.com/group/google-appengine/msg/d203cc1b93ee22d7
 """
 
 
@@ -78,108 +76,109 @@
 
  
 class ReferenceListProperty(db.Property):
-  """A property that stores a list of models. 
-  This is a parameterized property; the parameter must be a valid 
+  """A property that stores a list of models.
+  
+  This is a parameterized property; the parameter must be a valid
   Model type, and all items must conform to this type.
   """
-  def __init__(self, item_type, verbose_name=None, default=None, **kwds): 
+  def __init__(self, item_type, verbose_name=None, default=None, **kwds):
     """Construct ReferenceListProperty.
 
     Args:
-      item_type: Type for the list items; must be a subclass of Model. 
+      item_type: Type for the list items; must be a subclass of Model.
       verbose_name: Optional verbose name.
-      default: Optional default value; if omitted, an empty list is used. 
-      **kwds: Optional additional keyword arguments, passed to base class. 
+      default: Optional default value; if omitted, an empty list is used.
+      **kwds: Optional additional keyword arguments, passed to base class.
     """
-    if not issubclass(item_type, db.Model): 
-      raise TypeError('Item type should be a subclass of Model') 
+    if not issubclass(item_type, db.Model):
+      raise TypeError('Item type should be a subclass of Model')
     if default is None:
       default = []
-    self.item_type = item_type 
-    super(ReferenceListProperty, self).__init__(verbose_name, 
+    self.item_type = item_type
+    super(ReferenceListProperty, self).__init__(verbose_name,
                                                 default=default,
                                                 **kwds)
+  
   def validate(self, value):
     """Validate list.
 
-    Note that validation here is just as broken as for ListProperty. 
+    Note that validation here is just as broken as for ListProperty.
     The values in the list are only validated if the entire list is
-    swapped out.
-    If the list is directly modified, there is no attempt to validate 
-    the new items.
+    swapped out. If the list is directly modified, there is no attempt
+    to validate the new items.
 
     Returns:
-      A valid value. 
+      A valid value.
 
     Raises:
-      BadValueError if property is not a list whose items are 
+      BadValueError if property is not a list whose items are
       instances of the item_type given to the constructor.
-    """ 
-    value = super(ReferenceListProperty, self).validate(value) 
-    if value is not None: 
-      if not isinstance(value, list): 
-        raise db.BadValueError('Property %s must be a list' % 
+    """
+    value = super(ReferenceListProperty, self).validate(value)
+    if value is not None:
+      if not isinstance(value, list):
+        raise db.BadValueError('Property %s must be a list' %
                                self.name)
       for item in value:
-        if not isinstance(item, self.item_type): 
+        if not isinstance(item, self.item_type):
             raise db.BadValueError(
-                'Items in the %s list must all be %s instances' % 
+                'Items in the %s list must all be %s instances' %
                 (self.name, self.item_type.__name__))
     return value
 
-  def empty(self, value): 
+  def empty(self, value):
     """Is list property empty.
 
     [] is not an empty value.
  
     Returns:
-      True if value is None, else False. 
+      True if value is None, else False.
     """ 
     return value is None
 
   data_type = list
  
-  def default_value(self): 
+  def default_value(self):
     """Default value for list.
  
-    Because the property supplied to 'default' is a static value, 
-    that value must be shallow copied to prevent all fields with 
+    Because the property supplied to 'default' is a static value,
+    that value must be shallow copied to prevent all fields with
     default values from sharing the same instance.
  
-    Returns: 
-      Copy of the default value. 
+    Returns:
+      Copy of the default value.
     """ 
     return list(super(ReferenceListProperty, self).default_value())
  
-  def get_value_for_datastore(self, model_instance): 
+  def get_value_for_datastore(self, model_instance):
     """A list of key values is stored.
 
-    Prior to storage, we validate the items in the list. 
+    Prior to storage, we validate the items in the list.
     This check seems to be missing from ListProperty.
 
-    Args: 
+    Args:
       model_instance: Instance to fetch datastore value from.
  
-    Returns: 
-      A list of the keys for all Models in the value list. 
-    """ 
-    value = self.__get__(model_instance, model_instance.__class__) 
-    self.validate(value) 
-    if value is None: 
-        return None 
-    else: 
+    Returns:
+      A list of the keys for all Models in the value list.
+    """
+    value = self.__get__(model_instance, model_instance.__class__)
+    self.validate(value)
+    if value is None:
+        return None
+    else:
         return [v.key() for v in value]
  
-  def make_value_from_datastore(self, value): 
+  def make_value_from_datastore(self, value):
     """Recreates the list of Models from the list of keys.
  
     Args:
       value: value retrieved from the datastore entity.
 
-    Returns: 
-      None or a list of Models. 
+    Returns:
+      None or a list of Models.
     """ 
     if value is None:
         return None
     else:
-        return [db.get(v) for v in value] 
+        return [db.get(v) for v in value]