Changeset 4106
- Timestamp:
- 02/08/08 10:39:59 (6 months ago)
- Files:
-
- branches/1.0/turbogears/validators.py (modified) (15 diffs)
- branches/1.1/turbogears/validators.py (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/1.0/turbogears/validators.py
r3366 r4106 3 3 This module also imports everything from formencode.validators, so all 4 4 common validation routines are available here.""" 5 6 import pkg_resources7 #XXX Remove in 1.0.3 when everyone has already upgraded FE8 # so we don't need to keep this in sync with setup.py9 pkg_resources.require("FormEncode >= 0.7.1")10 5 11 6 import time 12 7 import re 13 8 from datetime import datetime 14 import cgi # FieldStorageUploadConverter15 9 import warnings 16 10 … … 26 20 from turbojson import jsonify 27 21 28 from formencode import validators # Needed to disambiguate the Number validator... 29 30 import __builtin__ 22 from formencode import validators # to disambiguate the Number validator... 31 23 32 24 def _(s): return s # dummy 33 25 34 Validator.gettextargs['domain'] = 'FormEncode' # FormEncode should call Tg's gettext \ 35 # function with domain = "FormEncode" 26 # FormEncode should call TG's gettext function with domain = "FormEncode" 27 Validator.gettextargs['domain'] = 'FormEncode' 28 36 29 37 30 class TgFancyValidator(FancyValidator): 38 gettextargs = {'domain':'TurboGears'} 31 gettextargs = {'domain': 'TurboGears'} 32 39 33 40 34 class Money(TgFancyValidator): 35 """Validate a monetary value with currency.""" 41 36 42 37 messages = { … … 54 49 55 50 def _to_python(self, value, state): 56 """ parse a string and returns a float or integer"""51 """Parse a string and return a float or integer.""" 57 52 try: 58 53 return format.parse_decimal(value) … … 61 56 62 57 def _from_python(self, value, state): 63 """ returns a string using the correct grouping"""58 """Return a string using the correct grouping.""" 64 59 return format.format_currency(value) 65 60 66 61 67 62 class Number(TgFancyValidator): 68 69 def _to_python(self, value, state): 70 """ parse a string and returns a float or integer """ 63 """Validate a decimal number.""" 64 65 def _to_python(self, value, state): 66 """Parse a string and return a float or integer.""" 71 67 if isinstance(value, basestring): 72 68 try: … … 77 73 78 74 def _from_python(self, value, state): 79 """ returns a string using the correct grouping"""75 """Return a string using the correct grouping.""" 80 76 dec_places = util.find_precision(value) 81 77 if dec_places > 0: … … 86 82 87 83 class DateTimeConverter(TgFancyValidator): 88 89 """ 90 Converts Python date and datetime objects into string representation and back. 91 """ 84 """Convert between Python datetime objects and strings.""" 85 92 86 messages = { 93 87 'badFormat': _('Invalid datetime format'), … … 95 89 } 96 90 97 def __init__(self, format = "%Y/%m/%d %H:%M", allow_empty =None,91 def __init__(self, format="%Y/%m/%d %H:%M", allow_empty=None, 98 92 *args, **kwargs): 99 93 if allow_empty is not None: … … 106 100 107 101 def _to_python(self, value, state): 108 """ parse a string and return a datetime object."""102 """Parse a string and return a datetime object.""" 109 103 if value and isinstance(value, datetime): 110 104 return value 111 105 else: 112 106 try: 113 # DBR start114 107 format = self.format 115 108 if callable(format): 116 109 format = format() 117 110 tpl = time.strptime(value, format) 118 # DBR end119 120 111 except ValueError: 121 112 raise Invalid(self.message('badFormat', state), value, state) … … 126 117 127 118 def _from_python(self, value, state): 119 """Return a string representation of a datetime object.""" 128 120 if not value: 129 121 return None 130 122 elif isinstance(value, datetime): 131 123 # Python stdlib can only handle dates with year greater than 1900 132 # DBR start133 124 format = self.format 134 125 if callable(format): … … 140 131 else: 141 132 return value.strftime(format) 142 # DBR end143 133 else: 144 134 return value 145 135 146 # formencode trunk contains UnicodeString implementation147 # but it is different from ours and was broken at the time.148 # remove this impl. when formencode.validators.UnicodeString will be identical to ours.149 class UnicodeString(String):150 encoding = 'utf-8'151 messages = {152 'badEncoding' : _("Invalid data or incorrect encoding"),153 }154 def __init__(self, inputEncoding=None, outputEncoding=None, **kw):155 String.__init__(self, **kw)156 self.inputEncoding = inputEncoding or self.encoding157 self.outputEncoding = outputEncoding or self.encoding158 def _to_python(self, value, state):159 if value:160 if isinstance(value, unicode):161 return value162 if hasattr(value, '__unicode__'):163 return unicode(value)164 try:165 return unicode(value, self.inputEncoding)166 except UnicodeDecodeError:167 raise Invalid(self.message('badEncoding', state), value, state)168 return u''169 def _from_python(self, value, state):170 if hasattr(value, '__unicode__'):171 value = unicode(value)172 if isinstance(value, unicode):173 return value.encode(self.outputEncoding)174 return str(value)175 176 # another formencode workaround,177 # see #1464357 on FE bugtracker (http://tinyurl.com/lm9ae).178 # Custom version of FieldStorage validator that does not break FE schema validator.179 class FieldStorageUploadConverter(TgFancyValidator):180 def to_python(self, value, state=None):181 if isinstance(value, cgi.FieldStorage):182 if value.filename:183 return value184 raise Invalid('invalid', value, state)185 else:186 return value187 136 188 137 # For translated messages that are not wrapped in a Validator.messages … … 193 142 _ = lambda s: turbogears.i18n.gettext(s, domain='TurboGears') 194 143 144 195 145 class MultipleSelection(ForEach): 146 """A default validator for SelectionFields with multiple selection.""" 147 196 148 if_missing = NoDefault 197 149 if_empty = [] … … 203 155 raise Invalid(_("Please select at least a value"), value, state) 204 156 157 205 158 class Schema(Schema): 206 """ A Schema validator """ 159 """Modified Schema validator for TurboGears.""" 160 207 161 filter_extra_fields = True 208 162 allow_extra_fields = True 209 163 if_key_missing = None 210 164 211 def from_python(self, value,state=None):165 def from_python(self, value, state=None): 212 166 # The Schema shouldn't do any from_python conversion because 213 167 # adjust_value already takes care of that for all childs. 214 168 return value 215 169 170 216 171 class JSONValidator(TgFancyValidator): 172 """A validator for JSON format.""" 217 173 218 174 def _from_python(self, value, state): … … 222 178 return simplejson.loads(value) 223 179 224 _illegal_s = re.compile(r"((^|[^%])(%%)*%s)") 180 181 # Auxiliary functions 225 182 226 183 def _findall(text, substr): … … 236 193 return sites 237 194 195 _illegal_s = re.compile(r"((^|[^%])(%%)*%s)") 196 238 197 def strftime_before1900(dt, fmt): 198 """strftime implementation supporting proleptic Gregorian dates before 1900. 199 200 @see: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/306860 201 239 202 """ 240 A strftime implementation that supports proleptic Gregorian dates before 1900.241 242 @see: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/306860243 """244 import datetime245 203 if _illegal_s.search(fmt): 246 204 raise TypeError("This strftime implementation does not handle %s") … … 253 211 delta = 2000 - year 254 212 off = 6*(delta // 100 + delta // 400) 255 year = year +off213 year += off 256 214 257 215 # Move to around the year 2000 branches/1.1/turbogears/validators.py
r3367 r4106 3 3 This module also imports everything from formencode.validators, so all 4 4 common validation routines are available here.""" 5 6 import pkg_resources7 #XXX Remove in 1.0.3 when everyone has already upgraded FE8 # so we don't need to keep this in sync with setup.py9 pkg_resources.require("FormEncode >= 0.7.1")10 5 11 6 import time 12 7 import re 13 8 from datetime import datetime 14 import cgi # FieldStorageUploadConverter15 9 import warnings 16 10 … … 26 20 from turbojson import jsonify 27 21 28 from formencode import validators # Needed to disambiguate the Number validator... 29 30 import __builtin__ 22 from formencode import validators # to disambiguate the Number validator... 31 23 32 24 def _(s): return s # dummy 33 25 34 Validator.gettextargs['domain'] = 'FormEncode' # FormEncode should call Tg's gettext \ 35 # function with domain = "FormEncode" 26 # FormEncode should call TG's gettext function with domain = "FormEncode" 27 Validator.gettextargs['domain'] = 'FormEncode' 28 36 29 37 30 class TgFancyValidator(FancyValidator): 38 gettextargs = {'domain':'TurboGears'} 31 gettextargs = {'domain': 'TurboGears'} 32 39 33 40 34 class Money(TgFancyValidator): 35 """Validate a monetary value with currency.""" 41 36 42 37 messages = { … … 54 49 55 50 def _to_python(self, value, state): 56 """ parse a string and returns a float or integer"""51 """Parse a string and return a float or integer.""" 57 52 try: 58 53 return format.parse_decimal(value) … … 61 56 62 57 def _from_python(self, value, state): 63 """ returns a string using the correct grouping"""58 """Return a string using the correct grouping.""" 64 59 return format.format_currency(value) 65 60 66 61 67 62 class Number(TgFancyValidator): 68 69 def _to_python(self, value, state): 70 """ parse a string and returns a float or integer """ 63 """Validate a decimal number.""" 64 65 def _to_python(self, value, state): 66 """Parse a string and return a float or integer.""" 71 67 if isinstance(value, basestring): 72 68 try: … … 77 73 78 74 def _from_python(self, value, state): 79 """ returns a string using the correct grouping"""75 """Return a string using the correct grouping.""" 80 76 dec_places = util.find_precision(value) 81 77 if dec_places > 0: … … 86 82 87 83 class DateTimeConverter(TgFancyValidator): 88 89 """ 90 Converts Python date and datetime objects into string representation and back. 91 """ 84 """Convert between Python datetime objects and strings.""" 85 92 86 messages = { 93 87 'badFormat': _('Invalid datetime format'), … … 95 89 } 96 90 97 def __init__(self, format = "%Y/%m/%d %H:%M", allow_empty =None,91 def __init__(self, format="%Y/%m/%d %H:%M", allow_empty=None, 98 92 *args, **kwargs): 99 93 if allow_empty is not None: … … 106 100 107 101 def _to_python(self, value, state): 108 """ parse a string and return a datetime object."""102 """Parse a string and return a datetime object.""" 109 103 if value and isinstance(value, datetime): 110 104 return value 111 105 else: 112 106 try: 113 # DBR start114 107 format = self.format 115 108 if callable(format): 116 109 format = format() 117 110 tpl = time.strptime(value, format) 118 # DBR end119 120 111 except ValueError: 121 112 raise Invalid(self.message('badFormat', state), value, state) … … 126 117 127 118 def _from_python(self, value, state): 119 """Return a string representation of a datetime object.""" 128 120 if not value: 129 121 return None 130 122 elif isinstance(value, datetime): 131 123 # Python stdlib can only handle dates with year greater than 1900 132 # DBR start133 124 format = self.format 134 125 if callable(format): … … 140 131 else: 141 132 return value.strftime(format) 142 # DBR end143 133 else: 144 134 return value 145 135 146 # formencode trunk contains UnicodeString implementation147 # but it is different from ours and was broken at the time.148 # remove this impl. when formencode.validators.UnicodeString will be identical to ours.149 class UnicodeString(String):150 encoding = 'utf-8'151 messages = {152 'badEncoding' : _("Invalid data or incorrect encoding"),153 }154 def __init__(self, inputEncoding=None, outputEncoding=None, **kw):155 String.__init__(self, **kw)156 self.inputEncoding = inputEncoding or self.encoding157 self.outputEncoding = outputEncoding or self.encoding158 def _to_python(self, value, state):159 if value:160 if isinstance(value, unicode):161 return value162 if hasattr(value, '__unicode__'):163 return unicode(value)164 try:165 return unicode(value, self.inputEncoding)166 except UnicodeDecodeError:167 raise Invalid(self.message('badEncoding', state), value, state)168 return u''169 def _from_python(self, value, state):170 if hasattr(value, '__unicode__'):171 value = unicode(value)172 if isinstance(value, unicode):173 return value.encode(self.outputEncoding)174 return str(value)175 176 # another formencode workaround,177 # see #1464357 on FE bugtracker (http://tinyurl.com/lm9ae).178 # Custom version of FieldStorage validator that does not break FE schema validator.179 class FieldStorageUploadConverter(TgFancyValidator):180 def to_python(self, value, state=None):181 if isinstance(value, cgi.FieldStorage):182 if value.filename:183 return value184 raise Invalid('invalid', value, state)185 else:186 return value187 136 188 137 # For translated messages that are not wrapped in a Validator.messages … … 193 142 _ = lambda s: turbogears.i18n.gettext(s, domain='TurboGears') 194 143 144 195 145 class MultipleSelection(ForEach): 146 """A default validator for SelectionFields with multiple selection.""" 147 196 148 if_missing = NoDefault 197 149 if_empty = [] … … 203 155 raise Invalid(_("Please select at least a value"), value, state) 204 156 157 205 158 class Schema(Schema): 206 """ A Schema validator """ 159 """Modified Schema validator for TurboGears.""" 160 207 161 filter_extra_fields = True 208 162 allow_extra_fields = True 209 163 if_key_missing = None 210 164 211 def from_python(self, value,state=None):165 def from_python(self, value, state=None): 212 166 # The Schema shouldn't do any from_python conversion because 213 167 # adjust_value already takes care of that for all childs. 214 168 return value 215 169 170 216 171 class JSONValidator(TgFancyValidator): 172 """A validator for JSON format.""" 217 173 218 174 def _from_python(self, value, state): … … 222 178 return simplejson.loads(value) 223 179 224 _illegal_s = re.compile(r"((^|[^%])(%%)*%s)") 180 181 # Auxiliary functions 225 182 226 183 def _findall(text, substr): … … 236 193 return sites 237 194 195 _illegal_s = re.compile(r"((^|[^%])(%%)*%s)") 196 238 197 def strftime_before1900(dt, fmt): 198 """strftime implementation supporting proleptic Gregorian dates before 1900. 199 200 @see: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/306860 201 239 202 """ 240 A strftime implementation that supports proleptic Gregorian dates before 1900.241 242 @see: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/306860243 """244 import datetime245 203 if _illegal_s.search(fmt): 246 204 raise TypeError("This strftime implementation does not handle %s") … … 253 211 delta = 2000 - year 254 212 off = 6*(delta // 100 + delta // 400) 255 year = year +off213 year += off 256 214 257 215 # Move to around the year 2000