more strict flake8. Fixed typos.

pull/46/head
Marius Kriegerowski 2021-03-15 10:59:13 +01:00 zatwierdzone przez Florian Ludwig
rodzic 2c1b425820
commit 613e77f6b4
21 zmienionych plików z 60 dodań i 68 usunięć

Wyświetl plik

@ -30,8 +30,8 @@ jobs:
python -m pip install . python -m pip install .
- name: Lint with flake8 and black - name: Lint with flake8 and black
run: | run: |
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics flake8 . --count --statistics --show-source --ignore=E501,W503,W605,E722
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics flake8 . --count --statistics --exit-zero --max-complexity=10 --ignore=E501,W503
black . --check black . --check
- name: Test with pytest - name: Test with pytest
run: | run: |

Wyświetl plik

@ -214,13 +214,13 @@ htmlhelp_basename = "aMQTTdoc"
latex_elements = { latex_elements = {
# The paper size ('letterpaper' or 'a4paper'). # The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper', # 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt'). # The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt', # 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble. # Additional stuff for the LaTeX preamble.
#'preamble': '', # 'preamble': '',
# Latex figure (float) alignment # Latex figure (float) alignment
#'figure_align': 'htbp', # 'figure_align': 'htbp',
} }
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples

Wyświetl plik

@ -1,7 +1,7 @@
# Copyright (c) 2015 Nicolas JOUANIN # Copyright (c) 2015 Nicolas JOUANIN
# #
# See the file license.txt for copying permission. # See the file license.txt for copying permission.
import asyncio
import io import io
from websockets.protocol import WebSocketCommonProtocol from websockets.protocol import WebSocketCommonProtocol
from websockets.exceptions import ConnectionClosed from websockets.exceptions import ConnectionClosed
@ -13,19 +13,20 @@ class ReaderAdapter:
""" """
Base class for all network protocol reader adapter. Base class for all network protocol reader adapter.
Reader adapters are used to adapt read operations on the network depending on the protocol used Reader adapters are used to adapt read operations on the network depending on the
protocol used
""" """
async def read(self, n=-1) -> bytes: async def read(self, n=-1) -> bytes:
""" """
Read up to n bytes. If n is not provided, or set to -1, read until EOF and return all read bytes. Read up to n bytes. If n is not provided, or set to -1, read until EOF and
If the EOF was received and the internal buffer is empty, return an empty bytes object. return all read bytes. If the EOF was received and the internal buffer is
:return: packet read as bytes data empty, return an empty bytes object. :return: packet read as bytes data
""" """
def feed_eof(self): def feed_eof(self):
""" """
Acknowleddge EOF Acknowledge EOF
""" """
@ -33,7 +34,8 @@ class WriterAdapter:
""" """
Base class for all network protocol writer adapter. Base class for all network protocol writer adapter.
Writer adapters are used to adapt write operations on the network depending on the protocol used Writer adapters are used to adapt write operations on the network depending on
the protocol used
""" """
def write(self, data): def write(self, data):

Wyświetl plik

@ -1,7 +1,7 @@
# Copyright (c) 2015 Nicolas JOUANIN # Copyright (c) 2015 Nicolas JOUANIN
# #
# See the file license.txt for copying permission. # See the file license.txt for copying permission.
from typing import Optional, Dict, Union from typing import Optional
import logging import logging
import ssl import ssl
import websockets import websockets
@ -147,7 +147,7 @@ class Broker:
MQTT 3.1.1 compliant broker implementation MQTT 3.1.1 compliant broker implementation
:param config: Example Yaml config :param config: Example Yaml config
:param loop: asyncio loop to use. Defaults to ``asyncio.get_event_loop()`` if none is given :param loop: asyncio loop to use. Defaults to ``asyncio.get_event_loop()``.
:param plugin_namespace: Plugin namespace to use when loading plugin entry_points. Defaults to ``hbmqtt.broker.plugins`` :param plugin_namespace: Plugin namespace to use when loading plugin entry_points. Defaults to ``hbmqtt.broker.plugins``
""" """

Wyświetl plik

