コード例 #1
0
ファイル: components.py プロジェクト: pengjianaixue/ptvsd
    def __init__(self, component, message):
        """Parses an "initialize" request or response and extracts the feature flags.

        For every "X" in self.PROPERTIES, sets self["X"] to the corresponding value
        from message.payload if it's present there, or to the default value otherwise.
        """

        assert message.is_request("initialize") or message.is_response(
            "initialize")

        self.component = component

        payload = message.payload
        for name, validate in self.PROPERTIES.items():
            value = payload.get(name, ())
            if not callable(validate):
                validate = json.default(validate)

            try:
                value = validate(value)
            except Exception as exc:
                raise message.isnt_valid("{0!j} {1}", name, exc)

            assert value != (), fmt(
                "{0!j} must provide a default value for missing properties.",
                validate)
            self[name] = value

        log.debug("{0}", self)
コード例 #2
0
ファイル: ide.py プロジェクト: Adespinoza/dotfiles
    def launch_request(self, request):
        from ptvsd.adapter import launchers

        if self.session.id != 1 or len(servers.connections()):
            raise request.cant_handle('"attach" expected')

        sudo = request("sudo",
                       json.default("Sudo" in self.session.debug_options))
        if sudo:
            if sys.platform == "win32":
                raise request.cant_handle(
                    '"sudo":true is not supported on Windows.')
        else:
            if "Sudo" in self.session.debug_options:
                raise request.isnt_valid(
                    '"sudo":false and "debugOptions":["Sudo"] are mutually exclusive'
                )

        # Launcher doesn't use the command line at all, but we pass the arguments so
        # that they show up in the terminal if we're using "runInTerminal".
        if "program" in request:
            args = request("program",
                           json.array(unicode, vectorize=True, size=(1, )))
        elif "module" in request:
            args = ["-m"] + request(
                "module", json.array(unicode, vectorize=True, size=(1, )))
        elif "code" in request:
            args = ["-c"] + request(
                "code", json.array(unicode, vectorize=True, size=(1, )))
        else:
            args = []
        args += request("args", json.array(unicode))

        console = request(
            "console",
            json.enum(
                "internalConsole",
                "integratedTerminal",
                "externalTerminal",
                optional=True,
            ),
        )
        console_title = request("consoleTitle",
                                json.default("Python Debug Console"))

        launchers.spawn_debuggee(self.session, request, sudo, args, console,
                                 console_title)
コード例 #3
0
    def launch_request(self, request):
        sudo = request("sudo",
                       json.default("Sudo" in self.session.debug_options))
        if sudo:
            if platform.system() == "Windows":
                raise request.cant_handle(
                    '"sudo":true is not supported on Windows.')
        else:
            if "Sudo" in self.session.debug_options:
                raise request.isnt_valid(
                    '"sudo":false and "debugOptions":["Sudo"] are mutually exclusive'
                )

        # Launcher doesn't use the command line at all, but we pass the arguments so
        # that they show up in the terminal if we're using "runInTerminal".
        if "program" in request:
            args = request("program",
                           json.array(unicode, vectorize=True, size=(1, )))
        elif "module" in request:
            args = ["-m"] + request(
                "module", json.array(unicode, vectorize=True, size=(1, )))
        elif "code" in request:
            args = ["-c"] + request(
                "code", json.array(unicode, vectorize=True, size=(1, )))
        else:
            args = []
        args += request("args", json.array(unicode))

        console = request(
            "console",
            json.enum(
                "internalConsole",
                "integratedTerminal",
                "externalTerminal",
                optional=True,
            ),
        )
        console_title = request("consoleTitle",
                                json.default("Python Debug Console"))

        self.session.spawn_debuggee(request, sudo, args, console,
                                    console_title)

        if "RedirectOutput" in self.session.debug_options:
            # The launcher is doing output redirection, so we don't need the server.
            request.arguments["debugOptions"].remove("RedirectOutput")
コード例 #4
0
 def property_or_debug_option(prop_name, flag_name):
     assert prop_name[0].islower() and flag_name[0].isupper()
     value = request(prop_name,
                     json.default(flag_name in debug_options))
     if value is False and flag_name in debug_options:
         raise request.isnt_valid(
             '{0!r}:false and "debugOptions":[{1!r}] are mutually exclusive',
             prop_name,
             flag_name,
         )
     return value
