diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000..a83da986 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,35 @@ +[run] +branch = True +include = + src/ptvsd/* +omit = + src/ptvsd/__init__.py + src/ptvsd/_version.py + src/ptvsd/_vendored/* + src/ptvsd/server/* +data_file = coverage/.coverage + +[report] +exclude_lines = + # Have to re-enable the standard pragma. + pragma: no cover + + # __repr__ is mostly used for error messages. + def __repr__ + + # Asserts and error conditions. + raise AssertionError + raise NotImplementedError + \.isnt_valid\( + \.cant_handle\( + + # Code that's deliberately excluded. + if 0: + if __name__ == .__main__.: + +[html] +directory = coverage/html +title = ptvsd coverage report + +[xml] +output = coverage/coverage.xml diff --git a/.gitignore b/.gitignore index e4821257..4a59dba7 100644 --- a/.gitignore +++ b/.gitignore @@ -37,7 +37,8 @@ pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports -htmlcov/ +coverage/html/ +coverage/coverage.xml tests/_logs/*.log .tox/ .coverage diff --git a/coverage/README b/coverage/README new file mode 100644 index 00000000..496c0919 --- /dev/null +++ b/coverage/README @@ -0,0 +1 @@ +codecov data files and HTML reports go here. diff --git a/src/ptvsd/__init__.py b/src/ptvsd/__init__.py index fe1e6af2..43bd1979 100644 --- a/src/ptvsd/__init__.py +++ b/src/ptvsd/__init__.py @@ -162,4 +162,4 @@ __file__ = os.path.abspath(__file__) # Preload encodings that we're going to use to avoid import deadlocks on Python 2, # before importing anything from ptvsd. -map(codecs.lookup, ["ascii", "utf8", "utf-8", "latin1", "latin-1"]) +map(codecs.lookup, ["ascii", "utf8", "utf-8", "latin1", "latin-1", "idna"]) diff --git a/src/ptvsd/adapter/session.py b/src/ptvsd/adapter/session.py index 79437634..7f9a273a 100644 --- a/src/ptvsd/adapter/session.py +++ b/src/ptvsd/adapter/session.py @@ -202,15 +202,15 @@ class Session(util.Observable): cmdline = ["sudo"] if sudo else [] cmdline += [sys.executable, os.path.dirname(ptvsd.launcher.__file__)] cmdline += args - env = {"PTVSD_SESSION_ID": str(self.id)} + env = {str("PTVSD_SESSION_ID"): str(self.id)} def spawn_launcher(): with self._accept_connection_from_launcher() as (_, launcher_port): - env["PTVSD_LAUNCHER_PORT"] = str(launcher_port) + env[str("PTVSD_LAUNCHER_PORT")] = str(launcher_port) if common_options.log_dir is not None: - env["PTVSD_LOG_DIR"] = compat.filename(common_options.log_dir) + env[str("PTVSD_LOG_DIR")] = compat.filename_str(common_options.log_dir) if adapter_options.log_stderr: - env["PTVSD_LOG_STDERR"] = "debug info warning error" + env[str("PTVSD_LOG_STDERR")] = str("debug info warning error") if console == "internalConsole": # If we are talking to the IDE over stdio, sys.stdin and sys.stdout are # redirected to avoid mangling the DAP message stream. Make sure the diff --git a/src/ptvsd/common/util.py b/src/ptvsd/common/util.py index d91f81e1..462679af 100644 --- a/src/ptvsd/common/util.py +++ b/src/ptvsd/common/util.py @@ -8,22 +8,6 @@ import threading import sys -def new_hidden_thread(name, target, prefix='ptvsd.common.', daemon=True, **kwargs): - """Return a thread that will be ignored by pydevd.""" - if prefix is not None and not name.startswith(prefix): - name = prefix + name - t = threading.Thread( - name=name, - target=target, - **kwargs - ) - t.pydev_do_not_trace = True - t.is_pydev_daemon_thread = True - if daemon: - t.daemon = False - return t - - def evaluate(code, path=__file__, mode="eval"): # Setting file path here to avoid breaking here if users have set # "break on exception raised" setting. This code can potentially run diff --git a/src/ptvsd/debugger.py b/src/ptvsd/debugger.py deleted file mode 100644 index a7cfe18b..00000000 --- a/src/ptvsd/debugger.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See LICENSE in the project root -# for license information. - -from __future__ import absolute_import, print_function, unicode_literals - -from ptvsd.server import log, options -from ptvsd.server.__main__ import run_file, run_module, run_code - - -RUNNERS = {"module": run_module, "script": run_file, "code": run_code} - -# Not actually used, but VS will try to add entries to it. -DONT_DEBUG = [] - - -# A legacy entrypoint for Visual Studio, to allow older versions to work with new ptvsd.server. -# All new code should use the entrypoints in ptvsd.server.__main__ directly. -def debug(filename, port_num, debug_id, debug_options, run_as): - log.to_file() - log.info( - "debug{0!r}", (filename, port_num, debug_id, debug_options, run_as) - ) - - try: - run = RUNNERS[run_as] - except KeyError: - raise ValueError("run_as must be one of: {0!r}".format(tuple(RUNNERS.keys()))) - - options.target_kind = "file" if run_as == "script" else run_as - options.target = filename - options.port = port_num - options.client = True - - # debug_id is ignored because it has no meaning in DAP. - # debug_options are ignored, because they will be passed later via DAP "launch" request. - - run() diff --git a/src/ptvsd/launcher/adapter.py b/src/ptvsd/launcher/adapter.py index 10a28d6a..ca87832c 100644 --- a/src/ptvsd/launcher/adapter.py +++ b/src/ptvsd/launcher/adapter.py @@ -116,6 +116,10 @@ class Handlers(object): cwd = None if program == () else (os.path.dirname(program) or None) env = os.environ.copy() + if "PTVSD_TEST" in env: + # If we're running as part of a ptvsd test, make sure that codecov is not + # applied to the debuggee, since it will conflict with pydevd. + env.pop("COV_CORE_SOURCE", None) env.update(request("env", json.object(unicode))) redirect_output = "RedirectOutput" in debug_options diff --git a/src/ptvsd/server/api.py b/src/ptvsd/server/api.py index 2c788a8a..26b5b154 100644 --- a/src/ptvsd/server/api.py +++ b/src/ptvsd/server/api.py @@ -61,7 +61,10 @@ def _starts_debugging(func): end_patterns, ) - return func(start_patterns, end_patterns) + try: + return func(start_patterns, end_patterns) + except Exception: + raise log.exception("{0}() failed:", func.__name__) return debug diff --git a/tests/debug/start_methods.py b/tests/debug/start_methods.py index dd23d987..2074c02c 100644 --- a/tests/debug/start_methods.py +++ b/tests/debug/start_methods.py @@ -279,6 +279,7 @@ class Launch(DebugStartBase): cwd = request("cwd", ".") env = os.environ.copy() + env.pop("COV_CORE_SOURCE", None) # disable codecov subprocess hook env.update(request("env", json.object(unicode))) if sys.version_info < (3,): @@ -346,6 +347,7 @@ class AttachBase(DebugStartBase): target_str = target.strpath env = os.environ.copy() + env.pop("COV_CORE_SOURCE", None) # disable codecov subprocess hook env.update(kwargs["env"]) cli_args = kwargs.get("cli_args") diff --git a/tests/requirements.txt b/tests/requirements.txt index fe8428d1..e46ef1b0 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -3,6 +3,7 @@ # pytest>=5 does not support Python 2.7 pytest<5 +pytest-cov pytest-timeout pytest-xdist tox diff --git a/tox.ini b/tox.ini index c3da8920..08b01cf4 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,11 @@ [tox] -envlist = py{27,34,35,36,37} +envlist = py{27,34,35,36,37}{,-cov} [testenv] deps = -rtests/requirements.txt passenv = PTVSD_LOG_DIR +setenv = + PTVSD_TEST=1 commands = - pytest {posargs:-n8} + !cov: pytest {posargs} + cov: pytest --cov --cov-append --cov-config=.coveragerc {posargs}