Skip to content

Commit b6336fc

Browse files
authored
Fix for urllib2>=2 (#201)
* Fix for `urllib2>=2` * Bump version for publishing a new release * Adding local container for partially replacing httpbin.org usage * Replacing httpbin.org with mockbin.org from Kong for what needs HTTPS
1 parent 44cb551 commit b6336fc

17 files changed

+159
-101
lines changed

.github/workflows/main.yml

+12-15
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,6 @@ jobs:
2020
matrix:
2121
python-version: ['3.5', '3.6', '3.7', '3.8', '3.9', '3.10', '3.11', 'pypy3.9']
2222

23-
services:
24-
# https://docs.github.com/en/actions/using-containerized-services/about-service-containers
25-
redis:
26-
# Docker Hub image
27-
image: redis
28-
# Set health checks to wait until redis has started
29-
options: >-
30-
--health-cmd "redis-cli ping"
31-
--health-interval 10s
32-
--health-timeout 5s
33-
--health-retries 5
34-
ports:
35-
# Maps port 6379 on service container to the host
36-
- 6379:6379
37-
3823
steps:
3924
- uses: actions/checkout@v3
4025
- name: Set up Python ${{ matrix.python-version }}
@@ -45,12 +30,24 @@ jobs:
4530
cache-dependency-path: |
4631
Pipfile
4732
setup.py
33+
- uses: isbang/compose-action@v1.4.1
34+
with:
35+
compose-file: "./docker-compose.yml"
36+
down-flags: "--remove-orphans"
37+
up-flags: "--no-start"
4838
- name: Install dependencies
4939
run: |
5040
make develop
41+
make services-up
42+
- name: Setup hostname
43+
run: |
44+
export CONTAINER_ID=$(docker-compose ps -q proxy)
45+
export CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $CONTAINER_ID)
46+
echo "$CONTAINER_IP httpbin.local" | sudo tee -a /etc/hosts
5147
- name: Test
5248
run: |
5349
make test
50+
make services-down
5451
- name: Push Coveralls
5552
run: |
5653
pip install -q coveralls coveralls[yaml]

.pre-commit-config.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.3.0
3+
rev: v4.4.0
44
hooks:
55
- id: check-yaml
66
args: ['--unsafe']
@@ -18,11 +18,11 @@ repos:
1818
args: ['--in-place', '--remove-all-unused-imports', '--remove-unused-variable']
1919

2020
- repo: https://github.com/timothycrosley/isort
21-
rev: 5.10.1
21+
rev: 5.12.0
2222
hooks:
2323
- id: isort
2424

2525
- repo: https://github.com/psf/black
26-
rev: 22.6.0
26+
rev: 23.3.0
2727
hooks:
2828
- id: black

Makefile

+10-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,21 @@
22

33
install-dev-requirements:
44
pip install -U pip
5-
pip install pipenv pre-commit
5+
pip install pipenv
66

77
install-test-requirements:
88
pipenv install --dev
99
pipenv run python -c "import pipfile; pf = pipfile.load('Pipfile'); print('\n'.join(package+version if version != '*' else package for package, version in pf.data['default'].items()))" > requirements.txt
1010

11+
services-up:
12+
pipenv run docker-compose up -d
13+
14+
services-down:
15+
pipenv run docker-compose down --remove-orphans
16+
1117
test-python:
1218
@echo "Running Python tests"
13-
pipenv run python run_tests.py || exit 1
19+
pipenv run wait-for-it --service httpbin.local:443 --service localhost:6379 --timeout 5 -- pipenv run python run_tests.py || exit 1
1420
@echo ""
1521

1622
lint-python:
@@ -37,4 +43,5 @@ clean:
3743
rm -rf *.egg-info dist/ requirements.txt Pipfile.lock
3844
find . -type d -name __pycache__ -exec rm -rf {} \;
3945

