Skip to content

Commit e3bad40

Browse files
committed
Merged trunk changes r13316:13342 into test-refactor SOC branch.
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2010/test-refactor@13343 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 8bdf160 commit e3bad40

File tree

20 files changed

+594
-461
lines changed

20 files changed

+594
-461
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ answer newbie questions, and generally made Django that much better:
220220
Kieran Holland <http://www.kieranholland.com>
221221
Sung-Jin Hong <[email protected]>
222222
Leo "hylje" Honkanen <[email protected]>
223+
Matt Hoskins <[email protected]>
223224
Tareque Hossain <http://www.codexn.com>
224225
Richard House <[email protected]>
225226
Robert Rock Howard <http://djangomojo.com/>

django/conf/locale/pl/formats.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@
2828
'%Y-%m-%d', # '2006-10-25'
2929
)
3030
DECIMAL_SEPARATOR = ','
31-
THOUSAND_SEPARATOR = '.'
32-
NUMBER_GROUPING = 3
31+
THOUSAND_SEPARATOR = ' '
32+
NUMBER_GROUPING = 3

django/core/handlers/base.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,8 @@ def get_response(self, request):
137137
raise
138138
except: # Handle everything else, including SuspiciousOperation, etc.
139139
# Get the exception info now, in case another exception is thrown later.
140-
exc_info = sys.exc_info()
141140
receivers = signals.got_request_exception.send(sender=self.__class__, request=request)
142-
return self.handle_uncaught_exception(request, resolver, exc_info)
141+
return self.handle_uncaught_exception(request, resolver, sys.exc_info())
143142
finally:
144143
# Reset URLconf for this thread on the way out for complete
145144
# isolation of request.urlconf

django/core/management/base.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,8 @@ def execute(self, *args, **options):
213213
sys.stderr.write(smart_str(self.style.ERROR('Error: %s\n' % e)))
214214
sys.exit(1)
215215
try:
216+
self.stdout = options.get('stdout', sys.stdout)
217+
self.stderr = options.get('stderr', sys.stderr)
216218
if self.requires_model_validation:
217219
self.validate()
218220
output = self.handle(*args, **options)
@@ -223,12 +225,12 @@ def execute(self, *args, **options):
223225
from django.db import connections, DEFAULT_DB_ALIAS
224226
connection = connections[options.get('database', DEFAULT_DB_ALIAS)]
225227
if connection.ops.start_transaction_sql():
226-
print self.style.SQL_KEYWORD(connection.ops.start_transaction_sql())
227-
print output
228+
self.stdout.write(self.style.SQL_KEYWORD(connection.ops.start_transaction_sql()))
229+
self.stdout.write(output)
228230
if self.output_transaction:
229-
print self.style.SQL_KEYWORD(connection.ops.end_transaction_sql())
231+
self.stdout.write(self.style.SQL_KEYWORD("COMMIT;") + '\n')
230232
except CommandError, e:
231-
sys.stderr.write(smart_str(self.style.ERROR('Error: %s\n' % e)))
233+
self.stderr.write(smart_str(self.style.ERROR('Error: %s\n' % e)))
232234
sys.exit(1)
233235

234236
def validate(self, app=None, display_num_errors=False):
@@ -250,7 +252,7 @@ def validate(self, app=None, display_num_errors=False):
250252
error_text = s.read()
251253
raise CommandError("One or more models did not validate:\n%s" % error_text)
252254
if display_num_errors:
253-
print "%s error%s found" % (num_errors, num_errors != 1 and 's' or '')
255+
self.stdout.write("%s error%s found\n" % (num_errors, num_errors != 1 and 's' or ''))
254256

