#2: [1.4] pass _initializing_ from Schema.setDefaults
- Contents
Schema.setDefaults should pass '_initializing_':True as part of kwargs to the Field.set method to allow fields and storages to distinguish between regular data saving and mere initialization. Also remove the related hack from Field.get.
- Proposed by
- madduck
- Seconded by
- optilude
- Proposal type
- Architecture
- Repository branch
- madduck-atinitfixes-branch
- State
- completed
Motivation
optilude and I are fighting with making custom SQL storages work.
One of the major problems we are facing is that
BaseObject.initializeArchetype calls Schema.setDefaults, which sets
all fields in a new instance to their defaults. In the context of an
SQL database (which may have constraints), this is not acceptable.
By adding a way to distinguish between data saving and initialization,
it would be possible to write better storages.
Assumptions
when Field.get is called, all field have been initialized thanks to the call to Schema.setDefaults.
Proposal
Therefore, right now, we must work around this with a really ugly
hack. We thus propose the following trivial change (see implementation) to the
Schema.setDefault method and kindly ask you to approve it for 1.3 to
enable us to write less-sucky storages.
This change is related to the hack found in Field.get, which catches
an AttributeError on attribute access and sets the field to its
default, while passing in the same _initializing_ sentinel in
kwargs:
def get(self, instance, **kwargs):
__traceback_info__ = (self.getName(), instance, kwargs)
try:
kwargs['field'] = self
return self.getStorage(instance).get(self.getName(), instance, **kwargs)
except AttributeError:
# happens if new Atts are added and not yet stored in the instance
if not kwargs.get('_initializing_', False):
self.set(instance, self.getDefault(instance), _initializing_=True, **kwargs)
return self.getDefault(instance)
In 1.4, we can actually remove this hack. My
rationale is that setDefaults will have been called for every
instance. Thus, if Storage.get actually raises an AttributeError,
it's a real error (presumably in the storage) and should not be
worked around with such a hack. The SVN commit r4000 also removes
the hack.
Risks
AttributeErrors will be raised when an instance does not have a requested attribute, possibly because it has never been accessed before and the instance was initialized before the change. This should not be such a big deal in development versions.
Participants
madduck

I have spent quite a lot of time investigating it and have come to
the conclusion that we can get rid of the Field.get hack. My
rationale is that setDefaults will have been called for every
instance. Thus, if Storage.get actually raises an AttributeError,
it's a real error (presumably in the storage) and should not be
worked around with such a hack. The SVN commit r4000 also removes
the hack.