Exemple #1
0
    def _prepare2(self):
        """Do more preparation to run Python code.

        Includes finding the module to run and adjusting sys.argv[0].
        This method is allowed to import code.

        """
        if self.as_module:
            self.modulename = self.arg0
            pathname, self.package, self.spec = find_module(self.modulename)
            if self.spec is not None:
                self.modulename = self.spec.name
            self.loader = DummyLoader(self.modulename)
            self.pathname = os.path.abspath(pathname)
            self.args[0] = self.arg0 = self.pathname
        elif os.path.isdir(self.arg0):
            # Running a directory means running the __main__.py file in that
            # directory.
            for ext in [".py", ".pyc", ".pyo"]:
                try_filename = os.path.join(self.arg0, "__main__" + ext)
                if os.path.exists(try_filename):
                    self.arg0 = try_filename
                    break
            else:
                raise NoSource("Can't find '__main__' module in '%s'" %
                               self.arg0)

            if env.PY2:
                self.arg0 = os.path.abspath(self.arg0)

            # Make a spec. I don't know if this is the right way to do it.
            try:
                import importlib.machinery
            except ImportError:
                pass
            else:
                try_filename = python_reported_file(try_filename)
                self.spec = importlib.machinery.ModuleSpec("__main__",
                                                           None,
                                                           origin=try_filename)
                self.spec.has_location = True
            self.package = ""
            self.loader = DummyLoader("__main__")
        else:
            if env.PY3:
                self.loader = DummyLoader("__main__")

        self.arg0 = python_reported_file(self.arg0)
Exemple #2
0
    def test_code_throws(self):
        self.make_file("throw.py", """\
            class MyException(Exception):
                pass

            def f1():
                raise MyException("hey!")

            def f2():
                f1()

            f2()
            """)

        # The important thing is for "coverage run" and "python" to report the
        # same traceback.
        status, out = self.run_command_status("coverage run throw.py")
        out2 = self.run_command("python throw.py")
        if env.PYPY:
            # Pypy has an extra frame in the traceback for some reason
            out2 = re_lines_text("toplevel", out2, match=False)
        assert out == out2

        # But also make sure that the output is what we expect.
        path = python_reported_file('throw.py')
        msg = f'File "{re.escape(path)}", line 8, in f2'
        assert re.search(msg, out)
        assert 'raise MyException("hey!")' in out
        assert status == 1
Exemple #3
0
    def prepare(self):
        """Set sys.path properly.

        This needs to happen before any importing, and without importing anything.
        """
        should_update_sys_path = True
        if self.as_module:
            if env.PYBEHAVIOR.actual_syspath0_dash_m:
                path0 = os.getcwd()
            else:
                path0 = ""
            sys.path[0] = path0
            should_update_sys_path = False
        elif os.path.isdir(self.arg0):
            # Running a directory means running the __main__.py file in that
            # directory.
            path0 = self.arg0
        else:
            path0 = os.path.abspath(os.path.dirname(self.arg0))

        if should_update_sys_path:
            # sys.path fakery.  If we are being run as a command, then sys.path[0]
            # is the directory of the "coverage" script.  If this is so, replace
            # sys.path[0] with the directory of the file we're running, or the
            # current directory when running modules.  If it isn't so, then we
            # don't know what's going on, and just leave it alone.
            top_file = inspect.stack()[-1][0].f_code.co_filename
            if os.path.abspath(sys.path[0]) == os.path.abspath(
                    os.path.dirname(top_file)):
                # Set sys.path correctly.
                sys.path[0] = python_reported_file(path0)
Exemple #4
0
    def test_run_python_file(self):
        run_python_file([TRY_EXECFILE, "arg1", "arg2"])
        mod_globs = json.loads(self.stdout())

        # The file should think it is __main__
        self.assertEqual(mod_globs['__name__'], "__main__")

        # It should seem to come from a file named try_execfile.py
        dunder_file = os.path.basename(mod_globs['__file__'])
        self.assertEqual(dunder_file, "try_execfile.py")

        # It should have its correct module data.
        self.assertEqual(mod_globs['__doc__'].splitlines()[0],
                         "Test file for run_python_file.")
        self.assertEqual(mod_globs['DATA'], "xyzzy")
        self.assertEqual(mod_globs['FN_VAL'], "my_fn('fooey')")

        # It must be self-importable as __main__.
        self.assertEqual(mod_globs['__main__.DATA'], "xyzzy")

        # Argv should have the proper values.
        self.assertEqual(mod_globs['argv0'],
                         python_reported_file(TRY_EXECFILE))
        self.assertEqual(mod_globs['argv1-n'], ["arg1", "arg2"])

        # __builtins__ should have the right values, like open().
        self.assertEqual(mod_globs['__builtins__.has_open'], True)
