Skip to content

Commit

Permalink
Merge pull request #2996 from reedsa/2546-formatter-handle-none
Browse files Browse the repository at this point in the history
Handle `None` in the formatting middleware
  • Loading branch information
reedsa authored Jun 22, 2023
2 parents 0a1da2d + 973ea10 commit 12f3702
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 1 deletion.
1 change: 1 addition & 0 deletions newsfragments/2546.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Handle `None` in the formatting middleware
126 changes: 126 additions & 0 deletions tests/core/middleware/test_formatting_middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import pytest
from unittest.mock import (
Mock,
)

from web3 import (
Web3,
)
from web3.middleware import (
construct_error_generator_middleware,
construct_formatting_middleware,
construct_result_generator_middleware,
)
from web3.providers.base import (
BaseProvider,
)
from web3.types import (
RPCEndpoint,
)


class DummyProvider(BaseProvider):
def make_request(self, method, params):
raise NotImplementedError(f"Cannot make request for {method}:{params}")


@pytest.fixture
def w3():
return Web3(provider=DummyProvider(), middlewares=[])


def test_formatting_middleware(w3):
# No formatters by default
w3.middleware_onion.add(construct_formatting_middleware())
w3.middleware_onion.add(
construct_result_generator_middleware(
{
"test_endpoint": lambda method, params: "done",
}
)
)

expected = "done"
actual = w3.manager.request_blocking("test_endpoint", [])
assert actual == expected


def test_formatting_middleware_no_method(w3):
w3.middleware_onion.add(construct_formatting_middleware())

# Formatting middleware requires an endpoint
with pytest.raises(NotImplementedError):
w3.manager.request_blocking("test_endpoint", [])


def test_formatting_middleware_request_formatters(w3):
callable_mock = Mock()
w3.middleware_onion.add(
construct_result_generator_middleware(
{RPCEndpoint("test_endpoint"): lambda method, params: "done"}
)
)

w3.middleware_onion.add(
construct_formatting_middleware(
request_formatters={RPCEndpoint("test_endpoint"): callable_mock}
)
)

expected = "done"
actual = w3.manager.request_blocking("test_endpoint", ["param1"])

callable_mock.assert_called_once_with(["param1"])
assert actual == expected


def test_formatting_middleware_result_formatters(w3):
w3.middleware_onion.add(
construct_result_generator_middleware(
{RPCEndpoint("test_endpoint"): lambda method, params: "done"}
)
)
w3.middleware_onion.add(
construct_formatting_middleware(
result_formatters={RPCEndpoint("test_endpoint"): lambda x: f"STATUS:{x}"}
)
)

expected = "STATUS:done"
actual = w3.manager.request_blocking("test_endpoint", [])
assert actual == expected


def test_formatting_middleware_result_formatters_for_none(w3):
w3.middleware_onion.add(
construct_result_generator_middleware(
{RPCEndpoint("test_endpoint"): lambda method, params: None}
)
)
w3.middleware_onion.add(
construct_formatting_middleware(
result_formatters={RPCEndpoint("test_endpoint"): lambda x: hex(x)}
)
)

expected = None
actual = w3.manager.request_blocking("test_endpoint", [])
assert actual == expected


def test_formatting_middleware_error_formatters(w3):
w3.middleware_onion.add(
construct_error_generator_middleware(
{RPCEndpoint("test_endpoint"): lambda method, params: "error"}
)
)
w3.middleware_onion.add(
construct_formatting_middleware(
result_formatters={RPCEndpoint("test_endpoint"): lambda x: f"STATUS:{x}"}
)
)

expected = "error"
with pytest.raises(ValueError) as err:
w3.manager.request_blocking("test_endpoint", [])
assert str(err.value) == expected
6 changes: 5 additions & 1 deletion web3/middleware/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ def _format_response(
response, response_type, method_response_formatter(appropriate_response)
)

if "result" in response and method in result_formatters:
if (
"result" in response
and response["result"] is not None
and method in result_formatters
):
return _format_response("result", result_formatters[method])
elif "error" in response and method in error_formatters:
return _format_response("error", error_formatters[method])
Expand Down

0 comments on commit 12f3702

Please sign in to comment.