Ticket #17671: django-ticket17671.diff

File django-ticket17671.diff, 3.7 KB (added by manfre, 3 years ago)

context manager shortcut without pass-thru

  • django/db/backends/util.py

    diff --git a/django/db/backends/util.py b/django/db/backends/util.py
    index 32e0f4f..30f0a16 100644
    a b class CursorWrapper(object): 
    3030    def __iter__(self):
    3131        return iter(self.cursor)
    3232
     33    def __enter__(self):
     34        return self
     35
     36    def __exit__(self, type, value, traceback):
     37        # Ticket #17671 - Close instead of passing thru to avoid backend
     38        # specific behavior.
     39        self.cursor.close()
    3340
    3441class CursorDebugWrapper(CursorWrapper):
    3542
  • docs/releases/1.5.txt

    diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt
    index 33f5003..900f692 100644
    a b Unicode parameters (``password``, ``salt`` or ``encoded``). If any of the 
    144144hashing methods need byte strings, you can use the
    145145:func:`~django.utils.encoding.smart_str` utility to encode the strings.
    146146
     147Using database cursors as context managers
     148~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     149
     150Prior to Python 2.6, database cursors could be used as a context manager. The
     151specific backend's cursor defined the behavior of the context manager. The
     152behavior of magic method lookups was changed with Python 2.7 and cursors were
     153no longer usable as context managers.
     154
     155Django 1.5 allows a cursor to be used as a context manager that is a shortcut
     156for the following, instead of backend specific behavior.
     157
     158.. code-block:: python
     159
     160    c = connection.cursor()
     161    try:
     162        c.execute(...)
     163    finally:
     164        c.close()
     165
    147166Features deprecated in 1.5
    148167==========================
    149168
  • docs/topics/db/sql.txt

    diff --git a/docs/topics/db/sql.txt b/docs/topics/db/sql.txt
    index 19daffd..577c58b 100644
    a b Here is an example of the difference between the two:: 
    262262    [{'parent_id': None, 'id': 54360982L}, {'parent_id': None, 'id': 54360880L}]
    263263
    264264
     265
    265266.. _transactions-and-raw-sql:
    266267
    267268Transactions and raw SQL
    technique, the underlying database library will automatically add quotes and 
    290291escaping to your parameter(s) as necessary. (Also note that Django expects the
    291292``"%s"`` placeholder, *not* the ``"?"`` placeholder, which is used by the SQLite
    292293Python bindings. This is for the sake of consistency and sanity.)
     294
     295.. versionchanged:: 1.5
     296
     297:pep:`249` does not state whether a cursor should be usable as a context
     298manager. Prior to Python 2.7, a cursor was usable as a context manager due
     299an unexpected behavior in magic method lookups (`Python ticket #9220`_).
     300Django 1.5 explicitly added support to allow using a cursor as context
     301manager.
     302
     303.. _`Python ticket #9220`: http://bugs.python.org/issue9220
     304
     305Using a cursor as a context manager:
     306
     307.. code-block:: python
     308
     309    with connection.cursor() as c:
     310        c.execute(...)
     311
     312is equivalent to:
     313
     314.. code-block:: python
     315
     316    c = connection.cursor()
     317    try:
     318        c.execute(...)
     319    finally:
     320        c.close()
  • tests/regressiontests/backends/tests.py

    diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
    index 109e1a5..2258388 100644
    a b class BackendTestCase(TestCase): 
    416416        with self.assertRaises(DatabaseError):
    417417            cursor.execute(query)
    418418
     419    def test_cursor_contextmanager(self):
     420        """
     421        Test that cursors can be used as a context manager
     422        """
     423        with connection.cursor() as cursor:
     424            from django.db.backends.util import CursorWrapper
     425            self.assertTrue(isinstance(cursor, CursorWrapper))
     426
    419427# We don't make these tests conditional because that means we would need to
    420428# check and differentiate between:
    421429# * MySQL+InnoDB, MySQL+MYISAM (something we currently can't do).
Back to Top