Merge lp:~jcsackett/launchpad/registry-errors-649836 into lp:launchpad

Proposed by j.c.sackett
Status: Merged
Approved by: j.c.sackett
Approved revision: no longer in the source branch.
Merged at revision: 11673
Proposed branch: lp:~jcsackett/launchpad/registry-errors-649836
Merge into: lp:launchpad
Diff against target: 1061 lines (+183/-178)
28 files modified
lib/canonical/launchpad/interfaces/__init__.py (+0/-1)
lib/canonical/launchpad/testing/pages.py (+2/-2)
lib/lp/code/model/branchlookup.py (+4/-2)
lib/lp/code/model/branchnamespace.py (+7/-9)
lib/lp/code/model/linkedbranch.py (+1/-1)
lib/lp/code/model/tests/test_branchlookup.py (+4/-2)
lib/lp/code/model/tests/test_branchnamespace.py (+4/-2)
lib/lp/code/model/tests/test_linkedbranch.py (+1/-1)
lib/lp/code/xmlrpc/branch.py (+4/-2)
lib/lp/registry/configure.zcml (+7/-0)
lib/lp/registry/errors.py (+97/-1)
lib/lp/registry/interfaces/distributionmirror.py (+6/-49)
lib/lp/registry/interfaces/distroseries.py (+1/-9)
lib/lp/registry/interfaces/person.py (+3/-21)
lib/lp/registry/interfaces/sourcepackagename.py (+2/-10)
lib/lp/registry/interfaces/structuralsubscription.py (+0/-16)
lib/lp/registry/interfaces/teammembership.py (+0/-12)
lib/lp/registry/model/distribution.py (+1/-2)
lib/lp/registry/model/distributionmirror.py (+10/-9)
lib/lp/registry/model/person.py (+2/-2)
lib/lp/registry/model/sourcepackagename.py (+3/-4)
lib/lp/registry/model/structuralsubscription.py (+4/-2)
lib/lp/registry/model/teammembership.py (+4/-2)
lib/lp/registry/tests/test_distribution.py (+1/-1)
lib/lp/registry/tests/test_distroseries.py (+4/-10)
lib/lp/registry/tests/test_person.py (+5/-3)
lib/lp/registry/tests/test_structuralsubscriptiontarget.py (+4/-2)
lib/lp/registry/tests/test_team_webservice.py (+2/-1)
To merge this branch: bzr merge lp:~jcsackett/launchpad/registry-errors-649836
Reviewer Review Type Date Requested Status
Edwin Grubbs (community) code Approve
Review via email: mp+36994@code.launchpad.net

Commit message

Creates an lp.registry.errors module to collect and register exceptions used by the webservice.

Description of the change

Summary
=======

Cleans up the webservice exceptions in registry by moving them all to lp.registry.errors and registering that module with the webservice. This helps our ongoing efforts to get away from circular import problems and start moving things out of canonical.launchpad.interfaces

Proposed Fix
============

Create an lp.registry.errors module and move all exceptions with the webservice_error directive in them to this module. Register the new module in lp/registry/configure.zcml so they're not part of the mess in canonical/launchpad.

Pre-Implementation Talk
=======================

Spoke with Curtis Hovey about restricting the scope of the branch since there's substantially more we'll want to move into errors over time.

Implementation details
======================

As in proposed.

Tests
=====

bin/test -m lp.registry
bin/test -t webservice

Demo and Q/A
============

This is largely not demo-able; everything over the webservice should continue to work largely as it has, with the exception of a few changed error codes. (400 -> more specific errors)

Lint
====

make lint output:

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/canonical/launchpad/testing/pages.py
  lib/lp/code/model/branchnamespace.py
  lib/lp/registry/errors.py
  lib/lp/registry/interfaces/distributionmirror.py
  lib/lp/registry/interfaces/person.py
  lib/lp/registry/interfaces/sourcepackagename.py
  lib/lp/registry/interfaces/teammembership.py
  lib/lp/registry/model/distribution.py
  lib/lp/registry/model/distributionmirror.py
  lib/lp/registry/model/person.py
  lib/lp/registry/model/sourcepackagename.py

./lib/canonical/launchpad/testing/pages.py
     460: E302 expected 2 blank lines, found 1
      96: Line contains a call to pdb.
./lib/lp/code/model/branchnamespace.py
     541: E301 expected 1 blank line, found 0
./lib/lp/registry/interfaces/distributionmirror.py
     163: Line exceeds 78 characters.
     169: Line exceeds 78 characters.
./lib/lp/registry/interfaces/person.py
     494: E302 expected 2 blank lines, found 1
./lib/lp/registry/model/distribution.py
    1254: E231 missing whitespace after ','
    1260: E231 missing whitespace after ','
    1272: E231 missing whitespace after ','
    1258: Line exceeds 78 characters.
./lib/lp/registry/model/distributionmirror.py
     589: E501 line too long (80 characters)
     455: Line exceeds 78 characters.
     473: Line exceeds 78 characters.
     589: Line exceeds 78 characters.
     807: Line exceeds 78 characters.
     860: Line exceeds 78 characters.
./lib/lp/registry/model/sourcepackagename.py
     148: W601 .has_key() is deprecated, use 'in'

This has touched so many files the lint output is all over the place; everything that's left is either lint complaining about valid things (e.g. commas in 1-tuples) or something I'm not sure should be altered. I have fixed everything that seems to related to my changes.

To post a comment you must log in.
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :

Hi JC,

Thanks for doing this boring refactoring work. I just have a couple of minor comments below.

-Edwin

