Colin Watson has proposed merging ~cjwatson/launchpad:stormify-milestone into launchpad:master.
Commit message: Convert Milestone to Storm Requested reviews: Launchpad code reviewers (launchpad-reviewers) For more details, see: https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/448474 -- Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-milestone into launchpad:master.
diff --git a/lib/lp/bugs/model/bugtask.py b/lib/lp/bugs/model/bugtask.py index 2606bed..c8cc080 100644 --- a/lib/lp/bugs/model/bugtask.py +++ b/lib/lp/bugs/model/bugtask.py @@ -2324,10 +2324,10 @@ class BugTaskSet: Milestone, Milestone.active == True, Or( - Milestone.distributionID.is_in(distro_ids), - Milestone.distroseriesID.is_in(distro_series_ids), - Milestone.productID.is_in(product_ids), - Milestone.productseriesID.is_in(product_series_ids), + Milestone.distribution_id.is_in(distro_ids), + Milestone.distroseries_id.is_in(distro_series_ids), + Milestone.product_id.is_in(product_ids), + Milestone.productseries_id.is_in(product_series_ids), ), ) diff --git a/lib/lp/bugs/model/bugtasksearch.py b/lib/lp/bugs/model/bugtasksearch.py index 9a49e53..f7a0fe1 100644 --- a/lib/lp/bugs/model/bugtasksearch.py +++ b/lib/lp/bugs/model/bugtasksearch.py @@ -379,7 +379,7 @@ def _build_query(params): tables=[Milestone, Product], where=And( Product.projectgroup == params.milestone.target, - Milestone.productID == Product.id, + Milestone.product_id == Product.id, Milestone.name == params.milestone.name, ProductSet.getProductPrivacyFilter(params.user), ), @@ -406,7 +406,7 @@ def _build_query(params): tables=[Milestone, Product, MilestoneTag], where=And( Product.projectgroup == params.milestone_tag.target, - Milestone.productID == Product.id, + Milestone.product_id == Product.id, Milestone.id == MilestoneTag.milestone_id, MilestoneTag.tag.is_in(params.milestone_tag.tags), ), diff --git a/lib/lp/bugs/vocabularies.py b/lib/lp/bugs/vocabularies.py index 5586ef3..ecf92ef 100644 --- a/lib/lp/bugs/vocabularies.py +++ b/lib/lp/bugs/vocabularies.py @@ -332,17 +332,17 @@ def milestone_matches_bugtask(milestone, bugtask): naked_milestone = removeSecurityProxy(milestone) if IProduct.providedBy(bug_target): - return bugtask.product.id == naked_milestone.productID + return bugtask.product == naked_milestone.product elif IProductSeries.providedBy(bug_target): - return bugtask.productseries.product.id == naked_milestone.productID + return bugtask.productseries.product == naked_milestone.product elif IDistribution.providedBy( bug_target ) or IDistributionSourcePackage.providedBy(bug_target): - return bugtask.distribution.id == naked_milestone.distributionID + return bugtask.distribution == naked_milestone.distribution elif IDistroSeries.providedBy(bug_target) or ISourcePackage.providedBy( bug_target ): - return bugtask.distroseries.id == naked_milestone.distroseriesID + return bugtask.distroseries == naked_milestone.distroseries return False diff --git a/lib/lp/registry/model/milestone.py b/lib/lp/registry/model/milestone.py index e86bb1c..55f396d 100644 --- a/lib/lp/registry/model/milestone.py +++ b/lib/lp/registry/model/milestone.py @@ -18,7 +18,7 @@ from operator import itemgetter from lazr.restful.declarations import error_status from storm.expr import And, Desc, LeftJoin, Select, Union -from storm.locals import Store +from storm.locals import Bool, Date, Int, Reference, Store, Unicode from storm.zope import IResultSet from zope.component import getUtility from zope.interface import implementer @@ -43,14 +43,7 @@ from lp.registry.interfaces.milestone import ( from lp.registry.model.productrelease import ProductRelease from lp.services.database.decoratedresultset import DecoratedResultSet from lp.services.database.interfaces import IStore -from lp.services.database.sqlbase import SQLBase -from lp.services.database.sqlobject import ( - AND, - BoolCol, - DateCol, - ForeignKey, - StringCol, -) +from lp.services.database.stormbase import StormBase from lp.services.propertycache import get_property_cache from lp.services.webapp.sorting import expand_numbers @@ -107,7 +100,8 @@ class HasMilestonesMixin: store = Store.of(self) result = store.find( Milestone, - And(self._getMilestoneCondition(), Milestone.active == True), + self._getMilestoneCondition(), + Milestone.active == True, ) return result.order_by(self._milestone_order) @@ -223,34 +217,59 @@ class MilestoneData: @implementer(IHasBugs, IMilestone, IBugSummaryDimension) class Milestone( - SQLBase, MilestoneData, StructuralSubscriptionTargetMixin, HasBugsBase + StormBase, MilestoneData, StructuralSubscriptionTargetMixin, HasBugsBase ): - active = BoolCol(notNull=True, default=True) + __storm_table__ = "Milestone" + + id = Int(primary=True) + + active = Bool(allow_none=False, default=True) # XXX: EdwinGrubbs 2009-02-06 bug=326384: # The Milestone.dateexpected should be changed into a date column, # since the class defines the field as a DateCol, so that a list of # milestones can't have some dateexpected attributes that are # datetimes and others that are dates, which can't be compared. - dateexpected = DateCol(notNull=False, default=None) + dateexpected = Date(allow_none=True, default=None) # XXX: Guilherme Salgado 2007-03-27 bug=40978: # Milestones should be associated with productseries/distroseries # so these columns are not needed. - product = ForeignKey(dbName="product", foreignKey="Product", default=None) - distribution = ForeignKey( - dbName="distribution", foreignKey="Distribution", default=None - ) - - productseries = ForeignKey( - dbName="productseries", foreignKey="ProductSeries", default=None - ) - distroseries = ForeignKey( - dbName="distroseries", foreignKey="DistroSeries", default=None - ) - name = StringCol(notNull=True) - summary = StringCol(notNull=False, default=None) - code_name = StringCol(dbName="codename", notNull=False, default=None) + product_id = Int(name="product", default=None) + product = Reference(product_id, "Product.id") + distribution_id = Int(name="distribution", default=None) + distribution = Reference(distribution_id, "Distribution.id") + + productseries_id = Int(name="productseries", default=None) + productseries = Reference(productseries_id, "ProductSeries.id") + distroseries_id = Int(name="distroseries", default=None) + distroseries = Reference(distroseries_id, "DistroSeries.id") + name = Unicode(allow_none=False) + summary = Unicode(allow_none=True, default=None) + code_name = Unicode(name="codename", allow_none=True, default=None) + + def __init__( + self, + name, + active=True, + dateexpected=None, + product=None, + distribution=None, + productseries=None, + distroseries=None, + summary=None, + code_name=None, + ): + super().__init__() + self.name = name + self.active = active + self.dateexpected = dateexpected + self.product = product + self.distribution = distribution + self.productseries = productseries + self.distroseries = distroseries + self.summary = summary + self.code_name = code_name def _milestone_ids_expr(self, user): return (self.id,) @@ -346,7 +365,7 @@ class Milestone( "You cannot delete a milestone which has a product release " "associated with it." ) - super().destroySelf() + Store.of(self).remove(self) def getBugSummaryContextWhereClause(self): """See BugTargetBase.""" @@ -415,7 +434,7 @@ class Milestone( class MilestoneSet: def __iter__(self): """See lp.registry.interfaces.milestone.IMilestoneSet.""" - yield from Milestone.select() + yield from IStore(Milestone).find(Milestone) def get(self, milestoneid): """See lp.registry.interfaces.milestone.IMilestoneSet.""" @@ -434,28 +453,31 @@ class MilestoneSet: def getByNameAndProduct(self, name, product, default=None): """See lp.registry.interfaces.milestone.IMilestoneSet.""" - query = AND( - Milestone.q.name == name, Milestone.q.productID == product.id + milestone = ( + IStore(Milestone).find(Milestone, name=name, product=product).one() ) - milestone = Milestone.selectOne(query) if milestone is None: return default return milestone def getByNameAndDistribution(self, name, distribution, default=None): """See lp.registry.interfaces.milestone.IMilestoneSet.""" - query = AND( - Milestone.q.name == name, - Milestone.q.distributionID == distribution.id, + milestone = ( + IStore(Milestone) + .find(Milestone, name=name, distribution=distribution) + .one() ) - milestone = Milestone.selectOne(query) if milestone is None: return default return milestone def getVisibleMilestones(self): """See lp.registry.interfaces.milestone.IMilestoneSet.""" - return Milestone.selectBy(active=True, orderBy="id") + return ( + IStore(Milestone) + .find(Milestone, active=True) + .order_by(Milestone.id) + ) @implementer(IProjectGroupMilestone) @@ -498,7 +520,7 @@ class ProjectMilestone(MilestoneData, HasBugsBase): tables=[Milestone, Product], where=And( Milestone.name == self.name, - Milestone.productID == Product.id, + Milestone.product_id == Product.id, Product.projectgroup == self.target, ProductSet.getProductPrivacyFilter(user), ), diff --git a/lib/lp/registry/model/milestonetag.py b/lib/lp/registry/model/milestonetag.py index bd23e71..984a5b4 100644 --- a/lib/lp/registry/model/milestonetag.py +++ b/lib/lp/registry/model/milestonetag.py @@ -85,7 +85,7 @@ class ProjectGroupMilestoneTag(MilestoneData): Milestone.id, tables=[Milestone, Product], where=And( - Milestone.productID == Product.id, + Milestone.product_id == Product.id, Product.projectgroup == self.target, tag_constraints, ), diff --git a/lib/lp/registry/model/productrelease.py b/lib/lp/registry/model/productrelease.py index a73d29a..8a87785 100644 --- a/lib/lp/registry/model/productrelease.py +++ b/lib/lp/registry/model/productrelease.py @@ -344,7 +344,7 @@ class ProductReleaseSet: .find( ProductRelease, And(ProductRelease.milestone == Milestone.id), - Milestone.productseriesID.is_in(series_ids), + Milestone.productseries_id.is_in(series_ids), ) .order_by(Desc(ProductRelease.datereleased)) ) diff --git a/lib/lp/registry/model/projectgroup.py b/lib/lp/registry/model/projectgroup.py index 428c718..dfc4609 100644 --- a/lib/lp/registry/model/projectgroup.py +++ b/lib/lp/registry/model/projectgroup.py @@ -10,7 +10,7 @@ __all__ = [ ] import six -from storm.expr import SQL, And, In, Join +from storm.expr import And, Desc, Func, In, Is, Join, Min from storm.locals import Int, Reference from storm.store import Store from zope.component import getUtility @@ -418,7 +418,7 @@ class ProjectGroup( user = getUtility(ILaunchBag).user privacy_filter = ProductSet.getProductPrivacyFilter(user) return And( - Milestone.productID == Product.id, + Milestone.product_id == Product.id, Product.projectgroupID == self.id, privacy_filter, ) @@ -436,8 +436,8 @@ class ProjectGroup( columns = ( Milestone.name, - SQL("MIN(Milestone.dateexpected)"), - SQL("BOOL_OR(Milestone.active)"), + Min(Milestone.dateexpected), + Func("bool_or", Milestone.active), ) privacy_filter = ProductSet.getProductPrivacyFilter(user) conditions = And( @@ -449,12 +449,17 @@ class ProjectGroup( result = store.find(columns, conditions) result.group_by(Milestone.name) if only_active: - result.having("BOOL_OR(Milestone.active) = TRUE") - # MIN(Milestone.dateexpected) has to be used to match the + result.having(Is(Func("bool_or", Milestone.active), True)) + # Min(Milestone.dateexpected) has to be used to match the # aggregate function in the `columns` variable. result.order_by( - "milestone_sort_key(MIN(Milestone.dateexpected), Milestone.name) " - "DESC" + Desc( + Func( + "milestone_sort_key", + Min(Milestone.dateexpected), + Milestone.name, + ) + ) ) # An extra query is required here in order to get the correct # products without affecting the group/order of the query above. diff --git a/lib/lp/registry/scripts/productreleasefinder/finder.py b/lib/lp/registry/scripts/productreleasefinder/finder.py index 107a570..2271655 100644 --- a/lib/lp/registry/scripts/productreleasefinder/finder.py +++ b/lib/lp/registry/scripts/productreleasefinder/finder.py @@ -171,7 +171,7 @@ class ProductReleaseFinder: LibraryFileAlias.filename, Product.name == product_name, Product.id == ProductSeries.productID, - Milestone.productseriesID == ProductSeries.id, + Milestone.productseries_id == ProductSeries.id, ProductRelease.milestone_id == Milestone.id, ProductReleaseFile.productrelease_id == ProductRelease.id, LibraryFileAlias.id == ProductReleaseFile.libraryfile_id, diff --git a/lib/lp/registry/vocabularies.py b/lib/lp/registry/vocabularies.py index 9add187..566e9f7 100644 --- a/lib/lp/registry/vocabularies.py +++ b/lib/lp/registry/vocabularies.py @@ -1212,7 +1212,7 @@ class ProductReleaseVocabulary(StormVocabularyBase): _order_by = [Product.name, ProductSeries.name, Milestone.name] _clauses = [ ProductRelease.milestone_id == Milestone.id, - Milestone.productseriesID == ProductSeries.id, + Milestone.productseries_id == ProductSeries.id, ProductSeries.productID == Product.id, ] @@ -1248,7 +1248,7 @@ class ProductReleaseVocabulary(StormVocabularyBase): .find( ProductRelease, ProductRelease.milestone_id == Milestone.id, - Milestone.productseriesID == ProductSeries.id, + Milestone.productseries_id == ProductSeries.id, ProductSeries.productID == Product.id, Product.name == productname, ProductSeries.name == productseriesname, @@ -1271,7 +1271,7 @@ class ProductReleaseVocabulary(StormVocabularyBase): .find( self._table, ProductRelease.milestone_id == Milestone.id, - Milestone.productseriesID == ProductSeries.id, + Milestone.productseries_id == ProductSeries.id, ProductSeries.productID == Product.id, Or( Product.name.contains_string(query), @@ -1393,11 +1393,11 @@ class FilteredProductSeriesVocabulary(SQLObjectVocabularyBase): yield self.toTerm(series) -class MilestoneVocabulary(SQLObjectVocabularyBase): +class MilestoneVocabulary(StormVocabularyBase): """The milestones for a target.""" _table = Milestone - _orderBy = None + _order_by = None def toTerm(self, obj): """See `IVocabulary`.""" @@ -1475,19 +1475,23 @@ class MilestoneVocabulary(SQLObjectVocabularyBase): # Prefetch products and distributions for rendering # milestones: optimization to reduce the number of queries. product_ids = { - removeSecurityProxy(milestone).productID + removeSecurityProxy(milestone).product_id for milestone in milestones } product_ids.discard(None) distro_ids = { - removeSecurityProxy(milestone).distributionID + removeSecurityProxy(milestone).distribution_id for milestone in milestones } distro_ids.discard(None) if len(product_ids) > 0: - list(Product.select("id IN %s" % sqlvalues(product_ids))) + list(IStore(Product).find(Product, Product.id.is_in(product_ids))) if len(distro_ids) > 0: - list(Distribution.select("id IN %s" % sqlvalues(distro_ids))) + list( + IStore(Distribution).find( + Distribution, Distribution.id.is_in(distro_ids) + ) + ) return sorted(milestones, key=attrgetter("displayname")) @@ -1507,7 +1511,7 @@ class MilestoneVocabulary(SQLObjectVocabularyBase): # so we special-case them here just for that purpose. return obj.target.getMilestone(obj.name) else: - return SQLObjectVocabularyBase.__contains__(self, obj) + return super().__contains__(obj) class MilestoneWithDateExpectedVocabulary(MilestoneVocabulary):
_______________________________________________ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp