changeset 5543:d9b78d8f1db3

cleanup: replace redirect with WebOb exceptions All redirect does is to log "Generating 302 redirect" with logging the actual location and raise a WebOb HTTPFound exception, and the logging is redundant, as WebOb exceptions and their status codes are already logged. Instead, just raise the exception directly, which is both explicit and simpler (and finally, gets rid of "return redirect" which never really returns).
author Søren Løvborg <sorenl@unity3d.com>
date Wed, 09 Sep 2015 12:41:20 +0200
parents 1fc8d7e9f3ab
children feef81a369b3
files kallithea/controllers/admin/auth_settings.py kallithea/controllers/admin/defaults.py kallithea/controllers/admin/gists.py kallithea/controllers/admin/my_account.py kallithea/controllers/admin/permissions.py kallithea/controllers/admin/repo_groups.py kallithea/controllers/admin/repos.py kallithea/controllers/admin/settings.py kallithea/controllers/admin/user_groups.py kallithea/controllers/admin/users.py kallithea/controllers/changelog.py kallithea/controllers/changeset.py kallithea/controllers/compare.py kallithea/controllers/files.py kallithea/controllers/forks.py kallithea/controllers/login.py kallithea/controllers/pullrequests.py kallithea/lib/auth.py kallithea/lib/base.py
diffstat 19 files changed, 130 insertions(+), 142 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/controllers/admin/auth_settings.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/admin/auth_settings.py	Wed Sep 09 12:41:20 2015 +0200
@@ -28,8 +28,8 @@
 import traceback
 
 from pylons import request, tmpl_context as c, url
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
+from webob.exc import HTTPFound
 
 from kallithea.lib import helpers as h
 from kallithea.lib.compat import formatted_json
@@ -146,4 +146,4 @@
             h.flash(_('error occurred during update of auth settings'),
                     category='error')
 
-        return redirect(url('auth_home'))
+        raise HTTPFound(location=url('auth_home'))
--- a/kallithea/controllers/admin/defaults.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/admin/defaults.py	Wed Sep 09 12:41:20 2015 +0200
@@ -31,8 +31,8 @@
 from formencode import htmlfill
 
 from pylons import request, tmpl_context as c, url
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
+from webob.exc import HTTPFound
 
 from kallithea.lib import helpers as h
 from kallithea.lib.auth import LoginRequired, HasPermissionAllDecorator
@@ -112,7 +112,7 @@
             h.flash(_('Error occurred during update of defaults'),
                     category='error')
 
-        return redirect(url('defaults'))
+        raise HTTPFound(location=url('defaults'))
 
     def delete(self, id):
         """DELETE /defaults/id: Delete an existing item"""
--- a/kallithea/controllers/admin/gists.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/admin/gists.py	Wed Sep 09 12:41:20 2015 +0200
@@ -31,8 +31,8 @@
 import formencode.htmlfill
 
 from pylons import request, response, tmpl_context as c, url
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
+from webob.exc import HTTPFound, HTTPNotFound, HTTPForbidden
 
 from kallithea.model.forms import GistForm
 from kallithea.model.gist import GistModel
@@ -44,7 +44,6 @@
 from kallithea.lib.utils import jsonify
 from kallithea.lib.utils2 import safe_int, time_to_datetime
 from kallithea.lib.helpers import Page
-from webob.exc import HTTPNotFound, HTTPForbidden
 from sqlalchemy.sql.expression import or_
 from kallithea.lib.vcs.exceptions import VCSError, NodeNotChangedError
 
@@ -144,8 +143,8 @@
         except Exception as e:
             log.error(traceback.format_exc())
             h.flash(_('Error occurred during gist creation'), category='error')
-            return redirect(url('new_gist'))
-        return redirect(url('gist', gist_id=new_gist_id))
+            raise HTTPFound(location=url('new_gist'))
+        raise HTTPFound(location=url('gist', gist_id=new_gist_id))
 
     @LoginRequired()
     @NotAnonymous()
@@ -185,7 +184,7 @@
         else:
             raise HTTPForbidden()
 
-        return redirect(url('gists'))
+        raise HTTPFound(location=url('gists'))
 
     @LoginRequired()
     def show(self, gist_id, revision='tip', format='html', f_path=None):
@@ -270,7 +269,7 @@
                 h.flash(_('Error occurred during update of gist %s') % gist_id,
                         category='error')
 
-            return redirect(url('gist', gist_id=gist_id))
+            raise HTTPFound(location=url('gist', gist_id=gist_id))
 
         return rendered
 
--- a/kallithea/controllers/admin/my_account.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/admin/my_account.py	Wed Sep 09 12:41:20 2015 +0200
@@ -32,8 +32,8 @@
 from sqlalchemy import func
 from formencode import htmlfill
 from pylons import request, tmpl_context as c, url
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
+from webob.exc import HTTPFound
 
 from kallithea import EXTERN_TYPE_INTERNAL
 from kallithea.lib import helpers as h
@@ -69,7 +69,7 @@
         if c.user.username == User.DEFAULT_USER:
             h.flash(_("You can't edit this user since it's"
                       " crucial for entire application"), category='warning')
-            return redirect(url('users'))
+            raise HTTPFound(location=url('users'))
         c.EXTERN_TYPE_INTERNAL = EXTERN_TYPE_INTERNAL
 
     def _load_my_repos_data(self, watched=False):
@@ -144,7 +144,7 @@
                 h.flash(_('Error occurred during update of user %s') \
                         % form_result.get('username'), category='error')
         if update:
