launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #03053
[Merge] lp:~leonardr/launchpad/explicit-versions into lp:launchpad
Leonard Richardson has proposed merging lp:~leonardr/launchpad/explicit-versions into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~leonardr/launchpad/explicit-versions/+merge/54558
This branch makes four changes:
1. A tiny change to lib/canonical/launchpad/rest/configuration.py, to turn on explicit version enforcement. From now on, if you publish an entry, a field, or a named operation, you must use as_of (or, for named operations, @operation_for_version)
2. Two new helper methods in apihelpers.py: patch_entry_explicit_version and patch_operation_explicit_version. These helpers let us grandfather in entries and operations that were defined before we turned on explicit version enforcement. The exceptions raised by patch_operation_explicit_version were useful to me while getting everything working, and will be useful in the future as we fix the operations that are currently grandfathered in.
3. A huge number of calls to the helper methods added to _schema_circular_imports, grandfathering in almost all of the existing entries and named operations to version 'beta' of the web service.
4. A large number of changes to the published entries and operations, made in cases where it was easier to actually fix the entry/operation than to grandfather in the change to be fixed later.
#4 is the one that needs the most explanation. Here's one common idiom:
- vocabulary=ServiceUsage),
- ('devel', {'exported': True}),
- exported=False,
- )
+ vocabulary=ServiceUsage), as_of="devel")
This field is exported starting in the 'devel' version, and not before. With our configuration, lazr.restful now requires an explicit 'as_of' argument when exporting a field. As a bonus, as_of="devel" is equivalent to
"('devel', {'exported': True}), exported=False," so the syntax is now much nicer.
I added as_of="beta" to fix some entries that had some fields exported in beta and other fields exported in devel.
I added @operation_for_version('beta') to a large number of methods, rather than grandfathering them in in apihelpers.py. I did this for methods that were defined in mixin interfaces such as IHasBugs. This is an artifact of the fact that when I generated the code that's currently in apihelpers.py, it did not say this:
patch_operation_explicit_version(IHasBugs, "operation", "beta")
Instead, it said this:
patch_operation_explicit_version(IInterface1, "operation", "beta")
...
patch_operation_explicit_version(IInterface2, "operation", "beta")
...
patch_operation_explicit_version(IInterface3, "operation", "beta")
Where IInterface1, IInterface2, ... are the interfaces that mix in IHasBugs. Since I already had to determine that the mixin interface for this particular operation was IHasBugs, I went ahead and fixed the operation at the source, which let me get rid of all three lines.
--
https://code.launchpad.net/~leonardr/launchpad/explicit-versions/+merge/54558
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~leonardr/launchpad/explicit-versions into lp:launchpad.
=== modified file 'database/schema/security.cfg'
=== modified file 'lib/canonical/launchpad/components/apihelpers.py'
--- lib/canonical/launchpad/components/apihelpers.py 2011-01-28 10:03:12 +0000
+++ lib/canonical/launchpad/components/apihelpers.py 2011-03-23 16:18:44 +0000
@@ -24,6 +24,9 @@
'patch_reference_property',
]
+
+from zope.schema import getFields
+
from lazr.restful.declarations import LAZR_WEBSERVICE_EXPORTED
@@ -126,3 +129,53 @@
exported_class[method_name].queryTaggedValue(
LAZR_WEBSERVICE_EXPORTED)[
'params'][param_name].vocabulary = vocabulary
+
+
+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_operation_explicit_version(interface, method_name, version):
+ """Make it look like 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)
=== modified file 'lib/canonical/launchpad/icing/style-3-0.css'
=== modified file 'lib/canonical/launchpad/interfaces/_schema_circular_imports.py'
--- lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2011-03-10 14:05:51 +0000
+++ lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2011-03-23 16:18:44 +0000
@@ -23,8 +23,10 @@
patch_choice_vocabulary,
patch_collection_property,
patch_collection_return_type,
+ patch_entry_explicit_version,
patch_entry_return_type,
patch_list_parameter_type,
+ patch_operation_explicit_version,
patch_plain_parameter_type,
patch_reference_property,
)
@@ -33,6 +35,11 @@
IMessage,
IUserToUserEmail,
)
+from canonical.launchpad.interfaces.emailaddress import IEmailAddress
+from canonical.launchpad.interfaces.temporaryblobstorage import (
+ ITemporaryBlobStorage,
+ ITemporaryStorageManager,
+ )
from lp.blueprints.interfaces.specification import ISpecification
from lp.blueprints.interfaces.specificationbranch import ISpecificationBranch
from lp.blueprints.interfaces.specificationtarget import (
@@ -44,9 +51,12 @@
IBug,
IFrontPageBugAddForm,
)
+from lp.bugs.interfaces.bugactivity import IBugActivity
+from lp.bugs.interfaces.bugattachment import IBugAttachment
from lp.bugs.interfaces.bugbranch import IBugBranch
from lp.bugs.interfaces.bugnomination import IBugNomination
from lp.bugs.interfaces.bugsubscriptionfilter import IBugSubscriptionFilter
+from lp.bugs.interfaces.bugsubscription import IBugSubscription
from lp.bugs.interfaces.bugtarget import (
IBugTarget,
IHasBugs,
@@ -56,13 +66,28 @@
IBugTracker,
IBugTrackerComponent,
IBugTrackerComponentGroup,
+ IBugTrackerSet,
)
from lp.bugs.interfaces.bugwatch import IBugWatch
+from lp.bugs.interfaces.cve import ICve
+from lp.bugs.interfaces.malone import IMaloneApplication
+from lp.bugs.interfaces.structuralsubscription import (
+ IStructuralSubscription,
+ IStructuralSubscriptionTarget,
+ )
from lp.buildmaster.enums import BuildStatus
+from lp.buildmaster.interfaces.builder import (
+ IBuilder,
+ IBuilderSet,
+ )
from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJob
from lp.buildmaster.interfaces.buildqueue import IBuildQueue
-from lp.code.interfaces.branch import IBranch
+from lp.code.interfaces.branch import (
+ IBranch,
+ IBranchSet,
+ )
from lp.code.interfaces.branchmergeproposal import IBranchMergeProposal
+from lp.code.interfaces.branchmergequeue import IBranchMergeQueue
from lp.code.interfaces.branchsubscription import IBranchSubscription
from lp.code.interfaces.codeimport import ICodeImport
from lp.code.interfaces.codereviewcomment import ICodeReviewComment
@@ -81,43 +106,91 @@
)
from lp.hardwaredb.interfaces.hwdb import (
HWBus,
+ IHWDBApplication,
+ IHWDevice,
+ IHWDeviceClass,
+ IHWDriver,
+ IHWDriverName,
+ IHWDriverPackageName,
IHWSubmission,
+ IHWSubmissionDevice,
+ IHWVendorID,
)
+from lp.registry.interfaces.commercialsubscription import ICommercialSubscription
from lp.registry.interfaces.distribution import IDistribution
from lp.registry.interfaces.distributionmirror import IDistributionMirror
from lp.registry.interfaces.distributionsourcepackage import (
IDistributionSourcePackage,
)
from lp.registry.interfaces.distroseries import IDistroSeries
+from lp.registry.interfaces.distroseriesdifference import (
+ IDistroSeriesDifference,
+ )
from lp.registry.interfaces.distroseriesdifferencecomment import (
IDistroSeriesDifferenceComment,
)
+from lp.registry.interfaces.gpg import IGPGKey
+from lp.registry.interfaces.irc import IIrcID
+from lp.registry.interfaces.jabber import IJabberID
+from lp.registry.interfaces.milestone import IHasMilestones
+from lp.registry.interfaces.milestone import IMilestone
from lp.registry.interfaces.person import (
IPerson,
IPersonPublic,
+ IPersonSet,
+ ITeam,
+ )
+from lp.registry.interfaces.pillar import (
+ IPillar,
+ IPillarNameSet,
)
from lp.registry.interfaces.pocket import PackagePublishingPocket
-from lp.registry.interfaces.product import IProduct
-from lp.registry.interfaces.productseries import IProductSeries
+from lp.registry.interfaces.product import (
+ IProduct,
+ IProductSet,
+ )
+from lp.registry.interfaces.productrelease import IProductRelease
+from lp.registry.interfaces.productrelease import IProductReleaseFile
+from lp.registry.interfaces.productseries import (
+ IProductSeries,
+ ITimelineProductSeries,
+ )
+from lp.registry.interfaces.projectgroup import (
+ IProjectGroup,
+ IProjectGroupSet,
+ )
from lp.registry.interfaces.sourcepackage import ISourcePackage
-from lp.bugs.interfaces.structuralsubscription import (
- IStructuralSubscription,
- IStructuralSubscriptionTarget,
- )
+from lp.registry.interfaces.ssh import ISSHKey
+from lp.registry.interfaces.teammembership import ITeamMembership
+from lp.registry.interfaces.wikiname import IWikiName
from lp.services.comments.interfaces.conversation import IComment
+from lp.services.worlddata.interfaces.country import (
+ ICountry,
+ ICountrySet,
+ )
+from lp.services.worlddata.interfaces.language import (
+ ILanguage,
+ ILanguageSet,
+ )
from lp.soyuz.enums import (
PackagePublishingStatus,
PackageUploadCustomFormat,
PackageUploadStatus,
)
+from lp.soyuz.interfaces.archivedependency import IArchiveDependency
from lp.soyuz.interfaces.archive import IArchive
-from lp.soyuz.interfaces.archivedependency import IArchiveDependency
from lp.soyuz.interfaces.archivepermission import IArchivePermission
from lp.soyuz.interfaces.archivesubscriber import IArchiveSubscriber
from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuild
+from lp.soyuz.interfaces.binarypackagerelease import (
+ IBinaryPackageReleaseDownloadCount,
+ )
from lp.soyuz.interfaces.buildrecords import IHasBuildRecords
from lp.soyuz.interfaces.distroarchseries import IDistroArchSeries
-from lp.soyuz.interfaces.packageset import IPackageset
+from lp.soyuz.interfaces.packageset import (
+ IPackageset,
+ IPackagesetSet,
+ )
from lp.soyuz.interfaces.publishing import (
IBinaryPackagePublishingHistory,
ISourcePackagePublishingHistory,
@@ -137,11 +210,12 @@
IPOTemplateSharingSubset,
IPOTemplateSubset,
)
+from lp.translations.interfaces.translationgroup import ITranslationGroup
from lp.translations.interfaces.translationimportqueue import (
+ ITranslationImportQueue,
ITranslationImportQueueEntry,
)
-
IBranch['bug_branches'].value_type.schema = IBugBranch
IBranch['linked_bugs'].value_type.schema = IBug
IBranch['dependent_branches'].value_type.schema = IBranchMergeProposal
@@ -567,3 +641,276 @@
IHasSpecifications, 'all_specifications', ISpecification)
patch_collection_property(
IHasSpecifications, 'valid_specifications', ISpecification)
+
+
+###
+#
+# 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 entry statements to
+# its definition and get rid of the patch calls here.
+#
+###
+
+patch_entry_explicit_version(IArchive, 'beta')
+patch_entry_explicit_version(IArchiveDependency, 'beta')
+patch_entry_explicit_version(IArchivePermission, 'beta')
+patch_entry_explicit_version(IArchiveSubscriber, 'beta')
+patch_entry_explicit_version(IBinaryPackageBuild, 'beta')
+patch_entry_explicit_version(IBinaryPackagePublishingHistory, 'beta')
+patch_entry_explicit_version(IBinaryPackageReleaseDownloadCount, 'beta')
+patch_entry_explicit_version(IBranch, 'beta')
+patch_entry_explicit_version(IBranchMergeProposal, 'beta')
+patch_entry_explicit_version(IBranchMergeQueue, 'beta')
+patch_entry_explicit_version(IBranchSubscription, 'beta')
+patch_entry_explicit_version(IBugActivity, 'beta')
+patch_entry_explicit_version(IBugAttachment, 'beta')
+patch_entry_explicit_version(IBug, 'beta')
+patch_entry_explicit_version(IBugBranch, 'beta')
+patch_entry_explicit_version(IBugNomination, 'beta')
+patch_entry_explicit_version(IBugSubscriptionFilter, 'beta')
+patch_entry_explicit_version(IBugTarget, 'beta')
+patch_entry_explicit_version(IBugTask, 'beta')
+patch_entry_explicit_version(IBugTracker, 'beta')
+patch_entry_explicit_version(IBugTrackerComponent, 'beta')
+patch_entry_explicit_version(IBugTrackerComponentGroup, 'beta')
+patch_entry_explicit_version(IBugWatch, 'beta')
+patch_entry_explicit_version(IBuilder, 'beta')
+patch_entry_explicit_version(ICodeImport, 'beta')
+patch_entry_explicit_version(ICodeReviewComment, 'beta')
+patch_entry_explicit_version(ICodeReviewVoteReference, 'beta')
+patch_entry_explicit_version(ICommercialSubscription, 'beta')
+patch_entry_explicit_version(ICountry, 'beta')
+patch_entry_explicit_version(ICve, 'beta')
+patch_entry_explicit_version(IDistroSeries, 'beta')
+patch_entry_explicit_version(IDistroSeriesDifference, 'beta')
+patch_entry_explicit_version(IDistroSeriesDifferenceComment, 'beta')
+patch_entry_explicit_version(IDistributionMirror, 'beta')
+patch_entry_explicit_version(IDistributionSourcePackage, 'beta')
+patch_entry_explicit_version(IDistroArchSeries, 'beta')
+patch_entry_explicit_version(IEmailAddress, 'beta')
+patch_entry_explicit_version(IGPGKey, 'beta')
+patch_entry_explicit_version(IHasBugs, 'beta')
+patch_entry_explicit_version(IHasMilestones, 'beta')
+patch_entry_explicit_version(IHasTranslationImports, 'beta')
+patch_entry_explicit_version(IHWDBApplication, 'beta')
+patch_entry_explicit_version(IHWDevice, 'beta')
+patch_entry_explicit_version(IHWDeviceClass, 'beta')
+patch_entry_explicit_version(IHWDriver, 'beta')
+patch_entry_explicit_version(IHWDriverName, 'beta')
+patch_entry_explicit_version(IHWDriverPackageName, 'beta')
+patch_entry_explicit_version(IHWSubmission, 'beta')
+patch_entry_explicit_version(IHWSubmissionDevice, 'beta')
+patch_entry_explicit_version(IHWVendorID, 'beta')
+patch_entry_explicit_version(IIrcID, 'beta')
+patch_entry_explicit_version(IJabberID, 'beta')
+patch_entry_explicit_version(ILanguage, 'beta')
+patch_entry_explicit_version(IMessage, 'beta')
+patch_entry_explicit_version(IMilestone, 'beta')
+patch_entry_explicit_version(IPackageset, 'beta')
+patch_entry_explicit_version(IPackageUpload, 'beta')
+patch_entry_explicit_version(IPerson, 'beta')
+patch_entry_explicit_version(IPillar, 'beta')
+patch_entry_explicit_version(IPillarNameSet, 'beta')
+patch_entry_explicit_version(IPOFile, 'beta')
+patch_entry_explicit_version(IPOTemplate, 'beta')
+patch_entry_explicit_version(IPreviewDiff, 'beta')
+patch_entry_explicit_version(IProduct, 'beta')
+patch_entry_explicit_version(IProductRelease, 'beta')
+patch_entry_explicit_version(IProductReleaseFile, 'beta')
+patch_entry_explicit_version(IProductSeries, 'beta')
+patch_entry_explicit_version(IProjectGroup, 'beta')
+patch_entry_explicit_version(ISourcePackage, 'beta')
+patch_entry_explicit_version(ISourcePackagePublishingHistory, 'beta')
+patch_entry_explicit_version(ISourcePackageRecipe, 'beta')
+patch_entry_explicit_version(ISourcePackageRecipeBuild, 'beta')
+patch_entry_explicit_version(ISSHKey, 'beta')
+patch_entry_explicit_version(IStructuralSubscription, 'beta')
+patch_entry_explicit_version(IStructuralSubscriptionTarget, 'beta')
+patch_entry_explicit_version(ITeam, 'beta')
+patch_entry_explicit_version(ITeamMembership, 'beta')
+patch_entry_explicit_version(ITimelineProductSeries, 'beta')
+patch_entry_explicit_version(ITranslationGroup, 'beta')
+patch_entry_explicit_version(ITranslationImportQueueEntry, 'beta')
+patch_entry_explicit_version(IWikiName, 'beta')
+
+patch_operation_explicit_version(IArchive, "_checkUpload", "beta")
+patch_operation_explicit_version(IArchive, "deleteComponentUploader", "beta")
+patch_operation_explicit_version(IArchive, "deletePackageUploader", "beta")
+patch_operation_explicit_version(IArchive, "deletePackagesetUploader", "beta")
+patch_operation_explicit_version(IArchive, "deleteQueueAdmin", "beta")
+patch_operation_explicit_version(IArchive, "getAllPublishedBinaries", "beta")
+patch_operation_explicit_version(IArchive, "getArchiveDependency", "beta")
+patch_operation_explicit_version(IArchive, "getBuildCounters", "beta")
+patch_operation_explicit_version(IArchive, "getBuildSummariesForSourceIds", "beta")
+patch_operation_explicit_version(IArchive, "getComponentsForQueueAdmin", "beta")
+patch_operation_explicit_version(IArchive, "getPackagesetsForSource", "beta")
+patch_operation_explicit_version(IArchive, "getPackagesetsForSourceUploader", "beta")
+patch_operation_explicit_version(IArchive, "getPackagesetsForUploader", "beta")
+patch_operation_explicit_version(IArchive, "getPermissionsForPerson", "beta")
+patch_operation_explicit_version(IArchive, "getPublishedSources", "beta")
+patch_operation_explicit_version(IArchive, "getQueueAdminsForComponent", "beta")
+patch_operation_explicit_version(IArchive, "getUploadersForComponent", "beta")
+patch_operation_explicit_version(IArchive, "getUploadersForPackage", "beta")
+patch_operation_explicit_version(IArchive, "getUploadersForPackageset", "beta")
+patch_operation_explicit_version(IArchive, "isSourceUploadAllowed", "beta")
+patch_operation_explicit_version(IArchive, "newComponentUploader", "beta")
+patch_operation_explicit_version(IArchive, "newPackageUploader", "beta")
+patch_operation_explicit_version(IArchive, "newPackagesetUploader", "beta")
+patch_operation_explicit_version(IArchive, "newQueueAdmin", "beta")
+patch_operation_explicit_version(IArchive, "newSubscription", "beta")
+patch_operation_explicit_version(IArchive, "syncSource", "beta")
+patch_operation_explicit_version(IArchive, "syncSources", "beta")
+patch_operation_explicit_version(IBinaryPackageBuild, "rescore", "beta")
+patch_operation_explicit_version(IBinaryPackageBuild, "retry", "beta")
+patch_operation_explicit_version(IBinaryPackagePublishingHistory, "getDailyDownloadTotals", "beta")
+patch_operation_explicit_version(IBinaryPackagePublishingHistory, "getDownloadCount", "beta")
+patch_operation_explicit_version(IBinaryPackagePublishingHistory, "getDownloadCounts", "beta")
+patch_operation_explicit_version(IBranchMergeProposal, "createComment", "beta")
+patch_operation_explicit_version(IBranchMergeProposal, "getComment", "beta")
+patch_operation_explicit_version(IBranchMergeProposal, "nominateReviewer", "beta")
+patch_operation_explicit_version(IBranchMergeProposal, "setStatus", "beta")
+patch_operation_explicit_version(IBranchMergeProposal, "updatePreviewDiff", "beta")
+patch_operation_explicit_version(IBranchMergeQueue, "setMergeQueueConfig", "beta")
+patch_operation_explicit_version(IBranchSubscription, "canBeUnsubscribedByUser", "beta")
+patch_operation_explicit_version(IBug, "addAttachment", "beta")
+patch_operation_explicit_version(IBug, "addNomination", "beta")
+patch_operation_explicit_version(IBug, "addTask", "beta")
+patch_operation_explicit_version(IBug, "addWatch", "beta")
+patch_operation_explicit_version(IBug, "canBeNominatedFor", "beta")
+patch_operation_explicit_version(IBug, "getHWSubmissions", "beta")
+patch_operation_explicit_version(IBug, "getNominationFor", "beta")
+patch_operation_explicit_version(IBug, "getNominations", "beta")
+patch_operation_explicit_version(IBug, "isExpirable", "beta")
+patch_operation_explicit_version(IBug, "isUserAffected", "beta")
+patch_operation_explicit_version(IBug, "linkCVEAndReturnNothing", "beta")
+patch_operation_explicit_version(IBug, "linkHWSubmission", "beta")
+patch_operation_explicit_version(IBug, "markAsDuplicate", "beta")
+patch_operation_explicit_version(IBug, "markUserAffected", "beta")
+patch_operation_explicit_version(IBug, "newMessage", "beta")
+patch_operation_explicit_version(IBug, "setCommentVisibility", "beta")
+patch_operation_explicit_version(IBug, "setPrivate", "beta")
+patch_operation_explicit_version(IBug, "setSecurityRelated", "beta")
+patch_operation_explicit_version(IBug, "subscribe", "beta")
+patch_operation_explicit_version(IBug, "unlinkCVE", "beta")
+patch_operation_explicit_version(IBug, "unlinkHWSubmission", "beta")
+patch_operation_explicit_version(IBug, "unsubscribe", "beta")
+patch_operation_explicit_version(IBug, "unsubscribeFromDupes", "beta")
+patch_operation_explicit_version(IBugAttachment, "removeFromBug", "beta")
+patch_operation_explicit_version(IBugNomination, "approve", "beta")
+patch_operation_explicit_version(IBugNomination, "canApprove", "beta")
+patch_operation_explicit_version(IBugNomination, "decline", "beta")
+patch_operation_explicit_version(IBugSubscription, "canBeUnsubscribedByUser", "beta")
+patch_operation_explicit_version(IBugSubscriptionFilter, "delete", "beta")
+patch_operation_explicit_version(IBugTask, "findSimilarBugs", "beta")
+patch_operation_explicit_version(IBugTask, "transitionToAssignee", "beta")
+patch_operation_explicit_version(IBugTask, "transitionToImportance", "beta")
+patch_operation_explicit_version(IBugTask, "transitionToMilestone", "beta")
+patch_operation_explicit_version(IBugTask, "transitionToStatus", "beta")
+patch_operation_explicit_version(IBugTask, "transitionToTarget", "beta")
+patch_operation_explicit_version(IBugTracker, "addRemoteComponentGroup", "beta")
+patch_operation_explicit_version(IBugTracker, "getAllRemoteComponentGroups", "beta")
+patch_operation_explicit_version(IBugTracker, "getRemoteComponentGroup", "beta")
+patch_operation_explicit_version(IBugTrackerComponentGroup, "addComponent", "beta")
+patch_operation_explicit_version(IBugTrackerSet, "ensureBugTracker", "beta")
+patch_operation_explicit_version(IBugTrackerSet, "getByName", "beta")
+patch_operation_explicit_version(IBugTrackerSet, "queryByBaseURL", "beta")
+patch_operation_explicit_version(IBuilderSet, "getByName", "beta")
+patch_operation_explicit_version(ICodeImport, "requestImport", "beta")
+patch_operation_explicit_version(ICodeReviewVoteReference, "claimReview", "beta")
+patch_operation_explicit_version(ICodeReviewVoteReference, "delete", "beta")
+patch_operation_explicit_version(ICodeReviewVoteReference, "reassignReview", "beta")
+patch_operation_explicit_version(ICountrySet, "getByCode", "beta")
+patch_operation_explicit_version(ICountrySet, "getByName", "beta")
+patch_operation_explicit_version(IDistribution, "getArchive", "beta")
+patch_operation_explicit_version(IDistribution, "getCommercialPPAs", "beta")
+patch_operation_explicit_version(IDistribution, "getCountryMirror", "beta")
+patch_operation_explicit_version(IDistribution, "getDevelopmentSeries", "beta")
+patch_operation_explicit_version(IDistribution, "getMirrorByName", "beta")
+patch_operation_explicit_version(IDistribution, "getSeries", "beta")
+patch_operation_explicit_version(IDistribution, "getSourcePackage", "beta")
+patch_operation_explicit_version(IDistribution, "searchSourcePackages", "beta")
+patch_operation_explicit_version(IDistributionMirror, "canTransitionToCountryMirror", "beta")
+patch_operation_explicit_version(IDistributionMirror, "getOverallFreshness", "beta")
+patch_operation_explicit_version(IDistributionMirror, "isOfficial", "beta")
+patch_operation_explicit_version(IDistributionMirror, "transitionToCountryMirror", "beta")
+patch_operation_explicit_version(IDistributionSourcePackage, "bugtasks", "beta")
+patch_operation_explicit_version(IDistroSeries, "deriveDistroSeries", "beta")
+patch_operation_explicit_version(IDistroSeries, "getDerivedSeries", "beta")
+patch_operation_explicit_version(IDistroSeries, "getDistroArchSeries", "beta")
+patch_operation_explicit_version(IDistroSeries, "getPackageUploads", "beta")
+patch_operation_explicit_version(IDistroSeries, "getSourcePackage", "beta")
+patch_operation_explicit_version(IDistroSeries, "newMilestone", "beta")
+patch_operation_explicit_version(IDistroSeriesDifference, "addComment", "beta")
+patch_operation_explicit_version(IDistroSeriesDifference, "blacklist", "beta")
+patch_operation_explicit_version(IDistroSeriesDifference, "requestPackageDiffs", "beta")
+patch_operation_explicit_version(IDistroSeriesDifference, "unblacklist", "beta")
+patch_operation_explicit_version(IHWDBApplication, "deviceDriverOwnersAffectedByBugs", "beta")
+patch_operation_explicit_version(IHWDBApplication, "devices", "beta")
+patch_operation_explicit_version(IHWDBApplication, "drivers", "beta")
+patch_operation_explicit_version(IHWDBApplication, "hwInfoByBugRelatedUsers", "beta")
+patch_operation_explicit_version(IHWDBApplication, "numDevicesInSubmissions", "beta")
+patch_operation_explicit_version(IHWDBApplication, "numOwnersOfDevice", "beta")
+patch_operation_explicit_version(IHWDBApplication, "numSubmissionsWithDevice", "beta")
+patch_operation_explicit_version(IHWDBApplication, "vendorIDs", "beta")
+patch_operation_explicit_version(IHWDevice, "getOrCreateDeviceClass", "beta")
+patch_operation_explicit_version(IHWDevice, "getSubmissions", "beta")
+patch_operation_explicit_version(IHWDevice, "removeDeviceClass", "beta")
+patch_operation_explicit_version(IHWDeviceClass, "delete", "beta")
+patch_operation_explicit_version(IHWDriver, "getSubmissions", "beta")
+patch_operation_explicit_version(ILanguageSet, "getAllLanguages", "beta")
+patch_operation_explicit_version(IMaloneApplication, "createBug", "beta")
+patch_operation_explicit_version(IPackageset, "addSources", "beta")
+patch_operation_explicit_version(IPackageset, "addSubsets", "beta")
+patch_operation_explicit_version(IPackageset, "getSourcesIncluded", "beta")
+patch_operation_explicit_version(IPackageset, "getSourcesNotSharedBy", "beta")
+patch_operation_explicit_version(IPackageset, "getSourcesSharedBy", "beta")
+patch_operation_explicit_version(IPackageset, "relatedSets", "beta")
+patch_operation_explicit_version(IPackageset, "removeSources", "beta")
+patch_operation_explicit_version(IPackageset, "removeSubsets", "beta")
+patch_operation_explicit_version(IPackageset, "setsIncluded", "beta")
+patch_operation_explicit_version(IPackageset, "setsIncludedBy", "beta")
+patch_operation_explicit_version(IPackagesetSet, "getByName", "beta")
+patch_operation_explicit_version(IPackagesetSet, "new", "beta")
+patch_operation_explicit_version(IPackagesetSet, "setsIncludingSource", "beta")
+patch_operation_explicit_version(IPillarNameSet, "search", "beta")
+patch_operation_explicit_version(IProduct, "getRelease", "beta")
+patch_operation_explicit_version(IProduct, "getSeries", "beta")
+patch_operation_explicit_version(IProduct, "getTimeline", "beta")
+patch_operation_explicit_version(IProduct, "newSeries", "beta")
+patch_operation_explicit_version(IProductRelease, "destroySelf", "beta")
+patch_operation_explicit_version(IProductRelease, "addReleaseFile", "beta")
+patch_operation_explicit_version(IProductSeries, "getTimeline", "beta")
+patch_operation_explicit_version(IProductSeries, "newMilestone", "beta")
+patch_operation_explicit_version(IProductReleaseFile, "destroySelf", "beta")
+patch_operation_explicit_version(IProductSet, "createProduct", "beta")
+patch_operation_explicit_version(IProductSet, "forReview", "beta")
+patch_operation_explicit_version(IProductSet, "latest", "beta")
+patch_operation_explicit_version(IProductSet, "search", "beta")
+patch_operation_explicit_version(IProjectGroupSet, "search", "beta")
+patch_operation_explicit_version(ISourcePackage, "getBranch", "beta")
+patch_operation_explicit_version(ISourcePackage, "linkedBranches", "beta")
+patch_operation_explicit_version(ISourcePackage, "setBranch", "beta")
+patch_operation_explicit_version(ISourcePackagePublishingHistory, "api_requestDeletion", "beta")
+patch_operation_explicit_version(ISourcePackagePublishingHistory, "binaryFileUrls", "beta")
+patch_operation_explicit_version(ISourcePackagePublishingHistory, "changesFileUrl", "beta")
+patch_operation_explicit_version(ISourcePackagePublishingHistory, "getBuilds", "beta")
+patch_operation_explicit_version(ISourcePackagePublishingHistory, "getPublishedBinaries", "beta")
+patch_operation_explicit_version(ISourcePackagePublishingHistory, "packageDiffUrl", "beta")
+patch_operation_explicit_version(ISourcePackagePublishingHistory, "sourceFileUrls", "beta")
+patch_operation_explicit_version(ISourcePackageRecipe, "performDailyBuild", "beta")
+patch_operation_explicit_version(ISourcePackageRecipe, "requestBuild", "beta")
+patch_operation_explicit_version(ISourcePackageRecipe, "setRecipeText", "beta")
+patch_operation_explicit_version(IStructuralSubscription, "delete", "beta")
+patch_operation_explicit_version(IStructuralSubscription, "newBugFilter", "beta")
+patch_operation_explicit_version(ITeamMembership, "setExpirationDate", "beta")
+patch_operation_explicit_version(ITeamMembership, "setStatus", "beta")
+patch_operation_explicit_version(ITemporaryBlobStorage, "getProcessedData", "beta")
+patch_operation_explicit_version(ITemporaryBlobStorage, "hasBeenProcessed", "beta")
+patch_operation_explicit_version(ITemporaryStorageManager, "fetch", "beta")
+patch_operation_explicit_version(ITranslationImportQueue, "getAllEntries", "beta")
+patch_operation_explicit_version(ITranslationImportQueue, "getFirstEntryToImport", "beta")
+patch_operation_explicit_version(ITranslationImportQueue, "getRequestTargets", "beta")
+patch_operation_explicit_version(ITranslationImportQueueEntry, "setStatus", "beta")
=== modified file 'lib/canonical/launchpad/interfaces/temporaryblobstorage.py'
--- lib/canonical/launchpad/interfaces/temporaryblobstorage.py 2011-03-09 04:49:00 +0000
+++ lib/canonical/launchpad/interfaces/temporaryblobstorage.py 2011-03-23 16:18:44 +0000
@@ -47,11 +47,12 @@
class ITemporaryBlobStorage(Interface):
"""A blob which we will store in the database temporarily."""
export_as_webservice_entry(
- singular_name='temporary_blob', plural_name='temporary_blobs')
+ singular_name='temporary_blob', plural_name='temporary_blobs',
+ as_of="beta")
uuid = exported(
Text(title=_('UUID'), required=True, readonly=True),
- exported_as='token')
+ exported_as='token', as_of="beta")
blob = Bytes(title=_('BLOB'), required=True, readonly=True)
date_created = Datetime(title=_('Date created'),
required=True, readonly=True)
=== modified file 'lib/canonical/launchpad/rest/configuration.py'
--- lib/canonical/launchpad/rest/configuration.py 2010-12-13 18:04:24 +0000
+++ lib/canonical/launchpad/rest/configuration.py 2011-03-23 16:18:44 +0000
@@ -27,6 +27,7 @@
last_version_with_mutator_named_operations = "beta"
first_version_with_total_size_link = "devel"
view_permission = "launchpad.View"
+ require_explicit_versions = True
compensate_for_mod_compress_etag_modification = True
service_description = """The Launchpad web service allows automated
=== modified file 'lib/lp/app/interfaces/launchpad.py'
--- lib/lp/app/interfaces/launchpad.py 2011-03-07 19:05:44 +0000
+++ lib/lp/app/interfaces/launchpad.py 2011-03-23 16:18:44 +0000
@@ -50,10 +50,7 @@
title=_('Type of service for translations application'),
description=_("Where does this pillar do translations?"),
default=ServiceUsage.UNKNOWN,
- vocabulary=ServiceUsage),
- ('devel', {'exported': True}),
- exported=False,
- )
+ vocabulary=ServiceUsage), as_of="devel")
bug_tracking_usage = Choice(
title=_('Type of service for tracking bugs'),
description=_("Where does this pillar track bugs?"),
=== modified file 'lib/lp/blueprints/interfaces/specification.py'
--- lib/lp/blueprints/interfaces/specification.py 2011-03-08 22:45:14 +0000
+++ lib/lp/blueprints/interfaces/specification.py 2011-03-23 16:18:44 +0000
@@ -144,28 +144,29 @@
"May contain lower-case letters, numbers, and dashes. "
"It will be used in the specification url. "
"Examples: mozilla-type-ahead-find, postgres-smart-serial.")),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
title = exported(
Title(
title=_('Title'), required=True, description=_(
"Describe the feature as clearly as possible in up to 70 "
"characters. This title is displayed in every feature "
"list or report.")),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
specurl = exported(
SpecURLField(
title=_('Specification URL'), required=False,
description=_(
"The URL of the specification. This is usually a wiki page."),
constraint=valid_webref),
- ('devel', dict(exported=True, exported_as='specification_url')),
- exported=False)
+ exported_as="specification_url",
+ as_of="devel",
+ )
summary = exported(
Summary(
title=_('Summary'), required=True, description=_(
"A single-paragraph description of the feature. "
"This will also be displayed in most feature listings.")),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
definition_status = exported(
Choice(
@@ -175,7 +176,7 @@
description=_(
"The current status of the process to define the "
"feature and get approval for the implementation plan.")),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
assignee = exported(
PublicPersonChoice(
@@ -183,14 +184,14 @@
description=_(
"The person responsible for implementing the feature."),
vocabulary='ValidPersonOrTeam'),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
drafter = exported(
PublicPersonChoice(
title=_('Drafter'), required=False,
description=_(
"The person responsible for drafting the specification."),
vocabulary='ValidPersonOrTeam'),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
approver = exported(
PublicPersonChoice(
title=_('Approver'), required=False,
@@ -198,23 +199,24 @@
"The person responsible for approving the specification, "
"and for reviewing the code when it's ready to be landed."),
vocabulary='ValidPersonOrTeam'),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
priority = exported(
Choice(
title=_('Priority'), vocabulary=SpecificationPriority,
default=SpecificationPriority.UNDEFINED, required=True),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
datecreated = exported(
Datetime(
title=_('Date Created'), required=True, readonly=True),
- ('devel', dict(exported=True, exported_as='date_created')),
- exported=False)
+ as_of="devel",
+ exported_as="date_created",
+ )
owner = exported(
PublicPersonChoice(
title=_('Owner'), required=True, readonly=True,
vocabulary='ValidPersonOrTeam'),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
product = Choice(title=_('Project'), required=False,
vocabulary='Product')
@@ -229,7 +231,9 @@
description=_(
"The project for which this proposal is being made."),
schema=ISpecificationTarget),
- ('devel', dict(exported=True, readonly=True)), exported=False)
+ as_of="devel",
+ readonly=True,
+ )
productseries = Choice(
title=_('Series Goal'), required=False,
@@ -252,7 +256,7 @@
"The milestone in which we would like this feature to be "
"delivered."),
schema=IMilestone),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
# nomination to a series for release management
# XXX: It'd be nice to export goal as read-only, but it's tricky because
@@ -277,7 +281,7 @@
description=_(
"Any notes on the status of this spec you would like to "
"make. Your changes will override the current text.")),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
direction_approved = exported(
Bool(title=_('Basic direction approved?'),
required=True, default=False,
@@ -285,7 +289,7 @@
"Check this to indicate that the drafter and assignee "
"have satisfied the approver that they are headed in "
"the right basic direction with this specification.")),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
man_days = Int(title=_("Estimated Developer Days"),
required=False, default=None, description=_("An estimate of the "
"number of developer days it will take to implement this feature. "
@@ -299,7 +303,7 @@
description=_(
"The state of progress being made on the actual "
"implementation or delivery of this feature.")),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
superseded_by = Choice(title=_("Superseded by"),
required=False, default=None,
vocabulary='Specification', description=_("The specification "
@@ -315,12 +319,12 @@
'The person who first set the state of the '
'spec to the values that we consider mark it as started.'),
vocabulary='ValidPersonOrTeam'),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
date_started = exported(
Datetime(
title=_('Date Started'), required=False, readonly=True,
description=_('The date when this spec was marked started.')),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
completer = exported(
PublicPersonChoice(
@@ -329,7 +333,7 @@
'The person who finally set the state of the '
'spec to the values that we consider mark it as complete.'),
vocabulary='ValidPersonOrTeam'),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
date_completed = exported(
Datetime(
@@ -339,7 +343,7 @@
'complete. Note that complete also includes "obsolete" and '
'superseded. Essentially, it is the state where no more work '
'will be done on the feature.')),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
# joins
subscriptions = Attribute('The set of subscriptions to this spec.')
@@ -352,7 +356,7 @@
title=_('Specs on which this one depends.'),
value_type=Reference(schema=Interface), # ISpecification, really.
readonly=True),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
blocked_specs = Attribute('Specs for which this spec is a dependency.')
all_deps = Attribute(
"All the dependencies, including dependencies of dependencies.")
@@ -364,7 +368,7 @@
"branches on which this spec is being implemented."),
value_type=Reference(schema=Interface), # ISpecificationBranch
readonly=True),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
# emergent properties
informational = Attribute('Is True if this spec is purely informational '
@@ -379,7 +383,7 @@
'code to be written. It is also true of obsolete and '
'superseded specs, since there is no longer any need '
'to schedule work for them.')),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
is_incomplete = Attribute('Is True if this work still needs to '
'be done. Is in fact always the opposite of is_complete.')
@@ -393,7 +397,7 @@
'we consider to be "started". This looks at the delivery '
'attribute, and also considers informational specs to be '
'started when they are approved.')),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
lifecycle_status = exported(
Choice(
@@ -401,7 +405,7 @@
vocabulary=SpecificationLifecycleStatus,
default=SpecificationLifecycleStatus.NOTSTARTED,
readonly=True),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
def validateMove(target):
"""Check that the specification can be moved to the target."""
@@ -548,7 +552,7 @@
IBugLinkTarget):
"""A Specification."""
- export_as_webservice_entry()
+ export_as_webservice_entry(as_of="devel")
class ISpecificationSet(IHasSpecifications):
=== modified file 'lib/lp/blueprints/interfaces/specificationbranch.py'
--- lib/lp/blueprints/interfaces/specificationbranch.py 2010-09-26 22:47:58 +0000
+++ lib/lp/blueprints/interfaces/specificationbranch.py 2011-03-23 16:18:44 +0000
@@ -17,6 +17,7 @@
export_operation_as,
export_write_operation,
exported,
+ operation_for_version,
)
from lazr.restful.fields import (
Reference,
@@ -35,28 +36,30 @@
class ISpecificationBranch(IHasDateCreated):
"""A branch linked to a specification."""
- export_as_webservice_entry()
+ export_as_webservice_entry(as_of="devel")
id = Int(title=_("Specification Branch #"))
specification = exported(
ReferenceChoice(
title=_("Blueprint"), vocabulary="Specification",
required=True,
- readonly=True, schema=ISpecification))
+ readonly=True, schema=ISpecification), as_of="devel")
branch = exported(
ReferenceChoice(
title=_("Branch"),
vocabulary="Branch",
required=True,
- schema=IBranch))
+ schema=IBranch), as_of="devel")
registrant = exported(
Reference(
schema=IPerson, readonly=True, required=True,
- title=_("The person who linked the bug to the branch")))
+ title=_("The person who linked the bug to the branch")),
+ as_of="devel")
@export_operation_as('delete')
@export_write_operation()
+ @operation_for_version('devel')
def destroySelf():
"""Destroy this specification branch link"""
=== modified file 'lib/lp/blueprints/interfaces/specificationtarget.py'
--- lib/lp/blueprints/interfaces/specificationtarget.py 2011-01-11 19:37:03 +0000
+++ lib/lp/blueprints/interfaces/specificationtarget.py 2011-03-23 16:18:44 +0000
@@ -51,7 +51,7 @@
description=_(
'A list of all specifications, regardless of status or '
'approval or completion, for this object.'))),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
has_any_specifications = Attribute(
'A true or false indicator of whether or not this object has any '
@@ -66,7 +66,7 @@
'All specifications that are not obsolete. When called from '
'an ISpecificationGoal it will also exclude the ones that '
'have not been accepted for that goal'))),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
latest_specifications = Attribute(
"The latest 5 specifications registered for this context.")
@@ -99,7 +99,7 @@
specifications directly attached to them.
"""
- export_as_webservice_entry()
+ export_as_webservice_entry(as_of="devel")
@operation_parameters(
name=TextLine(title=_('The name of the specification')))
=== modified file 'lib/lp/bugs/browser/bug.py'
--- lib/lp/bugs/browser/bug.py 2011-03-21 11:39:26 +0000
+++ lib/lp/bugs/browser/bug.py 2011-03-23 16:18:44 +0000
@@ -284,7 +284,11 @@
link = "+mute"
return Link(
+<<<<<<< TREE
link, text, icon='remove', summary=(
+=======
+ '+mute', text, icon='remove', summary=(
+>>>>>>> MERGE-SOURCE
"Mute this bug so that you will never receive emails "
"about it."))
=== modified file 'lib/lp/bugs/browser/bugalsoaffects.py'
=== modified file 'lib/lp/bugs/browser/bugtask.py'
=== modified file 'lib/lp/bugs/browser/tests/test_bugtask.py'
--- lib/lp/bugs/browser/tests/test_bugtask.py 2011-03-21 21:36:55 +0000
+++ lib/lp/bugs/browser/tests/test_bugtask.py 2011-03-23 16:18:44 +0000
@@ -545,6 +545,7 @@
view.form_fields['assignee'].field.vocabularyName)
+<<<<<<< TREE
class TestBugTaskEditView(TestCaseWithFactory):
"""Test the bug task edit form."""
@@ -642,6 +643,46 @@
self.assertTrue(notifications.pop().message.startswith(expected))
+=======
+class TestBugTaskEditView(TestCaseWithFactory):
+ """Test the bugs overview page for Project Groups."""
+
+ layer = DatabaseFunctionalLayer
+
+ def test_retarget_already_exists_error(self):
+ user = self.factory.makePerson()
+ login_person(user)
+ ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
+ dsp_1 = self.factory.makeDistributionSourcePackage(
+ distribution=ubuntu, sourcepackagename='mouse')
+ ignore = self.factory.makeSourcePackagePublishingHistory(
+ distroseries=ubuntu.currentseries,
+ sourcepackagename=dsp_1.sourcepackagename)
+ bug_task_1 = self.factory.makeBugTask(target=dsp_1)
+ dsp_2 = self.factory.makeDistributionSourcePackage(
+ distribution=ubuntu, sourcepackagename='rabbit')
+ ignore = self.factory.makeSourcePackagePublishingHistory(
+ distroseries=ubuntu.currentseries,
+ sourcepackagename=dsp_2.sourcepackagename)
+ bug_task_2 = self.factory.makeBugTask(
+ bug=bug_task_1.bug, target=dsp_2)
+ form = {
+ 'ubuntu_rabbit.actions.save': 'Save Changes',
+ 'ubuntu_rabbit.status': 'In Progress',
+ 'ubuntu_rabbit.importance': 'High',
+ 'ubuntu_rabbit.assignee.option':
+ 'ubuntu_rabbit.assignee.assign_to_nobody',
+ 'ubuntu_rabbit.sourcepackagename': 'mouse',
+ }
+ view = create_initialized_view(
+ bug_task_2, name='+editstatus', form=form, principal=user)
+ self.assertEqual(1, len(view.errors))
+ self.assertEqual(
+ 'This bug has already been reported on mouse (ubuntu).',
+ view.errors[0])
+
+
+>>>>>>> MERGE-SOURCE
class TestProjectGroupBugs(TestCaseWithFactory):
"""Test the bugs overview page for Project Groups."""
=== modified file 'lib/lp/bugs/interfaces/buglink.py'
--- lib/lp/bugs/interfaces/buglink.py 2010-12-02 15:13:58 +0000
+++ lib/lp/bugs/interfaces/buglink.py 2011-03-23 16:18:44 +0000
@@ -60,11 +60,11 @@
Examples include an ISpecification.
"""
- export_as_webservice_entry()
+ export_as_webservice_entry(as_of="beta")
bugs = exported(CollectionField(title=_("Bugs related to this object."),
value_type=Reference(schema=IBug), readonly=True),
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
bug_links = List(title=_("The links between bugs and this object."),
value_type=Object(schema=IBugLink), readonly=True)
=== modified file 'lib/lp/bugs/interfaces/bugsubscription.py'
--- lib/lp/bugs/interfaces/bugsubscription.py 2011-02-04 06:30:13 +0000
+++ lib/lp/bugs/interfaces/bugsubscription.py 2011-03-23 16:18:44 +0000
@@ -39,15 +39,15 @@
class IBugSubscription(Interface):
"""The relationship between a person and a bug."""
- export_as_webservice_entry(publish_web_link=False)
+ export_as_webservice_entry(publish_web_link=False, as_of="beta")
id = Int(title=_('ID'), readonly=True, required=True)
person = exported(PersonChoice(
title=_('Person'), required=True, vocabulary='ValidPersonOrTeam',
readonly=True, description=_("The person's Launchpad ID or "
- "e-mail address.")))
+ "e-mail address.")), as_of="beta")
bug = exported(Reference(
- IBug, title=_("Bug"), required=True, readonly=True))
+ IBug, title=_("Bug"), required=True, readonly=True), as_of="beta")
# We mark this as doNotSnapshot() because it's a magically-generated
# Storm attribute and it causes Snapshot to break.
bugID = doNotSnapshot(Int(title=u"The bug id.", readonly=True))
@@ -60,15 +60,15 @@
"The volume and type of bug notifications "
"this subscription will generate."),
),
- # We want this field to be exported in the devel version of the
- # API only.
- ('devel', dict(exported=True)), exported=False)
+ as_of="devel")
date_created = exported(
- Datetime(title=_('Date subscribed'), required=True, readonly=True))
+ Datetime(title=_('Date subscribed'), required=True, readonly=True),
+ as_of="beta")
subscribed_by = exported(PersonChoice(
title=_('Subscribed by'), required=True,
vocabulary='ValidPersonOrTeam', readonly=True,
- description=_("The person who created this subscription.")))
+ description=_("The person who created this subscription.")),
+ as_of="beta")
display_subscribed_by = Attribute(
"`subscribed_by` formatted for display.")
=== modified file 'lib/lp/bugs/interfaces/bugsupervisor.py'
--- lib/lp/bugs/interfaces/bugsupervisor.py 2011-01-25 21:30:49 +0000
+++ lib/lp/bugs/interfaces/bugsupervisor.py 2011-03-23 16:18:44 +0000
@@ -16,6 +16,7 @@
export_write_operation,
exported,
mutator_for,
+ operation_for_version,
operation_parameters,
REQUEST_USER,
)
@@ -43,5 +44,6 @@
@operation_parameters(
bug_supervisor=copy_field(bug_supervisor))
@export_write_operation()
+ @operation_for_version('beta')
def setBugSupervisor(bug_supervisor, user):
"""Set the bug contact and create a bug subscription."""
=== modified file 'lib/lp/bugs/interfaces/bugtarget.py'
--- lib/lp/bugs/interfaces/bugtarget.py 2011-01-31 13:05:20 +0000
+++ lib/lp/bugs/interfaces/bugtarget.py 2011-03-23 16:18:44 +0000
@@ -28,6 +28,7 @@
export_write_operation,
exported,
LAZR_WEBSERVICE_EXPORTED,
+ operation_for_version,
operation_parameters,
operation_removed_in_version,
operation_returns_collection_of,
@@ -229,7 +230,7 @@
@operation_parameters(**search_tasks_params_for_api_default)
@operation_returns_collection_of(IBugTask)
@export_read_operation()
-
+ @operation_for_version('beta')
def searchTasks(search_params, user=None,
order_by=None, search_text=None,
status=None, importance=None,
@@ -417,12 +418,14 @@
@operation_parameters(
tag=Tag(title=u'The official bug tag', required=True))
@export_write_operation()
+ @operation_for_version('beta')
def addOfficialBugTag(tag):
"""Add tag to the official bug tags of this target."""
@operation_parameters(
tag=Tag(title=u'The official bug tag', required=True))
@export_write_operation()
+ @operation_for_version('beta')
def removeOfficialBugTag(tag):
"""Remove tag from the official bug tags of this target."""
=== modified file 'lib/lp/bugs/interfaces/structuralsubscription.py'
--- lib/lp/bugs/interfaces/structuralsubscription.py 2011-03-07 15:39:27 +0000
+++ lib/lp/bugs/interfaces/structuralsubscription.py 2011-03-23 16:18:44 +0000
@@ -22,6 +22,7 @@
export_read_operation,
export_write_operation,
exported,
+ operation_for_version,
operation_parameters,
operation_returns_collection_of,
operation_returns_entry,
@@ -115,6 +116,7 @@
@operation_returns_collection_of(IStructuralSubscription)
@export_read_operation()
+ @operation_for_version('beta')
def getSubscriptions():
"""Return all the subscriptions with the specified levels.
@@ -136,6 +138,7 @@
@operation_parameters(person=Reference(schema=IPerson))
@operation_returns_entry(IStructuralSubscription)
@export_read_operation()
+ @operation_for_version('beta')
def getSubscription(person):
"""Return the subscription for `person`, if it exists."""
@@ -172,6 +175,7 @@
required=False))
@call_with(subscribed_by=REQUEST_USER)
@export_factory_operation(IStructuralSubscription, [])
+ @operation_for_version('beta')
def addBugSubscription(subscriber, subscribed_by):
"""Add a bug subscription for this structure.
@@ -194,6 +198,7 @@
required=False))
@call_with(unsubscribed_by=REQUEST_USER)
@export_write_operation()
+ @operation_for_version('beta')
def removeBugSubscription(subscriber, unsubscribed_by):
"""Remove a subscription to bugs from this structure.
=== modified file 'lib/lp/bugs/javascript/bugtask_index_portlets.js'
--- lib/lp/bugs/javascript/bugtask_index_portlets.js 2011-03-21 11:42:33 +0000
+++ lib/lp/bugs/javascript/bugtask_index_portlets.js 2011-03-23 16:18:44 +0000
@@ -285,9 +285,15 @@
mute_link.addClass('js-action');
mute_link.on('click', function(e) {
e.halt();
+<<<<<<< TREE
var is_muted = parent_node.hasClass('muted-true');
if (! is_muted) {
mute_subscription.enable_spinner('Muting...');
+=======
+ var is_muted = parent_node.hasClass('muted-true');
+ mute_subscription.enable_spinner('Muting...');
+ if (! is_muted) {
+>>>>>>> MERGE-SOURCE
mute_current_user(mute_subscription);
} else {
var unmute_overlay = setup_advanced_subscription_overlay(
@@ -298,6 +304,7 @@
});
}
+<<<<<<< TREE
/*
* Update the Mute link after the user's subscriptions or mutes have
* changed.
@@ -321,6 +328,22 @@
mute_subscription.disable_spinner("Mute bug mail");
}
}
+=======
+/*
+ * Update the Mute link after the user's subscriptions or mutes have
+ * changed.
+ */
+function update_mute_after_subscription_change(mute_subscription) {
+ var parent_node = mute_subscription.get('link').get('parentNode');
+ if (mute_subscription.get('is_muted')) {
+ parent_node.removeClass('muted-false');
+ parent_node.addClass('muted-true');
+ } else {
+ parent_node.removeClass('muted-true');
+ parent_node.addClass('muted-false');
+ }
+}
+>>>>>>> MERGE-SOURCE
/*
* Update the subscription links after the mute button has been clicked.
@@ -368,6 +391,7 @@
'link').get('parentNode').hasClass('dup-subscribed-true');
subscription.set('is_direct', is_direct);
subscription.set('has_dupes', has_dupes);
+<<<<<<< TREE
subscription.set('can_be_unsubscribed', true);
subscription.set('person', subscription.get('subscriber'));
subscription.set('is_team', false);
@@ -385,6 +409,22 @@
}
var subscription = get_subscribe_self_subscription();
+=======
+ return subscription;
+}
+
+/*
+ * Initialize callbacks for subscribe/unsubscribe links.
+ *
+ * @method setup_subscription_link_handlers
+ */
+function setup_subscription_link_handlers() {
+ if (LP.links.me === undefined) {
+ return;
+ }
+
+ var subscription = get_subscribe_self_subscription();
+>>>>>>> MERGE-SOURCE
var subscription_overlay;
if (namespace.use_advanced_subscriptions) {
subscription_overlay = setup_advanced_subscription_overlay(
@@ -648,8 +688,13 @@
'link').get('href') + '/++form++';
subscription_overlay.set(
'form_submit_callback', function(form_data) {
+<<<<<<< TREE
handle_advanced_subscription_overlay(form_data);
Y.lp.bugs.bug_subscription.clean_up_level_div();
+=======
+ handle_advanced_subscription_overlay(subscription, form_data);
+ Y.lp.bugs.bug_subscription.clean_up_level_div();
+>>>>>>> MERGE-SOURCE
subscription_overlay.hide();
});
=== modified file 'lib/lp/bugs/model/bug.py'
=== modified file 'lib/lp/bugs/model/bugtask.py'
=== modified file 'lib/lp/buildmaster/interfaces/buildfarmjob.py'
--- lib/lp/buildmaster/interfaces/buildfarmjob.py 2010-10-04 21:44:32 +0000
+++ lib/lp/buildmaster/interfaces/buildfarmjob.py 2011-03-23 16:18:44 +0000
@@ -172,7 +172,9 @@
title=_("Date created"), required=True, readonly=True,
description=_(
"The timestamp when the build farm job was created.")),
- ("1.0", dict(exported=True, exported_as="datecreated")))
+ ("1.0", dict(exported_as="datecreated")),
+ as_of="beta",
+ )
date_started = Datetime(
title=_("Date started"), required=False, readonly=True,
@@ -183,7 +185,9 @@
title=_("Date finished"), required=False, readonly=True,
description=_(
"The timestamp when the build farm job was finished.")),
- ("1.0", dict(exported=True, exported_as="datebuilt")))
+ ("1.0", dict(exported_as="datebuilt")),
+ as_of="beta",
+ )
duration = Timedelta(
title=_("Duration"), required=False,
@@ -214,7 +218,9 @@
# _schema_circular_imports.py
vocabulary=DBEnumeratedType,
description=_("The current status of the job.")),
- ("1.0", dict(exported=True, exported_as="buildstate")))
+ ("1.0", dict(exported_as="buildstate")),
+ as_of="beta",
+ )
log = Reference(
schema=ILibraryFileAlias, required=False,
@@ -226,7 +232,9 @@
title=_("Build Log URL"), required=False,
description=_("A URL for the build log. None if there is no "
"log available.")),
- ("1.0", dict(exported=True, exported_as="build_log_url")))
+ ("1.0", dict(exported_as="build_log_url")),
+ as_of="beta",
+ )
is_private = Bool(
title=_("is private"), required=False, readonly=True,
@@ -252,7 +260,8 @@
def gotFailure():
"""Increment the failure_count for this job."""
- title = exported(TextLine(title=_("Title"), required=False))
+ title = exported(TextLine(title=_("Title"), required=False),
+ as_of="beta")
was_built = Attribute("Whether or not modified by the builddfarm.")
@@ -263,7 +272,8 @@
title=_('Dependencies'), required=False,
description=_(
'Debian-like dependency line that must be satisfied before '
- 'attempting to build this request.')))
+ 'attempting to build this request.')),
+ as_of="beta")
class ISpecificBuildFarmJob(IBuildFarmJob):
=== modified file 'lib/lp/code/browser/sourcepackagerecipe.py'
=== modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipe.py'
--- lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2011-03-21 21:30:07 +0000
+++ lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2011-03-23 16:18:44 +0000
@@ -785,6 +785,7 @@
self.assertThat(
'PPA 2', MatchesPickerText(content, 'edit-daily_build_archive'))
+<<<<<<< TREE
def test_edit_recipe_sets_date_last_modified(self):
"""Editing a recipe sets the date_last_modified property."""
date_created = datetime(2000, 1, 1, 12, tzinfo=UTC)
@@ -801,6 +802,24 @@
self.assertSqlAttributeEqualsDate(
recipe, 'date_last_modified', UTC_NOW)
+=======
+ def test_edit_recipe_sets_date_last_modified(self):
+ """Editing a recipe sets the date_last_modified property."""
+ date_created = datetime(2000, 1, 1, 12, tzinfo=UTC)
+ recipe = self.factory.makeSourcePackageRecipe(
+ owner=self.chef, date_created=date_created)
+
+ login_person(self.chef)
+ view = SourcePackageRecipeEditView(recipe, LaunchpadTestRequest())
+ view.initialize()
+ view.request_action.success({
+ 'name': u'fings',
+ 'recipe_text': recipe.recipe_text,
+ 'distros': recipe.distroseries})
+ self.assertSqlAttributeEqualsDate(
+ recipe, 'date_last_modified', UTC_NOW)
+
+>>>>>>> MERGE-SOURCE
def test_admin_edit(self):
self.factory.makeDistroSeries(
displayname='Mumbly Midget', name='mumbly',
=== modified file 'lib/lp/code/configure.zcml'
=== modified file 'lib/lp/code/interfaces/branch.py'
--- lib/lp/code/interfaces/branch.py 2011-03-22 00:18:47 +0000
+++ lib/lp/code/interfaces/branch.py 2011-03-23 16:18:44 +0000
@@ -38,6 +38,7 @@
export_write_operation,
exported,
mutator_for,
+ operation_for_version,
operation_parameters,
operation_returns_collection_of,
operation_returns_entry,
@@ -261,6 +262,7 @@
@operation_parameters(
scheme=TextLine(title=_("URL scheme"), default=u'http'))
@export_read_operation()
+ @operation_for_version('beta')
def composePublicURL(scheme='http'):
"""Return a public URL for the branch using the given protocol.
@@ -348,6 +350,7 @@
title=_("A person for which the reviewer status is in question."),
schema=IPerson))
@export_read_operation()
+ @operation_for_version('beta')
def isPersonTrustedReviewer(reviewer):
"""Return true if the `reviewer` is a trusted reviewer.
@@ -424,6 +427,7 @@
@operation_parameters(
bug=Reference(schema=Interface)) # Really IBug
@export_write_operation()
+ @operation_for_version('beta')
def linkBug(bug, registrant):
"""Link a bug to this branch.
@@ -435,6 +439,7 @@
@operation_parameters(
bug=Reference(schema=Interface)) # Really IBug
@export_write_operation()
+ @operation_for_version('beta')
def unlinkBug(bug, user):
"""Unlink a bug to this branch.
@@ -447,12 +452,14 @@
CollectionField(
title=_("Specification linked to this branch."),
readonly=True,
- value_type=Reference(Interface))) # Really ISpecificationBranch
+ value_type=Reference(Interface)), # Really ISpecificationBranch
+ as_of="devel")
@call_with(registrant=REQUEST_USER)
@operation_parameters(
spec=Reference(schema=Interface)) # Really ISpecification
@export_write_operation()
+ @operation_for_version('devel')
def linkSpecification(spec, registrant):
"""Link an ISpecification to a branch.
@@ -464,6 +471,7 @@
@operation_parameters(
spec=Reference(schema=Interface)) # Really ISpecification
@export_write_operation()
+ @operation_for_version('devel')
def unlinkSpecification(spec, user):
"""Unlink an ISpecification to a branch.
@@ -557,6 +565,7 @@
@call_with(registrant=REQUEST_USER)
# IBranchMergeProposal supplied as Interface to avoid circular imports.
@export_factory_operation(Interface, [])
+ @operation_for_version('beta')
def _createMergeProposal(
registrant, target_branch, prerequisite_branch=None,
needs_review=True, initial_comment=None, commit_message=None,
@@ -604,6 +613,7 @@
@call_with(visible_by_user=REQUEST_USER)
@operation_returns_collection_of(Interface) # Really IBranchMergeProposal.
@export_read_operation()
+ @operation_for_version('beta')
def getMergeProposals(status=None, visible_by_user=None,
merged_revnos=None):
"""Return matching BranchMergeProposals."""
@@ -672,6 +682,7 @@
"""
@export_read_operation()
+ @operation_for_version('beta')
def canBeDeleted():
"""Can this branch be deleted in its current state.
@@ -760,6 +771,7 @@
@operation_returns_entry(Interface) # Really IBranchSubscription
@call_with(subscribed_by=REQUEST_USER)
@export_write_operation()
+ @operation_for_version('beta')
def subscribe(person, notification_level, max_diff_lines,
code_review_level, subscribed_by):
"""Subscribe this person to the branch.
@@ -781,6 +793,7 @@
schema=IPerson))
@operation_returns_entry(Interface) # Really IBranchSubscription
@export_read_operation()
+ @operation_for_version('beta')
def getSubscription(person):
"""Return the BranchSubscription for this person."""
@@ -793,6 +806,7 @@
schema=IPerson))
@call_with(unsubscribed_by=REQUEST_USER)
@export_write_operation()
+ @operation_for_version('beta')
def unsubscribe(person, unsubscribed_by):
"""Remove the person's subscription to this branch.
@@ -899,6 +913,7 @@
"""Return the URL used to pull the branch into the mirror area."""
@export_write_operation()
+ @operation_for_version('beta')
def requestMirror():
"""Request that this branch be mirrored on the next run of the branch
puller.
@@ -1026,6 +1041,7 @@
title=_("The new owner of the branch."),
schema=IPerson))
@export_write_operation()
+ @operation_for_version('beta')
def setOwner(new_owner, user):
"""Set the owner of the branch to be `new_owner`."""
@@ -1038,6 +1054,7 @@
title=_("The source package the branch belongs to."),
schema=Interface, required=False)) # Really ISourcePackage
@export_write_operation()
+ @operation_for_version('beta')
def setTarget(user, project=None, source_package=None):
"""Set the target of the branch to be `project` or `source_package`.
@@ -1071,6 +1088,7 @@
"""
@export_destructor_operation()
+ @operation_for_version('beta')
def destroySelfBreakReferences():
"""Delete the specified branch.
@@ -1113,6 +1131,7 @@
queue=Reference(title=_('Branch Merge Queue'),
schema=IBranchMergeQueue))
@export_write_operation()
+ @operation_for_version('beta')
def addToQueue(queue):
"""Add this branch to a specified queue.
@@ -1125,6 +1144,7 @@
@operation_parameters(
config=TextLine(title=_("A JSON string of config values.")))
@export_write_operation()
+ @operation_for_version('beta')
def setMergeQueueConfig(config):
"""Set the merge_queue_config property.
@@ -1156,6 +1176,7 @@
@operation_parameters(
private=Bool(title=_("Keep branch confidential")))
@export_write_operation()
+ @operation_for_version('beta')
def setPrivate(private, user):
"""Set the branch privacy for this branch."""
@@ -1239,6 +1260,7 @@
unique_name=TextLine(title=_('Branch unique name'), required=True))
@operation_returns_entry(IBranch)
@export_read_operation()
+ @operation_for_version('beta')
def getByUniqueName(unique_name):
"""Find a branch by its ~owner/product/name unique name.
@@ -1249,6 +1271,7 @@
url=TextLine(title=_('Branch URL'), required=True))
@operation_returns_entry(IBranch)
@export_read_operation()
+ @operation_for_version('beta')
def getByUrl(url):
"""Find a branch by URL.
@@ -1272,6 +1295,7 @@
value_type=TextLine(),
required=True))
@export_read_operation()
+ @operation_for_version('beta')
def getByUrls(urls):
"""Finds branches by URL.
=== modified file 'lib/lp/code/interfaces/branchlink.py'
--- lib/lp/code/interfaces/branchlink.py 2010-08-20 20:31:18 +0000
+++ lib/lp/code/interfaces/branchlink.py 2011-03-23 16:18:44 +0000
@@ -17,6 +17,7 @@
export_operation_as,
export_write_operation,
exported,
+ operation_for_version,
operation_parameters,
operation_returns_entry,
REQUEST_USER,
@@ -45,6 +46,7 @@
@operation_parameters(
branch=Reference(schema=IBranch))
@export_write_operation()
+ @operation_for_version('beta')
def linkBranch(branch, registrant):
"""Associate a branch with this bug.
@@ -56,6 +58,7 @@
@operation_parameters(
branch=Reference(schema=IBranch))
@export_write_operation()
+ @operation_for_version('beta')
def unlinkBranch(branch, user):
"""Unlink a branch from this bug.
=== modified file 'lib/lp/code/interfaces/hasbranches.py'
--- lib/lp/code/interfaces/hasbranches.py 2011-03-03 01:13:47 +0000
+++ lib/lp/code/interfaces/hasbranches.py 2011-03-23 16:18:44 +0000
@@ -18,6 +18,7 @@
call_with,
export_factory_operation,
export_read_operation,
+ operation_for_version,
operation_parameters,
operation_returns_collection_of,
REQUEST_USER,
@@ -59,6 +60,7 @@
@call_with(visible_by_user=REQUEST_USER)
@operation_returns_collection_of(Interface) # Really IBranch.
@export_read_operation()
+ @operation_for_version('beta')
def getBranches(status=None, visible_by_user=None,
modified_since=None, eager_load=False):
"""Returns all branches with the given lifecycle status.
@@ -90,6 +92,7 @@
@call_with(visible_by_user=REQUEST_USER)
@operation_returns_collection_of(Interface) # Really IBranchMergeProposal.
@export_read_operation()
+ @operation_for_version('beta')
def getMergeProposals(status=None, visible_by_user=None):
"""Returns all merge proposals of a given status.
@@ -116,6 +119,7 @@
@call_with(visible_by_user=REQUEST_USER)
@operation_returns_collection_of(Interface) # Really IBranchMergeProposal.
@export_read_operation()
+ @operation_for_version('beta')
def getRequestedReviews(status=None, visible_by_user=None):
"""Returns merge proposals where a person was asked to review.
@@ -150,6 +154,7 @@
)
@call_with(registrant=REQUEST_USER)
@export_factory_operation(Interface, []) # Really ICodeImport.
+ @operation_for_version('beta')
def newCodeImport(registrant=None, branch_name=None, rcs_type=None,
url=None, cvs_root=None, cvs_module=None, owner=None):
"""Create a new code import.
=== modified file 'lib/lp/code/interfaces/sourcepackagerecipe.py'
=== modified file 'lib/lp/code/model/branch.py'
=== modified file 'lib/lp/code/model/branchcollection.py'
--- lib/lp/code/model/branchcollection.py 2011-03-22 02:14:15 +0000
+++ lib/lp/code/model/branchcollection.py 2011-03-23 16:18:44 +0000
@@ -203,15 +203,31 @@
cache = caches[link.branchID]
cache._associatedSuiteSourcePackages.append(
link.suite_sourcepackage)
- load_related(Product, rows, ['productID'])
- # So far have only needed the persons for their canonical_url - no
- # need for validity etc in the /branches API call.
- load_related(Person, rows,
- ['ownerID', 'registrantID', 'reviewerID'])
- for code_import in IStore(CodeImport).find(
- CodeImport, CodeImport.branchID.is_in(branch_ids)):
- cache = caches[code_import.branchID]
- cache.code_import = code_import
+<<<<<<< TREE
+ load_related(Product, rows, ['productID'])
+ # So far have only needed the persons for their canonical_url - no
+ # need for validity etc in the /branches API call.
+ load_related(Person, rows,
+ ['ownerID', 'registrantID', 'reviewerID'])
+ for code_import in IStore(CodeImport).find(
+ CodeImport, CodeImport.branchID.is_in(branch_ids)):
+ cache = caches[code_import.branchID]
+ cache.code_import = code_import
+=======
+ load_related(Product, rows, ['productID'])
+ # So far have only needed the persons for their canonical_url - no
+ # need for validity etc in the /branches API call.
+ load_related(Person, rows,
+ ['ownerID', 'registrantID', 'reviewerID'])
+ # Cache all branches as having no code imports to prevent fruitless
+ # lookups on the ones we don't find.
+ for cache in caches.values():
+ cache.code_import = None
+ for code_import in IStore(CodeImport).find(
+ CodeImport, CodeImport.branchID.is_in(branch_ids)):
+ cache = caches[code_import.branchID]
+ cache.code_import = code_import
+>>>>>>> MERGE-SOURCE
return DecoratedResultSet(resultset, pre_iter_hook=do_eager_load)
def getMergeProposals(self, statuses=None, for_branches=None,
=== modified file 'lib/lp/code/model/branchmergeproposal.py'
=== modified file 'lib/lp/code/model/sourcepackagerecipe.py'
=== modified file 'lib/lp/code/model/tests/test_branch.py'
=== modified file 'lib/lp/registry/interfaces/distribution.py'
--- lib/lp/registry/interfaces/distribution.py 2011-02-24 15:30:54 +0000
+++ lib/lp/registry/interfaces/distribution.py 2011-03-23 16:18:44 +0000
@@ -644,7 +644,7 @@
source_name="apport",
distro_series=series)[0].source_package_version
"""
- export_as_webservice_entry()
+ export_as_webservice_entry(as_of="beta")
class IBaseDistribution(IDistribution):
=== modified file 'lib/lp/registry/interfaces/location.py'
--- lib/lp/registry/interfaces/location.py 2010-10-27 20:56:33 +0000
+++ lib/lp/registry/interfaces/location.py 2011-03-23 16:18:44 +0000
@@ -24,6 +24,7 @@
call_with,
export_write_operation,
exported,
+ operation_for_version,
operation_parameters,
REQUEST_USER,
)
@@ -89,6 +90,7 @@
longitude=copy_field(IHasLocation['longitude'], required=True),
time_zone=copy_field(IHasLocation['time_zone'], required=True))
@export_write_operation()
+ @operation_for_version('beta')
def setLocation(latitude, longitude, time_zone, user):
"""Specify the location and time zone of a person."""
=== modified file 'lib/lp/registry/interfaces/milestone.py'
--- lib/lp/registry/interfaces/milestone.py 2011-02-24 15:29:18 +0000
+++ lib/lp/registry/interfaces/milestone.py 2011-03-23 16:18:44 +0000
@@ -24,6 +24,7 @@
export_operation_as,
export_read_operation,
exported,
+ operation_for_version,
operation_parameters,
operation_returns_entry,
rename_parameters_as,
@@ -181,6 +182,7 @@
@export_factory_operation(
IProductRelease,
['datereleased', 'changelog', 'release_notes'])
+ @operation_for_version('beta')
def createProductRelease(owner, datereleased,
changelog=None, release_notes=None):
"""Create a new ProductRelease.
@@ -203,6 +205,7 @@
@export_destructor_operation()
@export_operation_as('delete')
+ @operation_for_version('beta')
def destroySelf():
"""Delete this milestone.
@@ -279,6 +282,7 @@
name=TextLine(title=_("Name"), required=True))
@operation_returns_entry(IMilestone)
@export_read_operation()
+ @operation_for_version('beta')
def getMilestone(name):
"""Return a milestone with the given name for this object, or None."""
=== modified file 'lib/lp/registry/interfaces/person.py'
--- lib/lp/registry/interfaces/person.py 2011-03-22 04:40:12 +0000
+++ lib/lp/registry/interfaces/person.py 2011-03-23 16:18:44 +0000
@@ -58,6 +58,7 @@
export_write_operation,
exported,
LAZR_WEBSERVICE_EXPORTED,
+ operation_for_version,
operation_parameters,
operation_returns_collection_of,
operation_returns_entry,
@@ -1010,6 +1011,7 @@
build_daily=Bool(),
)
@export_factory_operation(Interface, [])
+ @operation_for_version("beta")
def createRecipe(name, description, recipe_text, distroseries,
registrant, daily_build_archive=None, build_daily=False):
"""Create a SourcePackageRecipe owned by this person.
@@ -1027,6 +1029,7 @@
@operation_parameters(name=TextLine(required=True))
@operation_returns_entry(Interface) # Really ISourcePackageRecipe.
@export_read_operation()
+ @operation_for_version("beta")
def getRecipe(name):
"""Return the person's recipe with the given name."""
@@ -1035,6 +1038,7 @@
@call_with(requester=REQUEST_USER)
@export_read_operation()
+ @operation_for_version("beta")
def getArchiveSubscriptionURLs(requester):
"""Return private archive URLs that this person can see.
@@ -1047,6 +1051,7 @@
@operation_parameters(
archive=Reference(schema=Interface)) # Really IArchive
@export_write_operation()
+ @operation_for_version("beta")
def getArchiveSubscriptionURL(requester, archive):
"""Get a text line that is suitable to be used for a sources.list
entry.
@@ -1076,6 +1081,7 @@
@operation_returns_collection_of(Interface)
@export_read_operation()
+ @operation_for_version("beta")
def getBugSubscriberPackages():
"""Return the packages for which this person is a bug subscriber.
@@ -1369,6 +1375,7 @@
name=TextLine(required=True, constraint=name_validator))
@operation_returns_entry(Interface) # Really IArchive.
@export_read_operation()
+ @operation_for_version("beta")
def getPPAByName(name):
"""Return a PPA with the given name if it exists.
@@ -1383,6 +1390,7 @@
displayname=TextLine(required=False),
description=TextLine(required=False))
@export_factory_operation(Interface, []) # Really IArchive.
+ @operation_for_version("beta")
def createPPA(name=None, displayname=None, description=None):
"""Create a PPA.
@@ -1553,6 +1561,7 @@
@operation_parameters(status=copy_field(ITeamMembership['status']))
@operation_returns_collection_of(Interface) # Really IPerson
@export_read_operation()
+ @operation_for_version("beta")
def getMembersByStatus(status, orderby=None):
"""Return the people whose membership on this team match :status:.
@@ -1566,6 +1575,7 @@
@call_with(requester=REQUEST_USER)
@operation_parameters(team=copy_field(ITeamMembership['team']))
@export_write_operation()
+ @operation_for_version("beta")
def join(team, requester=None, may_subscribe_to_list=True):
"""Join the given team if its subscriptionpolicy is not RESTRICTED.
@@ -1592,6 +1602,7 @@
@operation_parameters(team=copy_field(ITeamMembership['team']))
@export_write_operation()
+ @operation_for_version("beta")
def leave(team):
"""Leave the given team.
@@ -1605,6 +1616,7 @@
@operation_parameters(
visible=copy_field(ILocationRecord['visible'], required=True))
@export_write_operation()
+ @operation_for_version("beta")
def setLocationVisibility(visible):
"""Specify the visibility of a person's location and time zone."""
@@ -1628,6 +1640,7 @@
status=copy_field(ITeamMembership['status']),
comment=Text(required=False))
@export_write_operation()
+ @operation_for_version("beta")
def addMember(person, reviewer, status=TeamMembershipStatus.APPROVED,
comment=None, force_team_add=False,
may_subscribe_to_list=True):
@@ -1668,6 +1681,7 @@
team=copy_field(ITeamMembership['team']),
comment=Text())
@export_write_operation()
+ @operation_for_version("beta")
def acceptInvitationToBeMemberOf(team, comment):
"""Accept an invitation to become a member of the given team.
@@ -1680,6 +1694,7 @@
team=copy_field(ITeamMembership['team']),
comment=Text())
@export_write_operation()
+ @operation_for_version("beta")
def declineInvitationToBeMemberOf(team, comment):
"""Decline an invitation to become a member of the given team.
@@ -1693,6 +1708,7 @@
team=copy_field(ITeamMembership['team']),
comment=Text(required=False))
@export_write_operation()
+ @operation_for_version("beta")
def retractTeamMembership(team, user, comment=None):
"""Retract this team's membership in the given team.
@@ -2036,6 +2052,7 @@
@export_factory_operation(
ITeam, ['name', 'displayname', 'teamdescription',
'defaultmembershipperiod', 'defaultrenewalperiod'])
+ @operation_for_version("beta")
def newTeam(teamowner, name, displayname, teamdescription=None,
subscriptionpolicy=TeamSubscriptionPolicy.MODERATED,
defaultmembershipperiod=None, defaultrenewalperiod=None):
@@ -2048,6 +2065,7 @@
email=TextLine(required=True, constraint=email_validator))
@operation_returns_entry(IPerson)
@export_read_operation()
+ @operation_for_version("beta")
def getByEmail(email):
"""Return the person with the given email address.
@@ -2081,6 +2099,7 @@
text=TextLine(title=_("Search text"), default=u""))
@operation_returns_collection_of(IPerson)
@export_read_operation()
+ @operation_for_version("beta")
def find(text=""):
"""Return all non-merged Persons and Teams whose name, displayname or
email address match <text>.
@@ -2103,6 +2122,7 @@
)
@operation_returns_collection_of(IPerson)
@export_read_operation()
+ @operation_for_version("beta")
def findPerson(text="", exclude_inactive_accounts=True,
must_have_email=False,
created_after=None, created_before=None):
@@ -2134,6 +2154,7 @@
text=TextLine(title=_("Search text"), default=u""))
@operation_returns_collection_of(IPerson)
@export_read_operation()
+ @operation_for_version("beta")
def findTeam(text=""):
"""Return all Teams whose name, displayname or email address
match <text>.
=== modified file 'lib/lp/registry/interfaces/productseries.py'
--- lib/lp/registry/interfaces/productseries.py 2011-03-08 15:28:40 +0000
+++ lib/lp/registry/interfaces/productseries.py 2011-03-23 16:18:44 +0000
@@ -239,10 +239,7 @@
vocabulary=TranslationsBranchImportMode,
required=True,
description=_("Specify which files will be imported from the "
- "source code branch.")),
- ('devel', {'exported': True}),
- exported=False
- )
+ "source code branch.")), as_of="devel")
potemplate_count = Int(
title=_("The total number of POTemplates in this series."),
=== modified file 'lib/lp/registry/model/person.py'
=== modified file 'lib/lp/registry/model/product.py'
=== modified file 'lib/lp/services/database/bulk.py'
--- lib/lp/services/database/bulk.py 2011-03-22 00:18:47 +0000
+++ lib/lp/services/database/bulk.py 2011-03-23 16:18:44 +0000
@@ -5,8 +5,12 @@
__metaclass__ = type
__all__ = [
+<<<<<<< TREE
'load',
'load_related',
+=======
+ 'load',
+>>>>>>> MERGE-SOURCE
'reload',
]
=== modified file 'lib/lp/services/features/__init__.py'
--- lib/lp/services/features/__init__.py 2011-03-22 06:39:21 +0000
+++ lib/lp/services/features/__init__.py 2011-03-23 16:18:44 +0000
@@ -208,6 +208,7 @@
if features is None:
return None
return features.getFlag(flag)
+<<<<<<< TREE
def make_script_feature_controller(script_name):
@@ -223,3 +224,18 @@
return FeatureController(
ScopesForScript(script_name).lookup, StormFeatureRuleSource())
+=======
+
+
+def make_script_feature_controller(script_name):
+ """Create and install a `FeatureController` for the named script."""
+ # Avoid circular import.
+ from lp.services.features.flags import FeatureController
+ from lp.services.features.rulesource import StormFeatureRuleSource
+ from lp.services.features.scopes import ScopesForScript
+
+ install_feature_controller(
+ FeatureController(
+ ScopesForScript(script_name).lookup,
+ StormFeatureRuleSource()))
+>>>>>>> MERGE-SOURCE
=== modified file 'lib/lp/services/scripts/base.py'
--- lib/lp/services/scripts/base.py 2011-03-22 06:39:21 +0000
+++ lib/lp/services/scripts/base.py 2011-03-23 16:18:44 +0000
@@ -39,11 +39,20 @@
setupInteractionByEmail,
)
from canonical.lp import initZopeless
-from lp.services.features import (
- get_relevant_feature_controller,
- install_feature_controller,
- make_script_feature_controller,
- )
+<<<<<<< TREE
+from lp.services.features import (
+ get_relevant_feature_controller,
+ install_feature_controller,
+ make_script_feature_controller,
+ )
+=======
+from lp.services.features import (
+ getFeatureFlag,
+ get_relevant_feature_controller,
+ install_feature_controller,
+ make_script_feature_controller,
+ )
+>>>>>>> MERGE-SOURCE
from lp.services.scripts.interfaces.scriptactivity import IScriptActivitySet
=== modified file 'lib/lp/services/scripts/tests/test_feature_controller.py'
--- lib/lp/services/scripts/tests/test_feature_controller.py 2011-03-22 06:39:21 +0000
+++ lib/lp/services/scripts/tests/test_feature_controller.py 2011-03-23 16:18:44 +0000
@@ -1,3 +1,4 @@
+<<<<<<< TREE
# Copyright 2011 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
@@ -63,3 +64,66 @@
FakeScript(name="mongo").run()
self.assertEqual(
previous_controller, get_relevant_feature_controller())
+=======
+# Copyright 2011 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Test feature controller in scripts."""
+
+__metaclass__ = type
+
+from canonical.testing.layers import DatabaseFunctionalLayer
+from lp.services.features import (
+ get_relevant_feature_controller,
+ install_feature_controller,
+ )
+from lp.services.features.flags import NullFeatureController
+from lp.services.features.testing import FeatureFixture
+from lp.services.scripts.base import LaunchpadScript
+from lp.testing import TestCase
+from lp.testing.fakemethod import FakeMethod
+
+
+class FakeScript(LaunchpadScript):
+ """A dummy script that only records which feature controller is active."""
+
+ observed_feature_controller = object()
+
+ def __init__(self, name):
+ super(FakeScript, self).__init__(name=name, test_args=[])
+
+ def main(self):
+ self.observed_feature_controller = get_relevant_feature_controller()
+
+ # Shortcut some underpinnings of LaunchpadScript.run that we can't
+ # afford to have happen in tests.
+ _init_zca = FakeMethod()
+ _init_db = FakeMethod()
+ record_activity = FakeMethod()
+
+
+class TestScriptFeatureController(TestCase):
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super(TestScriptFeatureController, self).setUp()
+ self.original_controller = get_relevant_feature_controller()
+
+ def tearDown(self):
+ install_feature_controller(self.original_controller)
+ super(TestScriptFeatureController, self).tearDown()
+
+ def test_script_installs_script_feature_controller(self):
+ script = FakeScript(name="bongo")
+ script_feature_controller = get_relevant_feature_controller()
+ self.assertNotEqual(
+ self.original_controller, script.observed_feature_controller)
+ self.assertNotEqual(None, script.observed_feature_controller)
+
+ def test_script_restores_feature_controller(self):
+ previous_controller = NullFeatureController()
+ install_feature_controller(previous_controller)
+ FakeScript(name="mongo").run()
+ self.assertEqual(
+ previous_controller, get_relevant_feature_controller())
+>>>>>>> MERGE-SOURCE
=== modified file 'lib/lp/soyuz/interfaces/buildrecords.py'
--- lib/lp/soyuz/interfaces/buildrecords.py 2010-08-20 20:31:18 +0000
+++ lib/lp/soyuz/interfaces/buildrecords.py 2011-03-23 16:18:44 +0000
@@ -19,6 +19,7 @@
from lazr.restful.declarations import (
call_with,
export_read_operation,
+ operation_for_version,
operation_parameters,
operation_returns_collection_of,
rename_parameters_as,
@@ -59,6 +60,7 @@
# Really a IBuild see _schema_circular_imports.
@operation_returns_collection_of(Interface)
@export_read_operation()
+ @operation_for_version('beta')
def getBuildRecords(build_state=None, name=None, pocket=None,
arch_tag=None, user=None, binary_only=True):
"""Return build records in the context it is implemented.
=== modified file 'lib/lp/testing/__init__.py'
=== modified file 'lib/lp/translations/interfaces/hastranslationimports.py'
--- lib/lp/translations/interfaces/hastranslationimports.py 2010-10-29 10:01:34 +0000
+++ lib/lp/translations/interfaces/hastranslationimports.py 2011-03-23 16:18:44 +0000
@@ -11,6 +11,7 @@
from lazr.restful.declarations import (
export_as_webservice_entry,
export_read_operation,
+ operation_for_version,
operation_parameters,
operation_returns_collection_of,
)
@@ -51,6 +52,7 @@
# _schema_circular_imports.py.
@operation_returns_collection_of(Interface)
@export_read_operation()
+ @operation_for_version('beta')
def getTranslationImportQueueEntries(import_status=None,
file_extension=None):
"""Return entries in the translation import queue for this entity.
=== modified file 'lib/lp/translations/interfaces/hastranslationtemplates.py'
--- lib/lp/translations/interfaces/hastranslationtemplates.py 2010-11-15 16:25:05 +0000
+++ lib/lp/translations/interfaces/hastranslationtemplates.py 2011-03-23 16:18:44 +0000
@@ -10,6 +10,7 @@
from lazr.restful.declarations import (
export_read_operation,
+ operation_for_version,
operation_returns_collection_of,
)
from zope.interface import Interface
@@ -84,6 +85,7 @@
@export_read_operation()
@operation_returns_collection_of(Interface)
+ @operation_for_version('beta')
def getTranslationTemplates():
"""Return an iterator over all its translation templates.
=== modified file 'lib/lp/translations/interfaces/translationgroup.py'
--- lib/lp/translations/interfaces/translationgroup.py 2011-03-07 19:05:44 +0000
+++ lib/lp/translations/interfaces/translationgroup.py 2011-03-23 16:18:44 +0000
@@ -61,8 +61,7 @@
descriptive, because it will be used in URLs. Examples:
gnome-translation-project, ubuntu-translators."""),
constraint=name_validator),
- ('devel', {'exported': True}),
- exported=False,
+ as_of="devel"
)
title = exported(Title(
title=_('Title'), required=True,
@@ -72,8 +71,7 @@
add "translation group" to this title, or it will be shown
double.
"""),),
- ('devel', {'exported': True}),
- exported=False,
+ as_of="devel"
)
summary = Summary(
title=_('Summary'), required=True,
=== modified file 'lib/lp/translations/interfaces/translationpolicy.py'
--- lib/lp/translations/interfaces/translationpolicy.py 2011-03-07 19:05:44 +0000
+++ lib/lp/translations/interfaces/translationpolicy.py 2011-03-23 16:18:44 +0000
@@ -46,20 +46,14 @@
" role depends on the permissions policy selected below."),
required=False,
vocabulary='TranslationGroup',
- schema=ITranslationGroup),
- ('devel', {'exported': True}),
- exported=False,
- )
+ schema=ITranslationGroup), as_of="devel")
translationpermission = exported(Choice(
title=_("Translation permissions policy"),
description=_("The policy this project or distribution uses to "
" balance openness and control for their translations."),
required=True,
- vocabulary=TranslationPermission),
- ('devel', {'exported': True}),
- exported=False,
- )
+ vocabulary=TranslationPermission), as_of="devel")
def getTranslationGroups():
"""List all applicable translation groups.
=== modified file 'versions.cfg'
--- versions.cfg 2011-03-17 05:29:08 +0000
+++ versions.cfg 2011-03-23 16:18:44 +0000
@@ -34,7 +34,11 @@
lazr.delegates = 1.2.0
lazr.enum = 1.1.2
lazr.lifecycle = 1.1
+<<<<<<< TREE
lazr.restful = 0.17.5
+=======
+lazr.restful = 0.18.0
+>>>>>>> MERGE-SOURCE
lazr.restfulclient = 0.11.2
lazr.smtptest = 1.1
lazr.testing = 0.1.1