launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #28560
[Merge] ~cjwatson/launchpad:stormify-launchpadstatistic into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:stormify-launchpadstatistic into launchpad:master.
Commit message:
Convert LaunchpadStatistic to Storm
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/424218
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-launchpadstatistic into launchpad:master.
diff --git a/lib/lp/services/statistics/model/statistics.py b/lib/lp/services/statistics/model/statistics.py
index 6170e56..2662af3 100644
--- a/lib/lp/services/statistics/model/statistics.py
+++ b/lib/lp/services/statistics/model/statistics.py
@@ -8,6 +8,12 @@ __all__ = [
'LaunchpadStatisticSet',
]
+import pytz
+from storm.locals import (
+ DateTime,
+ Int,
+ Unicode,
+ )
from zope.component import getUtility
from zope.interface import implementer
@@ -22,16 +28,9 @@ from lp.code.interfaces.gitcollection import IAllGitRepositories
from lp.registry.interfaces.person import IPersonSet
from lp.registry.model.product import Product
from lp.services.database.constants import UTC_NOW
-from lp.services.database.datetimecol import UtcDateTimeCol
from lp.services.database.interfaces import IStore
-from lp.services.database.sqlbase import (
- cursor,
- SQLBase,
- )
-from lp.services.database.sqlobject import (
- IntCol,
- StringCol,
- )
+from lp.services.database.sqlbase import cursor
+from lp.services.database.stormbase import StormBase
from lp.services.statistics.interfaces.statistic import (
ILaunchpadStatistic,
ILaunchpadStatisticSet,
@@ -43,45 +42,56 @@ from lp.translations.model.potemplate import POTemplate
@implementer(ILaunchpadStatistic)
-class LaunchpadStatistic(SQLBase):
+class LaunchpadStatistic(StormBase):
"""A table of Launchpad Statistics."""
- _table = 'LaunchpadStatistic'
- _defaultOrder = 'name'
+ __storm_table__ = "LaunchpadStatistic"
+ __storm_order__ = "name"
+
+ id = Int(primary=True)
+
+ name = Unicode(allow_none=False)
+ value = Int(allow_none=False)
+ dateupdated = DateTime(allow_none=False, default=UTC_NOW, tzinfo=pytz.UTC)
- # db field names
- name = StringCol(notNull=True, alternateID=True, unique=True)
- value = IntCol(notNull=True)
- dateupdated = UtcDateTimeCol(notNull=True, default=UTC_NOW)
+ def __init__(self, name, value):
+ super().__init__()
+ self.name = name
+ self.value = value
@implementer(ILaunchpadStatisticSet)
class LaunchpadStatisticSet:
- """See`ILaunchpadStatisticSet`."""
+ """See `ILaunchpadStatisticSet`."""
def __iter__(self):
"""See ILaunchpadStatisticSet."""
- return iter(LaunchpadStatistic.select(orderBy='name'))
+ store = IStore(LaunchpadStatistic)
+ return iter(store.find(LaunchpadStatistic).order_by("name"))
def update(self, name, value):
"""See ILaunchpadStatisticSet."""
- stat = LaunchpadStatistic.selectOneBy(name=name)
+ store = IStore(LaunchpadStatistic)
+ stat = store.find(LaunchpadStatistic, name=name).one()
if stat is None:
stat = LaunchpadStatistic(name=name, value=value)
+ store.add(stat)
else:
stat.value = value
stat.dateupdated = UTC_NOW
def dateupdated(self, name):
"""See ILaunchpadStatisticSet."""
- stat = LaunchpadStatistic.selectOneBy(name=name)
+ store = IStore(LaunchpadStatistic)
+ stat = store.find(LaunchpadStatistic, name=name).one()
if stat is None:
return None
return stat.dateupdated
def value(self, name):
"""See ILaunchpadStatisticSet."""
- stat = LaunchpadStatistic.selectOneBy(name=name)
+ store = IStore(LaunchpadStatistic)
+ stat = store.find(LaunchpadStatistic, name=name).one()
if stat is None:
return None
return stat.value
diff --git a/lib/lp/services/statistics/tests/test_update_stats.py b/lib/lp/services/statistics/tests/test_update_stats.py
index b027149..25a2462 100644
--- a/lib/lp/services/statistics/tests/test_update_stats.py
+++ b/lib/lp/services/statistics/tests/test_update_stats.py
@@ -3,20 +3,32 @@
"""Test updates to Distroseries stats."""
+from datetime import timedelta
import os
import subprocess
import unittest
+from storm.expr import (
+ Cast,
+ Max,
+ Select,
+ )
from zope.component import getUtility
from lp.registry.interfaces.distribution import IDistributionSet
from lp.registry.interfaces.distroseries import IDistroSeriesSet
+from lp.registry.model.distroseries import DistroSeries
from lp.services.config import config
-from lp.services.database.sqlbase import cursor
+from lp.services.database.constants import UTC_NOW
+from lp.services.database.interfaces import IStore
+from lp.services.database.stormexpr import IsTrue
+from lp.services.statistics.model.statistics import LaunchpadStatistic
from lp.services.worlddata.interfaces.language import ILanguageSet
+from lp.services.worlddata.model.language import Language
from lp.testing.dbuser import switch_dbuser
from lp.testing.layers import LaunchpadZopelessLayer
from lp.translations.interfaces.potemplate import IPOTemplateSet
+from lp.translations.model.distroserieslanguage import DistroSeriesLanguage
def get_script():
@@ -40,40 +52,33 @@ class UpdateStatsTest(unittest.TestCase):
def test_basic(self):
"""Test insert and update operations to LaunchpadStatistic."""
# Nuke some stats so we know that they are updated
- cur = cursor()
+ store = IStore(LaunchpadStatistic)
# Destroy the LaunchpadStatistic entries so we can confirm they are
# updated.
- cur.execute(
- "DELETE FROM LaunchpadStatistic WHERE name='pofile_count'")
- cur.execute("""
- UPDATE LaunchpadStatistic
- SET value=-1, dateupdated=now()-'10 weeks'::interval
- """)
+ ten_weeks_ago = UTC_NOW - Cast(timedelta(weeks=10), "interval")
+ store.find(LaunchpadStatistic, name="pofile_count").remove()
+ store.find(LaunchpadStatistic).set(value=-1, dateupdated=ten_weeks_ago)
# Destroy the messagecount caches on distroseries so we can confirm
# they are all updated.
- cur.execute("UPDATE DistroSeries SET messagecount=-1")
+ store.find(DistroSeries).set(messagecount=-1)
# Delete half the entries in the DistroSeriesLanguage cache so we
# can confirm they are created as required, and set the remainders
# to invalid values so we can confirm they are updated.
- cur.execute("""
- DELETE FROM DistroSeriesLanguage
- WHERE id > (SELECT max(id) FROM DistroSeriesLanguage)/2
- """)
- cur.execute("""
- UPDATE DistroSeriesLanguage
- SET
- currentcount=-1, updatescount=-1, rosettacount=-1,
- unreviewed_count=-1,contributorcount=-1,
- dateupdated=now()-'10 weeks'::interval
- """)
+ store.find(
+ DistroSeriesLanguage,
+ DistroSeriesLanguage.id > Select(
+ Max(DistroSeriesLanguage.id) / 2)).remove()
+ store.find(DistroSeriesLanguage).set(
+ currentcount=-1, updatescount=-1, rosettacount=-1,
+ unreviewed_count=-1, contributorcount=-1,
+ dateupdated=ten_weeks_ago)
# Update stats should create missing distroserieslanguage,
# so remember how many there are before the run.
- cur.execute("SELECT COUNT(*) FROM DistroSeriesLanguage")
- num_distroserieslanguage = cur.fetchone()[0]
+ num_distroserieslanguage = store.find(DistroSeriesLanguage).count()
# Commit our changes so the subprocess can see them
self.layer.txn.commit()
@@ -98,72 +103,39 @@ class UpdateStatsTest(unittest.TestCase):
# Now confirm it did stuff it is supposed to
self.layer.txn.abort()
- cur = cursor()
# Make sure all DistroSeries.messagecount entries are updated
- cur.execute(
- "SELECT COUNT(*) FROM DistroSeries WHERE messagecount=-1")
- self.assertEqual(cur.fetchone()[0], 0)
+ self.assertEqual(0, store.find(DistroSeries, messagecount=-1).count())
# Make sure we have created missing DistroSeriesLanguage entries
- cur.execute("SELECT COUNT(*) FROM DistroSeriesLanguage")
- self.assertTrue(cur.fetchone()[0] > num_distroserieslanguage)
-
- # Make sure existing DistroSeriesLangauge entries have been updated.
- cur.execute("""
- SELECT COUNT(*) FROM DistroSeriesLanguage, Language
- WHERE DistroSeriesLanguage.language = Language.id AND
- Language.visible = TRUE AND currentcount = -1
- """)
- self.assertEqual(cur.fetchone()[0], 0)
-
- cur.execute("""
- SELECT COUNT(*) FROM DistroSeriesLanguage, Language
- WHERE DistroSeriesLanguage.language = Language.id AND
- Language.visible = TRUE AND updatescount = -1
- """)
- self.assertEqual(cur.fetchone()[0], 0)
-
- cur.execute("""
- SELECT COUNT(*) FROM DistroSeriesLanguage, Language
- WHERE DistroSeriesLanguage.language = Language.id AND
- Language.visible = TRUE AND rosettacount = -1
- """)
- self.assertEqual(cur.fetchone()[0], 0)
-
- cur.execute("""
- SELECT COUNT(*) FROM DistroSeriesLanguage, Language
- WHERE DistroSeriesLanguage.language = Language.id AND
- Language.visible = TRUE AND unreviewed_count = -1
- """)
- self.assertEqual(cur.fetchone()[0], 0)
-
- cur.execute("""
- SELECT COUNT(*) FROM DistroSeriesLanguage, Language
- WHERE DistroSeriesLanguage.language = Language.id AND
- Language.visible = TRUE AND contributorcount = -1
- """)
- self.assertEqual(cur.fetchone()[0], 0)
-
- cur.execute("""
- SELECT COUNT(*) FROM DistroSeriesLanguage, Language
- WHERE DistroSeriesLanguage.language = Language.id AND
- Language.visible = TRUE AND
- dateupdated < now() - '2 days'::interval
- """)
- self.assertEqual(cur.fetchone()[0], 0)
+ self.assertGreater(
+ store.find(DistroSeriesLanguage).count(), num_distroserieslanguage)
+
+ # Make sure existing DistroSeriesLanguage entries have been updated.
+ two_days_ago = UTC_NOW - Cast(timedelta(days=2), "interval")
+ for term in (
+ DistroSeriesLanguage.currentcount == -1,
+ DistroSeriesLanguage.updatescount == -1,
+ DistroSeriesLanguage.rosettacount == -1,
+ DistroSeriesLanguage.unreviewed_count == -1,
+ DistroSeriesLanguage.contributorcount == -1,
+ DistroSeriesLanguage.dateupdated < two_days_ago,
+ ):
+ self.assertEqual(
+ 0,
+ store.find(
+ DistroSeriesLanguage,
+ DistroSeriesLanguage.language == Language.id,
+ IsTrue(Language.visible),
+ term).count())
# All LaunchpadStatistic rows should have been updated
- cur.execute("""
- SELECT COUNT(*) FROM LaunchpadStatistic
- WHERE value=-1
- """)
- self.assertEqual(cur.fetchone()[0], 0)
- cur.execute("""
- SELECT COUNT(*) FROM LaunchpadStatistic
- WHERE dateupdated < now() - '2 days'::interval
- """)
- self.assertEqual(cur.fetchone()[0], 0)
+ self.assertEqual(0, store.find(LaunchpadStatistic, value=-1).count())
+ self.assertEqual(
+ 0,
+ store.find(
+ LaunchpadStatistic,
+ LaunchpadStatistic.dateupdated < two_days_ago).count())
keys = [
'potemplate_count', 'pofile_count', 'pomsgid_count',
@@ -177,12 +149,10 @@ class UpdateStatsTest(unittest.TestCase):
]
for key in keys:
- cur.execute("""
- SELECT value from LaunchpadStatistic WHERE name=%(key)s
- """, dict(key=key))
- row = cur.fetchone()
- self.assertIsNotNone(row, '%s not updated' % key)
- self.assertTrue(row[0] >= 0, '%s is invalid' % key)
+ value = store.find(
+ LaunchpadStatistic.value, LaunchpadStatistic.name == key).one()
+ self.assertIsNotNone(value, "%s not updated" % key)
+ self.assertGreaterEqual(value, 0, "%s is invalid" % key)
class UpdateTranslationStatsTest(unittest.TestCase):