From: Joar Wandborg Date: Sun, 14 Oct 2012 11:46:31 +0000 (+0200) Subject: Switched most stuff over from Routes X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=7742dcc1fbda04c3a1c76a057a1a93a8f504502e;p=mediagoblin.git Switched most stuff over from Routes Removed the Routes routing functionality and replaced it with werkzeug.routes. Most views are functional. Known issues: - Translation integration with the request object is not yet figured out. This breaks 404 pages. --- diff --git a/mediagoblin/app.py b/mediagoblin/app.py index 08515df9..5758dbbb 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -18,11 +18,12 @@ import os import urllib import logging -import routes -from webob import exc +from mediagoblin.routing import url_map, view_functions, add_route + from werkzeug.wrappers import Request +from werkzeug.exceptions import HTTPException, NotFound -from mediagoblin import routing, meddleware, __version__ +from mediagoblin import meddleware, __version__ from mediagoblin.tools import common, translate, template from mediagoblin.tools.response import render_404 from mediagoblin.tools.theme import register_themes @@ -90,7 +91,10 @@ class MediaGoblinApp(object): self.public_store, self.queue_store = setup_storage() # set up routing - self.routing = routing.get_mapper(PluginManager().get_routes()) + self.url_map = url_map + + for route in PluginManager().get_routes(): + add_route(*route) # set up staticdirector tool self.staticdirector = get_staticdirector(app_config) @@ -135,7 +139,7 @@ class MediaGoblinApp(object): ## Routing / controller loading stuff path_info = request.path - route_match = self.routing.match(path_info) + map_adapter = self.url_map.bind_to_environ(request.environ) # By using fcgi, mediagoblin can run under a base path # like /mediagoblin/. request.path_info contains the @@ -154,47 +158,52 @@ class MediaGoblinApp(object): environ.pop('HTTPS') ## Attach utilities to the request object - request.matchdict = route_match - request.urlgen = routes.URLGenerator(self.routing, environ) # Do we really want to load this via middleware? Maybe? request.session = request.environ['beaker.session'] # Attach self as request.app # Also attach a few utilities from request.app for convenience? request.app = self - request.locale = translate.get_locale_from_request(request) - request.template_env = template.get_jinja_env( - self.template_loader, request.locale) request.db = self.db request.staticdirect = self.staticdirector mg_request.setup_user_in_request(request) - # No matching page? - if route_match is None: - # Try to do see if we have a match with a trailing slash - # added and if so, redirect - if not path_info.endswith('/') \ - and request.method == 'GET' \ - and self.routing.match(path_info + '/'): - new_path_info = path_info + '/' - if request.GET: - new_path_info = '%s?%s' % ( - new_path_info, urllib.urlencode(request.GET)) - redirect = exc.HTTPFound(location=new_path_info) - return request.get_response(redirect)(environ, start_response) - - # Okay, no matches. 404 time! - request.matchdict = {} # in case our template expects it + try: + endpoint, url_values = map_adapter.match() + request.matchdict = url_values + + request.locale = translate.get_locale_from_request(request) + request.template_env = template.get_jinja_env( + self.template_loader, request.locale) + except NotFound as exc: + return NotImplemented return render_404(request)(environ, start_response) + except HTTPException as exc: + # Support legacy webob.exc responses + return exc(environ, start_response) + + def build_proxy(endpoint, **kw): + try: + qualified = kw.pop('qualified') + except KeyError: + qualified = False + + return map_adapter.build( + endpoint, + values=dict(**kw), + force_external=qualified) + + request.urlgen = build_proxy + + view_func = view_functions[endpoint] - # import the controller, or if it's already a callable, call that - route_controller = route_match['controller'] - if isinstance(route_controller, unicode) \ - or isinstance(route_controller, str): - controller = common.import_component(route_match['controller']) + # import the endpoint, or if it's already a callable, call that + if isinstance(view_func, unicode) \ + or isinstance(view_func, str): + controller = common.import_component(view_func) else: - controller = route_match['controller'] + controller = view_func # pass the request through our meddleware classes for m in self.meddleware: diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py index 15d8fc3c..58faa5a3 100644 --- a/mediagoblin/auth/routing.py +++ b/mediagoblin/auth/routing.py @@ -14,25 +14,36 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from routes.route import Route - -auth_routes = [ - Route('mediagoblin.auth.register', '/register/', - controller='mediagoblin.auth.views:register'), - Route('mediagoblin.auth.login', '/login/', - controller='mediagoblin.auth.views:login'), - Route('mediagoblin.auth.logout', '/logout/', - controller='mediagoblin.auth.views:logout'), - Route('mediagoblin.auth.verify_email', '/verify_email/', - controller='mediagoblin.auth.views:verify_email'), - Route('mediagoblin.auth.resend_verification', '/resend_verification/', - controller='mediagoblin.auth.views:resend_activation'), - Route('mediagoblin.auth.resend_verification_success', - '/resend_verification_success/', - template='mediagoblin/auth/resent_verification_email.html', - controller='mediagoblin.views:simple_template_render'), - Route('mediagoblin.auth.forgot_password', '/forgot_password/', - controller='mediagoblin.auth.views:forgot_password'), - Route('mediagoblin.auth.verify_forgot_password', - '/forgot_password/verify/', - controller='mediagoblin.auth.views:verify_forgot_password')] +from routes.route import add_route +from mediagoblin.routing import add_route + +add_route('mediagoblin.auth.logout', + '/auth/logout/', 'mediagoblin.auth.views:logout') + + +add_route('mediagoblin.auth.register', '/register/', + 'mediagoblin.auth.views:register') + +add_route('mediagoblin.auth.login', '/login/', + 'mediagoblin.auth.views:login') + +add_route('mediagoblin.auth.logout', '/logout/', + 'mediagoblin.auth.views:logout') + +add_route('mediagoblin.auth.verify_email', '/verify_email/', + 'mediagoblin.auth.views:verify_email') + +add_route('mediagoblin.auth.resend_verification', '/resend_verification/', + 'mediagoblin.auth.views:resend_activation') + +add_route('mediagoblin.auth.resend_verification_success', + '/resend_verification_success/', + template='mediagoblin/auth/resent_verification_email.html', + 'mediagoblin.views:simple_template_render') + +add_route('mediagoblin.auth.forgot_password', '/forgot_password/', + 'mediagoblin.auth.views:forgot_password') + +add_route('mediagoblin.auth.verify_forgot_password', + '/forgot_password/verify/', + 'mediagoblin.auth.views:verify_forgot_password') diff --git a/mediagoblin/edit/routing.py b/mediagoblin/edit/routing.py index 321c1f44..28b73d1e 100644 --- a/mediagoblin/edit/routing.py +++ b/mediagoblin/edit/routing.py @@ -14,13 +14,9 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +from mediagoblin.routing import add_route -from routes.route import Route - -edit_routes = [ - # Media editing view handled in user_pages/routing.py - Route('mediagoblin.edit.profile', '/profile/', - controller="mediagoblin.edit.views:edit_profile"), - Route('mediagoblin.edit.account', '/account/', - controller="mediagoblin.edit.views:edit_account"), - ] +add_route('mediagoblin.edit.profile', '/edit/profile/', + 'mediagoblin.edit.views:edit_profile') +add_route('mediagoblin.edit.account', '/edit/account/', + 'mediagoblin.edit.views:edit_account') diff --git a/mediagoblin/listings/routing.py b/mediagoblin/listings/routing.py index d228a727..d25f1c8c 100644 --- a/mediagoblin/listings/routing.py +++ b/mediagoblin/listings/routing.py @@ -14,14 +14,10 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +from mediagoblin.routing import add_route -from routes.route import Route - -tag_routes = [ - # Route('mediagoblin.listings.tags_home', "/", - # controller="mediagoblin.listings.views:tags_home"), - Route('mediagoblin.listings.tags_listing', "/{tag}/", - controller="mediagoblin.listings.views:tag_listing"), - Route('mediagoblin.listings.tag_atom_feed', "/{tag}/atom/", - controller="mediagoblin.listings.views:tag_atom_feed"), - ] +add_route('mediagoblin.listings.tags_listing', + "/tag//", + "mediagoblin.listings.views:tag_listing") +add_route('mediagoblin.listings.tag_atom_feed', "/tag//atom/", + "mediagoblin.listings.views:tag_atom_feed") diff --git a/mediagoblin/plugins/api/__init__.py b/mediagoblin/plugins/api/__init__.py index 40722088..f370cca6 100644 --- a/mediagoblin/plugins/api/__init__.py +++ b/mediagoblin/plugins/api/__init__.py @@ -33,12 +33,12 @@ def setup_plugin(): _log.debug('API config: {0}'.format(config)) routes = [ - Route('mediagoblin.plugins.api.test', '/api/test', - controller='mediagoblin.plugins.api.views:api_test'), - Route('mediagoblin.plugins.api.entries', '/api/entries', - controller='mediagoblin.plugins.api.views:get_entries'), - Route('mediagoblin.plugins.api.post_entry', '/api/submit', - controller='mediagoblin.plugins.api.views:post_entry')] + ('mediagoblin.plugins.api.test', '/api/test', + 'mediagoblin.plugins.api.views:api_test'), + ('mediagoblin.plugins.api.entries', '/api/entries', + 'mediagoblin.plugins.api.views:get_entries'), + ('mediagoblin.plugins.api.post_entry', '/api/submit', + 'mediagoblin.plugins.api.views:post_entry')] pluginapi.register_routes(routes) diff --git a/mediagoblin/plugins/oauth/__init__.py b/mediagoblin/plugins/oauth/__init__.py index 63bf49a8..64acf0e7 100644 --- a/mediagoblin/plugins/oauth/__init__.py +++ b/mediagoblin/plugins/oauth/__init__.py @@ -36,21 +36,21 @@ def setup_plugin(): _log.debug('OAuth config: {0}'.format(config)) routes = [ - Route('mediagoblin.plugins.oauth.authorize', '/oauth/authorize', - controller='mediagoblin.plugins.oauth.views:authorize'), - Route('mediagoblin.plugins.oauth.authorize_client', '/oauth/client/authorize', - controller='mediagoblin.plugins.oauth.views:authorize_client'), - Route('mediagoblin.plugins.oauth.access_token', '/oauth/access_token', - controller='mediagoblin.plugins.oauth.views:access_token'), - Route('mediagoblin.plugins.oauth.access_token', + ('mediagoblin.plugins.oauth.authorize', '/oauth/authorize', + 'mediagoblin.plugins.oauth.views:authorize'), + ('mediagoblin.plugins.oauth.authorize_client', '/oauth/client/authorize', + 'mediagoblin.plugins.oauth.views:authorize_client'), + ('mediagoblin.plugins.oauth.access_token', '/oauth/access_token', + 'mediagoblin.plugins.oauth.views:access_token'), + ('mediagoblin.plugins.oauth.access_token', '/oauth/client/connections', - controller='mediagoblin.plugins.oauth.views:list_connections'), - Route('mediagoblin.plugins.oauth.register_client', + 'mediagoblin.plugins.oauth.views:list_connections'), + ('mediagoblin.plugins.oauth.register_client', '/oauth/client/register', - controller='mediagoblin.plugins.oauth.views:register_client'), - Route('mediagoblin.plugins.oauth.list_clients', + 'mediagoblin.plugins.oauth.views:register_client'), + ('mediagoblin.plugins.oauth.list_clients', '/oauth/client/list', - controller='mediagoblin.plugins.oauth.views:list_clients')] + 'mediagoblin.plugins.oauth.views:list_clients')] pluginapi.register_routes(routes) pluginapi.register_template_path(os.path.join(PLUGIN_DIR, 'templates')) diff --git a/mediagoblin/routing.py b/mediagoblin/routing.py index 90e1f3f8..4b9c42ee 100644 --- a/mediagoblin/routing.py +++ b/mediagoblin/routing.py @@ -14,36 +14,22 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from routes import Mapper +from werkzeug.routing import Map, Rule -from mediagoblin.auth.routing import auth_routes -from mediagoblin.submit.routing import submit_routes -from mediagoblin.user_pages.routing import user_routes -from mediagoblin.edit.routing import edit_routes -from mediagoblin.listings.routing import tag_routes -from mediagoblin.webfinger.routing import webfinger_well_known_routes, \ - webfinger_routes -from mediagoblin.admin.routing import admin_routes +url_map = Map() +view_functions = {'index': 'mediagoblin.views:index'} -def get_mapper(plugin_routes): - mapping = Mapper() - mapping.minimization = False +def add_route(endpoint, url, controller): + view_functions.update({endpoint: controller}) - # Plugin routes go first so they can override default routes. - mapping.extend(plugin_routes) + url_map.add(Rule(url, endpoint=endpoint)) - mapping.connect( - "index", "/", - controller="mediagoblin.views:root_view") +add_route('index', '/', 'mediagoblin.views:root_view') - mapping.extend(auth_routes, '/auth') - mapping.extend(submit_routes, '/submit') - mapping.extend(user_routes, '/u') - mapping.extend(edit_routes, '/edit') - mapping.extend(tag_routes, '/tag') - mapping.extend(webfinger_well_known_routes, '/.well-known') - mapping.extend(webfinger_routes, '/api/webfinger') - mapping.extend(admin_routes, '/a') - - return mapping +import mediagoblin.submit.routing +import mediagoblin.user_pages.routing +import mediagoblin.auth.routing +import mediagoblin.edit.routing +import mediagoblin.webfinger.routing +import mediagoblin.listings.routing diff --git a/mediagoblin/submit/routing.py b/mediagoblin/submit/routing.py index 1e399d1e..cbed1895 100644 --- a/mediagoblin/submit/routing.py +++ b/mediagoblin/submit/routing.py @@ -14,11 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from routes.route import Route +from mediagoblin.routing import add_route -submit_routes = [ - Route('mediagoblin.submit.start', '/', - controller='mediagoblin.submit.views:submit_start'), - Route('mediagoblin.submit.collection', '/collection', - controller='mediagoblin.submit.views:add_collection'), - ] +add_route('mediagoblin.submit.start', + '/submit/', 'mediagoblin.submit.views:submit_start') +add_route('collection_home', '/submit/collection', 'mediagoblin.submit.views:add_collection') diff --git a/mediagoblin/tools/pluginapi.py b/mediagoblin/tools/pluginapi.py index 7c1e108b..df3f51c4 100644 --- a/mediagoblin/tools/pluginapi.py +++ b/mediagoblin/tools/pluginapi.py @@ -162,7 +162,7 @@ def register_routes(routes): Be careful when designing your route urls. If they clash with core urls, then it could result in DISASTER! """ - if isinstance(routes, (tuple, list)): + if isinstance(routes, list): for route in routes: PluginManager().register_route(route) else: diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py index 1cfce2dd..678f18f9 100644 --- a/mediagoblin/user_pages/routing.py +++ b/mediagoblin/user_pages/routing.py @@ -14,48 +14,68 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from routes.route import Route - -user_routes = [ - Route('mediagoblin.user_pages.user_home', "/{user}/", - controller="mediagoblin.user_pages.views:user_home"), - Route('mediagoblin.user_pages.user_gallery', "/{user}/gallery/", - controller="mediagoblin.user_pages.views:user_gallery"), - Route('mediagoblin.user_pages.media_home', '/{user}/m/{media}/', - requirements=dict(m_id="[0-9a-fA-F]{24}"), - controller="mediagoblin.user_pages.views:media_home"), - Route('mediagoblin.user_pages.media_home.view_comment', - '/{user}/m/{media}/c/{comment}/', - controller="mediagoblin.user_pages.views:media_home"), - Route('mediagoblin.edit.edit_media', "/{user}/m/{media}/edit/", - controller="mediagoblin.edit.views:edit_media"), - Route('mediagoblin.edit.attachments', - '/{user}/m/{media}/attachments/', - controller="mediagoblin.edit.views:edit_attachments"), - Route('mediagoblin.user_pages.media_confirm_delete', - "/{user}/m/{media}/confirm-delete/", - controller="mediagoblin.user_pages.views:media_confirm_delete"), - Route('mediagoblin.user_pages.atom_feed', '/{user}/atom/', - controller="mediagoblin.user_pages.views:atom_feed"), - Route('mediagoblin.user_pages.media_post_comment', - '/{user}/m/{media}/comment/add/', - controller="mediagoblin.user_pages.views:media_post_comment"), - Route('mediagoblin.user_pages.media_collect', - "/{user}/m/{media}/collect/", - controller="mediagoblin.user_pages.views:media_collect"), - Route('mediagoblin.user_pages.user_collection', "/{user}/collection/{collection}/", - controller="mediagoblin.user_pages.views:user_collection"), - Route('mediagoblin.edit.edit_collection', "/{user}/c/{collection}/edit/", - controller="mediagoblin.edit.views:edit_collection"), - Route('mediagoblin.user_pages.collection_confirm_delete', - "/{user}/c/{collection}/confirm-delete/", - controller="mediagoblin.user_pages.views:collection_confirm_delete"), - Route('mediagoblin.user_pages.collection_item_confirm_remove', - "/{user}/collection/{collection}/{collection_item}/confirm_remove/", - controller="mediagoblin.user_pages.views:collection_item_confirm_remove"), - Route('mediagoblin.user_pages.collection_atom_feed', '/{user}/collection/{collection}/atom/', - controller="mediagoblin.user_pages.views:collection_atom_feed"), - Route('mediagoblin.user_pages.processing_panel', - '/{user}/panel/', - controller="mediagoblin.user_pages.views:processing_panel"), - ] +from mediagoblin.routing import add_route + +add_route('mediagoblin.user_pages.user_home', + '/u//', 'mediagoblin.user_pages.views:user_home') + +add_route('mediagoblin.user_pages.media_home', + '/u//m//', + 'mediagoblin.user_pages.views:media_home') + +add_route('mediagoblin.user_pages.media_confirm_delete', + '/u//m//confirm-delete/', + 'mediagoblin.user_pages.views:media_confirm_delete') + +add_route('mediagoblin.user_pages.media_post_comment', + '/u//m//comment/add/', + 'mediagoblin.user_pages.views:media_post_comment') + +add_route('mediagoblin.user_pages.user_gallery', + '/u//gallery/', + 'mediagoblin.user_pages.views:user_gallery') + +add_route('mediagoblin.user_pages.media_home.view_comment', + '/u//m//c//', + 'mediagoblin.user_pages.views:media_home') + +add_route('mediagoblin.user_pages.atom_feed', + '/u//atom/', + 'mediagoblin.user_pages.views:atom_feed') + +add_route('mediagoblin.user_pages.media_collect', + '/u//m//collect/', + 'mediagoblin.user_pages.views:media_collect') + +add_route('mediagoblin.user_pages.user_collection', + '/u//collection//', + 'mediagoblin.user_pages.views:user_collection') + +add_route('mediagoblin.edit.edit_collection', + '/u//c//edit/', + 'mediagoblin.edit.views:edit_collection') + +add_route('mediagoblin.user_pages.collection_confirm_delete', + '/u//c//confirm-delete/', + 'mediagoblin.user_pages.views:collection_confirm_delete') + +add_route('mediagoblin.user_pages.collection_item_confirm_remove', + '/u//collection///confirm_remove/', + 'mediagoblin.user_pages.views:collection_item_confirm_remove') + +add_route('mediagoblin.user_pages.collection_atom_feed', + '/u//collection//atom/', + 'mediagoblin.user_pages.views:collection_atom_feed') + +add_route('mediagoblin.user_pages.processing_panel', + '/u//panel/', + 'mediagoblin.user_pages.views:processing_panel') + +# Stray edit routes +add_route('mediagoblin.edit.edit_media', + '/u//m//edit/', + 'mediagoblin.user_pages.views:edit_media') + +add_route('mediagoblin.edit.attachments', + '/u//m//attachments/', + 'mediagoblin.user_pages.views:edit_attachments') diff --git a/mediagoblin/webfinger/routing.py b/mediagoblin/webfinger/routing.py index 7e84a00a..18f9eb02 100644 --- a/mediagoblin/webfinger/routing.py +++ b/mediagoblin/webfinger/routing.py @@ -14,12 +14,10 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from routes.route import Route +from mediagoblin.routing import add_route -webfinger_well_known_routes = [ - Route('mediagoblin.webfinger.host_meta', '/host-meta', - controller='mediagoblin.webfinger.views:host_meta')] +add_route('mediagoblin.webfinger.host_meta', '/.well-known/host-meta', + 'mediagoblin.webfinger.views:host_meta') -webfinger_routes = [ - Route('mediagoblin.webfinger.xrd', '/xrd', - controller='mediagoblin.webfinger.views:xrd')] +add_route('mediagoblin.webfinger.xrd', '/webfinger/xrd', + 'mediagoblin.webfinger.views:xrd')