launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #30350
[Merge] ~cjwatson/launchpad:stormify-milestone into launchpad:master
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):