← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:schema-explicit-versions-remaining into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:schema-explicit-versions-remaining into launchpad:master.

Commit message:
Set explicit webservice versions for remaining interfaces

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/425592

Similar to https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/423611.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:schema-explicit-versions-remaining into launchpad:master.
diff --git a/lib/lp/_schema_circular_imports.py b/lib/lp/_schema_circular_imports.py
index c621fef..804c5e5 100644
--- a/lib/lp/_schema_circular_imports.py
+++ b/lib/lp/_schema_circular_imports.py
@@ -43,10 +43,7 @@ from lp.bugs.interfaces.structuralsubscription import (
     IStructuralSubscriptionTarget,
     )
 from lp.bugs.interfaces.vulnerability import IVulnerability
-from lp.buildmaster.interfaces.builder import (
-    IBuilder,
-    IBuilderSet,
-    )
+from lp.buildmaster.interfaces.builder import IBuilder
 from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJob
 from lp.buildmaster.interfaces.buildqueue import IBuildQueue
 from lp.code.interfaces.branch import (
@@ -120,21 +117,11 @@ from lp.services.messages.interfaces.messagerevision import IMessageRevision
 from lp.services.webservice.apihelpers import (
     patch_collection_property,
     patch_collection_return_type,
-    patch_entry_explicit_version,
     patch_entry_return_type,
     patch_list_parameter_type,
-    patch_operations_explicit_version,
     patch_plain_parameter_type,
     patch_reference_property,
     )
-from lp.services.worlddata.interfaces.country import (
-    ICountry,
-    ICountrySet,
-    )
-from lp.services.worlddata.interfaces.language import (
-    ILanguage,
-    ILanguageSet,
-    )
 from lp.snappy.interfaces.snapbase import ISnapBase
 from lp.soyuz.interfaces.archive import IArchive
 from lp.soyuz.interfaces.archivedependency import IArchiveDependency
@@ -171,9 +158,7 @@ from lp.translations.interfaces.potemplate import (
     IPOTemplateSharingSubset,
     IPOTemplateSubset,
     )
-from lp.translations.interfaces.translationgroup import ITranslationGroup
 from lp.translations.interfaces.translationimportqueue import (
-    ITranslationImportQueue,
     ITranslationImportQueueEntry,
     )
 
@@ -248,6 +233,9 @@ patch_entry_return_type(IBug, 'addNomination', IBugNomination)
 patch_entry_return_type(IBug, 'getNominationFor', IBugNomination)
 patch_collection_return_type(IBug, 'getNominations', IBugNomination)
 
+# IBuilder
+patch_reference_property(IBuilder, 'current_build', IBuildFarmJob)
+
 patch_reference_property(
     IPreviewDiff, 'branch_merge_proposal', IBranchMergeProposal)
 
@@ -671,100 +659,3 @@ patch_collection_property(
 
 # IAccessToken
 patch_reference_property(IAccessToken, 'git_repository', IGitRepository)
-
-
-###
-#
-# Our web service configuration requires that every entry, field, and
-# named operation explicitly name the version in which it first
-# appears. This code grandfathers in entries and named operations that
-# were defined before this rule came into effect. When you change an
-# interface in the future, you should add explicit version statements to
-# its definition and get rid of the patch calls here.
-#
-###
-
-# IBranch
-patch_entry_explicit_version(IBranch, 'beta')
-
-# IBranchMergeProposal
-patch_entry_explicit_version(IBranchMergeProposal, 'beta')
-patch_operations_explicit_version(
-    IBranchMergeProposal, 'beta', "createComment", "getComment",
-    "nominateReviewer", "setStatus")
-
-# IBranchSubscription
-patch_entry_explicit_version(IBranchSubscription, 'beta')
-patch_operations_explicit_version(
-    IBranchSubscription, 'beta', "canBeUnsubscribedByUser")
-
-# IBuilder
-patch_entry_explicit_version(IBuilder, 'beta')
-patch_reference_property(IBuilder, 'current_build', IBuildFarmJob)
-
-# IBuilderSet
-patch_operations_explicit_version(IBuilderSet, 'beta', "getByName")
-
-# ICodeImport
-patch_entry_explicit_version(ICodeImport, 'beta')
-patch_operations_explicit_version(
-    ICodeImport, 'beta', "requestImport")
-
-# ICodeReviewComment
-patch_entry_explicit_version(ICodeReviewComment, 'beta')
-
-# ICodeReviewVoteReference
-patch_entry_explicit_version(ICodeReviewVoteReference, 'beta')
-patch_operations_explicit_version(
-    ICodeReviewVoteReference, 'beta', "claimReview", "delete",
-    "reassignReview")
-
-# ICountry
-patch_entry_explicit_version(ICountry, 'beta')
-
-# ICountrySet
-patch_operations_explicit_version(
-    ICountrySet, 'beta', "getByCode", "getByName")
-
-# IHasTranslationImports
-patch_entry_explicit_version(IHasTranslationImports, 'beta')
-
-# ILanguage
-patch_entry_explicit_version(ILanguage, 'beta')
-
-# ILanguageSet
-patch_operations_explicit_version(ILanguageSet, 'beta', "getAllLanguages")
-
-# IMessage
-patch_entry_explicit_version(IMessage, 'beta')
-
-# IPOFile
-patch_entry_explicit_version(IPOFile, 'beta')
-
-# IPOTemplate
-patch_entry_explicit_version(IPOTemplate, 'beta')
-
-# IPreviewDiff
-patch_entry_explicit_version(IPreviewDiff, 'beta')
-
-# ISourcePackageRecipe
-patch_entry_explicit_version(ISourcePackageRecipe, 'beta')
-patch_operations_explicit_version(
-    ISourcePackageRecipe, 'beta', "performDailyBuild", "requestBuild",
-    "setRecipeText")
-
-# ISourcePackageRecipeBuild
-patch_entry_explicit_version(ISourcePackageRecipeBuild, 'beta')
-
-# ITranslationGroup
-patch_entry_explicit_version(ITranslationGroup, 'beta')
-
-# ITranslationImportQueue
-patch_operations_explicit_version(
-    ITranslationImportQueue, 'beta', "getAllEntries", "getFirstEntryToImport",
-    "getRequestTargets")
-
-# ITranslationImportQueueEntry
-patch_entry_explicit_version(ITranslationImportQueueEntry, 'beta')
-patch_operations_explicit_version(
-    ITranslationImportQueueEntry, 'beta', "setStatus")
diff --git a/lib/lp/buildmaster/interfaces/builder.py b/lib/lp/buildmaster/interfaces/builder.py
index 3d35fa3..f062feb 100644
--- a/lib/lp/buildmaster/interfaces/builder.py
+++ b/lib/lp/buildmaster/interfaces/builder.py
@@ -221,7 +221,7 @@ class IBuilderEdit(Interface):
         """Update the clean status."""
 
 
-@exported_as_webservice_entry()
+@exported_as_webservice_entry(as_of="beta")
 class IBuilder(IBuilderEdit, IBuilderView, IBuilderModerateAttributes):
     """Builder information and state.
 
@@ -275,6 +275,7 @@ class IBuilderSet(IBuilderSetAdmin):
         name=TextLine(title=_("Builder name"), required=True))
     @operation_returns_entry(IBuilder)
     @export_read_operation()
+    @operation_for_version("beta")
     def getByName(name):
         """Retrieve a builder by name"""
 
diff --git a/lib/lp/code/interfaces/branch.py b/lib/lp/code/interfaces/branch.py
index 57d63e4..741c2a4 100644
--- a/lib/lp/code/interfaces/branch.py
+++ b/lib/lp/code/interfaces/branch.py
@@ -1246,7 +1246,7 @@ class IBranchEdit(IWebhookTarget):
         """
 
 
-@exported_as_webservice_entry(plural_name='branches')
+@exported_as_webservice_entry(plural_name="branches", as_of="beta")
 class IBranch(IBranchPublic, IBranchView, IBranchEdit,
               IBranchEditableAttributes, IBranchModerate,
               IBranchModerateAttributes, IBranchAnyone):
diff --git a/lib/lp/code/interfaces/branchmergeproposal.py b/lib/lp/code/interfaces/branchmergeproposal.py
index 562e1b8..880ee00 100644
--- a/lib/lp/code/interfaces/branchmergeproposal.py
+++ b/lib/lp/code/interfaces/branchmergeproposal.py
@@ -371,6 +371,7 @@ class IBranchMergeProposalView(Interface):
     # Really ICodeReviewComment.
     @operation_returns_entry(Interface)
     @export_read_operation()
+    @operation_for_version("beta")
     def getComment(id):
         """Return the CodeReviewComment with the specified ID.
 
@@ -569,6 +570,7 @@ class IBranchMergeProposalEdit(Interface):
                 "revision of the branch for the status change."),
             required=False))
     @export_write_operation()
+    @operation_for_version("beta")
     def setStatus(status, user, revision_id):
         """Set the state of the merge proposal to the specified status.
 
@@ -674,6 +676,7 @@ class IBranchMergeProposalEdit(Interface):
     # Really ICodeReviewVoteReference.
     @operation_returns_entry(Interface)
     @export_write_operation()
+    @operation_for_version("beta")
     def nominateReviewer(reviewer, registrant, review_type=None):
         """Set the specified person as a reviewer.
 
@@ -693,6 +696,7 @@ class IBranchMergeProposalAnyAllowedPerson(IBugLinkTarget):
     @call_with(owner=REQUEST_USER)
     # ICodeReviewComment supplied as Interface to avoid circular imports.
     @export_factory_operation(Interface, [])
+    @operation_for_version("beta")
     def createComment(owner, subject=None, content=None, vote=None,
                       review_type=None, parent=None,
                       previewdiff_id=None, inline_comments=None):
@@ -768,7 +772,7 @@ class IBranchMergeProposalAnyAllowedPerson(IBugLinkTarget):
         """Unlink a bug from this merge proposal."""
 
 
-@exported_as_webservice_entry()
+@exported_as_webservice_entry(as_of="beta")
 class IBranchMergeProposal(IBranchMergeProposalPublic,
                            IBranchMergeProposalView, IBranchMergeProposalEdit,
                            IBranchMergeProposalAnyAllowedPerson):
diff --git a/lib/lp/code/interfaces/branchsubscription.py b/lib/lp/code/interfaces/branchsubscription.py
index 0ada7b2..6b1417f 100644
--- a/lib/lp/code/interfaces/branchsubscription.py
+++ b/lib/lp/code/interfaces/branchsubscription.py
@@ -12,6 +12,7 @@ from lazr.restful.declarations import (
     export_read_operation,
     exported,
     exported_as_webservice_entry,
+    operation_for_version,
     REQUEST_USER,
     )
 from lazr.restful.fields import Reference
@@ -31,7 +32,7 @@ from lp.code.interfaces.branch import IBranch
 from lp.services.fields import PersonChoice
 
 
-@exported_as_webservice_entry()
+@exported_as_webservice_entry(as_of="beta")
 class IBranchSubscription(Interface):
     """The relationship between a person and a branch."""
 
@@ -88,5 +89,6 @@ class IBranchSubscription(Interface):
 
     @call_with(user=REQUEST_USER)
     @export_read_operation()
+    @operation_for_version("beta")
     def canBeUnsubscribedByUser(user):
         """Can the user unsubscribe the subscriber from the branch?"""
diff --git a/lib/lp/code/interfaces/codeimport.py b/lib/lp/code/interfaces/codeimport.py
index 6996d39..8001dfc 100644
--- a/lib/lp/code/interfaces/codeimport.py
+++ b/lib/lp/code/interfaces/codeimport.py
@@ -117,7 +117,7 @@ def validate_cvs_module(cvsmodule):
     return True
 
 
-@exported_as_webservice_entry()
+@exported_as_webservice_entry(as_of="beta")
 class ICodeImport(Interface):
     """A code import to a Bazaar branch or Git repository."""
 
@@ -270,6 +270,7 @@ class ICodeImport(Interface):
 
     @call_with(requester=REQUEST_USER)
     @export_write_operation()
+    @operation_for_version("beta")
     def requestImport(requester, error_if_already_requested=False):
         """Request that an import be tried soon.
 
diff --git a/lib/lp/code/interfaces/codereviewcomment.py b/lib/lp/code/interfaces/codereviewcomment.py
index 8c4a0e4..e16300b 100644
--- a/lib/lp/code/interfaces/codereviewcomment.py
+++ b/lib/lp/code/interfaces/codereviewcomment.py
@@ -101,7 +101,7 @@ class ICodeReviewCommentView(IMessageCommon):
         """
 
 
-@exported_as_webservice_entry()
+@exported_as_webservice_entry(as_of="beta")
 class ICodeReviewComment(ICodeReviewCommentView, IMessageEdit):
     """A link between a merge proposal and a message."""
 
diff --git a/lib/lp/code/interfaces/codereviewvote.py b/lib/lp/code/interfaces/codereviewvote.py
index b2c75c9..39bb9fe 100644
--- a/lib/lp/code/interfaces/codereviewvote.py
+++ b/lib/lp/code/interfaces/codereviewvote.py
@@ -13,6 +13,7 @@ from lazr.restful.declarations import (
     export_write_operation,
     exported,
     exported_as_webservice_entry,
+    operation_for_version,
     operation_parameters,
     REQUEST_USER,
     )
@@ -93,6 +94,7 @@ class ICodeReviewVoteReferenceEdit(Interface):
 
     @call_with(claimant=REQUEST_USER)
     @export_write_operation()
+    @operation_for_version("beta")
     def claimReview(claimant):
         """Change a pending review into a review for claimant.
 
@@ -120,6 +122,7 @@ class ICodeReviewVoteReferenceEdit(Interface):
             title=_("The person or team to assign to do the review."),
             schema=IPerson))
     @export_write_operation()
