Skip to content
Permalink
Browse files

Round out type coverage for server, parsers, and plugins

  • Loading branch information
lovett committed Dec 18, 2019
1 parent 7dab831 commit 3d897094f985cca63b62782db73706127d9d0e4b
Showing with 36 additions and 15 deletions.
  1. +2 −1 medley.py
  2. +28 −12 parsers/htmltext.py
  3. +1 −1 plugins/audio.py
  4. +4 −1 plugins/cache.py
  5. +1 −0 plugins/gcp_storage.py
@@ -13,6 +13,7 @@
import logging
import os
import os.path
import typing
import cherrypy
import sdnotify
import plugins.applog
@@ -93,7 +94,7 @@ def setup() -> None:
#
# Accept any environment variable that starts with "MEDLEY".
# Double underscores are used for systemd compatibilty.
environment_config = {
environment_config: typing.Dict[str, typing.Any] = {
key[8:].replace("__", "."): os.getenv(key)
for key in os.environ
if key.startswith("MEDLEY")
@@ -1,9 +1,12 @@
"""Extract the plain text of an HTML string."""

import typing
from html.parser import HTMLParser
from html.entities import name2codepoint
from collections import deque

ParserAttrs = typing.List[typing.Tuple[str, typing.Optional[str]]]


class Parser(HTMLParser): # pylint: disable=abstract-method
"""Convert an HTML document to plain text.
@@ -13,20 +16,24 @@ class Parser(HTMLParser): # pylint: disable=abstract-method
"""

stack = deque([], 50)
stack: typing.Deque[str] = deque([], 50)

always_ignored = ("br", "img")

blacklist = ()
blacklist: typing.Tuple[str, ...] = ()

whitelist = (
whitelist: typing.Tuple[str, ...] = (
"p", "span", "li", "div", "td", "a", "b",
"strong", "i", "em", "u", "font", "pre", "form"
)

result = []
result: typing.List[str] = []

def __init__(self, blacklist=(), whitelist=()):
def __init__(
self,
blacklist: typing.Tuple[str, ...] = (),
whitelist: typing.Tuple[str, ...] = ()
) -> None:
if blacklist:
self.blacklist = blacklist

@@ -35,7 +42,7 @@ def __init__(self, blacklist=(), whitelist=()):

super().__init__()

def parse(self, markup):
def parse(self, markup: str = '') -> str:
"""Parse an HTML string."""
self.result = []

@@ -47,7 +54,7 @@ def parse(self, markup):
self.feed(trimmed_markup)
return " ".join(self.result).strip()

def handle_starttag(self, tag, attrs):
def handle_starttag(self, tag: str, attrs: ParserAttrs) -> None:
"""Track the current tag."""

if tag in self.always_ignored:
@@ -56,8 +63,17 @@ def handle_starttag(self, tag, attrs):
if tag not in self.whitelist:
return

ids = tuple({attr[1] for attr in attrs if attr[0] == "id"})
classes = tuple({attr[1] for attr in attrs if attr[0] == "class"})
ids = typing.cast(
typing.Tuple[str, ...],
tuple(
{attr[1] for attr in attrs if attr[0] == "id"}
)
)

classes = typing.cast(
typing.Tuple[str, ...],
tuple({attr[1] for attr in attrs if attr[0] == "class"})
)

tag_name = tag
if ids:
@@ -67,7 +83,7 @@ def handle_starttag(self, tag, attrs):

self.stack.append(tag_name)

def handle_endtag(self, tag):
def handle_endtag(self, tag: str) -> None:
"""Track the current tag."""

if tag not in self.whitelist:
@@ -78,7 +94,7 @@ def handle_endtag(self, tag):
if popped_tag.startswith(tag):
break

def handle_data(self, data):
def handle_data(self, data: str) -> None:
"""Capture the text node for non-blacklisted tags."""

if not self.stack:
@@ -93,5 +109,5 @@ def handle_data(self, data):

self.result.append(data.strip())

def handle_entityref(self, name):
def handle_entityref(self, name: str) -> None:
self.result.append(chr(name2codepoint[name]))
@@ -44,7 +44,7 @@ def play_bytes(audio_bytes: bytes) -> None:
)

@staticmethod
def play_sound(keyword) -> None:
def play_sound(keyword: str) -> None:
"""Play an audio file specified as a keyword.
Keywords correspond to filenames under apps/shared/static/wav.
@@ -52,7 +52,10 @@ def keysplit(key: str) -> typing.Tuple[str, str]:
"""Break a key into two parts."""

if ":" in key:
return tuple(key.split(":", 1))
return typing.cast(
typing.Tuple[str, str],
tuple(key.split(":", 1))
)

return ("_", key)

@@ -10,6 +10,7 @@
from google.cloud import storage
from google.oauth2.service_account import Credentials
import google.api_core.exceptions
import google.auth.exceptions
from . import decorators


0 comments on commit 3d89709

Please sign in to comment.
You can’t perform that action at this time.