Exemple #5
0
    def _prepare2(self):
        """Do more preparation to run Python code.

        Includes finding the module to run and adjusting sys.argv[0].
        This method is allowed to import code.

        """
        if self.as_module:
            self.modulename = self.arg0
            pathname, self.package, self.spec = find_module(self.modulename)
            if self.spec is not None:
                self.modulename = self.spec.name
            self.loader = DummyLoader(self.modulename)
            self.pathname = os.path.abspath(pathname)
            self.args[0] = self.arg0 = self.pathname
        elif os.path.isdir(self.arg0):
            # Running a directory means running the __main__.py file in that
            # directory.
            for ext in [".py", ".pyc", ".pyo"]:
                try_filename = os.path.join(self.arg0, "__main__" + ext)
                # 3.8.10 changed how files are reported when running a
                # directory.  But I'm not sure how far this change is going to
                # spread, so I'll just hard-code it here for now.
                if env.PYVERSION >= (3, 8, 10):
                    try_filename = os.path.abspath(try_filename)
                if os.path.exists(try_filename):
                    self.arg0 = try_filename
                    break
            else:
                raise NoSource(
                    f"Can't find '__main__' module in '{self.arg0}'")

            # Make a spec. I don't know if this is the right way to do it.
            try_filename = python_reported_file(try_filename)
            self.spec = importlib.machinery.ModuleSpec("__main__",
                                                       None,
                                                       origin=try_filename)
            self.spec.has_location = True
            self.package = ""
            self.loader = DummyLoader("__main__")
        else:
            self.loader = DummyLoader("__main__")

        self.arg0 = python_reported_file(self.arg0)
Exemple #6
0
 def test_removing_directory_with_error(self):
     self.make_file("bug806.py", self.BUG_806)
     out = self.run_command("coverage run bug806.py")
     path = python_reported_file('bug806.py')
     # Python 3.11 adds an extra line to the traceback.
     # Check that the lines we expect are there.
     lines = textwrap.dedent(f"""\
         Traceback (most recent call last):
           File "{path}", line 8, in <module>
             print(sys.argv[1])
         IndexError: list index out of range
         """).splitlines(keepends=True)
     assert all(line in out for line in lines)
Exemple #7
0
    def test_running_py_from_binary(self):
        # Use make_file to get the bookkeeping. Ideally, it would
        # be able to write binary files.
        bf = self.make_file("binary")
        with open(bf, "wb") as f:
            f.write(b'\x7fELF\x02\x01\x01\x00\x00\x00')

        path = python_reported_file('binary')
        msg = (
            re.escape(f"Couldn't run '{path}' as Python code: ") +
            r"(TypeError|ValueError): source code string cannot contain null bytes"
        )
        with pytest.raises(Exception, match=msg):
            run_python_file([bf])
Exemple #8
0
    def test_warns_if_never_run(self):
        # Note: the name of the function can't have "warning" in it, or the
        # absolute path of the file will have "warning" in it, and an assertion
        # will fail.
        out = self.run_command("coverage run i_dont_exist.py")
        path = python_reported_file('i_dont_exist.py')
        assert f"No file to run: '{path}'" in out
        assert "warning" not in out
        assert "Exception" not in out

        out = self.run_command("coverage run -m no_such_module")
        assert (
            ("No module named no_such_module" in out) or
            ("No module named 'no_such_module'" in out)
        )
        assert "warning" not in out
        assert "Exception" not in out
    def test_running_py_from_binary(self):
        # Use make_file to get the bookkeeping. Ideally, it would
        # be able to write binary files.
        bf = self.make_file("binary")
        with open(bf, "wb") as f:
            f.write(b'\x7fELF\x02\x01\x01\x00\x00\x00')

        path = python_reported_file('binary')
        msg = (
            re.escape("Couldn't run '{}' as Python code: ".format(path)) +
            r"(TypeError|ValueError): "
            r"("
            r"compile\(\) expected string without null bytes"  # for py2
            r"|"
            r"source code string cannot contain null bytes"  # for py3
            r")")
        with self.assertRaisesRegex(Exception, msg):
            run_python_file([bf])