+    @operation_for_version("beta")
     def reassignReview(reviewer):
         """Reassign a pending review to someone else.
 
@@ -132,6 +135,7 @@ class ICodeReviewVoteReferenceEdit(Interface):
         """
 
     @export_destructor_operation()
+    @operation_for_version("beta")
     def delete():
         """Delete the pending review.
 
@@ -139,7 +143,7 @@ class ICodeReviewVoteReferenceEdit(Interface):
         """
 
 
-@exported_as_webservice_entry()
+@exported_as_webservice_entry(as_of="beta")
 class ICodeReviewVoteReference(ICodeReviewVoteReferencePublic,
                                ICodeReviewVoteReferenceEdit):
     """A reference to a vote on a IBranchMergeProposal.
diff --git a/lib/lp/code/interfaces/diff.py b/lib/lp/code/interfaces/diff.py
index adeb12a..2bf0d55 100644
--- a/lib/lp/code/interfaces/diff.py
+++ b/lib/lp/code/interfaces/diff.py
@@ -82,7 +82,7 @@ class IIncrementalDiff(Interface):
         IRevision, readonly=True, title=_('The new revision of the diff.'))
 
 
-@exported_as_webservice_entry()
+@exported_as_webservice_entry(as_of="beta")
 class IPreviewDiff(IDiff):
     """A diff generated to show actual diff between two branches.
 