-            return redirect('my_account')
+            raise HTTPFound(location='my_account')
         return htmlfill.render(
             render('admin/my_account/my_account.html'),
             defaults=defaults,
@@ -225,7 +225,7 @@
             log.error(traceback.format_exc())
             h.flash(_('An error occurred during email saving'),
                     category='error')
-        return redirect(url('my_account_emails'))
+        raise HTTPFound(location=url('my_account_emails'))
 
     def my_account_emails_delete(self):
         email_id = request.POST.get('del_email_id')
@@ -233,7 +233,7 @@
         user_model.delete_extra_email(self.authuser.user_id, email_id)
         Session().commit()
         h.flash(_("Removed email from user"), category='success')
-        return redirect(url('my_account_emails'))
+        raise HTTPFound(location=url('my_account_emails'))
 
     def my_account_api_keys(self):
         c.active = 'api_keys'
@@ -257,7 +257,7 @@
         ApiKeyModel().create(self.authuser.user_id, description, lifetime)
         Session().commit()
         h.flash(_("API key successfully created"), category='success')
-        return redirect(url('my_account_api_keys'))
+        raise HTTPFound(location=url('my_account_api_keys'))
 
     def my_account_api_keys_delete(self):
         api_key = request.POST.get('del_api_key')
@@ -274,4 +274,4 @@
             Session().commit()
             h.flash(_("API key successfully deleted"), category='success')
 
-        return redirect(url('my_account_api_keys'))
+        raise HTTPFound(location=url('my_account_api_keys'))
--- a/kallithea/controllers/admin/permissions.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/admin/permissions.py	Wed Sep 09 12:41:20 2015 +0200
@@ -32,8 +32,8 @@
 from formencode import htmlfill
 
 from pylons import request, tmpl_context as c, url
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
+from webob.exc import HTTPFound
 
 from kallithea.lib import helpers as h
 from kallithea.lib.auth import LoginRequired, HasPermissionAllDecorator
@@ -139,7 +139,7 @@
                 h.flash(_('Error occurred during update of permissions'),
                         category='error')
 
-            return redirect(url('admin_permissions'))
+            raise HTTPFound(location=url('admin_permissions'))
 
         c.user = User.get_default_user()
         defaults = {'anonymous': c.user.active}
--- a/kallithea/controllers/admin/repo_groups.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/admin/repo_groups.py	Wed Sep 09 12:41:20 2015 +0200
@@ -33,9 +33,8 @@
 from formencode import htmlfill
 
 from pylons import request, tmpl_context as c, url
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _, ungettext
-from webob.exc import HTTPForbidden, HTTPNotFound, HTTPInternalServerError
+from webob.exc import HTTPFound, HTTPForbidden, HTTPNotFound, HTTPInternalServerError
 
 import kallithea
 from kallithea.lib import helpers as h
@@ -189,10 +188,10 @@
                     % request.POST.get('group_name'), category='error')
             parent_group_id = form_result['group_parent_id']
             #TODO: maybe we should get back to the main view, not the admin one
-            return redirect(url('repos_groups', parent_group=parent_group_id))
+            raise HTTPFound(location=url('repos_groups', parent_group=parent_group_id))
         h.flash(_('Created repository group %s') % gr.group_name,
                 category='success')
-        return redirect(url('repos_group_home', group_name=gr.group_name))
+        raise HTTPFound(location=url('repos_group_home', group_name=gr.group_name))
 
     def new(self):
         """GET /repo_groups/new: Form to create a new item"""
@@ -266,7 +265,7 @@
             h.flash(_('Error occurred during update of repository group %s') \
                     % request.POST.get('group_name'), category='error')
 
-        return redirect(url('edit_repo_group', group_name=group_name))
+        raise HTTPFound(location=url('edit_repo_group', group_name=group_name))
 
     @HasRepoGroupPermissionAnyDecorator('group.admin')
     def delete(self, group_name):
@@ -283,13 +282,13 @@
         if repos:
             h.flash(_('This group contains %s repositories and cannot be '
                       'deleted') % len(repos), category='warning')
-            return redirect(url('repos_groups'))
+            raise HTTPFound(location=url('repos_groups'))
 
         children = gr.children.all()
         if children:
             h.flash(_('This group contains %s subgroups and cannot be deleted'
                       % (len(children))), category='warning')
-            return redirect(url('repos_groups'))
+            raise HTTPFound(location=url('repos_groups'))
 
         try:
             RepoGroupModel().delete(group_name)
@@ -303,8 +302,8 @@
                     % group_name, category='error')
 
         if gr.parent_group:
-            return redirect(url('repos_group_home', group_name=gr.parent_group.group_name))
-        return redirect(url('repos_groups'))
+            raise HTTPFound(location=url('repos_group_home', group_name=gr.parent_group.group_name))
+        raise HTTPFound(location=url('repos_groups'))
 
     def show_by_name(self, group_name):
         """
@@ -404,7 +403,7 @@
             if self._revoke_perms_on_yourself(form_result):
                 msg = _('Cannot revoke permission for yourself as admin')
                 h.flash(msg, category='warning')
-                return redirect(url('edit_repo_group_perms', group_name=group_name))
+                raise HTTPFound(location=url('edit_repo_group_perms', group_name=group_name))
         recursive = form_result['recursive']
         # iterate over all members(if in recursive mode) of this groups and
         # set the permissions !
@@ -418,7 +417,7 @@
         #              repo_name, self.ip_addr, self.sa)
         Session().commit()
         h.flash(_('Repository group permissions updated'), category='success')
-        return redirect(url('edit_repo_group_perms', group_name=group_name))
+        raise HTTPFound(location=url('edit_repo_group_perms', group_name=group_name))
 
     @HasRepoGroupPermissionAnyDecorator('group.admin')
     def delete_perms(self, group_name):
--- a/kallithea/controllers/admin/repos.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/admin/repos.py	Wed Sep 09 12:41:20 2015 +0200
@@ -29,11 +29,10 @@
 import traceback
 import formencode
 from formencode import htmlfill
-from webob.exc import HTTPInternalServerError, HTTPForbidden, HTTPNotFound
 from pylons import request, tmpl_context as c, url
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
 from sqlalchemy.sql.expression import func
+from webob.exc import HTTPFound, HTTPInternalServerError, HTTPForbidden, HTTPNotFound
 
 from kallithea.lib import helpers as h
 from kallithea.lib.auth import LoginRequired, \
@@ -71,7 +70,7 @@
 
         if repo_obj is None:
             h.not_mapped_error(repo_name)
-            return redirect(url('repos'))
+            raise HTTPFound(location=url('repos'))
 
         return repo_obj
 
@@ -152,9 +151,9 @@
             msg = (_('Error creating repository %s')
                    % form_result.get('repo_name'))
             h.flash(msg, category='error')
-            return redirect(url('home'))
+            raise HTTPFound(location=url('home'))
 
-        return redirect(h.url('repo_creating_home',
+        raise HTTPFound(location=h.url('repo_creating_home',
                               repo_name=form_result['repo_name_full'],
                               task_id=task_id))
 
@@ -282,7 +281,7 @@
             log.error(traceback.format_exc())
             h.flash(_('Error occurred during update of repository %s') \
                     % repo_name, category='error')
-        return redirect(url('edit_repo', repo_name=changed_name))
+        raise HTTPFound(location=url('edit_repo', repo_name=changed_name))
 
     @HasRepoPermissionAllDecorator('repository.admin')
     def delete(self, repo_name):
@@ -299,7 +298,7 @@
         repo = repo_model.get_by_repo_name(repo_name)
         if not repo:
             h.not_mapped_error(repo_name)
-            return redirect(url('repos'))
+            raise HTTPFound(location=url('repos'))
         try:
             _forks = repo.forks.count()
             handle_forks = None
@@ -327,8 +326,8 @@
                     category='error')
 
         if repo.group:
-            return redirect(url('repos_group_home', group_name=repo.group.group_name))
-        return redirect(url('repos'))
+            raise HTTPFound(location=url('repos_group_home', group_name=repo.group.group_name))
+        raise HTTPFound(location=url('repos'))
 
     @HasRepoPermissionAllDecorator('repository.admin')
     def edit(self, repo_name):
@@ -372,7 +371,7 @@
         #              repo_name, self.ip_addr, self.sa)
         Session().commit()
         h.flash(_('Repository permissions updated'), category='success')
-        return redirect(url('edit_repo_perms', repo_name=repo_name))
+        raise HTTPFound(location=url('edit_repo_perms', repo_name=repo_name))
 
     def edit_permissions_revoke(self, repo_name):
         try:
@@ -409,7 +408,7 @@
         c.active = 'fields'
         if request.POST:
 
-            return redirect(url('repo_edit_fields'))
+            raise HTTPFound(location=url('repo_edit_fields'))
         return render('admin/repos/repo_edit.html')
 
     @HasRepoPermissionAllDecorator('repository.admin')
@@ -431,7 +430,7 @@
             if isinstance(e, formencode.Invalid):
                 msg += ". " + e.msg
             h.flash(msg, category='error')
-        return redirect(url('edit_repo_fields', repo_name=repo_name))
+        raise HTTPFound(location=url('edit_repo_fields', repo_name=repo_name))
 
     @HasRepoPermissionAllDecorator('repository.admin')
     def delete_repo_field(self, repo_name, field_id):
@@ -443,7 +442,7 @@
             log.error(traceback.format_exc())
             msg = _('An error occurred during removal of field')
             h.flash(msg, category='error')
-        return redirect(url('edit_repo_fields', repo_name=repo_name))
+        raise HTTPFound(location=url('edit_repo_fields', repo_name=repo_name))
 
     @HasRepoPermissionAllDecorator('repository.admin')
     def edit_advanced(self, repo_name):
@@ -468,7 +467,7 @@
 
         c.active = 'advanced'
         if request.POST:
-            return redirect(url('repo_edit_advanced'))
+            raise HTTPFound(location=url('repo_edit_advanced'))
         return htmlfill.render(
             render('admin/repos/repo_edit.html'),
             defaults=defaults,
@@ -495,7 +494,7 @@
             h.flash(_('An error occurred during setting this'
                       ' repository in public journal'),
                     category='error')
-        return redirect(url('edit_repo_advanced', repo_name=repo_name))
+        raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name))
 
 
     @HasRepoPermissionAllDecorator('repository.admin')
@@ -521,7 +520,7 @@
             h.flash(_('An error occurred during this operation'),
                     category='error')
 
-        return redirect(url('edit_repo_advanced', repo_name=repo_name))
+        raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name))
 
     @HasRepoPermissionAllDecorator('repository.admin')
     def edit_advanced_locking(self, repo_name):
@@ -542,7 +541,7 @@
             log.error(traceback.format_exc())
             h.flash(_('An error occurred during unlocking'),
                     category='error')
-        return redirect(url('edit_repo_advanced', repo_name=repo_name))
+        raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name))
 
     @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
     def toggle_locking(self, repo_name):
@@ -567,7 +566,7 @@
             log.error(traceback.format_exc())
             h.flash(_('An error occurred during unlocking'),
                     category='error')
-        return redirect(url('summary_home', repo_name=repo_name))
+        raise HTTPFound(location=url('summary_home', repo_name=repo_name))
 
     @HasRepoPermissionAllDecorator('repository.admin')
     def edit_caches(self, repo_name):
@@ -586,7 +585,7 @@
                 h.flash(_('An error occurred during cache invalidation'),
                         category='error')
 
-            return redirect(url('edit_repo_caches', repo_name=c.repo_name))
+            raise HTTPFound(location=url('edit_repo_caches', repo_name=c.repo_name))
         return render('admin/repos/repo_edit.html')
 
     @HasRepoPermissionAllDecorator('repository.admin')
@@ -603,7 +602,7 @@
                 log.error(traceback.format_exc())
                 h.flash(_('An error occurred during pull from remote location'),
                         category='error')
-            return redirect(url('edit_repo_remote', repo_name=c.repo_name))
+            raise HTTPFound(location=url('edit_repo_remote', repo_name=c.repo_name))
         return render('admin/repos/repo_edit.html')
 
     @HasRepoPermissionAllDecorator('repository.admin')
@@ -636,6 +635,6 @@
                 log.error(traceback.format_exc())
                 h.flash(_('An error occurred during deletion of repository stats'),
                         category='error')
-            return redirect(url('edit_repo_statistics', repo_name=c.repo_name))
+            raise HTTPFound(location=url('edit_repo_statistics', repo_name=c.repo_name))
 
         return render('admin/repos/repo_edit.html')
--- a/kallithea/controllers/admin/settings.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/admin/settings.py	Wed Sep 09 12:41:20 2015 +0200
@@ -31,8 +31,8 @@
 
 from formencode import htmlfill
 from pylons import request, tmpl_context as c, url, config
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
+from webob.exc import HTTPFound
 
 from kallithea.lib import helpers as h
 from kallithea.lib.auth import LoginRequired, HasPermissionAllDecorator
@@ -218,7 +218,7 @@
                  for repo_name in added) or '-',
                  ', '.join(h.escape(safe_unicode(repo_name)) for repo_name in removed) or '-')),
                 category='success')
-            return redirect(url('admin_settings_mapping'))
+            raise HTTPFound(location=url('admin_settings_mapping'))
 
         defaults = Setting.get_app_settings()
         defaults.update(self._get_hg_ui_settings())
@@ -278,7 +278,7 @@
                           'application settings'),
                           category='error')
 
-            return redirect(url('admin_settings_global'))
+            raise HTTPFound(location=url('admin_settings_global'))
 
         defaults = Setting.get_app_settings()
         defaults.update(self._get_hg_ui_settings())
@@ -336,7 +336,7 @@
                           'visualisation settings'),
                         category='error')
 
-            return redirect(url('admin_settings_visual'))
+            raise HTTPFound(location=url('admin_settings_visual'))
 
         defaults = Setting.get_app_settings()
         defaults.update(self._get_hg_ui_settings())
@@ -359,7 +359,7 @@
                                'Kallithea version: %s' % c.kallithea_version)
             if not test_email:
                 h.flash(_('Please enter email address'), category='error')
-                return redirect(url('admin_settings_email'))
+                raise HTTPFound(location=url('admin_settings_email'))
 
             test_email_txt_body = EmailNotificationModel()\
                 .get_email_tmpl(EmailNotificationModel.TYPE_DEFAULT,
@@ -374,7 +374,7 @@
                      test_email_txt_body, test_email_html_body)
 
             h.flash(_('Send email task created'), category='success')
-            return redirect(url('admin_settings_email'))
+            raise HTTPFound(location=url('admin_settings_email'))
 
         defaults = Setting.get_app_settings()
         defaults.update(self._get_hg_ui_settings())
@@ -425,7 +425,7 @@
                     h.flash(_('Error occurred during hook creation'),
                             category='error')
 
-                return redirect(url('admin_settings_hooks'))
+                raise HTTPFound(location=url('admin_settings_hooks'))
 
         defaults = Setting.get_app_settings()
         defaults.update(self._get_hg_ui_settings())
@@ -449,7 +449,7 @@
             full_index = request.POST.get('full_index', False)
             run_task(tasks.whoosh_index, repo_location, full_index)
             h.flash(_('Whoosh reindex task scheduled'), category='success')
-            return redirect(url('admin_settings_search'))
+            raise HTTPFound(location=url('admin_settings_search'))
 
         defaults = Setting.get_app_settings()
         defaults.update(self._get_hg_ui_settings())
--- a/kallithea/controllers/admin/user_groups.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/admin/user_groups.py	Wed Sep 09 12:41:20 2015 +0200
@@ -31,8 +31,8 @@
 
 from formencode import htmlfill
 from pylons import request, tmpl_context as c, url, config
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
+from webob.exc import HTTPFound
 
 from sqlalchemy.orm import joinedload
 from sqlalchemy.sql.expression import func
@@ -163,7 +163,7 @@
             h.flash(_('Error occurred during creation of user group %s') \
                     % request.POST.get('users_group_name'), category='error')
 
-        return redirect(url('users_groups'))
+        raise HTTPFound(location=url('users_groups'))
 
     @HasPermissionAnyDecorator('hg.admin', 'hg.usergroup.create.true')
     def new(self, format='html'):
@@ -224,7 +224,7 @@
             h.flash(_('Error occurred during update of user group %s') \
                     % request.POST.get('users_group_name'), category='error')
 
-        return redirect(url('edit_users_group', id=id))
+        raise HTTPFound(location=url('edit_users_group', id=id))
 
     @HasUserGroupPermissionAnyDecorator('usergroup.admin')
     def delete(self, id):
@@ -246,7 +246,7 @@
             log.error(traceback.format_exc())
             h.flash(_('An error occurred during deletion of user group'),
                     category='error')
-        return redirect(url('users_groups'))
+        raise HTTPFound(location=url('users_groups'))
 
     def show(self, id, format='html'):
         """GET /user_groups/id: Show a specific item"""
@@ -312,13 +312,13 @@
                                                  form['perms_updates'])
         except RepoGroupAssignmentError:
             h.flash(_('Target group cannot be the same'), category='error')
-            return redirect(url('edit_user_group_perms', id=id))
+            raise HTTPFound(location=url('edit_user_group_perms', id=id))
         #TODO: implement this
         #action_logger(self.authuser, 'admin_changed_repo_permissions',
         #              repo_name, self.ip_addr, self.sa)
         Session().commit()
         h.flash(_('User group permissions updated'), category='success')
-        return redirect(url('edit_user_group_perms', id=id))
+        raise HTTPFound(location=url('edit_user_group_perms', id=id))
 
     @HasUserGroupPermissionAnyDecorator('usergroup.admin')
     def delete_perms(self, id):
@@ -444,7 +444,7 @@
             h.flash(_('An error occurred during permissions saving'),
                     category='error')
 
-        return redirect(url('edit_user_group_default_perms', id=id))
+        raise HTTPFound(location=url('edit_user_group_default_perms', id=id))
 
     @HasUserGroupPermissionAnyDecorator('usergroup.admin')
     def edit_advanced(self, id):
--- a/kallithea/controllers/admin/users.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/admin/users.py	Wed Sep 09 12:41:20 2015 +0200
@@ -31,10 +31,9 @@
 
 from formencode import htmlfill
 from pylons import request, tmpl_context as c, url, config
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
 from sqlalchemy.sql.expression import func
-from webob.exc import HTTPNotFound
+from webob.exc import HTTPFound, HTTPNotFound
 
 import kallithea
 from kallithea.lib.exceptions import DefaultUserException, \
@@ -148,7 +147,7 @@
             log.error(traceback.format_exc())
             h.flash(_('Error occurred during creation of user %s') \
                     % request.POST.get('username'), category='error')
-        return redirect(url('users'))
+        raise HTTPFound(location=url('users'))
 
     def new(self, format='html'):
         """GET /users/new: Form to create a new item"""
@@ -201,7 +200,7 @@
             log.error(traceback.format_exc())
             h.flash(_('Error occurred during update of user %s') \
                     % form_result.get('username'), category='error')
-        return redirect(url('edit_user', id=id))
+        raise HTTPFound(location=url('edit_user', id=id))
 
     def delete(self, id):
         """DELETE /users/id: Delete an existing item"""
@@ -222,7 +221,7 @@
             log.error(traceback.format_exc())
             h.flash(_('An error occurred during deletion of user'),
                     category='error')
-        return redirect(url('users'))
+        raise HTTPFound(location=url('users'))
 
     def show(self, id, format='html'):
         """GET /users/id: Show a specific item"""
@@ -306,7 +305,7 @@
         ApiKeyModel().create(c.user.user_id, description, lifetime)
         Session().commit()
         h.flash(_("API key successfully created"), category='success')
-        return redirect(url('edit_user_api_keys', id=c.user.user_id))
+        raise HTTPFound(location=url('edit_user_api_keys', id=c.user.user_id))
 
     def delete_api_key(self, id):
         c.user = self._get_user_or_raise_if_default(id)
@@ -324,7 +323,7 @@
             Session().commit()
             h.flash(_("API key successfully deleted"), category='success')
 
-        return redirect(url('edit_user_api_keys', id=c.user.user_id))
+        raise HTTPFound(location=url('edit_user_api_keys', id=c.user.user_id))
 
     def update_account(self, id):
         pass
@@ -387,7 +386,7 @@
             log.error(traceback.format_exc())
             h.flash(_('An error occurred during permissions saving'),
                     category='error')
-        return redirect(url('edit_user_perms', id=id))
+        raise HTTPFound(location=url('edit_user_perms', id=id))
 
     def edit_emails(self, id):
         c.user = self._get_user_or_raise_if_default(id)
@@ -420,7 +419,7 @@
             log.error(traceback.format_exc())
             h.flash(_('An error occurred during email saving'),
                     category='error')
-        return redirect(url('edit_user_emails', id=id))
+        raise HTTPFound(location=url('edit_user_emails', id=id))
 
     def delete_email(self, id):
         """DELETE /user_emails_delete/id: Delete an existing item"""
@@ -431,7 +430,7 @@
         user_model.delete_extra_email(id, email_id)
         Session().commit()
         h.flash(_("Removed email from user"), category='success')
-        return redirect(url('edit_user_emails', id=id))
+        raise HTTPFound(location=url('edit_user_emails', id=id))
 
     def edit_ips(self, id):
         c.user = self._get_user_or_raise_if_default(id)
@@ -470,8 +469,8 @@
                     category='error')
 
         if 'default_user' in request.POST:
-            return redirect(url('admin_permissions_ips'))
-        return redirect(url('edit_user_ips', id=id))
+            raise HTTPFound(location=url('admin_permissions_ips'))
+        raise HTTPFound(location=url('edit_user_ips', id=id))
 
     def delete_ip(self, id):
         """DELETE /user_ips_delete/id: Delete an existing item"""
@@ -483,5 +482,5 @@
         h.flash(_("Removed IP address from user whitelist"), category='success')
 
         if 'default_user' in request.POST:
-            return redirect(url('admin_permissions_ips'))
-        return redirect(url('edit_user_ips', id=id))
+            raise HTTPFound(location=url('admin_permissions_ips'))
+        raise HTTPFound(location=url('edit_user_ips', id=id))
--- a/kallithea/controllers/changelog.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/changelog.py	Wed Sep 09 12:41:20 2015 +0200
@@ -29,9 +29,8 @@
 import traceback
 
 from pylons import request, url, session, tmpl_context as c
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
-from webob.exc import HTTPNotFound, HTTPBadRequest
+from webob.exc import HTTPFound, HTTPNotFound, HTTPBadRequest
 
 import kallithea.lib.helpers as h
 from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
@@ -99,8 +98,8 @@
         if request.GET.get('set'):
             request.GET.pop('set', None)
             if revision is None:
-                return redirect(url('changelog_home', repo_name=repo_name, **request.GET))
-            return redirect(url('changelog_file_home', repo_name=repo_name, revision=revision, f_path=f_path, **request.GET))
+                raise HTTPFound(location=url('changelog_home', repo_name=repo_name, **request.GET))
+            raise HTTPFound(location=url('changelog_file_home', repo_name=repo_name, revision=revision, f_path=f_path, **request.GET))
 
         limit = 2000
         default = 100
@@ -118,7 +117,7 @@
             branch_name not in c.db_repo_scm_instance.branches and
             branch_name not in c.db_repo_scm_instance.closed_branches and
             not revision):
-            return redirect(url('changelog_file_home', repo_name=c.repo_name,
+            raise HTTPFound(location=url('changelog_file_home', repo_name=c.repo_name,
                                     revision=branch_name, f_path=f_path or ''))
 
         if revision == 'tip':
@@ -140,7 +139,7 @@
                         collection = cs.get_file_history(f_path)
                     except RepositoryError as e:
                         h.flash(safe_str(e), category='warning')
-                        redirect(h.url('changelog_home', repo_name=repo_name))
+                        raise HTTPFound(location=h.url('changelog_home', repo_name=repo_name))
                 collection = list(reversed(collection))
             else:
                 collection = c.db_repo_scm_instance.get_changesets(start=0, end=revision,
@@ -155,11 +154,11 @@
             c.statuses = c.db_repo.statuses(page_revisions)
         except EmptyRepositoryError as e:
             h.flash(safe_str(e), category='warning')
-            return redirect(url('summary_home', repo_name=c.repo_name))
+            raise HTTPFound(location=url('summary_home', repo_name=c.repo_name))
         except (RepositoryError, ChangesetDoesNotExistError, Exception) as e:
             log.error(traceback.format_exc())
             h.flash(safe_str(e), category='error')
-            return redirect(url('changelog_home', repo_name=c.repo_name))
+            raise HTTPFound(location=url('changelog_home', repo_name=c.repo_name))
 
         c.branch_name = branch_name
         c.branch_filters = [('', _('None'))] + \
--- a/kallithea/controllers/changeset.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/changeset.py	Wed Sep 09 12:41:20 2015 +0200
@@ -29,13 +29,12 @@
 import logging
 import traceback
 from collections import defaultdict
-from webob.exc import HTTPForbidden, HTTPBadRequest, HTTPNotFound
 
 from pylons import tmpl_context as c, request, response
 from pylons.i18n.translation import _
-from pylons.controllers.util import redirect
+from webob.exc import HTTPFound, HTTPForbidden, HTTPBadRequest, HTTPNotFound
+
 from kallithea.lib.utils import jsonify
-
 from kallithea.lib.vcs.exceptions import RepositoryError, \
     ChangesetDoesNotExistError
 
@@ -383,7 +382,7 @@
                 msg = _('Changing status on a changeset associated with '
                         'a closed pull request is not allowed')
                 h.flash(msg, category='warning')
-                return redirect(h.url('changeset_home', repo_name=repo_name,
+                raise HTTPFound(location=h.url('changeset_home', repo_name=repo_name,
                                       revision=revision))
         action_logger(self.authuser,
                       'user_commented_revision:%s' % revision,
@@ -392,7 +391,7 @@
         Session().commit()
 
         if not request.environ.get('HTTP_X_PARTIAL_XHR'):
-            return redirect(h.url('changeset_home', repo_name=repo_name,
+            raise HTTPFound(location=h.url('changeset_home', repo_name=repo_name,
                                   revision=revision))
         #only ajax below
         data = {
--- a/kallithea/controllers/compare.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/compare.py	Wed Sep 09 12:41:20 2015 +0200
@@ -30,10 +30,9 @@
 import logging
 import re
 
-from webob.exc import HTTPBadRequest
 from pylons import request, tmpl_context as c, url
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
+from webob.exc import HTTPFound, HTTPBadRequest
 
 from kallithea.lib.utils2 import safe_str
 from kallithea.lib.vcs.utils.hgcompat import unionrepo
@@ -207,19 +206,19 @@
             msg = 'Could not find org repo %s' % org_repo
             log.error(msg)
             h.flash(msg, category='error')
-            return redirect(url('compare_home', repo_name=c.repo_name))
+            raise HTTPFound(location=url('compare_home', repo_name=c.repo_name))
 
         if other_repo is None:
             msg = 'Could not find other repo %s' % other_repo
             log.error(msg)
             h.flash(msg, category='error')
-            return redirect(url('compare_home', repo_name=c.repo_name))
+            raise HTTPFound(location=url('compare_home', repo_name=c.repo_name))
 
         if org_repo.scm_instance.alias != other_repo.scm_instance.alias:
             msg = 'compare of two different kind of remote repos not available'
             log.error(msg)
             h.flash(msg, category='error')
-            return redirect(url('compare_home', repo_name=c.repo_name))
+            raise HTTPFound(location=url('compare_home', repo_name=c.repo_name))
 
         c.a_rev = self._get_ref_rev(org_repo, org_ref_type, org_ref_name,
             returnempty=True)
--- a/kallithea/controllers/files.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/files.py	Wed Sep 09 12:41:20 2015 +0200
@@ -33,9 +33,9 @@
 
 from pylons import request, response, tmpl_context as c, url
 from pylons.i18n.translation import _
-from pylons.controllers.util import redirect
+from webob.exc import HTTPFound
+
 from kallithea.lib.utils import jsonify, action_logger
-
 from kallithea.lib import diffs
 from kallithea.lib import helpers as h
 
@@ -306,7 +306,7 @@
                 % (h.person_by_id(repo.locked[0]),
                    h.fmt_date(h.time_to_datetime(repo.locked[1]))),
                 'warning')
-            return redirect(h.url('files_home',
+            raise HTTPFound(location=h.url('files_home',
                                   repo_name=repo_name, revision='tip'))
 
         # check if revision is a branch identifier- basically we cannot
@@ -316,7 +316,7 @@
         if revision not in _branches.keys() + _branches.values():
             h.flash(_('You can only delete files with revision '
                       'being a valid branch '), category='warning')
-            return redirect(h.url('files_home',
+            raise HTTPFound(location=h.url('files_home',
                                   repo_name=repo_name, revision='tip',
                                   f_path=f_path))
 
@@ -352,7 +352,7 @@
             except Exception:
                 log.error(traceback.format_exc())
                 h.flash(_('Error occurred during commit'), category='error')
-            return redirect(url('changeset_home',
+            raise HTTPFound(location=url('changeset_home',
                                 repo_name=c.repo_name, revision='tip'))
 
         return render('files/files_delete.html')
@@ -366,7 +366,7 @@
                 % (h.person_by_id(repo.locked[0]),
                    h.fmt_date(h.time_to_datetime(repo.locked[1]))),
                 'warning')
-            return redirect(h.url('files_home',
+            raise HTTPFound(location=h.url('files_home',
                                   repo_name=repo_name, revision='tip'))
 
         # check if revision is a branch identifier- basically we cannot
@@ -376,7 +376,7 @@
         if revision not in _branches.keys() + _branches.values():
             h.flash(_('You can only edit files with revision '
                       'being a valid branch '), category='warning')
-            return redirect(h.url('files_home',
+            raise HTTPFound(location=h.url('files_home',
                                   repo_name=repo_name, revision='tip',
                                   f_path=f_path))
 
@@ -386,7 +386,7 @@
         c.file = self.__get_filenode(c.cs, f_path)
 
         if c.file.is_binary:
-            return redirect(url('files_home', repo_name=c.repo_name,
+            raise HTTPFound(location=url('files_home', repo_name=c.repo_name,
                             revision=c.cs.raw_id, f_path=f_path))
         c.default_message = _('Edited file %s via Kallithea') % (f_path)
         c.f_path = f_path
@@ -405,7 +405,7 @@
 
             if content == old_content:
                 h.flash(_('No changes'), category='warning')
-                return redirect(url('changeset_home', repo_name=c.repo_name,
+                raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
                                     revision='tip'))
             try:
                 self.scm_model.commit_change(repo=c.db_repo_scm_instance,
@@ -418,7 +418,7 @@
             except Exception:
                 log.error(traceback.format_exc())
                 h.flash(_('Error occurred during commit'), category='error')
-            return redirect(url('changeset_home',
+            raise HTTPFound(location=url('changeset_home',
                                 repo_name=c.repo_name, revision='tip'))
 
         return render('files/files_edit.html')
@@ -433,7 +433,7 @@
                 % (h.person_by_id(repo.locked[0]),
                    h.fmt_date(h.time_to_datetime(repo.locked[1]))),
                   'warning')
-            return redirect(h.url('files_home',
+            raise HTTPFound(location=h.url('files_home',
                                   repo_name=repo_name, revision='tip'))
 
         r_post = request.POST
@@ -462,11 +462,11 @@
 
             if not content:
                 h.flash(_('No content'), category='warning')
-                return redirect(url('changeset_home', repo_name=c.repo_name,
+                raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
                                     revision='tip'))
             if not filename:
                 h.flash(_('No filename'), category='warning')
-                return redirect(url('changeset_home', repo_name=c.repo_name,
+                raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
                                     revision='tip'))
             #strip all crap out of file, just leave the basename
             filename = os.path.basename(filename)
@@ -492,14 +492,14 @@
             except NonRelativePathError as e:
                 h.flash(_('Location must be relative path and must not '
                           'contain .. in path'), category='warning')
-                return redirect(url('changeset_home', repo_name=c.repo_name,
+                raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
                                     revision='tip'))
             except (NodeError, NodeAlreadyExistsError) as e:
                 h.flash(_(e), category='error')
             except Exception:
                 log.error(traceback.format_exc())
                 h.flash(_('Error occurred during commit'), category='error')
-            return redirect(url('changeset_home',
+            raise HTTPFound(location=url('changeset_home',
                                 repo_name=c.repo_name, revision='tip'))
 
         return render('files/files_add.html')
@@ -620,7 +620,7 @@
                 _url = url('files_home', repo_name=c.repo_name,
                            revision=diff1, f_path=c.f_path)
 
-            return redirect(_url)
+            raise HTTPFound(location=_url)
         try:
             if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
                 c.changeset_1 = c.db_repo_scm_instance.get_changeset(diff1)
@@ -655,7 +655,7 @@
                 node2 = FileNode(f_path, '', changeset=c.changeset_2)
         except (RepositoryError, NodeError):
             log.error(traceback.format_exc())
-            return redirect(url('files_home', repo_name=c.repo_name,
+            raise HTTPFound(location=url('files_home', repo_name=c.repo_name,
                                 f_path=f_path))
 
         if c.action == 'download':
--- a/kallithea/controllers/forks.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/forks.py	Wed Sep 09 12:41:20 2015 +0200
@@ -31,8 +31,8 @@
 from formencode import htmlfill
 
 from pylons import tmpl_context as c, request, url
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
+from webob.exc import HTTPFound
 
 import kallithea.lib.helpers as h
 
@@ -77,7 +77,7 @@
 
         if c.repo_info is None:
             h.not_mapped_error(repo_name)
-            return redirect(url('repos'))
+            raise HTTPFound(location=url('repos'))
 
         c.default_user_id = User.get_default_user().user_id
         c.in_public_journal = UserFollowing.query()\
@@ -137,7 +137,7 @@
         c.repo_info = Repository.get_by_repo_name(repo_name)
         if not c.repo_info:
             h.not_mapped_error(repo_name)
-            return redirect(url('home'))
+            raise HTTPFound(location=url('home'))
 
         defaults = self.__load_data(repo_name)
 
@@ -186,6 +186,6 @@
             h.flash(_('An error occurred during repository forking %s') %
                     repo_name, category='error')
 
-        return redirect(h.url('repo_creating_home',
+        raise HTTPFound(location=h.url('repo_creating_home',
                               repo_name=form_result['repo_name_full'],
                               task_id=task_id))
--- a/kallithea/controllers/login.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/login.py	Wed Sep 09 12:41:20 2015 +0200
@@ -31,10 +31,9 @@
 import formencode
 
 from formencode import htmlfill
+from pylons.i18n.translation import _
+from pylons import request, session, tmpl_context as c, url
 from webob.exc import HTTPFound, HTTPBadRequest
-from pylons.i18n.translation import _
-from pylons.controllers.util import redirect
-from pylons import request, session, tmpl_context as c, url
 
 import kallithea.lib.helpers as h
 from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator
@@ -152,7 +151,7 @@
                 h.flash(_('You have successfully registered into Kallithea'),
                         category='success')
                 Session().commit()
-                return redirect(url('login_home'))
+                raise HTTPFound(location=url('login_home'))
 
             except formencode.Invalid as errors:
                 return htmlfill.render(
@@ -196,7 +195,7 @@
                 redirect_link = UserModel().send_reset_password_email(form_result)
                 h.flash(_('A password reset confirmation code has been sent'),
                             category='success')
-                return redirect(redirect_link)
+                raise HTTPFound(location=redirect_link)
 
             except formencode.Invalid as errors:
                 return htmlfill.render(
@@ -249,12 +248,12 @@
 
         UserModel().reset_password(form_result['email'], form_result['password'])
         h.flash(_('Successfully updated password'), category='success')
-        return redirect(url('login_home'))
+        raise HTTPFound(location=url('login_home'))
 
     def logout(self):
         session.delete()
         log.info('Logging out and deleting session for user')
-        redirect(url('home'))
+        raise HTTPFound(location=url('home'))
 
     def authentication_token(self):
         """Return the CSRF protection token for the session - just like it