@ -200,7 +200,7 @@ class MQTTClient:
while self.client_tasks: while self.client_tasks:
task = self.client_tasks.pop() task = self.client_tasks.pop()
task.cancel() task.cancel()
except IndexError as err: except IndexError:
pass pass
async def reconnect(self, cleansession=None): async def reconnect(self, cleansession=None):

Wyświetl plik

@ -1,7 +1,6 @@
# Copyright (c) 2015 Nicolas JOUANIN # Copyright (c) 2015 Nicolas JOUANIN
# #
# See the file license.txt for copying permission. # See the file license.txt for copying permission.
import asyncio
from hbmqtt.mqtt.packet import CONNACK, MQTTPacket, MQTTFixedHeader, MQTTVariableHeader from hbmqtt.mqtt.packet import CONNACK, MQTTPacket, MQTTFixedHeader, MQTTVariableHeader
from hbmqtt.codecs import read_or_raise, bytes_to_int from hbmqtt.codecs import read_or_raise, bytes_to_int
from hbmqtt.errors import HBMQTTException from hbmqtt.errors import HBMQTTException

Wyświetl plik

@ -1,7 +1,6 @@
# Copyright (c) 2015 Nicolas JOUANIN # Copyright (c) 2015 Nicolas JOUANIN
# #
# See the file license.txt for copying permission. # See the file license.txt for copying permission.
import asyncio
from hbmqtt.codecs import ( from hbmqtt.codecs import (
bytes_to_int, bytes_to_int,

Wyświetl plik

@ -1,7 +1,6 @@
# Copyright (c) 2015 Nicolas JOUANIN # Copyright (c) 2015 Nicolas JOUANIN
# #
# See the file license.txt for copying permission. # See the file license.txt for copying permission.
import asyncio
from asyncio import futures, Queue from asyncio import futures, Queue
from hbmqtt.mqtt.protocol.handler import ProtocolHandler from hbmqtt.mqtt.protocol.handler import ProtocolHandler
from hbmqtt.mqtt.connack import ( from hbmqtt.mqtt.connack import (

Wyświetl plik

@ -3,7 +3,6 @@
# See the file license.txt for copying permission. # See the file license.txt for copying permission.
import asyncio import asyncio
from asyncio import futures from asyncio import futures
import sys
from hbmqtt.mqtt.protocol.handler import ProtocolHandler, EVENT_MQTT_PACKET_RECEIVED from hbmqtt.mqtt.protocol.handler import ProtocolHandler, EVENT_MQTT_PACKET_RECEIVED
from hbmqtt.mqtt.disconnect import DisconnectPacket from hbmqtt.mqtt.disconnect import DisconnectPacket
from hbmqtt.mqtt.pingreq import PingReqPacket from hbmqtt.mqtt.pingreq import PingReqPacket
@ -120,7 +119,7 @@ class ClientProtocolHandler(ProtocolHandler):
try: try:
waiter = self._subscriptions_waiter.get(packet_id) waiter = self._subscriptions_waiter.get(packet_id)
waiter.set_result(suback.payload.return_codes) waiter.set_result(suback.payload.return_codes)
except KeyError as ke: except KeyError:
self.logger.warning( self.logger.warning(
"Received SUBACK for unknown pending subscription with Id: %s" "Received SUBACK for unknown pending subscription with Id: %s"
% packet_id % packet_id
@ -144,7 +143,7 @@ class ClientProtocolHandler(ProtocolHandler):
try: try:
waiter = self._unsubscriptions_waiter.get(packet_id) waiter = self._unsubscriptions_waiter.get(packet_id)
waiter.set_result(None) waiter.set_result(None)
except KeyError as ke: except KeyError:
self.logger.warning( self.logger.warning(
"Received UNSUBACK for unknown pending subscription with Id: %s" "Received UNSUBACK for unknown pending subscription with Id: %s"
% packet_id % packet_id

Wyświetl plik

@ -1,8 +1,6 @@
# Copyright (c) 2015 Nicolas JOUANIN # Copyright (c) 2015 Nicolas JOUANIN
# #
# See the file license.txt for copying permission. # See the file license.txt for copying permission.
import asyncio
from hbmqtt.mqtt.packet import ( from hbmqtt.mqtt.packet import (
MQTTPacket, MQTTPacket,
MQTTFixedHeader, MQTTFixedHeader,
@ -25,9 +23,9 @@ class SubackPayload(MQTTPayload):
RETURN_CODE_02 = 0x02 RETURN_CODE_02 = 0x02
RETURN_CODE_80 = 0x80 RETURN_CODE_80 = 0x80
def __init__(self, return_codes=[]): def __init__(self, return_codes=None):
super().__init__() super().__init__()
self.return_codes = return_codes self.return_codes = return_codes or []
def __repr__(self): def __repr__(self):
return type(self).__name__ + "(return_codes={0})".format( return type(self).__name__ + "(return_codes={0})".format(

Wyświetl plik

@ -25,9 +25,9 @@ class SubscribePayload(MQTTPayload):
__slots__ = ("topics",) __slots__ = ("topics",)
def __init__(self, topics=[]): def __init__(self, topics=None):
super().__init__() super().__init__()
self.topics = topics self.topics = topics or []
def to_bytes( def to_bytes(
self, fixed_header: MQTTFixedHeader, variable_header: MQTTVariableHeader self, fixed_header: MQTTFixedHeader, variable_header: MQTTVariableHeader
@ -55,7 +55,7 @@ class SubscribePayload(MQTTPayload):
qos = bytes_to_int(qos_byte) qos = bytes_to_int(qos_byte)
topics.append((topic, qos)) topics.append((topic, qos))
read_bytes += 2 + len(topic.encode("utf-8")) + 1 read_bytes += 2 + len(topic.encode("utf-8")) + 1
except NoDataException as exc: except NoDataException:
break break
return cls(topics) return cls(topics)

Wyświetl plik

@ -19,9 +19,9 @@ class UnubscribePayload(MQTTPayload):
__slots__ = ("topics",) __slots__ = ("topics",)
def __init__(self, topics=[]): def __init__(self, topics=None):
super().__init__() super().__init__()
self.topics = topics self.topics = topics or []
def to_bytes( def to_bytes(
self, fixed_header: MQTTFixedHeader, variable_header: MQTTVariableHeader self, fixed_header: MQTTFixedHeader, variable_header: MQTTVariableHeader

Wyświetl plik

@ -2,7 +2,6 @@
# #
# See the file license.txt for copying permission. # See the file license.txt for copying permission.
import logging import logging
import asyncio
from passlib.apps import custom_app_context as pwd_context from passlib.apps import custom_app_context as pwd_context
@ -55,7 +54,7 @@ class AnonymousAuthPlugin(BaseAuthPlugin):
"Authentication failure: session has an empty username" "Authentication failure: session has an empty username"
) )
except KeyError: except KeyError:
self.context.logger.warning("Session informations not available") self.context.logger.warning("Session information not available")
authenticated = False authenticated = False
return authenticated return authenticated
@ -74,8 +73,8 @@ class FileAuthPlugin(BaseAuthPlugin):
self.context.logger.debug( self.context.logger.debug(
"Reading user database from %s" % password_file "Reading user database from %s" % password_file
) )
for l in f: for line in f:
line = l.strip() line = line.strip()
if not line.startswith("#"): # Allow comments in files if not line.startswith("#"): # Allow comments in files
(username, pwd_hash) = line.split(sep=":", maxsplit=3) (username, pwd_hash) = line.split(sep=":", maxsplit=3)
if username: if username:

Wyświetl plik

@ -4,7 +4,6 @@
import logging import logging
import asyncio
from functools import partial from functools import partial

Wyświetl plik

@ -8,7 +8,6 @@ import pkg_resources
import logging import logging
import asyncio import asyncio
import copy import copy
import sys
from collections import namedtuple from collections import namedtuple
@ -31,9 +30,9 @@ class BaseContext:
class PluginManager: class PluginManager:
""" """
Wraps setuptools Entry point mechanism to provide a basic plugin system. Wraps setuptools Entry point mechanism to provide a basic plugin system. Plugins
Plugins are loaded for a given namespace (group). are loaded for a given namespace (group). This plugin manager uses coroutines to
This plugin manager uses coroutines to run plugin call asynchronously in an event queue run plugin call asynchronously in an event queue
""" """
def __init__(self, namespace, context, loop=None): def __init__(self, namespace, context, loop=None):
@ -95,7 +94,8 @@ class PluginManager:
async def close(self): async def close(self):
""" """
Free PluginManager resources and cancel pending event methods Free PluginManager resources and cancel pending event methods
This method call a close() coroutine for each plugin, allowing plugins to close and free resources This method call a close() coroutine for each plugin, allowing plugins to close
and free resources
:return: :return:
""" """
await self.map_plugin_coro("close") await self.map_plugin_coro("close")
@ -118,8 +118,8 @@ class PluginManager:
Fire an event to plugins. Fire an event to plugins.
PluginManager schedule async calls for each plugin on method called "on_" + event_name PluginManager schedule async calls for each plugin on method called "on_" + event_name
For example, on_connect will be called on event 'connect' For example, on_connect will be called on event 'connect'
Method calls are schedule in the asyn loop. wait parameter must be set to true to wait until all Method calls are schedule in the async loop. wait parameter must be set to true
mehtods are completed. to wait until all methods are completed.
:param event_name: :param event_name:
:param args: :param args:
:param kwargs: :param kwargs:
@ -159,7 +159,8 @@ class PluginManager:
Schedule a given coroutine call for each plugin. Schedule a given coroutine call for each plugin.
The coro called get the Plugin instance as first argument of its method call The coro called get the Plugin instance as first argument of its method call
:param coro: coro to call on each plugin :param coro: coro to call on each plugin
:param filter_plugins: list of plugin names to filter (only plugin whose name is in filter are called). :param filter_plugins: list of plugin names to filter (only plugin whose name is
in filter are called).
None will call all plugins. [] will call None. None will call all plugins. [] will call None.
:param args: arguments to pass to coro :param args: arguments to pass to coro
:param kwargs: arguments to pass to coro :param kwargs: arguments to pass to coro

Wyświetl plik

@ -1,7 +1,6 @@
# Copyright (c) 2015 Nicolas JOUANIN # Copyright (c) 2015 Nicolas JOUANIN
# #
# See the file license.txt for copying permission. # See the file license.txt for copying permission.
import asyncio
import sqlite3 import sqlite3
import pickle import pickle

Wyświetl plik

@ -2,12 +2,12 @@
# #
# See the file license.txt for copying permission. # See the file license.txt for copying permission.
from datetime import datetime from datetime import datetime
from collections import deque
import asyncio
import hbmqtt import hbmqtt
from hbmqtt.mqtt.packet import PUBLISH from hbmqtt.mqtt.packet import PUBLISH
from hbmqtt.codecs import int_to_bytes_str from hbmqtt.codecs import int_to_bytes_str
import asyncio
import sys
from collections import deque
DOLLAR_SYS_ROOT = "$SYS/broker/" DOLLAR_SYS_ROOT = "$SYS/broker/"
@ -69,7 +69,7 @@ class BrokerSysPlugin:
sys_interval = int(self.context.config.get("sys_interval", 0)) sys_interval = int(self.context.config.get("sys_interval", 0))
if sys_interval > 0: if sys_interval > 0:
self.context.logger.debug( self.context.logger.debug(
"Setup $SYS broadcasting every %d secondes" % sys_interval "Setup $SYS broadcasting every %d seconds" % sys_interval
) )
self.sys_handle = self.context.loop.call_later( self.sys_handle = self.context.loop.call_later(
sys_interval, self.broadcast_dollar_sys_topics sys_interval, self.broadcast_dollar_sys_topics

Wyświetl plik

@ -1,6 +1,3 @@
import asyncio
class BaseTopicPlugin: class BaseTopicPlugin:
def __init__(self, context): def __init__(self, context):
self.context = context self.context = context

Wyświetl plik

@ -129,13 +129,13 @@ async def do_pub(client, arguments):
logger.info("%s Disconnected from broker" % client.client_id) logger.info("%s Disconnected from broker" % client.client_id)
except ConnectException as ce: except ConnectException as ce:
logger.fatal("connection to '%s' failed: %r" % (arguments["--url"], ce)) logger.fatal("connection to '%s' failed: %r" % (arguments["--url"], ce))
except asyncio.CancelledError as cae: except asyncio.CancelledError:
logger.fatal("Publish canceled due to prvious error") logger.fatal("Publish canceled due to previous error")
def main(*args, **kwargs): def main(*args, **kwargs):
if sys.version_info[:2] < (3, 4): if sys.version_info[:2] < (3, 6):
logger.fatal("Error: Python 3.4+ is required") logger.fatal("Error: Python 3.6+ is required")
sys.exit(-1) sys.exit(-1)
arguments = docopt(__doc__, version=hbmqtt.__version__) arguments = docopt(__doc__, version=hbmqtt.__version__)
@ -148,7 +148,6 @@ def main(*args, **kwargs):
level = logging.INFO level = logging.INFO
logging.basicConfig(level=level, format=formatter) logging.basicConfig(level=level, format=formatter)
config = None
if arguments["-c"]: if arguments["-c"]:
config = read_yaml_config(arguments["-c"]) config = read_yaml_config(arguments["-c"])
else: else:

Wyświetl plik

@ -106,17 +106,16 @@ async def do_sub(client, arguments):
await client.disconnect() await client.disconnect()
except ConnectException as ce: except ConnectException as ce:
logger.fatal("connection to '%s' failed: %r" % (arguments["--url"], ce)) logger.fatal("connection to '%s' failed: %r" % (arguments["--url"], ce))
except asyncio.CancelledError as cae: except asyncio.CancelledError:
logger.fatal("Publish canceled due to prvious error") logger.fatal("Publish canceled due to previous error")
def main(*args, **kwargs): def main(*args, **kwargs):
if sys.version_info[:2] < (3, 4): if sys.version_info[:2] < (3, 6):
logger.fatal("Error: Python 3.4+ is required") logger.fatal("Error: Python 3.6+ is required")
sys.exit(-1) sys.exit(-1)
arguments = docopt(__doc__, version=hbmqtt.__version__) arguments = docopt(__doc__, version=hbmqtt.__version__)
# print(arguments)
formatter = "[%(asctime)s] :: %(levelname)s - %(message)s" formatter = "[%(asctime)s] :: %(levelname)s - %(message)s"
if arguments["-d"]: if arguments["-d"]:

Wyświetl plik

@ -1,11 +1,9 @@
# Copyright (c) 2015 Nicolas JOUANIN # Copyright (c) 2015 Nicolas JOUANIN
# #
# See the file license.txt for copying permission. # See the file license.txt for copying permission.
import sys
import asyncio import asyncio
import logging import logging
import unittest from unittest.mock import call, MagicMock
from unittest.mock import patch, call, MagicMock
import pytest import pytest
@ -20,7 +18,6 @@ from hbmqtt.broker import (
EVENT_BROKER_CLIENT_SUBSCRIBED, EVENT_BROKER_CLIENT_SUBSCRIBED,
EVENT_BROKER_CLIENT_UNSUBSCRIBED, EVENT_BROKER_CLIENT_UNSUBSCRIBED,
EVENT_BROKER_MESSAGE_RECEIVED, EVENT_BROKER_MESSAGE_RECEIVED,
Broker,
) )
from hbmqtt.client import MQTTClient, ConnectException from hbmqtt.client import MQTTClient, ConnectException
from hbmqtt.mqtt import ( from hbmqtt.mqtt import (
@ -432,8 +429,11 @@ async def test_client_subscribe_publish_dollar_topic_1(broker):
message = None message = None
try: try:
message = await sub_client.deliver_message(timeout=2) message = await sub_client.deliver_message(timeout=2)
except Exception as e: except asyncio.TimeoutError:
pass pass
except RuntimeError as e:
# The loop is closed with pending tasks. Needs fine tuning.
log.warning(e)
assert message is None assert message is None
await sub_client.disconnect() await sub_client.disconnect()
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
@ -455,8 +455,11 @@ async def test_client_subscribe_publish_dollar_topic_2(broker):
message = None message = None
try: try:
message = await sub_client.deliver_message(timeout=2) message = await sub_client.deliver_message(timeout=2)
except Exception as e: except asyncio.TimeoutError:
pass pass
except RuntimeError as e:
# The loop is closed with pending tasks. Needs fine tuning.
log.warning(e)
assert message is None assert message is None
await sub_client.disconnect() await sub_client.disconnect()
await asyncio.sleep(0.1) await asyncio.sleep(0.1)