>=== modified file 'lib/lp/registry/interfaces/distroseries.py'
>--- lib/lp/registry/interfaces/distroseries.py 2010-09-21 13:05:42 +0000
>+++ lib/lp/registry/interfaces/distroseries.py 2010-09-29 17:42:02 +0000
>@@ -12,7 +12,6 @@
> 'IDistroSeriesEditRestricted',
> 'IDistroSeriesPublic',
> 'IDistroSeriesSet',
>- 'NoSuchDistroSeries',
> ]
>
> from lazr.enum import DBEnumeratedType
>@@ -26,7 +25,6 @@
> operation_returns_collection_of,
> operation_returns_entry,
> rename_parameters_as,
>- webservice_error,
> )
> from lazr.restful.fields import (
> Reference,
>@@ -51,7 +49,6 @@
> from canonical.launchpad.validators.email import email_validator
> from canonical.launchpad.validators.name import name_validator
> from canonical.launchpad.validators.version import sane_version
>-from lp.app.errors import NameLookupFailed
> from lp.app.interfaces.launchpad import IServiceUsage
> from lp.blueprints.interfaces.specificationtarget import ISpecificationGoal
> from lp.bugs.interfaces.bugtarget import (
>@@ -59,6 +56,7 @@
> IHasBugs,
> IHasOfficialBugTags,
> )
>+from lp.registry.errors import NoSuchDistroSeries

It looks like we could use a separate file for special form fields,
since DistroSeriesNameField needs NoSuchDistroSeries, but we lose the
benefit of moving that exception to lp.registry.errors, if we are just
going to import it. Can you open a bug for that?

> from lp.registry.interfaces.milestone import (
> IHasMilestones,
> IMilestone,
>@@ -858,11 +856,5 @@
> """
>
>
>-class NoSuchDistroSeries(NameLookupFailed):
>- """Raised when we try to find a DistroSeries that doesn't exist."""
>- webservice_error(400) #Bad request.
>- _message_prefix = "No such distribution series"
>-
>-
> # Monkey patch for circular import avoidance done in
> # _schema_circular_imports.py
>
>=== modified file 'lib/lp/registry/interfaces/person.py'
>--- lib/lp/registry/interfaces/person.py 2010-09-24 21:10:47 +0000
>+++ lib/lp/registry/interfaces/person.py 2010-09-29 17:42:02 +0000
>@@ -65,9 +61,7 @@
> operation_returns_entry,
> rename_parameters_as,
> REQUEST_USER,
>- webservice_error,
> )
>-from lazr.restful.error import expose
> from lazr.restful.fields import (
> CollectionField,
> Reference,
>@@ -121,6 +115,9 @@
> IHasRequestedReviews,
> )
> from lp.code.interfaces.hasrecipes import IHasRecipes
>+from lp.registry.errors import (
>+ PrivatePersonLinkageError,
>+ )

Can you run utilities/format-imports on all the files you touched
in this branch? This import will fit on a single line.

> from lp.registry.interfaces.gpg import IGPGKey
> from lp.registry.interfaces.irc import IIrcID
> from lp.registry.interfaces.jabber import IJabberID

review: Approve (code)
Revision history for this message
j.c.sackett (jcsackett) wrote :

>> @@ -59,6 +56,7 @@
>> IHasBugs,
>> IHasOfficialBugTags,
>> )
>> +from lp.registry.errors import NoSuchDistroSeries
>
>
>
> It looks like we could use a separate file for special form fields,
> since DistroSeriesNameField needs NoSuchDistroSeries, but we lose the
> benefit of moving that exception to lp.registry.errors, if we are just
> going to import it. Can you open a bug for that?

I can and will.

>> from lp.code.interfaces.hasrecipes import IHasRecipes
>> +from lp.registry.errors import (
>> + PrivatePersonLinkageError,
>> + )
>
>
> Can you run utilities/format-imports on all the files you touched
> in this branch? This import will fit on a single line.

Done.

Thanks for the review, Edwin.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/interfaces/__init__.py'
2--- lib/canonical/launchpad/interfaces/__init__.py 2010-09-28 15:20:09 +0000
3+++ lib/canonical/launchpad/interfaces/__init__.py 2010-10-04 12:14:48 +0000
4@@ -96,7 +96,6 @@
5 from canonical.launchpad.interfaces.packagerelationship import *
6 from canonical.launchpad.interfaces.pathlookup import *
7 from lp.registry.interfaces.poll import *
8-from lp.registry.errors import TeamMembershipTransitionError
9 from lp.soyuz.interfaces.processor import *
10 from lp.registry.interfaces.product import *
11 from lp.registry.interfaces.productlicense import *
12
13=== modified file 'lib/canonical/launchpad/testing/pages.py'
14--- lib/canonical/launchpad/testing/pages.py 2010-08-20 20:31:18 +0000
15+++ lib/canonical/launchpad/testing/pages.py 2010-10-04 12:14:48 +0000
16@@ -63,7 +63,7 @@
17 from canonical.launchpad.webapp.interfaces import OAuthPermission
18 from canonical.launchpad.webapp.url import urlsplit
19 from canonical.testing import PageTestLayer
20-from lp.registry.interfaces.person import NameAlreadyTaken
21+from lp.registry.errors import NameAlreadyTaken
22 from lp.testing import (
23 ANONYMOUS,
24 launchpadlib_for,
25@@ -329,7 +329,7 @@
26 ( ) An unchecked option
27 """
28 main = BeautifulSoup(content)
29- buttons = main.findAll(
30+ buttons = main.findAll(
31 'input', {'name': 'field.%s' % name})
32 for button in buttons:
33 if button.parent.name == 'label':
34
35=== modified file 'lib/lp/code/model/branchlookup.py'
36--- lib/lp/code/model/branchlookup.py 2010-08-20 20:31:18 +0000
37+++ lib/lp/code/model/branchlookup.py 2010-10-04 12:14:48 +0000
38@@ -48,11 +48,14 @@
39 from lp.code.interfaces.branchnamespace import IBranchNamespaceSet
40 from lp.code.interfaces.linkedbranch import get_linked_to_branch
41 from lp.code.model.branch import Branch
42+from lp.registry.errors import (
43+ NoSuchDistroSeries,
44+ NoSuchSourcePackageName,
45+ )
46 from lp.registry.interfaces.distribution import IDistribution
47 from lp.registry.interfaces.distroseries import (
48 IDistroSeries,
49 IDistroSeriesSet,
50- NoSuchDistroSeries,
51 )
52 from lp.registry.interfaces.person import NoSuchPerson
53 from lp.registry.interfaces.pillar import IPillarNameSet
54@@ -62,7 +65,6 @@
55 NoSuchProduct,
56 )
57 from lp.registry.interfaces.productseries import NoSuchProductSeries
58-from lp.registry.interfaces.sourcepackagename import NoSuchSourcePackageName
59 from lp.registry.model.distribution import Distribution
60 from lp.registry.model.distroseries import DistroSeries
61 from lp.registry.model.person import Person
62
63=== modified file 'lib/lp/code/model/branchnamespace.py'
64--- lib/lp/code/model/branchnamespace.py 2010-08-20 20:31:18 +0000
65+++ lib/lp/code/model/branchnamespace.py 2010-10-04 12:14:48 +0000
66@@ -51,14 +51,15 @@
67 )
68 from lp.code.interfaces.branchtarget import IBranchTarget
69 from lp.code.model.branch import Branch
70+from lp.registry.errors import (
71+ NoSuchDistroSeries,
72+ NoSuchSourcePackageName,
73+ )
74 from lp.registry.interfaces.distribution import (
75 IDistributionSet,
76 NoSuchDistribution,
77 )
78-from lp.registry.interfaces.distroseries import (
79- IDistroSeriesSet,
80- NoSuchDistroSeries,
81- )
82+from lp.registry.interfaces.distroseries import IDistroSeriesSet
83 from lp.registry.interfaces.person import (
84 IPersonSet,
85 NoSuchPerson,
86@@ -70,10 +71,7 @@
87 NoSuchProduct,
88 )
89 from lp.registry.interfaces.projectgroup import IProjectGroup
90-from lp.registry.interfaces.sourcepackagename import (
91- ISourcePackageNameSet,
92- NoSuchSourcePackageName,
93- )
94+from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
95 from lp.registry.model.sourcepackage import SourcePackage
96 from lp.services.utils import iter_split
97
98@@ -302,7 +300,7 @@
99 @property
100 def name(self):
101 """See `IBranchNamespace`."""
102- return '~%s/+junk' % (self.owner.name,)
103+ return '~%s/+junk' % self.owner.name
104
105 def canBranchesBePrivate(self):
106 """See `IBranchNamespace`."""
107
108=== modified file 'lib/lp/code/model/linkedbranch.py'
109--- lib/lp/code/model/linkedbranch.py 2010-08-20 20:31:18 +0000
110+++ lib/lp/code/model/linkedbranch.py 2010-10-04 12:14:48 +0000
111@@ -17,10 +17,10 @@
112
113 from lp.archivepublisher.debversion import Version
114 from lp.code.interfaces.linkedbranch import ICanHasLinkedBranch
115+from lp.registry.errors import NoSuchDistroSeries
116 from lp.registry.interfaces.distributionsourcepackage import (
117 IDistributionSourcePackage,
118 )
119-from lp.registry.interfaces.distroseries import NoSuchDistroSeries
120 from lp.registry.interfaces.pocket import PackagePublishingPocket
121 from lp.registry.interfaces.product import IProduct
122 from lp.registry.interfaces.productseries import IProductSeries
123
124=== modified file 'lib/lp/code/model/tests/test_branchlookup.py'
125--- lib/lp/code/model/tests/test_branchlookup.py 2010-09-16 04:43:45 +0000
126+++ lib/lp/code/model/tests/test_branchlookup.py 2010-10-04 12:14:48 +0000
127@@ -26,7 +26,10 @@
128 )
129 from lp.code.interfaces.branchnamespace import get_branch_namespace
130 from lp.code.interfaces.linkedbranch import ICanHasLinkedBranch
131-from lp.registry.interfaces.distroseries import NoSuchDistroSeries
132+from lp.registry.errors import (
133+ NoSuchDistroSeries,
134+ NoSuchSourcePackageName,
135+ )
136 from lp.registry.interfaces.person import NoSuchPerson
137 from lp.registry.interfaces.pocket import PackagePublishingPocket
138 from lp.registry.interfaces.product import (
139@@ -34,7 +37,6 @@
140 NoSuchProduct,
141 )
142 from lp.registry.interfaces.productseries import NoSuchProductSeries
143-from lp.registry.interfaces.sourcepackagename import NoSuchSourcePackageName
144 from lp.testing import (
145 run_with_login,
146 TestCaseWithFactory,
147
148=== modified file 'lib/lp/code/model/tests/test_branchnamespace.py'
149--- lib/lp/code/model/tests/test_branchnamespace.py 2010-08-20 20:31:18 +0000
150+++ lib/lp/code/model/tests/test_branchnamespace.py 2010-10-04 12:14:48 +0000
151@@ -39,11 +39,13 @@
152 PersonalNamespace,
153 ProductNamespace,
154 )
155+from lp.registry.errors import (
156+ NoSuchDistroSeries,
157+ NoSuchSourcePackageName,
158+ )
159 from lp.registry.interfaces.distribution import NoSuchDistribution
160-from lp.registry.interfaces.distroseries import NoSuchDistroSeries
161 from lp.registry.interfaces.person import NoSuchPerson
162 from lp.registry.interfaces.product import NoSuchProduct
163-from lp.registry.interfaces.sourcepackagename import NoSuchSourcePackageName
164 from lp.registry.model.sourcepackage import SourcePackage
165 from lp.testing import TestCaseWithFactory
166
167
168=== modified file 'lib/lp/code/model/tests/test_linkedbranch.py'
169--- lib/lp/code/model/tests/test_linkedbranch.py 2010-08-20 20:31:18 +0000
170+++ lib/lp/code/model/tests/test_linkedbranch.py 2010-10-04 12:14:48 +0000
171@@ -18,7 +18,7 @@
172 get_linked_to_branch,
173 ICanHasLinkedBranch,
174 )
175-from lp.registry.interfaces.distroseries import NoSuchDistroSeries
176+from lp.registry.errors import NoSuchDistroSeries
177 from lp.registry.interfaces.pocket import PackagePublishingPocket
178 from lp.testing import (
179 run_with_login,
180
181=== modified file 'lib/lp/code/xmlrpc/branch.py'
182--- lib/lp/code/xmlrpc/branch.py 2010-09-07 05:39:39 +0000
183+++ lib/lp/code/xmlrpc/branch.py 2010-10-04 12:14:48 +0000
184@@ -52,7 +52,10 @@
185 compose_public_url,
186 SUPPORTED_SCHEMES,
187 )
188-from lp.registry.interfaces.distroseries import NoSuchDistroSeries
189+from lp.registry.errors import (
190+ NoSuchDistroSeries,
191+ NoSuchSourcePackageName,
192+ )
193 from lp.registry.interfaces.person import (
194 IPersonSet,
195 NoSuchPerson,
196@@ -63,7 +66,6 @@
197 NoSuchProduct,
198 )
199 from lp.registry.interfaces.productseries import NoSuchProductSeries
200-from lp.registry.interfaces.sourcepackagename import NoSuchSourcePackageName
201
202
203 class IBranchSetAPI(Interface):
204
205=== modified file 'lib/lp/registry/configure.zcml'
206--- lib/lp/registry/configure.zcml 2010-09-30 03:39:35 +0000
207+++ lib/lp/registry/configure.zcml 2010-10-04 12:14:48 +0000
208@@ -8,6 +8,7 @@
209 xmlns:i18n="http://namespaces.zope.org/i18n"
210 xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
211 xmlns:lp="http://namespaces.canonical.com/lp"
212+ xmlns:webservice="http://namespaces.canonical.com/webservice"
213 i18n_domain="launchpad">
214 <include
215 file="vocabularies.zcml"/>
216@@ -1872,6 +1873,12 @@
217 interface="lp.registry.interfaces.personproduct.IPersonProduct"/>
218 </class>
219
220+ <!-- Registers exceptions used in webservice defined in lp.registry.
221+ Other data is in module=canonical.launchpad.interfaces as defined in
222+ zcml there.-->
223+
224+ <webservice:register module="lp.registry.errors" />
225+
226 <adapter
227 provides="canonical.launchpad.webapp.interfaces.IBreadcrumb"
228 for="lp.registry.interfaces.personproduct.IPersonProduct"
229
230=== modified file 'lib/lp/registry/errors.py'
231--- lib/lp/registry/errors.py 2010-09-28 15:14:38 +0000
232+++ lib/lp/registry/errors.py 2010-10-04 12:14:48 +0000
233@@ -1,14 +1,110 @@
234-# Copyright 2009 Canonical Ltd. This software is licensed under the
235+# Copyright 2010 Canonical Ltd. This software is licensed under the
236 # GNU Affero General Public License version 3 (see the file LICENSE).
237
238 __metaclass__ = type
239 __all__ = [
240+ 'PrivatePersonLinkageError',
241+ 'NameAlreadyTaken',
242+ 'NoSuchDistroSeries',
243+ 'UserCannotChangeMembershipSilently',
244+ 'NoSuchSourcePackageName',
245+ 'CannotTransitionToCountryMirror',
246+ 'CountryMirrorAlreadySet',
247+ 'MirrorNotOfficial',
248+ 'MirrorHasNoHTTPURL',
249+ 'MirrorNotProbed',
250+ 'DeleteSubscriptionError',
251+ 'UserCannotSubscribePerson',
252 'TeamMembershipTransitionError',
253 ]
254
255 import httplib
256
257 from lazr.restful.declarations import webservice_error
258+from zope.security.interfaces import Unauthorized
259+
260+from lp.app.errors import NameLookupFailed
261+
262+
263+class PrivatePersonLinkageError(ValueError):
264+ """An attempt was made to link a private person/team to something."""
265+ webservice_error(httplib.FORBIDDEN)
266+
267+
268+class NameAlreadyTaken(Exception):
269+ """The name given for a person is already in use by other person."""
270+ webservice_error(httplib.CONFLICT)
271+
272+
273+class NoSuchDistroSeries(NameLookupFailed):
274+ """Raised when we try to find a DistroSeries that doesn't exist."""
275+ webservice_error(httplib.BAD_REQUEST)
276+ _message_prefix = "No such distribution series"
277+
278+
279+class UserCannotChangeMembershipSilently(Unauthorized):
280+ """User not permitted to change membership status silently.
281+
282+ Raised when a user tries to change someone's membership silently, and is
283+ not a Launchpad Administrator.
284+ """
285+ webservice_error(httplib.UNAUTHORIZED)
286+
287+
288+class NoSuchSourcePackageName(NameLookupFailed):
289+ """Raised when we can't find a particular sourcepackagename."""
290+ webservice_error(httplib.BAD_REQUEST)
291+ _message_prefix = "No such source package"
292+
293+
294+class CannotTransitionToCountryMirror(Exception):
295+ """Root exception for transitions to country mirrors."""
296+ webservice_error(httplib.BAD_REQUEST)
297+
298+
299+class CountryMirrorAlreadySet(CannotTransitionToCountryMirror):
300+ """Distribution mirror cannot be set as a country mirror.
301+
302+ Raised when a user tries to change set a distribution mirror as a country
303+ mirror, however there is already one set for that country.
304+ """
305+
306+
307+class MirrorNotOfficial(CannotTransitionToCountryMirror):
308+ """Distribution mirror is not permitted to become a country mirror.
309+
310+ Raised when a user tries to change set a distribution mirror as a country
311+ mirror, however the mirror in question is not official.
312+ """
313+
314+
315+class MirrorHasNoHTTPURL(CannotTransitionToCountryMirror):
316+ """Distribution mirror has no HTTP URL.
317+
318+ Raised when a user tries to make an official mirror a country mirror,
319+ however the mirror has not HTTP URL set.
320+ """
321+
322+
323+class MirrorNotProbed(CannotTransitionToCountryMirror):
324+ """Distribution mirror has not been probed.
325+
326+ Raised when a user tries to set an official mirror as a country mirror,
327+ however the mirror has not been probed yet.
328+ """
329+
330+
331+class DeleteSubscriptionError(Exception):
332+ """Delete Subscription Error.
333+
334+ Raised when an error occurred trying to delete a
335+ structural subscription."""
336+ webservice_error(httplib.BAD_REQUEST)
337+
338+
339+class UserCannotSubscribePerson(Exception):
340+ """User does not have permission to subscribe the person or team."""
341+ webservice_error(httplib.UNAUTHORIZED)
342
343
344 class TeamMembershipTransitionError(ValueError):
345
346=== modified file 'lib/lp/registry/interfaces/distributionmirror.py'
347--- lib/lp/registry/interfaces/distributionmirror.py 2010-08-20 20:31:18 +0000
348+++ lib/lp/registry/interfaces/distributionmirror.py 2010-10-04 12:14:48 +0000
349@@ -6,8 +6,6 @@
350 __metaclass__ = type
351
352 __all__ = [
353- 'CannotTransitionToCountryMirror',
354- 'CountryMirrorAlreadySet',
355 'IDistributionMirror',
356 'IMirrorDistroArchSeries',
357 'IMirrorDistroSeriesSource',
358@@ -16,11 +14,8 @@
359 'IMirrorCDImageDistroSeries',
360 'PROBE_INTERVAL',
361 'MirrorContent',
362+ 'MirrorSpeed',
363 'MirrorFreshness',
364- 'MirrorHasNoHTTPURL',
365- 'MirrorNotOfficial',
366- 'MirrorNotProbed',
367- 'MirrorSpeed',
368 'MirrorStatus',
369 'UnableToFetchCDImageFileList',
370 ]
371@@ -38,7 +33,6 @@
372 exported,
373 mutator_for,
374 operation_parameters,
375- webservice_error,
376 )
377 from lazr.restful.fields import (
378 Reference,
379@@ -76,43 +70,6 @@
380 PROBE_INTERVAL = 23
381
382
383-class CannotTransitionToCountryMirror(Exception):
384- """Root exception for transitions to country mirrors."""
385- webservice_error(400)
386-
387-
388-class CountryMirrorAlreadySet(CannotTransitionToCountryMirror):
389- """Distribution mirror cannot be set as a country mirror.
390-
391- Raised when a user tries to change set a distribution mirror as a country
392- mirror, however there is already one set for that country.
393- """
394-
395-
396-class MirrorNotOfficial(CannotTransitionToCountryMirror):
397- """Distribution mirror is not permitted to become a country mirror.
398-
399- Raised when a user tries to change set a distribution mirror as a country
400- mirror, however the mirror in question is not official.
401- """
402-
403-
404-class MirrorHasNoHTTPURL(CannotTransitionToCountryMirror):
405- """Distribution mirror has no HTTP URL.
406-
407- Raised when a user tries to make an official mirror a country mirror,
408- however the mirror has not HTTP URL set.
409- """
410-
411-
412-class MirrorNotProbed(CannotTransitionToCountryMirror):
413- """Distribution mirror has not been probed.
414-
415- Raised when a user tries to set an official mirror as a country mirror,
416- however the mirror has not been probed yet.
417- """
418-
419-
420 class MirrorContent(DBEnumeratedType):
421 """The content that is mirrored."""
422
423@@ -191,13 +148,13 @@
424 S2G = DBItem(90, """
425 2 Gbps
426
427- The upstream link of this mirror can make up to 2 gigabit per second.
428+ The upstream link of this mirror can make up to 2 gigabits per second.
429 """)
430
431 S4G = DBItem(100, """
432 4 Gbps
433
434- The upstream link of this mirror can make up to 4 gigabit per second.
435+ The upstream link of this mirror can make up to 4 gigabits per second.
436 """)
437
438 S10G = DBItem(110, """
439@@ -359,7 +316,8 @@
440 owner = exported(PublicPersonChoice(
441 title=_('Owner'), readonly=False, vocabulary='ValidOwner',
442 required=True, description=_(
443- "The person who is set as the current administrator of this mirror.")))
444+ "The person who is set as the current administrator of this"
445+ "mirror.")))
446 distribution = exported(
447 Reference(
448 Interface,
449@@ -461,7 +419,7 @@
450 @operation_parameters(country_dns_mirror=copy_field(country_dns_mirror))
451 @export_write_operation()
452 def transitionToCountryMirror(country_dns_mirror):
453- """Method run on changing country_dns_mirror."""
454+ """Method run on changing country_dns_mirror."""
455
456 @invariant
457 def mirrorMustHaveHTTPOrFTPURL(mirror):
458@@ -598,7 +556,6 @@
459 """
460
461
462-
463 class UnableToFetchCDImageFileList(Exception):
464 """Couldn't fetch the file list needed for probing cdimage mirrors."""
465
466
467=== modified file 'lib/lp/registry/interfaces/distroseries.py'
468--- lib/lp/registry/interfaces/distroseries.py 2010-09-21 13:05:42 +0000
469+++ lib/lp/registry/interfaces/distroseries.py 2010-10-04 12:14:48 +0000
470@@ -12,7 +12,6 @@
471 'IDistroSeriesEditRestricted',
472 'IDistroSeriesPublic',
473 'IDistroSeriesSet',
474- 'NoSuchDistroSeries',
475 ]
476
477 from lazr.enum import DBEnumeratedType
478@@ -26,7 +25,6 @@
479 operation_returns_collection_of,
480 operation_returns_entry,
481 rename_parameters_as,
482- webservice_error,
483 )
484 from lazr.restful.fields import (
485 Reference,
486@@ -51,7 +49,6 @@
487 from canonical.launchpad.validators.email import email_validator
488 from canonical.launchpad.validators.name import name_validator
489 from canonical.launchpad.validators.version import sane_version
490-from lp.app.errors import NameLookupFailed
491 from lp.app.interfaces.launchpad import IServiceUsage
492 from lp.blueprints.interfaces.specificationtarget import ISpecificationGoal
493 from lp.bugs.interfaces.bugtarget import (
494@@ -59,6 +56,7 @@
495 IHasBugs,
496 IHasOfficialBugTags,
497 )
498+from lp.registry.errors import NoSuchDistroSeries
499 from lp.registry.interfaces.milestone import (
500 IHasMilestones,
501 IMilestone,
502@@ -858,11 +856,5 @@
503 """
504
505
506-class NoSuchDistroSeries(NameLookupFailed):
507- """Raised when we try to find a DistroSeries that doesn't exist."""
508- webservice_error(400) #Bad request.
509- _message_prefix = "No such distribution series"
510-
511-
512 # Monkey patch for circular import avoidance done in
513 # _schema_circular_imports.py
514
515=== modified file 'lib/lp/registry/interfaces/person.py'
516--- lib/lp/registry/interfaces/person.py 2010-09-24 21:10:47 +0000
517+++ lib/lp/registry/interfaces/person.py 2010-10-04 12:14:48 +0000
518@@ -27,12 +27,10 @@
519 'ImmutableVisibilityError',
520 'InvalidName',
521 'JoinNotAllowed',
522- 'NameAlreadyTaken',
523 'NoSuchPerson',
524 'PersonCreationRationale',
525 'PersonVisibility',
526 'PersonalStanding',
527- 'PrivatePersonLinkageError',
528 'PRIVATE_TEAM_PREFIX',
529 'TeamContactMethod',
530 'TeamMembershipRenewalPolicy',
531@@ -41,8 +39,6 @@
532 'validate_public_person',
533 ]
534
535-import httplib
536-
537 from lazr.enum import (
538 DBEnumeratedType,
539 DBItem,
540@@ -65,9 +61,7 @@
541 operation_returns_entry,
542 rename_parameters_as,
543 REQUEST_USER,
544- webservice_error,
545 )
546-from lazr.restful.error import expose
547 from lazr.restful.fields import (
548 CollectionField,
549 Reference,
550@@ -121,6 +115,7 @@
551 IHasRequestedReviews,
552 )
553 from lp.code.interfaces.hasrecipes import IHasRecipes
554+from lp.registry.errors import PrivatePersonLinkageError
555 from lp.registry.interfaces.gpg import IGPGKey
556 from lp.registry.interfaces.irc import IIrcID
557 from lp.registry.interfaces.jabber import IJabberID
558@@ -158,14 +153,6 @@
559 PRIVATE_TEAM_PREFIX = 'private-'
560
561
562-class PrivatePersonLinkageError(ValueError):
563- """An attempt was made to link a private person/team to something."""
564- # HTTP 400 -- BAD REQUEST
565- # HTTP 403 would be better, but as this excpetion is raised inside a
566- # validator, it will default to 400 anyway.
567- webservice_error(httplib.BAD_REQUEST)
568-
569-
570 @block_implicit_flushes
571 def validate_person_common(obj, attr, value, validate_func):
572 """Validate the person using the supplied function."""
573@@ -178,10 +165,10 @@
574 from lp.registry.model.person import Person
575 person = Person.get(value)
576 if not validate_func(person):
577- raise expose(PrivatePersonLinkageError(
578+ raise PrivatePersonLinkageError(
579 "Cannot link person (name=%s, visibility=%s) to %s (name=%s)"
580 % (person.name, person.visibility.name,
581- obj, getattr(obj, 'name', None))))
582+ obj, getattr(obj, 'name', None)))
583 return value
584
585
586@@ -2182,11 +2169,6 @@
587 """The name given for a person is not valid."""
588
589
590-class NameAlreadyTaken(Exception):
591- """The name given for a person is already in use by other person."""
592- webservice_error(409)
593-
594-
595 class NoSuchPerson(NameLookupFailed):
596 """Raised when we try to look up an IPerson that doesn't exist."""
597
598
599=== modified file 'lib/lp/registry/interfaces/sourcepackagename.py'
600--- lib/lp/registry/interfaces/sourcepackagename.py 2010-08-20 20:31:18 +0000
601+++ lib/lp/registry/interfaces/sourcepackagename.py 2010-10-04 12:14:48 +0000
602@@ -10,10 +10,8 @@
603 __all__ = [
604 'ISourcePackageName',
605 'ISourcePackageNameSet',
606- 'NoSuchSourcePackageName',
607 ]
608
609-from lazr.restful.declarations import webservice_error
610 from zope.interface import (
611 Attribute,
612 Interface,
613@@ -25,7 +23,6 @@
614
615 from canonical.launchpad import _
616 from canonical.launchpad.validators.name import name_validator
617-from lp.app.errors import NameLookupFailed
618
619
620 class ISourcePackageName(Interface):
621@@ -54,7 +51,8 @@
622 def get(sourcepackagenameid):
623 """Return a sourcepackagename by its id.
624
625- If the sourcepackagename can't be found a NotFoundError will be raised.
626+ If the sourcepackagename can't be found a NotFoundError will be
627+ raised.
628 """
629
630 def getAll():
631@@ -74,9 +72,3 @@
632
633 def getOrCreateByName(name):
634 """Get a source package name by name, creating it if necessary."""
635-
636-
637-class NoSuchSourcePackageName(NameLookupFailed):
638- """Raised when we can't find a particular sourcepackagename."""
639- webservice_error(400)
640- _message_prefix = "No such source package"
641
642=== modified file 'lib/lp/registry/interfaces/structuralsubscription.py'
643--- lib/lp/registry/interfaces/structuralsubscription.py 2010-08-20 20:31:18 +0000
644+++ lib/lp/registry/interfaces/structuralsubscription.py 2010-10-04 12:14:48 +0000
645@@ -10,11 +10,9 @@
646 __all__ = [
647 'BlueprintNotificationLevel',
648 'BugNotificationLevel',
649- 'DeleteSubscriptionError',
650 'IStructuralSubscription',
651 'IStructuralSubscriptionForm',
652 'IStructuralSubscriptionTarget',
653- 'UserCannotSubscribePerson',
654 ]
655
656 from lazr.enum import (
657@@ -32,7 +30,6 @@
658 operation_returns_collection_of,
659 operation_returns_entry,
660 REQUEST_USER,
661- webservice_error,
662 )
663 from lazr.restful.fields import Reference
664 from zope.interface import (
665@@ -247,16 +244,3 @@
666 subscribe_me = Bool(
667 title=u"I want to receive these notifications by e-mail.",
668 required=False)
669-
670-
671-class DeleteSubscriptionError(Exception):
672- """Delete Subscription Error.
673-
674- Raised when an error occurred trying to delete a
675- structural subscription."""
676- webservice_error(400)
677-
678-
679-class UserCannotSubscribePerson(Exception):
680- """User does not have permission to subscribe the person or team."""
681- webservice_error(401)
682
683=== modified file 'lib/lp/registry/interfaces/teammembership.py'
684--- lib/lp/registry/interfaces/teammembership.py 2010-09-01 19:46:27 +0000
685+++ lib/lp/registry/interfaces/teammembership.py 2010-10-04 12:14:48 +0000
686@@ -14,7 +14,6 @@
687 'ITeamMembershipSet',
688 'ITeamParticipation',
689 'TeamMembershipStatus',
690- 'UserCannotChangeMembershipSilently',
691 ]
692
693 from lazr.enum import (
694@@ -28,7 +27,6 @@
695 exported,
696 operation_parameters,
697 REQUEST_USER,
698- webservice_error,
699 )
700 from lazr.restful.fields import Reference
701 from lazr.restful.interface import copy_field
702@@ -43,7 +41,6 @@
703 Int,
704 Text,
705 )
706-from zope.security.interfaces import Unauthorized
707
708 from canonical.launchpad import _
709
710@@ -53,15 +50,6 @@
711 DAYS_BEFORE_EXPIRATION_WARNING_IS_SENT = 7
712
713
714-class UserCannotChangeMembershipSilently(Unauthorized):
715- """User not permitted to change membership status silently.
716-
717- Raised when a user tries to change someone's membership silently, and is
718- not a Launchpad Administrator.
719- """
720- webservice_error(401) # HTTP Error: 'Unauthorized'
721-
722-
723 class TeamMembershipStatus(DBEnumeratedType):
724 """TeamMembership Status
725
726
727=== modified file 'lib/lp/registry/model/distribution.py'
728--- lib/lp/registry/model/distribution.py 2010-09-03 03:12:39 +0000
729+++ lib/lp/registry/model/distribution.py 2010-10-04 12:14:48 +0000
730@@ -88,7 +88,6 @@
731 SpecificationDefinitionStatus,
732 SpecificationFilter,
733 SpecificationImplementationStatus,
734- SpecificationSort,
735 )
736 from lp.blueprints.model.specification import (
737 HasSpecificationsMixin,
738@@ -112,6 +111,7 @@
739 OfficialBugTagTargetMixin,
740 )
741 from lp.bugs.model.bugtask import BugTask
742+from lp.registry.errors import NoSuchDistroSeries
743 from lp.registry.interfaces.distribution import (
744 IBaseDistribution,
745 IDerivativeDistribution,
746@@ -123,7 +123,6 @@
747 MirrorContent,
748 MirrorStatus,
749 )
750-from lp.registry.interfaces.distroseries import NoSuchDistroSeries
751 from lp.registry.interfaces.packaging import PackagingType
752 from lp.registry.interfaces.person import (
753 validate_person,
754
755=== modified file 'lib/lp/registry/model/distributionmirror.py'
756--- lib/lp/registry/model/distributionmirror.py 2010-08-24 15:29:01 +0000
757+++ lib/lp/registry/model/distributionmirror.py 2010-10-04 12:14:48 +0000
758@@ -56,9 +56,14 @@
759 MAIN_STORE,
760 )
761 from lp.archivepublisher.diskpool import poolify
762-from lp.registry.interfaces.distributionmirror import (
763+from lp.registry.errors import (
764 CannotTransitionToCountryMirror,
765 CountryMirrorAlreadySet,
766+ MirrorHasNoHTTPURL,
767+ MirrorNotOfficial,
768+ MirrorNotProbed,
769+ )
770+from lp.registry.interfaces.distributionmirror import (
771 IDistributionMirror,
772 IDistributionMirrorSet,
773 IMirrorCDImageDistroSeries,
774@@ -67,9 +72,6 @@
775 IMirrorProbeRecord,
776 MirrorContent,
777 MirrorFreshness,
778- MirrorHasNoHTTPURL,
779- MirrorNotOfficial,
780- MirrorNotProbed,
781 MirrorSpeed,
782 MirrorStatus,
783 PROBE_INTERVAL,
784@@ -353,7 +355,8 @@
785 if mirror is not None:
786 mirror.destroySelf()
787
788- def _getMirrorDistroArchSeries(self, distro_arch_series, pocket, component):
789+ def _getMirrorDistroArchSeries(
790+ self, distro_arch_series, pocket, component):
791 """Return MirrorDistroArchSeries given a arch series and pocket."""
792
793 return IStore(MirrorDistroArchSeries).find(
794@@ -525,7 +528,7 @@
795 class DistributionMirrorSet:
796 """See IDistributionMirrorSet"""
797
798- implements (IDistributionMirrorSet)
799+ implements(IDistributionMirrorSet)
800
801 def __getitem__(self, mirror_id):
802 """See IDistributionMirrorSet"""
803@@ -652,7 +655,7 @@
804 (MirrorFreshness.SIXHOURSBEHIND, 6.5),
805 (MirrorFreshness.ONEDAYBEHIND, 24.5),
806 (MirrorFreshness.TWODAYSBEHIND, 48.5),
807- (MirrorFreshness.ONEWEEKBEHIND, 168.5)
808+ (MirrorFreshness.ONEWEEKBEHIND, 168.5),
809 ]
810
811 def _getPackageReleaseURLFromPublishingRecord(self, publishing_record):
812@@ -799,7 +802,6 @@
813 query, clauseTables=['BinaryPackageFile'],
814 orderBy='-datepublished')
815
816-
817 def _getPackageReleaseURLFromPublishingRecord(self, publishing_record):
818 """Given a BinaryPackagePublishingHistory, return the URL on
819 this mirror from where the BinaryPackageRelease file can be downloaded.
820@@ -880,4 +882,3 @@
821 log_file = ForeignKey(
822 dbName='log_file', foreignKey='LibraryFileAlias', notNull=True)
823 date_created = UtcDateTimeCol(notNull=True, default=UTC_NOW)
824-
825
826=== modified file 'lib/lp/registry/model/person.py'
827--- lib/lp/registry/model/person.py 2010-09-21 02:47:03 +0000
828+++ lib/lp/registry/model/person.py 2010-10-04 12:14:48 +0000
829@@ -191,6 +191,7 @@
830 HasMergeProposalsMixin,
831 HasRequestedReviewsMixin,
832 )
833+from lp.registry.errors import NameAlreadyTaken
834 from lp.registry.interfaces.codeofconduct import ISignedCodeOfConductSet
835 from lp.registry.interfaces.distribution import IDistribution
836 from lp.registry.interfaces.gpg import IGPGKeySet
837@@ -217,7 +218,6 @@
838 IPersonSet,
839 ITeam,
840 JoinNotAllowed,
841- NameAlreadyTaken,
842 PersonalStanding,
843 PersonCreationRationale,
844 PersonVisibility,
845@@ -1256,7 +1256,7 @@
846 try:
847 return self._inTeam_cache[team.id]
848 except KeyError:
849- pass
850+ pass
851
852 tp = TeamParticipation.selectOneBy(team=team, person=self)
853 if tp is not None or self.id == team.teamownerID:
854
855=== modified file 'lib/lp/registry/model/sourcepackagename.py'
856--- lib/lp/registry/model/sourcepackagename.py 2010-08-20 20:31:18 +0000
857+++ lib/lp/registry/model/sourcepackagename.py 2010-10-04 12:14:48 +0000
858@@ -7,8 +7,8 @@
859 __all__ = [
860 'SourcePackageName',
861 'SourcePackageNameSet',
862- 'getSourcePackageDescriptions'
863-]
864+ 'getSourcePackageDescriptions',
865+ ]
866
867 from sqlobject import (
868 SQLMultipleJoin,
869@@ -24,10 +24,10 @@
870 sqlvalues,
871 )
872 from lp.app.errors import NotFoundError
873+from lp.registry.errors import NoSuchSourcePackageName
874 from lp.registry.interfaces.sourcepackagename import (
875 ISourcePackageName,
876 ISourcePackageNameSet,
877- NoSuchSourcePackageName,
878 )
879
880
881@@ -155,4 +155,3 @@
882 description = ", %s" % binarypackagename
883 descriptions[sourcepackagename] += description
884 return descriptions
885-
886
887=== modified file 'lib/lp/registry/model/structuralsubscription.py'
888--- lib/lp/registry/model/structuralsubscription.py 2010-08-20 20:31:18 +0000
889+++ lib/lp/registry/model/structuralsubscription.py 2010-10-04 12:14:48 +0000
890@@ -18,6 +18,10 @@
891 )
892 from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
893 from lp.registry.enum import BugNotificationLevel
894+from lp.registry.errors import (
895+ DeleteSubscriptionError,
896+ UserCannotSubscribePerson,
897+ )
898 from lp.registry.interfaces.distribution import IDistribution
899 from lp.registry.interfaces.distributionsourcepackage import (
900 IDistributionSourcePackage,
901@@ -33,10 +37,8 @@
902 from lp.registry.interfaces.projectgroup import IProjectGroup
903 from lp.registry.interfaces.structuralsubscription import (
904 BlueprintNotificationLevel,
905- DeleteSubscriptionError,
906 IStructuralSubscription,
907 IStructuralSubscriptionTarget,
908- UserCannotSubscribePerson,
909 )
910
911
912
913=== modified file 'lib/lp/registry/model/teammembership.py'
914--- lib/lp/registry/model/teammembership.py 2010-09-29 00:26:02 +0000
915+++ lib/lp/registry/model/teammembership.py 2010-10-04 12:14:48 +0000
916@@ -46,7 +46,10 @@
917 from canonical.launchpad.mailnotification import MailWrapper
918 from canonical.launchpad.webapp import canonical_url
919 from lp.app.browser.tales import DurationFormatterAPI
920-from lp.registry.errors import TeamMembershipTransitionError
921+from lp.registry.errors import (
922+ TeamMembershipTransitionError,
923+ UserCannotChangeMembershipSilently,
924+ )
925 from lp.registry.interfaces.person import (
926 IPersonSet,
927 TeamMembershipRenewalPolicy,
928@@ -59,7 +62,6 @@
929 ITeamMembershipSet,
930 ITeamParticipation,
931 TeamMembershipStatus,
932- UserCannotChangeMembershipSilently,
933 )
934
935
936
937=== modified file 'lib/lp/registry/tests/test_distribution.py'
938--- lib/lp/registry/tests/test_distribution.py 2010-08-23 08:46:04 +0000
939+++ lib/lp/registry/tests/test_distribution.py 2010-10-04 12:14:48 +0000
940@@ -12,8 +12,8 @@
941 DatabaseFunctionalLayer,
942 LaunchpadFunctionalLayer,
943 )
944+from lp.registry.errors import NoSuchDistroSeries
945 from lp.registry.interfaces.distribution import IDistribution
946-from lp.registry.interfaces.distroseries import NoSuchDistroSeries
947 from lp.registry.interfaces.series import SeriesStatus
948 from lp.registry.tests.test_distroseries import (
949 TestDistroSeriesCurrentSourceReleases,
950
951=== modified file 'lib/lp/registry/tests/test_distroseries.py'
952--- lib/lp/registry/tests/test_distroseries.py 2010-08-24 15:29:01 +0000
953+++ lib/lp/registry/tests/test_distroseries.py 2010-10-04 12:14:48 +0000
954@@ -19,25 +19,19 @@
955 DatabaseFunctionalLayer,
956 LaunchpadFunctionalLayer,
957 )
958-from lp.registry.interfaces.distroseries import (
959- IDistroSeriesSet,
960- NoSuchDistroSeries,
961- )
962+from lp.registry.errors import NoSuchDistroSeries
963+from lp.registry.interfaces.distroseries import IDistroSeriesSet
964 from lp.registry.interfaces.pocket import PackagePublishingPocket
965 from lp.soyuz.enums import (
966 ArchivePurpose,
967 PackagePublishingStatus,
968 )
969-from lp.soyuz.interfaces.archive import (
970- IArchiveSet,
971- )
972+from lp.soyuz.interfaces.archive import IArchiveSet
973 from lp.soyuz.interfaces.component import IComponentSet
974 from lp.soyuz.interfaces.distroseriessourcepackagerelease import (
975 IDistroSeriesSourcePackageRelease,
976 )
977-from lp.soyuz.interfaces.publishing import (
978- active_publishing_status,
979- )
980+from lp.soyuz.interfaces.publishing import active_publishing_status
981 from lp.soyuz.model.processor import ProcessorFamilySet
982 from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
983 from lp.testing import (
984
985=== modified file 'lib/lp/registry/tests/test_person.py'
986--- lib/lp/registry/tests/test_person.py 2010-09-28 03:01:37 +0000
987+++ lib/lp/registry/tests/test_person.py 2010-10-04 12:14:48 +0000
988@@ -9,9 +9,9 @@
989
990 from lazr.lifecycle.snapshot import Snapshot
991 import pytz
992+from storm.store import Store
993 from testtools.matchers import LessThan
994 import transaction
995-from storm.store import Store
996 from zope.component import getUtility
997 from zope.interface import providedBy
998 from zope.security.proxy import removeSecurityProxy
999@@ -43,15 +43,17 @@
1000 from lp.bugs.interfaces.bugtask import IllegalRelatedBugTasksParams
1001 from lp.bugs.model.bug import Bug
1002 from lp.bugs.model.bugtask import get_related_bugtasks_search_params
1003+from lp.registry.errors import (
1004+ NameAlreadyTaken,
1005+ PrivatePersonLinkageError,
1006+ )
1007 from lp.registry.interfaces.karma import IKarmaCacheManager
1008 from lp.registry.interfaces.person import (
1009 ImmutableVisibilityError,
1010 InvalidName,
1011 IPersonSet,
1012- NameAlreadyTaken,
1013 PersonCreationRationale,
1014 PersonVisibility,
1015- PrivatePersonLinkageError,
1016 )
1017 from lp.registry.interfaces.product import IProductSet
1018 from lp.registry.model.karma import KarmaCategory
1019
1020=== modified file 'lib/lp/registry/tests/test_structuralsubscriptiontarget.py'
1021--- lib/lp/registry/tests/test_structuralsubscriptiontarget.py 2010-08-20 20:31:18 +0000
1022+++ lib/lp/registry/tests/test_structuralsubscriptiontarget.py 2010-10-04 12:14:48 +0000
1023@@ -25,13 +25,15 @@
1024 from canonical.testing import LaunchpadFunctionalLayer
1025 from lp.bugs.interfaces.bug import CreateBugParams
1026 from lp.bugs.tests.test_bugtarget import bugtarget_filebug
1027+from lp.registry.errors import (
1028+ DeleteSubscriptionError,
1029+ UserCannotSubscribePerson,
1030+ )
1031 from lp.registry.interfaces.distribution import IDistributionSet
1032 from lp.registry.interfaces.product import IProductSet
1033 from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet
1034 from lp.registry.interfaces.structuralsubscription import (
1035- DeleteSubscriptionError,
1036 IStructuralSubscriptionTarget,
1037- UserCannotSubscribePerson,
1038 )
1039 from lp.registry.model.structuralsubscription import StructuralSubscription
1040 from lp.testing import (
1041
1042=== modified file 'lib/lp/registry/tests/test_team_webservice.py'
1043--- lib/lp/registry/tests/test_team_webservice.py 2010-09-24 21:10:47 +0000
1044+++ lib/lp/registry/tests/test_team_webservice.py 2010-10-04 12:14:48 +0000
1045@@ -3,6 +3,7 @@
1046
1047 __metaclass__ = type
1048
1049+import httplib
1050 import unittest
1051
1052 from lazr.restfulclient.errors import HTTPError
1053@@ -44,7 +45,7 @@
1054 team_one.addMember,
1055 person=team_two)
1056 self.assertIn('Cannot link person', api_error.content)
1057- self.assertEqual(400, api_error.response.status)
1058+ self.assertEqual(httplib.FORBIDDEN, api_error.response.status)
1059
1060
1061 def test_suite():