changeset 2410:e1f2066a923c

Route views by name, not by function reference
author Radomir Dopieralski <sheep-devel@sheep.art.pl>
date Sat, 18 May 2013 16:10:36 +0200
parents d41182b8c819
children 919edcf02dc0
files examples/slides/slides.py hatta/page.py hatta/request.py hatta/templates/base.html hatta/templates/history.html hatta/templates/page.html hatta/templates/page_special.html hatta/views.py hatta/wiki.py tests/test_hatta.py
diffstat 10 files changed, 85 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/examples/slides/slides.py	Sat May 18 14:42:59 2013 +0200
+++ b/examples/slides/slides.py	Sat May 18 16:10:36 2013 +0200
@@ -6,40 +6,40 @@
 """
 
 import werkzeug
-import os
 
-import hatta
+import hatta.wiki
+import hatta.page
+import hatta.views
 
-_ = lambda x: x
 
-class WikiPageWiki(hatta.WikiPageWiki):
+class WikiPageWiki(hatta.page.WikiPageWiki):
     def footer(self, special_title, edit_url):
+        _ = self.wiki.gettext
         for part in super(WikiPageWiki, self).footer(special_title, edit_url):
             yield part
         yield werkzeug.html.a(werkzeug.html(_('Slides')),
-            href=self.get_url(self.title, self.wiki.slides),
+            href=self.get_url(self.title, 'slides'),
             class_='slides')
         yield u'\n'
 
 
-class Wiki(hatta.Wiki):
-    @hatta.URL('/+slides/<title:title>')
-    def slides(self, request, title):
-        """Dump the HTML content of the pages listed."""
+@hatta.views.URL('/+slides/<title:title>')
+def slides(request, title):
+    """Dump the HTML content of the pages listed."""
 
-        items = self.index.page_links_and_labels(title)
-        contents = []
-        for t, label in items:
-            page = self.get_page(request, t)
-            try:
-                html = ''.join(page.view_content())
-            except hatta.error.NotFoundErr:
-                continue
-            slide_title = (u'<h1>%s</h1>' % werkzeug.escape(label))
-            contents.append(slide_title + html)
-        content = ('<div class="slide">%s</div>'
-                   % '</div><div class="slide">'.join(contents))
-        html = """<!DOCTYPE html>
+    items = request.wiki.index.page_links_and_labels(title)
+    contents = []
+    for t, label in items:
+        page = hatta.page.get_page(request, t)
+        try:
+            html = ''.join(page.view_content())
+        except hatta.error.NotFoundErr:
+            continue
+        slide_title = (u'<h1>%s</h1>' % werkzeug.escape(label))
+        contents.append(slide_title + html)
+    content = ('<div class="slide">%s</div>'
+               % '</div><div class="slide">'.join(contents))
+    html = """<!DOCTYPE html>
 <link type="text/css" href="../+download/slides.css" rel="stylesheet">
 <link type="text/css" href="../+download/pygments.css" rel="stylesheet">
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
@@ -48,12 +48,13 @@
 <script src="../+download/jquery.js"></script>
 <script src="../+download/slides.js"></script>
 """ % (werkzeug.escape(title), content)
-        response = hatta.WikiResponse(html, mimetype='text/html')
-        return response
+    response = hatta.WikiResponse(html, mimetype='text/html')
+    return response
 
 
 if __name__=='__main__':
     config = hatta.read_config()
-    wiki = Wiki(config)
+    wiki = hatta.wiki.Wiki(config)
     wiki.mime_map['text/x-wiki'] = WikiPageWiki
     hatta.main(wiki=wiki)
+
--- a/hatta/page.py	Sat May 18 14:42:59 2013 +0200
+++ b/hatta/page.py	Sat May 18 16:10:36 2013 +0200
@@ -257,7 +257,7 @@
         if self.title:
             try:
                 check_lock(self.wiki, self.title)
