return new finally: if state is not None: state.key = previous_key state.full_dict = previous_full_dict def add_chained_validator(self, cls, validator): if self is not None: if self.chained_validators is cls.chained_validators: self.chained_validators = cls.chained_validators[:] self.chained_validators.append(validator) else: cls.chained_validators.append(validator) add_chained_validator = declarative.classinstancemethod( add_chained_validator) def add_field(self, cls, name, validator): if self is not None: if self.fields is cls.fields: self.fields = cls.fields.copy() self.fields[name] = validator else: cls.fields[name] = validator add_field = declarative.classinstancemethod(add_field) def add_pre_validator(self, cls, validator): if self is not None: if self.pre_validators is cls.pre_validators: self.pre_validators = cls.pre_validators[:]
finally: if state is not None: state.key = previous_key state.full_dict = previous_full_dict def add_chained_validator(self, cls, validator): if self is not None: if self.chained_validators is cls.chained_validators: self.chained_validators = cls.chained_validators[:] self.chained_validators.append(validator) else: cls.chained_validators.append(validator) add_chained_validator = declarative.classinstancemethod( add_chained_validator) def add_field(self, cls, name, validator): if self is not None: if self.fields is cls.fields: self.fields = cls.fields.copy() self.fields[name] = validator else: cls.fields[name] = validator add_field = declarative.classinstancemethod(add_field) def add_pre_validator(self, cls, validator): if self is not None: if self.pre_validators is cls.pre_validators: self.pre_validators = cls.pre_validators[:]
class SQLSchema(schema.Schema): """ SQLSchema objects are FormEncode schemas that are attached to specific instances or classes. In ``.from_python(object)`` these schemas serialize SQLObject instances to dictionaries of values, or to empty dictionaries (when serializing a class). The object passed in should either be None (new or default object) or the object to edit. In ``.to_python`` these either create new objects (when no ``id`` field is present) or edit an object by the included id. The returned value is the created object. SQLObject validators are applied to the input, as is notNone restrictions. Also column restrictions and defaults are applied. Note that you can add extra fields to this schema, and they will be applied before the SQLObject validators and restrictions. This means you can use, for instance, ``validators.DateConverter()`` (assigning it to the same name as the SQLObject class's date column) to have this serialize date columns to/from strings. You can override ``update_object`` to change the actual instantiation. The basic idea is that a SQLSchema 'wraps' a class or instance (most typically a class). So it would look like:: class PersonSchema(SQLSchema): wrap = Person ps = PersonSchema() form_defaults = ps.from_python(None) new_object = ps.to_python(form_input) form_defaults = ps.from_python(aPerson) edited_person = ps.to_python(edited_form_input) """ # This is the object that gets wrapped, either a class (this is a # creating schema) or an instance (this is an updating schema): wrap = None # If this is true, then to_python calls that include an id # will cause an object update if this schema wraps a class. allow_edit = True # If this is true, then the IDs will be signed; you must also # give a secret if that is true. sign_id = False # This can be any object with a __str__ method: # @@: Should we just take a signer validator? secret = None # The SQLObject schema will pick these up: allow_extra_fields = True filter_extra_fields = False ignore_key_missing = True messages = { 'invalidID': 'The id is not valid: %(error)s', 'badID': 'The id %(value)r did not match the expected id', 'notNone': 'You may not provide None for that value', } def __initargs__(self, new_attrs): schema.Schema.__initargs__(self, new_attrs) if self.sign_id: self._signer = validators.SignedString(secret=self.secret) def is_empty(self, value): # For this class, None has special meaning, and isn't empty return False #@classinstancemethod def object(self, cls): """ Returns the object this schema wraps """ me = self or cls assert me.wrap is not None, ( "You must give %s an object to wrap" % me) if isinstance(me.wrap, (list, tuple)): # Special lazy case... assert len(me.wrap) == 2, ( "Lists/tuples must be (class, obj_id); not %r" % me.wrap) return me.wrap[0].get(me.wrap[1]) else: return me.wrap object = classinstancemethod(object) #@classinstancemethod def instance(self, cls): """ Returns true if we wrap a SQLObject instance, false if we wrap a SQLObject class """ me = self or cls assert me.wrap is not None, ( "You must give %s an object to wrap" % me) if isinstance(me.wrap, (list, tuple)): return True elif isinstance(me.wrap, sqlobject.SQLObject): return True else: return False instance = classinstancemethod(instance) def _from_python(self, obj, state): if obj is None: obj = self.object() if isinstance(obj, sqlobject.SQLObject): value_dict = self.get_current(obj, state) else: value_dict = self.get_defaults(obj, state) result = schema.Schema._from_python(self, value_dict, state) if 'id' in result and self.sign_id: result['id'] = self._signer.from_python(result['id']) return result def _to_python(self, value_dict, state): value_dict = value_dict.copy() add_values = {} if self.instance() or value_dict.get('id'): if not self.instance() and not self.allow_edit: raise Invalid(self.message('editNotAllowed', state, value=value_dict['id']), value_dict['id'], state) if 'id' not in value_dict: raise Invalid(self.message('missingValue', state), None, state) id = value_dict.pop('id') if self.sign_id: id = self._signer.to_python(id) try: id = self.object().sqlmeta.idType(id) except ValueError, e: raise Invalid(self.message('invalidID', state, error=e), id, state) add_values['id'] = id elif 'id' in value_dict and not value_dict['id']: # Empty id, which is okay and means we are creating # an object del value_dict['id']