Ejemplo n.º 1
0
    def test_as_client_default_host(self):
        addr = Address.as_client(None, 9786)

        self.assertEqual(
            addr,
            Address('localhost', 9786, isserver=False),
        )
Ejemplo n.º 2
0
    def test_as_server_public_host(self):
        addr = Address.as_server('', 9786)

        self.assertEqual(
            addr,
            Address('', 9786, isserver=True),
        )
Ejemplo n.º 3
0
    def test_new_wildcard_host(self):
        addr = Address('*', 9786)

        self.assertEqual(
            addr,
            Address('', 9786, isserver=True),
        )
Ejemplo n.º 4
0
    def test_as_client_public_host(self):
        addr = Address.as_client('', 9786)

        self.assertEqual(
            addr,
            Address('', 9786, isserver=False),
        )
Ejemplo n.º 5
0
    def test_as_server_default_host(self):
        addr = Address.as_server(None, 9786)

        self.assertEqual(
            addr,
            Address('localhost', 9786, isserver=True),
        )
Ejemplo n.º 6
0
    def test_server(self):
        addr = Address.as_server('10.0.1.1', 8888)
        run_module(addr, 'spam', _run=self._run, _prog='eggs')

        self.assertEqual(self.argv,
                         _get_args('--module', '--file', 'spam:'))

        self.assertEqual(self.addr, Address.as_server(*addr))
        self.assertEqual(self.kwargs, {})
Ejemplo n.º 7
0
    def test_as_client_valid_address(self):
        for host in ['localhost', '127.0.0.1', '::', '1.2.3.4']:
            with self.subTest(host):
                addr = Address.as_client(host, 9786)

                self.assertEqual(
                    addr,
                    Address(host, 9786, isserver=False),
                )
Ejemplo n.º 8
0
    def test_nodebug_module_no_args(self):
        addr = Address.as_server('10.0.1.1', 8888)
        run_main(addr, 'spam.py', 'module',
                 _runner=self._no_debug_runner)

        self.assertEqual(self.argv, ['spam.py'])

        self.assertEqual(self.addr, Address.as_server(*addr))
        self.assertTrue(self.is_module)
        self.assertEqual(self.args, ())
        self.assertEqual(self.kwargs, {})
Ejemplo n.º 9
0
def _parse_args(prog, argv):
    parser = argparse.ArgumentParser(
        prog=prog,
        usage=USAGE.format(prog),
    )

    parser.add_argument('--nodebug', action='store_true')

    host = parser.add_mutually_exclusive_group()
    host.add_argument('--host')
    host.add_argument('--server-host')
    parser.add_argument('--port', type=int, required=True)

    target = parser.add_mutually_exclusive_group(required=True)
    target.add_argument('-m', dest='module')
    target.add_argument('--pid', type=int)
    target.add_argument('filename', nargs='?')

    parser.add_argument('--single-session', action='store_true')
    parser.add_argument('--wait', action='store_true')

    parser.add_argument('-V', '--version', action='version')
    parser.version = __version__

    args = parser.parse_args(argv)
    ns = vars(args)

    serverhost = ns.pop('server_host', None)
    clienthost = ns.pop('host', None)
    if serverhost:
        args.address = Address.as_server(serverhost, ns.pop('port'))
    elif not clienthost:
        if args.nodebug:
            args.address = Address.as_client(clienthost, ns.pop('port'))
        else:
            args.address = Address.as_server(clienthost, ns.pop('port'))
    else:
        args.address = Address.as_client(clienthost, ns.pop('port'))

    pid = ns.pop('pid')
    module = ns.pop('module')
    filename = ns.pop('filename')
    if pid is not None:
        args.name = pid
        args.kind = 'pid'
    elif module is not None:
        args.name = module
        args.kind = 'module'
    else:
        args.name = filename
        args.kind = 'script'

    return args
