Add support for PyPy. Fixes #835

This commit is contained in:
Fabio Zadrozny 2019-09-09 12:07:23 -03:00
parent 90298c4e79
commit 522f60cc3b
30 changed files with 3182 additions and 2979 deletions

View file

@ -20,79 +20,86 @@ matrix:
- python: 2.7
env:
- PYDEVD_USE_CYTHON=NO
- PYDEVD_TEST_JYTHON=YES
- PYDEVD_TEST_VM=JYTHON
- JYTHON_URL=http://search.maven.org/remotecontent?filepath=org/python/jython-installer/2.7.1/jython-installer-2.7.1.jar
# PyPy
- python: 2.7
env:
- PYDEVD_PYTHON_VERSION=3.6
- PYDEVD_USE_CYTHON=NO
- PYDEVD_TEST_VM=PYPY
# Python 2.6 (with and without cython)
- python: 2.7
env:
- PYDEVD_PYTHON_VERSION=2.6
- PYDEVD_USE_CYTHON=NO
- PYDEVD_TEST_JYTHON=NO
- PYDEVD_TEST_VM=CPYTHON
# - python: 2.7
# env:
# - PYDEVD_PYTHON_VERSION=2.6
# - PYDEVD_USE_CYTHON=YES
# - PYDEVD_TEST_JYTHON=NO
# - PYDEVD_TEST_VM=CPYTHON
# Python 2.7 (with and without cython)
- python: 2.7
env:
- PYDEVD_PYTHON_VERSION=2.7
- PYDEVD_USE_CYTHON=NO
- PYDEVD_TEST_JYTHON=NO
# env:
# - PYDEVD_PYTHON_VERSION=2.7
# - PYDEVD_USE_CYTHON=NO
# - PYDEVD_TEST_VM=CPYTHON
- python: 2.7
env:
- PYDEVD_PYTHON_VERSION=2.7
- PYDEVD_USE_CYTHON=YES
- PYDEVD_TEST_JYTHON=NO
- PYDEVD_TEST_VM=CPYTHON
# Python 3.5 (with and without cython)
# - python: 2.7
# env:
# - PYDEVD_PYTHON_VERSION=3.5
# - PYDEVD_USE_CYTHON=NO
# - PYDEVD_TEST_JYTHON=NO
# - PYDEVD_TEST_VM=CPYTHON
- python: 2.7
env:
- PYDEVD_PYTHON_VERSION=3.5
- PYDEVD_USE_CYTHON=YES
- PYDEVD_TEST_JYTHON=NO
- PYDEVD_TEST_VM=CPYTHON
# Python 3.6 (with and without cython)
# - python: 2.7
# env:
# - PYDEVD_PYTHON_VERSION=3.6
# - PYDEVD_USE_CYTHON=NO
# - PYDEVD_TEST_JYTHON=NO
- python: 2.7
env:
- PYDEVD_PYTHON_VERSION=3.6
- PYDEVD_USE_CYTHON=YES
- PYDEVD_TEST_JYTHON=NO
- PYDEVD_USE_CYTHON=NO
- PYDEVD_TEST_VM=CPYTHON
# - python: 2.7
# env:
# - PYDEVD_PYTHON_VERSION=3.6
# - PYDEVD_USE_CYTHON=YES
# - PYDEVD_TEST_VM=CPYTHON
# Python 3.7 (with and without cython)
- python: 2.7
env:
- PYDEVD_PYTHON_VERSION=3.7
- PYDEVD_USE_CYTHON=NO
- PYDEVD_TEST_JYTHON=NO
# - python: 2.7
# env:
# - PYDEVD_PYTHON_VERSION=3.7
# - PYDEVD_USE_CYTHON=YES
# - PYDEVD_TEST_JYTHON=NO
# - PYDEVD_USE_CYTHON=NO
# - PYDEVD_TEST_VM=CPYTHON
- python: 2.7
env:
- PYDEVD_PYTHON_VERSION=3.7
- PYDEVD_USE_CYTHON=YES
- PYDEVD_TEST_VM=CPYTHON
before_install:
# CPython setup
- if [ "$PYDEVD_TEST_JYTHON" == "NO" ]; then wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh; fi
- if [ "$PYDEVD_TEST_JYTHON" == "NO" ]; then chmod +x miniconda.sh; fi
- if [ "$PYDEVD_TEST_JYTHON" == "NO" ]; then ./miniconda.sh -b; fi
- if [ "$PYDEVD_TEST_JYTHON" == "NO" ]; then export PATH=/home/travis/miniconda2/bin:$PATH; fi
- if [ "$PYDEVD_TEST_JYTHON" == "NO" ]; then conda update --yes conda; fi
# CPython / Pypy setup
- if [[ "$PYDEVD_TEST_VM" == "CPYTHON" || "$PYDEVD_TEST_VM" == "PYPY" ]]; then wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh; fi
- if [[ "$PYDEVD_TEST_VM" == "CPYTHON" || "$PYDEVD_TEST_VM" == "PYPY" ]]; then chmod +x miniconda.sh; fi
- if [[ "$PYDEVD_TEST_VM" == "CPYTHON" || "$PYDEVD_TEST_VM" == "PYPY" ]]; then ./miniconda.sh -b; fi
- if [[ "$PYDEVD_TEST_VM" == "CPYTHON" || "$PYDEVD_TEST_VM" == "PYPY" ]]; then export PATH=/home/travis/miniconda2/bin:$PATH; fi
- if [[ "$PYDEVD_TEST_VM" == "CPYTHON" || "$PYDEVD_TEST_VM" == "PYPY" ]]; then conda update --yes conda; fi
# Jython setup
- if [ "$PYDEVD_TEST_JYTHON" == "YES" ]; then wget $JYTHON_URL -O jython_installer.jar; java -jar jython_installer.jar -s -d $HOME/jython; export PATH=$HOME/jython:$HOME/jython/bin:$PATH; fi
- if [ "$PYDEVD_TEST_JYTHON" == "YES" ]; then jython -c "print('')"; fi
- if [ "$PYDEVD_TEST_VM" == "JYTHON" ]; then wget $JYTHON_URL -O jython_installer.jar; java -jar jython_installer.jar -s -d $HOME/jython; export PATH=$HOME/jython:$HOME/jython/bin:$PATH; fi
- if [ "$PYDEVD_TEST_VM" == "JYTHON" ]; then jython -c "print('')"; fi
# Fix issue with testGui
- "export DISPLAY=:99.0"
# Install packages
@ -100,22 +107,28 @@ install:
- sudo sysctl kernel.yama.ptrace_scope=0
# Both
- export PYTHONPATH=.
# Python setup
- if [ "$PYDEVD_TEST_JYTHON" == "NO" ]; then conda create --yes -n build_env python=$PYDEVD_PYTHON_VERSION; fi
- if [ "$PYDEVD_TEST_JYTHON" == "NO" ]; then source activate build_env; fi
- if [ "$PYDEVD_TEST_JYTHON" == "NO" ]; then chmod +x ./.travis_install_python_deps.sh; fi
- if [ "$PYDEVD_TEST_JYTHON" == "NO" ]; then ./.travis_install_python_deps.sh; fi
- if [ "$PYDEVD_TEST_JYTHON" == "NO" ]; then source activate build_env; python build_tools/build.py; fi
# CPython setup
- if [ "$PYDEVD_TEST_VM" == "CPYTHON" ]; then conda create --yes -n build_env python=$PYDEVD_PYTHON_VERSION; fi
- if [ "$PYDEVD_TEST_VM" == "CPYTHON" ]; then source activate build_env; fi
- if [ "$PYDEVD_TEST_VM" == "CPYTHON" ]; then chmod +x ./.travis_install_python_deps.sh; fi
- if [ "$PYDEVD_TEST_VM" == "CPYTHON" ]; then ./.travis_install_python_deps.sh; fi
- if [ "$PYDEVD_TEST_VM" == "CPYTHON" ]; then source activate build_env; python build_tools/build.py; fi
# Pypy setup
- if [ "$PYDEVD_TEST_VM" == "PYPY" ]; then conda create --yes -n build_env -c conda-forge pypy3.6; fi
- if [ "$PYDEVD_TEST_VM" == "PYPY" ]; then source activate build_env; fi
- if [ "$PYDEVD_TEST_VM" == "PYPY" ]; then chmod +x ./.travis_install_pypy_deps.sh; fi
- if [ "$PYDEVD_TEST_VM" == "PYPY" ]; then ./.travis_install_pypy_deps.sh; fi
# Jython setup
- if [ "$PYDEVD_TEST_JYTHON" == "YES" ]; then chmod +x ./.travis_install_jython_deps.sh; fi
- if [ "$PYDEVD_TEST_JYTHON" == "YES" ]; then ./.travis_install_jython_deps.sh; fi
- if [ "$PYDEVD_TEST_VM" == "JYTHON" ]; then chmod +x ./.travis_install_jython_deps.sh; fi
- if [ "$PYDEVD_TEST_VM" == "JYTHON" ]; then ./.travis_install_jython_deps.sh; fi
# Run test
# On local machine with jython: c:\bin\jython2.7.0\bin\jython.exe -Dpython.path=.;jython_test_deps/ant.jar;jython_test_deps/junit.jar -m pytest
# On remove machine with python: c:\bin\python27\python.exe -m pytest
script:
# pytest-xdist not available for python == 2.6 and timing out without output with 2.7
- if [[ ("$PYDEVD_TEST_JYTHON" == "NO") && ("$PYDEVD_PYTHON_VERSION" == "2.6" || "$PYDEVD_PYTHON_VERSION" == "2.7") ]]; then source activate build_env; python -m pytest; fi
- if [[ ("$PYDEVD_TEST_JYTHON" == "NO") && ("$PYDEVD_PYTHON_VERSION" != "2.6" && "$PYDEVD_PYTHON_VERSION" != "2.7") ]]; then source activate build_env; python -m pytest -n auto; fi
- if [ "$PYDEVD_TEST_JYTHON" == "YES" ]; then jython -Dpython.path=.:jython_test_deps/ant.jar:jython_test_deps/junit.jar -m pytest; fi
- if [[ ("$PYDEVD_TEST_VM" == "CPYTHON") && ("$PYDEVD_PYTHON_VERSION" == "2.6" || "$PYDEVD_PYTHON_VERSION" == "2.7") ]]; then source activate build_env; python -m pytest; fi
- if [[ ("$PYDEVD_TEST_VM" == "CPYTHON") && ("$PYDEVD_PYTHON_VERSION" != "2.6" && "$PYDEVD_PYTHON_VERSION" != "2.7") ]]; then source activate build_env; python -m pytest -n auto; fi
- if [ "$PYDEVD_TEST_VM" == "PYPY" ]; then source activate build_env; pypy3 -m pytest -n auto; fi
- if [ "$PYDEVD_TEST_VM" == "JYTHON" ]; then jython -Dpython.path=.:jython_test_deps/ant.jar:jython_test_deps/junit.jar -m pytest; fi

