~ubuntu-branches/ubuntu/precise/python-django/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/genericipaddressfield.diff/django/core/validators.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez, Julian Edwards
  • Date: 2012-11-20 16:00:41 UTC
  • Revision ID: package-import@ubuntu.com-20121120160041-140ztibl9h0omz79
Tags: 1.3.1-4ubuntu1.5
[ Julian Edwards ]
* debian/patches:
  - genericipaddressfield.diff: Backport GenericIPAddressField
    from 1.4 (LP: #1081391)
  - prefetch_related.diff: Backport prefetch_related from 1.4 (LP: #1081388)
  - bug15496-base64-multipart-fix.diff: Include fix for upstream bug #15496
    which makes 'Content-Transfer-Encoding: base64: work for multipart
    messages. (LP: #1081392)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import platform
 
2
import re
 
3
import urllib2
 
4
import urlparse
 
5
 
 
6
from django.core.exceptions import ValidationError
 
7
from django.utils.translation import ugettext_lazy as _
 
8
from django.utils.encoding import smart_unicode
 
9
 
 
10
# These values, if given to validate(), will trigger the self.required check.
 
11
EMPTY_VALUES = (None, '', [], (), {})
 
12
 
 
13
try:
 
14
    from django.conf import settings
 
15
    URL_VALIDATOR_USER_AGENT = settings.URL_VALIDATOR_USER_AGENT
 
16
except ImportError:
 
17
    # It's OK if Django settings aren't configured.
 
18
    URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)'
 
19
 
 
20
class RegexValidator(object):
 
21
    regex = ''
 
22
    message = _(u'Enter a valid value.')
 
23
    code = 'invalid'
 
24
 
 
25
    def __init__(self, regex=None, message=None, code=None):
 
26
        if regex is not None:
 
27
            self.regex = regex
 
28
        if message is not None:
 
29
            self.message = message
 
30
        if code is not None:
 
31
            self.code = code
 
32
 
 
33
        if isinstance(self.regex, basestring):
 
34
            self.regex = re.compile(regex)
 
35
 
 
36
    def __call__(self, value):
 
37
        """
 
38
        Validates that the input matches the regular expression.
 
39
        """
 
40
        if not self.regex.search(smart_unicode(value)):
 
41
            raise ValidationError(self.message, code=self.code)
 
42
 
 
43
class URLValidator(RegexValidator):
 
44
    regex = re.compile(
 
45
        r'^(?:http|ftp)s?://' # http:// or https://
 
46
        r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' #domain...
 
47
        r'localhost|' #localhost...
 
48
        r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
 
49
        r'(?::\d+)?' # optional port
 
50
        r'(?:/?|[/?]\S+)$', re.IGNORECASE)
 
51
 
 
52
    def __init__(self, verify_exists=False,
 
53
                 validator_user_agent=URL_VALIDATOR_USER_AGENT):
 
54
        super(URLValidator, self).__init__()
 
55
        self.verify_exists = verify_exists
 
56
        self.user_agent = validator_user_agent
 
57
 
 
58
    def __call__(self, value):
 
59
        try:
 
60
            super(URLValidator, self).__call__(value)
 
61
        except ValidationError, e:
 
62
            # Trivial case failed. Try for possible IDN domain
 
63
            if value:
 
64
                value = smart_unicode(value)
 
65
                scheme, netloc, path, query, fragment = urlparse.urlsplit(value)
 
66
                try:
 
67
                    netloc = netloc.encode('idna') # IDN -> ACE
 
68
                except UnicodeError: # invalid domain part
 
69
                    raise e
 
70
                url = urlparse.urlunsplit((scheme, netloc, path, query, fragment))
 
71
                super(URLValidator, self).__call__(url)
 
72
            else:
 
73
                raise
 
74
        else:
 
75
            url = value
 
76
 
 
77
        #This is deprecated and will be removed in a future release.
 
78
        if self.verify_exists:
 
79
            headers = {
 
80
                "Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
 
81
                "Accept-Language": "en-us,en;q=0.5",
 
82
                "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
 
83
                "Connection": "close",
 
84
                "User-Agent": self.user_agent,
 
85
            }
 
86
            url = url.encode('utf-8')
 
87
            broken_error = ValidationError(
 
88
                _(u'This URL appears to be a broken link.'), code='invalid_link')
 
89
            try:
 
90
                req = urllib2.Request(url, None, headers)
 
91
                req.get_method = lambda: 'HEAD'
 
92
                #Create an opener that does not support local file access
 
93
                opener = urllib2.OpenerDirector()
 
94
 
 
95
                #Don't follow redirects, but don't treat them as errors either
 
96
                error_nop = lambda *args, **kwargs: True
 
97
                http_error_processor = urllib2.HTTPErrorProcessor()
 
98
                http_error_processor.http_error_301 = error_nop
 
99
                http_error_processor.http_error_302 = error_nop
 
100
                http_error_processor.http_error_307 = error_nop
 
101
 
 
102
                handlers = [urllib2.UnknownHandler(),
 
103
                            urllib2.HTTPHandler(),
 
104
                            urllib2.HTTPDefaultErrorHandler(),
 
105
                            urllib2.FTPHandler(),
 
106
                            http_error_processor]
 
107
                try:
 
108
                    import ssl
 
109
                    handlers.append(urllib2.HTTPSHandler())
 
110
                except:
 
111
                    #Python isn't compiled with SSL support
 
112
                    pass
 
113
                map(opener.add_handler, handlers)
 
114
                if platform.python_version_tuple() >= (2, 6):
 
115
                    opener.open(req, timeout=10)
 
116
                else:
 
117
                    opener.open(req)
 
118
            except ValueError:
 
119
                raise ValidationError(_(u'Enter a valid URL.'), code='invalid')
 
120
            except: # urllib2.URLError, httplib.InvalidURL, etc.
 
121
                raise broken_error
 
122
 
 
123
 
 
124
def validate_integer(value):
 
125
    try:
 
126
        int(value)
 
127
    except (ValueError, TypeError), e:
 
128
        raise ValidationError('')
 
129
 
 
130
class EmailValidator(RegexValidator):
 
131
 
 
132
    def __call__(self, value):
 
133
        try:
 
134
            super(EmailValidator, self).__call__(value)
 
135
        except ValidationError, e:
 
136
            # Trivial case failed. Try for possible IDN domain-part
 
137
            if value and u'@' in value:
 
138
                parts = value.split(u'@')
 
139
                domain_part = parts[-1]
 
140
                try:
 
141
                    parts[-1] = parts[-1].encode('idna')
 
142
                except UnicodeError:
 
143
                    raise e
 
144
                super(EmailValidator, self).__call__(u'@'.join(parts))
 
145
            else:
 
146
                raise
 
147
 
 
148
email_re = re.compile(
 
149
    r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
 
150
    r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
 
151
    r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', re.IGNORECASE)  # domain
 
152
validate_email = EmailValidator(email_re, _(u'Enter a valid e-mail address.'), 'invalid')
 
153
 
 
154
slug_re = re.compile(r'^[-\w]+$')
 
155
validate_slug = RegexValidator(slug_re, _(u"Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."), 'invalid')
 
156
 
 
157
ipv4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')
 
158
validate_ipv4_address = RegexValidator(ipv4_re, _(u'Enter a valid IPv4 address.'), 'invalid')
 
159
 
 
160
comma_separated_int_list_re = re.compile('^[\d,]+$')
 
161
validate_comma_separated_integer_list = RegexValidator(comma_separated_int_list_re, _(u'Enter only digits separated by commas.'), 'invalid')
 
162
 
 
163
 
 
164
class BaseValidator(object):
 
165
    compare = lambda self, a, b: a is not b
 
166
    clean   = lambda self, x: x
 
167
    message = _(u'Ensure this value is %(limit_value)s (it is %(show_value)s).')
 
168
    code = 'limit_value'
 
169
 
 
170
    def __init__(self, limit_value):
 
171
        self.limit_value = limit_value
 
172
 
 
173
    def __call__(self, value):
 
174
        cleaned = self.clean(value)
 
175
        params = {'limit_value': self.limit_value, 'show_value': cleaned}
 
176
        if self.compare(cleaned, self.limit_value):
 
177
            raise ValidationError(
 
178
                self.message % params,
 
179
                code=self.code,
 
180
                params=params,
 
181
            )
 
182
 
 
183
class MaxValueValidator(BaseValidator):
 
184
    compare = lambda self, a, b: a > b
 
185
    message = _(u'Ensure this value is less than or equal to %(limit_value)s.')
 
186
    code = 'max_value'
 
187
 
 
188
class MinValueValidator(BaseValidator):
 
189
    compare = lambda self, a, b: a < b
 
190
    message = _(u'Ensure this value is greater than or equal to %(limit_value)s.')
 
191
    code = 'min_value'
 
192
 
 
193
class MinLengthValidator(BaseValidator):
 
194
    compare = lambda self, a, b: a < b
 
195
    clean   = lambda self, x: len(x)
 
196
    message = _(u'Ensure this value has at least %(limit_value)d characters (it has %(show_value)d).')
 
197
    code = 'min_length'
 
198
 
 
199
class MaxLengthValidator(BaseValidator):
 
200
    compare = lambda self, a, b: a > b
 
201
    clean   = lambda self, x: len(x)
 
202
    message = _(u'Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).')
 
203
    code = 'max_length'
 
204