Skip to content

Commit

Permalink
fix: update datetime usage for compatibility with Python versions
Browse files Browse the repository at this point in the history
Refactor datetime imports and usage to ensure compatibility with Python 3.12 and 3.13. Replace deprecated datetime.utcnow() with datetime.now(UTC) and handle ImportError for older versions.
  • Loading branch information
iamdhakrey committed Feb 12, 2025
1 parent 15f9ea6 commit 9e6ae24
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 10 deletions.
10 changes: 8 additions & 2 deletions jose/jwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
except ImportError:
from collections import Mapping

from datetime import UTC, datetime, timedelta
try:
from datetime import UTC, datetime, timedelta
utc_now = datetime.now(UTC) # Preferred in Python 3.13+
except ImportError:
from datetime import datetime, timedelta, timezone
utc_now = datetime.now(timezone.utc) # Preferred in Python 3.12 and below
UTC = timezone.utc

from jose import jws

Expand Down Expand Up @@ -386,7 +392,7 @@ def _validate_sub(claims, subject=None):
"sub" value is a case-sensitive string containing a StringOrURI
value. Use of this claim is OPTIONAL.
Args:
Arg
claims (dict): The claims dictionary to validate.
subject (str): The subject of the token.
"""
Expand Down
41 changes: 33 additions & 8 deletions tests/test_jwt.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import base64
import json
from datetime import UTC, datetime, timedelta

try:
from datetime import UTC, datetime, timedelta
utc_now = datetime.now(UTC) # Preferred in Python 3.13+
except ImportError:
from datetime import datetime, timedelta, timezone
utc_now = datetime.now(timezone.utc) # Preferred in Python 3.12 and below
UTC = timezone.utc


import pytest

Expand Down Expand Up @@ -84,7 +92,9 @@ def return_encoded_array(token, key, algorithms, verify=True):

jws.verify = return_encoded_array

with pytest.raises(JWTError, match="Invalid payload string: must be a json object"):
with pytest.raises(
JWTError, match="Invalid payload string: must be a json object"
):
jwt.decode(token, "secret", ["HS256"])
finally:
jws.verify = old_jws_verify
Expand Down Expand Up @@ -144,20 +154,35 @@ def test_deterministic_headers(self):

# manually decode header to compare it to known good
decoded_headers1 = base64url_decode(encoded_headers1.encode("utf-8"))
assert decoded_headers1 == b"""{"alg":"HS256","another_key":"another_value","kid":"my-key-id","typ":"JWT"}"""
assert (
decoded_headers1
== b"""{"alg":"HS256","another_key":"another_value","kid":"my-key-id","typ":"JWT"}"""
)

def test_encode(self, claims, key):
expected = (
("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9" ".eyJhIjoiYiJ9" ".xNtk2S0CNbCBZX_f67pFgGRugaP1xi2ICfet3nwOSxw"),
("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" ".eyJhIjoiYiJ9" ".jiMyrsmD8AoHWeQgmxZ5yq8z0lXS67_QGs52AzC8Ru8"),
(
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9"
".eyJhIjoiYiJ9"
".xNtk2S0CNbCBZX_f67pFgGRugaP1xi2ICfet3nwOSxw"
),
(
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
".eyJhIjoiYiJ9"
".jiMyrsmD8AoHWeQgmxZ5yq8z0lXS67_QGs52AzC8Ru8"
),
)

encoded = jwt.encode(claims, key)

assert encoded in expected

def test_decode(self, claims, key):
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" ".eyJhIjoiYiJ9" ".jiMyrsmD8AoHWeQgmxZ5yq8z0lXS67_QGs52AzC8Ru8"
token = (
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
".eyJhIjoiYiJ9"
".jiMyrsmD8AoHWeQgmxZ5yq8z0lXS67_QGs52AzC8Ru8"
)

decoded = jwt.decode(token, key)

Expand Down Expand Up @@ -504,8 +529,8 @@ def test_unverified_claims_object(self, claims, key):
[
("aud", "aud"),
("ait", "ait"),
("exp", datetime.now(UTC) + timedelta(seconds=3600)),
("nbf", datetime.now(UTC) - timedelta(seconds=5)),
("exp", utc_now + timedelta(seconds=3600)),
("nbf", utc_now - timedelta(seconds=5)),
("iss", "iss"),
("sub", "sub"),
("jti", "jti"),
Expand Down

0 comments on commit 9e6ae24

Please sign in to comment.