Major LINT fixes

This commit is contained in:
Fabio Manganiello 2021-04-05 00:58:44 +02:00
parent 86761e7088
commit 2a78f81a7b
101 changed files with 527 additions and 669 deletions

View file

@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
Given the high speed of development in the first phase, changes are being reported only starting from v0.20.2.
## [Unreleased]
### Fixed
- Major LINT fixes.
- Removed unmaintained integrations: TorrentCast and Booking.com
## [0.20.8] - 2021-04-04
### Added

View file

@ -28,7 +28,6 @@ Events
platypush/events/gps.rst
platypush/events/http.rst
platypush/events/http.hook.rst
platypush/events/http.ota.booking.rst
platypush/events/http.rss.rst
platypush/events/inotify.rst
platypush/events/joystick.rst

View file

@ -1,5 +0,0 @@
``platypush.message.event.http.ota.booking``
============================================
.. automodule:: platypush.message.event.http.ota.booking
:members:

View file

@ -1,5 +0,0 @@
``platypush.plugins.http.request.ota.booking``
==============================================
.. automodule:: platypush.plugins.http.request.ota.booking
:members:

View file

@ -1,5 +0,0 @@
``platypush.plugins.video.torrentcast``
=======================================
.. automodule:: platypush.plugins.video.torrentcast
:members:

View file

@ -61,7 +61,6 @@ Plugins
platypush/plugins/graphite.rst
platypush/plugins/homeseer.rst
platypush/plugins/http.request.rst
platypush/plugins/http.request.ota.booking.rst
platypush/plugins/http.request.rss.rst
platypush/plugins/http.webpage.rst
platypush/plugins/ifttt.rst
@ -137,7 +136,6 @@ Plugins
platypush/plugins/user.rst
platypush/plugins/utils.rst
platypush/plugins/variable.rst
platypush/plugins/video.torrentcast.rst
platypush/plugins/weather.rst
platypush/plugins/weather.buienradar.rst
platypush/plugins/weather.darksky.rst

View file

@ -6,10 +6,9 @@
import logging
import re
import socket
import threading
import time
from threading import Thread
from threading import Thread, Event as ThreadEvent, get_ident
from typing import Optional, Dict
from platypush.bus import Bus
@ -62,7 +61,7 @@ class Backend(Thread, EventGenerator):
self.poll_seconds = float(poll_seconds) if poll_seconds else None
self.device_id = Config.get('device_id')
self.thread_id = None
self._stop_event = threading.Event()
self._stop_event = ThreadEvent()
self._kwargs = kwargs
self.logger = logging.getLogger('platypush:backend:' + get_backend_name_by_class(self.__class__))
self.zeroconf = None
@ -220,7 +219,7 @@ class Backend(Thread, EventGenerator):
def run(self):
""" Starts the backend thread. To be implemented in the derived classes if the loop method isn't defined. """
self.thread_id = threading.get_ident()
self.thread_id = get_ident()
set_thread_name(self._thread_name)
if not callable(self.loop):
return

View file

@ -65,11 +65,11 @@ class AdafruitIoBackend(Backend):
def on_message(self, msg):
# noinspection PyUnusedLocal
def _handler(client, feed, data):
# noinspection PyBroadException
try:
data = float(data)
except:
pass
except Exception as e:
self.logger.debug('Not a number: {}: {}'.format(data, e))
self.bus.post(FeedUpdateEvent(feed=feed, data=data))
return _handler

View file

@ -55,15 +55,17 @@ class Alarm:
self._runtime_snooze_interval = snooze_interval
def get_next(self) -> float:
now = datetime.datetime.now().replace(tzinfo=gettz())
now = datetime.datetime.now().replace(tzinfo=gettz()) # lgtm [py/call-to-non-callable]
try:
cron = croniter.croniter(self.when, now)
return cron.get_next()
except (AttributeError, croniter.CroniterBadCronError):
try:
# lgtm [py/call-to-non-callable]
timestamp = datetime.datetime.fromisoformat(self.when).replace(tzinfo=gettz())
except (TypeError, ValueError):
# lgtm [py/call-to-non-callable]
timestamp = (datetime.datetime.now().replace(tzinfo=gettz()) +
datetime.timedelta(seconds=int(self.when)))

View file

