I have a codebase running Django 4.0.9 that passes all pytest unit tests. I am using python 3.9.6. Regardless of whether I use python 3.9, 3.10 or 3.11, when I upgrade the Django version from 4.0.9 to 4.1.0, about 70 of my pytest unit tests fail with the following error:
FAILED server/apps/task/tests/models/test_task_queryset.py::TestStuckTasks::test_stuck - AttributeError: 'NoneType' object has no attribute 'startswith'
When I downgrade back to Django 4.0.9, all the tests pass again. The behavior is very consistent.
Given below is detailed stack trace. I noticed at least one model with a missing column field definition that was present in the database. My guess is that this mismatch causes the “name” parameter to quote_name() to be None and that causes this error. Why is this a problem only with Django 4.1.0 and not with Django 4.0.9? How can I fix it without touching any of the models? I am able to upgrade to Django 4.0.10 without issues. This error is not seen with Django 4.0.9 or Django 4.0.10
Here is the detailed stack trace:
server/apps/task/tests/models/test_task_queryset.py:18:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/base.py:40: in __call__
return cls.create(**kwargs)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/base.py:528: in create
return cls._generate(enums.CREATE_STRATEGY, kwargs)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/django.py:117: in _generate
return super()._generate(strategy, params)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/base.py:465: in _generate
return step.build()
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/builder.py:258: in build
step.resolve(pre)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/builder.py:199: in resolve
self.attributes[field_name] = getattr(self.stub, field_name)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/builder.py:344: in __getattr__
value = value.evaluate_pre(
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/declarations.py:48: in evaluate_pre
return self.evaluate(instance, step, context)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/declarations.py:395: in evaluate
return step.recurse(subfactory, extra, force_sequence=force_sequence)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/builder.py:216: in recurse
return builder.build(parent_step=self, force_sequence=force_sequence)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/builder.py:262: in build
instance = self.factory_meta.instantiate(
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/base.py:317: in instantiate
return self.factory._create(model, *args, **kwargs)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/django.py:163: in _create
return cls._get_or_create(model_class, *args, **kwargs)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/factory/django.py:140: in _get_or_create
instance, _created = manager.get_or_create(*args, **key_fields)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/manager.py:85: in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/query.py:928: in get_or_create
return self.get(**kwargs), False
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/query.py:646: in get
num = len(clone)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/query.py:376: in __len__
self._fetch_all()
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/query.py:1866: in _fetch_all
self._result_cache = list(self._iterable_class(self))
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/query.py:87: in __iter__
results = compiler.execute_sql(
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/sql/compiler.py:1382: in execute_sql
sql, params = self.as_sql()
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/sql/compiler.py:615: in as_sql
self.compile(self.where) if self.where is not None else ("", [])
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/sql/compiler.py:503: in compile
sql, params = node.as_sql(self, self.connection)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/sql/where.py:112: in as_sql
sql, params = compiler.compile(child)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/sql/compiler.py:503: in compile
sql, params = node.as_sql(self, self.connection)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/lookups.py:357: in as_sql
return super().as_sql(compiler, connection)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/lookups.py:224: in as_sql
lhs_sql, params = self.process_lhs(compiler, connection)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/lookups.py:214: in process_lhs
lhs_sql, params = super().process_lhs(compiler, connection, lhs)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/lookups.py:102: in process_lhs
sql, params = compiler.compile(lhs)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/sql/compiler.py:503: in compile
sql, params = node.as_sql(self, self.connection)
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/expressions.py:1109: in as_sql
sql = ".".join(map(compiler.quote_name_unless_alias, identifiers))
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/models/sql/compiler.py:494: in quote_name_unless_alias
r = self.connection.ops.quote_name(name)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <django.db.backends.postgresql.operations.DatabaseOperations object at 0x108aca6e0>, name = None
def quote_name(self, name):
> if name.startswith('"') and name.endswith('"'):
E AttributeError: 'NoneType' object has no attribute 'startswith'
../../../.pyenv/versions/python3-10/lib/python3.10/site-packages/django/db/backends/postgresql/operations.py:163: AttributeError
I also tried updating other packages like factory-boy, pytest-django, pytest, pytest-mock. The upgrade of those other packages I tried had no effect. The only package that causes this error is Django==4.1.0