255257
def handle(self, *args, **options):
256258
"""

django/core/management/commands/loaddata.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,10 @@ def read(self):
112112

113113
if formats:
114114
if verbosity > 1:
115-
print "Loading '%s' fixtures..." % fixture_name
115+
self.stdout.write("Loading '%s' fixtures...\n" % fixture_name)
116116
else:
117117
sys.stderr.write(
118-
self.style.ERROR("Problem installing fixture '%s': %s is not a known serialization format." %
118+
self.style.ERROR("Problem installing fixture '%s': %s is not a known serialization format.\n" %
119119
(fixture_name, format)))
120120
transaction.rollback(using=using)
121121
transaction.leave_transaction_management(using=using)
@@ -128,7 +128,7 @@ def read(self):
128128

129129
for fixture_dir in fixture_dirs:
130130
if verbosity > 1:
131-
print "Checking %s for fixtures..." % humanize(fixture_dir)
131+
self.stdout.write("Checking %s for fixtures...\n" % humanize(fixture_dir))
132132

133133
label_found = False
134134
for combo in product([using, None], formats, compression_formats):
@@ -141,25 +141,25 @@ def read(self):
141141
)
142142

143143
if verbosity > 1:
144-
print "Trying %s for %s fixture '%s'..." % \
145-
(humanize(fixture_dir), file_name, fixture_name)
144+
self.stdout.write("Trying %s for %s fixture '%s'...\n" % \
145+
(humanize(fixture_dir), file_name, fixture_name))
146146
full_path = os.path.join(fixture_dir, file_name)
147147
open_method = compression_types[compression_format]
148148
try:
149149
fixture = open_method(full_path, 'r')
150150
if label_found:
151151
fixture.close()
152-
print self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting." %
153-
(fixture_name, humanize(fixture_dir)))
152+
self.stderr.write(self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting.\n" %
153+
(fixture_name, humanize(fixture_dir))))
154154
transaction.rollback(using=using)
155155
transaction.leave_transaction_management(using=using)
156156
return
157157
else:
158158
fixture_count += 1
159159
objects_in_fixture = 0
160160
if verbosity > 0:
161-
print "Installing %s fixture '%s' from %s." % \
162-
(format, fixture_name, humanize(fixture_dir))
161+
self.stdout.write("Installing %s fixture '%s' from %s.\n" % \
162+
(format, fixture_name, humanize(fixture_dir)))
163163
try:
164164
objects = serializers.deserialize(format, fixture, using=using)
165165
for obj in objects:
@@ -190,24 +190,24 @@ def read(self):
190190
# error was encountered during fixture loading.
191191
if objects_in_fixture == 0:
192192
sys.stderr.write(
193-
self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)" %
193+
self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)\n" %
194194
(fixture_name)))
195195
transaction.rollback(using=using)
196196
transaction.leave_transaction_management(using=using)
197197
return
198198

199199
except Exception, e:
200200
if verbosity > 1:
201-
print "No %s fixture '%s' in %s." % \
202-
(format, fixture_name, humanize(fixture_dir))
201+
self.stdout.write("No %s fixture '%s' in %s.\n" % \
202+
(format, fixture_name, humanize(fixture_dir)))
203203

204204
# If we found even one object in a fixture, we need to reset the
205205
# database sequences.
206206
if object_count > 0:
207207
sequence_sql = connection.ops.sequence_reset_sql(self.style, models)
208208
if sequence_sql:
209209
if verbosity > 1:
210-
print "Resetting sequences"
210+
self.stdout.write("Resetting sequences\n")
211211
for line in sequence_sql:
212212
cursor.execute(line)
213213

@@ -217,10 +217,10 @@ def read(self):
217217

218218
if object_count == 0:
219219
if verbosity > 0:
220-
print "No fixtures found."
220+
self.stdout.write("No fixtures found.\n")
221221
else:
222222
if verbosity > 0:
223-
print "Installed %d object(s) from %d fixture(s)" % (object_count, fixture_count)
223+
self.stdout.write("Installed %d object(s) from %d fixture(s)\n" % (object_count, fixture_count))
224224

225225
# Close the DB connection. This is required as a workaround for an
226226
# edge case in MySQL: if the same connection is used to

django/db/backends/postgresql/creation.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from django.db.backends.creation import BaseDatabaseCreation
2+
from django.db.backends.util import truncate_name
23

34
class DatabaseCreation(BaseDatabaseCreation):
45
# This dictionary maps Field objects to their associated PostgreSQL column
@@ -51,7 +52,7 @@ def sql_indexes_for_field(self, model, f, style):
5152

5253
def get_index_sql(index_name, opclass=''):
5354
return (style.SQL_KEYWORD('CREATE INDEX') + ' ' +
54-
style.SQL_TABLE(qn(index_name)) + ' ' +
55+
style.SQL_TABLE(qn(truncate_name(index_name,self.connection.ops.max_name_length()))) + ' ' +
5556
style.SQL_KEYWORD('ON') + ' ' +
5657
style.SQL_TABLE(qn(db_table)) + ' ' +
5758
"(%s%s)" % (style.SQL_FIELD(qn(f.column)), opclass) +

django/db/backends/postgresql/operations.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ def field_cast_sql(self, db_type):
5454
return '%s'
5555

5656
def last_insert_id(self, cursor, table_name, pk_name):
57-
cursor.execute("SELECT CURRVAL('\"%s_%s_seq\"')" % (table_name, pk_name))
57+
# Use pg_get_serial_sequence to get the underlying sequence name
58+
# from the table name and column name (available since PostgreSQL 8)
59+
cursor.execute("SELECT CURRVAL(pg_get_serial_sequence('%s','%s'))" % (table_name, pk_name))
5860
return cursor.fetchone()[0]
5961

6062
def no_limit_value(self):
@@ -90,13 +92,14 @@ def sql_flush(self, style, tables, sequences):
9092
for sequence_info in sequences:
9193
table_name = sequence_info['table']
9294
column_name = sequence_info['column']
93-
if column_name and len(column_name) > 0:
94-
sequence_name = '%s_%s_seq' % (table_name, column_name)
95-
else:
96-
sequence_name = '%s_id_seq' % table_name
97-
sql.append("%s setval('%s', 1, false);" % \
95+
if not (column_name and len(column_name) > 0):
96+
# This will be the case if it's an m2m using an autogenerated
97+
# intermediate table (see BaseDatabaseIntrospection.sequence_list)
98+
column_name = 'id'
99+
sql.append("%s setval(pg_get_serial_sequence('%s','%s'), 1, false);" % \
98100
(style.SQL_KEYWORD('SELECT'),
99-
style.SQL_FIELD(self.quote_name(sequence_name)))
101+
style.SQL_TABLE(table_name),
102+
style.SQL_FIELD(column_name))
100103
)
101104
return sql
102105
else:
@@ -110,11 +113,15 @@ def sequence_reset_sql(self, style, model_list):
110113
# Use `coalesce` to set the sequence for each model to the max pk value if there are records,
111114
# or 1 if there are none. Set the `is_called` property (the third argument to `setval`) to true
112115
# if there are records (as the max pk value is already in use), otherwise set it to false.
116+
# Use pg_get_serial_sequence to get the underlying sequence name from the table name
117+
# and column name (available since PostgreSQL 8)
118+
113119
for f in model._meta.local_fields:
114120
if isinstance(f, models.AutoField):
115-
output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \
121+
output.append("%s setval(pg_get_serial_sequence('%s','%s'), coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \
116122
(style.SQL_KEYWORD('SELECT'),
117-
style.SQL_FIELD(qn('%s_%s_seq' % (model._meta.db_table, f.column))),
123+
style.SQL_TABLE(model._meta.db_table),
124+
style.SQL_FIELD(f.column),
118125
style.SQL_FIELD(qn(f.column)),
119126
style.SQL_FIELD(qn(f.column)),
120127
style.SQL_KEYWORD('IS NOT'),
@@ -123,9 +130,10 @@ def sequence_reset_sql(self, style, model_list):
123130
break # Only one AutoField is allowed per model, so don't bother continuing.
124131
for f in model._meta.many_to_many:
125132
if not f.rel.through:
126-
output.append("%s setval('%s', coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \
133+
output.append("%s setval(pg_get_serial_sequence('%s','%s'), coalesce(max(%s), 1), max(%s) %s null) %s %s;" % \
127134
(style.SQL_KEYWORD('SELECT'),
128-
style.SQL_FIELD(qn('%s_id_seq' % f.m2m_db_table())),
135+
style.SQL_TABLE(model._meta.db_table),
136+
style.SQL_FIELD('id'),
129137
style.SQL_FIELD(qn('id')),
130138
style.SQL_FIELD(qn('id')),
131139
style.SQL_KEYWORD('IS NOT'),

django/middleware/csrf.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,6 @@ class CsrfViewMiddleware(object):
6262
tag.
6363
"""
6464
def process_view(self, request, callback, callback_args, callback_kwargs):
65-
if getattr(callback, 'csrf_exempt', False):
66-
return None
67-
6865
if getattr(request, 'csrf_processing_done', False):
6966
return None
7067

