Răsfoiți Sursa

Fixed #24335 -- Bumped required psycopg2 version to 2.4.5 (2.5 for contrib.postgres).

Tim Graham 10 ani în urmă
părinte
comite
3adc5f1ee6

+ 18 - 26
django/db/backends/postgresql_psycopg2/base.py

@@ -5,6 +5,7 @@ Requires psycopg 2: http://initd.org/projects/psycopg2
 """
 
 from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
 from django.db.backends.base.base import BaseDatabaseWrapper
 from django.db.backends.base.validation import BaseDatabaseValidation
 from django.utils.encoding import force_str
@@ -16,9 +17,19 @@ try:
     import psycopg2.extensions
     import psycopg2.extras
 except ImportError as e:
-    from django.core.exceptions import ImproperlyConfigured
     raise ImproperlyConfigured("Error loading psycopg2 module: %s" % e)
 
+
+def psycopg2_version():
+    version = psycopg2.__version__.split(' ', 1)[0]
+    return tuple(int(v) for v in version.split('.') if v.isdigit())
+
+PSYCOPG2_VERSION = psycopg2_version()
+
+if PSYCOPG2_VERSION < (2, 4, 5):
+    raise ImproperlyConfigured("psycopg2_version 2.4.5 or newer is required; you have %s" % psycopg2.__version__)
+
+
 # Some of these import psycopg2, so import them after checking if it's installed.
 from .client import DatabaseClient                          # isort:skip
 from .creation import DatabaseCreation                      # isort:skip
@@ -164,20 +175,15 @@ class DatabaseWrapper(BaseDatabaseWrapper):
         # - after connecting to the database in order to obtain the database's
         #   default when no value is explicitly specified in options.
         # - before calling _set_autocommit() because if autocommit is on, that
-        #   will set connection.isolation_level to ISOLATION_LEVEL_AUTOCOMMIT;
-        #   and if autocommit is off, on psycopg2 < 2.4.2, _set_autocommit()
-        #   needs self.isolation_level.
+        #   will set connection.isolation_level to ISOLATION_LEVEL_AUTOCOMMIT.
         options = self.settings_dict['OPTIONS']
         try:
             self.isolation_level = options['isolation_level']
         except KeyError:
             self.isolation_level = connection.isolation_level
         else:
-            # Set the isolation level to the value from OPTIONS. This isn't
-            # needed on psycopg2 < 2.4.2 because it happens as a side-effect
-            # of _set_autocommit(False).
-            if (self.isolation_level != connection.isolation_level and
-                    self.psycopg2_version >= (2, 4, 2)):
+            # Set the isolation level to the value from OPTIONS.
+            if self.isolation_level != connection.isolation_level:
                 connection.set_session(isolation_level=self.isolation_level)
 
         return connection
@@ -186,13 +192,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
         self.connection.set_client_encoding('UTF8')
 
         tz = self.settings_dict['TIME_ZONE']
-        try:
-            get_parameter_status = self.connection.get_parameter_status
-        except AttributeError:
-            # psycopg2 < 2.0.12 doesn't have get_parameter_status
-            conn_tz = None
-        else:
-            conn_tz = get_parameter_status('TimeZone')
+        conn_tz = self.connection.get_parameter_status('TimeZone')
 
         if conn_tz != tz:
             cursor = self.connection.cursor()
@@ -211,14 +211,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
 
     def _set_autocommit(self, autocommit):
         with self.wrap_database_errors:
-            if self.psycopg2_version >= (2, 4, 2):
-                self.connection.autocommit = autocommit
-            else:
-                if autocommit:
-                    level = psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT
-                else:
-                    level = self.isolation_level
-                self.connection.set_isolation_level(level)
+            self.connection.autocommit = autocommit
 
     def check_constraints(self, table_names=None):
         """
@@ -239,8 +232,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
 
     @cached_property
     def psycopg2_version(self):
-        version = psycopg2.__version__.split(' ', 1)[0]
-        return tuple(int(v) for v in version.split('.') if v.isdigit())
+        return PSYCOPG2_VERSION
 
     @cached_property
     def pg_version(self):

+ 5 - 0
docs/ref/contrib/postgres/index.txt

@@ -1,12 +1,17 @@
 ``django.contrib.postgres``
 ===========================
 
+.. module:: django.contrib.postgres
+    :synopsis: PostgreSQL-specific fields and features
+
 .. versionadded:: 1.8
 
 PostgreSQL has a number of features which are not shared by the other databases
 Django supports. This optional module contains model fields and form fields for
 a number of PostgreSQL specific data types.
 
+Psycopg2 2.5 or higher is required.
+
 .. note::
     Django is, and will continue to be, a database-agnostic web framework. We
     would encourage those writing reusable applications for the Django

+ 4 - 2
docs/ref/databases.txt

@@ -92,8 +92,10 @@ below for information on how to set up your database correctly.
 PostgreSQL notes
 ================
 
-Django supports PostgreSQL 9.0 and higher. It requires the use of Psycopg2
-2.0.9 or higher.
+Django supports PostgreSQL 9.0 and higher. It requires the use of `psycopg2`_
+2.4.5 or higher (or 2.5+ if you want to use :mod:`django.contrib.postgres`).
+
+.. _psycopg2: http://initd.org/psycopg/
 
 If you're on Windows, check out the unofficial `compiled Windows version`_
 of psycopg2.

+ 2 - 1
docs/releases/1.8.txt

@@ -834,7 +834,8 @@ officially supports.
 This also includes dropping support for PostGIS 1.3 and 1.4 as these versions
 are not supported on versions of PostgreSQL later than 8.4.
 
-Django also now requires the use of Psycopg2 version 2.0.9 or higher.
+Django also now requires the use of Psycopg2 version 2.4.5 or higher (or 2.5+
+if you want to use :mod:`django.contrib.postgres`).
 
 Support for MySQL versions older than 5.5
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ 3 - 3
tests/backends/tests.py

@@ -289,14 +289,14 @@ class PostgreSQLTests(TestCase):
             self.assertIn('::text', do.lookup_cast(lookup))
 
     def test_correct_extraction_psycopg2_version(self):
-        from django.db.backends.postgresql_psycopg2.base import DatabaseWrapper
+        from django.db.backends.postgresql_psycopg2.base import psycopg2_version
         version_path = 'django.db.backends.postgresql_psycopg2.base.Database.__version__'
 
         with mock.patch(version_path, '2.6.9'):
-            self.assertEqual(DatabaseWrapper.psycopg2_version.__get__(self), (2, 6, 9))
+            self.assertEqual(psycopg2_version(), (2, 6, 9))
 
         with mock.patch(version_path, '2.5.dev0'):
-            self.assertEqual(DatabaseWrapper.psycopg2_version.__get__(self), (2, 5))
+            self.assertEqual(psycopg2_version(), (2, 5))
 
 
 class DateQuotingTest(TestCase):

+ 1 - 1
tests/requirements/postgres.txt

@@ -1 +1 @@
-psycopg2
+psycopg2>=2.5