Skip to content

Commit 065a1da

Browse files
authored
Merge pull request #1520 from njgheorghita/type-hints-providers
Type hints web3.providers
2 parents d0ae459 + 645085d commit 065a1da

File tree

12 files changed

+186
-83
lines changed

12 files changed

+186
-83
lines changed

ens/constants.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from eth_typing import (
22
HexAddress,
3+
HexStr,
34
)
45
from hexbytes import (
56
HexBytes,
@@ -11,6 +12,6 @@
1112
AUCTION_START_GAS_MARGINAL = 39000
1213

1314
EMPTY_SHA3_BYTES = HexBytes(b'\0' * 32)
14-
EMPTY_ADDR_HEX = HexAddress('0x' + '00' * 20)
15+
EMPTY_ADDR_HEX = HexAddress(HexStr('0x' + '00' * 20))
1516

1617
REVERSE_REGISTRAR_DOMAIN = 'addr.reverse'

ens/main.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
ChecksumAddress,
1313
Hash32,
1414
HexAddress,
15+
HexStr,
1516
)
1617
from eth_utils import (
1718
is_binary_address,
@@ -56,7 +57,9 @@
5657
)
5758

5859

59-
ENS_MAINNET_ADDR = ChecksumAddress(HexAddress('0x314159265dD8dbb310642f98f50C066173C1259b'))
60+
ENS_MAINNET_ADDR = ChecksumAddress(
61+
HexAddress(HexStr('0x314159265dD8dbb310642f98f50C066173C1259b'))
62+
)
6063

6164

6265
class ENS:

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,4 @@ extras=linter
6363
commands=
6464
flake8 {toxinidir}/web3 {toxinidir}/ens {toxinidir}/ethpm {toxinidir}/tests
6565
isort --recursive --check-only --diff {toxinidir}/web3/ {toxinidir}/ens/ {toxinidir}/ethpm/ {toxinidir}/tests/
66-
mypy -p web3.providers.eth_tester -p web3.main -p web3.contract -p web3.datastructures -p web3.eth -p web3.exceptions -p web3.geth -p web3.iban -p web3.logs -p web3.manager -p web3.module -p web3.net -p web3.parity -p web3.middleware -p web3.pm -p web3.auto -p web3.gas_strategies -p web3.testing -p web3.tools -p web3.version -p ethpm -p ens --config-file {toxinidir}/mypy.ini
66+
mypy -p web3.providers -p web3.main -p web3.contract -p web3.datastructures -p web3.eth -p web3.exceptions -p web3.geth -p web3.iban -p web3.logs -p web3.manager -p web3.module -p web3.net -p web3.parity -p web3.middleware -p web3.pm -p web3.auto -p web3.gas_strategies -p web3.testing -p web3.tools -p web3.version -p ethpm -p ens --config-file {toxinidir}/mypy.ini

