| 1 | # $Id: WebInputMixin.py,v 1.10 2006/01/06 21:56:54 tavis_rudd Exp $ |
|---|
| 2 | """Provides helpers for Template.webInput(), a method for importing web |
|---|
| 3 | transaction variables in bulk. See the docstring of webInput for full details. |
|---|
| 4 | |
|---|
| 5 | Meta-Data |
|---|
| 6 | ================================================================================ |
|---|
| 7 | Author: Mike Orr <iron@mso.oz.net> |
|---|
| 8 | License: This software is released for unlimited distribution under the |
|---|
| 9 | terms of the MIT license. See the LICENSE file. |
|---|
| 10 | Version: $Revision: 1.10 $ |
|---|
| 11 | Start Date: 2002/03/17 |
|---|
| 12 | Last Revision Date: $Date: 2006/01/06 21:56:54 $ |
|---|
| 13 | """ |
|---|
| 14 | __author__ = "Mike Orr <iron@mso.oz.net>" |
|---|
| 15 | __revision__ = "$Revision: 1.10 $"[11:-2] |
|---|
| 16 | |
|---|
| 17 | from Cheetah.Utils.Misc import useOrRaise |
|---|
| 18 | |
|---|
| 19 | class NonNumericInputError(ValueError): pass |
|---|
| 20 | |
|---|
| 21 | ################################################## |
|---|
| 22 | ## PRIVATE FUNCTIONS AND CLASSES |
|---|
| 23 | |
|---|
| 24 | class _Converter: |
|---|
| 25 | """A container object for info about type converters. |
|---|
| 26 | .name, string, name of this converter (for error messages). |
|---|
| 27 | .func, function, factory function. |
|---|
| 28 | .default, value to use or raise if the real value is missing. |
|---|
| 29 | .error, value to use or raise if .func() raises an exception. |
|---|
| 30 | """ |
|---|
| 31 | def __init__(self, name, func, default, error): |
|---|
| 32 | self.name = name |
|---|
| 33 | self.func = func |
|---|
| 34 | self.default = default |
|---|
| 35 | self.error = error |
|---|
| 36 | |
|---|
| 37 | |
|---|
| 38 | def _lookup(name, func, multi, converters): |
|---|
| 39 | """Look up a Webware field/cookie/value/session value. Return |
|---|
| 40 | '(realName, value)' where 'realName' is like 'name' but with any |
|---|
| 41 | conversion suffix strips off. Applies numeric conversion and |
|---|
| 42 | single vs multi values according to the comments in the source. |
|---|
| 43 | """ |
|---|
| 44 | # Step 1 -- split off the conversion suffix from 'name'; e.g. "height:int". |
|---|
| 45 | # If there's no colon, the suffix is "". 'longName' is the name with the |
|---|
| 46 | # suffix, 'shortName' is without. |
|---|
| 47 | # XXX This implementation assumes "height:" means "height". |
|---|
| 48 | colon = name.find(':') |
|---|
| 49 | if colon != -1: |
|---|
| 50 | longName = name |
|---|
| 51 | shortName, ext = name[:colon], name[colon+1:] |
|---|
| 52 | else: |
|---|
| 53 | longName = shortName = name |
|---|
| 54 | ext = '' |
|---|
| 55 | |
|---|
| 56 | # Step 2 -- look up the values by calling 'func'. |
|---|
| 57 | if longName != shortName: |
|---|
| 58 | values = func(longName, None) or func(shortName, None) |
|---|
| 59 | else: |
|---|
| 60 | values = func(shortName, None) |
|---|
| 61 | # 'values' is a list of strings, a string or None. |
|---|
| 62 | |
|---|
| 63 | # Step 3 -- Coerce 'values' to a list of zero, one or more strings. |
|---|
| 64 | if values is None: |
|---|
| 65 | values = [] |
|---|
| 66 | elif isinstance(values, str): |
|---|
| 67 | values = [values] |
|---|
| 68 | |
|---|
| 69 | # Step 4 -- Find a _Converter object or raise TypeError. |
|---|
| 70 | try: |
|---|
| 71 | converter = converters[ext] |
|---|
| 72 | except KeyError: |
|---|
| 73 | fmt = "'%s' is not a valid converter name in '%s'" |
|---|
| 74 | tup = (ext, longName) |
|---|
| 75 | raise TypeError(fmt % tup) |
|---|
| 76 | |
|---|
| 77 | # Step 5 -- if there's a converter func, run it on each element. |
|---|
| 78 | # If the converter raises an exception, use or raise 'converter.error'. |
|---|
| 79 | if converter.func is not None: |
|---|
| 80 | tmp = values[:] |
|---|
| 81 | values = [] |
|---|
| 82 | for elm in tmp: |
|---|
| 83 | try: |
|---|
| 84 | elm = converter.func(elm) |
|---|
| 85 | except (TypeError, ValueError): |
|---|
| 86 | tup = converter.name, elm |
|---|
| 87 | errmsg = "%s '%s' contains invalid characters" % tup |
|---|
| 88 | elm = useOrRaise(converter.error, errmsg) |
|---|
| 89 | values.append(elm) |
|---|
| 90 | # 'values' is now a list of strings, ints or floats. |
|---|
| 91 | |
|---|
| 92 | # Step 6 -- If we're supposed to return a multi value, return the list |
|---|
| 93 | # as is. If we're supposed to return a single value and the list is |
|---|
| 94 | # empty, return or raise 'converter.default'. Otherwise, return the |
|---|
| 95 | # first element in the list and ignore any additional values. |
|---|
| 96 | if multi: |
|---|
| 97 | return shortName, values |
|---|
| 98 | if len(values) == 0: |
|---|
| 99 | return shortName, useOrRaise(converter.default) |
|---|
| 100 | return shortName, values[0] |
|---|
| 101 | |
|---|
| 102 | # vim: sw=4 ts=4 expandtab |
|---|