diff --git a/lib/lp/code/interfaces/sourcepackagerecipe.py b/lib/lp/code/interfaces/sourcepackagerecipe.py
index af05f7b..7973279 100644
--- a/lib/lp/code/interfaces/sourcepackagerecipe.py
+++ b/lib/lp/code/interfaces/sourcepackagerecipe.py
@@ -198,6 +198,7 @@ class ISourcePackageRecipeView(Interface):
         pocket=Choice(vocabulary=PackagePublishingPocket,))
     @operation_returns_entry(Interface)
     @export_write_operation()
+    @operation_for_version("beta")
     def requestBuild(archive, distroseries, requester, pocket):
         """Request that the recipe be built in to the specified archive.
 
@@ -213,6 +214,7 @@ class ISourcePackageRecipeView(Interface):
         """
 
     @export_write_operation()
+    @operation_for_version("beta")
     def performDailyBuild():
         """Perform a build into the daily build archive."""
 
@@ -286,6 +288,7 @@ class ISourcePackageRecipeEdit(Interface):
         recipe_text=copy_field(
             ISourcePackageRecipeView['recipe_text']))
     @export_write_operation()
+    @operation_for_version("beta")
     def setRecipeText(recipe_text):
         """Set the text of the recipe."""
 
@@ -309,7 +312,7 @@ class ISourcePackageRecipeDelete(Interface):
         """
 
 
-@exported_as_webservice_entry()
+@exported_as_webservice_entry(as_of="beta")
 class ISourcePackageRecipe(ISourcePackageRecipeData,
     ISourcePackageRecipeEdit, ISourcePackageRecipeEditableAttributes,
     ISourcePackageRecipeView):
diff --git a/lib/lp/code/interfaces/sourcepackagerecipebuild.py b/lib/lp/code/interfaces/sourcepackagerecipebuild.py
index 12fe659..d541dc7 100644
--- a/lib/lp/code/interfaces/sourcepackagerecipebuild.py
+++ b/lib/lp/code/interfaces/sourcepackagerecipebuild.py
@@ -84,7 +84,7 @@ class ISourcePackageRecipeBuildAdmin(IBuildFarmJobAdmin):
     """`ISourcePackageRecipeBuild` attributes that require launchpad.Admin."""
 
 
-@exported_as_webservice_entry()
+@exported_as_webservice_entry(as_of="beta")
 class ISourcePackageRecipeBuild(ISourcePackageRecipeBuildView,
                                 ISourcePackageRecipeBuildEdit,
                                 ISourcePackageRecipeBuildAdmin,
diff --git a/lib/lp/services/identity/interfaces/emailaddress.py b/lib/lp/services/identity/interfaces/emailaddress.py
index ef9bb14..53ecb85 100644
--- a/lib/lp/services/identity/interfaces/emailaddress.py
+++ b/lib/lp/services/identity/interfaces/emailaddress.py
@@ -93,7 +93,7 @@ VALID_EMAIL_STATUSES = (
     EmailAddressStatus.PREFERRED)
 
 
-@exported_as_webservice_entry(plural_name='email_addresses')
+@exported_as_webservice_entry(plural_name="email_addresses", as_of="beta")
 class IEmailAddress(IHasOwner):
     """The object that stores the `IPerson`'s emails."""
 
