[PATCH] gnu: python-debugpy: Update to 1.8.1.

  • Open
  • quality assurance status badge
Details
2 participants
  • Christopher Baines
  • Nicolas Graves
Owner
unassigned
Submitted by
Nicolas Graves
Severity
normal
Blocked by
N
N
Nicolas Graves wrote on 17 May 07:41 +0200
(address . guix-patches@gnu.org)(address . ngraves@ngraves.fr)
20240517054144.15296-1-ngraves@ngraves.fr
* gnu/packages/python-xyz.scm (python-debugpy): Update to 1.8.1.
* gnu/packages/patches/python-debugpy-unbundle-pydevd.patch: Update it.

Change-Id: Ice5f869fc36b29cb9d0ad998684b0526c16ab79d
---
.../python-debugpy-unbundle-pydevd.patch | 309 +++++++++++-------
gnu/packages/python-xyz.scm | 6 +-
2 files changed, 200 insertions(+), 115 deletions(-)

Toggle diff (385 lines)
diff --git a/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch b/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
index 7a6ad544896..899dea70577 100644
--- a/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
+++ b/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
@@ -1,93 +1,77 @@
Allow using pydevd as a regular dependency.
-Submitted upstream at: https://github.com/microsoft/debugpy/pull/902
+Submitted upstream at: https://github.com/microsoft/debugpy/pull/1586
diff --git a/setup.py b/setup.py
-index 5fc40070..3a530a29 100644
+index 1bfba237..afffc6b2 100644
--- a/setup.py
+++ b/setup.py
-@@ -11,6 +11,9 @@ import subprocess
+@@ -11,6 +11,8 @@ import subprocess
import sys
-+DEBUGPY_BUNDLING_DISABLED = bool(os.getenv('DEBUGPY_BUNDLING_DISABLED'))
-+
++BUNDLE_DEBUGPY = not (os.getenv("BUNDLE_DEBUGPY").strip().lower() == "0")
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import versioneer # noqa
-@@ -18,12 +21,15 @@ del sys.path[0]
+@@ -18,12 +20,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 not DEBUGPY_BUNDLING_DISABLED:
++if BUNDLE_DEBUGPY:
+ import debugpy._vendored
del sys.path[0]
-
+-
-PYDEVD_ROOT = debugpy._vendored.project_root("pydevd")
-+PYDEVD_ROOT = (None if DEBUGPY_BUNDLING_DISABLED else
-+ 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__))
-@@ -67,7 +73,7 @@ def iter_vendored_files():
+@@ -46,7 +50,7 @@ def get_buildplatform():
# relevant setuptools versions.
class ExtModules(list):
def __bool__(self):
- return True
-+ return not DEBUGPY_BUNDLING_DISABLED
++ return BUNDLE_DEBUGPY
def override_build(cmds):
-@@ -133,9 +139,24 @@ with open("DESCRIPTION.md", "r") as fh:
+@@ -147,7 +151,28 @@ if __name__ == "__main__":
-
- if __name__ == "__main__":
-- if not os.getenv("SKIP_CYTHON_BUILD"):
-+ if not (os.getenv("SKIP_CYTHON_BUILD") or DEBUGPY_BUNDLING_DISABLED):
- cython_build()
-
-+ # Etch bundling status in the source.
-+ if debugpy.__bundling_disabled__ != DEBUGPY_BUNDLING_DISABLED:
-+
-+ with open(os.path.join(DEBUGBY_ROOT, '__init__.py'), 'r') as f:
-+ lines = f.readlines()
-+ with open(os.path.join(DEBUGBY_ROOT, '__init__.py'), 'w') as f:
-+ edited = []
-+ for line in lines:
-+ if line.startswith('__bundling_disabled__'):
-+ edited.append(
-+ f'__bundling_disabled__ = {DEBUGPY_BUNDLING_DISABLED}\n')
-+ else:
-+ edited.append(line)
-+ f.writelines(edited)
-+
- extras = {}
- platforms = get_buildplatform()
- if platforms is not None:
-@@ -145,6 +166,18 @@ if __name__ == "__main__":
+ cmds = versioneer.get_cmdclass()
override_build(cmds)
- override_build_py(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 not DEBUGPY_BUNDLING_DISABLED:
-+ data.update({"debugpy._vendored": list(iter_vendored_files())})
++ "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",
- version=versioneer.get_version(),
-@@ -173,20 +206,10 @@ if __name__ == "__main__":
+@@ -177,23 +202,10 @@ if __name__ == "__main__":
"License :: OSI Approved :: MIT License",
],
package_dir={"": "src"},
@@ -101,37 +85,117 @@ index 5fc40070..3a530a29 100644
- ],
- package_data={
- "debugpy": ["ThirdPartyNotices.txt"],
-- "debugpy._vendored": list(iter_vendored_files()),
+- "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: not DEBUGPY_BUNDLING_DISABLED,
++ has_ext_modules=lambda: BUNDLE_DEBUGPY,
cmdclass=cmds,
**extras
)
diff --git a/src/debugpy/__init__.py b/src/debugpy/__init__.py
-index baa5a7c5..7b7a29aa 100644
+index 975bec79..512219d7 100644
--- a/src/debugpy/__init__.py
+++ b/src/debugpy/__init__.py
-@@ -206,6 +206,8 @@ def trace_this_thread(should_trace):
+@@ -24,6 +24,13 @@ __all__ = [ # noqa
- __version__ = _version.get_versions()["version"]
+ import sys
-+__bundling_disabled__ = False
++try:
++ import debugpy._vendored # noqa
+
- # Force absolute path on Python 2.
- __file__ = os.path.abspath(__file__)
++ 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."
+diff --git a/src/debugpy/_vendored/force_pydevd.py b/src/debugpy/_vendored/force_pydevd.py
+index cfd89275..99622f8c 100644
+--- a/src/debugpy/_vendored/force_pydevd.py
++++ b/src/debugpy/_vendored/force_pydevd.py
+@@ -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'
+-)
diff --git a/src/debugpy/server/__init__.py b/src/debugpy/server/__init__.py
-index e6a1ad66..5f29a87a 100644
+index 42d5367f..a27c6bf4 100644
--- a/src/debugpy/server/__init__.py
+++ b/src/debugpy/server/__init__.py
-@@ -4,6 +4,50 @@
-
- from __future__ import absolute_import, division, print_function, unicode_literals
+@@ -2,6 +2,70 @@
+ # 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
+
@@ -139,52 +203,70 @@ index e6a1ad66..5f29a87a 100644
# that the debugpy-vendored copy of pydevd gets used.
-import debugpy._vendored.force_pydevd # noqa
+import debugpy
-+if debugpy.__bundling_disabled__:
-+ # Do what force_pydevd.py does, but using the system-provided
-+ # pydevd.
+
-+ # XXX: This is copied here so that the whole '_vendored' directory
-+ # can be deleted when DEBUGPY_BUNDLING_DISABLED is set.
++# 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"
++ )
+
-+ # 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")
+
-+ # Work around https://github.com/microsoft/debugpy/issues/346.
-+ # 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")
++BUNDLE_DEBUGPY = bool(os.getenv("BUNDLE_DEBUGPY"))
+
-+ # Constants must be set before importing any other pydevd module
-+ # due to heavy use of "from" in them.
-+ pydevd_constants = import_module('_pydevd_bundle.pydevd_constants')
-+ # The default pydevd value is 1000.
-+ 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
++# Constants must be set before importing any other pydevd module
++# due to heavy use of "from" in them.
++if BUNDLE_DEBUGPY:
++ try:
++ import debugpy._vendored.force_pydevd # noqa
++ except Exception as e:
++ raise e
+else:
-+ import debugpy._vendored.force_pydevd # noqa
++ 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 BUNDLE_DEBUGPY:
++ pydevd_defaults.PydevdCustomization.PREIMPORT = "%s;%s" % (
++ os.path.dirname(os.path.dirname(debugpy.__file__)),
++ "debugpy._vendored.force_pydevd",
++ )
diff --git a/src/debugpy/server/attach_pid_injected.py b/src/debugpy/server/attach_pid_injected.py
-index e6345996..87cfdd53 100644
+index a8df6e1e..06e49600 100644
--- a/src/debugpy/server/attach_pid_injected.py
+++ b/src/debugpy/server/attach_pid_injected.py
-@@ -8,6 +8,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
+@@ -6,6 +6,7 @@
import os
@@ -192,7 +274,7 @@ index e6345996..87cfdd53 100644
__file__ = os.path.abspath(__file__)
_debugpy_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
-@@ -30,25 +31,29 @@ def attach(setup):
+@@ -28,25 +29,29 @@ def attach(setup):
def on_critical(msg):
print(msg, file=sys.stderr)
@@ -205,10 +287,7 @@ index e6345996..87cfdd53 100644
- )
- 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
-+ if debugpy.__bundling_disabled__:
++ if not debugpy.is_pydevd_bundled:
+ from pydevd_attach_to_process import attach_script
+ else:
+ pydevd_attach_to_process_path = os.path.join(
@@ -220,7 +299,9 @@ index e6345996..87cfdd53 100644
+ )
+ 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
@@ -230,25 +311,29 @@ index e6345996..87cfdd53 100644
- # NOTE: At this point it should be safe to remove this.
- sys.path.remove(pydevd_attach_to_process_path)
-+ if not debugpy.__bundling_disabled__:
++ 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
diff --git a/tests/tests/test_vendoring.py b/tests/tests/test_vendoring.py
-index dd6c4269..28c03702 100644
+index 9cf44220..3188eb9e 100644
--- a/tests/tests/test_vendoring.py
+++ b/tests/tests/test_vendoring.py
-@@ -1,3 +1,8 @@
+@@ -3,6 +3,12 @@
+ # for license information.
+
+
+import pytest
+
+import debugpy
+
-+@pytest.mark.skipif(debugpy.__bundling_disabled__, reason='Bundling disabled')
++
++@pytest.mark.skipif(not debugpy.is_pydevd_bundled, reason="pydevd is not bundled")
def test_vendoring(pyfile):
@pyfile
def import_debugpy():
--
-2.34.0
+2.41.0
Toggle diff (33 lines)
diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index cf953674b09..0be2f8dc08a 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -16807,7 +16807,7 @@ (define-public python-pydevd
(define-public python-debugpy
(package
(name "python-debugpy")
- (version "1.6.0")
+ (version "1.8.1")
(source
(origin
(method git-fetch)
@@ -16822,7 +16822,7 @@ (define-public python-debugpy
(patches (search-patches "python-debugpy-unbundle-pydevd.patch"))
(sha256
(base32
- "1dpfzs3p51648i7f3fz8dw5d0vrj39iwn1jhn0226idc02ybyqih"))))
+ "1nnm62c1x06vyq52h0dmyvc78gf7c20474x2mi07x3ab9kf1q3hh"))))
(build-system pyproject-build-system)
(arguments
(list
@@ -16854,7 +16854,7 @@ (define-public python-debugpy
(lambda _
;; This adjusts the behavior of debugpy to load pydevd from
;; Python site packages.
- (setenv "DEBUGPY_BUNDLING_DISABLED" "1"))))))
+ (setenv "BUNDLE_DEBUGPY" "0"))))))
(native-inputs
;; See: https://raw.githubusercontent.com/microsoft/debugpy/
;; main/tests/requirements.txt.
--
2.41.0
N
N
Nicolas Graves wrote on 18 May 12:00 +0200
[PATCH v2 1/2] gnu: python-debugpy: Move to pyproject-build-system.
(address . 70995@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20240518100040.13601-1-ngraves@ngraves.fr
* gnu/packages/python-xyz.scm (python-debugpy):
[build-system]: Move to pyproject-build-system.
[arguments]<#:test-flags>: Superset 'check phase replacement.

Change-Id: Ie112f4b25df8f7996124b465b81c84403294f2d5
---
gnu/packages/python-xyz.scm | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)

Toggle diff (51 lines)
diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index da01c71ce03..cf953674b09 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -16823,10 +16823,20 @@ (define-public python-debugpy
(sha256
(base32
"1dpfzs3p51648i7f3fz8dw5d0vrj39iwn1jhn0226idc02ybyqih"))))
- (build-system python-build-system)
+ (build-system pyproject-build-system)
(arguments
(list
#:tests? #f ; Fail on systems with YAMA LSM’s ptrace scope > 0.
+ #:test-flags
+ '(list "-n" (number->string (parallel-job-count))
+ "-k" (string-append
+ ;; These tests cannot be run in parallel because their
+ ;; test data would not be copied by xdist and lead to
+ ;; import errors. (see:
+ ;; https://github.com/microsoft/debugpy/issues/342 and
+ ;; https://github.com/microsoft/debugpy/issues/880).
+ "not test_custom_python_args "
+ "and not test_autokill "))
#:phases
#~(modify-phases %standard-phases
(add-after 'unpack 'patch-sh-in-tests
@@ -16844,21 +16854,7 @@ (define-public python-debugpy
(lambda _
;; This adjusts the behavior of debugpy to load pydevd from
;; Python site packages.
- (setenv "DEBUGPY_BUNDLING_DISABLED" "1")))
- (replace 'check
- (lambda* (#:key tests? #:allow-other-keys)
- (when tests?
- (invoke "pytest" "-vv"
- "-n" (number->string (parallel-job-count))
- "-k"
- (string-append
- ;; These tests cannot be run in parallel because their
- ;; test data would not be copied by xdist and lead to
- ;; import errors. (see:
- ;; https://github.com/microsoft/debugpy/issues/342 and
- ;; https://github.com/microsoft/debugpy/issues/880).
- "not test_custom_python_args "
- "and not test_autokill "))))))))
+ (setenv "DEBUGPY_BUNDLING_DISABLED" "1"))))))
(native-inputs
;; See: https://raw.githubusercontent.com/microsoft/debugpy/
;; main/tests/requirements.txt.
--
2.41.0
N
N
Nicolas Graves wrote on 18 May 12:00 +0200
[PATCH v2 2/2] gnu: python-debugpy: Update to 1.8.1.
(address . 70995@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20240518100040.13601-2-ngraves@ngraves.fr
* gnu/packages/python-xyz.scm (python-debugpy): Update to 1.8.1.
* gnu/packages/patches/python-debugpy-unbundle-pydevd.patch: Update it.

Change-Id: Ice5f869fc36b29cb9d0ad998684b0526c16ab79d
---
.../python-debugpy-unbundle-pydevd.patch | 309 +++++++++++-------
gnu/packages/python-xyz.scm | 6 +-
2 files changed, 200 insertions(+), 115 deletions(-)

Toggle diff (385 lines)
diff --git a/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch b/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
index 7a6ad544896..899dea70577 100644
--- a/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
+++ b/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
@@ -1,93 +1,77 @@
Allow using pydevd as a regular dependency.
-Submitted upstream at: https://github.com/microsoft/debugpy/pull/902
+Submitted upstream at: https://github.com/microsoft/debugpy/pull/1586
diff --git a/setup.py b/setup.py
-index 5fc40070..3a530a29 100644
+index 1bfba237..afffc6b2 100644
--- a/setup.py
+++ b/setup.py
-@@ -11,6 +11,9 @@ import subprocess
+@@ -11,6 +11,8 @@ import subprocess
import sys
-+DEBUGPY_BUNDLING_DISABLED = bool(os.getenv('DEBUGPY_BUNDLING_DISABLED'))
-+
++BUNDLE_DEBUGPY = not (os.getenv("BUNDLE_DEBUGPY").strip().lower() == "0")
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import versioneer # noqa
-@@ -18,12 +21,15 @@ del sys.path[0]
+@@ -18,12 +20,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 not DEBUGPY_BUNDLING_DISABLED:
++if BUNDLE_DEBUGPY:
+ import debugpy._vendored
del sys.path[0]
-
+-
-PYDEVD_ROOT = debugpy._vendored.project_root("pydevd")
-+PYDEVD_ROOT = (None if DEBUGPY_BUNDLING_DISABLED else
-+ 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__))
-@@ -67,7 +73,7 @@ def iter_vendored_files():
+@@ -46,7 +50,7 @@ def get_buildplatform():
# relevant setuptools versions.
class ExtModules(list):
def __bool__(self):
- return True
-+ return not DEBUGPY_BUNDLING_DISABLED
++ return BUNDLE_DEBUGPY
def override_build(cmds):
-@@ -133,9 +139,24 @@ with open("DESCRIPTION.md", "r") as fh:
+@@ -147,7 +151,28 @@ if __name__ == "__main__":
-
- if __name__ == "__main__":
-- if not os.getenv("SKIP_CYTHON_BUILD"):
-+ if not (os.getenv("SKIP_CYTHON_BUILD") or DEBUGPY_BUNDLING_DISABLED):
- cython_build()
-
-+ # Etch bundling status in the source.
-+ if debugpy.__bundling_disabled__ != DEBUGPY_BUNDLING_DISABLED:
-+
-+ with open(os.path.join(DEBUGBY_ROOT, '__init__.py'), 'r') as f:
-+ lines = f.readlines()
-+ with open(os.path.join(DEBUGBY_ROOT, '__init__.py'), 'w') as f:
-+ edited = []
-+ for line in lines:
-+ if line.startswith('__bundling_disabled__'):
-+ edited.append(
-+ f'__bundling_disabled__ = {DEBUGPY_BUNDLING_DISABLED}\n')
-+ else:
-+ edited.append(line)
-+ f.writelines(edited)
-+
- extras = {}
- platforms = get_buildplatform()
- if platforms is not None:
-@@ -145,6 +166,18 @@ if __name__ == "__main__":
+ cmds = versioneer.get_cmdclass()
override_build(cmds)
- override_build_py(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 not DEBUGPY_BUNDLING_DISABLED:
-+ data.update({"debugpy._vendored": list(iter_vendored_files())})
++ "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",
- version=versioneer.get_version(),
-@@ -173,20 +206,10 @@ if __name__ == "__main__":
+@@ -177,23 +202,10 @@ if __name__ == "__main__":
"License :: OSI Approved :: MIT License",
],
package_dir={"": "src"},
@@ -101,37 +85,117 @@ index 5fc40070..3a530a29 100644
- ],
- package_data={
- "debugpy": ["ThirdPartyNotices.txt"],
-- "debugpy._vendored": list(iter_vendored_files()),
+- "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: not DEBUGPY_BUNDLING_DISABLED,
++ has_ext_modules=lambda: BUNDLE_DEBUGPY,
cmdclass=cmds,
**extras
)
diff --git a/src/debugpy/__init__.py b/src/debugpy/__init__.py
-index baa5a7c5..7b7a29aa 100644
+index 975bec79..512219d7 100644
--- a/src/debugpy/__init__.py
+++ b/src/debugpy/__init__.py
-@@ -206,6 +206,8 @@ def trace_this_thread(should_trace):
+@@ -24,6 +24,13 @@ __all__ = [ # noqa
- __version__ = _version.get_versions()["version"]
+ import sys
-+__bundling_disabled__ = False
++try:
++ import debugpy._vendored # noqa
+
- # Force absolute path on Python 2.
- __file__ = os.path.abspath(__file__)
++ 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."
+diff --git a/src/debugpy/_vendored/force_pydevd.py b/src/debugpy/_vendored/force_pydevd.py
+index cfd89275..99622f8c 100644
+--- a/src/debugpy/_vendored/force_pydevd.py
++++ b/src/debugpy/_vendored/force_pydevd.py
+@@ -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'
+-)
diff --git a/src/debugpy/server/__init__.py b/src/debugpy/server/__init__.py
-index e6a1ad66..5f29a87a 100644
+index 42d5367f..a27c6bf4 100644
--- a/src/debugpy/server/__init__.py
+++ b/src/debugpy/server/__init__.py
-@@ -4,6 +4,50 @@
-
- from __future__ import absolute_import, division, print_function, unicode_literals
+@@ -2,6 +2,70 @@
+ # 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
+
@@ -139,52 +203,70 @@ index e6a1ad66..5f29a87a 100644
# that the debugpy-vendored copy of pydevd gets used.
-import debugpy._vendored.force_pydevd # noqa
+import debugpy
-+if debugpy.__bundling_disabled__:
-+ # Do what force_pydevd.py does, but using the system-provided
-+ # pydevd.
+
-+ # XXX: This is copied here so that the whole '_vendored' directory
-+ # can be deleted when DEBUGPY_BUNDLING_DISABLED is set.
++# 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"
++ )
+
-+ # 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")
+
-+ # Work around https://github.com/microsoft/debugpy/issues/346.
-+ # 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")
++BUNDLE_DEBUGPY = bool(os.getenv("BUNDLE_DEBUGPY"))
+
-+ # Constants must be set before importing any other pydevd module
-+ # due to heavy use of "from" in them.
-+ pydevd_constants = import_module('_pydevd_bundle.pydevd_constants')
-+ # The default pydevd value is 1000.
-+ 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
++# Constants must be set before importing any other pydevd module
++# due to heavy use of "from" in them.
++if BUNDLE_DEBUGPY:
++ try:
++ import debugpy._vendored.force_pydevd # noqa
++ except Exception as e:
++ raise e
+else:
-+ import debugpy._vendored.force_pydevd # noqa
++ 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 BUNDLE_DEBUGPY:
++ pydevd_defaults.PydevdCustomization.PREIMPORT = "%s;%s" % (
++ os.path.dirname(os.path.dirname(debugpy.__file__)),
++ "debugpy._vendored.force_pydevd",
++ )
diff --git a/src/debugpy/server/attach_pid_injected.py b/src/debugpy/server/attach_pid_injected.py
-index e6345996..87cfdd53 100644
+index a8df6e1e..06e49600 100644
--- a/src/debugpy/server/attach_pid_injected.py
+++ b/src/debugpy/server/attach_pid_injected.py
-@@ -8,6 +8,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
+@@ -6,6 +6,7 @@
import os
@@ -192,7 +274,7 @@ index e6345996..87cfdd53 100644
__file__ = os.path.abspath(__file__)
_debugpy_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
-@@ -30,25 +31,29 @@ def attach(setup):
+@@ -28,25 +29,29 @@ def attach(setup):
def on_critical(msg):
print(msg, file=sys.stderr)
@@ -205,10 +287,7 @@ index e6345996..87cfdd53 100644
- )
- 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
-+ if debugpy.__bundling_disabled__:
++ if not debugpy.is_pydevd_bundled:
+ from pydevd_attach_to_process import attach_script
+ else:
+ pydevd_attach_to_process_path = os.path.join(
@@ -220,7 +299,9 @@ index e6345996..87cfdd53 100644
+ )
+ 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
@@ -230,25 +311,29 @@ index e6345996..87cfdd53 100644
- # NOTE: At this point it should be safe to remove this.
- sys.path.remove(pydevd_attach_to_process_path)
-+ if not debugpy.__bundling_disabled__:
++ 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
diff --git a/tests/tests/test_vendoring.py b/tests/tests/test_vendoring.py
-index dd6c4269..28c03702 100644
+index 9cf44220..3188eb9e 100644
--- a/tests/tests/test_vendoring.py
+++ b/tests/tests/test_vendoring.py
-@@ -1,3 +1,8 @@
+@@ -3,6 +3,12 @@
+ # for license information.
+
+
+import pytest
+
+import debugpy
+
-+@pytest.mark.skipif(debugpy.__bundling_disabled__, reason='Bundling disabled')
++
++@pytest.mark.skipif(not debugpy.is_pydevd_bundled, reason="pydevd is not bundled")
def test_vendoring(pyfile):
@pyfile
def import_debugpy():
--
-2.34.0
+2.41.0
Toggle diff (33 lines)
diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index cf953674b09..0be2f8dc08a 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -16807,7 +16807,7 @@ (define-public python-pydevd
(define-public python-debugpy
(package
(name "python-debugpy")
- (version "1.6.0")
+ (version "1.8.1")
(source
(origin
(method git-fetch)
@@ -16822,7 +16822,7 @@ (define-public python-debugpy
(patches (search-patches "python-debugpy-unbundle-pydevd.patch"))
(sha256
(base32
- "1dpfzs3p51648i7f3fz8dw5d0vrj39iwn1jhn0226idc02ybyqih"))))
+ "1nnm62c1x06vyq52h0dmyvc78gf7c20474x2mi07x3ab9kf1q3hh"))))
(build-system pyproject-build-system)
(arguments
(list
@@ -16854,7 +16854,7 @@ (define-public python-debugpy
(lambda _
;; This adjusts the behavior of debugpy to load pydevd from
;; Python site packages.
- (setenv "DEBUGPY_BUNDLING_DISABLED" "1"))))))
+ (setenv "BUNDLE_DEBUGPY" "0"))))))
(native-inputs
;; See: https://raw.githubusercontent.com/microsoft/debugpy/
;; main/tests/requirements.txt.
--
2.41.0
N
N
Nicolas Graves wrote on 18 May 15:08 +0200
control message for bug #70995
(address . control@debbugs.gnu.org)
87wmnrclnl.fsf@ngraves.fr
block 70995 by 71037
quit


--
Best regards,
Nicolas Graves
N
N
Nicolas Graves wrote on 28 May 10:46 +0200
[PATCH v3 0/2] Update python-debugpy.
(address . 70995@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20240528084745.3953-1-ngraves@ngraves.fr
This proposed update is downgraded to the previous version, because of

Nicolas Graves (2):
gnu: python-debugpy: Move to pyproject-build-system.
gnu: python-debugpy: Update to 1.8.0.

.../python-debugpy-unbundle-pydevd.patch | 318 +++++++++++-------
gnu/packages/python-xyz.scm | 32 +-
2 files changed, 212 insertions(+), 138 deletions(-)

--
2.41.0
N
N
Nicolas Graves wrote on 28 May 10:46 +0200
[PATCH v3 1/2] gnu: python-debugpy: Move to pyproject-build-system.
(address . 70995@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20240528084745.3953-2-ngraves@ngraves.fr
* gnu/packages/python-xyz.scm (python-debugpy):
[build-system]: Move to pyproject-build-system.
[arguments]<#:test-flags>: Superset 'check phase replacement.

Change-Id: Ie112f4b25df8f7996124b465b81c84403294f2d5
---
gnu/packages/python-xyz.scm | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)

Toggle diff (51 lines)
diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index e9c89a15dbb..1a3c825faab 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -16817,10 +16817,20 @@ (define-public python-debugpy
(sha256
(base32
"1dpfzs3p51648i7f3fz8dw5d0vrj39iwn1jhn0226idc02ybyqih"))))
- (build-system python-build-system)
+ (build-system pyproject-build-system)
(arguments
(list
#:tests? #f ; Fail on systems with YAMA LSM’s ptrace scope > 0.
+ #:test-flags
+ '(list "-n" (number->string (parallel-job-count))
+ "-k" (string-append
+ ;; These tests cannot be run in parallel because their
+ ;; test data would not be copied by xdist and lead to
+ ;; import errors. (see:
+ ;; https://github.com/microsoft/debugpy/issues/342 and
+ ;; https://github.com/microsoft/debugpy/issues/880).
+ "not test_custom_python_args "
+ "and not test_autokill "))
#:phases
#~(modify-phases %standard-phases
(add-after 'unpack 'patch-sh-in-tests
@@ -16838,21 +16848,7 @@ (define-public python-debugpy
(lambda _
;; This adjusts the behavior of debugpy to load pydevd from
;; Python site packages.
- (setenv "DEBUGPY_BUNDLING_DISABLED" "1")))
- (replace 'check
- (lambda* (#:key tests? #:allow-other-keys)
- (when tests?
- (invoke "pytest" "-vv"
- "-n" (number->string (parallel-job-count))
- "-k"
- (string-append
- ;; These tests cannot be run in parallel because their
- ;; test data would not be copied by xdist and lead to
- ;; import errors. (see:
- ;; https://github.com/microsoft/debugpy/issues/342 and
- ;; https://github.com/microsoft/debugpy/issues/880).
- "not test_custom_python_args "
- "and not test_autokill "))))))))
+ (setenv "DEBUGPY_BUNDLING_DISABLED" "1"))))))
(native-inputs
;; See: https://raw.githubusercontent.com/microsoft/debugpy/
;; main/tests/requirements.txt.
--
2.41.0
N
N
Nicolas Graves wrote on 28 May 10:46 +0200
[PATCH v3 2/2] gnu: python-debugpy: Update to 1.8.0.
(address . 70995@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20240528084745.3953-3-ngraves@ngraves.fr
* gnu/packages/python-xyz.scm (python-debugpy): Update to 1.8.0.
* gnu/packages/patches/python-debugpy-unbundle-pydevd.patch: Update it.

Change-Id: Ice5f869fc36b29cb9d0ad998684b0526c16ab79d
---
.../python-debugpy-unbundle-pydevd.patch | 318 +++++++++++-------
gnu/packages/python-xyz.scm | 6 +-
2 files changed, 201 insertions(+), 123 deletions(-)

Toggle diff (392 lines)
diff --git a/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch b/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
index 7a6ad544896..dabdbd2b526 100644
--- a/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
+++ b/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
@@ -1,137 +1,194 @@
Allow using pydevd as a regular dependency.
-Submitted upstream at: https://github.com/microsoft/debugpy/pull/902
+Submitted upstream at: https://github.com/microsoft/debugpy/pull/1586
diff --git a/setup.py b/setup.py
-index 5fc40070..3a530a29 100644
+index 0bb4f00c..59fab822 100644
--- a/setup.py
+++ b/setup.py
-@@ -11,6 +11,9 @@ import subprocess
+@@ -11,6 +11,8 @@ import subprocess
import sys
-+DEBUGPY_BUNDLING_DISABLED = bool(os.getenv('DEBUGPY_BUNDLING_DISABLED'))
-+
++BUNDLE_DEBUGPY = not (os.getenv("BUNDLE_DEBUGPY").strip().lower() == "0")
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import versioneer # noqa
-@@ -18,12 +21,15 @@ del sys.path[0]
+@@ -18,12 +20,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 not DEBUGPY_BUNDLING_DISABLED:
++if BUNDLE_DEBUGPY:
+ import debugpy._vendored
del sys.path[0]
-
+-
-PYDEVD_ROOT = debugpy._vendored.project_root("pydevd")
-+PYDEVD_ROOT = (None if DEBUGPY_BUNDLING_DISABLED else
-+ 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__))
-@@ -67,7 +73,7 @@ def iter_vendored_files():
+@@ -46,7 +50,7 @@ def get_buildplatform():
# relevant setuptools versions.
class ExtModules(list):
def __bool__(self):
- return True
-+ return not DEBUGPY_BUNDLING_DISABLED
++ return BUNDLE_DEBUGPY
def override_build(cmds):
-@@ -133,9 +139,24 @@ with open("DESCRIPTION.md", "r") as fh:
+@@ -147,7 +151,28 @@ if __name__ == "__main__":
-
- if __name__ == "__main__":
-- if not os.getenv("SKIP_CYTHON_BUILD"):
-+ if not (os.getenv("SKIP_CYTHON_BUILD") or DEBUGPY_BUNDLING_DISABLED):
- cython_build()
-
-+ # Etch bundling status in the source.
-+ if debugpy.__bundling_disabled__ != DEBUGPY_BUNDLING_DISABLED:
-+
-+ with open(os.path.join(DEBUGBY_ROOT, '__init__.py'), 'r') as f:
-+ lines = f.readlines()
-+ with open(os.path.join(DEBUGBY_ROOT, '__init__.py'), 'w') as f:
-+ edited = []
-+ for line in lines:
-+ if line.startswith('__bundling_disabled__'):
-+ edited.append(
-+ f'__bundling_disabled__ = {DEBUGPY_BUNDLING_DISABLED}\n')
-+ else:
-+ edited.append(line)
-+ f.writelines(edited)
-+
- extras = {}
- platforms = get_buildplatform()
- if platforms is not None:
-@@ -145,6 +166,18 @@ if __name__ == "__main__":
+ cmds = versioneer.get_cmdclass()
override_build(cmds)
- override_build_py(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 not DEBUGPY_BUNDLING_DISABLED:
-+ data.update({"debugpy._vendored": list(iter_vendored_files())})
++ "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",
- version=versioneer.get_version(),
-@@ -173,20 +206,10 @@ if __name__ == "__main__":
+@@ -176,16 +201,10 @@ if __name__ == "__main__":
"License :: OSI Approved :: MIT License",
],
package_dir={"": "src"},
-- packages=[
-- "debugpy",
-- "debugpy.adapter",
-- "debugpy.common",
-- "debugpy.launcher",
-- "debugpy.server",
-- "debugpy._vendored",
-- ],
+- packages=setuptools.find_namespace_packages(where="src", include=["debugpy*"]),
- package_data={
- "debugpy": ["ThirdPartyNotices.txt"],
-- "debugpy._vendored": list(iter_vendored_files()),
+- "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: not DEBUGPY_BUNDLING_DISABLED,
++ has_ext_modules=lambda: BUNDLE_DEBUGPY,
cmdclass=cmds,
**extras
)
diff --git a/src/debugpy/__init__.py b/src/debugpy/__init__.py
-index baa5a7c5..7b7a29aa 100644
+index 975bec79..512219d7 100644
--- a/src/debugpy/__init__.py
+++ b/src/debugpy/__init__.py
-@@ -206,6 +206,8 @@ def trace_this_thread(should_trace):
+@@ -24,6 +24,13 @@ __all__ = [ # noqa
- __version__ = _version.get_versions()["version"]
+ import sys
-+__bundling_disabled__ = False
++try:
++ import debugpy._vendored # noqa
+
- # Force absolute path on Python 2.
- __file__ = os.path.abspath(__file__)
++ 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."
+diff --git a/src/debugpy/_vendored/force_pydevd.py b/src/debugpy/_vendored/force_pydevd.py
+index cfd89275..99622f8c 100644
+--- a/src/debugpy/_vendored/force_pydevd.py
++++ b/src/debugpy/_vendored/force_pydevd.py
+@@ -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'
+-)
diff --git a/src/debugpy/server/__init__.py b/src/debugpy/server/__init__.py
-index e6a1ad66..5f29a87a 100644
+index 42d5367f..a27c6bf4 100644
--- a/src/debugpy/server/__init__.py
+++ b/src/debugpy/server/__init__.py
-@@ -4,6 +4,50 @@
-
- from __future__ import absolute_import, division, print_function, unicode_literals
+@@ -2,6 +2,70 @@
+ # 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
+
@@ -139,52 +196,70 @@ index e6a1ad66..5f29a87a 100644
# that the debugpy-vendored copy of pydevd gets used.
-import debugpy._vendored.force_pydevd # noqa
+import debugpy
-+if debugpy.__bundling_disabled__:
-+ # Do what force_pydevd.py does, but using the system-provided
-+ # pydevd.
+
-+ # XXX: This is copied here so that the whole '_vendored' directory
-+ # can be deleted when DEBUGPY_BUNDLING_DISABLED is set.
++# 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"
++ )
+
-+ # 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")
+
-+ # Work around https://github.com/microsoft/debugpy/issues/346.
-+ # 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")
++BUNDLE_DEBUGPY = bool(os.getenv("BUNDLE_DEBUGPY"))
+
-+ # Constants must be set before importing any other pydevd module
-+ # due to heavy use of "from" in them.
-+ pydevd_constants = import_module('_pydevd_bundle.pydevd_constants')
-+ # The default pydevd value is 1000.
-+ 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
++# Constants must be set before importing any other pydevd module
++# due to heavy use of "from" in them.
++if BUNDLE_DEBUGPY:
++ try:
++ import debugpy._vendored.force_pydevd # noqa
++ except Exception as e:
++ raise e
+else:
-+ import debugpy._vendored.force_pydevd # noqa
++ 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 BUNDLE_DEBUGPY:
++ pydevd_defaults.PydevdCustomization.PREIMPORT = "%s;%s" % (
++ os.path.dirname(os.path.dirname(debugpy.__file__)),
++ "debugpy._vendored.force_pydevd",
++ )
diff --git a/src/debugpy/server/attach_pid_injected.py b/src/debugpy/server/attach_pid_injected.py
-index e6345996..87cfdd53 100644
+index a8df6e1e..06e49600 100644
--- a/src/debugpy/server/attach_pid_injected.py
+++ b/src/debugpy/server/attach_pid_injected.py
-@@ -8,6 +8,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
+@@ -6,6 +6,7 @@
import os
@@ -192,7 +267,7 @@ index e6345996..87cfdd53 100644
__file__ = os.path.abspath(__file__)
_debugpy_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
-@@ -30,25 +31,29 @@ def attach(setup):
+@@ -28,25 +29,29 @@ def attach(setup):
def on_critical(msg):
print(msg, file=sys.stderr)
@@ -205,10 +280,7 @@ index e6345996..87cfdd53 100644
- )
- 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
-+ if debugpy.__bundling_disabled__:
++ if not debugpy.is_pydevd_bundled:
+ from pydevd_attach_to_process import attach_script
+ else:
+ pydevd_attach_to_process_path = os.path.join(
@@ -220,7 +292,9 @@ index e6345996..87cfdd53 100644
+ )
+ 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
@@ -230,25 +304,29 @@ index e6345996..87cfdd53 100644
- # NOTE: At this point it should be safe to remove this.
- sys.path.remove(pydevd_attach_to_process_path)
-+ if not debugpy.__bundling_disabled__:
++ 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
diff --git a/tests/tests/test_vendoring.py b/tests/tests/test_vendoring.py
-index dd6c4269..28c03702 100644
+index 9cf44220..3188eb9e 100644
--- a/tests/tests/test_vendoring.py
+++ b/tests/tests/test_vendoring.py
-@@ -1,3 +1,8 @@
+@@ -3,6 +3,12 @@
+ # for license information.
+
+
+import pytest
+
+import debugpy
+
-+@pytest.mark.skipif(debugpy.__bundling_disabled__, reason='Bundling disabled')
++
++@pytest.mark.skipif(not debugpy.is_pydevd_bundled, reason="pydevd is not bundled")
def test_vendoring(pyfile):
@pyfile
def import_debugpy():
--
-2.34.0
+2.41.0
Toggle diff (33 lines)
diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index 1a3c825faab..1468da48999 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -16801,7 +16801,7 @@ (define-public python-pydevd
(define-public python-debugpy
(package
(name "python-debugpy")
- (version "1.6.0")
+ (version "1.8.0")
(source
(origin
(method git-fetch)
@@ -16816,7 +16816,7 @@ (define-public python-debugpy
(patches (search-patches "python-debugpy-unbundle-pydevd.patch"))
(sha256
(base32
- "1dpfzs3p51648i7f3fz8dw5d0vrj39iwn1jhn0226idc02ybyqih"))))
+ "0li02v3d6msr9qp12znzq2h1dki2zsivz6gzi0x06rskrdxxbnd7"))))
(build-system pyproject-build-system)
(arguments
(list
@@ -16848,7 +16848,7 @@ (define-public python-debugpy
(lambda _
;; This adjusts the behavior of debugpy to load pydevd from
;; Python site packages.
- (setenv "DEBUGPY_BUNDLING_DISABLED" "1"))))))
+ (setenv "BUNDLE_DEBUGPY" "0"))))))
(native-inputs
;; See: https://raw.githubusercontent.com/microsoft/debugpy/
;; main/tests/requirements.txt.
--
2.41.0
C
C
Christopher Baines wrote 5 days ago
Re: [bug#70995] [PATCH v3 0/2] Update python-debugpy.
(name . Nicolas Graves via Guix-patches via)(address . guix-patches@gnu.org)
875xufbw0t.fsf@cbaines.net
Nicolas Graves via Guix-patches via <guix-patches@gnu.org> writes:

Toggle quote (11 lines)
> This proposed update is downgraded to the previous version, because of
> the following issue: https://github.com/microsoft/debugpy/issues/1585
>
> Nicolas Graves (2):
> gnu: python-debugpy: Move to pyproject-build-system.
> gnu: python-debugpy: Update to 1.8.0.
>
> .../python-debugpy-unbundle-pydevd.patch | 318 +++++++++++-------
> gnu/packages/python-xyz.scm | 32 +-
> 2 files changed, 212 insertions(+), 138 deletions(-)

From looking at QA, it seems like this change might break
python-ipykernel, any ideas?
-----BEGIN PGP SIGNATURE-----

iQKlBAEBCgCPFiEEPonu50WOcg2XVOCyXiijOwuE9XcFAmZoKiJfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNF
ODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcRHG1haWxAY2Jh
aW5lcy5uZXQACgkQXiijOwuE9Xesiw/+MXt7nuFhQ3MI65YRBg3urvdZrCfj74R9
uqF5uMxpyQ2neQp+Qo2QXKRoeCV6dyVVrGu2XVBF7jFm0OIsp9tDZLsEMhF+2Zm7
u33D+KJDjazcB49tHxAZbXhKdBo4Dgv3HIA9V3ahtBi+JugmTH5819yFZD+BCf8S
2WwkGOTd6miW4H35w0p+jeTNfVG/LmH5fNbQ1PPuuEMP2Oe60e5c5Mxnb+evwwKE
kIPc/XxYgizf9GJAuG3lZwsZa+ndeqilT7TOzXlvnfHawF/2DqhHR9QWpUsHiTBN
bi0xPyEexsve51cHOzgZlUxdeos6ZFQQ55azVNg6NqbKj2S/Mju8KDvQR5Tkoq0I
zflfb+LRci8B5Ip1x2hhEfHKzjnwMCQ1cSUxQhCSlAuXfwfrDs3/pElKWNM1GWbD
chgdqIo6supUNpQWuNkwKzSFqsP49cPAkwrtIynA8Z3M1NW9e8FIOt74oVOBMW71
mHWHi0dU/UdBnC82hGmh+U+Ar8qLc4xTnJUVPCPC0sBp9YUefQGNlmpT34Lf4cXF
0DPP7rWIfLXJNkfECSHME2mjlNEbFdf0DQOBriK3SoDKMAJv35oPN6oUsonbsl9v
nocZypy92QUbtNwBiVnn5KjDUipJ/hqPjhq+2Bs8bL+T/vZ2qdah2rUEYb5uzdbs
BILzGGQjz4w=
=jfCV
-----END PGP SIGNATURE-----

N
N
Nicolas Graves wrote 18 hours ago
(name . Christopher Baines)(address . mail@cbaines.net)(address . 70995@debbugs.gnu.org)
87ed8y46b3.fsf@ngraves.fr
On 2024-06-11 11:42, Christopher Baines wrote:

Toggle quote (13 lines)
> Nicolas Graves via Guix-patches via <guix-patches@gnu.org> writes:
>
>> Nicolas Graves (2):
>> gnu: python-debugpy: Move to pyproject-build-system.
>> gnu: python-debugpy: Update to 1.8.0.
>>
>> .../python-debugpy-unbundle-pydevd.patch | 318 +++++++++++-------
>> gnu/packages/python-xyz.scm | 32 +-
>> 2 files changed, 212 insertions(+), 138 deletions(-)
>
> From looking at QA, it seems like this change might break
> python-ipykernel, any ideas?

I'm not sure it breaks, QA is not available anymore and I can build it
without any issues on my side. I've probably forgotten to block this
patch by the pydevd update though, will do.

Should I submit again after this?

IIRC, the merging order for the extend work around this is 70393/71037/70995.

--
Best regards,
Nicolas Graves
N
N
Nicolas Graves wrote 18 hours ago
(name . Christopher Baines)(address . mail@cbaines.net)(address . 70995@debbugs.gnu.org)
875xua447a.fsf@ngraves.fr
On 2024-06-15 16:41, Nicolas Graves via Guix-patches via wrote:

Toggle quote (24 lines)
> On 2024-06-11 11:42, Christopher Baines wrote:
>
>> Nicolas Graves via Guix-patches via <guix-patches@gnu.org> writes:
>>
>>> Nicolas Graves (2):
>>> gnu: python-debugpy: Move to pyproject-build-system.
>>> gnu: python-debugpy: Update to 1.8.0.
>>>
>>> .../python-debugpy-unbundle-pydevd.patch | 318 +++++++++++-------
>>> gnu/packages/python-xyz.scm | 32 +-
>>> 2 files changed, 212 insertions(+), 138 deletions(-)
>>
>> From looking at QA, it seems like this change might break
>> python-ipykernel, any ideas?
>
> I'm not sure it breaks, QA is not available anymore and I can build it
> without any issues on my side. I've probably forgotten to block this
> patch by the pydevd update though, will do.
>
> Should I submit again after this?
>
> IIRC, the merging order for the extend work around this is
> 70393/71037/70995.

In fact, it is properly blocked, and I don't see any issue locally with
python-ipykernel. This looks good for a review to me. I'll submit again
to give it another go with QA.

--
Best regards,
Nicolas Graves
N
N
Nicolas Graves wrote 17 hours ago
[PATCH v4 1/2] gnu: python-debugpy: Move to pyproject-build-system.
(address . 70995@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20240615152915.12986-1-ngraves@ngraves.fr
* gnu/packages/python-xyz.scm (python-debugpy):
[build-system]: Move to pyproject-build-system.
[arguments]<#:test-flags>: Superset 'check phase replacement.

Change-Id: Ie112f4b25df8f7996124b465b81c84403294f2d5
---
gnu/packages/python-xyz.scm | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)

Toggle diff (51 lines)
diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index bde5c92bf84..bdf841521fa 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -16857,10 +16857,20 @@ (define-public python-debugpy
(sha256
(base32
"1dpfzs3p51648i7f3fz8dw5d0vrj39iwn1jhn0226idc02ybyqih"))))
- (build-system python-build-system)
+ (build-system pyproject-build-system)
(arguments
(list
#:tests? #f ; Fail on systems with YAMA LSM’s ptrace scope > 0.
+ #:test-flags
+ '(list "-n" (number->string (parallel-job-count))
+ "-k" (string-append
+ ;; These tests cannot be run in parallel because their
+ ;; test data would not be copied by xdist and lead to
+ ;; import errors. (see:
+ ;; https://github.com/microsoft/debugpy/issues/342 and
+ ;; https://github.com/microsoft/debugpy/issues/880).
+ "not test_custom_python_args "
+ "and not test_autokill "))
#:phases
#~(modify-phases %standard-phases
(add-after 'unpack 'patch-sh-in-tests
@@ -16878,21 +16888,7 @@ (define-public python-debugpy
(lambda _
;; This adjusts the behavior of debugpy to load pydevd from
;; Python site packages.
- (setenv "DEBUGPY_BUNDLING_DISABLED" "1")))
- (replace 'check
- (lambda* (#:key tests? #:allow-other-keys)
- (when tests?
- (invoke "pytest" "-vv"
- "-n" (number->string (parallel-job-count))
- "-k"
- (string-append
- ;; These tests cannot be run in parallel because their
- ;; test data would not be copied by xdist and lead to
- ;; import errors. (see:
- ;; https://github.com/microsoft/debugpy/issues/342 and
- ;; https://github.com/microsoft/debugpy/issues/880).
- "not test_custom_python_args "
- "and not test_autokill "))))))))
+ (setenv "DEBUGPY_BUNDLING_DISABLED" "1"))))))
(native-inputs
;; See: https://raw.githubusercontent.com/microsoft/debugpy/
;; main/tests/requirements.txt.
--
2.45.1
N
N
Nicolas Graves wrote 17 hours ago
[PATCH v4 2/2] gnu: python-debugpy: Update to 1.8.0.
(address . 70995@debbugs.gnu.org)(address . ngraves@ngraves.fr)
20240615152915.12986-2-ngraves@ngraves.fr
* gnu/packages/python-xyz.scm (python-debugpy): Update to 1.8.0.
* gnu/packages/patches/python-debugpy-unbundle-pydevd.patch: Update it.

Change-Id: Ice5f869fc36b29cb9d0ad998684b0526c16ab79d
---
.../python-debugpy-unbundle-pydevd.patch | 318 +++++++++++-------
gnu/packages/python-xyz.scm | 6 +-
2 files changed, 201 insertions(+), 123 deletions(-)

Toggle diff (392 lines)
diff --git a/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch b/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
index 7a6ad544896..dabdbd2b526 100644
--- a/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
+++ b/gnu/packages/patches/python-debugpy-unbundle-pydevd.patch
@@ -1,137 +1,194 @@
Allow using pydevd as a regular dependency.
-Submitted upstream at: https://github.com/microsoft/debugpy/pull/902
+Submitted upstream at: https://github.com/microsoft/debugpy/pull/1586
diff --git a/setup.py b/setup.py
-index 5fc40070..3a530a29 100644
+index 0bb4f00c..59fab822 100644
--- a/setup.py
+++ b/setup.py
-@@ -11,6 +11,9 @@ import subprocess
+@@ -11,6 +11,8 @@ import subprocess
import sys
-+DEBUGPY_BUNDLING_DISABLED = bool(os.getenv('DEBUGPY_BUNDLING_DISABLED'))
-+
++BUNDLE_DEBUGPY = not (os.getenv("BUNDLE_DEBUGPY").strip().lower() == "0")
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import versioneer # noqa
-@@ -18,12 +21,15 @@ del sys.path[0]
+@@ -18,12 +20,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 not DEBUGPY_BUNDLING_DISABLED:
++if BUNDLE_DEBUGPY:
+ import debugpy._vendored
del sys.path[0]
-
+-
-PYDEVD_ROOT = debugpy._vendored.project_root("pydevd")
-+PYDEVD_ROOT = (None if DEBUGPY_BUNDLING_DISABLED else
-+ 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__))
-@@ -67,7 +73,7 @@ def iter_vendored_files():
+@@ -46,7 +50,7 @@ def get_buildplatform():
# relevant setuptools versions.
class ExtModules(list):
def __bool__(self):
- return True
-+ return not DEBUGPY_BUNDLING_DISABLED
++ return BUNDLE_DEBUGPY
def override_build(cmds):
-@@ -133,9 +139,24 @@ with open("DESCRIPTION.md", "r") as fh:
+@@ -147,7 +151,28 @@ if __name__ == "__main__":
-
- if __name__ == "__main__":
-- if not os.getenv("SKIP_CYTHON_BUILD"):
-+ if not (os.getenv("SKIP_CYTHON_BUILD") or DEBUGPY_BUNDLING_DISABLED):
- cython_build()
-
-+ # Etch bundling status in the source.
-+ if debugpy.__bundling_disabled__ != DEBUGPY_BUNDLING_DISABLED:
-+
-+ with open(os.path.join(DEBUGBY_ROOT, '__init__.py'), 'r') as f:
-+ lines = f.readlines()
-+ with open(os.path.join(DEBUGBY_ROOT, '__init__.py'), 'w') as f:
-+ edited = []
-+ for line in lines:
-+ if line.startswith('__bundling_disabled__'):
-+ edited.append(
-+ f'__bundling_disabled__ = {DEBUGPY_BUNDLING_DISABLED}\n')
-+ else:
-+ edited.append(line)
-+ f.writelines(edited)
-+
- extras = {}
- platforms = get_buildplatform()
- if platforms is not None:
-@@ -145,6 +166,18 @@ if __name__ == "__main__":
+ cmds = versioneer.get_cmdclass()
override_build(cmds)
- override_build_py(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 not DEBUGPY_BUNDLING_DISABLED:
-+ data.update({"debugpy._vendored": list(iter_vendored_files())})
++ "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",
- version=versioneer.get_version(),
-@@ -173,20 +206,10 @@ if __name__ == "__main__":
+@@ -176,16 +201,10 @@ if __name__ == "__main__":
"License :: OSI Approved :: MIT License",
],
package_dir={"": "src"},
-- packages=[
-- "debugpy",
-- "debugpy.adapter",
-- "debugpy.common",
-- "debugpy.launcher",
-- "debugpy.server",
-- "debugpy._vendored",
-- ],
+- packages=setuptools.find_namespace_packages(where="src", include=["debugpy*"]),
- package_data={
- "debugpy": ["ThirdPartyNotices.txt"],
-- "debugpy._vendored": list(iter_vendored_files()),
+- "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: not DEBUGPY_BUNDLING_DISABLED,
++ has_ext_modules=lambda: BUNDLE_DEBUGPY,
cmdclass=cmds,
**extras
)
diff --git a/src/debugpy/__init__.py b/src/debugpy/__init__.py
-index baa5a7c5..7b7a29aa 100644
+index 975bec79..512219d7 100644
--- a/src/debugpy/__init__.py
+++ b/src/debugpy/__init__.py
-@@ -206,6 +206,8 @@ def trace_this_thread(should_trace):
+@@ -24,6 +24,13 @@ __all__ = [ # noqa
- __version__ = _version.get_versions()["version"]
+ import sys
-+__bundling_disabled__ = False
++try:
++ import debugpy._vendored # noqa
+
- # Force absolute path on Python 2.
- __file__ = os.path.abspath(__file__)
++ 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."
+diff --git a/src/debugpy/_vendored/force_pydevd.py b/src/debugpy/_vendored/force_pydevd.py
+index cfd89275..99622f8c 100644
+--- a/src/debugpy/_vendored/force_pydevd.py
++++ b/src/debugpy/_vendored/force_pydevd.py
+@@ -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'
+-)
diff --git a/src/debugpy/server/__init__.py b/src/debugpy/server/__init__.py
-index e6a1ad66..5f29a87a 100644
+index 42d5367f..a27c6bf4 100644
--- a/src/debugpy/server/__init__.py
+++ b/src/debugpy/server/__init__.py
-@@ -4,6 +4,50 @@
-
- from __future__ import absolute_import, division, print_function, unicode_literals
+@@ -2,6 +2,70 @@
+ # 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
+
@@ -139,52 +196,70 @@ index e6a1ad66..5f29a87a 100644
# that the debugpy-vendored copy of pydevd gets used.
-import debugpy._vendored.force_pydevd # noqa
+import debugpy
-+if debugpy.__bundling_disabled__:
-+ # Do what force_pydevd.py does, but using the system-provided
-+ # pydevd.
+
-+ # XXX: This is copied here so that the whole '_vendored' directory
-+ # can be deleted when DEBUGPY_BUNDLING_DISABLED is set.
++# 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"
++ )
+
-+ # 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")
+
-+ # Work around https://github.com/microsoft/debugpy/issues/346.
-+ # 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")
++BUNDLE_DEBUGPY = bool(os.getenv("BUNDLE_DEBUGPY"))
+
-+ # Constants must be set before importing any other pydevd module
-+ # due to heavy use of "from" in them.
-+ pydevd_constants = import_module('_pydevd_bundle.pydevd_constants')
-+ # The default pydevd value is 1000.
-+ 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
++# Constants must be set before importing any other pydevd module
++# due to heavy use of "from" in them.
++if BUNDLE_DEBUGPY:
++ try:
++ import debugpy._vendored.force_pydevd # noqa
++ except Exception as e:
++ raise e
+else:
-+ import debugpy._vendored.force_pydevd # noqa
++ 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 BUNDLE_DEBUGPY:
++ pydevd_defaults.PydevdCustomization.PREIMPORT = "%s;%s" % (
++ os.path.dirname(os.path.dirname(debugpy.__file__)),
++ "debugpy._vendored.force_pydevd",
++ )
diff --git a/src/debugpy/server/attach_pid_injected.py b/src/debugpy/server/attach_pid_injected.py
-index e6345996..87cfdd53 100644
+index a8df6e1e..06e49600 100644
--- a/src/debugpy/server/attach_pid_injected.py
+++ b/src/debugpy/server/attach_pid_injected.py
-@@ -8,6 +8,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
+@@ -6,6 +6,7 @@
import os
@@ -192,7 +267,7 @@ index e6345996..87cfdd53 100644
__file__ = os.path.abspath(__file__)
_debugpy_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
-@@ -30,25 +31,29 @@ def attach(setup):
+@@ -28,25 +29,29 @@ def attach(setup):
def on_critical(msg):
print(msg, file=sys.stderr)
@@ -205,10 +280,7 @@ index e6345996..87cfdd53 100644
- )
- 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
-+ if debugpy.__bundling_disabled__:
++ if not debugpy.is_pydevd_bundled:
+ from pydevd_attach_to_process import attach_script
+ else:
+ pydevd_attach_to_process_path = os.path.join(
@@ -220,7 +292,9 @@ index e6345996..87cfdd53 100644
+ )
+ 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
@@ -230,25 +304,29 @@ index e6345996..87cfdd53 100644
- # NOTE: At this point it should be safe to remove this.
- sys.path.remove(pydevd_attach_to_process_path)
-+ if not debugpy.__bundling_disabled__:
++ 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
diff --git a/tests/tests/test_vendoring.py b/tests/tests/test_vendoring.py
-index dd6c4269..28c03702 100644
+index 9cf44220..3188eb9e 100644
--- a/tests/tests/test_vendoring.py
+++ b/tests/tests/test_vendoring.py
-@@ -1,3 +1,8 @@
+@@ -3,6 +3,12 @@
+ # for license information.
+
+
+import pytest
+
+import debugpy
+
-+@pytest.mark.skipif(debugpy.__bundling_disabled__, reason='Bundling disabled')
++
++@pytest.mark.skipif(not debugpy.is_pydevd_bundled, reason="pydevd is not bundled")
def test_vendoring(pyfile):
@pyfile
def import_debugpy():
--
-2.34.0
+2.41.0
Toggle diff (33 lines)
diff --git a/gnu/packages/python-xyz.scm b/gnu/packages/python-xyz.scm
index bdf841521fa..d4b5976218b 100644
--- a/gnu/packages/python-xyz.scm
+++ b/gnu/packages/python-xyz.scm
@@ -16841,7 +16841,7 @@ (define-public python-pydevd
(define-public python-debugpy
(package
(name "python-debugpy")
- (version "1.6.0")
+ (version "1.8.0")
(source
(origin
(method git-fetch)
@@ -16856,7 +16856,7 @@ (define-public python-debugpy
(patches (search-patches "python-debugpy-unbundle-pydevd.patch"))
(sha256
(base32
- "1dpfzs3p51648i7f3fz8dw5d0vrj39iwn1jhn0226idc02ybyqih"))))
+ "0li02v3d6msr9qp12znzq2h1dki2zsivz6gzi0x06rskrdxxbnd7"))))
(build-system pyproject-build-system)
(arguments
(list
@@ -16888,7 +16888,7 @@ (define-public python-debugpy
(lambda _
;; This adjusts the behavior of debugpy to load pydevd from
;; Python site packages.
- (setenv "DEBUGPY_BUNDLING_DISABLED" "1"))))))
+ (setenv "BUNDLE_DEBUGPY" "0"))))))
(native-inputs
;; See: https://raw.githubusercontent.com/microsoft/debugpy/
;; main/tests/requirements.txt.
--
2.45.1
?
Your comment

Commenting via the web interface is currently disabled.

To comment on this conversation send an email to 70995@debbugs.gnu.org

To respond to this issue using the mumi CLI, first switch to it
mumi current 70995
Then, you may apply the latest patchset in this issue (with sign off)
mumi am -- -s
Or, compose a reply to this issue
mumi compose
Or, send patches to this issue
mumi send-email *.patch