diff options
| author | Joseph Kocherhans <joseph@jkocherhans.com> | 2006-05-16 20:39:14 +0000 |
|---|---|---|
| committer | Joseph Kocherhans <joseph@jkocherhans.com> | 2006-05-16 20:39:14 +0000 |
| commit | e1184016a29b90694e3624d646b35b9d4aa4756e (patch) | |
| tree | f15b0c5f1ccd0f22b132b97403304263da579fb9 /django/core | |
| parent | 93937ed38a828e0f252fb25614516593ec7b9ab0 (diff) | |
multi-auth: Merged to [2919]
git-svn-id: http://code.djangoproject.com/svn/django/branches/multi-auth@2921 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/core')
| -rw-r--r-- | django/core/mail.py | 5 | ||||
| -rw-r--r-- | django/core/urlresolvers.py | 78 |
2 files changed, 82 insertions, 1 deletions
diff --git a/django/core/mail.py b/django/core/mail.py index 3baf191b5c..415cb6e8fc 100644 --- a/django/core/mail.py +++ b/django/core/mail.py @@ -2,6 +2,7 @@ from django.conf import settings from email.MIMEText import MIMEText +from email.Header import Header import smtplib class BadHeaderError(ValueError): @@ -12,6 +13,8 @@ class SafeMIMEText(MIMEText): "Forbids multi-line headers, to prevent header injection." if '\n' in val or '\r' in val: raise BadHeaderError, "Header values can't contain newlines (got %r for header %r)" % (val, name) + if name == "Subject": + val = Header(val, settings.DEFAULT_CHARSET) MIMEText.__setitem__(self, name, val) def send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=settings.EMAIL_HOST_USER, auth_password=settings.EMAIL_HOST_PASSWORD): @@ -42,7 +45,7 @@ def send_mass_mail(datatuple, fail_silently=False, auth_user=settings.EMAIL_HOST if not recipient_list: continue from_email = from_email or settings.DEFAULT_FROM_EMAIL - msg = SafeMIMEText(message) + msg = SafeMIMEText(message, 'plain', settings.DEFAULT_CHARSET) msg['Subject'] = subject msg['From'] = from_email msg['To'] = ', '.join(recipient_list) diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py index e11b63e977..db4967e1c5 100644 --- a/django/core/urlresolvers.py +++ b/django/core/urlresolvers.py @@ -14,12 +14,56 @@ import re class Resolver404(Http404): pass +class NoReverseMatch(Exception): + pass + def get_mod_func(callback): # Converts 'django.views.news.stories.story_detail' to # ['django.views.news.stories', 'story_detail'] dot = callback.rindex('.') return callback[:dot], callback[dot+1:] +class MatchChecker(object): + "Class used in reverse RegexURLPattern lookup." + def __init__(self, args, kwargs): + self.args, self.kwargs = args, kwargs + self.current_arg = 0 + + def __call__(self, match_obj): + # match_obj.group(1) is the contents of the parenthesis. + # First we need to figure out whether it's a named or unnamed group. + # + grouped = match_obj.group(1) + m = re.search(r'^\?P<(\w+)>(.*?)$', grouped) + if m: # If this was a named group... + # m.group(1) is the name of the group + # m.group(2) is the regex. + try: + value = self.kwargs[m.group(1)] + except KeyError: + # It was a named group, but the arg was passed in as a + # positional arg or not at all. + try: + value = self.args[self.current_arg] + self.current_arg += 1 + except IndexError: + # The arg wasn't passed in. + raise NoReverseMatch('Not enough positional arguments passed in') + test_regex = m.group(2) + else: # Otherwise, this was a positional (unnamed) group. + try: + value = self.args[self.current_arg] + self.current_arg += 1 + except IndexError: + # The arg wasn't passed in. + raise NoReverseMatch('Not enough positional arguments passed in') + test_regex = grouped + # Note we're using re.match here on purpose because the start of + # to string needs to match. + if not re.match(test_regex + '$', str(value)): # TODO: Unicode? + raise NoReverseMatch("Value %r didn't match regular expression %r" % (value, test_regex)) + return str(value) # TODO: Unicode? + class RegexURLPattern: def __init__(self, regex, callback, default_args=None): # regex is a string representing a regular expression. @@ -58,12 +102,37 @@ class RegexURLPattern: except AttributeError, e: raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e)) + def reverse(self, viewname, *args, **kwargs): + if viewname != self.callback: + raise NoReverseMatch + return self.reverse_helper(*args, **kwargs) + + def reverse_helper(self, *args, **kwargs): + """ + Does a "reverse" lookup -- returns the URL for the given args/kwargs. + The args/kwargs are applied to the regular expression in this + RegexURLPattern. For example: + + >>> RegexURLPattern('^places/(\d+)/$').reverse_helper(3) + 'places/3/' + >>> RegexURLPattern('^places/(?P<id>\d+)/$').reverse_helper(id=3) + 'places/3/' + >>> RegexURLPattern('^people/(?P<state>\w\w)/(\w+)/$').reverse_helper('adrian', state='il') + 'people/il/adrian/' + + Raises NoReverseMatch if the args/kwargs aren't valid for the RegexURLPattern. + """ + # TODO: Handle nested parenthesis in the following regex. + result = re.sub(r'\(([^)]+)\)', MatchChecker(args, kwargs), self.regex.pattern) + return result.replace('^', '').replace('$', '') + class RegexURLResolver(object): def __init__(self, regex, urlconf_name): # regex is a string representing a regular expression. # urlconf_name is a string representing the module containing urlconfs. self.regex = re.compile(regex) self.urlconf_name = urlconf_name + self.callback = None def resolve(self, path): tried = [] @@ -110,3 +179,12 @@ class RegexURLResolver(object): def resolve500(self): return self._resolve_special('500') + + def reverse(self, viewname, *args, **kwargs): + for pattern in self.urlconf_module.urlpatterns: + if pattern.callback == viewname: + try: + return pattern.reverse_helper(*args, **kwargs) + except NoReverseMatch: + continue + raise NoReverseMatch |
