← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~ilasc/launchpad:stormify-bugtask into launchpad:master

 

Ioana Lasc has proposed merging ~ilasc/launchpad:stormify-bugtask into launchpad:master.

Commit message:
Stormify BugTag

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~ilasc/launchpad/+git/launchpad/+merge/392464
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~ilasc/launchpad:stormify-bugtask into launchpad:master.
diff --git a/lib/lp/bugs/browser/tests/test_bugtarget_tags.py b/lib/lp/bugs/browser/tests/test_bugtarget_tags.py
index 0cd3f81..204861a 100644
--- a/lib/lp/bugs/browser/tests/test_bugtarget_tags.py
+++ b/lib/lp/bugs/browser/tests/test_bugtarget_tags.py
@@ -26,7 +26,7 @@ class TestBugTargetTags(TestCaseWithFactory):
         self.assertEqual([], [tag['tag'] for tag in view.tags_cloud_data])
 
     def test_tags(self):
-        self.factory.makeBug(target=self.target_product, tags=['foo'])
+        self.factory.makeBug(target=self.target_product, tags=[u'foo'])
         view = create_view(
             self.project_group,
             name="+bugtarget-portlet-tags-content")
@@ -36,13 +36,13 @@ class TestBugTargetTags(TestCaseWithFactory):
 
     def test_tags_order(self):
         """Test that the tags are ordered by most used first"""
-        self.factory.makeBug(target=self.target_product, tags=['tag-last'])
+        self.factory.makeBug(target=self.target_product, tags=[u'tag-last'])
         for counter in range(0, 2):
             self.factory.makeBug(
-                target=self.target_product, tags=['tag-middle'])
+                target=self.target_product, tags=[u'tag-middle'])
         for counter in range(0, 3):
             self.factory.makeBug(
-                target=self.target_product, tags=['tag-first'])
+                target=self.target_product, tags=[u'tag-first'])
         view = create_view(
             self.project_group,
             name="+bugtarget-portlet-tags-content")
diff --git a/lib/lp/bugs/doc/bug-tags.txt b/lib/lp/bugs/doc/bug-tags.txt
index 3fcc170..8448b71 100644
--- a/lib/lp/bugs/doc/bug-tags.txt
+++ b/lib/lp/bugs/doc/bug-tags.txt
@@ -23,7 +23,9 @@ Under the hood the tags are stored in a different table. If we take a
 look at it we can see that the added tags are there.
 
     >>> from lp.bugs.model.bug import BugTag
-    >>> bugtags = BugTag.selectBy(bugID=bug_one.id, orderBy='tag')
+    >>> from lp.services.database.interfaces import IStore
+    >>> bugtags = IStore(BugTag).find(
+    ...     BugTag, bug_id=bug_one.id).order_by(BugTag.tag)
     >>> for bugtag in bugtags:
     ...     print(bugtag.tag)
     sco
@@ -35,8 +37,11 @@ The tag will be added in the table.
     >>> bug_one.tags = [u'svg', u'sco', u'installl']
     >>> bug_one.tags
     [u'installl', u'sco', u'svg']
-
-    >>> bugtags = BugTag.selectBy(bugID=bug_one.id, orderBy='tag')
+    >>> from lp.services.database.interfaces import IStore
+    >>> bugtags = IStore(BugTag).find(
+    ...     BugTag, bug_id=bug_one.id).order_by(BugTag.tag)
+    >>> bugtags = IStore(BugTag).find(
+    ...     BugTag, bug_id=bug_one.id).order_by(BugTag.tag)
     >>> for bugtag in bugtags:
     ...     print(bugtag.tag)
     installl
@@ -56,7 +61,9 @@ Let's correct the spelling mistake we did and delete one of the tags:
     >>> bug_one.tags
     [u'install', u'sco']
 
-    >>> bugtags = BugTag.selectBy(bugID=bug_one.id, orderBy='tag')
+    >>> from lp.services.database.interfaces import IStore
+    >>> bugtags = IStore(BugTag).find(
+    ...     BugTag, bug_id=bug_one.id).order_by(BugTag.tag)
     >>> for bugtag in bugtags:
     ...     print(bugtag.tag)
     install
diff --git a/lib/lp/bugs/model/bug.py b/lib/lp/bugs/model/bug.py
index d52869a..c1e35a1 100644
--- a/lib/lp/bugs/model/bug.py
+++ b/lib/lp/bugs/model/bug.py
@@ -66,6 +66,7 @@ from storm.locals import (
     Reference,
     ReferenceSet,
     )
+from storm.properties import Unicode
 from storm.store import (
     EmptyResultSet,
     Store,
@@ -247,11 +248,23 @@ def snapshot_bug_params(bug_params):
             "importance", "milestone", "assignee", "cve"])
 
 
