from django import forms

def autostrip(cls):
    fields = [(key, value) for key, value in cls.base_fields.iteritems() if isinstance(value, forms.CharField)]
    for field_name, field_object in fields:
        def get_clean_func(original_clean):
            return lambda value: original_clean(value and value.strip())
        clean_func = get_clean_func(getattr(field_object, 'clean'))
        setattr(field_object, 'clean', clean_func)
    return cls

__test__ = {'USAGE': """

# Few lines to configure the test environment...
>>> from django.conf import settings
>>> settings.configure()

# Lets define a form that will be used for the test. Note last line of this block, thats how
# we apply ``autostrip`` decorator.
>>> class PersonForm(forms.Form):
...     name = forms.CharField(min_length=2, max_length=10)
...     email = forms.EmailField()
...     
...     def clean_name(self):
...         return self.cleaned_data['name'].capitalize()
>>> PersonForm = autostrip(PersonForm)

# Lets see how autostrip works against data with leading and trailing whitespace.
# Autostrip is performed on ``CharField``s and all its descendants such as ``EmailField``,
# ``URLField``, ``RegexField``, etc.
>>> form = PersonForm({'name': '  Victor  ', 'email': '  secret@example.ru  '})
>>> form.is_valid()
True
>>> form.cleaned_data
{'name': u'Victor', 'email': u'secret@example.ru'}

# ``clean_*`` methods works after stripping, so the letter and not the space is capitalized:
>>> form = PersonForm({'name': '  victor', 'email': 'zz@zz.zz'})
>>> form.is_valid()
True
>>> form.cleaned_data
{'name': u'Victor', 'email': u'zz@zz.zz'}

# min_length constraint is checked after strip, so it is imposible now to shut up validator with
# dummy spaces
>>> form = PersonForm({'name': '  E  ', 'email': 'zz@zz.zz'})
>>> form.is_valid()
False
>>> form.errors
{'name': [u'Ensure this value has at least 2 characters (it has 1).']}

# max_length constraint is checked after strip as well
>>> form = PersonForm({'name': '            Victor              ', 'email': 'zz@zz.zz'})
>>> form.is_valid()
True

"""}

if __name__ == "__main__":
    import doctest
    doctest.testmod()