thirdparty/google_appengine/google/appengine/api/datastore_types.py
changeset 3031 7678f72140e6
parent 2864 2e0b0af889be
equal deleted inserted replaced
3030:09cae668b536 3031:7678f72140e6
   323 
   323 
   324     Args:
   324     Args:
   325       # a base64-encoded primary key, generated by Key.__str__
   325       # a base64-encoded primary key, generated by Key.__str__
   326       encoded: str
   326       encoded: str
   327     """
   327     """
       
   328     self._str = None
   328     if encoded is not None:
   329     if encoded is not None:
   329       if not isinstance(encoded, basestring):
   330       if not isinstance(encoded, basestring):
   330         try:
   331         try:
   331           repr_encoded = repr(encoded)
   332           repr_encoded = repr(encoded)
   332         except:
   333         except:
   337       try:
   338       try:
   338         modulo = len(encoded) % 4
   339         modulo = len(encoded) % 4
   339         if modulo != 0:
   340         if modulo != 0:
   340           encoded += ('=' * (4 - modulo))
   341           encoded += ('=' * (4 - modulo))
   341 
   342 
   342         encoded_pb = base64.urlsafe_b64decode(str(encoded))
   343         self._str = str(encoded)
       
   344         encoded_pb = base64.urlsafe_b64decode(self._str)
   343         self.__reference = entity_pb.Reference(encoded_pb)
   345         self.__reference = entity_pb.Reference(encoded_pb)
   344         assert self.__reference.IsInitialized()
   346         assert self.__reference.IsInitialized()
       
   347 
       
   348         self._str = self._str.rstrip('=')
   345 
   349 
   346       except (AssertionError, TypeError), e:
   350       except (AssertionError, TypeError), e:
   347         raise datastore_errors.BadKeyError(
   351         raise datastore_errors.BadKeyError(
   348           'Invalid string key %s. Details: %s' % (encoded, e))
   352           'Invalid string key %s. Details: %s' % (encoded, e))
   349       except Exception, e:
   353       except Exception, e:
   352         else:
   356         else:
   353           raise
   357           raise
   354     else:
   358     else:
   355       self.__reference = entity_pb.Reference()
   359       self.__reference = entity_pb.Reference()
   356 
   360 
   357   def to_path(self):
   361   def to_path(self, _default_id=None):
   358     """Construct the "path" of this key as a list.
   362     """Construct the "path" of this key as a list.
   359 
   363 
   360     Returns:
   364     Returns:
   361       A list [kind_1, id_or_name_1, ..., kind_n, id_or_name_n] of the key path.
   365       A list [kind_1, id_or_name_1, ..., kind_n, id_or_name_n] of the key path.
   362 
   366 
   363     Raises:
   367     Raises:
   364       datastore_errors.BadKeyError if this key does not have a valid path.
   368       datastore_errors.BadKeyError if this key does not have a valid path.
   365     """
   369     """
       
   370 
   366     path = []
   371     path = []
   367     for path_element in self.__reference.path().element_list():
   372     for path_element in self.__reference.path().element_list():
   368       path.append(path_element.type().decode('utf-8'))
   373       path.append(path_element.type().decode('utf-8'))
   369       if path_element.has_name():
   374       if path_element.has_name():
   370         path.append(path_element.name().decode('utf-8'))
   375         path.append(path_element.name().decode('utf-8'))
   371       elif path_element.has_id():
   376       elif path_element.has_id():
   372         path.append(path_element.id())
   377         path.append(path_element.id())
       
   378       elif _default_id is not None:
       
   379         path.append(_default_id)
   373       else:
   380       else:
   374         raise datastore_errors.BadKeyError('Incomplete key found in to_path')
   381         raise datastore_errors.BadKeyError('Incomplete key found in to_path')
   375     return path
   382     return path
   376 
   383 
   377   @staticmethod
   384   @staticmethod
   629     the entity's id or name.
   636     the entity's id or name.
   630 
   637 
   631     Returns:
   638     Returns:
   632       string
   639       string
   633     """
   640     """
   634     if (self.has_id_or_name()):
   641     if self._str is None:
   635       encoded = base64.urlsafe_b64encode(self.__reference.Encode())
   642       if (self.has_id_or_name()):
   636       return encoded.replace('=', '')
   643         encoded = base64.urlsafe_b64encode(self.__reference.Encode())
   637     else:
   644         self._str = encoded.replace('=', '')
   638       raise datastore_errors.BadKeyError(
   645       else:
   639         'Cannot string encode an incomplete key!\n%s' % self.__reference)
   646         raise datastore_errors.BadKeyError(
       
   647           'Cannot string encode an incomplete key!\n%s' % self.__reference)
       
   648     return self._str
       
   649 
   640 
   650 
   641   def __repr__(self):
   651   def __repr__(self):
   642     """Returns an eval()able string representation of this key.
   652     """Returns an eval()able string representation of this key.
   643 
   653 
   644     Returns a Python string of the form 'datastore_types.Key.from_path(...)'
   654     Returns a Python string of the form 'datastore_types.Key.from_path(...)'
   673       Positive if self is greater than "other"
   683       Positive if self is greater than "other"
   674     """
   684     """
   675     if not isinstance(other, Key):
   685     if not isinstance(other, Key):
   676       return -2
   686       return -2
   677 
   687 
   678     self_args = []
   688     self_args = [self.__reference.app()]
   679     other_args = []
   689     self_args += self.to_path(_default_id=0)
   680 
   690 
   681     self_args.append(self.__reference.app())
   691     other_args = [other.__reference.app()]
   682     other_args.append(other.__reference.app())
   692     other_args += other.to_path(_default_id=0)
   683 
       
   684     for elem in self.__reference.path().element_list():
       
   685       self_args.append(elem.type())
       
   686       if elem.has_name():
       
   687         self_args.append(elem.name())
       
   688       else:
       
   689         self_args.append(elem.id())
       
   690 
       
   691     for elem in other.__reference.path().element_list():
       
   692       other_args.append(elem.type())
       
   693       if elem.has_name():
       
   694         other_args.append(elem.name())
       
   695       else:
       
   696         other_args.append(elem.id())
       
   697 
   693 
   698     for self_component, other_component in zip(self_args, other_args):
   694     for self_component, other_component in zip(self_args, other_args):
   699       comparison = cmp(self_component, other_component)
   695       comparison = cmp(self_component, other_component)
   700       if comparison != 0:
   696       if comparison != 0:
   701         return comparison
   697         return comparison
   709     dictionary keys.
   705     dictionary keys.
   710 
   706 
   711     Returns:
   707     Returns:
   712       int
   708       int
   713     """
   709     """
   714     return hash(self.__str__())
   710     args = self.to_path(_default_id=0)
       
   711     args.append(self.__reference.app())
       
   712     return hash(type(args)) ^ hash(tuple(args))
   715 
   713 
   716 
   714 
   717 class Category(unicode):
   715 class Category(unicode):
   718   """A tag, ie a descriptive word or phrase. Entities may be tagged by users,
   716   """A tag, ie a descriptive word or phrase. Entities may be tagged by users,
   719   and later returned by a queries for that tag. Tags can also be used for
   717   and later returned by a queries for that tag. Tags can also be used for
   898   address = None
   896   address = None
   899 
   897 
   900   def __init__(self, protocol, address=None):
   898   def __init__(self, protocol, address=None):
   901     if address is None:
   899     if address is None:
   902       try:
   900       try:
   903         split = protocol.split(' ')
   901         split = protocol.split(' ', 1)
   904         protocol, address = split
   902         protocol, address = split
   905       except (AttributeError, ValueError):
   903       except (AttributeError, ValueError):
   906         raise datastore_errors.BadValueError(
   904         raise datastore_errors.BadValueError(
   907           'Expected string of format "protocol address"; received %s' %
   905           'Expected string of format "protocol address"; received %s' %
   908           str(protocol))
   906           (protocol,))
   909 
   907 
   910     ValidateString(address, 'address')
   908     ValidateString(address, 'address')
   911     if protocol not in self.PROTOCOLS:
   909     if protocol not in self.PROTOCOLS:
   912       Link(protocol)
   910       Link(protocol)
   913 
   911