Skip to content

Commit

Permalink
Add type hints (#23)
Browse files Browse the repository at this point in the history
* Add type hints for ansq.tcp.connection module

* Add type hints for ansq.tcp.protocol module

* Add type hints for ansq.tcp.types.response_schemas module

* Add type hints for ansq.tcp.types.connection module

* Add type hints for ansq.tcp.types.message module

* Add type hints for ansq.http.base module

* Add type hints for ansq.http.lookupd module

* Add type hints for ansq.http.writer module

* Add type hints for ansq.utils module

* Add type hints for the rest modules

* Gather common typedefs

* Upgrade mypy

* Make ansq PEP 561 compatible
  • Loading branch information
atugushev committed Sep 8, 2020
1 parent c5c1dcd commit fd54721
Show file tree
Hide file tree
Showing 17 changed files with 253 additions and 169 deletions.
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ repos:
rev: 3.8.3
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.782
hooks:
- id: mypy
exclude: >
(?x)^(
tests/ |
examples/
)
- repo: https://github.com/asottile/pyupgrade
rev: v2.7.2
hooks:
Expand Down
22 changes: 16 additions & 6 deletions ansq/http/base.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
import json
from typing import TYPE_CHECKING, Any

import aiohttp

from ansq.typedefs import HTTPResponse

from ..utils import convert_to_str
from .http_exceptions import HTTP_EXCEPTIONS, NSQHTTPException

if TYPE_CHECKING:
from asyncio.events import AbstractEventLoop


class NSQHTTPConnection:
"""XXX"""

def __init__(self, host="127.0.0.1", port=4151, *, loop):
def __init__(
self, host: str = "127.0.0.1", port: int = 4151, *, loop: "AbstractEventLoop",
) -> None:
self._loop = loop
self._endpoint = (host, port)
self._base_url = "http://{}:{}/".format(*self._endpoint)

self._session = aiohttp.ClientSession()

@property
def endpoint(self):
def endpoint(self) -> str:
return "http://{}:{}".format(*self._endpoint)

async def close(self):
return await self._session.close()
async def close(self) -> None:
await self._session.close()

async def perform_request(self, method, url, params, body):
async def perform_request(
self, method: str, url: str, params: Any, body: Any
) -> HTTPResponse:
_body = convert_to_str(body) if body else body
url = self._base_url + url
resp = await self._session.request(method, url, params=params, data=_body)
Expand All @@ -43,6 +53,6 @@ async def perform_request(self, method, url, params, body):
raise exc_class(resp.status, resp_body, extra)
return response

def __repr__(self):
def __repr__(self) -> str:
cls_name = self.__class__.__name__
return f"<{cls_name}: {self._endpoint}>"
13 changes: 8 additions & 5 deletions ansq/http/http_exceptions.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from typing import Dict


class NSQHTTPException(Exception):
"""XXX"""

Expand All @@ -6,28 +9,28 @@ class TransportError(NSQHTTPException):
"""XXX"""

@property
def status_code(self):
def status_code(self) -> int:
"""XXX"""
return self.args[0]

@property
def error(self):
def error(self) -> str:
"""A string error message."""
return self.args[1]

@property
def info(self):
def info(self) -> Dict:
"""Dict of returned error info from ES, where available."""
return self.args[2]

def __str__(self):
def __str__(self) -> str:
return f"TransportError({self.status_code}, {self.error!r})"


class HTTPConnectionError(TransportError):
"""XXX"""

def __str__(self):
def __str__(self) -> str:
return "HttpConnectionError({}) caused by: {}({})".format(
self.error, self.info.__class__.__name__, self.info,
)
Expand Down
26 changes: 14 additions & 12 deletions ansq/http/lookupd.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from ansq.typedefs import HTTPResponse

from .base import NSQHTTPConnection


Expand All @@ -6,18 +8,18 @@ class NsqLookupd(NSQHTTPConnection):
:see: http://nsq.io/components/nsqlookupd.html
"""

async def ping(self):
async def ping(self) -> HTTPResponse:
"""Monitoring endpoint.
:returns: should return `"OK"`, otherwise raises an exception.
"""
return self.perform_request("GET", "ping", None, None)
return await self.perform_request("GET", "ping", None, None)

async def info(self):
async def info(self) -> HTTPResponse:
"""Returns version information."""
response = await self.perform_request("GET", "info", None, None)
return response

async def lookup(self, topic):
async def lookup(self, topic: str) -> HTTPResponse:
"""XXX
:param topic:
Expand All @@ -26,15 +28,15 @@ async def lookup(self, topic):
response = await self.perform_request("GET", "lookup", {"topic": topic}, None)
return response

async def topics(self):
async def topics(self) -> HTTPResponse:
"""XXX
:return:
"""
resp = await self.perform_request("GET", "topics", None, None)
return resp

async def channels(self, topic):
async def channels(self, topic: str) -> HTTPResponse:
"""XXX
:param topic:
Expand All @@ -43,15 +45,15 @@ async def channels(self, topic):
resp = await self.perform_request("GET", "channels", {"topic": topic}, None)
return resp

async def nodes(self):
async def nodes(self) -> HTTPResponse:
"""XXX
:return:
"""
resp = await self.perform_request("GET", "nodes", None, None)
return resp

async def create_topic(self, topic):
async def create_topic(self, topic: str) -> HTTPResponse:
"""XXX
:param topic:
Expand All @@ -62,7 +64,7 @@ async def create_topic(self, topic):
)
return resp

