← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:contextlib-nested-deprecation into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:contextlib-nested-deprecation into launchpad:master.

Commit message:
Avoid deprecated contextlib.nested

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/377292

Use contextlib.ExitStack instead, for now via the contextlib2 backport.

Dependencies MP: https://code.launchpad.net/~cjwatson/lp-source-dependencies/+git/lp-source-dependencies/+merge/377291
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:contextlib-nested-deprecation into launchpad:master.
diff --git a/constraints.txt b/constraints.txt
index 27c1009..223cd85 100644
--- a/constraints.txt
+++ b/constraints.txt
@@ -185,6 +185,7 @@ celery==4.1.1
 Chameleon==3.6.2
 configobj==5.0.6
 constantly==15.1.0
+contextlib2==0.6.0.post1
 cookies==2.2.1
 cryptography==2.7
 cssselect==0.9.1
diff --git a/lib/lp/code/model/branchmergeproposaljob.py b/lib/lp/code/model/branchmergeproposaljob.py
index 58c47a0..cc6b20c 100644
--- a/lib/lp/code/model/branchmergeproposaljob.py
+++ b/lib/lp/code/model/branchmergeproposaljob.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2016 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2020 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Job classes related to BranchMergeProposals are in here.
@@ -27,6 +27,7 @@ from datetime import (
     timedelta,
     )
 
+from contextlib2 import ExitStack
 from lazr.delegates import delegate_to
 from lazr.enum import (
     DBEnumeratedType,
@@ -363,15 +364,12 @@ class UpdatePreviewDiffJob(BranchMergeProposalJobDerived):
     def run(self):
         """See `IRunnableJob`."""
         self.checkReady()
-        if self.branch_merge_proposal.source_branch is not None:
-            server_context = server(get_ro_server(), no_replace=True)
-        else:
-            # A no-op context manager.  (This could be simplified with
-            # contextlib.ExitStack from Python 3.3.)
-            server_context = contextmanager(lambda: (None for _ in [None]))()
+        if self.branch_merge_proposal.source_git_ref is not None:
             # Update related bug links based on commits in the source branch.
             self.branch_merge_proposal.updateRelatedBugsFromSource()
-        with server_context:
+        with ExitStack() as stack:
+            if self.branch_merge_proposal.source_branch is not None:
+                stack.enter_context(server(get_ro_server(), no_replace=True))
             with BranchMergeProposalDelta.monitor(self.branch_merge_proposal):
                 PreviewDiff.fromBranchMergeProposal(self.branch_merge_proposal)
 
diff --git a/lib/lp/code/model/diff.py b/lib/lp/code/model/diff.py
index 500dd5c..d3a61d0 100644
--- a/lib/lp/code/model/diff.py
+++ b/lib/lp/code/model/diff.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2016 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2020 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Implementation classes for IDiff, etc."""
@@ -10,7 +10,6 @@ __all__ = [
     'PreviewDiff',
     ]
 
-from contextlib import nested
 from cStringIO import StringIO
 from operator import attrgetter
 import sys
@@ -24,6 +23,7 @@ from breezy.patches import (
     Patch,
     )
 from breezy.plugins.difftacular.generate_diff import diff_ignore_branches
+from contextlib2 import ExitStack
 from lazr.delegates import delegate_to
 import simplejson
 from sqlobject import (
@@ -300,9 +300,9 @@ class Diff(SQLBase):
         :return: a `Diff`.
         """
         diff_content = StringIO()
-        read_locks = [read_locked(branch) for branch in [source_branch] +
-                ignore_branches]
-        with nested(*read_locks):
+        with ExitStack() as stack:
+            for branch in [source_branch] + ignore_branches:
+                stack.enter_context(read_locked(branch))
             diff_ignore_branches(
                 source_branch, ignore_branches, old_revision.revision_id,
                 new_revision.revision_id, diff_content)
diff --git a/lib/lp/scripts/runlaunchpad.py b/lib/lp/scripts/runlaunchpad.py
index b66e26f..7e55f9b 100644
--- a/lib/lp/scripts/runlaunchpad.py
+++ b/lib/lp/scripts/runlaunchpad.py
@@ -1,16 +1,16 @@
-# Copyright 2009-2019 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2020 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 __metaclass__ = type
 __all__ = ['start_launchpad']
 
 
-from contextlib import nested
 import os
 import signal
 import subprocess
 import sys
 
+from contextlib2 import ExitStack
 import fixtures
 from lazr.config import as_host_port
 from rabbitfixture.server import RabbitServerResources
@@ -407,7 +407,9 @@ def start_launchpad(argv=list(sys.argv), setup=None):
         # This is the setup from start_testapp, above.
         setup()
     try:
-        with nested(*services):
+        with ExitStack() as stack:
+            for service in services:
+                stack.enter_context(service)
             # Store our process id somewhere
             make_pidfile('launchpad')
             if config.launchpad.launch:
diff --git a/lib/lp/testing/tests/test_layers_functional.py b/lib/lp/testing/tests/test_layers_functional.py
index e5e6ab3..5a97097 100644
--- a/lib/lp/testing/tests/test_layers_functional.py
+++ b/lib/lp/testing/tests/test_layers_functional.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2019 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2020 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 from __future__ import with_statement
@@ -11,7 +11,6 @@ to confirm that the environment hasn't been corrupted by tests
 
 __metaclass__ = type
 
-from contextlib import nested
 from cStringIO import StringIO
 import os
 import signal
@@ -312,10 +311,7 @@ class LibrarianLayerTest(TestCase, TestWithFixtures):
         download_port = config.librarian.download_port
         restricted_download_port = config.librarian.restricted_download_port
         self.useFixture(BaseLayerIsolator())
-        with nested(
-            LayerFixture(BaseLayer),
-            LayerFixture(DatabaseLayer),
-            ):
+        with LayerFixture(BaseLayer), LayerFixture(DatabaseLayer):
             with LayerFixture(LibrarianLayer):
                 active_root = config.librarian_server.root
                 # The config settings have changed:
diff --git a/setup.py b/setup.py
index 600dfb2..cdc2960 100644
--- a/setup.py
+++ b/setup.py
@@ -152,6 +152,7 @@ setup(
         'breezy',
         'bzr',
         'celery',
+        'contextlib2',
         'cssselect',
         'cssutils',
         'defusedxml',