@@ -90,6 +87,11 @@ def accept():
9087
# place of a CSRF cookie for this request only.
9188
cookie_is_new = True
9289

90+
# Wait until request.META["CSRF_COOKIE"] has been manipulated before
91+
# bailing out, so that get_token still works
92+
if getattr(callback, 'csrf_exempt', False):
93+
return None
94+
9395
if request.method == 'POST':
9496
if getattr(request, '_dont_enforce_csrf_checks', False):
9597
# Mechanism to turn off CSRF checks for test suite. It comes after

docs/howto/custom-management-commands.txt

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Writing custom django-admin commands
88

99
Applications can register their own actions with ``manage.py``. For example,
1010
you might want to add a ``manage.py`` action for a Django app that you're
11-
distributing. In this document, we will be building a custom ``closepoll``
11+
distributing. In this document, we will be building a custom ``closepoll``
1212
command for the ``polls`` application from the
1313
:ref:`tutorial<intro-tutorial01>`.
1414

@@ -62,9 +62,16 @@ look like this:
6262
poll.opened = False
6363
poll.save()
6464

65-
print 'Successfully closed poll "%s"' % poll_id
65+
self.stdout.write('Successfully closed poll "%s"\n' % poll_id)
6666

67-
The new custom command can be called using ``python manage.py closepoll
67+
.. note::
68+
When you are using management commands and wish to provide console
69+
output, you should write to ``self.stdout`` and ``self.stderr``,
70+
instead of printing to ``stdout`` and ``stderr`` directly. By
71+
using these proxies, it becomes much easier to test your custom
72+
command.
73+
74+
The new custom command can be called using ``python manage.py closepoll
6875
<poll_id>``.
6976

