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:
Karthik Nadig 2018-06-25 13:20:22 -07:00 committed by GitHub
parent ca30f3e01c
commit 618a107e11
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 111 additions and 35 deletions

View file

@ -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"

View file

@ -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

View file

@ -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):

View file

@ -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',

View file

@ -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)

View file

@ -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 ''