If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

The list:string type does not store empty strings. Because of the way the function bar_encode() formats an empty list as ||, there's no room for empty strings in it.


But that's python and web2py.. it can't be difficult.


class EmptyStrAble(object):
    """ (1)Define filter_in/filter_out for the desired field and (2)wrap its 
        `contains` operator for full functionality as a list:string able to 
        work with empty strings 
    empty_string_mark = '-*- empty string -*-' 

    def filter_in(self, obj):
        """ change empty string with empty_string_mark
        if obj == '':
            obj = self.empty_string_mark
        elif hasattr(obj, '__iter__'):
            if '' in obj:
                obj[obj.index('')] = self.empty_string_mark
        return obj

    def filter_out(self, obj):
        """ change empty_string_mark with empty string
        if isinstance(obj, list):  # it's list or None
            if self.empty_string_mark in obj:
                obj[obj.index(self.empty_string_mark)] = ''
        return obj

    def contains_wrapper(self, func):
        """ apply `filter_in` to the first argument of  `contains` operator wich
            always is either a string or a list of strings
        def checker(*args, **kwargs):
            largs = args[:]
            largs[0] = self.filter_in(largs[0])
            return func(*largs, **kwargs)
        return checker


And apply:

# ==== in models =====
    Field('options', 'list:string'))

# Define filters and wrap `contains` operator
esa = EmptyStringAble()

db.thing.options.filter_in = lambda obj, my_in=esa.filter_in: my_in( obj )
db.thing.options.filter_out = lambda obj, my_out=esa.filter_out: my_out( obj )

db.thing.options.contains = esa.contains_wrapper( db.thing.options.contains )


Now we've got our desire satisfied:

def test_me():    
    db.thing.insert(options=['a', '', 'ca'])    
    assert(db(db.thing.options.contains('')).count()==2), 'Error'
    assert(db(db.thing.options.contains('', all=True)).count()==2), 'Error'
    assert(db(db.thing.options.contains(['', 'ca'], all=True)).count()==1), 'Error'
    return 'Python and Web2py rules!'




Related slices

Comments (0)

Hosting graciously provided by:
Python Anywhere