Permalink
Browse files

boulder-oracle-sprint: Merged rest of package to trunk [4719]

  • Loading branch information...
1 parent 429a542 commit ca343fc0ac546822839e5737c30c887dd59176b3 Boulder Sprinters committed Mar 13, 2007
View
1 AUTHORS
@@ -85,6 +85,7 @@ answer newbie questions, and generally made Django that much better:
Marc Fargas <telenieko@telenieko.com>
favo@exoweb.net
Eric Floehr <eric@intellovations.com>
+ Jorge Gajon <gajon@gajon.org>
gandalf@owca.info
Baishampayan Ghose
martin.glueck@gmail.com
View
4 django/bin/make-messages.py
@@ -81,7 +81,7 @@ def make_messages():
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 -o - "%s"' % (
+ cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy --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, 'b')
msgs = stdout.read()
@@ -103,7 +103,7 @@ def make_messages():
open(os.path.join(dirpath, '%s.py' % file), "wb").write(templatize(src))
thefile = '%s.py' % file
if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
- cmd = 'xgettext %s -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy -o - "%s"' % (
+ cmd = 'xgettext %s -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy --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, 'b')
msgs = stdout.read()
View
BIN django/conf/locale/fr/LC_MESSAGES/django.mo
Binary file not shown.
View
3,544 django/conf/locale/fr/LC_MESSAGES/django.po
2,022 additions, 1,522 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
6 django/contrib/admin/views/doc.py
@@ -168,7 +168,7 @@ def model_detail(request, app_label, model_name):
model = m
break
if model is None:
- raise Http404, _("Model %r not found in app %r") % (model_name, app_label)
+ raise Http404, _("Model %(name)r not found in app %(label)r") % {'name': model_name, 'label': app_label}
opts = model._meta
@@ -180,7 +180,7 @@ def model_detail(request, app_label, model_name):
if isinstance(field, models.ForeignKey):
data_type = related_object_name = field.rel.to.__name__
app_label = field.rel.to._meta.app_label
- verbose = utils.parse_rst((_("the related `%s.%s` object") % (app_label, data_type)), 'model', _('model:') + data_type)
+ verbose = utils.parse_rst((_("the related `%(label)s.%(type)s` object") % {'label': app_label, 'type': data_type}), 'model', _('model:') + data_type)
else:
data_type = get_readable_field_data_type(field)
verbose = field.verbose_name
@@ -211,7 +211,7 @@ def model_detail(request, app_label, model_name):
# Gather related objects
for rel in opts.get_all_related_objects():
- verbose = _("related `%s.%s` objects") % (rel.opts.app_label, rel.opts.object_name)
+ verbose = _("related `%(label)s.%(name)s` objects") % {'label': rel.opts.app_label, 'name': rel.opts.object_name}
accessor = rel.get_accessor_name()
fields.append({
'name' : "%s.all" % accessor,
View
1 django/contrib/contenttypes/management.py
@@ -7,6 +7,7 @@
def create_contenttypes(app, created_models, verbosity=2):
from django.contrib.contenttypes.models import ContentType
+ ContentType.objects.clear_cache()
app_models = get_models(app)
if not app_models:
return
View
10 django/contrib/contenttypes/models.py
@@ -19,6 +19,16 @@ def get_for_model(self, model):
model=key[1], defaults={'name': str(opts.verbose_name)})
CONTENT_TYPE_CACHE[key] = ct
return ct
+
+ def clear_cache(self):
+ """
+ Clear out the content-type cache. This needs to happen during database
+ flushes to prevent caching of "stale" content type IDs (see
+ django.contrib.contenttypes.management.create_contenttypes for where
+ this gets called).
+ """
+ global CONTENT_TYPE_CACHE
+ CONTENT_TYPE_CACHE = {}
class ContentType(models.Model):
name = models.CharField(maxlength=100)
View
17 django/contrib/humanize/templatetags/humanize.py
@@ -1,3 +1,5 @@
+from django.utils.translation import ngettext
+from django.utils.translation import gettext_lazy as _
from django import template
import re
@@ -12,9 +14,9 @@ def ordinal(value):
value = int(value)
except ValueError:
return value
- t = ('th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th')
+ t = (_('th'), _('st'), _('nd'), _('rd'), _('th'), _('th'), _('th'), _('th'), _('th'), _('th'))
if value % 100 in (11, 12, 13): # special case
- return '%dth' % value
+ return "%d%s" % (value, t[0])
return '%d%s' % (value, t[value % 10])
register.filter(ordinal)
@@ -41,11 +43,14 @@ def intword(value):
if value < 1000000:
return value
if value < 1000000000:
- return '%.1f million' % (value / 1000000.0)
+ new_value = value / 1000000.0
+ return ngettext('%(value).1f million', '%(value).1f million', new_value) % {'value': new_value}
if value < 1000000000000:
- return '%.1f billion' % (value / 1000000000.0)
+ new_value = value / 1000000000.0
+ return ngettext('%(value).1f billion', '%(value).1f billion', new_value) % {'value': new_value}
if value < 1000000000000000:
- return '%.1f trillion' % (value / 1000000000000.0)
+ new_value = value / 1000000000000.0
+ return ngettext('%(value).1f trillion', '%(value).1f trillion', new_value) % {'value': new_value}
return value
register.filter(intword)
@@ -60,5 +65,5 @@ def apnumber(value):
return value
if not 0 < value < 10:
return value
- return ('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine')[value-1]
+ return (_('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'))[value-1]
register.filter(apnumber)
View
4 django/core/management.py
@@ -1463,7 +1463,7 @@ def dump_data(app_labels, format='json', indent=None):
for model in get_models(app):
objects.extend(model.objects.all())
try:
- print serializers.serialize(format, objects, indent=indent)
+ return serializers.serialize(format, objects, indent=indent)
except Exception, e:
sys.stderr.write(style.ERROR("Unable to serialize database: %s\n" % e))
dump_data.help_doc = 'Output the contents of the database as a fixture of the given format'
@@ -1609,7 +1609,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
parser.print_usage_and_exit()
elif action == 'dumpdata':
try:
- action_mapping[action](args[1:], options.format, options.indent)
+ print action_mapping[action](args[1:], options.format, options.indent)
except IndexError:
parser.print_usage_and_exit()
elif action in ('startapp', 'startproject'):
View
7 django/core/serializers/__init__.py
@@ -25,6 +25,13 @@
"json" : "django.core.serializers.json",
}
+# Check for PyYaml and register the serializer if it's available.
+try:
+ import yaml
+ BUILTIN_SERIALIZERS["yaml"] = "django.core.serializers.pyyaml"
+except ImportError:
+ pass
+
_serializers = {}
def register_serializer(format, serializer_module):
View
6 django/core/serializers/base.py
@@ -54,11 +54,7 @@ def get_string_value(self, obj, field):
Convert a field's value to a string.
"""
if isinstance(field, models.DateTimeField):
- value = getattr(obj, field.name)
- if value is None:
- value = ''
- else:
- value = value.strftime("%Y-%m-%d %H:%M:%S")
+ value = getattr(obj, field.name).strftime("%Y-%m-%d %H:%M:%S")
elif isinstance(field, models.FileField):
value = getattr(obj, "get_%s_url" % field.name, lambda: None)()
else:
View
9 django/core/serializers/python.py
@@ -57,7 +57,7 @@ def Deserializer(object_list, **options):
for d in object_list:
# Look up the model and starting build a dict of data for it.
Model = _get_model(d["model"])
- data = {Model._meta.pk.attname : d["pk"]}
+ data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])}
m2m_data = {}
# Handle each field
@@ -70,16 +70,17 @@ def Deserializer(object_list, **options):
# Handle M2M relations
if field.rel and isinstance(field.rel, models.ManyToManyRel):
pks = []
+ m2m_convert = field.rel.to._meta.pk.to_python
for pk in field_value:
if isinstance(pk, unicode):
- pks.append(pk.encode(options.get("encoding", settings.DEFAULT_CHARSET)))
+ pks.append(m2m_convert(pk.encode(options.get("encoding", settings.DEFAULT_CHARSET))))
else:
- pks.append(pk)
+ pks.append(m2m_convert(pk))
m2m_data[field.name] = pks
# Handle FK fields
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
- data[field.attname] = field_value
+ data[field.attname] = field.rel.to._meta.pk.to_python(field_value)
# Handle all other fields
else:
View
36 django/core/serializers/pyyaml.py
@@ -0,0 +1,36 @@
+"""
+YAML serializer.
+
+Requires PyYaml (http://pyyaml.org/), but that's checked for in __init__.
+"""
+
+import datetime
+from django.core.serializers.python import Serializer as PythonSerializer
+from django.core.serializers.python import Deserializer as PythonDeserializer
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+import yaml
+
+class Serializer(PythonSerializer):
+ """
+ Convert a queryset to JSON.
+ """
+ def end_serialization(self):
+ yaml.dump(self.objects, self.stream, **self.options)
+
+ def getvalue(self):
+ return self.stream.getvalue()
+
+def Deserializer(stream_or_string, **options):
+ """
+ Deserialize a stream or string of JSON data.
+ """
+ if isinstance(stream_or_string, basestring):
+ stream = StringIO(stream_or_string)
+ else:
+ stream = stream_or_string
+ for obj in PythonDeserializer(yaml.load(stream)):
+ yield obj
+
View
31 django/core/serializers/xml_serializer.py
@@ -57,10 +57,12 @@ def handle_field(self, obj, field):
})
# Get a "string version" of the object's data (this is handled by the
- # serializer base class). None is handled specially.
- value = self.get_string_value(obj, field)
- if value is not None:
+ # serializer base class).
+ if getattr(obj, field.name) is not None:
+ value = self.get_string_value(obj, field)
self.xml.characters(str(value))
+ else:
+ self.xml.addQuickElement("None")
self.xml.endElement("field")
@@ -127,7 +129,8 @@ def _handle_object(self, node):
pk = node.getAttribute("pk")
if not pk:
raise base.DeserializationError("<object> node is missing the 'pk' attribute")
- data = {Model._meta.pk.name : pk}
+
+ data = {Model._meta.pk.attname : Model._meta.pk.to_python(pk)}
# Also start building a dict of m2m data (this is saved as
# {m2m_accessor_attribute : [list_of_related_objects]})
@@ -148,31 +151,37 @@ def _handle_object(self, node):
# As is usually the case, relation fields get the special treatment.
if field.rel and isinstance(field.rel, models.ManyToManyRel):
- m2m_data[field.name] = self._handle_m2m_field_node(field_node)
+ m2m_data[field.name] = self._handle_m2m_field_node(field_node, field)
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
- data[field.attname] = self._handle_fk_field_node(field_node)
+ data[field.attname] = self._handle_fk_field_node(field_node, field)
else:
- value = field.to_python(getInnerText(field_node).strip().encode(self.encoding))
+ if len(field_node.childNodes) == 1 and field_node.childNodes[0].nodeName == 'None':
+ value = None
+ else:
+ value = field.to_python(getInnerText(field_node).strip().encode(self.encoding))
data[field.name] = value
# Return a DeserializedObject so that the m2m data has a place to live.
return base.DeserializedObject(Model(**data), m2m_data)
- def _handle_fk_field_node(self, node):
+ def _handle_fk_field_node(self, node, field):
"""
Handle a <field> node for a ForeignKey
"""
# Check if there is a child node named 'None', returning None if so.
if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None':
return None
else:
- return getInnerText(node).strip().encode(self.encoding)
+ return field.rel.to._meta.pk.to_python(
+ getInnerText(node).strip().encode(self.encoding))
- def _handle_m2m_field_node(self, node):
+ def _handle_m2m_field_node(self, node, field):
"""
Handle a <field> node for a ManyToManyField
"""
- return [c.getAttribute("pk").encode(self.encoding) for c in node.getElementsByTagName("object")]
+ return [field.rel.to._meta.pk.to_python(
+ c.getAttribute("pk").encode(self.encoding))
+ for c in node.getElementsByTagName("object")]
def _get_model_from_node(self, node, attr):
"""
View
5 django/core/validators.py
@@ -140,7 +140,8 @@ def _isValidDate(date_string):
try:
date(year, month, day)
except ValueError, e:
- raise ValidationError, gettext('Invalid date: %s.' % e)
+ msg = gettext('Invalid date: %s') % gettext(str(e))
+ raise ValidationError, msg
def isValidANSIDate(field_data, all_data):
if not ansi_date_re.search(field_data):
@@ -363,7 +364,7 @@ def __init__(self, lower=None, upper=None, error_message=''):
self.lower, self.upper = lower, upper
if not error_message:
if lower and upper:
- self.error_message = gettext("This value must be between %s and %s.") % (lower, upper)
+ self.error_message = gettext("This value must be between %(lower)s and %(upper)s.") % {'lower': lower, 'upper': upper}
elif lower:
self.error_message = gettext("This value must be at least %s.") % lower
elif upper:
View
7 django/db/models/fields/__init__.py
@@ -762,6 +762,13 @@ def __init__(self, *args, **kwargs):
kwargs['null'] = True
Field.__init__(self, *args, **kwargs)
+ def to_python(self, value):
+ if value in (None, True, False): return value
+ if value in ('None'): return None
+ if value in ('t', 'True', '1'): return True
+ if value in ('f', 'False', '0'): return False
+ raise validators.ValidationError, gettext("This value must be either None, True or False.")
+
def get_manipulator_field_objs(self):
return [oldforms.NullBooleanField]
View
2 django/db/models/related.py
@@ -16,7 +16,7 @@ def __init__(self, parent_model, model, field):
self.opts = model._meta
self.field = field
self.edit_inline = field.rel.edit_inline
- self.name = '%s_%s' % (self.opts.app_label, self.opts.module_name)
+ self.name = '%s:%s' % (self.opts.app_label, self.opts.module_name)
self.var_name = self.opts.object_name.lower()
def flatten_data(self, follow, obj=None):
View
7 django/oldforms/__init__.py
@@ -130,7 +130,9 @@ def __getitem__(self, key):
if self.edit_inline:
self.fill_inline_collections()
for inline_collection in self._inline_collections:
- if inline_collection.name == key:
+ # The 'orig_name' comparison is for backwards compatibility
+ # with hand-crafted forms.
+ if inline_collection.name == key or (':' not in key and inline_collection.orig_name == key):
return inline_collection
raise KeyError, "Could not find Formfield or InlineObjectCollection named %r" % key
@@ -226,6 +228,9 @@ def __init__(self, parent_manipulator, rel_obj, data, errors):
self.errors = errors
self._collections = None
self.name = rel_obj.name
+ # This is the name used prior to fixing #1839. Needs for backwards
+ # compatibility.
+ self.orig_name = rel_obj.opts.module_name
def __len__(self):
self.fill()
View
17 django/template/defaultfilters.py
@@ -70,14 +70,15 @@ def floatformat(text, arg=-1):
With a negative numeric argument, it will display that many decimal
places -- but only if there's places to be displayed.
Examples:
- num1 = 34.23234
- num2 = 34.00000
- num1|floatformat results in 34.2
- num2|floatformat is 34
- num1|floatformat:3 is 34.232
- num2|floatformat:3 is 34.000
- num1|floatformat:-3 is 34.232
- num2|floatformat:-3 is 34
+
+ * num1 = 34.23234
+ * num2 = 34.00000
+ * num1|floatformat results in 34.2
+ * num2|floatformat is 34
+ * num1|floatformat:3 is 34.232
+ * num2|floatformat:3 is 34.000
+ * num1|floatformat:-3 is 34.232
+ * num2|floatformat:-3 is 34
"""
try:
f = float(text)
View
51 django/template/defaulttags.py
@@ -435,6 +435,15 @@ def cycle(parser, token):
cycle = register.tag(cycle)
def debug(parser, token):
+ """
+ Output a whole load of debugging information, including the current context and imported modules.
+
+ Sample usage::
+
+ <pre>
+ {% debug %}
+ </pre>
+ """
return DebugNode()
debug = register.tag(debug)
@@ -538,21 +547,6 @@ def do_for(parser, token):
do_for = register.tag("for", do_for)
def do_ifequal(parser, token, negate):
- """
- Output the contents of the block if the two arguments equal/don't equal each other.
-
- Examples::
-
- {% ifequal user.id comment.user_id %}
- ...
- {% endifequal %}
-
- {% ifnotequal user.id comment.user_id %}
- ...
- {% else %}
- ...
- {% endifnotequal %}
- """
bits = list(token.split_contents())
if len(bits) != 3:
raise TemplateSyntaxError, "%r takes two arguments" % bits[0]
@@ -568,11 +562,27 @@ def do_ifequal(parser, token, negate):
#@register.tag
def ifequal(parser, token):
+ """
+ Output the contents of the block if the two arguments equal each other.
+
+ Examples::
+
+ {% ifequal user.id comment.user_id %}
+ ...
+ {% endifequal %}
+
+ {% ifnotequal user.id comment.user_id %}
+ ...
+ {% else %}
+ ...
+ {% endifnotequal %}
+ """
return do_ifequal(parser, token, False)
ifequal = register.tag(ifequal)
#@register.tag
def ifnotequal(parser, token):
+ """Output the contents of the block if the two arguments are not equal. See ifequal"""
return do_ifequal(parser, token, True)
ifnotequal = register.tag(ifnotequal)
@@ -889,8 +899,9 @@ def templatetag(parser, token):
def url(parser, token):
"""
- Returns an absolute URL matching given view with its parameters. This is a
- way to define links that aren't tied to a particular url configuration:
+ Returns an absolute URL matching given view with its parameters.
+
+ This is a way to define links that aren't tied to a particular url configuration::
{% url path.to.some_view arg1,arg2,name1=value1 %}
@@ -901,16 +912,16 @@ def url(parser, token):
URL. All arguments for the URL should be present.
For example if you have a view ``app_name.client`` taking client's id and
- the corresponding line in a urlconf looks like this:
+ the corresponding line in a urlconf looks like this::
('^client/(\d+)/$', 'app_name.client')
and this app's urlconf is included into the project's urlconf under some
- path:
+ path::
('^clients/', include('project_name.app_name.urls'))
- then in a template you can create a link for a certain client like this:
+ then in a template you can create a link for a certain client like this::
{% url app_name.client client.id %}
View
13 django/utils/dateformat.py
@@ -13,6 +13,7 @@
from django.utils.dates import MONTHS, MONTHS_3, MONTHS_AP, WEEKDAYS
from django.utils.tzinfo import LocalTimezone
+from django.utils.translation import gettext as _
from calendar import isleap, monthrange
import re, time
@@ -36,14 +37,14 @@ def __init__(self, t):
def a(self):
"'a.m.' or 'p.m.'"
if self.data.hour > 11:
- return 'p.m.'
- return 'a.m.'
+ return _('p.m.')
+ return _('a.m.')
def A(self):
"'AM' or 'PM'"
if self.data.hour > 11:
- return 'PM'
- return 'AM'
+ return _('PM')
+ return _('AM')
def B(self):
"Swatch Internet time"
@@ -91,9 +92,9 @@ def P(self):
Proprietary extension.
"""
if self.data.minute == 0 and self.data.hour == 0:
- return 'midnight'
+ return _('midnight')
if self.data.minute == 0 and self.data.hour == 12:
- return 'noon'
+ return _('noon')
return '%s %s' % (self.f(), self.a())
def s(self):
View
6 django/views/i18n.py
@@ -9,16 +9,16 @@ def set_language(request):
"""
Redirect to a given url while setting the chosen language in the
session or cookie. The url and the language code need to be
- specified in the GET paramters.
+ specified in the GET parameters.
"""
- lang_code = request.GET['language']
+ lang_code = request.GET.get('language', None)
next = request.GET.get('next', None)
if not next:
next = request.META.get('HTTP_REFERER', None)
if not next:
next = '/'
response = http.HttpResponseRedirect(next)
- if check_for_language(lang_code):
+ if lang_code and check_for_language(lang_code):
if hasattr(request, 'session'):
request.session['django_language'] = lang_code
else:
View
11 docs/fastcgi.txt
@@ -304,3 +304,14 @@ If you have access to a command shell on a Unix system, you can accomplish this
easily by using the ``touch`` command::
touch mysite.fcgi
+
+Serving admin media files
+=========================
+
+Regardless of the server and configuration you eventually decide to use, you will
+also need to give some thought to how to serve the admin media files. The
+advice given in the modpython_ documentation is also applicable in the setups
+detailed above.
+
+.. _modpython: ../modpython/#serving-the-admin-files
+
View
21 docs/forms.txt
@@ -417,6 +417,27 @@ Here's a simple function that might drive the above form::
form = forms.FormWrapper(manipulator, new_data, errors)
return render_to_response('contact_form.html', {'form': form})
+Implementing ``flatten_data`` for custom manipulators
+------------------------------------------------------
+
+It is possible (although rarely needed) to replace the default automatically
+created manipulators on a model with your own custom manipulators. If you do
+this and you are intending to use those models in generic views, you should
+also define a ``flatten_data`` method in any ``ChangeManipulator`` replacement.
+This should act like the default ``flatten_data`` and return a dictionary
+mapping field names to their values, like so::
+
+ def flatten_data(self):
+ obj = self.original_object
+ return dict(
+ from = obj.from,
+ subject = obj.subject,
+ ...
+ )
+
+In this way, your new change manipulator will act exactly like the default
+version.
+
``FileField`` and ``ImageField`` special cases
==============================================
View
11 docs/i18n.txt
@@ -282,6 +282,17 @@ How to create language files
Once you've tagged your strings for later translation, you need to write (or
obtain) the language translations themselves. Here's how that works.
+.. admonition:: Locale restrictions
+
+ Django does not support localising your application into a locale for
+ which Django itself has not been translated -- it will ignore your
+ translation files. If you were to try this and Django supported it, you
+ would inevitably see a mixture of translated strings (from your
+ application) and English strings (from Django itself). If you are wanting
+ to support a locale for your application that is not already part of
+ Django, you will need to make at least a minimal translation of the Django
+ core.
+
Message files
-------------

0 comments on commit ca343fc

Please sign in to comment.