@ -13,37 +13,41 @@ Bd addr are represented as standard python strings, e.g. "aa:bb:cc:dd:ee:ff".
import asyncio
from enum import Enum
from collections import namedtuple
import time
import struct
import itertools
class CreateConnectionChannelError(Enum):
NoError = 0
MaxPendingConnectionsReached = 1
class ConnectionStatus(Enum):
Disconnected = 0
Connected = 1
Ready = 2
class DisconnectReason(Enum):
Unspecified = 0
ConnectionEstablishmentFailed = 1
TimedOut = 2
BondingKeysMismatch = 3
class RemovedReason(Enum):
RemovedByThisClient = 0
ForceDisconnectedByThisClient = 1
ForceDisconnectedByOtherClient = 2
ButtonIsPrivate = 3
VerifyTimeout = 4
InternetBackendError = 5
InvalidData = 6
CouldntLoadDevice = 7
class ClickType(Enum):
ButtonDown = 0
ButtonUp = 1
@ -52,20 +56,24 @@ class ClickType(Enum):
ButtonDoubleClick = 4
ButtonHold = 5
class BdAddrType(Enum):
PublicBdAddrType = 0
RandomBdAddrType = 1
class LatencyMode(Enum):
NormalLatency = 0
LowLatency = 1
HighLatency = 2
class BluetoothControllerState(Enum):
Detached = 0
Resetting = 1
Attached = 2
class ScanWizardResult(Enum):
WizardSuccess = 0
WizardCancelledByUser = 1
@ -75,24 +83,26 @@ class ScanWizardResult(Enum):
WizardInternetBackendError = 5
WizardInvalidData = 6
class ButtonScanner:
"""ButtonScanner class.
Usage:
scanner = ButtonScanner()
scanner.on_advertisement_packet = lambda scanner, bd_addr, name, rssi, is_private, already_verified: ...
client.add_scanner(scanner)
"""
_cnt = itertools.count()
def __init__(self):
self._scan_id = next(ButtonScanner._cnt)
self.on_advertisement_packet = lambda scanner, bd_addr, name, rssi, is_private, already_verified: None
class ScanWizard:
"""ScanWizard class
Usage:
wizard = ScanWizard()
wizard.on_found_private_button = lambda scan_wizard: ...
@ -101,9 +111,9 @@ class ScanWizard:
wizard.on_completed = lambda scan_wizard, result, bd_addr, name: ...
client.add_scan_wizard(wizard)
"""
_cnt = itertools.count()
def __init__(self):
self._scan_wizard_id = next(ScanWizard._cnt)
self._bd_addr = None
@ -113,33 +123,34 @@ class ScanWizard:
self.on_button_connected = lambda scan_wizard, bd_addr, name: None
self.on_completed = lambda scan_wizard, result, bd_addr, name: None
class ButtonConnectionChannel:
"""ButtonConnectionChannel class.
This class represents a connection channel to a Flic button.
Add this button connection channel to a FlicClient by executing client.add_connection_channel(connection_channel).
You may only have this connection channel added to one FlicClient at a time.
Before you add the connection channel to the client, you should set up your callback functions by assigning
the corresponding properties to this object with a function. Each callback function has a channel parameter as the first one,
referencing this object.
Available properties and the function parameters are:
on_create_connection_channel_response: channel, error, connection_status
on_removed: channel, removed_reason
on_connection_status_changed: channel, connection_status, disconnect_reason
on_button_up_or_down / on_button_click_or_hold / on_button_single_or_double_click / on_button_single_or_double_click_or_hold: channel, click_type, was_queued, time_diff
"""
_cnt = itertools.count()
def __init__(self, bd_addr, latency_mode = LatencyMode.NormalLatency, auto_disconnect_time = 511):
def __init__(self, bd_addr, latency_mode=LatencyMode.NormalLatency, auto_disconnect_time=511):
self._conn_id = next(ButtonConnectionChannel._cnt)
self._bd_addr = bd_addr
self._latency_mode = latency_mode
self._auto_disconnect_time = auto_disconnect_time
self._client = None
self.on_create_connection_channel_response = lambda channel, error, connection_status: None
self.on_removed = lambda channel, removed_reason: None
self.on_connection_status_changed = lambda channel, connection_status, disconnect_reason: None
@ -147,61 +158,66 @@ class ButtonConnectionChannel:
self.on_button_click_or_hold = lambda channel, click_type, was_queued, time_diff: None
self.on_button_single_or_double_click = lambda channel, click_type, was_queued, time_diff: None
self.on_button_single_or_double_click_or_hold = lambda channel, click_type, was_queued, time_diff: None
@property
def bd_addr(self):
return self._bd_addr
@property
def latency_mode(self):
return self._latency_mode
@latency_mode.setter
def latency_mode(self, latency_mode):
if self._client is None:
self._latency_mode = latency_mode
return
self._latency_mode = latency_mode
if not self._client._closed:
self._client._send_command("CmdChangeModeParameters", {"conn_id": self._conn_id, "latency_mode": self._latency_mode, "auto_disconnect_time": self._auto_disconnect_time})
self._client._send_command("CmdChangeModeParameters",
{"conn_id": self._conn_id, "latency_mode": self._latency_mode,
"auto_disconnect_time": self._auto_disconnect_time})
@property
def auto_disconnect_time(self):
return self._auto_disconnect_time
@auto_disconnect_time.setter
def auto_disconnect_time(self, auto_disconnect_time):
if self._client is None:
self._auto_disconnect_time = auto_disconnect_time
return
self._auto_disconnect_time = auto_disconnect_time
if not self._client._closed:
self._client._send_command("CmdChangeModeParameters", {"conn_id": self._conn_id, "latency_mode": self._latency_mode, "auto_disconnect_time": self._auto_disconnect_time})
self._client._send_command("CmdChangeModeParameters",
{"conn_id": self._conn_id, "latency_mode": self._latency_mode,
"auto_disconnect_time": self._auto_disconnect_time})
class FlicClient(asyncio.Protocol):
"""FlicClient class.
When this class is constructed, a socket connection is established.
You may then send commands to the server and set timers.
Once you are ready with the initialization you must call the handle_events() method which is a main loop that never exits, unless the socket is closed.
For a more detailed description of all commands, events and enums, check the protocol specification.
All commands are wrapped in more high level functions and events are reported using callback functions.
All methods called on this class will take effect only if you eventually call the handle_events() method.
The ButtonScanner is used to set up a handler for advertisement packets.
The ButtonConnectionChannel is used to interact with connections to flic buttons and receive their events.
Other events are handled by the following callback functions that can be assigned to this object (and a list of the callback function parameters):
on_new_verified_button: bd_addr
on_no_space_for_new_connection: max_concurrently_connected_buttons
on_got_space_for_new_connection: max_concurrently_connected_buttons
on_bluetooth_controller_state_change: state
"""
_EVENTS = [
("EvtAdvertisementPacket", "<I6s17pb??", "scan_id bd_addr name rssi is_private already_verified"),
("EvtCreateConnectionChannelResponse", "<IBB", "conn_id error connection_status"),
@ -212,7 +228,8 @@ class FlicClient(asyncio.Protocol):
("EvtButtonSingleOrDoubleClick", "<IBBI", "conn_id click_type was_queued time_diff"),
("EvtButtonSingleOrDoubleClickOrHold", "<IBBI", "conn_id click_type was_queued time_diff"),
("EvtNewVerifiedButton", "<6s", "bd_addr"),
("EvtGetInfoResponse", "<B6sBBhBBH", "bluetooth_controller_state my_bd_addr my_bd_addr_type max_pending_connections max_concurrently_connected_buttons current_pending_connections currently_no_space_for_new_connection nb_verified_buttons"),
("EvtGetInfoResponse", "<B6sBBhBBH",
"bluetooth_controller_state my_bd_addr my_bd_addr_type max_pending_connections max_concurrently_connected_buttons current_pending_connections currently_no_space_for_new_connection nb_verified_buttons"),
("EvtNoSpaceForNewConnection", "<B", "max_concurrently_connected_buttons"),
("EvtGotSpaceForNewConnection", "<B", "max_concurrently_connected_buttons"),
("EvtBluetoothControllerStateChange", "<B", "state"),
@ -223,9 +240,9 @@ class FlicClient(asyncio.Protocol):
("EvtScanWizardButtonConnected", "<I", "scan_wizard_id"),
("EvtScanWizardCompleted", "<IB", "scan_wizard_id result")
]
_EVENT_STRUCTS = list(map(lambda x: None if x == None else struct.Struct(x[1]), _EVENTS))
_EVENT_NAMED_TUPLES = list(map(lambda x: None if x == None else namedtuple(x[0], x[2]), _EVENTS))
_EVENT_STRUCTS = list(map(lambda x: None if x is None else struct.Struct(x[1]), _EVENTS))
_EVENT_NAMED_TUPLES = list(map(lambda x: None if x is None else namedtuple(x[0], x[2]), _EVENTS))
_COMMANDS = [
("CmdGetInfo", "", ""),
("CmdCreateScanner", "<I", "scan_id"),
@ -239,168 +256,169 @@ class FlicClient(asyncio.Protocol):
("CmdCreateScanWizard", "<I", "scan_wizard_id"),
("CmdCancelScanWizard", "<I", "scan_wizard_id")
]
_COMMAND_STRUCTS = list(map(lambda x: struct.Struct(x[1]), _COMMANDS))
_COMMAND_NAMED_TUPLES = list(map(lambda x: namedtuple(x[0], x[2]), _COMMANDS))
_COMMAND_NAME_TO_OPCODE = dict((x[0], i) for i, x in enumerate(_COMMANDS))
@staticmethod
def _bdaddr_bytes_to_string(bdaddr_bytes):
return ":".join(map(lambda x: "%02x" % x, reversed(bdaddr_bytes)))
@staticmethod
def _bdaddr_string_to_bytes(bdaddr_string):
return bytearray.fromhex("".join(reversed(bdaddr_string.split(":"))))
def __init__(self, loop,parent=None):
def __init__(self, loop, parent=None):
self.loop = loop
self.buffer=b""
self.transport=None
self.parent=parent
self.buffer = b""
self.transport = None
self.parent = parent
self._scanners = {}
self._scan_wizards = {}
self._connection_channels = {}
self._closed = False
self.on_new_verified_button = lambda bd_addr: None
self.on_no_space_for_new_connection = lambda max_concurrently_connected_buttons: None
self.on_got_space_for_new_connection = lambda max_concurrently_connected_buttons: None
self.on_bluetooth_controller_state_change = lambda state: None
self.on_bluetooth_controller_state_change = lambda state: None
self.on_get_info = lambda items: None
self.on_get_button_uuid = lambda addr, uuid: None
def connection_made(self, transport):
self.transport=transport
self.transport = transport
if self.parent:
self.parent.register_protocol(self)
def close(self):
"""Closes the client. The handle_events() method will return."""
if self._closed:
return
self._closed = True
def add_scanner(self, scanner):
"""Add a ButtonScanner object.
The scan will start directly once the scanner is added.
"""
if scanner._scan_id in self._scanners:
return
self._scanners[scanner._scan_id] = scanner
self._send_command("CmdCreateScanner", {"scan_id": scanner._scan_id})
def remove_scanner(self, scanner):
"""Remove a ButtonScanner object.
You will no longer receive advertisement packets.
"""
if scanner._scan_id not in self._scanners:
return
del self._scanners[scanner._scan_id]
self._send_command("CmdRemoveScanner", {"scan_id": scanner._scan_id})
def add_scan_wizard(self, scan_wizard):
"""Add a ScanWizard object.
The scan wizard will start directly once the scan wizard is added.
"""
if scan_wizard._scan_wizard_id in self._scan_wizards:
return
self._scan_wizards[scan_wizard._scan_wizard_id] = scan_wizard
self._send_command("CmdCreateScanWizard", {"scan_wizard_id": scan_wizard._scan_wizard_id})
def cancel_scan_wizard(self, scan_wizard):
"""Cancel a ScanWizard.
Note: The effect of this command will take place at the time the on_completed event arrives on the scan wizard object.
If cancelled due to this command, "result" in the on_completed event will be "WizardCancelledByUser".
"""
if scan_wizard._scan_wizard_id not in self._scan_wizards:
return
self._send_command("CmdCancelScanWizard", {"scan_wizard_id": scan_wizard._scan_wizard_id})
def add_connection_channel(self, channel):
"""Adds a connection channel to a specific Flic button.
This will start listening for a specific Flic button's connection and button events.
Make sure the Flic is either in public mode (by holding it down for 7 seconds) or already verified before calling this method.
The on_create_connection_channel_response callback property will be called on the
connection channel after this command has been received by the server.
You may have as many connection channels as you wish for a specific Flic Button.
"""
if channel._conn_id in self._connection_channels:
return
channel._client = self
self._connection_channels[channel._conn_id] = channel
self._send_command("CmdCreateConnectionChannel", {"conn_id": channel._conn_id, "bd_addr": channel.bd_addr, "latency_mode": channel._latency_mode, "auto_disconnect_time": channel._auto_disconnect_time})
self._send_command("CmdCreateConnectionChannel", {"conn_id": channel._conn_id, "bd_addr": channel.bd_addr,
"latency_mode": channel._latency_mode,
"auto_disconnect_time": channel._auto_disconnect_time})
def remove_connection_channel(self, channel):
"""Remove a connection channel.
This will stop listening for new events for a specific connection channel that has previously been added.
Note: The effect of this command will take place at the time the on_removed event arrives on the connection channel object.
"""
if channel._conn_id not in self._connection_channels:
return
self._send_command("CmdRemoveConnectionChannel", {"conn_id": channel._conn_id})
def force_disconnect(self, bd_addr):
"""Force disconnection or cancel pending connection of a specific Flic button.
This removes all connection channels for all clients connected to the server for this specific Flic button.
"""
self._send_command("CmdForceDisconnect", {"bd_addr": bd_addr})
def get_info(self):
"""Get info about the current state of the server.
The server will send back its information directly and the callback will be called once the response arrives.
The callback takes only one parameter: info. This info parameter is a dictionary with the following objects:
bluetooth_controller_state, my_bd_addr, my_bd_addr_type, max_pending_connections, max_concurrently_connected_buttons,
current_pending_connections, currently_no_space_for_new_connection, bd_addr_of_verified_buttons (a list of bd addresses).
"""
self._send_command("CmdGetInfo", {})
def get_button_uuid(self, bd_addr):
"""Get button uuid for a verified button.
The server will send back its information directly and the callback will be called once the response arrives.
Responses will arrive in the same order as requested.
The callback takes two parameters: bd_addr, uuid (hex string of 32 characters).
Note: if the button isn't verified, the uuid sent to the callback will rather be None.
"""
self._send_command("CmdGetButtonUUID", {"bd_addr": bd_addr})
def run_on_handle_events_thread(self, callback):
"""Run a function on the thread that handles the events."""
if threading.get_ident() == self._handle_event_thread_ident:
callback()
else:
self.set_timer(0, callback)
def _send_command(self, name, items):
for key, value in items.items():
if isinstance(value, Enum):
items[key] = value.value
if "bd_addr" in items:
items["bd_addr"] = FlicClient._bdaddr_string_to_bytes(items["bd_addr"])
items["bd_addr"] = FlicClient._bdaddr_string_to_bytes()
opcode = FlicClient._COMMAND_NAME_TO_OPCODE[name]
data_bytes = FlicClient._COMMAND_STRUCTS[opcode].pack(*FlicClient._COMMAND_NAMED_TUPLES[opcode](**items))
bytes = bytearray(3)
@ -409,83 +427,85 @@ class FlicClient(asyncio.Protocol):
bytes[2] = opcode
bytes += data_bytes
self.transport.write(bytes)
def _dispatch_event(self, data):
if len(data) == 0:
return
opcode = data[0]
if opcode >= len(FlicClient._EVENTS) or FlicClient._EVENTS[opcode] == None:
if opcode >= len(FlicClient._EVENTS) or FlicClient._EVENTS[opcode] is None:
return
event_name = FlicClient._EVENTS[opcode][0]
data_tuple = FlicClient._EVENT_STRUCTS[opcode].unpack(data[1 : 1 + FlicClient._EVENT_STRUCTS[opcode].size])
data_tuple = FlicClient._EVENT_STRUCTS[opcode].unpack(data[1: 1 + FlicClient._EVENT_STRUCTS[opcode].size])
items = FlicClient._EVENT_NAMED_TUPLES[opcode]._make(data_tuple)._asdict()
# Process some kind of items whose data type is not supported by struct
if "bd_addr" in items:
items["bd_addr"] = FlicClient._bdaddr_bytes_to_string(items["bd_addr"])
items["bd_addr"] = FlicClient._bdaddr_bytes_to_string()
if "name" in items:
items["name"] = items["name"].decode("utf-8")
if event_name == "EvtCreateConnectionChannelResponse":
items["error"] = CreateConnectionChannelError(items["error"])
items["connection_status"] = ConnectionStatus(items["connection_status"])
if event_name == "EvtConnectionStatusChanged":
items["connection_status"] = ConnectionStatus(items["connection_status"])
items["disconnect_reason"] = DisconnectReason(items["disconnect_reason"])
if event_name == "EvtConnectionChannelRemoved":
items["removed_reason"] = RemovedReason(items["removed_reason"])
if event_name.startswith("EvtButton"):
items["click_type"] = ClickType(items["click_type"])
if event_name == "EvtGetInfoResponse":
items["bluetooth_controller_state"] = BluetoothControllerState(items["bluetooth_controller_state"])
items["my_bd_addr"] = FlicClient._bdaddr_bytes_to_string(items["my_bd_addr"])
items["my_bd_addr"] = FlicClient._bdaddr_bytes_to_string()
items["my_bd_addr_type"] = BdAddrType(items["my_bd_addr_type"])
items["bd_addr_of_verified_buttons"] = []
pos = FlicClient._EVENT_STRUCTS[opcode].size
for i in range(items["nb_verified_buttons"]):
items["bd_addr_of_verified_buttons"].append(FlicClient._bdaddr_bytes_to_string(data[1 + pos : 1 + pos + 6]))
items["bd_addr_of_verified_buttons"].append(
FlicClient._bdaddr_bytes_to_string())
pos += 6
if event_name == "EvtBluetoothControllerStateChange":
items["state"] = BluetoothControllerState(items["state"])
if event_name == "EvtGetButtonUUIDResponse":
items["uuid"] = "".join(map(lambda x: "%02x" % x, items["uuid"]))
if items["uuid"] == "00000000000000000000000000000000":
items["uuid"] = None
if event_name == "EvtScanWizardCompleted":
items["result"] = ScanWizardResult(items["result"])
# Process event
if event_name == "EvtAdvertisementPacket":
scanner = self._scanners.get(items["scan_id"])
if scanner is not None:
scanner.on_advertisement_packet(scanner, items["bd_addr"], items["name"], items["rssi"], items["is_private"], items["already_verified"])
scanner.on_advertisement_packet(scanner, items["bd_addr"], items["name"], items["rssi"],
items["is_private"], items["already_verified"])
if event_name == "EvtCreateConnectionChannelResponse":
channel = self._connection_channels[items["conn_id"]]
if items["error"] != CreateConnectionChannelError.NoError:
del self._connection_channels[items["conn_id"]]
channel.on_create_connection_channel_response(channel, items["error"], items["connection_status"])
if event_name == "EvtConnectionStatusChanged":
channel = self._connection_channels[items["conn_id"]]
channel.on_connection_status_changed(channel, items["connection_status"], items["disconnect_reason"])
if event_name == "EvtConnectionChannelRemoved":
channel = self._connection_channels[items["conn_id"]]
del self._connection_channels[items["conn_id"]]
channel.on_removed(channel, items["removed_reason"])
if event_name == "EvtButtonUpOrDown":
channel = self._connection_channels[items["conn_id"]]
channel.on_button_up_or_down(channel, items["click_type"], items["was_queued"], items["time_diff"])
@ -494,61 +514,60 @@ class FlicClient(asyncio.Protocol):
channel.on_button_click_or_hold(channel, items["click_type"], items["was_queued"], items["time_diff"])
if event_name == "EvtButtonSingleOrDoubleClick":
channel = self._connection_channels[items["conn_id"]]
channel.on_button_single_or_double_click(channel, items["click_type"], items["was_queued"], items["time_diff"])
channel.on_button_single_or_double_click(channel, items["click_type"], items["was_queued"],
items["time_diff"])
if event_name == "EvtButtonSingleOrDoubleClickOrHold":
channel = self._connection_channels[items["conn_id"]]
channel.on_button_single_or_double_click_or_hold(channel, items["click_type"], items["was_queued"], items["time_diff"])
channel.on_button_single_or_double_click_or_hold(channel, items["click_type"], items["was_queued"],
items["time_diff"])
if event_name == "EvtNewVerifiedButton":
self.on_new_verified_button(items["bd_addr"])
if event_name == "EvtGetInfoResponse":
self.on_get_info(items)
if event_name == "EvtNoSpaceForNewConnection":
self.on_no_space_for_new_connection(items["max_concurrently_connected_buttons"])
if event_name == "EvtGotSpaceForNewConnection":
self.on_got_space_for_new_connection(items["max_concurrently_connected_buttons"])
if event_name == "EvtBluetoothControllerStateChange":
self.on_bluetooth_controller_state_change(items["state"])
if event_name == "EvtGetButtonUUIDResponse":
self.on_get_button_uuid(items["bd_addr"], items["uuid"])
if event_name == "EvtScanWizardFoundPrivateButton":
scan_wizard = self._scan_wizards[items["scan_wizard_id"]]
scan_wizard.on_found_private_button(scan_wizard)
if event_name == "EvtScanWizardFoundPublicButton":
scan_wizard = self._scan_wizards[items["scan_wizard_id"]]
scan_wizard._bd_addr = items["bd_addr"]
scan_wizard._name = items["name"]
scan_wizard.on_found_public_button(scan_wizard, scan_wizard._bd_addr, scan_wizard._name)
if event_name == "EvtScanWizardButtonConnected":
scan_wizard = self._scan_wizards[items["scan_wizard_id"]]
scan_wizard.on_button_connected(scan_wizard, scan_wizard._bd_addr, scan_wizard._name)
if event_name == "EvtScanWizardCompleted":
scan_wizard = self._scan_wizards[items["scan_wizard_id"]]
del self._scan_wizards[items["scan_wizard_id"]]
scan_wizard.on_completed(scan_wizard, items["result"], scan_wizard._bd_addr, scan_wizard._name)
def data_received(self,data):
cdata=self.buffer+data
self.buffer=b""
def data_received(self, data):
cdata = self.buffer + data
self.buffer = b""
while len(cdata):
packet_len = cdata[0] | (cdata[1] << 8)
packet_len += 2
if len(cdata)>= packet_len:
if len(cdata) >= packet_len:
self._dispatch_event(cdata[2:packet_len])
cdata=cdata[packet_len:]
cdata = cdata[packet_len:]
else:
if len(cdata):
self.buffer=cdata #unlikely to happen but.....
self.buffer = cdata # unlikely to happen but.....
break

