Skip to content

Commit 44cb163

Browse files
committed
Remove legacy base methods and add tests
1 parent 6d906cd commit 44cb163

13 files changed

+410
-472
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,4 @@ repos:
4444
types: [python]
4545
files: "^tests/"
4646
args:
47-
- --disable=consider-using-f-string,duplicate-code,missing-docstring,invalid-name,protected-access
47+
- --disable=consider-using-f-string,duplicate-code,missing-docstring,invalid-name,protected-access,redefined-outer-name

adafruit_requests.py

Lines changed: 2 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class Response:
8686

8787
encoding = None
8888

89-
def __init__(self, sock: SocketType, session: Optional["Session"] = None) -> None:
89+
def __init__(self, sock: SocketType, session: "Session") -> None:
9090
self.socket = sock
9191
self.encoding = "utf-8"
9292
self._cached = None
@@ -101,10 +101,7 @@ def __init__(self, sock: SocketType, session: Optional["Session"] = None) -> Non
101101

102102
http = self._readto(b" ")
103103
if not http:
104-
if session:
105-
session._connection_manager.close_socket(self.socket)
106-
else:
107-
self.socket.close()
104+
session._connection_manager.close_socket(self.socket)
108105
raise RuntimeError("Unable to read HTTP response.")
109106
self.status_code: int = int(bytes(self._readto(b" ")))
110107
"""The status code returned by the server"""
@@ -614,67 +611,3 @@ def patch(self, url: str, **kw) -> Response:
614611
def delete(self, url: str, **kw) -> Response:
615612
"""Send HTTP DELETE request"""
616613
return self.request("DELETE", url, **kw)
617-
618-
619-
_default_session = None # pylint: disable=invalid-name
620-
621-
622-
def create_default_session(
623-
socket_pool: SocketpoolModuleType,
624-
ssl_context: Optional[SSLContextType] = None,
625-
):
626-
"""Create a default session for using globally"""
627-
global _default_session # pylint: disable=global-statement
628-
_default_session = Session(socket_pool, ssl_context)
629-
630-
631-
def request(
632-
method: str,
633-
url: str,
634-
data: Optional[Any] = None,
635-
json: Optional[Any] = None,
636-
headers: Optional[Dict[str, str]] = None,
637-
stream: bool = False,
638-
timeout: float = 1,
639-
) -> None:
640-
"""Send HTTP request"""
641-
# pylint: disable=too-many-arguments
642-
_default_session.request(
643-
method,
644-
url,
645-
data=data,
646-
json=json,
647-
headers=headers,
648-
stream=stream,
649-
timeout=timeout,
650-
)
651-
652-
653-
def head(url: str, **kw):
654-
"""Send HTTP HEAD request"""
655-
return _default_session.request("HEAD", url, **kw)
656-
657-
658-
def get(url: str, **kw):
659-
"""Send HTTP GET request"""
660-
return _default_session.request("GET", url, **kw)
661-
662-
663-
def post(url: str, **kw):
664-
"""Send HTTP POST request"""
665-
return _default_session.request("POST", url, **kw)
666-
667-
668-
def put(url: str, **kw):
669-
"""Send HTTP PUT request"""
670-
return _default_session.request("PUT", url, **kw)
671-
672-
673-
def patch(url: str, **kw):
674-
"""Send HTTP PATCH request"""
675-
return _default_session.request("PATCH", url, **kw)
676-
677-
678-
def delete(url: str, **kw):
679-
"""Send HTTP DELETE request"""
680-
return _default_session.request("DELETE", url, **kw)

conftest.py

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

tests/chunked_redirect_test.py

Lines changed: 126 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,25 @@
1313

1414
IP = "1.2.3.4"
1515
HOST = "docs.google.com"
16-
PATH = (
16+
PATH_BASE = (
1717
"/spreadsheets/d/e/2PACX-1vR1WjUKz35-ek6SiR5droDfvPp51MTds4wUs57vEZNh2uDfihSTPhTaiiRo"
18-
"vLbNe1mkeRgurppRJ_Zy/pub?output=tsv"
18+
"vLbNe1mkeRgurppRJ_Zy/"
19+
)
20+
PATH = PATH_BASE + "pub?output=tsv"
21+
22+
FILE_REDIRECT = (
23+
b"e@2PACX-1vR1WjUKz35-ek6SiR5droDfvPp51MTds4wUs57vEZNh2uDfihSTPhTai"
24+
b"iRovLbNe1mkeRgurppRJ_Zy?output=tsv"
25+
)
26+
RELATIVE_RELATIVE_REDIRECT = (
27+
b"370cmver1f290kjsnpar5ku2h9g/3llvt5u8njbvat22m9l19db1h4/1656191325000/109226138307867586192/*/"
28+
+ FILE_REDIRECT
29+
)
30+
RELATIVE_ABSOLUTE_REDIRECT = (
31+
b"/pub/70cmver1f290kjsnpar5ku2h9g/" + RELATIVE_RELATIVE_REDIRECT
32+
)
33+
ABSOLUTE_ABSOLUTE_REDIRECT = (
34+
b"https://doc-14-2g-sheets.googleusercontent.com" + RELATIVE_ABSOLUTE_REDIRECT
1935
)
2036

2137
# response headers returned from the initial request
@@ -26,10 +42,7 @@
2642
b"Pragma: no-cache\r\n"
2743
b"Expires: Mon, 01 Jan 1990 00:00:00 GMT\r\n"
2844
b"Date: Sat, 25 Jun 2022 21:08:48 GMT\r\n"
29-
b"Location: https://doc-14-2g-sheets.googleusercontent.com/pub/70cmver1f290kjsnpar5ku2h9g/3"
30-
b"llvt5u8njbvat22m9l19db1h4/1656191325000"
31-
b"/109226138307867586192/*/e@2PACX-1vR1WjUKz35-ek6SiR5droDfvPp51MTds4wUs57vEZNh2uDfihSTPhTai"
32-
b"iRovLbNe1mkeRgurppRJ_Zy?output=tsv\r\n"
45+
b"Location: NEW_LOCATION_HERE\r\n"
3346
b'P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."\r\n'
3447
b"X-Content-Type-Options: nosniff\r\n"
3548
b"X-XSS-Protection: 1; mode=block\r\n"
@@ -118,13 +131,16 @@ def _recv_into(self, buf, nbytes=0):
118131
return read
119132

120133

121-
def do_test_chunked_redirect():
134+
def test_chunked_absolute_absolute_redirect():
122135
pool = mocket.MocketPool()
123136
pool.getaddrinfo.return_value = ((None, None, None, None, (IP, 443)),)
124137
chunk = _chunk(BODY_REDIRECT, len(BODY_REDIRECT))
125138
chunk2 = _chunk(BODY, len(BODY))
126139

127-
sock1 = MocketRecvInto(HEADERS_REDIRECT + chunk)
140+
redirect = HEADERS_REDIRECT.replace(
141+
b"NEW_LOCATION_HERE", ABSOLUTE_ABSOLUTE_REDIRECT
142+
)
143+
sock1 = MocketRecvInto(redirect + chunk)
128144
sock2 = mocket.Mocket(HEADERS + chunk2)
129145
pool.socket.side_effect = (sock1, sock2)
130146

@@ -135,9 +151,109 @@ def do_test_chunked_redirect():
135151
sock2.connect.assert_called_once_with(
136152
("doc-14-2g-sheets.googleusercontent.com", 443)
137153
)
154+
sock2.send.assert_has_calls([mock.call(RELATIVE_ABSOLUTE_REDIRECT[1:])])
155+
156+
assert response.text == str(BODY, "utf-8")
157+
158+
159+
def test_chunked_relative_absolute_redirect():
160+
pool = mocket.MocketPool()
161+
pool.getaddrinfo.return_value = ((None, None, None, None, (IP, 443)),)
162+
chunk = _chunk(BODY_REDIRECT, len(BODY_REDIRECT))
163+
chunk2 = _chunk(BODY, len(BODY))
164+
165+
redirect = HEADERS_REDIRECT.replace(
166+
b"NEW_LOCATION_HERE", RELATIVE_ABSOLUTE_REDIRECT
167+
)
168+
sock1 = MocketRecvInto(redirect + chunk)
169+
sock2 = mocket.Mocket(HEADERS + chunk2)
170+
pool.socket.side_effect = (sock1, sock2)
171+
172+
requests_session = adafruit_requests.Session(pool, mocket.SSLContext())
173+
response = requests_session.get("https://" + HOST + PATH)
174+
175+
sock1.connect.assert_called_once_with((HOST, 443))
176+
sock2.connect.assert_called_once_with(("docs.google.com", 443))
177+
sock2.send.assert_has_calls([mock.call(RELATIVE_ABSOLUTE_REDIRECT[1:])])
178+
179+
assert response.text == str(BODY, "utf-8")
180+
181+
182+
def test_chunked_relative_relative_redirect():
183+
pool = mocket.MocketPool()
184+
pool.getaddrinfo.return_value = ((None, None, None, None, (IP, 443)),)
185+
chunk = _chunk(BODY_REDIRECT, len(BODY_REDIRECT))
186+
chunk2 = _chunk(BODY, len(BODY))
187+
188+
redirect = HEADERS_REDIRECT.replace(
189+
b"NEW_LOCATION_HERE", RELATIVE_RELATIVE_REDIRECT
190+
)
191+
sock1 = MocketRecvInto(redirect + chunk)
192+
sock2 = mocket.Mocket(HEADERS + chunk2)
193+
pool.socket.side_effect = (sock1, sock2)
194+
195+
requests_session = adafruit_requests.Session(pool, mocket.SSLContext())
196+
response = requests_session.get("https://" + HOST + PATH)
197+
198+
sock1.connect.assert_called_once_with((HOST, 443))
199+
sock2.connect.assert_called_once_with(("docs.google.com", 443))
200+
sock2.send.assert_has_calls(
201+
[mock.call(bytes(PATH_BASE[1:], "utf-8") + RELATIVE_RELATIVE_REDIRECT)]
202+
)
138203

139204
assert response.text == str(BODY, "utf-8")
140205

141206

142-
def test_chunked_redirect():
143-
do_test_chunked_redirect()
207+
def test_chunked_relative_relative_redirect_backstep():
208+
pool = mocket.MocketPool()
209+
pool.getaddrinfo.return_value = ((None, None, None, None, (IP, 443)),)
210+
chunk = _chunk(BODY_REDIRECT, len(BODY_REDIRECT))
211+
chunk2 = _chunk(BODY, len(BODY))
212+
213+
remove_paths = 2
214+
backstep = b"../" * remove_paths
215+
path_base_parts = PATH_BASE.split("/")
216+
# PATH_BASE starts with "/" so skip it and also remove from the count
217+
path_base = (
218+
"/".join(path_base_parts[1 : len(path_base_parts) - remove_paths - 1]) + "/"
219+
)
220+
221+
redirect = HEADERS_REDIRECT.replace(
222+
b"NEW_LOCATION_HERE", backstep + RELATIVE_RELATIVE_REDIRECT
223+
)
224+
sock1 = MocketRecvInto(redirect + chunk)
225+
sock2 = mocket.Mocket(HEADERS + chunk2)
226+
pool.socket.side_effect = (sock1, sock2)
227+
228+
requests_session = adafruit_requests.Session(pool, mocket.SSLContext())
229+
response = requests_session.get("https://" + HOST + PATH)
230+
231+
sock1.connect.assert_called_once_with((HOST, 443))
232+
sock2.connect.assert_called_once_with(("docs.google.com", 443))
233+
sock2.send.assert_has_calls(
234+
[mock.call(bytes(path_base, "utf-8") + RELATIVE_RELATIVE_REDIRECT)]
235+
)
236+
237+
assert response.text == str(BODY, "utf-8")
238+
239+
240+
def test_chunked_allow_redirects_false():
241+
pool = mocket.MocketPool()
242+
pool.getaddrinfo.return_value = ((None, None, None, None, (IP, 443)),)
243+
chunk = _chunk(BODY_REDIRECT, len(BODY_REDIRECT))
244+
chunk2 = _chunk(BODY, len(BODY))
245+
246+
redirect = HEADERS_REDIRECT.replace(
247+
b"NEW_LOCATION_HERE", ABSOLUTE_ABSOLUTE_REDIRECT
248+
)
249+
sock1 = MocketRecvInto(redirect + chunk)
250+
sock2 = mocket.Mocket(HEADERS + chunk2)
251+
pool.socket.side_effect = (sock1, sock2)
252+
253+
requests_session = adafruit_requests.Session(pool, mocket.SSLContext())
254+
response = requests_session.get("https://" + HOST + PATH, allow_redirects=False)
255+
256+
sock1.connect.assert_called_once_with((HOST, 443))
257+
sock2.connect.assert_not_called()
258+
259+
assert response.text == str(BODY_REDIRECT, "utf-8")

tests/concurrent_test.py

Lines changed: 21 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,16 @@
99

1010
import mocket
1111

12-
import adafruit_requests
13-
14-
IP = "1.2.3.4"
15-
HOST = "wifitest.adafruit.com"
16-
HOST2 = "test.adafruit.com"
17-
PATH = "/testwifi/index.html"
18-
TEXT = b"This is a test of Adafruit WiFi!\r\nIf you can read this, its working :)"
19-
RESPONSE = b"HTTP/1.0 200 OK\r\nContent-Length: 70\r\n\r\n" + TEXT
20-
21-
22-
def test_second_connect_fails_memoryerror():
23-
pool = mocket.MocketPool()
24-
pool.getaddrinfo.return_value = ((None, None, None, None, (IP, 80)),)
25-
sock = mocket.Mocket(RESPONSE)
26-
sock2 = mocket.Mocket(RESPONSE)
27-
sock3 = mocket.Mocket(RESPONSE)
12+
13+
def test_second_connect_fails_memoryerror(pool, requests_ssl):
14+
sock = mocket.Mocket()
15+
sock2 = mocket.Mocket()
16+
sock3 = mocket.Mocket()
2817
pool.socket.call_count = 0 # Reset call count
2918
pool.socket.side_effect = [sock, sock2, sock3]
3019
sock2.connect.side_effect = MemoryError()
3120

32-
ssl = mocket.SSLContext()
33-
34-
requests_session = adafruit_requests.Session(pool, ssl)
35-
response = requests_session.get("https://" + HOST + PATH)
21+
response = requests_ssl.get("https://" + mocket.MOCK_ENDPOINT_1)
3622

3723
sock.send.assert_has_calls(
3824
[
@@ -48,34 +34,29 @@ def test_second_connect_fails_memoryerror():
4834
mock.call(b"\r\n"),
4935
]
5036
)
51-
assert response.text == str(TEXT, "utf-8")
37+
assert response.text == str(mocket.MOCK_RESPONSE_TEXT, "utf-8")
5238

53-
requests_session.get("https://" + HOST2 + PATH)
39+
requests_ssl.get("https://" + mocket.MOCK_ENDPOINT_2)
5440

55-
sock.connect.assert_called_once_with((HOST, 443))
56-
sock2.connect.assert_called_once_with((HOST2, 443))
57-
sock3.connect.assert_called_once_with((HOST2, 443))
41+
sock.connect.assert_called_once_with((mocket.MOCK_HOST_1, 443))
42+
sock2.connect.assert_called_once_with((mocket.MOCK_HOST_2, 443))
43+
sock3.connect.assert_called_once_with((mocket.MOCK_HOST_2, 443))
5844
# Make sure that the socket is closed after send fails.
5945
sock.close.assert_called_once()
6046
sock2.close.assert_called_once()
6147
assert sock3.close.call_count == 0
6248
assert pool.socket.call_count == 3
6349

6450

65-
def test_second_connect_fails_oserror():
66-
pool = mocket.MocketPool()
67-
pool.getaddrinfo.return_value = ((None, None, None, None, (IP, 80)),)
68-
sock = mocket.Mocket(RESPONSE)
69-
sock2 = mocket.Mocket(RESPONSE)
70-
sock3 = mocket.Mocket(RESPONSE)
51+
def test_second_connect_fails_oserror(pool, requests_ssl):
52+
sock = mocket.Mocket()
53+
sock2 = mocket.Mocket()
54+
sock3 = mocket.Mocket()
7155
pool.socket.call_count = 0 # Reset call count
7256
pool.socket.side_effect = [sock, sock2, sock3]
7357
sock2.connect.side_effect = OSError(errno.ENOMEM)
7458

75-
ssl = mocket.SSLContext()
76-
77-
requests_session = adafruit_requests.Session(pool, ssl)
78-
response = requests_session.get("https://" + HOST + PATH)
59+
response = requests_ssl.get("https://" + mocket.MOCK_ENDPOINT_1)
7960

8061
sock.send.assert_has_calls(
8162
[
@@ -91,13 +72,13 @@ def test_second_connect_fails_oserror():
9172
mock.call(b"\r\n"),
9273
]
9374
)
94-
assert response.text == str(TEXT, "utf-8")
75+
assert response.text == str(mocket.MOCK_RESPONSE_TEXT, "utf-8")
9576

96-
requests_session.get("https://" + HOST2 + PATH)
77+
requests_ssl.get("https://" + mocket.MOCK_ENDPOINT_2)
9778

98-
sock.connect.assert_called_once_with((HOST, 443))
99-
sock2.connect.assert_called_once_with((HOST2, 443))
100-
sock3.connect.assert_called_once_with((HOST2, 443))
79+
sock.connect.assert_called_once_with((mocket.MOCK_HOST_1, 443))
80+
sock2.connect.assert_called_once_with((mocket.MOCK_HOST_2, 443))
81+
sock3.connect.assert_called_once_with((mocket.MOCK_HOST_2, 443))
10182
# Make sure that the socket is closed after send fails.
10283
sock.close.assert_called_once()
10384
sock2.close.assert_called_once()

0 commit comments

Comments
 (0)