From 62ba18d7506693592e45fff47eb81be467818de5 Mon Sep 17 00:00:00 2001 From: Boulder Sprinters Date: Mon, 23 Apr 2007 16:16:27 +0000 Subject: [PATCH] boulder-oracle-sprint: Merged to [5061] git-svn-id: http://code.djangoproject.com/svn/django/branches/boulder-oracle-sprint@5062 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- AUTHORS | 3 ++ django/contrib/auth/models.py | 2 +- django/newforms/fields.py | 8 ++-- django/template/defaultfilters.py | 10 ++--- django/template/defaulttags.py | 9 +++-- django/utils/datastructures.py | 2 +- django/views/debug.py | 50 ++++++++++++++++-------- docs/distributions.txt | 10 +++-- docs/generic_views.txt | 2 +- tests/regressiontests/templates/tests.py | 4 ++ 10 files changed, 65 insertions(+), 35 deletions(-) diff --git a/AUTHORS b/AUTHORS index 7fa7981aab..35f865c962 100644 --- a/AUTHORS +++ b/AUTHORS @@ -78,6 +78,7 @@ answer newbie questions, and generally made Django that much better: Jason Davies (Esaj) Alex Dedul deric@monowerks.com + Max Derkachev dne@mayonnaise.net Maximillian Dornseif Jeremy Dunck @@ -113,6 +114,7 @@ answer newbie questions, and generally made Django that much better: Tom Insam Baurzhan Ismagulov jcrasta@gmail.com + Zak Johnson Michael Josephson jpellerin@gmail.com junzhang.jn@gmail.com @@ -180,6 +182,7 @@ answer newbie questions, and generally made Django that much better: Brian Ray remco@diji.biz rhettg@gmail.com + Armin Ronacher Oliver Rutherfurd Ivan Sagalaev (Maniac) David Schein diff --git a/django/contrib/auth/models.py b/django/contrib/auth/models.py index f686d90e7a..6fe781a041 100644 --- a/django/contrib/auth/models.py +++ b/django/contrib/auth/models.py @@ -273,7 +273,7 @@ class AnonymousUser(object): pass def __str__(self): - return 'AnonymousUser' + return _('AnonymousUser') def __eq__(self, other): return isinstance(other, self.__class__) diff --git a/django/newforms/fields.py b/django/newforms/fields.py index c3b74e93f7..7c542b9001 100644 --- a/django/newforms/fields.py +++ b/django/newforms/fields.py @@ -332,7 +332,9 @@ class NullBooleanField(BooleanField): return {True: True, False: False}.get(value, None) class ChoiceField(Field): - def __init__(self, choices=(), required=True, widget=Select, label=None, initial=None, help_text=None): + widget = Select + + def __init__(self, choices=(), required=True, widget=None, label=None, initial=None, help_text=None): super(ChoiceField, self).__init__(required, widget, label, initial, help_text) self.choices = choices @@ -364,9 +366,7 @@ class ChoiceField(Field): class MultipleChoiceField(ChoiceField): hidden_widget = MultipleHiddenInput - - def __init__(self, choices=(), required=True, widget=SelectMultiple, label=None, initial=None, help_text=None): - super(MultipleChoiceField, self).__init__(choices, required, widget, label, initial, help_text) + widget = SelectMultiple def clean(self, value): """ diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py index a025365c90..bbaceba24a 100644 --- a/django/template/defaultfilters.py +++ b/django/template/defaultfilters.py @@ -2,7 +2,7 @@ from django.template import resolve_variable, Library from django.conf import settings -from django.utils.translation import gettext +from django.utils.translation import gettext, ngettext import re import random as random_module @@ -517,12 +517,12 @@ def filesizeformat(bytes): return "0 bytes" if bytes < 1024: - return "%d byte%s" % (bytes, bytes != 1 and 's' or '') + return ngettext("%(size)d byte", "%(size)d bytes", bytes) % {'size': bytes} if bytes < 1024 * 1024: - return "%.1f KB" % (bytes / 1024) + return gettext("%.1f KB") % (bytes / 1024) if bytes < 1024 * 1024 * 1024: - return "%.1f MB" % (bytes / (1024 * 1024)) - return "%.1f GB" % (bytes / (1024 * 1024 * 1024)) + return gettext("%.1f MB") % (bytes / (1024 * 1024)) + return gettext("%.1f GB") % (bytes / (1024 * 1024 * 1024)) def pluralize(value, arg='s'): """ diff --git a/django/template/defaulttags.py b/django/template/defaulttags.py index 448ad8a50b..d997d20077 100644 --- a/django/template/defaulttags.py +++ b/django/template/defaulttags.py @@ -41,7 +41,10 @@ class FilterNode(Node): def render(self, context): output = self.nodelist.render(context) # apply filters - return self.filter_expr.resolve(Context({'var': output})) + context.update({'var': output}) + filtered = self.filter_expr.resolve(context) + context.pop() + return filtered class FirstOfNode(Node): def __init__(self, vars): @@ -990,7 +993,7 @@ def do_with(parser, token): """ Add a value to the context (inside of this block) for caching and easy access. - + For example:: {% with person.some_sql_method as total %} @@ -999,7 +1002,7 @@ def do_with(parser, token): """ bits = list(token.split_contents()) if len(bits) != 4 or bits[2] != "as": - raise TemplateSyntaxError, "%r expected format is 'value as name'" % tagname + raise TemplateSyntaxError, "%r expected format is 'value as name'" % bits[0] var = parser.compile_filter(bits[1]) name = bits[3] nodelist = parser.parse(('endwith',)) diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py index 7b7fa2b0f0..dbf8660c75 100644 --- a/django/utils/datastructures.py +++ b/django/utils/datastructures.py @@ -211,7 +211,7 @@ class MultiValueDict(dict): def update(self, *args, **kwargs): "update() extends rather than replaces existing key lists. Also accepts keyword args." if len(args) > 1: - raise TypeError, "update expected at most 1 arguments, got %d", len(args) + raise TypeError, "update expected at most 1 arguments, got %d" % len(args) if args: other_dict = args[0] if isinstance(other_dict, MultiValueDict): diff --git a/django/views/debug.py b/django/views/debug.py index b49a98a864..2530350e26 100644 --- a/django/views/debug.py +++ b/django/views/debug.py @@ -90,11 +90,18 @@ def technical_500_response(request, exc_type, exc_value, tb): exc_type, exc_value, tb, template_info = get_template_exception_info(exc_type, exc_value, tb) frames = [] while tb is not None: + # support for __traceback_hide__ which is used by a few libraries + # to hide internal frames. + if tb.tb_frame.f_locals.get('__traceback_hide__'): + tb = tb.tb_next + continue filename = tb.tb_frame.f_code.co_filename function = tb.tb_frame.f_code.co_name lineno = tb.tb_lineno - 1 - pre_context_lineno, pre_context, context_line, post_context = _get_lines_from_file(filename, lineno, 7) - if pre_context_lineno: + loader = tb.tb_frame.f_globals.get('__loader__') + module_name = tb.tb_frame.f_globals.get('__name__') + pre_context_lineno, pre_context, context_line, post_context = _get_lines_from_file(filename, lineno, 7, loader, module_name) + if pre_context_lineno is not None: frames.append({ 'tb': tb, 'filename': filename, @@ -161,24 +168,35 @@ def empty_urlconf(request): }) return HttpResponseNotFound(t.render(c), mimetype='text/html') -def _get_lines_from_file(filename, lineno, context_lines): +def _get_lines_from_file(filename, lineno, context_lines, loader=None, module_name=None): """ Returns context_lines before and after lineno from file. Returns (pre_context_lineno, pre_context, context_line, post_context). """ - try: - source = open(filename).readlines() - lower_bound = max(0, lineno - context_lines) - upper_bound = lineno + context_lines - - pre_context = [line.strip('\n') for line in source[lower_bound:lineno]] - context_line = source[lineno].strip('\n') - post_context = [line.strip('\n') for line in source[lineno+1:upper_bound]] - - return lower_bound, pre_context, context_line, post_context - except (OSError, IOError): + source = None + if loader is not None: + source = loader.get_source(module_name).splitlines() + else: + try: + f = open(filename) + try: + source = f.readlines() + finally: + f.close() + except (OSError, IOError): + pass + if source is None: return None, [], None, [] + lower_bound = max(0, lineno - context_lines) + upper_bound = lineno + context_lines + + pre_context = [line.strip('\n') for line in source[lower_bound:lineno]] + context_line = source[lineno].strip('\n') + post_context = [line.strip('\n') for line in source[lineno+1:upper_bound]] + + return lower_bound, pre_context, context_line, post_context + # # Templates are embedded in the file so that we know the error handler will # always work even if the template loader is broken. @@ -314,7 +332,7 @@ TECHNICAL_500_TEMPLATE = """ Exception Location: - {{ lastframe.filename }} in {{ lastframe.function }}, line {{ lastframe.lineno }} + {{ lastframe.filename|escape }} in {{ lastframe.function|escape }}, line {{ lastframe.lineno }} @@ -361,7 +379,7 @@ TECHNICAL_500_TEMPLATE = """
    {% for frame in frames %}
  • - {{ frame.filename }} in {{ frame.function }} + {{ frame.filename|escape }} in {{ frame.function|escape }} {% if frame.context_line %}
    diff --git a/docs/distributions.txt b/docs/distributions.txt index 63206c535e..4ec265f93c 100644 --- a/docs/distributions.txt +++ b/docs/distributions.txt @@ -47,16 +47,18 @@ Fedora ------ A Django package is available for `Fedora Linux`_, in the "Fedora Extras" -repository. The `current Fedora package`_ is based on Django 0.95.1, and can be -installed by typing ``yum install Django``. +repository. The `current Fedora package`_ is based on Django 0.96, and can be +installed by typing ``yum install Django``. The previous link is for the i386 +binary. Users of other architectures should be able to use that as a starting +point to find their preferred version. .. _Fedora Linux: http://fedora.redhat.com/ -.. _current Fedora package: http://fedoraproject.org/extras/6/i386/repodata/repoview/Django-0-0.95.1-1.fc6.html +.. _current Fedora package: http://download.fedora.redhat.com/pub/fedora/linux/extras/6/i386/repoview/Django.html Gentoo ------ -A Django build is available for `Gentoo Linux`_, and is based on Django 0.95.1. +A Django build is available for `Gentoo Linux`_, and is based on Django 0.96. The `current Gentoo build`_ can be installed by typing ``emerge django``. .. _Gentoo Linux: http://www.gentoo.org/ diff --git a/docs/generic_views.txt b/docs/generic_views.txt index 0496a58691..5f7a669652 100644 --- a/docs/generic_views.txt +++ b/docs/generic_views.txt @@ -44,7 +44,7 @@ simple weblog app that drives the blog on djangoproject.com:: (r'^(?P\d{4})/(?P[a-z]{3})/(?P\w{1,2})/$', 'archive_day', info_dict), (r'^(?P\d{4})/(?P[a-z]{3})/$', 'archive_month', info_dict), (r'^(?P\d{4})/$', 'archive_year', info_dict), - (r'^/?$', 'archive_index', info_dict), + (r'^$', 'archive_index', info_dict), ) As you can see, this URLconf defines a few options in ``info_dict``. diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index b544207be8..93fb1ecb4d 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -259,6 +259,7 @@ class Templates(unittest.TestCase): 'filter01': ('{% filter upper %}{% endfilter %}', {}, ''), 'filter02': ('{% filter upper %}django{% endfilter %}', {}, 'DJANGO'), 'filter03': ('{% filter upper|lower %}django{% endfilter %}', {}, 'django'), + 'filter04': ('{% filter cut:remove %}djangospam{% endfilter %}', {'remove': 'spam'}, 'django'), ### FIRSTOF TAG ########################################################### 'firstof01': ('{% firstof a b c %}', {'a':0,'b':0,'c':0}, ''), @@ -654,6 +655,9 @@ class Templates(unittest.TestCase): 'with01': ('{% with dict.key as key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, '50'), 'with02': ('{{ key }}{% with dict.key as key %}{{ key }}-{{ dict.key }}-{{ key }}{% endwith %}{{ key }}', {'dict': {'key':50}}, ('50-50-50', 'INVALID50-50-50INVALID')), + 'with-error01': ('{% with dict.key xx key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, template.TemplateSyntaxError), + 'with-error02': ('{% with dict.key as %}{{ key }}{% endwith %}', {'dict': {'key':50}}, template.TemplateSyntaxError), + ### NOW TAG ######################################################## # Simple case 'now01' : ('{% now "j n Y"%}', {}, str(datetime.now().day) + ' ' + str(datetime.now().month) + ' ' + str(datetime.now().year)),