From d8c30bd0ea107408c4cfcbc7ca7b694e596cf59a Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 3 Apr 2018 17:29:09 +0000 Subject: [PATCH 1/9] Add unit tests for __main__.py. --- ptvsd/__main__.py | 26 ++-- tests/ptvsd/test___main__.py | 234 +++++++++++++++++++++++++++++++++++ 2 files changed, 249 insertions(+), 11 deletions(-) create mode 100644 tests/ptvsd/test___main__.py diff --git a/ptvsd/__main__.py b/ptvsd/__main__.py index ee9654f9d..07a1376b1 100644 --- a/ptvsd/__main__.py +++ b/ptvsd/__main__.py @@ -17,19 +17,23 @@ def run_module(address, modname, *extra, **kwargs): """Run pydevd for the given module.""" + run = kwargs.pop('_run', _run) + prog = kwargs.pop('_prog', sys.argv[0]) filename = modname + ':' - argv = _run_argv(address, filename, *extra) + argv = _run_argv(address, filename, extra, _prog=prog) argv.insert(argv.index('--file'), '--module') - _run(argv, **kwargs) + run(argv, **kwargs) def run_file(address, filename, *extra, **kwargs): """Run pydevd for the given Python file.""" - argv = _run_argv(address, filename, *extra) - _run(argv, **kwargs) + run = kwargs.pop('_run', _run) + prog = kwargs.pop('_prog', sys.argv[0]) + argv = _run_argv(address, filename, extra, _prog=prog) + run(argv, **kwargs) -def _run_argv(address, filename, *extra): +def _run_argv(address, filename, extra, _prog=sys.argv[0]): """Convert the given values to an argv that pydevd.main() supports.""" if '--' in extra: pydevd = list(extra[:extra.index('--')]) @@ -42,7 +46,7 @@ def _run_argv(address, filename, *extra): #if host is None: # host = '127.0.0.1' argv = [ - sys.argv[0], + _prog, '--port', str(port), ] if host is not None: @@ -54,7 +58,7 @@ def _run_argv(address, filename, *extra): ] + extra -def _run(argv, **kwargs): +def _run(argv, _pydevd=pydevd, _install=ptvsd.wrapper.install, **kwargs): """Start pydevd with the given commandline args.""" #print(' '.join(argv)) @@ -72,14 +76,14 @@ def _run(argv, **kwargs): # imports of the "pydevd" module then return the wrong module. We # work around this by avoiding lazy imports of the "pydevd" module. # We also replace the __main__ module with the "pydevd" module here. - if sys.modules['__main__'].__file__ != pydevd.__file__: + if sys.modules['__main__'].__file__ != _pydevd.__file__: sys.modules['__main___orig'] = sys.modules['__main__'] - sys.modules['__main__'] = pydevd + sys.modules['__main__'] = _pydevd - ptvsd.wrapper.install(pydevd, **kwargs) + _install(_pydevd, **kwargs) sys.argv[:] = argv try: - pydevd.main() + _pydevd.main() except SystemExit as ex: ptvsd.wrapper.ptvsd_sys_exit_code = int(ex.code) raise diff --git a/tests/ptvsd/test___main__.py b/tests/ptvsd/test___main__.py new file mode 100644 index 000000000..21736ae39 --- /dev/null +++ b/tests/ptvsd/test___main__.py @@ -0,0 +1,234 @@ +import sys +import unittest + +from _pydevd_bundle import pydevd_comm + +import ptvsd.wrapper +from ptvsd.__main__ import run_module, run_file + + +class FakePyDevd(object): + + def __init__(self, __file__, handle_main): + self.__file__ = __file__ + self.handle_main = handle_main + + def main(self): + self.handle_main() + + +class RunBase(object): + + def setUp(self): + super(RunBase, self).setUp() + self.argv = None + self.kwargs = None + + def _run(self, argv, **kwargs): + self.argv = argv + self.kwargs = kwargs + + +class RunModuleTests(RunBase, unittest.TestCase): + + def test_local(self): + addr = (None, 8888) + run_module(addr, 'spam', _run=self._run, _prog='eggs') + + self.assertEqual(self.argv, [ + 'eggs', + '--port', '8888', + '--module', + '--file', 'spam:', + ]) + self.assertEqual(self.kwargs, {}) + + def test_remote(self): + addr = ('1.2.3.4', 8888) + run_module(addr, 'spam', _run=self._run, _prog='eggs') + + self.assertEqual(self.argv, [ + 'eggs', + '--port', '8888', + '--client', '1.2.3.4', + '--module', + '--file', 'spam:', + ]) + self.assertEqual(self.kwargs, {}) + + def test_extra(self): + addr = (None, 8888) + run_module(addr, 'spam', '--vm_type', 'xyz', '--', '--DEBUG', + _run=self._run, _prog='eggs') + + self.assertEqual(self.argv, [ + 'eggs', + '--port', '8888', + '--vm_type', 'xyz', + '--module', + '--file', 'spam:', + '--DEBUG', + ]) + self.assertEqual(self.kwargs, {}) + + def test_executable(self): + addr = (None, 8888) + run_module(addr, 'spam', _run=self._run) + + self.assertEqual(self.argv, [ + sys.argv[0], + '--port', '8888', + '--module', + '--file', 'spam:', + ]) + self.assertEqual(self.kwargs, {}) + + +class RunScriptTests(RunBase, unittest.TestCase): + + def test_local(self): + addr = (None, 8888) + run_file(addr, 'spam.py', _run=self._run, _prog='eggs') + + self.assertEqual(self.argv, [ + 'eggs', + '--port', '8888', + '--file', 'spam.py', + ]) + self.assertEqual(self.kwargs, {}) + + def test_remote(self): + addr = ('1.2.3.4', 8888) + run_file(addr, 'spam.py', _run=self._run, _prog='eggs') + + self.assertEqual(self.argv, [ + 'eggs', + '--port', '8888', + '--client', '1.2.3.4', + '--file', 'spam.py', + ]) + self.assertEqual(self.kwargs, {}) + + def test_extra(self): + addr = (None, 8888) + run_file(addr, 'spam.py', '--vm_type', 'xyz', '--', '--DEBUG', + _run=self._run, _prog='eggs') + + self.assertEqual(self.argv, [ + 'eggs', + '--port', '8888', + '--vm_type', 'xyz', + '--file', 'spam.py', + '--DEBUG', + ]) + self.assertEqual(self.kwargs, {}) + + def test_executable(self): + addr = (None, 8888) + run_file(addr, 'spam.py', _run=self._run) + + self.assertEqual(self.argv, [ + sys.argv[0], + '--port', '8888', + '--file', 'spam.py', + ]) + self.assertEqual(self.kwargs, {}) + + +class IntegratedRunTests(unittest.TestCase): + + def setUp(self): + super(IntegratedRunTests, self).setUp() + self.__main__ = sys.modules['__main__'] + self.argv = sys.argv + ptvsd.wrapper.ptvsd_sys_exit_code = 0 + self.start_server = pydevd_comm.start_server + self.start_client = pydevd_comm.start_client + + self.pydevd = None + self.kwargs = None + self.maincalls = 0 + self.mainexc = None + + def tearDown(self): + sys.argv[:] = self.argv + sys.modules['__main__'] = self.__main__ + sys.modules.pop('__main___orig', None) + ptvsd.wrapper.ptvsd_sys_exit_code = 0 + pydevd_comm.start_server = self.start_server + pydevd_comm.start_client = self.start_client + # We shouldn't need to restore __main__.start_*. + super(IntegratedRunTests, self).tearDown() + + def _install(self, pydevd, **kwargs): + self.pydevd = pydevd + self.kwargs = kwargs + + def _main(self): + self.maincalls += 1 + if self.mainexc is not None: + raise self.mainexc + + def test_run(self): + pydevd = FakePyDevd('pydevd/pydevd.py', self._main) + addr = (None, 8888) + run_file(addr, 'spam.py', _pydevd=pydevd, _install=self._install) + + self.assertEqual(self.pydevd, pydevd) + self.assertEqual(self.kwargs, {}) + self.assertEqual(self.maincalls, 1) + self.assertEqual(sys.argv, [ + sys.argv[0], + '--port', '8888', + '--file', 'spam.py', + ]) + self.assertEqual(ptvsd.wrapper.ptvsd_sys_exit_code, 0) + + def test_failure(self): + self.mainexc = RuntimeError('boom!') + pydevd = FakePyDevd('pydevd/pydevd.py', self._main) + addr = (None, 8888) + with self.assertRaises(RuntimeError) as cm: + run_file(addr, 'spam.py', _pydevd=pydevd, _install=self._install) + exc = cm.exception + + self.assertEqual(self.pydevd, pydevd) + self.assertEqual(self.kwargs, {}) + self.assertEqual(self.maincalls, 1) + self.assertEqual(sys.argv, [ + sys.argv[0], + '--port', '8888', + '--file', 'spam.py', + ]) + self.assertEqual(ptvsd.wrapper.ptvsd_sys_exit_code, 0) + self.assertIs(exc, self.mainexc) + + def test_exit(self): + self.mainexc = SystemExit(1) + pydevd = FakePyDevd('pydevd/pydevd.py', self._main) + addr = (None, 8888) + with self.assertRaises(SystemExit): + run_file(addr, 'spam.py', _pydevd=pydevd, _install=self._install) + + self.assertEqual(self.pydevd, pydevd) + self.assertEqual(self.kwargs, {}) + self.assertEqual(self.maincalls, 1) + self.assertEqual(sys.argv, [ + sys.argv[0], + '--port', '8888', + '--file', 'spam.py', + ]) + self.assertEqual(ptvsd.wrapper.ptvsd_sys_exit_code, 1) + + def test_installed(self): + pydevd = FakePyDevd('pydevd/pydevd.py', self._main) + addr = (None, 8888) + run_file(addr, 'spam.py', _pydevd=pydevd) + + self.assertIs(pydevd_comm.start_server, ptvsd.wrapper.start_server) + self.assertIs(pydevd_comm.start_client, ptvsd.wrapper.start_client) + self.assertIs(pydevd.start_server, ptvsd.wrapper.start_server) + self.assertIs(pydevd.start_client, ptvsd.wrapper.start_client) + __main__ = sys.modules['__main__'] + self.assertIs(__main__.start_server, ptvsd.wrapper.start_server) + self.assertIs(__main__.start_client, ptvsd.wrapper.start_client) From be82fc67c1eb605203d53c549860c7ef01296cd5 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 3 Apr 2018 17:36:28 +0000 Subject: [PATCH 2/9] Add unit tests for debugger.py. --- ptvsd/debugger.py | 22 ++++-- tests/ptvsd/test_debugger.py | 143 +++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 tests/ptvsd/test_debugger.py diff --git a/ptvsd/debugger.py b/ptvsd/debugger.py index ec6717868..f7996ce42 100644 --- a/ptvsd/debugger.py +++ b/ptvsd/debugger.py @@ -11,11 +11,21 @@ # TODO: not needed? DONT_DEBUG = [] +RUNNERS = { + 'module': run_module, # python -m spam + 'script': run_file, # python spam.py + 'code': run_file, # python -c 'print("spam")' + None: run_file, # catchall +} -def debug(filename, port_num, debug_id, debug_options, run_as, **kwargs): + +def debug(filename, port_num, debug_id, debug_options, run_as, + _runners=RUNNERS, *args, **kwargs): # TODO: docstring - address = ('localhost', port_num) - if run_as == 'module': - run_module(address, filename, **kwargs) - else: - run_file(address, filename, **kwargs) + address = (None, port_num) + try: + run = _runners[run_as] + except KeyError: + # TODO: fail? + run = _runners[None] + run(address, filename, *args, **kwargs) diff --git a/tests/ptvsd/test_debugger.py b/tests/ptvsd/test_debugger.py new file mode 100644 index 000000000..340aec11b --- /dev/null +++ b/tests/ptvsd/test_debugger.py @@ -0,0 +1,143 @@ +import unittest + +from ptvsd.debugger import debug + + +class DebugTests(unittest.TestCase): + + def setUp(self): + super(DebugTests, self).setUp() + self.runners = {} + for kind in ('module', 'script', 'code', None): + def run(addr, name, kind=kind, **kwargs): + self._run(kind, addr, name, **kwargs) + self.runners[kind] = run + self.kind = None + self.args = None + self.kwargs = None + + def _run(self, kind, *args, **kwargs): + self.kind = kind + self.args = args + self.kwargs = kwargs + + def test_module(self): + filename = 'spam' + _, port = addr = (None, 8888) + debug_id = 1 + debug_options = {'x': 'y'} + debug(filename, port, debug_id, debug_options, 'module', + _runners=self.runners) + + self.assertEqual(self.kind, 'module') + self.assertEqual(self.args, (addr, filename)) + self.assertEqual(self.kwargs, {}) + + def test_script(self): + filename = 'spam.py' + _, port = addr = (None, 8888) + debug_id = 1 + debug_options = {'x': 'y'} + debug(filename, port, debug_id, debug_options, 'script', + _runners=self.runners) + + self.assertEqual(self.kind, 'script') + self.assertEqual(self.args, (addr, filename)) + self.assertEqual(self.kwargs, {}) + + def test_code(self): + filename = "print('spam')" + _, port = addr = (None, 8888) + debug_id = 1 + debug_options = {'x': 'y'} + debug(filename, port, debug_id, debug_options, 'code', + _runners=self.runners) + + self.assertEqual(self.kind, 'code') + self.assertEqual(self.args, (addr, filename)) + self.assertEqual(self.kwargs, {}) + + def test_unsupported(self): + filename = 'spam' + _, port = addr = (None, 8888) + debug_id = 1 + debug_options = {'x': 'y'} + debug(filename, port, debug_id, debug_options, '???', + _runners=self.runners) + + self.assertIs(self.kind, None) + self.assertEqual(self.args, (addr, filename)) + self.assertEqual(self.kwargs, {}) + + +class IntegrationTests(unittest.TestCase): + + def setUp(self): + super(IntegrationTests, self).setUp() + self.argv = None + self.kwargs = None + + def _run(self, argv, **kwargs): + self.argv = argv + self.kwargs = kwargs + + def test_module(self): + filename = 'spam' + port = 8888 + debug_id = 1 + debug_options = {'x': 'y'} + debug(filename, port, debug_id, debug_options, 'module', + _run=self._run, _prog='eggs') + + self.assertEqual(self.argv, [ + 'eggs', + '--port', '8888', + '--module', + '--file', 'spam:', + ]) + self.assertEqual(self.kwargs, {}) + + def test_script(self): + filename = 'spam.py' + port = 8888 + debug_id = 1 + debug_options = {'x': 'y'} + debug(filename, port, debug_id, debug_options, 'script', + _run=self._run, _prog='eggs') + + self.assertEqual(self.argv, [ + 'eggs', + '--port', '8888', + '--file', 'spam.py', + ]) + self.assertEqual(self.kwargs, {}) + + def test_code(self): + filename = "print('spam')" + port = 8888 + debug_id = 1 + debug_options = {'x': 'y'} + debug(filename, port, debug_id, debug_options, 'code', + _run=self._run, _prog='eggs') + + self.assertEqual(self.argv, [ + 'eggs', + '--port', '8888', + '--file', filename, + ]) + self.assertEqual(self.kwargs, {}) + + def test_unsupported(self): + filename = 'spam' + port = 8888 + debug_id = 1 + debug_options = {'x': 'y'} + debug(filename, port, debug_id, debug_options, '???', + _run=self._run, _prog='eggs') + + self.assertEqual(self.argv, [ + 'eggs', + '--port', '8888', + '--file', 'spam', + ]) + self.assertEqual(self.kwargs, {}) From 37fe9206d2efda0ff42dd25f25148f945f7d6a0b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 3 Apr 2018 17:46:41 +0000 Subject: [PATCH 3/9] Do not add an unnecessary -- in parse_args(). --- ptvsd/__main__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ptvsd/__main__.py b/ptvsd/__main__.py index 07a1376b1..1c567f232 100644 --- a/ptvsd/__main__.py +++ b/ptvsd/__main__.py @@ -139,7 +139,10 @@ def parse_args(argv=None): supported, pydevd, script = _group_args(argv) args = _parse_args(prog, supported) - return args, pydevd + ['--'] + script + extra = pydevd + if script: + extra += ['--'] + script + return args, extra def _group_args(argv): From 54fc37dfdb9d28fecfa31ec93bdac8d3ace9e711 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 3 Apr 2018 18:50:32 +0000 Subject: [PATCH 4/9] Add unit tests for parse_args(). --- ptvsd/__main__.py | 4 +- tests/ptvsd/test___main__.py | 180 ++++++++++++++++++++++++++++++++++- 2 files changed, 181 insertions(+), 3 deletions(-) diff --git a/ptvsd/__main__.py b/ptvsd/__main__.py index 1c567f232..f3d97fd51 100644 --- a/ptvsd/__main__.py +++ b/ptvsd/__main__.py @@ -183,9 +183,9 @@ def _group_args(argv): if arg == '--client': arg = '--host' elif arg == '--file': - if nextarg is None: + if nextarg is None: # The filename is missing... pydevd.append(arg) - continue + continue # This will get handled later. if nextarg.endswith(':') and '--module' in pydevd: pydevd.remove('--module') arg = '-m' diff --git a/tests/ptvsd/test___main__.py b/tests/ptvsd/test___main__.py index 21736ae39..a4fd3d6d2 100644 --- a/tests/ptvsd/test___main__.py +++ b/tests/ptvsd/test___main__.py @@ -1,10 +1,40 @@ +import contextlib +try: + from io import StringIO +except ImportError: + from StringIO import StringIO import sys import unittest from _pydevd_bundle import pydevd_comm import ptvsd.wrapper -from ptvsd.__main__ import run_module, run_file +from ptvsd.__main__ import run_module, run_file, parse_args + + +@contextlib.contextmanager +def captured_stdio(out=None, err=None): + if out is None: + if err is None: + out = err = StringIO() + elif err is False: + out = StringIO() + elif err is None and out is False: + err = StringIO() + if out is False: + out = None + if err is False: + err = None + + orig = sys.stdout, sys.stderr + if out is not None: + sys.stdout = out + if err is not None: + sys.stderr = err + try: + yield out, err + finally: + sys.stdout, sys.stderr = orig class FakePyDevd(object): @@ -232,3 +262,151 @@ def test_installed(self): __main__ = sys.modules['__main__'] self.assertIs(__main__.start_server, ptvsd.wrapper.start_server) self.assertIs(__main__.start_client, ptvsd.wrapper.start_client) + + +class ParseArgsTests(unittest.TestCase): + + def test_module(self): + args, extra = parse_args([ + 'eggs', + '--port', '8888', + '-m', 'spam', + ]) + + self.assertEqual(vars(args), { + 'kind': 'module', + 'name': 'spam', + 'address': (None, 8888), + }) + self.assertEqual(extra, []) + + def test_script(self): + args, extra = parse_args([ + 'eggs', + '--port', '8888', + 'spam.py', + ]) + + self.assertEqual(vars(args), { + 'kind': 'script', + 'name': 'spam.py', + 'address': (None, 8888), + }) + self.assertEqual(extra, []) + + def test_remote(self): + args, extra = parse_args([ + 'eggs', + '--host', '1.2.3.4', + '--port', '8888', + 'spam.py', + ]) + + self.assertEqual(vars(args), { + 'kind': 'script', + 'name': 'spam.py', + 'address': ('1.2.3.4', 8888), + }) + self.assertEqual(extra, []) + + def test_extra(self): + args, extra = parse_args([ + 'eggs', + '--DEBUG', + '--port', '8888', + '--vm_type', '???', + 'spam.py', + '--xyz', '123', + 'abc', + '--cmd-line', + '--', + 'foo', + '--server', + '--bar' + ]) + + self.assertEqual(vars(args), { + 'kind': 'script', + 'name': 'spam.py', + 'address': (None, 8888), + }) + self.assertEqual(extra, [ + '--DEBUG', + '--vm_type', '???', + '--', + '--xyz', '123', + 'abc', + '--cmd-line', + 'foo', + '--server', + '--bar', + ]) + + def test_unsupported_arg(self): + with self.assertRaises(SystemExit): + with captured_stdio(): + parse_args([ + 'eggs', + '--port', '8888', + '--xyz', '123', + 'spam.py', + ]) + + def test_backward_compatibility_host(self): + args, extra = parse_args([ + 'eggs', + '--client', '1.2.3.4', + '--port', '8888', + '-m', 'spam', + ]) + + self.assertEqual(vars(args), { + 'kind': 'module', + 'name': 'spam', + 'address': ('1.2.3.4', 8888), + }) + self.assertEqual(extra, []) + + def test_backward_compatibility_module(self): + args, extra = parse_args([ + 'eggs', + '--port', '8888', + '--module', + '--file', 'spam:', + ]) + + self.assertEqual(vars(args), { + 'kind': 'module', + 'name': 'spam', + 'address': (None, 8888), + }) + self.assertEqual(extra, []) + + def test_backward_compatibility_script(self): + args, extra = parse_args([ + 'eggs', + '--port', '8888', + '--file', 'spam.py', + ]) + + self.assertEqual(vars(args), { + 'kind': 'script', + 'name': 'spam.py', + 'address': (None, 8888), + }) + self.assertEqual(extra, []) + + def test_pseudo_backward_compatibility(self): + args, extra = parse_args([ + 'eggs', + '--port', '8888', + '--module', + '--file', 'spam', + ]) + + self.assertEqual(vars(args), { + 'kind': 'script', + 'name': 'spam', + 'address': (None, 8888), + }) + self.assertEqual(extra, ['--module']) From 2f364e61711d0751c0edbe2f2bad1e1772f89401 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 3 Apr 2018 23:59:44 +0000 Subject: [PATCH 5/9] Preserve extra sys.argv args in debug(). --- ptvsd/debugger.py | 8 +++++- tests/ptvsd/test_debugger.py | 55 +++++++++++++++++++++++++++++++----- 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/ptvsd/debugger.py b/ptvsd/debugger.py index f7996ce42..a157d84ec 100644 --- a/ptvsd/debugger.py +++ b/ptvsd/debugger.py @@ -2,6 +2,8 @@ # Licensed under the MIT License. See LICENSE in the project root # for license information. +import sys + from ptvsd.__main__ import run_module, run_file @@ -20,12 +22,16 @@ def debug(filename, port_num, debug_id, debug_options, run_as, - _runners=RUNNERS, *args, **kwargs): + _runners=RUNNERS, _extra=None, *args, **kwargs): # TODO: docstring + if _extra is None: + _extra = sys.argv[1:] address = (None, port_num) try: run = _runners[run_as] except KeyError: # TODO: fail? run = _runners[None] + if _extra: + args = _extra + list(args) run(address, filename, *args, **kwargs) diff --git a/tests/ptvsd/test_debugger.py b/tests/ptvsd/test_debugger.py index 340aec11b..c209df23e 100644 --- a/tests/ptvsd/test_debugger.py +++ b/tests/ptvsd/test_debugger.py @@ -1,3 +1,4 @@ +import sys import unittest from ptvsd.debugger import debug @@ -7,11 +8,13 @@ class DebugTests(unittest.TestCase): def setUp(self): super(DebugTests, self).setUp() + def _make_run(kind): + def run(addr, name, *args, **kwargs): + self._run(kind, addr, name, *args, **kwargs) + return run self.runners = {} for kind in ('module', 'script', 'code', None): - def run(addr, name, kind=kind, **kwargs): - self._run(kind, addr, name, **kwargs) - self.runners[kind] = run + self.runners[kind] = _make_run(kind) self.kind = None self.args = None self.kwargs = None @@ -27,7 +30,7 @@ def test_module(self): debug_id = 1 debug_options = {'x': 'y'} debug(filename, port, debug_id, debug_options, 'module', - _runners=self.runners) + _runners=self.runners, _extra=()) self.assertEqual(self.kind, 'module') self.assertEqual(self.args, (addr, filename)) @@ -39,7 +42,7 @@ def test_script(self): debug_id = 1 debug_options = {'x': 'y'} debug(filename, port, debug_id, debug_options, 'script', - _runners=self.runners) + _runners=self.runners, _extra=()) self.assertEqual(self.kind, 'script') self.assertEqual(self.args, (addr, filename)) @@ -51,7 +54,7 @@ def test_code(self): debug_id = 1 debug_options = {'x': 'y'} debug(filename, port, debug_id, debug_options, 'code', - _runners=self.runners) + _runners=self.runners, _extra=()) self.assertEqual(self.kind, 'code') self.assertEqual(self.args, (addr, filename)) @@ -63,12 +66,23 @@ def test_unsupported(self): debug_id = 1 debug_options = {'x': 'y'} debug(filename, port, debug_id, debug_options, '???', - _runners=self.runners) + _runners=self.runners, _extra=()) self.assertIs(self.kind, None) self.assertEqual(self.args, (addr, filename)) self.assertEqual(self.kwargs, {}) + def test_extra_sys_argv(self): + filename = 'spam.py' + _, port = addr = (None, 8888) + debug_id = 1 + debug_options = {'x': 'y'} + extra = ['--eggs', 'abc'] + debug(filename, port, debug_id, debug_options, 'script', + _runners=self.runners, _extra=extra) + + self.assertEqual(self.args, (addr, filename, '--eggs', 'abc')) + class IntegrationTests(unittest.TestCase): @@ -76,6 +90,11 @@ def setUp(self): super(IntegrationTests, self).setUp() self.argv = None self.kwargs = None + self._sys_argv = list(sys.argv) + + def tearDown(self): + sys.argv[:] = self._sys_argv + super(IntegrationTests, self).tearDown() def _run(self, argv, **kwargs): self.argv = argv @@ -86,6 +105,7 @@ def test_module(self): port = 8888 debug_id = 1 debug_options = {'x': 'y'} + sys.argv = [filename] debug(filename, port, debug_id, debug_options, 'module', _run=self._run, _prog='eggs') @@ -102,6 +122,7 @@ def test_script(self): port = 8888 debug_id = 1 debug_options = {'x': 'y'} + sys.argv = [filename] debug(filename, port, debug_id, debug_options, 'script', _run=self._run, _prog='eggs') @@ -117,6 +138,7 @@ def test_code(self): port = 8888 debug_id = 1 debug_options = {'x': 'y'} + sys.argv = [filename] debug(filename, port, debug_id, debug_options, 'code', _run=self._run, _prog='eggs') @@ -132,6 +154,7 @@ def test_unsupported(self): port = 8888 debug_id = 1 debug_options = {'x': 'y'} + sys.argv = [filename] debug(filename, port, debug_id, debug_options, '???', _run=self._run, _prog='eggs') @@ -141,3 +164,21 @@ def test_unsupported(self): '--file', 'spam', ]) self.assertEqual(self.kwargs, {}) + + def test_extra_sys_argv(self): + filename = 'spam.py' + port = 8888 + debug_id = 1 + debug_options = {'x': 'y'} + sys.argv = [filename, '--abc', 'xyz', '42'] + debug(filename, port, debug_id, debug_options, 'script', + _run=self._run, _prog='eggs') + + self.assertEqual(self.argv, [ + 'eggs', + '--port', '8888', + '--file', 'spam.py', + '--abc', 'xyz', + '42', + ]) + self.assertEqual(self.kwargs, {}) From 899d146dd7cf408420f99a55d66b9770bf3195fe Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 4 Apr 2018 00:09:15 +0000 Subject: [PATCH 6/9] Always use a localhost addr in debug(). --- ptvsd/debugger.py | 4 +++- tests/ptvsd/test_debugger.py | 17 +++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ptvsd/debugger.py b/ptvsd/debugger.py index a157d84ec..465735795 100644 --- a/ptvsd/debugger.py +++ b/ptvsd/debugger.py @@ -13,6 +13,8 @@ # TODO: not needed? DONT_DEBUG = [] +LOCALHOST = '127.0.0.1' + RUNNERS = { 'module': run_module, # python -m spam 'script': run_file, # python spam.py @@ -26,7 +28,7 @@ def debug(filename, port_num, debug_id, debug_options, run_as, # TODO: docstring if _extra is None: _extra = sys.argv[1:] - address = (None, port_num) + address = (LOCALHOST, port_num) try: run = _runners[run_as] except KeyError: diff --git a/tests/ptvsd/test_debugger.py b/tests/ptvsd/test_debugger.py index c209df23e..d22a99b78 100644 --- a/tests/ptvsd/test_debugger.py +++ b/tests/ptvsd/test_debugger.py @@ -1,7 +1,7 @@ import sys import unittest -from ptvsd.debugger import debug +from ptvsd.debugger import debug, LOCALHOST class DebugTests(unittest.TestCase): @@ -26,7 +26,7 @@ def _run(self, kind, *args, **kwargs): def test_module(self): filename = 'spam' - _, port = addr = (None, 8888) + _, port = addr = (LOCALHOST, 8888) debug_id = 1 debug_options = {'x': 'y'} debug(filename, port, debug_id, debug_options, 'module', @@ -38,7 +38,7 @@ def test_module(self): def test_script(self): filename = 'spam.py' - _, port = addr = (None, 8888) + _, port = addr = (LOCALHOST, 8888) debug_id = 1 debug_options = {'x': 'y'} debug(filename, port, debug_id, debug_options, 'script', @@ -50,7 +50,7 @@ def test_script(self): def test_code(self): filename = "print('spam')" - _, port = addr = (None, 8888) + _, port = addr = (LOCALHOST, 8888) debug_id = 1 debug_options = {'x': 'y'} debug(filename, port, debug_id, debug_options, 'code', @@ -62,7 +62,7 @@ def test_code(self): def test_unsupported(self): filename = 'spam' - _, port = addr = (None, 8888) + _, port = addr = (LOCALHOST, 8888) debug_id = 1 debug_options = {'x': 'y'} debug(filename, port, debug_id, debug_options, '???', @@ -74,7 +74,7 @@ def test_unsupported(self): def test_extra_sys_argv(self): filename = 'spam.py' - _, port = addr = (None, 8888) + _, port = addr = (LOCALHOST, 8888) debug_id = 1 debug_options = {'x': 'y'} extra = ['--eggs', 'abc'] @@ -112,6 +112,7 @@ def test_module(self): self.assertEqual(self.argv, [ 'eggs', '--port', '8888', + '--client', LOCALHOST, '--module', '--file', 'spam:', ]) @@ -129,6 +130,7 @@ def test_script(self): self.assertEqual(self.argv, [ 'eggs', '--port', '8888', + '--client', LOCALHOST, '--file', 'spam.py', ]) self.assertEqual(self.kwargs, {}) @@ -145,6 +147,7 @@ def test_code(self): self.assertEqual(self.argv, [ 'eggs', '--port', '8888', + '--client', LOCALHOST, '--file', filename, ]) self.assertEqual(self.kwargs, {}) @@ -161,6 +164,7 @@ def test_unsupported(self): self.assertEqual(self.argv, [ 'eggs', '--port', '8888', + '--client', LOCALHOST, '--file', 'spam', ]) self.assertEqual(self.kwargs, {}) @@ -177,6 +181,7 @@ def test_extra_sys_argv(self): self.assertEqual(self.argv, [ 'eggs', '--port', '8888', + '--client', LOCALHOST, '--file', 'spam.py', '--abc', 'xyz', '42', From 91cf8a801b229fe26dbf7efb0cf5cc929980d7e2 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 4 Apr 2018 00:09:47 +0000 Subject: [PATCH 7/9] lint --- tests/ptvsd/test_debugger.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ptvsd/test_debugger.py b/tests/ptvsd/test_debugger.py index d22a99b78..5fceacbe7 100644 --- a/tests/ptvsd/test_debugger.py +++ b/tests/ptvsd/test_debugger.py @@ -8,6 +8,7 @@ class DebugTests(unittest.TestCase): def setUp(self): super(DebugTests, self).setUp() + def _make_run(kind): def run(addr, name, *args, **kwargs): self._run(kind, addr, name, *args, **kwargs) From a96efb72e0cab5e2cd14cb47f945de715a290d5b Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 4 Apr 2018 00:14:14 +0000 Subject: [PATCH 8/9] Switch to "localhost". --- ptvsd/debugger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ptvsd/debugger.py b/ptvsd/debugger.py index 465735795..ff6df4775 100644 --- a/ptvsd/debugger.py +++ b/ptvsd/debugger.py @@ -13,7 +13,7 @@ # TODO: not needed? DONT_DEBUG = [] -LOCALHOST = '127.0.0.1' +LOCALHOST = 'localhost' RUNNERS = { 'module': run_module, # python -m spam From a1bf02b2690846276f4487d8233f89161a5698ac Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 4 Apr 2018 14:40:29 +0000 Subject: [PATCH 9/9] Use BytesIO in Python 2. --- tests/ptvsd/test___main__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ptvsd/test___main__.py b/tests/ptvsd/test___main__.py index a4fd3d6d2..ece74e6ae 100644 --- a/tests/ptvsd/test___main__.py +++ b/tests/ptvsd/test___main__.py @@ -1,8 +1,5 @@ import contextlib -try: - from io import StringIO -except ImportError: - from StringIO import StringIO +from io import StringIO import sys import unittest @@ -11,6 +8,9 @@ import ptvsd.wrapper from ptvsd.__main__ import run_module, run_file, parse_args +if sys.version_info < (3,): + from io import BytesIO as StringIO # noqa + @contextlib.contextmanager def captured_stdio(out=None, err=None):