web3/main.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,6 @@
4747
from web3._utils.normalizers import (
4848
abi_ens_resolver,
4949
)
50-
from web3.datastructures import (
51-
NamedElementOnion,
52-
)
5350
from web3.eth import (
5451
Eth,
5552
)
@@ -93,8 +90,9 @@
9390
from web3.testing import (
9491
Testing,
9592
)
96-
from web3.types import (
93+
from web3.types import ( # noqa: F401
9794
Middleware,
95+
MiddlewareOnion,
9896
)
9997
from web3.version import (
10098
Version,
@@ -175,7 +173,7 @@ def __init__(
175173
self.ens = ens
176174

177175
@property
178-
def middleware_onion(self) -> NamedElementOnion[str, Middleware]:
176+
def middleware_onion(self) -> MiddlewareOnion:
179177
return self.manager.middleware_onion
180178

181179
@property

web3/manager.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
Dict,
77
List,
88
NoReturn,
9+
Optional,
910
Sequence,
1011
Tuple,
1112
)
@@ -40,8 +41,9 @@
4041
AutoProvider,
4142
BaseProvider,
4243
)
43-
from web3.types import (
44+
from web3.types import ( # noqa: F401
4445
Middleware,
46+
MiddlewareOnion,
4547
RPCResponse,
4648
)
4749

@@ -74,7 +76,7 @@ def __init__(
7476
if middlewares is None:
7577
middlewares = self.default_middlewares(web3)
7678

77-
self.middleware_onion: NamedElementOnion[str, Middleware] = NamedElementOnion(middlewares)
79+
self.middleware_onion: MiddlewareOnion = NamedElementOnion(middlewares)
7880

7981
if provider is None:
8082
self.provider = AutoProvider()
@@ -117,14 +119,14 @@ def default_middlewares(
117119
def _make_request(self, method: str, params: Any) -> RPCResponse:
118120
request_func = self.provider.request_func(
119121
self.web3,
120-
tuple(self.middleware_onion))
122+
self.middleware_onion)
121123
self.logger.debug("Making request. Method: %s", method)
122124
return request_func(method, params)
123125

124126
async def _coro_make_request(self, method: str, params: Any) -> RPCResponse:
125127
request_func = self.provider.request_func(
126128
self.web3,
127-
tuple(self.middleware_onion))
129+
self.middleware_onion)
128130
self.logger.debug("Making request. Method: %s", method)
129131
return await request_func(method, params)
130132

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: 42 additions & 17 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,
@@ -11,26 +18,42 @@
1118
from web3.middleware import (
1219
combine_middlewares,
1320
)
21+
from web3.types import (
22+
Middleware,
23+
MiddlewareOnion,
24+
RPCEndpoint,
25+
RPCResponse,
26+
)
27+
28+
if TYPE_CHECKING:
29+
from web3 import Web3 # noqa: F401
1430

1531

1632
class BaseProvider:
17-
_middlewares = ()
18-
_request_func_cache = (None, None) # a tuple of (all_middlewares, request_func)
33+
_middlewares: Tuple[Middleware, ...] = ()
34+
# a tuple of (all_middlewares, request_func)
35+
_request_func_cache: Tuple[Tuple[Middleware, ...], Callable[..., RPCResponse]] = (None, None)
1936

2037
@property
21-
def middlewares(self):
38+
def middlewares(self) -> Tuple[Middleware, ...]:
2239
return self._middlewares
2340

2441
@middlewares.setter
25-
def middlewares(self, values):
26-
self._middlewares = tuple(values)
27-
28-
def request_func(self, web3, outer_middlewares):
42+
def middlewares(
43+
self, values: MiddlewareOnion
44+
) -> None:
45+
# tuple(values) converts to MiddlewareOnion -> Tuple[Middleware, ...]
46+
self._middlewares = tuple(values) # type: ignore
47+
48+
def request_func(
49+
self, web3: "Web3", outer_middlewares: MiddlewareOnion
50+
) -> Callable[..., RPCResponse]:
2951
"""
3052
@param outer_middlewares is an iterable of middlewares, ordered by first to execute
3153
@returns a function that calls all the middleware and eventually self.make_request()
3254
"""
33-
all_middlewares = tuple(outer_middlewares) + tuple(self.middlewares)
55+
# type ignored b/c tuple(MiddlewareOnion) converts to tuple of middlewares
56+
all_middlewares: Tuple[Middleware] = tuple(outer_middlewares) + tuple(self.middlewares) # type: ignore # noqa: E501
3457

3558
cache_key = self._request_func_cache[0]
3659
if cache_key is None or cache_key != all_middlewares:
@@ -40,29 +63,31 @@ def request_func(self, web3, outer_middlewares):
4063
)
4164
return self._request_func_cache[-1]
4265

43-
def _generate_request_func(self, web3, middlewares):
66+
def _generate_request_func(
67+
self, web3: "Web3", middlewares: Sequence[Middleware]
68+
) -> Callable[..., RPCResponse]:
4469
return combine_middlewares(
4570
middlewares=middlewares,
4671
web3=web3,
4772
provider_request_fn=self.make_request,
4873
)
4974

50-
def make_request(self, method, params):
75+
def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
5176
raise NotImplementedError("Providers must implement this method")
5277

53-
def isConnected(self):
78+
def isConnected(self) -> bool:
5479
raise NotImplementedError("Providers must implement this method")
5580

5681

5782
class JSONBaseProvider(BaseProvider):
58-
def __init__(self):
83+
def __init__(self) -> None:
5984
self.request_counter = itertools.count()
6085

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

65-
def encode_rpc_request(self, method, params):
90+
def encode_rpc_request(self, method: RPCEndpoint, params: Any) -> bytes:
6691
rpc_dict = {
6792
"jsonrpc": "2.0",
6893
"method": method,
@@ -72,9 +97,9 @@ def encode_rpc_request(self, method, params):
7297
encoded = FriendlyJsonSerde().json_encode(rpc_dict)
7398
return to_bytes(text=encoded)
7499

75-
def isConnected(self):
100+
def isConnected(self) -> bool:
76101
try:
77-
response = self.make_request('web3_clientVersion', [])
102+
response = self.make_request(RPCEndpoint('web3_clientVersion'), [])
78103
except IOError:
79104
return False
80105

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)