11
22import json
33from abc import ABCMeta , abstractmethod as abstract_method
4+ from asyncio import Future
45from collections import deque
56from inspect import isabstract as is_abstract
67from logging import DEBUG , Logger
78from socket import getdefaulttimeout as get_default_timeout
8- from typing import Container , Dict , List , Optional , Text , Tuple , Union
9- from httpx import AsyncClient , Response , codes , auth
9+ from typing import Container , List , Optional , Tuple , Union , Any , Dict
10+ from httpx import AsyncClient , Response , codes , BasicAuth
1011import asyncio
1112
1213from iota .exceptions import with_context
3132"""
3233
3334# Custom types for type hints and docstrings.
34- AdapterSpec = Union [Text , 'BaseAdapter' ]
35+ AdapterSpec = Union [str , 'BaseAdapter' ]
3536"""
3637Placeholder that means “URI or adapter instance”.
3738
4243# Load SplitResult for IDE type hinting and autocompletion.
4344from urllib .parse import SplitResult , urlsplit
4445
45- def async_return (result ):
46+
47+ def async_return (result : Any ) -> Future :
4648 """
4749 Turns 'result' into a `Future` object with 'result' value.
4850
@@ -52,6 +54,7 @@ def async_return(result):
5254 f .set_result (result )
5355 return f
5456
57+
5558class BadApiResponse (ValueError ):
5659 """
5760 Indicates that a non-success response was received from the node.
@@ -66,21 +69,20 @@ class InvalidUri(ValueError):
6669 pass
6770
6871
69- adapter_registry = {} # type : Dict[Text, AdapterMeta]
72+ adapter_registry : Dict [str , ' AdapterMeta' ] = {}
7073"""
7174Keeps track of available adapters and their supported protocols.
7275"""
7376
7477
75- def resolve_adapter (uri ):
76- # type: (AdapterSpec) -> BaseAdapter
78+ def resolve_adapter (uri : AdapterSpec ) -> 'BaseAdapter' :
7779 """
7880 Given a URI, returns a properly-configured adapter instance.
7981 """
8082 if isinstance (uri , BaseAdapter ):
8183 return uri
8284
83- parsed = urlsplit (uri ) # type: SplitResult
85+ parsed : SplitResult = urlsplit (uri )
8486
8587 if not parsed .scheme :
8688 raise with_context (
@@ -116,7 +118,7 @@ class AdapterMeta(ABCMeta):
116118 Automatically registers new adapter classes in ``adapter_registry``.
117119 """
118120
119- def __init__ (cls , what , bases = None , dict = None ):
121+ def __init__ (cls , what , bases = None , dict = None ) -> None :
120122 super (AdapterMeta , cls ).__init__ (what , bases , dict )
121123
122124 if not is_abstract (cls ):
@@ -125,8 +127,7 @@ def __init__(cls, what, bases=None, dict=None):
125127 # adapters.
126128 adapter_registry .setdefault (protocol , cls )
127129
128- def configure (cls , parsed ):
129- # type: (Union[Text, SplitResult]) -> HttpAdapter
130+ def configure (cls , parsed : Union [str , SplitResult ]) -> 'HttpAdapter' :
130131 """
131132 Creates a new instance using the specified URI.
132133
@@ -143,21 +144,20 @@ class BaseAdapter(object, metaclass=AdapterMeta):
143144 Adapters make it easy to customize the way an API instance
144145 communicates with a node.
145146 """
146- supported_protocols = () # type : Tuple[Text]
147+ supported_protocols : Tuple [str ] = ()
147148 """
148149 Protocols that ``resolve_adapter`` can use to identify this adapter
149150 type.
150151 """
151152
152- def __init__ (self ):
153+ def __init__ (self ) -> None :
153154 super (BaseAdapter , self ).__init__ ()
154155
155- self ._logger = None # type: Logger
156- self .local_pow = False # type: boolean
156+ self ._logger : Optional [ Logger ] = None
157+ self .local_pow : bool = False
157158
158159 @abstract_method
159- def get_uri (self ):
160- # type: () -> Text
160+ def get_uri (self ) -> str :
161161 """
162162 Returns the URI that this adapter will use.
163163 """
@@ -166,8 +166,7 @@ def get_uri(self):
166166 )
167167
168168 @abstract_method
169- def send_request (self , payload , ** kwargs ):
170- # type: (dict, dict) -> dict
169+ def send_request (self , payload : dict , ** kwargs : Any ) -> dict :
171170 """
172171 Sends an API request to the node.
173172
@@ -188,8 +187,7 @@ def send_request(self, payload, **kwargs):
188187 'Not implemented in {cls}.' .format (cls = type (self ).__name__ ),
189188 )
190189
191- def set_logger (self , logger ):
192- # type: (Logger) -> BaseAdapter
190+ def set_logger (self , logger : Logger ) -> 'BaseAdapter' :
193191 """
194192 Attaches a logger instance to the adapter.
195193 The adapter will send information about API requests/responses
@@ -198,16 +196,19 @@ def set_logger(self, logger):
198196 self ._logger = logger
199197 return self
200198
201- def _log (self , level , message , context = None ):
202- # type: (int, Text, Optional[dict]) -> None
199+ def _log (
200+ self ,
201+ level : int ,
202+ message : str ,
203+ context : Optional [dict ] = None
204+ ) -> None :
203205 """
204206 Sends a message to the instance's logger, if configured.
205207 """
206208 if self ._logger :
207209 self ._logger .log (level , message , extra = {'context' : context or {}})
208210
209- def set_local_pow (self , local_pow ):
210- # type: (bool) -> None
211+ def set_local_pow (self , local_pow : bool ) -> None :
211212 """
212213 Sets the local_pow attribute of the adapter. If it is true,
213214 attach_to_tangle command calls external interface to perform
@@ -216,6 +217,7 @@ def set_local_pow(self, local_pow):
216217 """
217218 self .local_pow = local_pow
218219
220+
219221class HttpAdapter (BaseAdapter ):
220222 """
221223 Sends standard HTTP(S) requests to the node.
@@ -229,7 +231,7 @@ class HttpAdapter(BaseAdapter):
229231 :param Optional[int] timeout:
230232 Connection timeout in seconds.
231233
232- :param Optional[Tuple(Text,Text )] authentication:
234+ :param Optional[Tuple(str,str )] authentication:
233235 Credetentials for basic authentication with the node.
234236
235237 :return:
@@ -257,16 +259,20 @@ class HttpAdapter(BaseAdapter):
257259 in the ``headers`` kwarg.
258260 """
259261
260- def __init__ (self , uri , timeout = None , authentication = None ):
261- # type: (Union[Text, SplitResult], Optional[int]) -> None
262+ def __init__ (
263+ self ,
264+ uri : Union [str , SplitResult ],
265+ timeout : Optional [int ] = None ,
266+ authentication : Optional [Tuple [str , str ]] = None
267+ ) -> None :
262268 super (HttpAdapter , self ).__init__ ()
263269
264270 self .client = AsyncClient ()
265271 self .timeout = timeout
266272 self .authentication = authentication
267273
268274 if isinstance (uri , str ):
269- uri = urlsplit (uri ) # type: SplitResult
275+ uri : SplitResult = urlsplit (uri )
270276
271277 if uri .scheme not in self .supported_protocols :
272278 raise with_context (
@@ -310,19 +316,16 @@ def __init__(self, uri, timeout=None, authentication=None):
310316 self .uri = uri
311317
312318 @property
313- def node_url (self ):
314- # type: () -> Text
319+ def node_url (self ) -> str :
315320 """
316321 Returns the node URL.
317322 """
318323 return self .uri .geturl ()
319324
320- def get_uri (self ):
321- # type: () -> Text
325+ def get_uri (self ) -> str :
322326 return self .uri .geturl ()
323327
324- async def send_request (self , payload , ** kwargs ):
325- # type: (dict, dict) -> dict
328+ async def send_request (self , payload : dict , ** kwargs : Any ) -> dict :
326329 kwargs .setdefault ('headers' , {})
327330 for key , value in self .DEFAULT_HEADERS .items ():
328331 kwargs ['headers' ].setdefault (key , value )
@@ -338,8 +341,13 @@ async def send_request(self, payload, **kwargs):
338341
339342 return self ._interpret_response (response , payload , {codes ['OK' ]})
340343
341- async def _send_http_request (self , url , payload , method = 'post' , ** kwargs ):
342- # type: (Text, Optional[Text], Text, dict) -> Response
344+ async def _send_http_request (
345+ self ,
346+ url : str ,
347+ payload : Optional [str ],
348+ method : str = 'post' ,
349+ ** kwargs : Any
350+ ) -> Response :
343351 """
344352 Sends the actual HTTP request.
345353
@@ -352,7 +360,7 @@ async def _send_http_request(self, url, payload, method='post', **kwargs):
352360 )
353361
354362 if self .authentication :
355- kwargs .setdefault ('auth' , auth . HTTPBasicAuth (* self .authentication ))
363+ kwargs .setdefault ('auth' , BasicAuth (* self .authentication ))
356364
357365 self ._log (
358366 level = DEBUG ,
@@ -394,8 +402,12 @@ async def _send_http_request(self, url, payload, method='post', **kwargs):
394402
395403 return response
396404
397- def _interpret_response (self , response , payload , expected_status ):
398- # type: (Response, dict, Container[int]) -> dict
405+ def _interpret_response (
406+ self ,
407+ response : Response ,
408+ payload : dict ,
409+ expected_status : Container [int ]
410+ ) -> dict :
399411 """
400412 Interprets the HTTP response from the node.
401413
@@ -425,7 +437,7 @@ def _interpret_response(self, response, payload, expected_status):
425437 )
426438
427439 try :
428- decoded = json .loads (raw_content ) # type: dict
440+ decoded : dict = json .loads (raw_content )
429441 # :bc: py2k doesn't have JSONDecodeError
430442 except ValueError :
431443 raise with_context (
@@ -523,17 +535,16 @@ class MockAdapter(BaseAdapter):
523535 def configure (cls , uri ):
524536 return cls ()
525537
526- def __init__ (self ):
538+ def __init__ (self ) -> None :
527539 super (MockAdapter , self ).__init__ ()
528540
529- self .responses = {} # type : Dict[Text , deque]
530- self .requests = [] # type: List[dict ]
541+ self .responses : Dict [str , deque ] = {}
542+ self .requests : List [ dict ] = [ ]
531543
532- def get_uri (self ):
544+ def get_uri (self ) -> str :
533545 return 'mock://'
534546
535- def seed_response (self , command , response ):
536- # type: (Text, dict) -> MockAdapter
547+ def seed_response (self , command : str , response : dict ) -> 'MockAdapter' :
537548 """
538549 Sets the response that the adapter will return for the specified
539550 command.
@@ -547,7 +558,7 @@ def seed_response(self, command, response):
547558 have a seeded response for a particular command, it will raise a
548559 ``BadApiResponse`` exception (simulates a 404 response).
549560
550- :param Text command:
561+ :param str command:
551562 The name of the command. Note that this is the camelCase version
552563 of the command name (e.g., ``getNodeInfo``, not ``get_node_info``).
553564
@@ -573,11 +584,10 @@ def seed_response(self, command, response):
573584 self .responses [command ].append (response )
574585 return self
575586
576- async def send_request (self , payload , ** kwargs ) :
587+ async def send_request (self , payload : Dict , ** kwargs : Any ) -> dict :
577588 """
578589 Mimic asynchronous behavior of `HttpAdapter.send_request`.
579590 """
580- # type: (dict, dict) -> dict
581591 # Store a snapshot so that we can inspect the request later.
582592 self .requests .append (dict (payload ))
583593
0 commit comments