diff options
author | Andrew Godwin <andrew@aeracode.org> | 2019-04-12 06:15:18 -0700 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2019-06-20 12:29:43 +0200 |
commit | a415ce70bef6d91036b00dd2c8544aed7aeeaaed (patch) | |
tree | 3583cef22e9b56d2ed52456ab586d9c47620bc51 /django/db/backends/postgresql/base.py | |
parent | cce47ff65a4dd3786c049ec14ee889e128ca7de9 (diff) | |
download | django-a415ce70bef6d91036b00dd2c8544aed7aeeaaed.tar.gz |
Fixed #30451 -- Added ASGI handler and coroutine-safety.
This adds an ASGI handler, asgi.py file for the default project layout,
a few async utilities and adds async-safety to many parts of Django.
Diffstat (limited to 'django/db/backends/postgresql/base.py')
-rw-r--r-- | django/db/backends/postgresql/base.py | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py index 6f8e06fe23..7e34a3a177 100644 --- a/django/db/backends/postgresql/base.py +++ b/django/db/backends/postgresql/base.py @@ -4,6 +4,7 @@ PostgreSQL database backend for Django. Requires psycopg 2: http://initd.org/projects/psycopg2 """ +import asyncio import threading import warnings @@ -15,6 +16,7 @@ from django.db.backends.utils import ( CursorDebugWrapper as BaseCursorDebugWrapper, ) from django.db.utils import DatabaseError as WrappedDatabaseError +from django.utils.asyncio import async_unsafe from django.utils.functional import cached_property from django.utils.safestring import SafeString from django.utils.version import get_version_tuple @@ -177,6 +179,7 @@ class DatabaseWrapper(BaseDatabaseWrapper): conn_params['port'] = settings_dict['PORT'] return conn_params + @async_unsafe def get_new_connection(self, conn_params): connection = Database.connect(**conn_params) @@ -217,6 +220,7 @@ class DatabaseWrapper(BaseDatabaseWrapper): if not self.get_autocommit(): self.connection.commit() + @async_unsafe def create_cursor(self, name=None): if name: # In autocommit mode, the cursor will be used outside of a @@ -227,12 +231,34 @@ class DatabaseWrapper(BaseDatabaseWrapper): cursor.tzinfo_factory = utc_tzinfo_factory if settings.USE_TZ else None return cursor + @async_unsafe def chunked_cursor(self): self._named_cursor_idx += 1 + # Get the current async task + # Note that right now this is behind @async_unsafe, so this is + # unreachable, but in future we'll start loosening this restriction. + # For now, it's here so that every use of "threading" is + # also async-compatible. + try: + if hasattr(asyncio, 'current_task'): + # Python 3.7 and up + current_task = asyncio.current_task() + else: + # Python 3.6 + current_task = asyncio.Task.current_task() + except RuntimeError: + current_task = None + # Current task can be none even if the current_task call didn't error + if current_task: + task_ident = str(id(current_task)) + else: + task_ident = 'sync' + # Use that and the thread ident to get a unique name return self._cursor( - name='_django_curs_%d_%d' % ( - # Avoid reusing name in other threads + name='_django_curs_%d_%s_%d' % ( + # Avoid reusing name in other threads / tasks threading.current_thread().ident, + task_ident, self._named_cursor_idx, ) ) |