Merge lp:~jtv/launchpad/bug-511097 into lp:launchpad

Proposed by Jeroen T. Vermeulen
Status: Merged
Approved by: Jeroen T. Vermeulen
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~jtv/launchpad/bug-511097
Merge into: lp:launchpad
Prerequisite: lp:~jtv/launchpad/bug-135052
Diff against target: 106 lines (+69/-5)
2 files modified
lib/lp/translations/browser/potemplate.py (+39/-2)
lib/lp/translations/stories/standalone/xx-potemplate-admin.txt (+30/-3)
To merge this branch: bzr merge lp:~jtv/launchpad/bug-511097
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve
Review via email: mp+18072@code.launchpad.net

Commit message

Make potemplate admin form check for uniqueness of changed name/domain.

To post a comment you must log in.
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

= Bug 511097 =

When a translation template's name or domain is changed, the new name must of course still be available within that package or productseries. There was no explicit check for this, and so the form would bomb out before it even got to a database constraint violation.

The failure was particularly horrific in the case of a name change, where the http(s) request gets redirected to an updated URL (the template's URL contains its name) which does not in fact exist because the name change failed. You wouldn't even get an oops in that case, just a "failed to contact server" message.

This branch builds on the fix for bug 135052 (not yet landed) which adds a validator method for the form in question.

To Q/A, go to the translations page for a source package or productseries with multiple translation templates. "Administer" (shiver) the template, changing its name and/or translation domain to that of one of the other templates. The form should come back with errors shown in red saying that the respective name and/or domain is already in use.

Test:
{{{
./bin/test -vv -t xx-potemplate-admin.txt
}}}

No lint.

Jeroen

Revision history for this message
Brad Crittenden (bac) wrote :

Hi Jeroen,

Nice branch and tests. One small suggestion.

Thanks!

--Brad

> === modified file 'lib/lp/translations/stories/standalone/xx-potemplate-admin.txt'
> --- lib/lp/translations/stories/standalone/xx-potemplate-admin.txt 2009-12-11 11:33:39 +0000
> +++ lib/lp/translations/stories/standalone/xx-potemplate-admin.txt 2010-01-26 12:50:30 +0000
> @@ -254,3 +254,67 @@
> >>> group_owner_browser.getControl('Change').click()

> +Input Check
> +-----------
> +
> +The template admin form requires either a productseries or a
> +distroseries.
> +
> + >>> login(ANONYMOUS)
> + >>> product = factory.makeProduct(name='aproduct')
> + >>> template = factory.makePOTemplate(
> + ... productseries=product.getSeries('trunk'))
> + >>> template_url = canonical_url(template)
> + >>> logout()
> +
> + >>> admin_browser.open(template_url + '/+admin')
> +
> + >>> admin_browser.getControl(name='field.distroseries').value = [None]
> + >>> admin_browser.getControl(name='field.productseries').value = ''
> + >>> admin_browser.getControl('Change').click()
> + >>> print_errors(admin_browser.contents)
> + There is 1 error.
> + Choose either a distribution release series or a project release series.
> +
> +It can't be both.
> +
> + >>> admin_browser.open(template_url + '/+admin')
> +
> + >>> admin_browser.getControl(name='field.distroseries').value = [
> + ... 'ubuntu/hoary']
> + >>> print admin_browser.getControl(name='field.productseries').value
> + aproduct/trunk

Rather than demonstrating that a value is already there it would be
easier to follow if you just set it, as above.

review: Approve (code)
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Brad,

Once again, your suggestion implemented with gratitude.

Jeroen

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/translations/browser/potemplate.py'
2--- lib/lp/translations/browser/potemplate.py 2010-01-21 15:57:29 +0000
3+++ lib/lp/translations/browser/potemplate.py 2010-02-01 19:29:25 +0000
4@@ -556,9 +556,33 @@
5 label = 'Administer translation template'
6 page_title = "Administer"
7
8+ def validateName(self, name, similar_templates):
9+ """Form submission changes template name. Validate it."""
10+ if name == self.context.name:
11+ # Not changed.
12+ return
13+
14+ if similar_templates.getPOTemplateByName(name) is not None:
15+ self.setFieldError('name', "Name is already in use.")
16+ return
17+
18+ def validateDomain(self, domain, similar_templates):
19+ if domain == self.context.translation_domain:
20+ # Not changed.
21+ return
22+
23+ other_template = similar_templates.getPOTemplateByTranslationDomain(
24+ domain)
25+ if other_template is not None:
26+ self.setFieldError(
27+ 'translation_domain', "Domain is already in use.")
28+ return
29+
30 def validate(self, data):
31- distroseries = data['distroseries']
32- productseries = data['productseries']
33+ distroseries = data.get('distroseries')
34+ sourcepackagename = data.get('sourcepackagename')
35+ productseries = data.get('productseries')
36+
37 if distroseries is not None and productseries is not None:
38 message = ("Choose a distribution release series or a project "
39 "release series, but not both.")
40@@ -570,6 +594,19 @@
41
42 if message is not None:
43 self.addError(message)
44+ return
45+
46+ # Validate name and domain; they should be unique within the
47+ # template's translation target (productseries or source
48+ # package). Validate against the target selected by the form,
49+ # not the template's existing target; the form may change the
50+ # template's target as well.
51+ similar_templates = getUtility(IPOTemplateSet).getSubset(
52+ distroseries=distroseries, sourcepackagename=sourcepackagename,
53+ productseries=productseries)
54+
55+ self.validateName(data.get('name'), similar_templates)
56+ self.validateDomain(data.get('translation_domain'), similar_templates)
57
58
59 class POTemplateExportView(BaseExportView):
60
61=== modified file 'lib/lp/translations/stories/standalone/xx-potemplate-admin.txt'
62--- lib/lp/translations/stories/standalone/xx-potemplate-admin.txt 2010-01-21 15:57:29 +0000
63+++ lib/lp/translations/stories/standalone/xx-potemplate-admin.txt 2010-02-01 19:29:25 +0000
64@@ -282,12 +282,39 @@
65
66 >>> admin_browser.getControl(name='field.distroseries').value = [
67 ... 'ubuntu/hoary']
68- >>> print admin_browser.getControl(name='field.productseries').value
69- aproduct/trunk
70+ >>> admin_browser.getControl(name='field.productseries').value = (
71+ ... 'aproduct/trunk')
72 >>> admin_browser.getControl('Change').click()
73 >>> print_errors(admin_browser.contents)
74 There is 1 error.
75 Choose a distribution release series or a project release series,
76 but not both.
77
78-
79+Also, the form won't allow you to set a name that duplicates that of
80+another template.
81+
82+ >>> login(ANONYMOUS)
83+ >>> other_template = factory.makePOTemplate(
84+ ... productseries=template.productseries)
85+ >>> other_name = other_template.name
86+ >>> other_domain = other_template.translation_domain
87+ >>> logout()
88+
89+ >>> admin_browser.open(template_url + '/+admin')
90+ >>> admin_browser.getControl(name='field.name').value = other_name
91+ >>> admin_browser.getControl('Change').click()
92+ >>> print_errors(admin_browser.contents)
93+ There is 1 error.
94+ Template name: Name is already in use.
95+ ...
96+
97+Similar for the translation domain.
98+
99+ >>> admin_browser.open(template_url + '/+admin')
100+ >>> admin_browser.getControl(name='field.translation_domain').value = (
101+ ... other_domain)
102+ >>> admin_browser.getControl('Change').click()
103+ >>> print_errors(admin_browser.contents)
104+ There is 1 error.
105+ Translation domain: Domain is already in use.
106+ ...