Merge lp:~james-w/launchpad/export-code-import into lp:launchpad

Proposed by James Westby
Status: Merged
Approved by: Curtis Hovey
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~james-w/launchpad/export-code-import
Merge into: lp:launchpad
Diff against target: 184 lines (+28/-16)
6 files modified
lib/canonical/launchpad/doc/webservice-marshallers.txt (+5/-3)
lib/canonical/launchpad/interfaces/_schema_circular_imports.py (+4/-0)
lib/lp/code/interfaces/codeimport.py (+6/-3)
lib/lp/registry/interfaces/distroseries.py (+6/-5)
lib/lp/registry/interfaces/productseries.py (+2/-1)
lib/lp/registry/interfaces/projectgroup.py (+5/-4)
To merge this branch: bzr merge lp:~james-w/launchpad/export-code-import
Reviewer Review Type Date Requested Status
Curtis Hovey (community) Approve
Review via email: mp+22175@code.launchpad.net

Commit message

Various attributes are now exported correctly so that they can be used by launchpadlib.

Description of the change

Fix various exports to use ReferenceChoice.

When exporting something that is a link to another exported
object you must use a lazr.restful field, rather than a plain
zope one.

This is because lazr.restful has to know that it is a link to
an exported object so that it can have special behaviour.

Currently when you don't do this you don't get an error until
you come to access it with launchpadlib.

What happens is that the tales that writes out the wadl just
considers it to be a plain attribute, and so writes out
<wadl attribute name> == <field name>.

However, when the marshaller comes to write out the JSON for the
object that it will find there it sees that it is an exported
object and so writes out the URL instead. As it does this though
it gives it name of <field name> + "_link", which doesn't match
the wadl.

Therefore the webservice doesn't behave as stated and the client
falls over.

Thanks,

James

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Hi James.

