Thanks for the snippet above, Ian. > What outcome do you actually want? Only the first or last thing from the > list to get validated? Or an error if there is more than one thing ?
I think the validator must raise an exception in such a case. I'm going to create a ticket in the formencode's tracker. Do you have any additional suggestions that should be mentioned in it? On Feb 11, 5:10 am, Ian Wilson <[email protected]> wrote: > After thinking about this more it would probably be better if UnicodeString > just had a parameter that turned coercion of everything but instances of > basestring and None off. Or maybe another validator was created that did > that. It makes more sense for the validator that is assigned that key to > respond to both lists and non-lists. > > What outcome do you actually want? Only the first or last thing from the > list to get validated? Or an error if there is more than one thing ? > > Here is a validator I hacked together from the String and UnicodeString > validators that only accepts None and basestrings. None and non-unicode > strings are both converted to unicode. > > class StrictUnicodeString(FancyValidator): > """""" > > min = None > max = None > not_empty = None > convert_none = True > encoding = 'utf-8' > > messages = { > 'notString': "Please enter a string", > 'tooLong': "Enter a value less than %(max)i characters long", > 'tooShort': "Enter a value %(min)i characters long or more", > 'badEncoding' : "Invalid data or incorrect encoding", > } > > def __initargs__(self, new_attrs): > if self.not_empty is None and self.min: > self.not_empty = True > > def __init__(self, input_encoding=None, output_encoding=None, > convert_none=True, **kw): > FancyValidator.__init__(self, **kw) > self.input_encoding = input_encoding or self.encoding > self.output_encoding = output_encoding or self.encoding > self.convert_none = convert_none > > def _to_python(self, value, state): > """ Converts to unicode. """ > if self.convert_none and value is None: > value = u'' > if not isinstance(value, basestring): > raise Invalid(self.message('notString', state), value, state) > if not isinstance(value, unicode): > try: > value = unicode(value, self.input_encoding) > except UnicodeDecodeError: > raise Invalid(self.message('badEncoding', state), value, > state) > return value > > def _from_python(self, value, state): > """ Converts to a bytestring. """ > if not isinstance(value, unicode): > if hasattr(value, '__unicode__'): > value = unicode(value) > else: > value = str(value) > if isinstance(value, unicode): > value = value.encode(self.output_encoding) > return value > > def validate_other(self, value, state): > if (self.max is not None and value is not None > and len(value) > self.max): > raise Invalid(self.message('tooLong', state, > max=self.max), > value, state) > if (self.min is not None > and (not value or len(value) < self.min)): > raise Invalid(self.message('tooShort', state, > min=self.min), > value, state) > > def empty_value(self, value): > return u'' > > -Ian > > On Thu, Feb 10, 2011 at 2:52 PM, Maxim Avanov <[email protected]>wrote: > > > Hi, Ian. Thanks for reply. > > > >If you want to be EXTRA strict then you could try ConfirmType and > > UnicodeString combined in an All validator to catch this error. Or something > > to that effect. > > > This solution will work, but I wouldn't like to use it for several > > reasons. First of all, we already have a huge code base that > > intensively uses UnicodeStrings. Surely, we could define our own > > UnicodeString validator like below, > > > UnicodeString = > > formencode.All(formencode.ConfirmType(subclass=unicode), > > formencode.UnicodeString()) > > > but we trying to keep our design clean. Moreover, "All" and > > "ConfirmType" require extra validation steps (and hence more function > > calls). I think it has to be solved in more generic and concise way > > (i.e. in formencode's internal api level). > > > > Also note that someone could actually send ?username=[u'John', u'Mike'] > > in > > > the query which would exhibit similar behavior. > > > Yes, and it is the place where the inconsistency of validators > > behaviour comes. if we'd have an unified behaviour for all single- > > value validators (Int, UnicodeString, Bool etc.) we could get > > "[u'John', u'Mike']" result only for "/?username=[u'John', u'Mike']" > > request. But now, we can get the same result by the two different > > requests - by "/?username=[u'John', u'Mike']" and by "/? > > username=John&username=Mike". This shouldn't be allowed. And it's not > > allowed for all single-value validators except the UnicodeString. > > > > If we don't use mixed then how do we get the multiple values when we want > > > them? > > > We might explicitly specify our expectations with ForEach() and Set() > > validators. > > formencode's FancyValidator could internally test currently running > > validator by calling something like > > > isinstance(current_validator, ForEach) > > > and then perform appropriate actions for this case (i.e. call single- > > value validator for each found item with the same key). > > > P.S. I hope Ian Bicking will see this topic and give his opinion all > > about this, as I might miss something important here. > > > On Feb 9, 6:38 am, Ian Wilson <[email protected]> wrote: > > > Hi, > > > > I think this behavior happens because mixed is used herehttps:// > > bitbucket.org/ianb/formencode/src/d95237b33f3c/formencode/api.... > > > If you don't want that to happen ever then I think you need to cast > > params > > > to a regular dictionary, with something like > > dict(request.params.items()). > > > This will silently ignore one of the names though which might be worse. > > > > If you want to be EXTRA strict then you could try ConfirmType and > > > UnicodeString combined in an All validator to catch this error. Or > > > something to that effect. > > > > Also note that someone could actually send ?username=[u'John', u'Mike'] > > in > > > the query which would exhibit similar behavior. So as far as I can tell > > if > > > that is a problem you'd need to validate it either way. > > > > I agree that this might be misleading but its a difficult problem to > > solve. > > > If we don't use mixed then how do we get the multiple values when we want > > > them? I think formencode might just need better internal integration > > with > > > multiple value dictionaries so that different types don't show up > > depending > > > on the input. It tries to be input agnostic though. > > > > -Ian > > > > On Tue, Feb 8, 2011 at 10:25 AM, Maxim Avanov <[email protected] > > >wrote: > > > > > Here's an example. > > > > > # ===================== > > > > from formencode import Schema, Invalid > > > > from formencode.validators import UnicodeString, Int > > > > from webob import Request > > > > > class StrictSchema(Schema): > > > > allow_extra_fields = False > > > > > class IntegerTestSchema(StrictSchema): > > > > testfield = Int(not_empty=True) > > > > > class StringTestSchema(StrictSchema): > > > > testfield = UnicodeString(not_empty=True) > > > > > # Testing. > > > > # ===================== > > > > req = Request.blank('/?testfield=111') > > > > print IntegerTestSchema.to_python(req.params) > > > > > # This raises an exception > > > > req = Request.blank('/?testfield=111&testfield=222') > > > > try: > > > > IntegerTestSchema.to_python(req.params) > > > > except Invalid as e: > > > > print "Caught Exception: {0}".format(e) > > > > > req = Request.blank('/?testfield=aaa') > > > > print StringTestSchema.to_python(req.params) > > > > > # This will be passed successfully (!) > > > > # The output will be {'testfield': u"[u'aaa', u'bbb']"} > > > > req = Request.blank('/?testfield=aaa&testfield=bbb') > > > > print StringTestSchema.to_python(req.params) > > > > > # ======================== > > > > > Please note we do not use formencode.ForEach() or formencode.Set() > > > > here. I think this is very unclear behaviour. > > > > Imagine an UsernameValidator (or something related to "not-so-strict- > > > > string-validator"). Instead of indicating an input error, we show the > > > > service realization details to our users -- "{'username': u"[u'John', > > > > u'Mike']"}" - "Ok. This is Python list inside the dict". > > > > > According to WebOb documentation (http://pythonpaste.org/webob/ > > > > #multidict), we probably should use request.GET.getone() instead of > > > > request.GET.getall(). > > > > > -- > > > > You received this message because you are subscribed to the Google > > Groups > > > > "pylons-discuss" group. > > > > To post to this group, send email to [email protected]. > > > > To unsubscribe from this group, send email to > > > > [email protected]. > > > > For more options, visit this group at > > > >http://groups.google.com/group/pylons-discuss?hl=en. > > > -- > > You received this message because you are subscribed to the Google Groups > > "pylons-discuss" group. > > To post to this group, send email to [email protected]. > > To unsubscribe from this group, send email to > > [email protected]. > > For more options, visit this group at > >http://groups.google.com/group/pylons-discuss?hl=en. -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.
