mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Added Python 3.7 support and fixed issues related to Jython on Travis. (#692)
This commit is contained in:
parent
75e53eed24
commit
e5027cb5a5
30 changed files with 495 additions and 184 deletions
|
|
@ -2,39 +2,78 @@ language: python
|
|||
|
||||
matrix:
|
||||
include:
|
||||
# Python 2.6 (with and without cython)
|
||||
- python: 2.6
|
||||
env: PYDEVD_USE_CYTHON=YES
|
||||
env: PYDEVD_TEST_JYTHON=NO
|
||||
- python: 2.6
|
||||
env: PYDEVD_USE_CYTHON=NO
|
||||
env: PYDEVD_TEST_JYTHON=NO
|
||||
# Python 2.7 (with and without cython)
|
||||
- python: 2.7
|
||||
env: PYDEVD_USE_CYTHON=YES
|
||||
env: PYDEVD_TEST_JYTHON=NO
|
||||
- python: 2.7
|
||||
env: PYDEVD_USE_CYTHON=NO
|
||||
env: PYDEVD_TEST_JYTHON=NO
|
||||
# Python 3.5 (with and without cython)
|
||||
- python: 3.5
|
||||
env: PYDEVD_USE_CYTHON=YES
|
||||
env: PYDEVD_TEST_JYTHON=NO
|
||||
- python: 3.5
|
||||
env: PYDEVD_USE_CYTHON=NO
|
||||
env: PYDEVD_TEST_JYTHON=NO
|
||||
# Python 3.6 (with and without cython)
|
||||
- python: 3.6
|
||||
env: PYDEVD_USE_CYTHON=YES
|
||||
env: PYDEVD_TEST_JYTHON=NO
|
||||
- python: 3.6
|
||||
env: PYDEVD_USE_CYTHON=NO
|
||||
env: PYDEVD_TEST_JYTHON=NO
|
||||
# Note: python is always 2.7 because it's the installed version
|
||||
# in the travis system (so, faster to startup).
|
||||
# We'll always use conda later on anyways to get what we want.
|
||||
|
||||
# Note: some envs commented out to have a faster test suite.
|
||||
|
||||
# Jython
|
||||
- python: 2.7
|
||||
env: PYDEVD_USE_CYTHON=NO
|
||||
env: PYDEVD_TEST_JYTHON=YES
|
||||
env: JYTHON_URL=http://search.maven.org/remotecontent?filepath=org/python/jython-installer/2.7.0/jython-installer-2.7.0.jar
|
||||
env:
|
||||
- PYDEVD_USE_CYTHON=NO
|
||||
- PYDEVD_TEST_JYTHON=YES
|
||||
- JYTHON_URL=http://search.maven.org/remotecontent?filepath=org/python/jython-installer/2.7.0/jython-installer-2.7.0.jar
|
||||
|
||||
# Python 2.6 (with and without cython)
|
||||
# - python: 2.7
|
||||
# env:
|
||||
# - PYDEVD_PYTHON_VERSION=2.6
|
||||
# - PYDEVD_USE_CYTHON=NO
|
||||
# - PYDEVD_TEST_JYTHON=NO
|
||||
- python: 2.7
|
||||
env:
|
||||
- PYDEVD_PYTHON_VERSION=2.6
|
||||
- PYDEVD_USE_CYTHON=YES
|
||||
- PYDEVD_TEST_JYTHON=NO
|
||||
|
||||
# Python 2.7 (with and without cython)
|
||||
- python: 2.7
|
||||
env:
|
||||
- PYDEVD_PYTHON_VERSION=2.7
|
||||
- PYDEVD_USE_CYTHON=NO
|
||||
- PYDEVD_TEST_JYTHON=NO
|
||||
- python: 2.7
|
||||
env:
|
||||
- PYDEVD_PYTHON_VERSION=2.7
|
||||
- PYDEVD_USE_CYTHON=YES
|
||||
- PYDEVD_TEST_JYTHON=NO
|
||||
|
||||
# Python 3.5 (with and without cython)
|
||||
# - python: 2.7
|
||||
# env:
|
||||
# - PYDEVD_PYTHON_VERSION=3.5
|
||||
# - PYDEVD_USE_CYTHON=NO
|
||||
# - PYDEVD_TEST_JYTHON=NO
|
||||
- python: 2.7
|
||||
env:
|
||||
- PYDEVD_PYTHON_VERSION=3.5
|
||||
- PYDEVD_USE_CYTHON=YES
|
||||
- PYDEVD_TEST_JYTHON=NO
|
||||
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
before_install:
|
||||
# CPython setup
|
||||
|
|
@ -57,19 +96,21 @@ install:
|
|||
# Both
|
||||
- export PYTHONPATH=.
|
||||
# Python setup
|
||||
- if [ "$PYDEVD_TEST_JYTHON" = "NO" ]; then conda create --yes -n build_env python=$TRAVIS_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 python build_tools/build.py; fi
|
||||
- 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
|
||||
# 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_JYTHON" == "YES" ]; then chmod +x ./.travis_install_jython_deps.sh; fi
|
||||
- if [ "$PYDEVD_TEST_JYTHON" == "YES" ]; 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:
|
||||
- if [ "$PYDEVD_TEST_JYTHON" = "NO" ]; then python -m pytest; fi
|
||||
- if [ "$PYDEVD_TEST_JYTHON" = "YES" ]; then jython -Dpython.path=.:jython_test_deps/ant.jar:jython_test_deps/junit.jar -m pytest; fi
|
||||
# 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
|
||||
|
||||
|
|
|
|||
|
|
@ -2,3 +2,5 @@
|
|||
set -ev
|
||||
|
||||
pip install pytest
|
||||
pip install pytest-xdist
|
||||
pip install untangle
|
||||
|
|
@ -1,21 +1,28 @@
|
|||
#!/bin/bash
|
||||
set -ev
|
||||
|
||||
conda install --yes numpy ipython cython pytest psutil
|
||||
source activate build_env
|
||||
conda install --yes numpy ipython pytest cython psutil
|
||||
|
||||
if [ "$TRAVIS_PYTHON_VERSION" = "2.6" ]; then
|
||||
if [ "$PYDEVD_PYTHON_VERSION" = "2.6" ]; then
|
||||
conda install --yes pyqt=4
|
||||
# Django 1.7 does not support Python 2.7
|
||||
else
|
||||
# pytest-xdist not available for python 2.6
|
||||
pip install pytest-xdist
|
||||
fi
|
||||
if [ "$TRAVIS_PYTHON_VERSION" = "2.7" ]; then
|
||||
|
||||
if [ "$PYDEVD_PYTHON_VERSION" = "2.7" ]; then
|
||||
conda install --yes pyqt=4
|
||||
pip install "django>=1.7,<1.8"
|
||||
|
||||
fi
|
||||
if [ "$TRAVIS_PYTHON_VERSION" = "3.5" ]; then
|
||||
|
||||
if [ "$PYDEVD_PYTHON_VERSION" = "3.5" ]; then
|
||||
conda install --yes pyqt=5
|
||||
pip install "django>=1.7,<1.8"
|
||||
fi
|
||||
|
||||
pip install Pympler
|
||||
pip install pytest
|
||||
pip install untangle
|
||||
pip install scapy==2.4.0
|
||||
|
|
@ -6,13 +6,19 @@ from _pydev_bundle._pydev_tipper_common import do_find
|
|||
from _pydevd_bundle.pydevd_constants import IS_PY2
|
||||
|
||||
if IS_PY2:
|
||||
from inspect import getargspec
|
||||
from inspect import getargspec as _originalgetargspec
|
||||
def getargspec(*args, **kwargs):
|
||||
ret = list(_originalgetargspec(*args, **kwargs))
|
||||
ret.append([])
|
||||
ret.append({})
|
||||
return ret
|
||||
|
||||
else:
|
||||
from inspect import getfullargspec
|
||||
|
||||
def getargspec(*args, **kwargs):
|
||||
arg_spec = getfullargspec(*args, **kwargs)
|
||||
return arg_spec.args, arg_spec.varargs, arg_spec.varkw, arg_spec.defaults
|
||||
return arg_spec.args, arg_spec.varargs, arg_spec.varkw, arg_spec.defaults, arg_spec.kwonlyargs or [], arg_spec.kwonlydefaults or {}
|
||||
|
||||
try:
|
||||
xrange
|
||||
|
|
@ -150,13 +156,15 @@ def check_char(c):
|
|||
return '_'
|
||||
return c
|
||||
|
||||
_SENTINEL = object()
|
||||
|
||||
def generate_imports_tip_for_module(obj_to_complete, dir_comps=None, getattr=getattr, filter=lambda name:True):
|
||||
'''
|
||||
@param obj_to_complete: the object from where we should get the completions
|
||||
@param dir_comps: if passed, we should not 'dir' the object and should just iterate those passed as a parameter
|
||||
@param getattr: the way to get a given object from the obj_to_complete (used for the completer)
|
||||
@param filter: a callable that receives the name and decides if it should be appended or not to the results
|
||||
@return: list of tuples, so that each tuple represents a completion with:
|
||||
@param dir_comps: if passed, we should not 'dir' the object and should just iterate those passed as kwonly_arg parameter
|
||||
@param getattr: the way to get kwonly_arg given object from the obj_to_complete (used for the completer)
|
||||
@param filter: kwonly_arg callable that receives the name and decides if it should be appended or not to the results
|
||||
@return: list of tuples, so that each tuple represents kwonly_arg completion with:
|
||||
name, doc, args, type (from the TYPE_* constants)
|
||||
'''
|
||||
ret = []
|
||||
|
|
@ -222,14 +230,18 @@ def generate_imports_tip_for_module(obj_to_complete, dir_comps=None, getattr=get
|
|||
|
||||
if inspect.ismethod(obj) or inspect.isbuiltin(obj) or inspect.isfunction(obj) or inspect.isroutine(obj):
|
||||
try:
|
||||
args, vargs, kwargs, defaults = getargspec(obj)
|
||||
args, vargs, kwargs, defaults, kwonly_args, kwonly_defaults = getargspec(obj)
|
||||
|
||||
r = ''
|
||||
for a in (args):
|
||||
if len(r) > 0:
|
||||
r = r + ', '
|
||||
r = r + str(a)
|
||||
args = '(%s)' % (r)
|
||||
args = args[:]
|
||||
|
||||
for kwonly_arg in kwonly_args:
|
||||
default = kwonly_defaults.get(kwonly_arg, _SENTINEL)
|
||||
if default is not _SENTINEL:
|
||||
args.append('%s=%s' % (kwonly_arg, default))
|
||||
else:
|
||||
args.append(str(kwonly_arg))
|
||||
|
||||
args = '(%s)' % (', '.join(args))
|
||||
except TypeError:
|
||||
#ok, let's see if we can get the arguments from the doc
|
||||
args, doc = signature_from_docstring(doc, getattr(obj, '__name__', None))
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ elif hasattr(_temp, '_Thread__stopped'): # Python 2.x has this
|
|||
return not t._Thread__stopped
|
||||
|
||||
else:
|
||||
# Make it an error: we want to detect only stops (so, isAlive() can't be used because it may return True before the
|
||||
# thread is actually running).
|
||||
raise AssertionError('Check how to detect that a thread has been stopped.')
|
||||
# Jython wraps a native java thread and thus only obeys the public API.
|
||||
def is_thread_alive(t):
|
||||
return t.isAlive()
|
||||
|
||||
del _temp
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import os
|
|||
import sys
|
||||
import traceback
|
||||
from _pydev_imps._pydev_saved_modules import threading
|
||||
from _pydevd_bundle.pydevd_constants import get_thread_id, get_global_debugger
|
||||
from _pydevd_bundle.pydevd_constants import get_thread_id, get_global_debugger, IS_WINDOWS, IS_JYTHON
|
||||
from _pydev_bundle import pydev_log
|
||||
|
||||
try:
|
||||
|
|
@ -534,20 +534,21 @@ def patch_new_process_functions():
|
|||
monkey_patch_os('spawnvp', create_spawnv)
|
||||
monkey_patch_os('spawnvpe', create_spawnve)
|
||||
|
||||
if sys.platform != 'win32':
|
||||
monkey_patch_os('fork', create_fork)
|
||||
try:
|
||||
import _posixsubprocess
|
||||
monkey_patch_module(_posixsubprocess, 'fork_exec', create_fork_exec)
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
# Windows
|
||||
try:
|
||||
import _subprocess
|
||||
except ImportError:
|
||||
import _winapi as _subprocess
|
||||
monkey_patch_module(_subprocess, 'CreateProcess', create_CreateProcess)
|
||||
if not IS_JYTHON:
|
||||
if not IS_WINDOWS:
|
||||
monkey_patch_os('fork', create_fork)
|
||||
try:
|
||||
import _posixsubprocess
|
||||
monkey_patch_module(_posixsubprocess, 'fork_exec', create_fork_exec)
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
# Windows
|
||||
try:
|
||||
import _subprocess
|
||||
except ImportError:
|
||||
import _winapi as _subprocess
|
||||
monkey_patch_module(_subprocess, 'CreateProcess', create_CreateProcess)
|
||||
|
||||
|
||||
def patch_new_process_functions_with_warning():
|
||||
|
|
@ -568,20 +569,21 @@ def patch_new_process_functions_with_warning():
|
|||
monkey_patch_os('spawnvp', create_warn_multiproc)
|
||||
monkey_patch_os('spawnvpe', create_warn_multiproc)
|
||||
|
||||
if sys.platform != 'win32':
|
||||
monkey_patch_os('fork', create_warn_multiproc)
|
||||
try:
|
||||
import _posixsubprocess
|
||||
monkey_patch_module(_posixsubprocess, 'fork_exec', create_warn_fork_exec)
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
# Windows
|
||||
try:
|
||||
import _subprocess
|
||||
except ImportError:
|
||||
import _winapi as _subprocess
|
||||
monkey_patch_module(_subprocess, 'CreateProcess', create_CreateProcessWarnMultiproc)
|
||||
if not IS_JYTHON:
|
||||
if not IS_WINDOWS:
|
||||
monkey_patch_os('fork', create_warn_multiproc)
|
||||
try:
|
||||
import _posixsubprocess
|
||||
monkey_patch_module(_posixsubprocess, 'fork_exec', create_warn_fork_exec)
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
# Windows
|
||||
try:
|
||||
import _subprocess
|
||||
except ImportError:
|
||||
import _winapi as _subprocess
|
||||
monkey_patch_module(_subprocess, 'CreateProcess', create_CreateProcessWarnMultiproc)
|
||||
|
||||
|
||||
class _NewThreadStartupWithTrace:
|
||||
|
|
@ -660,6 +662,8 @@ def patch_thread_module(thread_module):
|
|||
|
||||
if getattr(thread_module, '_original_start_new_thread', None) is None:
|
||||
if thread_module is threading:
|
||||
if not hasattr(thread_module, '_start_new_thread'):
|
||||
return # Jython doesn't have it.
|
||||
_original_start_new_thread = thread_module._original_start_new_thread = thread_module._start_new_thread
|
||||
else:
|
||||
_original_start_new_thread = thread_module._original_start_new_thread = thread_module.start_new_thread
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@ try:
|
|||
import Queue
|
||||
except:
|
||||
import queue as Queue #@UnresolvedImport
|
||||
from _pydevd_bundle.pydevd_constants import * #@UnusedWildImport
|
||||
from _pydev_runfiles import pydev_runfiles_xml_rpc
|
||||
import time
|
||||
import os
|
||||
import threading
|
||||
import sys
|
||||
|
||||
#=======================================================================================================================
|
||||
# flatten_test_suite
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
from _pydevd_bundle.pydevd_constants import * #@UnusedWildImport
|
||||
from _pydev_bundle.pydev_imports import xmlrpclib, _queue
|
||||
Queue = _queue.Queue
|
||||
import traceback
|
||||
import sys
|
||||
from _pydev_runfiles.pydev_runfiles_coverage import start_coverage_support_from_params
|
||||
|
||||
import threading
|
||||
|
||||
|
||||
#=======================================================================================================================
|
||||
|
|
|
|||
|
|
@ -254,6 +254,8 @@ def report_test(status, filename, test, captured_output, error_contents, duratio
|
|||
pydev_runfiles_xml_rpc.notifyTest(
|
||||
status, captured_output, error_contents, filename, test, time_str)
|
||||
|
||||
if not hasattr(pytest, 'hookimpl'):
|
||||
raise AssertionError('Please upgrade pytest (the current version of pytest: %s is unsupported)' % (pytest.__version__,))
|
||||
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
|
|
|
|||
|
|
@ -48,9 +48,15 @@ import os
|
|||
|
||||
from _pydevd_bundle import pydevd_vm_type
|
||||
|
||||
# Constant detects when running on Jython/windows properly later on.
|
||||
IS_WINDOWS = sys.platform == 'win32'
|
||||
|
||||
IS_JYTHON = pydevd_vm_type.get_vm_type() == pydevd_vm_type.PydevdVmType.JYTHON
|
||||
IS_JYTH_LESS25 = False
|
||||
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
from _pydevd_bundle.pydevd_comm import get_global_debugger
|
||||
from _pydevd_bundle.pydevd_constants import DebugInfoHolder, IS_PY2
|
||||
import pydevd_tracing
|
||||
import traceback
|
||||
|
||||
#=======================================================================================================================
|
||||
# replace_builtin_property
|
||||
|
|
@ -17,14 +18,14 @@ def replace_builtin_property(new_property=None):
|
|||
__builtin__.__dict__['property'] = new_property
|
||||
except:
|
||||
if DebugInfoHolder.DEBUG_TRACE_LEVEL:
|
||||
import traceback;traceback.print_exc() #@Reimport
|
||||
traceback.print_exc() #@Reimport
|
||||
else:
|
||||
try:
|
||||
import builtins #Python 3.0 does not have the __builtin__ module @UnresolvedImport
|
||||
builtins.__dict__['property'] = new_property
|
||||
except:
|
||||
if DebugInfoHolder.DEBUG_TRACE_LEVEL:
|
||||
import traceback;traceback.print_exc() #@Reimport
|
||||
traceback.print_exc() #@Reimport
|
||||
return original
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -324,12 +324,14 @@ def dump_threads(stream=None):
|
|||
t.name, t.daemon, getattr(t, 'is_pydev_daemon_thread', False))
|
||||
except:
|
||||
pass
|
||||
|
||||
from _pydevd_bundle.pydevd_additional_thread_info_regular import _current_frames
|
||||
|
||||
stream.write('===============================================================================\n')
|
||||
stream.write('Threads running\n')
|
||||
stream.write('================================= Thread Dump =================================\n')
|
||||
|
||||
for thread_id, stack in sys._current_frames().items():
|
||||
for thread_id, stack in _current_frames().items():
|
||||
stream.write('\n-------------------------------------------------------------------------------\n')
|
||||
stream.write(" Thread %s" % thread_id_to_name.get(thread_id, thread_id))
|
||||
stream.write('\n\n')
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ environment:
|
|||
# http://www.appveyor.com/docs/installed-software#python
|
||||
# The list here is complete (excluding Python 2.6, which
|
||||
# isn't covered by this document) at the time of writing.
|
||||
|
||||
# Note: some envs commented out to have a faster test suite.
|
||||
|
||||
- PYTHON_FOLDER: "C:\\Python27"
|
||||
PYDEVD_USE_CYTHON: YES
|
||||
|
|
@ -23,12 +25,17 @@ environment:
|
|||
|
||||
- PYTHON_FOLDER: "C:\\Python35-x64"
|
||||
PYDEVD_USE_CYTHON: YES
|
||||
- PYTHON_FOLDER: "C:\\Python35-x64"
|
||||
# - PYTHON_FOLDER: "C:\\Python35-x64"
|
||||
# PYDEVD_USE_CYTHON: NO
|
||||
|
||||
# - PYTHON_FOLDER: "C:\\Python36-x64"
|
||||
# PYDEVD_USE_CYTHON: YES
|
||||
- PYTHON_FOLDER: "C:\\Python36-x64"
|
||||
PYDEVD_USE_CYTHON: NO
|
||||
|
||||
- PYTHON_FOLDER: "C:\\Python36-x64"
|
||||
- PYTHON_FOLDER: "C:\\Python37-x64"
|
||||
PYDEVD_USE_CYTHON: YES
|
||||
- PYTHON_FOLDER: "C:\\Python36-x64"
|
||||
- PYTHON_FOLDER: "C:\\Python37-x64"
|
||||
PYDEVD_USE_CYTHON: NO
|
||||
|
||||
# Disable IronPython tests (must be investigated in appveyor).
|
||||
|
|
@ -44,20 +51,18 @@ install:
|
|||
- cmd: IF "%TEST_IRONPYTHON%"=="YES" (7z x ironpython.zip -oironpython)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="YES" (ironpython\IronPython-2.7.5\ipy.exe -X:Frames -X:ExceptionDetail -X:ShowClrExceptions -m ensurepip)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="YES" (ironpython\IronPython-2.7.5\ipy.exe -X:Frames -X:ExceptionDetail -X:ShowClrExceptions -m pip install pytest)
|
||||
- ps: |
|
||||
if ($env:TEST_IRONPYTHON -ne "YES"){
|
||||
$PYTHON_EXE = $Env:PYTHON_EXE
|
||||
& $PYTHON_EXE -m pip install --upgrade pip
|
||||
& $PYTHON_EXE -m pip install wheel --no-warn-script-location
|
||||
& $PYTHON_EXE -m pip install cython --no-warn-script-location
|
||||
& $PYTHON_EXE -m pip install numpy
|
||||
& $PYTHON_EXE -m pip install pytest --no-warn-script-location
|
||||
& $PYTHON_EXE -m pip install psutil
|
||||
& $PYTHON_EXE -m pip install ipython --no-warn-script-location
|
||||
if ($env:PYTHON -eq "C:\\Python27"){
|
||||
"%PYTHON%\\python.exe -m pip install django>=1.7,<1.8"
|
||||
}
|
||||
}
|
||||
# Regular python:
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pip install --upgrade pip)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pip install wheel --no-warn-script-location)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pip install cython --no-warn-script-location)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pip install numpy)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pip install pytest --no-warn-script-location)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pip install pytest-xdist --no-warn-script-location)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pip install psutil)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pip install ipython --no-warn-script-location)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pip install untangle --no-warn-script-location)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" IF %PYTHON_FOLDER%=="C:\\Python27" (%PYTHON_EXE% -m pip install django>=1.7,<1.8)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pip install scapy==2.4.0 --no-warn-script-location)
|
||||
- cmd: "set PYTHONPATH=%PYTHONPATH%;%APPVEYOR_BUILD_FOLDER%"
|
||||
|
||||
build_script:
|
||||
|
|
@ -65,7 +70,7 @@ build_script:
|
|||
|
||||
test_script:
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="YES" (ironpython\IronPython-2.7.5\ipy.exe -X:Frames -X:ExceptionDetail -X:ShowClrExceptions -m pytest --assert=plain -k "not samples")
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pytest)
|
||||
- cmd: IF "%TEST_IRONPYTHON%"=="" (%PYTHON_EXE% -m pytest -n auto)
|
||||
|
||||
artifacts:
|
||||
# bdist_wheel puts your built wheel in the dist directory
|
||||
|
|
|
|||
|
|
@ -8,6 +8,80 @@ from tests_python.debug_constants import TEST_JYTHON
|
|||
def pytest_report_header(config):
|
||||
print('PYDEVD_USE_CYTHON: %s' % (TEST_CYTHON,))
|
||||
print('PYDEVD_TEST_JYTHON: %s' % (TEST_JYTHON,))
|
||||
try:
|
||||
import multiprocessing
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
print('Number of processors: %s' % (multiprocessing.cpu_count(),))
|
||||
|
||||
|
||||
_started_monitoring_threads = False
|
||||
|
||||
|
||||
def _start_monitoring_threads():
|
||||
# After the session finishes, wait 20 seconds to see if everything finished properly
|
||||
# and if it doesn't report an error.
|
||||
global _started_monitoring_threads
|
||||
if _started_monitoring_threads:
|
||||
return
|
||||
|
||||
_started_monitoring_threads = True
|
||||
import threading
|
||||
if hasattr(sys, '_current_frames') and hasattr(threading, 'enumerate'):
|
||||
import time
|
||||
import traceback
|
||||
|
||||
class DumpThreads(threading.Thread):
|
||||
|
||||
def run(self):
|
||||
time.sleep(20)
|
||||
|
||||
thread_id_to_name = {}
|
||||
try:
|
||||
for t in threading.enumerate():
|
||||
thread_id_to_name[t.ident] = '%s (daemon: %s)' % (t.name, t.daemon)
|
||||
except:
|
||||
pass
|
||||
|
||||
stack_trace = [
|
||||
'===============================================================================',
|
||||
'pydev pyunit runner: Threads still found running after tests finished',
|
||||
'================================= Thread Dump =================================']
|
||||
|
||||
for thread_id, stack in sys._current_frames().items():
|
||||
stack_trace.append('\n-------------------------------------------------------------------------------')
|
||||
stack_trace.append(" Thread %s" % thread_id_to_name.get(thread_id, thread_id))
|
||||
stack_trace.append('')
|
||||
|
||||
if 'self' in stack.f_locals:
|
||||
sys.stderr.write(str(stack.f_locals['self']) + '\n')
|
||||
|
||||
for filename, lineno, name, line in traceback.extract_stack(stack):
|
||||
stack_trace.append(' File "%s", line %d, in %s' % (filename, lineno, name))
|
||||
if line:
|
||||
stack_trace.append(" %s" % (line.strip()))
|
||||
stack_trace.append('\n=============================== END Thread Dump ===============================')
|
||||
sys.stderr.write('\n'.join(stack_trace))
|
||||
|
||||
# Force thread run to finish
|
||||
import os
|
||||
os._exit(123)
|
||||
|
||||
dump_current_frames_thread = DumpThreads()
|
||||
dump_current_frames_thread.setDaemon(True) # Daemon so that this thread doesn't halt it!
|
||||
dump_current_frames_thread.start()
|
||||
|
||||
|
||||
def pytest_unconfigure():
|
||||
_start_monitoring_threads()
|
||||
|
||||
|
||||
@pytest.yield_fixture(scope="session", autouse=True)
|
||||
def check_no_threads():
|
||||
yield
|
||||
_start_monitoring_threads()
|
||||
|
||||
|
||||
# see: http://goo.gl/kTQMs
|
||||
SYMBOLS = {
|
||||
|
|
@ -19,6 +93,7 @@ SYMBOLS = {
|
|||
'zebi', 'yobi'),
|
||||
}
|
||||
|
||||
|
||||
def bytes2human(n, format='%(value).1f %(symbol)s', symbols='customary'):
|
||||
"""
|
||||
Bytes-to-human / human-to-bytes converter.
|
||||
|
|
@ -71,24 +146,28 @@ def bytes2human(n, format='%(value).1f %(symbol)s', symbols='customary'):
|
|||
symbols = SYMBOLS[symbols]
|
||||
prefix = {}
|
||||
for i, s in enumerate(symbols[1:]):
|
||||
prefix[s] = 1 << (i+1)*10
|
||||
prefix[s] = 1 << (i + 1) * 10
|
||||
for symbol in reversed(symbols[1:]):
|
||||
if n >= prefix[symbol]:
|
||||
value = float(n) / prefix[symbol]
|
||||
return format % locals()
|
||||
return format % dict(symbol=symbols[0], value=n)
|
||||
|
||||
|
||||
def format_memory_info(memory_info, curr_proc_memory_info):
|
||||
return 'Total: %s, Available: %s, Used: %s %%, Curr process: %s' % (
|
||||
bytes2human(memory_info.total), bytes2human(memory_info.available), memory_info.percent, format_process_memory_info(curr_proc_memory_info))
|
||||
|
||||
|
||||
def format_process_memory_info(proc_memory_info):
|
||||
return bytes2human(proc_memory_info.rss)
|
||||
|
||||
|
||||
DEBUG_MEMORY_INFO = False
|
||||
|
||||
_global_collect_info = False
|
||||
|
||||
|
||||
@pytest.yield_fixture(autouse=True)
|
||||
def before_after_each_function(request):
|
||||
global _global_collect_info
|
||||
|
|
@ -160,10 +239,12 @@ Memory after: %s
|
|||
''' % (
|
||||
request.function,
|
||||
format_memory_info(psutil.virtual_memory(), after_curr_proc_memory_info),
|
||||
'' if not processes_info else '\nLeaked processes:\n'+'\n'.join(processes_info)),
|
||||
'' if not processes_info else '\nLeaked processes:\n' + '\n'.join(processes_info)),
|
||||
)
|
||||
|
||||
|
||||
if IS_JYTHON or IS_IRONPYTHON:
|
||||
|
||||
# On Jython and IronPython, it's a no-op.
|
||||
def before_after_each_function():
|
||||
pass
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ r'''
|
|||
machine for the paths that'll actually have breakpoints).
|
||||
'''
|
||||
|
||||
from _pydevd_bundle.pydevd_constants import IS_PY2, IS_PY3K, DebugInfoHolder
|
||||
from _pydevd_bundle.pydevd_constants import IS_PY2, IS_PY3K, DebugInfoHolder, IS_WINDOWS, IS_JYTHON
|
||||
from _pydev_bundle._pydev_filesystem_encoding import getfilesystemencoding
|
||||
import json
|
||||
import os.path
|
||||
|
|
@ -144,24 +144,40 @@ if sys.platform == 'win32':
|
|||
convert_to_long_pathname = _convert_to_long_pathname
|
||||
convert_to_short_pathname = _convert_to_short_pathname
|
||||
get_path_with_real_case = _get_path_with_real_case
|
||||
|
||||
elif IS_JYTHON and IS_WINDOWS:
|
||||
def get_path_with_real_case(filename):
|
||||
from java.io import File
|
||||
f = File(filename)
|
||||
ret = f.getCanonicalPath()
|
||||
if IS_PY2 and not isinstance(ret, str):
|
||||
return ret.encode(getfilesystemencoding())
|
||||
return ret
|
||||
|
||||
|
||||
if sys.platform == 'win32':
|
||||
if IS_WINDOWS:
|
||||
|
||||
def normcase(filename):
|
||||
# `normcase` doesn't lower case on Python 2 for non-English locale, but Java
|
||||
# side does it, so we should do it manually.
|
||||
if '~' in filename:
|
||||
filename = convert_to_long_pathname(filename)
|
||||
if IS_JYTHON:
|
||||
def normcase(filename):
|
||||
return filename.lower()
|
||||
|
||||
else:
|
||||
|
||||
filename = _os_normcase(filename)
|
||||
return filename.lower()
|
||||
def normcase(filename):
|
||||
# `normcase` doesn't lower case on Python 2 for non-English locale, but Java
|
||||
# side does it, so we should do it manually.
|
||||
if '~' in filename:
|
||||
filename = convert_to_long_pathname(filename)
|
||||
|
||||
filename = _os_normcase(filename)
|
||||
return filename.lower()
|
||||
|
||||
else:
|
||||
|
||||
def normcase(filename):
|
||||
return filename # no-op
|
||||
|
||||
_ide_os = 'WINDOWS' if sys.platform == 'win32' else 'UNIX'
|
||||
_ide_os = 'WINDOWS' if IS_WINDOWS else 'UNIX'
|
||||
|
||||
|
||||
def set_ide_os(os):
|
||||
|
|
@ -382,7 +398,7 @@ def setup_client_server_paths(paths):
|
|||
return
|
||||
|
||||
# Work on the client and server slashes.
|
||||
python_sep = '\\' if sys.platform == 'win32' else '/'
|
||||
python_sep = '\\' if IS_WINDOWS else '/'
|
||||
eclipse_sep = '\\' if _ide_os == 'WINDOWS' else '/'
|
||||
|
||||
# only setup translation functions if absolutely needed!
|
||||
|
|
@ -430,7 +446,7 @@ def setup_client_server_paths(paths):
|
|||
translated_proper_case = get_path_with_real_case(translated)
|
||||
translated = _NormFile(translated_proper_case)
|
||||
|
||||
if sys.platform == 'win32':
|
||||
if IS_WINDOWS:
|
||||
if translated.lower() != translated_proper_case.lower():
|
||||
translated_proper_case = translated
|
||||
if DEBUG_CLIENT_SERVER_TRANSLATION:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
[pytest]
|
||||
norecursedirs=tests_runfiles/samples
|
||||
addopts=--capture=no -vv
|
||||
addopts=-vv
|
||||
testpaths=test_pydevd_reload tests tests_mainloop tests_python tests_runfiles
|
||||
|
|
@ -93,6 +93,7 @@ class Test(unittest.TestCase):
|
|||
|
||||
|
||||
def test_get_referrers6(self):
|
||||
import sys
|
||||
container = dict(a=[1])
|
||||
|
||||
def should_appear(obj):
|
||||
|
|
@ -100,7 +101,11 @@ class Test(unittest.TestCase):
|
|||
return pydevd_referrers.get_referrer_info(obj)
|
||||
|
||||
result = should_appear(container['a'])
|
||||
assert 'should_appear' in result
|
||||
if sys.version_info[:2] >= (3, 7):
|
||||
# In Python 3.7 the frame is not appearing in gc.get_referrers.
|
||||
assert 'should_appear' not in result
|
||||
else:
|
||||
assert 'should_appear' in result
|
||||
|
||||
|
||||
def test_get_referrers7(self):
|
||||
|
|
|
|||
|
|
@ -103,17 +103,17 @@ class TestJython(unittest.TestCase):
|
|||
'''
|
||||
Creates the connections needed for testing.
|
||||
'''
|
||||
p1 = self.get_free_port()
|
||||
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
server.bind((pycompletionserver.HOST, 0))
|
||||
server.listen(1) #socket to receive messages.
|
||||
|
||||
from thread import start_new_thread
|
||||
t = pycompletionserver.CompletionServer(p1)
|
||||
t = pycompletionserver.CompletionServer(server.getsockname()[1])
|
||||
t.exit_process_on_kill = False
|
||||
|
||||
start_new_thread(t.run, ())
|
||||
|
||||
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
server.bind((pycompletionserver.HOST, p1))
|
||||
server.listen(1)
|
||||
|
||||
sock, _addr = server.accept()
|
||||
|
||||
return t, sock
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class TestMod(unittest.TestCase):
|
|||
def test_imports1(self):
|
||||
f, tip = _pydev_jy_imports_tipper.generate_tip('junit.framework.TestCase')
|
||||
assert f.endswith('junit.jar')
|
||||
ret = self.assert_in('assertEqual', tip)
|
||||
ret = self.assert_in('assertEquals', tip)
|
||||
# self.assertEqual('', ret[2])
|
||||
|
||||
def test_imports2(self):
|
||||
|
|
|
|||
|
|
@ -126,7 +126,8 @@ class Test(unittest.TestCase):
|
|||
desc == "<built-in method join of str object>" or
|
||||
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,
|
||||
desc.find('join(self: str, sequence: list) -> str') >= 0 or
|
||||
desc.find('Concatenate any number of strings.') >= 0,
|
||||
"Could not recognize: %s" % (desc,))
|
||||
finally:
|
||||
sys.stdout = self.original_stdout
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class TestCPython(unittest.TestCase):
|
|||
t.exit_process_on_kill = False
|
||||
start_new_thread(t.run, ())
|
||||
|
||||
s, addr = server.accept()
|
||||
s, _addr = server.accept()
|
||||
|
||||
return t, s
|
||||
|
||||
|
|
@ -102,11 +102,13 @@ class TestCPython(unittest.TestCase):
|
|||
#math is a builtin and because of that, it starts with None as a file
|
||||
start = '@@COMPLETIONS(None,(__doc__,'
|
||||
start_2 = '@@COMPLETIONS(None,(__name__,'
|
||||
if '/math.so,' in completions or\
|
||||
'/math.cpython-33m.so,' in completions or \
|
||||
'/math.cpython-34m.so,' in completions or \
|
||||
'math.cpython-35m' in completions or \
|
||||
'math.cpython-36m' in completions:
|
||||
if ('/math.so,' in completions or
|
||||
'/math.cpython-33m.so,' in completions or
|
||||
'/math.cpython-34m.so,' in completions or
|
||||
'math.cpython-35m' in completions or
|
||||
'math.cpython-36m' in completions or
|
||||
'math.cpython-37m' in completions
|
||||
):
|
||||
return
|
||||
self.assertTrue(completions.startswith(start) or completions.startswith(start_2), '%s DOESNT START WITH %s' % (completions, (start, start_2)))
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class TestCPython(unittest.TestCase):
|
|||
'(self, object cmp, object key, bool reverse)',
|
||||
'(self, cmp: object, key: object, reverse: bool)',
|
||||
'(key=None, reverse=False)',
|
||||
'(self, key=None, reverse=False)',
|
||||
)
|
||||
|
||||
def test_imports2a(self):
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
from _pydevd_bundle.pydevd_constants import IS_JYTHON
|
||||
try:
|
||||
from urllib import quote, quote_plus, unquote_plus
|
||||
except ImportError:
|
||||
|
|
@ -403,6 +404,20 @@ class AbstractWriterThread(threading.Thread):
|
|||
if re.match(r'^(\d+)\t(\d)+', line):
|
||||
return True
|
||||
|
||||
if IS_JYTHON:
|
||||
for expected in (
|
||||
'org.python.netty.util.concurrent.DefaultPromise',
|
||||
'org.python.netty.util.concurrent.SingleThreadEventExecutor',
|
||||
'Failed to submit a listener notification task. Event loop shut down?',
|
||||
'java.util.concurrent.RejectedExecutionException',
|
||||
'An event executor terminated with non-empty task',
|
||||
):
|
||||
if expected in line:
|
||||
return True
|
||||
|
||||
if line.strip().startswith('at '):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def additional_output_checks(self, stdout, stderr):
|
||||
|
|
@ -605,6 +620,8 @@ class AbstractWriterThread(threading.Thread):
|
|||
expected_vars = [expected_vars]
|
||||
|
||||
all_found = []
|
||||
ignored = []
|
||||
|
||||
while True:
|
||||
try:
|
||||
last = self.reader_thread.get_next_message('wait_for_multiple_vars: %s' % (expected_vars,))
|
||||
|
|
@ -613,23 +630,36 @@ class AbstractWriterThread(threading.Thread):
|
|||
for v in expected_vars:
|
||||
if v not in all_found:
|
||||
missing.append(v)
|
||||
raise ValueError('Not Found:\n%s\nNot found messages: %s\nFound messages: %s\nExpected messages: %s' % (
|
||||
'\n'.join(missing), len(missing), len(all_found), len(expected_vars)))
|
||||
found = 0
|
||||
raise ValueError('Not Found:\n%s\nNot found messages: %s\nFound messages: %s\nExpected messages: %s\nIgnored messages:\n%s' % (
|
||||
'\n'.join(missing), len(missing), len(all_found), len(expected_vars), '\n'.join(ignored)))
|
||||
|
||||
was_message_used = False
|
||||
new_expected = []
|
||||
for expected in expected_vars:
|
||||
found_expected = False
|
||||
if isinstance(expected, (tuple, list)):
|
||||
for e in expected:
|
||||
if self._is_var_in_last(e, last):
|
||||
was_message_used = True
|
||||
found_expected = True
|
||||
all_found.append(expected)
|
||||
found += 1
|
||||
break
|
||||
else:
|
||||
if self._is_var_in_last(expected, last):
|
||||
was_message_used = True
|
||||
found_expected = True
|
||||
all_found.append(expected)
|
||||
found += 1
|
||||
|
||||
if found == len(expected_vars):
|
||||
if not found_expected:
|
||||
new_expected.append(expected)
|
||||
|
||||
expected_vars = new_expected
|
||||
|
||||
if not expected_vars:
|
||||
return True
|
||||
|
||||
if not was_message_used:
|
||||
ignored.append(last)
|
||||
|
||||
wait_for_var = wait_for_multiple_vars
|
||||
wait_for_vars = wait_for_multiple_vars
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import time
|
||||
if __name__ == '__main__':
|
||||
for i in range(10):
|
||||
for i in range(6):
|
||||
print('here %s' % i)
|
||||
time.sleep(1)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,19 @@
|
|||
import threading
|
||||
event_set = False
|
||||
inner_started = False
|
||||
|
||||
def method():
|
||||
global inner_started
|
||||
inner_started = True
|
||||
while not event_set:
|
||||
import time
|
||||
time.sleep(.1)
|
||||
|
||||
t = threading.Thread(target=method)
|
||||
t.start()
|
||||
while not inner_started:
|
||||
import time
|
||||
time.sleep(.1)
|
||||
|
||||
print('break here')
|
||||
event_set = True
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import threading
|
||||
|
||||
semaphore1 = threading.Semaphore(0)
|
||||
lock = threading.Lock()
|
||||
proceed = False
|
||||
|
||||
|
||||
|
|
@ -10,9 +9,8 @@ def thread_target():
|
|||
import time
|
||||
|
||||
while True:
|
||||
with lock:
|
||||
if proceed:
|
||||
break
|
||||
if proceed:
|
||||
break
|
||||
time.sleep(1 / 30.)
|
||||
|
||||
|
||||
|
|
@ -26,7 +24,6 @@ semaphore1.acquire() # let second thread run
|
|||
# At this point we know both other threads are already running.
|
||||
print('break here')
|
||||
|
||||
with lock:
|
||||
proceed = True
|
||||
proceed = True
|
||||
|
||||
print('TEST SUCEEDED!')
|
||||
|
|
|
|||
|
|
@ -1,19 +1,31 @@
|
|||
# coding: utf-8
|
||||
import os.path
|
||||
from _pydevd_bundle.pydevd_constants import IS_WINDOWS, IS_JYTHON
|
||||
|
||||
|
||||
def test_convert_utilities(tmpdir):
|
||||
import pydevd_file_utils
|
||||
import sys
|
||||
|
||||
test_dir = str(tmpdir.mkdir("Test_Convert_Utilities"))
|
||||
if sys.platform == 'win32':
|
||||
|
||||
if IS_WINDOWS:
|
||||
normalized = pydevd_file_utils.normcase(test_dir)
|
||||
assert isinstance(normalized, str) # bytes on py2, unicode on py3
|
||||
assert normalized.lower() == normalized
|
||||
|
||||
upper_version = os.path.join(test_dir, 'ÁÉÍÓÚ')
|
||||
with open(upper_version, 'w') as stream:
|
||||
stream.write('test')
|
||||
|
||||
with open(upper_version, 'r') as stream:
|
||||
assert stream.read() == 'test'
|
||||
|
||||
with open(pydevd_file_utils.normcase(upper_version), 'r') as stream:
|
||||
assert stream.read() == 'test'
|
||||
|
||||
assert '~' not in normalized
|
||||
assert '~' in pydevd_file_utils.convert_to_short_pathname(normalized)
|
||||
if not IS_JYTHON:
|
||||
assert '~' in pydevd_file_utils.convert_to_short_pathname(normalized)
|
||||
|
||||
real_case = pydevd_file_utils.get_path_with_real_case(normalized)
|
||||
assert isinstance(real_case, str) # bytes on py2, unicode on py3
|
||||
|
|
@ -32,13 +44,12 @@ def test_to_server_and_to_client(tmpdir):
|
|||
try:
|
||||
|
||||
def check(obtained, expected):
|
||||
assert obtained == expected
|
||||
assert obtained == expected, '%s (%s) != %s (%s)' % (obtained, type(obtained), expected, type(expected))
|
||||
assert isinstance(obtained, str) # bytes on py2, unicode on py3
|
||||
assert isinstance(expected, str) # bytes on py2, unicode on py3
|
||||
|
||||
import pydevd_file_utils
|
||||
import sys
|
||||
if sys.platform == 'win32':
|
||||
if IS_WINDOWS:
|
||||
# Check with made-up files
|
||||
|
||||
# Client and server are on windows.
|
||||
|
|
@ -159,7 +170,7 @@ def test_zip_paths(tmpdir):
|
|||
# Check that we can deal with the zip path.
|
||||
assert pydevd_file_utils.exists(zipfile_path)
|
||||
abspath, realpath, basename = pydevd_file_utils.get_abs_path_real_path_and_base_from_file(zipfile_path)
|
||||
if sys.platform == 'win32':
|
||||
if IS_WINDOWS:
|
||||
assert abspath == zipfile_path.lower()
|
||||
assert basename == zip_basename.lower()
|
||||
else:
|
||||
|
|
@ -179,4 +190,4 @@ def test_zip_paths(tmpdir):
|
|||
assert pydevd_file_utils.exists(realpath), 'Expected exists to return True for path:\n%s' % (realpath,)
|
||||
|
||||
assert zipfile_path in pydevd_file_utils._ZIP_SEARCH_CACHE, '%s not in %s' % (
|
||||
zipfile_path, '\n'.join(sorted(pydevd_file_utils._ZIP_SEARCH_CACHE.keys())))
|
||||
zipfile_path, '\n'.join(sorted(pydevd_file_utils._ZIP_SEARCH_CACHE.keys())))
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ from tests_python import debugger_unittest
|
|||
from tests_python.debugger_unittest import (get_free_port, CMD_SET_PROPERTY_TRACE, REASON_CAUGHT_EXCEPTION,
|
||||
REASON_UNCAUGHT_EXCEPTION, REASON_STOP_ON_BREAKPOINT, REASON_THREAD_SUSPEND, overrides, CMD_THREAD_CREATE,
|
||||
CMD_GET_THREAD_STACK)
|
||||
from _pydevd_bundle.pydevd_constants import IS_WINDOWS
|
||||
|
||||
IS_CPYTHON = platform.python_implementation() == 'CPython'
|
||||
IS_IRONPYTHON = platform.python_implementation() == 'IronPython'
|
||||
|
|
@ -254,7 +255,12 @@ class WriterThreadCase19(debugger_unittest.AbstractWriterThread):
|
|||
assert line == 8, 'Expected return to be in line 8, was: %s' % line
|
||||
|
||||
self.write_evaluate_expression('%s\t%s\t%s' % (thread_id, frame_id, 'LOCAL'), 'a.__var')
|
||||
self.wait_for_evaluation('<var name="a.__var" type="int" qualifier="{0}" value="int'.format(builtin_qualifier))
|
||||
self.wait_for_evaluation([
|
||||
[
|
||||
'<var name="a.__var" type="int" qualifier="{0}" value="int'.format(builtin_qualifier),
|
||||
'<var name="a.__var" type="int" value="int', # jython
|
||||
]
|
||||
])
|
||||
self.write_run_thread(thread_id)
|
||||
|
||||
|
||||
|
|
@ -528,6 +534,19 @@ class WriterThreadCase14(debugger_unittest.AbstractWriterThread):
|
|||
class WriterThreadCase13(debugger_unittest.AbstractWriterThread):
|
||||
|
||||
TEST_FILE = debugger_unittest._get_debugger_test_file('_debugger_case13.py')
|
||||
|
||||
def _ignore_stderr_line(self, line):
|
||||
if debugger_unittest.AbstractWriterThread._ignore_stderr_line(self, line):
|
||||
return True
|
||||
|
||||
if IS_JYTHON:
|
||||
for expected in (
|
||||
"RuntimeWarning: Parent module '_pydevd_bundle' not found while handling absolute import",
|
||||
"import __builtin__"):
|
||||
if expected in line:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
self.start_socket()
|
||||
|
|
@ -766,7 +785,12 @@ class WriterThreadCase7(debugger_unittest.AbstractWriterThread):
|
|||
|
||||
self.write_get_frame(thread_id, frame_id)
|
||||
|
||||
self.wait_for_vars('<xml><var name="variable_for_test_1" type="int" qualifier="{0}" value="int%253A 10" />%0A</xml>'.format(builtin_qualifier))
|
||||
self.wait_for_vars([
|
||||
[
|
||||
'<xml><var name="variable_for_test_1" type="int" qualifier="{0}" value="int%253A 10" />%0A</xml>'.format(builtin_qualifier),
|
||||
'<var name="variable_for_test_1" type="int" value="int', # jython
|
||||
]
|
||||
])
|
||||
|
||||
self.write_step_over(thread_id)
|
||||
|
||||
|
|
@ -775,7 +799,12 @@ class WriterThreadCase7(debugger_unittest.AbstractWriterThread):
|
|||
|
||||
self.write_get_frame(thread_id, frame_id)
|
||||
|
||||
self.wait_for_vars('<xml><var name="variable_for_test_1" type="int" qualifier="{0}" value="int%253A 10" />%0A<var name="variable_for_test_2" type="int" qualifier="{0}" value="int%253A 20" />%0A</xml>'.format(builtin_qualifier))
|
||||
self.wait_for_vars([
|
||||
[
|
||||
'<xml><var name="variable_for_test_1" type="int" qualifier="{0}" value="int%253A 10" />%0A<var name="variable_for_test_2" type="int" qualifier="{0}" value="int%253A 20" />%0A</xml>'.format(builtin_qualifier),
|
||||
'<var name="variable_for_test_1" type="int" value="int%253A 10" />%0A<var name="variable_for_test_2" type="int" value="int%253A 20" />%0A', # jython
|
||||
]
|
||||
])
|
||||
|
||||
self.write_run_thread(thread_id)
|
||||
|
||||
|
|
@ -873,7 +902,8 @@ class WriterThreadCase4(debugger_unittest.AbstractWriterThread):
|
|||
|
||||
self.write_suspend_thread(thread_id)
|
||||
|
||||
time.sleep(4) # wait for time enough for the test to finish if it wasn't suspended
|
||||
thread_id2, frame_id, suspend_type = self.wait_for_breakpoint_hit_with_suspend_type(REASON_THREAD_SUSPEND)
|
||||
assert thread_id2 == thread_id
|
||||
|
||||
self.write_run_thread(thread_id)
|
||||
|
||||
|
|
@ -913,9 +943,9 @@ class WriterThreadCase3(debugger_unittest.AbstractWriterThread):
|
|||
self.finished_ok = True
|
||||
|
||||
#=======================================================================================================================
|
||||
# WriterThreadCaseUnhandledExceptions
|
||||
# WriterThreadCaseUnhandledExceptionsBasic
|
||||
#=======================================================================================================================
|
||||
class WriterThreadCaseUnhandledExceptions(debugger_unittest.AbstractWriterThread):
|
||||
class WriterThreadCaseUnhandledExceptionsBasic(debugger_unittest.AbstractWriterThread):
|
||||
|
||||
# Note: expecting unhandled exceptions to be printed to stdout.
|
||||
TEST_FILE = debugger_unittest._get_debugger_test_file('_debugger_case_unhandled_exceptions.py')
|
||||
|
|
@ -1550,7 +1580,12 @@ class WriterThreadCaseTypeExt(debugger_unittest.AbstractWriterThread):
|
|||
|
||||
thread_id, frame_id, line = self.wait_for_breakpoint_hit('111', True)
|
||||
self.write_get_frame(thread_id, frame_id)
|
||||
assert self.wait_for_var(r'<var name="my_rect" type="Rect" qualifier="__main__" value="Rectangle%255BLength%253A 5%252C Width%253A 10 %252C Area%253A 50%255D" isContainer="True" />')
|
||||
assert self.wait_for_var([
|
||||
[
|
||||
r'<var name="my_rect" type="Rect" qualifier="__main__" value="Rectangle%255BLength%253A 5%252C Width%253A 10 %252C Area%253A 50%255D" isContainer="True" />',
|
||||
r'<var name="my_rect" type="Rect" value="Rect: <__main__.Rect object at', # Jython
|
||||
]
|
||||
])
|
||||
self.write_get_variable(thread_id, frame_id, 'my_rect')
|
||||
assert self.wait_for_var(r'<var name="area" type="int" qualifier="{0}" value="int%253A 50" />'.format(builtin_qualifier))
|
||||
self.write_run_thread(thread_id)
|
||||
|
|
@ -1888,7 +1923,7 @@ class WriterThreadCasePathTranslation(debugger_unittest.AbstractWriterThread):
|
|||
|
||||
# Request a file that exists
|
||||
files_to_match = [file_in_client]
|
||||
if sys.platform == 'win32':
|
||||
if IS_WINDOWS:
|
||||
files_to_match.append(file_in_client.upper())
|
||||
for f in files_to_match:
|
||||
self.write_load_source(f)
|
||||
|
|
@ -2076,7 +2111,7 @@ class WriterCaseBreakpointSuspensionPolicy(debugger_unittest.AbstractWriterThrea
|
|||
|
||||
def run(self):
|
||||
self.start_socket()
|
||||
self.write_add_breakpoint(27, '', filename=self.TEST_FILE, hit_condition='', is_logpoint=False, suspend_policy='ALL')
|
||||
self.write_add_breakpoint(25, '', filename=self.TEST_FILE, hit_condition='', is_logpoint=False, suspend_policy='ALL')
|
||||
self.write_make_initial_run()
|
||||
|
||||
thread_ids = []
|
||||
|
|
@ -2098,9 +2133,22 @@ class WriterCaseGetThreadStack(debugger_unittest.AbstractWriterThread):
|
|||
|
||||
TEST_FILE = debugger_unittest._get_debugger_test_file('_debugger_case_get_thread_stack.py')
|
||||
|
||||
def _ignore_stderr_line(self, line):
|
||||
if debugger_unittest.AbstractWriterThread._ignore_stderr_line(self, line):
|
||||
return True
|
||||
|
||||
if IS_JYTHON:
|
||||
for expected in (
|
||||
"RuntimeWarning: Parent module '_pydev_bundle' not found while handling absolute import",
|
||||
"from java.lang import System"):
|
||||
if expected in line:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
self.start_socket()
|
||||
self.write_add_breakpoint(12, None)
|
||||
self.write_add_breakpoint(18, None)
|
||||
self.write_make_initial_run()
|
||||
|
||||
thread_created_msgs = [self.wait_for_message(lambda msg:msg.startswith('%s\t' % (CMD_THREAD_CREATE,)))]
|
||||
|
|
@ -2267,6 +2315,7 @@ class Test(unittest.TestCase, debugger_unittest.DebuggerRunner):
|
|||
def test_case_19(self):
|
||||
self.check_case(WriterThreadCase19)
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Monkey-patching related to starting threads not done on Jython.')
|
||||
def test_case_20(self):
|
||||
self.check_case(WriterThreadCase20)
|
||||
|
||||
|
|
@ -2321,22 +2370,27 @@ class Test(unittest.TestCase, debugger_unittest.DebuggerRunner):
|
|||
def test_module_entry_point(self):
|
||||
self.check_case(WriterThreadCaseModuleWithEntryPoint)
|
||||
|
||||
def test_unhandled_exceptions(self):
|
||||
self.check_case(WriterThreadCaseUnhandledExceptions)
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Failing on Jython -- needs to be investigated).')
|
||||
def test_unhandled_exceptions_basic(self):
|
||||
self.check_case(WriterThreadCaseUnhandledExceptionsBasic)
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Failing on Jython -- needs to be investigated).')
|
||||
def test_unhandled_exceptions_in_top_level(self):
|
||||
self.check_case(WriterThreadCaseUnhandledExceptionsOnTopLevel)
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Failing on Jython -- needs to be investigated).')
|
||||
def test_unhandled_exceptions_in_top_level2(self):
|
||||
self.check_case(WriterThreadCaseUnhandledExceptionsOnTopLevel2)
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Failing on Jython -- needs to be investigated).')
|
||||
def test_unhandled_exceptions_in_top_level3(self):
|
||||
self.check_case(WriterThreadCaseUnhandledExceptionsOnTopLevel3)
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Failing on Jython -- needs to be investigated).')
|
||||
def test_unhandled_exceptions_in_top_level4(self):
|
||||
self.check_case(WriterThreadCaseUnhandledExceptionsOnTopLevel4)
|
||||
|
||||
@pytest.mark.skipif(not IS_CPYTHON or (IS_PY36 and sys.platform != 'win32'), reason='Only for Python (failing on 3.6 on travis (linux) -- needs to be investigated).')
|
||||
@pytest.mark.skipif(not IS_CPYTHON or (IS_PY36 and not IS_WINDOWS), reason='Only for Python (failing on 3.6 on travis (linux) -- needs to be investigated).')
|
||||
def test_case_set_next_statement(self):
|
||||
self.check_case(WriterThreadCaseSetNextStatement)
|
||||
|
||||
|
|
@ -2344,14 +2398,15 @@ class Test(unittest.TestCase, debugger_unittest.DebuggerRunner):
|
|||
def test_case_get_next_statement_targets(self):
|
||||
self.check_case(WriterThreadCaseGetNextStatementTargets)
|
||||
|
||||
@pytest.mark.skipif(IS_IRONPYTHON, reason='Failing on IronPython (needs to be investigated).')
|
||||
@pytest.mark.skipif(IS_IRONPYTHON or IS_JYTHON, reason='Failing on IronPython and Jython (needs to be investigated).')
|
||||
def test_case_type_ext(self):
|
||||
self.check_case(WriterThreadCaseTypeExt)
|
||||
|
||||
@pytest.mark.skipif(IS_IRONPYTHON, reason='Failing on IronPython (needs to be investigated).')
|
||||
@pytest.mark.skipif(IS_IRONPYTHON or IS_JYTHON, reason='Failing on IronPython and Jython (needs to be investigated).')
|
||||
def test_case_event_ext(self):
|
||||
self.check_case(WriterThreadCaseEventExt)
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Jython does not seem to be creating thread started inside tracing (investigate).')
|
||||
def test_case_writer_thread_creation_deadlock(self):
|
||||
self.check_case(WriterThreadCaseThreadCreationDeadlock)
|
||||
|
||||
|
|
@ -2361,6 +2416,7 @@ class Test(unittest.TestCase, debugger_unittest.DebuggerRunner):
|
|||
def test_case_handled_exceptions(self):
|
||||
self.check_case(WriterThreadCaseHandledExceptions)
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Not working on Jython (needs to be investigated).')
|
||||
def test_case_handled_exceptions1(self):
|
||||
self.check_case(WriterThreadCaseHandledExceptions1)
|
||||
|
||||
|
|
@ -2373,11 +2429,11 @@ class Test(unittest.TestCase, debugger_unittest.DebuggerRunner):
|
|||
def test_case_settrace(self):
|
||||
self.check_case(WriterCaseSetTrace)
|
||||
|
||||
@pytest.mark.skipif(IS_PY26, reason='scapy only supports 2.7 onwards.')
|
||||
@pytest.mark.skipif(IS_PY26 or IS_JYTHON, reason='scapy only supports 2.7 onwards, not available for jython.')
|
||||
def test_case_scapy(self):
|
||||
self.check_case(WriterThreadCaseScapy)
|
||||
|
||||
@pytest.mark.skipif(IS_APPVEYOR, reason='Flaky on appveyor.')
|
||||
@pytest.mark.skipif(IS_APPVEYOR or IS_JYTHON, reason='Flaky on appveyor / Jython encoding issues (needs investigation).')
|
||||
def test_redirect_output(self):
|
||||
self.check_case(WriterThreadCaseRedirectOutput)
|
||||
|
||||
|
|
@ -2393,6 +2449,7 @@ class Test(unittest.TestCase, debugger_unittest.DebuggerRunner):
|
|||
def test_case_print(self):
|
||||
self.check_case(WriterCasePrint)
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Not working on Jython (needs to be investigated).')
|
||||
def test_case_lamdda(self):
|
||||
self.check_case(WriterCaseLamda)
|
||||
|
||||
|
|
@ -2400,9 +2457,11 @@ class Test(unittest.TestCase, debugger_unittest.DebuggerRunner):
|
|||
def setup_fixtures(self, tmpdir):
|
||||
self.tmpdir = tmpdir
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Not working properly on Jython (needs investigation).')
|
||||
def test_debug_zip_files(self):
|
||||
self.check_case(WriterDebugZipFiles(self.tmpdir))
|
||||
|
||||
@pytest.mark.skipif(IS_JYTHON, reason='Not working properly on Jython (needs investigation).')
|
||||
def test_case_suspension_policy(self):
|
||||
self.check_case(WriterCaseBreakpointSuspensionPolicy)
|
||||
|
||||
|
|
|
|||
|
|
@ -197,7 +197,10 @@ class WriterThreadAddTerminationExceptionBreak(debugger_unittest.AbstractWriterT
|
|||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not IS_PY36 or not IS_CPYTHON or not TEST_CYTHON or IS_APPVEYOR, reason='Test requires Python 3.6 / flaky on appveyor')
|
||||
True,
|
||||
reason='Frame eval is not currently meant to be used in the debugger and tests are flaky.\n'
|
||||
'Feature must be reviewed to be included again.\n'
|
||||
)
|
||||
class TestFrameEval(unittest.TestCase, debugger_unittest.DebuggerRunner):
|
||||
|
||||
def get_command_line(self):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import os.path
|
||||
import sys
|
||||
from tests_python.test_debugger import IS_PY26
|
||||
|
||||
IS_JYTHON = sys.platform.find('java') != -1
|
||||
|
||||
|
|
@ -199,6 +200,21 @@ class RunfilesTest(unittest.TestCase):
|
|||
for t in tests:
|
||||
total += t.countTestCases()
|
||||
return total
|
||||
|
||||
def test_runfile_imports(self):
|
||||
from _pydev_runfiles import pydev_runfiles_coverage
|
||||
from _pydev_runfiles import pydev_runfiles_parallel_client
|
||||
from _pydev_runfiles import pydev_runfiles_parallel
|
||||
import pytest
|
||||
if IS_PY26:
|
||||
with pytest.raises(AssertionError) as e:
|
||||
from _pydev_runfiles import pydev_runfiles_pytest2
|
||||
assert 'Please upgrade pytest' in str(e)
|
||||
else:
|
||||
from _pydev_runfiles import pydev_runfiles_pytest2
|
||||
from _pydev_runfiles import pydev_runfiles_unittest
|
||||
from _pydev_runfiles import pydev_runfiles_xml_rpc
|
||||
from _pydev_runfiles import pydev_runfiles
|
||||
|
||||
def test___match(self):
|
||||
matcher = self.MyTestRunner._PydevTestRunner__match
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue