From f82be9ebc79e30fef796bbc61fec4b9694cb779f Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Fri, 9 Nov 2018 19:09:36 -0500 Subject: [PATCH] Fixed #29934 -- Added sqlparse as a require dependency. --- django/db/backends/base/features.py | 4 --- django/db/backends/base/operations.py | 17 ++++------ django/db/backends/postgresql/features.py | 1 - .../contributing/writing-code/unit-tests.txt | 2 +- docs/ref/migration-operations.txt | 5 +-- docs/releases/2.2.txt | 7 ++++ setup.py | 2 +- tests/migrations/test_commands.py | 34 +++++++------------ tests/migrations/test_multidb.py | 9 ----- tests/migrations/test_operations.py | 9 ----- 10 files changed, 29 insertions(+), 61 deletions(-) diff --git a/django/db/backends/base/features.py b/django/db/backends/base/features.py index dbbb5a796fd..8fec5454864 100644 --- a/django/db/backends/base/features.py +++ b/django/db/backends/base/features.py @@ -194,10 +194,6 @@ class BaseDatabaseFeatures: # Does 'a' LIKE 'A' match? 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. bare_select_suffix = '' diff --git a/django/db/backends/base/operations.py b/django/db/backends/base/operations.py index 7296fd0e670..2a2227435de 100644 --- a/django/db/backends/base/operations.py +++ b/django/db/backends/base/operations.py @@ -2,8 +2,9 @@ import datetime import decimal from importlib import import_module +import sqlparse + from django.conf import settings -from django.core.exceptions import ImproperlyConfigured from django.db import NotSupportedError, transaction from django.db.backends import utils from django.utils import timezone @@ -298,16 +299,10 @@ class BaseDatabaseOperations: cursor.execute() call and PEP 249 doesn't talk about this use case, the default implementation is conservative. """ - try: - import sqlparse - except ImportError: - 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] + return [ + sqlparse.format(statement, strip_comments=True) + for statement in sqlparse.split(sql) if statement + ] def process_clob(self, value): """ diff --git a/django/db/backends/postgresql/features.py b/django/db/backends/postgresql/features.py index 148e0766edf..4fae7b1d348 100644 --- a/django/db/backends/postgresql/features.py +++ b/django/db/backends/postgresql/features.py @@ -26,7 +26,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): nulls_order_largest = True closed_cursor_error_class = InterfaceError has_case_insensitive_like = False - requires_sqlparse_for_splitting = False greatest_least_ignores_nulls = True can_clone_databases = True supports_temporal_subtraction = True diff --git a/docs/internals/contributing/writing-code/unit-tests.txt b/docs/internals/contributing/writing-code/unit-tests.txt index 973ed276449..c3af1cd02f1 100644 --- a/docs/internals/contributing/writing-code/unit-tests.txt +++ b/docs/internals/contributing/writing-code/unit-tests.txt @@ -233,7 +233,7 @@ dependencies: * memcached_, plus a :ref:`supported Python binding ` * gettext_ (:ref:`gettext_on_windows`) * selenium_ -* sqlparse_ +* sqlparse_ (required) You can find these dependencies in `pip requirements files`_ inside the ``tests/requirements`` directory of the Django source tree and install them diff --git a/docs/ref/migration-operations.txt b/docs/ref/migration-operations.txt index c117145fdeb..2aaabab720b 100644 --- a/docs/ref/migration-operations.txt +++ b/docs/ref/migration-operations.txt @@ -240,8 +240,7 @@ partial indexes. ``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 -split the SQL into individual statements prior to executing them. This -requires installing the sqlparse_ Python library. +split the SQL into individual statements prior to executing them. 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() @@ -294,8 +293,6 @@ be removed (elided) when :ref:`squashing migrations `. want the operation not to do anything in the given direction. This is especially useful in making the operation reversible. -.. _sqlparse: https://pypi.org/project/sqlparse/ - ``RunPython`` ------------- diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt index 37ef7fd3a8e..4dd3c72e20c 100644 --- a/docs/releases/2.2.txt +++ b/docs/releases/2.2.txt @@ -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 :class:`~django.test.TransactionTestCase`'s internals. +``sqlparse`` is required dependency +----------------------------------- + +To simplify a few parts of Django's database handling, `sqlparse +`_ is now a required dependency. It's +automatically installed along with Django. + Miscellaneous ------------- diff --git a/setup.py b/setup.py index 6e4cf1f7150..227af529c7d 100644 --- a/setup.py +++ b/setup.py @@ -83,7 +83,7 @@ setup( entry_points={'console_scripts': [ 'django-admin = django.core.management:execute_from_command_line', ]}, - install_requires=['pytz'], + install_requires=['pytz', 'sqlparse'], extras_require={ "bcrypt": ["bcrypt"], "argon2": ["argon2-cffi >= 16.1.0"], diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py index 63e8615e677..25488046772 100644 --- a/tests/migrations/test_commands.py +++ b/tests/migrations/test_commands.py @@ -20,11 +20,6 @@ from .models import UnicodeModel, UnserializableModel from .routers import TestRouter from .test_base import MigrationTestBase -try: - import sqlparse -except ImportError: - sqlparse = None - class MigrateTests(MigrationTestBase): """ @@ -355,22 +350,19 @@ class MigrateTests(MigrationTestBase): out.getvalue() ) # Show the plan when an operation is irreversible. - # Migration 0004's RunSQL uses a SQL string instead of a list, so - # sqlparse may be required for splitting. - if sqlparse or not connection.features.requires_sqlparse_for_splitting: - # Migrate to the fourth migration. - call_command('migrate', 'migrations', '0004', verbosity=0) - out = io.StringIO() - call_command('migrate', 'migrations', '0003', plan=True, stdout=out, no_color=True) - self.assertEqual( - 'Planned operations:\n' - 'migrations.0004_fourth\n' - ' Raw SQL operation -> IRREVERSIBLE\n', - out.getvalue() - ) - # Cleanup by unmigrating everything: fake the irreversible, then - # migrate all to zero. - call_command('migrate', 'migrations', '0003', fake=True, verbosity=0) + # Migrate to the fourth migration. + call_command('migrate', 'migrations', '0004', verbosity=0) + out = io.StringIO() + call_command('migrate', 'migrations', '0003', plan=True, stdout=out, no_color=True) + self.assertEqual( + 'Planned operations:\n' + 'migrations.0004_fourth\n' + ' Raw SQL operation -> IRREVERSIBLE\n', + out.getvalue() + ) + # 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) @override_settings(MIGRATION_MODULES={'migrations': 'migrations.test_migrations_empty'}) diff --git a/tests/migrations/test_multidb.py b/tests/migrations/test_multidb.py index 16cd8f33d1a..0bed042964c 100644 --- a/tests/migrations/test_multidb.py +++ b/tests/migrations/test_multidb.py @@ -1,16 +1,9 @@ -import unittest - from django.db import connection, migrations, models from django.db.migrations.state import ProjectState from django.test import override_settings from .test_operations import OperationTestBase -try: - import sqlparse -except ImportError: - sqlparse = None - class AgnosticRouter: """ @@ -128,12 +121,10 @@ class MultiDBOperationTests(OperationTestBase): else: 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()]) def test_run_sql(self): 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()]) def test_run_sql2(self): self._test_run_sql("test_mltdb_runsql2", should_run=False) diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py index 117b124ae4d..2f35b5ba8fb 100644 --- a/tests/migrations/test_operations.py +++ b/tests/migrations/test_operations.py @@ -1,5 +1,3 @@ -import unittest - from django.core.exceptions import FieldDoesNotExist from django.db import connection, migrations, models, transaction 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 .test_base import MigrationTestBase -try: - import sqlparse -except ImportError: - sqlparse = None - class Mixin: pass @@ -2051,7 +2044,6 @@ class OperationTests(OperationTestBase): self.assertColumnExists("test_afknfk_rider", "pony_id") 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): """ Tests the RunSQL operation. @@ -2561,7 +2553,6 @@ class OperationTests(OperationTestBase): operation.database_forwards("test_runpython", editor, project_state, new_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): """ Tests the SeparateDatabaseAndState operation.