diff --git a/libpathod/app.py b/libpathod/app.py index 399d13401..51bd014b7 100644 --- a/libpathod/app.py +++ b/libpathod/app.py @@ -37,10 +37,8 @@ class Log(_Page): class Pathod(object): - anchor = "/p/" - def __init__(self, application, request, **settings): + def __init__(self, spec, application, request, **settings): self.application, self.request, self.settings = application, request, settings - spec = urllib.unquote(self.request.uri)[len(self.anchor):] try: self.response = rparse.parse(self.settings, spec) except rparse.ParseException, v: @@ -53,9 +51,17 @@ class Pathod(object): self.response.render(self.request) +class RequestPathod(Pathod): + anchor = "/p/" + def __init__(self, application, request, **settings): + spec = urllib.unquote(request.uri)[len(self.anchor):] + Pathod.__init__(self, spec, application, request, **settings) + + class PathodApp(tornado.web.Application): def __init__(self, **settings): self.templates = tornado.template.Loader(utils.data.path("templates")) + self.appsettings = settings tornado.web.Application.__init__( self, [ @@ -63,13 +69,37 @@ class PathodApp(tornado.web.Application): (r"/log", Log), (r"/help", Help), (r"/preview", Preview), - (r"/p/.*", Pathod, settings), + (r"/p/.*", RequestPathod, settings), ], static_path = utils.data.path("static"), template_path = utils.data.path("templates"), debug=True ) + def add_anchor(self, pattern, spec): + """ + Anchors are added to the beginning of the handlers. + """ + # We assume we have only one host... + l = self.handlers[0][1] + class FixedPathod(Pathod): + def __init__(self, application, request, **settings): + Pathod.__init__(self, spec, application, request, **settings) + FixedPathod.spec = spec + l.insert(0, tornado.web.URLSpec(pattern, FixedPathod, self.appsettings)) + + def get_anchors(self, pattern, spec): + """ + Anchors are added to the beginning of the handlers. + """ + pass + + def remove_anchor(self, pattern, spec): + """ + Anchors are added to the beginning of the handlers. + """ + pass + # begin nocover def run(application, port, ssl_options): diff --git a/libpathod/utils.py b/libpathod/utils.py index 104ee1482..daeccdeab 100644 --- a/libpathod/utils.py +++ b/libpathod/utils.py @@ -1,4 +1,27 @@ -import copy, os +import copy, os, re +import rparse + +class AnchorError(Exception): pass + +def parse_anchor_spec(s, settings): + """ + For now, this is very simple, and you can't have an '=' in your regular + expression. + """ + if not "=" in s: + raise AnchorError("Invalid anchor definition: %s"%s) + rex, spec = s.split("=", 1) + try: + re.compile(rex) + except re.error: + raise AnchorError("Invalid regex in anchor: %s"%s) + try: + rparse.parse(settings, spec) + except rparse.ParseException, v: + raise AnchorError("Invalid page spec in anchor: '%s', %s"%(s, str(v))) + + return rex, spec + class Data: def __init__(self, name): diff --git a/pathod b/pathod index 810763e2a..fd321da12 100755 --- a/pathod +++ b/pathod @@ -1,11 +1,15 @@ #!/usr/bin/env python -import argparse +import argparse, sys from libpathod import app, utils import tornado.ioloop if __name__ == "__main__": parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument("-p", dest='port', default=8888, type=int, help='Port.') + parser.add_argument( + "-a", dest='anchors', default=[], type=str, action="append", + help='Add an anchor. Specified as a string with the form pattern=pagespec' + ) parser.add_argument( "-d", dest='staticdir', default=None, type=str, help='Directory for static files.' @@ -26,10 +30,17 @@ if __name__ == "__main__": help='SSL cert file. If not specified, a default cert is used.' ) args = parser.parse_args() + settings = dict( + staticdir=args.staticdir + ) + application = app.PathodApp(**settings) + for i in args.anchors: + try: + rex, spec = utils.parse_anchor_spec(i, settings) + except utils.AnchorError, v: + parser.error(str(v)) + application.add_anchor(rex, spec) - application = app.PathodApp( - staticdir=args.staticdir - ) if args.ssl: ssl = dict( keyfile = args.ssl_keyfile or utils.data.path("resources/server.key"), diff --git a/test/test_app.py b/test/test_app.py index 6355a88a2..3a147385a 100644 --- a/test/test_app.py +++ b/test/test_app.py @@ -2,8 +2,14 @@ import libpry from libpathod import app from tornado import httpserver - class uApplication(libpry.AutoTree): + def test_anchors(self): + a = app.PathodApp(staticdir=None) + a.add_anchor("/foo", "200") + assert a.handlers[0][1][0].handler_class.__name__ == "FixedPathod" + + +class uPages(libpry.AutoTree): def dummy_page(self, path): # A hideous, hideous kludge, but Tornado seems to have no more sensible # way to do this. @@ -15,9 +21,6 @@ class uApplication(libpry.AutoTree): del r.connection return klass(a, r) - def test_create(self): - assert app.PathodApp(staticdir=None) - def test_index(self): page = self.dummy_page("/") page.get() @@ -31,5 +34,6 @@ class uApplication(libpry.AutoTree): tests = [ - uApplication() + uApplication(), + uPages() ] diff --git a/test/test_utils.py b/test/test_utils.py index 7c6c7cb1d..f8c7edb78 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -2,7 +2,13 @@ import libpry from libpathod import utils +class uparse_anchor_spec(libpry.AutoTree): + def test_simple(self): + assert utils.parse_anchor_spec("foo=200", {}) == ("foo", "200") + libpry.raises(utils.AnchorError, utils.parse_anchor_spec, "*=200", {}) + libpry.raises(utils.AnchorError, utils.parse_anchor_spec, "foo=bar", {}) tests = [ + uparse_anchor_spec() ] diff --git a/todo b/todo index f5564c0b7..05be23e43 100644 --- a/todo +++ b/todo @@ -1,5 +1,4 @@ -- HTTPS - Anchors - Logs, log reset, log retrieval - Add anchors programmatically?