Skip to content

Commit f7eeb78

Browse files
authored
Support for Python 3.12 (#204)
* Fix for Python 3.12 * Getting rid of Python 3.7, since it's not supported anymore. * Precommit hooks' autoupdate. * Disabling `aiohttp` for testing Python 3.12.
1 parent e69071a commit f7eeb78

File tree

11 files changed

+113
-121
lines changed

11 files changed

+113
-121
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
runs-on: ubuntu-20.04
1919
strategy:
2020
matrix:
21-
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', 'pypy3.10']
21+
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', 'pypy3.10']
2222

2323
steps:
2424
- uses: actions/checkout@v3

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
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.4.0
3+
rev: v4.5.0
44
hooks:
55
- id: check-yaml
66
args: ['--unsafe']
@@ -23,6 +23,6 @@ repos:
2323
- id: isort
2424

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

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ services-down:
1414

1515
test-python:
1616
@echo "Running Python tests"
17-
wait-for-it --service httpbin.local:443 --service localhost:6379 --timeout 5 -- python run_tests.py || exit 1
17+
wait-for-it --service httpbin.local:443 --service localhost:6379 --timeout 5 -- pytest tests/ || exit 1
1818
@echo ""
1919

2020
lint-python:

mocket/__init__.py

Lines changed: 1 addition & 1 deletion
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.1"
6+
__version__ = "3.12.0"

mocket/mocket.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@
5656
true_gethostname = socket.gethostname
5757
true_getaddrinfo = socket.getaddrinfo
5858
true_socketpair = socket.socketpair
59-
true_ssl_wrap_socket = ssl.wrap_socket
59+
true_ssl_wrap_socket = getattr(
60+
ssl, "wrap_socket", None
61+
) # in Py3.12 it's only under SSLContext
6062
true_ssl_socket = ssl.SSLSocket
6163
true_ssl_context = ssl.SSLContext
6264
true_inet_pton = socket.inet_pton
@@ -538,7 +540,8 @@ def disable():
538540
socket.gethostbyname = socket.__dict__["gethostbyname"] = true_gethostbyname
539541
socket.getaddrinfo = socket.__dict__["getaddrinfo"] = true_getaddrinfo
540542
socket.socketpair = socket.__dict__["socketpair"] = true_socketpair
541-
ssl.wrap_socket = ssl.__dict__["wrap_socket"] = true_ssl_wrap_socket
543+
if true_ssl_wrap_socket:
544+
ssl.wrap_socket = ssl.__dict__["wrap_socket"] = true_ssl_wrap_socket
542545
ssl.SSLContext = ssl.__dict__["SSLContext"] = true_ssl_context
543546
socket.inet_pton = socket.__dict__["inet_pton"] = true_inet_pton
544547
urllib3.util.ssl_.wrap_socket = urllib3.util.ssl_.__dict__[
@@ -602,9 +605,7 @@ def __init__(self, location, responses):
602605
else:
603606
self.responses = []
604607
for r in responses:
605-
if isinstance(r, BaseException):
606-
pass
607-
elif not getattr(r, "data", False):
608+
if not isinstance(r, BaseException) and not getattr(r, "data", False):
608609
if isinstance(r, text_type):
609610
r = encode_to_bytes(r)
610611
r = self.response_cls(r)

mocket/mockhttp.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
STATUS = {k: v[0] for k, v in BaseHTTPRequestHandler.responses.items()}
1818
CRLF = "\r\n"
19+
ASCII = "ascii"
1920

2021

2122
class Protocol:
@@ -25,7 +26,7 @@ def __init__(self):
2526
self.headers = {}
2627

2728
def on_header(self, name: bytes, value: bytes):
28-
self.headers[name.decode("ascii")] = value.decode("ascii")
29+
self.headers[name.decode(ASCII)] = value.decode(ASCII)
2930

3031
def on_body(self, body: bytes):
3132
try:
@@ -34,7 +35,7 @@ def on_body(self, body: bytes):
3435
self.body = body
3536

3637
def on_url(self, url: bytes):
37-
self.url = url.decode("ascii")
38+
self.url = url.decode(ASCII)
3839

3940

4041
class Request:
@@ -51,7 +52,7 @@ def add_data(self, data):
5152

5253
@property
5354
def method(self):
54-
return self._parser.get_method().decode("ascii")
55+
return self._parser.get_method().decode(ASCII)
5556

5657
@property
5758
def path(self):
@@ -110,7 +111,7 @@ def get_protocol_data(self, str_format_fun_name="capitalize"):
110111
for k, v in self.headers.items()
111112
)
112113
)
113-
return "{0}\r\n{1}\r\n\r\n".format(status_line, header_lines).encode("utf-8")
114+
return "{0}\r\n{1}\r\n\r\n".format(status_line, header_lines).encode(ENCODING)
114115

115116
def set_base_headers(self):
116117
self.headers = {
@@ -121,7 +122,7 @@ def set_base_headers(self):
121122
"Content-Length": str(len(self.body)),
122123
}
123124
if not self.is_file_object:
124-
self.headers["Content-Type"] = "text/plain; charset=utf-8"
125+
self.headers["Content-Type"] = f"text/plain; charset={ENCODING}"
125126
elif self.magic:
126127
self.headers["Content-Type"] = do_the_magic(self.magic, self.body)
127128

@@ -237,7 +238,6 @@ def _parse_requestline(line):
237238

