launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #28567
[Merge] ~cjwatson/launchpad:stormify-bugattachment into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:stormify-bugattachment into launchpad:master.
Commit message:
Migrate BugAttachment to Storm
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/424282
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:stormify-bugattachment into launchpad:master.
diff --git a/lib/lp/bugs/browser/bugtask.py b/lib/lp/bugs/browser/bugtask.py
index 14f37aa..7228fc7 100644
--- a/lib/lp/bugs/browser/bugtask.py
+++ b/lib/lp/bugs/browser/bugtask.py
@@ -242,7 +242,7 @@ def get_comments_for_bugtask(bugtask, truncate=False, for_display=False,
get_property_cache(comment._message).bugattachments = []
for attachment in bugtask.bug.attachments_unpopulated:
- message_id = attachment._messageID
+ message_id = attachment._message_id
if message_id not in comments:
# We are not showing this message.
continue
diff --git a/lib/lp/bugs/doc/bug-export.txt b/lib/lp/bugs/doc/bug-export.txt
index b0736e2..c78c506 100644
--- a/lib/lp/bugs/doc/bug-export.txt
+++ b/lib/lp/bugs/doc/bug-export.txt
@@ -140,7 +140,7 @@ the file when we later serialise the bug:
>>> bug4.addAttachment(
... sampleperson, io.BytesIO(b'Hello World'), 'Added attachment',
... 'hello.txt', description='"Hello World" attachment')
- <BugAttachment ...>
+ <lp.bugs.model.bugattachment.BugAttachment ...>
>>> transaction.commit()
diff --git a/lib/lp/bugs/doc/bugattachments.txt b/lib/lp/bugs/doc/bugattachments.txt
index 2b63a94..385e8f2 100644
--- a/lib/lp/bugs/doc/bugattachments.txt
+++ b/lib/lp/bugs/doc/bugattachments.txt
@@ -54,7 +54,7 @@ ObjectCreatedEvent in order to trigger email notifications:
... comment=message,
... is_patch=False)
Attachment added: 'foo.bar'
- <BugAttachment ...>
+ <lp.bugs.model.bugattachment.BugAttachment ...>
>>> import transaction
>>> transaction.commit()
@@ -549,7 +549,7 @@ LibraryFileAlias.restricted and Bug.private. See also the section
>>> bug.linkAttachment(
... owner=bug.owner, file_alias=file_alias,
... comment="Some attachment")
- <BugAttachment ...>
+ <lp.bugs.model.bugattachment.BugAttachment ...>
>>> bug.attachments.count()
1
@@ -575,7 +575,7 @@ meaningful description.
... owner=bug.owner, file_alias=file_alias,
... comment="Some attachment", is_patch=True,
... description="An attachment of some sort")
- <BugAttachment ...>
+ <lp.bugs.model.bugattachment.BugAttachment ...>
>>> bug.attachments.count()
2
diff --git a/lib/lp/bugs/interfaces/bugattachment.py b/lib/lp/bugs/interfaces/bugattachment.py
index 25ee2af..ef93552 100644
--- a/lib/lp/bugs/interfaces/bugattachment.py
+++ b/lib/lp/bugs/interfaces/bugattachment.py
@@ -81,13 +81,12 @@ class IBugAttachmentView(IHasBug):
description=_(
'A short and descriptive description of the attachment'),
required=True))
- libraryfile = Bytes(title=_("The attachment content."),
- required=True)
- data = exported(
+ libraryfile = exported(
Bytes(title=_("The attachment content."),
required=True,
- readonly=True))
- _messageID = Int(title=_("Message ID"))
+ readonly=True),
+ exported_as="data")
+ _message_id = Int(title=_("Message ID"))
message = exported(
Reference(IMessage, title=_("The message that was created when we "
"added this attachment.")))
@@ -100,7 +99,7 @@ class IBugAttachmentView(IHasBug):
"""Return the `ILibraryFileAlias` for the given file name.
NotFoundError is raised if the given filename does not match
- libraryfile.filename.
+ data.filename.
"""
@@ -128,14 +127,14 @@ class IBugAttachment(IBugAttachmentView, IBugAttachmentEdit):
for attachment in bug.attachments:
buffer = attachment.data.open()
for line in buffer:
- print line
+ print(line)
buffer.close()
Launchpadlib example of accessing metadata about an attachment::
attachment = bug.attachments[0]
- print "title:", attachment.title
- print "ispatch:", attachment.type
+ print("title:", attachment.title)
+ print("ispatch:", attachment.type)
For information about the file-like object returned by
attachment.data.open() see lazr.restfulclient's documentation of the
@@ -145,9 +144,9 @@ class IBugAttachment(IBugAttachmentView, IBugAttachmentEdit):
the "message" attribute::
message = attachment.message
- print "subject:", message.subject.encode('utf-8')
- print "owner:", message.owner.display_name.encode('utf-8')
- print "created:", message.date_created
+ print("subject:", message.subject)
+ print("owner:", message.owner.display_name)
+ print("created:", message.date_created)
"""
diff --git a/lib/lp/bugs/model/bug.py b/lib/lp/bugs/model/bug.py
index 3f9bc62..4ae8c4e 100644
--- a/lib/lp/bugs/model/bug.py
+++ b/lib/lp/bugs/model/bug.py
@@ -2184,7 +2184,7 @@ class Bug(SQLBase, InformationTypeMixin):
return store.find(
(BugAttachment, LibraryFileAlias, LibraryFileContent),
BugAttachment.bug == self,
- BugAttachment.libraryfileID == LibraryFileAlias.id,
+ BugAttachment.libraryfile == LibraryFileAlias.id,
LibraryFileContent.id == LibraryFileAlias.contentID,
).order_by(BugAttachment.id)
@@ -2207,7 +2207,7 @@ class Bug(SQLBase, InformationTypeMixin):
attachment = row[0]
# row[1] - the LibraryFileAlias is now in the storm cache and
# will be found without a query when dereferenced.
- indexed_message = message_to_indexed.get(attachment._messageID)
+ indexed_message = message_to_indexed.get(attachment._message_id)
if indexed_message is not None:
get_property_cache(attachment).message = indexed_message
return attachment
diff --git a/lib/lp/bugs/model/bugattachment.py b/lib/lp/bugs/model/bugattachment.py
index d200d3d..1aa211b 100644
--- a/lib/lp/bugs/model/bugattachment.py
+++ b/lib/lp/bugs/model/bugattachment.py
@@ -7,7 +7,12 @@ from lazr.lifecycle.event import (
ObjectCreatedEvent,
ObjectDeletedEvent,
)
-from storm.store import Store
+from storm.locals import (
+ Int,
+ Reference,
+ Store,
+ Unicode,
+ )
from zope.event import notify
from zope.interface import implementer
@@ -18,33 +23,38 @@ from lp.bugs.interfaces.bugattachment import (
IBugAttachmentSet,
)
from lp.services.database.enumcol import DBEnum
-from lp.services.database.sqlbase import SQLBase
-from lp.services.database.sqlobject import (
- ForeignKey,
- SQLObjectNotFound,
- StringCol,
- )
+from lp.services.database.interfaces import IStore
+from lp.services.database.stormbase import StormBase
from lp.services.propertycache import cachedproperty
@implementer(IBugAttachment)
-class BugAttachment(SQLBase):
+class BugAttachment(StormBase):
"""A bug attachment."""
- _table = 'BugAttachment'
+ __storm_table__ = "BugAttachment"
- bug = ForeignKey(
- foreignKey='Bug', dbName='bug', notNull=True)
+ id = Int(primary=True)
+
+ bug_id = Int(name="bug", allow_none=False)
+ bug = Reference(bug_id, "Bug.id")
type = DBEnum(
enum=BugAttachmentType, allow_none=False,
default=IBugAttachment['type'].default)
- title = StringCol(notNull=True)
- libraryfile = ForeignKey(
- foreignKey='LibraryFileAlias', dbName='libraryfile', notNull=True)
- data = ForeignKey(
- foreignKey='LibraryFileAlias', dbName='libraryfile', notNull=True)
- _message = ForeignKey(
- foreignKey='Message', dbName='message', notNull=True)
+ title = Unicode(allow_none=False)
+ libraryfile_id = Int(name="libraryfile", allow_none=False)
+ libraryfile = Reference(libraryfile_id, "LibraryFileAlias.id")
+ _message_id = Int(name="message", allow_none=False)
+ _message = Reference(_message_id, "Message.id")
+
+ def __init__(self, bug, title, libraryfile, message,
+ type=IBugAttachment["type"].default):
+ super().__init__()
+ self.bug = bug
+ self.title = title
+ self.libraryfile = libraryfile
+ self._message = message
+ self.type = type
@cachedproperty
def message(self):
@@ -72,7 +82,7 @@ class BugAttachment(SQLBase):
# in order to avoid problems with not deleted files as described
# in bug 387188.
self.libraryfile.content = None
- super().destroySelf()
+ Store.of(self).remove(self)
def getFileByName(self, filename):
"""See IBugAttachment."""
@@ -91,9 +101,8 @@ class BugAttachmentSet:
attach_id = int(attach_id)
except ValueError:
raise NotFoundError(attach_id)
- try:
- item = BugAttachment.get(attach_id)
- except SQLObjectNotFound:
+ item = IStore(BugAttachment).get(BugAttachment, attach_id)
+ if item is None:
raise NotFoundError(attach_id)
return item
@@ -105,7 +114,7 @@ class BugAttachmentSet:
attach_type = IBugAttachment['type'].default
attachment = BugAttachment(
bug=bug, libraryfile=filealias, type=attach_type, title=title,
- _message=message)
+ message=message)
# canonial_url(attachment) (called by notification subscribers
# to generate the download URL of the attachments) blows up if
# attachment.id is not (yet) set.
diff --git a/lib/lp/bugs/model/bugtasksearch.py b/lib/lp/bugs/model/bugtasksearch.py
index db6b3f2..d0089e4 100644
--- a/lib/lp/bugs/model/bugtasksearch.py
+++ b/lib/lp/bugs/model/bugtasksearch.py
@@ -444,7 +444,7 @@ def _build_query(params):
extra_clauses.append(
BugTaskFlat.bug_id.is_in(
Select(
- BugAttachment.bugID, tables=[BugAttachment],
+ BugAttachment.bug_id, tables=[BugAttachment],
where=search_value_to_storm_where_condition(
BugAttachment.type, params.attachmenttype))))
diff --git a/lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt b/lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt
index 1e818e2..3ffdd6d 100644
--- a/lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt
+++ b/lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt
@@ -300,7 +300,7 @@ Patches also appear as badges in bug listings.
... description="this fixes the bug",
... comment=message,
... is_patch=True)
- <BugAttachment at ...>
+ <lp.bugs.model.bugattachment.BugAttachment object at ...>
>>> transaction.commit()
>>> logout()
>>> browser.open('http://bugs.launchpad.test/firefox/+bugs')
diff --git a/lib/lp/bugs/stories/patches-view/patches-view.txt b/lib/lp/bugs/stories/patches-view/patches-view.txt
index e90e90d..934bf4c 100644
--- a/lib/lp/bugs/stories/patches-view/patches-view.txt
+++ b/lib/lp/bugs/stories/patches-view/patches-view.txt
@@ -59,7 +59,7 @@ After we add a non-patch attachment to that bug, the patches view
still shows no patches.
>>> with_anybody(factory.makeBugAttachment)(bug=bug_a, is_patch=False)
- <BugAttachment at...
+ <lp.bugs.model.bugattachment.BugAttachment object at...
>>> transaction.commit()
>>> anon_browser.open(
... 'http://bugs.launchpad.test/patchy-product-1/+patches')
@@ -76,7 +76,7 @@ patches view.
... comment="comment about patch a",
... filename="patch_a.diff", owner=patch_submitter,
... description="description of patch a", bug=bug_a, is_patch=True)
- <BugAttachment at...
+ <lp.bugs.model.bugattachment.BugAttachment object at...
>>> transaction.commit()
>>> anon_browser.open(
... 'http://bugs.launchpad.test/patchy-product-1/+patches')
@@ -112,40 +112,40 @@ attachments, and various statuses...
... comment="comment about patch b",
... filename="patch_b.diff", owner=patch_submitter,
... description="description of patch b", bug=bug_b, is_patch=True)
- <BugAttachment at...
+ <lp.bugs.model.bugattachment.BugAttachment object at...
>>> transaction.commit()
>>> with_anybody(factory.makeBugAttachment)(
... comment="comment about patch c",
... filename="patch_c.diff", owner=patch_submitter,
... description="description of patch c", bug=bug_b, is_patch=True)
- <BugAttachment at...
+ <lp.bugs.model.bugattachment.BugAttachment object at...
>>> transaction.commit()
>>> with_anybody(factory.makeBugAttachment)(bug=bug_c, is_patch=False)
- <BugAttachment at...
+ <lp.bugs.model.bugattachment.BugAttachment object at...
>>> transaction.commit()
>>> with_anybody(factory.makeBugAttachment)(
... comment="comment about patch d",
... filename="patch_d.diff", owner=patch_submitter,
... description="description of patch d", bug=bug_c, is_patch=True)
- <BugAttachment at...
+ <lp.bugs.model.bugattachment.BugAttachment object at...
>>> transaction.commit()
>>> with_anybody(factory.makeBugAttachment)(
... comment="comment about patch e",
... filename="patch_e.diff", owner=patch_submitter,
... description="description of patch e", bug=bug_c, is_patch=True)
- <BugAttachment at...
+ <lp.bugs.model.bugattachment.BugAttachment object at...
>>> transaction.commit()
>>> with_anybody(factory.makeBugAttachment)(
... comment="comment about patch f",
... filename="patch_f.diff", owner=patch_submitter,
... description="description of patch f", bug=bug_c, is_patch=True)
- <BugAttachment at...
+ <lp.bugs.model.bugattachment.BugAttachment object at...
>>> transaction.commit()
>>> with_anybody(factory.makeBugAttachment)(
... comment="comment about patch g",
... filename="patch_g.diff", owner=patch_submitter,
... description="description of patch g", bug=bug_d, is_patch=True)
- <BugAttachment at...
+ <lp.bugs.model.bugattachment.BugAttachment object at...
>>> transaction.commit()
...the youngest patch on each bug is visible in the patch report
diff --git a/lib/lp/bugs/tests/test_bugchanges.py b/lib/lp/bugs/tests/test_bugchanges.py
index e89383f..0b017cc 100644
--- a/lib/lp/bugs/tests/test_bugchanges.py
+++ b/lib/lp/bugs/tests/test_bugchanges.py
@@ -871,6 +871,7 @@ class TestBugChanges(TestCaseWithFactory):
# and BugNotification.
attachment = self.factory.makeBugAttachment(
bug=self.bug, owner=self.user)
+ attachment_title = attachment.title
self.saveOldChanges()
download_url = ProxiedLibraryFileAlias(
attachment.libraryfile, attachment).http_url
@@ -887,13 +888,13 @@ class TestBugChanges(TestCaseWithFactory):
'whatchanged': 'attachment removed',
'newvalue': None,
'oldvalue': '%s %s' % (
- attachment.title, download_url),
+ attachment_title, download_url),
}
attachment_removed_notification = {
'person': self.user,
'text': '** Attachment removed: "%s"\n %s' % (
- attachment.title, download_url),
+ attachment_title, download_url),
}
self.assertRecordedChange(
diff --git a/lib/lp/services/messages/model/message.py b/lib/lp/services/messages/model/message.py
index 102a813..4b4b86b 100644
--- a/lib/lp/services/messages/model/message.py
+++ b/lib/lp/services/messages/model/message.py
@@ -35,6 +35,7 @@ from storm.locals import (
Int,
Max,
Reference,
+ ReferenceSet,
Store,
Storm,
Unicode,
@@ -126,7 +127,8 @@ class Message(SQLBase):
raw = ForeignKey(foreignKey='LibraryFileAlias', dbName='raw',
default=None)
- _bugattachments = SQLMultipleJoin('BugAttachment', joinColumn='_message')
+ _bugattachments = ReferenceSet(
+ "<primary key>", "BugAttachment._message_id")
@cachedproperty
def bugattachments(self):