From 94001421321bd8808c4027a72aa32a1eef005764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anssi=20K=C3=A4=C3=A4ri=C3=A4inen?= Date: Sun, 15 Sep 2013 10:12:16 +0300 Subject: [PATCH] Fixed #21109 -- made db cursor error wrapping faster --- django/db/backends/__init__.py | 11 ++++++----- django/db/backends/utils.py | 16 ++++++++++------ django/db/utils.py | 3 ++- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index 49d6b80ae4..ae9fdbba54 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -122,29 +122,29 @@ class BaseDatabaseWrapper(object): Guarantees that a connection to the database is established. """ if self.connection is None: - with self.wrap_database_errors(): + with self.wrap_database_errors: self.connect() ##### Backend-specific wrappers for PEP-249 connection methods ##### def _cursor(self): self.ensure_connection() - with self.wrap_database_errors(): + with self.wrap_database_errors: return self.create_cursor() def _commit(self): if self.connection is not None: - with self.wrap_database_errors(): + with self.wrap_database_errors: return self.connection.commit() def _rollback(self): if self.connection is not None: - with self.wrap_database_errors(): + with self.wrap_database_errors: return self.connection.rollback() def _close(self): if self.connection is not None: - with self.wrap_database_errors(): + with self.wrap_database_errors: return self.connection.close() ##### Generic wrappers for PEP-249 connection methods ##### @@ -484,6 +484,7 @@ class BaseDatabaseWrapper(object): ##### Miscellaneous ##### + @cached_property def wrap_database_errors(self): """ Context manager and decorator that re-throws backend-specific database diff --git a/django/db/backends/utils.py b/django/db/backends/utils.py index f8157c50e7..0e2aa4503e 100644 --- a/django/db/backends/utils.py +++ b/django/db/backends/utils.py @@ -19,13 +19,17 @@ class CursorWrapper(object): self.cursor = cursor self.db = db + SET_DIRTY_ATTRS = frozenset(['execute', 'executemany', 'callproc']) + WRAP_ERROR_ATTRS = frozenset([ + 'callproc', 'close', 'execute', 'executemany', + 'fetchone', 'fetchmany', 'fetchall', 'nextset']) + def __getattr__(self, attr): - if attr in ('execute', 'executemany', 'callproc'): + if attr in CursorWrapper.SET_DIRTY_ATTRS: self.db.set_dirty() cursor_attr = getattr(self.cursor, attr) - if attr in ('callproc', 'close', 'execute', 'executemany', - 'fetchone', 'fetchmany', 'fetchall', 'nextset'): - return self.db.wrap_database_errors()(cursor_attr) + if attr in CursorWrapper.WRAP_ERROR_ATTRS: + return self.db.wrap_database_errors(cursor_attr) else: return cursor_attr @@ -39,7 +43,7 @@ class CursorDebugWrapper(CursorWrapper): self.db.set_dirty() start = time() try: - with self.db.wrap_database_errors(): + with self.db.wrap_database_errors: if params is None: # params default might be backend specific return self.cursor.execute(sql) @@ -60,7 +64,7 @@ class CursorDebugWrapper(CursorWrapper): self.db.set_dirty() start = time() try: - with self.db.wrap_database_errors(): + with self.db.wrap_database_errors: return self.cursor.executemany(sql, param_list) finally: stop = time() diff --git a/django/db/utils.py b/django/db/utils.py index bcfb06f584..100fc5e878 100644 --- a/django/db/utils.py +++ b/django/db/utils.py @@ -94,7 +94,8 @@ class DatabaseErrorWrapper(object): six.reraise(dj_exc_type, dj_exc_value, traceback) def __call__(self, func): - @wraps(func) + # Note that we are intentionally not using @wraps here for performance + # reasons. Refs #21109. def inner(*args, **kwargs): with self: return func(*args, **kwargs)