app/soc/logic/models/base.py
changeset 1513 13efb916a73c
parent 1512 97c4a718d6f4
child 1514 4a233f5a4264
equal deleted inserted replaced
1512:97c4a718d6f4 1513:13efb916a73c
    37 
    37 
    38 
    38 
    39 class Error(Exception):
    39 class Error(Exception):
    40   """Base class for all exceptions raised by this module.
    40   """Base class for all exceptions raised by this module.
    41   """
    41   """
       
    42 
       
    43   pass
       
    44 
       
    45 class InvalidArgumentError(Error):
       
    46   """Raised when an invalid argument is passed to a method.
       
    47 
       
    48   For example, if an argument is None, but must always be non-False.
       
    49   """
       
    50 
       
    51   pass
       
    52 
       
    53 class NoEntityError(InvalidArgumentError):
       
    54   """Raised when no entity is passed to a method that requires one.
       
    55   """
       
    56 
    42   pass
    57   pass
    43 
    58 
    44 
    59 
    45 class Logic(object):
    60 class Logic(object):
    46   """Base logic for entity classes.
    61   """Base logic for entity classes.
   103       entity: the unaltered entity
   118       entity: the unaltered entity
   104       name: the name of the field to be changed
   119       name: the name of the field to be changed
   105       value: the new value
   120       value: the new value
   106     """
   121     """
   107 
   122 
       
   123     if not entity:
       
   124       raise NoEntityError
       
   125 
       
   126     if not entity_properties or (name not in entity_properties):
       
   127       raise InvalidArgumentError
       
   128 
   108     return True
   129     return True
   109   
   130 
   110   def _onCreate(self, entity):
   131   def _onCreate(self, entity):
   111     """Called when an entity has been created.
   132     """Called when an entity has been created.
   112 
   133 
   113     Classes that override this can use it to do any post-creation operations.
   134     Classes that override this can use it to do any post-creation operations.
   114     """
   135     """
   115 
   136 
       
   137     if not entity:
       
   138       raise NoEntityError
       
   139 
   116     sidebar.flush()
   140     sidebar.flush()
   117   
   141 
   118   def _onUpdate(self, entity):
   142   def _onUpdate(self, entity):
   119     """Called when an entity has been updated.
   143     """Called when an entity has been updated.
   120     
   144 
   121     Classes that override this can use it to do any post-update operations.
   145     Classes that override this can use it to do any post-update operations.
   122     """
   146     """
   123     
   147 
   124     pass
   148     if not entity:
   125   
   149       raise NoEntityError
       
   150 
   126   def _onDelete(self, entity):
   151   def _onDelete(self, entity):
   127     """Called when an entity has been deleted.
   152     """Called when an entity has been deleted.
   128     
   153 
   129     Classes that override this can use it to do any post-deletion operations.
   154     Classes that override this can use it to do any post-deletion operations.
   130     """
   155     """
   131     
   156 
   132     pass
   157     if not entity:
       
   158       raise NoEntityError
   133 
   159 
   134   def getKeyNameFromFields(self, fields):
   160   def getKeyNameFromFields(self, fields):
   135     """Returns the KeyName constructed from fields dict for this type of entity.
   161     """Returns the KeyName constructed from fields dict for this type of entity.
   136 
   162 
   137     The KeyName is in the following format:
   163     The KeyName is in the following format:
   138     <key_value1>/<key_value2>/.../<key_valueN>
   164     <key_value1>/<key_value2>/.../<key_valueN>
   139     """
   165     """
   140 
   166 
       
   167     if not fields:
       
   168       raise InvalidArgumentError
       
   169 
   141     key_field_names = self.getKeyFieldNames()
   170     key_field_names = self.getKeyFieldNames()
   142 
   171 
   143     # check if all key_field_names for this entity are present in fields
   172     # check if all key_field_names for this entity are present in fields
   144     if not all(field in fields.keys() for field in key_field_names):
   173     if not all(field in fields.keys() for field in key_field_names):
   145       raise Error("Not all the required key fields are present")
   174       raise InvalidArgumentError("Not all the required key fields are present")
   146 
   175 
   147     if not all(fields.get(field) for field in key_field_names):
   176     if not all(fields.get(field) for field in key_field_names):
   148       raise Error("Not all KeyValues are non-false")
   177       raise InvalidArgumentError("Not all KeyValues are non-false")
   149 
   178 
   150     # construct the KeyValues in the order given by getKeyFieldNames()
   179     # construct the KeyValues in the order given by getKeyFieldNames()
   151     keyvalues = []
   180     keyvalues = []
   152     for key_field_name in key_field_names:
   181     for key_field_name in key_field_names:
   153       keyvalues.append(fields[key_field_name])
   182       keyvalues.append(fields[key_field_name])
   155     # construct the KeyName in the appropriate format
   184     # construct the KeyName in the appropriate format
   156     return '/'.join(keyvalues)
   185     return '/'.join(keyvalues)
   157 
   186 
   158   def getFullModelClassName(self):
   187   def getFullModelClassName(self):
   159     """Returns fully-qualified model module.class name string.
   188     """Returns fully-qualified model module.class name string.
   160     """ 
   189     """
       
   190 
   161     return '%s.%s' % (self._model.__module__, self._model.__name__)
   191     return '%s.%s' % (self._model.__module__, self._model.__name__)
   162 
   192 
   163   def getKeyValuesFromEntity(self, entity):
   193   def getKeyValuesFromEntity(self, entity):
   164     """Extracts the key values from entity and returns them.
   194     """Extracts the key values from entity and returns them.
   165 
   195 
   167 
   197 
   168     Args:
   198     Args:
   169       entity: the entity from which to extract the key values
   199       entity: the entity from which to extract the key values
   170     """
   200     """
   171 
   201 
       
   202     if not entity:
       
   203       raise NoEntityError
       
   204 
   172     return [entity.scope_path, entity.link_id]
   205     return [entity.scope_path, entity.link_id]
   173 
   206 
   174   def getKeyValuesFromFields(self, fields):
   207   def getKeyValuesFromFields(self, fields):
   175     """Extracts the key values from a dict and returns them.
   208     """Extracts the key values from a dict and returns them.
   176 
   209 
   178 
   211 
   179     Args:
   212     Args:
   180       fields: the dict from which to extract the key values
   213       fields: the dict from which to extract the key values
   181     """
   214     """
   182 
   215 
       
   216     if not all( (i in fields for i in ['scope_path', 'link_id']) ):
       
   217       raise InvalidArgumentError
       
   218 
   183     return [fields['scope_path'], fields['link_id']]
   219     return [fields['scope_path'], fields['link_id']]
   184 
   220 
   185   def getKeyFieldNames(self):
   221   def getKeyFieldNames(self):
   186     """Returns an array with the names of the Key Fields.
   222     """Returns an array with the names of the Key Fields.
   187 
   223 
   212     required translations/modifications performed.
   248     required translations/modifications performed.
   213 
   249 
   214     Args:
   250     Args:
   215       dictionary: The arguments to massage
   251       dictionary: The arguments to massage
   216     """
   252     """
       
   253 
       
   254     if not dictionary:
       
   255       raise InvalidArgumentError
   217 
   256 
   218     keys = self.getKeyFieldNames()
   257     keys = self.getKeyFieldNames()
   219     values = self.getKeyValuesFromFields(dictionary)
   258     values = self.getKeyValuesFromFields(dictionary)
   220     key_fields = dicts.zip(keys, values)
   259     key_fields = dicts.zip(keys, values)
   221 
   260 
   226 
   265 
   227     Args:
   266     Args:
   228       key_name: key name of entity
   267       key_name: key name of entity
   229     """
   268     """
   230 
   269 
       
   270     if not key_name:
       
   271       raise InvalidArgumentError
       
   272 
   231     return self._model.get_by_key_name(key_name)
   273     return self._model.get_by_key_name(key_name)
   232 
   274 
   233   def getFromKeyFields(self, fields):
   275   def getFromKeyFields(self, fields):
   234     """Returns the entity for the specified key names, or None if not found.
   276     """Returns the entity for the specified key names, or None if not found.
   235 
   277 
   236     Args:
   278     Args:
   237       fields: a dict containing the fields of the entity that 
   279       fields: a dict containing the fields of the entity that
   238         uniquely identifies it
   280         uniquely identifies it
   239     """
   281     """
       
   282 
       
   283     if not fields:
       
   284       raise InvalidArgumentError
   240 
   285 
   241     key_fields = self.getKeyFieldsFromFields(fields)
   286     key_fields = self.getKeyFieldsFromFields(fields)
   242 
   287 
   243     if all(key_fields.values()):
   288     if all(key_fields.values()):
   244       key_name = self.getKeyNameFromFields(key_fields)
   289       key_name = self.getKeyNameFromFields(key_fields)
   333 
   378 
   334     Returns:
   379     Returns:
   335       The original entity with any supplied properties changed.
   380       The original entity with any supplied properties changed.
   336     """
   381     """
   337 
   382 
       
   383     if not entity:
       
   384       raise NoEntityError
       
   385 
       
   386     if not entity_properties:
       
   387       raise InvalidArgumentError
       
   388 
   338     def update():
   389     def update():
   339       return self._unsafeUpdateEntityProperties(entity, entity_properties)
   390       return self._unsafeUpdateEntityProperties(entity, entity_properties)
   340 
   391 
   341     entity = db.run_in_transaction(update)
   392     entity = db.run_in_transaction(update)
   342 
   393 
   378       properties changed, or a new entity now associated with the
   429       properties changed, or a new entity now associated with the
   379       supplied key_name and properties.
   430       supplied key_name and properties.
   380     """
   431     """
   381 
   432 
   382     entity = self.getFromKeyName(key_name)
   433     entity = self.getFromKeyName(key_name)
   383     
   434 
   384     create_entity = not entity
   435     create_entity = not entity
   385     
   436 
   386     if create_entity:
   437     if create_entity:
   387       # entity did not exist, so create one in a transaction
   438       # entity did not exist, so create one in a transaction
   388       entity = self._model.get_or_insert(key_name, **properties)
   439       entity = self._model.get_or_insert(key_name, **properties)
   389       
   440 
   390     
   441 
   391     # there is no way to be sure if get_or_insert() returned a new entity or
   442     # there is no way to be sure if get_or_insert() returned a new entity or
   392     # got an existing one due to a race, so update with properties anyway,
   443     # got an existing one due to a race, so update with properties anyway,
   393     # in a transaction
   444     # in a transaction
   394     entity = self.updateEntityProperties(entity, properties, silent=True)
   445     entity = self.updateEntityProperties(entity, properties, silent=True)
   395 
   446 
   397       # a new entity has been created call _onCreate
   448       # a new entity has been created call _onCreate
   398       self._onCreate(entity)
   449       self._onCreate(entity)
   399     else:
   450     else:
   400       # the entity has been updated call _onUpdate
   451       # the entity has been updated call _onUpdate
   401       self._onUpdate(entity)
   452       self._onUpdate(entity)
   402       
   453 
   403     return entity
   454     return entity
   404 
   455 
   405   def isDeletable(self, entity):
   456   def isDeletable(self, entity):
   406     """Returns whether the specified entity can be deleted.
   457     """Returns whether the specified entity can be deleted.
   407     
   458 
   408     Args:
   459     Args:
   409       entity: an existing entity in datastore
   460       entity: an existing entity in datastore
   410     """
   461     """
   411     
   462 
   412     return True
   463     return True
   413 
   464 
   414   def delete(self, entity):
   465   def delete(self, entity):
   415     """Delete existing entity from datastore.
   466     """Delete existing entity from datastore.
   416     
   467 
   417     Args:
   468     Args:
   418       entity: an existing entity in datastore
   469       entity: an existing entity in datastore
   419     """
   470     """
   420 
   471 
   421     entity.delete()
   472     entity.delete()