Skip to content

Commit

Permalink
Merge pull request #440 from dstufft/redirects
Browse files Browse the repository at this point in the history
Redirect the old /pypi/<name>/<version>/ URLs to /project/
  • Loading branch information
dstufft committed Mar 15, 2015
2 parents 2bff691 + a120a1f commit 488bffd
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 0 deletions.
1 change: 1 addition & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ def __init__(self):
pretend.call(".csrf"),
pretend.call(".accounts"),
pretend.call(".packaging"),
pretend.call(".redirects"),
pretend.call(".routes"),
]
assert configurator_obj.add_jinja2_renderer.calls == [
Expand Down
67 changes: 67 additions & 0 deletions tests/test_redirects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import pretend

from pyramid.httpexceptions import HTTPMovedPermanently

from warehouse import redirects


def test_redirect_view():
target = "/{wat}/{_request.method}"
view = redirects.redirect_view_factory(target)

request = pretend.stub(method="GET", matchdict={"wat": "the-thing"})
resp = view(request)

assert isinstance(resp, HTTPMovedPermanently)
assert resp.headers["Location"] == "/the-thing/GET"


def test_add_redirect(monkeypatch):
rview = pretend.stub()
rview_factory = pretend.call_recorder(lambda target, redirect: rview)
monkeypatch.setattr(redirects, "redirect_view_factory", rview_factory)

config = pretend.stub(
add_route=pretend.call_recorder(lambda name, route: None),
add_view=pretend.call_recorder(lambda view, route_name: None),
)

source = "/the/{thing}/"
target = "/other/{thing}/"
redirect = pretend.stub()

redirects.add_redirect(config, source, target, redirect=redirect)

assert config.add_route.calls == [
pretend.call("warehouse.redirects." + source, source),
]
assert config.add_view.calls == [
pretend.call(rview, route_name="warehouse.redirects." + source),
]
assert rview_factory.calls == [pretend.call(target, redirect=redirect)]


def test_includeme():
config = pretend.stub(
add_directive=pretend.call_recorder(lambda n, fn, action_wrap: None),
)
redirects.includeme(config)
assert config.add_directive.calls == [
pretend.call(
"add_redirect",
redirects.add_redirect,
action_wrap=False,
),
]
10 changes: 10 additions & 0 deletions tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ class FakeConfig:
def add_route(*args, **kwargs):
pass

@staticmethod
@pretend.call_recorder
def add_redirect(*args, **kwargs):
pass

config = FakeConfig()
includeme(config)

Expand Down Expand Up @@ -55,3 +60,8 @@ def add_route(*args, **kwargs):
traverse="/{name}/",
),
]

assert config.add_redirect.calls == [
pretend.call("/pypi/{name}/", "/project/{name}/"),
pretend.call("/pypi/{name}/{version}/", "/project/{name}/{version}/"),
]
3 changes: 3 additions & 0 deletions warehouse/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ def configure(settings=None):
# Allow the packaging app to register any services it has.
config.include(".packaging")

# Configure redirection support
config.include(".redirects")

# Register all our URL routes for Warehouse.
config.include(".routes")

Expand Down
30 changes: 30 additions & 0 deletions warehouse/redirects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from pyramid.httpexceptions import HTTPMovedPermanently


def redirect_view_factory(target, redirect=HTTPMovedPermanently):
def redirect_view(request):
return redirect(target.format(_request=request, **request.matchdict))
return redirect_view


def add_redirect(config, source, target, **kw):
route_name = "warehouse.redirects." + source

config.add_route(route_name, source)
config.add_view(redirect_view_factory(target, **kw), route_name=route_name)


def includeme(config):
config.add_directive("add_redirect", add_redirect, action_wrap=False)
7 changes: 7 additions & 0 deletions warehouse/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,10 @@ def includeme(config):
factory="warehouse.packaging.models:ProjectFactory",
traverse="/{name}/",
)

# Legacy Redirects
config.add_redirect("/pypi/{name}/", "/project/{name}/")
config.add_redirect(
"/pypi/{name}/{version}/",
"/project/{name}/{version}/",
)

0 comments on commit 488bffd

Please sign in to comment.