Package orm2 :: Module validators
[hide private]
[frames] | no frames]

Source Code for Module orm2.validators

  1  #!/usr/bin/env python 
  2  # -*- coding: iso-8859-1 -*- 
  3   
  4  ##  This file is part of orm, The Object Relational Membrane Version 2. 
  5  ## 
  6  ##  Copyright 2002-2006 by Diedrich Vorberg <diedrich@tux4web.de> 
  7  ## 
  8  ##  All Rights Reserved 
  9  ## 
 10  ##  For more Information on orm see the README file. 
 11  ## 
 12  ##  This program is free software; you can redistribute it and/or modify 
 13  ##  it under the terms of the GNU General Public License as published by 
 14  ##  the Free Software Foundation; either version 2 of the License, or 
 15  ##  (at your option) any later version. 
 16  ## 
 17  ##  This program is distributed in the hope that it will be useful, 
 18  ##  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 19  ##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 20  ##  GNU General Public License for more details. 
 21  ## 
 22  ##  You should have received a copy of the GNU General Public License 
 23  ##  along with this program; if not, write to the Free Software 
 24  ##  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 25  ## 
 26  ##  I have added a copy of the GPL in the file gpl.txt. 
 27   
 28  # 
 29  # $Log: validators.py,v $ 
 30  # Revision 1.8  2008/01/04 17:35:14  diedrich 
 31  # Removed ^ and $ from res 
 32  # 
 33  # Revision 1.7  2006/07/08 17:09:40  diedrich 
 34  # Changed email and domain regex to contain ^ and $ 
 35  # 
 36  # Revision 1.6  2006/07/05 21:42:37  diedrich 
 37  # - Added not_empty_validator 
 38  # - Several validators didn't handle None values as expected, fixed that 
 39  # 
 40  # Revision 1.5  2006/07/04 22:45:44  diedrich 
 41  # Import string 
 42  # 
 43  # Revision 1.4  2006/05/13 17:23:41  diedrich 
 44  # Massive docstring update. 
 45  # 
 46  # Revision 1.3  2006/04/28 09:49:26  diedrich 
 47  # Docstring updates for epydoc 
 48  # 
 49  # Revision 1.2  2006/04/28 08:45:11  diedrich 
 50  # Added validators. 
 51  # 
 52  # Revision 1.1  2006/04/21 18:55:10  diedrich 
 53  # Initial commit 
 54  # 
 55  # 
 56   
 57  """ 
 58  This module defines classes for validating values stored in dbproperties 
 59  before they screw up the database or cause a CONSTRAINT error. 
 60  """ 
 61   
 62   
 63  import re 
 64  from types import * 
 65  from string import * 
 66  from orm2.exceptions import * 
 67   
