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 Milton Waddams wam-djangobug@wamber.net - wangchun + Wang Chun Filip Wasilewski Dan Watson Chris Wesseling 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 Binary files a/django/conf/locale/de/LC_MESSAGES/django.mo and b/django/conf/locale/de/LC_MESSAGES/django.mo 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 , 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 "" - -#: contrib/humanize/templatetags/humanize.py:47 -#, python-format -msgid "%(value).1f million" -msgid_plural "%(value).1f million" -msgstr[0] "" -msgstr[1] "" +msgstr "." #: contrib/humanize/templatetags/humanize.py:50 #, python-format -msgid "%(value).1f billion" -msgid_plural "%(value).1f billion" -msgstr[0] "" -msgstr[1] "" +msgid "%(value).1f million" +msgid_plural "%(value).1f million" +msgstr[0] "%(value).1f Million" +msgstr[1] "%(value).1f Millionen" #: contrib/humanize/templatetags/humanize.py:53 #, python-format +msgid "%(value).1f billion" +msgid_plural "%(value).1f billion" +msgstr[0] "%(value).1f Milliarde" +msgstr[1] "%(value).1f Milliarden" + +#: 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' ' % (escape(value), selected_html, escape(display_name))) + output.append(u' ' % (escape(value), selected_html, force_unicode(escape(display_name)))) output.append(u' ') 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' ' % (escape(value), selected_html, escape(choice))) + output.append(u' ' % (escape(value), selected_html, force_unicode(escape(choice)))) output.append(u' ') 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) + +>>> unicode(django.utils.translation.string_concat("dja", "ngo")) +u'django' """