40-
.PHONY: clean publish safetest test setup develop lint-python test-python install-test-requirements install-dev-requirements
46+
.PHONY: clean publish safetest test setup develop lint-python test-python
47+
.PHONY: services-up services-down install-test-requirements install-dev-requirements

Pipfile

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ wheel = "*"
3030
twine = "*"
3131
anaconda-client = "*"
3232
fastapi = "*"
33+
docker-compose = "*"
34+
wait-for-it = "*"
3335

3436
[requires]
3537
python_version = "3"

docker-compose.yml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
services:
2+
proxy:
3+
container_name: proxy
4+
image: shroomlife/docker-https-proxy:latest
5+
hostname: "httpbin.local"
6+
ports:
7+
- "80:80"
8+
- "443:443"
9+
httpbin:
10+
container_name: httpbin.local.proxy
11+
image: kennethreitz/httpbin:latest
12+
redis:
13+
image: redis:latest
14+
ports:
15+
- "6379:6379"

mocket/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44
__all__ = ("async_mocketize", "mocketize", "Mocket", "MocketEntry", "Mocketizer")
55

6-
__version__ = "3.11.0"
6+
__version__ = "3.11.1"

mocket/mocket.py

+14-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
import urllib3
1616
from urllib3.connection import match_hostname as urllib3_match_hostname
1717
from urllib3.util.ssl_ import ssl_wrap_socket as urllib3_ssl_wrap_socket
18-
from urllib3.util.ssl_ import wrap_socket as urllib3_wrap_socket
18+
19+
try:
20+
from urllib3.util.ssl_ import wrap_socket as urllib3_wrap_socket
21+
except ImportError:
22+
urllib3_wrap_socket = None
1923

2024
from .compat import basestring, byte_type, decode_from_bytes, encode_to_bytes, text_type
2125
from .exceptions import StrictMocketException
@@ -68,6 +72,7 @@ class FakeSetter(int):
6872
def __set__(self, *args):
6973
pass
7074

75+
minimum_version = FakeSetter()
7176
options = FakeSetter()
7277
verify_mode = FakeSetter(ssl.CERT_NONE)
7378

@@ -164,7 +169,7 @@ class MocketSocket:
164169
_secure_socket = False
165170

166171
def __init__(
167-
self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, *args, **kwargs
172+
self, family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0, **kwargs
168173
):
169174
self.true_socket = true_socket(family, type, proto)
170175
self._buflen = 65536
@@ -380,7 +385,6 @@ def true_sendall(self, data, *args, **kwargs):
380385

381386
# dump the resulting dictionary to a JSON file
382387
if Mocket.get_truesocket_recording_dir():
383-
384388
# update the dictionary with request and response lines
385389
response_dict["request"] = req
386390
response_dict["response"] = hexdump(encoded_response)
@@ -509,12 +513,15 @@ def enable(namespace=None, truesocket_recording_dir=None):
509513
urllib3.util.ssl_.ssl_wrap_socket = urllib3.util.ssl_.__dict__[
510514
"ssl_wrap_socket"
511515
] = FakeSSLContext.wrap_socket
516+
urllib3.util.ssl_wrap_socket = urllib3.util.__dict__[
517+
"ssl_wrap_socket"
518+
] = FakeSSLContext.wrap_socket
512519
urllib3.connection.ssl_wrap_socket = urllib3.connection.__dict__[
513520
"ssl_wrap_socket"
514521
] = FakeSSLContext.wrap_socket
515522
urllib3.connection.match_hostname = urllib3.connection.__dict__[
516523
"match_hostname"
517-
] = lambda cert, hostname: None
524+
] = lambda *args: None
518525
if pyopenssl_override: # pragma: no cover
519526
# Take out the pyopenssl version - use the default implementation
520527
extract_from_urllib3()
@@ -540,6 +547,9 @@ def disable():
540547
urllib3.util.ssl_.ssl_wrap_socket = urllib3.util.ssl_.__dict__[
541548
"ssl_wrap_socket"
542549
] = true_urllib3_ssl_wrap_socket
550+
urllib3.util.ssl_wrap_socket = urllib3.util.__dict__[
551+
"ssl_wrap_socket"
552+
] = true_urllib3_ssl_wrap_socket
543553
urllib3.connection.ssl_wrap_socket = urllib3.connection.__dict__[
544554
"ssl_wrap_socket"
545555
] = true_urllib3_ssl_wrap_socket

