Merge ~cjwatson/launchpad:revert-object-lookup-redirection into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 9906df01808f21211cb889d67fbbfba3ba7ac1d9
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:revert-object-lookup-redirection
Merge into: launchpad:master
Diff against target: 241 lines (+8/-105)
5 files modified
lib/lp/registry/browser/distribution.py (+2/-4)
lib/lp/registry/browser/product.py (+1/-2)
lib/lp/registry/browser/tests/test_distribution.py (+1/-31)
lib/lp/registry/browser/tests/test_product.py (+2/-37)
lib/lp/services/webapp/publisher.py (+2/-31)
Reviewer Review Type Date Requested Status
Thiago F. Pappacena (community) Approve
Review via email: mp+387999@code.launchpad.net

Commit message

Revert "Make series redirections compatible with object lookup"

Description of the change

This reverts commit 4176a750bdbf1656fee93ac7c18a69fa8e8eff8b.

This is insufficiently-understood, doesn't quite fix what it was originally intended to fix (non-canonical series URLs in webservice method parameters) and has caused at least one regression, so let's back it out for now and try again later.

I've left the lazr.restful upgrade in place; I think that part of it should be harmless enough.

To post a comment you must log in.
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

LGTM! Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/registry/browser/distribution.py b/lib/lp/registry/browser/distribution.py
2index 8d566e0..41aa5cd 100644
3--- a/lib/lp/registry/browser/distribution.py
4+++ b/lib/lp/registry/browser/distribution.py
5@@ -190,14 +190,12 @@ class DistributionNavigation(
6 @stepthrough('+series')
7 def traverse_series(self, name):
8 series, _ = self._resolveSeries(name)
9- return self.redirectSubTree(
10- canonical_url(series, request=self.request), status=303)
11+ return self.redirectSubTree(canonical_url(series), status=303)
12
13 def traverse(self, name):
14 series, is_alias = self._resolveSeries(name)
15 if is_alias:
16- return self.redirectSubTree(
17- canonical_url(series, request=self.request), status=303)
18+ return self.redirectSubTree(canonical_url(series), status=303)
19 else:
20 return series
21
22diff --git a/lib/lp/registry/browser/product.py b/lib/lp/registry/browser/product.py
23index e7dbe7e..790ff91 100644
24--- a/lib/lp/registry/browser/product.py
25+++ b/lib/lp/registry/browser/product.py
26@@ -287,8 +287,7 @@ class ProductNavigation(
27 @stepthrough('+series')
28 def traverse_series(self, name):
29 series = self.context.getSeries(name)
30- return self.redirectSubTree(
31- canonical_url(series, request=self.request), status=303)
32+ return self.redirectSubTree(canonical_url(series), status=303)
33
34 def traverse(self, name):
35 return self.context.getSeries(name)
36diff --git a/lib/lp/registry/browser/tests/test_distribution.py b/lib/lp/registry/browser/tests/test_distribution.py
37index 7e4c989..904462f 100644
38--- a/lib/lp/registry/browser/tests/test_distribution.py
39+++ b/lib/lp/registry/browser/tests/test_distribution.py
40@@ -9,30 +9,23 @@ from __future__ import absolute_import, print_function, unicode_literals
41 __metaclass__ = type
42
43 from fixtures import FakeLogger
44-from lazr.restful.fields import Reference
45-from lazr.restful.interfaces import (
46- IFieldMarshaller,
47- IJSONRequestCache,
48- )
49+from lazr.restful.interfaces import IJSONRequestCache
50 import soupmatchers
51 from testtools.matchers import (
52 MatchesAll,
53 MatchesAny,
54 Not,
55 )
56-from zope.component import getMultiAdapter
57 from zope.schema.vocabulary import SimpleVocabulary
58 from zope.security.proxy import removeSecurityProxy
59
60 from lp.app.browser.lazrjs import vocabulary_to_choice_edit_items
61 from lp.registry.enums import EXCLUSIVE_TEAM_POLICY
62-from lp.registry.interfaces.distroseries import IDistroSeries
63 from lp.registry.interfaces.ociproject import OCI_PROJECT_ALLOW_CREATE
64 from lp.registry.interfaces.series import SeriesStatus
65 from lp.services.features.testing import FeatureFixture
66 from lp.services.webapp import canonical_url
67 from lp.services.webapp.publisher import RedirectionView
68-from lp.services.webapp.servers import WebServiceTestRequest
69 from lp.testing import (
70 admin_logged_in,
71 login_celebrity,
72@@ -88,29 +81,6 @@ class TestDistributionNavigation(TestCaseWithFactory):
73 "http://launchpad.test/%s/%s" % (
74 distroseries.distribution.name, distroseries.name))
75
76- def test_new_series_url_supports_object_lookup(self):
77- # New-style +series URLs are compatible with webservice object
78- # lookup.
79- field = Reference(schema=IDistroSeries)
80- request = WebServiceTestRequest()
81- request.setVirtualHostRoot(names=["devel"])
82- marshaller = getMultiAdapter((field, request), IFieldMarshaller)
83- distroseries = self.factory.makeDistroSeries()
84- distroseries_url = "/%s/+series/%s" % (
85- distroseries.distribution.name, distroseries.name)
86- self.assertEqual(
87- distroseries, marshaller.marshall_from_json_data(distroseries_url))
88- # Objects subordinate to the redirected series work too.
89- distroarchseries = self.factory.makeDistroArchSeries(
90- distroseries=distroseries)
91- distroarchseries_url = "/%s/+series/%s/%s" % (
92- distroarchseries.distroseries.distribution.name,
93- distroarchseries.distroseries.name,
94- distroarchseries.architecturetag)
95- self.assertEqual(
96- distroarchseries,
97- marshaller.marshall_from_json_data(distroarchseries_url))
98-
99
100 class TestDistributionPage(TestCaseWithFactory):
101 """A TestCase for the distribution index page."""
102diff --git a/lib/lp/registry/browser/tests/test_product.py b/lib/lp/registry/browser/tests/test_product.py
103index 714e84f..52544c0 100644
104--- a/lib/lp/registry/browser/tests/test_product.py
105+++ b/lib/lp/registry/browser/tests/test_product.py
106@@ -9,11 +9,7 @@ __all__ = ['make_product_form']
107
108 import re
109
110-from lazr.restful.fields import Reference
111-from lazr.restful.interfaces import (
112- IFieldMarshaller,
113- IJSONRequestCache,
114- )
115+from lazr.restful.interfaces import IJSONRequestCache
116 from six.moves.urllib.parse import (
117 urlencode,
118 urlsplit,
119@@ -28,10 +24,7 @@ from testtools.matchers import (
120 Not,
121 )
122 import transaction
123-from zope.component import (
124- getMultiAdapter,
125- getUtility,
126- )
127+from zope.component import getUtility
128 from zope.schema.vocabulary import SimpleVocabulary
129 from zope.security.proxy import removeSecurityProxy
130
131@@ -56,7 +49,6 @@ from lp.registry.interfaces.product import (
132 IProductSet,
133 License,
134 )
135-from lp.registry.interfaces.productseries import IProductSeries
136 from lp.registry.model.product import Product
137 from lp.services.config import config
138 from lp.services.database.interfaces import IStore
139@@ -64,7 +56,6 @@ from lp.services.webapp.publisher import (
140 canonical_url,
141 RedirectionView,
142 )
143-from lp.services.webapp.servers import WebServiceTestRequest
144 from lp.services.webapp.vhosts import allvhosts
145 from lp.testing import (
146 BrowserTestCase,
147@@ -117,32 +108,6 @@ class TestProductNavigation(TestCaseWithFactory):
148 "http://launchpad.test/%s/%s" % (
149 productseries.product.name, productseries.name))
150
151- def test_new_series_url_supports_object_lookup(self):
152- # New-style +series URLs are compatible with webservice object
153- # lookup.
154- field = Reference(schema=IProductSeries)
155- request = WebServiceTestRequest()
156- request.setVirtualHostRoot(names=["devel"])
157- marshaller = getMultiAdapter((field, request), IFieldMarshaller)
158- productseries = self.factory.makeProductSeries()
159- productseries_url = "/%s/+series/%s" % (
160- productseries.product.name, productseries.name)
161- resource = marshaller.dereference_url(productseries_url)
162- self.assertIsInstance(resource, RedirectionView)
163- self.assertEqual(
164- productseries,
165- marshaller.marshall_from_json_data(productseries_url))
166-
167- # Objects subordinate to the redirected series work too.
168- productrelease = self.factory.makeProductRelease(
169- productseries=productseries)
170- productrelease_url = "/%s/+series/%s/%s" % (
171- productrelease.product.name, productrelease.productseries.name,
172- productrelease.version)
173- self.assertEqual(
174- productrelease,
175- marshaller.marshall_from_json_data(productrelease_url))
176-
177
178 class TestProductConfiguration(BrowserTestCase):
179 """Tests the configuration links and helpers."""
180diff --git a/lib/lp/services/webapp/publisher.py b/lib/lp/services/webapp/publisher.py
181index f01466d..a67601e 100644
182--- a/lib/lp/services/webapp/publisher.py
183+++ b/lib/lp/services/webapp/publisher.py
184@@ -1,4 +1,4 @@
185-# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
186+# Copyright 2009-2018 Canonical Ltd. This software is licensed under the
187 # GNU Affero General Public License version 3 (see the file LICENSE).
188
189 """Publisher of objects as web pages.
190@@ -36,7 +36,6 @@ from lazr.restful import (
191 )
192 from lazr.restful.declarations import error_status
193 from lazr.restful.interfaces import IJSONRequestCache
194-from lazr.restful.marshallers import URLDereferencingMixin
195 from lazr.restful.tales import WebLayerAPI
196 from lazr.restful.utils import get_current_browser_request
197 import simplejson
198@@ -1082,7 +1081,7 @@ class Navigation:
199
200
201 @implementer(IBrowserPublisher)
202-class RedirectionView(URLDereferencingMixin):
203+class RedirectionView:
204
205 def __init__(self, target, request, status=None, cache_view=None):
206 self.target = target
207@@ -1107,34 +1106,6 @@ class RedirectionView(URLDereferencingMixin):
208 def browserDefault(self, request):
209 return self, ()
210
211- @property
212- def context(self):
213- """Find the context object corresponding to the redirection target.
214-
215- Passing objects as arguments to webservice methods is done by URL,
216- and ObjectLookupFieldMarshaller constructs an internal request to
217- traverse this and find the appropriate object. If the URL in
218- question results in a redirection, then we must recursively traverse
219- the target URL until we find something that the webservice
220- understands.
221- """
222- # Circular import.
223- from lp.services.webapp.servers import WebServiceClientRequest
224-
225- if not isinstance(self.request, WebServiceClientRequest):
226- # Raise AttributeError here (as if the "context" attribute
227- # didn't exist) so that e.g.
228- # lp.testing.publication.test_traverse knows to fall back to
229- # other approaches.
230- raise AttributeError(
231- "RedirectionView.context is only supported for webservice "
232- "requests.")
233- if urlparse(self.target).query:
234- raise AttributeError(
235- "RedirectionView.context is not supported for URLs with "
236- "query strings.")
237- return self.dereference_url_as_object(self.target)
238-
239
240 @implementer(IBrowserPublisher)
241 class RenamedView:

Subscribers

People subscribed via source and target branches

to status/vote changes: