diff --git a/duniterpy/api/bma/blockchain.py b/duniterpy/api/bma/blockchain.py index 8cd3fa45ad6ce204c24c18af39358a4d14b58208..57faf3c232f155513ab2fb09f65d8c9b74dc7768 100644 --- a/duniterpy/api/bma/blockchain.py +++ b/duniterpy/api/bma/blockchain.py @@ -18,9 +18,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. import logging from typing import Union -from aiohttp import ClientResponse +from http.client import HTTPResponse -from duniterpy.api.client import Client, RESPONSE_AIOHTTP +from duniterpy.api.client import Client, RESPONSE_HTTP logger = logging.getLogger("duniter/blockchain") @@ -222,17 +222,17 @@ DIFFICULTIES_SCHEMA = { BRANCHES_SCHEMA = {"type": "object", "properties": {"blocks": BLOCKS_SCHEMA}} -async def parameters(client: Client) -> dict: +def parameters(client: Client) -> dict: """ GET the blockchain parameters used by this node :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/parameters", schema=PARAMETERS_SCHEMA) + return client.get(MODULE + "/parameters", schema=PARAMETERS_SCHEMA) -async def memberships(client: Client, search: str) -> dict: +def memberships(client: Client, search: str) -> dict: """ GET list of Membership documents for UID/Public key @@ -240,12 +240,10 @@ async def memberships(client: Client, search: str) -> dict: :param search: UID/Public key :return: """ - return await client.get( - MODULE + "/memberships/%s" % search, schema=MEMBERSHIPS_SCHEMA - ) + return client.get(MODULE + "/memberships/%s" % search, schema=MEMBERSHIPS_SCHEMA) -async def membership(client: Client, membership_signed_raw: str) -> ClientResponse: +def membership(client: Client, membership_signed_raw: str) -> HTTPResponse: """ POST a Membership document @@ -253,26 +251,26 @@ async def membership(client: Client, membership_signed_raw: str) -> ClientRespon :param membership_signed_raw: Membership signed raw document :return: """ - return await client.post( + return client.post( MODULE + "/membership", {"membership": membership_signed_raw}, - rtype=RESPONSE_AIOHTTP, + rtype=RESPONSE_HTTP, ) -async def current(client: Client) -> dict: +def current(client: Client) -> dict: """ GET the last accepted block :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/current", schema=BLOCK_SCHEMA) + return client.get(MODULE + "/current", schema=BLOCK_SCHEMA) -async def block( +def block( client: Client, number: int = 0, block_raw: str = None, signature: str = None -) -> Union[dict, ClientResponse]: +) -> Union[dict, HTTPResponse]: """ GET/POST a block from/to the blockchain @@ -284,16 +282,16 @@ async def block( """ # POST block if block_raw is not None and signature is not None: - return await client.post( + return client.post( MODULE + "/block", {"block": block_raw, "signature": signature}, - rtype=RESPONSE_AIOHTTP, + rtype=RESPONSE_HTTP, ) # GET block - return await client.get(MODULE + "/block/%d" % number, schema=BLOCK_SCHEMA) + return client.get(MODULE + "/block/%d" % number, schema=BLOCK_SCHEMA) -async def blocks(client: Client, count: int, start: int) -> list: +def blocks(client: Client, count: int, start: int) -> list: """ GET list of blocks from the blockchain @@ -305,12 +303,10 @@ async def blocks(client: Client, count: int, start: int) -> list: assert type(count) is int assert type(start) is int - return await client.get( - MODULE + "/blocks/%d/%d" % (count, start), schema=BLOCKS_SCHEMA - ) + return client.get(MODULE + "/blocks/%d/%d" % (count, start), schema=BLOCKS_SCHEMA) -async def hardship(client: Client, pubkey: str) -> dict: +def hardship(client: Client, pubkey: str) -> dict: """ GET hardship level for given member's public key for writing next block @@ -318,114 +314,114 @@ async def hardship(client: Client, pubkey: str) -> dict: :param pubkey: Public key of the member :return: """ - return await client.get(MODULE + "/hardship/%s" % pubkey, schema=HARDSHIP_SCHEMA) + return client.get(MODULE + "/hardship/%s" % pubkey, schema=HARDSHIP_SCHEMA) -async def difficulties(client: Client) -> dict: +def difficulties(client: Client) -> dict: """ GET difficulties levels for members into current window for writing next block :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/difficulties", schema=DIFFICULTIES_SCHEMA) + return client.get(MODULE + "/difficulties", schema=DIFFICULTIES_SCHEMA) -async def branches(client: Client) -> list: +def branches(client: Client) -> list: """ GET current branches of the node (top block of each branch) :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/branches", schema=BRANCHES_SCHEMA) + return client.get(MODULE + "/branches", schema=BRANCHES_SCHEMA) -async def newcomers(client: Client) -> dict: +def newcomers(client: Client) -> dict: """ GET the block numbers containing newcomers :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/with/newcomers", schema=BLOCK_NUMBERS_SCHEMA) + return client.get(MODULE + "/with/newcomers", schema=BLOCK_NUMBERS_SCHEMA) -async def certifications(client: Client) -> dict: +def certifications(client: Client) -> dict: """ GET the block numbers containing certifications :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/with/certs", schema=BLOCK_NUMBERS_SCHEMA) + return client.get(MODULE + "/with/certs", schema=BLOCK_NUMBERS_SCHEMA) -async def joiners(client: Client) -> dict: +def joiners(client: Client) -> dict: """ GET the block numbers containing joiners :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/with/joiners", schema=BLOCK_NUMBERS_SCHEMA) + return client.get(MODULE + "/with/joiners", schema=BLOCK_NUMBERS_SCHEMA) -async def actives(client: Client) -> dict: +def actives(client: Client) -> dict: """ GET the block numbers containing actives :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/with/actives", schema=BLOCK_NUMBERS_SCHEMA) + return client.get(MODULE + "/with/actives", schema=BLOCK_NUMBERS_SCHEMA) -async def leavers(client: Client) -> dict: +def leavers(client: Client) -> dict: """ GET the block numbers containing leavers :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/with/leavers", schema=BLOCK_NUMBERS_SCHEMA) + return client.get(MODULE + "/with/leavers", schema=BLOCK_NUMBERS_SCHEMA) -async def revoked(client: Client) -> dict: +def revoked(client: Client) -> dict: """ GET the block numbers containing revoked members. :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/with/revoked", schema=BLOCK_NUMBERS_SCHEMA) + return client.get(MODULE + "/with/revoked", schema=BLOCK_NUMBERS_SCHEMA) -async def excluded(client: Client) -> dict: +def excluded(client: Client) -> dict: """ GET the block numbers containing excluded :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/with/excluded", schema=BLOCK_NUMBERS_SCHEMA) + return client.get(MODULE + "/with/excluded", schema=BLOCK_NUMBERS_SCHEMA) -async def ud(client: Client) -> dict: +def ud(client: Client) -> dict: """ GET the block numbers containing universal dividend :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/with/ud", schema=BLOCK_NUMBERS_SCHEMA) + return client.get(MODULE + "/with/ud", schema=BLOCK_NUMBERS_SCHEMA) -async def tx(client: Client) -> dict: +def tx(client: Client) -> dict: """ GET the block numbers containing transactions :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/with/tx", schema=BLOCK_NUMBERS_SCHEMA) + return client.get(MODULE + "/with/tx", schema=BLOCK_NUMBERS_SCHEMA) diff --git a/duniterpy/api/bma/network.py b/duniterpy/api/bma/network.py index 1f6fdaf1a9e404ebc1bed9fd9f11dd59640df4ee..b29eb6e41a3fc5932b6cc8c48024311abd006c65 100644 --- a/duniterpy/api/bma/network.py +++ b/duniterpy/api/bma/network.py @@ -17,9 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. import logging -from aiohttp import ClientResponse +from http.client import HTTPResponse -from duniterpy.api.client import Client, RESPONSE_AIOHTTP +from duniterpy.api.client import Client, RESPONSE_HTTP logger = logging.getLogger("duniter/network") @@ -120,7 +120,7 @@ WS2P_HEADS_SCHEMA = { } -async def peers(client: Client) -> dict: +def peers(client: Client) -> dict: """ GET the exhaustive list of peers known by the node @@ -128,20 +128,20 @@ async def peers(client: Client) -> dict: :return: """ - return await client.get(MODULE + "/peers", schema=PEERS_SCHEMA) + return client.get(MODULE + "/peers", schema=PEERS_SCHEMA) -async def peering(client: Client) -> dict: +def peering(client: Client) -> dict: """ GET peering information about a peer :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/peering", schema=PEERING_SCHEMA) + return client.get(MODULE + "/peering", schema=PEERING_SCHEMA) -async def peering_peers(client: Client, leaves: bool = False, leaf: str = "") -> dict: +def peering_peers(client: Client, leaves: bool = False, leaf: str = "") -> dict: """ GET peering entries of every node inside the currency network @@ -151,17 +151,17 @@ async def peering_peers(client: Client, leaves: bool = False, leaf: str = "") -> :return: """ if leaves is True: - response = await client.get( + response = client.get( MODULE + "/peering/peers", {"leaves": "true"}, schema=PEERING_PEERS_SCHEMA ) else: - response = await client.get( + response = client.get( MODULE + "/peering/peers", {"leaf": leaf}, schema=PEERING_PEERS_SCHEMA ) return response -async def peer(client: Client, peer_signed_raw: str) -> ClientResponse: +def peer(client: Client, peer_signed_raw: str) -> HTTPResponse: """ POST a Peer signed raw document @@ -169,16 +169,16 @@ async def peer(client: Client, peer_signed_raw: str) -> ClientResponse: :param peer_signed_raw: Peer signed raw document :return: """ - return await client.post( - MODULE + "/peering/peers", {"peer": peer_signed_raw}, rtype=RESPONSE_AIOHTTP + return client.post( + MODULE + "/peering/peers", {"peer": peer_signed_raw}, rtype=RESPONSE_HTTP ) -async def ws2p_heads(client: Client) -> dict: +def ws2p_heads(client: Client) -> dict: """ GET ws2p heads known by the node :param client: Client to connect to the api :rtype: dict """ - return await client.get(MODULE + "/ws2p/heads", schema=WS2P_HEADS_SCHEMA) + return client.get(MODULE + "/ws2p/heads", schema=WS2P_HEADS_SCHEMA) diff --git a/duniterpy/api/bma/node.py b/duniterpy/api/bma/node.py index 5518134bf07c538a13f6c182c26592bae9edc850..92da3a35f4d670086cbf661e5a108aba3a5d6855 100644 --- a/duniterpy/api/bma/node.py +++ b/duniterpy/api/bma/node.py @@ -56,21 +56,21 @@ SANDBOXES_SCHEMA = { } -async def summary(client: Client) -> dict: +def summary(client: Client) -> dict: """ GET Duniter node version and infos :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/summary", schema=SUMMARY_SCHEMA) + return client.get(MODULE + "/summary", schema=SUMMARY_SCHEMA) -async def sandboxes(client: Client) -> dict: +def sandboxes(client: Client) -> dict: """ GET Duniter node version and infos :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/sandboxes", schema=SANDBOXES_SCHEMA) + return client.get(MODULE + "/sandboxes", schema=SANDBOXES_SCHEMA) diff --git a/duniterpy/api/bma/tx.py b/duniterpy/api/bma/tx.py index 980f52eb35abc595cf3aa4b00c50909175ceffc4..06c9876a015388775fd6629b9aafd9424de41942 100644 --- a/duniterpy/api/bma/tx.py +++ b/duniterpy/api/bma/tx.py @@ -17,9 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. import logging -from aiohttp import ClientResponse +from http.client import HTTPResponse -from duniterpy.api.client import Client, RESPONSE_AIOHTTP +from duniterpy.api.client import Client, RESPONSE_HTTP logger = logging.getLogger("duniter/tx") @@ -125,7 +125,7 @@ SOURCES_SCHEMA = { } -async def history(client: Client, pubkey: str) -> dict: +def history(client: Client, pubkey: str) -> dict: """ Get transactions history of public key @@ -133,10 +133,10 @@ async def history(client: Client, pubkey: str) -> dict: :param pubkey: Public key :return: """ - return await client.get(MODULE + "/history/%s" % pubkey, schema=HISTORY_SCHEMA) + return client.get(MODULE + "/history/%s" % pubkey, schema=HISTORY_SCHEMA) -async def process(client: Client, transaction_signed_raw: str) -> ClientResponse: +def process(client: Client, transaction_signed_raw: str) -> HTTPResponse: """ POST a transaction raw document @@ -144,14 +144,14 @@ async def process(client: Client, transaction_signed_raw: str) -> ClientResponse :param transaction_signed_raw: Transaction signed raw document :return: """ - return await client.post( + return client.post( MODULE + "/process", {"transaction": transaction_signed_raw}, - rtype=RESPONSE_AIOHTTP, + rtype=RESPONSE_HTTP, ) -async def sources(client: Client, pubkey: str) -> dict: +def sources(client: Client, pubkey: str) -> dict: """ GET transaction sources @@ -159,10 +159,10 @@ async def sources(client: Client, pubkey: str) -> dict: :param pubkey: Public key :return: """ - return await client.get(MODULE + "/sources/%s" % pubkey, schema=SOURCES_SCHEMA) + return client.get(MODULE + "/sources/%s" % pubkey, schema=SOURCES_SCHEMA) -async def pending(client: Client, pubkey: str) -> dict: +def pending(client: Client, pubkey: str) -> dict: """ GET pending transaction history for the given pubkey @@ -170,12 +170,10 @@ async def pending(client: Client, pubkey: str) -> dict: :param pubkey: Public key :return: """ - return await client.get( - MODULE + "/history/%s/pending" % pubkey, schema=HISTORY_SCHEMA - ) + return client.get(MODULE + "/history/%s/pending" % pubkey, schema=HISTORY_SCHEMA) -async def blocks(client: Client, pubkey: str, start: int, end: int) -> dict: +def blocks(client: Client, pubkey: str, start: int, end: int) -> dict: """ GET public key transactions history between start and end block number @@ -185,13 +183,13 @@ async def blocks(client: Client, pubkey: str, start: int, end: int) -> dict: :param end: End to block number :return: """ - return await client.get( + return client.get( MODULE + "/history/%s/blocks/%s/%s" % (pubkey, start, end), schema=HISTORY_SCHEMA, ) -async def times(client: Client, pubkey: str, start: int, end: int) -> dict: +def times(client: Client, pubkey: str, start: int, end: int) -> dict: """ GET public key transactions history between start and end timestamp @@ -201,6 +199,6 @@ async def times(client: Client, pubkey: str, start: int, end: int) -> dict: :param end: End to timestamp :return: """ - return await client.get( + return client.get( MODULE + "/history/%s/times/%s/%s" % (pubkey, start, end), schema=HISTORY_SCHEMA ) diff --git a/duniterpy/api/bma/ud.py b/duniterpy/api/bma/ud.py index a8c80dc16b32844cf42e73d348199f50f12259cf..7ace432a8130db864547a1307b0144e4481f5201 100644 --- a/duniterpy/api/bma/ud.py +++ b/duniterpy/api/bma/ud.py @@ -51,7 +51,7 @@ UD_SCHEMA = { } -async def history(client: Client, pubkey: str) -> dict: +def history(client: Client, pubkey: str) -> dict: """ Get UD history of a member account @@ -59,4 +59,4 @@ async def history(client: Client, pubkey: str) -> dict: :param pubkey: Public key of the member :return: """ - return await client.get(MODULE + "/history/%s" % pubkey, schema=UD_SCHEMA) + return client.get(MODULE + "/history/%s" % pubkey, schema=UD_SCHEMA) diff --git a/duniterpy/api/bma/wot.py b/duniterpy/api/bma/wot.py index 43bbe2b3652adca861021f79e4ba9569d4ea229a..4c01fa4a27a0043dd4745ab5b50de398cafb6889 100644 --- a/duniterpy/api/bma/wot.py +++ b/duniterpy/api/bma/wot.py @@ -17,9 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. import logging -from aiohttp import ClientResponse +from http.client import HTTPResponse -from duniterpy.api.client import Client, RESPONSE_AIOHTTP +from duniterpy.api.client import Client, RESPONSE_HTTP logger = logging.getLogger("duniter/wot") @@ -230,7 +230,7 @@ IDENTITY_OF_SCHEMA = { } -async def add(client: Client, identity_signed_raw: str) -> ClientResponse: +def add(client: Client, identity_signed_raw: str) -> HTTPResponse: """ POST identity raw document @@ -238,12 +238,12 @@ async def add(client: Client, identity_signed_raw: str) -> ClientResponse: :param identity_signed_raw: Identity raw document :return: """ - return await client.post( - MODULE + "/add", {"identity": identity_signed_raw}, rtype=RESPONSE_AIOHTTP + return client.post( + MODULE + "/add", {"identity": identity_signed_raw}, rtype=RESPONSE_HTTP ) -async def certify(client: Client, certification_signed_raw: str) -> ClientResponse: +def certify(client: Client, certification_signed_raw: str) -> HTTPResponse: """ POST certification raw document @@ -251,12 +251,12 @@ async def certify(client: Client, certification_signed_raw: str) -> ClientRespon :param certification_signed_raw: Certification raw document :return: """ - return await client.post( - MODULE + "/certify", {"cert": certification_signed_raw}, rtype=RESPONSE_AIOHTTP + return client.post( + MODULE + "/certify", {"cert": certification_signed_raw}, rtype=RESPONSE_HTTP ) -async def revoke(client: Client, revocation_signed_raw: str) -> ClientResponse: +def revoke(client: Client, revocation_signed_raw: str) -> HTTPResponse: """ POST revocation document @@ -264,14 +264,14 @@ async def revoke(client: Client, revocation_signed_raw: str) -> ClientResponse: :param revocation_signed_raw: Certification raw document :return: """ - return await client.post( + return client.post( MODULE + "/revoke", {"revocation": revocation_signed_raw}, - rtype=RESPONSE_AIOHTTP, + rtype=RESPONSE_HTTP, ) -async def lookup(client: Client, search: str) -> dict: +def lookup(client: Client, search: str) -> dict: """ GET UID/Public key data @@ -279,10 +279,10 @@ async def lookup(client: Client, search: str) -> dict: :param search: UID or public key :return: """ - return await client.get(MODULE + "/lookup/%s" % search, schema=LOOKUP_SCHEMA) + return client.get(MODULE + "/lookup/%s" % search, schema=LOOKUP_SCHEMA) -async def certifiers_of(client: Client, search: str) -> dict: +def certifiers_of(client: Client, search: str) -> dict: """ GET UID/Public key certifiers @@ -290,12 +290,12 @@ async def certifiers_of(client: Client, search: str) -> dict: :param search: UID or public key :return: """ - return await client.get( + return client.get( MODULE + "/certifiers-of/%s" % search, schema=CERTIFICATIONS_SCHEMA ) -async def certified_by(client: Client, search: str) -> dict: +def certified_by(client: Client, search: str) -> dict: """ GET identities certified by UID/Public key @@ -303,22 +303,22 @@ async def certified_by(client: Client, search: str) -> dict: :param search: UID or public key :return: """ - return await client.get( + return client.get( MODULE + "/certified-by/%s" % search, schema=CERTIFICATIONS_SCHEMA ) -async def members(client: Client) -> dict: +def members(client: Client) -> dict: """ GET list of all current members of the Web of Trust :param client: Client to connect to the api :return: """ - return await client.get(MODULE + "/members", schema=MEMBERS_SCHEMA) + return client.get(MODULE + "/members", schema=MEMBERS_SCHEMA) -async def requirements(client: Client, search: str) -> dict: +def requirements(client: Client, search: str) -> dict: """ GET list of requirements for a given UID/Public key @@ -326,12 +326,10 @@ async def requirements(client: Client, search: str) -> dict: :param search: UID or public key :return: """ - return await client.get( - MODULE + "/requirements/%s" % search, schema=REQUIREMENTS_SCHEMA - ) + return client.get(MODULE + "/requirements/%s" % search, schema=REQUIREMENTS_SCHEMA) -async def requirements_of_pending(client: Client, minsig: int) -> dict: +def requirements_of_pending(client: Client, minsig: int) -> dict: """ GET list of requirements of all pending identities with a minimum of minsig certifications @@ -339,12 +337,12 @@ async def requirements_of_pending(client: Client, minsig: int) -> dict: :param minsig: Minimum number of certifications :return: """ - return await client.get( + return client.get( MODULE + "/requirements-of-pending/%d" % minsig, schema=REQUIREMENTS_SCHEMA ) -async def identity_of(client: Client, search: str) -> dict: +def identity_of(client: Client, search: str) -> dict: """ GET Identity data written in the blockchain @@ -352,6 +350,4 @@ async def identity_of(client: Client, search: str) -> dict: :param search: UID or public key :return: """ - return await client.get( - MODULE + "/identity-of/%s" % search, schema=IDENTITY_OF_SCHEMA - ) + return client.get(MODULE + "/identity-of/%s" % search, schema=IDENTITY_OF_SCHEMA) diff --git a/duniterpy/api/bma/ws.py b/duniterpy/api/bma/ws.py index cd4b5687120a35f51a08c226b1711f8cbade25f9..624b8329ebc0de773963036298d514b744a530cf 100644 --- a/duniterpy/api/bma/ws.py +++ b/duniterpy/api/bma/ws.py @@ -29,21 +29,21 @@ WS_BLOCK_SCHEMA = BLOCK_SCHEMA WS_PEER_SCHEMA = PEERING_SCHEMA -async def block(client: Client) -> WSConnection: +def block(client: Client) -> WSConnection: """ Connect to block websocket :param client: Client to connect to the api :return: """ - return await client.connect_ws(MODULE + "/block") + return client.connect_ws(MODULE + "/block") -async def peer(client: Client) -> WSConnection: +def peer(client: Client) -> WSConnection: """ Connect to peer websocket :param client: Client to connect to the api :return: """ - return await client.connect_ws(MODULE + "/peer") + return client.connect_ws(MODULE + "/peer") diff --git a/duniterpy/api/client.py b/duniterpy/api/client.py index e2922b6a0650a9e81e13a669c52fa3d3d7e62522..5216596ee8507a963b562cca49a8caa491bde478 100644 --- a/duniterpy/api/client.py +++ b/duniterpy/api/client.py @@ -14,6 +14,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. """ +import copy import json import logging from typing import Callable, Union, Any, Optional, Dict @@ -21,7 +22,6 @@ from urllib import request, parse import jsonschema from websocket import WebSocket -from aiohttp import ClientSession from http.client import HTTPResponse import duniterpy.api.endpoint as endpoint @@ -32,12 +32,8 @@ logger = logging.getLogger("duniter") # Response type constants RESPONSE_JSON = "json" RESPONSE_TEXT = "text" -RESPONSE_AIOHTTP = "aiohttp" RESPONSE_HTTP = "http" -# Connection type constants -CONNECTION_TYPE_AIOHTTP = 1 - # jsonschema validator ERROR_SCHEMA = { "type": "object", @@ -81,11 +77,11 @@ def parse_error(text: str) -> dict: return data -async def parse_response(response: str, schema: dict) -> Any: +def parse_response(response: str, schema: dict) -> Any: """ Validate and parse the BMA answer - :param response: Response of aiohttp request + :param response: Response content :param schema: The expected response structure :return: the json data """ @@ -113,7 +109,7 @@ class WSConnection: """ self.connection = connection - async def send_str(self, data: str) -> None: + def send_str(self, data: str): """ Send a data string to the web socket connection @@ -124,9 +120,8 @@ class WSConnection: raise Exception("Connection property is empty") self.connection.send(data) - return None - async def receive_str(self, timeout: Optional[float] = None) -> str: + def receive_str(self, timeout: Optional[float] = None) -> str: """ Wait for a data string from the web socket connection @@ -139,7 +134,7 @@ class WSConnection: self.connection.settimeout(timeout) return self.connection.recv() - async def receive_json(self, timeout: Optional[float] = None) -> Any: + def receive_json(self, timeout: Optional[float] = None) -> Any: """ Wait for json data from the web socket connection @@ -152,7 +147,7 @@ class WSConnection: self.connection.settimeout(timeout) return json.loads(self.connection.recv()) - async def close(self) -> None: + def close(self) -> None: """ Close the web socket connection @@ -161,12 +156,12 @@ class WSConnection: if self.connection is None: raise Exception("Connection property is empty") - await self.connection.close() + self.connection.close() class API: """ - API is a class used as an abstraction layer over the request library (AIOHTTP). + API is a class used as an abstraction layer over the http/websocket libraries. """ def __init__( @@ -212,7 +207,7 @@ class API: return url - async def request_url( + def request_url( self, path: str, method: str = "GET", @@ -265,7 +260,7 @@ class API: response = request.urlopen(duniter_request, timeout=15) # type: HTTPResponse if response.status != 200: - content = response.read() + content = response.read().decode("utf-8") if bma_errors: try: error_data = parse_error(content) @@ -280,16 +275,17 @@ class API: ) # get response content - content = response.read() + return_response = copy.copy(response) + content = response.read().decode("utf-8") response.close() # if schema supplied... if schema is not None: # validate response - await parse_response(content, schema) + parse_response(content, schema) # return the chosen type - result = response # type: Any + result = return_response # type: Any if rtype == RESPONSE_TEXT: result = content elif rtype == RESPONSE_JSON: @@ -297,14 +293,9 @@ class API: return result - async def connect_ws(self, path: str) -> WSConnection: + def connect_ws(self, path: str) -> WSConnection: """ - Connect to a websocket in order to use API parameters - - In reality, aiohttp.session.ws_connect returns a aiohttp.client._WSRequestContextManager instance. - It must be used in a with statement to get the ClientWebSocketResponse instance from it (__aenter__). - At the end of the with statement, aiohttp.client._WSRequestContextManager.__aexit__ is called - and close the ClientWebSocketResponse in it. + Connect to a websocket :param path: the url path :return: @@ -316,7 +307,7 @@ class API: proxy_split = ":".split(self.connection_handler.proxy) if len(proxy_split) == 2: host = proxy_split[0] - port = proxy_split[1] + port = int(proxy_split[1]) else: host = self.connection_handler.proxy port = 80 @@ -335,14 +326,12 @@ class Client: def __init__( self, _endpoint: Union[str, endpoint.Endpoint], - session: Optional[ClientSession] = None, proxy: Optional[str] = None, ) -> None: """ Init Client instance :param _endpoint: Endpoint string in duniter format - :param session: Aiohttp client session (optional, default None) :param proxy: Proxy server as hostname:port (optional, default None) """ if isinstance(_endpoint, str): @@ -356,15 +345,9 @@ class Client: "{0} endpoint in not supported".format(self.endpoint.api) ) - # if no user session... - if session is None: - # open a session - self.session = ClientSession() - else: - self.session = session self.proxy = proxy - async def get( + def get( self, url_path: str, params: Optional[dict] = None, @@ -383,14 +366,14 @@ class Client: if params is None: params = dict() - client = API(self.endpoint.conn_handler(self.session, self.proxy)) + client = API(self.endpoint.conn_handler(self.proxy)) # get response - return await client.request_url( + return client.request_url( url_path, "GET", rtype, schema, bma_errors=True, **params ) - async def post( + def post( self, url_path: str, params: Optional[dict] = None, @@ -409,14 +392,14 @@ class Client: if params is None: params = dict() - client = API(self.endpoint.conn_handler(self.session, self.proxy)) + client = API(self.endpoint.conn_handler(self.proxy)) # get response - return await client.request_url( + return client.request_url( url_path, "POST", rtype, schema, bma_errors=True, **params ) - async def query( + def query( self, query: str, variables: Optional[dict] = None, @@ -427,7 +410,6 @@ class Client: :param query: GraphQL query string :param variables: Variables for the query (optional, default None) - :param rtype: Response type (optional, default RESPONSE_JSON) :param schema: Json Schema to validate response (optional, default None) :return: """ @@ -436,37 +418,29 @@ class Client: if variables is not None: payload["variables"] = variables - client = API(self.endpoint.conn_handler(self.session, self.proxy)) + client = API(self.endpoint.conn_handler(self.proxy)) - # get aiohttp response - response = await client.request_url( + # get json response + response = client.request_url( "", "POST", rtype=RESPONSE_JSON, schema=schema, json_data=payload ) # if schema supplied... if schema is not None: # validate response - await parse_response(response, schema) + parse_response(response, schema) return response - async def connect_ws(self, path: str = "") -> WSConnection: + def connect_ws(self, path: str = "") -> WSConnection: """ Connect to a websocket in order to use API parameters :param path: the url path :return: """ - client = API(self.endpoint.conn_handler(self.session, self.proxy)) - return await client.connect_ws(path) - - async def close(self): - """ - Close aiohttp session - - :return: - """ - await self.session.close() + client = API(self.endpoint.conn_handler(self.proxy)) + return client.connect_ws(path) def __call__(self, _function: Callable, *args: Any, **kwargs: Any) -> Any: """ diff --git a/duniterpy/api/endpoint.py b/duniterpy/api/endpoint.py index 75e3c9b716188efb6f510e53683b8a0f7a1957b8..44ee2c698cdd9ec786441654e3ddf19e15594eba 100644 --- a/duniterpy/api/endpoint.py +++ b/duniterpy/api/endpoint.py @@ -18,8 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. import re from typing import Any, Optional, TypeVar, Type, Dict -from aiohttp import ClientSession - import duniterpy.constants as constants from ..documents import MalformedDocumentError @@ -34,7 +32,6 @@ class ConnectionHandler: server: str, port: int, path: str, - session: ClientSession, proxy: Optional[str] = None, ) -> None: """ @@ -45,7 +42,6 @@ class ConnectionHandler: :param server: Server IP or domain name :param port: Port number :param port: Url path - :param session: Session AIOHTTP :param proxy: Proxy (optional, default=None) """ self.http_scheme = http_scheme @@ -54,7 +50,6 @@ class ConnectionHandler: self.port = port self.path = path self.proxy = proxy - self.session = session def __str__(self) -> str: return "connection info: %s:%d" % (self.server, self.port) @@ -72,9 +67,7 @@ class Endpoint: def inline(self) -> str: raise NotImplementedError("inline() is not implemented") - def conn_handler( - self, session: ClientSession, proxy: str = None - ) -> ConnectionHandler: + def conn_handler(self, proxy: str = None) -> ConnectionHandler: raise NotImplementedError("conn_handler is not implemented") def __str__(self) -> str: @@ -121,17 +114,14 @@ class UnknownEndpoint(Endpoint): doc += " {0}".format(p) return doc - def conn_handler( - self, session: ClientSession, proxy: str = None - ) -> ConnectionHandler: + def conn_handler(self, proxy: str = None) -> ConnectionHandler: """ - Return connection handler from session + Return connection handler - :param session: AIOHTTP Session :param proxy: Proxy server :return: """ - return ConnectionHandler("", "", "", 0, "", ClientSession()) + return ConnectionHandler("", "", "", 0, "") def __str__(self) -> str: return "{0} {1}".format( @@ -205,27 +195,24 @@ class BMAEndpoint(Endpoint): PORT=(" {0}".format(self.port) if self.port else ""), ) - def conn_handler( - self, session: ClientSession, proxy: str = None - ) -> ConnectionHandler: + def conn_handler(self, proxy: str = None) -> ConnectionHandler: """ Return connection handler instance for the endpoint - :param session: AIOHTTP client session instance :param proxy: Proxy url :return: """ if self.server: conn_handler = ConnectionHandler( - "http", "ws", self.server, self.port, "", session, proxy + "http", "ws", self.server, self.port, "", proxy ) elif self.ipv6: conn_handler = ConnectionHandler( - "http", "ws", "[{0}]".format(self.ipv6), self.port, "", session, proxy + "http", "ws", "[{0}]".format(self.ipv6), self.port, "", proxy ) else: conn_handler = ConnectionHandler( - "http", "ws", self.ipv4, self.port, "", session, proxy + "http", "ws", self.ipv4, self.port, "", proxy ) return conn_handler @@ -310,33 +297,24 @@ class SecuredBMAEndpoint(BMAEndpoint): ] return SecuredBMAEndpoint.API + " " + " ".join(inlined) - def conn_handler( - self, session: ClientSession, proxy: str = None - ) -> ConnectionHandler: + def conn_handler(self, proxy: str = None) -> ConnectionHandler: """ Return connection handler instance for the endpoint - :param session: AIOHTTP client session instance :param proxy: Proxy url :return: """ if self.server: conn_handler = ConnectionHandler( - "https", "wss", self.server, self.port, self.path, session, proxy + "https", "wss", self.server, self.port, self.path, proxy ) elif self.ipv6: conn_handler = ConnectionHandler( - "https", - "wss", - "[{0}]".format(self.ipv6), - self.port, - self.path, - session, - proxy, + "https", "wss", "[{0}]".format(self.ipv6), self.port, self.path, proxy ) else: conn_handler = ConnectionHandler( - "https", "wss", self.ipv4, self.port, self.path, session, proxy + "https", "wss", self.ipv4, self.port, self.path, proxy ) return conn_handler @@ -396,13 +374,10 @@ class WS2PEndpoint(Endpoint): ] return WS2PEndpoint.API + " " + " ".join(inlined) - def conn_handler( - self, session: ClientSession, proxy: str = None - ) -> ConnectionHandler: + def conn_handler(self, proxy: str = None) -> ConnectionHandler: """ Return connection handler instance for the endpoint - :param session: AIOHTTP client session instance :param proxy: Proxy url :return: """ @@ -412,13 +387,7 @@ class WS2PEndpoint(Endpoint): http_scheme += "s" websocket_scheme += "s" return ConnectionHandler( - http_scheme, - websocket_scheme, - self.server, - self.port, - self.path, - session, - proxy, + http_scheme, websocket_scheme, self.server, self.port, self.path, proxy ) def __str__(self) -> str: @@ -478,19 +447,14 @@ class ESCoreEndpoint(Endpoint): inlined = [str(info) for info in (self.server, self.port) if info] return ESCoreEndpoint.API + " " + " ".join(inlined) - def conn_handler( - self, session: ClientSession, proxy: str = None - ) -> ConnectionHandler: + def conn_handler(self, proxy: str = None) -> ConnectionHandler: """ Return connection handler instance for the endpoint - :param session: AIOHTTP client session instance :param proxy: Proxy url :return: """ - return ConnectionHandler( - "https", "wss", self.server, self.port, "", session, proxy - ) + return ConnectionHandler("https", "wss", self.server, self.port, "", proxy) def __str__(self) -> str: return self.inline() @@ -544,19 +508,14 @@ class ESUserEndpoint(Endpoint): inlined = [str(info) for info in (self.server, self.port) if info] return ESUserEndpoint.API + " " + " ".join(inlined) - def conn_handler( - self, session: ClientSession, proxy: str = None - ) -> ConnectionHandler: + def conn_handler(self, proxy: str = None) -> ConnectionHandler: """ Return connection handler instance for the endpoint - :param session: AIOHTTP client session instance :param proxy: Proxy url :return: """ - return ConnectionHandler( - "https", "wss", self.server, self.port, "", session, proxy - ) + return ConnectionHandler("https", "wss", self.server, self.port, "", proxy) def __str__(self) -> str: return self.inline() @@ -614,19 +573,14 @@ class ESSubscribtionEndpoint(Endpoint): inlined = [str(info) for info in (self.server, self.port) if info] return ESSubscribtionEndpoint.API + " " + " ".join(inlined) - def conn_handler( - self, session: ClientSession, proxy: str = None - ) -> ConnectionHandler: + def conn_handler(self, proxy: str = None) -> ConnectionHandler: """ Return connection handler instance for the endpoint - :param session: AIOHTTP client session instance :param proxy: Proxy url :return: """ - return ConnectionHandler( - "https", "wss", self.server, self.port, "", session, proxy - ) + return ConnectionHandler("https", "wss", self.server, self.port, "", proxy) def __str__(self) -> str: return self.inline() @@ -718,13 +672,10 @@ class GVAEndpoint(Endpoint): ] return self.API + " " + " ".join(inlined) - def conn_handler( - self, session: ClientSession, proxy: str = None - ) -> ConnectionHandler: + def conn_handler(self, proxy: str = None) -> ConnectionHandler: """ Return connection handler instance for the endpoint - :param session: AIOHTTP client session instance :param proxy: Proxy url :return: """ @@ -733,13 +684,7 @@ class GVAEndpoint(Endpoint): if self.server: conn_handler = ConnectionHandler( - scheme_http, - scheme_ws, - self.server, - self.port, - self.path, - session, - proxy, + scheme_http, scheme_ws, self.server, self.port, self.path, proxy ) elif self.ipv6: conn_handler = ConnectionHandler( @@ -748,12 +693,11 @@ class GVAEndpoint(Endpoint): "[{0}]".format(self.ipv6), self.port, self.path, - session, proxy, ) else: conn_handler = ConnectionHandler( - scheme_http, scheme_ws, self.ipv4, self.port, self.path, session, proxy + scheme_http, scheme_ws, self.ipv4, self.port, self.path, proxy ) return conn_handler diff --git a/duniterpy/helpers/network.py b/duniterpy/helpers/network.py index 70da09b1d1276d9e91c79d48c4cd6f192d9f5230..af15122335c4378d126f127fc17a8fa4676a4e93 100644 --- a/duniterpy/helpers/network.py +++ b/duniterpy/helpers/network.py @@ -26,7 +26,7 @@ from itertools import groupby from duniterpy.key import VerifyingKey -async def get_available_nodes(client: Client) -> List[List[Dict[str, Any]]]: +def get_available_nodes(client: Client) -> List[List[Dict[str, Any]]]: """ Get available nodes grouped and sorted by descending blockstamp @@ -52,8 +52,8 @@ async def get_available_nodes(client: Client) -> List[List[Dict[str, Any]]]: :return: """ # capture heads and peers - heads_response = await client(bma.network.ws2p_heads) - peers_response = await client(bma.network.peers) + heads_response = client(bma.network.ws2p_heads) + peers_response = client(bma.network.peers) # get heads instances from WS2P messages heads = [] diff --git a/duniterpy/helpers/ws2p.py b/duniterpy/helpers/ws2p.py index e79119e9ae02e3c459421fca9477dfdaa80a0a44..80e671f0607321024d6de6f674d724bea93f6575 100644 --- a/duniterpy/helpers/ws2p.py +++ b/duniterpy/helpers/ws2p.py @@ -25,7 +25,7 @@ from duniterpy.key import SigningKey import logging -async def handshake(ws: WSConnection, signing_key: SigningKey, currency: str): +def handshake(ws: WSConnection, signing_key: SigningKey, currency: str): """ Perform ws2p handshake on the web socket connection using the signing_key instance @@ -41,14 +41,14 @@ async def handshake(ws: WSConnection, signing_key: SigningKey, currency: str): connect_message = connect_document.get_signed_json(signing_key) logging.debug("Send CONNECT message") - await ws.send_str(connect_message) + ws.send_str(connect_message) loop = True remote_connect_document = None # Iterate on each message received... while loop: - data = await ws.receive_json() + data = ws.receive_json() if "auth" in data and data["auth"] == "CONNECT": jsonschema.validate(data, ws2p.network.WS2P_CONNECT_MESSAGE_SCHEMA) @@ -67,7 +67,7 @@ async def handshake(ws: WSConnection, signing_key: SigningKey, currency: str): # Send ACK message logging.debug("Send ACK message...") - await ws.send_str(ack_message) + ws.send_str(ack_message) if "auth" in data and data["auth"] == "ACK": jsonschema.validate(data, ws2p.network.WS2P_ACK_MESSAGE_SCHEMA) @@ -86,7 +86,7 @@ async def handshake(ws: WSConnection, signing_key: SigningKey, currency: str): # Send OK message logging.debug("Send OK message...") - await ws.send_str(ok_message) + ws.send_str(ok_message) if ( remote_connect_document is not None @@ -113,7 +113,7 @@ async def handshake(ws: WSConnection, signing_key: SigningKey, currency: str): break -async def generate_ws2p_endpoint( +def generate_ws2p_endpoint( bma_endpoint: Union[str, BMAEndpoint, SecuredBMAEndpoint] ) -> WS2PEndpoint: """ @@ -121,8 +121,7 @@ async def generate_ws2p_endpoint( Take the first one found """ bma_client = Client(bma_endpoint) - peering = await bma_client(bma.network.peering) - await bma_client.close() + peering = bma_client(bma.network.peering) for endpoint in peering["endpoints"]: if endpoint.startswith("WS2P"):