mongokit icon indicating copy to clipboard operation
mongokit copied to clipboard

"filters" descriptor

Open namlook opened this issue 14 years ago • 5 comments

See http://groups.google.com/group/mongokit/browse_thread/thread/f282f4dee0dfe1ce Maybe we should call this descriptor "process" as it will process the value before saving it...

namlook avatar Oct 20 '10 10:10 namlook

via anonymous:

"filters"? hmmm... "process"? hmm... "cleaners"? maybe "process" sounds like it's doing more things such as taking in the value, cleaning it up, saving it and indexing it or something. Django's form implementation has a convention that you can create methods on the form class called "clean_" which serves two purposes, a) to do extra non-trivial validation and b) ability to modify the value. Django also solves the problem of invariants by allowing you to define a method called clean which is where you can do non-trivial validation of combinations of values. Their approach is very handy but having magically named methods feels a little less pythonic. One thing you could do is define a class inside the Document subclass whose method names are expected to be the keys of the structure.

class Doc(Document):
    structure = {'first_name': unicode,
                        'last_name': unicode}
    class Filters:
          def first_name(value):
                if first_name == 'XXX':
                    raise mongokit.ValidationError("Bad name")
                return first_name.strip()

Or another alternative that might be easier to wrap in your own custom inheritance would be this:

class MyNameFilters(object):
      def first_name(value):
            if first_name == 'XXX':
                raise mongokit.ValidationError("Bad name")
            return first_name.strip()

class Doc(Document):
    structure = {'first_name': unicode,
                        'last_name': unicode}
    filters = MyNameFilters()
    # alternatively, ...
    #filters = (MyNameFilters(), )

namlook avatar Oct 20 '10 10:10 namlook

via Phillip Oldham

Maybe properties could be used? For instance, while I poked around trying to get something to work my first idea was something like this:

class Doc(Document):
    structure = {
        'name': unicode,
        'shortname': unicode,
    }

    def _get_shortname(self):
        return self.structure.shortname
    
    def _set_shortname(self, shortname):
        self.structure.shortname = shortname.lower()

    def _get_name(self):
        return self.structure.name

    def _set_name(self):
        self.structure.name = name
        self.structure.shortname = name.lower().replace(" ", "")

    shortname = property(self._get_shortname, self._set_shortname)

Now, I'm not sure how things work under the hood; I'm assuming that __setattr__ and __getattribute__ are being used, so maybe jumping into that workflow or altering it somehow could mean properties could be used in this way?

namlook avatar Oct 20 '10 10:10 namlook

this (the property way) work fine. I use it in mongokit.auth.user.

Need to think more about it : I often want to do little basic manipulations of values before setting them. For example turning byte strings into unicode and stripping whitespace. Could help with unit-testing when there are many attributes which need to be "cleaned" or adjusted when being set

If there is enough vote for this feature, I will implement it. (to vote, just post a comment)

namlook avatar Oct 20 '10 10:10 namlook

via cjoudrey:

Overloading the validate() method works fine, but a faster way to do this would be greatly appreciated. This would especially be useful for columns that need to be normalized before save (i.e. lower casing a column before validate(), unicoding a column before validate(), etc..)

namlook avatar Oct 20 '10 10:10 namlook

via Andrey Gusev

+1:

def _set_FIELDNAME(self, old_value):
    return NEW_VALUE

a.somefield = 'blahblu' runs like setattr(a, 'somefield', a._set_somefield('blahblu'))

namlook avatar Oct 20 '10 10:10 namlook