From 9a46039f6c7fd59beab553f32d6827e35ced56e6 Mon Sep 17 00:00:00 2001 From: Vincent Texier <vit@free.fr> Date: Thu, 19 Jul 2018 19:25:38 +0200 Subject: [PATCH] issue #52 use mypy to check static typing Update README with make check command --- .gitignore | 2 +- Makefile | 5 ++++- README.rst | 14 +++++++++---- duniterpy/api/client.py | 18 ++++++++--------- duniterpy/api/endpoint.py | 41 ++++++++++++++++++++------------------- requirements_dev.txt | 2 +- 6 files changed, 46 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index 07e928e3..22e92cd8 100644 --- a/.gitignore +++ b/.gitignore @@ -38,4 +38,4 @@ nosetests.xml .python-version docs/_build docs/duniterpy.* - +.mypy_cache diff --git a/Makefile b/Makefile index e14bc3e2..d615fe9c 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: docs tests +.PHONY: docs tests check # generate documentation docs: @@ -8,3 +8,6 @@ docs: tests: python -m unittest +# check static typing +check: + mypy duniterpy --ignore-missing-imports diff --git a/README.rst b/README.rst index 44bf9cb0..72eaf65c 100644 --- a/README.rst +++ b/README.rst @@ -44,15 +44,21 @@ Development pip install -r requirements.txt * Add PYTHONPATH env var to your shell containing the path to this repository -* Run unit tests with:: - - make tests - * Take a look at examples folder * Run examples from parent folder:: python examples/request_data.py +* Before submit a merge requests, please check the static typing and tests. + +* Check static typing with `mypy <http://mypy-lang.org/>`_:: + + make check + +* Run unit tests with:: + + make tests + Documentation ------------- diff --git a/duniterpy/api/client.py b/duniterpy/api/client.py index f1b53e85..ff796ab2 100644 --- a/duniterpy/api/client.py +++ b/duniterpy/api/client.py @@ -4,7 +4,7 @@ # vit import json import logging -from typing import Callable, Union +from typing import Callable, Union, Any import aiohttp import jsonschema @@ -34,7 +34,7 @@ ERROR_SCHEMA = { } -def parse_text(text: str, schema: dict) -> any: +def parse_text(text: str, schema: dict) -> Any: """ Validate and parse the BMA answer from websocket @@ -51,7 +51,7 @@ def parse_text(text: str, schema: dict) -> any: return data -def parse_error(text: str) -> any: +def parse_error(text: str) -> Any: """ Validate and parse the BMA answer from websocket @@ -67,7 +67,7 @@ def parse_error(text: str) -> any: return data -async def parse_response(response: aiohttp.ClientResponse, schema: dict) -> any: +async def parse_response(response: aiohttp.ClientResponse, schema: dict) -> Any: """ Validate and parse the BMA answer @@ -91,7 +91,7 @@ class API(object): """ schema = {} - def __init__(self, connection_handler: endpoint.ConnectionHandler, module: str): + def __init__(self, connection_handler: endpoint.ConnectionHandler, module: str) -> None: """ Asks a module in order to create the url used then by derivated classes. @@ -189,7 +189,7 @@ class Client: """ def __init__(self, _endpoint: Union[str, endpoint.Endpoint], session: aiohttp.ClientSession = None, - proxy: str = None): + proxy: str = None) -> None: """ Init Client instance @@ -214,7 +214,7 @@ class Client: self.session = session self.proxy = proxy - async def get(self, url_path: str, params: dict = None, rtype: str = RESPONSE_JSON, schema: dict = None) -> any: + async def get(self, url_path: str, params: dict = None, rtype: str = RESPONSE_JSON, schema: dict = None) -> Any: """ GET request on self.endpoint + url_path @@ -245,7 +245,7 @@ class Client: elif rtype == RESPONSE_JSON: return await response.json() - async def post(self, url_path: str, params: dict = None, rtype: str = RESPONSE_JSON, schema: dict = None) -> any: + async def post(self, url_path: str, params: dict = None, rtype: str = RESPONSE_JSON, schema: dict = None) -> Any: """ POST request on self.endpoint + url_path @@ -294,7 +294,7 @@ class Client: """ await self.session.close() - def __call__(self, _function: Callable, *args: any, **kwargs: any) -> any: + def __call__(self, _function: Callable, *args: Any, **kwargs: Any) -> Any: """ Call the _function given with the args given So we can call many packages wrapping the REST API diff --git a/duniterpy/api/endpoint.py b/duniterpy/api/endpoint.py index 0d1acd8b..42e96f5d 100644 --- a/duniterpy/api/endpoint.py +++ b/duniterpy/api/endpoint.py @@ -1,4 +1,5 @@ import re +from typing import Any, Optional import aiohttp @@ -9,8 +10,8 @@ from ..documents import MalformedDocumentError class ConnectionHandler: """Helper class used by other API classes to ease passing server connection information.""" - def __init__(self, http_scheme: str, ws_scheme: str, server: str, port: int, path: str = "", proxy: str = None, - session: aiohttp.ClientSession = None): + def __init__(self, http_scheme: str, ws_scheme: str, server: str, port: int, path: str, + session: aiohttp.ClientSession, proxy: Optional[str] = None) -> None: """ Init instance of connection handler @@ -18,9 +19,9 @@ class ConnectionHandler: :param ws_scheme: Web socket scheme :param server: Server IP or domain name :param port: Port number - :param port: Url path (optional, default="") + :param port: Url path + :param session: Session AIOHTTP :param proxy: Proxy (optional, default=None) - :param session: Session AIOHTTP (optional, default=None) """ self.http_scheme = http_scheme self.ws_scheme = ws_scheme @@ -48,14 +49,14 @@ class Endpoint: def __str__(self) -> str: raise NotImplementedError("__str__ is not implemented") - def __eq__(self, other: any) -> bool: + def __eq__(self, other: Any) -> bool: raise NotImplementedError("__eq__ is not implemented") class UnknownEndpoint(Endpoint): API = None - def __init__(self, api: str, properties: list): + def __init__(self, api: str, properties: list) -> None: self.api = api self.properties = properties @@ -86,12 +87,12 @@ class UnknownEndpoint(Endpoint): return doc def conn_handler(self, session: aiohttp.ClientSession, proxy: str = None) -> ConnectionHandler: - return ConnectionHandler("", "", "", 0, "") + return ConnectionHandler("", "", "", 0, "", aiohttp.ClientSession()) def __str__(self) -> str: return "{0} {1}".format(self.api, ' '.join(["{0}".format(p) for p in self.properties])) - def __eq__(self, other: any) -> bool: + def __eq__(self, other: Any) -> bool: if isinstance(other, UnknownEndpoint): return self.api == other.api and self.properties == other.properties else: @@ -123,7 +124,7 @@ class BMAEndpoint(Endpoint): ipv4_regex=IPV4_REGEX, ipv6_regex=IPV6_REGEX)) - def __init__(self, server: str, ipv4: str, ipv6: str, port: int): + def __init__(self, server: str, ipv4: str, ipv6: str, port: int) -> None: """ Init BMAEndpoint instance @@ -175,11 +176,11 @@ class BMAEndpoint(Endpoint): :return: """ if self.server: - return ConnectionHandler("http", "ws", self.server, self.port, "", proxy, session) + return ConnectionHandler("http", "ws", self.server, self.port, "", session, proxy) elif self.ipv6: - return ConnectionHandler("http", "ws", "[{0}]".format(self.ipv6), self.port, "", proxy, session) + return ConnectionHandler("http", "ws", "[{0}]".format(self.ipv6), self.port, "", session, proxy) - return ConnectionHandler("http", "ws", self.ipv4, self.port, "", proxy, session) + return ConnectionHandler("http", "ws", self.ipv4, self.port, "", session, proxy) def __str__(self): return self.inline() @@ -204,7 +205,7 @@ class SecuredBMAEndpoint(BMAEndpoint): ipv6_regex=IPV6_REGEX, path_regex=PATH_REGEX)) - def __init__(self, server: str, ipv4: str, ipv6: str, port: int, path: str): + def __init__(self, server: str, ipv4: str, ipv6: str, port: int, path: str) -> None: """ Init SecuredBMAEndpoint instance @@ -255,11 +256,11 @@ class SecuredBMAEndpoint(BMAEndpoint): :return: """ if self.server: - return ConnectionHandler("https", "wss", self.server, self.port, self.path, proxy, session) + return ConnectionHandler("https", "wss", self.server, self.port, self.path, session, proxy) elif self.ipv6: - return ConnectionHandler("https", "wss", "[{0}]".format(self.ipv6), self.port, self.path, proxy, session) + return ConnectionHandler("https", "wss", "[{0}]".format(self.ipv6), self.port, self.path, session, proxy) - return ConnectionHandler("https", "wss", self.ipv4, self.port, self.path, proxy, session) + return ConnectionHandler("https", "wss", self.ipv4, self.port, self.path, session, proxy) class WS2PEndpoint(Endpoint): @@ -303,7 +304,7 @@ class WS2PEndpoint(Endpoint): :param str proxy: Proxy url :rtype: ConnectionHandler """ - return ConnectionHandler("https", "wss", self.server, self.port, self.path, proxy, session) + return ConnectionHandler("https", "wss", self.server, self.port, self.path, session, proxy) def __str__(self): return self.inline() @@ -350,7 +351,7 @@ class ESCoreEndpoint(Endpoint): :param str proxy: Proxy url :rtype: ConnectionHandler """ - return ConnectionHandler("https", "wss", self.server, self.port, "", proxy, session) + return ConnectionHandler("https", "wss", self.server, self.port, "", session, proxy) def __str__(self): return self.inline() @@ -396,7 +397,7 @@ class ESUserEndpoint(Endpoint): :param str proxy: Proxy url :rtype: ConnectionHandler """ - return ConnectionHandler("https", "wss", self.server, self.port, "", proxy, session) + return ConnectionHandler("https", "wss", self.server, self.port, "", session, proxy) def __str__(self): return self.inline() @@ -442,7 +443,7 @@ class ESSubscribtionEndpoint(Endpoint): :param str proxy: Proxy url :rtype: ConnectionHandler """ - return ConnectionHandler("https", "wss", self.server, self.port, "", proxy, session) + return ConnectionHandler("https", "wss", self.server, self.port, "", session, proxy) def __str__(self): return self.inline() diff --git a/requirements_dev.txt b/requirements_dev.txt index fe4bbdea..ff19235a 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,2 +1,2 @@ sphinx - +mypy -- GitLab