Closed johnnymetz closed 1 week ago
Background
I recently upgraded to Django 5.1.1 and I'm seeing a PicklingError in my unit tests for all djoser endpoints that send an email.
PicklingError
Here are some minimalist unit tests that are failing (note I'm using pytest-django):
@pytest.mark.django_db def test_create_user(client): url = reverse("user-list") data = { "email": "jj@email.com", "password": "pw123", "re_password": "pw123", } client.post(url, data=data) @pytest.mark.django_db def test_activate_user(client): u = UserFactory(is_active=False) url = reverse("user-activation") data = { "uid": djoser.utils.encode_uid(u.pk), "token": default_token_generator.make_token(u), } client.post(url, data=data) @pytest.mark.django_db def test_reset_password(client): u = UserFactory() url = reverse("user-reset-password-confirm") new_pw = "new_pw" data = { "uid": djoser.utils.encode_uid(u.pk), "token": default_token_generator.make_token(u), "new_password": new_pw, "re_new_password": new_pw, } client.post(url, data=data)
All of these tests fail. Here's the full traceback for the first test (test_create_user):
test_create_user
Traceback (most recent call last): File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) ^^^^^^^^^^^^^^^^^^^^^ File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper return view_func(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/rest_framework/viewsets.py", line 124, in view return self.dispatch(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/rest_framework/views.py", line 509, in dispatch response = self.handle_exception(exc) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/rest_framework/views.py", line 469, in handle_exception self.raise_uncaught_exception(exc) File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception raise exc File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch response = handler(request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/rest_framework/mixins.py", line 19, in create self.perform_create(serializer) File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/djoser/views.py", line 142, in perform_create settings.EMAIL.activation(self.request, context).send(to) File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/templated_mail/mail.py", line 78, in send super(BaseEmailMessage, self).send(*args, **kwargs) File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/django/core/mail/message.py", line 301, in send return self.get_connection(fail_silently).send_messages([self]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/django/core/mail/backends/locmem.py", line 31, in send_messages mail.outbox.append(copy.deepcopy(message)) ^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 172, in deepcopy y = _reconstruct(x, memo, *rv) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 271, in _reconstruct state = deepcopy(state, memo) ^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 146, in deepcopy y = copier(x, memo) ^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 231, in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) ^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 172, in deepcopy y = _reconstruct(x, memo, *rv) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 271, in _reconstruct state = deepcopy(state, memo) ^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 146, in deepcopy y = copier(x, memo) ^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 231, in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) ^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 172, in deepcopy y = _reconstruct(x, memo, *rv) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 271, in _reconstruct state = deepcopy(state, memo) ^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 146, in deepcopy y = copier(x, memo) ^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 231, in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) ^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py", line 161, in deepcopy rv = reductor(4) ^^^^^^^^^^^ File "/Users/johnnymetz/Repos/personal/notifier-app/venv/lib/python3.11/site-packages/django/urls/resolvers.py", line 105, in __reduce_ex__ raise PicklingError(f"Cannot pickle {self.__class__.__qualname__}.") _pickle.PicklingError: Cannot pickle ResolverMatch. users/tests/views/test_user.py:28 (test_create_user) client = <django.test.client.Client object at 0x104808190> @pytest.mark.django_db def test_create_user(client): url = reverse("user-list") data = { "email": "jj@email.com", "password": TEST_PASSWORD, "re_password": TEST_PASSWORD, } > client.post(url, data=data) test_user.py:37: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../../../venv/lib/python3.11/site-packages/django/test/client.py:1158: in post response = super().post( ../../../venv/lib/python3.11/site-packages/django/test/client.py:503: in post return self.generic( ../../../venv/lib/python3.11/site-packages/django/test/client.py:676: in generic return self.request(**r) ../../../venv/lib/python3.11/site-packages/django/test/client.py:1092: in request self.check_exception(response) ../../../venv/lib/python3.11/site-packages/django/test/client.py:805: in check_exception raise exc_value ../../../venv/lib/python3.11/site-packages/django/core/handlers/exception.py:55: in inner response = get_response(request) ../../../venv/lib/python3.11/site-packages/django/core/handlers/base.py:197: in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) ../../../venv/lib/python3.11/site-packages/django/views/decorators/csrf.py:65: in _view_wrapper return view_func(request, *args, **kwargs) ../../../venv/lib/python3.11/site-packages/rest_framework/viewsets.py:124: in view return self.dispatch(request, *args, **kwargs) ../../../venv/lib/python3.11/site-packages/rest_framework/views.py:509: in dispatch response = self.handle_exception(exc) ../../../venv/lib/python3.11/site-packages/rest_framework/views.py:469: in handle_exception self.raise_uncaught_exception(exc) ../../../venv/lib/python3.11/site-packages/rest_framework/views.py:480: in raise_uncaught_exception raise exc ../../../venv/lib/python3.11/site-packages/rest_framework/views.py:506: in dispatch response = handler(request, *args, **kwargs) ../../../venv/lib/python3.11/site-packages/rest_framework/mixins.py:19: in create self.perform_create(serializer) ../../../venv/lib/python3.11/site-packages/djoser/views.py:142: in perform_create settings.EMAIL.activation(self.request, context).send(to) ../../../venv/lib/python3.11/site-packages/templated_mail/mail.py:78: in send super(BaseEmailMessage, self).send(*args, **kwargs) ../../../venv/lib/python3.11/site-packages/django/core/mail/message.py:301: in send return self.get_connection(fail_silently).send_messages([self]) ../../../venv/lib/python3.11/site-packages/django/core/mail/backends/locmem.py:31: in send_messages mail.outbox.append(copy.deepcopy(message)) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:172: in deepcopy y = _reconstruct(x, memo, *rv) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:271: in _reconstruct state = deepcopy(state, memo) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:146: in deepcopy y = copier(x, memo) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:231: in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:172: in deepcopy y = _reconstruct(x, memo, *rv) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:271: in _reconstruct state = deepcopy(state, memo) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:146: in deepcopy y = copier(x, memo) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:231: in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:172: in deepcopy y = _reconstruct(x, memo, *rv) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:271: in _reconstruct state = deepcopy(state, memo) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:146: in deepcopy y = copier(x, memo) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:231: in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo) /opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/copy.py:161: in deepcopy rv = reductor(4) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = ResolverMatch(func=djoser.views.UserViewSet, args=(), kwargs={}, url_name='user-list', app_names=[], namespaces=[], route='api/auth/users/$') protocol = 4 def __reduce_ex__(self, protocol): > raise PicklingError(f"Cannot pickle {self.__class__.__qualname__}.") E _pickle.PicklingError: Cannot pickle ResolverMatch.
Got a similar issue while going from Django 5.0.9 to Django 5.1.1 with djoser 2.2.3
Fixed in 2.3.1.
Background
I recently upgraded to Django 5.1.1 and I'm seeing a
PicklingError
in my unit tests for all djoser endpoints that send an email.Here are some minimalist unit tests that are failing (note I'm using pytest-django):
All of these tests fail. Here's the full traceback for the first test (
test_create_user
):