mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Change the meaning of array for "code" debug configuration property to represent multiple lines of code. Switch tests to use "args".
164 lines
4.7 KiB
Python
164 lines
4.7 KiB
Python
# 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, division, print_function, unicode_literals
|
|
|
|
import py
|
|
|
|
from debugpy.common import fmt
|
|
from tests.patterns import some
|
|
|
|
|
|
class Target(object):
|
|
"""Describes Python code that gets run by a Runner.
|
|
"""
|
|
|
|
def __init__(self, filename, args=()):
|
|
if filename is not None and not isinstance(filename, py.path.local):
|
|
filename = py.path.local(filename)
|
|
|
|
self.filename = filename
|
|
self.args = args
|
|
|
|
if self.filename is None:
|
|
self.code = None
|
|
else:
|
|
with open(self.filename.strpath, "rb") as f:
|
|
self.code = f.read().decode("utf-8")
|
|
|
|
def configure(self, session):
|
|
"""Configures the session to execute this target.
|
|
|
|
This should only modify session.config, but gets access to the entire session
|
|
to retrieve information about it.
|
|
"""
|
|
|
|
raise NotImplementedError
|
|
|
|
def cli(self, env):
|
|
"""Provides the command line arguments, suitable for passing to python or
|
|
python -m debugpy, to execute this target.
|
|
|
|
Returns command line arguments as a list, e.g. ["-m", "module"].
|
|
|
|
If any environment variables are needed to properly interpret the command
|
|
line - e.g. PYTHONPATH - the implementation should send them in env.
|
|
"""
|
|
raise NotImplementedError
|
|
|
|
@property
|
|
def co_filename(self):
|
|
"""co_filename of code objects created at runtime from the source that this
|
|
Target describes, assuming no path mapping.
|
|
"""
|
|
assert (
|
|
self.filename is not None
|
|
), "co_filename requires Target created from filename"
|
|
return self.filename.strpath
|
|
|
|
@property
|
|
def source(self):
|
|
"""DAP "source" JSON for this Target."""
|
|
return some.dap.source(py.path.local(self.co_filename))
|
|
|
|
@property
|
|
def lines(self):
|
|
"""Same as self.filename.lines, if it is valid - e.g. for @pyfile objects.
|
|
"""
|
|
assert (
|
|
self.filename is not None
|
|
), "lines() requires Target created from filename"
|
|
return self.filename.lines
|
|
|
|
|
|
class Program(Target):
|
|
"""A Python script, executed directly: python foo.py
|
|
"""
|
|
|
|
pytest_id = "program"
|
|
|
|
def __repr__(self):
|
|
return fmt("program {0!j}", self.filename)
|
|
|
|
def configure(self, session):
|
|
session.config["program"] = self.filename
|
|
session.config["args"] = self.args
|
|
|
|
def cli(self, env):
|
|
return [self.filename.strpath] + list(self.args)
|
|
|
|
|
|
class Module(Target):
|
|
"""A Python module, executed by name: python -m foo.bar
|
|
|
|
If created from a filename, the module name is the name of the file, and the
|
|
Target will automatically add a PYTHONPATH entry.
|
|
"""
|
|
|
|
pytest_id = "module"
|
|
|
|
def __init__(self, filename=None, name=None, args=()):
|
|
assert (filename is None) ^ (name is None)
|
|
super(Module, self).__init__(filename, args)
|
|
self.name = name if name is not None else self.filename.purebasename
|
|
|
|
def __repr__(self):
|
|
return fmt("module {0}", self.name)
|
|
|
|
def configure(self, session):
|
|
session.config["module"] = self.name
|
|
session.config["args"] = self.args
|
|
|
|
def cli(self, env):
|
|
if self.filename is not None:
|
|
env.prepend_to("PYTHONPATH", self.filename.dirname)
|
|
return ["-m", self.name] + list(self.args)
|
|
|
|
|
|
class Code(Target):
|
|
"""A snippet of Python code: python -c "print('foo')"
|
|
|
|
If created from a filename, the code is the contents of the file.
|
|
"""
|
|
|
|
pytest_id = "code"
|
|
|
|
def __init__(self, filename=None, code=None, args=()):
|
|
assert (filename is None) ^ (code is None)
|
|
super(Code, self).__init__(filename, args)
|
|
if code is not None:
|
|
self.code = code
|
|
|
|
def __repr__(self):
|
|
lines = self.code.split("\n")
|
|
return fmt("code: {0!j}", lines)
|
|
|
|
def configure(self, session):
|
|
session.config["code"] = self.code
|
|
session.config["args"] = self.args
|
|
|
|
def cli(self, env):
|
|
return ["-c", self.code] + list(self.args)
|
|
|
|
@property
|
|
def co_filename(self):
|
|
return "<string>"
|
|
|
|
@property
|
|
def source(self):
|
|
"""DAP "source" JSON for this Target."""
|
|
return some.dap.source("<string>")
|
|
|
|
|
|
all_named = [Program, Module]
|
|
"""All targets that produce uniquely named code objects at runtime, and thus can
|
|
have breakpoints set in them.
|
|
"""
|
|
|
|
all_unnamed = [Code]
|
|
"""All targets that produce unnamed code objects at runtime, and thus cannot have
|
|
breakpoints set in them.
|
|
"""
|
|
|
|
all = all_named + all_unnamed
|