Fixed #29934 -- Added sqlparse as a require dependency.

This commit is contained in:
Tim Graham 2018-11-09 19:09:36 -05:00 committed by GitHub
parent f9ff1df1da
commit f82be9ebc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 29 additions and 61 deletions

View File

@ -194,10 +194,6 @@ class BaseDatabaseFeatures:
# Does 'a' LIKE 'A' match? # Does 'a' LIKE 'A' match?
has_case_insensitive_like = True has_case_insensitive_like = True
# Does the backend require the sqlparse library for splitting multi-line
# statements before executing them?
requires_sqlparse_for_splitting = True
# Suffix for backends that don't support "SELECT xxx;" queries. # Suffix for backends that don't support "SELECT xxx;" queries.
bare_select_suffix = '' bare_select_suffix = ''

View File

@ -2,8 +2,9 @@ import datetime
import decimal import decimal
from importlib import import_module from importlib import import_module
import sqlparse
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.db import NotSupportedError, transaction from django.db import NotSupportedError, transaction
from django.db.backends import utils from django.db.backends import utils
from django.utils import timezone from django.utils import timezone
@ -298,16 +299,10 @@ class BaseDatabaseOperations:
cursor.execute() call and PEP 249 doesn't talk about this use case, cursor.execute() call and PEP 249 doesn't talk about this use case,
the default implementation is conservative. the default implementation is conservative.
""" """
try: return [
import sqlparse sqlparse.format(statement, strip_comments=True)
except ImportError: for statement in sqlparse.split(sql) if statement
raise ImproperlyConfigured( ]
"The sqlparse package is required if you don't split your SQL "
"statements manually."
)
else:
return [sqlparse.format(statement, strip_comments=True)
for statement in sqlparse.split(sql) if statement]
def process_clob(self, value): def process_clob(self, value):
""" """

View File

@ -26,7 +26,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
nulls_order_largest = True nulls_order_largest = True
closed_cursor_error_class = InterfaceError closed_cursor_error_class = InterfaceError
has_case_insensitive_like = False has_case_insensitive_like = False
requires_sqlparse_for_splitting = False
greatest_least_ignores_nulls = True greatest_least_ignores_nulls = True
can_clone_databases = True can_clone_databases = True
supports_temporal_subtraction = True supports_temporal_subtraction = True

View File

@ -233,7 +233,7 @@ dependencies:
* memcached_, plus a :ref:`supported Python binding <memcached>` * memcached_, plus a :ref:`supported Python binding <memcached>`
* gettext_ (:ref:`gettext_on_windows`) * gettext_ (:ref:`gettext_on_windows`)
* selenium_ * selenium_
* sqlparse_ * sqlparse_ (required)
You can find these dependencies in `pip requirements files`_ inside the You can find these dependencies in `pip requirements files`_ inside the
``tests/requirements`` directory of the Django source tree and install them ``tests/requirements`` directory of the Django source tree and install them

View File

@ -240,8 +240,7 @@ partial indexes.
``sql``, and ``reverse_sql`` if provided, should be strings of SQL to run on ``sql``, and ``reverse_sql`` if provided, should be strings of SQL to run on
the database. On most database backends (all but PostgreSQL), Django will the database. On most database backends (all but PostgreSQL), Django will
split the SQL into individual statements prior to executing them. This split the SQL into individual statements prior to executing them.
requires installing the sqlparse_ Python library.
You can also pass a list of strings or 2-tuples. The latter is used for passing You can also pass a list of strings or 2-tuples. The latter is used for passing
queries and parameters in the same way as :ref:`cursor.execute() queries and parameters in the same way as :ref:`cursor.execute()
@ -294,8 +293,6 @@ be removed (elided) when :ref:`squashing migrations <migration-squashing>`.
want the operation not to do anything in the given direction. This is want the operation not to do anything in the given direction. This is
especially useful in making the operation reversible. especially useful in making the operation reversible.
.. _sqlparse: https://pypi.org/project/sqlparse/
``RunPython`` ``RunPython``
------------- -------------

View File

@ -330,6 +330,13 @@ properly (the database was empty at the end of the whole test suite). This
change shouldn't have an impact on your tests unless you've customized change shouldn't have an impact on your tests unless you've customized
:class:`~django.test.TransactionTestCase`'s internals. :class:`~django.test.TransactionTestCase`'s internals.
``sqlparse`` is required dependency
-----------------------------------
To simplify a few parts of Django's database handling, `sqlparse
<https://pypi.org/project/sqlparse/>`_ is now a required dependency. It's
automatically installed along with Django.
Miscellaneous Miscellaneous
------------- -------------

View File