diff --git a/lib/lp/services/identity/interfaces/webservice.py b/lib/lp/services/identity/interfaces/webservice.py
index 2ae054b..0d85d64 100644
--- a/lib/lp/services/identity/interfaces/webservice.py
+++ b/lib/lp/services/identity/interfaces/webservice.py
@@ -14,8 +14,3 @@ __all__ = [
     ]
 
 from lp.services.identity.interfaces.emailaddress import IEmailAddress
-from lp.services.webservice.apihelpers import patch_entry_explicit_version
-
-
-# IEmailAddress
-patch_entry_explicit_version(IEmailAddress, 'beta')
diff --git a/lib/lp/services/messages/interfaces/message.py b/lib/lp/services/messages/interfaces/message.py
index a699dd9..300764a 100644
--- a/lib/lp/services/messages/interfaces/message.py
+++ b/lib/lp/services/messages/interfaces/message.py
@@ -158,7 +158,7 @@ class IMessageView(IMessageCommon):
         """Return None because messages are not threaded over the API."""
 
 
-@exported_as_webservice_entry('message')
+@exported_as_webservice_entry("message", as_of="beta")
 class IMessage(IMessageEdit, IMessageView):
     """A Message."""
 
diff --git a/lib/lp/services/temporaryblobstorage/interfaces.py b/lib/lp/services/temporaryblobstorage/interfaces.py
index 1ed23df..4aef989 100644
--- a/lib/lp/services/temporaryblobstorage/interfaces.py
+++ b/lib/lp/services/temporaryblobstorage/interfaces.py
@@ -15,6 +15,7 @@ from lazr.restful.declarations import (
     exported,
     exported_as_webservice_collection,
     exported_as_webservice_entry,
+    operation_for_version,
     operation_parameters,
     rename_parameters_as,
     )
