On Dec 22, 2007, at 12:34 AM, Andreas Jung wrote:
> > > --On 21. Dezember 2007 16:33:34 -0500 Michael Bayer <[EMAIL PROTECTED] > > wrote: > >> >> On Dec 21, 2007, at 3:13 PM, Rick Morrison wrote: > >> >> >> I think the only way something like this should be done is as a test >> fixture which decorates classes during unit tests. It would be >> fairly clumsy to have in production code. >> >> If you have coworkers who write broken code, the way you solve that >> is >> by having unit tests which will fail when the coworkers in question >> do >> something theyre not supposed to. If other people are writing code >> that sets attrbutes its not supposed to and breaks things, you need >> more tests to catch those conditions. If youre putting code into >> production that hasnt been tested, then you need a build process, >> automated testing, etc. There is definitely a "best practice" here >> and test driven development is it. > > With all respect, this is not a useful answer. Even with tests > (unittests and weeks of manual tests) I had the case that a simple > programming error > (of my own) produced a data disaster after some weeks. There is no > 100% test coverage. Tests don't solve all problems. There is > sometimes the need for a better security belt. > I am certainly suggesting a fixture that detects illegal assignments to attributes. That it be limited to just unit tests is only a suggestion. To establish this functionality regardless of environment, like Rick said just create properties which prohibit assignment. Create mappers like this: class AttrGetter(object): def __init__(self, name): self.name = name def __get__(self, instance, name): if instance is None: return self return getattr(instance, '_' + name) def __set__(self, instance, value): raise AssertionError("Sets are not allowed") def __delete__(self, instance): raise AssertionError("Deletes are not allowed") class MyClass(object): somecolumn = AttrGetter('somecolumn') someothercolumn = AttrGetter('someothercolumn') mapper(MyClass, sometable, properties={ '_somecolumn':sometable.c.somecolumn, '_someothercolumn':sometable.c.someothercolumn }) To automate the above process with no modifications to source code, create an instrumented mapper() function which applies the above recipe to all table columns: from sqlalchemy.orm import mapper as _mapper def mapper(cls, table, **kwargs): attrs = {} for c in table.c: attrs['_' + c.key] = c setattr(cls, c.key, AttrGetter(c.key)) properties = kwargs.setdefault('properties', {}) properties.update(attrs) return _mapper(cls, table, **kwargs) Hope this helps. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~----------~----~----~----~------~----~------~--~---