Skip to content

Commit fd60ca4

Browse files
committed
Add type hints to web3.providers
1 parent dfdf94d commit fd60ca4

File tree

8 files changed

+172
-64
lines changed

8 files changed

+172
-64
lines changed

web3/manager.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ def __init__(
7474
if middlewares is None:
7575
middlewares = self.default_middlewares(web3)
7676

77-
self.middleware_onion: NamedElementOnion[str, Middleware] = NamedElementOnion(middlewares)
77+
# web3/manager.py:77: error: "NamedElementOnion" expects 2 type arguments, but 1 given
78+
self.middleware_onion: NamedElementOnion[Sequence[Tuple[Middleware, str]]] = NamedElementOnion(middlewares) # type: ignore # noqa: E501
7879

7980
if provider is None:
8081
self.provider = AutoProvider()

web3/providers/auto.py

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
11
import os
2+
from typing import (
3+
Any,
4+
Callable,
5+
Dict,
6+
Optional,
7+
Sequence,
8+
Tuple,
9+
Type,
10+
Union,
11+
)
212
from urllib.parse import (
313
urlparse,
414
)
515

16+
from eth_typing import (
17+
URI,
18+
)
19+
620
from web3.exceptions import (
721
CannotHandleRequest,
822
)
@@ -12,20 +26,26 @@
1226
IPCProvider,
1327
WebsocketProvider,
1428
)
29+
from web3.types import (
30+
RPCEndpoint,
31+
RPCResponse,
32+
)
1533

1634
HTTP_SCHEMES = {'http', 'https'}
1735
WS_SCHEMES = {'ws', 'wss'}
1836

1937

20-
def load_provider_from_environment():
21-
uri_string = os.environ.get('WEB3_PROVIDER_URI', '')
38+
def load_provider_from_environment() -> BaseProvider:
39+
uri_string = URI(os.environ.get('WEB3_PROVIDER_URI', ''))
2240
if not uri_string:
2341
return None
2442

2543
return load_provider_from_uri(uri_string)
2644

2745

28-
def load_provider_from_uri(uri_string, headers=None):
46+
def load_provider_from_uri(
47+
uri_string: URI, headers: Dict[str, Tuple[str, str]]=None
48+
) -> BaseProvider:
2949
uri = urlparse(uri_string)
3050
if uri.scheme == 'file':
3151
return IPCProvider(uri.path)
@@ -52,7 +72,10 @@ class AutoProvider(BaseProvider):
5272
)
5373
_active_provider = None
5474

55-
def __init__(self, potential_providers=None):
75+
def __init__(
76+
self,
77+
potential_providers: Sequence[Union[Callable[..., BaseProvider], Type[BaseProvider]]]=None
78+
) -> None:
5679
"""
5780
:param iterable potential_providers: ordered series of provider classes to attempt with
5881
@@ -65,17 +88,17 @@ def __init__(self, potential_providers=None):
6588
else:
6689
self._potential_providers = self.default_providers
6790

68-
def make_request(self, method, params):
91+
def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
6992
try:
7093
return self._proxy_request(method, params)
7194
except IOError as exc:
7295
return self._proxy_request(method, params, use_cache=False)
7396

74-
def isConnected(self):
97+
def isConnected(self) -> bool:
7598
provider = self._get_active_provider(use_cache=True)
7699
return provider is not None and provider.isConnected()
77100

78-
def _proxy_request(self, method, params, use_cache=True):
101+
def _proxy_request(self, method: RPCEndpoint, params: Any, use_cache: bool=True) -> RPCResponse:
79102
provider = self._get_active_provider(use_cache)
80103
if provider is None:
81104
raise CannotHandleRequest(
@@ -87,7 +110,7 @@ def _proxy_request(self, method, params, use_cache=True):
87110

88111
return provider.make_request(method, params)
89112

90-
def _get_active_provider(self, use_cache):
113+
def _get_active_provider(self, use_cache: bool) -> Optional[BaseProvider]:
91114
if use_cache and self._active_provider is not None:
92115
return self._active_provider
93116

web3/providers/base.py

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
import itertools
2+
from typing import (
3+
TYPE_CHECKING,
4+
Any,
5+
Callable,
6+
Sequence,
7+
Tuple,
8+
)
29

310
from eth_utils import (
411
to_bytes,
@@ -8,24 +15,41 @@
815
from web3._utils.encoding import (
916
FriendlyJsonSerde,
1017
)
18+
from web3.datastructures import (
19+
NamedElementOnion,
20+
)
1121
from web3.middleware import (
1222
combine_middlewares,
1323
)
24+
from web3.types import (
25+
Middleware,
26+
RPCEndpoint,
27+
RPCResponse,
28+
)
29+
30+
if TYPE_CHECKING:
31+
from web3 import Web3 # noqa: F401
1432

1533

1634
class BaseProvider:
17-
_middlewares = ()
18-
_request_func_cache = (None, None) # a tuple of (all_middlewares, request_func)
35+
_middlewares: Tuple[Middleware, ...] = ()
36+
# a tuple of (all_middlewares, request_func)
37+
_request_func_cache: Tuple[Tuple[Middleware, ...], Callable[..., RPCResponse]] = (None, None)
1938

2039
@property
21-
def middlewares(self):
40+
def middlewares(self) -> Tuple[Middleware, ...]:
2241
return self._middlewares
2342

43+
# web3/manager.py:77: error: "NamedElementOnion" expects 2 type arguments, but 1 given
2444
@middlewares.setter
25-
def middlewares(self, values):
45+
def middlewares(
46+
self, values: NamedElementOnion[Sequence[Tuple[Middleware, str]]] # type: ignore
47+
) -> None:
2648
self._middlewares = tuple(values)
2749

28-
def request_func(self, web3, outer_middlewares):
50+
def request_func(
51+
self, web3: "Web3", outer_middlewares: Sequence[Middleware]
52+
) -> Callable[..., RPCResponse]:
2953
"""
3054
@param outer_middlewares is an iterable of middlewares, ordered by first to execute
3155
@returns a function that calls all the middleware and eventually self.make_request()
@@ -40,29 +64,31 @@ def request_func(self, web3, outer_middlewares):
4064
)
4165
return self._request_func_cache[-1]
4266

