diff --git a/jobserver/signing.py b/jobserver/signing.py index c04098d2d..ae38e2447 100644 --- a/jobserver/signing.py +++ b/jobserver/signing.py @@ -1,7 +1,8 @@ import hashlib -from datetime import datetime, timezone +from datetime import datetime import itsdangerous +from django.utils import timezone from pydantic import BaseModel, Field, ValidationError, root_validator, validator @@ -82,7 +83,7 @@ def check_url(cls, url): @validator("expiry") def check_expiry(cls, expiry): """Enforce the token has not expired.""" - if datetime.now(timezone.utc) > expiry: + if timezone.now() > expiry: raise ValueError(f"token expired on {expiry.isoformat()}") return expiry diff --git a/pyproject.toml b/pyproject.toml index f488691d2..a63594df5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,8 +70,6 @@ filterwarnings = [ "error", "ignore::pytest.PytestUnraisableExceptionWarning:", "ignore:distutils Version classes are deprecated:DeprecationWarning:pytest_freezegun", - "ignore:'django_extensions' defines default_app_config:django.utils.deprecation.RemovedInDjango41Warning:django", - "ignore:'slippers' defines default_app_config:django.utils.deprecation.RemovedInDjango41Warning:django", ] markers = [ "verification: tests that verify fakes", diff --git a/requirements.prod.txt b/requirements.prod.txt index a4100c679..ecef2fb96 100644 --- a/requirements.prod.txt +++ b/requirements.prod.txt @@ -31,9 +31,9 @@ argon2-cffi-bindings==21.2.0 \ --hash=sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e \ --hash=sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351 # via argon2-cffi -asgiref==3.5.0 \ - --hash=sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0 \ - --hash=sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9 +asgiref==3.5.2 \ + --hash=sha256:1d2880b792ae8757289136f1db2b7b99100ce959b2aa57fd69dab783d05afac4 \ + --hash=sha256:4a29362a6acebe09bf1d6640db38c1dc3d9217c68e6f9f6204d72667fc19a424 # via django attrs==21.4.0 \ --hash=sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4 \ @@ -228,9 +228,9 @@ dj-email-url==1.0.5 \ --hash=sha256:64257c4f9d8139a4af8e5267229d32260e433fbf257b0cf8fc855bb0cc39ca7d \ --hash=sha256:ef36f8a324ec57cf3be5c7a7ef44ed6900ca0208624a918ab33adc1cf6427b39 # via environs -django==4.0.7 \ - --hash=sha256:41bd65a9e5f8a89cdbfa7a7bba45cd7431ae89e750af82dea8a35fd1a7ecbe66 \ - --hash=sha256:9c6d5ad36be798e562ddcaa6b17b1c3ff2d3c4f529a47432b69fb9a30f847461 +django==4.1 \ + --hash=sha256:031ccb717782f6af83a0063a1957686e87cb4581ea61b47b3e9addf60687989a \ + --hash=sha256:032f8a6fc7cf05ccd1214e4a2e21dfcd6a23b9d575c6573cacc8c67828dbe642 # via # django-anymail # django-browser-reload diff --git a/tests/factories/applications.py b/tests/factories/applications.py index 041e5d171..a6a4df89c 100644 --- a/tests/factories/applications.py +++ b/tests/factories/applications.py @@ -1,6 +1,7 @@ +from datetime import timezone + import factory import factory.fuzzy -from django.utils import timezone from applications.models import ( Application, diff --git a/tests/factories/jobserver.py b/tests/factories/jobserver.py index f94a1d66a..a025c0427 100644 --- a/tests/factories/jobserver.py +++ b/tests/factories/jobserver.py @@ -1,8 +1,7 @@ -from datetime import datetime +from datetime import datetime, timezone import factory import factory.fuzzy -from django.utils import timezone from social_django.models import UserSocialAuth from jobserver.models import ( diff --git a/tests/fakes.py b/tests/fakes.py index 72906d825..fdf0b1a5d 100644 --- a/tests/fakes.py +++ b/tests/fakes.py @@ -1,7 +1,7 @@ import textwrap -from datetime import datetime +from datetime import datetime, timezone -from django.utils import timezone +from django.utils.timezone import now class FakeGitHubAPI: @@ -67,35 +67,35 @@ def get_repos_with_dates(self, org): "name": "research-repo-1", "url": "https://github.com/opensafely/research-repo-1", "is_private": True, - "created_at": timezone.now(), + "created_at": now(), "topics": ["github-releases"], }, { "name": "research-repo-2", "url": "https://github.com/opensafely/research-repo-2", "is_private": True, - "created_at": timezone.now(), + "created_at": now(), "topics": [], }, { "name": "research-repo-3", "url": "https://github.com/opensafely/research-repo-3", "is_private": False, - "created_at": timezone.now(), + "created_at": now(), "topics": ["github-releases"], }, { "name": "no workspaces or jobs", "url": "https://github.com/opensafely/research-repo-4", "is_private": True, - "created_at": timezone.now(), + "created_at": now(), "topics": [], }, { "name": "jobs haven't run", "url": "https://github.com/opensafely/research-repo-5", "is_private": True, - "created_at": timezone.now(), + "created_at": now(), "topics": [], }, ] diff --git a/tests/unit/jobserver/models/test_stats.py b/tests/unit/jobserver/models/test_stats.py index cd63f63d7..37ebba35d 100644 --- a/tests/unit/jobserver/models/test_stats.py +++ b/tests/unit/jobserver/models/test_stats.py @@ -1,6 +1,4 @@ -from datetime import datetime - -from django.utils import timezone +from datetime import datetime, timezone from ....factories import BackendFactory, StatsFactory diff --git a/tests/unit/jobserver/test_signing.py b/tests/unit/jobserver/test_signing.py index 0bf277860..afa8989c0 100644 --- a/tests/unit/jobserver/test_signing.py +++ b/tests/unit/jobserver/test_signing.py @@ -1,8 +1,9 @@ import json import secrets -from datetime import datetime, timedelta, timezone +from datetime import timedelta import pytest +from django.utils import timezone from pydantic import ValidationError from pydantic.json import pydantic_encoder @@ -26,7 +27,7 @@ def test_token_sign_verify_roundtrip(secret_key): token1 = signing.AuthToken( url="https://example.com/url", user="user", - expiry=datetime.now(timezone.utc) + timedelta(minutes=1), + expiry=timezone.now() + timedelta(minutes=1), ) token_string = token1.sign(secret_key, "salt") @@ -39,7 +40,7 @@ def test_token_object_url_invalid(): signing.AuthToken( url="bad", user="user", - expiry=datetime.now(timezone.utc) + timedelta(minutes=1), + expiry=timezone.now() + timedelta(minutes=1), ) @@ -48,7 +49,7 @@ def test_token_object_expired(): signing.AuthToken( url="https://example.com/url", user="user", - expiry=datetime.now(timezone.utc) - timedelta(minutes=1), + expiry=timezone.now() - timedelta(minutes=1), ) @@ -56,7 +57,7 @@ def test_token_verify_mismatched_secrets(): payload = dict( url="https://example.com/url", user="user", - expiry=datetime.now(timezone.utc) + timedelta(minutes=1), + expiry=timezone.now() + timedelta(minutes=1), ) token = create_raw_token(payload, "secret1" * 10) @@ -76,7 +77,7 @@ def test_token_verify_expired(secret_key): payload = dict( url="https://example.com/url", user="user", - expiry=datetime.now(timezone.utc) - timedelta(minutes=1), + expiry=timezone.now() - timedelta(minutes=1), ) token = create_raw_token(payload, secret_key) with pytest.raises(signing.AuthToken.Expired): @@ -87,7 +88,7 @@ def test_token_verify_wrong_all_the_things(secret_key): payload = dict( url="bad url", # missing user - expiry=datetime.now(timezone.utc) - timedelta(minutes=1), + expiry=timezone.now() - timedelta(minutes=1), ) token = create_raw_token(payload, secret_key) with pytest.raises(ValidationError) as exc_info: diff --git a/tests/unit/jobserver/views/test_status.py b/tests/unit/jobserver/views/test_status.py index 3a3c787e5..54f8f7a56 100644 --- a/tests/unit/jobserver/views/test_status.py +++ b/tests/unit/jobserver/views/test_status.py @@ -1,9 +1,9 @@ import functools import time -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone import pytest -from django.utils import timezone +from django.utils.timezone import now from first import first from jobserver.views.status import DBAvailability, PerBackendStatus, Status @@ -82,7 +82,7 @@ def test_status_healthy(rf): # acked, because JobFactory will implicitly create JobRequests JobFactory.create_batch(3, job_request__backend=backend) - last_seen = minutes_ago(timezone.now(), 1) + last_seen = minutes_ago(now(), 1) StatsFactory(backend=backend, api_last_seen=last_seen) request = rf.get("/") @@ -110,7 +110,7 @@ def test_status_no_last_seen(rf): def test_status_unacked_jobs_but_recent_api_contact(rf): backend = BackendFactory() - last_seen = minutes_ago(timezone.now(), 1) + last_seen = minutes_ago(now(), 1) StatsFactory(backend=backend, api_last_seen=last_seen) request = rf.get("/") @@ -131,7 +131,7 @@ def test_status_unhealthy(rf): # unacked, because it has no Jobs JobRequestFactory(backend=backend) - last_seen = minutes_ago(timezone.now(), 10) + last_seen = minutes_ago(now(), 10) StatsFactory(backend=backend, api_last_seen=last_seen, url="foo") request = rf.get("/")