We talked IRC and agreed that this branch does fix the specific issues, but not the root cause. You are already working on a fix for the root cause that will not require us to rewrite the existing tests...which gave us a false sense that the wadl and json were in agreement.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/doc/webservice-marshallers.txt'
2--- lib/canonical/launchpad/doc/webservice-marshallers.txt 2010-03-24 16:01:58 +0000
3+++ lib/canonical/launchpad/doc/webservice-marshallers.txt 2010-03-25 20:49:29 +0000
4@@ -29,13 +29,16 @@
5 string is a URL corresponding to a vocabulary item, the marshaller
6 returns that item. Otherwise it raises a ValueError.
7
8+ >>> from canonical.launchpad.interfaces import IPerson
9 >>> from zope.component import getMultiAdapter
10- >>> from zope.schema import Choice
11+ >>> from lazr.restful.fields import ReferenceChoice
12 >>> from lazr.restful.interfaces import IFieldMarshaller
13 >>> from lazr.restful import EntryResource
14
15 # Bind the field, to resolve the vocabulary name.
16- >>> field = Choice(__name__='some_person', vocabulary='ValidPersonOrTeam')
17+ >>> field = ReferenceChoice(
18+ ... __name__='some_person', vocabulary='ValidPersonOrTeam',
19+ ... schema=IPerson)
20 >>> field = field.bind(None)
21 >>> marshaller = getMultiAdapter((field, request), IFieldMarshaller)
22 >>> verifyObject(IFieldMarshaller, marshaller)
23@@ -49,7 +52,6 @@
24 >>> person.name
25 u'salgado'
26
27- >>> from canonical.launchpad.interfaces import IPerson
28 >>> ubuntu_team = marshaller.marshall_from_json_data(
29 ... "http://api.launchpad.dev/beta/~ubuntu-team")
30 >>> ubuntu_team.name
31
32=== modified file 'lib/canonical/launchpad/interfaces/_schema_circular_imports.py'
33--- lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2010-03-18 17:30:14 +0000
34+++ lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2010-03-25 20:49:29 +0000
35@@ -294,6 +294,7 @@
36 IDistroSeries, 'getPackageUploads', 'archive', IArchive)
37 patch_collection_return_type(
38 IDistroSeries, 'getPackageUploads', IPackageUpload)
39+patch_reference_property(IDistroSeries, 'parent_series', IDistroSeries)
40
41 # IDistroArchSeries
42 patch_reference_property(IDistroArchSeries, 'main_archive', IArchive)
43@@ -374,3 +375,6 @@
44
45 # IBugTracker
46 patch_reference_property(IBugTracker, 'owner', IPerson)
47+
48+# IProductSeries
49+patch_reference_property(IProductSeries, 'product', IProduct)
50
51=== modified file 'lib/lp/code/interfaces/codeimport.py'
52--- lib/lp/code/interfaces/codeimport.py 2010-03-18 17:30:14 +0000
53+++ lib/lp/code/interfaces/codeimport.py 2010-03-25 20:49:29 +0000
54@@ -22,9 +22,11 @@
55 from canonical.launchpad.fields import PublicPersonChoice, URIField
56 from canonical.launchpad.validators import LaunchpadValidationError
57 from lp.code.enums import CodeImportReviewStatus, RevisionControlSystems
58+from lp.code.interfaces.branch import IBranch
59
60 from lazr.restful.declarations import (
61 export_as_webservice_entry, exported)
62+from lazr.restful.fields import ReferenceChoice
63
64
65 def validate_cvs_root(cvsroot):
66@@ -70,10 +72,11 @@
67 title=_("Date Created"), required=True, readonly=True)
68
69 branch = exported(
70- Choice(
71+ ReferenceChoice(
72 title=_('Branch'), required=True, readonly=True,
73- vocabulary='Branch',
74- description=_("The Bazaar branch produced by the import system.")))
75+ vocabulary='Branch', schema=IBranch,
76+ description=_("The Bazaar branch produced by the "
77+ "import system.")))
78
79 registrant = PublicPersonChoice(
80 title=_('Registrant'), required=True, readonly=True,
81
82=== modified file 'lib/lp/registry/interfaces/distroseries.py'
83--- lib/lp/registry/interfaces/distroseries.py 2010-03-15 15:01:48 +0000
84+++ lib/lp/registry/interfaces/distroseries.py 2010-03-25 20:49:29 +0000
85@@ -25,7 +25,7 @@
86 export_factory_operation, export_read_operation, exported,
87 operation_parameters, operation_returns_collection_of,
88 operation_returns_entry, rename_parameters_as, webservice_error)
89-from lazr.restful.fields import Reference
90+from lazr.restful.fields import Reference, ReferenceChoice
91
92 from canonical.launchpad import _
93 from canonical.launchpad.fields import (
94@@ -43,6 +43,7 @@
95 from lp.bugs.interfaces.bugtarget import (
96 IBugTarget, IHasBugs, IHasOfficialBugTags)
97 from lp.registry.interfaces.milestone import IHasMilestones, IMilestone
98+from lp.registry.interfaces.person import IPerson
99 from lp.registry.interfaces.role import IHasOwner
100 from lp.registry.interfaces.series import ISeriesMixin, SeriesStatus
101 from lp.registry.interfaces.sourcepackage import ISourcePackage
102@@ -193,23 +194,23 @@
103 datereleased = exported(
104 Datetime(title=_("Date released")))
105 parent_series = exported(
106- Choice(
107+ ReferenceChoice(
108 title=_("Parent series"),
109 description=_("The series from which this one was branched."),
110- required=True,
111+ required=True, schema=Interface, # Really IDistroSeries, see below
112 vocabulary='DistroSeries'))
113 owner = exported(
114 PublicPersonChoice(title=_("Owner"), vocabulary='ValidOwner'))
115 date_created = exported(
116 Datetime(title=_("The date this series was registered.")))
117 driver = exported(
118- Choice(
119+ ReferenceChoice(
120 title=_("Driver"),
121 description=_(
122 "The person or team responsible for decisions about features "
123 "and bugs that will be targeted to this series of the "
124 "distribution."),
125- required=False, vocabulary='ValidPersonOrTeam'))
126+ required=False, vocabulary='ValidPersonOrTeam', schema=IPerson))
127 changeslist = exported(
128 TextLine(
129 title=_("E-mail changes to"), required=True,
130
131=== modified file 'lib/lp/registry/interfaces/productseries.py'
132--- lib/lp/registry/interfaces/productseries.py 2010-03-18 13:27:47 +0000
133+++ lib/lp/registry/interfaces/productseries.py 2010-03-25 20:49:29 +0000
134@@ -99,7 +99,8 @@
135 id = Int(title=_('ID'))
136
137 product = exported(
138- Choice(title=_('Project'), required=True, vocabulary='Product'),
139+ ReferenceChoice(title=_('Project'), required=True,
140+ vocabulary='Product', schema=Interface), # really IProduct
141 exported_as='project')
142
143 status = exported(
144
145=== modified file 'lib/lp/registry/interfaces/projectgroup.py'
146--- lib/lp/registry/interfaces/projectgroup.py 2010-03-24 14:32:20 +0000
147+++ lib/lp/registry/interfaces/projectgroup.py 2010-03-25 20:49:29 +0000
148@@ -15,7 +15,7 @@
149 ]
150
151 from zope.interface import Interface, Attribute
152-from zope.schema import Bool, Choice, Datetime, Int, Object, Text, TextLine
153+from zope.schema import Bool, Datetime, Int, Object, Text, TextLine
154
155 from canonical.launchpad import _
156 from canonical.launchpad.fields import (
157@@ -25,6 +25,7 @@
158 IHasBranchVisibilityPolicy)
159 from lp.code.interfaces.hasbranches import IHasBranches, IHasMergeProposals
160 from lp.bugs.interfaces.bugtarget import IHasBugs, IHasOfficialBugTags
161+from lp.bugs.interfaces.bugtracker import IBugTracker
162 from lp.registry.interfaces.karma import IKarmaContext
163 from canonical.launchpad.interfaces.launchpad import (
164 IHasAppointedDriver, IHasDrivers, IHasIcon, IHasLogo, IHasMugshot)
165@@ -45,7 +46,7 @@
166 from canonical.launchpad.fields import (
167 IconImageUpload, LogoImageUpload, MugshotImageUpload, PillarNameField)
168
169-from lazr.restful.fields import CollectionField, Reference
170+from lazr.restful.fields import CollectionField, Reference, ReferenceChoice
171 from lazr.restful.declarations import (
172 collection_default_content, export_as_webservice_collection,
173 export_as_webservice_entry, export_read_operation, exported,
174@@ -236,8 +237,8 @@
175 "reviewed.")))
176
177 bugtracker = exported(
178- Choice(title=_('Bug Tracker'), required=False,
179- vocabulary='BugTracker',
180+ ReferenceChoice(title=_('Bug Tracker'), required=False,
181+ vocabulary='BugTracker', schema=IBugTracker,
182 description=_(
183 "The bug tracker the projects in this project group use.")),
184 exported_as="bug_tracker")