mocket/utils.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from .compat import decode_from_bytes, encode_to_bytes
77

8-
SSL_PROTOCOL = ssl.PROTOCOL_SSLv23
8+
SSL_PROTOCOL = ssl.PROTOCOL_TLSv1_2
99

1010

1111
class MocketSocketCore(io.BytesIO):

tests/main/test_http.py

+18-14
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def assertEqualHeaders(self, first, second, msg=None):
2828
class TrueHttpEntryTestCase(HttpTestCase):
2929
@mocketize
3030
def test_truesendall(self):
31-
url = "http://httpbin.org/ip"
31+
url = "http://httpbin.local/ip"
3232
resp = urlopen(url)
3333
self.assertEqual(resp.code, 200)
3434
resp = requests.get(url)
@@ -37,7 +37,7 @@ def test_truesendall(self):
3737
def test_truesendall_with_recording(self):
3838
with tempfile.TemporaryDirectory() as temp_dir:
3939
with Mocketizer(truesocket_recording_dir=temp_dir):
40-
url = "http://httpbin.org/ip"
40+
url = "http://httpbin.local/ip"
4141

4242
urlopen(url)
4343
requests.get(url)
@@ -54,12 +54,12 @@ def test_truesendall_with_recording(self):
5454
with io.open(dump_filename) as f:
5555
responses = json.load(f)
5656

57-
self.assertEqual(len(responses["httpbin.org"]["80"].keys()), 2)
57+
self.assertEqual(len(responses["httpbin.local"]["80"].keys()), 2)
5858

5959
def test_truesendall_with_gzip_recording(self):
6060
with tempfile.TemporaryDirectory() as temp_dir:
6161
with Mocketizer(truesocket_recording_dir=temp_dir):
62-
url = "http://httpbin.org/gzip"
62+
url = "http://httpbin.local/gzip"
6363

6464
requests.get(url)
6565
resp = requests.get(url)
@@ -72,12 +72,12 @@ def test_truesendall_with_gzip_recording(self):
7272
with io.open(dump_filename) as f:
7373
responses = json.load(f)
7474

75-
assert len(responses["httpbin.org"]["80"].keys()) == 1
75+
assert len(responses["httpbin.local"]["80"].keys()) == 1
7676

7777
def test_truesendall_with_chunk_recording(self):
7878
with tempfile.TemporaryDirectory() as temp_dir:
7979
with Mocketizer(truesocket_recording_dir=temp_dir):
80-
url = "http://httpbin.org/range/70000?chunk_size=65536"
80+
url = "http://httpbin.local/range/70000?chunk_size=65536"
8181

8282
requests.get(url)
8383
resp = requests.get(url)
@@ -90,12 +90,14 @@ def test_truesendall_with_chunk_recording(self):
9090
with io.open(dump_filename) as f:
9191
responses = json.load(f)
9292

93-
assert len(responses["httpbin.org"]["80"].keys()) == 1
93+
assert len(responses["httpbin.local"]["80"].keys()) == 1
9494

9595
@mocketize
9696
def test_wrongpath_truesendall(self):
97-
Entry.register(Entry.GET, "http://httpbin.org/user.agent", Response(status=404))
98-
response = urlopen("http://httpbin.org/ip")
97+
Entry.register(
98+
Entry.GET, "http://httpbin.local/user.agent", Response(status=404)
99+
)
100+
response = urlopen("http://httpbin.local/ip")
99101
self.assertEqual(response.code, 200)
100102

101103

@@ -209,7 +211,7 @@ def test_mockhttp_entry_collect_duplicates(self):
209211