@@ -54,10 +55,12 @@ class ITemporaryBlobStorage(Interface):
     file_alias = Attribute("Link to actual storage of blob")
 
     @export_read_operation()
+    @operation_for_version("beta")
     def hasBeenProcessed():
         """Return True if this blob has been processed."""
 
     @export_read_operation()
+    @operation_for_version("beta")
     def getProcessedData():
         """Returns a dict containing the processed blob data."""
 
@@ -79,6 +82,7 @@ class ITemporaryStorageManager(Interface):
     @rename_parameters_as(uuid='token')
     @operation_parameters(uuid=copy_field(ITemporaryBlobStorage['uuid']))
     @export_read_operation()
+    @operation_for_version("beta")
     def fetch(uuid):
         """Retrieve a TemporaryBlobStorage by uuid."""
 
diff --git a/lib/lp/services/temporaryblobstorage/webservice.py b/lib/lp/services/temporaryblobstorage/webservice.py
index 3549f41..71671e4 100644
--- a/lib/lp/services/temporaryblobstorage/webservice.py
+++ b/lib/lp/services/temporaryblobstorage/webservice.py
@@ -18,15 +18,3 @@ from lp.services.temporaryblobstorage.interfaces import (
     ITemporaryBlobStorage,
     ITemporaryStorageManager,
     )