43-
def _generate_request_func(self, web3, middlewares):
67+
def _generate_request_func(
68+
self, web3: "Web3", middlewares: Sequence[Middleware]
69+
) -> Callable[..., RPCResponse]:
4470
return combine_middlewares(
4571
middlewares=middlewares,
4672
web3=web3,
4773
provider_request_fn=self.make_request,
4874
)
4975

50-
def make_request(self, method, params):
76+
def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
5177
raise NotImplementedError("Providers must implement this method")
5278

53-
def isConnected(self):
79+
def isConnected(self) -> bool:
5480
raise NotImplementedError("Providers must implement this method")
5581

5682

5783
class JSONBaseProvider(BaseProvider):
58-
def __init__(self):
84+
def __init__(self) -> None:
5985
self.request_counter = itertools.count()
6086

61-
def decode_rpc_response(self, response):
62-
text_response = to_text(response)
87+
def decode_rpc_response(self, raw_response: bytes) -> RPCResponse:
88+
text_response = to_text(raw_response)
6389
return FriendlyJsonSerde().json_decode(text_response)
6490

65-
def encode_rpc_request(self, method, params):
91+
def encode_rpc_request(self, method: RPCEndpoint, params: Any) -> bytes:
6692
rpc_dict = {
6793
"jsonrpc": "2.0",
6894
"method": method,
@@ -72,9 +98,9 @@ def encode_rpc_request(self, method, params):
7298
encoded = FriendlyJsonSerde().json_encode(rpc_dict)
7399
return to_bytes(text=encoded)
74100

75-
def isConnected(self):
101+
def isConnected(self) -> bool:
76102
try:
77-
response = self.make_request('web3_clientVersion', [])
103+
response = self.make_request(RPCEndpoint('web3_clientVersion'), [])
78104
except IOError:
79105
return False
80106

web3/providers/eth_tester/defaults.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ def not_implemented(*args: Any, **kwargs: Any) -> NoReturn:
5757
raise NotImplementedError("RPC method not implemented")
5858

5959

60-
# double check RPCResponse
6160
@curry
6261
def call_eth_tester(
6362
fn_name: str, eth_tester: "EthereumTester", fn_args: Any, fn_kwargs: Any=None

web3/providers/eth_tester/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ async def make_request(
4444

4545

4646
class EthereumTesterProvider(BaseProvider):
47-
middlewares = [
47+
middlewares = (
4848
default_transaction_fields_middleware,
4949
ethereum_tester_middleware,
50-
]
50+
)
5151
ethereum_tester = None
5252
api_endpoints = None
5353

0 commit comments

Comments
 (0)