238239
@classmethod
239240
def register(cls, method, uri, *responses, **config):
240-
241241
if "body" in config or "status" in config:
242242
raise AttributeError("Did you mean `Entry.single_register(...)`?")
243243

@@ -263,7 +263,6 @@ def single_register(
263263
match_querystring=True,
264264
exception=None,
265265
):
266-
267266
response = (
268267
exception
269268
if exception

pyproject.toml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ classifiers = [
1414
"Development Status :: 6 - Mature",
1515
"Intended Audience :: Developers",
1616
"Operating System :: OS Independent",
17-
"Programming Language :: Python :: 3.7",
1817
"Programming Language :: Python :: 3.8",
1918
"Programming Language :: Python :: 3.9",
2019
"Programming Language :: Python :: 3.10",
2120
"Programming Language :: Python :: 3.11",
21+
"Programming Language :: Python :: 3.12",
2222
"Programming Language :: Python :: Implementation :: CPython",
2323
"Programming Language :: Python :: Implementation :: PyPy",
2424
"Topic :: Software Development",
@@ -45,9 +45,9 @@ test = [
4545
"gevent",
4646
"sure",
4747
"pook",
48-
"flake8",
48+
"flake8>5",
4949
"xxhash",
50-
"aiohttp",
50+
"aiohttp;python_version<'3.12'",
5151
"httpx",
5252
"pipfile",
5353
"build",
@@ -56,8 +56,8 @@ test = [
5656
"wait-for-it",
5757
]
5858
speedups = [
59-
'xxhash;platform_python_implementation=="CPython"',
60-
'xxhash-cffi;platform_python_implementation=="PyPy"',
59+
"xxhash;platform_python_implementation=='CPython'",
60+
"xxhash-cffi;platform_python_implementation=='PyPy'",
6161
]
6262
pook = [
6363
"pook>=0.2.1",
@@ -71,7 +71,6 @@ ignore-vcs = true
7171

7272
[tool.hatch.build.targets.sdist]
7373
include = [
74-
"run_tests.py",
7574
"README.rst",
7675
"LICENSE",
7776
"pyproject.toml",

run_tests.py

Lines changed: 0 additions & 27 deletions
This file was deleted.

tests/main/test_https.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
from mocket.mockhttp import Entry
1212

1313

14+
@pytest.fixture
15+
def url_to_mock():
16+
return "https://httpbin.org/ip"
17+
18+
1419
@pytest.fixture
1520
def response():
1621
return {
@@ -39,13 +44,11 @@ def test_json(response):
3944

4045

4146
@pytest.mark.skipif('os.getenv("SKIP_TRUE_HTTP", False)')
42-
def test_truesendall_with_recording_https():
47+
def test_truesendall_with_recording_https(url_to_mock):
4348
with tempfile.TemporaryDirectory() as temp_dir:
4449
with Mocketizer(truesocket_recording_dir=temp_dir):
45-
url = "https://mockbin.org/ip"
46-
47-
requests.get(url, headers={"Accept": "application/json"})
48-
resp = requests.get(url, headers={"Accept": "application/json"})
50+
requests.get(url_to_mock, headers={"Accept": "application/json"})
51+
resp = requests.get(url_to_mock, headers={"Accept": "application/json"})
4952
assert resp.status_code == 200
5053

5154
dump_filename = os.path.join(
@@ -55,25 +58,25 @@ def test_truesendall_with_recording_https():
5558
with io.open(dump_filename) as f:
5659
responses = json.load(f)
5760

58-
assert len(responses["mockbin.org"]["443"].keys()) == 1
61+
assert len(responses["httpbin.org"]["443"].keys()) == 1
5962

6063

6164
@pytest.mark.skipif('os.getenv("SKIP_TRUE_HTTP", False)')
62-
def test_truesendall_after_mocket_session():
65+
def test_truesendall_after_mocket_session(url_to_mock):
6366
Mocket.enable()
6467
Mocket.disable()
6568

66-
url = "https://mockbin.org/ip"
67-
resp = requests.get(url)
69+
resp = requests.get(url_to_mock)
6870
assert resp.status_code == 200
6971

7072

7173
@pytest.mark.skipif('os.getenv("SKIP_TRUE_HTTP", False)')
72-
def test_real_request_session():
74+
def test_real_request_session(url_to_mock):
7375
session = requests.Session()
7476

75-
url1 = "https://mockbin.org/ip"
76-
url2 = "http://httpbin.org/headers"
77+
url_to_compare = "http://httpbin.org/headers"
7778

7879
with Mocketizer():
79-
assert len(session.get(url1).content) < len(session.get(url2).content)
80+
assert len(session.get(url_to_mock).content) < len(
81+
session.get(url_to_compare).content
82+
)

tests/main/test_httpx.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import json
22

3-
import aiohttp
43
import httpx
54
import pytest
65
from asgiref.sync import async_to_sync
@@ -9,11 +8,9 @@
98
from mocket.mockhttp import Entry
109
from mocket.plugins.httpretty import httprettified, httpretty
1110

12-
timeout = aiohttp.ClientTimeout(total=3)
13-
1411

1512
@mocketize
16-
@pytest.mark.parametrize("url", ["http://httpbin.org/ip", "https://httpbin.org/ip"])
13+
@pytest.mark.parametrize("url", ("http://httpbin.org/ip", "https://httpbin.org/ip"))
1714
def test_body(url):
1815
body = "asd" * 100
1916
Entry.single_register(Entry.GET, url, body=body, status=404)

0 commit comments

Comments
 (0)