Merge lp:~wallyworld/launchpad/improved-broken-link-handling into lp:launchpad
| Status: | Merged | ||||
|---|---|---|---|---|---|
| Approved by: | Ian Booth on 2010-10-23 | ||||
| Approved revision: | no longer in the source branch. | ||||
| Merged at revision: | 11806 | ||||
| Proposed branch: | lp:~wallyworld/launchpad/improved-broken-link-handling | ||||
| Merge into: | lp:launchpad | ||||
| Diff against target: |
570 lines (+415/-28) 12 files modified
lib/canonical/launchpad/icing/style-3-0.css.in (+6/-0) lib/lp/app/browser/configure.zcml (+6/-0) lib/lp/app/browser/linkchecker.py (+77/-0) lib/lp/app/browser/stringformatter.py (+3/-1) lib/lp/app/browser/tests/test_linkchecker.py (+83/-0) lib/lp/app/configure.zcml (+0/-14) lib/lp/app/doc/displaying-paragraphs-of-text.txt (+11/-11) lib/lp/app/javascript/lp-links.js (+105/-0) lib/lp/app/templates/base-layout-macros.pt (+9/-0) lib/lp/bugs/windmill/tests/test_bug_commenting.py (+1/-1) lib/lp/code/windmill/tests/test_branch_broken_links.py (+113/-0) lib/lp/code/windmill/tests/test_branchmergeproposal_review.py (+1/-1) |
||||
| To merge this branch: | bzr merge lp:~wallyworld/launchpad/improved-broken-link-handling | ||||
| Related bugs: |
|
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Gavin Panella (community) | 2010-10-20 | Approve on 2010-10-22 | |
| Launchpad code reviewers | js | 2010-10-21 | Pending |
|
Review via email:
|
|||
Commit Message
Add invalid-link style to invalid lp branch short links and prevent click through
Description of the Change
Summary
------------
Render lp: shortcuts such that any invalid ones are shown as grey and their onclick() is suppressed.
This branch supports processing +branch links.
Implementation detail
-------
When the links are harvested via the linkify_
Tests
------
New tests:
lp/app/
lp/code/
The windmill test is broken because windmill has an issue making the ajax call. Manual testing shows the functionality works as expected.
Lint
----
Linting changed files:
lib/canonical
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
./lib/canonical
144: Line exceeds 78 characters.
1324: Line exceeds 78 characters.
1941: Line exceeds 78 characters.
1957: Line exceeds 78 characters.
1961: Line exceeds 78 characters.
1969: Line exceeds 78 characters.
1973: Line exceeds 78 characters.
2001: Line exceeds 78 characters.
2017: Line exceeds 78 characters.
2025: Line exceeds 78 characters.
2029: Line exceeds 78 characters.
2033: Line exceeds 78 characters.
2037: Line exceeds 78 characters.
2041: Line exceeds 78 characters.
2045: Line exceeds 78 characters.
2058: Line exceeds 78 characters.
2062: Line exceeds 78 characters.
2094: Line exceeds 78 characters.
2106: Line exceeds 78 characters.
2110: Line exceeds 78 characters.
2114: Line exceeds 78 characters.
2122: Line exceeds 78 characters.
2126: Line exceeds 78 characters.
2134: Line exceeds 78 characters.
2162: Line exceeds 78 characters.
2166: Line exceeds 78 characters.
2194: Line exceeds 78 characters.
2202: Line exceeds 78 characters.
2207: Line exceeds 78 characters.
2211: Line exceeds 78 characters.
2216: Line exceeds 78 characters.
2220: Line exceeds 78 characters.
2224: Line exceeds 78 characters.
2228: Line exceeds 78 characters.
2232: Line exceeds 78 characters.
2284: Line exceeds 78 characters.
2292: Line exceeds 78 characters.
2296: Line exceeds 78 characters.
2304: Line exceeds 78 characters.
2316: Line exceeds 78 characters.
2324: Line exceeds 78 characters.
2328: Line exceeds 78 characters.
2332: Line exceeds 78 characters.
2340: Line exceeds 78 characters.
2344: Line exceeds 78 characters.
2348: Line exceeds 78 characters.
2352: Line exceeds 78 characters.
2356: Line exceeds 78 characters.
2365: Line exceeds 78 characters.
2373: Line exceeds 78 characters.
2505: Line exceeds 78 characters.
2506: Line exceeds 78 characters.
2575: Line exceeds 78 characters.
2576: Line exceeds 78 characters.
./lib/lp/
409: E501 line too long (90 characters)
413: E501 line too long (88 characters)
409: Line exceeds 78 characters.
413: Line exceeds 78 characters.
./lib/lp/
1: narrative uses a moin header.
7: narrative uses a moin header.
32: want exceeds 78 characters.
33: want exceeds 78 characters.
43: source exceeds 78 characters.
49: want exceeds 78 characters.
83: want exceeds 78 characters.
84: want exceeds 78 characters.
86: want exceeds 78 characters.
87: want exceeds 78 characters.
102: want exceeds 78 characters.
103: want exceeds 78 characters.
104: want exceeds 78 characters.
105: want exceeds 78 characters.
106: want exceeds 78 characters.
107: want exceeds 78 characters.
110: narrative uses a moin header.
138: source exceeds 78 characters.
155: want exceeds 78 characters.
156: want exceeds 78 characters.
157: want exceeds 78 characters.
158: want exceeds 78 characters.
159: want exceeds 78 characters.
160: want exceeds 78 characters.
161: want exceeds 78 characters.
162: want exceeds 78 characters.
163: want exceeds 78 characters.
164: want exceeds 78 characters.
165: want exceeds 78 characters.
166: want exceeds 78 characters.
167: want exceeds 78 characters.
168: want exceeds 78 characters.
169: want exceeds 78 characters.
170: want exceeds 78 characters.
171: want exceeds 78 characters.
172: want exceeds 78 characters.
173: want exceeds 78 characters.
174: want exceeds 78 characters.
175: want exceeds 78 characters.
176: want exceeds 78 characters.
177: want exceeds 78 characters.
178: want exceeds 78 characters.
179: want exceeds 78 characters.
180: want exceeds 78 characters.
181: want exceeds 78 characters.
182: want exceeds 78 characters.
183: want exceeds 78 characters.
184: want exceeds 78 characters.
185: want exceeds 78 characters.
186: want exceeds 78 characters.
187: want exceeds 78 characters.
188: want exceeds 78 characters.
189: want exceeds 78 characters.
190: want exceeds 78 characters.
191: want exceeds 78 characters.
204: narrative uses a moin header.
314: narrative uses a moin header.
332: want exceeds 78 characters.
343: narrative uses a moin header.
361: want exceeds 78 characters.
363: want exceeds 78 characters.
387: narrative uses a moin header.
424: want exceeds 78 characters.
430: want exceeds 78 characters.
434: want exceeds 78 characters.
438: want exceeds 78 characters.
442: want exceeds 78 characters.
472: narrative uses a moin header.
487: narrative exceeds 78 characters.
./lib/lp/
90: E501 line too long (102 characters)
96: E501 line too long (96 characters)
123: E302 expected 2 blank lines, found 3
90: Line exceeds 78 characters.
96: Line exceeds 78 characters.
| Jeroen T. Vermeulen (jtv) wrote : | # |
| Ian Booth (wallyworld) wrote : | # |
There's only one real instance, due to a cut'n'paste :-) The other one
was a file that was deleted and then reverted and bzr has treated it as
a delete and then an add, so it is a false positive.
On 21/10/10 19:47, Jeroen T. Vermeulen wrote:
> Just a note, not a review: why so much 2009 and so little 2010 in the copyright notices? :-)
| Gavin Panella (allenap) wrote : | # |
This is a nice piece of functionality. I have a lot of comments but
most if not all of them are trivial or minor. I'm going to ask someone
else who has more up-to-date experience with Javascript in Launchpad
to give this a look too.
[1]
+ <browser:page
+ for="*"
+ name="+check-links"
+ class="
+ permission=
+ />
Although the indentation is inconsistent in that file, and although it
doesn't matter very much, can you make this consistent with what's
already there?
[2]
+from zope.component._api import getUtility
getUtility is normally imported directly from zope.component.
[3]
+from zope.component._api import getUtility
+
+from lp.code.
+
+__metaclass__ = type
+
+__all__ = [
+ 'LinkCheckerAPI',
+ ]
+
+import simplejson
I think __metaclass__ and __all__ normally appear first in Launchpad
source, followed by imports. I think utilities/
that too (and you should also run this on your changed files, or use
utilities/
[4]
+ """ Validates Launchpad shortcut links.
s/" V/"V/
[5]
+ result[
s/[+=]/ \1 /
[6]
+ path = link.strip(
Is it possible that the branch link does not begin with +branch? I'm
not used to seeing branches with +branch in their URLs.
[7]
+ try:
+ branch_
+ except:
+ invalid_
Don't use default except clauses like this. Catch Exception if
absolutely necessary, or, preferably, catch just those exceptions that
could be raised.
[8]
+ return '<a href="%s" class="
+ "branch-
Just chuck "branch-short-link" into the format string rather than
interpolate.
[9]
+ self.assertEqua
+ self.assertEqua
Only the second test is needed. In fact, if the first test fails the
error message will be less informative than if the second fails (which
it will if the first fails).
[10]
+ def invoke_
+ self, valid_branch_
Default arguments must not be mutable. Use None as a default then
check for that in the method.
[11]
Is it likely that we hit any query length problems when requesting the
status of a page with many links?
[12]
+ // Get any links of the specified link_class and put store them as the
+ // specified link_type in the specified links_holder
s/put store/store/
[13]
+function harvest_links(Y, links_holder, link_class, link_type) {
I think this function would be cleaner if it returned the link_info
array instead of putting it into links_holder. That way it need only
accept two arguments, Y and link_class. Callers should check if the
returned array is empty.
[14]
Also, given [13] and the presence of the YUI collection module,
harvest_links() could be much shorter ...
| Ian Booth (wallyworld) wrote : | # |
Hi
Thanks for the most excellent review. It's the most thorough one I've
had. I've addressed most of the issues except for the one item - see my
comments. The import issues were due to the "curse" of having an IDE
that auto imports missing references and it guessed wrong. A small price
to pay given all the other great stuff it does.
>
> I think __metaclass__ and __all__ normally appear first in Launchpad
> source, followed by imports. I think utilities/
> that too (and you should also run this on your changed files, or use
> utilities/
>
Thanks for the tip - I had no idea those scripts existed.
>
> [6]
>
> + path = link.strip(
>
> Is it possible that the branch link does not begin with +branch? I'm
> not used to seeing branches with +branch in their URLs.
>
No, all branch links processed by this new functionality begin with
+branch. See line 276 of stringformatter.py:
url = '/+branch/%s' % path
>
> [11]
>
> Is it likely that we hit any query length problems when requesting the
> status of a page with many links?
>
I don't think so? A post operation is used so I thought that would have
it covered?
>
> [13]
>
> +function harvest_links(Y, links_holder, link_class, link_type) {
>
> I think this function would be cleaner if it returned the link_info
> array instead of putting it into links_holder. That way it need only
> accept two arguments, Y and link_class. Callers should check if the
> returned array is empty.
>
The code has been written so support processing for than just one type
of link. At the moment, there's only branch links. But there will also
be bugs links etc. So the code will look like:
var links_to_check = {}
harvest_links(Y, links_to_check, 'branch-
harvest_links(Y, links_to_check, 'bug-link', 'bugs_links');
etc
So we are building a dict mapping link_type_
The review comment would be valid if we only ever were going to process
the one type of link. I think the implementation as written is ok given
the above explanation?
>
> [14]
>
> Also, given [13] and the presence of the YUI collection module,
> harvest_links() could be much shorter and probably quicker:
>
> return Y.Array.unique(
> Y.all('.' + link_class)
>
> To get the collection module you'll need to add the following in the
> right place (I added it at line 108) in base-layout-
>
> <script type="text/
> tal:attributes="src string:
>
I think Array.unique() is only available in YUI 3.2 and at the time of
writing we were not using that version yet. I originally tried to use
Array.unique() only to be disappointed :-(
>
> [15]
>
> + alert(msg);
>
> Really? Just checking :)
I wanted to give the user feedback why the "link" they just clicked on
didn't seem to work instead of just swallowing the onclick().
> [16]
>
> In TestBranchBugLinks (which should probably be renamed), instead of
> creating a new question via the browser, consider creating a new
> question...
| Gavin Panella (allenap) wrote : | # |
> Thanks for the most excellent review. It's the most thorough one
> I've had.
I hope it was useful...
I often do quite thorough reviews and I worry that I'm being too
thorough. Let me know if you ever feel that my reviews are
demotivating or too picky. That would mean I'm doing it wrong :)
[14]
> I think Array.unique() is only available in YUI 3.2 and at the time
> of writing we were not using that version yet. I originally tried to
> use Array.unique() only to be disappointed :-(
Okay. Fwiw, this should work now in Launchpad, though it's confusing
because Array.unique() is a static function (or whatever YUI calls
it), and is not available on instances of Array.
[19]
> *news flash* - problem "solved" wtf. By changing the test to
> creating a bug instead of a question, it works in windmill. Go
> figure. But it works now \o/
Hurrah! And weird. But mostly hurrah :)
| Ian Booth (wallyworld) wrote : | # |
On 22/10/10 19:11, Gavin Panella wrote:
> Review: Approve
>> Thanks for the most excellent review. It's the most thorough one
>> I've had.
>
> I hope it was useful...
>
Extremely. Thanks. Especially since I'm a new to lp and have figured
stuff out mostly by trial and error or by looking at what others have
done or reverse engineering etc.
> I often do quite thorough reviews and I worry that I'm being too
> thorough. Let me know if you ever feel that my reviews are
> demotivating or too picky. That would mean I'm doing it wrong :)
>
>
On the contrary, I see code reviews as a great learning opportunity,
regardless of how experienced the code author may or may not be. A 2nd
set of eyes always picks up issues that the author is often too close to
the code to see. Plus they are a great way to help share knowledge
across team boundaries.

Just a note, not a review: why so much 2009 and so little 2010 in the copyright notices? :-)