Skip to content

Commit 12f3702

Browse files
authored
Merge pull request #2996 from reedsa/2546-formatter-handle-none
Handle `None` in the formatting middleware
2 parents 0a1da2d + 973ea10 commit 12f3702

File tree

3 files changed

+132
-1
lines changed

3 files changed

+132
-1
lines changed

newsfragments/2546.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Handle `None` in the formatting middleware
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import pytest
2+
from unittest.mock import (
3+
Mock,
4+
)
5+
6+
from web3 import (
7+
Web3,
8+
)
9+
from web3.middleware import (
10+
construct_error_generator_middleware,
11+
construct_formatting_middleware,
12+
construct_result_generator_middleware,
13+
)
14+
from web3.providers.base import (
15+
BaseProvider,
16+
)
17+
from web3.types import (
18+
RPCEndpoint,
19+
)
20+
21+
22+
class DummyProvider(BaseProvider):
23+
def make_request(self, method, params):
24+
raise NotImplementedError(f"Cannot make request for {method}:{params}")
25+
26+
27+
@pytest.fixture
28+
def w3():
29+
return Web3(provider=DummyProvider(), middlewares=[])
30+
31+
32+
def test_formatting_middleware(w3):
33+
# No formatters by default
34+
w3.middleware_onion.add(construct_formatting_middleware())
35+
w3.middleware_onion.add(
36+
construct_result_generator_middleware(
37+
{
38+
"test_endpoint": lambda method, params: "done",
39+
}
40+
)
41+
)
42+
43+
expected = "done"
44+
actual = w3.manager.request_blocking("test_endpoint", [])
45+
assert actual == expected
46+
47+
48+
def test_formatting_middleware_no_method(w3):
49+
w3.middleware_onion.add(construct_formatting_middleware())
50+
51+
# Formatting middleware requires an endpoint
52+
with pytest.raises(NotImplementedError):
53+
w3.manager.request_blocking("test_endpoint", [])
54+
55+
56+
def test_formatting_middleware_request_formatters(w3):
57+
callable_mock = Mock()
58+
w3.middleware_onion.add(
59+
construct_result_generator_middleware(
60+
{RPCEndpoint("test_endpoint"): lambda method, params: "done"}
61+
)
62+
)
63+
64+
w3.middleware_onion.add(
65+
construct_formatting_middleware(
66+
request_formatters={RPCEndpoint("test_endpoint"): callable_mock}
67+
)
68+
)
69+
70+
expected = "done"
71+
actual = w3.manager.request_blocking("test_endpoint", ["param1"])
72+
73+
callable_mock.assert_called_once_with(["param1"])
74+
assert actual == expected
75+
76+
77+
def test_formatting_middleware_result_formatters(w3):
78+
w3.middleware_onion.add(
79+
construct_result_generator_middleware(
80+
{RPCEndpoint("test_endpoint"): lambda method, params: "done"}
81+
)
82+
)
83+
w3.middleware_onion.add(
84+
construct_formatting_middleware(
85+
result_formatters={RPCEndpoint("test_endpoint"): lambda x: f"STATUS:{x}"}
86+
)
87+
)
88+
89+
expected = "STATUS:done"
90+
actual = w3.manager.request_blocking("test_endpoint", [])
91+
assert actual == expected
92+
93+
94+
def test_formatting_middleware_result_formatters_for_none(w3):
95+
w3.middleware_onion.add(
96+
construct_result_generator_middleware(
97+
{RPCEndpoint("test_endpoint"): lambda method, params: None}
98+
)
99+
)
100+
w3.middleware_onion.add(
101+
construct_formatting_middleware(
102+
result_formatters={RPCEndpoint("test_endpoint"): lambda x: hex(x)}
103+
)
104+
)
105+
106+
expected = None
107+
actual = w3.manager.request_blocking("test_endpoint", [])
108+
assert actual == expected
109+
110+
111+
def test_formatting_middleware_error_formatters(w3):
112+
w3.middleware_onion.add(
113+
construct_error_generator_middleware(
114+
{RPCEndpoint("test_endpoint"): lambda method, params: "error"}
115+
)
116+
)
117+
w3.middleware_onion.add(
118+
construct_formatting_middleware(
119+
result_formatters={RPCEndpoint("test_endpoint"): lambda x: f"STATUS:{x}"}
120+
)
121+
)
122+
123+
expected = "error"
124+
with pytest.raises(ValueError) as err:
125+
w3.manager.request_blocking("test_endpoint", [])
126+
assert str(err.value) == expected

web3/middleware/formatting.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ def _format_response(
5050
response, response_type, method_response_formatter(appropriate_response)
5151
)
5252

53-
if "result" in response and method in result_formatters:
53+
if (
54+
"result" in response
55+
and response["result"] is not None
56+
and method in result_formatters
57+
):
5458
return _format_response("result", result_formatters[method])
5559
elif "error" in response and method in error_formatters:
5660
return _format_response("error", error_formatters[method])

0 commit comments

Comments
 (0)