コード例 #5
0
        def handle(self, request):
            assert request.is_request("launch", "attach")
            if self._initialize_request is None:
                raise request.isnt_valid("Session is not initialized yet")
            if self.launcher:
                raise request.isnt_valid("Session is already started")

            self.session.no_debug = request("noDebug", json.default(False))
            self.session.debug_options = set(
                request("debugOptions", json.array(unicode)))

            f(self, request)

            if self.server:
                self.server.initialize(self._initialize_request)
                self._initialize_request = None

                # pydevd doesn't send "initialized", and responds to the start request
                # immediately, without waiting for "configurationDone". If it changes
                # to conform to the DAP spec, we'll need to defer waiting for response.
                self.server.channel.delegate(request)

            if self.session.no_debug:
                request.respond({})
                self._propagate_deferred_events()
                return

            if {"WindowsClient", "Windows"} & self.session.debug_options:
                client_os_type = "WINDOWS"
            elif {"UnixClient", "UNIX"} & self.session.debug_options:
                client_os_type = "UNIX"
            else:
                client_os_type = "WINDOWS" if platform.system(
                ) == "Windows" else "UNIX"
            self.server.channel.request(
                "setDebuggerProperty",
                {
                    "skipSuspendOnBreakpointException": ("BaseException", ),
                    "skipPrintBreakpointException": ("NameError", ),
                    "multiThreadsSingleNotification": True,
                    "ideOS": client_os_type,
                },
            )

            # Let the IDE know that it can begin configuring the adapter.
            self.channel.send_event("initialized")

            self._start_request = request
            return messaging.NO_RESPONSE  # will respond on "configurationDone"
コード例 #6
0
ファイル: ide.py プロジェクト: Adespinoza/dotfiles
        def handle(self, request):
            assert request.is_request("launch", "attach")
            if self._initialize_request is None:
                raise request.isnt_valid("Session is not initialized yet")
            if self.launcher or self.server:
                raise request.isnt_valid("Session is already started")

            self.session.no_debug = request("noDebug", json.default(False))
            if self.session.no_debug:
                servers.dont_wait_for_first_connection()

            self.session.debug_options = debug_options = set(
                request("debugOptions", json.array(unicode)))

            f(self, request)

            if self.server:
                self.server.initialize(self._initialize_request)
                self._initialize_request = None

                arguments = request.arguments
                if self.launcher:
                    if "RedirectOutput" in debug_options:
                        # The launcher is doing output redirection, so we don't need the
                        # server to do it, as well.
                        arguments = dict(arguments)
                        arguments["debugOptions"] = list(debug_options -
                                                         {"RedirectOutput"})

                    if arguments.get("redirectOutput"):
                        arguments = dict(arguments)
                        del arguments["redirectOutput"]

                # pydevd doesn't send "initialized", and responds to the start request
                # immediately, without waiting for "configurationDone". If it changes
                # to conform to the DAP spec, we'll need to defer waiting for response.
                try:
                    self.server.channel.request(request.command, arguments)
                except messaging.MessageHandlingError as exc:
                    exc.propagate(request)

            if self.session.no_debug:
                self.start_request = request
                self.has_started = True
                request.respond({})
                self._propagate_deferred_events()
                return

            if {"WindowsClient", "Windows"} & debug_options:
                client_os_type = "WINDOWS"
            elif {"UnixClient", "UNIX"} & debug_options:
                client_os_type = "UNIX"
            else:
                client_os_type = "WINDOWS" if sys.platform == "win32" else "UNIX"
            self.server.channel.request(
                "setDebuggerProperty",
                {
                    "skipSuspendOnBreakpointException": ("BaseException", ),
                    "skipPrintBreakpointException": ("NameError", ),
                    "multiThreadsSingleNotification": True,
                    "ideOS": client_os_type,
                },
            )

            # Let the IDE know that it can begin configuring the adapter.
            self.channel.send_event("initialized")

            self.start_request = request
            return messaging.NO_RESPONSE  # will respond on "configurationDone"