Ejemplo n.º 10
0
    def test_as_server_bad_port(self):
        port = None
        for host in [None, '', 'localhost', '1.2.3.4']:
            with self.subTest((host, port)):
                with self.assertRaises(TypeError):
                    Address.as_server(host, port)

        for port in ['', -1, 65536]:
            for host in [None, '', 'localhost', '1.2.3.4']:
                with self.subTest((host, port)):
                    with self.assertRaises(ValueError):
                        Address.as_server(host, port)
Ejemplo n.º 11
0
    def test_remote_localhost(self):
        addr = Address.as_client(None, 8888)
        run_module(addr, 'spam', _run=self._run, _prog='eggs')

        self.assertEqual(self.argv,
                         _get_args(
                             '--module', '--file', 'spam:',
                             ptvsd_extras=['--client', 'localhost']))

        self.assertEqual(self.addr, Address.as_client(*addr))
        self.assertEqual(self.kwargs, {
            'singlesession': True,
        })
Ejemplo n.º 12
0
    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,
            _get_args('--file',
                      'spam.py',
                      '--abc',
                      'xyz',
                      '42',
                      ptvsd_extras=['--client', LOCALHOST]))
        self.assertEqual(self.addr, Address.as_client(None, port))
        self.assertEqual(self.kwargs, {
            'singlesession': True,
        })
Ejemplo n.º 13
0
    def test_pseudo_backward_compatibility_nodebug(self):
        args, extra = parse_args([
            'eggs',
            '--nodebug',
            '--client',
            '--host',
            'localhost',
            '--port',
            '8888',
            '--module',
            '--file',
            'spam',
        ])

        self.assertEqual(
            vars(args), {
                'kind': 'script',
                'name': 'spam',
                'address': Address.as_client('localhost', 8888),
                'nodebug': True,
                'single_session': False,
                'wait': False,
                'multiprocess': False,
            })
        self.assertEqual(extra, ['--module'] + self.EXPECTED_EXTRA)
Ejemplo n.º 14
0
    def test_extra_nodebug(self):
        args, extra = parse_args([
            'eggs', '--DEBUG', '--nodebug', '--port', '8888', '--vm_type',
            '???', 'spam.py', '--xyz', '123', 'abc', '--cmd-line', '--', 'foo',
            '--server', '--bar'
        ])

        self.assertEqual(
            vars(args), {
                'kind': 'script',
                'name': 'spam.py',
                'address': Address.as_client(None, 8888),
                'nodebug': True,
                'single_session': False,
                'wait': False,
            })
        self.assertEqual(
            extra,
            [
                '--DEBUG',
                '--vm_type',
                '???',
                '--',  # Expected pydevd defaults separator
                '--xyz',
                '123',
                'abc',
                '--cmd-line',
                'foo',
                '--server',
                '--bar',
            ])
Ejemplo n.º 15
0
def install(pydevd,
            address,
            start_server=start_server,
            start_client=start_client,
            **kwargs):
    """Configure pydevd to use our wrapper.

    This is a bit of a hack to allow us to run our VSC debug adapter
    in the same process as pydevd.  Note that, as with most hacks,
    this is somewhat fragile (since the monkeypatching sites may
    change).
    """
    addr = Address.from_raw(address)
    daemon = Daemon(**kwargs)

    _start_server = (lambda p: start_server(daemon, addr.host, p))
    _start_server.orig = start_server
    _start_client = (lambda h, p: start_client(daemon, h, p))
    _start_client.orig = start_client

    # These are the functions pydevd invokes to get a socket to the client.
    pydevd_comm.start_server = _start_server
    pydevd_comm.start_client = _start_client

    # Ensure that pydevd is using our functions.
    pydevd.start_server = _start_server
    pydevd.start_client = _start_client
    __main__ = sys.modules['__main__']
    if __main__ is not pydevd:
        if getattr(__main__, '__file__', None) == pydevd.__file__:
            __main__.start_server = _start_server
            __main__.start_client = _start_client
    return daemon
