Add linting for autopep8

This commit is contained in:
Matthew Stratford 2021-09-11 17:18:35 +01:00
parent 2941d90f60
commit e5e3267e75
10 changed files with 145 additions and 91 deletions

View file

@ -0,0 +1,3 @@
flake8
black
autopep8

View file

@ -1,4 +1,4 @@
autopep8
wheel
pygame==2.0.1
sanic==21.3.4
sanic-Cors==1.0.0

View file

@ -41,7 +41,7 @@ class FileManager:
while not terminator.terminate:
# If all channels have received the delete command, reset for the next one.
if (
self.channel_received == None
self.channel_received is None
or self.channel_received == [True] * self.channel_count
):
self.channel_received = [False] * self.channel_count
@ -60,18 +60,22 @@ class FileManager:
if command == "GETPLAN":
if (
self.channel_received != [False] * self.channel_count
self.channel_received != [
False] * self.channel_count
and self.channel_received[channel] != True
):
# We've already received a delete trigger on a channel, let's not delete the folder more than once.
# If the channel was already in the process of being deleted, the user has requested it again, so allow it.
# If the channel was already in the process of being deleted, the user has
# requested it again, so allow it.
self.channel_received[channel] = True
continue
# Delete the previous show files!
# Note: The players load into RAM. If something is playing over the load, the source file can still be deleted.
path: str = resolve_external_file_path("/music-tmp/")
# Note: The players load into RAM. If something is playing over the load,
# the source file can still be deleted.
path: str = resolve_external_file_path(
"/music-tmp/")
if not os.path.isdir(path):
self.logger.log.warning(
@ -102,7 +106,8 @@ class FileManager:
)
continue
self.channel_received[channel] = True
self.known_channels_preloaded = [False] * self.channel_count
self.known_channels_preloaded = [
False] * self.channel_count
self.known_channels_normalised = [
False
] * self.channel_count
@ -142,7 +147,8 @@ class FileManager:
sleep(0.2)
except Exception as e:
self.logger.log.exception("Received unexpected exception: {}".format(e))
self.logger.log.exception(
"Received unexpected exception: {}".format(e))
del self.logger
# Attempt to preload a file onto disk.
@ -169,7 +175,8 @@ class FileManager:
)
)
# Getting the file name will only pull the new file if the file doesn't already exist, so this is not too inefficient.
# Getting the file name will only pull the new file if the file doesn't
# already exist, so this is not too inefficient.
item_obj.filename, did_download = sync(
self.api.get_filename(item_obj, True)
)
@ -181,7 +188,8 @@ class FileManager:
if did_download:
downloaded_something = True
self.logger.log.info(
"File successfully preloaded: {}".format(item_obj.filename)
"File successfully preloaded: {}".format(
item_obj.filename)
)
break
else:
@ -189,7 +197,8 @@ class FileManager:
# Let's try the next one.
continue
# Tell the file manager that this channel is fully downloaded, this is so it can consider normalising once all channels have files.
# Tell the file manager that this channel is fully downloaded, this is so
# it can consider normalising once all channels have files.
self.known_channels_preloaded[channel] = not downloaded_something
self.next_channel_preload += 1
@ -241,7 +250,8 @@ class FileManager:
normalised_something = True
break # Now go let another channel have a go.
except Exception as e:
self.logger.log.exception("Failed to generate normalised file.", str(e))
self.logger.log.exception(
"Failed to generate normalised file.", str(e))
continue
self.known_channels_normalised[channel] = not normalised_something

View file

@ -39,7 +39,8 @@ def startServer(notifications=False):
# Catch the handler being killed externally.
except Exception as e:
printer("Received Exception {} with args: {}".format(type(e).__name__, e.args))
printer("Received Exception {} with args: {}".format(
type(e).__name__, e.args))
if server and server.is_alive():
server.terminate()
server.join()

View file

