← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/tidy-circular-import-helpers into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/tidy-circular-import-helpers into lp:launchpad.

Commit message:
Use lp.services.webservice.apihelpers functions throughout rather than handling circular imports more manually.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/tidy-circular-import-helpers/+merge/248157

_schema_circular_imports.py and the various other places where circular imports are handled were using a mix of styles, which made them unnecessarily hard to read and confusing to edit.  This branch syncs everything up to use the common helper functions introduced in 2009.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/tidy-circular-import-helpers into lp:launchpad.
=== modified file 'lib/lp/_schema_circular_imports.py'
--- lib/lp/_schema_circular_imports.py	2014-08-01 08:47:28 +0000
+++ lib/lp/_schema_circular_imports.py	2015-01-30 18:57:10 +0000
@@ -15,7 +15,6 @@
 __all__ = []
 
 
-from lazr.restful.declarations import LAZR_WEBSERVICE_EXPORTED
 from lazr.restful.fields import Reference
 
 from lp.blueprints.interfaces.specification import ISpecification
@@ -163,7 +162,7 @@
     )
 from lp.services.webservice.apihelpers import (
     patch_choice_parameter_type,
-    patch_choice_vocabulary,
+    patch_choice_property,
     patch_collection_property,
     patch_collection_return_type,
     patch_entry_explicit_version,
@@ -234,34 +233,29 @@
     )
 
 
-IBranch['bug_branches'].value_type.schema = IBugBranch
-IBranch['linked_bugs'].value_type.schema = IBug
-IBranch['dependent_branches'].value_type.schema = IBranchMergeProposal
-IBranch['getSubscription'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['return_type'].schema = IBranchSubscription
-IBranch['landing_candidates'].value_type.schema = IBranchMergeProposal
-IBranch['landing_targets'].value_type.schema = IBranchMergeProposal
-IBranch['linkBug'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['params']['bug'].schema = IBug
-IBranch['linkSpecification'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['params']['spec'].schema = ISpecification
-IBranch['product'].schema = IProduct
+patch_collection_property(IBranch, 'bug_branches', IBugBranch)
+patch_collection_property(IBranch, 'linked_bugs', IBug)
+patch_collection_property(IBranch, 'dependent_branches', IBranchMergeProposal)
+patch_entry_return_type(IBranch, 'getSubscription', IBranchSubscription)
+patch_collection_property(IBranch, 'landing_candidates', IBranchMergeProposal)
+patch_collection_property(IBranch, 'landing_targets', IBranchMergeProposal)
+patch_plain_parameter_type(IBranch, 'linkBug', 'bug', IBug)
+patch_plain_parameter_type(
+    IBranch, 'linkSpecification', 'spec', ISpecification)
+patch_reference_property(IBranch, 'product', IProduct)
 
-patch_plain_parameter_type(
-    IBranch, 'setTarget', 'project', IProduct)
+patch_plain_parameter_type(IBranch, 'setTarget', 'project', IProduct)
 patch_plain_parameter_type(
     IBranch, 'setTarget', 'source_package', ISourcePackage)
 patch_reference_property(IBranch, 'sourcepackage', ISourcePackage)
 patch_reference_property(IBranch, 'code_import', ICodeImport)
 
-IBranch['spec_links'].value_type.schema = ISpecificationBranch
-IBranch['subscribe'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['return_type'].schema = IBranchSubscription
-IBranch['subscriptions'].value_type.schema = IBranchSubscription
-IBranch['unlinkBug'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['params']['bug'].schema = IBug
-IBranch['unlinkSpecification'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['params']['spec'].schema = ISpecification
+patch_collection_property(IBranch, 'spec_links', ISpecificationBranch)
+patch_entry_return_type(IBranch, 'subscribe', IBranchSubscription)
+patch_collection_property(IBranch, 'subscriptions', IBranchSubscription)
+patch_plain_parameter_type(IBranch, 'unlinkBug', 'bug', IBug)
+patch_plain_parameter_type(
+    IBranch, 'unlinkSpecification', 'spec', ISpecification)
 
 patch_entry_return_type(IBranch, '_createMergeProposal', IBranchMergeProposal)
 patch_plain_parameter_type(
@@ -274,17 +268,17 @@
 patch_collection_return_type(
     IBranchSet, 'getMergeProposals', IBranchMergeProposal)
 
-IBranchMergeProposal['getComment'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['return_type'].schema = ICodeReviewComment
-IBranchMergeProposal['createComment'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['params']['parent'].schema = \
-        ICodeReviewComment
+patch_entry_return_type(IBranchMergeProposal, 'getComment', ICodeReviewComment)
+patch_plain_parameter_type(
+    IBranchMergeProposal, 'createComment', 'parent', ICodeReviewComment)
 patch_entry_return_type(
     IBranchMergeProposal, 'createComment', ICodeReviewComment)
-IBranchMergeProposal['all_comments'].value_type.schema = ICodeReviewComment
-IBranchMergeProposal['nominateReviewer'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['return_type'].schema = ICodeReviewVoteReference
-IBranchMergeProposal['votes'].value_type.schema = ICodeReviewVoteReference
+patch_collection_property(
+    IBranchMergeProposal, 'all_comments', ICodeReviewComment)
+patch_entry_return_type(
+    IBranchMergeProposal, 'nominateReviewer', ICodeReviewVoteReference)
+patch_collection_property(
+    IBranchMergeProposal, 'votes', ICodeReviewVoteReference)
 patch_collection_return_type(
     IBranchMergeProposal, 'getRelatedBugTasks', IBugTask)
 
@@ -293,32 +287,27 @@
     IHasMergeProposals, 'getMergeProposals', IBranchMergeProposal)
 patch_collection_return_type(
     IHasRequestedReviews, 'getRequestedReviews', IBranchMergeProposal)
-patch_entry_return_type(
-    IHasCodeImports, 'newCodeImport', ICodeImport)
-patch_plain_parameter_type(
-    IHasCodeImports, 'newCodeImport', 'owner', IPerson)
+patch_entry_return_type(IHasCodeImports, 'newCodeImport', ICodeImport)
+patch_plain_parameter_type(IHasCodeImports, 'newCodeImport', 'owner', IPerson)
 
 # IBugTask
 
-IBugTask['findSimilarBugs'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['return_type'].value_type.schema = IBug
+patch_collection_return_type(IBugTask, 'findSimilarBugs', IBug)
 patch_plain_parameter_type(
     IBug, 'linkHWSubmission', 'submission', IHWSubmission)
 patch_plain_parameter_type(
     IBug, 'unlinkHWSubmission', 'submission', IHWSubmission)
-patch_collection_return_type(
-    IBug, 'getHWSubmissions', IHWSubmission)
-IBug['getNominations'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['params']['nominations'].value_type.schema = (
-        IBugNomination)
+patch_collection_return_type(IBug, 'getHWSubmissions', IHWSubmission)
+patch_list_parameter_type(
+    IBug, 'getNominations', 'nominations', Reference(schema=IBugNomination))
 patch_entry_return_type(IBug, 'addNomination', IBugNomination)
 patch_entry_return_type(IBug, 'getNominationFor', IBugNomination)
 patch_collection_return_type(IBug, 'getNominations', IBugNomination)
 
-patch_choice_parameter_type(
-    IHasBugs, 'searchTasks', 'hardware_bus', HWBus)
+patch_choice_parameter_type(IHasBugs, 'searchTasks', 'hardware_bus', HWBus)
 
-IPreviewDiff['branch_merge_proposal'].schema = IBranchMergeProposal
+patch_reference_property(
+    IPreviewDiff, 'branch_merge_proposal', IBranchMergeProposal)
 
 patch_reference_property(IPersonViewRestricted, 'archive', IArchive)
 patch_collection_property(IPersonViewRestricted, 'ppas', IArchive)
@@ -329,28 +318,21 @@
     IPersonEditRestricted, 'createPPA', 'distribution', IDistribution)
 patch_entry_return_type(IPersonEditRestricted, 'createPPA', IArchive)
 
-IHasBuildRecords['getBuildRecords'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)[
-        'params']['pocket'].vocabulary = PackagePublishingPocket
-IHasBuildRecords['getBuildRecords'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)[
-        'params']['build_state'].vocabulary = BuildStatus
-IHasBuildRecords['getBuildRecords'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)[
-        'return_type'].value_type.schema = IBinaryPackageBuild
+patch_choice_parameter_type(
+    IHasBuildRecords, 'getBuildRecords', 'pocket', PackagePublishingPocket)
+patch_choice_parameter_type(
+    IHasBuildRecords, 'getBuildRecords', 'build_state', BuildStatus)
+patch_collection_return_type(
+    IHasBuildRecords, 'getBuildRecords', IBinaryPackageBuild)
 
-ISourcePackagePublic['distroseries'].schema = IDistroSeries
-ISourcePackagePublic['productseries'].schema = IProductSeries
-ISourcePackagePublic['getBranch'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)[
-        'params']['pocket'].vocabulary = PackagePublishingPocket
-ISourcePackagePublic['getBranch'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['return_type'].schema = IBranch
-ISourcePackageEdit['setBranch'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)[
-        'params']['pocket'].vocabulary = PackagePublishingPocket
-ISourcePackageEdit['setBranch'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['params']['branch'].schema = IBranch
+patch_reference_property(ISourcePackagePublic, 'distroseries', IDistroSeries)
+patch_reference_property(ISourcePackagePublic, 'productseries', IProductSeries)
+patch_choice_parameter_type(
+    ISourcePackagePublic, 'getBranch', 'pocket', PackagePublishingPocket)
+patch_entry_return_type(ISourcePackagePublic, 'getBranch', IBranch)
+patch_choice_parameter_type(
+    ISourcePackageEdit, 'setBranch', 'pocket', PackagePublishingPocket)
+patch_plain_parameter_type(ISourcePackageEdit, 'setBranch', 'branch', IBranch)
 patch_reference_property(ISourcePackage, 'distribution', IDistribution)
 
 # IPerson
@@ -367,19 +349,16 @@
 patch_collection_return_type(IPerson, 'getOwnedProjects', IProduct)
 
 # IHasRecipe
-patch_collection_property(
-    IHasRecipes, 'recipes', ISourcePackageRecipe)
+patch_collection_property(IHasRecipes, 'recipes', ISourcePackageRecipe)
 
-IPerson['hardware_submissions'].value_type.schema = IHWSubmission
+patch_collection_property(IPerson, 'hardware_submissions', IHWSubmission)
 
 # publishing.py
-ISourcePackagePublishingHistoryPublic['getBuilds'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['return_type'].value_type.schema = (
-        IBinaryPackageBuild)
-ISourcePackagePublishingHistoryPublic[
-    'getPublishedBinaries'].queryTaggedValue(
-        LAZR_WEBSERVICE_EXPORTED)[
-            'return_type'].value_type.schema = IBinaryPackagePublishingHistory
+patch_collection_return_type(
+    ISourcePackagePublishingHistoryPublic, 'getBuilds', IBinaryPackageBuild)
+patch_collection_return_type(
+    ISourcePackagePublishingHistoryPublic, 'getPublishedBinaries',
+    IBinaryPackagePublishingHistory)
 patch_reference_property(
     IBinaryPackagePublishingHistory, 'distroarchseries',
     IDistroArchSeries)
@@ -505,45 +484,39 @@
     IArchive, 'enableRestrictedProcessor', 'processor', IProcessor)
 
 # IBuildFarmJob
-IBuildFarmJob['status'].vocabulary = BuildStatus
-IBuildFarmJob['buildqueue_record'].schema = IBuildQueue
+patch_choice_property(IBuildFarmJob, 'status', BuildStatus)
+patch_reference_property(IBuildFarmJob, 'buildqueue_record', IBuildQueue)
 
 # IComment
-IComment['comment_author'].schema = IPerson
+patch_reference_property(IComment, 'comment_author', IPerson)
 
 # IDistribution
-IDistribution['series'].value_type.schema = IDistroSeries
-IDistribution['derivatives'].value_type.schema = IDistroSeries
-patch_reference_property(
-    IDistribution, 'currentseries', IDistroSeries)
-patch_entry_return_type(
-    IDistribution, 'getArchive', IArchive)
-patch_entry_return_type(
-    IDistribution, 'getSeries', IDistroSeries)
+patch_collection_property(IDistribution, 'series', IDistroSeries)
+patch_collection_property(IDistribution, 'derivatives', IDistroSeries)
+patch_reference_property(IDistribution, 'currentseries', IDistroSeries)
+patch_entry_return_type(IDistribution, 'getArchive', IArchive)
+patch_entry_return_type(IDistribution, 'getSeries', IDistroSeries)
 patch_collection_return_type(
     IDistribution, 'getDevelopmentSeries', IDistroSeries)
 patch_entry_return_type(
     IDistribution, 'getSourcePackage', IDistributionSourcePackage)
 patch_collection_return_type(
     IDistribution, 'searchSourcePackages', IDistributionSourcePackage)
-patch_reference_property(
-    IDistribution, 'main_archive', IArchive)
-IDistribution['all_distro_archives'].value_type.schema = IArchive
+patch_reference_property(IDistribution, 'main_archive', IArchive)
+patch_collection_property(IDistribution, 'all_distro_archives', IArchive)
 
 
 # IDistributionMirror
-IDistributionMirror['distribution'].schema = IDistribution
+patch_reference_property(IDistributionMirror, 'distribution', IDistribution)
 
 
 # IDistroSeries
 patch_entry_return_type(
     IDistroSeries, 'getDistroArchSeries', IDistroArchSeries)
-patch_reference_property(
-    IDistroSeries, 'main_archive', IArchive)
+patch_reference_property(IDistroSeries, 'main_archive', IArchive)
 patch_collection_property(
     IDistroSeries, 'enabled_architectures', IDistroArchSeries)
-patch_reference_property(
-    IDistroSeries, 'distribution', IDistribution)
+patch_reference_property(IDistroSeries, 'distribution', IDistribution)
 patch_choice_parameter_type(
     IDistroSeries, 'getPackageUploads', 'status', PackageUploadStatus)
 patch_choice_parameter_type(
@@ -558,10 +531,8 @@
 patch_reference_property(IDistroSeries, 'previous_series', IDistroSeries)
 patch_reference_property(
     IDistroSeries, 'nominatedarchindep', IDistroArchSeries)
-patch_collection_return_type(
-    IDistroSeries, 'getDerivedSeries', IDistroSeries)
-patch_collection_return_type(
-    IDistroSeries, 'getParentSeries', IDistroSeries)
+patch_collection_return_type(IDistroSeries, 'getDerivedSeries', IDistroSeries)
+patch_collection_return_type(IDistroSeries, 'getParentSeries', IDistroSeries)
 patch_plain_parameter_type(
     IDistroSeries, 'getDifferencesTo', 'parent_series', IDistroSeries)
 patch_choice_parameter_type(
@@ -580,7 +551,8 @@
     IDistroSeriesDifference, 'latest_comment', IDistroSeriesDifferenceComment)
 
 # IDistroSeriesDifferenceComment
-IDistroSeriesDifferenceComment['comment_author'].schema = IPerson
+patch_reference_property(
+    IDistroSeriesDifferenceComment, 'comment_author', IPerson)
 
 # IDistroArchSeries
 patch_reference_property(IDistroArchSeries, 'main_archive', IArchive)
@@ -590,24 +562,21 @@
 
 # ILiveFSView
 patch_entry_return_type(ILiveFSView, 'requestBuild', ILiveFSBuild)
-ILiveFSView['builds'].value_type.schema = ILiveFSBuild
-ILiveFSView['completed_builds'].value_type.schema = ILiveFSBuild
-ILiveFSView['pending_builds'].value_type.schema = ILiveFSBuild
+patch_collection_property(ILiveFSView, 'builds', ILiveFSBuild)
+patch_collection_property(ILiveFSView, 'completed_builds', ILiveFSBuild)
+patch_collection_property(ILiveFSView, 'pending_builds', ILiveFSBuild)
 
 # IPackageset
-patch_collection_return_type(
-    IPackageset, 'setsIncluded', IPackageset)
-patch_collection_return_type(
-    IPackageset, 'setsIncludedBy', IPackageset)
+patch_collection_return_type(IPackageset, 'setsIncluded', IPackageset)
+patch_collection_return_type(IPackageset, 'setsIncludedBy', IPackageset)
 patch_plain_parameter_type(
     IPackageset, 'getSourcesSharedBy', 'other_package_set', IPackageset)
 patch_plain_parameter_type(
     IPackageset, 'getSourcesNotSharedBy', 'other_package_set', IPackageset)
-patch_collection_return_type(
-    IPackageset, 'relatedSets', IPackageset)
+patch_collection_return_type(IPackageset, 'relatedSets', IPackageset)
 
 # IPackageUpload
-IPackageUpload['pocket'].vocabulary = PackagePublishingPocket
+patch_choice_property(IPackageUpload, 'pocket', PackagePublishingPocket)
 patch_reference_property(IPackageUpload, 'distroseries', IDistroSeries)
 patch_reference_property(IPackageUpload, 'archive', IArchive)
 patch_reference_property(IPackageUpload, 'copy_source_archive', IArchive)
@@ -646,20 +615,13 @@
     ISourcePackageRecipe, 'completed_builds', ISourcePackageRecipeBuild)
 
 # IHasBugs
-patch_plain_parameter_type(
-    IHasBugs, 'searchTasks', 'assignee', IPerson)
-patch_plain_parameter_type(
-    IHasBugs, 'searchTasks', 'bug_reporter', IPerson)
-patch_plain_parameter_type(
-    IHasBugs, 'searchTasks', 'bug_supervisor', IPerson)
-patch_plain_parameter_type(
-    IHasBugs, 'searchTasks', 'bug_commenter', IPerson)
-patch_plain_parameter_type(
-    IHasBugs, 'searchTasks', 'bug_subscriber', IPerson)
-patch_plain_parameter_type(
-    IHasBugs, 'searchTasks', 'owner', IPerson)
-patch_plain_parameter_type(
-    IHasBugs, 'searchTasks', 'affected_user', IPerson)
+patch_plain_parameter_type(IHasBugs, 'searchTasks', 'assignee', IPerson)
+patch_plain_parameter_type(IHasBugs, 'searchTasks', 'bug_reporter', IPerson)
+patch_plain_parameter_type(IHasBugs, 'searchTasks', 'bug_supervisor', IPerson)
+patch_plain_parameter_type(IHasBugs, 'searchTasks', 'bug_commenter', IPerson)
+patch_plain_parameter_type(IHasBugs, 'searchTasks', 'bug_subscriber', IPerson)
+patch_plain_parameter_type(IHasBugs, 'searchTasks', 'owner', IPerson)
+patch_plain_parameter_type(IHasBugs, 'searchTasks', 'affected_user', IPerson)
 patch_plain_parameter_type(
     IHasBugs, 'searchTasks', 'structural_subscriber', IPerson)
 
@@ -693,7 +655,7 @@
     IBug, 'getNominationFor', 'target', IBugTarget)
 patch_plain_parameter_type(
     IBug, 'getNominations', 'target', IBugTarget)
-patch_choice_vocabulary(
+patch_choice_parameter_type(
     IBug, 'subscribe', 'level', BugNotificationLevel)
 
 
@@ -740,10 +702,8 @@
 patch_reference_property(IProductSeries, 'product', IProduct)
 
 # ISpecification
-ISpecification['linkBug'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['params']['bug'].schema = IBug
-ISpecification['unlinkBug'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['params']['bug'].schema = IBug
+patch_plain_parameter_type(ISpecification, 'linkBug', 'bug', IBug)
+patch_plain_parameter_type(ISpecification, 'unlinkBug', 'bug', IBug)
 patch_collection_property(ISpecification, 'dependencies', ISpecification)
 patch_collection_property(
     ISpecification, 'linked_branches', ISpecificationBranch)
@@ -892,7 +852,7 @@
 
 # IBuilder
 patch_entry_explicit_version(IBuilder, 'beta')
-IBuilder['current_build'].schema = IBuildFarmJob
+patch_reference_property(IBuilder, 'current_build', IBuildFarmJob)
 
 # IBuilderSet
 patch_operations_explicit_version(IBuilderSet, 'beta', "getByName")

=== modified file 'lib/lp/bugs/interfaces/bug.py'
--- lib/lp/bugs/interfaces/bug.py	2015-01-16 01:59:39 +0000
+++ lib/lp/bugs/interfaces/bug.py	2015-01-30 18:57:10 +0000
@@ -93,6 +93,10 @@
     Title,
     )
 from lp.services.messages.interfaces.message import IMessage
+from lp.services.webservice.apihelpers import (
+    patch_collection_property,
+    patch_reference_property,
+    )
 
 
 class CreateBugParams:
@@ -1013,16 +1017,16 @@
 
 
 # We are forced to define these now to avoid circular import problems.
-IBugAttachment['bug'].schema = IBug
-IBugWatch['bug'].schema = IBug
-IMessage['bugs'].value_type.schema = IBug
-ICve['bugs'].value_type.schema = IBug
+patch_reference_property(IBugAttachment, 'bug', IBug)
+patch_reference_property(IBugWatch, 'bug', IBug)
+patch_collection_property(IMessage, 'bugs', IBug)
+patch_collection_property(ICve, 'bugs', IBug)
 
 # In order to avoid circular dependencies, we only import
 # IBugSubscription (which itself imports IBug) here, and assign it as
 # the value type for the `subscriptions` collection.
 from lp.bugs.interfaces.bugsubscription import IBugSubscription
-IBug['subscriptions'].value_type.schema = IBugSubscription
+patch_collection_property(IBug, 'subscriptions', IBugSubscription)
 
 
 class IBugDelta(Interface):

=== modified file 'lib/lp/bugs/interfaces/bugattachment.py'
--- lib/lp/bugs/interfaces/bugattachment.py	2013-01-07 02:40:55 +0000
+++ lib/lp/bugs/interfaces/bugattachment.py	2015-01-30 18:57:10 +0000
@@ -38,6 +38,7 @@
 from lp.bugs.interfaces.hasbug import IHasBug
 from lp.services.fields import Title
 from lp.services.messages.interfaces.message import IMessage
+from lp.services.webservice.apihelpers import patch_collection_property
 
 
 class BugAttachmentType(DBEnumeratedType):
@@ -144,7 +145,7 @@
 
 
 # Need to do this here because of circular imports.
-IMessage['bugattachments'].value_type.schema = IBugAttachment
+patch_collection_property(IMessage, 'bugattachments', IBugAttachment)
 
 
 class IBugAttachmentSet(Interface):

=== modified file 'lib/lp/bugs/interfaces/bugtarget.py'
--- lib/lp/bugs/interfaces/bugtarget.py	2012-11-16 20:21:51 +0000
+++ lib/lp/bugs/interfaces/bugtarget.py	2015-01-30 18:57:10 +0000
@@ -28,7 +28,6 @@
     export_read_operation,
     export_write_operation,
     exported,
-    LAZR_WEBSERVICE_EXPORTED,
     operation_for_version,
     operation_parameters,
     operation_removed_in_version,
@@ -67,6 +66,10 @@
     )
 from lp.registry.enums import BugSharingPolicy
 from lp.services.fields import Tag
+from lp.services.webservice.apihelpers import (
+    patch_plain_parameter_type,
+    patch_reference_property,
+    )
 
 
 search_tasks_params_common = {
@@ -352,9 +355,9 @@
 
 # We assign the schema for an `IBugTask` attribute here
 # in order to avoid circular dependencies.
-IBugTask['target'].schema = IBugTarget
-IBugTask['transitionToTarget'].getTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['params']['target'].schema = IBugTarget
+patch_reference_property(IBugTask, 'target', IBugTarget)
+patch_plain_parameter_type(
+    IBugTask, 'transitionToTarget', 'target', IBugTarget)
 
 
 class BugDistroSeriesTargetDetails:

=== modified file 'lib/lp/bugs/interfaces/bugtask.py'
--- lib/lp/bugs/interfaces/bugtask.py	2013-11-28 01:30:11 +0000
+++ lib/lp/bugs/interfaces/bugtask.py	2015-01-30 18:57:10 +0000
@@ -96,6 +96,7 @@
     StrippedTextLine,
     Summary,
     )
+from lp.services.webservice.apihelpers import patch_collection_property
 
 
 class BugTaskImportance(DBEnumeratedType):
@@ -793,10 +794,10 @@
 
 # Set schemas that were impossible to specify during the definition of
 # IBugTask itself.
-IBugTask['related_tasks'].value_type.schema = IBugTask
+patch_collection_property(IBugTask, 'related_tasks', IBugTask)
 
 # We are forced to define this now to avoid circular import problems.
-IBugWatch['bugtasks'].value_type.schema = IBugTask
+patch_collection_property(IBugWatch, 'bugtasks', IBugTask)
 
 
 class IBugTaskDelta(Interface):

=== modified file 'lib/lp/bugs/interfaces/bugwatch.py'
--- lib/lp/bugs/interfaces/bugwatch.py	2012-10-24 23:53:18 +0000
+++ lib/lp/bugs/interfaces/bugwatch.py	2015-01-30 18:57:10 +0000
@@ -45,6 +45,7 @@
 from lp.bugs.interfaces.bugtracker import IBugTracker
 from lp.bugs.interfaces.hasbug import IHasBug
 from lp.services.fields import StrippedTextLine
+from lp.services.webservice.apihelpers import patch_collection_property
 
 
 class BugWatchActivityStatus(DBEnumeratedType):
@@ -295,7 +296,7 @@
 
 
 # Defined here because of circular imports.
-IBugTracker['watches'].value_type.schema = IBugWatch
+patch_collection_property(IBugTracker, 'watches', IBugWatch)
 
 
 class IBugWatchSet(Interface):

=== modified file 'lib/lp/code/interfaces/branchmergeproposal.py'
--- lib/lp/code/interfaces/branchmergeproposal.py	2014-05-07 06:12:40 +0000
+++ lib/lp/code/interfaces/branchmergeproposal.py	2015-01-30 18:57:10 +0000
@@ -85,6 +85,7 @@
     IRunnableJob,
     )
 from lp.services.webapp.interfaces import ITableBatchNavigator
+from lp.services.webservice.apihelpers import patch_reference_property
 
 
 BRANCH_MERGE_PROPOSAL_FINAL_STATES = (
@@ -723,7 +724,7 @@
         """
 
 for name in ['supersedes', 'superseded_by']:
-    IBranchMergeProposal[name].schema = IBranchMergeProposal
+    patch_reference_property(IBranchMergeProposal, name, IBranchMergeProposal)
 
 
 class IMergeProposalNeedsReviewEmailJob(IRunnableJob):

=== modified file 'lib/lp/code/interfaces/webservice.py'
--- lib/lp/code/interfaces/webservice.py	2011-12-22 16:19:11 +0000
+++ lib/lp/code/interfaces/webservice.py	2015-01-30 18:57:10 +0000
@@ -61,9 +61,10 @@
 from lp.code.interfaces.sourcepackagerecipebuild import (
     ISourcePackageRecipeBuild,
     )
-
-
-IBranchMergeQueue['branches'].value_type.schema = IBranch
+from lp.services.webservice.apihelpers import patch_collection_property
+
+
+patch_collection_property(IBranchMergeQueue, 'branches', IBranch)
 
 # XXX: JonathanLange 2010-11-09 bug=673083: Legacy work-around for circular
 # import bugs.  Break this up into a per-package thing.

=== modified file 'lib/lp/hardwaredb/interfaces/hwdb.py'
--- lib/lp/hardwaredb/interfaces/hwdb.py	2013-01-07 02:40:55 +0000
+++ lib/lp/hardwaredb/interfaces/hwdb.py	2015-01-30 18:57:10 +0000
@@ -91,6 +91,10 @@
 from lp.registry.interfaces.person import IPerson
 from lp.registry.interfaces.product import License
 from lp.services.webapp.interfaces import ILaunchpadApplication
+from lp.services.webservice.apihelpers import (
+    patch_collection_property,
+    patch_reference_property,
+    )
 from lp.soyuz.interfaces.distroarchseries import IDistroArchSeries
 
 
@@ -917,7 +921,7 @@
 
 
 # Fix cyclic reference.
-IHWDeviceClass['device'].schema = IHWDevice
+patch_reference_property(IHWDeviceClass, 'device', IHWDevice)
 
 
 class IHWDeviceSet(Interface):
@@ -1087,8 +1091,8 @@
 
 
 # Fix cyclic references.
-IHWSubmissionDevice['parent'].schema = IHWSubmissionDevice
-IHWSubmission['devices'].value_type.schema = IHWSubmissionDevice
+patch_reference_property(IHWSubmissionDevice, 'parent', IHWSubmissionDevice)
+patch_collection_property(IHWSubmission, 'devices', IHWSubmissionDevice)
 
 
 class IHWSubmissionDeviceSet(Interface):

=== modified file 'lib/lp/registry/interfaces/distroseries.py'
--- lib/lp/registry/interfaces/distroseries.py	2014-11-09 23:32:23 +0000
+++ lib/lp/registry/interfaces/distroseries.py	2015-01-30 18:57:10 +0000
@@ -26,7 +26,6 @@
     export_read_operation,
     export_write_operation,
     exported,
-    LAZR_WEBSERVICE_EXPORTED,
     operation_for_version,
     operation_parameters,
     operation_returns_collection_of,
@@ -91,6 +90,7 @@
     Title,
     UniqueField,
     )
+from lp.services.webservice.apihelpers import patch_plain_parameter_type
 from lp.soyuz.interfaces.buildrecords import IHasBuildRecords
 from lp.translations.interfaces.hastranslationimports import (
     IHasTranslationImports,
@@ -968,8 +968,8 @@
 
 # We assign the schema for an `IHasBugs` method argument here
 # in order to avoid circular dependencies.
-IHasBugs['searchTasks'].queryTaggedValue(LAZR_WEBSERVICE_EXPORTED)[
-    'params']['nominated_for'].schema = IDistroSeries
+patch_plain_parameter_type(
+    IHasBugs, 'searchTasks', 'nominated_for', IDistroSeries)
 
 
 class IDistroSeriesSet(Interface):

=== modified file 'lib/lp/registry/interfaces/milestone.py'
--- lib/lp/registry/interfaces/milestone.py	2013-04-03 03:59:28 +0000
+++ lib/lp/registry/interfaces/milestone.py	2015-01-30 18:57:10 +0000
@@ -65,7 +65,11 @@
     NoneableDescription,
     NoneableTextLine,
     )
-from lp.services.webservice.apihelpers import patch_plain_parameter_type
+from lp.services.webservice.apihelpers import (
+    patch_collection_property,
+    patch_plain_parameter_type,
+    patch_reference_property,
+    )
 
 
 class MilestoneNameField(ContentNameField):
@@ -273,8 +277,8 @@
 
 
 # Avoid circular imports
-IBugTask['milestone'].schema = IMilestone
-IBugTaskSearchBase['milestone'].value_type.schema = IMilestone
+patch_reference_property(IBugTask, 'milestone', IMilestone)
+patch_collection_property(IBugTaskSearchBase, 'milestone', IMilestone)
 patch_plain_parameter_type(
     IBugTask, 'transitionToMilestone', 'new_milestone', IMilestone)
 
@@ -349,6 +353,6 @@
 
 
 # Fix cyclic references.
-IMilestone['target'].schema = IHasMilestones
-IMilestone['series_target'].schema = IHasMilestones
-IProductRelease['milestone'].schema = IMilestone
+patch_reference_property(IMilestone, 'target', IHasMilestones)
+patch_reference_property(IMilestone, 'series_target', IHasMilestones)
+patch_reference_property(IProductRelease, 'milestone', IMilestone)

=== modified file 'lib/lp/registry/interfaces/person.py'
--- lib/lp/registry/interfaces/person.py	2015-01-07 00:35:53 +0000
+++ lib/lp/registry/interfaces/person.py	2015-01-30 18:57:10 +0000
@@ -59,7 +59,6 @@
     export_read_operation,
     export_write_operation,
     exported,
-    LAZR_WEBSERVICE_EXPORTED,
     mutator_for,
     operation_for_version,
     operation_parameters,
@@ -162,6 +161,12 @@
 from lp.services.identity.interfaces.emailaddress import IEmailAddress
 from lp.services.webapp.authorization import check_permission
 from lp.services.webapp.interfaces import ILaunchpadApplication
+from lp.services.webservice.apihelpers import (
+    patch_collection_property,
+    patch_collection_return_type,
+    patch_plain_parameter_type,
+    patch_reference_property,
+    )
 from lp.services.worlddata.interfaces.language import ILanguage
 from lp.translations.interfaces.hastranslationimports import (
     IHasTranslationImports,
@@ -2531,53 +2536,51 @@
     'api_deactivatedmembers',
     'api_expiredmembers',
     ]:
-    IPersonViewRestricted[name].value_type.schema = IPerson
+    patch_collection_property(IPersonViewRestricted, name, IPerson)
 
-IPersonViewRestricted['sub_teams'].value_type.schema = ITeam
-IPersonViewRestricted['super_teams'].value_type.schema = ITeam
+patch_collection_property(IPersonViewRestricted, 'sub_teams', ITeam)
+patch_collection_property(IPersonViewRestricted, 'super_teams', ITeam)
 # XXX: salgado, 2008-08-01: Uncomment these when teams_*participated_in are
 # exported again.
-# IPersonViewRestricted['teams_participated_in'].value_type.schema = ITeam
-# IPersonViewRestricted[
-#   'teams_indirectly_participated_in'].value_type.schema = ITeam
+# patch_collection_property(
+#     IPersonViewRestricted, 'teams_participated_in', ITeam)
+# patch_collection_property(
+#     IPersonViewRestricted, 'teams_indirectly_participated_in', ITeam)
 
 # Fix schema of operation parameters. We need zope.deferredimport!
 params_to_fix = [
     # XXX: salgado, 2008-08-01: Uncomment these when they are exported again.
     # (IPersonViewRestricted['findPathToTeam'], 'team'),
     # (IPersonViewRestricted['inTeam'], 'team'),
-    (IPersonEditRestricted['join'], 'team'),
-    (IPersonEditRestricted['leave'], 'team'),
-    (IPersonEditRestricted['addMember'], 'person'),
-    (IPersonEditRestricted['acceptInvitationToBeMemberOf'], 'team'),
-    (IPersonEditRestricted['declineInvitationToBeMemberOf'], 'team'),
-    (IPersonEditRestricted['retractTeamMembership'], 'team'),
+    ('join', 'team'),
+    ('leave', 'team'),
+    ('addMember', 'person'),
+    ('acceptInvitationToBeMemberOf', 'team'),
+    ('declineInvitationToBeMemberOf', 'team'),
+    ('retractTeamMembership', 'team'),
     ]
 for method, name in params_to_fix:
-    method.queryTaggedValue(
-        'lazr.restful.exported')['params'][name].schema = IPerson
+    patch_plain_parameter_type(IPersonEditRestricted, method, name, IPerson)
 
 # Fix schema of operation return values.
 # XXX: salgado, 2008-08-01: Uncomment when findPathToTeam is exported again.
-# IPersonPublic['findPathToTeam'].queryTaggedValue(
-#     'lazr.webservice.exported')['return_type'].value_type.schema = IPerson
-IPersonViewRestricted['getMembersByStatus'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['return_type'].value_type.schema = IPerson
-IPersonViewRestricted['getOwnedTeams'].queryTaggedValue(
-    LAZR_WEBSERVICE_EXPORTED)['return_type'].value_type.schema = ITeam
+# patch_collection_return_type(IPersonPublic, 'findPathToTeam', IPerson)
+patch_collection_return_type(
+    IPersonViewRestricted, 'getMembersByStatus', IPerson)
+patch_collection_return_type(IPersonViewRestricted, 'getOwnedTeams', ITeam)
 
 # Fix schema of ITeamMembership fields.  Has to be done here because of
 # circular dependencies.
 for name in ['team', 'person', 'last_changed_by']:
-    ITeamMembership[name].schema = IPerson
+    patch_reference_property(ITeamMembership, name, IPerson)
 
 # Fix schema of ITeamParticipation fields.  Has to be done here because of
 # circular dependencies.
 for name in ['team', 'person']:
-    ITeamParticipation[name].schema = IPerson
+    patch_reference_property(ITeamParticipation, name, IPerson)
 
 # Thank circular dependencies once again.
-IIrcID['person'].schema = IPerson
-IJabberID['person'].schema = IPerson
-IWikiName['person'].schema = IPerson
-IEmailAddress['person'].schema = IPerson
+patch_reference_property(IIrcID, 'person', IPerson)
+patch_reference_property(IJabberID, 'person', IPerson)
+patch_reference_property(IWikiName, 'person', IPerson)
+patch_reference_property(IEmailAddress, 'person', IPerson)

=== modified file 'lib/lp/registry/interfaces/product.py'
--- lib/lp/registry/interfaces/product.py	2015-01-29 16:28:30 +0000
+++ lib/lp/registry/interfaces/product.py	2015-01-30 18:57:10 +0000
@@ -140,6 +140,10 @@
     Title,
     URIField,
     )
+from lp.services.webservice.apihelpers import (
+    patch_collection_property,
+    patch_reference_property,
+    )
 from lp.translations.interfaces.hastranslationimports import (
     IHasTranslationImports,
     )
@@ -903,8 +907,8 @@
 
 
 # Fix cyclic references.
-IProjectGroup['products'].value_type = Reference(IProduct)
-IProductRelease['product'].schema = IProduct
+patch_collection_property(IProjectGroup, 'products', IProduct)
+patch_reference_property(IProductRelease, 'product', IProduct)
 
 
 class IProductSet(Interface):
@@ -1171,6 +1175,7 @@
 # Fix circular imports.
 from lp.registry.interfaces.distributionsourcepackage import (
     IDistributionSourcePackage)
-IDistributionSourcePackage['upstream_product'].schema = IProduct
+patch_reference_property(
+    IDistributionSourcePackage, 'upstream_product', IProduct)
 
-ICommercialSubscription['product'].schema = IProduct
+patch_reference_property(ICommercialSubscription, 'product', IProduct)

=== modified file 'lib/lp/registry/interfaces/productrelease.py'
--- lib/lp/registry/interfaces/productrelease.py	2013-02-06 04:22:43 +0000
+++ lib/lp/registry/interfaces/productrelease.py	2015-01-30 18:57:10 +0000
@@ -59,6 +59,7 @@
     ContentNameField,
     PersonChoice,
     )
+from lp.services.webservice.apihelpers import patch_reference_property
 
 
 def file_size_constraint(value, max_size):
@@ -386,7 +387,8 @@
 
 
 # Set the schema for IProductReleaseFile now that IProductRelease is defined.
-IProductReleaseFile['productrelease'].schema = IProductRelease
+patch_reference_property(
+    IProductReleaseFile, 'productrelease', IProductRelease)
 
 
 class IProductReleaseFileAddForm(Interface):

=== modified file 'lib/lp/services/messages/interfaces/message.py'
--- lib/lp/services/messages/interfaces/message.py	2013-08-12 03:12:44 +0000
+++ lib/lp/services/messages/interfaces/message.py	2015-01-30 18:57:10 +0000
@@ -48,6 +48,7 @@
 from lp import _
 from lp.app.errors import NotFoundError
 from lp.services.librarian.interfaces import ILibraryFileAlias
+from lp.services.webservice.apihelpers import patch_reference_property
 
 
 class IMessage(Interface):
@@ -117,7 +118,7 @@
 
 
 # Fix for self-referential schema.
-IMessage['parent'].schema = IMessage
+patch_reference_property(IMessage, 'parent', IMessage)
 
 
 class IMessageSet(Interface):

=== modified file 'lib/lp/services/webservice/apihelpers.py'
--- lib/lp/services/webservice/apihelpers.py	2011-12-20 20:21:29 +0000
+++ lib/lp/services/webservice/apihelpers.py	2015-01-30 18:57:10 +0000
@@ -119,18 +119,15 @@
     exported_class[property_name].value_type.schema = collection_type
 
 
-def patch_choice_vocabulary(exported_class, method_name, param_name,
-                            vocabulary):
-    """Set the `Vocabulary` for a `Choice` parameter for a given method.
+def patch_choice_property(exported_class, property_name, choice_type):
+    """Set the `Choice` type of the given property on the given class.
 
     :param exported_class: The class containing the property.
     :param property_name: The name of the property whose type you need
         to patch.
-    :param vocabulary: The `Vocabulary` type.
+    :param choice_type: The new `Choice` type for the property.
     """
-    exported_class[method_name].queryTaggedValue(
-        LAZR_WEBSERVICE_EXPORTED)[
-            'params'][param_name].vocabulary = vocabulary
+    exported_class[property_name].vocabulary = choice_type
 
 
 def patch_entry_explicit_version(interface, version):


Follow ups