--- a/kallithea/controllers/pullrequests.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/controllers/pullrequests.py	Wed Sep 09 12:41:20 2015 +0200
@@ -30,11 +30,9 @@
 import formencode
 import re
 
-from webob.exc import HTTPNotFound, HTTPForbidden, HTTPBadRequest
-
 from pylons import request, tmpl_context as c, url
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
+from webob.exc import HTTPFound, HTTPNotFound, HTTPForbidden, HTTPBadRequest
 
 from kallithea.lib.vcs.utils.hgcompat import unionrepo
 from kallithea.lib.compat import json
@@ -237,7 +235,7 @@
         except EmptyRepositoryError as e:
             h.flash(h.literal(_('There are no changesets yet')),
                     category='warning')
-            redirect(url('summary_home', repo_name=org_repo.repo_name))
+            raise HTTPFound(location=url('summary_home', repo_name=org_repo.repo_name))
 
         org_rev = request.GET.get('rev_end')
         # rev_start is not directly useful - its parent could however be used
@@ -369,9 +367,9 @@
             h.flash(_('Error occurred while creating pull request'),
                     category='error')
             log.error(traceback.format_exc())
-            return redirect(url('pullrequest_home', repo_name=repo_name))
+            raise HTTPFound(location=url('pullrequest_home', repo_name=repo_name))
 