Exemple #10
0
    def prepare(self):
        """Set sys.path properly.

        This needs to happen before any importing, and without importing anything.
        """
        if self.as_module:
            if env.PYBEHAVIOR.actual_syspath0_dash_m:
                path0 = os.getcwd()
            else:
                path0 = ""
        elif os.path.isdir(self.arg0):
            # Running a directory means running the __main__.py file in that
            # directory.
            path0 = self.arg0
        else:
            path0 = os.path.abspath(os.path.dirname(self.arg0))

        if os.path.isdir(sys.path[0]):
            # sys.path fakery.  If we are being run as a command, then sys.path[0]
            # is the directory of the "coverage" script.  If this is so, replace
            # sys.path[0] with the directory of the file we're running, or the
            # current directory when running modules.  If it isn't so, then we
            # don't know what's going on, and just leave it alone.
            top_file = inspect.stack()[-1][0].f_code.co_filename
            sys_path_0_abs = os.path.abspath(sys.path[0])
            top_file_dir_abs = os.path.abspath(os.path.dirname(top_file))
            sys_path_0_abs = canonical_filename(sys_path_0_abs)
            top_file_dir_abs = canonical_filename(top_file_dir_abs)
            if sys_path_0_abs != top_file_dir_abs:
                path0 = None

        else:
            # sys.path[0] is a file. Is the next entry the directory containing
            # that file?
            if sys.path[1] == os.path.dirname(sys.path[0]):
                # Can it be right to always remove that?
                del sys.path[1]

        if path0 is not None:
            sys.path[0] = python_reported_file(path0)
 def test_no_such_file(self):
     path = python_reported_file('xyzzy.py')
     msg = re.escape("No file to run: '{}'".format(path))
     with self.assertRaisesRegex(NoSource, msg):
         run_python_file(["xyzzy.py"])
Exemple #12
0
 def test_no_such_file(self):
     path = python_reported_file('xyzzy.py')
     msg = re.escape("No file to run: '{}'".format(path))
     with pytest.raises(NoSource, match=msg):
         run_python_file(["xyzzy.py"])
 def test_no_such_pyc_file(self):
     path = python_reported_file('xyzzy.pyc')
     msg = re.escape(f"No file to run: '{path}'")
     with pytest.raises(NoCode, match=msg):
         run_python_file(["xyzzy.pyc"])
Exemple #14
0
    def prepare(self):
        """Do initial preparation to run Python code.

        Includes finding the module to run, adjusting sys.argv[0], and changing
        sys.path to match what Python does.

        """
        should_update_sys_path = True

        if self.as_module:
            if env.PYBEHAVIOR.actual_syspath0_dash_m:
                path0 = os.getcwd()
            else:
                path0 = ""
            sys.path[0] = path0
            should_update_sys_path = False
            self.modulename = self.arg0
            pathname, self.package, self.spec = find_module(self.modulename)
            if self.spec is not None:
                self.modulename = self.spec.name
            self.loader = DummyLoader(self.modulename)
            self.pathname = os.path.abspath(pathname)
            self.args[0] = self.arg0 = self.pathname
        elif os.path.isdir(self.arg0):
            # Running a directory means running the __main__.py file in that
            # directory.
            path0 = self.arg0
            for ext in [".py", ".pyc", ".pyo"]:
                try_filename = os.path.join(self.arg0, "__main__" + ext)
                if os.path.exists(try_filename):
                    self.arg0 = try_filename
                    break
            else:
                raise NoSource("Can't find '__main__' module in '%s'" %
                               self.arg0)

            if env.PY2:
                self.arg0 = os.path.abspath(self.arg0)

            # Make a spec. I don't know if this is the right way to do it.
            try:
                import importlib.machinery
            except ImportError:
                pass
            else:
                try_filename = python_reported_file(try_filename)
                self.spec = importlib.machinery.ModuleSpec("__main__",
                                                           None,
                                                           origin=try_filename)
                self.spec.has_location = True
            self.package = ""
            self.loader = DummyLoader("__main__")
        else:
            path0 = os.path.abspath(os.path.dirname(self.arg0))
            if env.PY3:
                self.loader = DummyLoader("__main__")

        self.args[0] = python_reported_file(self.args[0])
        self.arg0 = python_reported_file(self.arg0)

        if self.modulename is None:
            self.modulename = '__main__'

        if should_update_sys_path:
            # sys.path fakery.  If we are being run as a command, then sys.path[0]
            # is the directory of the "coverage" script.  If this is so, replace
            # sys.path[0] with the directory of the file we're running, or the
            # current directory when running modules.  If it isn't so, then we
            # don't know what's going on, and just leave it alone.
            top_file = inspect.stack()[-1][0].f_code.co_filename
            if os.path.abspath(sys.path[0]) == os.path.abspath(
                    os.path.dirname(top_file)):
                # Set sys.path correctly.
                sys.path[0] = python_reported_file(path0)