View file

@ -34,7 +34,7 @@ class CameraPiBackend(Backend):
return self.value == other
# noinspection PyUnresolvedReferences,PyPackageRequirements
def __init__(self, listen_port, x_resolution=640, y_resolution=480,
def __init__(self, listen_port, bind_address='0.0.0.0', x_resolution=640, y_resolution=480,
redis_queue='platypush/camera/pi',
start_recording_on_startup=True,
framerate=24, hflip=False, vflip=False,
@ -49,13 +49,17 @@ class CameraPiBackend(Backend):
:param listen_port: Port where the camera process will provide the video output while recording
:type listen_port: int
:param bind_address: Bind address (default: 0.0.0.0).
:type bind_address: str
"""
super().__init__(**kwargs)
self.bind_address = bind_address
self.listen_port = listen_port
self.server_socket = socket.socket()
self.server_socket.bind(('0.0.0.0', self.listen_port))
self.server_socket.bind((self.bind_address, self.listen_port))
self.server_socket.listen(0)
import picamera
@ -134,13 +138,13 @@ class CameraPiBackend(Backend):
self.logger.info('Client closed connection')
try:
self.stop_recording()
except:
pass
except Exception as e:
self.logger.warning('Could not stop recording: {}'.format(str(e)))
try:
connection.close()
except:
pass
except Exception as e:
self.logger.warning('Could not close connection: {}'.format(str(e)))
self.send_camera_action(self.CameraAction.START_RECORDING)

View file

@ -51,11 +51,10 @@ class GooglePubsubBackend(Backend):
def _message_callback(self, topic):
def callback(msg):
data = msg.data.decode()
# noinspection PyBroadException
try:
data = json.loads(data)
except:
pass
except Exception as e:
self.logger.debug('Not a valid JSON: {}: {}'.format(data, str(e)))
msg.ack()
self.bus.post(GooglePubsubMessageEvent(topic=topic, msg=data))

View file

@ -31,8 +31,8 @@ def _hook(hook_name):
# noinspection PyBroadException
try:
event_args['data'] = json.loads(event_args['data'])
except:
pass
except Exception as e:
logger().warning('Not a valid JSON string: {}: {}'.format(event_args['data'], str(e)))
event = WebhookEvent(**event_args)

View file

@ -31,7 +31,7 @@ def login():
if session_token:
user, session = user_manager.authenticate_user_session(session_token)
if user:
return redirect(redirect_page, 302)
return redirect(redirect_page, 302) # lgtm [py/url-redirection]
if request.form:
username = request.form.get('username')
@ -44,7 +44,7 @@ def login():
expires_at=expires)
if session:
redirect_target = redirect(redirect_page, 302)
redirect_target = redirect(redirect_page, 302) # lgtm [py/url-redirection]
response = make_response(redirect_target)
response.set_cookie('session_token', session.session_token, expires=expires)
return response

View file

@ -25,7 +25,7 @@ def logout():
if not user:
return abort(403, 'Invalid session token')
redirect_target = redirect(redirect_page, 302)
redirect_target = redirect(redirect_page, 302) # lgtm [py/url-redirection]
response = make_response(redirect_target)
response.set_cookie('session_token', '', expires=0)
return response

View file

@ -32,8 +32,8 @@ def add_media():
args = {}
try:
args = json.loads(request.data.decode('utf-8'))
except:
abort(400, 'Invalid JSON request')
except Exception as e:
abort(400, 'Invalid JSON request: {}'.format(str(e)))
source = args.get('source')
if not source:

View file

@ -40,7 +40,7 @@ def audio_feed(device, fifo, sample_rate, blocksize, latency, channels):
channels=channels)
try:
with open(fifo, 'rb') as f:
with open(fifo, 'rb') as f: # lgtm [py/path-injection]
send_header = True
while True:

View file

@ -31,10 +31,10 @@ def register():
if session_token:
user, session = user_manager.authenticate_user_session(session_token)
if user:
return redirect(redirect_page, 302)
return redirect(redirect_page, 302) # lgtm [py/url-redirection]
if user_manager.get_user_count() > 0:
return redirect('/login?redirect=' + redirect_page, 302)
return redirect('/login?redirect=' + redirect_page, 302) # lgtm [py/url-redirection]
if request.form:
username = request.form.get('username')
@ -49,7 +49,7 @@ def register():
if not remember else None)
if session:
redirect_target = redirect(redirect_page, 302)
redirect_target = redirect(redirect_page, 302) # lgtm [py/url-redirection]
response = make_response(redirect_target)
response.set_cookie('session_token', session.session_token)
return response

View file

@ -123,7 +123,8 @@ def _authenticate_token():
try:
user_manager.validate_jwt_token(user_token)
return True
except:
except Exception as e:
logger().debug(str(e))
return token and user_token == token

View file

@ -78,11 +78,11 @@ class HttpRequest(object):
def get_new_items(self, response):
""" Gets new items out of a response """
raise ("get_new_items must be implemented in a derived class")
raise NotImplementedError("get_new_items must be implemented in a derived class")
def __iter__(self):
for (key, value) in self.request_args.items():
yield (key, value)
yield key, value
class JsonHttpRequest(HttpRequest):
@ -96,7 +96,7 @@ class JsonHttpRequest(HttpRequest):
new_entries = []
if self.path:
m = re.match('\$\{\s*(.*)\s*\}', self.path)
m = re.match(r'\${\s*(.*)\s*}', self.path)
response = eval(m.group(1))
for entry in response:

View file

@ -238,15 +238,15 @@ class RssUpdates(HttpRequest):
with open(digest_filename, 'w', encoding='utf-8') as f:
f.write(content)
elif self.digest_format == 'pdf':
import weasyprint
from weasyprint import HTML, CSS
from weasyprint.fonts import FontConfiguration
body_style = 'body { {body_style} }'.format(body_style=self.body_style)
body_style = 'body { ' + self.body_style + ' }'
font_config = FontConfiguration()
css = [weasyprint.CSS('https://fonts.googleapis.com/css?family=Merriweather'),
weasyprint.CSS(string=body_style, font_config=font_config)]
css = [CSS('https://fonts.googleapis.com/css?family=Merriweather'),
CSS(string=body_style, font_config=font_config)]
weasyprint.HTML(string=content).write_pdf(digest_filename, stylesheets=css)
HTML(string=content).write_pdf(digest_filename, stylesheets=css)
else:
raise RuntimeError('Unsupported format: {}. Supported formats: ' +
'html or pdf'.format(self.digest_format))

View file

@ -50,15 +50,13 @@ class HttpUtils(object):
for name, resource_path in resource_dirs.items():
resource_path = os.path.abspath(os.path.expanduser(resource_path))
if directory.startswith(resource_path):
subdir = re.sub('^{}(.*)$'.format(resource_path),
'\\1', directory)
uri = '/resources/' + name
break
if not uri:
raise RuntimeError(('Directory {} not found among the available ' +
'static resources on the webserver').format(
directory))
'static resources on the webserver').format(
directory))
results = [
re.sub('^{}(.*)$'.format(resource_path), uri + '\\1', path)
@ -92,10 +90,11 @@ class HttpUtils(object):
@classmethod
def plugin_name_to_tag(cls, module_name):
return module_name.replace('.','-')
return module_name.replace('.', '-')
@classmethod
def find_templates_in_dir(cls, directory):
# noinspection PyTypeChecker
return [
os.path.join(directory, file)
for root, path, files in os.walk(os.path.abspath(os.path.join(template_folder, directory)))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -380,20 +380,16 @@ export default {
this.request(this.action.name, args).then(this.onResponse).catch(this.onError).finally(this.onDone)
} else {
let request = this.rawRequest
try {
request = JSON.parse(this.rawRequest)
const request = JSON.parse(this.rawRequest)
this.execute(request).then(this.onResponse).catch(this.onError).finally(this.onDone)
} catch (e) {
this.notify({
error: true,
title: 'Invalid JSON request',
text: e.toString(),
})
return
}
this.execute(request).then(this.onResponse).catch(this.onError).finally(this.onDone)
}
},

View file

@ -110,6 +110,7 @@ export class ColorConverter {
if (isNaN(blue))
blue = 0;
// lgtm [js/automatic-semicolon-insertion]
return [red, green, blue].map((c) => Math.min(Math.max(0, c), 255))
}

View file

@ -454,9 +454,10 @@ export default {
brightness: hsl[2],
color: {
hue: hsl[0],
'`${satAttr}': hsl[1],
}
}
request.value.color[satAttr] = hsl[1]
}
}
break

View file

@ -35,6 +35,7 @@ class KafkaBackend(Backend):
self.topic_prefix = topic
self.topic = self._topic_by_device_id(self.device_id)
self.producer = None
self.consumer = None
# Kafka can be veryyyy noisy
logging.getLogger('kafka').setLevel(logging.ERROR)
@ -47,8 +48,8 @@ class KafkaBackend(Backend):
try:
msg = Message.build(msg)
is_platypush_message = True
except:
pass
except Exception as e:
self.logger.debug(str(e))
self.logger.info('Received message on Kafka backend: {}'.format(msg))
@ -60,7 +61,7 @@ class KafkaBackend(Backend):
def _topic_by_device_id(self, device_id):
return '{}.{}'.format(self.topic_prefix, device_id)
def send_message(self, msg):
def send_message(self, msg, **kwargs):
target = msg.target
kafka_plugin = get_plugin('kafka')
kafka_plugin.send_message(msg=msg,

View file

@ -108,8 +108,8 @@ class LogEventHandler(EventHandler):
url = m.group(5).split(' ')[1]
method = m.group(5).split(' ')[0]
http_version = m.group(5).split(' ')[2].split('/')[1]
except:
pass
except Exception as e:
logger.debug(str(e))
if not url:
return

View file

@ -275,8 +275,8 @@ class MqttBackend(Backend):
try:
data = data.decode('utf-8')
data = json.loads(data)
except:
pass
except Exception as e:
self.logger.debug(str(e))
# noinspection PyProtectedMember
self.bus.post(MQTTMessageEvent(host=client._host, port=client._port, topic=msg.topic, msg=data))
@ -303,8 +303,8 @@ class MqttBackend(Backend):
try:
msg = json.loads(msg)
msg = Message.build(msg)
except:
pass
except Exception as e:
self.logger.debug(str(e))
if not msg:
return

View file

@ -49,10 +49,10 @@ class PushbulletBackend(Backend):
from pushbullet import Pushbullet
self.pb = Pushbullet(self.token)
# noinspection PyBroadException
try:
self.device = self.pb.get_device(self.device_name)
except:
except Exception as e:
self.logger.info('Device {} does not exist: {}. Creating it'.format(self.device_name, str(e)))
self.device = self.pb.new_device(self.device_name)
self.pb_device_id = self.get_device_id()

View file

@ -60,15 +60,17 @@ class RedisBackend(Backend):
msg = data[1].decode()
try:
msg = Message.build(msg)
except:
except Exception as e:
self.logger.debug(str(e))
try:
import ast
msg = Message.build(ast.literal_eval(msg))
except:
except Exception as ee:
self.logger.debug(str(ee))
try:
msg = json.loads(msg)
except Exception as e:
self.logger.exception(e)
except Exception as eee:
self.logger.exception(eee)
return msg

View file

@ -119,12 +119,11 @@ class SensorBackend(Backend):
if self.data is None or new_data is None:
return new_data
# noinspection PyBroadException
try:
# Scalar data case
new_data = self._get_value(new_data)
return new_data if abs(new_data - self.data) >= self.tolerance else None
except:
except (ValueError, TypeError):
# If it's not a scalar then it should be a dict
assert isinstance(new_data, dict), 'Invalid type {} received for sensor data'.format(type(new_data))

View file

@ -6,12 +6,9 @@ import re
import time
from platypush.backend import Backend
from platypush.message import Message
from platypush.message.event.wiimote import WiimoteEvent, \
WiimoteConnectionEvent, WiimoteDisconnectionEvent
from platypush.message.request import Request
class WiimoteBackend(Backend):
"""
@ -110,8 +107,8 @@ class WiimoteBackend(Backend):
try:
self._wiimote.close()
except:
pass
except Exception as e:
self.logger.warning('Could not close Wiimote connection: {}'.format(str(e)))
self._wiimote = None
self.bus.post(WiimoteDisconnectionEvent())

View file

@ -232,10 +232,9 @@ class ZigbeeMqttBackend(MqttBackend):
if not data:
return
# noinspection PyBroadException
try:
data = json.loads(data)
except:
except (ValueError, TypeError):
pass
if topic == 'bridge/state':

View file

@ -57,7 +57,7 @@ class Cronjob(threading.Thread):
self.state = CronjobState.ERROR
def wait(self):
now = datetime.datetime.now().replace(tzinfo=gettz())
now = datetime.datetime.now().replace(tzinfo=gettz()) # lgtm [py/call-to-non-callable]
cron = croniter.croniter(self.cron_expression, now)
next_run = cron.get_next()
self._should_stop.wait(next_run - now.timestamp())

View file

@ -13,7 +13,7 @@ class EventGenerator(object):
logger = logging.getLogger('platypush')
def __init__(self, *args, **kwargs):
self._event_handlers = {} # Event type => callback map
self._event_handlers = {} # Event type => callback map
def fire_event(self, event):
"""
@ -25,8 +25,8 @@ class EventGenerator(object):
:type event: :class:`platypush.message.event.Event` or a subclass
"""
def hndl_thread():
hndl(event)
def hndl_thread(handler):
handler(event)
from platypush.backend import Backend
from platypush.context import get_bus
@ -44,8 +44,7 @@ class EventGenerator(object):
handlers.update(self._event_handlers[cls])
for hndl in handlers:
threading.Thread(target=hndl_thread).start()
threading.Thread(target=hndl_thread, args=(hndl,)).start()
def register_handler(self, event_type, callback):
"""
@ -64,7 +63,6 @@ class EventGenerator(object):
self._event_handlers[event_type] = set()
self._event_handlers[event_type].add(callback)
def unregister_handler(self, event_type, callback):
"""
Unregisters a callback handler from a camera event type.

View file

@ -61,7 +61,8 @@ class EventProcessor(object):
if hook.priority > max_priority:
priority_hooks = {hook}
elif hook.priority == max_priority and max_priority > 0:
max_priority = hook.priority
elif hook.priority == max_priority:
priority_hooks.add(hook)
matched_hooks.update(priority_hooks)

View file

@ -106,10 +106,9 @@ class Message(object):
if isinstance(msg, bytes) or isinstance(msg, bytearray):
msg = msg.decode('utf-8')
if isinstance(msg, str):
# noinspection PyBroadException
try:
msg = json.loads(msg.strip())
except:
except (ValueError, TypeError):
logger.warning('Invalid JSON message: {}'.format(msg))
assert isinstance(msg, dict)

View file

@ -1,5 +1,3 @@
import json
from platypush.message.event import Event

View file

@ -119,7 +119,6 @@ class Request(Message):
return event_args
# noinspection PyBroadException
@classmethod
def expand_value_from_context(cls, _value, **context):
for (k, v) in context.items():
@ -127,7 +126,8 @@ class Request(Message):
v = json.loads(str(v))
try:
exec('{}={}'.format(k, v))
except:
except Exception as e:
logger.debug(str(e))
if isinstance(v, str):
try:
exec('{}="{}"'.format(k, re.sub(r'(^|[^\\])"', '\1\\"', v)))
@ -171,7 +171,7 @@ class Request(Message):
try:
return json.loads(parsed_value)
except:
except (ValueError, TypeError):
return parsed_value
def _send_response(self, response):

View file

@ -40,10 +40,9 @@ class RectModel(Mapping):
class ResultModel(Mapping):
def __init__(self, result: Decoded, *args, **kwargs):
super().__init__(*args, **kwargs)
# noinspection PyBroadException
try:
data = result.data.decode()
except:
except (ValueError, TypeError):
data = base64.encodebytes(result.data).decode()
self.data = data

View file

@ -142,7 +142,7 @@ class AssistantGooglePushtotalkPlugin(AssistantPlugin):
)
)
audio_sink = audio_device = (
audio_sink = (
audio_device or audio_helpers.SoundDeviceStream(
sample_rate=self.audio_sample_rate,
sample_width=self.audio_sample_width,

View file

@ -1,8 +1,6 @@
import json
import requests
from platypush.config import Config
from platypush.message import Message
from platypush.plugins import Plugin, action
@ -22,7 +20,7 @@ class AutoremotePlugin(Plugin):
_AUTOREMOTE_MESSAGE_URL = _AUTOREMOTE_BASE_URL + '/sendmessage'
_AUTOREMOTE_NOTIFICATION_URL = _AUTOREMOTE_BASE_URL + '/sendnotification'
def __init__(self, devices=None, key=None, password=None, *args, **kwargs):
def __init__(self, devices=None, key=None, password=None, **kwargs):
"""
:param devices: Set this attribute if you want to control multiple AutoRemote devices.
This will be a map in the format::
@ -47,7 +45,7 @@ class AutoremotePlugin(Plugin):
:type password: str
"""
super().__init__(*args, **kwargs)
super().__init__(**kwargs)
if key:
self.devices = { key: { 'key': key, 'password': password } }

View file

@ -404,11 +404,10 @@ class CameraPlugin(Plugin, ABC):
frame_queue.put(None)
self.stop_preview(camera)
for output in camera.get_outputs():
# noinspection PyBroadException
try:
output.close()
except:
pass
except Exception as e:
self.logger.warning('Could not close camera output: {}'.format(str(e)))
self.close_device(camera, wait_capture=False)
frame_processor.join(timeout=5.0)

View file

@ -114,11 +114,10 @@ class StreamWriter(VideoWriter, ABC):
def close(self):
self.buffer.close()
if self.sock:
# noinspection PyBroadException
try:
self.sock.close()
except:
pass
except Exception as e:
self.logger.warning('Could not close camera resource: {}'.format(str(e)))
super().close()

View file

@ -24,12 +24,11 @@ class CvFileWriter(FileVideoWriter):
if not self.writer:
return
# noinspection PyBroadException
try:
if isinstance(img, ImageType):
# noinspection PyTypeChecker
img = np.array(img)
except:
except (ValueError, TypeError):
pass
self.writer.write(img)

View file

@ -78,7 +78,7 @@ class DbPlugin(Plugin):
engine = self._get_engine(engine, *args, **kwargs)
with engine.connect() as connection:
result = connection.execute(statement)
connection.execute(statement)
def _get_table(self, table, engine=None, *args, **kwargs):
if not engine:

View file

@ -188,11 +188,10 @@ class EspPlugin(Plugin):
def on_close(self, conn: Connection):
def callback(ws):
# noinspection PyBroadException
try:
ws.close()
except:
pass
except Exception as e:
self.logger.warning('Could not close connection: {}'.format(str(e)))
conn.on_close()
self.logger.info('Connection to {}:{} closed'.format(conn.host, conn.port))
@ -608,7 +607,8 @@ if {miso}:
self.execute(code, **kwargs)
@action
def i2c_open(self, scl: Optional[int] = None, sda: Optional[int] = None, id: int = -1, baudrate: int = 400000, **kwargs):
def i2c_open(self, scl: Optional[int] = None, sda: Optional[int] = None, id: int = -1, baudrate: int = 400000,
**kwargs):
"""
Open a connection to an I2C (or "two-wire") port.

View file

@ -150,11 +150,10 @@ class Connection:
self._echo_received.set()
def close(self):
# noinspection PyBroadException
try:
self.ws.close()
except:
pass
except Exception as e:
self.logger.warning('Could not close connection: {}'.format(str(e)))
self.on_close()
@ -243,6 +242,7 @@ class Connection:
chunk = self._downloaded_chunks.get(timeout=timeout)
except queue.Empty:
self.on_timeout('File download timed out')
break
if chunk is None:
break

View file

@ -19,7 +19,7 @@ class FilePlugin(Plugin):
def _to_string(cls, content):
try:
return json.dumps(content)
except:
except (ValueError, TypeError):
return str(content)
@action

View file

@ -2,9 +2,7 @@
.. moduleauthor:: Fabio Manganiello <blacklight86@gmail.com>
"""
import base64
import datetime
import os
from platypush.plugins import action
from platypush.plugins.google import GooglePlugin
@ -21,7 +19,6 @@ class GoogleCalendarPlugin(GooglePlugin, CalendarInterface):
def __init__(self, *args, **kwargs):
super().__init__(scopes=self.scopes, *args, **kwargs)
@action
def get_upcoming_events(self, max_results=10):
"""
@ -40,4 +37,3 @@ class GoogleCalendarPlugin(GooglePlugin, CalendarInterface):
# vim:sw=4:ts=4:et:

View file

@ -23,12 +23,12 @@ def get_credentials(scope):
credentials_file = get_credentials_filename(*sorted(scope.split(' ')))
if not os.path.exists(credentials_file):
raise RuntimeError(('Credentials file {} not found. Generate it through:\n' +
'\tpython -m platypush.plugins.google.credentials "{}" ' +
'<path to client_secret.json>\n' +
'\t\t[--auth_host_name AUTH_HOST_NAME]\n' +
'\t\t[--noauth_local_webserver]\n' +
'\t\t[--auth_host_port [AUTH_HOST_PORT [AUTH_HOST_PORT ...]]]\n' +
'\t\t[--logging_level [DEBUG,INFO,WARNING,ERROR,CRITICAL]]\n').
'\tpython -m platypush.plugins.google.credentials "{}" ' +
'<path to client_secret.json>\n' +
'\t\t[--auth_host_name AUTH_HOST_NAME]\n' +
'\t\t[--noauth_local_webserver]\n' +
'\t\t[--auth_host_port [AUTH_HOST_PORT [AUTH_HOST_PORT ...]]]\n' +
'\t\t[--logging_level [DEBUG,INFO,WARNING,ERROR,CRITICAL]]\n').
format(credentials_file, scope))
store = Storage(credentials_file)
@ -48,7 +48,7 @@ def generate_credentials(client_secret_path, scope):
flow.user_agent = 'Platypush'
flow.access_type = 'offline'
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
credentials = tools.run_flow(flow, store, flags)
tools.run_flow(flow, store, flags)
print('Storing credentials to ' + credentials_file)
@ -61,7 +61,7 @@ def main():
"""
scope = sys.argv.pop(1) if len(sys.argv) > 1 \
else input('Space separated list of OAuth scopes: ')
else input('Space separated list of OAuth scopes: ')
client_secret_path = os.path.expanduser(
sys.argv.pop(1) if len(sys.argv) > 1
@ -76,6 +76,4 @@ def main():
if __name__ == '__main__':
main()
# vim:sw=4:ts=4:et:

View file

@ -3,7 +3,6 @@
"""
import base64
import httplib2
import mimetypes
import os
@ -29,7 +28,6 @@ class GoogleMailPlugin(GooglePlugin):
def __init__(self, *args, **kwargs):
super().__init__(scopes=self.scopes, *args, **kwargs)
@action
def compose(self, sender, to, subject, body, files=None):
"""
@ -66,9 +64,11 @@ class GoogleMailPlugin(GooglePlugin):
content_type = 'application/octet-stream'
main_type, sub_type = content_type.split('/', 1)
with open(file, 'rb') as fp: content = fp.read()
with open(file, 'rb') as fp:
content = fp.read()
if main_type == 'text':
# noinspection PyUnresolvedReferences
msg = mimetypes.MIMEText(content, _subtype=sub_type)
elif main_type == 'image':
msg = MIMEImage(content, _subtype=sub_type)
@ -86,13 +86,12 @@ class GoogleMailPlugin(GooglePlugin):
message.attach(msg)
service = self.get_service('gmail', 'v1')
body = { 'raw': base64.urlsafe_b64encode(message.as_bytes()).decode() }
body = {'raw': base64.urlsafe_b64encode(message.as_bytes()).decode()}
message = (service.users().messages().send(
userId='me', body=body).execute())
return message
@action
def get_labels(self):
"""
@ -103,5 +102,4 @@ class GoogleMailPlugin(GooglePlugin):
labels = results.get('labels', [])
return labels
# vim:sw=4:ts=4:et:

View file

@ -2,7 +2,6 @@
.. moduleauthor:: Fabio Manganiello <blacklight86@gmail.com>
"""
import json
import requests
from platypush.plugins import action
@ -18,14 +17,14 @@ class GoogleMapsPlugin(GooglePlugin):
def __init__(self, api_key, *args, **kwargs):
"""
:param api_key: Server-side API key to be used for the requests, get one at https://console.developers.google.com
:param api_key: Server-side API key to be used for the requests, get one at
https://console.developers.google.com
:type api_key: str
"""
super().__init__(scopes=self.scopes, *args, **kwargs)
self.api_key = api_key
@action
def get_address_from_latlng(self, latitude, longitude):
"""
@ -39,7 +38,7 @@ class GoogleMapsPlugin(GooglePlugin):
"""
response = requests.get('https://maps.googleapis.com/maps/api/geocode/json',
params = {
params={
'latlng': '{},{}'.format(latitude, longitude),
'key': self.api_key,
}).json()
@ -54,7 +53,7 @@ class GoogleMapsPlugin(GooglePlugin):
if 'results' in response and response['results']:
result = response['results'][0]
self.logger.info('Google Maps geocode response for latlng ({},{}): {}'.
format(latitude, longitude, result))
format(latitude, longitude, result))
address['address'] = result['formatted_address'].split(',')[0]
for addr_component in result['address_components']:
@ -81,7 +80,7 @@ class GoogleMapsPlugin(GooglePlugin):
"""
response = requests.get('https://maps.googleapis.com/maps/api/elevation/json',
params = {
params={
'locations': '{},{}'.format(latitude, longitude),
'key': self.api_key,
}).json()
@ -91,8 +90,6 @@ class GoogleMapsPlugin(GooglePlugin):
if response.get('results'):
elevation = response['results'][0]['elevation']
return { 'elevation': elevation }
return {'elevation': elevation}
# vim:sw=4:ts=4:et:

View file

@ -78,8 +78,8 @@ class GpioSensorDistanceVl53L1XPlugin(GpioSensorPlugin):
try:
self._device.stop_ranging()
self._device.close()
except:
pass
except Exception as e:
self.logger.warning('Error while closing device: {}'.format(str(e)))
self._device = None
time.sleep(1)

View file

@ -12,7 +12,7 @@ class MCP3008Mode(enum.Enum):
class GpioSensorMcp3008Plugin(GpioSensorPlugin):
"""
Plugin to read analog sensor values from an MCP3008 chipset. The MCP3008
chipset is a circuit that allows you to read measuremnts from multiple
chipset is a circuit that allows you to read measurements from multiple
analog sources (e.g. sensors) and multiplex them to a digital device like a
Raspberry Pi or a regular laptop. See
https://learn.adafruit.com/raspberry-pi-analog-to-digital-converters/mcp3008
@ -25,8 +25,9 @@ class GpioSensorMcp3008Plugin(GpioSensorPlugin):
N_CHANNELS = 8
# noinspection PyPep8Naming
def __init__(self, CLK=None, MISO=None, MOSI=None, CS=None, spi_port=None,
spi_device=None, channels=None, Vdd=3.3, *args, **kwargs):
spi_device=None, channels=None, Vdd=3.3, **kwargs):
"""
The MCP3008 can be connected in two modes:
@ -54,8 +55,8 @@ class GpioSensorMcp3008Plugin(GpioSensorPlugin):
:param spi_device: (hardware SPI mode) SPI device name
:type spi_device: str
:param channels: name-value mapping between MCP3008 output PINs and sensor names. This mapping will be used when you get values through :func:`.get_measurement()`.
Example::
:param channels: name-value mapping between MCP3008 output PINs and sensor names. This mapping will be used
when you get values through :func:`.get_measurement()`. Example::
channels = {
"0": {
@ -83,7 +84,7 @@ class GpioSensorMcp3008Plugin(GpioSensorPlugin):
:type Vdd: float
"""
super().__init__(*args, **kwargs)
super().__init__(**kwargs)
if CLK and MISO and MOSI and CS:
self.CLK = CLK
@ -154,6 +155,7 @@ class GpioSensorMcp3008Plugin(GpioSensorPlugin):
if i in self.channels:
channel = self.channels[i]
if 'conv_function' in channel:
# noinspection PyUnusedLocal
x = value
value = eval(channel['conv_function'])

View file

@ -164,8 +164,9 @@ Warning, this new I?C address will still be used after resetting the power on th
print('Missing ZeroBorg at %02X' % oldAddress)
except KeyboardInterrupt:
raise
except:
except Exception as e:
foundChip = False
print(str(e))
print('Missing ZeroBorg at %02X' % oldAddress)
if foundChip:
bus.RawWrite(COMMAND_SET_I2C_ADD, [newAddress])
@ -188,8 +189,9 @@ Warning, this new I?C address will still be used after resetting the power on th
print('Missing ZeroBorg at %02X' % newAddress)
except KeyboardInterrupt:
raise
except:
except Exception as e:
foundChip = False
print(str(e))
print('Missing ZeroBorg at %02X' % newAddress)
if foundChip:
print('New I?C address of %02X set successfully' % newAddress)
@ -332,9 +334,9 @@ the current busNumber.
self.Print('Missing ZeroBorg at %02X' % self.i2cAddress)
except KeyboardInterrupt:
raise
except:
except Exception as e:
self.foundChip = False
self.Print('Missing ZeroBorg at %02X' % self.i2cAddress)
self.Print('Missing ZeroBorg at %02X: %s' % (self.i2cAddress, str(e)))
# See if we are missing chips
if not self.foundChip:
@ -383,8 +385,8 @@ SetMotor1(1) -> motor 1 moving forward at 100% power
self.RawWrite(command, [pwm])
except KeyboardInterrupt:
raise
except:
self.Print('Failed sending motor 1 drive level!')
except Exception as e:
self.Print('Failed sending motor 1 drive level! {}'.format(str(e)))
def GetMotor1(self):
"""
@ -402,8 +404,8 @@ e.g.
i2cRecv = self.RawRead(COMMAND_GET_A, I2C_NORM_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading motor 1 drive level!')
except Exception as e:
self.Print('Failed reading motor 1 drive level! {}'.format(str(e)))
return
power = float(i2cRecv[2]) / float(PWM_MAX)
@ -444,8 +446,8 @@ SetMotor2(1) -> motor 2 moving forward at 100% power
self.RawWrite(command, [pwm])
except KeyboardInterrupt:
raise
except:
self.Print('Failed sending motor 2 drive level!')
except Exception as e:
self.Print('Failed sending motor 2 drive level! {}'.format(str(e)))
def GetMotor2(self):
"""
@ -463,8 +465,8 @@ e.g.
i2cRecv = self.RawRead(COMMAND_GET_B, I2C_NORM_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading motor 2 drive level!')
except Exception as e:
self.Print('Failed reading motor 2 drive level! {}'.format(str(e)))
return
power = float(i2cRecv[2]) / float(PWM_MAX)
@ -505,8 +507,8 @@ SetMotor3(1) -> motor 3 moving forward at 100% power
self.RawWrite(command, [pwm])
except KeyboardInterrupt:
raise
except:
self.Print('Failed sending motor 3 drive level!')
except Exception as e:
self.Print('Failed sending motor 3 drive level! {}'.format(str(e)))
def GetMotor3(self):
"""
@ -524,8 +526,8 @@ e.g.
i2cRecv = self.RawRead(COMMAND_GET_C, I2C_NORM_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading motor 3 drive level!')
except Exception as e:
self.Print('Failed reading motor 3 drive level! {}'.format(str(e)))
return
power = float(i2cRecv[2]) / float(PWM_MAX)
@ -566,8 +568,8 @@ SetMotor4(1) -> motor 4 moving forward at 100% power
self.RawWrite(command, [pwm])
except KeyboardInterrupt:
raise
except:
self.Print('Failed sending motor 4 drive level!')
except Exception as e:
self.Print('Failed sending motor 4 drive level! {}'.format(str(e)))
def GetMotor4(self):
"""
@ -585,8 +587,8 @@ e.g.
i2cRecv = self.RawRead(COMMAND_GET_D, I2C_NORM_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading motor 4 drive level!')
except Exception as e:
self.Print('Failed reading motor 4 drive level! {}'.format(str(e)))
return
power = float(i2cRecv[2]) / float(PWM_MAX)
@ -627,8 +629,8 @@ SetMotors(1) -> all motors are moving forward at 100% power
self.RawWrite(command, [pwm])
except KeyboardInterrupt:
raise
except:
self.Print('Failed sending all motors drive level!')
except Exception as e:
self.Print('Failed sending all motors drive level! {}'.format(str(e)))
def MotorsOff(self):
"""
@ -641,8 +643,8 @@ Sets all motors to stopped, useful when ending a program
self.RawWrite(COMMAND_ALL_OFF, [0])
except KeyboardInterrupt:
raise
except:
self.Print('Failed sending motors off command!')
except Exception as e:
self.Print('Failed sending motors off command! {}'.format(str(e)))
def SetLed(self, state):
"""
@ -674,8 +676,8 @@ Reads the current state of the LED, False for off, True for on
i2cRecv = self.RawRead(COMMAND_GET_LED, I2C_NORM_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading LED state!')
except Exception as e:
self.Print('Failed reading LED state! {}'.format(str(e)))
return
if i2cRecv[1] == COMMAND_VALUE_OFF:
@ -694,8 +696,8 @@ Resets the EPO latch state, use to allow movement again after the EPO has been t
self.RawWrite(COMMAND_RESET_EPO, [0])
except KeyboardInterrupt:
raise
except:
self.Print('Failed resetting EPO!')
except Exception as e:
self.Print('Failed resetting EPO! {}'.format(str(e)))
def GetEpo(self):
"""
@ -711,8 +713,8 @@ If True the EPO has been tripped, movement is disabled if the EPO is not ignored
i2cRecv = self.RawRead(COMMAND_GET_EPO, I2C_NORM_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading EPO ignore state!')
except Exception as e:
self.Print('Failed reading EPO ignore state! {}'.format(str(e)))
return
if i2cRecv[1] == COMMAND_VALUE_OFF:
@ -736,8 +738,8 @@ Sets the system to ignore or use the EPO latch, set to False if you have an EPO
self.RawWrite(COMMAND_SET_EPO_IGNORE, [level])
except KeyboardInterrupt:
raise
except:
self.Print('Failed sending EPO ignore state!')
except Exception as e:
self.Print('Failed sending EPO ignore state! {}'.format(str(e)))
def GetEpoIgnore(self):
"""
@ -750,8 +752,8 @@ Reads the system EPO ignore state, False for using the EPO latch, True for ignor
i2cRecv = self.RawRead(COMMAND_GET_EPO_IGNORE, I2C_NORM_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading EPO ignore state!')
except Exception as e:
self.Print('Failed reading EPO ignore state! {}'.format(str(e)))
return
if i2cRecv[1] == COMMAND_VALUE_OFF:
@ -793,8 +795,8 @@ Use HasNewIrMessage() to see if there has been a new IR message since the last c
i2cRecv = self.RawRead(COMMAND_GET_LAST_IR, I2C_LONG_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading IR message!')
except Exception as e:
self.Print('Failed reading IR message! {}'.format(str(e)))
return
message = ''
@ -818,8 +820,8 @@ Sets if IR messages control the state of the LED, False for no effect, True for
self.RawWrite(COMMAND_SET_LED_IR, [level])
except KeyboardInterrupt:
raise
except:
self.Print('Failed sending LED state!')
except Exception as e:
self.Print('Failed sending LED state! {}'.format(str(e)))
def GetLedIr(self):
"""
@ -832,8 +834,8 @@ Reads if IR messages control the state of the LED, False for no effect, True for
i2cRecv = self.RawRead(COMMAND_GET_LED_IR, I2C_NORM_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading LED state!')
except Exception as e:
self.Print('Failed reading LED state! {}'.format(str(e)))
return
if i2cRecv[1] == COMMAND_VALUE_OFF:
@ -853,8 +855,8 @@ Returns the value as a voltage based on the 3.3 V reference pin (pin 1).
i2cRecv = self.RawRead(COMMAND_GET_ANALOG_1, I2C_NORM_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading analog level #1!')
except Exception as e:
self.Print('Failed reading analog level #1! {}'.format(str(e)))
return
raw = (i2cRecv[1] << 8) + i2cRecv[2]
@ -873,8 +875,8 @@ Returns the value as a voltage based on the 3.3 V reference pin (pin 1).
i2cRecv = self.RawRead(COMMAND_GET_ANALOG_2, I2C_NORM_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading analog level #2!')
except Exception as e:
self.Print('Failed reading analog level #2! {}'.format(str(e)))
return
raw = (i2cRecv[1] << 8) + i2cRecv[2]
@ -900,8 +902,8 @@ The failsafe is disabled at power on
self.RawWrite(COMMAND_SET_FAILSAFE, [level])
except KeyboardInterrupt:
raise
except:
self.Print('Failed sending communications failsafe state!')
except Exception as e:
self.Print('Failed sending communications failsafe state! {}'.format(str(e)))
def GetCommsFailsafe(self):
"""
@ -915,8 +917,8 @@ The failsafe will turn the motors off unless it is commanded at least once every
i2cRecv = self.RawRead(COMMAND_GET_FAILSAFE, I2C_NORM_LEN)
except KeyboardInterrupt:
raise
except:
self.Print('Failed reading communications failsafe state!')
except Exception as e:
self.Print('Failed reading communications failsafe state! {}'.format(str(e)))
return
if i2cRecv[1] == COMMAND_VALUE_OFF:
@ -930,6 +932,7 @@ Help()
Displays the names and descriptions of the various functions and settings provided
"""
# noinspection PyTypeChecker
funcList = [ZeroBorg.__dict__.get(a) for a in dir(ZeroBorg) if
isinstance(ZeroBorg.__dict__.get(a), types.FunctionType)]
funcListSorted = sorted(funcList, key=lambda x: x.func_code.co_firstlineno)

View file

@ -1,42 +0,0 @@
import datetime
import dateutil.parser
from platypush.plugins import action
from platypush.plugins.http.request import HttpRequestPlugin
class HttpRequestOtaBookingPlugin(HttpRequestPlugin):
""" Plugin to send requests to the Booking Hub API """
def __init__(self, hotel_id, token, timeout=5, **kwargs):
self.hotel_id = hotel_id
self.token = token
self.timeout = timeout
@action
def get_reservations(self, day='today'):
url = 'https://hub-api.booking.com/v1/hotels/{}/reservations' \
.format(self.hotel_id)
today = datetime.date.today().isoformat()
if day == 'today': day = today
headers = { 'X-Booking-Auth-Token': self.token }
params = { 'checkin': day }
response = self.get(url, headers=headers, params=params,
output='json', timeout=self.timeout)
reservations = [res for res in response.output
if res['status'] != 'CANCELLED']
response.output = {
'reservations': reservations,
'n_reservations': len(reservations),
}
return response
# vim:sw=4:ts=4:et:

View file

@ -24,14 +24,12 @@ class HttpWebpagePlugin(Plugin):
_mercury_script = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'mercury-parser.js')
def _parse(self, proc):
output = ''
@staticmethod
def _parse(proc):
with subprocess.Popen(proc, stdout=subprocess.PIPE, stderr=None) as parser:
output = parser.communicate()[0].decode()
return output
return parser.communicate()[0].decode()
# noinspection PyShadowingBuiltins
@action
def simplify(self, url, type='html', html=None, outfile=None):
"""
@ -124,15 +122,12 @@ class HttpWebpagePlugin(Plugin):
weasyprint.HTML(string=content).write_pdf(outfile, stylesheets=css)
else:
content = '''
<html>
content = '''<html>
<head>
<title>{title}</title>
<style>{style}</style>
</head>
<body>{{content}}</body>
</html>
'''.format(title=title, style=style, content=content)
</head>'''.format(title=title, style=style, content=content) + \
'<body>{{' + content + '}}</body></html>'
with open(outfile, 'w', encoding='utf-8') as f:
f.write(content)

View file

@ -188,10 +188,10 @@ class InspectPlugin(Plugin):
for _, modname, _ in pkgutil.walk_packages(path=package.__path__,
prefix=prefix,
onerror=lambda x: None):
# noinspection PyBroadException
try:
module = importlib.import_module(modname)
except:
except Exception as e:
self.logger.debug(f'Could not import module {modname}: {str(e)}')
continue
for _, obj in inspect.getmembers(module):
@ -207,10 +207,10 @@ class InspectPlugin(Plugin):
for _, modname, _ in pkgutil.walk_packages(path=package.__path__,
prefix=prefix,
onerror=lambda x: None):
# noinspection PyBroadException
try:
module = importlib.import_module(modname)
except:
except Exception as e:
self.logger.debug(f'Could not import module {modname}: {str(e)}')
continue
for _, obj in inspect.getmembers(module):
@ -226,10 +226,10 @@ class InspectPlugin(Plugin):
for _, modname, _ in pkgutil.walk_packages(path=package.__path__,
prefix=prefix,
onerror=lambda x: None):
# noinspection PyBroadException
try:
module = importlib.import_module(modname)
except:
except Exception as e:
self.logger.debug(f'Could not import module {modname}: {str(e)}')
continue
for _, obj in inspect.getmembers(module):
@ -250,10 +250,10 @@ class InspectPlugin(Plugin):
for _, modname, _ in pkgutil.walk_packages(path=package.__path__,
prefix=prefix,
onerror=lambda x: None):
# noinspection PyBroadException
try:
module = importlib.import_module(modname)
except:
except Exception as e:
self.logger.debug(f'Could not import module {modname}: {str(e)}')
continue
for _, obj in inspect.getmembers(module):

View file

@ -1,6 +1,5 @@
import json
import logging
import time
from platypush.context import get_backend
from platypush.plugins import Plugin, action
@ -19,10 +18,14 @@ class KafkaPlugin(Plugin):
* **kafka** (``pip install kafka-python``)
"""
def __init__(self, server=None, **kwargs):
def __init__(self, server=None, port=9092, **kwargs):
"""
:param server: Default Kafka server name or address + port (format: ``host:port``) to dispatch the messages to. If None (default), then it has to be specified upon message sending.
:param server: Default Kafka server name or address. If None (default), then it has to be specified upon
message sending.
:type server: str
:param port: Default Kafka server port (default: 9092).
:type port: int
"""
super().__init__(**kwargs)
@ -35,13 +38,17 @@ class KafkaPlugin(Plugin):
# Kafka can be veryyyy noisy
logging.getLogger('kafka').setLevel(logging.ERROR)
@action
def send_message(self, msg, topic, server=None, **kwargs):
def send_message(self, msg, topic, server=None):
"""
:param msg: Message to send - as a string, bytes stream, JSON, Platypush message, dictionary, or anything that implements ``__str__``
:param msg: Message to send - as a string, bytes stream, JSON, Platypush message, dictionary, or anything
that implements ``__str__``
:param server: Kafka server name or address + port (format: ``host:port``). If None, then the default server will be used
:param topic: Topic to send the message to.
:type topic: str
:param server: Kafka server name or address + port (format: ``host:port``). If None, then the default server
will be used
:type server: str
"""
@ -52,8 +59,8 @@ class KafkaPlugin(Plugin):
try:
kafka_backend = get_backend('kafka')
server = kafka_backend.server
except:
raise RuntimeError('No Kafka server nor default server specified')
except Exception as e:
raise RuntimeError(f'No Kafka server nor default server specified: {str(e)}')
else:
server = self.server
@ -67,4 +74,3 @@ class KafkaPlugin(Plugin):
# vim:sw=4:ts=4:et:

View file

@ -3,9 +3,9 @@ import functools
import os
import queue
import re
import requests
from typing import Optional, List, Dict, Union
import requests
import subprocess
import tempfile
import threading
@ -214,8 +214,8 @@ class MediaPlugin(Plugin):
try:
torrents = get_plugin(self.torrent_plugin)
torrents.quit()
except:
pass
except Exception as e:
self.logger.warning(f'Could not stop torrent plugin: {str(e)}')
@action
def play(self, resource, *args, **kwargs):
@ -423,7 +423,6 @@ class MediaPlugin(Plugin):
}
"""
import requests
http = get_backend('http')
if not http:
@ -445,8 +444,6 @@ class MediaPlugin(Plugin):
@action
def stop_streaming(self, media_id):
import requests
http = get_backend('http')
if not http:
self.logger.warning('Cannot unregister {}: HTTP backend unavailable'.
@ -536,9 +533,9 @@ class MediaPlugin(Plugin):
return functools.reduce(
lambda t, t_i: t + t_i,
[float(t) * pow(60, i) for (i, t) in enumerate(re.search(
'^Duration:\s*([^,]+)', [x.decode()
for x in result.stdout.readlines()
if "Duration" in x.decode()].pop().strip()
r'^Duration:\s*([^,]+)', [x.decode()
for x in result.stdout.readlines()
if "Duration" in x.decode()].pop().strip()
).group(1).split(':')[::-1])]
)

View file

@ -2,7 +2,7 @@ import datetime
import re
import time
from platypush.context import get_plugin, get_bus
from platypush.context import get_bus
from platypush.plugins import action
from platypush.plugins.media import MediaPlugin
from platypush.utils import get_mime_type
@ -91,6 +91,7 @@ class MediaChromecastPlugin(MediaPlugin):
post_event(MediaStopEvent, device=self.name)
if status.get('volume') != self.status.get('volume'):
post_event(MediaVolumeChangedEvent, volume=status.get('volume'), device=self.name)
# noinspection PyUnresolvedReferences
if abs(status.get('position') - self.status.get('position')) > time.time() - self.last_status_timestamp + 5:
post_event(MediaSeekEvent, position=status.get('position'), device=self.name)
@ -104,7 +105,7 @@ class MediaChromecastPlugin(MediaPlugin):
self.initialized = False
# pylint: disable=unused-argument
def new_media_status(self, status):
def new_media_status(self, *_):
if self.subtitle_id and not self.initialized:
self.mc.update_status()
self.mc.enable_subtitle(self.subtitle_id)
@ -327,9 +328,9 @@ class MediaChromecastPlugin(MediaPlugin):
@classmethod
def _get_youtube_url(cls, url):
m = re.match('https?://www.youtube.com/watch\?v=([^&]+).*', url)
m = re.match(r'https?://(www\.)?youtube\.com/watch\?v=([^&]+).*', url)
if m:
return m.group(1)
return m.group(2)
m = re.match('youtube:video:(.*)', url)
if m:

View file

@ -1,5 +1,4 @@
import json
import re
import threading
import time
@ -7,7 +6,7 @@ from platypush.context import get_bus
from platypush.plugins import action
from platypush.plugins.media import MediaPlugin, PlayerState
from platypush.message.event.media import MediaPlayEvent, MediaPauseEvent, MediaStopEvent, \
MediaSeekEvent, MediaVolumeChangedEvent, NewPlayingMediaEvent
MediaSeekEvent, MediaVolumeChangedEvent
# noinspection PyUnusedLocal
@ -602,7 +601,8 @@ class MediaKodiPlugin(MediaPlugin):
try:
kodi = self._get_kodi()
players = kodi.Player.GetActivePlayers().get('result', [])
except:
except Exception as e:
self.logger.debug(f'Could not get active players: {str(e)}')
return ret
ret['state'] = PlayerState.STOP.value

View file

@ -1,5 +1,4 @@
import enum
import math
import urllib.parse
from platypush.context import get_bus
@ -119,8 +118,8 @@ class MediaOmxplayerPlugin(MediaPlugin):
try:
try:
self._player.stop()
except:
pass
except Exception as e:
self.logger.warning(f'Could not stop player: {str(e)}')
self._player.quit()
except OMXPlayerDeadError:

View file

@ -3,9 +3,7 @@ import os
import re
import time
from sqlalchemy import create_engine, func, or_, Column, Integer, String, \
DateTime, PrimaryKeyConstraint, ForeignKey
from sqlalchemy import create_engine, Column, Integer, String, DateTime, PrimaryKeyConstraint, ForeignKey
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.sql.expression import func
@ -17,6 +15,7 @@ from platypush.plugins.media.search import MediaSearcher
Base = declarative_base()
Session = scoped_session(sessionmaker())
class LocalMediaSearcher(MediaSearcher):
"""
This class will search for media in the local configured directories. It
@ -29,7 +28,7 @@ class LocalMediaSearcher(MediaSearcher):
* **sqlalchemy** (``pip install sqlalchemy``)
"""
_filename_separators = '[.,_\-@()\[\]\{\}\s\'\"]+'
_filename_separators = r'[.,_\-@()\[\]\{\}\s\'\"]+'
def __init__(self, dirs, *args, **kwargs):
super().__init__()

View file

@ -97,8 +97,8 @@ class MediaWebtorrentPlugin(MediaPlugin):
if Config.get(plugin_name):
self._media_plugin = get_plugin(plugin_name)
break
except:
pass
except Exception as e:
self.logger.debug(f'Could not get media plugin {plugin_name}: {str(e)}')
if not self._media_plugin:
raise RuntimeError(('No media player specified and no ' +
@ -109,7 +109,7 @@ class MediaWebtorrentPlugin(MediaPlugin):
def _read_process_line(self):
line = self._webtorrent_process.stdout.readline().decode().strip()
# Strip output of the colors
return re.sub('\x1b\[(([0-9]+m)|(.{1,2}))', '', line).strip()
return re.sub(r'\x1b\[(([0-9]+m)|(.{1,2}))', '', line).strip()
def _process_monitor(self, resource, download_dir, download_only,
player_type, player_args):
@ -142,7 +142,7 @@ class MediaWebtorrentPlugin(MediaPlugin):
and state == TorrentState.IDLE:
# IDLE -> DOWNLOADING_METADATA
state = TorrentState.DOWNLOADING_METADATA
bus.post(TorrentDownloadedMetadataEvent(resource=resource))
bus.post(TorrentDownloadedMetadataEvent(url=webtorrent_url, resource=resource))
elif 'downloading: ' in line.lower() \
and media_file is None:
# Find video files in torrent directory
@ -177,10 +177,9 @@ class MediaWebtorrentPlugin(MediaPlugin):
if state.value <= TorrentState.DOWNLOADING_METADATA.value \
and media_file and webtorrent_url:
# DOWNLOADING_METADATA -> DOWNLOADING
state = TorrentState.DOWNLOADING
bus.post(TorrentDownloadStartEvent(
resource=resource, media_file=media_file,
stream_url=webtorrent_url))
stream_url=webtorrent_url, url=webtorrent_url))
break
if not output_dir:
@ -193,8 +192,11 @@ class MediaWebtorrentPlugin(MediaPlugin):
self.logger.warning('WebTorrent could not start streaming')
# Keep downloading but don't start the player
try: self._webtorrent_process.wait()
except: pass
try:
self._webtorrent_process.wait()
except Exception as e:
self.logger.warning(f'WebTorrent process error: {str(e)}')
return
player = None
@ -237,10 +239,14 @@ class MediaWebtorrentPlugin(MediaPlugin):
self.logger.info('Torrent player terminated')
bus.post(TorrentDownloadCompletedEvent(resource=resource,
output_dir=output_dir,
media_file=media_file))
media_file=media_file,
url=webtorrent_url))
try:
self.quit()
except Exception as e:
self.logger.warning(f'Could not terminate WebTorrent process: {str(e)}')
try: self.quit()
except: pass
self.logger.info('WebTorrent process terminated')
return _thread
@ -252,6 +258,7 @@ class MediaWebtorrentPlugin(MediaPlugin):
media_cls = player.__class__.__name__
if media_cls == 'MediaMplayerPlugin':
# noinspection PyProtectedMember
stop_evt = player._mplayer_stopped_event
elif media_cls == 'MediaMpvPlugin' or media_cls == 'MediaVlcPlugin':
stop_evt = threading.Event()
@ -359,8 +366,8 @@ class MediaWebtorrentPlugin(MediaPlugin):
stream_url = self._torrent_stream_urls.get(resource)
if not stream_url:
return (None, ('The webtorrent process hasn\'t started ' +
'streaming after {} seconds').format(
return (None, ("The webtorrent process hasn't started " +
"streaming after {} seconds").format(
self._web_stream_ready_timeout))
return {'resource': resource, 'url': stream_url}
@ -380,8 +387,10 @@ class MediaWebtorrentPlugin(MediaPlugin):
if self._is_process_alive():
self._webtorrent_process.terminate()
self._webtorrent_process.wait()
try: self._webtorrent_process.kill()
except: pass
try:
self._webtorrent_process.kill()
except Exception as e:
self.logger.warning(f'Error on WebTorrent process kill: {str(e)}')
self._webtorrent_process = None

View file

@ -173,11 +173,10 @@ class MqttPlugin(Plugin):
if isinstance(msg, (dict, list)):
msg = json.dumps(msg)
# noinspection PyBroadException
try:
msg = Message.build(json.loads(msg))
except:
pass
except Exception as e:
self.logger.debug(f'Not a valid JSON: {str(e)}')
host = host or self.host
port = port or self.port or 1883
@ -209,11 +208,10 @@ class MqttPlugin(Plugin):
response_buffer.close()
if client:
# noinspection PyBroadException
try:
client.loop_stop()
except:
pass
except Exception as e:
self.logger.warning(f'Could not stop client loop: {e}')
client.disconnect()

View file

@ -62,7 +62,8 @@ class MusicMpdPlugin(MusicPlugin):
time.sleep(0.5)
self.client = None
raise error
if error:
raise error
def _exec(self, method, *args, **kwargs):
error = None
@ -383,14 +384,14 @@ class MusicMpdPlugin(MusicPlugin):
if not resource:
return
m = re.search('^https://open.spotify.com/([^?]+)', resource)
m = re.search(r'^https?://open\.spotify\.com/([^?]+)', resource)
if m:
resource = 'spotify:{}'.format(m.group(1).replace('/', ':'))
if resource.startswith('spotify:'):
resource = resource.split('?')[0]
m = re.match('spotify:playlist:(.*)', resource)
m = re.match(r'spotify:playlist:(.*)', resource)
if m:
# Old Spotify URI format, convert it to new
resource = 'spotify:user:spotify:playlist:' + m.group(1)
@ -423,8 +424,8 @@ class MusicMpdPlugin(MusicPlugin):
"""
Seek to the specified position (DEPRECATED, use :meth:`.seek` instead).
:param value: Seek position in seconds, or delta string (e.g. '+15' or '-15') to indicate a seek relative to the current position
:type value: int
:param value: Seek position in seconds, or delta string (e.g. '+15' or '-15') to indicate a seek relative to
the current position :type value: int
"""
return self.seek(value)
@ -434,8 +435,8 @@ class MusicMpdPlugin(MusicPlugin):
"""
Seek to the specified position
:param position: Seek position in seconds, or delta string (e.g. '+15' or '-15') to indicate a seek relative to the current position
:type position: int
:param position: Seek position in seconds, or delta string (e.g. '+15' or '-15') to indicate a seek relative
to the current position :type position: int
"""
return self._exec('seekcur', position)
@ -486,7 +487,8 @@ class MusicMpdPlugin(MusicPlugin):
try:
n_tries -= 1
self._connect()
return self.client.status()
if self.client:
return self.client.status()
except Exception as e:
error = e
self.logger.warning('Exception while getting MPD status: {}'.
@ -523,7 +525,7 @@ class MusicMpdPlugin(MusicPlugin):
or not track['artist']
or re.search('^https?://', track['file'])
or re.search('^tunein:', track['file'])):
m = re.match('^\s*(.+?)\s+-\s+(.*)\s*$', track['title'])
m = re.match(r'^\s*(.+?)\s+-\s+(.*)\s*$', track['title'])
if m and m.group(1) and m.group(2):
track['artist'] = m.group(1)
track['title'] = m.group(2)
@ -781,10 +783,7 @@ class MusicMpdPlugin(MusicPlugin):
items = self._exec('search', *filter, *args, return_status=False, **kwargs)
# Spotify results first
items = sorted(items, key=lambda item:
0 if item['file'].startswith('spotify:') else 1)
return items
return sorted(items, key=lambda item: 0 if item['file'].startswith('spotify:') else 1)
# noinspection PyShadowingBuiltins
@action

View file

@ -96,6 +96,7 @@ class MusicSnapcastPlugin(Plugin):
'method': 'Server.GetStatus'
}
# noinspection PyTypeChecker
self._send(sock, request)
return (self._recv(sock) or {}).get('server', {})
@ -214,8 +215,8 @@ class MusicSnapcastPlugin(Plugin):
finally:
try:
sock.close()
except:
pass
except Exception as e:
self.logger.warning(f'Error on socket close: {e}')
@action
def mute(self, client=None, group=None, mute=None, host=None, port=None):
@ -266,13 +267,14 @@ class MusicSnapcastPlugin(Plugin):
request['params']['volume']['percent'] = client['config']['volume']['percent']
request['params']['volume']['muted'] = not cur_muted if mute is None else mute
# noinspection PyTypeChecker
self._send(sock, request)
return self._recv(sock)
finally:
try:
sock.close()
except:
pass
except Exception as e:
self.logger.warning('Error on socket close', e)
@action
def volume(self, client, volume=None, delta=None, mute=None, host=None,
@ -336,13 +338,14 @@ class MusicSnapcastPlugin(Plugin):
request['params']['volume'] = {}
request['params']['volume']['percent'] = volume
request['params']['volume']['muted'] = mute
# noinspection PyTypeChecker
self._send(sock, request)
return self._recv(sock)
finally:
try:
sock.close()
except:
pass
except Exception as e:
self.logger.warning('Error on socket close', e)
@action
def set_client_name(self, client, name, host=None, port=None):
@ -376,13 +379,14 @@ class MusicSnapcastPlugin(Plugin):
client = self._get_client(sock, client)
request['params']['id'] = client['id']
request['params']['name'] = name
# noinspection PyTypeChecker
self._send(sock, request)
return self._recv(sock)
finally:
try:
sock.close()
except:
pass
except Exception as e:
self.logger.warning('Error on socket close', e)
@action
def set_group_name(self, group, name, host=None, port=None):
@ -416,13 +420,14 @@ class MusicSnapcastPlugin(Plugin):
}
}
# noinspection PyTypeChecker
self._send(sock, request)
return self._recv(sock)
finally:
try:
sock.close()
except:
pass
except Exception as e:
self.logger.warning('Error on socket close', e)
@action
def set_latency(self, client, latency, host=None, port=None):
@ -457,13 +462,14 @@ class MusicSnapcastPlugin(Plugin):
client = self._get_client(sock, client)
request['params']['id'] = client['id']
# noinspection PyTypeChecker
self._send(sock, request)
return self._recv(sock)
finally:
try:
sock.close()
except:
pass
except Exception as e:
self.logger.warning('Error on socket close', e)
@action
def delete_client(self, client, host=None, port=None):
@ -493,13 +499,14 @@ class MusicSnapcastPlugin(Plugin):
client = self._get_client(sock, client)
request['params']['id'] = client['id']
# noinspection PyTypeChecker
self._send(sock, request)
return self._recv(sock)
finally:
try:
sock.close()
except:
pass
except Exception as e:
self.logger.warning('Error on socket close', e)
@action
def group_set_clients(self, group, clients, host=None, port=None):
@ -538,13 +545,14 @@ class MusicSnapcastPlugin(Plugin):
client = self._get_client(sock, client)
request['params']['clients'].append(client['id'])
# noinspection PyTypeChecker
self._send(sock, request)
return self._recv(sock)
finally:
try:
sock.close()
except:
pass
except Exception as e:
self.logger.warning('Error on socket close', e)
@action
def group_set_stream(self, group, stream_id, host=None, port=None):
@ -579,13 +587,14 @@ class MusicSnapcastPlugin(Plugin):
}
}
# noinspection PyTypeChecker
self._send(sock, request)
return self._recv(sock)
finally:
try:
sock.close()
except:
pass
except Exception as e:
self.logger.warning('Error on socket close', e)
@action
def get_backend_hosts(self):

View file

@ -1,6 +1,5 @@
import json
import os
from typing import Optional
import requests
@ -101,6 +100,7 @@ class PushbulletPlugin(Plugin):
kwargs['type'] = 'link' if url else 'note'
if device:
# noinspection PyTypeChecker
kwargs['device_iden'] = device['iden']
resp = requests.post('https://api.pushbullet.com/v2/pushes',
@ -143,6 +143,7 @@ class PushbulletPlugin(Plugin):
raise Exception('Pushbullet file upload failed with status {}'.
format(resp.status_code))
# noinspection PyTypeChecker
resp = requests.post('https://api.pushbullet.com/v2/pushes',
headers={'Authorization': 'Bearer ' + self.token,
'Content-Type': 'application/json'},

View file

@ -19,13 +19,12 @@ class RedisPlugin(Plugin):
self.kwargs = kwargs
if not kwargs:
# noinspection PyBroadException
try:
redis_backend = get_backend('redis')
if redis_backend and redis_backend.redis_args:
self.kwargs = redis_backend.redis_args
except:
pass
except Exception as e:
self.logger.debug(e)
def _get_redis(self):
return Redis(*self.args, **self.kwargs)

View file

@ -8,7 +8,6 @@ from platypush.plugins import action
from platypush.plugins.sensor import SensorPlugin
# noinspection PyBroadException
class SerialPlugin(SensorPlugin):
"""
The serial plugin can read data from a serial device, as long as the serial
@ -129,7 +128,8 @@ class SerialPlugin(SensorPlugin):
if serial_available:
try:
ser = self._get_serial(device=device, baud_rate=baud_rate)
except:
except Exception as e:
self.logger.debug(e)
time.sleep(1)
ser = self._get_serial(device=device, baud_rate=baud_rate, reset=True)
@ -137,16 +137,15 @@ class SerialPlugin(SensorPlugin):
try:
data = json.loads(data)
except:
self.logger.warning('Invalid JSON message from {}: {}'.
format(self.device, data))
except (ValueError, TypeError):
self.logger.warning('Invalid JSON message from {}: {}'.format(self.device, data))
else:
data = self.last_measurement
finally:
try:
self.serial_lock.release()
except:
pass
except Exception as e:
self.logger.debug(e)
if data:
self.last_measurement = data
@ -194,7 +193,8 @@ class SerialPlugin(SensorPlugin):
if serial_available:
try:
ser = self._get_serial(device=device, baud_rate=baud_rate)
except:
except Exception as e:
self.logger.debug(e)
time.sleep(1)
ser = self._get_serial(device=device, baud_rate=baud_rate, reset=True)
@ -216,12 +216,12 @@ class SerialPlugin(SensorPlugin):
finally:
try:
self.serial_lock.release()
except:
pass
except Exception as e:
self.logger.debug(e)
try:
data = data.decode()
except:
except (ValueError, TypeError):
data = base64.encodebytes(data)
return data
@ -261,7 +261,8 @@ class SerialPlugin(SensorPlugin):
if serial_available:
try:
ser = self._get_serial(device=device, baud_rate=baud_rate)
except:
except Exception as e:
self.logger.debug(e)
time.sleep(1)
ser = self._get_serial(device=device, baud_rate=baud_rate, reset=True)
@ -270,8 +271,8 @@ class SerialPlugin(SensorPlugin):
finally:
try:
self.serial_lock.release()
except:
pass
except Exception as e:
self.logger.debug(e)
# vim:sw=4:ts=4:et:

View file

@ -166,8 +166,7 @@ class SoundPlugin(Plugin):
is_raw_stream = streamtype == sd.RawOutputStream
# noinspection PyUnusedLocal
def audio_callback(outdata, frames, frame_time, status):
def audio_callback(outdata, frames, *, status):
if self._get_playback_state(stream_index) == PlaybackState.STOPPED:
raise sd.CallbackStop
@ -181,7 +180,7 @@ class SoundPlugin(Plugin):
if status.output_underflow:
self.logger.warning('Output underflow: increase blocksize?')
outdata = (b'\x00' if is_raw_stream else 0.) * len(outdata)
outdata[:] = (b'\x00' if is_raw_stream else 0.) * len(outdata)
return
if status:
@ -397,7 +396,6 @@ class SoundPlugin(Plugin):
finally:
if f and not f.closed:
f.close()
f = None
self.stop_playback([stream_index])

View file

@ -221,10 +221,9 @@ class SshPlugin(Plugin):
client = self._connect(**kwargs)
def decode(buf: bytes) -> str:
# noinspection PyBroadException
try:
buf = buf.decode()
except:
except (ValueError, TypeError):
buf = base64.encodebytes(buf).decode()
if buf.endswith('\n'):
@ -341,11 +340,10 @@ class SshPlugin(Plugin):
try:
if os.path.isdir(local_path):
# noinspection PyBroadException
try:
sftp.mkdir(remote_path)
except:
pass
except Exception as e:
self.logger.warning(f'mkdir {remote_path}: {e}')
assert recursive, '{} is a directory but recursive has been set to False'.format(local_path)
assert self.is_directory(sftp, remote_path), \
@ -355,11 +353,10 @@ class SshPlugin(Plugin):
os.chdir(local_path)
for path, folders, files in os.walk('.'):
# noinspection PyBroadException
try:
sftp.mkdir(path)
except:
pass
except Exception as e:
self.logger.warning(f'mkdir {remote_path}: {e}')
for file in files:
src = os.path.join(path, file)

View file

@ -47,12 +47,11 @@ def reverse_tunnel(server_port, remote_host, remote_port, transport, bind_addr='
should_run[key] = True
while should_run.get(key):
# noinspection PyBroadException
try:
chan = transport.accept(1)
if chan is None:
raise AssertionError
except:
assert chan is not None
except Exception as e:
logger.warning(e)
continue
thr = threading.Thread(

View file

@ -128,7 +128,6 @@ class SwitchSwitchbotPlugin(SwitchPlugin, BluetoothBlePlugin):
compatible_devices = {}
for dev in devices:
# noinspection PyBroadException
try:
characteristics = [
chrc for chrc in self.discover_characteristics(
@ -139,8 +138,8 @@ class SwitchSwitchbotPlugin(SwitchPlugin, BluetoothBlePlugin):
if characteristics:
compatible_devices[dev['addr']] = None
except:
pass
except Exception as e:
self.logger.warning('Device scan error', e)
return BluetoothScanResponse(devices=compatible_devices)

View file

@ -83,11 +83,10 @@ class TensorflowPlugin(Plugin):
assert success, 'Unable to acquire the model lock'
yield
finally:
# noinspection PyBroadException
try:
self._model_locks[model_name].release()
except:
pass
except Exception as e:
self.logger.info(f'Model {model_name} lock release error: {e}')
def _load_model(self, model_name: str, reload: bool = False) -> Model:
if model_name in self.models and not reload:

View file

@ -1,5 +1,5 @@
import requests
from typing import Callable, Dict, Any, List, Optional
from typing import Callable, Dict, Any, List
from platypush.plugins import Plugin, action

View file

@ -1,93 +0,0 @@
import json
import urllib3
import urllib.request
import urllib.parse
from platypush.plugins import Plugin, action
from platypush.plugins.media import PlayerState
class VideoTorrentcastPlugin(Plugin):
def __init__(self, server='localhost', port=9090, *args, **kwargs):
self.server = server
self.port = port
self.state = PlayerState.STOP.value
@action
def play(self, url):
request = urllib.request.urlopen(
'http://{}:{}/play/'.format(self.server, self.port),
data=urllib.parse.urlencode({
'url': url
}).encode()
)
self.state = PlayerState.PLAY.value
return request.read()
@action
def pause(self):
http = urllib3.PoolManager()
request = http.request('POST',
'http://{}:{}/pause/'.format(self.server, self.port))
self.state = PlayerState.PAUSE.value
return request.read()
@action
def stop(self):
http = urllib3.PoolManager()
request = http.request('POST',
'http://{}:{}/stop/'.format(self.server, self.port))
self.state = PlayerState.STOP.value
return request.read()
@action
def search(self, query):
request = urllib.request.urlopen(urllib.request.Request(
'https://api.apidomain.info/list?' + urllib.parse.urlencode({
'sort': 'relevance',
'quality': '720p,1080p,3d',
'page': 1,
'keywords': query,
}),
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 ' +
'(KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
})
)
results = json.loads(request.read())
return results
@action
def search_and_play(self, query):
response = self.search(query)
if not response.output['MovieList']:
self.logger.info('No torrent results found for {}'.format(query))
item = response.output['MovieList'][0]
magnet = item['items'][0]['torrent_magnet']
self.logger.info('Playing torrent "{}" from {}'
.format(item['title'], magnet))
return self.play(magnet)
@action
def voldown(self): raise NotImplementedError()
@action
def volup(self): raise NotImplementedError()
@action
def back(self): raise NotImplementedError()
@action
def forward(self): raise NotImplementedError()
@action
def status(self): return { 'state': self.state }
# vim:sw=4:ts=4:et:

View file

@ -3,8 +3,7 @@ import socket
import time
from typing import List, Dict, Any, Optional, Union
import zeroconf
from zeroconf import Zeroconf, ServiceInfo, ServiceBrowser
from zeroconf import Zeroconf, ServiceInfo, ServiceBrowser, ServiceListener, ZeroconfServiceTypes
from platypush.context import get_bus
from platypush.message.event.zeroconf import ZeroconfServiceAddedEvent, ZeroconfServiceRemovedEvent, \
@ -12,7 +11,7 @@ from platypush.message.event.zeroconf import ZeroconfServiceAddedEvent, Zeroconf
from platypush.plugins import Plugin, action
class ZeroconfListener(zeroconf.ServiceListener):
class ZeroconfListener(ServiceListener):
def __init__(self, evt_queue: queue.Queue):
super().__init__()
self.evt_queue = evt_queue
@ -79,7 +78,7 @@ class ZeroconfPlugin(Plugin):
:param timeout: Discovery timeout in seconds (default: 5).
:return: List of the services as strings.
"""
return list(zeroconf.ZeroconfServiceTypes.find(timeout=timeout))
return list(ZeroconfServiceTypes.find(timeout=timeout))
@action
def discover_service(self, service: Union[str, list], timeout: Optional[int] = 5) -> Dict[str, Any]:

View file

@ -125,9 +125,10 @@ class ZigbeeMqttPlugin(MqttPlugin, SwitchPlugin):
:param password: If the connection requires user authentication, specify the password (default: None)
"""
super().__init__(host=host, port=port, tls_certfile=tls_certfile, tls_keyfile=tls_keyfile,
tls_version=tls_version, tls_ciphers=tls_ciphers, username=username,
password=password, **kwargs)
SwitchPlugin.__init__(self)
MqttPlugin.__init__(self, host=host, port=port, tls_certfile=tls_certfile, tls_keyfile=tls_keyfile,
tls_version=tls_version, tls_ciphers=tls_ciphers, username=username,
password=password, **kwargs)
self.base_topic = base_topic
self.timeout = timeout

View file

@ -270,12 +270,12 @@ class ForProcedure(LoopProcedure):
self.iterable = iterable
def execute(self, _async=None, **context):
# noinspection PyBroadException
try:
iterable = eval(self.iterable)
assert hasattr(iterable, '__iter__'), 'Object of type {} is not iterable: {}'.\
format(type(iterable), iterable)
except:
except Exception as e:
logger.debug(f'Iterable {self.iterable} expansion error: {e}')
iterable = Request.expand_value_from_context(self.iterable, **context)
response = Response()
@ -334,10 +334,10 @@ class WhileProcedure(LoopProcedure):
@staticmethod
def _get_context(**context):
for (k, v) in context.items():
# noinspection PyBroadException
try:
context[k] = eval(v)
except:
except Exception as e:
logger.debug(f'Evaluation error for {v}: {e}')
if isinstance(v, str):
# noinspection PyBroadException
try:
@ -356,8 +356,8 @@ class WhileProcedure(LoopProcedure):
for k, v in context.items():
try:
exec('{}={}'.format(k, v))
except:
pass
except Exception as e:
logger.debug(f'Evaluation error: {k}={v}: {e}')
while True:
condition_true = eval(self.condition)
@ -386,8 +386,8 @@ class WhileProcedure(LoopProcedure):
for k, v in new_context.items():
try:
exec('{}={}'.format(k, v))
except:
pass
except Exception as e:
logger.debug(f'Evaluation error: {k}={v}: {e}')
return response
@ -453,7 +453,8 @@ class IfProcedure(Procedure):
for (k, v) in context.items():
try:
exec('{}={}'.format(k, v))
except:
except Exception as e:
logger.debug(f'Evaluation error: {k}={v}: {e}')
if isinstance(v, str):
try:
exec('{}="{}"'.format(k, re.sub(r'(^|[^\\])"', '\1\\"', v)))

View file

@ -169,14 +169,6 @@ class UserManager:
"""
session = self._get_db_session()
return session.query(User).join(UserSession).filter_by(session_token=session_token).first()
if not user:
return None
return {
'user_id': user.user_id,
'username': user.username,
'created_at': user.created_at,
}
def generate_jwt_token(self, username: str, password: str, expires_at: Optional[datetime.datetime] = None) -> str:
"""

Some files were not shown because too many files have changed in this diff Show more