210212
@mocketize
211213
def test_multipart(self):
212-
url = "http://httpbin.org/post"
214+
url = "http://httpbin.local/post"
213215
data = '--xXXxXXyYYzzz\r\nContent-Disposition: form-data; name="content"\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: 68\r\n\r\nAction: comment\nText: Comment with attach\nAttachment: x1.txt, x2.txt\r\n--xXXxXXyYYzzz\r\nContent-Disposition: form-data; name="attachment_2"; filename="x.txt"\r\nContent-Type: text/plain\r\nContent-Length: 4\r\n\r\nbye\n\r\n--xXXxXXyYYzzz\r\nContent-Disposition: form-data; name="attachment_1"; filename="x.txt"\r\nContent-Type: text/plain\r\nContent-Length: 4\r\n\r\nbye\n\r\n--xXXxXXyYYzzz--\r\n'
214216
headers = {
215217
"Content-Length": "495",
@@ -233,7 +235,7 @@ def test_multipart(self):
233235
"accept-encoding": "identity",
234236
"content-length": "495",
235237
"content-type": "multipart/form-data; boundary=xXXxXXyYYzzz",
236-
"host": "httpbin.org",
238+
"host": "httpbin.local",
237239
"user-agent": "Mocket",
238240
"connection": "keep-alive",
239241
},
@@ -304,9 +306,11 @@ def test_request_bodies(self):
304306

305307
@mocketize(truesocket_recording_dir=os.path.dirname(__file__))
306308
def test_truesendall_with_dump_from_recording(self):
307-
requests.get("http://httpbin.org/ip", headers={"user-agent": "Fake-User-Agent"})
308309
requests.get(
309-
"http://httpbin.org/gzip", headers={"user-agent": "Fake-User-Agent"}
310+
"http://httpbin.local/ip", headers={"user-agent": "Fake-User-Agent"}
311+
)
312+
requests.get(
313+
"http://httpbin.local/gzip", headers={"user-agent": "Fake-User-Agent"}
310314
)
311315

312316
dump_filename = os.path.join(
@@ -315,7 +319,7 @@ def test_truesendall_with_dump_from_recording(self):
315319
with io.open(dump_filename) as f:
316320
responses = json.load(f)
317321

318-
self.assertEqual(len(responses["httpbin.org"]["80"].keys()), 2)
322+
self.assertEqual(len(responses["httpbin.local"]["80"].keys()), 2)
319323

320324
@mocketize
321325
def test_post_file_object(self):

tests/main/test_http_with_xxhash.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,26 @@
66
import os
77

88
import requests
9-
from tests.main.test_http import HttpTestCase
109

1110
from mocket import Mocket, mocketize
11+
from tests.main.test_http import HttpTestCase
1212

1313

1414
class HttpEntryTestCase(HttpTestCase):
15-
1615
@mocketize(truesocket_recording_dir=os.path.dirname(__file__))
1716
def test_truesendall_with_dump_from_recording(self):
18-
requests.get('http://httpbin.org/ip', headers={"user-agent": "Fake-User-Agent"})
19-
requests.get('http://httpbin.org/gzip', headers={"user-agent": "Fake-User-Agent"})
17+
requests.get(
18+
"http://httpbin.local/ip", headers={"user-agent": "Fake-User-Agent"}
19+
)
20+
requests.get(
21+
"http://httpbin.local/gzip", headers={"user-agent": "Fake-User-Agent"}
22+
)
2023

2124
dump_filename = os.path.join(
2225
Mocket.get_truesocket_recording_dir(),
23-
Mocket.get_namespace() + '.json',
26+
Mocket.get_namespace() + ".json",
2427
)
2528
with io.open(dump_filename) as f:
2629
responses = json.load(f)
2730

28-
self.assertEqual(len(responses['httpbin.org']['80'].keys()), 2)
31+
self.assertEqual(len(responses["httpbin.local"]["80"].keys()), 2)

0 commit comments

Comments
 (0)