@ -83,7 +83,7 @@ setup(
entry_points={'console_scripts': [ entry_points={'console_scripts': [
'django-admin = django.core.management:execute_from_command_line', 'django-admin = django.core.management:execute_from_command_line',
]}, ]},
install_requires=['pytz'], install_requires=['pytz', 'sqlparse'],
extras_require={ extras_require={
"bcrypt": ["bcrypt"], "bcrypt": ["bcrypt"],
"argon2": ["argon2-cffi >= 16.1.0"], "argon2": ["argon2-cffi >= 16.1.0"],

View File

@ -20,11 +20,6 @@ from .models import UnicodeModel, UnserializableModel
from .routers import TestRouter from .routers import TestRouter
from .test_base import MigrationTestBase from .test_base import MigrationTestBase
try:
import sqlparse
except ImportError:
sqlparse = None
class MigrateTests(MigrationTestBase): class MigrateTests(MigrationTestBase):
""" """
@ -355,22 +350,19 @@ class MigrateTests(MigrationTestBase):
out.getvalue() out.getvalue()
) )
# Show the plan when an operation is irreversible. # Show the plan when an operation is irreversible.
# Migration 0004's RunSQL uses a SQL string instead of a list, so # Migrate to the fourth migration.
# sqlparse may be required for splitting. call_command('migrate', 'migrations', '0004', verbosity=0)
if sqlparse or not connection.features.requires_sqlparse_for_splitting: out = io.StringIO()
# Migrate to the fourth migration. call_command('migrate', 'migrations', '0003', plan=True, stdout=out, no_color=True)
call_command('migrate', 'migrations', '0004', verbosity=0) self.assertEqual(
out = io.StringIO() 'Planned operations:\n'
call_command('migrate', 'migrations', '0003', plan=True, stdout=out, no_color=True) 'migrations.0004_fourth\n'
self.assertEqual( ' Raw SQL operation -> IRREVERSIBLE\n',
'Planned operations:\n' out.getvalue()
'migrations.0004_fourth\n' )
' Raw SQL operation -> IRREVERSIBLE\n', # Cleanup by unmigrating everything: fake the irreversible, then
out.getvalue() # migrate all to zero.
) call_command('migrate', 'migrations', '0003', fake=True, verbosity=0)
# Cleanup by unmigrating everything: fake the irreversible, then
# migrate all to zero.
call_command('migrate', 'migrations', '0003', fake=True, verbosity=0)
call_command('migrate', 'migrations', 'zero', verbosity=0) call_command('migrate', 'migrations', 'zero', verbosity=0)
@override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_empty'}) @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_empty'})

View File

@ -1,16 +1,9 @@
import unittest
from django.db import connection, migrations, models from django.db import connection, migrations, models
from django.db.migrations.state import ProjectState from django.db.migrations.state import ProjectState
from django.test import override_settings from django.test import override_settings
from .test_operations import OperationTestBase from .test_operations import OperationTestBase
try:
import sqlparse
except ImportError:
sqlparse = None
class AgnosticRouter: class AgnosticRouter:
""" """
@ -128,12 +121,10 @@ class MultiDBOperationTests(OperationTestBase):
else: else:
self.assertEqual(Pony.objects.count(), 0) self.assertEqual(Pony.objects.count(), 0)
@unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse")
@override_settings(DATABASE_ROUTERS=[MigrateNothingRouter()]) @override_settings(DATABASE_ROUTERS=[MigrateNothingRouter()])
def test_run_sql(self): def test_run_sql(self):
self._test_run_sql("test_mltdb_runsql", should_run=False) self._test_run_sql("test_mltdb_runsql", should_run=False)
@unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse")
@override_settings(DATABASE_ROUTERS=[MigrateWhenFooRouter()]) @override_settings(DATABASE_ROUTERS=[MigrateWhenFooRouter()])
def test_run_sql2(self): def test_run_sql2(self):
self._test_run_sql("test_mltdb_runsql2", should_run=False) self._test_run_sql("test_mltdb_runsql2", should_run=False)

View File

@ -1,5 +1,3 @@
import unittest
from django.core.exceptions import FieldDoesNotExist from django.core.exceptions import FieldDoesNotExist
from django.db import connection, migrations, models, transaction from django.db import connection, migrations, models, transaction
from django.db.migrations.migration import Migration from django.db.migrations.migration import Migration
@ -14,11 +12,6 @@ from django.test import SimpleTestCase, override_settings, skipUnlessDBFeature
from .models import FoodManager, FoodQuerySet, UnicodeModel from .models import FoodManager, FoodQuerySet, UnicodeModel
from .test_base import MigrationTestBase from .test_base import MigrationTestBase
try:
import sqlparse
except ImportError:
sqlparse = None
class Mixin: class Mixin:
pass pass
@ -2051,7 +2044,6 @@ class OperationTests(OperationTestBase):
self.assertColumnExists("test_afknfk_rider", "pony_id") self.assertColumnExists("test_afknfk_rider", "pony_id")
self.assertColumnNotExists("test_afknfk_rider", "pony") self.assertColumnNotExists("test_afknfk_rider", "pony")
@unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse")
def test_run_sql(self): def test_run_sql(self):
""" """
Tests the RunSQL operation. Tests the RunSQL operation.
@ -2561,7 +2553,6 @@ class OperationTests(OperationTestBase):
operation.database_forwards("test_runpython", editor, project_state, new_state) operation.database_forwards("test_runpython", editor, project_state, new_state)
operation.database_backwards("test_runpython", editor, new_state, project_state) operation.database_backwards("test_runpython", editor, new_state, project_state)
@unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse")
def test_separate_database_and_state(self): def test_separate_database_and_state(self):
""" """
Tests the SeparateDatabaseAndState operation. Tests the SeparateDatabaseAndState operation.