Ejemplo n.º 16
0
    def test_attach_started_separately(self):
        lockfile = self.workspace.lockfile()
        done, waitscript = lockfile.wait_in_script()
        filename = self.write_script('spam.py', waitscript)
        addr = Address('localhost', 8888)
        with DebugAdapter.start_for_attach(addr, filename) as adapter:
            with DebugClient() as editor:
                session = editor.attach_socket(addr, adapter)

                with session.wait_for_event('thread'):
                    (req_initialize, req_launch, req_config, _, _, _
                     ) = lifecycle_handshake(session, 'attach')

                done()
                adapter.wait()

        received = list(_strip_newline_output_events(session.received))
        self.assert_received(received[:7], [
            self.new_version_event(session.received),
            self.new_response(req_initialize.req, **INITIALIZE_RESPONSE),
            self.new_event('initialized'),
            self.new_response(req_launch.req),
            self.new_response(req_config.req),
            self.new_event('process', **{
                'isLocalProcess': True,
                'systemProcessId': adapter.pid,
                'startMethod': 'attach',
                'name': filename,
            }),
            self.new_event('thread', reason='started', threadId=1),
            #self.new_event('thread', reason='exited', threadId=1),
            #self.new_event('exited', exitCode=0),
            #self.new_event('terminated'),
        ])
Ejemplo n.º 17
0
    def test_wait_for_attach(self):
        addr = Address('localhost', PORT)
        filename = self.write_script(
            'spam.py',
            """
            import sys
            sys.path.insert(0, {!r})
            import ptvsd
            ptvsd.enable_attach({}, redirect_output=False)

            ptvsd.wait_for_attach()
            # <ready>
            # <wait>
            """.format(PROJECT_ROOT, tuple(addr)),
        )
        lockfile1 = self.workspace.lockfile()
        _, wait = set_release(filename, lockfile1, 'ready')
        lockfile2 = self.workspace.lockfile()
        done, _ = set_lock(filename, lockfile2, 'wait')

        adapter = DebugAdapter.start_embedded(addr, filename)
        with adapter:
            with DebugClient() as editor:
                session = editor.attach_socket(addr, adapter, timeout=1)
                # Ensure that it really does wait.
                with self.assertRaises(LockTimeoutError):
                    wait(timeout=0.5)

                lifecycle_handshake(session, 'attach')
                wait(timeout=1)
                done()
                adapter.wait()
Ejemplo n.º 18
0
 def start_for_attach(cls, addr, *args, **kwargs):
     srvtimeout = kwargs.pop('srvtimeout', SERVER_READY_TIMEOUT)
     addr = Address.as_server(*addr)
     adapter = cls._start_as(addr, *args, server=True, **kwargs)
     if srvtimeout is not None:
         wait_for_socket_server(addr, timeout=srvtimeout)
     return adapter
    def start_client(self, addr):
        """Return ("socket", start_session) with a new client socket."""

        ptvsd.log.debug('Starting client daemon on {0!r}.', addr)

        addr = Address.from_raw(addr)
        self._singlesession = True
        with self.started():
            assert self.session is None
            client = create_client()
            connect(client, addr)
        sock = self._sock

        def start_session(**kwargs):
            self._check_ready_for_session()
            if self._server is not None:
                raise RuntimeError('running as server')
            if self._numsessions:
                raise RuntimeError('session stopped')

            try:
                self._bind_session(client)
                self._start_session_safely('ptvsd.Client', **kwargs)
                return self._session
            except Exception:
                self._stop_quietly()
                raise

        return sock, start_session
Ejemplo n.º 20
0
def run_file(address, filename, *extra, **kwargs):
    """Run pydevd for the given Python file."""
    addr = Address.from_raw(address)
    run = kwargs.pop('_run', _run)
    prog = kwargs.pop('_prog', sys.argv[0])
    argv = _run_argv(addr, filename, extra, _prog=prog)
    run(argv, addr, **kwargs)
Ejemplo n.º 21
0
def enable_attach(address,
                  on_attach=(lambda: None),
                  redirect_output=True,
                  _pydevd=pydevd,
                  _install=install,
                  _settrace=_pydevd_settrace,
                  **kwargs):
    addr = Address.as_server(*address)
    debug('installing ptvsd as server')
    # pydevd.settrace() forces a "client" connection, so we trick it
    # by setting start_client to start_server..
    daemon = _install(_pydevd,
                      addr,
                      start_client=start_server,
                      notify_session_debugger_ready=(lambda s: on_attach()),
                      singlesession=False,
                      **kwargs)

    def start_pydevd():
        debug('enabling pydevd')
        # Only pass the port so start_server() gets triggered.
        # As noted above, we also have to trick settrace() because it
        # *always* forces a client connection.
        _settrace(
            stdoutToServer=redirect_output,
            stderrToServer=redirect_output,
            port=addr.port,
            suspend=False,
            _pydevd=_pydevd,
        )
        debug('pydevd enabled')

    t = new_hidden_thread('start-pydevd', start_pydevd)
    t.start()

    def wait(timeout=None):
        t.join(timeout)
        return not t.is_alive()

    def debug_current_thread(suspend=False, **kwargs):
        # Make sure that pydevd has finished starting before enabling
        # in the current thread.
        t.join()
        debug('enabling pydevd (current thread)')
        _settrace(
            host=None,  # ignored
            stdoutToServer=False,  # ignored
            stderrToServer=False,  # ignored
            port=None,  # ignored
            suspend=suspend,
            trace_only_current_thread=True,
            overwrite_prev_trace=True,
            patch_multiprocessing=False,
            _pydevd=_pydevd,
            **kwargs)
        debug('pydevd enabled (current thread)')

    return daemon, wait, debug_current_thread
Ejemplo n.º 22
0
def run_file(address, filename, *extra, **kwargs):
    """Run pydevd for the given Python file."""
    addr = Address.from_raw(address)
    if not addr.isserver:
        kwargs['singlesession'] = True
    run = kwargs.pop('_run', _run)
    prog = kwargs.pop('_prog', sys.argv[0])
    argv = _run_argv(addr, filename, extra, _prog=prog)
    run(argv, addr, **kwargs)
Ejemplo n.º 23
0
def run_file(address, filename, *extra, **kwargs):
    """Run pydevd for the given Python file."""
    addr = Address.from_raw(address)
    if not addr.isserver:
        kwargs['singlesession'] = True
    run = kwargs.pop('_run', _run)
    prog = kwargs.pop('_prog', sys.argv[0])
    argv = _run_argv(addr, filename, extra, _prog=prog)
    run(argv, addr, **kwargs)
Ejemplo n.º 24
0
def run_module(address, modname, *extra, **kwargs):
    """Run pydevd for the given module."""
    addr = Address.from_raw(address)
    run = kwargs.pop('_run', _run)
    prog = kwargs.pop('_prog', sys.argv[0])
    filename = modname + ':'
    argv = _run_argv(addr, filename, extra, _prog=prog)
    argv.insert(argv.index('--file'), '--module')
    run(argv, addr, **kwargs)
Ejemplo n.º 25
0
    def test_local(self):
        addr = (None, 8888)
        run_file(addr, 'spam.py', _run=self._run, _prog='eggs')

        self.assertEqual(self.argv,
                         _get_args('--file', 'spam.py'))

        self.assertEqual(self.addr, Address.as_server(*addr))
        self.assertEqual(self.kwargs, {})
Ejemplo n.º 26
0
    def test_executable(self):
        addr = (None, 8888)
        run_file(addr, 'spam.py', _run=self._run)

        self.assertEqual(self.argv,
                         _get_args('--file', 'spam.py', prog=sys.argv[0]))

        self.assertEqual(self.addr, Address.as_server(*addr))
        self.assertEqual(self.kwargs, {})
Ejemplo n.º 27
0
    def test_attach_embedded(self):
        lockfile = self.workspace.lockfile()
        done, waitscript = lockfile.wait_in_script()
        addr = Address('localhost', 8888)
        script = dedent("""
            from __future__ import print_function
            import sys
            sys.path.insert(0, {!r})
            import ptvsd
            ptvsd.enable_attach({}, redirect_output={})
            ptvsd.wait_for_attach()

            print('success!', end='')

            %s
            """).format(os.getcwd(), tuple(addr), True)
        filename = self.write_script('spam.py', script % waitscript)
        with DebugAdapter.start_embedded(addr, filename) as adapter:
            with DebugClient() as editor:
                session = editor.attach_socket(addr, adapter)

                (req_initialize, req_launch, req_config, _, _,
                 _) = lifecycle_handshake(session, 'attach')
                Awaitable.wait_all(req_initialize, req_launch)
                done()
                adapter.wait()

        for i in range(10):
            # It could take some additional time for the adapter
            # to actually get the success output, so, wait for the
            # expected condition in a busy loop.
            out = adapter.output.decode('utf-8')
            if 'success!' in out:
                break
            import time
            time.sleep(.1)

        received = list(_strip_newline_output_events(session.received))
        self.assert_contains(received, [
            self.new_version_event(session.received),
            self.new_response(req_initialize.req, **INITIALIZE_RESPONSE),
            self.new_event('initialized'),
            self.new_response(req_launch.req),
            self.new_response(req_config.req),
            self.new_event(
                'process', **{
                    'isLocalProcess': True,
                    'systemProcessId': adapter.pid,
                    'startMethod': 'attach',
                    'name': filename,
                }),
            self.new_event('output', output='success!', category='stdout'),
            self.new_event('exited', exitCode=0),
            self.new_event('terminated'),
        ])
        self.assertIn('success!', out)
Ejemplo n.º 28
0
def _parse_args(prog, argv):
    parser = argparse.ArgumentParser(
        prog=prog,
        usage=USAGE.format(prog),
    )
    parser.add_argument('--nodebug', action='store_true')
    host = parser.add_mutually_exclusive_group()
    host.add_argument('--host')
    host.add_argument('--server-host')
    parser.add_argument('--port', type=int, required=True)

    target = parser.add_mutually_exclusive_group(required=True)
    target.add_argument('-m', dest='module')
    target.add_argument('filename', nargs='?')

    args = parser.parse_args(argv)
    ns = vars(args)

    serverhost = ns.pop('server_host', None)
    clienthost = ns.pop('host', None)
    if serverhost:
        args.address = Address.as_server(serverhost, ns.pop('port'))
    elif not clienthost:
        if args.nodebug:
            args.address = Address.as_client(clienthost, ns.pop('port'))
        else:
            args.address = Address.as_server(clienthost, ns.pop('port'))
    else:
        args.address = Address.as_client(clienthost, ns.pop('port'))

    module = ns.pop('module')
    filename = ns.pop('filename')
    if module is None:
        args.name = filename
        args.kind = 'script'
    else:
        args.name = module
        args.kind = 'module'
    #if argv[-1] != args.name or (module and argv[-1] != '-m'):
    #    parser.error('script/module must be last arg')

    return args
    def start_server(self, addr, hidebadsessions=True):
        """Return ("socket", next_session) with a new server socket."""

        ptvsd.log.debug('Starting server daemon on {0!r}.', addr)

        addr = Address.from_raw(addr)
        with self.started():
            assert self._sessionlock is None
            assert self.session is None
            self._server = create_server(addr.host, addr.port)
            host, port = self._server.getsockname()
            ptvsd.log.debug('Server socket created on {0!r}', addr)
            self._sessionlock = threading.Lock()
        sock = self._sock

        def check_ready(**kwargs):
            self._check_ready_for_session(**kwargs)
            if self._server is None:
                raise DaemonStoppedError()

        def next_session(timeout=None, **kwargs):
            server = self._server
            sessionlock = self._sessionlock
            check_ready(checksession=False)

            ptvsd.log.debug('Getting next session...')
            sessionlock.acquire()  # Released in _finish_session().
            ptvsd.log.debug('Session lock acquired.')
            # It may have closed or stopped while we waited.
            check_ready()

            timeout = kwargs.pop('timeout', None)
            try:
                ptvsd.log.debug('Getting session socket...')
                client = connect(server, None, **kwargs)
                self._bind_session(client)
                ptvsd.log.debug('Starting session...')
                self._start_session_safely('ptvsd.Server', timeout=timeout)
                ptvsd.log.debug('Session started.')
                return self._session
            except Exception:
                ptvsd.log.exception(category=('D' if hidebadsessions else 'E'))
                with ignore_errors():
                    self._finish_session()
                if hidebadsessions:
                    ptvsd.log.debug('Hiding bad session')
                    return None
                self._stop_quietly()
                raise

        if options.subprocess_notify:
            multiproc.notify_root(port)

        return sock, next_session