-class BugTag(SQLBase):
+class BugTag(StormBase):
     """A tag belonging to a bug."""
+    __storm_table__ = 'BugTag'
+    id = Int(primary=True)
 
     bug = ForeignKey(dbName='bug', foreignKey='Bug', notNull=True)
-    tag = StringCol(notNull=True)
+    bug_id = Int(name='bug', allow_none=False)
+    bug = Reference(bug_id, 'Bug.id')
+
+    tag = Unicode(allow_none=False)
+
+    def __init__(self, bug, tag):
+        self.bug = bug
+        self.tag = tag
+
+    def destroySelf(self):
+        Store.of(self).remove(self)
 
 
 def get_bug_tags_open_count(context_condition, user, tag_limit=0,
@@ -1849,7 +1862,7 @@ class Bug(SQLBase, InformationTypeMixin):
     @cachedproperty
     def _cached_tags(self):
         return list(Store.of(self).find(
-            BugTag.tag, BugTag.bugID == self.id).order_by(BugTag.tag))
+            BugTag.tag, BugTag.bug_id == self.id).order_by(BugTag.tag))
 
     def _setTags(self, tags):
         """Set the tags from a list of strings."""
@@ -1862,7 +1875,9 @@ class Bug(SQLBase, InformationTypeMixin):
         # Find the set of tags that are to be removed and remove them.
         removed_tags = old_tags.difference(new_tags)
         for removed_tag in removed_tags:
-            tag = BugTag.selectOneBy(bug=self, tag=removed_tag)
+            tag = IStore(BugTag).find(
+                BugTag,
+                bug=self, tag=removed_tag).one()
             tag.destroySelf()
         # Find the set of tags that are to be added and add them.
         added_tags = new_tags.difference(old_tags)
diff --git a/lib/lp/bugs/model/bugtask.py b/lib/lp/bugs/model/bugtask.py
index 4cd5a7b..fb2bfee 100644
--- a/lib/lp/bugs/model/bugtask.py
+++ b/lib/lp/bugs/model/bugtask.py
@@ -1363,7 +1363,7 @@ class BugTaskSet:
             (BugTag.tag, BugTask.id),
             BugTask.bug == Bug.id,
             BugTag.bug == Bug.id,
-            BugTag.bugID.is_in(bug_ids),
+            BugTag.bug_id.is_in(bug_ids),
             BugTask.id.is_in(bugtask_ids)).order_by(BugTag.tag)
         tags_by_bugtask = defaultdict(list)
         for tag_name, bugtask_id in tags:
diff --git a/lib/lp/bugs/model/bugtasksearch.py b/lib/lp/bugs/model/bugtasksearch.py
index 3335442..15a489d 100644
--- a/lib/lp/bugs/model/bugtasksearch.py
+++ b/lib/lp/bugs/model/bugtasksearch.py
@@ -168,7 +168,7 @@ orderby_expression = {
                     # tag that comes first in alphabetic order.
                     BugTag.id == Select(
                         BugTag.id, tables=[BugTag],
-                        where=(BugTag.bugID == BugTaskFlat.bug_id),
+                        where=(BugTag.bug_id == BugTaskFlat.bug_id),
                         order_by=BugTag.tag, limit=1))),
             ]
         ),
@@ -1223,7 +1223,7 @@ def _build_upstream_clause(params):
 def _build_tag_set_query(clauses):
     subselects = [
         Select(
-            1, tables=[BugTag], where=And(BugTag.bugID == BugTaskFlat.bug_id,
+            1, tables=[BugTag], where=And(BugTag.bug_id == BugTaskFlat.bug_id,
             clause))
         for clause in clauses]
     if len(subselects) == 1:
@@ -1295,7 +1295,7 @@ def _build_tag_search_clause(tags_spec):
 
     universal_clause = (
         Exists(Select(
-            1, tables=[BugTag], where=BugTag.bugID == BugTaskFlat.bug_id)))
+            1, tables=[BugTag], where=BugTag.bug_id == BugTaskFlat.bug_id)))
 
     # Search for the *presence* of any tag.
     if '*' in wildcards:
diff --git a/lib/lp/bugs/scripts/bugsummaryrebuild.py b/lib/lp/bugs/scripts/bugsummaryrebuild.py
index f000905..3537a98 100644
--- a/lib/lp/bugs/scripts/bugsummaryrebuild.py
+++ b/lib/lp/bugs/scripts/bugsummaryrebuild.py
@@ -286,7 +286,7 @@ def calculate_bugsummary_rows(target):
     null_viewed_by = Alias(Cast(None, 'integer'), 'viewed_by')
     null_policy = Alias(Cast(None, 'integer'), 'access_policy')
 
