← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/snapshot-modifying-helper-use-bugs-doctests into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/snapshot-modifying-helper-use-bugs-doctests into lp:launchpad.

Commit message:
Convert doctests under lp.bugs to notify_modified.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/snapshot-modifying-helper-use-bugs-doctests/+merge/361257
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/snapshot-modifying-helper-use-bugs-doctests into lp:launchpad.
=== modified file 'lib/lp/bugs/doc/bug.txt'
--- lib/lp/bugs/doc/bug.txt	2018-06-29 23:10:57 +0000
+++ lib/lp/bugs/doc/bug.txt	2018-12-21 23:02:24 +0000
@@ -210,19 +210,11 @@
 
 We must use setPrivate:
 
-    >>> from zope.event import notify
-    >>> from lazr.lifecycle.event import (
-    ...     ObjectModifiedEvent, ObjectCreatedEvent)
-    >>> from lazr.lifecycle.snapshot import Snapshot
+    >>> from lp.services.webapp.snapshot import notify_modified
 
-    >>> old_state = Snapshot(firefox_crashes, providing=IBug)
-    >>> firefox_crashes.setPrivate(True, current_user())
+    >>> with notify_modified(firefox_crashes, ["id", "title", "private"]):
+    ...     firefox_crashes.setPrivate(True, current_user())
     True
-    >>> bug_set_private = ObjectModifiedEvent(
-    ...     firefox_crashes, old_state,
-    ...     ["id", "title", "private"])
-
-    >>> notify(bug_set_private)
     >>> flush_database_updates()
 
 Trying to mark a private bug as private is a no-op, as is marking a
@@ -297,14 +289,9 @@
 
 And again, let's fake setting the bug private:
 
-    >>> old_state = Snapshot(reflow_problems_bug, providing=IBug)
-    >>> reflow_problems_bug.setPrivate(True, current_user())
+    >>> with notify_modified(reflow_problems_bug, ["id", "title", "private"]):
+    ...     reflow_problems_bug.setPrivate(True, current_user())
     True
-    >>> bug_set_private = ObjectModifiedEvent(
-    ...     reflow_problems_bug, old_state,
-    ...     ["id", "title", "private"])
-
-    >>> notify(bug_set_private)
     >>> flush_database_updates()
 
 Then let's permit the Ubuntu Team to access this bug by adding them to
@@ -495,34 +482,20 @@
 
 Changing the bug summary.
 
-    >>> from lp.bugs.interfaces.bug import IBug
-
-    >>> bug_before_modification = Snapshot(firefox_bug, providing=IBug)
-
-    >>> firefox_bug.title = "a new title"
-
-    >>> bug_summary_changed = ObjectModifiedEvent(
-    ...     firefox_bug, bug_before_modification, ["title"])
-
     >>> current_date_last_updated = firefox_bug.date_last_updated
 
-    >>> notify(bug_summary_changed)
+    >>> with notify_modified(firefox_bug, ["title"]):
+    ...     firefox_bug.title = "a new title"
 
     >>> firefox_bug.date_last_updated > current_date_last_updated
     True
 
 Changing the description.
 
-    >>> bug_before_modification = Snapshot(firefox_bug, providing=IBug)
-
-    >>> firefox_bug.description = "a new description"
-
-    >>> bug_description_changed = ObjectModifiedEvent(
-    ...     firefox_bug, bug_before_modification, ["description"])
-
     >>> current_date_last_updated = firefox_bug.date_last_updated
 
-    >>> notify(bug_description_changed)
+    >>> with notify_modified(firefox_bug, ["description"]):
+    ...     firefox_bug.description = "a new description"
 
     >>> firefox_bug.date_last_updated > current_date_last_updated
     True
@@ -530,7 +503,7 @@
 Modifying a bugtask will update IBug.date_last_updated.
 
     >>> from lp.bugs.interfaces.bugtask import (
-    ...     BugTaskImportance, BugTaskStatus, IBugTask)
+    ...     BugTaskImportance, BugTaskStatus)
 
     >>> firefox_task = firefox_bug.bugtasks[0]
 
@@ -542,27 +515,21 @@
     >>> print(firefox_task.status.title)
     New
 
-    >>> bugtask_before_modification = Snapshot(
-    ...     firefox_task, providing=IBugTask)
-
-    >>> firefox_task.transitionToImportance(
-    ...     BugTaskImportance.CRITICAL, current_user())
-    >>> firefox_task.transitionToStatus(
-    ...     BugTaskStatus.CONFIRMED, current_user())
-
-    >>> bugtask_modified = ObjectModifiedEvent(
-    ...     firefox_task, bugtask_before_modification,
-    ...     ["status", "importance"])
-
     >>> current_date_last_updated = firefox_bug.date_last_updated
 
-    >>> notify(bugtask_modified)
+    >>> with notify_modified(firefox_task, ["status", "importance"]):
+    ...     firefox_task.transitionToImportance(
+    ...         BugTaskImportance.CRITICAL, current_user())
+    ...     firefox_task.transitionToStatus(
+    ...         BugTaskStatus.CONFIRMED, current_user())
 
     >>> firefox_bug.date_last_updated > current_date_last_updated
     True
 
 Adding a new task.
 
+    >>> from zope.event import notify
+    >>> from lazr.lifecycle.event import ObjectCreatedEvent
     >>> from lp.bugs.interfaces.bugtask import IBugTaskSet
 
     >>> thunderbird = productset.getByName("thunderbird")
@@ -656,56 +623,41 @@
 
 Changing bug visibility.
 
-    >>> bug_before_modification = Snapshot(firefox_bug, providing=IBug)
-
     >>> firefox_bug.private
     False
-    >>> firefox_bug.setPrivate(True, current_user())
-    True
-
-    >>> bug_visibility_changed = ObjectModifiedEvent(
-    ...     firefox_bug, bug_before_modification, ["private"])
 
     >>> current_date_last_updated = firefox_bug.date_last_updated
 
-    >>> notify(bug_visibility_changed)
+    >>> with notify_modified(firefox_bug, ["private"]):
+    ...     firefox_bug.setPrivate(True, current_user())
+    True
 
     >>> firefox_bug.date_last_updated > current_date_last_updated
     True
 
 Changing bug security.
 
-    >>> bug_before_modification = Snapshot(firefox_bug, providing=IBug)
-
     >>> firefox_bug.security_related
     False
-    >>> changed = firefox_bug.setSecurityRelated(True,
-    ...     getUtility(ILaunchBag).user)
-
-    >>> bug_security_changed = ObjectModifiedEvent(
-    ...     firefox_bug, bug_before_modification, ["security_related"])
 
     >>> current_date_last_updated = firefox_bug.date_last_updated
 
-    >>> notify(bug_security_changed)
+    >>> with notify_modified(firefox_bug, ["security_related"]):
+    ...     changed = firefox_bug.setSecurityRelated(
+    ...         True, getUtility(ILaunchBag).user)
 
     >>> firefox_bug.date_last_updated > current_date_last_updated
     True
 
 Marking as duplicate.
 
-    >>> bug_before_modification = Snapshot(firefox_bug, providing=IBug)
-
     >>> print(firefox_bug.duplicateof)
     None
-    >>> firefox_bug.markAsDuplicate(factory.makeBug())
-
-    >>> bug_duplicateof_changed = ObjectModifiedEvent(
-    ...     firefox_bug, bug_before_modification, ["duplicateof"])
 
     >>> current_date_last_updated = firefox_bug.date_last_updated
 
-    >>> notify(bug_duplicateof_changed)
+    >>> with notify_modified(firefox_bug, ["duplicateof"]):
+    ...     firefox_bug.markAsDuplicate(factory.makeBug())
 
     >>> firefox_bug.date_last_updated > current_date_last_updated
     True
@@ -749,20 +701,10 @@
 
 Editing an attachment.
 
-    >>> from lp.bugs.interfaces.bugattachment import IBugAttachment
-
-    >>> attachment_before_modification = Snapshot(
-    ...     attachment, providing=IBugAttachment)
-
-    >>> attachment.title = "a new title"
-
-    >>> attachment_changed = ObjectModifiedEvent(
-    ...     attachment, attachment_before_modification,
-    ...     ["title"])
-
     >>> current_date_last_updated = firefox_bug.date_last_updated
 
-    >>> notify(attachment_changed)
+    >>> with notify_modified(attachment, ["title"]):
+    ...     attachment.title = "a new title"
 
     >>> firefox_bug.date_last_updated > current_date_last_updated
     True
@@ -807,23 +749,14 @@
 
 Editing the external bug watch.
 
-    >>> from lp.bugs.interfaces.bugwatch import IBugWatch
-
-    >>> bugwatch_before_modification = Snapshot(
-    ...     bugwatch, providing=IBugWatch)
-
     >>> print(bugwatch.remotebug)
     1234
 
-    >>> bugwatch.remotebug = '5678'
-
-    >>> bugwatch_changed = ObjectModifiedEvent(
-    ...     bugwatch, bugwatch_before_modification, ["remotebug"],
-    ...     bugwatch.bug.owner)
-
     >>> current_date_last_updated = firefox_bug.date_last_updated
 
-    >>> notify(bugwatch_changed)
+    >>> with notify_modified(
+    ...         bugwatch, ["remotebug"], user=bugwatch.bug.owner):
+    ...     bugwatch.remotebug = '5678'
 
     >>> firefox_bug.date_last_updated > current_date_last_updated
     True

=== modified file 'lib/lp/bugs/doc/bugactivity.txt'
--- lib/lp/bugs/doc/bugactivity.txt	2018-06-29 23:10:57 +0000
+++ lib/lp/bugs/doc/bugactivity.txt	2018-12-21 23:02:24 +0000
@@ -21,14 +21,9 @@
 Bug activity tracking is done using event subscribers. The handlers
 are simple little functions.
 
-    >>> from zope.event import notify
-    >>> from lazr.lifecycle.event import ObjectModifiedEvent
-    >>> from lazr.lifecycle.snapshot import Snapshot
-    >>> from lp.bugs.interfaces.bugtask import (
-    ...     IBugTask,
-    ...     IBugTaskSet,
-    ...     )
+    >>> from lp.bugs.interfaces.bugtask import IBugTaskSet
     >>> from lp.registry.interfaces.product import IProductSet
+    >>> from lp.services.webapp.snapshot import notify_modified
     >>> user = getUtility(ILaunchBag).user
 
 
@@ -54,12 +49,8 @@
 Bug title edited
 ================
 
-    >>> from lp.bugs.interfaces.bug import IBug
-    >>> old_state = Snapshot(bug, providing=IBug)
-    >>> bug.title = "new bug title"
-    >>> bug_edited = ObjectModifiedEvent(
-    ...     bug, old_state, ["title", "description"])
-    >>> notify(bug_edited)
+    >>> with notify_modified(bug, ["title", "description"]):
+    ...     bug.title = "new bug title"
     >>> latest_activity = bug.activity[-1]
     >>> latest_activity.whatchanged
     u'summary'
@@ -72,7 +63,6 @@
 Source package assignment edited
 ================================
 
-    >>> from lazr.lifecycle.snapshot import Snapshot
     >>> from lp.bugs.interfaces.bugtask import BugTaskStatus
     >>> from lp.registry.interfaces.distribution import IDistributionSet
     >>> from lp.registry.interfaces.sourcepackagename import (
@@ -84,14 +74,9 @@
     >>> edit_fields = [
     ...     "distribution", "sourcepackagename", "milestone", "status",
     ...     "importance", "assignee", "bugwatch"]
-    >>> old_source_package_assignment = Snapshot(
-    ...   source_package_assignment, providing=IBugTask)
-    >>> source_package_assignment.transitionToStatus(
-    ...     BugTaskStatus.CONFIRMED, getUtility(ILaunchBag).user)
-    >>> source_package_assignment_edited = ObjectModifiedEvent(
-    ...     source_package_assignment, old_source_package_assignment,
-    ...     edit_fields)
-    >>> notify(source_package_assignment_edited)
+    >>> with notify_modified(source_package_assignment, edit_fields):
+    ...     source_package_assignment.transitionToStatus(
+    ...         BugTaskStatus.CONFIRMED, getUtility(ILaunchBag).user)
     >>> latest_activity = bug.activity[-1]
     >>> latest_activity.whatchanged
     u'mozilla-firefox (Ubuntu): status'
@@ -132,13 +117,9 @@
     >>> edit_fields = [
     ...     "product", "milestone", "status", "assignee", "bugwatch",
     ...     "importance"]
-    >>> old_product_assignment = Snapshot(
-    ...     product_assignment, providing=IBugTask)
-    >>> product_assignment.transitionToStatus(
-    ...     BugTaskStatus.INVALID, getUtility(ILaunchBag).user)
-    >>> product_assignment_edited = ObjectModifiedEvent(
-    ...     product_assignment, old_product_assignment, edit_fields)
-    >>> notify(product_assignment_edited)
+    >>> with notify_modified(product_assignment, edit_fields):
+    ...     product_assignment.transitionToStatus(
+    ...         BugTaskStatus.INVALID, getUtility(ILaunchBag).user)
     >>> latest_activity = bug.activity[-1]
     >>> latest_activity.whatchanged
     u'thunderbird: status'
@@ -158,11 +139,9 @@
     >>> edit_fields = [
     ...     "id", "title", "description", "name",
     ...     "private", "duplicateof", "security_related"]
-    >>> old_bug = Snapshot(bug, providing=IBug)
-    >>> latest_bug = factory.makeBug()
-    >>> bug.markAsDuplicate(latest_bug)
-    >>> bug_edited = ObjectModifiedEvent(bug, old_bug, edit_fields)
-    >>> notify(bug_edited)
+    >>> with notify_modified(bug, edit_fields):
+    ...     latest_bug = factory.makeBug()
+    ...     bug.markAsDuplicate(latest_bug)
     >>> latest_activity = bug.activity[-1]
     >>> latest_activity.whatchanged
     u'marked as duplicate'
@@ -178,11 +157,9 @@
     >>> edit_fields = [
     ...     "id", "title", "description", "name", "private", "duplicateof",
     ...     "security_related"]
-    >>> old_bug = Snapshot(bug, providing=IBug)
-    >>> another_bug = factory.makeBug()
-    >>> bug.markAsDuplicate(another_bug)
-    >>> bug_edited = ObjectModifiedEvent(bug, old_bug, edit_fields)
-    >>> notify(bug_edited)
+    >>> with notify_modified(bug, edit_fields):
+    ...     another_bug = factory.makeBug()
+    ...     bug.markAsDuplicate(another_bug)
     >>> latest_activity = bug.activity[-1]
     >>> latest_activity.whatchanged
     u'changed duplicate marker'
@@ -198,10 +175,8 @@
     >>> edit_fields = [
     ...     "id", "title", "description", "name", "private", "duplicateof",
     ...     "security_related"]
-    >>> old_bug = Snapshot(bug, providing=IBug)
-    >>> bug.markAsDuplicate(None)
-    >>> bug_edited = ObjectModifiedEvent(bug, old_bug, edit_fields)
-    >>> notify(bug_edited)
+    >>> with notify_modified(bug, edit_fields):
+    ...     bug.markAsDuplicate(None)
     >>> latest_activity = bug.activity[-1]
     >>> latest_activity.whatchanged
     u'removed duplicate marker'

=== modified file 'lib/lp/bugs/doc/bugnotifications.txt'
--- lib/lp/bugs/doc/bugnotifications.txt	2018-06-29 23:10:57 +0000
+++ lib/lp/bugs/doc/bugnotifications.txt	2018-12-21 23:02:24 +0000
@@ -24,8 +24,7 @@
 === Reporting a new bug ===
 
     >>> from zope.event import notify
-    >>> from lazr.lifecycle.event import (
-    ...     ObjectModifiedEvent, ObjectCreatedEvent)
+    >>> from lazr.lifecycle.event import ObjectCreatedEvent
     >>> from lp.bugs.interfaces.bug import CreateBugParams
     >>> from lp.registry.interfaces.distribution import IDistributionSet
     >>> from lp.registry.interfaces.distroseries import IDistroSeriesSet
@@ -64,14 +63,10 @@
 
 === Editing a bug report ===
 
-    >>> from lazr.lifecycle.snapshot import Snapshot
-    >>> from lp.bugs.interfaces.bug import IBug
-    >>> bug_before_modification = Snapshot(firefox_crashes, providing=IBug)
-    >>> firefox_crashes.description = "a new description"
-    >>> firefox_crashes_modified = ObjectModifiedEvent(
-    ...     firefox_crashes, bug_before_modification,
-    ...     ["description"])
-    >>> notify(firefox_crashes_modified)
+    >>> from lp.services.webapp.snapshot import notify_modified
+
+    >>> with notify_modified(firefox_crashes, ["description"]):
+    ...     firefox_crashes.description = "a new description"
 
     >>> latest_notification = BugNotification.selectFirst(orderBy='-id')
     >>> print(latest_notification.message.owner.displayname)
@@ -225,21 +220,13 @@
 Let's demonstrate a notification email where Sample Person marks a
 task Fixed, and assigns themselves to it.
 
-    >>> from lazr.lifecycle.snapshot import Snapshot
-    >>> from lp.bugs.interfaces.bugtask import (
-    ...     BugTaskStatus,
-    ...     IBugTask,
-    ...     )
+    >>> from lp.bugs.interfaces.bugtask import BugTaskStatus
 
-    >>> bugtask_before_modification = Snapshot(
-    ...     firefox_crashes_in_debian, providing=IBugTask)
-    >>> firefox_crashes_in_debian.transitionToStatus(
-    ...     BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
-    >>> firefox_crashes_in_debian.transitionToAssignee(bug_submitter)
-    >>> debian_task_modified = ObjectModifiedEvent(
-    ...     firefox_crashes_in_debian, bugtask_before_modification,
-    ...     ["status", "assignee"])
-    >>> notify(debian_task_modified)
+    >>> with notify_modified(
+    ...         firefox_crashes_in_debian, ["status", "assignee"]):
+    ...     firefox_crashes_in_debian.transitionToStatus(
+    ...         BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
+    ...     firefox_crashes_in_debian.transitionToAssignee(bug_submitter)
 
     >>> latest_notification = BugNotification.selectFirst(orderBy='-id')
     >>> print(latest_notification.message.owner.displayname)
@@ -251,15 +238,11 @@
     ** Changed in: mozilla-firefox (Debian)
     ...
 
-    >>> bugtask_before_modification = Snapshot(
-    ...     firefox_crashes_in_trunk, providing=IBugTask)
-    >>> firefox_crashes_in_trunk.transitionToStatus(
-    ...     BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
-    >>> firefox_crashes_in_trunk.transitionToAssignee(bug_submitter)
-    >>> firefox_task_modified = ObjectModifiedEvent(
-    ...     firefox_crashes_in_trunk, bugtask_before_modification,
-    ...     ["status", "assignee"])
-    >>> notify(firefox_task_modified)
+    >>> with notify_modified(
+    ...         firefox_crashes_in_trunk, ["status", "assignee"]):
+    ...     firefox_crashes_in_trunk.transitionToStatus(
+    ...         BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
+    ...     firefox_crashes_in_trunk.transitionToAssignee(bug_submitter)
 
     >>> latest_notification = BugNotification.selectFirst(orderBy='-id')
     >>> print(latest_notification.message.owner.displayname)

=== modified file 'lib/lp/bugs/doc/initial-bug-contacts.txt'
--- lib/lp/bugs/doc/initial-bug-contacts.txt	2018-06-29 23:10:57 +0000
+++ lib/lp/bugs/doc/initial-bug-contacts.txt	2018-12-21 23:02:24 +0000
@@ -125,13 +125,9 @@
 pmount, to show that the subscription changes behave correctly when a
 subscriber to the new package is already subscribed to the bug:
 
-    >>> from zope.event import notify
-
     >>> import transaction
-    >>> from lazr.lifecycle.event import ObjectModifiedEvent
-    >>> from lazr.lifecycle.snapshot import Snapshot
-    >>> from lp.bugs.interfaces.bugtask import IBugTask
     >>> from lp.services.mail import stub
+    >>> from lp.services.webapp.snapshot import notify_modified
 
     >>> daf = personset.getByName("daf")
     >>> ubuntu_pmount.addBugSubscription(daf, daf)
@@ -140,16 +136,10 @@
     >>> ubuntu_pmount.addBugSubscription(sample_person, sample_person)
     <...StructuralSubscription object at ...>
 
-    >>> old_state = Snapshot(
-    ...        bug_one_in_ubuntu_firefox, providing=IBugTask)
-
-    >>> bug_one_in_ubuntu_firefox.transitionToTarget(ubuntu_pmount, daf)
-
-    >>> source_package_changed = ObjectModifiedEvent(
-    ...        bug_one_in_ubuntu_firefox, old_state,
-    ...        ["id", "title", "sourcepackagename"])
-
-    >>> notify(source_package_changed)
+    >>> with notify_modified(
+    ...         bug_one_in_ubuntu_firefox,
+    ...         ["id", "title", "sourcepackagename"]):
+    ...     bug_one_in_ubuntu_firefox.transitionToTarget(ubuntu_pmount, daf)
     >>> transaction.commit()
 
 With the source package changed, we can see that daf is now subscribed:
@@ -239,15 +229,9 @@
 Let's see that nothing unexpected happens when we set the source package
 to None.
 
-    >>> old_state = Snapshot(
-    ...        bug_one_in_ubuntu_firefox, providing=IBugTask)
-
-    >>> bug_one_in_ubuntu_firefox.transitionToTarget(ubuntu, daf)
-
-    >>> source_package_changed = ObjectModifiedEvent(
-    ...        bug_one_in_ubuntu_firefox, old_state, ["sourcepackagename"])
-
-    >>> notify(source_package_changed)
+    >>> with notify_modified(
+    ...         bug_one_in_ubuntu_firefox, ["sourcepackagename"]):
+    ...     bug_one_in_ubuntu_firefox.transitionToTarget(ubuntu, daf)
     >>> transaction.commit()
     >>> stub.test_emails = []
 
@@ -272,15 +256,9 @@
     >>> ubuntu_pmount.addBugSubscription(ubuntu_gnome, ubuntu_gnome)
     <...StructuralSubscription object at ...>
 
-    >>> old_state = Snapshot(
-    ...        bug_one_in_ubuntu_firefox, providing=IBugTask)
-
-    >>> bug_one_in_ubuntu_firefox.transitionToTarget(ubuntu_pmount, daf)
-
-    >>> source_package_changed = ObjectModifiedEvent(
-    ...        bug_one_in_ubuntu_firefox, old_state, ["sourcepackagename"])
-
-    >>> notify(source_package_changed)
+    >>> with notify_modified(
+    ...         bug_one_in_ubuntu_firefox, ["sourcepackagename"]):
+    ...     bug_one_in_ubuntu_firefox.transitionToTarget(ubuntu_pmount, daf)
     >>> transaction.commit()
 
 The Ubuntu Gnome team was subscribed to the bug:
@@ -317,14 +295,8 @@
     ...         bug_two_in_ubuntu.bug.subscriptions])
     [u'Steve Alexander']
 
-    >>> old_state = Snapshot(bug_two_in_ubuntu, providing=IBugTask)
-
-    >>> bug_two_in_ubuntu.transitionToTarget(mozilla_firefox, daf)
-
-    >>> product_changed = ObjectModifiedEvent(
-    ...        bug_two_in_ubuntu, old_state, ["id", "title", "product"])
-
-    >>> notify(product_changed)
+    >>> with notify_modified(bug_two_in_ubuntu, ["id", "title", "product"]):
+    ...     bug_two_in_ubuntu.transitionToTarget(mozilla_firefox, daf)
     >>> transaction.commit()
 
 

=== modified file 'lib/lp/bugs/doc/malone-karma.txt'
--- lib/lp/bugs/doc/malone-karma.txt	2018-06-29 23:10:57 +0000
+++ lib/lp/bugs/doc/malone-karma.txt	2018-12-21 23:02:24 +0000
@@ -25,8 +25,7 @@
 
 Create a bug:
 
-    >>> from lazr.lifecycle.event import (
-    ...     ObjectCreatedEvent, ObjectModifiedEvent)
+    >>> from lazr.lifecycle.event import ObjectCreatedEvent
     >>> from lp.bugs.interfaces.bug import CreateBugParams
     >>> debian = getUtility(IDistributionSet).getByName('debian')
     >>> params = CreateBugParams(
@@ -36,18 +35,15 @@
 
 Change the title of a bug:
 
-    >>> from lazr.lifecycle.snapshot import Snapshot
-    >>> from lp.bugs.interfaces.bug import IBug
-    >>> old_bug = Snapshot(bug, providing=IBug)
-    >>> bug.title = "Better Title"
-    >>> notify(ObjectModifiedEvent(bug, old_bug, ['title']))
+    >>> from lp.services.webapp.snapshot import notify_modified
+    >>> with notify_modified(bug, ['title']):
+    ...     bug.title = "Better Title"
     Karma added: action=bugtitlechanged, distribution=debian
 
 Change the description of a bug:
 
-    >>> old_bug = Snapshot(bug, providing=IBug)
-    >>> bug.description = "Description of bug"
-    >>> notify(ObjectModifiedEvent(bug, old_bug, ['description']))
+    >>> with notify_modified(bug, ['description']):
+    ...     bug.description = "Description of bug"
     Karma added: action=bugdescriptionchanged, distribution=debian
 
 Add a CVE reference to a bug:
@@ -79,15 +75,11 @@
 
 Mark a bug task as fixed:
 
-    >>> from lp.bugs.interfaces.bugtask import (
-    ...     BugTaskStatus,
-    ...     IBugTask,
-    ...     )
+    >>> from lp.bugs.interfaces.bugtask import BugTaskStatus
     >>> bugtask = bug.bugtasks[0]
-    >>> old_bugtask = Snapshot(bugtask, providing=IBugTask)
-    >>> bugtask.transitionToStatus(
-    ...     BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
-    >>> notify(ObjectModifiedEvent(bugtask, old_bugtask, ['status']))
+    >>> with notify_modified(bugtask, ['status']):
+    ...     bugtask.transitionToStatus(
+    ...         BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
     Karma added: action=bugfixed, distribution=debian
 
 Mark a bug task as fixed when it is assigned awards the karma to the assignee:
@@ -96,10 +88,9 @@
     >>> assignee = factory.makePerson(name='assignee')
     >>> assigned_bugtask = factory.makeBugTask(bug=bug, target=ufo_product)
     >>> assigned_bugtask.transitionToAssignee(assignee)
-    >>> old_bugtask = Snapshot(assigned_bugtask, providing=IBugTask)
-    >>> assigned_bugtask.transitionToStatus(
-    ...     BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
-    >>> notify(ObjectModifiedEvent(assigned_bugtask, old_bugtask, ['status']))
+    >>> with notify_modified(assigned_bugtask, ['status']):
+    ...     assigned_bugtask.transitionToStatus(
+    ...         BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user)
     Karma added: action=bugfixed, product=ufo
 
     >>> for karma in assignee.latestKarma():
@@ -108,27 +99,24 @@
 
 Reject a bug task:
 
-    >>> old_bugtask = Snapshot(bugtask, providing=IBugTask)
-    >>> bugtask.transitionToStatus(
-    ...     BugTaskStatus.INVALID, bugtask.target.owner)
-    >>> notify(ObjectModifiedEvent(bugtask, old_bugtask, ['status']))
+    >>> with notify_modified(bugtask, ['status']):
+    ...     bugtask.transitionToStatus(
+    ...         BugTaskStatus.INVALID, bugtask.target.owner)
     Karma added: action=bugrejected, distribution=debian
 
 User accept a bug task:
 
-    >>> old_bugtask = Snapshot(bugtask, providing=IBugTask)
-    >>> bugtask.transitionToStatus(
-    ...     BugTaskStatus.CONFIRMED, getUtility(ILaunchBag).user)
-    >>> notify(ObjectModifiedEvent(bugtask, old_bugtask, ['status']))
+    >>> with notify_modified(bugtask, ['status']):
+    ...     bugtask.transitionToStatus(
+    ...         BugTaskStatus.CONFIRMED, getUtility(ILaunchBag).user)
     Karma added: action=bugaccepted, distribution=debian
 
 Driver accept a bug task:
 
     >>> ignored = login_person(bugtask.target.owner)
-    >>> old_bugtask = Snapshot(bugtask, providing=IBugTask)
-    >>> bugtask.transitionToStatus(
-    ...     BugTaskStatus.TRIAGED, getUtility(ILaunchBag).user)
-    >>> notify(ObjectModifiedEvent(bugtask, old_bugtask, ['status']))
+    >>> with notify_modified(bugtask, ['status']):
+    ...     bugtask.transitionToStatus(
+    ...         BugTaskStatus.TRIAGED, getUtility(ILaunchBag).user)
     Karma added: action=bugaccepted, distribution=debian
 
     >>> login('admin@xxxxxxxxxxxxx')
@@ -139,11 +127,10 @@
     >>> bugtask.transitionToImportance(
     ...     BugTaskImportance.HIGH, getUtility(ILaunchBag).user)
     >>> for importance in BugTaskImportance.items:
-    ...     old_bugtask = Snapshot(bugtask, providing=IBugTask)
-    ...     bugtask.transitionToImportance(
-    ...         importance, getUtility(ILaunchBag).user)
-    ...     print(importance.name)
-    ...     notify(ObjectModifiedEvent(bugtask, old_bugtask, ['importance']))
+    ...     with notify_modified(bugtask, ['importance']):
+    ...         bugtask.transitionToImportance(
+    ...             importance, getUtility(ILaunchBag).user)
+    ...         print(importance.name)
     UNKNOWN
     Karma added: action=bugtaskimportancechanged, distribution=debian
     UNDECIDED
@@ -189,36 +176,29 @@
 
     >>> debian_woody_task.transitionToStatus(
     ...     BugTaskStatus.NEW, getUtility(ILaunchBag).user)
-    >>> old_bugtask = Snapshot(
-    ...     debian_woody_task, providing=IBugTask)
-    >>> debian_woody_task.transitionToStatus(
-    ...     BugTaskStatus.CONFIRMED, getUtility(ILaunchBag).user)
-    >>> notify(ObjectModifiedEvent(
-    ...     debian_woody_task, old_bugtask, ['status']))
+    >>> with notify_modified(debian_woody_task, ['status']):
+    ...     debian_woody_task.transitionToStatus(
+    ...         BugTaskStatus.CONFIRMED, getUtility(ILaunchBag).user)
     Karma added: action=bugaccepted, distribution=debian
 
 Accept a productseries task.
 
     >>> evolution_trunk_task.transitionToStatus(
     ...     BugTaskStatus.NEW, getUtility(ILaunchBag).user)
-    >>> old_bugtask = Snapshot(
-    ...     evolution_trunk_task, providing=IBugTask)
-    >>> evolution_trunk_task.transitionToStatus(
-    ...     BugTaskStatus.CONFIRMED, getUtility(ILaunchBag).user)
-    >>> notify(ObjectModifiedEvent(
-    ...     evolution_trunk_task, old_bugtask, ['status']))
+    >>> with notify_modified(evolution_trunk_task, ['status']):
+    ...     evolution_trunk_task.transitionToStatus(
+    ...         BugTaskStatus.CONFIRMED, getUtility(ILaunchBag).user)
     Karma added: action=bugaccepted, product=evolution
 
 Mark a bug as a duplicate:
 
+(Notice how changing a bug with multiple bugtasks will assign karma to you
+once for each bugtask. This is so because we consider changes in a bug to
+be actual contributions to all bugtasks of that bug.)
+
     >>> bug_one = getUtility(IBugSet).get(1)
-    >>> old_bug = Snapshot(bug, providing=IBug)
-    >>> bug.markAsDuplicate(bug_one)
-
-    (Notice how changing a bug with multiple bugtasks will assign karma to you
-    once for each bugtask. This is so because we consider changes in a bug to
-    be actual contributions to all bugtasks of that bug)
-    >>> notify(ObjectModifiedEvent(bug, old_bug, ['duplicateof']))
+    >>> with notify_modified(bug, ['duplicateof']):
+    ...     bug.markAsDuplicate(bug_one)
     Karma added: action=bugmarkedasduplicate, product=evolution
     Karma added: action=bugmarkedasduplicate, product=evolution
     Karma added: action=bugmarkedasduplicate, product=ufo


Follow ups