mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Allow using pydevd as a regular dependency.
This commit is contained in:
parent
6a7f7c0f2d
commit
c9edf762df
6 changed files with 131 additions and 77 deletions
56
setup.py
56
setup.py
|
|
@ -11,6 +11,10 @@ import subprocess
|
|||
import sys
|
||||
|
||||
|
||||
# pydevd is unbundled iff BUNDLE_DEBUGPY is set to 0
|
||||
BUNDLE_DEBUGPY = bool(os.getenv("BUNDLE_DEBUGPY", "1").strip().lower() != "0")
|
||||
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
import versioneer # noqa
|
||||
|
||||
|
|
@ -18,12 +22,14 @@ del sys.path[0]
|
|||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "src"))
|
||||
import debugpy
|
||||
import debugpy._vendored
|
||||
|
||||
if BUNDLE_DEBUGPY:
|
||||
import debugpy._vendored
|
||||
|
||||
del sys.path[0]
|
||||
|
||||
|
||||
PYDEVD_ROOT = debugpy._vendored.project_root("pydevd")
|
||||
if BUNDLE_DEBUGPY:
|
||||
PYDEVD_ROOT = debugpy._vendored.project_root("pydevd")
|
||||
DEBUGBY_ROOT = os.path.dirname(os.path.abspath(debugpy.__file__))
|
||||
|
||||
|
||||
|
|
@ -46,7 +52,7 @@ def get_buildplatform():
|
|||
# relevant setuptools versions.
|
||||
class ExtModules(list):
|
||||
def __bool__(self):
|
||||
return True
|
||||
return BUNDLE_DEBUGPY
|
||||
|
||||
|
||||
def override_build(cmds):
|
||||
|
|
@ -147,7 +153,28 @@ if __name__ == "__main__":
|
|||
|
||||
cmds = versioneer.get_cmdclass()
|
||||
override_build(cmds)
|
||||
override_build_py(cmds)
|
||||
if BUNDLE_DEBUGPY:
|
||||
override_build_py(cmds)
|
||||
|
||||
data = {"debugpy": ["ThirdPartyNotices.txt"]}
|
||||
packages = [
|
||||
"debugpy",
|
||||
"debugpy.adapter",
|
||||
"debugpy.common",
|
||||
"debugpy.launcher",
|
||||
"debugpy.server",
|
||||
]
|
||||
if BUNDLE_DEBUGPY:
|
||||
data.update(
|
||||
{
|
||||
"debugpy._vendored": [
|
||||
# pydevd extensions must be built before this list can
|
||||
# be computed properly, so it is populated in the
|
||||
# overridden build_py.finalize_options().
|
||||
]
|
||||
}
|
||||
)
|
||||
packages.append("debugpy._vendored")
|
||||
|
||||
setuptools.setup(
|
||||
name="debugpy",
|
||||
|
|
@ -177,23 +204,10 @@ if __name__ == "__main__":
|
|||
"License :: OSI Approved :: MIT License",
|
||||
],
|
||||
package_dir={"": "src"},
|
||||
packages=[
|
||||
"debugpy",
|
||||
"debugpy.adapter",
|
||||
"debugpy.common",
|
||||
"debugpy.launcher",
|
||||
"debugpy.server",
|
||||
"debugpy._vendored",
|
||||
],
|
||||
package_data={
|
||||
"debugpy": ["ThirdPartyNotices.txt"],
|
||||
"debugpy._vendored": [
|
||||
# pydevd extensions must be built before this list can be computed properly,
|
||||
# so it is populated in the overridden build_py.finalize_options().
|
||||
],
|
||||
},
|
||||
packages=packages,
|
||||
package_data=data,
|
||||
ext_modules=ExtModules(),
|
||||
has_ext_modules=lambda: True,
|
||||
has_ext_modules=lambda: BUNDLE_DEBUGPY,
|
||||
cmdclass=cmds,
|
||||
# allow the user to call "debugpy" instead of "python -m debugpy"
|
||||
entry_points={"console_scripts": ["debugpy = debugpy.server.cli:main"]},
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ __all__ = [ # noqa
|
|||
|
||||
import sys
|
||||
|
||||
try:
|
||||
import debugpy._vendored # noqa
|
||||
|
||||
is_pydevd_bundled = True
|
||||
except ImportError:
|
||||
is_pydevd_bundled = False
|
||||
|
||||
assert sys.version_info >= (3, 7), (
|
||||
"Python 3.6 and below is not supported by this version of debugpy; "
|
||||
"use debugpy 1.5.1 or earlier."
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
# for license information.
|
||||
|
||||
from importlib import import_module
|
||||
import os
|
||||
import warnings
|
||||
|
||||
from . import check_modules, prefix_matcher, preimport, vendored
|
||||
|
|
@ -17,23 +16,12 @@ if _unvendored:
|
|||
# raise ImportError(msg)
|
||||
warnings.warn(msg + ':\n {}'.format('\n '.join(_unvendored)))
|
||||
|
||||
# If debugpy logging is enabled, enable it for pydevd as well
|
||||
if "DEBUGPY_LOG_DIR" in os.environ:
|
||||
os.environ[str("PYDEVD_DEBUG")] = str("True")
|
||||
os.environ[str("PYDEVD_DEBUG_FILE")] = os.environ["DEBUGPY_LOG_DIR"] + str("/debugpy.pydevd.log")
|
||||
|
||||
# Disable pydevd frame-eval optimizations only if unset, to allow opt-in.
|
||||
if "PYDEVD_USE_FRAME_EVAL" not in os.environ:
|
||||
os.environ[str("PYDEVD_USE_FRAME_EVAL")] = str("NO")
|
||||
|
||||
# Constants must be set before importing any other pydevd module
|
||||
# # due to heavy use of "from" in them.
|
||||
# due to heavy use of "from" in them.
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", category=DeprecationWarning)
|
||||
with vendored('pydevd'):
|
||||
pydevd_constants = import_module('_pydevd_bundle.pydevd_constants')
|
||||
# We limit representation size in our representation provider when needed.
|
||||
pydevd_constants.MAXIMUM_VARIABLE_REPRESENTATION_SIZE = 2 ** 32
|
||||
|
||||
# Now make sure all the top-level modules and packages in pydevd are
|
||||
# loaded. Any pydevd modules that aren't loaded at this point, will
|
||||
|
|
@ -50,32 +38,3 @@ with warnings.catch_warnings():
|
|||
'pydevd_plugins',
|
||||
'pydevd',
|
||||
])
|
||||
|
||||
# When pydevd is imported it sets the breakpoint behavior, but it needs to be
|
||||
# overridden because by default pydevd will connect to the remote debugger using
|
||||
# its own custom protocol rather than DAP.
|
||||
import pydevd # noqa
|
||||
import debugpy # noqa
|
||||
|
||||
|
||||
def debugpy_breakpointhook():
|
||||
debugpy.breakpoint()
|
||||
|
||||
|
||||
pydevd.install_breakpointhook(debugpy_breakpointhook)
|
||||
|
||||
# Ensure that pydevd uses JSON protocol
|
||||
from _pydevd_bundle import pydevd_constants
|
||||
from _pydevd_bundle import pydevd_defaults
|
||||
pydevd_defaults.PydevdCustomization.DEFAULT_PROTOCOL = pydevd_constants.HTTP_JSON_PROTOCOL
|
||||
|
||||
# Enable some defaults related to debugpy such as sending a single notification when
|
||||
# threads pause and stopping on any exception.
|
||||
pydevd_defaults.PydevdCustomization.DEBUG_MODE = 'debugpy-dap'
|
||||
|
||||
# This is important when pydevd attaches automatically to a subprocess. In this case, we have to
|
||||
# make sure that debugpy is properly put back in the game for users to be able to use it.
|
||||
pydevd_defaults.PydevdCustomization.PREIMPORT = '%s;%s' % (
|
||||
os.path.dirname(os.path.dirname(debugpy.__file__)),
|
||||
'debugpy._vendored.force_pydevd'
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,69 @@
|
|||
# Licensed under the MIT License. See LICENSE in the project root
|
||||
# for license information.
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
from importlib import import_module
|
||||
import os
|
||||
|
||||
# "force_pydevd" must be imported first to ensure (via side effects)
|
||||
# that the debugpy-vendored copy of pydevd gets used.
|
||||
import debugpy._vendored.force_pydevd # noqa
|
||||
import debugpy
|
||||
|
||||
# If debugpy logging is enabled, enable it for pydevd as well
|
||||
if "DEBUGPY_LOG_DIR" in os.environ:
|
||||
os.environ[str("PYDEVD_DEBUG")] = str("True")
|
||||
os.environ[str("PYDEVD_DEBUG_FILE")] = os.environ["DEBUGPY_LOG_DIR"] + str(
|
||||
"/debugpy.pydevd.log"
|
||||
)
|
||||
|
||||
# Disable pydevd frame-eval optimizations only if unset, to allow opt-in.
|
||||
if "PYDEVD_USE_FRAME_EVAL" not in os.environ:
|
||||
os.environ[str("PYDEVD_USE_FRAME_EVAL")] = str("NO")
|
||||
|
||||
# Constants must be set before importing any other pydevd module
|
||||
# due to heavy use of "from" in them.
|
||||
if debugpy.is_pydevd_bundled:
|
||||
try:
|
||||
import debugpy._vendored.force_pydevd # noqa
|
||||
pydevd_constants = debugpy._vendored.force_pydevd.pydevd_constants
|
||||
except Exception as e:
|
||||
raise e
|
||||
else:
|
||||
pydevd_constants = import_module("_pydevd_bundle.pydevd_constants")
|
||||
|
||||
# We limit representation size in our representation provider when needed.
|
||||
pydevd_constants.MAXIMUM_VARIABLE_REPRESENTATION_SIZE = 2**32
|
||||
|
||||
# When pydevd is imported it sets the breakpoint behavior, but it needs to be
|
||||
# overridden because by default pydevd will connect to the remote debugger using
|
||||
# its own custom protocol rather than DAP.
|
||||
import pydevd # noqa
|
||||
import debugpy # noqa
|
||||
|
||||
|
||||
def debugpy_breakpointhook():
|
||||
debugpy.breakpoint()
|
||||
|
||||
|
||||
pydevd.install_breakpointhook(debugpy_breakpointhook)
|
||||
|
||||
# Ensure that pydevd uses JSON protocol
|
||||
from _pydevd_bundle import pydevd_constants
|
||||
from _pydevd_bundle import pydevd_defaults
|
||||
|
||||
pydevd_defaults.PydevdCustomization.DEFAULT_PROTOCOL = (
|
||||
pydevd_constants.HTTP_JSON_PROTOCOL
|
||||
)
|
||||
|
||||
# Enable some defaults related to debugpy such as sending a single notification when
|
||||
# threads pause and stopping on any exception.
|
||||
pydevd_defaults.PydevdCustomization.DEBUG_MODE = "debugpy-dap"
|
||||
|
||||
# This is important when pydevd attaches automatically to a subprocess. In this case, we have to
|
||||
# make sure that debugpy is properly put back in the game for users to be able to use it.
|
||||
if not(debugpy.is_pydevd_bundled):
|
||||
pydevd_defaults.PydevdCustomization.PREIMPORT = "%s;%s" % (
|
||||
os.path.dirname(os.path.dirname(debugpy.__file__)),
|
||||
"debugpy._vendored.force_pydevd",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import os
|
||||
|
||||
import debugpy
|
||||
|
||||
__file__ = os.path.abspath(__file__)
|
||||
_debugpy_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
|
|
@ -28,25 +29,29 @@ def attach(setup):
|
|||
def on_critical(msg):
|
||||
print(msg, file=sys.stderr)
|
||||
|
||||
pydevd_attach_to_process_path = os.path.join(
|
||||
_debugpy_dir,
|
||||
"debugpy",
|
||||
"_vendored",
|
||||
"pydevd",
|
||||
"pydevd_attach_to_process",
|
||||
)
|
||||
assert os.path.exists(pydevd_attach_to_process_path)
|
||||
sys.path.insert(0, pydevd_attach_to_process_path)
|
||||
if not debugpy.is_pydevd_bundled:
|
||||
from pydevd_attach_to_process import attach_script
|
||||
else:
|
||||
pydevd_attach_to_process_path = os.path.join(
|
||||
_debugpy_dir,
|
||||
"debugpy",
|
||||
"_vendored",
|
||||
"pydevd",
|
||||
"pydevd_attach_to_process",
|
||||
)
|
||||
assert os.path.exists(pydevd_attach_to_process_path)
|
||||
sys.path.insert(0, pydevd_attach_to_process_path)
|
||||
|
||||
# NOTE: that it's not a part of the pydevd PYTHONPATH
|
||||
import attach_script
|
||||
# NOTE: that it's not a part of the pydevd PYTHONPATH
|
||||
import attach_script
|
||||
|
||||
attach_script.fix_main_thread_id(
|
||||
on_warn=on_warn, on_exception=on_exception, on_critical=on_critical
|
||||
)
|
||||
|
||||
# NOTE: At this point it should be safe to remove this.
|
||||
sys.path.remove(pydevd_attach_to_process_path)
|
||||
if debugpy.is_pydevd_bundled:
|
||||
# NOTE: At this point it should be safe to remove this.
|
||||
sys.path.remove(pydevd_attach_to_process_path)
|
||||
except:
|
||||
import traceback
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,12 @@
|
|||
# for license information.
|
||||
|
||||
|
||||
import pytest
|
||||
|
||||
import debugpy
|
||||
|
||||
|
||||
@pytest.mark.skipif(not debugpy.is_pydevd_bundled, reason="pydevd is not bundled")
|
||||
def test_vendoring(pyfile):
|
||||
@pyfile
|
||||
def import_debugpy():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue