blob: aa8e5897617be2b50849852f7d01ca675c2f9b07 [file] [edit]
from datetime import datetime, timedelta
from io import BytesIO
from time import sleep
import pytest
from requests import Response
from urllib3.response import HTTPResponse
from requests_cache.models.response import CachedResponse, OriginalResponse, format_file_size
from requests_cache.policy import CacheActions, utcnow
from tests.conftest import MOCKED_URL
def test_basic_attrs(mock_session):
response = CachedResponse.from_response(mock_session.get(MOCKED_URL))
assert response.from_cache is True
assert response.url == MOCKED_URL
assert response.status_code == 200
assert response.reason is None
assert response.encoding == 'ISO-8859-1'
assert response.headers['Content-Type'] == 'text/plain'
assert response.text == 'mock response'
assert isinstance(response.created_at, datetime)
assert response.expires is None
assert response.is_expired is False
@pytest.mark.parametrize(
'response',
[
OriginalResponse(),
OriginalResponse.wrap_response(Response(), CacheActions()),
],
)
def test_original_response(response):
"""Test both instantiating directly and wrapping a `requests.Response`"""
response = OriginalResponse()
assert response._content is False
assert response._content_consumed is False
assert response.status_code is None
assert isinstance(response.created_at, datetime)
assert response.expires is None
assert response.revalidated is False
assert response.cache_key == ''
def test_history(mock_session):
original_response = mock_session.get(MOCKED_URL)
original_response.history = [mock_session.get(MOCKED_URL)] * 3
response = CachedResponse.from_response(original_response)
assert len(response.history) == 3
assert all(isinstance(r, CachedResponse) for r in response.history)
@pytest.mark.parametrize(
'expires, is_expired',
[
(utcnow() + timedelta(days=1), False),
(utcnow() - timedelta(days=1), True),
],
)
def test_is_expired(expires, is_expired, mock_session):
response = CachedResponse.from_response(mock_session.get(MOCKED_URL), expires=expires)
assert response.from_cache is True
assert response.is_expired == is_expired
def test_is_expired__timezone_naive(mock_session):
response = CachedResponse.from_response(
mock_session.get(MOCKED_URL),
expires=datetime.now() - timedelta(days=1),
)
assert response.is_expired is True
def test_iterator(mock_session):
# Set up mock response with streamed content
url = f'{MOCKED_URL}/stream'
mock_raw_response = HTTPResponse(
body=BytesIO(b'mock response'),
status=200,
request_method='GET',
decode_content=False,
preload_content=False,
)
mock_session.mock_adapter.register_uri(
'GET',
url,
status_code=200,
raw=mock_raw_response,
)
# Expect the same chunks of data from the original response and subsequent cached responses
last_request_chunks = None
for i in range(3):
response = mock_session.get(url, stream=True)
chunks = list(response.iter_lines())
if i == 0:
assert response.from_cache is False
else:
assert response.from_cache is True
assert chunks == last_request_chunks
last_request_chunks = chunks
def test_reset_expiration__extend_expiration(mock_session):
# Start with an expired response
response = CachedResponse.from_response(
mock_session.get(MOCKED_URL),
expires=utcnow() - timedelta(seconds=0.01),
)
assert response.is_expired is True
# Set expiration in the future
is_expired = response.reset_expiration(utcnow() + timedelta(seconds=0.01))
assert is_expired is response.is_expired is False
sleep(0.1)
assert response.is_expired is True
def test_reset_expiration__shorten_expiration(mock_session):
# Start with a non-expired response
response = CachedResponse.from_response(
mock_session.get(MOCKED_URL),
expires=utcnow() + timedelta(seconds=1),
)
assert response.is_expired is False
# Set expiration in the past
is_expired = response.reset_expiration(utcnow() - timedelta(seconds=1))
assert is_expired is response.is_expired is True
def test_size(mock_session):
response = CachedResponse.from_response(mock_session.get(MOCKED_URL))
response._content = None
assert response.size == 0
response._content = b'1' * 1024
assert response.size == 1024
def test_str(mock_session):
"""Just ensure that a subset of relevant attrs get included in the response str; the format
may change without breaking the test.
"""
response = CachedResponse.from_response(mock_session.get(MOCKED_URL))
response._content = b'1010'
expected_values = ['GET', MOCKED_URL, 200, '4 bytes', 'created', 'expires', 'fresh']
assert all(str(v) in str(response) for v in expected_values)
def test_repr(mock_session):
"""Just ensure that a subset of relevant attrs get included in the response repr"""
response = CachedResponse.from_response(mock_session.get(MOCKED_URL))
expected_values = ['GET', MOCKED_URL, 200, 'ISO-8859-1', response.headers]
print(repr(response))
assert repr(response).startswith('CachedResponse(') and repr(response).endswith(')')
assert all(str(v) in repr(response) for v in expected_values)
@pytest.mark.parametrize(
'n_bytes, expected_size',
[
(None, '0 bytes'),
(5, '5 bytes'),
(3 * 1024, '3.00 KiB'),
(1024 * 3000, '2.93 MiB'),
(1024 * 1024 * 5000, '4.88 GiB'),
],
)
def test_format_file_size(n_bytes, expected_size):
assert format_file_size(n_bytes) == expected_size