>In FormEncode (Sandbox/ianbicking/FormEncode/Schema.py) I handle this >by validating the entire request dictionary. A form validator is a >validator that has sub-validators, and collects the output from all of >them. It works quite nicely, and keeps the interface small -- >validating a request has the same interface as validating a single >field.
Thanks Ian, though I got lost in some of the details the approach of validating the entire request (formfields, query strings) is very attractive to me. I think session variables need to be taken into account as well though. I think of servlets as a little like functions : def servlet(POST_DATA,QueryString,session): ..do some stuff with what we have been passed... at the moment there is no standard WebWare way of doing assert()s to ensure that servlets are receiving valid input or acting in an environment that gives them what they need - i.e. no standard way of enforcing a contract. Makes me wonder if people ARE checking that what they get in query strings is valid? However it comes about I'd like to see that incorporated into Webware or a Kit. Unfortunately I can't do much more to advance this than bring attention to its lack. Thanks for being an ear. - Ian S. -----Original Message----- From: Ian Bicking [mailto:[EMAIL PROTECTED] Sent: Tuesday, October 07, 2003 6:16 PM To: Ian Sparks Cc: Webware-Discuss (E-mail) Subject: Re: [Webware-discuss] Validators for Sessions and QueryStrings (an example) On Tuesday, October 7, 2003, at 04:45 PM, Ian Sparks wrote: > The ValidatorConverters are one of the really neat ideas from > FunFormKit (though I use dalchemys FormKit) > > I found myself wanting to do some additional Validation of Query > Strings and Session values and I wanted to re-use the > ValidatorConverters that I had. > > The code I'm going to present isn't pretty, maybe someone has done > this better already and if so I'd prefer to use that but its a > *technique* I think has some value even if my coding is under-par. > > Even a simple webpage might take a query-string value like 'id'. You > need to do several tests : > > 1. Make sure the query string contains "id". > 2. Make sure "id" is numeric and if not, try to convert it. > 3. Make sure "id" is in range. > 4. If any of the above fail, redirect somewhere to say "Nice try buddy" > 5. Put "id" somewhere useful so you don't have to refer to it as > self.request.field('id') - maybe self.id would be nice? In FormEncode (Sandbox/ianbicking/FormEncode/Schema.py) I handle this by validating the entire request dictionary. A form validator is a validator that has sub-validators, and collects the output from all of them. It works quite nicely, and keeps the interface small -- validating a request has the same interface as validating a single field. Using the old ValidatorConverter model it might look like (roughly): class MyIDValidator(ValidatorConverter): def convert(self, value): value = value.copy() if not value.has_key('id'): raise InvalidField, 'some message' try: value['id'] = int(value['id']) except ValueError: raise InvalidField, 'yada yada' return value Or in FormEncode: class MyIDValidator(FormEncode.Schema.Schema): id = FormEncode.Validator.Int() Neither of these puts the value someplace convenient. Another thing I've experimented with is a dictionary unpacker (Sandbox/ianbicking/FormEncode/DictCall.py). It reads your method signature and works from that, so you might do: def someAction(self, id_int): ... You'd run this like DictCall.dictCall(self.someAction, self.request().fields()), though obviously some fiddling with Page would make this more elegant. If a value doesn't have a default (as id_int does not) then it is required. If you give **kw in the signature then that gets all the extra fields. You append _int, _float, _list, _set, and _dict for type conversion. _list and _dict do unpacking (e.g., "a:b=10&a:c=20" becomes {'a': {'b': 10, 'c': 20}}), and you can do some nesting like a_dict_int. It's not really extensible on several levels -- like you can't validate that the integer is within a range, and you can't do other sorts of conversion. But it does pretty decent unpacking within its range of functionality. FormEncode/VariableDecode.py does a somewhat more robust but limited unpacking (unlike DictCall, it's meant to be used with FormEncode validators). Maybe a more elegant solution would be something like: class MyPage(FormEncodeAwarePage): def someAction(self, id): ... # The schema is implicitly associated with someAction by its name: class someActionSchema(FormEncode.Schema.Schema): id = FormEncode.Validator.Int() Then in FormEncodeAwarePage.respond it might handle actions like: # You set this class variable in subclasses: _defaultAction = None # (Most pages would have a default action) def respond(self, trans): action = self._defaultAction for name, value in trans.request().fields(): if name.startswith('_action_'): if name == '_action_': action = value else: action = name[len('_action_'):] break if action: schema = getattr(self, action+'Schema', None) if not schema: raise Forbidden input = schema().toPython(self.request().fields()) getattr(self, action)(**input) So, just some ideas on the same line of thinking. (All code in above email is untested, of course) -- Ian Bicking | [EMAIL PROTECTED] | http://blog.ianbicking.org ------------------------------------------------------- This sf.net email is sponsored by:ThinkGeek Welcome to geek heaven. http://thinkgeek.com/sf _______________________________________________ Webware-discuss mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/webware-discuss ------------------------------------------------------- This SF.net email is sponsored by: SF.net Giveback Program. SourceForge.net hosts over 70,000 Open Source Projects. See the people who have HELPED US provide better services: Click here: http://sourceforge.net/supporters.php _______________________________________________ Webware-discuss mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/webware-discuss