@ -12,7 +12,8 @@
"presenter-install": "cd presenter && git submodule update --init && yarn --network-timeout 100000",
"presenter-make": "npm run presenter-install && (rm -r presenter-build || true) && cd presenter && yarn build-baps && cp -r build ../presenter-build && cd ../ && npm install",
"test": "echo \"Error: no test specified\" && exit 1",
"presenter-start": "cd presenter && yarn start"
"presenter-start": "cd presenter && yarn start",
"lint": "autopep8 -r ./*.py -a -a --ignore E402,E226,E24,W50,W690 --max-line-length 127 --in-place"
},
"repository": {
"type": "git",

125
player.py
View file

@ -20,29 +20,28 @@
# that we respond with something, FAIL or OKAY. The server doesn't like to be kept waiting.
# Stop the Pygame Hello message.
import package
from baps_types.marker import Marker
from baps_types.plan import PlanItem
from helpers.logging_manager import LoggingManager
from helpers.state_manager import StateManager
from helpers.myradio_api import MyRadioAPI
from helpers.normalisation import get_normalised_filename_if_available
from threading import Timer
from syncer import sync
from mutagen.mp3 import MP3
from pygame import mixer
from typing import Any, Callable, Dict, List, Optional
import time
import json
import copy
import setproctitle
import multiprocessing
from queue import Empty
import os
os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "hide"
from queue import Empty
import multiprocessing
import setproctitle
import copy
import json
import time
from typing import Any, Callable, Dict, List, Optional
from pygame import mixer
from mutagen.mp3 import MP3
from syncer import sync
from threading import Timer
from helpers.normalisation import get_normalised_filename_if_available
from helpers.myradio_api import MyRadioAPI
from helpers.state_manager import StateManager
from helpers.logging_manager import LoggingManager
from baps_types.plan import PlanItem
from baps_types.marker import Marker
import package
# TODO ENUM
VALID_MESSAGE_SOURCES = ["WEBSOCKET", "UI", "CONTROLLER", "TEST", "ALL"]
@ -329,25 +328,28 @@ class Player:
# Right. So this may be confusing.
# So... If the user has just moved the loaded item in the channel (by removing above and readding)
# Then we want to re-associate the loaded_item object reference with the new one.
# The loaded item object before this change is now an ophan, which was kept around while the loaded item was potentially moved to another channel.
# The loaded item object before this change is now an ophan, which was
# kept around while the loaded item was potentially moved to another
# channel.
if loaded_item.timeslotitemid == new_item_obj.timeslotitemid:
self.state.update("loaded_item", new_item_obj)
# NOPE NOPE NOPE
# THIS IS AN EXAMPLE OF WHAT NOT TO DO!
# ONCE AGAIN, THE LOADED ITEM IS THE SAME OBJECT INSTANCE AS THE ONE IN THE SHOW PLAN (AS LONG AS IT HASN'T BEEN RE/MOVED)
# ONCE AGAIN, THE LOADED ITEM IS THE SAME OBJECT INSTANCE AS THE ONE IN
# THE SHOW PLAN (AS LONG AS IT HASN'T BEEN RE/MOVED)
## loaded_item.weight = new_item_obj.weight
# loaded_item.weight = new_item_obj.weight
# Bump the loaded_item's weight if we just added a new item above it.
##elif loaded_item.weight >= new_item_obj.weight:
## loaded_item.weight += 1
# elif loaded_item.weight >= new_item_obj.weight:
# loaded_item.weight += 1
# Else, new weight stays the same.
##else:
## return True
# else:
# return True
##self.state.update("loaded_item", loaded_item)
# self.state.update("loaded_item", loaded_item)
return True
@ -422,12 +424,14 @@ class Player:
break
if loaded_item is None:
self.logger.log.error("Failed to find weight: {}".format(weight))
self.logger.log.error(
"Failed to find weight: {}".format(weight))
return False
reload = False
if loaded_item.filename == "" or loaded_item.filename is None:
self.logger.log.info("Filename is not specified, loading from API.")
self.logger.log.info(
"Filename is not specified, loading from API.")
reload = True
elif not os.path.exists(loaded_item.filename):
self.logger.log.warn(
@ -436,7 +440,8 @@ class Player:
reload = True
if reload:
loaded_item.filename = sync(self.api.get_filename(item=loaded_item))
loaded_item.filename = sync(
self.api.get_filename(item=loaded_item))
if not loaded_item.filename:
return False
@ -462,7 +467,8 @@ class Player:
while load_attempt < 5:
load_attempt += 1
try:
self.logger.log.info("Loading file: " + str(loaded_item.filename))
self.logger.log.info(
"Loading file: " + str(loaded_item.filename))
mixer.music.load(loaded_item.filename)
except Exception:
# We couldn't load that file.
@ -487,10 +493,12 @@ class Player:
# WARNING! Pygame / SDL can't seek .wav files :/
self.state.update(
"length",
mixer.Sound(loaded_item.filename).get_length() / 1000,
mixer.Sound(
loaded_item.filename).get_length() / 1000,
)
except Exception:
self.logger.log.exception("Failed to update the length of item.")
self.logger.log.exception(
"Failed to update the length of item.")
time.sleep(1)
continue # Try loading again.
@ -505,7 +513,8 @@ class Player:
return True
self.logger.log.error("Failed to load track after numerous retries.")
self.logger.log.error(
"Failed to load track after numerous retries.")
return False
return False
@ -610,7 +619,8 @@ class Player:
if set_loaded:
try:
self.state.update(
"loaded_item", self.state.get()["loaded_item"].set_marker(marker)
"loaded_item", self.state.get(
)["loaded_item"].set_marker(marker)
)
except Exception as e:
self.logger.log.error(
@ -677,7 +687,8 @@ class Player:
def _potentially_end_tracklist(self):
if self.tracklist_start_timer:
self.logger.log.info("A tracklist start timer was running, cancelling.")
self.logger.log.info(
"A tracklist start timer was running, cancelling.")
self.tracklist_start_timer.cancel()
self.tracklist_start_timer = None
@ -708,7 +719,8 @@ class Player:
return
self.state.update("tracklist_id", None)
# This threads it, so it won't hang track loading if it fails.
self.tracklist_end_timer = Timer(1, self._tracklist_end, [tracklist_id])
self.tracklist_end_timer = Timer(
1, self._tracklist_end, [tracklist_id])
self.tracklist_end_timer.start()
else:
self.logger.log.warning(
@ -731,7 +743,8 @@ class Player:
tracklist_id = state["tracklist_id"]
if not tracklist_id:
if state["tracklist_mode"] == "fader-live" and not state["live"]:
self.logger.log.info("Not tracklisting since fader is not live.")
self.logger.log.info(
"Not tracklisting since fader is not live.")
else:
self.logger.log.info(
"Tracklisting item: '{}'".format(loaded_item.name)
@ -742,7 +755,8 @@ class Player:
"Failed to tracklist '{}'".format(loaded_item.name)
)
else:
self.logger.log.info("Tracklist id: '{}'".format(tracklist_id))
self.logger.log.info(
"Tracklist id: '{}'".format(tracklist_id))
self.state.update("tracklist_id", tracklist_id)
else:
self.logger.log.info(
@ -857,7 +871,8 @@ class Player:
self.state.update(
"remaining",
max(0, (self.state.get()["length"] - self.state.get()["pos_true"])),
max(0, (self.state.get()["length"] -
self.state.get()["pos_true"])),
)
def _ping_times(self):
@ -904,7 +919,8 @@ class Player:
def _send_status(self):
# TODO This is hacky
self._retMsg(str(self.status), okay_str=True, custom_prefix="ALL:STATUS:")
self._retMsg(str(self.status), okay_str=True,
custom_prefix="ALL:STATUS:")
def _fix_and_update_weights(self, plan):
def _sort_weight(e: PlanItem):
@ -949,7 +965,8 @@ class Player:
self.running = True
self.out_q = out_q
self.logger = LoggingManager("Player" + str(channel), debug=package.build_beta)
self.logger = LoggingManager(
"Player" + str(channel), debug=package.build_beta)
self.api = MyRadioAPI(self.logger, server_state)
@ -963,7 +980,8 @@ class Player:
self.state.add_callback(self._send_status)
self.state.update("channel", channel)
self.state.update("tracklist_mode", server_state.get()["tracklist_mode"])
self.state.update("tracklist_mode", server_state.get()[
"tracklist_mode"])
self.state.update(
"live", True
) # Channel is live until controller says it isn't.
@ -975,7 +993,8 @@ class Player:
loaded_state = copy.copy(self.state.state)
if loaded_state["output"]:
self.logger.log.info("Setting output to: " + str(loaded_state["output"]))
self.logger.log.info("Setting output to: " +
str(loaded_state["output"]))
self.output(loaded_state["output"])
else:
self.logger.log.info("Using default output device.")
@ -996,7 +1015,8 @@ class Player:
if loaded_state["playing"] is True:
self.logger.log.info("Resuming playback on init.")
self.unpause() # Use un-pause as we don't want to jump to a new position.
# Use un-pause as we don't want to jump to a new position.
self.unpause()
else:
self.logger.log.info("No file was previously loaded to resume.")
@ -1012,7 +1032,8 @@ class Player:
self.last_msg_source = ""
self.last_msg = ""
self.logger.log.warn(
"Message from unknown sender source: {}".format(source)
"Message from unknown sender source: {}".format(
source)
)
continue
@ -1080,11 +1101,13 @@ class Player:
"UNLOAD": lambda: self._retMsg(self.unload()),
"ADD": lambda: self._retMsg(
self.add_to_plan(
json.loads(":".join(self.last_msg.split(":")[1:]))
json.loads(
":".join(self.last_msg.split(":")[1:]))
)
),
"REMOVE": lambda: self._retMsg(
self.remove_from_plan(int(self.last_msg.split(":")[1]))
self.remove_from_plan(
int(self.last_msg.split(":")[1]))
),
"CLEAR": lambda: self._retMsg(self.clear_channel_plan()),
"SETMARKER": lambda: self._retMsg(
@ -1105,7 +1128,8 @@ class Player:
)
),
"SETLIVE": lambda: self._retMsg(
self.set_live(self.last_msg.split(":")[1] == "True")
self.set_live(
self.last_msg.split(":")[1] == "True")
),
}
@ -1134,7 +1158,8 @@ class Player:
except SystemExit:
self.logger.log.info("Received SystemExit")
except Exception as e:
self.logger.log.exception("Received unexpected Exception: {}".format(e))
self.logger.log.exception(
"Received unexpected Exception: {}".format(e))
self.logger.log.info("Quiting player " + str(channel))
self.quit()

View file

@ -47,6 +47,7 @@ class PlayerHandler:
sleep(0.02)
except Exception as e:
self.logger.log.exception("Received unexpected exception: {}".format(e))
self.logger.log.exception(
"Received unexpected exception: {}".format(e))
del self.logger
_exit(0)

View file

@ -22,15 +22,12 @@ import json
from setproctitle import setproctitle
import psutil
from helpers.os_environment import isBundelled, isMacOS
from helpers.os_environment import isMacOS
if not isMacOS():
# Rip, this doesn't like threading on MacOS.
import pyttsx3
if isBundelled():
import build
import package
from typing import Dict, List
from helpers.state_manager import StateManager
@ -111,7 +108,8 @@ class BAPSicleServer:
log_function = self.logger.log.info
while (
not terminator.terminate and self.state.get()["running_state"] == "running"
not terminator.terminate and self.state.get()[
"running_state"] == "running"
):
for channel in range(self.state.get()["num_channels"]):
@ -122,7 +120,8 @@ class BAPSicleServer:
or not self.player[channel].is_alive()
or not psutil.pid_exists(self.player[channel].pid)
):
log_function("Player {} not running, (re)starting.".format(channel))
log_function(
"Player {} not running, (re)starting.".format(channel))
self.player[channel] = multiprocessing.Process(
target=player.Player,
args=(
@ -183,7 +182,8 @@ class BAPSicleServer:
):
log_function("Webserver not running, (re)starting.")
self.webserver = multiprocessing.Process(
target=WebServer, args=(self.player_to_q, self.ui_to_q, self.state)
target=WebServer, args=(
self.player_to_q, self.ui_to_q, self.state)
)
self.webserver.start()
@ -320,7 +320,8 @@ class BAPSicleServer:
self.player_handler.join(timeout=PROCESS_KILL_TIMEOUT_S)
del self.player_handler
# Now we've stopped everything else, now is the time to stop the players. This is to keep playing for as long as possible during a restart.
# Now we've stopped everything else, now is the time to stop the players.
# This is to keep playing for as long as possible during a restart.
print("Stopping Players")
for q in self.player_to_q:
q.put("ALL:QUIT")

View file

@ -1,4 +1,4 @@
from sanic import Sanic, log
from sanic import Sanic
from sanic.exceptions import NotFound, abort
from sanic.response import html, file, redirect
from sanic.response import json as resp_json
@ -131,7 +131,8 @@ def ui_status(request):
for i in range(server_state.get()["num_channels"]):
channel_states.append(status(i))
data = {"channels": channel_states, "ui_page": "status", "ui_title": "Status"}
data = {"channels": channel_states,
"ui_page": "status", "ui_title": "Status"}
return render_template("status.html", data=data)
@ -175,16 +176,20 @@ def ui_config_server_update(request):
server_state.update("ws_port", int(request.form.get("ws_port")))
serial_port = request.form.get("serial_port")
server_state.update("serial_port", None if serial_port == "None" else serial_port)
server_state.update("serial_port", None if serial_port ==
"None" else serial_port)
# Because we're not showing the api key once it's set.
if "myradio_api_key" in request.form and request.form.get("myradio_api_key") != "":
server_state.update("myradio_api_key", request.form.get("myradio_api_key"))
server_state.update("myradio_api_key",
request.form.get("myradio_api_key"))
server_state.update("myradio_base_url", request.form.get("myradio_base_url"))
server_state.update("myradio_base_url",
request.form.get("myradio_base_url"))
server_state.update("myradio_api_url", request.form.get("myradio_api_url"))
server_state.update(
"myradio_api_tracklist_source", request.form.get("myradio_api_tracklist_source")
"myradio_api_tracklist_source", request.form.get(
"myradio_api_tracklist_source")
)
server_state.update("tracklist_mode", request.form.get("tracklist_mode"))
@ -195,9 +200,9 @@ def ui_config_server_update(request):
def ui_logs_list(request):
files = os.listdir(resolve_external_file_path("/logs"))
log_files = []
for file in files:
if file.endswith(".log"):
log_files.append(file.rstrip(".log"))
for file_name in files:
if file_name.endswith(".log"):
log_files.append(file_name.rstrip(".log"))
log_files.sort()
data = {"ui_page": "logs", "ui_title": "Logs", "logs": log_files}
@ -215,7 +220,7 @@ def ui_logs_render(request, path):
log_file = open(resolve_external_file_path("/logs/{}.log").format(path))
data = {
"logs": log_file.read().splitlines()[
-300 * page : (-300 * (page - 1) if page > 1 else None)
-300 * page:(-300 * (page - 1) if page > 1 else None)
][::-1],
"ui_page": "logs",
"ui_title": "Logs - {}".format(path),
@ -380,7 +385,8 @@ def json_status(request):
async def audio_file(request, type: str, id: int):
if type not in ["managed", "track"]:
abort(404)
filename = resolve_external_file_path("music-tmp/{}-{}.mp3".format(type, id))
filename = resolve_external_file_path(
"music-tmp/{}-{}.mp3".format(type, id))
# Swap with a normalised version if it's ready, else returns original.
filename = get_normalised_filename_if_available(filename)
@ -411,7 +417,8 @@ app.static(
def status(channel: int):
while not player_from_q[channel].empty():
player_from_q[channel].get() # Just waste any previous status responses.
# Just waste any previous status responses.
player_from_q[channel].get()
player_to_q[channel].put("UI:STATUS")
retries = 0
@ -421,7 +428,7 @@ def status(channel: int):
if response.startswith("UI:STATUS:"):
response = response.split(":", 2)[2]
# TODO: Handle OKAY / FAIL
response = response[response.index(":") + 1 :]
response = response[response.index(":") + 1:]
try:
response = json.loads(response)
except Exception as e:

View file

@ -71,7 +71,8 @@ class WebsocketServer:
for channel in self.channel_to_q:
channel.put("WEBSOCKET:STATUS")
self.from_webstudio = asyncio.create_task(self.handle_from_webstudio(websocket))
self.from_webstudio = asyncio.create_task(
self.handle_from_webstudio(websocket))
try:
self.threads = await shield(asyncio.gather(self.from_webstudio))
@ -93,7 +94,8 @@ class WebsocketServer:
await asyncio.wait([conn.send(message) for conn in self.baps_clients])
except websockets.exceptions.ConnectionClosedError as e:
self.logger.log.error("Client Disconncted {}, {}".format(websocket, e))
self.logger.log.error(
"Client Disconncted {}, {}".format(websocket, e))
except Exception as e:
self.logger.log.exception(
@ -176,13 +178,15 @@ class WebsocketServer:
except ValueError as e:
self.logger.log.exception(
"Error decoding extra data {} for command {} ".format(e, command)
"Error decoding extra data {} for command {} ".format(
e, command)
)
pass
# Stick the message together and send!
message += (
command # Put the command in at the end, in case MOVE etc changed it.
# Put the command in at the end, in case MOVE etc changed it.
command
)
if extra != "":
message += ":" + extra
@ -197,7 +201,8 @@ class WebsocketServer:
)
else:
self.logger.log.error("Command missing from message. Data: {}".format(data))
self.logger.log.error(
"Command missing from message. Data: {}".format(data))
async def handle_to_webstudio(self):