-from lp.services.webservice.apihelpers import (
-    patch_operations_explicit_version,
-    )
-
-
-# ITemporaryBlobStorage
-patch_operations_explicit_version(
-    ITemporaryBlobStorage, 'beta', "getProcessedData", "hasBeenProcessed")
-
-# ITemporaryStorageManager
-patch_operations_explicit_version(
-    ITemporaryStorageManager, 'beta', "fetch")
diff --git a/lib/lp/services/webservice/apihelpers.py b/lib/lp/services/webservice/apihelpers.py
index 471e727..088d4e5 100644
--- a/lib/lp/services/webservice/apihelpers.py
+++ b/lib/lp/services/webservice/apihelpers.py
@@ -16,18 +16,14 @@ __all__ = [
     'patch_choice_property',
     'patch_collection_property',
     'patch_collection_return_type',
-    'patch_entry_explicit_version',
     'patch_entry_return_type',
     'patch_list_parameter_type',
-    'patch_operation_explicit_version',
-    'patch_operations_explicit_version',
     'patch_plain_parameter_type',
     'patch_reference_property',
     ]
 
 
 from lazr.restful.declarations import LAZR_WEBSERVICE_EXPORTED
-from zope.schema import getFields
 
 
 def patch_entry_return_type(exported_class, method_name, return_type):