View file

@ -0,0 +1,15 @@
#!/bin/bash
set -ev
source activate build_env
pypy3 -m ensurepip
pypy3 -m pip install pytest
pypy3 -m pip install pytest-xdist
pypy3 -m pip install pytest-timeout
pypy3 -m pip install colorama
pypy3 -m pip install psutil
pypy3 -m pip install numpy
pypy3 -m pip install ipython
pypy3 -m pip install untangle

View file

@ -1,4 +1,8 @@
include *.rst *.txt *.md LICENSE .travis.yml appveyor.yml *.pyx
recursive-include pydevd_attach_to_process *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx
recursive-include _pydevd_bundle *.pyx
include *.rst *.txt *.md LICENSE .travis.yml appveyor.yml *.pyx *.cpp *.hpp
recursive-include pydevd_attach_to_process *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx *.cpp *.hpp
recursive-include pydevd_attach_to_process/common *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx *.cpp *.hpp
recursive-include pydevd_attach_to_process/linux_and_mac *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx *.cpp *.hpp
recursive-include pydevd_attach_to_process/winappdbg *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx *.cpp *.hpp
recursive-include pydevd_attach_to_process/windows *.py *.dll *.so *.dylib *.txt *.c *.h *.bat Makefile *.sh *.pyx *.cpp *.hpp
recursive-include _pydevd_bundle *.pyx *.cpp *.hpp
recursive-include build_tools *.py

View file

@ -192,6 +192,8 @@ def completions_to_xml(completions):
msg = ["<xml>"]
for comp in completions:
if IS_PY2:
comp = [(x.encode('utf-8') if x.__class__ == unicode else x) for x in comp]
msg.append('<comp p0="')
msg.append(valid_xml(quote(comp[0], '/>_= \t')))
msg.append('" p1="')

View file

@ -43,7 +43,14 @@ def _pydevd_log(level, msg, *args):
msg = msg % args
except:
msg = '%s - %s' % (msg, args)
DebugInfoHolder.DEBUG_STREAM.write('%s\n' % (msg,))
msg = '%s\n' % (msg,)
try:
DebugInfoHolder.DEBUG_STREAM.write(msg)
except TypeError:
if isinstance(msg, bytes):
# Depending on the StringIO flavor, it may only accept unicode.
msg = msg.decode('utf-8', 'replace')
DebugInfoHolder.DEBUG_STREAM.write(msg)
DebugInfoHolder.DEBUG_STREAM.flush()
except:
pass

View file

@ -1,5 +1,6 @@
import sys
from _pydevd_bundle.pydevd_constants import STATE_RUN, PYTHON_SUSPEND, IS_JYTHON, IS_IRONPYTHON
from _pydevd_bundle.pydevd_constants import (STATE_RUN, PYTHON_SUSPEND, IS_JYTHON,
USE_CUSTOM_SYS_CURRENT_FRAMES, USE_CUSTOM_SYS_CURRENT_FRAMES_MAP)
from _pydev_bundle import pydev_log
# IFDEF CYTHON
# pydev_log.debug("Using Cython speedups")
@ -9,7 +10,7 @@ from _pydevd_bundle.pydevd_frame import PyDBFrame
version = 11
if not hasattr(sys, '_current_frames'):
if USE_CUSTOM_SYS_CURRENT_FRAMES:
# Some versions of Jython don't have it (but we can provide a replacement)
if IS_JYTHON:
@ -40,7 +41,7 @@ if not hasattr(sys, '_current_frames'):
ret[thread.getId()] = frame
return ret
elif IS_IRONPYTHON:
elif USE_CUSTOM_SYS_CURRENT_FRAMES_MAP:
_tid_to_last_frame = {}
# IronPython doesn't have it. Let's use our workaround...

View file

@ -1130,8 +1130,11 @@ def build_exception_info_response(dbg, thread_id, request_seq, set_additional_th
break
frame = frame.f_back
while trace_obj.tb_next is not None:
trace_obj = trace_obj.tb_next
while True:
tb_next = getattr(trace_obj, 'tb_next', None)
if tb_next is None:
break
trace_obj = tb_next
info = dbg.suspended_frames_manager.get_topmost_frame_and_frame_id_to_line(thread_id)
if info is not None:

View file

@ -72,12 +72,17 @@ IS_64BIT_PROCESS = sys.maxsize > (2 ** 32)
IS_JYTHON = pydevd_vm_type.get_vm_type() == pydevd_vm_type.PydevdVmType.JYTHON
IS_JYTH_LESS25 = False
IS_PYPY = platform.python_implementation() == 'PyPy'
if IS_JYTHON:
import java.lang.System # @UnresolvedImport
IS_WINDOWS = java.lang.System.getProperty("os.name").lower().startswith("windows")
if sys.version_info[0] == 2 and sys.version_info[1] < 5:
IS_JYTH_LESS25 = True
USE_CUSTOM_SYS_CURRENT_FRAMES = not hasattr(sys, '_current_frames') or IS_PYPY
USE_CUSTOM_SYS_CURRENT_FRAMES_MAP = USE_CUSTOM_SYS_CURRENT_FRAMES and (IS_PYPY or IS_IRONPYTHON)
IS_PYTHON_STACKLESS = "stackless" in sys.version.lower()
CYTHON_SUPPORTED = False

File diff suppressed because it is too large Load diff

View file

@ -5,7 +5,8 @@ from __future__ import print_function
# DO NOT edit manually!
# DO NOT edit manually!
import sys
from _pydevd_bundle.pydevd_constants import STATE_RUN, PYTHON_SUSPEND, IS_JYTHON, IS_IRONPYTHON
from _pydevd_bundle.pydevd_constants import (STATE_RUN, PYTHON_SUSPEND, IS_JYTHON,
USE_CUSTOM_SYS_CURRENT_FRAMES, USE_CUSTOM_SYS_CURRENT_FRAMES_MAP)
from _pydev_bundle import pydev_log
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
pydev_log.debug("Using Cython speedups")
@ -15,7 +16,7 @@ pydev_log.debug("Using Cython speedups")
version = 11
if not hasattr(sys, '_current_frames'):
if USE_CUSTOM_SYS_CURRENT_FRAMES:
# Some versions of Jython don't have it (but we can provide a replacement)
if IS_JYTHON:
@ -46,7 +47,7 @@ if not hasattr(sys, '_current_frames'):
ret[thread.getId()] = frame
return ret
elif IS_IRONPYTHON:
elif USE_CUSTOM_SYS_CURRENT_FRAMES_MAP:
_tid_to_last_frame = {}
# IronPython doesn't have it. Let's use our workaround...
@ -913,11 +914,13 @@ cdef class PyDBFrame:
# end trace_dispatch
from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
from _pydev_bundle.pydev_log import exception as pydev_log_exception
from _pydev_imps._pydev_saved_modules import threading
from _pydevd_bundle.pydevd_constants import get_current_thread_id, IS_IRONPYTHON, NO_FTRACE
from _pydevd_bundle.pydevd_constants import (get_current_thread_id, NO_FTRACE,
USE_CUSTOM_SYS_CURRENT_FRAMES_MAP)
from _pydevd_bundle.pydevd_kill_all_pydevd_threads import kill_all_pydev_threads
from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER
from _pydev_bundle.pydev_log import exception as pydev_log_exception
# IFDEF CYTHON -- DONT EDIT THIS FILE (it is automatically generated)
from cpython.object cimport PyObject
from cpython.ref cimport Py_INCREF, Py_XDECREF
@ -1421,7 +1424,7 @@ cdef class ThreadTracer:
return None if event == 'call' else NO_FTRACE
if IS_IRONPYTHON:
if USE_CUSTOM_SYS_CURRENT_FRAMES_MAP:
# This is far from ideal, as we'll leak frames (we'll always have the last created frame, not really
# the last topmost frame saved -- this should be Ok for our usage, but it may leak frames and things
# may live longer... as IronPython is garbage-collected, things should live longer anyways, so, it

View file

@ -21,7 +21,7 @@ from _pydevd_bundle.pydevd_net_command_factory_xml import NetCommandFactory
from _pydevd_bundle.pydevd_utils import get_non_pydevd_threads
import pydevd_file_utils
from _pydevd_bundle.pydevd_comm import build_exception_info_response, pydevd_find_thread_by_id
from _pydevd_bundle.pydevd_additional_thread_info_regular import set_additional_thread_info
from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_info
class ModulesManager(object):

View file

@ -1,9 +1,11 @@
from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
from _pydev_bundle.pydev_log import exception as pydev_log_exception
from _pydev_imps._pydev_saved_modules import threading
from _pydevd_bundle.pydevd_constants import get_current_thread_id, IS_IRONPYTHON, NO_FTRACE
from _pydevd_bundle.pydevd_constants import (get_current_thread_id, NO_FTRACE,
USE_CUSTOM_SYS_CURRENT_FRAMES_MAP)
from _pydevd_bundle.pydevd_kill_all_pydevd_threads import kill_all_pydev_threads
from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame, NORM_PATHS_AND_BASE_CONTAINER
from _pydev_bundle.pydev_log import exception as pydev_log_exception
# IFDEF CYTHON
# from cpython.object cimport PyObject
# from cpython.ref cimport Py_INCREF, Py_XDECREF
@ -513,7 +515,7 @@ class ThreadTracer(object):
return None if event == 'call' else NO_FTRACE
if IS_IRONPYTHON:
if USE_CUSTOM_SYS_CURRENT_FRAMES_MAP:
# This is far from ideal, as we'll leak frames (we'll always have the last created frame, not really
# the last topmost frame saved -- this should be Ok for our usage, but it may leak frames and things
# may live longer... as IronPython is garbage-collected, things should live longer anyways, so, it

View file

@ -9,7 +9,7 @@ except:
import inspect
import sys
from _pydevd_bundle.pydevd_constants import IS_PY3K
from _pydevd_bundle.pydevd_constants import IS_PY3K, USE_CUSTOM_SYS_CURRENT_FRAMES, IS_PYPY
from _pydev_imps._pydev_saved_modules import threading
@ -166,7 +166,12 @@ def dump_threads(stream=None):
except:
pass
from _pydevd_bundle.pydevd_additional_thread_info_regular import _current_frames
if USE_CUSTOM_SYS_CURRENT_FRAMES and IS_PYPY:
# On PyPy we can use its fake_frames to get the traceback
# (instead of the actual real frames that need the tracing to be correct).
_current_frames = sys._current_frames
else:
from _pydevd_bundle.pydevd_additional_thread_info_regular import _current_frames
stream.write('===============================================================================\n')
stream.write('Threads running\n')

View file

@ -10,10 +10,12 @@ stop_frame_eval = None
dummy_trace_dispatch = None
clear_thread_local_info = None
use_cython = os.getenv('PYDEVD_USE_CYTHON', None)
# "NO" means we should not use frame evaluation, 'YES' we should use it (and fail if not there) and unspecified uses if possible.
use_frame_eval = os.environ.get('PYDEVD_USE_FRAME_EVAL', None)
if use_frame_eval == 'NO':
if use_frame_eval == 'NO' or use_cython == 'NO':
pass
elif use_frame_eval == 'YES':

View file

@ -2,7 +2,7 @@ import pytest
import sys
from _pydevd_bundle.pydevd_constants import IS_JYTHON, IS_IRONPYTHON
from tests_python.debug_constants import TEST_CYTHON
from tests_python.debug_constants import TEST_JYTHON
from tests_python.debug_constants import PYDEVD_TEST_VM
import site
import os
from _pydev_bundle import pydev_log
@ -10,7 +10,7 @@ from _pydev_bundle import pydev_log
def pytest_report_header(config):
print('PYDEVD_USE_CYTHON: %s' % (TEST_CYTHON,))
print('PYDEVD_TEST_JYTHON: %s' % (TEST_JYTHON,))
print('PYDEVD_TEST_VM: %s' % (PYDEVD_TEST_VM,))
try:
import multiprocessing
except ImportError:
@ -19,6 +19,7 @@ def pytest_report_header(config):
print('Number of processors: %s' % (multiprocessing.cpu_count(),))
print('Relevant system paths:')
print('sys.executable: %s' % (sys.executable,))
print('sys.prefix: %s' % (sys.prefix,))
if hasattr(sys, 'base_prefix'):
@ -193,7 +194,13 @@ _global_collect_info = False
@pytest.yield_fixture(autouse=True)
def before_after_each_function(request):
global _global_collect_info
import psutil
try:
import psutil # Don't fail if not there
except ImportError:
yield
return
current_pids = set(proc.pid for proc in psutil.process_iter())
before_curr_proc_memory_info = psutil.Process().memory_info()

View file

@ -39,7 +39,7 @@ from _pydevd_bundle.pydevd_comm_constants import (CMD_THREAD_SUSPEND, CMD_STEP_I
from _pydevd_bundle.pydevd_constants import (IS_JYTH_LESS25, get_thread_id, get_current_thread_id,
dict_keys, dict_iter_items, DebugInfoHolder, PYTHON_SUSPEND, STATE_SUSPEND, STATE_RUN, get_frame,
clear_cached_thread_id, INTERACTIVE_MODE_AVAILABLE, SHOW_DEBUG_INFO_ENV, IS_PY34_OR_GREATER, IS_PY2, NULL,
NO_FTRACE, IS_IRONPYTHON, JSON_PROTOCOL, IS_CPYTHON, call_only_once)
NO_FTRACE, IS_IRONPYTHON, JSON_PROTOCOL, IS_CPYTHON, USE_CUSTOM_SYS_CURRENT_FRAMES_MAP, call_only_once)
from _pydevd_bundle.pydevd_defaults import PydevdCustomization
from _pydevd_bundle.pydevd_custom_frames import CustomFramesContainer, custom_frames_container_init
from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE, PYDEV_FILE, LIB_FILE
@ -73,6 +73,9 @@ from _pydevd_bundle.pydevd_suspended_frames import SuspendedFramesManager
from socket import SHUT_RDWR
from _pydevd_bundle.pydevd_api import PyDevdAPI
if USE_CUSTOM_SYS_CURRENT_FRAMES_MAP:
from _pydevd_bundle.pydevd_additional_thread_info_regular import _tid_to_last_frame
__version_info__ = (1, 3, 3)
__version_info_str__ = []
for v in __version_info__:
@ -623,9 +626,12 @@ class PyDB(object):
def _internal_get_file_type(self, abs_real_path_and_basename):
basename = abs_real_path_and_basename[-1]
if basename.startswith('<frozen '):
# In Python 3.7 "<frozen ..." appear multiple times during import and should be
# In Python 3.7 "<frozen ..." appears multiple times during import and should be
# ignored for the user.
return self.PYDEV_FILE
if abs_real_path_and_basename[0].startswith('<builtin'):
# In PyPy "<builtin> ..." can appear and should be ignored for the user.
return self.PYDEV_FILE
return self._dont_trace_get_file_type(basename)
def dont_trace_external_files(self, abs_path):
@ -1583,6 +1589,8 @@ class PyDB(object):
as the paused location on the top-level frame (exception info must be passed on 'arg').
"""
# print('do_wait_suspend %s %s %s %s' % (frame.f_lineno, frame.f_code.co_name, frame.f_code.co_filename, event))
if USE_CUSTOM_SYS_CURRENT_FRAMES_MAP:
_tid_to_last_frame[thread.ident] = sys._getframe()
self.process_internal_commands()
thread_id = get_current_thread_id(thread)

View file

@ -21,18 +21,21 @@ build_tools\pydevd_release_process.txt
for release process.
'''
from setuptools import setup
from setuptools.dist import Distribution
from distutils.extension import Extension
import os
class BinaryDistribution(Distribution):
def is_pure(self):
return False
data_files = []
def accept_file(f):
f = f.lower()
for ext in '.py .dll .so .dylib .txt .cpp .h .bat .c .sh .md .txt'.split():
@ -41,6 +44,7 @@ def accept_file(f):
return f in ['readme', 'makefile']
data_files.append(('pydevd_attach_to_process', [os.path.join('pydevd_attach_to_process', f) for f in os.listdir('pydevd_attach_to_process') if accept_file(f)]))
for root, dirs, files in os.walk("pydevd_attach_to_process"):
for d in dirs:
@ -52,7 +56,7 @@ version = pydevd.__version__
args = dict(
name='pydevd',
version=version,
description = 'PyDev.Debugger (used in PyDev, PyCharm and VSCode Python)',
description='PyDev.Debugger (used in PyDev, PyCharm and VSCode Python)',
author='Fabio Zadrozny and others',
url='https://github.com/fabioz/PyDev.Debugger/',
license='EPL (Eclipse Public License)',
@ -67,7 +71,7 @@ args = dict(
# 'pydev_sitecustomize', -- Not actually a package (not added)
# 'pydevd_attach_to_process', -- Not actually a package (included in MANIFEST.in)
'pydevd_attach_to_process',
'pydevd_concurrency_analyser',
'pydevd_plugins',
@ -119,8 +123,6 @@ args = dict(
zip_safe=False,
)
import sys
try:
args_with_binaries = args.copy()
@ -129,7 +131,7 @@ try:
ext_modules=[
# In this setup, don't even try to compile with cython, just go with the .c file which should've
# been properly generated from a tested version.
Extension('_pydevd_bundle.pydevd_cython', ["_pydevd_bundle/pydevd_cython.c",])
Extension('_pydevd_bundle.pydevd_cython', ["_pydevd_bundle/pydevd_cython.c", ])
]
))
setup(**args_with_binaries)

View file

@ -5,6 +5,7 @@ import unittest
import pytest
from _pydevd_bundle import pydevd_referrers
from _pydev_bundle.pydev_imports import StringIO
from tests_python.debugger_unittest import IS_PYPY
try:
import gc
@ -13,10 +14,10 @@ try:
except NotImplementedError:
has_referrers = False
# Only do get referrers tests if it's actually available.
@pytest.mark.skipif(not has_referrers, reason='gc.get_referrers not implemented')
class Test(unittest.TestCase):
# Only do get referrers tests if it's actually available.
@pytest.mark.skipif(not has_referrers or IS_PYPY, reason='gc.get_referrers not implemented')
class Test(unittest.TestCase):
def test_get_referrers1(self):
@ -34,6 +35,7 @@ class Test(unittest.TestCase):
def test_get_referrers2(self):
class MyClass(object):
def __init__(self):
pass
@ -48,10 +50,10 @@ class Test(unittest.TestCase):
assert 'found_as="contained"' in result
assert 'MyClass' in result
def test_get_referrers3(self):
class MyClass(object):
def __init__(self):
pass
@ -66,10 +68,10 @@ class Test(unittest.TestCase):
assert 'found_as="contained"' in result
assert 'MyClass' in result
def test_get_referrers4(self):
class MyClass(object):
def __init__(self):
pass
@ -78,20 +80,18 @@ class Test(unittest.TestCase):
# Let's see if we detect the cycle...
result = pydevd_referrers.get_referrer_info(obj)
assert 'found_as="me"' in result #Cyclic ref
assert 'found_as="me"' in result # Cyclic ref
def test_get_referrers5(self):
container = dict(a=[1])
# Let's see if we detect the cycle...
result = pydevd_referrers.get_referrer_info(container['a'])
assert 'test_get_referrers5' not in result #I.e.: NOT in the current method
assert 'test_get_referrers5' not in result # I.e.: NOT in the current method
assert 'found_as="a"' in result
assert 'dict' in result
assert str(id(container)) in result
def test_get_referrers6(self):
import sys
container = dict(a=[1])
@ -107,12 +107,12 @@ class Test(unittest.TestCase):
else:
assert 'should_appear' in result
def test_get_referrers7(self):
class MyThread(threading.Thread):
def run(self):
#Note: we do that because if we do
# Note: we do that because if we do
self.frame = sys._getframe()
t = MyThread()

View file

@ -11,6 +11,7 @@ try:
except NameError:
raw_input_name = 'input'
#=======================================================================================================================
# Test
#=======================================================================================================================
@ -27,9 +28,9 @@ class Test(unittest.TestCase):
try:
client_port, _server_port = self.get_free_addresses()
client_thread = self.start_client_thread(client_port) #@UnusedVariable
client_thread = self.start_client_thread(client_port) # @UnusedVariable
import time
time.sleep(.3) #let's give it some time to start the threads
time.sleep(.3) # let's give it some time to start the threads
from _pydev_bundle import pydev_localhost
interpreter = pydevconsole.InterpreterInterface(pydev_localhost.get_localhost(), client_port, threading.currentThread())
@ -39,16 +40,15 @@ class Test(unittest.TestCase):
finally:
sys.stdout = self.original_stdout
def test_console_requests(self):
self.original_stdout = sys.stdout
sys.stdout = pydevd_io.IOBuf()
try:
client_port, _server_port = self.get_free_addresses()
client_thread = self.start_client_thread(client_port) #@UnusedVariable
client_thread = self.start_client_thread(client_port) # @UnusedVariable
import time
time.sleep(.3) #let's give it some time to start the threads
time.sleep(.3) # let's give it some time to start the threads
from _pydev_bundle import pydev_localhost
from _pydev_bundle.pydev_console_utils import CodeFragment
@ -66,9 +66,9 @@ class Test(unittest.TestCase):
self.assertEqual(['50', 'input_request'], found)
except:
try:
self.assertEqual(['input_request'], found) #IPython
self.assertEqual(['input_request'], found) # IPython
except:
self.assertEqual([u'50', u'input_request'], found[1:]) # IPython 5.1
self.assertEqual([u'50', u'input_request'], found[1:]) # IPython 5.1
self.assertTrue(found[0].startswith(u'Out'))
comps = interpreter.getCompletions('foo.', 'foo.')
@ -86,7 +86,6 @@ class Test(unittest.TestCase):
'Did not find __add__ in : %s' % (comps,)
)
completions = interpreter.getCompletions('', '')
for c in completions:
if c[0] == 'AssertionError':
@ -114,7 +113,7 @@ class Test(unittest.TestCase):
desc.find('str(object=\'\') -> string') >= 0 or
desc.find('str(value: Char*)') >= 0 or
desc.find('str(object=\'\') -> str') >= 0 or
desc.find('The most base type') >= 0 # Jython 2.7 is providing this :P
desc.find('The most base type') >= 0 # Jython 2.7 is providing this :P
,
'Could not find what was needed in %s' % desc)
@ -127,20 +126,24 @@ class Test(unittest.TestCase):
desc.find('str join(str self, list sequence)') >= 0 or
desc.find('S.join(iterable) -> str') >= 0 or
desc.find('join(self: str, sequence: list) -> str') >= 0 or
desc.find('Concatenate any number of strings.') >= 0,
desc.find('Concatenate any number of strings.') >= 0 or
desc.find('bound method str.join') >= 0, # PyPy
"Could not recognize: %s" % (desc,))
finally:
sys.stdout = self.original_stdout
def start_client_thread(self, client_port):
class ClientThread(threading.Thread):
def __init__(self, client_port):
threading.Thread.__init__(self)
self.client_port = client_port
def run(self):
class HandleRequestInput:
def RequestInput(self):
client_thread.requested_input = True
return 'input_request'
@ -164,13 +167,15 @@ class Test(unittest.TestCase):
client_thread.start()
return client_thread
def start_debugger_server_thread(self, debugger_port, socket_code):
class DebuggerServerThread(threading.Thread):
def __init__(self, debugger_port, socket_code):
threading.Thread.__init__(self)
self.debugger_port = debugger_port
self.socket_code = socket_code
def run(self):
import socket
s = socket.socket()
@ -184,26 +189,26 @@ class Test(unittest.TestCase):
debugger_thread.start()
return debugger_thread
def get_free_addresses(self):
from _pydev_bundle.pydev_localhost import get_socket_names
socket_names = get_socket_names(2, True)
port0 = socket_names[0][1]
port1 = socket_names[1][1]
assert port0 != port1
assert port0 > 0
assert port1 > 0
return port0, port1
def test_server(self):
self.original_stdout = sys.stdout
sys.stdout = pydevd_io.IOBuf()
try:
client_port, server_port = self.get_free_addresses()
class ServerThread(threading.Thread):
def __init__(self, client_port, server_port):
threading.Thread.__init__(self)
self.client_port = client_port
@ -212,14 +217,15 @@ class Test(unittest.TestCase):
def run(self):
from _pydev_bundle import pydev_localhost
pydevconsole.start_server(pydev_localhost.get_localhost(), self.server_port, self.client_port)
server_thread = ServerThread(client_port, server_port)
server_thread.setDaemon(True)
server_thread.start()
client_thread = self.start_client_thread(client_port) #@UnusedVariable
client_thread = self.start_client_thread(client_port) # @UnusedVariable
import time
time.sleep(.3) #let's give it some time to start the threads
time.sleep(.3) # let's give it some time to start the threads
sys.stdout = pydevd_io.IOBuf()
from _pydev_bundle import pydev_localhost

View file

@ -8,12 +8,11 @@ import sys
import unittest
try:
import __builtin__ #@UnusedImport
import __builtin__ # @UnusedImport
BUILTIN_MOD = '__builtin__'
except ImportError:
BUILTIN_MOD = 'builtins'
IS_JYTHON = sys.platform.find('java') != -1
HAS_WX = False
@ -56,6 +55,8 @@ class TestCPython(unittest.TestCase):
'(self, cmp: object, key: object, reverse: bool)',
'(key=None, reverse=False)',
'(self, key=None, reverse=False)',
'(self, cmp, key, reverse)',
'(self, key, reverse)',
)
def test_imports2a(self):
@ -74,7 +75,7 @@ class TestCPython(unittest.TestCase):
def test_imports2c(self):
try:
file # file is not available on py 3
file # file is not available on py 3
except:
pass
else:
@ -120,17 +121,38 @@ class TestCPython(unittest.TestCase):
self.assert_in('RuntimeWarning' , tip)
# Remove cmp as it's not available on py 3
#t = self.assert_in('cmp' , tip)
#self.check_args(t, '(x, y)', '(object x, object y)', '(x: object, y: object)') #args
# t = self.assert_in('cmp' , tip)
# self.check_args(t, '(x, y)', '(object x, object y)', '(x: object, y: object)') #args
t = self.assert_in('isinstance' , tip)
self.check_args(t, '(object, class_or_type_or_tuple)', '(object o, type typeinfo)', '(o: object, typeinfo: type)', '(obj, class_or_tuple)') #args
self.check_args(
t,
'(object, class_or_type_or_tuple)',
'(object o, type typeinfo)',
'(o: object, typeinfo: type)',
'(obj, class_or_tuple)',
'(obj, klass_or_tuple)',
) # args
t = self.assert_in('compile' , tip)
self.check_args(t, '(source, filename, mode)', '()', '(o: object, name: str, val: object)', '(source, filename, mode, flags, dont_inherit, optimize)') #args
self.check_args(
t,
'(source, filename, mode)',
'()',
'(o: object, name: str, val: object)',
'(source, filename, mode, flags, dont_inherit, optimize)',
'(source, filename, mode, flags, dont_inherit)',
) # args
t = self.assert_in('setattr' , tip)
self.check_args(t, '(object, name, value)', '(object o, str name, object val)', '(o: object, name: str, val: object)', '(obj, name, value)') #args
self.check_args(
t,
'(object, name, value)',
'(object o, str name, object val)',
'(o: object, name: str, val: object)',
'(obj, name, value)',
'(object, name, val)',
) # args
try:
import compiler
@ -142,7 +164,7 @@ class TestCPython(unittest.TestCase):
except ImportError:
compiler_module = None
if compiler_module is not None: #Not available in iron python
if compiler_module is not None: # Not available in iron python
tip = _pydev_imports_tipper.generate_tip(compiler_module)
if compiler_module == 'compiler':
self.assert_args('parse', '(buf, mode)', tip)
@ -153,14 +175,12 @@ class TestCPython(unittest.TestCase):
self.assert_args('walk', '(node)', tip)
self.assert_in('parse' , tip)
def check_args(self, t, *expected):
for x in expected:
if x == t[2]:
return
self.fail('Found: %s. Expected: %s' % (t[2], expected))
def assert_args(self, tok, args, tips):
for a in tips[1]:
if tok == a[0]:
@ -174,13 +194,11 @@ class TestCPython(unittest.TestCase):
return a
raise AssertionError('%s not in %s' % (tok, tips))
def test_search(self):
s = _pydev_imports_tipper.search_definition('inspect.ismodule')
(f, line, col), foundAs = s
self.assertTrue(line > 0)
def test_dot_net_libraries(self):
if sys.platform == 'cli':
tip = _pydev_imports_tipper.generate_tip('System.Drawing')
@ -189,10 +207,10 @@ class TestCPython(unittest.TestCase):
tip = _pydev_imports_tipper.generate_tip('System.Drawing.Brushes')
self.assert_in('Aqua' , tip)
def test_inspect(self):
class C(object):
def metA(self, a, b):
pass

View file

@ -3,7 +3,7 @@ import sys
import platform
TEST_CYTHON = os.getenv('PYDEVD_USE_CYTHON', None) == 'YES'
TEST_JYTHON = os.getenv('PYDEVD_TEST_JYTHON', None) == 'YES'
PYDEVD_TEST_VM = os.getenv('PYDEVD_TEST_VM', None)
IS_PY3K = sys.version_info[0] >= 3
IS_PY36_OR_GREATER = sys.version_info[0:2] >= (3, 6)

View file

@ -8,7 +8,7 @@ import pytest
from tests_python import debugger_unittest
from tests_python.debugger_unittest import (get_free_port, overrides, IS_CPYTHON, IS_JYTHON, IS_IRONPYTHON,
IS_PY3K, CMD_ADD_DJANGO_EXCEPTION_BREAK, CMD_REMOVE_DJANGO_EXCEPTION_BREAK,
CMD_ADD_EXCEPTION_BREAK, wait_for_condition)
CMD_ADD_EXCEPTION_BREAK, wait_for_condition, IS_PYPY)
from tests_python.debug_constants import IS_PY2
from _pydevd_bundle.pydevd_comm_constants import file_system_encoding
@ -202,7 +202,7 @@ class DebuggerRunnerSimple(debugger_unittest.DebuggerRunner):
'org.python.util.jython'
]
if IS_CPYTHON:
if IS_CPYTHON or IS_PYPY:
return [sys.executable, '-u']
if IS_IRONPYTHON:

View file

@ -111,6 +111,7 @@ import platform
IS_CPYTHON = platform.python_implementation() == 'CPython'
IS_IRONPYTHON = platform.python_implementation() == 'IronPython'
IS_JYTHON = platform.python_implementation() == 'Jython'
IS_PYPY = platform.python_implementation() == 'PyPy'
IS_APPVEYOR = os.environ.get('APPVEYOR', '') in ('True', 'true', '1')
try:
@ -589,6 +590,7 @@ class AbstractWriterThread(threading.Thread):
'java.lang.UnsupportedOperationException',
"RuntimeWarning: Parent module '_pydevd_bundle' not found while handling absolute import",
'from _pydevd_bundle.pydevd_additional_thread_info_regular import _current_frames',
'from _pydevd_bundle.pydevd_additional_thread_info import _current_frames',
'import org.python.core as PyCore #@UnresolvedImport',
'from _pydevd_bundle.pydevd_additional_thread_info import set_additional_thread_info',
"RuntimeWarning: Parent module '_pydevd_bundle._debug_adapter' not found while handling absolute import",
@ -780,7 +782,12 @@ class AbstractWriterThread(threading.Thread):
# 10 seconds default timeout
timeout = int(os.environ.get('PYDEVD_CONNECT_TIMEOUT', 10))
s.settimeout(timeout)
s.connect((host, port))
for _i in range(6):
try:
s.connect((host, port))
break
except:
time.sleep(.5) # We may have to wait a bit more and retry (especially on PyPy).
s.settimeout(None) # no timeout after connected
if SHOW_WRITES_AND_READS:
print("Connected.")

View file

@ -0,0 +1,53 @@
import threading, atexit, sys
import time
try:
from thread import start_new_thread
except:
from _thread import start_new_thread
class MyError(Exception):
def __init__(self, msg):
return Exception.__init__(self)
def _atexit():
print('TEST SUCEEDED')
sys.stderr.write('TEST SUCEEDED\n')
sys.stderr.flush()
sys.stdout.flush()
# Register the TEST SUCEEDED msg to the exit of the process.
atexit.register(_atexit)
def thread_func():
raise MyError('in thread 1')
start_new_thread(thread_func, ())
# Wait for the first to be handled... otherwise, tests can become flaky if
# both stop at the same time only 1 notification may be given for both, whereas
# the test expects 2 notifications.
time.sleep(.5)
def thread_func2(n):
raise MyError('in thread 2')
th = threading.Thread(target=lambda: thread_func2(1))
th.setDaemon(True)
th.start()
th.join()
# This is a bit tricky: although we waited on the event, there's a slight chance
# that we didn't get the notification because the thread could've stopped executing,
# so, sleep a bit so that the test does not become flaky.
time.sleep(.5)
raise MyError('in main')

View file

@ -6,9 +6,12 @@ import pytest
from _pydevd_frame_eval.pydevd_modify_bytecode import insert_code
from opcode import EXTENDED_ARG
from tests_python.debugger_unittest import IS_PYPY
from _pydevd_bundle.pydevd_constants import IS_PY37_OR_GREATER
TRACE_MESSAGE = "Trace called"
def tracing():
print(TRACE_MESSAGE)
@ -20,10 +23,11 @@ def call_tracing():
def bar(a, b):
return a + b
IS_PY36 = sys.version_info[0] == 3 and sys.version_info[1] == 6
IS_PY36 = sys.version_info[0] == 3 and sys.version_info[1] >= 6
@pytest.mark.skipif(not IS_PY36, reason='Test requires Python 3.6')
@pytest.mark.skipif(not IS_PY36 or IS_PYPY, reason='Test requires Python 3.6 onwards')
class TestInsertCode(unittest.TestCase):
lines_separator = "---Line tested---"
@ -82,7 +86,7 @@ class TestInsertCode(unittest.TestCase):
# Sometimes indexes of variable names and consts may be different, when we insert them, it's ok
continue
else:
self.assertEquals(arg1, arg2, "Different arguments at offset {}".format(of))
self.assertEqual(arg1, arg2, "Different arguments at offset {}".format(of))
def test_line(self):
@ -112,6 +116,7 @@ class TestInsertCode(unittest.TestCase):
sys.stdout = StringIO()
try:
def original():
a = 1
b = 2
@ -127,6 +132,7 @@ class TestInsertCode(unittest.TestCase):
sys.stdout = StringIO()
try:
def original():
n = 3
sum = 0
@ -144,6 +150,7 @@ class TestInsertCode(unittest.TestCase):
sys.stdout = StringIO()
try:
def original():
if True:
a = 1
@ -162,6 +169,7 @@ class TestInsertCode(unittest.TestCase):
sys.stdout = StringIO()
try:
def original():
if False:
a = 1
@ -180,6 +188,7 @@ class TestInsertCode(unittest.TestCase):
sys.stdout = StringIO()
try:
def original():
sum = 0
for i in range(3):
@ -231,6 +240,7 @@ class TestInsertCode(unittest.TestCase):
sys.stdout = StringIO()
try:
def original():
a = 5
b = 0
@ -302,6 +312,7 @@ class TestInsertCode(unittest.TestCase):
sys.stdout = StringIO()
try:
def original():
a = 1
b = 3
@ -338,7 +349,9 @@ class TestInsertCode(unittest.TestCase):
sys.stdout = StringIO()
try:
class A(object):
@staticmethod
def foo():
print("i'm in foo")
@ -362,6 +375,7 @@ class TestInsertCode(unittest.TestCase):
sys.stdout = StringIO()
try:
def foo():
a = 1
b = 2 # breakpoint
@ -428,6 +442,7 @@ class TestInsertCode(unittest.TestCase):
sys.stdout = StringIO()
try:
def foo():
a = 1
b = 1 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23 if a > 1 else 2 if a > 0 else 3 if a > 4 else 23
@ -465,6 +480,7 @@ class TestInsertCode(unittest.TestCase):
finally:
sys.stdout = self.original_stdout
@pytest.mark.skipif(IS_PY37_OR_GREATER, reason='It seems a new minor release of CPython 3.7 broke this (needs to be investigated).')
def test_extended_arg_overflow(self):
from tests_python.resources._bytecode_overflow_example import Dummy, DummyTracing
@ -476,6 +492,7 @@ class TestInsertCode(unittest.TestCase):
sys.stdout = StringIO()
try:
def foo():
a = 1
b = 2
@ -554,7 +571,7 @@ class TestInsertCode(unittest.TestCase):
b = b - 1 if a > 0 else b + 1
b = b - 1 if a > 0 else b + 1
b = b - 1 if a > 0 else b + 1
not tracing() # add 'not' to balance EXTENDED_ARG when jumping
not tracing() # add 'not' to balance EXTENDED_ARG when jumping
b = b - 1 if a > 0 else b + 1
b = b - 1 if a > 0 else b + 1
b = b - 1 if a > 0 else b + 1
@ -571,6 +588,5 @@ class TestInsertCode(unittest.TestCase):
self.check_insert_to_line_by_symbols(foo, call_tracing, foo.__code__.co_firstlineno + 21,
foo_check_2.__code__)
finally:
sys.stdout = self.original_stdout

View file

@ -4,7 +4,7 @@ import sys
import traceback
from _pydevd_bundle.pydevd_collect_try_except_info import collect_try_except_info
from tests_python.debugger_unittest import IS_CPYTHON
from tests_python.debugger_unittest import IS_CPYTHON, IS_PYPY
def _method_call_with_error():
@ -189,7 +189,7 @@ def test_collect_try_except_info2():
code = method.__code__
lst = collect_try_except_info(code, use_func_first_line=True)
if IS_CPYTHON:
if IS_CPYTHON or IS_PYPY:
assert str(lst) == '[{try:1 except 3 end block 5 raises: 5}]'
else:
assert lst == []

View file

@ -17,7 +17,7 @@ from tests_python.debugger_unittest import (CMD_SET_PROPERTY_TRACE, REASON_CAUGH
IS_APPVEYOR, wait_for_condition, CMD_GET_FRAME, CMD_GET_BREAKPOINT_EXCEPTION,
CMD_THREAD_SUSPEND, CMD_STEP_OVER, REASON_STEP_OVER, CMD_THREAD_SUSPEND_SINGLE_NOTIFICATION,
CMD_THREAD_RESUME_SINGLE_NOTIFICATION, REASON_STEP_RETURN, REASON_STEP_RETURN_MY_CODE,
REASON_STEP_OVER_MY_CODE, REASON_STEP_INTO, CMD_THREAD_KILL)
REASON_STEP_OVER_MY_CODE, REASON_STEP_INTO, CMD_THREAD_KILL, IS_PYPY)
from _pydevd_bundle.pydevd_constants import IS_WINDOWS
from _pydevd_bundle.pydevd_comm_constants import CMD_RELOAD_CODE
import json
@ -46,7 +46,7 @@ else:
builtin_qualifier = "builtins"
@pytest.mark.skipif(IS_IRONPYTHON or IS_JYTHON, reason='Test needs gc.get_referrers to really check anything.')
@pytest.mark.skipif(not IS_CPYTHON, reason='Test needs gc.get_referrers/reference counting to really check anything.')
def test_case_referrers(case_setup):
with case_setup.test_file('_debugger_case1.py') as writer:
writer.log.append('writing add breakpoint')
@ -123,21 +123,26 @@ def test_case_2(case_setup):
[['ValueError'], ['Exception']],
[['Exception'], ['ValueError']], # ValueError will also suspend/print since we're dealing with a NameError
)
)
)
def test_case_breakpoint_condition_exc(case_setup, skip_suspend_on_breakpoint_exception, skip_print_breakpoint_exception):
msgs_in_stderr = (
'Error while evaluating expression: i > 5',
"NameError: name 'i' is not defined",
'Traceback (most recent call last):',
'File "<string>", line 1, in <module>',
)
# It could be one or the other in PyPy depending on the version.
msgs_one_in_stderr = (
"NameError: name 'i' is not defined",
"global name 'i' is not defined",
)
def _ignore_stderr_line(line):
if original_ignore_stderr_line(line):
return True
for msg in msgs_in_stderr:
for msg in msgs_in_stderr + msgs_one_in_stderr:
if msg in line:
return True
@ -148,8 +153,15 @@ def test_case_breakpoint_condition_exc(case_setup, skip_suspend_on_breakpoint_ex
if skip_print_breakpoint_exception in ([], ['ValueError']):
for msg in msgs_in_stderr:
assert msg in stderr
for msg in msgs_one_in_stderr:
if msg in stderr:
break
else:
raise AssertionError('Did not find any of: %s in stderr: %s' % (
msgs_one_in_stderr, stderr))
else:
for msg in msgs_in_stderr:
for msg in msgs_in_stderr + msgs_one_in_stderr:
assert msg not in stderr
with case_setup.test_file('_debugger_case_breakpoint_condition_exc.py') as writer:
@ -2862,7 +2874,7 @@ def test_custom_frames(case_setup):
writer.finished_ok = True
@pytest.mark.skipif((not (IS_PY36 or IS_PY27)) or IS_JYTHON, reason='Gevent only installed on Py36/Py27 for tests.')
@pytest.mark.skipif((not (IS_PY36 or IS_PY27)) or IS_JYTHON or IS_PYPY, reason='Gevent only installed on Py36/Py27 for tests.')
def test_gevent(case_setup):
def get_environ(writer):

View file

@ -478,19 +478,23 @@ def test_case_handled_exception_breaks(case_setup):
writer.finished_ok = True
def test_case_unhandled_exception(case_setup):
@pytest.mark.parametrize('target_file', [
'_debugger_case_unhandled_exceptions.py',
'_debugger_case_unhandled_exceptions_custom.py'
])
def test_case_unhandled_exception(case_setup, target_file):
def check_test_suceeded_msg(writer, stdout, stderr):
# Don't call super (we have an unhandled exception in the stack trace).
return 'TEST SUCEEDED' in ''.join(stdout) and 'TEST SUCEEDED' in ''.join(stderr)
def additional_output_checks(writer, stdout, stderr):
if 'raise Exception' not in stderr:
if 'raise MyError' not in stderr and 'raise Exception' not in stderr:
raise AssertionError('Expected test to have an unhandled exception.\nstdout:\n%s\n\nstderr:\n%s' % (
stdout, stderr))
with case_setup.test_file(
'_debugger_case_unhandled_exceptions.py',
target_file,
check_test_suceeded_msg=check_test_suceeded_msg,
additional_output_checks=additional_output_checks,
EXPECTED_RETURNCODE=1,
@ -505,15 +509,15 @@ def test_case_unhandled_exception(case_setup):
line_in_thread2 = writer.get_line_index_with_content('in thread 2')
line_in_main = writer.get_line_index_with_content('in main')
json_facade.wait_for_thread_stopped(
reason='exception', line=(line_in_thread1, line_in_thread2), file='_debugger_case_unhandled_exceptions.py')
reason='exception', line=(line_in_thread1, line_in_thread2), file=target_file)
json_facade.write_continue()
json_facade.wait_for_thread_stopped(
reason='exception', line=(line_in_thread1, line_in_thread2), file='_debugger_case_unhandled_exceptions.py')
reason='exception', line=(line_in_thread1, line_in_thread2), file=target_file)
json_facade.write_continue()
json_facade.wait_for_thread_stopped(
reason='exception', line=line_in_main, file='_debugger_case_unhandled_exceptions.py')
reason='exception', line=line_in_main, file=target_file)
json_facade.write_continue(wait_for_response=False)
writer.finished_ok = True

View file

@ -8,4 +8,4 @@ def test_dump_threads():
pydevd.dump_threads(stream=stream)
contents = stream.getvalue()
assert 'Thread MainThread (daemon: False, pydevd thread: False)' in contents
assert 'test_dump_threads' in contents
assert 'test_dump_threads' in contents

View file

@ -26,7 +26,7 @@ class Test(unittest.TestCase):
def _do_analyze(self, files):
invalid_files = []
p = subprocess.Popen(["python", self._coverage_file, "--pydev-analyze"],
p = subprocess.Popen([sys.executable, self._coverage_file, "--pydev-analyze"],
stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
__, stderrdata = p.communicate("|".join(files).encode())