Skip to content

Commit

Permalink
fix: compatibility with urllib3 2.0
Browse files Browse the repository at this point in the history
Signed-off-by: Frost Ming <me@frostming.com>
  • Loading branch information
frostming committed May 5, 2023
1 parent c05ef9e commit 1c60088
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 78 deletions.
23 changes: 11 additions & 12 deletions cachecontrol/serialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,29 +43,28 @@ def dumps(self, request, response, body=None):
# doesn't know the difference. Forcing these to unicode will be
# enough to have msgpack know the difference.
data = {
u"response": {
u"body": body, # Empty bytestring if body is stored separately
u"headers": dict(
"response": {
"body": body, # Empty bytestring if body is stored separately
"headers": dict(
(text_type(k), text_type(v)) for k, v in response.headers.items()
),
u"status": response.status,
u"version": response.version,
u"reason": text_type(response.reason),
u"strict": response.strict,
u"decode_content": response.decode_content,
"status": response.status,
"version": response.version,
"reason": text_type(response.reason),
"decode_content": response.decode_content,
}
}

# Construct our vary headers
data[u"vary"] = {}
if u"vary" in response_headers:
varied_headers = response_headers[u"vary"].split(",")
data["vary"] = {}
if "vary" in response_headers:
varied_headers = response_headers["vary"].split(",")
for header in varied_headers:
header = text_type(header).strip()
header_value = request.headers.get(header, None)
if header_value is not None:
header_value = text_type(header_value)
data[u"vary"][header] = header_value
data["vary"][header] = header_value

return b",".join([b"cc=4", msgpack.dumps(data, use_bin_type=True)])

Expand Down
66 changes: 39 additions & 27 deletions tests/test_cache_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@
"""
Unit tests that verify our caching methods work correctly.
"""
import pytest
from mock import ANY, Mock
import time
from tempfile import mkdtemp

import pytest
from mock import ANY, Mock

from cachecontrol import CacheController
from cachecontrol.cache import DictCache
from cachecontrol.caches import SeparateBodyFileCache
from .utils import NullSerializer, DummyResponse, DummyRequest

TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT"
from .utils import DummyRequest, DummyResponse, NullSerializer

TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT"


class TestCacheControllerResponse(object):
Expand Down Expand Up @@ -126,13 +127,16 @@ def test_update_cached_response_no_local_cache(self):
cache = DictCache({})
cc = CacheController(cache)
req = DummyRequest(url="http://localhost/", headers={"if-match": "xyz"})
resp = DummyResponse(status=304, headers={
"ETag": "xyz",
"x-value": "b",
"Date": time.strftime(TIME_FMT, time.gmtime()),
"Cache-Control": "max-age=60",
"Content-Length": "200"
})
resp = DummyResponse(
status=304,
headers={
"ETag": "xyz",
"x-value": "b",
"Date": time.strftime(TIME_FMT, time.gmtime()),
"Cache-Control": "max-age=60",
"Content-Length": "200",
},
)
# First, ensure the response from update_cached_response() matches the
# cached one:
result = cc.update_cached_response(req, resp)
Expand Down Expand Up @@ -176,13 +180,16 @@ def update_cached_response_with_valid_headers_test(self, cache):
cc = CacheController(cache)
url = "http://localhost:123/x"
req = DummyRequest(url=url, headers={})
cached_resp = DummyResponse(status=200, headers={
"ETag": etag,
"x-value:": "a",
"Content-Length": "100",
"Cache-Control": "max-age=60",
"Date": time.strftime(TIME_FMT, time.gmtime()),
})
cached_resp = DummyResponse(
status=200,
headers={
"ETag": etag,
"x-value:": "a",
"Content-Length": "100",
"Cache-Control": "max-age=60",
"Date": time.strftime(TIME_FMT, time.gmtime()),
},
)
cc._cache_set(url, req, cached_resp, b"my body")

# Now we get another request, and it's a 304, with new value for
Expand All @@ -191,13 +198,16 @@ def update_cached_response_with_valid_headers_test(self, cache):
# Set our content length to 200. That would be a mistake in
# the server, but we'll handle it gracefully... for now.
req = DummyRequest(url=url, headers={"if-match": etag})
resp = DummyResponse(status=304, headers={
"ETag": etag,
"x-value": "b",
"Date": time.strftime(TIME_FMT, time.gmtime()),
"Cache-Control": "max-age=60",
"Content-Length": "200"
})
resp = DummyResponse(
status=304,
headers={
"ETag": etag,
"x-value": "b",
"Date": time.strftime(TIME_FMT, time.gmtime()),
"Cache-Control": "max-age=60",
"Content-Length": "200",
},
)
# First, ensure the response from update_cached_response() matches the
# cached one:
result = cc.update_cached_response(req, resp)
Expand All @@ -214,15 +224,17 @@ def update_cached_response_with_valid_headers_test(self, cache):
class TestCacheControlRequest(object):
url = "http://foo.com/bar"

def setup(self):
def setup_method(self):
self.c = CacheController(DictCache(), serializer=NullSerializer())

def req(self, headers):
mock_request = Mock(url=self.url, headers=headers)
return self.c.cached_request(mock_request)

def test_cache_request_no_headers(self):
cached_resp = Mock(headers={"ETag": "jfd9094r808", "Content-Length": 100}, status=200)
cached_resp = Mock(
headers={"ETag": "jfd9094r808", "Content-Length": 100}, status=200
)
self.c.cache = DictCache({self.url: cached_resp})
resp = self.req({})
assert not resp
Expand Down
7 changes: 3 additions & 4 deletions tests/test_etag.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
# SPDX-License-Identifier: Apache-2.0

import pytest

from mock import Mock, patch

import requests
from mock import Mock, patch

from cachecontrol import CacheControl
from cachecontrol.cache import DictCache
from cachecontrol.compat import urljoin

from .utils import NullSerializer


Expand Down Expand Up @@ -136,7 +135,7 @@ def test_not_modified_releases_connection(self, server, url):

# This is how the urllib3 response is created in
# requests.adapters
response_mod = "requests.adapters.HTTPResponse.from_httplib"
response_mod = "urllib3.HTTPConnectionPool.urlopen"

with patch(response_mod, Mock(return_value=resp)):
sess.get(etag_url)
Expand Down
41 changes: 17 additions & 24 deletions tests/test_expires_heuristics.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@

import calendar
import time

from email.utils import formatdate, parsedate
from datetime import datetime
from email.utils import formatdate, parsedate
from pprint import pprint

from mock import Mock
from requests import Session, get

from cachecontrol import CacheControl
from cachecontrol.heuristics import LastModified, ExpiresAfter, OneDayCache
from cachecontrol.heuristics import TIME_FMT
from cachecontrol.heuristics import BaseHeuristic
from .utils import DummyResponse
from cachecontrol.heuristics import (
TIME_FMT,
BaseHeuristic,
ExpiresAfter,
LastModified,
OneDayCache,
)

from pprint import pprint
from .utils import DummyResponse


class TestHeuristicWithoutWarning(object):

def setup(self):

def setup_method(self):
class NoopHeuristic(BaseHeuristic):
warning = Mock()

Expand All @@ -35,17 +36,14 @@ def update_headers(self, resp):

def test_no_header_change_means_no_warning_header(self, url):
the_url = url + "optional_cacheable_request"
resp = self.sess.get(the_url)
self.sess.get(the_url)

assert not self.heuristic.warning.called


class TestHeuristicWith3xxResponse(object):

def setup(self):

def setup_method(self):
class DummyHeuristic(BaseHeuristic):

def update_headers(self, resp):
return {"x-dummy-header": "foobar"}

Expand All @@ -63,16 +61,14 @@ def test_heuristic_applies_to_304(self, url):


class TestUseExpiresHeuristic(object):

def test_expires_heuristic_arg(self):
sess = Session()
cached_sess = CacheControl(sess, heuristic=Mock())
assert cached_sess


class TestOneDayCache(object):

def setup(self):
def setup_method(self):
self.sess = Session()
self.cached_sess = CacheControl(self.sess, heuristic=OneDayCache())

Expand All @@ -91,8 +87,7 @@ def test_cache_for_one_day(self, url):


class TestExpiresAfter(object):

def setup(self):
def setup_method(self):
self.sess = Session()
self.cache_sess = CacheControl(self.sess, heuristic=ExpiresAfter(days=1))

Expand All @@ -112,8 +107,7 @@ def test_expires_after_one_day(self, url):


class TestLastModified(object):

def setup(self):
def setup_method(self):
self.sess = Session()
self.cached_sess = CacheControl(self.sess, heuristic=LastModified())

Expand All @@ -136,11 +130,10 @@ def datetime_to_header(dt):


class TestModifiedUnitTests(object):

def last_modified(self, period):
return time.strftime(TIME_FMT, time.gmtime(self.time_now - period))

def setup(self):
def setup_method(self):
self.heuristic = LastModified()
self.time_now = time.time()
day_in_seconds = 86400
Expand Down
6 changes: 2 additions & 4 deletions tests/test_redirects.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@


class TestPermanentRedirects(object):

def setup(self):
def setup_method(self):
self.sess = CacheControl(requests.Session())

def test_redirect_response_is_cached(self, url):
Expand All @@ -33,8 +32,7 @@ def test_bust_cache_on_redirect(self, url):


class TestMultipleChoicesRedirects(object):

def setup(self):
def setup_method(self):
self.sess = CacheControl(requests.Session())

def test_multiple_choices_is_cacheable(self, url):
Expand Down
7 changes: 3 additions & 4 deletions tests/test_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


class TestSerializer(object):
def setup(self):
def setup_method(self):
self.serializer = Serializer()
self.response_data = {
u"response": {
Expand All @@ -27,7 +27,6 @@ def setup(self):
u"status": 200,
u"version": 11,
u"reason": u"",
u"strict": True,
u"decode_content": True,
}
}
Expand All @@ -46,7 +45,7 @@ def test_read_version_v1(self):

def test_read_version_v2(self):
req = Mock()
compressed_base64_json = b"x\x9c%O\xb9\n\x83@\x10\xfd\x97\xa9-\x92%E\x14R\xe4 +\x16\t\xe6\x10\xbb\xb0\xc7\xe0\x81\xb8\xb2\xbb*A\xfc\xf7\x8c\xa6|\xe7\xbc\x99\xc0\xa2\xebL\xeb\x10\xa2\t\xa4\xd1_\x88\xe0\xc93'\xf9\xbe\xc8X\xf8\x95<=@\x00\x1a\x95\xd1\xf8Q\xa6\xf5\xd8z\x88\xbc\xed1\x80\x12\x85F\xeb\x96h\xca\xc2^\xf3\xac\xd7\xe7\xed\x1b\xf3SC5\x04w\xfa\x1c\x8e\x92_;Y\x1c\x96\x9a\x94]k\xc1\xdf~u\xc7\xc9 \x8fDG\xa0\xe2\xac\x92\xbc\xa9\xc9\xf1\xc8\xcbQ\xe4I\xa3\xc6U\xb9_\x14\xbb\xbdh\xc2\x1c\xd0R\xe1LK$\xd9\x9c\x17\xbe\xa7\xc3l\xb3Y\x80\xad\x94\xff\x0b\x03\xed\xa9V\x17[2\x83\xb0\xf4\xd14\xcf?E\x03Im"
compressed_base64_json = b'x\x9c\x1d\x8fK\x0f\x820\x10\x84\xff\xcb\x9e9h\xe3A\x9ax\xf0\x11K8hPi\xb8\x99>6\n!\xd4\xd0\x02!\x84\xff\xee\xc2qg\xbe\x9d\x9d\x9d\xa0E\xffs\x8dG\xe0\x13hgG\xe0\xf0\x14\xd2k\xb1\xffH\x16\x8fZd\x07\x88\xc0\xa2q\x16\xdf\xc65\x01\x9b\x00<\xb4\x1dF\xf0Ee\xb1\xf5\xcbj\xc6\xe2\xce\n\xd9\xd9\xf36\xc7\xe2TS\x0c\x8d;{\x8e\x07-\xae?\xfd9,1\x19\xbbVJ\xe4a\xa5\x93\xb4\xd7G\x929\x98D\x96Z\xd4\x15\x11\x8f\xe2;\xa8"\xad\xcd\xb0:\xf7\x8ba\xb7\x17U\x98#j\xaa\xbckH$\xcc\x07\x15::\xcc6\x9b\x08z\xeaP\xae\x0e[\xb8^\xb5\xf4\xc54\xcf\x7f\xef\xc0E\xe6'
resp = self.serializer._loads_v2(req, compressed_base64_json)
# We have to decode our urllib3 data back into a unicode string.
assert resp.data == "Hello World".encode("utf-8")
Expand All @@ -72,7 +71,7 @@ def test_read_v1_serialized_with_py2_TypeError(self):
b"(dp1\nS'response'\np2\n(dp3\nS'body'\np4\nS'Hello World'\n",
b"p5\nsS'version'\np6\nS'2'\nsS'status'\np7\nI200\n",
b"sS'reason'\np8\nS''\nsS'decode_content'\np9\nI01\n",
b"sS'strict'\np10\nS''\nsS'headers'\np11\n(dp12\n",
b"sS'headers'\np11\n(dp12\n",
b"S'Content-Type'\np13\nS'text/plain'\np14\n",
b"sS'Cache-Control'\np15\nS'public'\np16\n",
b"sS'Expires'\np17\nS'87654'\np18\nsss.",
Expand Down
4 changes: 2 additions & 2 deletions tests/test_storage_redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
from datetime import datetime

from mock import Mock

from cachecontrol.caches import RedisCache


class TestRedisCache(object):

def setup(self):
def setup_method(self):
self.conn = Mock()
self.cache = RedisCache(self.conn)

Expand Down
1 change: 0 additions & 1 deletion tests/test_vary.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ def cached_equal(self, cached, resp):
cached.status == resp.raw.status,
cached.version == resp.raw.version,
cached.reason == resp.raw.reason,
cached.strict == resp.raw.strict,
cached.decode_content == resp.raw.decode_content,
]

Expand Down

0 comments on commit 1c60088

Please sign in to comment.