-                edit_url = self.get_url(self.title, self.wiki.edit)
+                edit_url = self.get_url(self.title, 'edit')
             except hatta.error.ForbiddenErr:
                 pass
         context = {
--- a/hatta/request.py	Sat May 18 14:42:59 2013 +0200
+++ b/hatta/request.py	Sat May 18 16:10:36 2013 +0200
@@ -22,14 +22,14 @@
     def get_url(self, title=None, view=None, method='GET',
                 external=False, **kw):
         if view is None:
-            view = hatta.views.view
+            view = 'view'
         if title is not None:
             kw['title'] = title.strip()
         return self.adapter.build(view, kw, method=method,
                                   force_external=external)
 
     def get_download_url(self, title):
-        return self.get_url(title, view=hatta.views.download)
+        return self.get_url(title, 'download')
 
     def get_author(self):
         """Try to guess the author name. Use IP address as last resort."""
--- a/hatta/templates/base.html	Sat May 18 14:42:59 2013 +0200
+++ b/hatta/templates/base.html	Sat May 18 16:10:36 2013 +0200
@@ -6,14 +6,14 @@
 
 {% block links %}
     <link rel="stylesheet" type="text/css"
-          href="{{ url(None, wiki.style_css) }}">
+          href="{{ url(None, 'style_css') }}">
     <link rel="stylesheet" type="text/css"
-          href="{{ url(None, wiki.pygments_css) }}">
+          href="{{ url(None, 'pygments_css') }}">
     <link rel="shortcut icon" type="image/x-icon"
-          href="{{ url(None, wiki.favicon_ico) }}">
+          href="{{ url(None, 'favicon_ico') }}">
     <link rel="alternate" type="application/rss+xml"
           title="{{ wiki.site_name }} (ATOM)"
-          href="{{ url(None, wiki.atom) }}">
+          href="{{ url(None, 'atom') }}">
     {% if edit_url %}
         <link rel="alternate" type="application/wiki"
               href="{{ edit_url }}">
@@ -22,7 +22,7 @@
 
 {% block scripts %}
     <script type="text/javascript"
-            src="{{ url(None, wiki.scripts_js) }}"></script>
+            src="{{ url(None, 'scripts_js') }}"></script>
     {% if wiki.math_url == 'mathjax' %}
     <script type="text/x-mathjax-config">
         MathJax.Hub.Config({
@@ -54,7 +54,7 @@
 {% endblock %}
 
 {% block search %}
-    <form action="{{ url(None, wiki.search) }}" id="hatta-search" method="GET"
+    <form action="{{ url(None, 'search') }}" id="hatta-search" method="GET"
       ><div><input
         id="hatta-search-q" name="q"><input
         class="button" type="submit" value="Search"
--- a/hatta/templates/history.html	Sat May 18 14:42:59 2013 +0200
+++ b/hatta/templates/history.html	Sat May 18 16:10:36 2013 +0200
@@ -9,7 +9,7 @@
 
 {% block content %}
     <p>{{ _("History of changes for %(link)s.", link=page.wiki_link(title)|safe) }}</p>
-    <form action="{{ url(title, wiki.undo, method='POST') }}" method="POST">
+    <form action="{{ url(title, 'undo', method='POST') }}" method="POST">
         <ul id="hatta-history">
             {% for date, date_url, rev, author, comment in history %}
                 <li><a href="{{ date_url }}"
--- a/hatta/templates/page.html	Sat May 18 14:42:59 2013 +0200
+++ b/hatta/templates/page.html	Sat May 18 16:10:36 2013 +0200
@@ -8,8 +8,8 @@
         <a href="{{ edit_url }}"
            class="edit">{{ _('Edit') }}</a>
     {% endif %}
-    <a href="{{ url(title, wiki.history) }}"
+    <a href="{{ url(title, 'history') }}"
        class="hatta-history">{{ _('History') }}</a>
-    <a href="{{ url(title, wiki.backlinks) }}"
+    <a href="{{ url(title, 'backlinks') }}"
        class="hatta-backlinks">{{ _('Backlinks') }}</a>
 {% endblock %}
--- a/hatta/templates/page_special.html	Sat May 18 14:42:59 2013 +0200
+++ b/hatta/templates/page_special.html	Sat May 18 16:10:36 2013 +0200
@@ -6,8 +6,8 @@
 {% block title %}{{ special_title }} - {{ wiki.site_name }}{% endblock %}
 
 {% block footer %}
-<a href="{{ url(None, wiki.recent_changes) }}" class="changes">{{ _('Changes') }}</a>
-<a href="{{ url(None, wiki.all_pages) }}" class="index">{{ _('Index') }}</a>
-<a href="{{ url(None, wiki.orphaned) }}" class="orphaned">{{ _('Orphaned') }}</a>
-<a href="{{ url(None, wiki.wanted) }}" class="wanted">{{ _('Wanted') }}</a>
+<a href="{{ url(None, 'recent_changes') }}" class="changes">{{ _('Changes') }}</a>
+<a href="{{ url(None, 'all_pages') }}" class="index">{{ _('Index') }}</a>
+<a href="{{ url(None, 'orphaned') }}" class="orphaned">{{ _('Orphaned') }}</a>
+<a href="{{ url(None, 'wanted') }}" class="wanted">{{ _('Wanted') }}</a>
 {% endblock %}
--- a/hatta/views.py	Sat May 18 14:42:59 2013 +0200
+++ b/hatta/views.py	Sat May 18 16:10:36 2013 +0200
@@ -41,18 +41,23 @@
     def __call__(self, func):
         """The actual decorator only records the data."""
 
-        self.urls.append((func, self.url, self.methods))
+        self.urls.append((func.__name__, func, self.url, self.methods))
         return func
 
     @classmethod
-    def rules(cls, app):
-        """Returns the routing rules and sets them on the app."""
+    def get_rules(cls):
+        """Returns the routing rules."""
 
-        for func, url, methods in cls.urls:
-            setattr(app, func.__name__, func)
-            if not callable(func):
-                continue
-            yield werkzeug.routing.Rule(url, endpoint=func, methods=methods)
+        return [
+            werkzeug.routing.Rule(url, endpoint=name, methods=methods)
+            for name, func, url, methods in cls.urls
+        ]
+
+    @classmethod
+    def get_views(cls):
+        """Returns a dict of views."""
+
+        return {name: func for name, func, url, methods in cls.urls}
 
 
 def _serve_default(request, title, content=None, mime=None):
@@ -86,7 +91,7 @@
         if request.wiki.read_only:
             raise hatta.error.NotFoundErr(_(u"Page not found."))
 
-        url = request.get_url(title, request.wiki.edit, external=True)
+        url = request.get_url(title, 'edit', external=True)
         return werkzeug.routing.redirect(url, code=303)
     html = page.template("page.html", content=content)
     dependencies = page.dependencies()
@@ -217,7 +222,7 @@
     _ = request.wiki.gettext
     feed = werkzeug.contrib.atom.AtomFeed(request.wiki.site_name,
         feed_url=request.url,
-        url=request.adapter.build(request.wiki.view, force_external=True),
+        url=request.adapter.build('view', force_external=True),
         subtitle=_(u'Track the most recent changes to the wiki '
                    u'in this feed.'))
     history = itertools.islice(request.wiki.storage.history(), None, 10, None)
@@ -227,13 +232,13 @@
             continue
         unique_titles.add(title)
         if rev > 0:
-            url = request.adapter.build(request.wiki.diff, {
+            url = request.adapter.build('diff', {
                 'title': title,
                 'from_rev': rev - 1,
                 'to_rev': rev,
             }, force_external=True)
         else:
-            url = request.adapter.build(request.wiki.revision, {
+            url = request.adapter.build('revision', {
                 'title': title,
                 'rev': rev,
             }, force_external=True)
@@ -354,7 +359,7 @@
             request.wiki.storage.save_data(title, data, author, comment, parent)
         page = hatta.page.get_page(request, title)
         request.wiki.index.update_page(page, title, data=data)
-    url = request.adapter.build(request.wiki.history, {'title': title},
+    url = request.adapter.build('history', {'title': title},
                                 method='GET', force_external=True)
     return werkzeug.redirect(url, 303)
 
@@ -369,11 +374,16 @@
         if max_rev < rev:
             max_rev = rev
         if rev > 0:
-            date_url = request.adapter.build(request.wiki.diff, {
-                'title': title, 'from_rev': rev - 1, 'to_rev': rev})
+            date_url = request.adapter.build('diff', {
+                'title': title,
+                'from_rev': rev - 1,
+                'to_rev': rev,
+            })
         else:
-            date_url = request.adapter.build(request.wiki.revision, {
-                'title': title, 'rev': rev})
+            date_url = request.adapter.build('revision', {
+                'title': title,
+                'rev': rev,
+            })
         history.append((date, date_url, rev, author, comment))
     html = page.template('history.html', history=history,
                          date_html=hatta.page.date_html, parent=max_rev)
@@ -395,17 +405,18 @@
             if count > 100:
                 break
             if rev > 0:
-                date_url = request.adapter.build(request.wiki.diff, {
+                date_url = request.adapter.build('diff', {
                     'title': title,
                     'from_rev': rev - 1,
                     'to_rev': lastrev.get(title, rev),
                 })
             elif rev == 0:
-                date_url = request.adapter.build(request.wiki.revision, {
-                    'title': title, 'rev': rev})
+                date_url = request.adapter.build('revision', {
+                    'title': title,
+                    'rev': rev,
+                })
             else:
-                date_url = request.adapter.build(request.wiki.history, {
-                    'title': title})
+                date_url = request.adapter.build('history', {'title': title})
             last[title] = author, comment
             lastrev[title] = rev
 
@@ -426,8 +437,8 @@
     _ = request.wiki.gettext
     page = hatta.page.get_page(request, title)
     build = request.adapter.build
-    from_url = build(request.wiki.revision, {'title': title, 'rev': from_rev})
-    to_url = build(request.wiki.revision, {'title': title, 'rev': to_rev})
+    from_url = build('revision', {'title': title, 'rev': from_rev})
+    to_url = build('revision', {'title': title, 'rev': to_rev})
     a = werkzeug.html.a
     links = {
         'link1': a(str(from_rev), href=from_url),
--- a/hatta/wiki.py	Sat May 18 14:42:59 2013 +0200
+++ b/hatta/wiki.py	Sat May 18 16:10:36 2013 +0200
@@ -124,7 +124,8 @@
         )
         self.index = self.index_class(self.cache, self.language, self.storage)
         self.index.update(self)
-        self.url_rules = hatta.views.URL.rules(self)
+        self.url_rules = hatta.views.URL.get_rules()
+        self.views = hatta.views.URL.get_views()
         self.url_converters = {
             'title': WikiTitleConverter,
             'all': WikiAllConverter,
@@ -134,10 +135,11 @@
             converters=self.url_converters,
         )
 
-    def add_url_rule(self, rule):
+    def add_url_rule(self, rule, name, func):
         """Let plugins add additional url rules."""
 
         self.url_rules.append(rule)
+        self.views[name] = func
         self.url_map = werkzeug.routing.Map(
             self.url_rules,
             converters=self.url_converters,
@@ -151,7 +153,8 @@
         request = hatta.request.WikiRequest(self, adapter, environ)
         try:
             endpoint, values = adapter.match()
-            return endpoint(request, **values)
+            view = self.views[endpoint]
+            return view(request, **values)
         except werkzeug.exceptions.HTTPException as err:
             return err
 
--- a/tests/test_hatta.py	Sat May 18 14:42:59 2013 +0200
+++ b/tests/test_hatta.py	Sat May 18 16:10:36 2013 +0200
@@ -8,7 +8,6 @@
 from test_parser import HTML
 
 import hatta
-import hatta.views
 
 
 def clear_directory(top):
@@ -213,11 +212,11 @@
             u'/+download/title',
             u'/%2Bdownload/title',
         )
-        assert request.get_url('title', hatta.views.edit) in (
+        assert request.get_url('title', 'edit') in (
             u'/+edit/title',
             u'/%2Bedit/title',
         )
-        assert request.get_url(None, hatta.views.favicon_ico) == u'/favicon.ico'
+        assert request.get_url(None, 'favicon_ico') == u'/favicon.ico'
 
     @py.test.mark.xfail
     def test_html_page(self, req):