68 -class validator:
69 """ 70 The default validator: It doesn't check anything. 71 """
72 - def check(self, dbobj, dbproperty, value):
73 return True
74
75 -class not_null_validator(validator):
76 """ 77 For NOT NULL columns. 78 """
79 - def check(self, dbobj, dbproperty, value):
80 if value is None: 81 tpl = ( dbobj.__class__.__name__, 82 dbproperty.attribute_name, ) 83 raise NotNullError("%s.%s may not be NULL (None)" % tpl, 84 dbobj, dbproperty, value)
85 86 87 not_none_validator = not_null_validator # which identifyer makes more sense?? 88
89 -class not_empty_validator(validator):
90 """ 91 For columns which may not contain empty strings. 92 """
93 - def check(self, dbobj, dbproperty, value):
94 if type(value) == StringType or type(value) == UnicodeType: 95 if value == "": 96 tpl = ( dbobj.__class__.__name__, 97 dbproperty.attribute_name, ) 98 raise NotEmptyError("%s.%s may not be empty" % tpl, 99 dbobj, dbproperty, value)
100
101 -class length_validator(validator):
102 """ 103 Check an argument value's length. None values will be ignored. 104 """
105 - def __init__(self, max_length):
106 self.max_length = max_length
107
108 - def check(self, dbobj, dbproperty, value):
109 if value is not None and len(value) > self.max_length: 110 msg = "Length check failed on %s.%s" % (dbobj.__class__.__name__, 111 dbproperty.attribute_name,) 112 raise LengthValidatorException(msg, dbobj, dbproperty, value)
113
114 -class range_validator(validator):
115 """ 116 A generic validator for value ranges (fortunately Python doesn't care, it 117 can be used for numerals, dates, strings...) 118 """
119 - def __init__(self, lo, hi, include_bounds=False):
120 """ 121 The formula goes:: 122 123 lo < value < hi 124 125 if include_bounds is False (the default) or:: 126 127 lo <= value <= hi 128 129 otherwise. If above formula is not valid, a RangeValidatorError will 130 be raised by check() 131 """ 132 self.lo = lo 133 self.hi = hi 134 self.include_bounds = include_bounds
135
136 - def check(self, dbobj, dbproperty, value):
137 if not self.include_bounds: 138 if self.lo < value and value < self.hi: 139 return 140 else: 141 message = "Unmatched condition: %s < %s < %s (%s.%s)" 142 else: 143 if self.lo <= value and value <= self.hi: 144 return 145 else: 146 message = "Unmatched condition: %s <= %s <= %s (%s.%s)" 147 148 tpl = ( repr(self.lo), repr(self.hi), repr(value), 149 dbobj.__class__.__name__, dbproperty.attribute_name, ) 150 raise RangeValidatorException(message % tpl, dbobj, dbproperty, value)
151
152 -class re_validator(validator):
153 """ 154 Regular expression validator. For strings and Unicode Objects 155 """
156 - def __init__(self, re):
157 if type(re) in ( StringType, UnicodeType, ): 158 self.re = re.compile(re) 159 else: 160 self.re = re
161
162 - def check(self, dbobj, dbproperty, value):
163 match = self.re.match(value) 164 165 if match is None: 166 tpl = ( repr(value), self.re.pattern, 167 dbobj.__class__.__name__, dbproperty.attribute_name, ) 168 msg = "%s does not match regular expression %s (%s.%s)" % tpl 169 raise ReValidatorException(msg, dbobj, dbproperty, self.re, value)
170 171 172 # some usefull validators for standard situations ######################### 173 174 175 # regular expressions that may proof usefull 176 domain_name_re = re.compile("([0-9a-z]([0-9a-z-]*[0-9a-z])?\.)+[a-z]{2,4}") 177 local_part_re = re.compile(r"[-a-z0-9_\.]+") 178 email_re = re.compile("[-a-z0-9_\.]+@([0-9a-z]([0-9a-z-]*[0-9a-z])?\.)+[a-z]{2,4}") 179
180 -class email_validator(re_validator):
181 """ 182 Check if the value is a valid e-Mail Address using a regular expression. 183 Note that the re will not match un-encoded idna Domains, but it will work 184 on Unicode strings. 185 """ 186
187 - def __init__(self):
189
190 -class fqdn_validator(re_validator):
191 """ 192 Check if the value is a valid fully qualified domain name. Note 193 that the rgex used will not match un-encoded idna Domains. 194 """ 195
196 - def __init__(self):
198
199 -class idna_fqdn_validator(fqdn_validator):
200 """ 201 Like fqdn_validator above, but for idna Domains (Unicode) 202 """
203 - def check(self, dbobj, dbproperty, value):
204 if value is None: 205 return 206 207 if type(value) != UnicodeType: 208 raise TypeError("An idna fqdn must be represented as a " + \ 209 "unicode string!") 210 211 value = value.encode("idna") 212 fqdn_validator.check(self, dbobj, dbproperty, value)
213 214
215 -class idna_email_validator(email_validator):
216 """ 217 Like email_validator above, but for idna Domains (Unicode) 218 """ 219
220 - def check(self, dbobj, dbproperty, value):
221 if value is None: 222 return 223 224 if type(value) != UnicodeType: 225 raise TypeError("An idna fqdn must be represented as a " + \ 226 "unicode string!") 227 228 parts = split(value, "@") 229 if len(parts) == 2: 230 local_part, remote_part = parts 231 232 try: 233 local_part = local_part.encode("ascii") 234 except UnicodeDecodeError: 235 msg = "The local part of an e-mail address may not contain "+\ 236 "non-ascii characters! (Even for an idna Domain!)" 237 raise ReValidatorException(msg, dbobj, dbproperty, 238 self.re, value) 239 240 remote_part = remote_part.encode("idna") 241 242 email_validator().check(dbobj, dbproperty, 243 local_part + "@" + remote_part) 244 else: 245 tpl = ( repr(value), self.re.pattern, 246 dbobj.__class__.__name__, dbproperty.attribute_name, ) 247 msg = "%s does not match regular expression %s (%s.%s)" % tpl 248 raise ReValidatorException(msg, dbobj, dbproperty, self.re, value)
249 250 251 252 # Local variables: 253 # mode: python 254 # ispell-local-dictionary: "english" 255 # End: 256