diff --git a/kallithea/config/routing.py b/kallithea/config/routing.py --- a/kallithea/config/routing.py +++ b/kallithea/config/routing.py @@ -19,6 +19,7 @@ may take precedent over the more generic refer to the routes manual at http://routes.groovie.org/docs/ """ +from pylons import request from routes import Mapper # prefix for non repository related links needs to be prefixed with `/` @@ -800,3 +801,27 @@ def make_map(config): conditions=dict(function=check_repo)) return rmap + + +class UrlGenerator(object): + """Emulate pylons.url in providing a wrapper around routes.url + + This code was added during migration from Pylons to Turbogears2. Pylons + already provided a wrapper like this, but Turbogears2 does not. + + When the routing of Kallithea is changed to use less Routes and more + Turbogears2-style routing, this class may disappear or change. + + url() (the __call__ method) returns the URL based on a route name and + arguments. + url.current() returns the URL of the current page with arguments applied. + + Refer to documentation of Routes for details: + https://routes.readthedocs.io/en/latest/generating.html#generation + """ + def __call__(self, *args, **kwargs): + return request.environ['routes.url'](*args, **kwargs) + def current(self, *args, **kwargs): + return request.environ['routes.url'].current(*args, **kwargs) + +url = UrlGenerator() diff --git a/kallithea/controllers/admin/admin.py b/kallithea/controllers/admin/admin.py --- a/kallithea/controllers/admin/admin.py +++ b/kallithea/controllers/admin/admin.py @@ -28,13 +28,14 @@ Original author and date, and relevant c import logging -from pylons import request, tmpl_context as c, url +from pylons import request, tmpl_context as c from sqlalchemy.orm import joinedload from whoosh.qparser.default import QueryParser from whoosh.qparser.dateparse import DateParserPlugin from whoosh import query from sqlalchemy.sql.expression import or_, and_, func +from kallithea.config.routing import url from kallithea.model.db import UserLog from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator from kallithea.lib.base import BaseController, render diff --git a/kallithea/controllers/admin/auth_settings.py b/kallithea/controllers/admin/auth_settings.py --- a/kallithea/controllers/admin/auth_settings.py +++ b/kallithea/controllers/admin/auth_settings.py @@ -27,10 +27,11 @@ import logging import formencode.htmlfill import traceback -from pylons import request, tmpl_context as c, url +from pylons import request, tmpl_context as c from pylons.i18n.translation import _ from webob.exc import HTTPFound +from kallithea.config.routing import url from kallithea.lib import helpers as h from kallithea.lib.compat import formatted_json from kallithea.lib.base import BaseController, render diff --git a/kallithea/controllers/admin/defaults.py b/kallithea/controllers/admin/defaults.py --- a/kallithea/controllers/admin/defaults.py +++ b/kallithea/controllers/admin/defaults.py @@ -30,10 +30,11 @@ import traceback import formencode from formencode import htmlfill -from pylons import request, tmpl_context as c, url +from pylons import request, tmpl_context as c from pylons.i18n.translation import _ from webob.exc import HTTPFound +from kallithea.config.routing import url from kallithea.lib import helpers as h from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator from kallithea.lib.base import BaseController, render diff --git a/kallithea/controllers/admin/gists.py b/kallithea/controllers/admin/gists.py --- a/kallithea/controllers/admin/gists.py +++ b/kallithea/controllers/admin/gists.py @@ -30,10 +30,11 @@ import logging import traceback import formencode.htmlfill -from pylons import request, response, tmpl_context as c, url +from pylons import request, response, tmpl_context as c from pylons.i18n.translation import _ from webob.exc import HTTPFound, HTTPNotFound, HTTPForbidden +from kallithea.config.routing import url from kallithea.model.forms import GistForm from kallithea.model.gist import GistModel from kallithea.model.meta import Session diff --git a/kallithea/controllers/admin/my_account.py b/kallithea/controllers/admin/my_account.py --- a/kallithea/controllers/admin/my_account.py +++ b/kallithea/controllers/admin/my_account.py @@ -31,10 +31,11 @@ import formencode from sqlalchemy import func from formencode import htmlfill -from pylons import request, tmpl_context as c, url +from pylons import request, tmpl_context as c from pylons.i18n.translation import _ from webob.exc import HTTPFound +from kallithea.config.routing import url from kallithea.lib import helpers as h from kallithea.lib import auth_modules from kallithea.lib.auth import LoginRequired, NotAnonymous, AuthUser diff --git a/kallithea/controllers/admin/permissions.py b/kallithea/controllers/admin/permissions.py --- a/kallithea/controllers/admin/permissions.py +++ b/kallithea/controllers/admin/permissions.py @@ -31,10 +31,11 @@ import traceback import formencode from formencode import htmlfill -from pylons import request, tmpl_context as c, url +from pylons import request, tmpl_context as c from pylons.i18n.translation import _ from webob.exc import HTTPFound +from kallithea.config.routing import url from kallithea.lib import helpers as h from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator from kallithea.lib.base import BaseController, render diff --git a/kallithea/controllers/admin/repo_groups.py b/kallithea/controllers/admin/repo_groups.py --- a/kallithea/controllers/admin/repo_groups.py +++ b/kallithea/controllers/admin/repo_groups.py @@ -32,11 +32,12 @@ import itertools from formencode import htmlfill -from pylons import request, tmpl_context as c, url +from pylons import request, tmpl_context as c from pylons.i18n.translation import _, ungettext from webob.exc import HTTPFound, HTTPForbidden, HTTPNotFound, HTTPInternalServerError import kallithea +from kallithea.config.routing import url from kallithea.lib import helpers as h from kallithea.lib.compat import json from kallithea.lib.auth import LoginRequired, \ diff --git a/kallithea/controllers/admin/repos.py b/kallithea/controllers/admin/repos.py --- a/kallithea/controllers/admin/repos.py +++ b/kallithea/controllers/admin/repos.py @@ -29,11 +29,12 @@ import logging import traceback import formencode from formencode import htmlfill -from pylons import request, tmpl_context as c, url +from pylons import request, tmpl_context as c from pylons.i18n.translation import _ from sqlalchemy.sql.expression import func from webob.exc import HTTPFound, HTTPInternalServerError, HTTPForbidden, HTTPNotFound +from kallithea.config.routing import url from kallithea.lib import helpers as h from kallithea.lib.auth import LoginRequired, \ HasRepoPermissionAnyDecorator, NotAnonymous, HasPermissionAny diff --git a/kallithea/controllers/admin/settings.py b/kallithea/controllers/admin/settings.py --- a/kallithea/controllers/admin/settings.py +++ b/kallithea/controllers/admin/settings.py @@ -30,10 +30,11 @@ import traceback import formencode from formencode import htmlfill -from pylons import request, tmpl_context as c, url, config +from pylons import request, tmpl_context as c, config from pylons.i18n.translation import _ from webob.exc import HTTPFound +from kallithea.config.routing import url from kallithea.lib import helpers as h from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator from kallithea.lib.base import BaseController, render diff --git a/kallithea/controllers/admin/user_groups.py b/kallithea/controllers/admin/user_groups.py --- a/kallithea/controllers/admin/user_groups.py +++ b/kallithea/controllers/admin/user_groups.py @@ -30,7 +30,7 @@ import traceback import formencode from formencode import htmlfill -from pylons import request, tmpl_context as c, url, config +from pylons import request, tmpl_context as c, config from pylons.i18n.translation import _ from webob.exc import HTTPFound @@ -39,6 +39,7 @@ from sqlalchemy.sql.expression import fu from webob.exc import HTTPInternalServerError import kallithea +from kallithea.config.routing import url from kallithea.lib import helpers as h from kallithea.lib.exceptions import UserGroupsAssignedException, \ RepoGroupAssignmentError diff --git a/kallithea/controllers/admin/users.py b/kallithea/controllers/admin/users.py --- a/kallithea/controllers/admin/users.py +++ b/kallithea/controllers/admin/users.py @@ -30,12 +30,13 @@ import traceback import formencode from formencode import htmlfill -from pylons import request, tmpl_context as c, url, config +from pylons import request, tmpl_context as c, config from pylons.i18n.translation import _ from sqlalchemy.sql.expression import func from webob.exc import HTTPFound, HTTPNotFound import kallithea +from kallithea.config.routing import url from kallithea.lib.exceptions import DefaultUserException, \ UserOwnsReposException, UserCreationError from kallithea.lib import helpers as h diff --git a/kallithea/controllers/changelog.py b/kallithea/controllers/changelog.py --- a/kallithea/controllers/changelog.py +++ b/kallithea/controllers/changelog.py @@ -28,11 +28,12 @@ Original author and date, and relevant c import logging import traceback -from pylons import request, url, session, tmpl_context as c +from pylons import request, session, tmpl_context as c from pylons.i18n.translation import _ from webob.exc import HTTPFound, HTTPNotFound, HTTPBadRequest import kallithea.lib.helpers as h +from kallithea.config.routing import url from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator from kallithea.lib.base import BaseRepoController, render from kallithea.lib.helpers import RepoPage diff --git a/kallithea/controllers/compare.py b/kallithea/controllers/compare.py --- a/kallithea/controllers/compare.py +++ b/kallithea/controllers/compare.py @@ -30,10 +30,11 @@ Original author and date, and relevant c import logging import re -from pylons import request, tmpl_context as c, url +from pylons import request, tmpl_context as c from pylons.i18n.translation import _ from webob.exc import HTTPFound, HTTPBadRequest +from kallithea.config.routing import url from kallithea.lib.utils2 import safe_str, safe_int from kallithea.lib.vcs.utils.hgcompat import unionrepo from kallithea.lib import helpers as h diff --git a/kallithea/controllers/files.py b/kallithea/controllers/files.py --- a/kallithea/controllers/files.py +++ b/kallithea/controllers/files.py @@ -32,10 +32,11 @@ import traceback import tempfile import shutil -from pylons import request, response, tmpl_context as c, url +from pylons import request, response, tmpl_context as c from pylons.i18n.translation import _ from webob.exc import HTTPFound +from kallithea.config.routing import url from kallithea.lib.utils import jsonify, action_logger from kallithea.lib import diffs from kallithea.lib import helpers as h diff --git a/kallithea/controllers/forks.py b/kallithea/controllers/forks.py --- a/kallithea/controllers/forks.py +++ b/kallithea/controllers/forks.py @@ -30,12 +30,13 @@ import formencode import traceback from formencode import htmlfill -from pylons import tmpl_context as c, request, url +from pylons import tmpl_context as c, request from pylons.i18n.translation import _ from webob.exc import HTTPFound import kallithea.lib.helpers as h +from kallithea.config.routing import url from kallithea.lib.helpers import Page from kallithea.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, \ NotAnonymous, HasRepoPermissionAny, HasPermissionAnyDecorator, HasPermissionAny diff --git a/kallithea/controllers/journal.py b/kallithea/controllers/journal.py --- a/kallithea/controllers/journal.py +++ b/kallithea/controllers/journal.py @@ -37,9 +37,10 @@ from sqlalchemy.sql.expression import fu from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed from webob.exc import HTTPBadRequest -from pylons import request, tmpl_context as c, response, url +from pylons import request, tmpl_context as c, response from pylons.i18n.translation import _ +from kallithea.config.routing import url from kallithea.controllers.admin.admin import _journal_filter from kallithea.model.db import UserLog, UserFollowing, Repository, User from kallithea.model.meta import Session diff --git a/kallithea/controllers/login.py b/kallithea/controllers/login.py --- a/kallithea/controllers/login.py +++ b/kallithea/controllers/login.py @@ -32,10 +32,11 @@ import formencode from formencode import htmlfill from pylons.i18n.translation import _ -from pylons import request, session, tmpl_context as c, url +from pylons import request, session, tmpl_context as c from webob.exc import HTTPFound, HTTPBadRequest import kallithea.lib.helpers as h +from kallithea.config.routing import url from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator from kallithea.lib.base import BaseController, log_in_user, render from kallithea.lib.exceptions import UserCreationError diff --git a/kallithea/controllers/pullrequests.py b/kallithea/controllers/pullrequests.py --- a/kallithea/controllers/pullrequests.py +++ b/kallithea/controllers/pullrequests.py @@ -30,10 +30,11 @@ import traceback import formencode import re -from pylons import request, tmpl_context as c, url +from pylons import request, tmpl_context as c from pylons.i18n.translation import _ from webob.exc import HTTPFound, HTTPNotFound, HTTPForbidden, HTTPBadRequest +from kallithea.config.routing import url from kallithea.lib.vcs.utils.hgcompat import unionrepo from kallithea.lib.compat import json, OrderedDict from kallithea.lib.base import BaseRepoController, render diff --git a/kallithea/lib/auth.py b/kallithea/lib/auth.py --- a/kallithea/lib/auth.py +++ b/kallithea/lib/auth.py @@ -34,7 +34,7 @@ import collections from decorator import decorator -from pylons import url, request, session +from pylons import request, session from pylons.i18n.translation import _ from webhelpers.pylonslib import secure_form from sqlalchemy import or_ @@ -43,6 +43,7 @@ from sqlalchemy.orm import joinedload from webob.exc import HTTPFound, HTTPBadRequest, HTTPForbidden, HTTPMethodNotAllowed from kallithea import __platform__, is_windows, is_unix +from kallithea.config.routing import url from kallithea.lib.vcs.utils.lazy import LazyProperty from kallithea.model import meta from kallithea.model.meta import Session diff --git a/kallithea/lib/base.py b/kallithea/lib/base.py --- a/kallithea/lib/base.py +++ b/kallithea/lib/base.py @@ -38,13 +38,14 @@ import paste.httpexceptions import paste.auth.basic import paste.httpheaders -from pylons import config, tmpl_context as c, request, session, url +from pylons import config, tmpl_context as c, request, session from pylons.controllers import WSGIController from pylons.templating import render_mako as render # don't remove this import from pylons.i18n.translation import _ from kallithea import __version__, BACKENDS +from kallithea.config.routing import url from kallithea.lib.utils2 import str2bool, safe_unicode, AttributeDict, \ safe_str, safe_int from kallithea.lib import auth_modules diff --git a/kallithea/lib/helpers.py b/kallithea/lib/helpers.py --- a/kallithea/lib/helpers.py +++ b/kallithea/lib/helpers.py @@ -28,7 +28,6 @@ import textwrap from beaker.cache import cache_region from pygments.formatters.html import HtmlFormatter from pygments import highlight as code_highlight -from pylons import url from pylons.i18n.translation import _, ungettext from webhelpers.html import literal, HTML, escape @@ -52,6 +51,7 @@ from webhelpers.paginate import Page as from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \ convert_boolean_attrs, NotGiven, _make_safe_id_component +from kallithea.config.routing import url from kallithea.lib.annotate import annotate_highlight from kallithea.lib.utils import repo_name_slug, get_custom_lexer from kallithea.lib.utils2 import str2bool, safe_unicode, safe_str, \ @@ -866,7 +866,7 @@ def gravatar(email_address, cls='', size def gravatar_url(email_address, size=30, default=''): # doh, we need to re-import those to mock it later - from pylons import url + from kallithea.config.routing import url from pylons import tmpl_context as c if not c.visual.use_gravatar: return "" @@ -1290,7 +1290,7 @@ def urlify_text(s, repo_name=None, link_ return '%s' % mention hash_ = match_obj.group('hash') if hash_ is not None and repo_name is not None: - from pylons import url # doh, we need to re-import url to mock it later + from kallithea.config.routing import url # doh, we need to re-import url to mock it later return '%(hash)s' % { 'url': url('changeset_home', repo_name=repo_name, revision=hash_), 'hash': hash_, diff --git a/kallithea/tests/base.py b/kallithea/tests/base.py --- a/kallithea/tests/base.py +++ b/kallithea/tests/base.py @@ -219,4 +219,3 @@ class TestController(object): def checkSessionFlashRegex(self, response, regex, skip=0): self.checkSessionFlash(response, regex, skip=skip, _matcher=re.search) - diff --git a/kallithea/tests/other/test_libs.py b/kallithea/tests/other/test_libs.py --- a/kallithea/tests/other/test_libs.py +++ b/kallithea/tests/other/test_libs.py @@ -66,6 +66,24 @@ TEST_URLS += [ '%s://example.com:8080' % proto), ] +class FakeUrlGenerator(object): + + def __init__(self, current_url=None, default_route=None, **routes): + """Initialize using specified 'current' URL template, + default route template, and all other aguments describing known + routes (format: route=template)""" + self.current_url = current_url + self.default_route = default_route + self.routes = routes + + def __call__(self, route_name, *args, **kwargs): + if route_name in self.routes: + return self.routes[route_name] % kwargs + + return self.default_route % kwargs + + def current(self, *args, **kwargs): + return self.current_url % kwargs class TestLibs(TestController): @@ -202,12 +220,6 @@ class TestLibs(TestController): from kallithea.lib.helpers import gravatar_url _md5 = lambda s: hashlib.md5(s).hexdigest() - #mock pylons.url - class fake_url(object): - @classmethod - def current(cls, *args, **kwargs): - return 'https://example.com' - #mock pylons.tmpl_context def fake_tmpl_context(_url): _c = AttributeDict() @@ -217,11 +229,11 @@ class TestLibs(TestController): return _c - - with mock.patch('pylons.url', fake_url): + fake_url = FakeUrlGenerator(current_url='https://example.com') + with mock.patch('kallithea.config.routing.url', fake_url): fake = fake_tmpl_context(_url='http://example.com/{email}') with mock.patch('pylons.tmpl_context', fake): - from pylons import url + from kallithea.config.routing import url assert url.current() == 'https://example.com' grav = gravatar_url(email_address='test@example.com', size=24) assert grav == 'http://example.com/test@example.com' @@ -283,7 +295,7 @@ class TestLibs(TestController): def url_func(match_obj): _url = match_obj.groups()[0] - return tmpl % (url_ or '/some-url', _url) + return tmpl % (url_ or '/repo_name/changeset/%s' % _url, _url) return URL_PAT.sub(url_func, text) @parametrize('sample,expected', [ @@ -314,12 +326,9 @@ class TestLibs(TestController): """ sometimes !"""), ]) def test_urlify_text(self, sample, expected): - def fake_url(self, *args, **kwargs): - return '/some-url' - expected = self._quick_url(expected) - - with mock.patch('pylons.url', fake_url): + fake_url = FakeUrlGenerator(changeset_home='/%(repo_name)s/changeset/%(revision)s') + with mock.patch('kallithea.config.routing.url', fake_url): from kallithea.lib.helpers import urlify_text assert urlify_text(sample, 'repo_name') == expected @@ -368,10 +377,12 @@ class TestLibs(TestController): # tags are covered by test_tag_extractor ]) def test_urlify_test(self, sample, expected, url_): - from kallithea.lib.helpers import urlify_text expected = self._quick_url(expected, tmpl="""%s""", url_=url_) - assert urlify_text(sample, 'repo_name', stylize=True) == expected + fake_url = FakeUrlGenerator(changeset_home='/%(repo_name)s/changeset/%(revision)s') + with mock.patch('kallithea.config.routing.url', fake_url): + from kallithea.lib.helpers import urlify_text + assert urlify_text(sample, 'repo_name', stylize=True) == expected @parametrize('sample,expected', [ ("deadbeefcafe @mention, and http://foo.bar/ yo", @@ -381,8 +392,10 @@ class TestLibs(TestController): """ yo"""), ]) def test_urlify_link(self, sample, expected): - from kallithea.lib.helpers import urlify_text - assert urlify_text(sample, 'repo_name', link_='#the-link') == expected + fake_url = FakeUrlGenerator(changeset_home='/%(repo_name)s/changeset/%(revision)s') + with mock.patch('kallithea.config.routing.url', fake_url): + from kallithea.lib.helpers import urlify_text + assert urlify_text(sample, 'repo_name', link_='#the-link') == expected @parametrize('test,expected', [ ("", None),