コード例 #7
0
def launch_request(request):
    debug_options = set(request("debugOptions", json.array(unicode)))

    # Handling of properties that can also be specified as legacy "debugOptions" flags.
    # If property is explicitly set to false, but the flag is in "debugOptions", treat
    # it as an error. Returns None if the property wasn't explicitly set either way.
    def property_or_debug_option(prop_name, flag_name):
        assert prop_name[0].islower() and flag_name[0].isupper()

        value = request(prop_name, bool, optional=True)
        if value == ():
            value = None

        if flag_name in debug_options:
            if value is False:
                raise request.isnt_valid(
                    '{0!j}:false and "debugOptions":[{1!j}] are mutually exclusive',
                    prop_name,
                    flag_name,
                )
            value = True

        return value

    cmdline = []
    if property_or_debug_option("sudo", "Sudo"):
        if sys.platform == "win32":
            raise request.cant_handle('"sudo":true is not supported on Windows.')
        else:
            cmdline += ["sudo"]

    # "pythonPath" is a deprecated legacy spelling. If "python" is missing, then try
    # the alternative. But if both are missing, the error message should say "python".
    python_key = "python"
    if python_key in request:
        if "pythonPath" in request:
            raise request.isnt_valid(
                '"pythonPath" is not valid if "python" is specified'
            )
    elif "pythonPath" in request:
        python_key = "pythonPath"
    python = request(python_key, json.array(unicode, vectorize=True, size=(1,)))
    if not len(python):
        python = [compat.filename(sys.executable)]
    cmdline += python

    if not request("noDebug", json.default(False)):
        port = request("port", int)
        cmdline += [
            compat.filename(os.path.dirname(ptvsd.__file__)),
            "--client",
            "--host",
            "127.0.0.1",
            "--port",
            str(port),
        ]
        client_access_token = request("clientAccessToken", unicode, optional=True)
        if client_access_token != ():
            cmdline += ["--client-access-token", compat.filename(client_access_token)]
        ptvsd_args = request("ptvsdArgs", json.array(unicode))
        cmdline += ptvsd_args

    program = module = code = ()
    if "program" in request:
        program = request("program", json.array(unicode, vectorize=True, size=(1,)))
        cmdline += program
        process_name = program[0]
    if "module" in request:
        module = request("module", json.array(unicode, vectorize=True, size=(1,)))
        cmdline += ["-m"] + module
        process_name = module[0]
    if "code" in request:
        code = request("code", json.array(unicode, vectorize=True, size=(1,)))
        cmdline += ["-c"] + code
        process_name = python[0]

    num_targets = len([x for x in (program, module, code) if x != ()])
    if num_targets == 0:
        raise request.isnt_valid(
            'either "program", "module", or "code" must be specified'
        )
    elif num_targets != 1:
        raise request.isnt_valid(
            '"program", "module", and "code" are mutually exclusive'
        )

    cmdline += request("args", json.array(unicode))

    cwd = request("cwd", unicode, optional=True)
    if cwd == ():
        # If it's not specified, but we're launching a file rather than a module,
        # and the specified path has a directory in it, use that.
        cwd = None if program == () else (os.path.dirname(program[0]) 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)))

    if request("gevent", False):
        env["GEVENT_SUPPORT"] = "True"

    redirect_output = property_or_debug_option("redirectOutput", "RedirectOutput")
    if redirect_output is None:
        # If neither the property nor the option were specified explicitly, choose
        # the default depending on console type - "internalConsole" needs it to
        # provide any output at all, but it's unnecessary for the terminals.
        redirect_output = request("console", unicode) == "internalConsole"
    if redirect_output:
        # sys.stdout buffering must be disabled - otherwise we won't see the output
        # at all until the buffer fills up.
        env["PYTHONUNBUFFERED"] = "1"
        # Force UTF-8 output to minimize data loss due to re-encoding.
        env["PYTHONIOENCODING"] = "utf-8"

    if property_or_debug_option("waitOnNormalExit", "WaitOnNormalExit"):
        debuggee.wait_on_exit_predicates.append(lambda code: code == 0)
    if property_or_debug_option("waitOnAbnormalExit", "WaitOnAbnormalExit"):
        debuggee.wait_on_exit_predicates.append(lambda code: code != 0)

    if sys.version_info < (3,):
        # Popen() expects command line and environment to be bytes, not Unicode.
        # Assume that values are filenames - it's usually either that, or numbers -
        # but don't allow encoding to fail if we guessed wrong.
        encode = functools.partial(compat.filename_bytes, errors="replace")
        cmdline = [encode(s) for s in cmdline]
        env = {encode(k): encode(v) for k, v in env.items()}

    debuggee.spawn(process_name, cmdline, cwd, env, redirect_output)
    return {}
コード例 #8
0
 def disconnect_request(self, request):
     self.session.finalize(
         'IDE requested "disconnect"',
         request("terminateDebuggee", json.default(bool(self.launcher))),
     )
     return {}