Opened 3 years ago

Closed 21 months ago

#22279 closed Bug (fixed)

AttributeError: 'db.backends.dummy.base.DatabaseWrapper' object has no attribute 'Database'

Reported by: Daniel Hahler Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I am getting a AttributeError: 'DatabaseWrapper' object has no attribute 'Database' exception, while trying to setup/use py.test with Django.

DJANGO_SECRET_KEY=foo DJANGO_SETTINGS_MODULE=config.settings PYTHONPATH=. py.test -s --ipdb project/model/tests.py

self.wrapper is django.db.backends.dummy.base.DatabaseWrapper.

> …/django-master/django/db/utils.py(86)__exit__()
     85         ):
---> 86             db_exc_type = getattr(self.wrapper.Database, dj_exc_type.__name__)
     87             if issubclass(exc_type, db_exc_type):

ipdb> bt
  …/django-master/django/test/testcases.py(857)<genexpr>()
    855     """
    856     return all(conn.features.supports_transactions
--> 857                for conn in connections.all())
    858 
    859 

  …/django-master/django/utils/functional.py(55)__get__()
     53         if instance is None:
     54             return self
---> 55         res = instance.__dict__[self.func.__name__] = self.func(instance)
     56         return res
     57 

  …/django-master/django/db/backends/__init__.py(701)supports_transactions()
    699                 self.connection.commit()
    700         finally:
--> 701             self.connection.leave_transaction_management()
    702         return count == 0
    703 

  …/django-master/django/db/backends/__init__.py(320)leave_transaction_management()
    318                 "Transaction managed block ended with pending COMMIT/ROLLBACK")
    319 
--> 320         if managed == self.get_autocommit():
    321             self.set_autocommit(not managed)
    322 

  …/django-master/django/db/backends/__init__.py(327)get_autocommit()
    325         Check the autocommit state.
    326         """
--> 327         self.ensure_connection()
    328         return self.autocommit
    329 

  …/django-master/django/db/backends/__init__.py(124)ensure_connection()
    122         if self.connection is None:
    123             with self.wrap_database_errors:
--> 124                 self.connect()
    125 
    126     ##### Backend-specific wrappers for PEP-249 connection methods #####

> …/django-master/django/db/utils.py(86)__exit__()
     84                 Error,
     85         ):
---> 86             db_exc_type = getattr(self.wrapper.Database, dj_exc_type.__name__)
     87             if issubclass(exc_type, db_exc_type):
     88                 dj_exc_value = dj_exc_type(*exc_value.args)

  …/django-master/django/test/testcases.py(182)__call__()
    180         if not skipped:
    181             try:
--> 182                 self._pre_setup()
    183             except Exception:
    184                 result.addError(self, sys.exc_info())

  …/django-master/django/test/testcases.py(749)_pre_setup()
    747                 flush.Command.emit_post_migrate(verbosity=0, interactive=False, database=db_name)
    748         try:
--> 749             self._fixture_setup()
    750         except Exception:
    751             if self.available_apps is not None:

  …/django-master/django/test/testcases.py(870)_fixture_setup()
    868 
    869     def _fixture_setup(self):
--> 870         if not connections_support_transactions():
    871             return super(TestCase, self)._fixture_setup()
    872 

  …/django-master/django/test/testcases.py(857)connections_support_transactions()
    855     """
    856     return all(conn.features.supports_transactions
--> 857                for conn in connections.all())
    858 
    859 

  …/django-master/django/test/testcases.py(857)<genexpr>()
    855     """
    856     return all(conn.features.supports_transactions
--> 857                for conn in connections.all())
    858 
    859 

  …/django-master/django/utils/functional.py(55)__get__()
     53         if instance is None:
     54             return self
---> 55         res = instance.__dict__[self.func.__name__] = self.func(instance)
     56         return res
     57 

  …/django-master/django/db/backends/__init__.py(701)supports_transactions()
    699                 self.connection.commit()
    700         finally:
--> 701             self.connection.leave_transaction_management()
    702         return count == 0
    703 

  …/django-master/django/db/backends/__init__.py(320)leave_transaction_management()
    318                 "Transaction managed block ended with pending COMMIT/ROLLBACK")
    319 
--> 320         if managed == self.get_autocommit():
    321             self.set_autocommit(not managed)
    322 

  …/django-master/django/db/backends/__init__.py(327)get_autocommit()
    325         Check the autocommit state.
    326         """
--> 327         self.ensure_connection()
    328         return self.autocommit
    329 

  …/django-master/django/db/backends/__init__.py(124)ensure_connection()
    122         if self.connection is None:
    123             with self.wrap_database_errors:
--> 124                 self.connect()
    125 
    126     ##### Backend-specific wrappers for PEP-249 connection methods #####

> …/django-master/django/db/utils.py(86)__exit__()
     84                 Error,
     85         ):
---> 86             db_exc_type = getattr(self.wrapper.Database, dj_exc_type.__name__)
     87             if issubclass(exc_type, db_exc_type):
     88                 dj_exc_value = dj_exc_type(*exc_value.args)

Change History (8)

comment:1 Changed 3 years ago by Tim Graham

Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset
Resolution: needsinfo
Status: newclosed

It's not clear to me that this is a bug in Django, or if it is, how we can reproduce it. More likely, you should first use our support channels to see if others have been able to use py.test with Django. A quick search reveals pytest-django which suggests others have been able successfully integrate the two projects.

https://code.djangoproject.com/wiki/TicketClosingReasons/UseSupportChannels

comment:2 Changed 3 years ago by Daniel Hahler

Resolution: needsinfo
Status: closednew

I am using pytest-django already.

The problem gets triggered, because DATABASES is empty and therefore the dummy database is used.

From DatabaseErrorWrapper:

It must have a Database attribute defining PEP-249 exceptions.

class DatabaseErrorWrapper(object):
    """
    Context manager and decorator that re-throws backend-specific database
    exceptions using Django's common wrappers.
    """

    def __init__(self, wrapper):
        """
        wrapper is a database wrapper.

        It must have a Database attribute defining PEP-249 exceptions.
        """
        self.wrapper = wrapper

comment:3 Changed 3 years ago by Tim Graham

Thanks for the additional info. Can you provide a test case for Django's test suite that isn't dependent on py.test (or at least a sample project we can use to reproduce the error)? Is this a regression on master for something that worked with Django 1.6?

comment:4 Changed 3 years ago by Daniel Hahler

It's rather trivial: create a new project, an app, add a model and tests that use the model (and therefore the database).
Then remove the DATABASES setting, and run the tests.

This is constructed, of course, but I've run into this when DATABASES was not setup correctly by accident - and the error could have been friendlier.

Again, I think that the dummy backend has to provide the Database attribute required by DatabaseErrorWrapper - or it must never get wrapped in the first place (if that's an option).

comment:5 Changed 3 years ago by Aymeric Augustin

Triage Stage: UnreviewedAccepted

comment:6 Changed 21 months ago by Claude Paroz

Has patch: set

comment:7 Changed 21 months ago by Tim Graham

Triage Stage: AcceptedReady for checkin

comment:8 Changed 21 months ago by Claude Paroz <claude@…>

Resolution: fixed
Status: newclosed

In 3c5d1edb39020f549c58e0696b8ab2f03a88d753:

Fixed #22279 -- Prevented dummy backend going through DatabaseErrorWrapper

Thanks Daniel Hahler for the report and Tim Graham for the review.

Note: See TracTickets for help on using tickets.
Back to Top