Skip to content
Permalink
Browse files

Add mypy and start adding type hints

As a first step, go back to definining exposed and user_facing in all
app controllers rather than using importlib in the server to set
defaults. This is more repetitive, but sidesteps some typing
complications. Although importlib was valued at the time it was
implemented for cutting down on repetition, I'm more interested in
having things be more obvious and less magical.
  • Loading branch information
lovett committed Oct 17, 2019
1 parent 9cbbe87 commit 30b38a6c5c5c3cc2e085a209942861ce5bfc65fb
@@ -24,3 +24,4 @@ venv
cache
node_modules
.pytest_cache
.mypy_cache
@@ -7,6 +7,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "App Log"
exposed = True
user_facing = True

@staticmethod
@cherrypy.tools.negotiable()
@@ -6,6 +6,7 @@
class Controller:
"""Dispatch application requests based on HTTP verb."""

exposed = True
user_facing = False

@staticmethod
@@ -7,6 +7,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Bookmarklets"
exposed = True
user_facing = True

@staticmethod
@cherrypy.tools.negotiable()
@@ -7,6 +7,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Bookmarks"
exposed = True
user_facing = True

@staticmethod
def check_wayback_availability(url):
@@ -8,6 +8,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Bounce"
exposed = True
user_facing = True

common_names = {
"dev",
@@ -7,6 +7,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Calls"
exposed = True
user_facing = True

@staticmethod
@cherrypy.tools.negotiable()
@@ -7,6 +7,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Captures"
exposed = True
user_facing = True

@staticmethod
@cherrypy.tools.negotiable()
@@ -6,6 +6,8 @@
class Controller:
"""Dispatch application requests based on HTTP verb."""

exposed = True

user_facing = False

cache_key = "countries"
@@ -7,6 +7,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Coverage"
exposed = True
user_facing = True

@staticmethod
def GET():
@@ -28,7 +28,7 @@ def tearDownClass(cls):
def test_allow(self):
"""Verify the controller's supported HTTP methods"""
response = self.request("/", method="HEAD")
self.assertAllowedMethods(response, ("GET",))
self.assert_allowed(response, ("GET",))

@mock.patch("cherrypy.engine.publish")
def test_redirect(self, publish_mock):
@@ -6,6 +6,7 @@
class Controller:
"""Dispatch application requests based on HTTP verb."""

exposed = True
user_facing = False

@staticmethod
@@ -10,6 +10,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Grids"
exposed = True
user_facing = True

@cherrypy.tools.negotiable()
def GET(self, *_args, **kwargs):
@@ -72,7 +74,7 @@ def GET(self, *_args, **kwargs):
"html": ("grids.jinja.html", {
"headers": headers,
"name": name,
"names": [key for key in grids.keys()],
"names": grids.keys(),
"options": options,
"rows": rows
})
@@ -7,6 +7,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Headers"
exposed = True
user_facing = True

@staticmethod
@cherrypy.tools.negotiable()
@@ -8,6 +8,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Headlines"
exposed = True
user_facing = True

cache_key = "headlines"

@@ -9,6 +9,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Homepage"
exposed = True
user_facing = True

@decorators.log_runtime
def catalog_apps(self, apps):
@@ -8,6 +8,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "HTML Head"
exposed = True
user_facing = True

@staticmethod
@cherrypy.tools.negotiable()
@@ -7,6 +7,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "IP"
exposed = True
user_facing = True

cache_key = "ip:external"

@@ -29,6 +29,7 @@
class Controller:
"""Dispatch application requests based on HTTP verb."""

exposed = True
user_facing = False

@cherrypy.tools.json_in()
@@ -8,6 +8,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Later"
exposed = True
user_facing = True

@staticmethod
@cherrypy.tools.negotiable()
@@ -13,6 +13,8 @@ class Controller:
@staticmethod
def parse_log_date(val):
"""Convert a date string in either date or filename format
exposed = True
user_facing = True
to a datetime.
Date format is YYYY-mm-dd. Filename format is the same, but with
@@ -7,8 +7,10 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

user_facing = False
exposed = True

def POST(self, group):
@staticmethod
def POST(group=None):
"""
Schedule maintenance operations.
"""
@@ -36,7 +36,7 @@ def test_group_required(self):
"/",
method="POST"
)
self.assertEqual(response.code, 404)
self.assertEqual(response.code, 400)

def test_group_valid(self):
"""The group parameter must be valid."""
@@ -7,6 +7,7 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

user_facing = False
exposed = True

@staticmethod
@cherrypy.tools.capture()
@@ -7,6 +7,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Phone"
exposed = True
user_facing = True

messages = {
"invalid": "The number provided was invalid",
@@ -7,7 +7,7 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Redirect"

exposed = True
user_facing = False

@staticmethod
@@ -7,6 +7,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Registry"
exposed = True
user_facing = True

@staticmethod
@cherrypy.tools.negotiable()
@@ -10,6 +10,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Reminder"
exposed = True
user_facing = True

registry_key = "reminder:template"

@@ -7,6 +7,7 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

user_facing = False
exposed = True

@staticmethod
def GET(*_args, **_kwargs):
@@ -7,9 +7,12 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Speak"
exposed = True
user_facing = True

@staticmethod
@cherrypy.tools.negotiable()
def GET(self, *_args, **_kwargs):
def GET(*_args, **_kwargs):
"""Present an interface for on-demand and scheduled muting of the
application.
@@ -9,6 +9,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Startpage"
exposed = True
user_facing = True

default_page_name = "default"

@@ -9,6 +9,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Transform"
exposed = True
user_facing = True

transforms = {}

@@ -15,6 +15,8 @@ class Controller:
"""

name = "Visitors"
exposed = True
user_facing = True

@cherrypy.tools.negotiable()
def GET(self, *_args, **kwargs):
@@ -9,6 +9,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Wakeup"
exposed = True
user_facing = True

@staticmethod
@cherrypy.tools.negotiable()
@@ -11,6 +11,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Weather"
exposed = True
user_facing = True

@cherrypy.tools.negotiable()
def GET(self, *_args, **_kwargs):
@@ -11,6 +11,8 @@ class Controller:
"""Dispatch application requests based on HTTP verb."""

name = "Whois"
exposed = True
user_facing = True

@staticmethod
@cherrypy.tools.negotiable()
@@ -48,7 +48,7 @@

# pylint: disable=too-many-statements
@plugins.decorators.log_runtime
def setup():
def setup() -> None:
"""Configure and start the application server
The application server is the backbone that individual
@@ -128,17 +128,6 @@ def setup():

app_module = importlib.import_module(f"apps.{app}.main")

# Treat all controllers as exposed by default.
# This is a Cherrypy-ism.
if not hasattr(app_module.Controller, "exposed"):
app_module.Controller.exposed = True

# Treat all controllers as user-facing by default. This is a
# Medley-ism. Service apps should override this attribute
# locally.
if not hasattr(app_module.Controller, "user_facing"):
app_module.Controller.user_facing = True

app_config = {
"/": {
"request.dispatch": cherrypy.dispatch.MethodDispatcher()
@@ -186,7 +175,7 @@ def setup():
})

cherrypy.tree.mount(
app_module.Controller(),
app_module.Controller(), # type: ignore
app_path,
app_config
)
@@ -0,0 +1,6 @@
[mypy]
python_version = 3.7
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = True
ignore_missing_imports = True
@@ -3,6 +3,7 @@ coverage==4.5.4
flake8==3.7.8
flake8-comprehensions==2.2.0
mock==3.0.5
mypy==0.740
pylint==2.4.2
pytest-cov==2.8.1
pytest-timeout==1.3.3

0 comments on commit 30b38a6

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