Ejemplo n.º 30
0
def run_module(address, modname, *extra, **kwargs):
    """Run pydevd for the given module."""
    addr = Address.from_raw(address)
    if not addr.isserver:
        kwargs['singlesession'] = True
    run = kwargs.pop('_run', _run)
    prog = kwargs.pop('_prog', sys.argv[0])
    filename = modname + ':'
    argv = _run_argv(addr, filename, extra, _prog=prog)
    argv.insert(argv.index('--file'), '--module')
    run(argv, addr, **kwargs)
Ejemplo n.º 31
0
    def test_nodebug_module_args(self):
        addr = (None, 8888)
        args = ('--one', '--two', '--three')
        run_main(addr, 'spam.py', 'module', *args,
                 _runner=self._no_debug_runner)

        self.assertEqual(self.argv, ['spam.py'] + list(args))

        self.assertEqual(self.addr, Address.as_server(*addr))
        self.assertTrue(self.is_module)
        self.assertEqual(self.args, args)
        self.assertEqual(self.kwargs, {})
Ejemplo n.º 32
0
    def test_extra(self):
        addr = (None, 8888)
        run_module(addr, 'spam', '--vm_type', 'xyz', '--', '--DEBUG',
                   _run=self._run, _prog='eggs')

        self.assertEqual(self.argv,
                         _get_args(
                             '--module', '--file', 'spam:', '--DEBUG',
                             ptvsd_extras=['--vm_type', 'xyz']))

        self.assertEqual(self.addr, Address.as_server(*addr))
        self.assertEqual(self.kwargs, {})
Ejemplo n.º 33
0
def install(pydevd_module, address,
            start_server=start_server, start_client=start_client,
            **kwargs):
    """Configure pydevd to use our wrapper.

    This is a bit of a hack to allow us to run our VSC debug adapter
    in the same process as pydevd.  Note that, as with most hacks,
    this is somewhat fragile (since the monkeypatching sites may
    change).
    """

    ptvsd.log.debug('Installing pydevd hooks.')

    addr = Address.from_raw(address)
    daemon = Daemon(**kwargs)

    _start_server = (lambda p: start_server(daemon, addr.host, p))
    _start_server.orig = start_server
    _start_client = (lambda h, p: start_client(daemon, h, p))
    _start_client.orig = start_client

    # These are the functions pydevd invokes to get a socket to the client.
    pydevd_comm.start_server = _start_server
    pydevd_comm.start_client = _start_client

    # This is invoked when a child process is spawned with multiproc debugging enabled.
    pydev_monkey.patch_args = multiproc.patch_and_quote_args
    if not options.multiprocess and not options.no_debug:
        # This means '--multiprocess' flag was not passed via command line args. Patch the
        # new process functions here to handle multiprocess being enabled via debug options.
        ptvsd.log.debug('Monkey-patching multiprocess functions.')
        pydev_monkey.patch_new_process_functions()

    # Ensure that pydevd is using our functions.
    pydevd_module.start_server = _start_server
    pydevd_module.start_client = _start_client
    __main__ = sys.modules['__main__']
    if __main__ is not pydevd:
        if getattr(__main__, '__file__', None) == pydevd.__file__:
            __main__.start_server = _start_server
            __main__.start_client = _start_client

    return daemon
Ejemplo n.º 34
0
def run_main(address, name, kind, *extra, **kwargs):
    addr = Address.from_raw(address)
    sys.argv[:] = _run_main_argv(name, extra)
    runner = kwargs.pop('_runner', no_debug_runner)
    runner(addr, name, kind == 'module', *extra, **kwargs)