-        return redirect(pull_request.url())
+        raise HTTPFound(location=pull_request.url())
 
     def create_update(self, old_pull_request, updaterev, title, description, reviewers_ids):
         org_repo = RepoModel()._get_repo(old_pull_request.org_repo.repo_name)
@@ -456,7 +454,7 @@
             h.flash(_('Error occurred while creating pull request'),
                     category='error')
             log.error(traceback.format_exc())
-            return redirect(old_pull_request.url())
+            raise HTTPFound(location=old_pull_request.url())
 
         ChangesetCommentsModel().create(
             text=_('Closed, replaced by %s .') % pull_request.url(canonical=True),
@@ -470,7 +468,7 @@
         h.flash(_('Pull request update created'),
                 category='success')
 
-        return redirect(pull_request.url())
+        raise HTTPFound(location=pull_request.url())
 
     # pullrequest_post for PR editing
     @LoginRequired()
@@ -513,7 +511,7 @@
         Session().commit()
         h.flash(_('Pull request updated'), category='success')
 
-        return redirect(pull_request.url())
+        raise HTTPFound(location=pull_request.url())
 
     @LoginRequired()
     @NotAnonymous()
@@ -528,7 +526,7 @@
             Session().commit()
             h.flash(_('Successfully deleted pull request'),
                     category='success')
-            return redirect(url('my_pullrequests'))
+            raise HTTPFound(location=url('my_pullrequests'))
         raise HTTPForbidden()
 
     @LoginRequired()
@@ -762,7 +760,7 @@
         Session().commit()
 
         if not request.environ.get('HTTP_X_PARTIAL_XHR'):
-            return redirect(pull_request.url())
+            raise HTTPFound(location=pull_request.url())
 
         data = {
            'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))),
--- a/kallithea/lib/auth.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/lib/auth.py	Wed Sep 09 12:41:20 2015 +0200
@@ -35,13 +35,12 @@
 from decorator import decorator
 
 from pylons import url, request, session
-from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
 from webhelpers.pylonslib import secure_form
 from sqlalchemy import or_
 from sqlalchemy.orm.exc import ObjectDeletedError
 from sqlalchemy.orm import joinedload
-from webob.exc import HTTPBadRequest, HTTPForbidden, HTTPMethodNotAllowed
+from webob.exc import HTTPFound, HTTPBadRequest, HTTPForbidden, HTTPMethodNotAllowed
 
 from kallithea import __platform__, is_windows, is_unix
 from kallithea.lib.vcs.utils.lazy import LazyProperty
@@ -717,7 +716,7 @@
     if message:
         h.flash(h.literal(message), category='warning')
     log.debug('Redirecting to login page, origin: %s', p)
-    return redirect(url('login_home', came_from=p))
+    raise HTTPFound(location=url('login_home', came_from=p))
 
 
 class LoginRequired(object):
--- a/kallithea/lib/base.py	Mon Sep 07 15:07:35 2015 +0200
+++ b/kallithea/lib/base.py	Wed Sep 09 12:41:20 2015 +0200
@@ -40,7 +40,6 @@
 
 from pylons import config, tmpl_context as c, request, session, url
 from pylons.controllers import WSGIController
-from pylons.controllers.util import redirect
 from pylons.templating import render_mako as render  # don't remove this import
 from pylons.i18n.translation import _
 
@@ -479,7 +478,7 @@
                 if route in ['repo_creating_home']:
                     return
                 check_url = url('repo_creating_home', repo_name=c.repo_name)
-                return redirect(check_url)
+                raise webob.exc.HTTPFound(location=check_url)
 
             dbr = c.db_repo = _dbr
             c.db_repo_scm_instance = c.db_repo.scm_instance