-    tag_join = Join(BugTag, BugTag.bugID == RelevantTask.bug_id)
+    tag_join = Join(BugTag, BugTag.bug_id == RelevantTask.bug_id)
 
     public_constraint = RelevantTask.information_type.is_in(
         PUBLIC_INFORMATION_TYPES)
diff --git a/lib/lp/bugs/tests/test_searchtasks_webservice.py b/lib/lp/bugs/tests/test_searchtasks_webservice.py
index 1a0ee93..40e5b32 100644
--- a/lib/lp/bugs/tests/test_searchtasks_webservice.py
+++ b/lib/lp/bugs/tests/test_searchtasks_webservice.py
@@ -132,14 +132,17 @@ class TestMaloneApplicationSearchTasks(TestCaseWithFactory):
     def test_global_search_by_tag(self):
         project1 = self.factory.makeProduct()
         project2 = self.factory.makeProduct()
-        bug1 = self.factory.makeBug(target=project1, tags=["foo"])
-        self.factory.makeBug(target=project1, tags=["bar"])
-        bug3 = self.factory.makeBug(target=project2, tags=["foo"])
-        self.factory.makeBug(target=project2, tags=["baz"])
+        bug1 = self.factory.makeBug(target=project1, tags=[u'foo'])
+        self.factory.makeBug(target=project1, tags=[u'bar'])
+        bug3 = self.factory.makeBug(target=project2, tags=[u'foo'])
+        self.factory.makeBug(target=project2, tags=[u'baz'])
         webservice = LaunchpadWebServiceCaller(
             "launchpad-library", "salgado-change-anything")
         response = webservice.named_get(
-            "/bugs", "searchTasks", api_version="devel", tags="foo").jsonBody()
+            "/bugs",
+            "searchTasks",
+            api_version="devel",
+            tags=u'foo').jsonBody()
         self.assertEqual(2, response["total_size"])
         self.assertContentEqual(
             [bug1.id, bug3.id],
diff --git a/lib/lp/bugs/tests/test_structuralsubscription.py b/lib/lp/bugs/tests/test_structuralsubscription.py
index cb648d4..6ca025b 100644
--- a/lib/lp/bugs/tests/test_structuralsubscription.py
+++ b/lib/lp/bugs/tests/test_structuralsubscription.py
@@ -241,7 +241,7 @@ class FilteredStructuralSubscriptionTestBase:
         self.assertSubscribers([])
 
         # With any tag the subscription is found.
-        self.bug.tags = ["foo"]
+        self.bug.tags = [u'foo']
         self.assertSubscribers([self.ordinary_subscriber])
 
     def test_getStructuralSubscribers_with_filter_exclude_any_tags(self):
@@ -254,7 +254,7 @@ class FilteredStructuralSubscriptionTestBase:
         self.assertSubscribers([self.ordinary_subscriber])
 
         # With any tag the subscription is not found.
-        self.bug.tags = ["foo"]
+        self.bug.tags = [u'foo']
         self.assertSubscribers([])
 
     def test_getStructuralSubscribers_with_filter_for_any_tag(self):
@@ -262,14 +262,14 @@ class FilteredStructuralSubscriptionTestBase:
         # tags must be present, bugs with any of those tags are matched.
 
         # Looking for either the "foo" or the "bar" tag.
-        self.initial_filter.tags = [u"foo", u"bar"]
+        self.initial_filter.tags = [u'foo', u'bar']
         self.initial_filter.find_all_tags = False
 
         # Without either tag the subscription is not found.
         self.assertSubscribers([])
 
         # With either tag the subscription is found.
-        self.bug.tags = ["bar", "baz"]
+        self.bug.tags = [u'bar', u'baz']
         self.assertSubscribers([self.ordinary_subscriber])
 
     def test_getStructuralSubscribers_with_filter_for_all_tags(self):
@@ -277,18 +277,18 @@ class FilteredStructuralSubscriptionTestBase:
         # tags must be present, bugs with all of those tags are matched.
 
         # Looking for both the "foo" and the "bar" tag.
-        self.initial_filter.tags = [u"foo", u"bar"]
+        self.initial_filter.tags = [u'foo', u'bar']
         self.initial_filter.find_all_tags = True
 
         # Without either tag the subscription is not found.
         self.assertSubscribers([])
 
         # Without only one of the required tags the subscription is not found.
-        self.bug.tags = ["foo"]
+        self.bug.tags = [u'foo']
         self.assertSubscribers([])
 
         # With both required tags the subscription is found.
-        self.bug.tags = ["foo", "bar"]
+        self.bug.tags = [u'foo', u'bar']
         self.assertSubscribers([self.ordinary_subscriber])
 
     def test_getStructuralSubscribers_with_filter_for_not_any_tag(self):
@@ -304,11 +304,11 @@ class FilteredStructuralSubscriptionTestBase:
         self.assertSubscribers([self.ordinary_subscriber])
 
         # With both tags, the subscription is omitted.
-        self.bug.tags = ["foo", "bar"]
+        self.bug.tags = [u'foo', u'bar']
         self.assertSubscribers([])
 
         # With only one tag, the subscription is found again.
-        self.bug.tags = ["foo"]
+        self.bug.tags = [u'foo']
         self.assertSubscribers([self.ordinary_subscriber])
 
         # However, if find_all_tags is True, even a single excluded tag
@@ -317,7 +317,7 @@ class FilteredStructuralSubscriptionTestBase:
         self.assertSubscribers([])
 
         # This is also true, of course, if the bug has both tags.
-        self.bug.tags = ["foo", "bar"]
+        self.bug.tags = [u'foo', u'bar']
         self.assertSubscribers([])
 
     def test_getStructuralSubscribers_with_filter_for_not_all_tags(self):
@@ -326,7 +326,7 @@ class FilteredStructuralSubscriptionTestBase:
         # matched.
 
         # Looking to exclude the "foo" and "bar" tags.
-        self.initial_filter.tags = [u"-foo", u"-bar"]
+        self.initial_filter.tags = [u'-foo', u'-bar']
         self.initial_filter.find_all_tags = True
 
         # Without either tag the subscription is found.
@@ -335,11 +335,11 @@ class FilteredStructuralSubscriptionTestBase:
         # With only one of the excluded tags the subscription is not
         # found--we are saying that we want to find both an absence of foo
         # and an absence of bar, and yet foo exists.
-        self.bug.tags = ["foo"]
+        self.bug.tags = [u'foo']
         self.assertSubscribers([])
 
         # With both tags the subscription is also not found.
-        self.bug.tags = ["foo", "bar"]
+        self.bug.tags = [u'foo', u'bar']
         self.assertSubscribers([])
 
     def test_getStructuralSubscribers_with_multiple_filters(self):
@@ -347,7 +347,7 @@ class FilteredStructuralSubscriptionTestBase:
         # match.
 
         # Add the "foo" tag to the bug.
-        self.bug.tags = ["foo"]
+        self.bug.tags = [u'foo']
         self.assertSubscribers([self.ordinary_subscriber])
 
         # Filter the subscription to bugs in the CRITICAL state.
@@ -369,13 +369,13 @@ class FilteredStructuralSubscriptionTestBase:
 
         # If the filter is given some tag criteria, the subscription is not
         # found.
-        self.initial_filter.tags = [u"-foo", u"bar", u"baz"]
+        self.initial_filter.tags = [u'-foo', u'bar', u'baz']
         self.initial_filter.find_all_tags = False
         self.assertSubscribers([])
 
         # After removing the "foo" tag and adding the "bar" tag, the
         # subscription is found.
-        self.bug.tags = ["bar"]
+        self.bug.tags = [u'bar']
         self.assertSubscribers([self.ordinary_subscriber])
 
         # Requiring that all tag criteria are fulfilled causes the
@@ -384,7 +384,7 @@ class FilteredStructuralSubscriptionTestBase:
         self.assertSubscribers([])
 
         # After adding the "baz" tag, the subscription is found again.
-        self.bug.tags = ["bar", "baz"]
+        self.bug.tags = [u'bar', u'baz']
         self.assertSubscribers([self.ordinary_subscriber])
 
     def test_getStructuralSubscribers_any_filter_is_a_match(self):
@@ -394,7 +394,7 @@ class FilteredStructuralSubscriptionTestBase:
         subscription_filter1 = self.initial_filter
         subscription_filter1.statuses = [BugTaskStatus.CONFIRMED]
         subscription_filter2 = self.subscription.newBugFilter()
-        subscription_filter2.tags = [u"foo"]
+        subscription_filter2.tags = [u'foo']
 
         # With the filter the subscription is not found.
         self.assertSubscribers([])
@@ -407,7 +407,7 @@ class FilteredStructuralSubscriptionTestBase:
 
         # If the filter is adjusted to also match the criteria of the second
         # filter, the subscription is still found.
-        self.bugtask.bug.tags = [u"foo"]
+        self.bugtask.bug.tags = [u'foo']
         self.assertSubscribers([self.ordinary_subscriber])
 
         # If the bugtask is adjusted to no longer match the criteria of the