Skip to content

Commit 6665ba7

Browse files
committed
Merge branch 'main' into feature/pne-203-file-links-on-windows
2 parents cbd53a5 + 8d17d52 commit 6665ba7

File tree

8 files changed

+32
-36
lines changed

8 files changed

+32
-36
lines changed

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
arrow==1.3.0
22
boto3==1.34.35
33
deprecation==2.1.0
4-
gemd==2.1.8
4+
gemd==2.1.9
55
pyjwt==2.8.0
6-
requests==2.32.0
6+
requests==2.32.2
77
tqdm==4.66.3
88

99
# boto3 (through botocore) depends on urllib3. Version 1.34.35 requires

setup.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,21 @@
2222
package_dir={'': 'src'},
2323
packages=find_packages(where='src'),
2424
install_requires=[
25-
"requests>=2.31.0,<3",
25+
"requests>=2.32.2,<3",
2626
"pyjwt>=2,<3",
2727
"arrow>=1.0.0,<2",
28-
"gemd>=2.1.8,<3",
28+
"gemd>=2.1.9,<3",
2929
"boto3>=1.34.35,<2",
3030
"deprecation>=2.1.0,<3",
3131
"urllib3>=1.26.18,<3",
3232
"tqdm>=4.27.0,<5",
33-
"pint>=0.21,<0.24"
3433
],
3534
extras_require={
3635
"tests": [
3736
"factory-boy>=3.3.0,<4",
3837
"mock>=5.1.0,<6",
3938
"pandas>=2.0.3,<3",
4039
"pytest>=8.0.0,<9",
41-
"pytz>=2024.1",
4240
"requests-mock>=1.11.0,<2",
4341
]
4442
},

src/citrine/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "3.5.1"
1+
__version__ = "3.5.2"

src/citrine/_session.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import platform
2-
from datetime import datetime, timedelta
2+
from datetime import datetime, timedelta, timezone
33
from json.decoder import JSONDecodeError
44
from logging import getLogger
55
from os import environ
@@ -25,7 +25,7 @@
2525

2626
# Choose a 5-second buffer so that there's no chance of the access token
2727
# expiring during the check for expiration
28-
EXPIRATION_BUFFER_MILLIS: timedelta = timedelta(milliseconds=5000)
28+
EXPIRATION_BUFFER: timedelta = timedelta(seconds=5)
2929
logger = getLogger(__name__)
3030

3131

@@ -53,7 +53,7 @@ def __init__(self,
5353
self.authority = ':'.join(([host] if host else []) + ([port] if port else []))
5454
self.refresh_token: str = refresh_token
5555
self.access_token: Optional[str] = None
56-
self.access_token_expiration: datetime = datetime.utcnow()
56+
self.access_token_expiration: datetime = datetime.now(timezone.utc)
5757

5858
agent = "{}/{} python-requests/{} citrine-python/{}".format(
5959
platform.python_implementation(),
@@ -106,7 +106,8 @@ def _versioned_base_url(self, version: str = 'v1'):
106106
))
107107

108108
def _is_access_token_expired(self):
109-
return self.access_token_expiration - EXPIRATION_BUFFER_MILLIS <= datetime.utcnow()
109+
buffered_expire = self.access_token_expiration - EXPIRATION_BUFFER
110+
return datetime.now(timezone.utc) > buffered_expire
110111

111112
def _refresh_access_token(self) -> None:
112113
"""Optionally refresh our access token (if the previous one is about to expire)."""
@@ -118,10 +119,13 @@ def _refresh_access_token(self) -> None:
118119
if response.status_code != 200:
119120
raise UnauthorizedRefreshToken()
120121
self.access_token = response.json()['access_token']
121-
self.access_token_expiration = datetime.utcfromtimestamp(
122-
jwt.decode(self.access_token,
123-
options={"verify_signature": False},
124-
algorithms=["HS256"])['exp']
122+
self.access_token_expiration = datetime.fromtimestamp(
123+
jwt.decode(
124+
self.access_token,
125+
options={"verify_signature": False},
126+
algorithms=["HS256"]
127+
)['exp'],
128+
timezone.utc
125129
)
126130

127131
# Explicitly set an updated 'auth', so as to not rely on implicit cookie handling.

src/citrine/resources/data_concepts.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,9 @@ def _path_template(self):
248248
@property
249249
def _dataset_agnostic_path_template(self):
250250
if self.project_id is None:
251-
return f'teams/{self.team_id}/{self._collection_key.replace("_","-")}'
251+
return f'teams/{self.team_id}/{self._collection_key.replace("_", "-")}'
252252
else:
253-
return f'projects/{self.project_id}/{self._collection_key.replace("_","-")}'
253+
return f'projects/{self.project_id}/{self._collection_key.replace("_", "-")}'
254254

255255
def build(self, data: dict) -> ResourceType:
256256
"""

test_requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ flake8-docstrings==1.7.0
55
mock==5.1.0
66
pytest==8.0.0
77
pytest-cov==4.1.0
8-
pytz==2024.1
98
requests-mock==1.11.0
109

1110
# faker is a dependency of factory-boy, but factory-boy sets a very low floor

tests/test_citrine.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import platform
2-
from datetime import datetime
2+
from datetime import datetime, timezone
33

44
import jwt
55
import pytest
6-
import pytz
76
import requests_mock
87

98
from citrine import Citrine
@@ -17,7 +16,7 @@ def refresh_token(expiration: datetime = None) -> dict:
1716
return {'access_token': token}
1817

1918

20-
token_refresh_response = refresh_token(datetime(2019, 3, 14, tzinfo=pytz.utc))
19+
token_refresh_response = refresh_token(datetime(2019, 3, 14, tzinfo=timezone.utc))
2120

2221

2322
def test_citrine_creation():

tests/test_session.py

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
1-
import json
2-
31
import jwt
42
import pytest
5-
import unittest
63

74
from citrine.exceptions import (
85
BadRequest,
9-
CitrineException,
106
Conflict,
117
NonRetryableException,
128
WorkflowNotReadyException,
139
RetryableException)
1410

15-
from datetime import datetime, timedelta
16-
import pytz
11+
from datetime import datetime, timedelta, timezone
12+
1713
import mock
1814
import requests
1915
import requests_mock
@@ -32,7 +28,7 @@ def refresh_token(expiration: datetime = None) -> dict:
3228

3329
@pytest.fixture
3430
def session():
35-
token_refresh_response = refresh_token(datetime(2019, 3, 14, tzinfo=pytz.utc))
31+
token_refresh_response = refresh_token(datetime(2019, 3, 14, tzinfo=timezone.utc))
3632
with requests_mock.Mocker() as m:
3733
m.post('http://citrine-testing.fake/api/v1/tokens/refresh', json=token_refresh_response)
3834
session = Session(
@@ -43,13 +39,13 @@ def session():
4339
# Default behavior is to *not* require a refresh - those tests can clear this out
4440
# As rule of thumb, we should be using freezegun or similar to never rely on the system clock
4541
# for these scenarios, but I thought this is light enough to postpone that for the time being
46-
session.access_token_expiration = datetime.utcnow() + timedelta(minutes=3)
42+
session.access_token_expiration = datetime.now(timezone.utc) + timedelta(minutes=3)
4743

4844
return session
4945

5046

5147
def test_session_signature(monkeypatch):
52-
token_refresh_response = refresh_token(datetime(2019, 3, 14, tzinfo=pytz.utc))
48+
token_refresh_response = refresh_token(datetime(2019, 3, 14, tzinfo=timezone.utc))
5349
with requests_mock.Mocker() as m:
5450
m.post('ftp://citrine-testing.fake:8080/api/v1/tokens/refresh', json=token_refresh_response)
5551

@@ -77,8 +73,8 @@ def test_session_signature(monkeypatch):
7773

7874

7975
def test_get_refreshes_token(session: Session):
80-
session.access_token_expiration = datetime.utcnow() - timedelta(minutes=1)
81-
token_refresh_response = refresh_token(datetime(2019, 3, 14, tzinfo=pytz.utc))
76+
session.access_token_expiration = datetime.now(timezone.utc) - timedelta(minutes=1)
77+
token_refresh_response = refresh_token(datetime(2019, 3, 14, tzinfo=timezone.utc))
8278

8379
with requests_mock.Mocker() as m:
8480
m.post('http://citrine-testing.fake/api/v1/tokens/refresh', json=token_refresh_response)
@@ -89,11 +85,11 @@ def test_get_refreshes_token(session: Session):
8985
resp = session.get_resource('/foo')
9086

9187
assert {'foo': 'bar'} == resp
92-
assert datetime(2019, 3, 14) == session.access_token_expiration
88+
assert datetime(2019, 3, 14, tzinfo=timezone.utc) == session.access_token_expiration
9389

9490

9591
def test_get_refresh_token_failure(session: Session):
96-
session.access_token_expiration = datetime.utcnow() - timedelta(minutes=1)
92+
session.access_token_expiration = datetime.now(timezone.utc) - timedelta(minutes=1)
9793

9894
with requests_mock.Mocker() as m:
9995
m.post('http://citrine-testing.fake/api/v1/tokens/refresh', status_code=401)
@@ -197,7 +193,7 @@ def test_connection_error(session: Session):
197193

198194

199195
def test_post_refreshes_token_when_denied(session: Session):
200-
token_refresh_response = refresh_token(datetime(2019, 3, 14, tzinfo=pytz.utc))
196+
token_refresh_response = refresh_token(datetime(2019, 3, 14, tzinfo=timezone.utc))
201197

202198
with requests_mock.Mocker() as m:
203199
m.post('http://citrine-testing.fake/api/v1/tokens/refresh', json=token_refresh_response)
@@ -209,7 +205,7 @@ def test_post_refreshes_token_when_denied(session: Session):
209205
resp = session.post_resource('/foo', json={'data': 'hi'})
210206

211207
assert {'foo': 'bar'} == resp
212-
assert datetime(2019, 3, 14) == session.access_token_expiration
208+
assert datetime(2019, 3, 14, tzinfo=timezone.utc) == session.access_token_expiration
213209

214210

215211
# this test exists to provide 100% coverage for the legacy 401 status on Unauthorized responses

0 commit comments

Comments
 (0)