-
Notifications
You must be signed in to change notification settings - Fork 813
Closed
Labels
Description
When I run tox locally for dj40, I see an error due to referencing model instance pk
(which makes sense based on reading the code) but I don't see the same error when it is run in GitHub Actions where the py39-dj40
log is clean.
Here's a portion of local execution:
django-oauth-toolkit$ tox -e py39-dj40 tests/test_models.py::TestClearExpired::test_clear_expired_tokens_with_tokens
GLOB sdist-make: /Users/ac45/src/django-oauth-toolkit/setup.py
py39-dj40 inst-nodeps: /Users/ac45/src/django-oauth-toolkit/.tox/.tmp/package/1/django-oauth-toolkit-2.0.0.zip
py39-dj40 installed: asgiref==3.5.2,attrs==21.4.0,certifi==2022.5.18.1,cffi==1.15.0,charset-normalizer==2.0.12,coverage==6.4,cryptography==37.0.2,Deprecated==1.2.13,Django==4.0.4,django-oauth-toolkit==2.0.0,djangorestframework==3.13.1,execnet==1.9.0,idna==3.3,iniconfig==1.1.1,jwcrypto==1.3.1,oauthlib==3.2.0,packaging==21.3,pluggy==1.0.0,py==1.11.0,pycparser==2.21,pyparsing==3.0.9,pytest==7.1.2,pytest-cov==3.0.0,pytest-django==4.5.2,pytest-forked==1.4.0,pytest-mock==3.7.0,pytest-xdist==2.5.0,pytz==2022.1,requests==2.27.1,sqlparse==0.4.2,tomli==2.0.1,urllib3==1.26.9,wrapt==1.14.1
py39-dj40 run-test-pre: PYTHONHASHSEED='2725533432'
py39-dj40 run-test: commands[0] | pytest tests/test_models.py::TestClearExpired::test_clear_expired_tokens_with_tokens
======================================================== test session starts ========================================================
platform darwin -- Python 3.9.11, pytest-7.1.2, pluggy-1.0.0
cachedir: .tox/py39-dj40/.pytest_cache
django: settings: tests.settings (from env)
rootdir: /Users/ac45/src/django-oauth-toolkit, configfile: tox.ini
plugins: xdist-2.5.0, forked-1.4.0, mock-3.7.0, django-4.5.2, cov-3.0.0
collected 1 item
tests/test_models.py F
============================================================= FAILURES ==============================================================
______________________________________ TestClearExpired.test_clear_expired_tokens_with_tokens _______________________________________
self = <tests.test_models.TestClearExpired testMethod=test_clear_expired_tokens_with_tokens>
def setUp(self):
super().setUp()
# Insert many tokens, both expired and not, and grants.
self.num_tokens = 100
now = timezone.now()
earlier = now - timedelta(seconds=100)
later = now + timedelta(seconds=100)
app = Application.objects.create(
name="test_app",
redirect_uris="http://localhost http://example.com http://example.org",
user=self.user,
client_type=Application.CLIENT_CONFIDENTIAL,
authorization_grant_type=Application.GRANT_AUTHORIZATION_CODE,
)
# make 200 access tokens, half current and half expired.
expired_access_tokens = AccessToken.objects.bulk_create(
AccessToken(token="expired AccessToken {}".format(i), expires=earlier)
for i in range(self.num_tokens)
)
current_access_tokens = AccessToken.objects.bulk_create(
AccessToken(token=f"current AccessToken {i}", expires=later) for i in range(self.num_tokens)
)
# Give the first half of the access tokens a refresh token,
# alternating between current and expired ones.
> RefreshToken.objects.bulk_create(
RefreshToken(
token=f"expired AT's refresh token {i}",
application=app,
access_token=expired_access_tokens[i].pk,
user=self.user,
)
for i in range(0, len(expired_access_tokens) // 2, 2)
)
tests/test_models.py:321:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.tox/py39-dj40/lib/python3.9/site-packages/django/db/models/manager.py:85: in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
.tox/py39-dj40/lib/python3.9/site-packages/django/db/models/query.py:559: in bulk_create
objs = list(objs)
tests/test_models.py:322: in <genexpr>
RefreshToken(
.tox/py39-dj40/lib/python3.9/site-packages/django/db/models/base.py:541: in __init__
_setattr(self, field.name, rel_obj)
.tox/py39-dj40/lib/python3.9/site-packages/django/db/models/fields/related_descriptors.py:338: in __set__
super().__set__(instance, value)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <django.db.models.fields.related_descriptors.ForwardOneToOneDescriptor object at 0x109e0b160>
instance = <RefreshToken: expired AT's refresh token 0>, value = 1
def __set__(self, instance, value):
"""
Set the related instance through the forward relation.
With the example above, when setting ``child.parent = parent``:
- ``self`` is the descriptor managing the ``parent`` attribute
- ``instance`` is the ``child`` instance
- ``value`` is the ``parent`` instance on the right of the equal sign
"""
# An object must be an instance of the related class.
if value is not None and not isinstance(
value, self.field.remote_field.model._meta.concrete_model
):
> raise ValueError(
'Cannot assign "%r": "%s.%s" must be a "%s" instance.'
% (
value,
instance._meta.object_name,
self.field.name,
self.field.remote_field.model._meta.object_name,
)
E ValueError: Cannot assign "1": "RefreshToken.access_token" must be a "AccessToken" instance.
.tox/py39-dj40/lib/python3.9/site-packages/django/db/models/fields/related_descriptors.py:235: ValueError
Looking in, for example, this execution log all the tests pass.
@Andrew-Chen-Wang the only environmental difference I can see is that sqlite3 version is 3.31 on GH and 3.37 locally.
Related is it appears the error wasn't being logged in earlier Django release because the value of pk
is None?? This is what I see when debugging under PyCharm. I think I may just revert the bulk_create which doesn't do a save. It's all an in-memory DB anyway so it's not a huge performance win.