mirror of
https://github.com/microsoft/debugpy.git
synced 2025-12-23 08:48:12 +00:00
Compatibility python 3.4 (#519)
* Test compat fixes for python 3.4 tests * Enable python 3.4 CI in travis * Fix for 3.4 missing text in traceback list * Fix linter * Add python 3.4 to classifiers * Fix for line text
This commit is contained in:
parent
ca30f3e01c
commit
618a107e11
6 changed files with 111 additions and 35 deletions
|
|
@ -2,6 +2,7 @@ language: python
|
|||
cache: pip
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.4"
|
||||
- "3.5-dev"
|
||||
# 3.6 is tested via coverage
|
||||
- "3.7-dev"
|
||||
|
|
|
|||
|
|
@ -337,3 +337,15 @@ class Startable(object):
|
|||
|
||||
def _stop(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def is_py34():
|
||||
return sys.version_info >= (3, 4,) and sys.version_info < (3, 5,)
|
||||
|
||||
|
||||
def get_line_for_traceback(file_path, line_no):
|
||||
try:
|
||||
with open(file_path, 'r') as f:
|
||||
return f.readlines()[line_no - 1]
|
||||
except Exception:
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -2234,15 +2234,22 @@ class VSCodeMessageProcessor(VSCLifecycleMsgProcessor):
|
|||
xml = self.parse_xml_response(resp_args)
|
||||
text = unquote(xml.var[1]['type'])
|
||||
description = unquote(xml.var[1]['value'])
|
||||
frame_data = ((
|
||||
unquote(f['file']),
|
||||
int(f['line']),
|
||||
unquote(f['name']),
|
||||
None)
|
||||
for f in xframes
|
||||
if not self.internals_filter.is_internal_path(
|
||||
unquote(f['file']))
|
||||
)
|
||||
frame_data = []
|
||||
for f in xframes:
|
||||
file_path = unquote(f['file'])
|
||||
if not self.internals_filter.is_internal_path(file_path):
|
||||
line_no = int(f['line'])
|
||||
func_name = unquote(f['name'])
|
||||
if _util.is_py34():
|
||||
# NOTE: In 3.4.* format_list requires the text
|
||||
# to be passed in the tuple list.
|
||||
line_text = _util.get_line_for_traceback(file_path,
|
||||
line_no)
|
||||
frame_data.append((file_path, line_no,
|
||||
func_name, line_text))
|
||||
else:
|
||||
frame_data.append((file_path, line_no,
|
||||
func_name, None))
|
||||
stack = ''.join(traceback.format_list(frame_data))
|
||||
source = unquote(xframe['file'])
|
||||
if self.internals_filter.is_internal_path(source):
|
||||
|
|
|
|||
1
setup.py
1
setup.py
|
|
@ -61,6 +61,7 @@ if __name__ == '__main__':
|
|||
classifiers=[
|
||||
'Development Status :: 3 - Alpha',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import contextlib
|
||||
import io
|
||||
import sys
|
||||
from textwrap import dedent
|
||||
import unittest
|
||||
|
||||
|
|
@ -34,6 +35,23 @@ class CommandRegistryTests(unittest.TestCase):
|
|||
})
|
||||
|
||||
|
||||
class internal_redirect_stderr:
|
||||
"""Context manager for temporarily redirecting stderr to another file
|
||||
"""
|
||||
|
||||
def __init__(self, new_target):
|
||||
self._new_target = new_target
|
||||
self._old_targets = []
|
||||
|
||||
def __enter__(self):
|
||||
self._old_targets.append(sys.stderr)
|
||||
sys.stderr = self._new_target
|
||||
return self._new_target
|
||||
|
||||
def __exit__(self, exctype, excinst, exctb):
|
||||
sys.stderr = self._old_targets.pop()
|
||||
|
||||
|
||||
class HandleDownloadTests(unittest.TestCase):
|
||||
|
||||
def test_default_args(self):
|
||||
|
|
@ -45,8 +63,13 @@ class HandleDownloadTests(unittest.TestCase):
|
|||
opener = StubOpener(schemafile, outfile, buf, metafile)
|
||||
|
||||
stdout = io.StringIO()
|
||||
try:
|
||||
redirect_stderr = contextlib.redirect_stderr
|
||||
except AttributeError:
|
||||
redirect_stderr = internal_redirect_stderr
|
||||
|
||||
with contextlib.redirect_stdout(stdout):
|
||||
with contextlib.redirect_stderr(stdout):
|
||||
with redirect_stderr(stdout):
|
||||
handle_download(
|
||||
_open=opener.open, _open_url=opener.open)
|
||||
metadata = '\n'.join(line
|
||||
|
|
@ -86,8 +109,13 @@ class HandleCheckTests(unittest.TestCase):
|
|||
)
|
||||
|
||||
stdout = io.StringIO()
|
||||
try:
|
||||
redirect_stderr = contextlib.redirect_stderr
|
||||
except AttributeError:
|
||||
redirect_stderr = internal_redirect_stderr
|
||||
|
||||
with contextlib.redirect_stdout(stdout):
|
||||
with contextlib.redirect_stderr(stdout):
|
||||
with redirect_stderr(stdout):
|
||||
handle_check(
|
||||
_open=opener.open, _open_url=opener.open)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,33 @@ from tests.helpers import http
|
|||
from debugger_protocol.schema.__main__ import handle_check
|
||||
|
||||
|
||||
class InternalSubprocessResult:
|
||||
def __init__(self):
|
||||
self.stdout = b''
|
||||
self.stderr = b''
|
||||
self.returncode = 0
|
||||
|
||||
|
||||
def _run_subprocess(args, stdout, stderr):
|
||||
if hasattr(subprocess, 'run'):
|
||||
res = subprocess.run(args,
|
||||
stdout=stdout,
|
||||
stderr=stderr)
|
||||
return res
|
||||
else:
|
||||
with tempfile.TemporaryFile() as tempf:
|
||||
res = InternalSubprocessResult()
|
||||
try:
|
||||
res.stdout = subprocess.check_output(args, stderr=tempf)
|
||||
except subprocess.CalledProcessError as err:
|
||||
res.returncode = err.returncode
|
||||
res.stdout = err.output
|
||||
tempf.flush()
|
||||
tempf.seek(0)
|
||||
res.stderr = tempf.read()
|
||||
return res
|
||||
|
||||
|
||||
class VendoredSchemaTests(unittest.TestCase):
|
||||
"""Tests to make sure our vendored schema is up-to-date."""
|
||||
|
||||
|
|
@ -57,9 +84,9 @@ class DownloadCommandTests(unittest.TestCase):
|
|||
|
||||
@unittest.skipUnless(os.environ.get('HAS_NETWORK'), 'no network')
|
||||
def test_default_source(self):
|
||||
res = subprocess.run(self.args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
res = _run_subprocess(self.args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
self.assertEqual(res.returncode, 0)
|
||||
self.assertEqual(res.stdout.decode(), self.get_expected_stdout([
|
||||
|
|
@ -73,9 +100,9 @@ class DownloadCommandTests(unittest.TestCase):
|
|||
handler = http.json_file_handler(b'<a schema>')
|
||||
with http.Server(handler) as srv:
|
||||
upstream = 'http://{}/schema.json'.format(srv.address)
|
||||
res = subprocess.run(self.args + ['--source', upstream],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
res = _run_subprocess(self.args + ['--source', upstream],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout = res.stdout.decode() if res.stdout else ''
|
||||
stderr = res.stderr.decode() if res.stderr else ''
|
||||
|
||||
|
|
@ -155,9 +182,9 @@ class CheckCommandTests(unittest.TestCase):
|
|||
'--schemafile', schemafile,
|
||||
'--upstream', upstream,
|
||||
]
|
||||
res = subprocess.run(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
res = _run_subprocess(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout = res.stdout.decode() if res.stdout else ''
|
||||
stderr = res.stderr.decode() if res.stderr else ''
|
||||
|
||||
|
|
@ -181,9 +208,9 @@ class CheckCommandTests(unittest.TestCase):
|
|||
'--schemafile', schemafile,
|
||||
'--upstream', '<a URL>',
|
||||
]
|
||||
res = subprocess.run(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
res = _run_subprocess(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout = res.stdout.decode() if res.stdout else ''
|
||||
stderr = res.stderr.decode() if res.stderr else ''
|
||||
|
||||
|
|
@ -199,9 +226,9 @@ class CheckCommandTests(unittest.TestCase):
|
|||
'--schemafile', schemafile,
|
||||
'--upstream', '<a URL>',
|
||||
]
|
||||
res = subprocess.run(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
res = _run_subprocess(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout = res.stdout.decode() if res.stdout else ''
|
||||
stderr = res.stderr.decode() if res.stderr else ''
|
||||
|
||||
|
|
@ -223,9 +250,9 @@ class CheckCommandTests(unittest.TestCase):
|
|||
'--schemafile', schemafile,
|
||||
'--upstream', '<a URL>',
|
||||
]
|
||||
res = subprocess.run(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
res = _run_subprocess(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout = res.stdout.decode() if res.stdout else ''
|
||||
stderr = res.stderr.decode() if res.stderr else ''
|
||||
|
||||
|
|
@ -250,9 +277,9 @@ class CheckCommandTests(unittest.TestCase):
|
|||
'--schemafile', schemafile,
|
||||
'--upstream', upstream,
|
||||
]
|
||||
res = subprocess.run(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
res = _run_subprocess(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout = res.stdout.decode() if res.stdout else ''
|
||||
stderr = res.stderr.decode() if res.stderr else ''
|
||||
|
||||
|
|
@ -278,9 +305,9 @@ class CheckCommandTests(unittest.TestCase):
|
|||
'--schemafile', schemafile,
|
||||
'--upstream', upstream,
|
||||
]
|
||||
res = subprocess.run(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
res = _run_subprocess(args,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
stdout = res.stdout.decode() if res.stdout else ''
|
||||
stderr = res.stderr.decode() if res.stderr else ''
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue