about summary refs log tree commit diff stats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rwxr-xr-xtests/manpage_completion_test.py6
-rw-r--r--tests/pylint/py2_compat.py20
-rw-r--r--tests/pylint/test_py2_compat.py38
3 files changed, 61 insertions, 3 deletions
diff --git a/tests/manpage_completion_test.py b/tests/manpage_completion_test.py
index b9504d06..1a01f944 100755
--- a/tests/manpage_completion_test.py
+++ b/tests/manpage_completion_test.py
@@ -26,13 +26,15 @@ def get_path_of_man_page():
 
 def read_manpage():
     path = get_path_of_man_page()
-    return open(path, 'r').read()
+    # pylint: disable=unspecified-encoding
+    with open(path, 'r') as man_page:
+        return man_page.read()
 
 
 def get_sections():
     manpage = read_manpage()
     parts = manpage.split('=head1 ')
-    sections = dict()
+    sections = {}
     for part in parts:
         if '\n' in part:
             section_name, section_content = part.split('\n', 1)
diff --git a/tests/pylint/py2_compat.py b/tests/pylint/py2_compat.py
index f3c4398c..7e136148 100644
--- a/tests/pylint/py2_compat.py
+++ b/tests/pylint/py2_compat.py
@@ -45,7 +45,12 @@ class Py2CompatibilityChecker(BaseChecker):
         "E4220": ('Use explicit format spec numbering',
                   "implicit-format-spec",
                   'Python 2.6 does not support implicit format spec numbering'
-                  ' "{}", use explicit numbering "{0}" or keywords "{key}".')
+                  ' "{}", use explicit numbering "{0}" or keywords "{key}".'),
+        "E4230": ("Use popen23.Popen with with-statements",
+                  "with-popen23",
+                  "Python 2 subprocess.Popen objects were not contextmanagers,"
+                  "popen23.Popen wraps them to enable use with"
+                  "with-statements."),
     }
     # This class variable declares the options
     # that are configurable by the user.
@@ -116,6 +121,19 @@ class Py2CompatibilityChecker(BaseChecker):
                     self.add_message("implicit-format-spec", node=node,
                                      confidence=HIGH)
 
+    def visit_with(self, node):
+        """Make sure subprocess.Popen objects aren't used in with-statements"""
+        for (cm, _) in node.items:
+            if isinstance(cm, astroid.nodes.Call):
+                if ((isinstance(cm.func, astroid.nodes.Name)
+                    and cm.func.name.endswith("Popen")
+                    and (node.root().scope_lookup(node.root(), "Popen")[1][0]
+                         ).modname == "subprocess")
+                    or (isinstance(cm.func, astroid.nodes.Attribute)
+                        and cm.func.expr == "subprocess"
+                        and cm.func.attrname == "Popen")):
+                    self.add_message("with-popen23", node=node, confidence=HIGH)
+
 
 def register(linter):
     """This required method auto registers the checker.
diff --git a/tests/pylint/test_py2_compat.py b/tests/pylint/test_py2_compat.py
index a5d2e284..7156aba7 100644
--- a/tests/pylint/test_py2_compat.py
+++ b/tests/pylint/test_py2_compat.py
@@ -5,6 +5,9 @@ import py2_compat
 import astroid
 import pylint.testutils
 
+from sys import version_info
+PY2 = version_info[0] < 3
+
 
 class TestPy2CompatibilityChecker(pylint.testutils.CheckerTestCase):
     CHECKER_CLASS = py2_compat.Py2CompatibilityChecker
@@ -42,6 +45,9 @@ class TestPy2CompatibilityChecker(pylint.testutils.CheckerTestCase):
             self.checker.visit_classdef(from_new)
 
     def test_print_without_import(self):
+        if PY2:
+            return
+
         print_function_call = astroid.extract_node("""
         print("Print function call without importing print_function")
         """)
@@ -73,6 +79,9 @@ class TestPy2CompatibilityChecker(pylint.testutils.CheckerTestCase):
             self.checker.visit_call(nested_print_function_call)
 
     def test_print_late_import(self):
+        if PY2:
+            return
+
         early_print_function_call = astroid.extract_node("""
         print("Nested print with import in scope") #@
         def f():
@@ -91,6 +100,9 @@ class TestPy2CompatibilityChecker(pylint.testutils.CheckerTestCase):
             self.checker.visit_call(early_print_function_call)
 
     def test_implicit_format_spec(self):
+        if PY2:
+            return
+
         implicit_format_spec = astroid.extract_node("""
         "{}".format("implicit") #@
         """)
@@ -103,6 +115,32 @@ class TestPy2CompatibilityChecker(pylint.testutils.CheckerTestCase):
         ):
             self.checker.visit_call(implicit_format_spec)
 
+    def test_with_Popen(self):
+        with_subprocess_Popen, with_Popen, with_Popen23 = astroid.extract_node("""
+        import subprocess
+        with subprocess.Popen(): #@
+            pass
+
+        from subprocess import Popen
+        with Popen(): #@
+            pass
+
+        from ranger.ext.popen23 import Popen23
+        with Popen23(): #@
+            pass
+        """)
+
+        with self.assertAddsMessages(
+            pylint.testutils.Message(
+                msg_id='with-popen23',
+                node=with_Popen,
+            ),
+        ):
+            self.checker.visit_with(with_subprocess_Popen)
+            self.checker.visit_with(with_Popen)
+        with self.assertNoMessages():
+            self.checker.visit_with(with_Popen23)
+
     # # These checks still exist as old-division and no-absolute-import
     # def test_division_without_import(self):
     #     division = astroid.extract_node("""