diff --git a/ptvsd/_vendored/pydevd/pydev_coverage.py b/ptvsd/_vendored/pydevd/pydev_coverage.py index 279ae65a..b98731cd 100644 --- a/ptvsd/_vendored/pydevd/pydev_coverage.py +++ b/ptvsd/_vendored/pydevd/pydev_coverage.py @@ -2,6 +2,25 @@ Entry point module to run code-coverage. ''' + +def is_valid_py_file(path): + ''' + Checks whether the file can be read by the coverage module. This is especially + needed for .pyx files and .py files with syntax errors. + ''' + import os + + is_valid = False + if os.path.isfile(path) and not os.path.splitext(path)[1] == '.pyx': + try: + with open(path, 'rb') as f: + compile(f.read(), path, 'exec') + is_valid = True + except: + pass + return is_valid + + def execute(): import os import sys @@ -17,20 +36,29 @@ def execute(): #given in the java side, let's just gather that info here). sys.argv.remove('--pydev-analyze') try: - s = raw_input() + s = raw_input() # @UndefinedVariable except: s = input() s = s.replace('\r', '') s = s.replace('\n', '') - files = s.split('|') - files = [v for v in files if len(v) > 0] - #Note that in this case we'll already be in the working dir with the coverage files, so, the - #coverage file location is not passed. + files = [] + invalid_files = [] + for v in s.split('|'): + if is_valid_py_file(v): + files.append(v) + else: + invalid_files.append(v) + if invalid_files: + sys.stderr.write('Invalid files not passed to coverage: %s\n' + % ', '.join(invalid_files)) + + # Note that in this case we'll already be in the working dir with the coverage files, + # so, the coverage file location is not passed. else: - #For all commands, the coverage file is configured in pydev, and passed as the first argument - #in the command line, so, let's make sure this gets to the coverage module. + # For all commands, the coverage file is configured in pydev, and passed as the first + # argument in the command line, so, let's make sure this gets to the coverage module. os.environ['COVERAGE_FILE'] = sys.argv[1] del sys.argv[1] @@ -38,18 +66,24 @@ def execute(): import coverage #@UnresolvedImport except: sys.stderr.write('Error: coverage module could not be imported\n') - sys.stderr.write('Please make sure that the coverage module (http://nedbatchelder.com/code/coverage/)\n') + sys.stderr.write('Please make sure that the coverage module ' + '(http://nedbatchelder.com/code/coverage/)\n') sys.stderr.write('is properly installed in your interpreter: %s\n' % (sys.executable,)) import traceback;traceback.print_exc() return - - version = tuple(map(int, coverage.__version__.split('.')[:2])) - if version < (4, 3): - sys.stderr.write('Error: minimum supported coverage version is 4.3.\nFound: %s\nLocation: %s' % ('.'.join(str(x) for x in version), coverage.__file__)) - sys.exit(1) - #print(coverage.__version__) TODO: Check if the version is a version we support (should be at least 3.4) -- note that maybe the attr is not there. + if hasattr(coverage, '__version__'): + version = tuple(map(int, coverage.__version__.split('.')[:2])) + if version < (4, 3): + sys.stderr.write('Error: minimum supported coverage version is 4.3.' + '\nFound: %s\nLocation: %s\n' + % ('.'.join(str(x) for x in version), coverage.__file__)) + sys.exit(1) + else: + sys.stderr.write('Warning: Could not determine version of python module coverage.' + '\nEnsure coverage version is >= 4.3\n') + from coverage.cmdline import main #@UnresolvedImport if files is not None: @@ -59,4 +93,4 @@ def execute(): main() if __name__ == '__main__': - execute() \ No newline at end of file + execute() diff --git a/ptvsd/_vendored/pydevd/pydevd_attach_to_process/_test_attach_to_process_linux.py b/ptvsd/_vendored/pydevd/pydevd_attach_to_process/_test_attach_to_process_linux.py index 8bc3d38b..335fc91b 100644 --- a/ptvsd/_vendored/pydevd/pydevd_attach_to_process/_test_attach_to_process_linux.py +++ b/ptvsd/_vendored/pydevd/pydevd_attach_to_process/_test_attach_to_process_linux.py @@ -58,8 +58,8 @@ if __name__ == '__main__': cmd.extend([ "--eval-command='call dlopen(\"/home/fabioz/Desktop/dev/PyDev.Debugger/pydevd_attach_to_process/linux/attach_linux.so\", 2)'", - "--eval-command='call DoAttach(1, \"print(\\\"check11111check\\\")\", 0)'", - #"--eval-command='call SetSysTraceFunc(1, 0)'", -- never call this way, always use "--command='...gdb_threads_settrace.py'", + "--eval-command='call (int)DoAttach(1, \"print(\\\"check11111check\\\")\", 0)'", + #"--eval-command='call (int)SetSysTraceFunc(1, 0)'", -- never call this way, always use "--command='...gdb_threads_settrace.py'", #So that threads are all stopped! "--command='/home/fabioz/Desktop/dev/PyDev.Debugger/pydevd_attach_to_process/linux/gdb_threads_settrace.py'", ]) diff --git a/ptvsd/_vendored/pydevd/pydevd_attach_to_process/add_code_to_python_process.py b/ptvsd/_vendored/pydevd/pydevd_attach_to_process/add_code_to_python_process.py index 2b5c2929..9fe7ee00 100644 --- a/ptvsd/_vendored/pydevd/pydevd_attach_to_process/add_code_to_python_process.py +++ b/ptvsd/_vendored/pydevd/pydevd_attach_to_process/add_code_to_python_process.py @@ -441,7 +441,7 @@ def run_python_code_linux(pid, python_code, connect_debugger_tracing=False, show cmd.extend([ "--eval-command='call dlopen(\"%s\", 2)'" % target_dll, - "--eval-command='call DoAttach(%s, \"%s\", %s)'" % ( + "--eval-command='call (int)DoAttach(%s, \"%s\", %s)'" % ( is_debug, python_code, show_debug_info) ]) diff --git a/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/gdb_threads_settrace.py b/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/gdb_threads_settrace.py index 48e3a7bc..5966f31b 100644 --- a/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/gdb_threads_settrace.py +++ b/ptvsd/_vendored/pydevd/pydevd_attach_to_process/linux/gdb_threads_settrace.py @@ -10,7 +10,7 @@ if __name__ == '__main__': t.switch() if t.is_stopped(): #print('Will settrace in: %s' % (t,)) - gdb.execute("call SetSysTraceFunc(%s, %s)" % ( + gdb.execute("call (int)SetSysTraceFunc(%s, %s)" % ( show_debug_info, is_debug)) except: import traceback;traceback.print_exc() diff --git a/ptvsd/_vendored/pydevd/tests_python/resources/_pydev_coverage_cyrillic_encoding_py2.py b/ptvsd/_vendored/pydevd/tests_python/resources/_pydev_coverage_cyrillic_encoding_py2.py new file mode 100644 index 00000000..e56d5d09 --- /dev/null +++ b/ptvsd/_vendored/pydevd/tests_python/resources/_pydev_coverage_cyrillic_encoding_py2.py @@ -0,0 +1,8 @@ +# -*- coding: iso-8859-5 -*- + +# Ʋ³´µ¶ +class Dummy(object): + def Print(self): + print ('Ʋ³´µ¶') + +Dummy().Print() diff --git a/ptvsd/_vendored/pydevd/tests_python/resources/_pydev_coverage_cyrillic_encoding_py3.py b/ptvsd/_vendored/pydevd/tests_python/resources/_pydev_coverage_cyrillic_encoding_py3.py new file mode 100644 index 00000000..f099c539 --- /dev/null +++ b/ptvsd/_vendored/pydevd/tests_python/resources/_pydev_coverage_cyrillic_encoding_py3.py @@ -0,0 +1,8 @@ +# -*- coding: iso-8859-5 -*- + +# Ʋ³´µ¶ +class DummyƲ³´µ¶(object): + def Print(self): + print ('Ʋ³´µ¶') + +DummyƲ³´µ¶().Print() diff --git a/ptvsd/_vendored/pydevd/tests_python/resources/_pydev_coverage_syntax_error.py b/ptvsd/_vendored/pydevd/tests_python/resources/_pydev_coverage_syntax_error.py new file mode 100644 index 00000000..6faf573c --- /dev/null +++ b/ptvsd/_vendored/pydevd/tests_python/resources/_pydev_coverage_syntax_error.py @@ -0,0 +1,8 @@ +# -*- coding: iso-8859-5 -*- + +# Ʋ³´µ¶ +class Dummy(object): + def Print(self) + print ('Ʋ³´µ¶') + +Dummy().Print() diff --git a/ptvsd/_vendored/pydevd/tests_python/test_pydevcoverage.py b/ptvsd/_vendored/pydevd/tests_python/test_pydevcoverage.py new file mode 100644 index 00000000..9563b1ac --- /dev/null +++ b/ptvsd/_vendored/pydevd/tests_python/test_pydevcoverage.py @@ -0,0 +1,68 @@ +import os +import re +import sys +import subprocess +import tempfile +import unittest + + +#======================================================================================================================= +# Test +#======================================================================================================================= +class Test(unittest.TestCase): + """ + Unittest for pydev_coverage.py. + TODO: + - 'combine' in arguments + - no 'combine' and no 'pydev-analyze' in arguments + """ + + def setUp(self): + unittest.TestCase.setUp(self) + project_path = os.path.dirname(os.path.dirname(__file__)) + self._resources_path = os.path.join(project_path, "tests_python", "resources") + self._coverage_file = os.path.join(project_path, "pydev_coverage.py") + + def _do_analyze(self, files): + invalid_files = [] + + p = subprocess.Popen(["python", self._coverage_file, "--pydev-analyze"], + stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + __, stderrdata = p.communicate("|".join(files).encode()) + + if stderrdata: + match = re.search("Invalid files not passed to coverage: (.*?)$", + stderrdata.decode(), re.M) # @UndefinedVariable + if match: + invalid_files = [f.strip() for f in match.group(1).split(",")] + return invalid_files + + def test_pydev_analyze_ok(self): + ref_valid_files = [__file__, + os.path.join(self._resources_path, "_debugger_case18.py")] + ref_invalid_files = [] + + invalid_files = self._do_analyze(ref_valid_files) + + self.assertEqual(ref_invalid_files, invalid_files) + + def test_pydev_analyse_non_standard_encoding(self): + ref_valid_files = [os.path.join(self._resources_path, + "_pydev_coverage_cyrillic_encoding_py%i.py" + % sys.version_info[0])] + ref_invalid_files = [] + + invalid_files = self._do_analyze(ref_valid_files + ref_invalid_files) + + self.assertEqual(ref_invalid_files, invalid_files) + + def test_pydev_analyse_invalid_files(self): + with tempfile.NamedTemporaryFile(suffix=".pyx") as pyx_file: + ref_valid_files = [] + ref_invalid_files = [os.path.join(self._resources_path, + "_pydev_coverage_syntax_error.py"), + pyx_file.name] + + invalid_files = self._do_analyze(ref_valid_files + ref_invalid_files) + + self.assertEqual(ref_invalid_files, invalid_files)