@@ -126,65 +122,3 @@ def patch_choice_property(exported_class, property_name, choice_type):
     :param choice_type: The new `Choice` type for the property.
     """
     exported_class[property_name].vocabulary = choice_type
-
-
-def patch_entry_explicit_version(interface, version):
-    """Make it look as though an entry definition used as_of.
-
-    This function should be phased out in favor of actually using
-    as_of. This function patches the entry's fields as well as the
-    entry itself. Fields that are explicitly published as of a given
-    version (even though the entry is not) are ignored.
-    """
-    tagged = interface.getTaggedValue(LAZR_WEBSERVICE_EXPORTED)
-    versioned = tagged.dict_for_name(version) or tagged.dict_for_name(None)
-    versioned['_as_of_was_used'] = True
-
-    # Now tag the fields.
-    for name, field in getFields(interface).items():
-        tagged = field.queryTaggedValue(LAZR_WEBSERVICE_EXPORTED)
-        if tagged is None:
-            continue
-        versioned = (
-            tagged.dict_for_name(version) or
-            tagged.dict_for_name(None))
-        if versioned is None:
-            # This field is explicitly published in some other version.
-            # Just ignore it.
-            continue
-        else:
-            versioned['_as_of_was_used'] = True
-
-
-def patch_operations_explicit_version(interface, version, *method_names):
-    """Make it look like operations' first tags were @operation_for_version.
-
-    This function should be phased out in favor of actually using
-    @operation_for_version, everywhere.
-    """
-    for method in method_names:
-        patch_operation_explicit_version(interface, version, method)
-
-
-def patch_operation_explicit_version(interface, version, method_name):
-    """Make it look like an operation's first tag was @operation_for_version.
-
-    This function should be phased out in favor of actually using
-    @operation_for_version, everywhere.
-    """
-    tagged = interface[method_name].getTaggedValue(LAZR_WEBSERVICE_EXPORTED)
-    error_prefix = "%s.%s: Attempted to patch to version %s, but " % (
-        interface.__name__, method_name, version)
-    if (len(tagged.stack) > 1
-        and tagged.stack[0].version == None
-        and tagged.stack[1].version == version):
-        raise ValueError(
-            error_prefix + (
-                'it is already published in %s. Did you just change '
-                'it to be explicitly published?' % version))
-    if tagged.stack[0].version == version:
-        raise ValueError(
-            error_prefix + (
-                'it seems to have already been patched. Does this '
-                'method come from a mixin used in multiple interfaces?'))
-    tagged.rename_version(None, version)
diff --git a/lib/lp/services/worlddata/interfaces/country.py b/lib/lp/services/worlddata/interfaces/country.py
index c7e53e1..2abefab 100644
--- a/lib/lp/services/worlddata/interfaces/country.py
+++ b/lib/lp/services/worlddata/interfaces/country.py
@@ -15,6 +15,7 @@ from lazr.restful.declarations import (
     exported,
     exported_as_webservice_collection,
     exported_as_webservice_entry,
+    operation_for_version,
     operation_parameters,
     operation_returns_entry,
     )
@@ -35,7 +36,8 @@ from lp.services.fields import (
     )
 
 
-@exported_as_webservice_entry(plural_name='countries', publish_web_link=False)
+@exported_as_webservice_entry(
+    plural_name="countries", publish_web_link=False, as_of="beta")
 class ICountry(Interface):
     """The country description."""
 
@@ -78,6 +80,7 @@ class ICountrySet(Interface):
         name=TextLine(title=_("Name"), required=True))
     @operation_returns_entry(ICountry)
     @export_read_operation()
+    @operation_for_version("beta")
     def getByName(name):
         """Return a country by its name."""
 
@@ -85,6 +88,7 @@ class ICountrySet(Interface):
         code=TextLine(title=_("Code"), required=True))
     @operation_returns_entry(ICountry)
     @export_read_operation()
+    @operation_for_version("beta")
     def getByCode(code):
         """Return a country by its code."""
 
diff --git a/lib/lp/services/worlddata/interfaces/language.py b/lib/lp/services/worlddata/interfaces/language.py
index a56f84e..b659725 100644
--- a/lib/lp/services/worlddata/interfaces/language.py
+++ b/lib/lp/services/worlddata/interfaces/language.py
@@ -21,6 +21,7 @@ from lazr.restful.declarations import (
     exported,
     exported_as_webservice_collection,
     exported_as_webservice_entry,
+    operation_for_version,
     operation_returns_collection_of,
     )
 from zope.interface import (
@@ -55,7 +56,7 @@ class TextDirection(DBEnumeratedType):
         """)
 
 
-@exported_as_webservice_entry()
+@exported_as_webservice_entry(as_of="beta")
 class ILanguage(Interface):
     """A Language."""
 
@@ -183,6 +184,7 @@ class ILanguageSet(Interface):
     @export_read_operation()
     @operation_returns_collection_of(ILanguage)
     @call_with(want_translators_count=True)
+    @operation_for_version("beta")
     def getAllLanguages(want_translators_count=False):
         """Return a result set of all ILanguages from Launchpad."""
 
diff --git a/lib/lp/translations/interfaces/hastranslationimports.py b/lib/lp/translations/interfaces/hastranslationimports.py
index f6ff362..a8443c0 100644
--- a/lib/lp/translations/interfaces/hastranslationimports.py
+++ b/lib/lp/translations/interfaces/hastranslationimports.py
@@ -25,8 +25,9 @@ from lp.translations.enums import RosettaImportStatus
 
 
 @exported_as_webservice_entry(
-    singular_name='object_with_translation_imports',
-    plural_name='objects_with_translation_imports')
+    singular_name="object_with_translation_imports",
+    plural_name="objects_with_translation_imports",
+    as_of="beta")
 class IHasTranslationImports(Interface):
     """An entity that has a translation import queue.
 
diff --git a/lib/lp/translations/interfaces/pofile.py b/lib/lp/translations/interfaces/pofile.py
index 6424c56..87fcb5d 100644
--- a/lib/lp/translations/interfaces/pofile.py
+++ b/lib/lp/translations/interfaces/pofile.py
@@ -46,7 +46,8 @@ from lp.translations.interfaces.translationsperson import ITranslationsPerson
 
 @exported_as_webservice_entry(
     singular_name="translation_file",
-    plural_name="translation_files")
+    plural_name="translation_files",
+    as_of="beta")
 class IPOFile(IRosettaStats):
     """A translation file."""
 
diff --git a/lib/lp/translations/interfaces/potemplate.py b/lib/lp/translations/interfaces/potemplate.py
index ebfea42..3a7ef3a 100644
--- a/lib/lp/translations/interfaces/potemplate.py
+++ b/lib/lp/translations/interfaces/potemplate.py
@@ -51,8 +51,9 @@ class LanguageNotFound(NotFoundError):
 
 
 @exported_as_webservice_entry(
-    singular_name='translation_template',
-    plural_name='translation_templates')
+    singular_name="translation_template",
+    plural_name="translation_templates",
+    as_of="beta")
 class IPOTemplate(IRosettaStats):
     """A translation template."""
 
diff --git a/lib/lp/translations/interfaces/translationgroup.py b/lib/lp/translations/interfaces/translationgroup.py
index 6b7bd7c..250c3a0 100644
--- a/lib/lp/translations/interfaces/translationgroup.py
+++ b/lib/lp/translations/interfaces/translationgroup.py
@@ -42,7 +42,8 @@ from lp.translations.enums import TranslationPermission
 
 
 @exported_as_webservice_entry(
-    singular_name='translation_group', plural_name='translation_groups')
+    singular_name="translation_group", plural_name="translation_groups",
+    as_of="beta")
 class ITranslationGroup(IHasOwner):
     """A TranslationGroup."""
 
diff --git a/lib/lp/translations/interfaces/translationimportqueue.py b/lib/lp/translations/interfaces/translationimportqueue.py
index 4a39b01..7b83a1d 100644
--- a/lib/lp/translations/interfaces/translationimportqueue.py
+++ b/lib/lp/translations/interfaces/translationimportqueue.py
@@ -19,6 +19,7 @@ from lazr.restful.declarations import (
     exported,
     exported_as_webservice_collection,
     exported_as_webservice_entry,
+    operation_for_version,
     operation_parameters,
     operation_returns_collection_of,
     operation_returns_entry,
@@ -119,8 +120,9 @@ class SpecialTranslationImportTargetFilter(DBEnumeratedType):
 
 
 @exported_as_webservice_entry(
-    singular_name='translation_import_queue_entry',
-    plural_name='translation_import_queue_entries')
+    singular_name="translation_import_queue_entry",
+    plural_name="translation_import_queue_entries",
+    as_of="beta")
 class ITranslationImportQueueEntry(Interface):
     """An entry of the Translation Import Queue."""
 
@@ -249,6 +251,7 @@ class ITranslationImportQueueEntry(Interface):
     @call_with(user=REQUEST_USER)
     @operation_parameters(new_status=copy_field(status))
     @export_write_operation()
+    @operation_for_version("beta")
     def setStatus(new_status, user):
         """Transition to a new status if possible.
 
@@ -363,6 +366,7 @@ class ITranslationImportQueue(Interface):
         import_status=copy_field(ITranslationImportQueueEntry['status']))
     @operation_returns_collection_of(ITranslationImportQueueEntry)
     @export_read_operation()
+    @operation_for_version("beta")
     def getAllEntries(target=None, import_status=None, file_extensions=None):
         """Return all entries this import queue has.
 
@@ -380,6 +384,7 @@ class ITranslationImportQueue(Interface):
     @export_read_operation()
     @operation_parameters(target=Reference(schema=IHasTranslationImports))
     @operation_returns_entry(ITranslationImportQueueEntry)
+    @operation_for_version("beta")
     def getFirstEntryToImport(target=None):
         """Return the first entry of the queue ready to be imported.
 
@@ -393,6 +398,7 @@ class ITranslationImportQueue(Interface):
         status=copy_field(ITranslationImportQueueEntry['status']))
     @operation_returns_collection_of(IHasTranslationImports)
     @call_with(user=REQUEST_USER)
+    @operation_for_version("beta")
     def getRequestTargets(user,  status=None):
         """List `Product`s and `DistroSeries` with pending imports.