diff --git a/.gitignore b/.gitignore index 6d45836b..b5055472 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,9 @@ coverage.xml # mypy *.mypy_cache/ +# pytype +.pytype/ + # sphinx sphinx-build docs/.buildinfo diff --git a/.travis.yml b/.travis.yml index 675b6dd0..6b91037d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,7 @@ script: # to find types, use reveal_type eg: reveal_type(asyncio.get_event_loop()) # see: http://mypy.readthedocs.io/en/latest/common_issues.html#displaying-the-type-of-an-expression - mypy --show-column-numbers --ignore-missing-imports -p cli -p naz #--strict + - pytype --verbosity 0 --python-version 3.6 --protocols --strict-import --keep-going naz/ cli/ - naz-cli --version && naz-cli --help - naz-cli --client examples.example_config.client --dry-run - coverage erase diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ee95f55..3fe16eb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ most recent version is listed first. +## **version:** v0.6.3 +- added static analysis support using pytype: https://github.com/komuw/naz/pull/148 + + ## **version:** v0.6.2 - If `naz` were to encounter an SMPP protocol error, it now bails early by unbinding and closing connection: https://github.com/komuw/naz/pull/147 diff --git a/Makefile b/Makefile index 6a73a2c0..e79b36e7 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,8 @@ test: @printf "\n run flake8::\n" && flake8 . @printf "\n run pylint::\n" && pylint --enable=E --disable=W,R,C naz/ tests/ cli/ documentation/ examples/ benchmarks/ @printf "\n run bandit::\n" && bandit -r --exclude .venv -ll . - @printf "\n run mypy::\n" && mypy --show-column-numbers --strict naz/ + @printf "\n run mypy::\n" && mypy --show-column-numbers --ignore-missing-imports -p cli -p naz + @printf "\n run pytype::\n" && pytype --verbosity 0 --python-version 3.6 --protocols --strict-import --keep-going naz/ cli/ # note `.nojekyll` file is important inside `docs/` folder sphinx: diff --git a/benchmarks/my_hook.py b/benchmarks/my_hook.py index 26e6e50a..335253e2 100644 --- a/benchmarks/my_hook.py +++ b/benchmarks/my_hook.py @@ -45,7 +45,11 @@ async def request(self, smpp_command: str, log_id: str, hook_metadata: str) -> N await self.loop.run_in_executor(executor, functools.partial(self._publish)) async def response( - self, smpp_command: str, log_id: str, hook_metadata: str, smsc_response: naz.CommandStatus + self, + smpp_command: str, + log_id: str, + hook_metadata: str, + smsc_response: naz.state.CommandStatus, ) -> None: self.counter.labels( project="naz_benchmarks", diff --git a/naz/__version__.py b/naz/__version__.py index e13a74fb..ddcb15e2 100644 --- a/naz/__version__.py +++ b/naz/__version__.py @@ -2,7 +2,7 @@ "__title__": "naz", "__description__": "Naz is an async SMPP client.", "__url__": "https://github.com/komuw/naz", - "__version__": "v0.6.2", + "__version__": "v0.6.3", "__author__": "komuW", "__author_email__": "komuw05@gmail.com", "__license__": "MIT", diff --git a/naz/client.py b/naz/client.py index acd91da3..bb3bf855 100644 --- a/naz/client.py +++ b/naz/client.py @@ -7,6 +7,7 @@ import asyncio import logging +# pytype: disable=pyi-error from . import q from . import hooks from . import logger @@ -25,6 +26,8 @@ SmppOptionalTag, ) +# pytype: disable=pyi-error + class Client: """ @@ -2414,7 +2417,8 @@ async def _unbind_and_disconnect(self): # in that order # see: https://github.com/komuw/naz/issues/117 - self.writer.transport.set_write_buffer_limits(0) + self.writer.transport.set_write_buffer_limits(0) # pytype: disable=attribute-error + # https://github.com/google/pytype/issues/350 await self.unbind() async with self.drain_lock: await self.writer.drain() diff --git a/naz/hooks.py b/naz/hooks.py index b88eb577..55df201a 100644 --- a/naz/hooks.py +++ b/naz/hooks.py @@ -5,7 +5,7 @@ from . import logger if typing.TYPE_CHECKING: - import naz # noqa: F401 + from . import state # noqa: F401 class BaseHook(abc.ABC): @@ -32,7 +32,11 @@ async def request(self, smpp_command: str, log_id: str, hook_metadata: str) -> N @abc.abstractmethod async def response( - self, smpp_command: str, log_id: str, hook_metadata: str, smsc_response: "naz.CommandStatus" + self, + smpp_command: str, + log_id: str, + hook_metadata: str, + smsc_response: "state.CommandStatus", ) -> None: """ called after a response is received from SMSC. @@ -78,7 +82,11 @@ async def request(self, smpp_command: str, log_id: str, hook_metadata: str) -> N ) async def response( - self, smpp_command: str, log_id: str, hook_metadata: str, smsc_response: "naz.CommandStatus" + self, + smpp_command: str, + log_id: str, + hook_metadata: str, + smsc_response: "state.CommandStatus", ) -> None: self.logger.log( logging.NOTSET, diff --git a/naz/logger.py b/naz/logger.py index 8bd452b8..ccd0e35e 100644 --- a/naz/logger.py +++ b/naz/logger.py @@ -82,7 +82,7 @@ def bind(self, level: typing.Union[str, int], log_metadata: dict) -> None: self._logger.setLevel(level) self.logger = NazLoggingAdapter(self._logger, log_metadata) - def log(self, level: typing.Union[str, int], log_data: dict) -> None: + def log(self, level: typing.Union[str, int], log_data: typing.Union[str, dict]) -> None: level = self._nameToLevel(level=level) if not self.logger: diff --git a/naz/nazcodec.py b/naz/nazcodec.py index 2ed5b8b6..7bf5281f 100644 --- a/naz/nazcodec.py +++ b/naz/nazcodec.py @@ -139,8 +139,13 @@ def handle_decode_error(self, char, handler_type, position, obj, indexErrorExcep @staticmethod def handle_decode_strict_error(char, position, obj, indexErrorException): + # https://github.com/google/pytype/issues/349 raise UnicodeDecodeError( - "gsm0338", chr(char).encode("latin-1"), position, position + 1, repr(obj) + "gsm0338", + chr(char).encode("latin-1"), + position, + position + 1, + repr(obj), # pytype: disable=wrong-arg-types ) from indexErrorException @staticmethod @@ -159,10 +164,11 @@ class UCS2Codec(codecs.Codec): """ def encode(self, input, errors="strict"): - return codecs.utf_16_be_encode(input, errors) + # https://github.com/google/pytype/issues/348 + return codecs.utf_16_be_encode(input, errors) # pytype: disable=module-attr def decode(self, input, errors="strict"): - return codecs.utf_16_be_decode(input, errors) + return codecs.utf_16_be_decode(input, errors) # pytype: disable=module-attr class BaseNazCodec(abc.ABC): diff --git a/setup.py b/setup.py index 1ae2bd61..a06800be 100644 --- a/setup.py +++ b/setup.py @@ -99,7 +99,7 @@ "redis==3.2.1", "pika==1.0.1", ], - "test": ["flake8", "pylint", "black", "bandit", "docker==4.0.1", "mypy"], + "test": ["flake8", "pylint", "black", "bandit", "docker==4.0.1", "mypy", "pytype"], "benchmarks": [ "asyncpg==0.18.3", "docker==4.0.1",