7077
The ``handle()`` method takes zero or more ``poll_ids`` and sets ``poll.opened``
@@ -91,8 +98,8 @@ must be added to :attr:`~BaseCommand.option_list` like this:
9198
)
9299
# ...
93100

94-
In addition to being able to add custom command line options, all
95-
:ref:`management commands<ref-django-admin>` can accept some
101+
In addition to being able to add custom command line options, all
102+
:ref:`management commands<ref-django-admin>` can accept some
96103
default options such as :djadminopt:`--verbosity` and :djadminopt:`--traceback`.
97104

98105
Command objects
@@ -113,7 +120,7 @@ Subclassing the :class:`BaseCommand` class requires that you implement the
113120
Attributes
114121
----------
115122

116-
All attributes can be set in your derived class and can be used in
123+
All attributes can be set in your derived class and can be used in
117124
:class:`BaseCommand`'s :ref:`subclasses<ref-basecommand-subclasses>`.
118125

119126
.. attribute:: BaseCommand.args
@@ -133,7 +140,7 @@ All attributes can be set in your derived class and can be used in
133140
.. attribute:: BaseCommand.help
134141

135142
A short description of the command, which will be printed in the
136-
help message when the user runs the command
143+
help message when the user runs the command
137144
``python manage.py help <command>``.
138145

139146
.. attribute:: BaseCommand.option_list
@@ -230,7 +237,7 @@ Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement
230237
A command which takes no arguments on the command line.
231238

232239
Rather than implementing :meth:`~BaseCommand.handle`, subclasses must implement
233-
:meth:`~NoArgsCommand.handle_noargs`; :meth:`~BaseCommand.handle` itself is
240+
:meth:`~NoArgsCommand.handle_noargs`; :meth:`~BaseCommand.handle` itself is
234241
overridden to ensure no arguments are passed to the command.
235242

236243
.. method:: NoArgsCommand.handle_noargs(**options)

docs/ref/settings.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ to be displayed.
441441

442442
See also ``DATETIME_INPUT_FORMATS`` and ``TIME_INPUT_FORMATS``.
443443

444-
.. _datetime: http://docs.python.org/library/datetime.html#strftime-behavior
444+
.. _datetime: http://docs.python.org/library/datetime.html#strftime-strptime-behavior
445445

446446
.. setting:: DATETIME_FORMAT
447447

@@ -481,7 +481,7 @@ to be displayed.
481481

482482
See also ``DATE_INPUT_FORMATS`` and ``TIME_INPUT_FORMATS``.
483483

484-
.. _datetime: http://docs.python.org/library/datetime.html#strftime-behavior
484+
.. _datetime: http://docs.python.org/library/datetime.html#strftime-strptime-behavior
485485

486486
.. setting:: DEBUG
487487

@@ -1532,7 +1532,7 @@ to be displayed.
15321532

15331533
See also ``DATE_INPUT_FORMATS`` and ``DATETIME_INPUT_FORMATS``.
15341534

1535-
.. _datetime: http://docs.python.org/library/datetime.html#strftime-behavior
1535+
.. _datetime: http://docs.python.org/library/datetime.html#strftime-strptime-behavior
15361536

15371537
.. setting:: TIME_ZONE
15381538

0 commit comments

Comments
 (0)