summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Bronn <jbronn@gmail.com>2007-10-16 16:54:23 +0000
committerJustin Bronn <jbronn@gmail.com>2007-10-16 16:54:23 +0000
commit58fc7897653b0a64658b3ece5d0ff429b4636130 (patch)
tree95ed4b510620ad3740b16cdff1395b4f10dbaee4
parentba9fa9844c7996bf1362b9769c2c2fecf760a039 (diff)
Merged revisions 6442-6524 via svnmerge from [repos:django/trunk trunk].
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@6525 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--AUTHORS2
-rwxr-xr-xdjango/bin/compile-messages.py3
-rwxr-xr-xdjango/bin/make-messages.py95
-rw-r--r--django/conf/locale/de/LC_MESSAGES/django.mobin44119 -> 44534 bytes
-rw-r--r--django/conf/locale/de/LC_MESSAGES/django.po59
-rw-r--r--django/core/handlers/modpython.py2
-rw-r--r--django/core/handlers/wsgi.py2
-rw-r--r--django/core/management/__init__.py2
-rw-r--r--django/core/management/base.py27
-rw-r--r--django/core/management/color.py10
-rw-r--r--django/core/management/commands/runserver.py2
-rw-r--r--django/core/management/commands/startapp.py2
-rw-r--r--django/db/backends/postgresql/operations.py2
-rw-r--r--django/db/models/fields/__init__.py2
-rw-r--r--django/http/__init__.py5
-rw-r--r--django/newforms/widgets.py18
-rw-r--r--django/oldforms/__init__.py4
-rw-r--r--django/utils/datastructures.py5
-rw-r--r--django/utils/translation/__init__.py14
-rw-r--r--django/utils/translation/trans_null.py1
-rw-r--r--django/utils/translation/trans_real.py6
-rw-r--r--django/views/static.py16
-rw-r--r--docs/databases.txt6
-rw-r--r--docs/i18n.txt9
-rw-r--r--docs/newforms.txt4
-rw-r--r--docs/request_response.txt4
-rw-r--r--docs/templates_python.txt2
-rw-r--r--docs/unicode.txt30
-rw-r--r--tests/modeltests/basic/models.py2
-rw-r--r--tests/modeltests/field_defaults/models.py2
-rw-r--r--tests/regressiontests/datastructures/tests.py8
-rw-r--r--tests/regressiontests/i18n/models.py12
-rw-r--r--tests/regressiontests/i18n/tests.py8
33 files changed, 214 insertions, 152 deletions
diff --git a/AUTHORS b/AUTHORS
index a6926b37b2..5af5c71f6e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -313,7 +313,7 @@ answer newbie questions, and generally made Django that much better:
Vlado <vlado@labath.org>
Milton Waddams
wam-djangobug@wamber.net
- wangchun <yaohua2000@gmail.com>
+ Wang Chun <wangchun@exoweb.net>
Filip Wasilewski <filip.wasilewski@gmail.com>
Dan Watson <http://theidioteque.net/>
Chris Wesseling <Chris.Wesseling@cwi.nl>
diff --git a/django/bin/compile-messages.py b/django/bin/compile-messages.py
index 2838cb8aa4..8693022644 100755
--- a/django/bin/compile-messages.py
+++ b/django/bin/compile-messages.py
@@ -14,7 +14,8 @@ def compile_messages(locale=None):
basedirs = [os.path.join('conf', 'locale'), 'locale']
if os.environ.get('DJANGO_SETTINGS_MODULE'):
from django.conf import settings
- basedirs += settings.LOCALE_PATHS
+ if hasattr(settings, 'LOCALE_PATHS'):
+ basedirs += settings.LOCALE_PATHS
# Gather existing directories.
basedirs = set(map(os.path.abspath, filter(os.path.isdir, basedirs)))
diff --git a/django/bin/make-messages.py b/django/bin/make-messages.py
index 11616c9ca5..44040390ea 100755
--- a/django/bin/make-messages.py
+++ b/django/bin/make-messages.py
@@ -74,59 +74,62 @@ def make_messages():
if os.path.exists(potfile):
os.unlink(potfile)
+ all_files = []
for (dirpath, dirnames, filenames) in os.walk("."):
- for file in filenames:
- if domain == 'djangojs' and file.endswith('.js'):
- if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
+ all_files.extend([(dirpath, f) for f in filenames])
+ all_files.sort()
+ for dirpath, file in all_files:
+ if domain == 'djangojs' and file.endswith('.js'):
+ if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
+ src = open(os.path.join(dirpath, file), "rb").read()
+ src = pythonize_re.sub('\n#', src)
+ open(os.path.join(dirpath, '%s.py' % file), "wb").write(src)
+ thefile = '%s.py' % file
+ cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
+ os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
+ (stdin, stdout, stderr) = os.popen3(cmd, 't')
+ msgs = stdout.read()
+ errors = stderr.read()
+ if errors:
+ print "errors happened while running xgettext on %s" % file
+ print errors
+ sys.exit(8)
+ old = '#: '+os.path.join(dirpath, thefile)[2:]
+ new = '#: '+os.path.join(dirpath, file)[2:]
+ msgs = msgs.replace(old, new)
+ if msgs:
+ open(potfile, 'ab').write(msgs)
+ os.unlink(os.path.join(dirpath, thefile))
+ elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')):
+ thefile = file
+ if file.endswith('.html'):
src = open(os.path.join(dirpath, file), "rb").read()
- src = pythonize_re.sub('\n#', src)
- open(os.path.join(dirpath, '%s.py' % file), "wb").write(src)
thefile = '%s.py' % file
- cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
- os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
- (stdin, stdout, stderr) = os.popen3(cmd, 't')
- msgs = stdout.read()
- errors = stderr.read()
- if errors:
- print "errors happened while running xgettext on %s" % file
- print errors
- sys.exit(8)
+ open(os.path.join(dirpath, thefile), "wb").write(templatize(src))
+ if verbose:
+ sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
+ cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
+ domain, os.path.join(dirpath, thefile))
+ (stdin, stdout, stderr) = os.popen3(cmd, 't')
+ msgs = stdout.read()
+ errors = stderr.read()
+ if errors:
+ print "errors happened while running xgettext on %s" % file
+ print errors
+ sys.exit(8)
+ if thefile != file:
old = '#: '+os.path.join(dirpath, thefile)[2:]
new = '#: '+os.path.join(dirpath, file)[2:]
msgs = msgs.replace(old, new)
- if msgs:
- open(potfile, 'ab').write(msgs)
+ if os.path.exists(potfile):
+ # Strip the header
+ msgs = '\n'.join(dropwhile(len, msgs.split('\n')))
+ else:
+ msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8')
+ if msgs:
+ open(potfile, 'ab').write(msgs)
+ if thefile != file:
os.unlink(os.path.join(dirpath, thefile))
- elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')):
- thefile = file
- if file.endswith('.html'):
- src = open(os.path.join(dirpath, file), "rb").read()
- thefile = '%s.py' % file
- open(os.path.join(dirpath, thefile), "wb").write(templatize(src))
- if verbose:
- sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
- cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
- domain, os.path.join(dirpath, thefile))
- (stdin, stdout, stderr) = os.popen3(cmd, 't')
- msgs = stdout.read()
- errors = stderr.read()
- if errors:
- print "errors happened while running xgettext on %s" % file
- print errors
- sys.exit(8)
- if thefile != file:
- old = '#: '+os.path.join(dirpath, thefile)[2:]
- new = '#: '+os.path.join(dirpath, file)[2:]
- msgs = msgs.replace(old, new)
- if os.path.exists(potfile):
- # Strip the header
- msgs = '\n'.join(dropwhile(len, msgs.split('\n')))
- else:
- msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8')
- if msgs:
- open(potfile, 'ab').write(msgs)
- if thefile != file:
- os.unlink(os.path.join(dirpath, thefile))
if os.path.exists(potfile):
(stdin, stdout, stderr) = os.popen3('msguniq --to-code=utf-8 "%s"' % potfile, 'b')
diff --git a/django/conf/locale/de/LC_MESSAGES/django.mo b/django/conf/locale/de/LC_MESSAGES/django.mo
index 307976e4d5..2699d25e55 100644
--- a/django/conf/locale/de/LC_MESSAGES/django.mo
+++ b/django/conf/locale/de/LC_MESSAGES/django.mo
Binary files differ
diff --git a/django/conf/locale/de/LC_MESSAGES/django.po b/django/conf/locale/de/LC_MESSAGES/django.po
index 6978cf2d44..50fa66d43f 100644
--- a/django/conf/locale/de/LC_MESSAGES/django.po
+++ b/django/conf/locale/de/LC_MESSAGES/django.po
@@ -1,6 +1,7 @@
-# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-# This file is distributed under the same license as the PACKAGE package.
-# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# Translation of django.po to German
+#
+# Copyright (C) 2005-2007,
+# This file is distributed under the same license as the django package.
#
msgid ""
""
@@ -1629,76 +1630,76 @@ msgstr "Webseite"
msgid "flat pages"
msgstr "Webseiten"
-#: contrib/humanize/templatetags/humanize.py:17
+#: contrib/humanize/templatetags/humanize.py:20
msgid "th"
-msgstr ""
+msgstr "."
-#: contrib/humanize/templatetags/humanize.py:17
+#: contrib/humanize/templatetags/humanize.py:20
msgid "st"
-msgstr ""
+msgstr "."
-#: contrib/humanize/templatetags/humanize.py:17
+#: contrib/humanize/templatetags/humanize.py:20
msgid "nd"
-msgstr ""
+msgstr "."
-#: contrib/humanize/templatetags/humanize.py:17
+#: contrib/humanize/templatetags/humanize.py:20
msgid "rd"
-msgstr ""
+msgstr "."
-#: contrib/humanize/templatetags/humanize.py:47
+#: contrib/humanize/templatetags/humanize.py:50
#, python-format
msgid "%(value).1f million"
msgid_plural "%(value).1f million"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%(value).1f Million"
+msgstr[1] "%(value).1f Millionen"
-#: contrib/humanize/templatetags/humanize.py:50
+#: contrib/humanize/templatetags/humanize.py:53
#, python-format
msgid "%(value).1f billion"
msgid_plural "%(value).1f billion"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%(value).1f Milliarde"
+msgstr[1] "%(value).1f Milliarden"
-#: contrib/humanize/templatetags/humanize.py:53
+#: contrib/humanize/templatetags/humanize.py:56
#, python-format
msgid "%(value).1f trillion"
msgid_plural "%(value).1f trillion"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%(value).1f Billion"
+msgstr[1] "%(value).1f Billionen"
-#: contrib/humanize/templatetags/humanize.py:68
+#: contrib/humanize/templatetags/humanize.py:71
msgid "one"
msgstr "ein"
-#: contrib/humanize/templatetags/humanize.py:68
+#: contrib/humanize/templatetags/humanize.py:71
msgid "two"
msgstr "zwei"
-#: contrib/humanize/templatetags/humanize.py:68
+#: contrib/humanize/templatetags/humanize.py:71
msgid "three"
msgstr "drei"
-#: contrib/humanize/templatetags/humanize.py:68
+#: contrib/humanize/templatetags/humanize.py:71
msgid "four"
msgstr "vier"
-#: contrib/humanize/templatetags/humanize.py:68
+#: contrib/humanize/templatetags/humanize.py:71
msgid "five"
msgstr "fünf"
-#: contrib/humanize/templatetags/humanize.py:68
+#: contrib/humanize/templatetags/humanize.py:71
msgid "six"
msgstr "sechs"
-#: contrib/humanize/templatetags/humanize.py:68
+#: contrib/humanize/templatetags/humanize.py:71
msgid "seven"
msgstr "sieben"
-#: contrib/humanize/templatetags/humanize.py:68
+#: contrib/humanize/templatetags/humanize.py:71
msgid "eight"
msgstr "acht"
-#: contrib/humanize/templatetags/humanize.py:68
+#: contrib/humanize/templatetags/humanize.py:71
msgid "nine"
msgstr "neun"
diff --git a/django/core/handlers/modpython.py b/django/core/handlers/modpython.py
index d4f5e55011..52419d9e6c 100644
--- a/django/core/handlers/modpython.py
+++ b/django/core/handlers/modpython.py
@@ -14,7 +14,7 @@ import os
class ModPythonRequest(http.HttpRequest):
def __init__(self, req):
self._req = req
- self.path = force_unicode(req.uri)
+ self.path = force_unicode(req.uri, errors='ignore')
def __repr__(self):
# Since this is called as part of error handling, we need to be very
diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py
index 16d1d822e0..95c5f9cbda 100644
--- a/django/core/handlers/wsgi.py
+++ b/django/core/handlers/wsgi.py
@@ -75,7 +75,7 @@ def safe_copyfileobj(fsrc, fdst, length=16*1024, size=0):
class WSGIRequest(http.HttpRequest):
def __init__(self, environ):
self.environ = environ
- self.path = force_unicode(environ['PATH_INFO'])
+ self.path = force_unicode(environ['PATH_INFO'], errors='ignore')
self.META = environ
self.method = environ['REQUEST_METHOD'].upper()
diff --git a/django/core/management/__init__.py b/django/core/management/__init__.py
index e15dfccdf2..cd90fd6109 100644
--- a/django/core/management/__init__.py
+++ b/django/core/management/__init__.py
@@ -239,7 +239,7 @@ def setup_environ(settings_mod):
project_directory, settings_filename = os.path.split(settings_mod.__file__)
project_name = os.path.basename(project_directory)
settings_name = os.path.splitext(settings_filename)[0]
- sys.path.append(os.path.join(project_directory, '..'))
+ sys.path.append(os.path.join(project_directory, os.pardir))
project_module = __import__(project_name, {}, {}, [''])
sys.path.pop()
diff --git a/django/core/management/base.py b/django/core/management/base.py
index 26ecef4ff5..0c458126e8 100644
--- a/django/core/management/base.py
+++ b/django/core/management/base.py
@@ -1,10 +1,10 @@
+import os
+import sys
+from optparse import make_option, OptionParser
+
import django
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style
-import itertools
-from optparse import make_option, OptionParser
-import sys
-import os
class CommandError(Exception):
pass
@@ -19,7 +19,7 @@ def handle_default_options(options):
os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
if options.pythonpath:
sys.path.insert(0, options.pythonpath)
-
+
class BaseCommand(object):
# Metadata about this command.
option_list = (
@@ -161,17 +161,25 @@ class NoArgsCommand(BaseCommand):
args = ''
def handle(self, *args, **options):
- from django.db import models
- if len(args) != 0:
+ if args:
raise CommandError("Command doesn't accept any arguments")
-
return self.handle_noargs(**options)
def handle_noargs(self, **options):
raise NotImplementedError()
def copy_helper(style, app_or_project, name, directory, other_name=''):
- import django
+ """
+ Copies either a Django application layout template or a Django project
+ layout template into the specified directory.
+
+ * style - A color style object (see django.core.management.color).
+ * app_or_project - The string 'app' or 'project'.
+ * name - The name of the application or project.
+ * directory - The directory to copy the layout template to.
+ * other_name - When copying an application layout, this should be the name
+ of the project.
+ """
import re
import shutil
other = {'project': 'app', 'app': 'project'}[app_or_project]
@@ -221,4 +229,3 @@ def _make_writeable(filename):
st = os.stat(filename)
new_permissions = stat.S_IMODE(st.st_mode) | stat.S_IWUSR
os.chmod(filename, new_permissions)
-
diff --git a/django/core/management/color.py b/django/core/management/color.py
index ce95401491..40fd4e7fdd 100644
--- a/django/core/management/color.py
+++ b/django/core/management/color.py
@@ -2,12 +2,14 @@
Sets up the terminal color scheme.
"""
-from django.utils import termcolors
import sys
+from django.utils import termcolors
+
def color_style():
- "Returns a Style object with the Django color scheme."
- if sys.platform == 'win32' or sys.platform == 'Pocket PC' or sys.platform.startswith('java') or not sys.stdout.isatty():
+ """Returns a Style object with the Django color scheme."""
+ if (sys.platform == 'win32' or sys.platform == 'Pocket PC'
+ or sys.platform.startswith('java') or not sys.stdout.isatty()):
return no_style()
class dummy: pass
style = dummy()
@@ -21,7 +23,7 @@ def color_style():
return style
def no_style():
- "Returns a Style object that has no colors."
+ """Returns a Style object that has no colors."""
class dummy:
def __getattr__(self, attr):
return lambda x: x
diff --git a/django/core/management/commands/runserver.py b/django/core/management/commands/runserver.py
index 5b141d03ed..12808bcaad 100644
--- a/django/core/management/commands/runserver.py
+++ b/django/core/management/commands/runserver.py
@@ -20,7 +20,7 @@ class Command(BaseCommand):
import django
from django.core.servers.basehttp import run, AdminMediaHandler, WSGIServerException
from django.core.handlers.wsgi import WSGIHandler
- if len(args) != 0:
+ if args:
raise CommandError('Usage is runserver %s' % self.args)
if not addrport:
addr = ''
diff --git a/django/core/management/commands/startapp.py b/django/core/management/commands/startapp.py
index 1da2776cf5..c238e74a08 100644
--- a/django/core/management/commands/startapp.py
+++ b/django/core/management/commands/startapp.py
@@ -16,7 +16,7 @@ class Command(LabelCommand):
directory = os.getcwd()
# Determine the project_name a bit naively -- by looking at the name of
# the parent directory.
- project_dir = os.path.normpath(os.path.join(directory, '..'))
+ project_dir = os.path.normpath(os.path.join(directory, os.pardir))
parent_dir = os.path.basename(project_dir)
project_name = os.path.basename(directory)
if app_name == project_name:
diff --git a/django/db/backends/postgresql/operations.py b/django/db/backends/postgresql/operations.py
index 9f36596ace..20392b238e 100644
--- a/django/db/backends/postgresql/operations.py
+++ b/django/db/backends/postgresql/operations.py
@@ -100,5 +100,5 @@ class DatabaseOperations(BaseDatabaseOperations):
style.SQL_FIELD(qn('id')),
style.SQL_KEYWORD('IS NOT'),
style.SQL_KEYWORD('FROM'),
- style.SQL_TABLE(f.m2m_db_table())))
+ style.SQL_TABLE(qn(f.m2m_db_table()))))
return output
diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
index 4766f97199..6186063b1d 100644
--- a/django/db/models/fields/__init__.py
+++ b/django/db/models/fields/__init__.py
@@ -238,7 +238,7 @@ class Field(object):
if self.default is not NOT_PROVIDED:
if callable(self.default):
return self.default()
- return self.default
+ return force_unicode(self.default, strings_only=True)
if not self.empty_strings_allowed or (self.null and settings.DATABASE_ENGINE != 'oracle'):
return None
return ""
diff --git a/django/http/__init__.py b/django/http/__init__.py
index 9a47e70592..508c6d2f3e 100644
--- a/django/http/__init__.py
+++ b/django/http/__init__.py
@@ -47,8 +47,9 @@ class HttpRequest(object):
def get_host(self):
"Returns the HTTP host using the environment or request headers."
# We try three options, in order of decreasing preference.
- host = self.META.get('HTTP_X_FORWARDED_HOST', '')
- if 'HTTP_HOST' in self.META:
+ if 'HTTP_X_FORWARDED_HOST' in self.META:
+ host = self.META['HTTP_X_FORWARDED_HOST']
+ elif 'HTTP_HOST' in self.META:
host = self.META['HTTP_HOST']
else:
# Reconstruct the host using the algorithm from PEP 333.
diff --git a/django/newforms/widgets.py b/django/newforms/widgets.py
index 0e7752499e..2c235513d0 100644
--- a/django/newforms/widgets.py
+++ b/django/newforms/widgets.py
@@ -7,7 +7,9 @@ try:
except NameError:
from sets import Set as set # Python 2.3 fallback
+import copy
from itertools import chain
+
from django.utils.datastructures import MultiValueDict
from django.utils.html import escape
from django.utils.translation import ugettext
@@ -32,6 +34,12 @@ class Widget(object):
else:
self.attrs = {}
+ def __deepcopy__(self, memo):
+ obj = copy.copy(self)
+ obj.attrs = self.attrs.copy()
+ memo[id(self)] = obj
+ return obj
+
def render(self, name, value, attrs=None):
"""
Returns this Widget rendered as HTML, as a Unicode string.
@@ -88,7 +96,7 @@ class PasswordInput(Input):
input_type = 'password'
def __init__(self, attrs=None, render_value=True):
- self.attrs = attrs or {}
+ super(PasswordInput, self).__init__(attrs)
self.render_value = render_value
def render(self, name, value, attrs=None):
@@ -105,8 +113,8 @@ class MultipleHiddenInput(HiddenInput):
of values.
"""
def __init__(self, attrs=None, choices=()):
+ super(MultipleHiddenInput, self).__init__(attrs)
# choices can be any iterable
- self.attrs = attrs or {}
self.choices = choices
def render(self, name, value, attrs=None, choices=()):
@@ -145,9 +153,9 @@ class Textarea(Widget):
class CheckboxInput(Widget):
def __init__(self, attrs=None, check_test=bool):
+ super(CheckboxInput, self).__init__(attrs)
# check_test is a callable that takes a value and returns True
# if the checkbox should be checked for that value.
- self.attrs = attrs or {}
self.check_test = check_test
def render(self, name, value, attrs=None):
@@ -164,7 +172,7 @@ class CheckboxInput(Widget):
class Select(Widget):
def __init__(self, attrs=None, choices=()):
- self.attrs = attrs or {}
+ super(Select, self).__init__(attrs)
# choices can be any iterable, but we may need to render this widget
# multiple times. Thus, collapse it into a list so it can be consumed
# more than once.
@@ -203,8 +211,8 @@ class NullBooleanSelect(Select):
class SelectMultiple(Widget):
def __init__(self, attrs=None, choices=()):
+ super(SelectMultiple, self).__init__(attrs)
# choices can be any iterable
- self.attrs = attrs or {}
self.choices = choices
def render(self, name, value, attrs=None, choices=()):
diff --git a/django/oldforms/__init__.py b/django/oldforms/__init__.py
index 9bb90416c4..5f7b9fc2ad 100644
--- a/django/oldforms/__init__.py
+++ b/django/oldforms/__init__.py
@@ -500,7 +500,7 @@ class SelectField(FormField):
selected_html = u''
if smart_unicode(value) == str_data:
selected_html = u' selected="selected"'
- output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, escape(display_name)))
+ output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, force_unicode(escape(display_name))))
output.append(u' </select>')
return u'\n'.join(output)
@@ -612,7 +612,7 @@ class SelectMultipleField(SelectField):
selected_html = u''
if smart_unicode(value) in str_data_list:
selected_html = u' selected="selected"'
- output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, escape(choice)))
+ output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, force_unicode(escape(choice))))
output.append(u' </select>')
return u'\n'.join(output)
diff --git a/django/utils/datastructures.py b/django/utils/datastructures.py
index 2f3c9bb568..d750f098f0 100644
--- a/django/utils/datastructures.py
+++ b/django/utils/datastructures.py
@@ -54,7 +54,10 @@ class SortedDict(dict):
def __init__(self, data=None):
if data is None: data = {}
dict.__init__(self, data)
- self.keyOrder = data.keys()
+ if isinstance(data, dict):
+ self.keyOrder = data.keys()
+ else:
+ self.keyOrder=[key for key, value in data]
def __setitem__(self, key, value):
dict.__setitem__(self, key, value)
diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py
index 13fc8a847a..9ca7419e1e 100644
--- a/django/utils/translation/__init__.py
+++ b/django/utils/translation/__init__.py
@@ -2,6 +2,7 @@
Internationalization support.
"""
from django.utils.functional import lazy
+from django.utils.encoding import force_unicode
__all__ = ['gettext', 'gettext_noop', 'gettext_lazy', 'ngettext',
'ngettext_lazy', 'string_concat', 'activate', 'deactivate',
@@ -39,7 +40,7 @@ def delayed_loader(*args, **kwargs):
g['real_%s' % name] = getattr(trans, name)
# Make the originally requested function call on the way out the door.
- return g[caller](*args, **kwargs)
+ return g['real_%s' % caller](*args, **kwargs)
g = globals()
for name in __all__:
@@ -63,14 +64,10 @@ def ugettext(message):
def ungettext(singular, plural, number):
return real_ungettext(singular, plural, number)
-def string_concat(*strings):
- return real_string_concat(*strings)
-
ngettext_lazy = lazy(ngettext, str)
gettext_lazy = lazy(gettext, str)
ungettext_lazy = lazy(ungettext, unicode)
ugettext_lazy = lazy(ugettext, unicode)
-string_concat = lazy(string_concat, unicode)
def activate(language):
return real_activate(language)
@@ -108,3 +105,10 @@ def templatize(src):
def deactivate_all():
return real_deactivate_all()
+def string_concat(*strings):
+ """
+ Lazy variant of string concatenation, needed for translations that are
+ constructed from multiple parts.
+ """
+ return u''.join([force_unicode(s) for s in strings])
+string_concat = lazy(string_concat, unicode)
diff --git a/django/utils/translation/trans_null.py b/django/utils/translation/trans_null.py
index e3f89567a5..771a80e99c 100644
--- a/django/utils/translation/trans_null.py
+++ b/django/utils/translation/trans_null.py
@@ -13,7 +13,6 @@ ngettext_lazy = ngettext
def ungettext(singular, plural, number):
return force_unicode(ngettext(singular, plural, number))
-string_concat = lambda *strings: u''.join([force_unicode(el) for el in strings])
activate = lambda x: None
deactivate = deactivate_all = install = lambda: None
get_language = lambda: settings.LANGUAGE_CODE
diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
index 5fff1ea63a..250af04e8c 100644
--- a/django/utils/translation/trans_real.py
+++ b/django/utils/translation/trans_real.py
@@ -516,9 +516,3 @@ def templatize(src):
out.write(blankout(t.contents, 'X'))
return out.getvalue()
-def string_concat(*strings):
- """"
- Lazy variant of string concatenation, needed for translations that are
- constructed from multiple parts.
- """
- return u''.join([force_unicode(s) for s in strings])
diff --git a/django/views/static.py b/django/views/static.py
index 3ec4ca14a1..dce45d914d 100644
--- a/django/views/static.py
+++ b/django/views/static.py
@@ -1,6 +1,8 @@
-from django.template import loader
-from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified
-from django.template import Template, Context, TemplateDoesNotExist
+"""
+Views and functions for serving static files. These are only to be used
+during development, and SHOULD NOT be used in a production setting.
+"""
+
import mimetypes
import os
import posixpath
@@ -9,6 +11,10 @@ import rfc822
import stat
import urllib
+from django.template import loader
+from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseNotModified
+from django.template import Template, Context, TemplateDoesNotExist
+
def serve(request, path, document_root=None, show_indexes=False):
"""
Serve static files below a given point in the directory structure.
@@ -29,12 +35,12 @@ def serve(request, path, document_root=None, show_indexes=False):
newpath = ''
for part in path.split('/'):
if not part:
- # strip empty path components
+ # Strip empty path components.
continue
drive, part = os.path.splitdrive(part)
head, part = os.path.split(part)
if part in (os.curdir, os.pardir):
- # strip '.' amd '..' in path
+ # Strip '.' and '..' in path.
continue
newpath = os.path.join(newpath, part).replace('\\', '/')
if newpath and path != newpath:
diff --git a/docs/databases.txt b/docs/databases.txt
index 4d8824aa3d..213c2d666c 100644
--- a/docs/databases.txt
+++ b/docs/databases.txt
@@ -175,9 +175,9 @@ operators. You will also need the `cx_Oracle`_ driver, version 4.3.1 or newer.
.. _`cx_Oracle`: http://cx-oracle.sourceforge.net/
To run ``python manage.py syncdb``, you'll need to create an Oracle database
-user with CREATE TABLE, CREATE SEQUENCE, and CREATE PROCEDURE privileges. To
-run Django's test suite, the user also needs CREATE and DROP DATABASE and
-CREATE and DROP TABLESPACE privileges.
+user with CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE, and CREATE TRIGGER
+privileges. To run Django's test suite, the user also needs
+CREATE and DROP DATABASE and CREATE and DROP TABLESPACE privileges.
Connecting to the Database
--------------------------
diff --git a/docs/i18n.txt b/docs/i18n.txt
index bf73c88008..2c43e7884e 100644
--- a/docs/i18n.txt
+++ b/docs/i18n.txt
@@ -456,10 +456,13 @@ otherwise, they'll be tacked together without whitespace!
.. admonition:: Mind your charset
- When creating a ``.po`` file with your favorite text editor, first edit
+ When creating a PO file with your favorite text editor, first edit
the charset line (search for ``"CHARSET"``) and set it to the charset
- you'll be using to edit the content. Generally, utf-8 should work for most
- languages, but ``gettext`` should handle any charset you throw at it.
+ you'll be using to edit the content. Due to the way the ``gettext`` tools
+ work internally and because we want to allow non-ASCII source strings in
+ Django's core and your applications, you **must** use UTF-8 as the encoding
+ for your PO file (this means that everybody will be using the same
+ encoding, which is important when Django processes the PO files).
To reexamine all source code and templates for new translation strings and
update all message files for **all** languages, run this::
diff --git a/docs/newforms.txt b/docs/newforms.txt
index 11e19e847f..2005adeec8 100644
--- a/docs/newforms.txt
+++ b/docs/newforms.txt
@@ -2075,9 +2075,9 @@ More coming soon
================
That's all the documentation for now. For more, see the file
-http://code.djangoproject.com/browser/django/trunk/tests/regressiontests/forms/tests.py
+http://code.djangoproject.com/browser/django/trunk/tests/regressiontests/forms
-- the unit tests for ``django.newforms``. This can give you a good idea of
-what's possible.
+what's possible. (Each submodule there contains separate tests.)
If you're really itching to learn and use this library, please be patient.
We're working hard on finishing both the code and documentation.
diff --git a/docs/request_response.txt b/docs/request_response.txt
index 7806886841..8da00cdf09 100644
--- a/docs/request_response.txt
+++ b/docs/request_response.txt
@@ -381,8 +381,8 @@ Methods
``mimetype``. Historically, the parameter was only called ``mimetype``,
but since this is actually the value included in the HTTP ``Content-Type``
header, it can also include the character set encoding, which makes it
- more than just a MIME type specification. If ``mimetype`` is specifiedi
- (not None), that value is used. Otherwise, ``content_type`` is used. If
+ more than just a MIME type specification. If ``mimetype`` is specified
+ (not None), that value is used. Otherwise, ``content_type`` is used. If
neither is given, the ``DEFAULT_CONTENT_TYPE`` setting is used.
``__setitem__(header, value)``
diff --git a/docs/templates_python.txt b/docs/templates_python.txt
index b6173ad39a..bd105888ce 100644
--- a/docs/templates_python.txt
+++ b/docs/templates_python.txt
@@ -316,7 +316,7 @@ optional, third positional argument, ``processors``. In this example, the
}, [ip_address_processor])
return t.render(c)
-Note::
+.. note::
If you're using Django's ``render_to_response()`` shortcut to populate a
template with the contents of a dictionary, your template will be passed a
``Context`` instance by default (not a ``RequestContext``). To use a
diff --git a/docs/unicode.txt b/docs/unicode.txt
index 1ab255970c..a0e2648f57 100644
--- a/docs/unicode.txt
+++ b/docs/unicode.txt
@@ -110,19 +110,22 @@ Conversion functions
The ``django.utils.encoding`` module contains a few functions that are handy
for converting back and forth between Unicode and bytestrings.
- * ``smart_unicode(s, encoding='utf-8', errors='strict')`` converts its
- input to a Unicode string. The ``encoding`` parameter specifies the input
- encoding. (For example, Django uses this internally when processing form
- input data, which might not be UTF-8 encoded.) The ``errors`` parameter
- takes any of the values that are accepted by Python's ``unicode()``
- function for its error handling.
+ * ``smart_unicode(s, encoding='utf-8', strings_only=False, errors='strict')``
+ converts its input to a Unicode string. The ``encoding`` parameter
+ specifies the input encoding. (For example, Django uses this internally
+ when processing form input data, which might not be UTF-8 encoded.) The
+ ``strings_only`` parameter, if set to True, will result in Python
+ numbers, booleans and ``None`` not being converted to a string (they keep
+ their original types). The ``errors`` parameter takes any of the values
+ that are accepted by Python's ``unicode()`` function for its error
+ handling.
If you pass ``smart_unicode()`` an object that has a ``__unicode__``
method, it will use that method to do the conversion.
- * ``force_unicode(s, encoding='utf-8', errors='strict')`` is identical to
- ``smart_unicode()`` in almost all cases. The difference is when the
- first argument is a `lazy translation`_ instance. While
+ * ``force_unicode(s, encoding='utf-8', strings_only=False, errors='strict')``
+ is identical to ``smart_unicode()`` in almost all cases. The difference
+ is when the first argument is a `lazy translation`_ instance. While
``smart_unicode()`` preserves lazy translations, ``force_unicode()``
forces those objects to a Unicode string (causing the translation to
occur). Normally, you'll want to use ``smart_unicode()``. However,
@@ -132,11 +135,10 @@ for converting back and forth between Unicode and bytestrings.
* ``smart_str(s, encoding='utf-8', strings_only=False, errors='strict')``
is essentially the opposite of ``smart_unicode()``. It forces the first
- argument to a bytestring. The ``strings_only`` parameter, if set to True,
- will result in Python integers, booleans and ``None`` not being
- converted to a string (they keep their original types). This is slightly
- different semantics from Python's builtin ``str()`` function, but the
- difference is needed in a few places within Django's internals.
+ argument to a bytestring. The ``strings_only`` parameter has the same
+ behaviour as for ``smart_unicode()`` and ``force_unicode()``. This is
+ slightly different semantics from Python's builtin ``str()`` function,
+ but the difference is needed in a few places within Django's internals.
Normally, you'll only need to use ``smart_unicode()``. Call it as early as
possible on any input data that might be either Unicode or a bytestring, and
diff --git a/tests/modeltests/basic/models.py b/tests/modeltests/basic/models.py
index 58770ef2ce..2f4b932fe0 100644
--- a/tests/modeltests/basic/models.py
+++ b/tests/modeltests/basic/models.py
@@ -152,7 +152,7 @@ TypeError: 'foo' is an invalid keyword argument for this function
>>> a6 = Article(pub_date=datetime(2005, 7, 31))
>>> a6.save()
>>> a6.headline
-'Default headline'
+u'Default headline'
# For DateTimeFields, Django saves as much precision (in seconds) as you
# give it.
diff --git a/tests/modeltests/field_defaults/models.py b/tests/modeltests/field_defaults/models.py
index 23c4733b8f..1132f1ca41 100644
--- a/tests/modeltests/field_defaults/models.py
+++ b/tests/modeltests/field_defaults/models.py
@@ -42,7 +42,7 @@ __test__ = {'API_TESTS':"""
# Access database columns via Python attributes.
>>> a.headline
-'Default headline'
+u'Default headline'
# make sure the two dates are sufficiently close
>>> d = now - a.pub_date
diff --git a/tests/regressiontests/datastructures/tests.py b/tests/regressiontests/datastructures/tests.py
index 3920e1ca40..b58ee79693 100644
--- a/tests/regressiontests/datastructures/tests.py
+++ b/tests/regressiontests/datastructures/tests.py
@@ -55,6 +55,14 @@ True
>>> print repr(d)
{'one': 'not one', 'two': 'two', 'three': 'three'}
+Init from sequence of tuples
+>>> d = SortedDict((
+... (1, "one"),
+... (0, "zero"),
+... (2, "two")))
+>>> print repr(d)
+{1: 'one', 0: 'zero', 2: 'two'}
+
### DotExpandedDict ############################################################
>>> d = DotExpandedDict({'person.1.firstname': ['Simon'], 'person.1.lastname': ['Willison'], 'person.2.firstname': ['Adrian'], 'person.2.lastname': ['Holovaty']})
diff --git a/tests/regressiontests/i18n/models.py b/tests/regressiontests/i18n/models.py
index e69de29bb2..e1eefb8477 100644
--- a/tests/regressiontests/i18n/models.py
+++ b/tests/regressiontests/i18n/models.py
@@ -0,0 +1,12 @@
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+
+class TestModel(models.Model):
+ text = models.CharField(max_length=10, default=_('Anything'))
+
+__test__ = {'API_TESTS': '''
+>>> tm = TestModel()
+>>> tm.save()
+'''
+}
+
diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
index 8a7d2bee3e..99204451e4 100644
--- a/tests/regressiontests/i18n/tests.py
+++ b/tests/regressiontests/i18n/tests.py
@@ -30,4 +30,12 @@ True
>>> s4 = ugettext_lazy('Some other string')
>>> s == s4
False
+
+unicode(string_concat(...)) should not raise a TypeError - #4796
+
+>>> import django.utils.translation
+>>> reload(django.utils.translation)
+<module 'django.utils.translation' from ...>
+>>> unicode(django.utils.translation.string_concat("dja", "ngo"))
+u'django'
"""