async def delete_topic(self, topic):
async def delete_topic(self, topic: str) -> HTTPResponse:
"""XXX
:param topic:
Expand All @@ -73,7 +75,7 @@ async def delete_topic(self, topic):
)
return resp

async def create_channel(self, topic, channel):
async def create_channel(self, topic: str, channel: str) -> HTTPResponse:
"""XXX
:param topic:
Expand All @@ -85,7 +87,7 @@ async def create_channel(self, topic, channel):
)
return resp

async def delete_channel(self, topic, channel):
async def delete_channel(self, topic: str, channel: str) -> HTTPResponse:
"""XXX
:param topic:
Expand All @@ -97,7 +99,7 @@ async def delete_channel(self, topic, channel):
)
return resp

async def tombstone_topic_producer(self, topic, node):
async def tombstone_topic_producer(self, topic: str, node: str) -> HTTPResponse:
"""XXX
:param topic:
Expand Down
46 changes: 25 additions & 21 deletions ansq/http/writer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from typing import Any

from ansq.typedefs import HTTPResponse

from ..utils import convert_to_str
from .base import NSQHTTPConnection

Expand All @@ -7,107 +11,107 @@ class NSQDHTTPWriter(NSQHTTPConnection):
:see: http://nsq.io/components/nsqd.html
"""

async def ping(self):
async def ping(self) -> HTTPResponse:
"""Monitoring endpoint.
:returns: should return `"OK"`, otherwise raises an exception.
"""
return await self.perform_request("GET", "ping", None, None)

async def info(self):
async def info(self) -> HTTPResponse:
"""Returns version information."""
resp = await self.perform_request("GET", "info", None, None)
return resp

async def stats(self):
async def stats(self) -> HTTPResponse:
"""Returns stats information."""
resp = await self.perform_request("GET", "stats", {"format": "json"}, None)
return resp

async def pub(self, topic, message):
async def pub(self, topic: str, message: Any) -> HTTPResponse:
resp = await self.perform_request("POST", "pub", {"topic": topic}, message)
return resp

async def mpub(self, topic, *messages):
async def mpub(self, topic: str, *messages: Any) -> HTTPResponse:
assert len(messages), "Specify one or more messages"
msgs = "\n".join(convert_to_str(m) for m in messages)
resp = await self.perform_request("POST", "mpub", {"topic": topic}, msgs)
return resp

async def create_topic(self, topic):
async def create_topic(self, topic: str) -> HTTPResponse:
resp = await self.perform_request(
"POST", "topic/create", {"topic": topic}, None,
)
return resp

async def delete_topic(self, topic):
async def delete_topic(self, topic: str) -> HTTPResponse:
resp = await self.perform_request(
"POST", "topic/delete", {"topic": topic}, None,
)
return resp

async def create_channel(self, topic, channel):
async def create_channel(self, topic: str, channel: str) -> HTTPResponse:
resp = await self.perform_request(
"POST", "channel/create", {"topic": topic, "channel": channel}, None,
)
return resp

async def delete_channel(self, topic, channel):
async def delete_channel(self, topic: str, channel: str) -> HTTPResponse:
resp = await self.perform_request(
"POST", "channel/delete", {"topic": topic, "channel": channel}, None,
)
return resp

async def empty_topic(self, topic):
async def empty_topic(self, topic: str) -> HTTPResponse:
resp = await self.perform_request("POST", "topic/empty", {"topic": topic}, None)
return resp

async def topic_pause(self, topic):
async def topic_pause(self, topic: str) -> HTTPResponse:
resp = await self.perform_request("POST", "topic/pause", {"topic": topic}, None)
return resp

async def topic_unpause(self, topic):
async def topic_unpause(self, topic: str) -> HTTPResponse:
resp = await self.perform_request(
"POST", "topic/unpause", {"topic": topic}, None,
)
return resp

async def pause_channel(self, channel, topic):
async def pause_channel(self, channel: str, topic: str) -> HTTPResponse:
resp = await self.perform_request(
"POST", "channel/pause", {"topic": topic, "channel": channel}, None,
)
return resp

async def unpause_channel(self, channel, topic):
async def unpause_channel(self, channel: str, topic: str) -> HTTPResponse:
resp = await self.perform_request(
"POST", "channel/unpause", {"topic": topic, "channel": channel}, None,
)
return resp

async def debug_pprof(self):
async def debug_pprof(self) -> HTTPResponse:
resp = await self.perform_request("GET", "debug/pprof", None, None)
return resp

async def debug_pprof_profile(self):
async def debug_pprof_profile(self) -> HTTPResponse:
resp = await self.perform_request("GET", "debug/pprof/profile", None, None)
return resp

async def debug_pprof_goroutine(self):
async def debug_pprof_goroutine(self) -> HTTPResponse:
resp = await self.perform_request("GET", "debug/pprof/goroutine", None, None)
return resp

async def debug_pprof_heap(self):
async def debug_pprof_heap(self) -> HTTPResponse:
resp = await self.perform_request("GET", "debug/pprof/heap", None, None)
return resp

async def debug_pprof_block(self):
async def debug_pprof_block(self) -> HTTPResponse:
resp = await self.perform_request("GET", "debug/pprof/block", None, None)
return resp

async def debug_pprof_threadcreate(self):
async def debug_pprof_threadcreate(self) -> HTTPResponse:
resp = await self.perform_request("GET", "debug/pprof/threadcreate", None, None)
return resp

async def nsqlookupd_tcp_addresses(self):
async def nsqlookupd_tcp_addresses(self) -> HTTPResponse:
"""
List of nsqlookupd TCP addresses.
"""
Expand Down
Empty file added ansq/py.typed
Empty file.
Loading

0 comments on commit fd54721

Please sign in to comment.