thirdparty/google_appengine/google/appengine/api/datastore_types.py
changeset 3031 7678f72140e6
parent 2864 2e0b0af889be
--- a/thirdparty/google_appengine/google/appengine/api/datastore_types.py	Fri Oct 23 11:17:07 2009 -0700
+++ b/thirdparty/google_appengine/google/appengine/api/datastore_types.py	Fri Oct 23 13:54:11 2009 -0500
@@ -325,6 +325,7 @@
       # a base64-encoded primary key, generated by Key.__str__
       encoded: str
     """
+    self._str = None
     if encoded is not None:
       if not isinstance(encoded, basestring):
         try:
@@ -339,10 +340,13 @@
         if modulo != 0:
           encoded += ('=' * (4 - modulo))
 
-        encoded_pb = base64.urlsafe_b64decode(str(encoded))
+        self._str = str(encoded)
+        encoded_pb = base64.urlsafe_b64decode(self._str)
         self.__reference = entity_pb.Reference(encoded_pb)
         assert self.__reference.IsInitialized()
 
+        self._str = self._str.rstrip('=')
+
       except (AssertionError, TypeError), e:
         raise datastore_errors.BadKeyError(
           'Invalid string key %s. Details: %s' % (encoded, e))
@@ -354,7 +358,7 @@
     else:
       self.__reference = entity_pb.Reference()
 
-  def to_path(self):
+  def to_path(self, _default_id=None):
     """Construct the "path" of this key as a list.
 
     Returns:
@@ -363,6 +367,7 @@
     Raises:
       datastore_errors.BadKeyError if this key does not have a valid path.
     """
+
     path = []
     for path_element in self.__reference.path().element_list():
       path.append(path_element.type().decode('utf-8'))
@@ -370,6 +375,8 @@
         path.append(path_element.name().decode('utf-8'))
       elif path_element.has_id():
         path.append(path_element.id())
+      elif _default_id is not None:
+        path.append(_default_id)
       else:
         raise datastore_errors.BadKeyError('Incomplete key found in to_path')
     return path
@@ -631,12 +638,15 @@
     Returns:
       string
     """
-    if (self.has_id_or_name()):
-      encoded = base64.urlsafe_b64encode(self.__reference.Encode())
-      return encoded.replace('=', '')
-    else:
-      raise datastore_errors.BadKeyError(
-        'Cannot string encode an incomplete key!\n%s' % self.__reference)
+    if self._str is None:
+      if (self.has_id_or_name()):
+        encoded = base64.urlsafe_b64encode(self.__reference.Encode())
+        self._str = encoded.replace('=', '')
+      else:
+        raise datastore_errors.BadKeyError(
+          'Cannot string encode an incomplete key!\n%s' % self.__reference)
+    return self._str
+
 
   def __repr__(self):
     """Returns an eval()able string representation of this key.
@@ -675,25 +685,11 @@
     if not isinstance(other, Key):
       return -2
 
-    self_args = []
-    other_args = []
-
-    self_args.append(self.__reference.app())
-    other_args.append(other.__reference.app())
+    self_args = [self.__reference.app()]
+    self_args += self.to_path(_default_id=0)
 
-    for elem in self.__reference.path().element_list():
-      self_args.append(elem.type())
-      if elem.has_name():
-        self_args.append(elem.name())
-      else:
-        self_args.append(elem.id())
-
-    for elem in other.__reference.path().element_list():
-      other_args.append(elem.type())
-      if elem.has_name():
-        other_args.append(elem.name())
-      else:
-        other_args.append(elem.id())
+    other_args = [other.__reference.app()]
+    other_args += other.to_path(_default_id=0)
 
     for self_component, other_component in zip(self_args, other_args):
       comparison = cmp(self_component, other_component)
@@ -711,7 +707,9 @@
     Returns:
       int
     """
-    return hash(self.__str__())
+    args = self.to_path(_default_id=0)
+    args.append(self.__reference.app())
+    return hash(type(args)) ^ hash(tuple(args))
 
 
 class Category(unicode):
@@ -900,12 +898,12 @@
   def __init__(self, protocol, address=None):
     if address is None:
       try:
-        split = protocol.split(' ')
+        split = protocol.split(' ', 1)
         protocol, address = split
       except (AttributeError, ValueError):
         raise datastore_errors.BadValueError(
           'Expected string of format "protocol address"; received %s' %
-          str(protocol))
+          (protocol,))
 
     ValidateString(address, 'address')
     if protocol not in self.PROTOCOLS: