Enrique Sánchez has proposed merging ~enriqueesanchz/launchpad:add-bugtaskstatus-deferred into launchpad:master.
Commit message: Add DEFERRED to BugTaskStatus model Requested reviews: Launchpad code reviewers (launchpad-reviewers) For more details, see: https://code.launchpad.net/~enriqueesanchz/launchpad/+git/launchpad/+merge/484235 -- Your team Launchpad code reviewers is requested to review the proposed merge of ~enriqueesanchz/launchpad:add-bugtaskstatus-deferred into launchpad:master.
diff --git a/lib/canonical/launchpad/icing/css/colours.scss b/lib/canonical/launchpad/icing/css/colours.scss index 937af46..58ea80b 100644 --- a/lib/canonical/launchpad/icing/css/colours.scss +++ b/lib/canonical/launchpad/icing/css/colours.scss @@ -204,7 +204,7 @@ } } - .statusINVALID, .statusWONTFIX, .statusDOESNOTEXIST, .status.statusOPINION { + .statusINVALID, .statusWONTFIX, .statusDOESNOTEXIST, .statusDEFERRED, .status.statusOPINION { color: #555; a { @@ -301,7 +301,7 @@ } } - .statusEXPIRED, .statusINVALID, .statusWONTFIX, .statusDOESNOTEXIST, .statusOPINION { + .statusEXPIRED, .statusINVALID, .statusWONTFIX, .statusDOESNOTEXIST, .statusDEFERRED, .statusOPINION { color: #464646; background-color: #ddd; diff --git a/lib/lp/bugs/browser/buglisting.py b/lib/lp/bugs/browser/buglisting.py index f6aebfd..8adda0b 100644 --- a/lib/lp/bugs/browser/buglisting.py +++ b/lib/lp/bugs/browser/buglisting.py @@ -129,6 +129,7 @@ DISPLAY_BUG_STATUS_FOR_PATCHES = { BugTaskStatus.CONFIRMED: True, BugTaskStatus.TRIAGED: True, BugTaskStatus.INPROGRESS: True, + BugTaskStatus.DEFERRED: True, BugTaskStatus.FIXCOMMITTED: True, BugTaskStatus.FIXRELEASED: False, BugTaskStatus.UNKNOWN: False, @@ -1529,7 +1530,7 @@ class BugTaskSearchListingView(LaunchpadFormView, FeedsMixin, BugsInfoMixin): checked=term.value in default_values, ) ) - return shortlist(widget_values, longest_expected=13) + return shortlist(widget_values, longest_expected=14) def getStatusWidgetValues(self): """Return data used to render the status checkboxes.""" diff --git a/lib/lp/bugs/browser/bugtarget.py b/lib/lp/bugs/browser/bugtarget.py index 199309d..d29d033 100644 --- a/lib/lp/bugs/browser/bugtarget.py +++ b/lib/lp/bugs/browser/bugtarget.py @@ -265,6 +265,7 @@ class FileBugViewBase(LaunchpadFormView): BugTaskStatus.WONTFIX, BugTaskStatus.INCOMPLETE, BugTaskStatus.DOESNOTEXIST, + BugTaskStatus.DEFERRED, ], ) cache.objects["bugtask_status_data"] = bugtask_status_data diff --git a/lib/lp/bugs/browser/tests/person-bug-views.rst b/lib/lp/bugs/browser/tests/person-bug-views.rst index 376bc71..ec08a1c 100644 --- a/lib/lp/bugs/browser/tests/person-bug-views.rst +++ b/lib/lp/bugs/browser/tests/person-bug-views.rst @@ -251,7 +251,7 @@ render the overview report. >>> print(ubuntu_firefox_bugcounts["package_name"]) mozilla-firefox in Ubuntu >>> print(ubuntu_firefox_bugcounts["package_search_url"]) # noqa - http://bugs.launchpad.test/ubuntu/+source/mozilla-firefox?field.status=New&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed&search=Search + http://bugs.launchpad.test/ubuntu/+source/mozilla-firefox?field.status=New&field.status=Deferred&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed&search=Search >>> print(ubuntu_firefox_bugcounts["open_bugs_count"]) 1 @@ -263,11 +263,11 @@ render the overview report. 0 >>> print(ubuntu_firefox_bugcounts["open_bugs_url"]) # noqa - http://bugs.launchpad.test/ubuntu/+source/mozilla-firefox?field.status=New&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed&search=Search + http://bugs.launchpad.test/ubuntu/+source/mozilla-firefox?field.status=New&field.status=Deferred&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed&search=Search >>> print(ubuntu_firefox_bugcounts["critical_bugs_url"]) # noqa - http://bugs.launchpad.test/ubuntu/+source/mozilla-firefox?field.importance=Critical&field.status=New&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed&search=Search + http://bugs.launchpad.test/ubuntu/+source/mozilla-firefox?field.importance=Critical&field.status=New&field.status=Deferred&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed&search=Search >>> print(ubuntu_firefox_bugcounts["unassigned_bugs_url"]) # noqa - http://bugs.launchpad.test/ubuntu/+source/mozilla-firefox?assignee_option=none&field.status=New&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed&search=Search + http://bugs.launchpad.test/ubuntu/+source/mozilla-firefox?assignee_option=none&field.status=New&field.status=Deferred&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed&search=Search >>> print(ubuntu_firefox_bugcounts["inprogress_bugs_url"]) # noqa http://bugs.launchpad.test/ubuntu/+source/mozilla-firefox?field.status=In+Progress&search=Search diff --git a/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py b/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py index 769e610..17a673f 100644 --- a/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py +++ b/lib/lp/bugs/browser/tests/test_bugtarget_filebug.py @@ -1105,6 +1105,7 @@ class TestFileBugRequestCache(TestCaseWithFactory): BugTaskStatus.OPINION, BugTaskStatus.WONTFIX, BugTaskStatus.DOESNOTEXIST, + BugTaskStatus.DEFERRED, BugTaskStatus.INCOMPLETE, ] bugtask_status_data = [] diff --git a/lib/lp/bugs/browser/tests/test_bugtask.py b/lib/lp/bugs/browser/tests/test_bugtask.py index 2a1eb92..8d665f0 100644 --- a/lib/lp/bugs/browser/tests/test_bugtask.py +++ b/lib/lp/bugs/browser/tests/test_bugtask.py @@ -1414,6 +1414,7 @@ class TestBugTaskEditViewStatusField(TestCaseWithFactory): "Confirmed", "Triaged", "In Progress", + "Deferred", "Fix Committed", "Fix Released", ], diff --git a/lib/lp/bugs/doc/bugtask-status-changes.rst b/lib/lp/bugs/doc/bugtask-status-changes.rst index 0918240..8693ed9 100644 --- a/lib/lp/bugs/doc/bugtask-status-changes.rst +++ b/lib/lp/bugs/doc/bugtask-status-changes.rst @@ -5,9 +5,10 @@ Restrictions ------------ There are a few simple rules around who can change the status of a -bug task. There are four statuses that can only be set by either +bug task. There are five statuses that can only be set by either the project maintainer, driver or bug supervisor: + * Deferred * Won't Fix * Does Not Exist * Expired @@ -20,6 +21,10 @@ the project maintainer, driver or bug supervisor: >>> from lp.bugs.interfaces.bugtask import BugTaskStatus >>> ignored = login_person(owner) + >>> bugtask.transitionToStatus(BugTaskStatus.DEFERRED, owner) + >>> print(bugtask.status.title) + Deferred + >>> bugtask.transitionToStatus(BugTaskStatus.WONTFIX, owner) >>> print(bugtask.status.title) Won't Fix @@ -31,7 +36,7 @@ the project maintainer, driver or bug supervisor: Regular users of Launchpad cannot transition a bug task to any of these statuses. -An additional restraint is added to Won't Fix and Does Not Exist. +An additional restraint is added to Won't Fix, Does Not Exist and Deferred. Only the product maintainer, driver or bug supervisor can change from this status to any other status. @@ -57,6 +62,14 @@ from this status to any other status. ... lp.bugs.interfaces.bugtask.UserCannotEditBugTaskStatus: ... + >>> bugtask.transitionToStatus(BugTaskStatus.DEFERRED, owner) + >>> print(bugtask.status.title) + Deferred + >>> bugtask.transitionToStatus(BugTaskStatus.CONFIRMED, user) + Traceback (most recent call last): + ... + lp.bugs.interfaces.bugtask.UserCannotEditBugTaskStatus: ... + This is fully tested in lp.bugs.tests.test_bugtask_status.TestBugTaskStatusSetting. diff --git a/lib/lp/bugs/interfaces/bugtask.py b/lib/lp/bugs/interfaces/bugtask.py index 3864b76..f9be6c0 100644 --- a/lib/lp/bugs/interfaces/bugtask.py +++ b/lib/lp/bugs/interfaces/bugtask.py @@ -241,6 +241,15 @@ class BugTaskStatus(DBEnumeratedType): """, ) + DEFERRED = DBItem( + 23, + """ + Deferred + + Fixing has been deferred. + """, + ) + FIXCOMMITTED = DBItem( 25, """ @@ -346,6 +355,7 @@ class BugTaskStatusSearchDisplay(DBEnumeratedType): UNRESOLVED_BUGTASK_STATUSES = ( BugTaskStatus.NEW, + BugTaskStatus.DEFERRED, BugTaskStatus.INCOMPLETE, BugTaskStatus.CONFIRMED, BugTaskStatus.TRIAGED, @@ -374,6 +384,7 @@ RESOLVED_BUGTASK_STATUSES = ( BUG_SUPERVISOR_BUGTASK_STATUSES = ( BugTaskStatus.WONTFIX, + BugTaskStatus.DEFERRED, BugTaskStatus.EXPIRED, BugTaskStatus.TRIAGED, BugTaskStatus.DOESNOTEXIST, diff --git a/lib/lp/bugs/interfaces/bugtasksearch.py b/lib/lp/bugs/interfaces/bugtasksearch.py index c78d1cc..83253c6 100644 --- a/lib/lp/bugs/interfaces/bugtasksearch.py +++ b/lib/lp/bugs/interfaces/bugtasksearch.py @@ -493,6 +493,7 @@ DEFAULT_SEARCH_BUGTASK_STATUSES = ( BugTaskStatusSearch.CONFIRMED, BugTaskStatusSearch.TRIAGED, BugTaskStatusSearch.INPROGRESS, + BugTaskStatusSearch.DEFERRED, BugTaskStatusSearch.FIXCOMMITTED, ) diff --git a/lib/lp/bugs/interfaces/tests/test_bugtask.py b/lib/lp/bugs/interfaces/tests/test_bugtask.py index 3e5981a..f804e75 100644 --- a/lib/lp/bugs/interfaces/tests/test_bugtask.py +++ b/lib/lp/bugs/interfaces/tests/test_bugtask.py @@ -53,6 +53,7 @@ class TestFunctions(TestCase): BugTaskStatus.TRIAGED: BugTaskStatus.TRIAGED, BugTaskStatus.UNKNOWN: BugTaskStatus.UNKNOWN, BugTaskStatus.WONTFIX: BugTaskStatus.WONTFIX, + BugTaskStatus.DEFERRED: BugTaskStatus.DEFERRED, } observed = { status: normalize_bugtask_status(status) @@ -80,6 +81,7 @@ class TestFunctions(TestCase): BugTaskStatusSearch.OPINION: BugTaskStatus.OPINION, BugTaskStatusSearch.TRIAGED: BugTaskStatus.TRIAGED, BugTaskStatusSearch.WONTFIX: BugTaskStatus.WONTFIX, + BugTaskStatusSearch.DEFERRED: BugTaskStatus.DEFERRED, } observed = { status: normalize_bugtask_status(status) @@ -112,6 +114,7 @@ class TestFunctions(TestCase): BugTaskStatusSearchDisplay.OPINION: BugTaskStatus.OPINION, BugTaskStatusSearchDisplay.TRIAGED: BugTaskStatus.TRIAGED, BugTaskStatusSearchDisplay.WONTFIX: BugTaskStatus.WONTFIX, + BugTaskStatusSearchDisplay.DEFERRED: BugTaskStatus.DEFERRED, } observed = { status: normalize_bugtask_status(status) diff --git a/lib/lp/bugs/model/bugtask.py b/lib/lp/bugs/model/bugtask.py index 2d9845e..799c8cf 100644 --- a/lib/lp/bugs/model/bugtask.py +++ b/lib/lp/bugs/model/bugtask.py @@ -1026,9 +1026,11 @@ class BugTask(StormBase): return False elif ( self.status == BugTaskStatus.WONTFIX + or self.status == BugTaskStatus.DEFERRED or self.status == BugTaskStatus.DOESNOTEXIST ): - # Only bug supervisors can switch away from WONTFIX and DNE. + # Only bug supervisors can switch away from WONTFIX, + # DEFERRED and DNE. return False # Non-supervisors can transition to non-supervisor statuses. return new_status not in BUG_SUPERVISOR_BUGTASK_STATUSES diff --git a/lib/lp/bugs/model/tests/test_bugtask.py b/lib/lp/bugs/model/tests/test_bugtask.py index f607999..2eed994 100644 --- a/lib/lp/bugs/model/tests/test_bugtask.py +++ b/lib/lp/bugs/model/tests/test_bugtask.py @@ -2313,7 +2313,33 @@ class TestConjoinedBugTasks(TestCaseWithFactory): self.assertEqual("trunk", alsa_utils.development_focus.name) current_series_netapplet_task.transitionToStatus( - BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user + BugTaskStatus.DEFERRED, getUtility(ILaunchpadCelebrities).admin + ) + + # The attributes were synced with the generic task. + self.assertEqual( + "Deferred", current_series_netapplet_task.status.title + ) + + self.assertEqual( + current_series_netapplet_task.date_assigned, + generic_netapplet_task.date_assigned, + ) + self.assertEqual( + current_series_netapplet_task.date_confirmed, + generic_netapplet_task.date_confirmed, + ) + self.assertEqual( + current_series_netapplet_task.date_inprogress, + generic_netapplet_task.date_inprogress, + ) + self.assertEqual( + current_series_netapplet_task.date_closed, + generic_netapplet_task.date_closed, + ) + # Only admin can transition from BugTaskStatus.DEFERRED + current_series_netapplet_task.transitionToStatus( + BugTaskStatus.FIXRELEASED, getUtility(ILaunchpadCelebrities).admin ) self.assertIsInstance(generic_netapplet_task.date_left_new, datetime) diff --git a/lib/lp/bugs/model/tests/test_bugtask_status.py b/lib/lp/bugs/model/tests/test_bugtask_status.py index 0ad43a2..fb0f2e6 100644 --- a/lib/lp/bugs/model/tests/test_bugtask_status.py +++ b/lib/lp/bugs/model/tests/test_bugtask_status.py @@ -43,6 +43,12 @@ class TestBugTaskStatusTransitionForUser(TestCaseWithFactory): self.assertRaises( UserCannotEditBugTaskStatus, self.task.transitionToStatus, + BugTaskStatus.DEFERRED, + self.user, + ) + self.assertRaises( + UserCannotEditBugTaskStatus, + self.task.transitionToStatus, BugTaskStatus.DOESNOTEXIST, self.user, ) @@ -87,6 +93,18 @@ class TestBugTaskStatusTransitionForUser(TestCaseWithFactory): self.user, ) + def test_user_cannot_unset_deferred_status(self): + # A regular user should not be able to transition a bug away + # from Deferred + removeSecurityProxy(self.task)._status = BugTaskStatus.DEFERRED + with person_logged_in(self.user): + self.assertRaises( + UserCannotEditBugTaskStatus, + self.task.transitionToStatus, + BugTaskStatus.CONFIRMED, + self.user, + ) + def test_user_cannot_unset_does_not_exist_status(self): # A regular user should not be able to transition a bug away # from Does not exist. @@ -119,6 +137,10 @@ class TestBugTaskStatusTransitionForUser(TestCaseWithFactory): False, ) self.assertEqual( + self.task.canTransitionToStatus(BugTaskStatus.DEFERRED, self.user), + False, + ) + self.assertEqual( self.task.canTransitionToStatus( BugTaskStatus.DOESNOTEXIST, self.user ), @@ -183,6 +205,15 @@ class TestBugTaskStatusTransitionForUser(TestCaseWithFactory): False, ) + def test_user_canTransitionToStatus_from_deferred(self): + # A regular user cannot transition away from Deferred + # so canTransitionToStatus should return False. + removeSecurityProxy(self.task)._status = BugTaskStatus.DEFERRED + self.assertEqual( + self.task.canTransitionToStatus(BugTaskStatus.NEW, self.user), + False, + ) + def test_user_canTransitionToStatus_from_doesnotexist(self): # A regular user cannot transition away from Does Not Exist, # so canTransitionToStatus should return False. @@ -324,6 +355,8 @@ class TestBugTaskStatusTransitionForPrivilegedUserBase: with person_logged_in(self.person): self.task.transitionToStatus(BugTaskStatus.WONTFIX, self.person) self.assertEqual(self.task.status, BugTaskStatus.WONTFIX) + self.task.transitionToStatus(BugTaskStatus.DEFERRED, self.person) + self.assertEqual(self.task.status, BugTaskStatus.DEFERRED) self.task.transitionToStatus( BugTaskStatus.DOESNOTEXIST, self.person ) @@ -360,6 +393,13 @@ class TestBugTaskStatusTransitionForPrivilegedUserBase: self.task.transitionToStatus(BugTaskStatus.CONFIRMED, self.person) self.assertEqual(self.task.status, BugTaskStatus.CONFIRMED) + def test_privileged_user_can_unset_deferred_status(self): + # Privileged users can transition away from Deferred + removeSecurityProxy(self.task)._status = BugTaskStatus.DEFERRED + with person_logged_in(self.person): + self.task.transitionToStatus(BugTaskStatus.CONFIRMED, self.person) + self.assertEqual(self.task.status, BugTaskStatus.CONFIRMED) + def test_privileged_user_can_unset_does_not_exist_status(self): # Privileged users can transition away from Does Not Exist. removeSecurityProxy(self.task)._status = BugTaskStatus.DOESNOTEXIST @@ -386,6 +426,12 @@ class TestBugTaskStatusTransitionForPrivilegedUserBase: ) self.assertEqual( self.task.canTransitionToStatus( + BugTaskStatus.DEFERRED, self.person + ), + True, + ) + self.assertEqual( + self.task.canTransitionToStatus( BugTaskStatus.DOESNOTEXIST, self.person ), True, @@ -458,6 +504,15 @@ class TestBugTaskStatusTransitionForPrivilegedUserBase: True, ) + def test_privileged_user_canTransitionToStatus_from_deferred(self): + # A privileged user can transition away from Deferred, so + # canTransitionToStatus should return True. + removeSecurityProxy(self.task)._status = BugTaskStatus.DEFERRED + self.assertEqual( + self.task.canTransitionToStatus(BugTaskStatus.NEW, self.person), + True, + ) + def test_privileged_user_canTransitionToStatus_from_doesnotexist(self): # A privileged user can transition away from Does Not Exist, so # canTransitionToStatus should return True. diff --git a/lib/lp/bugs/scripts/uct/models.py b/lib/lp/bugs/scripts/uct/models.py index 418f074..910881b 100644 --- a/lib/lp/bugs/scripts/uct/models.py +++ b/lib/lp/bugs/scripts/uct/models.py @@ -454,8 +454,7 @@ class CVE: UCTRecord.PackageStatus.DOES_NOT_EXIST: BugTaskStatus.DOESNOTEXIST, UCTRecord.PackageStatus.RELEASED: BugTaskStatus.FIXRELEASED, UCTRecord.PackageStatus.NOT_AFFECTED: BugTaskStatus.INVALID, - # we don't have a corresponding BugTaskStatus for this yet - # PackageStatus.DEFERRED: ..., + UCTRecord.PackageStatus.DEFERRED: BugTaskStatus.DEFERRED, UCTRecord.PackageStatus.NEEDED: BugTaskStatus.NEW, UCTRecord.PackageStatus.PENDING: BugTaskStatus.FIXCOMMITTED, } diff --git a/lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.rst b/lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.rst index fa5725c..aa9cbec 100644 --- a/lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.rst +++ b/lib/lp/bugs/stories/bugtask-management/xx-bug-privileged-statuses.rst @@ -58,6 +58,11 @@ those statuses are not shown in the UI: ... zope.testbrowser.browser.ItemNotFoundError: Does Not Exist + >>> status_control.displayValue = ["Deferred"] + Traceback (most recent call last): + ... + zope.testbrowser.browser.ItemNotFoundError: Deferred + Bug Supervisor -------------- diff --git a/lib/lp/bugs/tests/bugs-emailinterface.rst b/lib/lp/bugs/tests/bugs-emailinterface.rst index 75daf6a..7eaf399 100644 --- a/lib/lp/bugs/tests/bugs-emailinterface.rst +++ b/lib/lp/bugs/tests/bugs-emailinterface.rst @@ -1617,7 +1617,7 @@ Invalid status: ... The 'status' command expects any of the following arguments: new, incomplete, opinion, invalid, wontfix, expired, confirmed, triaged, - inprogress, fixcommitted, fixreleased, doesnotexist + inprogress, deferred, fixcommitted, fixreleased, doesnotexist <BLANKLINE> For example: <BLANKLINE> diff --git a/lib/lp/registry/browser/tests/test_productseries_views.py b/lib/lp/registry/browser/tests/test_productseries_views.py index f43eb49..8082157 100644 --- a/lib/lp/registry/browser/tests/test_productseries_views.py +++ b/lib/lp/registry/browser/tests/test_productseries_views.py @@ -252,6 +252,7 @@ class TestProductSeriesStatus(TestCaseWithFactory): (BugTaskStatus.CONFIRMED, 1), (BugTaskStatus.TRIAGED, 1), (BugTaskStatus.INPROGRESS, 1), + (BugTaskStatus.DEFERRED, 1), (BugTaskStatus.FIXCOMMITTED, 1), (BugTaskStatus.FIXRELEASED, 1), (BugTaskStatus.DOESNOTEXIST, 1),
_______________________________________________ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : launchpad-reviewers@lists.launchpad.net Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp