diff options
| author | Jon Dufresne <jon.dufresne@gmail.com> | 2017-11-28 05:12:28 -0800 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2017-11-28 11:28:09 -0500 |
| commit | 7a6fbf36b1fdb8978ea0842075ccce83bcd63789 (patch) | |
| tree | a48e72be7e31066d92de43a85458b0bfb7e2cfcd /django | |
| parent | 3308085838f520db49f606b72345a301c1cf2a3e (diff) | |
Fixed #28853 -- Updated connection.cursor() uses to use a context manager.
Diffstat (limited to 'django')
| -rw-r--r-- | django/contrib/gis/db/backends/mysql/introspection.py | 6 | ||||
| -rw-r--r-- | django/contrib/gis/db/backends/oracle/introspection.py | 6 | ||||
| -rw-r--r-- | django/contrib/gis/db/backends/postgis/introspection.py | 12 | ||||
| -rw-r--r-- | django/contrib/gis/db/backends/spatialite/introspection.py | 6 | ||||
| -rw-r--r-- | django/db/backends/base/base.py | 5 | ||||
| -rw-r--r-- | django/db/backends/base/introspection.py | 29 | ||||
| -rw-r--r-- | django/db/backends/mysql/base.py | 57 | ||||
| -rw-r--r-- | django/db/backends/oracle/creation.py | 147 | ||||
| -rw-r--r-- | django/db/backends/sqlite3/base.py | 58 | ||||
| -rw-r--r-- | django/db/migrations/executor.py | 3 | ||||
| -rw-r--r-- | django/test/testcases.py | 6 |
11 files changed, 155 insertions, 180 deletions
diff --git a/django/contrib/gis/db/backends/mysql/introspection.py b/django/contrib/gis/db/backends/mysql/introspection.py index 364cdeecfe..ba125ec4af 100644 --- a/django/contrib/gis/db/backends/mysql/introspection.py +++ b/django/contrib/gis/db/backends/mysql/introspection.py @@ -11,8 +11,7 @@ class MySQLIntrospection(DatabaseIntrospection): data_types_reverse[FIELD_TYPE.GEOMETRY] = 'GeometryField' def get_geometry_type(self, table_name, geo_col): - cursor = self.connection.cursor() - try: + with self.connection.cursor() as cursor: # In order to get the specific geometry type of the field, # we introspect on the table definition using `DESCRIBE`. cursor.execute('DESCRIBE %s' % @@ -27,9 +26,6 @@ class MySQLIntrospection(DatabaseIntrospection): field_type = OGRGeomType(typ).django field_params = {} break - finally: - cursor.close() - return field_type, field_params def supports_spatial_index(self, cursor, table_name): diff --git a/django/contrib/gis/db/backends/oracle/introspection.py b/django/contrib/gis/db/backends/oracle/introspection.py index 446dc78216..7f4f886a34 100644 --- a/django/contrib/gis/db/backends/oracle/introspection.py +++ b/django/contrib/gis/db/backends/oracle/introspection.py @@ -11,8 +11,7 @@ class OracleIntrospection(DatabaseIntrospection): data_types_reverse[cx_Oracle.OBJECT] = 'GeometryField' def get_geometry_type(self, table_name, geo_col): - cursor = self.connection.cursor() - try: + with self.connection.cursor() as cursor: # Querying USER_SDO_GEOM_METADATA to get the SRID and dimension information. try: cursor.execute( @@ -40,7 +39,4 @@ class OracleIntrospection(DatabaseIntrospection): dim = dim.size() if dim != 2: field_params['dim'] = dim - finally: - cursor.close() - return field_type, field_params diff --git a/django/contrib/gis/db/backends/postgis/introspection.py b/django/contrib/gis/db/backends/postgis/introspection.py index 3a90ebf5c5..97fa7480e6 100644 --- a/django/contrib/gis/db/backends/postgis/introspection.py +++ b/django/contrib/gis/db/backends/postgis/introspection.py @@ -59,15 +59,11 @@ class PostGISIntrospection(DatabaseIntrospection): # to query the PostgreSQL pg_type table corresponding to the # PostGIS custom data types. oid_sql = 'SELECT "oid" FROM "pg_type" WHERE "typname" = %s' - cursor = self.connection.cursor() - try: + with self.connection.cursor() as cursor: for field_type in field_types: cursor.execute(oid_sql, (field_type[0],)) for result in cursor.fetchall(): postgis_types[result[0]] = field_type[1] - finally: - cursor.close() - return postgis_types def get_field_type(self, data_type, description): @@ -88,8 +84,7 @@ class PostGISIntrospection(DatabaseIntrospection): PointField or a PolygonField). Thus, this routine queries the PostGIS metadata tables to determine the geometry type. """ - cursor = self.connection.cursor() - try: + with self.connection.cursor() as cursor: try: # First seeing if this geometry column is in the `geometry_columns` cursor.execute('SELECT "coord_dimension", "srid", "type" ' @@ -122,7 +117,4 @@ class PostGISIntrospection(DatabaseIntrospection): field_params['srid'] = srid if dim != 2: field_params['dim'] = dim - finally: - cursor.close() - return field_type, field_params diff --git a/django/contrib/gis/db/backends/spatialite/introspection.py b/django/contrib/gis/db/backends/spatialite/introspection.py index 98fda427d0..5cd5613b69 100644 --- a/django/contrib/gis/db/backends/spatialite/introspection.py +++ b/django/contrib/gis/db/backends/spatialite/introspection.py @@ -25,8 +25,7 @@ class SpatiaLiteIntrospection(DatabaseIntrospection): data_types_reverse = GeoFlexibleFieldLookupDict() def get_geometry_type(self, table_name, geo_col): - cursor = self.connection.cursor() - try: + with self.connection.cursor() as cursor: # Querying the `geometry_columns` table to get additional metadata. cursor.execute('SELECT coord_dimension, srid, geometry_type ' 'FROM geometry_columns ' @@ -55,9 +54,6 @@ class SpatiaLiteIntrospection(DatabaseIntrospection): field_params['srid'] = srid if (isinstance(dim, str) and 'Z' in dim) or dim == 3: field_params['dim'] = 3 - finally: - cursor.close() - return field_type, field_params def get_constraints(self, cursor, table_name): diff --git a/django/db/backends/base/base.py b/django/db/backends/base/base.py index 468eb16e14..53c3c30063 100644 --- a/django/db/backends/base/base.py +++ b/django/db/backends/base/base.py @@ -573,11 +573,10 @@ class BaseDatabaseWrapper: Provide a cursor: with self.temporary_connection() as cursor: ... """ must_close = self.connection is None - cursor = self.cursor() try: - yield cursor + with self.cursor() as cursor: + yield cursor finally: - cursor.close() if must_close: self.close() diff --git a/django/db/backends/base/introspection.py b/django/db/backends/base/introspection.py index 154ae22bf1..8fe8966a21 100644 --- a/django/db/backends/base/introspection.py +++ b/django/db/backends/base/introspection.py @@ -116,21 +116,20 @@ class BaseDatabaseIntrospection: from django.db import router sequence_list = [] - cursor = self.connection.cursor() - - for app_config in apps.get_app_configs(): - for model in router.get_migratable_models(app_config, self.connection.alias): - if not model._meta.managed: - continue - if model._meta.swapped: - continue - sequence_list.extend(self.get_sequences(cursor, model._meta.db_table, model._meta.local_fields)) - for f in model._meta.local_many_to_many: - # If this is an m2m using an intermediate table, - # we don't need to reset the sequence. - if f.remote_field.through is None: - sequence = self.get_sequences(cursor, f.m2m_db_table()) - sequence_list.extend(sequence or [{'table': f.m2m_db_table(), 'column': None}]) + with self.connection.cursor() as cursor: + for app_config in apps.get_app_configs(): + for model in router.get_migratable_models(app_config, self.connection.alias): + if not model._meta.managed: + continue + if model._meta.swapped: + continue + sequence_list.extend(self.get_sequences(cursor, model._meta.db_table, model._meta.local_fields)) + for f in model._meta.local_many_to_many: + # If this is an m2m using an intermediate table, + # we don't need to reset the sequence. + if f.remote_field.through is None: + sequence = self.get_sequences(cursor, f.m2m_db_table()) + sequence_list.extend(sequence or [{'table': f.m2m_db_table(), 'column': None}]) return sequence_list def get_sequences(self, cursor, table_name, table_fields=()): diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py index abf8f55736..6b82afc45d 100644 --- a/django/db/backends/mysql/base.py +++ b/django/db/backends/mysql/base.py @@ -294,36 +294,37 @@ class DatabaseWrapper(BaseDatabaseWrapper): Backends can override this method if they can more directly apply constraint checking (e.g. via "SET CONSTRAINTS ALL IMMEDIATE") """ - cursor = self.cursor() - if table_names is None: - table_names = self.introspection.table_names(cursor) - for table_name in table_names: - primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name) - if not primary_key_column_name: - continue - key_columns = self.introspection.get_key_columns(cursor, table_name) - for column_name, referenced_table_name, referenced_column_name in key_columns: - cursor.execute( - """ - SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING - LEFT JOIN `%s` as REFERRED - ON (REFERRING.`%s` = REFERRED.`%s`) - WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL - """ % ( - primary_key_column_name, column_name, table_name, - referenced_table_name, column_name, referenced_column_name, - column_name, referenced_column_name, - ) - ) - for bad_row in cursor.fetchall(): - raise utils.IntegrityError( - "The row in table '%s' with primary key '%s' has an invalid " - "foreign key: %s.%s contains a value '%s' that does not have a corresponding value in %s.%s." - % ( - table_name, bad_row[0], table_name, column_name, - bad_row[1], referenced_table_name, referenced_column_name, + with self.cursor() as cursor: + if table_names is None: + table_names = self.introspection.table_names(cursor) + for table_name in table_names: + primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name) + if not primary_key_column_name: + continue + key_columns = self.introspection.get_key_columns(cursor, table_name) + for column_name, referenced_table_name, referenced_column_name in key_columns: + cursor.execute( + """ + SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING + LEFT JOIN `%s` as REFERRED + ON (REFERRING.`%s` = REFERRED.`%s`) + WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL + """ % ( + primary_key_column_name, column_name, table_name, + referenced_table_name, column_name, referenced_column_name, + column_name, referenced_column_name, ) ) + for bad_row in cursor.fetchall(): + raise utils.IntegrityError( + "The row in table '%s' with primary key '%s' has an invalid " + "foreign key: %s.%s contains a value '%s' that does not " + "have a corresponding value in %s.%s." + % ( + table_name, bad_row[0], table_name, column_name, + bad_row[1], referenced_table_name, referenced_column_name, + ) + ) def is_usable(self): try: diff --git a/django/db/backends/oracle/creation.py b/django/db/backends/oracle/creation.py index fe053c54f7..aa57e6a6ab 100644 --- a/django/db/backends/oracle/creation.py +++ b/django/db/backends/oracle/creation.py @@ -30,75 +30,72 @@ class DatabaseCreation(BaseDatabaseCreation): def _create_test_db(self, verbosity=1, autoclobber=False, keepdb=False): parameters = self._get_test_db_params() - cursor = self._maindb_connection.cursor() - if self._test_database_create(): - try: - self._execute_test_db_creation(cursor, parameters, verbosity, keepdb) - except Exception as e: - if 'ORA-01543' not in str(e): - # All errors except "tablespace already exists" cancel tests - sys.stderr.write("Got an error creating the test database: %s\n" % e) - sys.exit(2) - if not autoclobber: - confirm = input( - "It appears the test database, %s, already exists. " - "Type 'yes' to delete it, or 'no' to cancel: " % parameters['user']) - if autoclobber or confirm == 'yes': - if verbosity >= 1: - print("Destroying old test database for alias '%s'..." % self.connection.alias) - try: - self._execute_test_db_destruction(cursor, parameters, verbosity) - except DatabaseError as e: - if 'ORA-29857' in str(e): - self._handle_objects_preventing_db_destruction(cursor, parameters, - verbosity, autoclobber) - else: - # Ran into a database error that isn't about leftover objects in the tablespace + with self._maindb_connection.cursor() as cursor: + if self._test_database_create(): + try: + self._execute_test_db_creation(cursor, parameters, verbosity, keepdb) + except Exception as e: + if 'ORA-01543' not in str(e): + # All errors except "tablespace already exists" cancel tests + sys.stderr.write("Got an error creating the test database: %s\n" % e) + sys.exit(2) + if not autoclobber: + confirm = input( + "It appears the test database, %s, already exists. " + "Type 'yes' to delete it, or 'no' to cancel: " % parameters['user']) + if autoclobber or confirm == 'yes': + if verbosity >= 1: + print("Destroying old test database for alias '%s'..." % self.connection.alias) + try: + self._execute_test_db_destruction(cursor, parameters, verbosity) + except DatabaseError as e: + if 'ORA-29857' in str(e): + self._handle_objects_preventing_db_destruction(cursor, parameters, + verbosity, autoclobber) + else: + # Ran into a database error that isn't about leftover objects in the tablespace + sys.stderr.write("Got an error destroying the old test database: %s\n" % e) + sys.exit(2) + except Exception as e: sys.stderr.write("Got an error destroying the old test database: %s\n" % e) sys.exit(2) - except Exception as e: - sys.stderr.write("Got an error destroying the old test database: %s\n" % e) - sys.exit(2) - try: - self._execute_test_db_creation(cursor, parameters, verbosity, keepdb) - except Exception as e: - sys.stderr.write("Got an error recreating the test database: %s\n" % e) - sys.exit(2) - else: - print("Tests cancelled.") - sys.exit(1) + try: + self._execute_test_db_creation(cursor, parameters, verbosity, keepdb) + except Exception as e: + sys.stderr.write("Got an error recreating the test database: %s\n" % e) + sys.exit(2) + else: + print("Tests cancelled.") + sys.exit(1) - if self._test_user_create(): - if verbosity >= 1: - print("Creating test user...") - try: - self._create_test_user(cursor, parameters, verbosity, keepdb) - except Exception as e: - if 'ORA-01920' not in str(e): - # All errors except "user already exists" cancel tests - sys.stderr.write("Got an error creating the test user: %s\n" % e) - sys.exit(2) - if not autoclobber: - confirm = input( - "It appears the test user, %s, already exists. Type " - "'yes' to delete it, or 'no' to cancel: " % parameters['user']) - if autoclobber or confirm == 'yes': - try: - if verbosity >= 1: - print("Destroying old test user...") - self._destroy_test_user(cursor, parameters, verbosity) - if verbosity >= 1: - print("Creating test user...") - self._create_test_user(cursor, parameters, verbosity, keepdb) - except Exception as e: - sys.stderr.write("Got an error recreating the test user: %s\n" % e) + if self._test_user_create(): + if verbosity >= 1: + print("Creating test user...") + try: + self._create_test_user(cursor, parameters, verbosity, keepdb) + except Exception as e: + if 'ORA-01920' not in str(e): + # All errors except "user already exists" cancel tests + sys.stderr.write("Got an error creating the test user: %s\n" % e) sys.exit(2) - else: - print("Tests cancelled.") - sys.exit(1) - - # Cursor must be closed before closing connection. - cursor.close() + if not autoclobber: + confirm = input( + "It appears the test user, %s, already exists. Type " + "'yes' to delete it, or 'no' to cancel: " % parameters['user']) + if autoclobber or confirm == 'yes': + try: + if verbosity >= 1: + print("Destroying old test user...") + self._destroy_test_user(cursor, parameters, verbosity) + if verbosity >= 1: + print("Creating test user...") + self._create_test_user(cursor, parameters, verbosity, keepdb) + except Exception as e: + sys.stderr.write("Got an error recreating the test user: %s\n" % e) + sys.exit(2) + else: + print("Tests cancelled.") + sys.exit(1) self._maindb_connection.close() # done with main user -- test user and tablespaces created self._switch_to_test_user(parameters) return self.connection.settings_dict['NAME'] @@ -175,17 +172,15 @@ class DatabaseCreation(BaseDatabaseCreation): self.connection.settings_dict['PASSWORD'] = self.connection.settings_dict['SAVED_PASSWORD'] self.connection.close() parameters = self._get_test_db_params() - cursor = self._maindb_connection.cursor() - if self._test_user_create(): - if verbosity >= 1: - print('Destroying test user...') - self._destroy_test_user(cursor, parameters, verbosity) - if self._test_database_create(): - if verbosity >= 1: - print('Destroying test database tables...') - self._execute_test_db_destruction(cursor, parameters, verbosity) - # Cursor must be closed before closing connection. - cursor.close() + with self._maindb_connection.cursor() as cursor: + if self._test_user_create(): + if verbosity >= 1: + print('Destroying test user...') + self._destroy_test_user(cursor, parameters, verbosity) + if self._test_database_create(): + if verbosity >= 1: + print('Destroying test database tables...') + self._execute_test_db_destruction(cursor, parameters, verbosity) self._maindb_connection.close() def _execute_test_db_creation(self, cursor, parameters, verbosity, keepdb=False): diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py index 40b205cf30..13f9a575e2 100644 --- a/django/db/backends/sqlite3/base.py +++ b/django/db/backends/sqlite3/base.py @@ -237,37 +237,37 @@ class DatabaseWrapper(BaseDatabaseWrapper): Backends can override this method if they can more directly apply constraint checking (e.g. via "SET CONSTRAINTS ALL IMMEDIATE") """ - cursor = self.cursor() - if table_names is None: - table_names = self.introspection.table_names(cursor) - for table_name in table_names: - primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name) - if not primary_key_column_name: - continue - key_columns = self.introspection.get_key_columns(cursor, table_name) - for column_name, referenced_table_name, referenced_column_name in key_columns: - cursor.execute( - """ - SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING - LEFT JOIN `%s` as REFERRED - ON (REFERRING.`%s` = REFERRED.`%s`) - WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL - """ - % ( - primary_key_column_name, column_name, table_name, - referenced_table_name, column_name, referenced_column_name, - column_name, referenced_column_name, - ) - ) - for bad_row in cursor.fetchall(): - raise utils.IntegrityError( - "The row in table '%s' with primary key '%s' has an " - "invalid foreign key: %s.%s contains a value '%s' that " - "does not have a corresponding value in %s.%s." % ( - table_name, bad_row[0], table_name, column_name, - bad_row[1], referenced_table_name, referenced_column_name, + with self.cursor() as cursor: + if table_names is None: + table_names = self.introspection.table_names(cursor) + for table_name in table_names: + primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name) + if not primary_key_column_name: + continue + key_columns = self.introspection.get_key_columns(cursor, table_name) + for column_name, referenced_table_name, referenced_column_name in key_columns: + cursor.execute( + """ + SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING + LEFT JOIN `%s` as REFERRED + ON (REFERRING.`%s` = REFERRED.`%s`) + WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL + """ + % ( + primary_key_column_name, column_name, table_name, + referenced_table_name, column_name, referenced_column_name, + column_name, referenced_column_name, ) ) + for bad_row in cursor.fetchall(): + raise utils.IntegrityError( + "The row in table '%s' with primary key '%s' has an " + "invalid foreign key: %s.%s contains a value '%s' that " + "does not have a corresponding value in %s.%s." % ( + table_name, bad_row[0], table_name, column_name, + bad_row[1], referenced_table_name, referenced_column_name, + ) + ) def is_usable(self): return True diff --git a/django/db/migrations/executor.py b/django/db/migrations/executor.py index ea7bc70db3..ebaf75634b 100644 --- a/django/db/migrations/executor.py +++ b/django/db/migrations/executor.py @@ -322,7 +322,8 @@ class MigrationExecutor: apps = after_state.apps found_create_model_migration = False found_add_field_migration = False - existing_table_names = self.connection.introspection.table_names(self.connection.cursor()) + with self.connection.cursor() as cursor: + existing_table_names = self.connection.introspection.table_names(cursor) # Make sure all create model and add field operations are done for operation in migration.operations: if isinstance(operation, migrations.CreateModel): diff --git a/django/test/testcases.py b/django/test/testcases.py index afab58f2dc..4c32c87da5 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -852,9 +852,9 @@ class TransactionTestCase(SimpleTestCase): no_style(), conn.introspection.sequence_list()) if sql_list: with transaction.atomic(using=db_name): - cursor = conn.cursor() - for sql in sql_list: - cursor.execute(sql) + with conn.cursor() as cursor: + for sql in sql_list: + cursor.execute(sql) def _fixture_setup(self): for db_name in self._databases_names(include_mirrors=False): |
