Merge lp:~edwin-grubbs/launchpad/bug-602385-register-project-from-sourcepackage-page-part2 into lp:launchpad/db-devel
- bug-602385-register-project-from-sourcepackage-page-part2
- Merge into db-devel
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Curtis Hovey | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 9653 | ||||
Proposed branch: | lp:~edwin-grubbs/launchpad/bug-602385-register-project-from-sourcepackage-page-part2 | ||||
Merge into: | lp:launchpad/db-devel | ||||
Prerequisite: | lp:~edwin-grubbs/launchpad/bug-602385-register-project-from-sourcepackage-page | ||||
Diff against target: |
772 lines (+340/-97) 10 files modified
README (+106/-4) lib/canonical/launchpad/emailtemplates/product-other-license.txt (+3/-2) lib/canonical/widgets/product.py (+1/-0) lib/canonical/widgets/templates/license.pt (+23/-5) lib/lp/registry/browser/product.py (+81/-9) lib/lp/registry/browser/sourcepackage.py (+9/-6) lib/lp/registry/browser/tests/project-add-views.txt (+23/-23) lib/lp/registry/browser/tests/test_sourcepackage_views.py (+71/-39) lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt (+19/-5) lib/lp/registry/templates/product-new.pt (+4/-4) |
||||
To merge this branch: | bzr merge lp:~edwin-grubbs/launchpad/bug-602385-register-project-from-sourcepackage-page-part2 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Curtis Hovey (community) | ui | Approve | |
Leonard Richardson (community) | Approve | ||
Review via email: mp+32234@code.launchpad.net |
Commit message
Description of the change
Summary
-------
This branch finishes the work on bug 602385. When you register a project
off of the source package page, you will now get to see the source
package's copyright info, so that you can choose the license more
easily. When the project is created, it will automatically be linked to
the source package.
Implementation details
-------
Added LicenseWidget.
template can display $source_
lib/
lib/
Add source_package_name and distroseries hidden fields to
ProjectAddStepO
into self.request.form, since they are already available as
self.request.
Verify that the user is redirected back to the source package, that they
are linked, and that there is an informational message explaining that.
lib/
lib/
lib/
Add source_package_name and distroseries to the url that takes you from
the source package page to the /projects/+new page. Since the source
package is autolinked after creating the project, there is no need to
redirect the user back to +edit-packaging, so the return_url is now just
set to the canonical url for the source package.
lib/
lib/
Fixed bad tests that were dependent on copying fields from data to
self.request.form.
lib/
Tests
-----
./bin/test -vv -t 'test_sourcepac
Demo and Q/A
------------
Add copyright information on launchpad.dev by running this query.
UPDATE SourcePackageRe
SET copyright =
'The following line should be highlighted since it looks like a license
/usr/
foo
bar
baz
1
2
3
4';
* Open http://
1. Select "Register the upstream project" radio button.
2. Click on "Link to Upstream Project"
3. You should now be on Step 2 of the /projects/+new page.
4. Verify that clicking on the green "Copyright info from source package"
link expands the copyright.
5. Select a license.
6. Click on "Complete registration and link to pmount package".
7. You now be redirected back to
http://
There should be an informational message saying:
"Linked Pmount project to pmount source package"
and the "Upstream connections" portlet should show Pmount=>trunk.
* Click on the yellow edit-icon next to Pmount=>trunk.
* Click on the "Register the upstream project" link.
* The /projects/+new page should give you an error that pmount is
already used by another project.
* Choose a different URL, click Continue, click
"No, this is a new project", and then follow steps 3 through 6 above.
* If you didn't use a different displayname, you will have to hover
over the first link in Pmount=>trunk to see that it points to the
new pmount project and not the first one you created.
Edwin Grubbs (edwin-grubbs) wrote : | # |
Thanks for the review. The count was actually used by the javascript to decide whether to expand a section of licenses by the count of licenses checked. I changed the attribute to start_expanded to clearly describe its intent.
Curtis Hovey (sinzui) wrote : | # |
This looks nice. The lack realistic sourcepackages in sample data make this hard to see. I like what I do see. I think this is fine to land. We can fix issues that users report, or we see when the form is used with real data.
Preview Diff
1 | === modified file 'README' | |||
2 | --- README 2010-04-06 20:07:30 +0000 | |||
3 | +++ README 2010-08-12 16:55:41 +0000 | |||
4 | @@ -1,4 +1,106 @@ | |||
9 | 1 | This is the top level project, that supplies the infrastructure for testing, | 1 | ==================== |
10 | 2 | and running launchpad. | 2 | README for Launchpad |
11 | 3 | 3 | ==================== | |
12 | 4 | Documentation is in the doc directory or on the wiki. | 4 | |
13 | 5 | Launchpad is an open source suite of tools that help people and teams to work | ||
14 | 6 | together on software projects. Unlike many open source projects, Launchpad | ||
15 | 7 | isn't something you install and run yourself (although you are welcome to do | ||
16 | 8 | so), instead, contributors help make <https://launchpad.net> better. | ||
17 | 9 | |||
18 | 10 | Launchpad is a project of Canonical <http://www.canonical.com> and has | ||
19 | 11 | received many contributions from many wonderful people | ||
20 | 12 | <https://dev.launchpad.net/Contributions>. | ||
21 | 13 | |||
22 | 14 | If you want help using Launchpad, then please visit our help wiki at: | ||
23 | 15 | |||
24 | 16 | https://help.launchpad.net | ||
25 | 17 | |||
26 | 18 | If you'd like to contribute to Launchpad, have a look at: | ||
27 | 19 | |||
28 | 20 | https://dev.launchpad.net | ||
29 | 21 | |||
30 | 22 | Alternatively, have a poke around in the code, which you probably already know | ||
31 | 23 | how to get if you are reading this file. | ||
32 | 24 | |||
33 | 25 | |||
34 | 26 | Getting started | ||
35 | 27 | =============== | ||
36 | 28 | |||
37 | 29 | There's a full guide for getting up-and-running with a development Launchpad | ||
38 | 30 | environment at <https://dev.launchpad.net/Getting>. When you are ready to | ||
39 | 31 | submit a patch, please consult <https://dev.launchpad.net/PatchSubmission>. | ||
40 | 32 | |||
41 | 33 | Our bug tracker is at <https://bugs.launchpad.net/launchpad/> and you can get | ||
42 | 34 | the source code any time by doing: | ||
43 | 35 | |||
44 | 36 | $ bzr branch lp:launchpad | ||
45 | 37 | |||
46 | 38 | |||
47 | 39 | Navigating the tree | ||
48 | 40 | ------------------- | ||
49 | 41 | |||
50 | 42 | The Launchpad tree is big, messy and changing. Sorry about that. Don't panic | ||
51 | 43 | though, it can sense fear. Keep a firm grip on `grep` and pay attention to | ||
52 | 44 | these important top-level folders: | ||
53 | 45 | |||
54 | 46 | bin/, utilities/ | ||
55 | 47 | Where you will find scripts intended for developers and admins. There's | ||
56 | 48 | no rhyme or reason to what goes in bin/ and what goes in utilities/, so | ||
57 | 49 | take a look in both. bin/ will be empty in a fresh checkout, the actual | ||
58 | 50 | content lives in 'buildout-templates'. | ||
59 | 51 | |||
60 | 52 | configs/ | ||
61 | 53 | Configuration files for various kinds of Launchpad instances. | ||
62 | 54 | 'development' and 'testrunner' are of particular interest to developers. | ||
63 | 55 | |||
64 | 56 | cronscripts/ | ||
65 | 57 | Scripts that are run on actual production instances of Launchpad as | ||
66 | 58 | cronjobs. | ||
67 | 59 | |||
68 | 60 | daemons/ | ||
69 | 61 | Entry points for various daemons that form part of Launchpad | ||
70 | 62 | |||
71 | 63 | database/ | ||
72 | 64 | Our database schema, our sample data, and some other stuff that causes | ||
73 | 65 | fear. | ||
74 | 66 | |||
75 | 67 | doc/ | ||
76 | 68 | General system-wide documentation. You can also find documentation on | ||
77 | 69 | <https://dev.launchpad.net>, in docstrings and in doctests. | ||
78 | 70 | |||
79 | 71 | lib/ | ||
80 | 72 | Where the vast majority of the code lives, along with our templates, tests | ||
81 | 73 | and the bits of our documentation that are written as doctests. 'lp' and | ||
82 | 74 | 'canonical' are the two most interesting packages. Note that 'canonical' | ||
83 | 75 | is deprecated in favour of 'lp'. To learn more about how the 'lp' package | ||
84 | 76 | is laid out, take a look at its docstring. | ||
85 | 77 | |||
86 | 78 | Makefile | ||
87 | 79 | Ahh, bliss. The Makefile has all sorts of goodies. If you spend any | ||
88 | 80 | length of time hacking on Launchpad, you'll use it often. The most | ||
89 | 81 | important targets are 'make clean', 'make compile', 'make schema', 'make | ||
90 | 82 | run' and 'make run_all'. | ||
91 | 83 | |||
92 | 84 | scripts/ | ||
93 | 85 | Scripts that are run on actual production instances of Launchpad, | ||
94 | 86 | generally triggered by some automatic process. | ||
95 | 87 | |||
96 | 88 | |||
97 | 89 | You can spend years hacking on Launchpad full-time and not know what all of | ||
98 | 90 | the files in the top-level directory are for. However, here's a guide to some | ||
99 | 91 | of the ones that come up from time to time. | ||
100 | 92 | |||
101 | 93 | buildout-templates/ | ||
102 | 94 | Templates that are generated into actual files, normally bin/ scripts, | ||
103 | 95 | when buildout is run. If you want to change the behaviour of bin/test, | ||
104 | 96 | look here. | ||
105 | 97 | |||
106 | 98 | bzrplugins/, optionalbzrplugins/ | ||
107 | 99 | Bazaar plugins used in running Launchpad. | ||
108 | 100 | |||
109 | 101 | sourcecode/ | ||
110 | 102 | A directory into which we symlink branches of some of Launchpad's | ||
111 | 103 | dependencies. Don't ask. | ||
112 | 104 | |||
113 | 105 | You never have to care about 'benchmarks', 'override-includes' or | ||
114 | 106 | 'package-includes'. | ||
115 | 5 | 107 | ||
116 | === modified file 'lib/canonical/launchpad/emailtemplates/product-other-license.txt' | |||
117 | --- lib/canonical/launchpad/emailtemplates/product-other-license.txt 2010-05-12 19:06:17 +0000 | |||
118 | +++ lib/canonical/launchpad/emailtemplates/product-other-license.txt 2010-08-12 16:55:41 +0000 | |||
119 | @@ -28,8 +28,9 @@ | |||
120 | 28 | questions. | 28 | questions. |
121 | 29 | 29 | ||
122 | 30 | Sometimes new projects are licensed as 'Other/Open Source' because the | 30 | Sometimes new projects are licensed as 'Other/Open Source' because the |
125 | 31 | licensing decisions have not yet been made. If that is your situation we urge | 31 | licensing decisions have not yet been made. If that is your situation |
126 | 32 | you to update the licensing in Launchpad as soon as you make that choice. | 32 | we urge you to update the licensing in Launchpad as soon as you make |
127 | 33 | that choice. | ||
128 | 33 | 34 | ||
129 | 34 | If the license for your project needs to be corrected you can do so by | 35 | If the license for your project needs to be corrected you can do so by |
130 | 35 | following the 'Change Details' link on your project's overview page. | 36 | following the 'Change Details' link on your project's overview page. |
131 | 36 | 37 | ||
132 | === modified file 'lib/canonical/widgets/product.py' | |||
133 | --- lib/canonical/widgets/product.py 2010-06-21 04:08:54 +0000 | |||
134 | +++ lib/canonical/widgets/product.py 2010-08-12 16:55:41 +0000 | |||
135 | @@ -316,6 +316,7 @@ | |||
136 | 316 | self, 'license_info', self.license_info, IInputWidget, | 316 | self, 'license_info', self.license_info, IInputWidget, |
137 | 317 | prefix='field', value=initial_value, | 317 | prefix='field', value=initial_value, |
138 | 318 | context=field.context) | 318 | context=field.context) |
139 | 319 | self.source_package_release = None | ||
140 | 319 | # These will get filled in by _categorize(). They are the number of | 320 | # These will get filled in by _categorize(). They are the number of |
141 | 320 | # selected licenses in the category. The actual count doesn't matter, | 321 | # selected licenses in the category. The actual count doesn't matter, |
142 | 321 | # since if it's greater than 0 it will start opened. NOte that we | 322 | # since if it's greater than 0 it will start opened. NOte that we |
143 | 322 | 323 | ||
144 | === modified file 'lib/canonical/widgets/templates/license.pt' | |||
145 | --- lib/canonical/widgets/templates/license.pt 2009-07-17 17:59:07 +0000 | |||
146 | +++ lib/canonical/widgets/templates/license.pt 2010-08-12 16:55:41 +0000 | |||
147 | @@ -42,7 +42,7 @@ | |||
148 | 42 | // the slider depends on whether there are any checked | 42 | // the slider depends on whether there are any checked |
149 | 43 | // licenses in that category. A '0' means 'no'. | 43 | // licenses in that category. A '0' means 'no'. |
150 | 44 | var arrow = Y.get(arrow_name); | 44 | var arrow = Y.get(arrow_name); |
152 | 45 | if (arrow.getAttribute('count') == '0') { | 45 | if (arrow.getAttribute('start_expanded') == '0') { |
153 | 46 | target.slide = Y.lazr.effects.slide_in(table_name); | 46 | target.slide = Y.lazr.effects.slide_in(table_name); |
154 | 47 | } | 47 | } |
155 | 48 | else { | 48 | else { |
156 | @@ -76,6 +76,7 @@ | |||
157 | 76 | target.slide.run(); | 76 | target.slide.run(); |
158 | 77 | }, target_name); | 77 | }, target_name); |
159 | 78 | } | 78 | } |
160 | 79 | make_slider({which: 'copyright'}); | ||
161 | 79 | make_slider({which: 'recommended'}); | 80 | make_slider({which: 'recommended'}); |
162 | 80 | make_slider({which: 'more'}); | 81 | make_slider({which: 'more'}); |
163 | 81 | make_slider({which: 'deprecated'}); | 82 | make_slider({which: 'deprecated'}); |
164 | @@ -136,6 +137,23 @@ | |||
165 | 136 | //]]> | 137 | //]]> |
166 | 137 | </script> | 138 | </script> |
167 | 138 | <div style="color: black"> | 139 | <div style="color: black"> |
168 | 140 | <tal:copyright condition="view/source_package_release"> | ||
169 | 141 | <a href="" id="copyright-expand" class="js-action"> | ||
170 | 142 | <img id="copyright-expand-arrow" | ||
171 | 143 | src="/@@/treeCollapsed" | ||
172 | 144 | title="Copyright info from source package" | ||
173 | 145 | alt="Copyright info from source package" | ||
174 | 146 | start_expanded="0"/> | ||
175 | 147 | Copyright info from source package | ||
176 | 148 | </a> | ||
177 | 149 | <div id="copyright"> | ||
178 | 150 | <div | ||
179 | 151 | tal:content="structure view/source_package_release/@@+copyright" | ||
180 | 152 | style="overflow-x: hidden; overflow-y: auto; | ||
181 | 153 | max-width: 60em; max-height: 32em; background: #f7f7f7" | ||
182 | 154 | /> | ||
183 | 155 | </div> | ||
184 | 156 | </tal:copyright> | ||
185 | 139 | 157 | ||
186 | 140 | Select the license(s) under which you release your project. | 158 | Select the license(s) under which you release your project. |
187 | 141 | <div tal:condition="view/allow_pending_license" | 159 | <div tal:condition="view/allow_pending_license" |
188 | @@ -159,7 +177,7 @@ | |||
189 | 159 | src="/@@/treeExpanded" | 177 | src="/@@/treeExpanded" |
190 | 160 | title="Recommended open source licenses" | 178 | title="Recommended open source licenses" |
191 | 161 | alt="Recommended open source licenses" | 179 | alt="Recommended open source licenses" |
193 | 162 | tal:attributes="count view/recommended_count"/> | 180 | tal:attributes="start_expanded view/recommended_count"/> |
194 | 163 | Recommended open source licenses | 181 | Recommended open source licenses |
195 | 164 | </a> | 182 | </a> |
196 | 165 | <input tal:replace="structure view/recommended" /> | 183 | <input tal:replace="structure view/recommended" /> |
197 | @@ -168,7 +186,7 @@ | |||
198 | 168 | src="/@@/treeCollapsed" | 186 | src="/@@/treeCollapsed" |
199 | 169 | title="More open source licenses" | 187 | title="More open source licenses" |
200 | 170 | alt="More open source licenses" | 188 | alt="More open source licenses" |
202 | 171 | tal:attributes="count view/more_count"/> | 189 | tal:attributes="start_expanded view/more_count"/> |
203 | 172 | More open source licenses | 190 | More open source licenses |
204 | 173 | </a> | 191 | </a> |
205 | 174 | <input tal:replace="structure view/more" /> | 192 | <input tal:replace="structure view/more" /> |
206 | @@ -178,7 +196,7 @@ | |||
207 | 178 | src="/@@/treeCollapsed" | 196 | src="/@@/treeCollapsed" |
208 | 179 | title="Deprecated licenses" | 197 | title="Deprecated licenses" |
209 | 180 | alt="Deprecated licenses" | 198 | alt="Deprecated licenses" |
211 | 181 | tal:attributes="count view/deprecated_count"/> | 199 | tal:attributes="start_expanded view/deprecated_count"/> |
212 | 182 | Deprecated licenses | 200 | Deprecated licenses |
213 | 183 | </a> | 201 | </a> |
214 | 184 | <input tal:replace="structure view/deprecated" /> | 202 | <input tal:replace="structure view/deprecated" /> |
215 | @@ -188,7 +206,7 @@ | |||
216 | 188 | src="/@@/treeCollapsed" | 206 | src="/@@/treeCollapsed" |
217 | 189 | title="Other choices" | 207 | title="Other choices" |
218 | 190 | alt="Other choices" | 208 | alt="Other choices" |
220 | 191 | tal:attributes="count view/special_count"/> | 209 | tal:attributes="start_expanded view/special_count"/> |
221 | 192 | Other choices | 210 | Other choices |
222 | 193 | </a> | 211 | </a> |
223 | 194 | <input tal:replace="structure view/special" /> | 212 | <input tal:replace="structure view/special" /> |
224 | 195 | 213 | ||
225 | === modified file 'lib/lp/registry/browser/product.py' | |||
226 | --- lib/lp/registry/browser/product.py 2010-08-12 16:55:39 +0000 | |||
227 | +++ lib/lp/registry/browser/product.py 2010-08-12 16:55:41 +0000 | |||
228 | @@ -83,6 +83,7 @@ | |||
229 | 83 | from lp.registry.interfaces.pillar import IPillarNameSet | 83 | from lp.registry.interfaces.pillar import IPillarNameSet |
230 | 84 | from lp.registry.interfaces.product import IProductReviewSearch, License | 84 | from lp.registry.interfaces.product import IProductReviewSearch, License |
231 | 85 | from lp.registry.interfaces.series import SeriesStatus | 85 | from lp.registry.interfaces.series import SeriesStatus |
232 | 86 | from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet | ||
233 | 86 | from lp.registry.interfaces.product import ( | 87 | from lp.registry.interfaces.product import ( |
234 | 87 | IProduct, IProductSet, LicenseStatus) | 88 | IProduct, IProductSet, LicenseStatus) |
235 | 88 | from lp.registry.interfaces.productrelease import ( | 89 | from lp.registry.interfaces.productrelease import ( |
236 | @@ -1833,6 +1834,17 @@ | |||
237 | 1833 | return canonical_url(self.product) | 1834 | return canonical_url(self.product) |
238 | 1834 | 1835 | ||
239 | 1835 | 1836 | ||
240 | 1837 | def create_source_package_fields(): | ||
241 | 1838 | return form.Fields( | ||
242 | 1839 | Choice(__name__='source_package_name', | ||
243 | 1840 | vocabulary='SourcePackageName', | ||
244 | 1841 | required=False), | ||
245 | 1842 | Choice(__name__='distroseries', | ||
246 | 1843 | vocabulary='DistroSeries', | ||
247 | 1844 | required=False), | ||
248 | 1845 | ) | ||
249 | 1846 | |||
250 | 1847 | |||
251 | 1836 | class ProjectAddStepOne(StepView): | 1848 | class ProjectAddStepOne(StepView): |
252 | 1837 | """product/+new view class for creating a new project.""" | 1849 | """product/+new view class for creating a new project.""" |
253 | 1838 | 1850 | ||
254 | @@ -1849,6 +1861,19 @@ | |||
255 | 1849 | step_description = 'Project basics' | 1861 | step_description = 'Project basics' |
256 | 1850 | search_results_count = 0 | 1862 | search_results_count = 0 |
257 | 1851 | 1863 | ||
258 | 1864 | def setUpFields(self): | ||
259 | 1865 | """See `LaunchpadFormView`.""" | ||
260 | 1866 | super(ProjectAddStepOne, self).setUpFields() | ||
261 | 1867 | self.form_fields = ( | ||
262 | 1868 | self.form_fields + | ||
263 | 1869 | create_source_package_fields()) | ||
264 | 1870 | |||
265 | 1871 | def setUpWidgets(self): | ||
266 | 1872 | """See `LaunchpadFormView`.""" | ||
267 | 1873 | super(ProjectAddStepOne, self).setUpWidgets() | ||
268 | 1874 | self.widgets['source_package_name'].visible = False | ||
269 | 1875 | self.widgets['distroseries'].visible = False | ||
270 | 1876 | |||
271 | 1852 | @property | 1877 | @property |
272 | 1853 | def _return_url(self): | 1878 | def _return_url(self): |
273 | 1854 | """This view is using the hidden _return_url field. | 1879 | """This view is using the hidden _return_url field. |
274 | @@ -1872,9 +1897,6 @@ | |||
275 | 1872 | def main_action(self, data): | 1897 | def main_action(self, data): |
276 | 1873 | """See `MultiStepView`.""" | 1898 | """See `MultiStepView`.""" |
277 | 1874 | self.next_step = self._next_step | 1899 | self.next_step = self._next_step |
278 | 1875 | self.request.form['displayname'] = data['displayname'] | ||
279 | 1876 | self.request.form['name'] = data['name'].lower() | ||
280 | 1877 | self.request.form['summary'] = data['summary'] | ||
281 | 1878 | 1900 | ||
282 | 1879 | # Make this a safe_action, so that the sourcepackage page can skip | 1901 | # Make this a safe_action, so that the sourcepackage page can skip |
283 | 1880 | # the first step with a link (GET request) providing form values. | 1902 | # the first step with a link (GET request) providing form values. |
284 | @@ -1887,7 +1909,6 @@ | |||
285 | 1887 | _field_names = ['displayname', 'name', 'title', 'summary', | 1909 | _field_names = ['displayname', 'name', 'title', 'summary', |
286 | 1888 | 'description', 'licenses', 'license_info', | 1910 | 'description', 'licenses', 'license_info', |
287 | 1889 | ] | 1911 | ] |
288 | 1890 | main_action_label = u'Complete Registration' | ||
289 | 1891 | schema = IProduct | 1912 | schema = IProduct |
290 | 1892 | step_name = 'projectaddstep2' | 1913 | step_name = 'projectaddstep2' |
291 | 1893 | template = ViewPageTemplateFile('../templates/product-new.pt') | 1914 | template = ViewPageTemplateFile('../templates/product-new.pt') |
292 | @@ -1901,6 +1922,15 @@ | |||
293 | 1901 | custom_widget('license_info', GhostWidget) | 1922 | custom_widget('license_info', GhostWidget) |
294 | 1902 | 1923 | ||
295 | 1903 | @property | 1924 | @property |
296 | 1925 | def main_action_label(self): | ||
297 | 1926 | if self.source_package_name is None: | ||
298 | 1927 | return u'Complete Registration' | ||
299 | 1928 | else: | ||
300 | 1929 | return u'Complete registration and link to %s package' % ( | ||
301 | 1930 | self.source_package_name.name, | ||
302 | 1931 | ) | ||
303 | 1932 | |||
304 | 1933 | @property | ||
305 | 1904 | def _return_url(self): | 1934 | def _return_url(self): |
306 | 1905 | """This view is using the hidden _return_url field. | 1935 | """This view is using the hidden _return_url field. |
307 | 1906 | 1936 | ||
308 | @@ -1921,7 +1951,8 @@ | |||
309 | 1921 | """See `LaunchpadFormView`.""" | 1951 | """See `LaunchpadFormView`.""" |
310 | 1922 | super(ProjectAddStepTwo, self).setUpFields() | 1952 | super(ProjectAddStepTwo, self).setUpFields() |
311 | 1923 | self.form_fields = (self.form_fields + | 1953 | self.form_fields = (self.form_fields + |
313 | 1924 | self._createDisclaimMaintainerField()) | 1954 | self._createDisclaimMaintainerField() + |
314 | 1955 | create_source_package_fields()) | ||
315 | 1925 | 1956 | ||
316 | 1926 | def _createDisclaimMaintainerField(self): | 1957 | def _createDisclaimMaintainerField(self): |
317 | 1927 | """Return a Bool field for disclaiming maintainer. | 1958 | """Return a Bool field for disclaiming maintainer. |
318 | @@ -1954,12 +1985,39 @@ | |||
319 | 1954 | "this will be the project's URL.") | 1985 | "this will be the project's URL.") |
320 | 1955 | self.widgets['displayname'].visible = False | 1986 | self.widgets['displayname'].visible = False |
321 | 1956 | 1987 | ||
322 | 1988 | self.widgets['source_package_name'].visible = False | ||
323 | 1989 | self.widgets['distroseries'].visible = False | ||
324 | 1990 | |||
325 | 1991 | # Set the source_package_release attribute on the licenses | ||
326 | 1992 | # widget, so that the source package's copyright info can be | ||
327 | 1993 | # displayed. | ||
328 | 1994 | ubuntu = getUtility(ILaunchpadCelebrities).ubuntu | ||
329 | 1995 | if self.source_package_name is not None: | ||
330 | 1996 | release_list = ubuntu.getCurrentSourceReleases( | ||
331 | 1997 | [self.source_package_name]) | ||
332 | 1998 | if len(release_list) != 0: | ||
333 | 1999 | self.widgets['licenses'].source_package_release = ( | ||
334 | 2000 | release_list.items()[0][1]) | ||
335 | 2001 | |||
336 | 2002 | @property | ||
337 | 2003 | def source_package_name(self): | ||
338 | 2004 | # setUpWidgets() doesn't have access to the data dictionary, | ||
339 | 2005 | # so the source package name needs to be converted from a string | ||
340 | 2006 | # into an object here. | ||
341 | 2007 | package_name_string = self.request.form.get( | ||
342 | 2008 | 'field.source_package_name') | ||
343 | 2009 | if package_name_string is None: | ||
344 | 2010 | return None | ||
345 | 2011 | else: | ||
346 | 2012 | return getUtility(ISourcePackageNameSet).queryByName( | ||
347 | 2013 | package_name_string) | ||
348 | 2014 | |||
349 | 1957 | @cachedproperty | 2015 | @cachedproperty |
350 | 1958 | def _search_string(self): | 2016 | def _search_string(self): |
351 | 1959 | """Return the ORed terms to match.""" | 2017 | """Return the ORed terms to match.""" |
355 | 1960 | search_text = SPACE.join((self.request.form['name'], | 2018 | search_text = SPACE.join((self.request.form['field.name'], |
356 | 1961 | self.request.form['displayname'], | 2019 | self.request.form['field.displayname'], |
357 | 1962 | self.request.form['summary'])) | 2020 | self.request.form['field.summary'])) |
358 | 1963 | # OR all the terms together. | 2021 | # OR all the terms together. |
359 | 1964 | return OR.join(search_text.split()) | 2022 | return OR.join(search_text.split()) |
360 | 1965 | 2023 | ||
361 | @@ -1996,7 +2054,8 @@ | |||
362 | 1996 | def label(self): | 2054 | def label(self): |
363 | 1997 | """See `LaunchpadFormView`.""" | 2055 | """See `LaunchpadFormView`.""" |
364 | 1998 | return 'Register %s (%s) in Launchpad' % ( | 2056 | return 'Register %s (%s) in Launchpad' % ( |
366 | 1999 | self.request.form['displayname'], self.request.form['name']) | 2057 | self.request.form['field.displayname'], |
367 | 2058 | self.request.form['field.name']) | ||
368 | 2000 | 2059 | ||
369 | 2001 | def create_product(self, data): | 2060 | def create_product(self, data): |
370 | 2002 | """Create the product from the user data.""" | 2061 | """Create the product from the user data.""" |
371 | @@ -2020,11 +2079,24 @@ | |||
372 | 2020 | license_info=data['license_info'], | 2079 | license_info=data['license_info'], |
373 | 2021 | project=project) | 2080 | project=project) |
374 | 2022 | 2081 | ||
375 | 2082 | def link_source_package(self, product, data): | ||
376 | 2083 | if (data.get('distroseries') is not None | ||
377 | 2084 | and self.source_package_name is not None): | ||
378 | 2085 | source_package = data['distroseries'].getSourcePackage( | ||
379 | 2086 | self.source_package_name) | ||
380 | 2087 | source_package.setPackaging( | ||
381 | 2088 | product.development_focus, self.user) | ||
382 | 2089 | self.request.response.addInfoNotification( | ||
383 | 2090 | 'Linked %s project to %s source package.' % ( | ||
384 | 2091 | product.displayname, self.source_package_name.name)) | ||
385 | 2092 | |||
386 | 2023 | def main_action(self, data): | 2093 | def main_action(self, data): |
387 | 2024 | """See `MultiStepView`.""" | 2094 | """See `MultiStepView`.""" |
388 | 2025 | self.product = self.create_product(data) | 2095 | self.product = self.create_product(data) |
389 | 2026 | self.notifyCommercialMailingList() | 2096 | self.notifyCommercialMailingList() |
390 | 2027 | notify(ObjectCreatedEvent(self.product)) | 2097 | notify(ObjectCreatedEvent(self.product)) |
391 | 2098 | self.link_source_package(self.product, data) | ||
392 | 2099 | |||
393 | 2028 | if self._return_url is None: | 2100 | if self._return_url is None: |
394 | 2029 | self.next_url = canonical_url(self.product) | 2101 | self.next_url = canonical_url(self.product) |
395 | 2030 | else: | 2102 | else: |
396 | 2031 | 2103 | ||
397 | === modified file 'lib/lp/registry/browser/sourcepackage.py' | |||
398 | --- lib/lp/registry/browser/sourcepackage.py 2010-08-12 16:55:39 +0000 | |||
399 | +++ lib/lp/registry/browser/sourcepackage.py 2010-08-12 16:55:41 +0000 | |||
400 | @@ -66,10 +66,15 @@ | |||
401 | 66 | from canonical.lazr.utils import smartquote | 66 | from canonical.lazr.utils import smartquote |
402 | 67 | 67 | ||
403 | 68 | 68 | ||
405 | 69 | def get_register_upstream_url(source_package, return_url): | 69 | def get_register_upstream_url(source_package): |
406 | 70 | displayname = string.capwords(source_package.name.replace('-', ' ')) | 70 | displayname = string.capwords(source_package.name.replace('-', ' ')) |
407 | 71 | distroseries_string = "%s/%s" % ( | ||
408 | 72 | source_package.distroseries.distribution.name, | ||
409 | 73 | source_package.distroseries.name) | ||
410 | 71 | params = { | 74 | params = { |
412 | 72 | '_return_url': return_url, | 75 | '_return_url': canonical_url(source_package), |
413 | 76 | 'field.source_package_name': source_package.sourcepackagename.name, | ||
414 | 77 | 'field.distroseries': distroseries_string, | ||
415 | 73 | 'field.name': source_package.name, | 78 | 'field.name': source_package.name, |
416 | 74 | 'field.displayname': displayname, | 79 | 'field.displayname': displayname, |
417 | 75 | 'field.title': displayname, | 80 | 'field.title': displayname, |
418 | @@ -220,8 +225,7 @@ | |||
419 | 220 | 225 | ||
420 | 221 | @property | 226 | @property |
421 | 222 | def register_upstream_url(self): | 227 | def register_upstream_url(self): |
424 | 223 | return get_register_upstream_url( | 228 | return get_register_upstream_url(self.context) |
423 | 224 | self.context, return_url=self.request.getURL()) | ||
425 | 225 | 229 | ||
426 | 226 | 230 | ||
427 | 227 | class SourcePackageChangeUpstreamStepTwo(ReturnToReferrerMixin, StepView): | 231 | class SourcePackageChangeUpstreamStepTwo(ReturnToReferrerMixin, StepView): |
428 | @@ -526,8 +530,7 @@ | |||
429 | 526 | return | 530 | return |
430 | 527 | elif upstream is self.register_upstream: | 531 | elif upstream is self.register_upstream: |
431 | 528 | # The user wants to create a new project. | 532 | # The user wants to create a new project. |
434 | 529 | url = get_register_upstream_url( | 533 | url = get_register_upstream_url(self.context) |
433 | 530 | self.context, return_url=self.request.getURL()) | ||
435 | 531 | self.request.response.redirect(url) | 534 | self.request.response.redirect(url) |
436 | 532 | return | 535 | return |
437 | 533 | self.context.setPackaging(upstream.development_focus, self.user) | 536 | self.context.setPackaging(upstream.development_focus, self.user) |
438 | 534 | 537 | ||
439 | === modified file 'lib/lp/registry/browser/tests/project-add-views.txt' | |||
440 | --- lib/lp/registry/browser/tests/project-add-views.txt 2010-05-25 04:41:12 +0000 | |||
441 | +++ lib/lp/registry/browser/tests/project-add-views.txt 2010-08-12 16:55:41 +0000 | |||
442 | @@ -15,25 +15,24 @@ | |||
443 | 15 | are forwarded in the form data to the second step. The title is also | 15 | are forwarded in the form data to the second step. The title is also |
444 | 16 | forwarded, but is only required by the Zope machinery, not the view. | 16 | forwarded, but is only required by the Zope machinery, not the view. |
445 | 17 | 17 | ||
447 | 18 | >>> form = {'field.actions.continue': 'Continue'} | 18 | >>> from lp.registry.browser.product import ProjectAddStepOne |
448 | 19 | >>> form = { | ||
449 | 20 | ... 'field.actions.continue': 'Continue', | ||
450 | 21 | ... 'field.__visited_steps__': ProjectAddStepOne.step_name, | ||
451 | 22 | ... 'field.displayname': '', | ||
452 | 23 | ... 'field.name': '', | ||
453 | 24 | ... 'field.summary': '', | ||
454 | 25 | ... } | ||
455 | 19 | 26 | ||
456 | 20 | >>> view = create_initialized_view(product_set, name='+new', form=form) | 27 | >>> view = create_initialized_view(product_set, name='+new', form=form) |
460 | 21 | Traceback (most recent call last): | 28 | >>> for error in view.view.errors: |
461 | 22 | ... | 29 | ... print error |
462 | 23 | KeyError: 'displayname' | 30 | ('displayname', 'Name', RequiredMissing()) |
463 | 31 | ('name', 'URL', RequiredMissing()) | ||
464 | 32 | ('summary', u'Summary', RequiredMissing()) | ||
465 | 24 | 33 | ||
466 | 25 | >>> form['field.displayname'] = 'Snowdog' | 34 | >>> form['field.displayname'] = 'Snowdog' |
467 | 26 | >>> view = create_initialized_view(product_set, name='+new', form=form) | ||
468 | 27 | Traceback (most recent call last): | ||
469 | 28 | ... | ||
470 | 29 | KeyError: 'name' | ||
471 | 30 | |||
472 | 31 | >>> form['field.name'] = 'snowdog' | 35 | >>> form['field.name'] = 'snowdog' |
473 | 32 | >>> view = create_initialized_view(product_set, name='+new', form=form) | ||
474 | 33 | Traceback (most recent call last): | ||
475 | 34 | ... | ||
476 | 35 | KeyError: 'summary' | ||
477 | 36 | |||
478 | 37 | >>> form['field.summary'] = 'By-tor and the Snowdog' | 36 | >>> form['field.summary'] = 'By-tor and the Snowdog' |
479 | 38 | >>> view = create_initialized_view(product_set, name='+new', form=form) | 37 | >>> view = create_initialized_view(product_set, name='+new', form=form) |
480 | 39 | 38 | ||
481 | @@ -44,7 +43,6 @@ | |||
482 | 44 | # steps individually. | 43 | # steps individually. |
483 | 45 | 44 | ||
484 | 46 | >>> from canonical.launchpad.webapp.servers import LaunchpadTestRequest | 45 | >>> from canonical.launchpad.webapp.servers import LaunchpadTestRequest |
485 | 47 | >>> from lp.registry.browser.product import ProjectAddStepOne | ||
486 | 48 | 46 | ||
487 | 49 | >>> form['field.__visited_steps__'] = ProjectAddStepOne.step_name | 47 | >>> form['field.__visited_steps__'] = ProjectAddStepOne.step_name |
488 | 50 | >>> request = LaunchpadTestRequest(form=form, method='POST') | 48 | >>> request = LaunchpadTestRequest(form=form, method='POST') |
489 | @@ -63,10 +61,12 @@ | |||
490 | 63 | 61 | ||
491 | 64 | >>> from lp.registry.browser.product import ProjectAddStepTwo | 62 | >>> from lp.registry.browser.product import ProjectAddStepTwo |
492 | 65 | >>> form = { | 63 | >>> form = { |
497 | 66 | ... 'displayname': 'Snowdog', | 64 | ... 'field.actions.continue': 'Continue', |
498 | 67 | ... 'name': 'snowdog', | 65 | ... 'field.__visited_steps__': ProjectAddStepTwo.step_name, |
499 | 68 | ... 'title': 'The Snowdog', | 66 | ... 'field.displayname': 'Snowdog', |
500 | 69 | ... 'summary': 'By-tor and the Snowdog', | 67 | ... 'field.name': 'snowdog', |
501 | 68 | ... 'field.title': 'The Snowdog', | ||
502 | 69 | ... 'field.summary': 'By-tor and the Snowdog', | ||
503 | 70 | ... } | 70 | ... } |
504 | 71 | 71 | ||
505 | 72 | >>> request = LaunchpadTestRequest(form=form, method='POST') | 72 | >>> request = LaunchpadTestRequest(form=form, method='POST') |
506 | @@ -90,7 +90,7 @@ | |||
507 | 90 | existing projects for possible matches. By tweaking the project summary, we | 90 | existing projects for possible matches. By tweaking the project summary, we |
508 | 91 | can see that there are search results available. | 91 | can see that there are search results available. |
509 | 92 | 92 | ||
511 | 93 | >>> form['summary'] = 'My Snowdog ate your Firefox' | 93 | >>> form['field.summary'] = 'My Snowdog ate your Firefox' |
512 | 94 | 94 | ||
513 | 95 | >>> request = LaunchpadTestRequest(form=form, method='POST') | 95 | >>> request = LaunchpadTestRequest(form=form, method='POST') |
514 | 96 | >>> view = ProjectAddStepTwo(product_set, request) | 96 | >>> view = ProjectAddStepTwo(product_set, request) |
515 | @@ -229,9 +229,9 @@ | |||
516 | 229 | questions. | 229 | questions. |
517 | 230 | <BLANKLINE> | 230 | <BLANKLINE> |
518 | 231 | Sometimes new projects are licensed as 'Other/Open Source' because the | 231 | Sometimes new projects are licensed as 'Other/Open Source' because the |
522 | 232 | licensing decisions have not yet been made. If that is your situation we u= | 232 | licensing decisions have not yet been made. If that is your situation |
523 | 233 | rge | 233 | we urge you to update the licensing in Launchpad as soon as you make |
524 | 234 | you to update the licensing in Launchpad as soon as you make that choice. | 234 | that choice. |
525 | 235 | <BLANKLINE> | 235 | <BLANKLINE> |
526 | 236 | If the license for your project needs to be corrected you can do so by | 236 | If the license for your project needs to be corrected you can do so by |
527 | 237 | following the 'Change Details' link on your project's overview page. | 237 | following the 'Change Details' link on your project's overview page. |
528 | 238 | 238 | ||
529 | === modified file 'lib/lp/registry/browser/tests/test_sourcepackage_views.py' | |||
530 | --- lib/lp/registry/browser/tests/test_sourcepackage_views.py 2010-08-12 16:55:39 +0000 | |||
531 | +++ lib/lp/registry/browser/tests/test_sourcepackage_views.py 2010-08-12 16:55:41 +0000 | |||
532 | @@ -9,11 +9,16 @@ | |||
533 | 9 | import urllib | 9 | import urllib |
534 | 10 | 10 | ||
535 | 11 | from zope.component import getUtility | 11 | from zope.component import getUtility |
536 | 12 | from zope.interface import implements | ||
537 | 12 | 13 | ||
538 | 13 | from canonical.testing import DatabaseFunctionalLayer | 14 | from canonical.testing import DatabaseFunctionalLayer |
539 | 14 | 15 | ||
540 | 16 | |||
541 | 15 | from lp.registry.browser.sourcepackage import get_register_upstream_url | 17 | from lp.registry.browser.sourcepackage import get_register_upstream_url |
543 | 16 | from lp.registry.interfaces.distroseries import IDistroSeriesSet | 18 | from lp.registry.interfaces.distribution import IDistribution |
544 | 19 | from lp.registry.interfaces.distroseries import ( | ||
545 | 20 | IDistroSeries, IDistroSeriesSet) | ||
546 | 21 | from lp.registry.interfaces.sourcepackage import ISourcePackage | ||
547 | 17 | from lp.soyuz.tests.test_publishing import SoyuzTestPublisher | 22 | from lp.soyuz.tests.test_publishing import SoyuzTestPublisher |
548 | 18 | from lp.testing import TestCaseWithFactory | 23 | from lp.testing import TestCaseWithFactory |
549 | 19 | 24 | ||
550 | @@ -24,25 +29,35 @@ | |||
551 | 24 | layer = DatabaseFunctionalLayer | 29 | layer = DatabaseFunctionalLayer |
552 | 25 | 30 | ||
553 | 26 | def test_get_register_upstream_url_displayname(self): | 31 | def test_get_register_upstream_url_displayname(self): |
554 | 32 | distroseries = self.factory.makeDistroRelease( | ||
555 | 33 | distribution=self.factory.makeDistribution(name='zoobuntu'), | ||
556 | 34 | name='walrus') | ||
557 | 27 | source_package = self.factory.makeSourcePackage( | 35 | source_package = self.factory.makeSourcePackage( |
558 | 36 | distroseries=distroseries, | ||
559 | 28 | sourcepackagename='python-super-package') | 37 | sourcepackagename='python-super-package') |
568 | 29 | return_url = 'http://example.com/foo?a=b&c=d' | 38 | url = get_register_upstream_url(source_package) |
569 | 30 | url = get_register_upstream_url(source_package, return_url) | 39 | expected_base = '/projects/+new' |
570 | 31 | expected_url = ( | 40 | expected_params = [ |
571 | 32 | '/projects/+new?' | 41 | ('_return_url', |
572 | 33 | '_return_url=' | 42 | 'http://launchpad.dev/zoobuntu/walrus/' |
573 | 34 | 'http%3A%2F%2Fexample.com%2Ffoo%3Fa%3Db%26c%3Dd' | 43 | '+source/python-super-package'), |
574 | 35 | '&field.__visited_steps__=projectaddstep1' | 44 | ('field.__visited_steps__', 'projectaddstep1'), |
575 | 36 | '&field.actions.continue=Continue' | 45 | ('field.actions.continue', 'Continue'), |
576 | 37 | # The sourcepackagename 'python-super-package' is split on | 46 | # The sourcepackagename 'python-super-package' is split on |
577 | 38 | # the hyphens, and each word is capitalized. | 47 | # the hyphens, and each word is capitalized. |
585 | 39 | '&field.displayname=Python+Super+Package' | 48 | ('field.displayname', 'Python Super Package'), |
586 | 40 | '&field.name=python-super-package' | 49 | ('field.distroseries', 'zoobuntu/walrus'), |
587 | 41 | # The summary is empty, since the source package doesn't | 50 | ('field.name', 'python-super-package'), |
588 | 42 | # have a binary package release. | 51 | # The summary is missing, since the source package doesn't |
589 | 43 | '&field.summary=' | 52 | # have a binary package release, and parse_qsl() excludes |
590 | 44 | '&field.title=Python+Super+Package') | 53 | # empty params. |
591 | 45 | self.assertEqual(expected_url, url) | 54 | ('field.source_package_name', 'python-super-package'), |
592 | 55 | ('field.title', 'Python Super Package'), | ||
593 | 56 | ] | ||
594 | 57 | base, query = urllib.splitquery(url) | ||
595 | 58 | params = cgi.parse_qsl(query) | ||
596 | 59 | self.assertEqual((expected_base, expected_params), | ||
597 | 60 | (base, params)) | ||
598 | 46 | 61 | ||
599 | 47 | def test_get_register_upstream_url_summary(self): | 62 | def test_get_register_upstream_url_summary(self): |
600 | 48 | test_publisher = SoyuzTestPublisher() | 63 | test_publisher = SoyuzTestPublisher() |
601 | @@ -57,15 +72,17 @@ | |||
602 | 57 | # objects need to be reloaded. | 72 | # objects need to be reloaded. |
603 | 58 | distroseries = getUtility(IDistroSeriesSet).get(distroseries_id) | 73 | distroseries = getUtility(IDistroSeriesSet).get(distroseries_id) |
604 | 59 | source_package = distroseries.getSourcePackage(source_package_name) | 74 | source_package = distroseries.getSourcePackage(source_package_name) |
607 | 60 | return_url = 'http://example.com/foo?a=b&c=d' | 75 | url = get_register_upstream_url(source_package) |
606 | 61 | url = get_register_upstream_url(source_package, return_url) | ||
608 | 62 | expected_base = '/projects/+new' | 76 | expected_base = '/projects/+new' |
609 | 63 | expected_params = [ | 77 | expected_params = [ |
611 | 64 | ('_return_url', 'http://example.com/foo?a=b&c=d'), | 78 | ('_return_url', |
612 | 79 | 'http://launchpad.dev/youbuntu/busy/+source/bonkers'), | ||
613 | 65 | ('field.__visited_steps__', 'projectaddstep1'), | 80 | ('field.__visited_steps__', 'projectaddstep1'), |
614 | 66 | ('field.actions.continue', 'Continue'), | 81 | ('field.actions.continue', 'Continue'), |
615 | 67 | ('field.displayname', 'Bonkers'), | 82 | ('field.displayname', 'Bonkers'), |
616 | 83 | ('field.distroseries', 'youbuntu/busy'), | ||
617 | 68 | ('field.name', 'bonkers'), | 84 | ('field.name', 'bonkers'), |
618 | 85 | ('field.source_package_name', 'bonkers'), | ||
619 | 69 | ('field.summary', 'summary for flubber-bin\n' | 86 | ('field.summary', 'summary for flubber-bin\n' |
620 | 70 | + 'summary for flubber-lib'), | 87 | + 'summary for flubber-lib'), |
621 | 71 | ('field.title', 'Bonkers'), | 88 | ('field.title', 'Bonkers'), |
622 | @@ -77,32 +94,47 @@ | |||
623 | 77 | 94 | ||
624 | 78 | def test_get_register_upstream_url_summary_duplicates(self): | 95 | def test_get_register_upstream_url_summary_duplicates(self): |
625 | 79 | 96 | ||
645 | 80 | class FakeDistroSeriesBinaryPackage: | 97 | class Faker: |
646 | 81 | def __init__(self, summary): | 98 | # Fakes attributes easily. |
647 | 82 | self.summary = summary | 99 | def __init__(self, **kw): |
648 | 83 | 100 | self.__dict__.update(kw) | |
649 | 84 | class FakeDistributionSourcePackageRelease: | 101 | |
650 | 85 | sample_binary_packages = [ | 102 | class FakeSourcePackage(Faker): |
651 | 86 | FakeDistroSeriesBinaryPackage('summary for foo'), | 103 | # Interface necessary for canonical_url() call in |
652 | 87 | FakeDistroSeriesBinaryPackage('summary for bar'), | 104 | # get_register_upstream_url(). |
653 | 88 | FakeDistroSeriesBinaryPackage('summary for baz'), | 105 | implements(ISourcePackage) |
654 | 89 | FakeDistroSeriesBinaryPackage('summary for baz'), | 106 | |
655 | 90 | ] | 107 | class FakeDistroSeries(Faker): |
656 | 91 | 108 | implements(IDistroSeries) | |
657 | 92 | class FakeSourcePackage: | 109 | |
658 | 93 | name = 'foo' | 110 | class FakeDistribution(Faker): |
659 | 94 | releases = [FakeDistributionSourcePackageRelease()] | 111 | implements(IDistribution) |
660 | 95 | 112 | ||
661 | 96 | source_package = FakeSourcePackage() | 113 | releases = Faker(sample_binary_packages=[ |
662 | 97 | return_url = 'http://example.com/foo?a=b&c=d' | 114 | Faker(summary='summary for foo'), |
663 | 98 | url = get_register_upstream_url(source_package, return_url) | 115 | Faker(summary='summary for bar'), |
664 | 116 | Faker(summary='summary for baz'), | ||
665 | 117 | Faker(summary='summary for baz'), | ||
666 | 118 | ]) | ||
667 | 119 | source_package = FakeSourcePackage( | ||
668 | 120 | name='foo', | ||
669 | 121 | sourcepackagename=Faker(name='foo'), | ||
670 | 122 | distroseries=FakeDistroSeries( | ||
671 | 123 | name='walrus', | ||
672 | 124 | distribution=FakeDistribution(name='zoobuntu')), | ||
673 | 125 | releases=[releases]) | ||
674 | 126 | |||
675 | 127 | url = get_register_upstream_url(source_package) | ||
676 | 99 | expected_base = '/projects/+new' | 128 | expected_base = '/projects/+new' |
677 | 100 | expected_params = [ | 129 | expected_params = [ |
679 | 101 | ('_return_url', 'http://example.com/foo?a=b&c=d'), | 130 | ('_return_url', |
680 | 131 | 'http://launchpad.dev/zoobuntu/walrus/+source/foo'), | ||
681 | 102 | ('field.__visited_steps__', 'projectaddstep1'), | 132 | ('field.__visited_steps__', 'projectaddstep1'), |
682 | 103 | ('field.actions.continue', 'Continue'), | 133 | ('field.actions.continue', 'Continue'), |
683 | 104 | ('field.displayname', 'Foo'), | 134 | ('field.displayname', 'Foo'), |
684 | 135 | ('field.distroseries', 'zoobuntu/walrus'), | ||
685 | 105 | ('field.name', 'foo'), | 136 | ('field.name', 'foo'), |
686 | 137 | ('field.source_package_name', 'foo'), | ||
687 | 106 | ('field.summary', 'summary for bar\n' | 138 | ('field.summary', 'summary for bar\n' |
688 | 107 | + 'summary for baz\n' | 139 | + 'summary for baz\n' |
689 | 108 | + 'summary for foo'), | 140 | + 'summary for foo'), |
690 | 109 | 141 | ||
691 | === modified file 'lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt' | |||
692 | --- lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt 2010-08-12 16:55:39 +0000 | |||
693 | +++ lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt 2010-08-12 16:55:41 +0000 | |||
694 | @@ -84,11 +84,13 @@ | |||
695 | 84 | ... 'Register the upstream project').selected = True | 84 | ... 'Register the upstream project').selected = True |
696 | 85 | >>> user_browser.getControl("Link to Upstream Project").click() | 85 | >>> user_browser.getControl("Link to Upstream Project").click() |
697 | 86 | >>> print user_browser.url.replace('&', '\n&') | 86 | >>> print user_browser.url.replace('&', '\n&') |
699 | 87 | http://launchpad.dev/projects/+new?_return_url=http...%2Bindex | 87 | http://launchpad.dev/projects/+new?_return_url=http...%2Bsource%2Fbonkers |
700 | 88 | &field.__visited_steps__=projectaddstep1 | 88 | &field.__visited_steps__=projectaddstep1 |
701 | 89 | &field.actions.continue=Continue | 89 | &field.actions.continue=Continue |
702 | 90 | &field.displayname=Bonkers | 90 | &field.displayname=Bonkers |
703 | 91 | &field.distroseries=youbuntu%2Fbusy | ||
704 | 91 | &field.name=bonkers | 92 | &field.name=bonkers |
705 | 93 | &field.source_package_name=bonkers | ||
706 | 92 | &field.summary=summary+for+flubber-bin%0Asummary+for+flubber-lib | 94 | &field.summary=summary+for+flubber-bin%0Asummary+for+flubber-lib |
707 | 93 | &field.title=Bonkers | 95 | &field.title=Bonkers |
708 | 94 | >>> print user_browser.getControl(name='field.name').value | 96 | >>> print user_browser.getControl(name='field.name').value |
709 | @@ -118,11 +120,13 @@ | |||
710 | 118 | 120 | ||
711 | 119 | >>> user_browser.getLink("Register the upstream project").click() | 121 | >>> user_browser.getLink("Register the upstream project").click() |
712 | 120 | >>> print user_browser.url.replace('&', '\n&') | 122 | >>> print user_browser.url.replace('&', '\n&') |
714 | 121 | http://launchpad.dev/projects/+new?_return_url=http...%2Bedit-packaging | 123 | http://launchpad.dev/projects/+new?_return_url=http...%2Bsource%2Fbonkers |
715 | 122 | &field.__visited_steps__=projectaddstep1 | 124 | &field.__visited_steps__=projectaddstep1 |
716 | 123 | &field.actions.continue=Continue | 125 | &field.actions.continue=Continue |
717 | 124 | &field.displayname=Bonkers | 126 | &field.displayname=Bonkers |
718 | 127 | &field.distroseries=youbuntu%2Fbusy | ||
719 | 125 | &field.name=bonkers | 128 | &field.name=bonkers |
720 | 129 | &field.source_package_name=bonkers | ||
721 | 126 | &field.summary=summary+for+flubber-bin%0Asummary+for+flubber-lib | 130 | &field.summary=summary+for+flubber-bin%0Asummary+for+flubber-lib |
722 | 127 | &field.title=Bonkers | 131 | &field.title=Bonkers |
723 | 128 | >>> print user_browser.getControl(name='field.name').value | 132 | >>> print user_browser.getControl(name='field.name').value |
724 | @@ -140,9 +144,19 @@ | |||
725 | 140 | 144 | ||
726 | 141 | If there are no problems with the prefilled data, then the license | 145 | If there are no problems with the prefilled data, then the license |
727 | 142 | just needs to be selected. The user will then be redirected back | 146 | just needs to be selected. The user will then be redirected back |
729 | 143 | to the source package page so that it can be linked. | 147 | to the source package page and an informational message will be displayed. |
730 | 144 | 148 | ||
731 | 145 | >>> user_browser.getControl(name='field.licenses').value = ['BSD'] | 149 | >>> user_browser.getControl(name='field.licenses').value = ['BSD'] |
733 | 146 | >>> user_browser.getControl("Complete Registration").click() | 150 | >>> user_browser.getControl( |
734 | 151 | ... "Complete registration and link to bonkers package").click() | ||
735 | 147 | >>> print user_browser.url | 152 | >>> print user_browser.url |
737 | 148 | http://launchpad.dev/youbuntu/busy/+source/bonkers/+edit-packaging | 153 | http://launchpad.dev/youbuntu/busy/+source/bonkers |
738 | 154 | >>> for tag in find_tags_by_class( | ||
739 | 155 | ... user_browser.contents, 'informational message'): | ||
740 | 156 | ... print extract_text(tag) | ||
741 | 157 | Linked Bonkers project to bonkers source package. | ||
742 | 158 | >>> print extract_text( | ||
743 | 159 | ... find_tag_by_id(user_browser.contents, 'upstreams')) | ||
744 | 160 | Bonkers ⇒ trunk | ||
745 | 161 | Change upstream link | ||
746 | 162 | Remove upstream link... | ||
747 | 149 | 163 | ||
748 | === modified file 'lib/lp/registry/templates/product-new.pt' | |||
749 | --- lib/lp/registry/templates/product-new.pt 2010-05-12 19:06:17 +0000 | |||
750 | +++ lib/lp/registry/templates/product-new.pt 2010-08-12 16:55:41 +0000 | |||
751 | @@ -299,8 +299,8 @@ | |||
752 | 299 | <img src="/@@/info" /> | 299 | <img src="/@@/info" /> |
753 | 300 | There are similar projects already registered in Launchpad. | 300 | There are similar projects already registered in Launchpad. |
754 | 301 | Is project | 301 | Is project |
757 | 302 | <strong><tal:displayname tal:replace="view/request/displayname" /> | 302 | <strong><tal:displayname tal:replace="view/request/field.displayname" /> |
758 | 303 | (<tal:name tal:replace="view/request/name" />)</strong> | 303 | (<tal:name tal:replace="view/request/field.name" />)</strong> |
759 | 304 | one of these? | 304 | one of these? |
760 | 305 | </div> | 305 | </div> |
761 | 306 | 306 | ||
762 | @@ -326,8 +326,8 @@ | |||
763 | 326 | tal:condition="view/search_results_count" | 326 | tal:condition="view/search_results_count" |
764 | 327 | >Registration details</h3> | 327 | >Registration details</h3> |
765 | 328 | Select the licenses for project | 328 | Select the licenses for project |
768 | 329 | <strong><tal:displayname tal:replace="view/request/displayname" /> | 329 | <strong><tal:displayname tal:replace="view/request/field.displayname" /> |
769 | 330 | (<tal:name tal:replace="view/request/name" />)</strong> | 330 | (<tal:name tal:replace="view/request/field.name" />)</strong> |
770 | 331 | and complete the registration. You may also update the project's | 331 | and complete the registration. You may also update the project's |
771 | 332 | title and summary. | 332 | title and summary. |
772 | 333 | </div> | 333 | </div> |
r=me with the minor changes discussed on IRC (Seeing whether 'count' is really neccessary, reformatting the line wrap when printing out the email so as to avoid confusing readers of the tests.)