webapp.py: generalize url router
authorHelmut Grohne <helmut@subdivi.de>
Wed, 12 Jan 2022 04:58:22 +0000 (05:58 +0100)
committerHelmut Grohne <helmut@subdivi.de>
Wed, 12 Jan 2022 04:58:22 +0000 (05:58 +0100)
Each view now has its own view function following the show_ pattern and
it accepts its parsed parameters as keyword-only arguments now.

webapp.py

index 162a5a4..da66ed7 100755 (executable)
--- a/webapp.py
+++ b/webapp.py
@@ -92,23 +92,12 @@ class Application:
         mapadapter = self.routingmap.bind_to_environ(request.environ)
         try:
             endpoint, args = mapadapter.match()
-            if endpoint == "package":
-                return self.show_package(args["package"])
-            elif endpoint == "detail":
-                return self.show_detail(args["package1"], args["package2"])
-            elif endpoint == "hash":
-                if args["function"] == "image_sha512":
-                    # backwards compatibility
-                    raise InternalRedirect("/hash/png_sha512/%s" %
-                                           args["hashvalue"])
-                return self.show_hash(args["function"], args["hashvalue"])
-            elif endpoint == "index":
-                if not request.environ["PATH_INFO"]:
-                    raise InternalRedirect("/")
-                return html_response(index_template.stream(dict(urlroot="")))
-            elif endpoint == "source":
-                return self.show_source(args["package"])
-            raise NotFound()
+            if endpoint == "index" and not request.environ["PATH_INFO"]:
+                raise InternalRedirect("/")
+            method = getattr(self, "show_" + endpoint, None)
+            if method is None:
+                return NotFound()
+            return method(**args)
         except InternalRedirect as r:
             return redirect(request.environ["SCRIPT_NAME"] + r.target, r.code)
         except HTTPException as e:
@@ -154,7 +143,10 @@ class Application:
                                      savable=size))
         return sharedstats
 
-    def show_package(self, package):
+    def show_index(self):
+        return html_response(index_template.stream(dict(urlroot="")))
+
+    def show_package(self, *, package):
         params = self.get_details(package)
         params["dependencies"] = self.get_dependencies(params["pid"])
         params["shared"] = self.cached_sharedstats(params["pid"])
@@ -207,7 +199,7 @@ class Application:
             if len(entry["matches"]) >= minmatch:
                 yield entry
 
-    def show_detail(self, package1, package2):
+    def show_detail(self, *, package1, package2):
         details1 = details2 = self.get_details(package1)
         if package1 != package2:
             details2 = self.get_details(package2)
@@ -220,7 +212,11 @@ class Application:
             shared=shared)
         return html_response(detail_template.stream(params))
 
-    def show_hash(self, function, hashvalue):
+    def show_hash(self, *, function, hashvalue):
+        if function == "image_sha512":
+            # backwards compatibility
+            raise InternalRedirect("/hash/png_sha512/%s" % hashvalue)
+
         with self.cursor() as cur:
             cur.execute("SELECT package.name, content.filename, content.size, f2.name FROM hash JOIN content ON hash.cid = content.id JOIN package ON content.pid = package.id JOIN function AS f2 ON hash.fid = f2.id JOIN function AS f1 ON f2.eqclass = f1.eqclass WHERE f1.name = ? AND hash = ?;",
                         (function, hashvalue,))
@@ -241,7 +237,7 @@ class Application:
                       urlroot="../..")
         return html_response(hash_template.stream(params))
 
-    def show_source(self, package):
+    def show_source(self, *, package):
         with self.cursor() as cur:
             cur.execute("SELECT name FROM package WHERE source = ?;",
                         (package,))