diff options
author | Ms2ger <Ms2ger@gmail.com> | 2016-04-12 09:07:41 +0200 |
---|---|---|
committer | Ms2ger <Ms2ger@gmail.com> | 2016-04-12 10:47:32 +0200 |
commit | 299ad0f9d0fcc699f0e5b72f2928fb4e8f9f59d0 (patch) | |
tree | 71b49d8f24c32984f74866037de9e350890e42b9 /tests/wpt/web-platform-tests/tools/py/testing/code | |
parent | f9608022caf7f223dfdfe960c31fb5fe7eb0d1f1 (diff) | |
download | servo-299ad0f9d0fcc699f0e5b72f2928fb4e8f9f59d0.tar.gz servo-299ad0f9d0fcc699f0e5b72f2928fb4e8f9f59d0.zip |
Update web-platform-tests to revision d011702f368b88b3bae86e7a8fd2ddd22e18b33c
Diffstat (limited to 'tests/wpt/web-platform-tests/tools/py/testing/code')
4 files changed, 2027 insertions, 0 deletions
diff --git a/tests/wpt/web-platform-tests/tools/py/testing/code/test_assertion.py b/tests/wpt/web-platform-tests/tools/py/testing/code/test_assertion.py new file mode 100644 index 00000000000..e2154d0fc7a --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/code/test_assertion.py @@ -0,0 +1,308 @@ +import pytest, py + +def exvalue(): + return py.std.sys.exc_info()[1] + +def f(): + return 2 + +def test_assert(): + try: + assert f() == 3 + except AssertionError: + e = exvalue() + s = str(e) + assert s.startswith('assert 2 == 3\n') + + +def test_assert_within_finally(): + excinfo = py.test.raises(ZeroDivisionError, """ + try: + 1/0 + finally: + i = 42 + """) + s = excinfo.exconly() + assert py.std.re.search("division.+by zero", s) is not None + + #def g(): + # A.f() + #excinfo = getexcinfo(TypeError, g) + #msg = getmsg(excinfo) + #assert msg.find("must be called with A") != -1 + + +def test_assert_multiline_1(): + try: + assert (f() == + 3) + except AssertionError: + e = exvalue() + s = str(e) + assert s.startswith('assert 2 == 3\n') + +def test_assert_multiline_2(): + try: + assert (f() == (4, + 3)[-1]) + except AssertionError: + e = exvalue() + s = str(e) + assert s.startswith('assert 2 ==') + +def test_in(): + try: + assert "hi" in [1, 2] + except AssertionError: + e = exvalue() + s = str(e) + assert s.startswith("assert 'hi' in") + +def test_is(): + try: + assert 1 is 2 + except AssertionError: + e = exvalue() + s = str(e) + assert s.startswith("assert 1 is 2") + + +@py.test.mark.skipif("sys.version_info < (2,6)") +def test_attrib(): + class Foo(object): + b = 1 + i = Foo() + try: + assert i.b == 2 + except AssertionError: + e = exvalue() + s = str(e) + assert s.startswith("assert 1 == 2") + +@py.test.mark.skipif("sys.version_info < (2,6)") +def test_attrib_inst(): + class Foo(object): + b = 1 + try: + assert Foo().b == 2 + except AssertionError: + e = exvalue() + s = str(e) + assert s.startswith("assert 1 == 2") + +def test_len(): + l = list(range(42)) + try: + assert len(l) == 100 + except AssertionError: + e = exvalue() + s = str(e) + assert s.startswith("assert 42 == 100") + assert "where 42 = len([" in s + + +def test_assert_keyword_arg(): + def f(x=3): + return False + try: + assert f(x=5) + except AssertionError: + e = exvalue() + assert "x=5" in e.msg + +# These tests should both fail, but should fail nicely... +class WeirdRepr: + def __repr__(self): + return '<WeirdRepr\nsecond line>' + +def bug_test_assert_repr(): + v = WeirdRepr() + try: + assert v == 1 + except AssertionError: + e = exvalue() + assert e.msg.find('WeirdRepr') != -1 + assert e.msg.find('second line') != -1 + assert 0 + +def test_assert_non_string(): + try: + assert 0, ['list'] + except AssertionError: + e = exvalue() + assert e.msg.find("list") != -1 + +def test_assert_implicit_multiline(): + try: + x = [1,2,3] + assert x != [1, + 2, 3] + except AssertionError: + e = exvalue() + assert e.msg.find('assert [1, 2, 3] !=') != -1 + + +def test_assert_with_brokenrepr_arg(): + class BrokenRepr: + def __repr__(self): 0 / 0 + e = AssertionError(BrokenRepr()) + if e.msg.find("broken __repr__") == -1: + py.test.fail("broken __repr__ not handle correctly") + +def test_multiple_statements_per_line(): + try: + a = 1; assert a == 2 + except AssertionError: + e = exvalue() + assert "assert 1 == 2" in e.msg + +def test_power(): + try: + assert 2**3 == 7 + except AssertionError: + e = exvalue() + assert "assert (2 ** 3) == 7" in e.msg + + +class TestView: + + def setup_class(cls): + cls.View = py.test.importorskip("py._code._assertionold").View + + def test_class_dispatch(self): + ### Use a custom class hierarchy with existing instances + + class Picklable(self.View): + pass + + class Simple(Picklable): + __view__ = object + def pickle(self): + return repr(self.__obj__) + + class Seq(Picklable): + __view__ = list, tuple, dict + def pickle(self): + return ';'.join( + [Picklable(item).pickle() for item in self.__obj__]) + + class Dict(Seq): + __view__ = dict + def pickle(self): + return Seq.pickle(self) + '!' + Seq(self.values()).pickle() + + assert Picklable(123).pickle() == '123' + assert Picklable([1,[2,3],4]).pickle() == '1;2;3;4' + assert Picklable({1:2}).pickle() == '1!2' + + def test_viewtype_class_hierarchy(self): + # Use a custom class hierarchy based on attributes of existing instances + class Operation: + "Existing class that I don't want to change." + def __init__(self, opname, *args): + self.opname = opname + self.args = args + + existing = [Operation('+', 4, 5), + Operation('getitem', '', 'join'), + Operation('setattr', 'x', 'y', 3), + Operation('-', 12, 1)] + + class PyOp(self.View): + def __viewkey__(self): + return self.opname + def generate(self): + return '%s(%s)' % (self.opname, ', '.join(map(repr, self.args))) + + class PyBinaryOp(PyOp): + __view__ = ('+', '-', '*', '/') + def generate(self): + return '%s %s %s' % (self.args[0], self.opname, self.args[1]) + + codelines = [PyOp(op).generate() for op in existing] + assert codelines == ["4 + 5", "getitem('', 'join')", + "setattr('x', 'y', 3)", "12 - 1"] + +def test_underscore_api(): + py.code._AssertionError + py.code._reinterpret_old # used by pypy + py.code._reinterpret + +@py.test.mark.skipif("sys.version_info < (2,6)") +def test_assert_customizable_reprcompare(monkeypatch): + util = pytest.importorskip("_pytest.assertion.util") + monkeypatch.setattr(util, '_reprcompare', lambda *args: 'hello') + try: + assert 3 == 4 + except AssertionError: + e = exvalue() + s = str(e) + assert "hello" in s + +def test_assert_long_source_1(): + try: + assert len == [ + (None, ['somet text', 'more text']), + ] + except AssertionError: + e = exvalue() + s = str(e) + assert 're-run' not in s + assert 'somet text' in s + +def test_assert_long_source_2(): + try: + assert(len == [ + (None, ['somet text', 'more text']), + ]) + except AssertionError: + e = exvalue() + s = str(e) + assert 're-run' not in s + assert 'somet text' in s + +def test_assert_raise_alias(testdir): + testdir.makepyfile(""" + import sys + EX = AssertionError + def test_hello(): + raise EX("hello" + "multi" + "line") + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "*def test_hello*", + "*raise EX*", + "*1 failed*", + ]) + + +@pytest.mark.skipif("sys.version_info < (2,5)") +def test_assert_raise_subclass(): + class SomeEx(AssertionError): + def __init__(self, *args): + super(SomeEx, self).__init__() + try: + raise SomeEx("hello") + except AssertionError: + s = str(exvalue()) + assert 're-run' not in s + assert 'could not determine' in s + +def test_assert_raises_in_nonzero_of_object_pytest_issue10(): + class A(object): + def __nonzero__(self): + raise ValueError(42) + def __lt__(self, other): + return A() + def __repr__(self): + return "<MY42 object>" + def myany(x): + return True + try: + assert not(myany(A() < 0)) + except AssertionError: + e = exvalue() + s = str(e) + assert "<MY42 object> < 0" in s diff --git a/tests/wpt/web-platform-tests/tools/py/testing/code/test_code.py b/tests/wpt/web-platform-tests/tools/py/testing/code/test_code.py new file mode 100644 index 00000000000..28ec628b00d --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/code/test_code.py @@ -0,0 +1,159 @@ +import py +import sys + +def test_ne(): + code1 = py.code.Code(compile('foo = "bar"', '', 'exec')) + assert code1 == code1 + code2 = py.code.Code(compile('foo = "baz"', '', 'exec')) + assert code2 != code1 + +def test_code_gives_back_name_for_not_existing_file(): + name = 'abc-123' + co_code = compile("pass\n", name, 'exec') + assert co_code.co_filename == name + code = py.code.Code(co_code) + assert str(code.path) == name + assert code.fullsource is None + +def test_code_with_class(): + class A: + pass + py.test.raises(TypeError, "py.code.Code(A)") + +if True: + def x(): + pass + +def test_code_fullsource(): + code = py.code.Code(x) + full = code.fullsource + assert 'test_code_fullsource()' in str(full) + +def test_code_source(): + code = py.code.Code(x) + src = code.source() + expected = """def x(): + pass""" + assert str(src) == expected + +def test_frame_getsourcelineno_myself(): + def func(): + return sys._getframe(0) + f = func() + f = py.code.Frame(f) + source, lineno = f.code.fullsource, f.lineno + assert source[lineno].startswith(" return sys._getframe(0)") + +def test_getstatement_empty_fullsource(): + def func(): + return sys._getframe(0) + f = func() + f = py.code.Frame(f) + prop = f.code.__class__.fullsource + try: + f.code.__class__.fullsource = None + assert f.statement == py.code.Source("") + finally: + f.code.__class__.fullsource = prop + +def test_code_from_func(): + co = py.code.Code(test_frame_getsourcelineno_myself) + assert co.firstlineno + assert co.path + + + +def test_builtin_patch_unpatch(monkeypatch): + cpy_builtin = py.builtin.builtins + comp = cpy_builtin.compile + def mycompile(*args, **kwargs): + return comp(*args, **kwargs) + class Sub(AssertionError): + pass + monkeypatch.setattr(cpy_builtin, 'AssertionError', Sub) + monkeypatch.setattr(cpy_builtin, 'compile', mycompile) + py.code.patch_builtins() + assert cpy_builtin.AssertionError != Sub + assert cpy_builtin.compile != mycompile + py.code.unpatch_builtins() + assert cpy_builtin.AssertionError is Sub + assert cpy_builtin.compile == mycompile + + +def test_unicode_handling(): + value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8') + def f(): + raise Exception(value) + excinfo = py.test.raises(Exception, f) + s = str(excinfo) + if sys.version_info[0] < 3: + u = unicode(excinfo) + +def test_code_getargs(): + def f1(x): + pass + c1 = py.code.Code(f1) + assert c1.getargs(var=True) == ('x',) + + def f2(x, *y): + pass + c2 = py.code.Code(f2) + assert c2.getargs(var=True) == ('x', 'y') + + def f3(x, **z): + pass + c3 = py.code.Code(f3) + assert c3.getargs(var=True) == ('x', 'z') + + def f4(x, *y, **z): + pass + c4 = py.code.Code(f4) + assert c4.getargs(var=True) == ('x', 'y', 'z') + + +def test_frame_getargs(): + def f1(x): + return sys._getframe(0) + fr1 = py.code.Frame(f1('a')) + assert fr1.getargs(var=True) == [('x', 'a')] + + def f2(x, *y): + return sys._getframe(0) + fr2 = py.code.Frame(f2('a', 'b', 'c')) + assert fr2.getargs(var=True) == [('x', 'a'), ('y', ('b', 'c'))] + + def f3(x, **z): + return sys._getframe(0) + fr3 = py.code.Frame(f3('a', b='c')) + assert fr3.getargs(var=True) == [('x', 'a'), ('z', {'b': 'c'})] + + def f4(x, *y, **z): + return sys._getframe(0) + fr4 = py.code.Frame(f4('a', 'b', c='d')) + assert fr4.getargs(var=True) == [('x', 'a'), ('y', ('b',)), + ('z', {'c': 'd'})] + + +class TestExceptionInfo: + + def test_bad_getsource(self): + try: + if False: pass + else: assert False + except AssertionError: + exci = py.code.ExceptionInfo() + assert exci.getrepr() + + +class TestTracebackEntry: + + def test_getsource(self): + try: + if False: pass + else: assert False + except AssertionError: + exci = py.code.ExceptionInfo() + entry = exci.traceback[0] + source = entry.getsource() + assert len(source) == 4 + assert 'else: assert False' in source[3] diff --git a/tests/wpt/web-platform-tests/tools/py/testing/code/test_excinfo.py b/tests/wpt/web-platform-tests/tools/py/testing/code/test_excinfo.py new file mode 100644 index 00000000000..65742c6f62e --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/code/test_excinfo.py @@ -0,0 +1,909 @@ +# -*- coding: utf-8 -*- + +import py +from py._code.code import FormattedExcinfo, ReprExceptionInfo +queue = py.builtin._tryimport('queue', 'Queue') + +failsonjython = py.test.mark.xfail("sys.platform.startswith('java')") +from test_source import astonly + +try: + import importlib +except ImportError: + invalidate_import_caches = None +else: + invalidate_import_caches = getattr(importlib, "invalidate_caches", None) + +import pytest +pytest_version_info = tuple(map(int, pytest.__version__.split(".")[:3])) + +class TWMock: + def __init__(self): + self.lines = [] + def sep(self, sep, line=None): + self.lines.append((sep, line)) + def line(self, line, **kw): + self.lines.append(line) + def markup(self, text, **kw): + return text + + fullwidth = 80 + +def test_excinfo_simple(): + try: + raise ValueError + except ValueError: + info = py.code.ExceptionInfo() + assert info.type == ValueError + +def test_excinfo_getstatement(): + def g(): + raise ValueError + def f(): + g() + try: + f() + except ValueError: + excinfo = py.code.ExceptionInfo() + linenumbers = [py.code.getrawcode(f).co_firstlineno-1+3, + py.code.getrawcode(f).co_firstlineno-1+1, + py.code.getrawcode(g).co_firstlineno-1+1,] + l = list(excinfo.traceback) + foundlinenumbers = [x.lineno for x in l] + assert foundlinenumbers == linenumbers + #for x in info: + # print "%s:%d %s" %(x.path.relto(root), x.lineno, x.statement) + #xxx + +# testchain for getentries test below +def f(): + # + raise ValueError + # +def g(): + # + __tracebackhide__ = True + f() + # +def h(): + # + g() + # + +class TestTraceback_f_g_h: + def setup_method(self, method): + try: + h() + except ValueError: + self.excinfo = py.code.ExceptionInfo() + + def test_traceback_entries(self): + tb = self.excinfo.traceback + entries = list(tb) + assert len(tb) == 4 # maybe fragile test + assert len(entries) == 4 # maybe fragile test + names = ['f', 'g', 'h'] + for entry in entries: + try: + names.remove(entry.frame.code.name) + except ValueError: + pass + assert not names + + def test_traceback_entry_getsource(self): + tb = self.excinfo.traceback + s = str(tb[-1].getsource() ) + assert s.startswith("def f():") + assert s.endswith("raise ValueError") + + @astonly + @failsonjython + def test_traceback_entry_getsource_in_construct(self): + source = py.code.Source("""\ + def xyz(): + try: + raise ValueError + except somenoname: + pass + xyz() + """) + try: + exec (source.compile()) + except NameError: + tb = py.code.ExceptionInfo().traceback + print (tb[-1].getsource()) + s = str(tb[-1].getsource()) + assert s.startswith("def xyz():\n try:") + assert s.strip().endswith("except somenoname:") + + def test_traceback_cut(self): + co = py.code.Code(f) + path, firstlineno = co.path, co.firstlineno + traceback = self.excinfo.traceback + newtraceback = traceback.cut(path=path, firstlineno=firstlineno) + assert len(newtraceback) == 1 + newtraceback = traceback.cut(path=path, lineno=firstlineno+2) + assert len(newtraceback) == 1 + + def test_traceback_cut_excludepath(self, testdir): + p = testdir.makepyfile("def f(): raise ValueError") + excinfo = py.test.raises(ValueError, "p.pyimport().f()") + basedir = py.path.local(py.test.__file__).dirpath() + newtraceback = excinfo.traceback.cut(excludepath=basedir) + for x in newtraceback: + if hasattr(x, 'path'): + assert not py.path.local(x.path).relto(basedir) + assert newtraceback[-1].frame.code.path == p + + def test_traceback_filter(self): + traceback = self.excinfo.traceback + ntraceback = traceback.filter() + assert len(ntraceback) == len(traceback) - 1 + + def test_traceback_recursion_index(self): + def f(n): + if n < 10: + n += 1 + f(n) + excinfo = py.test.raises(RuntimeError, f, 8) + traceback = excinfo.traceback + recindex = traceback.recursionindex() + assert recindex == 3 + + def test_traceback_only_specific_recursion_errors(self, monkeypatch): + def f(n): + if n == 0: + raise RuntimeError("hello") + f(n-1) + + excinfo = pytest.raises(RuntimeError, f, 100) + monkeypatch.delattr(excinfo.traceback.__class__, "recursionindex") + repr = excinfo.getrepr() + assert "RuntimeError: hello" in str(repr.reprcrash) + + def test_traceback_no_recursion_index(self): + def do_stuff(): + raise RuntimeError + def reraise_me(): + import sys + exc, val, tb = sys.exc_info() + py.builtin._reraise(exc, val, tb) + def f(n): + try: + do_stuff() + except: + reraise_me() + excinfo = py.test.raises(RuntimeError, f, 8) + traceback = excinfo.traceback + recindex = traceback.recursionindex() + assert recindex is None + + def test_traceback_messy_recursion(self): + #XXX: simplified locally testable version + decorator = py.test.importorskip('decorator').decorator + + def log(f, *k, **kw): + print('%s %s' % (k, kw)) + f(*k, **kw) + log = decorator(log) + + def fail(): + raise ValueError('') + + fail = log(log(fail)) + + excinfo = py.test.raises(ValueError, fail) + assert excinfo.traceback.recursionindex() is None + + + + def test_traceback_getcrashentry(self): + def i(): + __tracebackhide__ = True + raise ValueError + def h(): + i() + def g(): + __tracebackhide__ = True + h() + def f(): + g() + + excinfo = py.test.raises(ValueError, f) + tb = excinfo.traceback + entry = tb.getcrashentry() + co = py.code.Code(h) + assert entry.frame.code.path == co.path + assert entry.lineno == co.firstlineno + 1 + assert entry.frame.code.name == 'h' + + def test_traceback_getcrashentry_empty(self): + def g(): + __tracebackhide__ = True + raise ValueError + def f(): + __tracebackhide__ = True + g() + + excinfo = py.test.raises(ValueError, f) + tb = excinfo.traceback + entry = tb.getcrashentry() + co = py.code.Code(g) + assert entry.frame.code.path == co.path + assert entry.lineno == co.firstlineno + 2 + assert entry.frame.code.name == 'g' + +def hello(x): + x + 5 + +def test_tbentry_reinterpret(): + try: + hello("hello") + except TypeError: + excinfo = py.code.ExceptionInfo() + tbentry = excinfo.traceback[-1] + msg = tbentry.reinterpret() + assert msg.startswith("TypeError: ('hello' + 5)") + +def test_excinfo_exconly(): + excinfo = py.test.raises(ValueError, h) + assert excinfo.exconly().startswith('ValueError') + excinfo = py.test.raises(ValueError, + "raise ValueError('hello\\nworld')") + msg = excinfo.exconly(tryshort=True) + assert msg.startswith('ValueError') + assert msg.endswith("world") + +def test_excinfo_repr(): + excinfo = py.test.raises(ValueError, h) + s = repr(excinfo) + assert s == "<ExceptionInfo ValueError tblen=4>" + +def test_excinfo_str(): + excinfo = py.test.raises(ValueError, h) + s = str(excinfo) + assert s.startswith(__file__[:-9]) # pyc file and $py.class + assert s.endswith("ValueError") + assert len(s.split(":")) >= 3 # on windows it's 4 + +def test_excinfo_errisinstance(): + excinfo = py.test.raises(ValueError, h) + assert excinfo.errisinstance(ValueError) + +def test_excinfo_no_sourcecode(): + try: + exec ("raise ValueError()") + except ValueError: + excinfo = py.code.ExceptionInfo() + s = str(excinfo.traceback[-1]) + if py.std.sys.version_info < (2,5): + assert s == " File '<string>':1 in ?\n ???\n" + else: + assert s == " File '<string>':1 in <module>\n ???\n" + +def test_excinfo_no_python_sourcecode(tmpdir): + #XXX: simplified locally testable version + tmpdir.join('test.txt').write("{{ h()}}:") + + jinja2 = py.test.importorskip('jinja2') + loader = jinja2.FileSystemLoader(str(tmpdir)) + env = jinja2.Environment(loader=loader) + template = env.get_template('test.txt') + excinfo = py.test.raises(ValueError, + template.render, h=h) + for item in excinfo.traceback: + print(item) #XXX: for some reason jinja.Template.render is printed in full + item.source # shouldnt fail + if item.path.basename == 'test.txt': + assert str(item.source) == '{{ h()}}:' + + +def test_entrysource_Queue_example(): + try: + queue.Queue().get(timeout=0.001) + except queue.Empty: + excinfo = py.code.ExceptionInfo() + entry = excinfo.traceback[-1] + source = entry.getsource() + assert source is not None + s = str(source).strip() + assert s.startswith("def get") + +def test_codepath_Queue_example(): + try: + queue.Queue().get(timeout=0.001) + except queue.Empty: + excinfo = py.code.ExceptionInfo() + entry = excinfo.traceback[-1] + path = entry.path + assert isinstance(path, py.path.local) + assert path.basename.lower() == "queue.py" + assert path.check() + +class TestFormattedExcinfo: + def pytest_funcarg__importasmod(self, request): + def importasmod(source): + source = py.code.Source(source) + tmpdir = request.getfuncargvalue("tmpdir") + modpath = tmpdir.join("mod.py") + tmpdir.ensure("__init__.py") + modpath.write(source) + if invalidate_import_caches is not None: + invalidate_import_caches() + return modpath.pyimport() + return importasmod + + def excinfo_from_exec(self, source): + source = py.code.Source(source).strip() + try: + exec (source.compile()) + except KeyboardInterrupt: + raise + except: + return py.code.ExceptionInfo() + assert 0, "did not raise" + + def test_repr_source(self): + pr = FormattedExcinfo() + source = py.code.Source(""" + def f(x): + pass + """).strip() + pr.flow_marker = "|" + lines = pr.get_source(source, 0) + assert len(lines) == 2 + assert lines[0] == "| def f(x):" + assert lines[1] == " pass" + + def test_repr_source_excinfo(self): + """ check if indentation is right """ + pr = FormattedExcinfo() + excinfo = self.excinfo_from_exec(""" + def f(): + assert 0 + f() + """) + pr = FormattedExcinfo() + source = pr._getentrysource(excinfo.traceback[-1]) + lines = pr.get_source(source, 1, excinfo) + assert lines == [ + ' def f():', + '> assert 0', + 'E assert 0' + ] + + + def test_repr_source_not_existing(self): + pr = FormattedExcinfo() + co = compile("raise ValueError()", "", "exec") + try: + exec (co) + except ValueError: + excinfo = py.code.ExceptionInfo() + repr = pr.repr_excinfo(excinfo) + assert repr.reprtraceback.reprentries[1].lines[0] == "> ???" + + def test_repr_many_line_source_not_existing(self): + pr = FormattedExcinfo() + co = compile(""" +a = 1 +raise ValueError() +""", "", "exec") + try: + exec (co) + except ValueError: + excinfo = py.code.ExceptionInfo() + repr = pr.repr_excinfo(excinfo) + assert repr.reprtraceback.reprentries[1].lines[0] == "> ???" + + def test_repr_source_failing_fullsource(self): + pr = FormattedExcinfo() + + class FakeCode(object): + class raw: + co_filename = '?' + path = '?' + firstlineno = 5 + + def fullsource(self): + return None + fullsource = property(fullsource) + + class FakeFrame(object): + code = FakeCode() + f_locals = {} + f_globals = {} + + class FakeTracebackEntry(py.code.Traceback.Entry): + def __init__(self, tb): + self.lineno = 5+3 + + @property + def frame(self): + return FakeFrame() + + class Traceback(py.code.Traceback): + Entry = FakeTracebackEntry + + class FakeExcinfo(py.code.ExceptionInfo): + typename = "Foo" + def __init__(self): + pass + + def exconly(self, tryshort): + return "EXC" + def errisinstance(self, cls): + return False + + excinfo = FakeExcinfo() + class FakeRawTB(object): + tb_next = None + tb = FakeRawTB() + excinfo.traceback = Traceback(tb) + + fail = IOError() + repr = pr.repr_excinfo(excinfo) + assert repr.reprtraceback.reprentries[0].lines[0] == "> ???" + + fail = py.error.ENOENT + repr = pr.repr_excinfo(excinfo) + assert repr.reprtraceback.reprentries[0].lines[0] == "> ???" + + + def test_repr_local(self): + p = FormattedExcinfo(showlocals=True) + loc = {'y': 5, 'z': 7, 'x': 3, '@x': 2, '__builtins__': {}} + reprlocals = p.repr_locals(loc) + assert reprlocals.lines + assert reprlocals.lines[0] == '__builtins__ = <builtins>' + assert reprlocals.lines[1] == 'x = 3' + assert reprlocals.lines[2] == 'y = 5' + assert reprlocals.lines[3] == 'z = 7' + + def test_repr_tracebackentry_lines(self, importasmod): + mod = importasmod(""" + def func1(): + raise ValueError("hello\\nworld") + """) + excinfo = py.test.raises(ValueError, mod.func1) + excinfo.traceback = excinfo.traceback.filter() + p = FormattedExcinfo() + reprtb = p.repr_traceback_entry(excinfo.traceback[-1]) + + # test as intermittent entry + lines = reprtb.lines + assert lines[0] == ' def func1():' + assert lines[1] == '> raise ValueError("hello\\nworld")' + + # test as last entry + p = FormattedExcinfo(showlocals=True) + repr_entry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo) + lines = repr_entry.lines + assert lines[0] == ' def func1():' + assert lines[1] == '> raise ValueError("hello\\nworld")' + assert lines[2] == 'E ValueError: hello' + assert lines[3] == 'E world' + assert not lines[4:] + + loc = repr_entry.reprlocals is not None + loc = repr_entry.reprfileloc + assert loc.path == mod.__file__ + assert loc.lineno == 3 + #assert loc.message == "ValueError: hello" + + def test_repr_tracebackentry_lines(self, importasmod): + mod = importasmod(""" + def func1(m, x, y, z): + raise ValueError("hello\\nworld") + """) + excinfo = py.test.raises(ValueError, mod.func1, "m"*90, 5, 13, "z"*120) + excinfo.traceback = excinfo.traceback.filter() + entry = excinfo.traceback[-1] + p = FormattedExcinfo(funcargs=True) + reprfuncargs = p.repr_args(entry) + assert reprfuncargs.args[0] == ('m', repr("m"*90)) + assert reprfuncargs.args[1] == ('x', '5') + assert reprfuncargs.args[2] == ('y', '13') + assert reprfuncargs.args[3] == ('z', repr("z" * 120)) + + p = FormattedExcinfo(funcargs=True) + repr_entry = p.repr_traceback_entry(entry) + assert repr_entry.reprfuncargs.args == reprfuncargs.args + tw = TWMock() + repr_entry.toterminal(tw) + assert tw.lines[0] == "m = " + repr('m' * 90) + assert tw.lines[1] == "x = 5, y = 13" + assert tw.lines[2] == "z = " + repr('z' * 120) + + def test_repr_tracebackentry_lines_var_kw_args(self, importasmod): + mod = importasmod(""" + def func1(x, *y, **z): + raise ValueError("hello\\nworld") + """) + excinfo = py.test.raises(ValueError, mod.func1, 'a', 'b', c='d') + excinfo.traceback = excinfo.traceback.filter() + entry = excinfo.traceback[-1] + p = FormattedExcinfo(funcargs=True) + reprfuncargs = p.repr_args(entry) + assert reprfuncargs.args[0] == ('x', repr('a')) + assert reprfuncargs.args[1] == ('y', repr(('b',))) + assert reprfuncargs.args[2] == ('z', repr({'c': 'd'})) + + p = FormattedExcinfo(funcargs=True) + repr_entry = p.repr_traceback_entry(entry) + assert repr_entry.reprfuncargs.args == reprfuncargs.args + tw = TWMock() + repr_entry.toterminal(tw) + assert tw.lines[0] == "x = 'a', y = ('b',), z = {'c': 'd'}" + + def test_repr_tracebackentry_short(self, importasmod): + mod = importasmod(""" + def func1(): + raise ValueError("hello") + def entry(): + func1() + """) + excinfo = py.test.raises(ValueError, mod.entry) + p = FormattedExcinfo(style="short") + reprtb = p.repr_traceback_entry(excinfo.traceback[-2]) + lines = reprtb.lines + basename = py.path.local(mod.__file__).basename + assert lines[0] == ' func1()' + assert basename in str(reprtb.reprfileloc.path) + assert reprtb.reprfileloc.lineno == 5 + + # test last entry + p = FormattedExcinfo(style="short") + reprtb = p.repr_traceback_entry(excinfo.traceback[-1], excinfo) + lines = reprtb.lines + assert lines[0] == ' raise ValueError("hello")' + assert lines[1] == 'E ValueError: hello' + assert basename in str(reprtb.reprfileloc.path) + assert reprtb.reprfileloc.lineno == 3 + + def test_repr_tracebackentry_no(self, importasmod): + mod = importasmod(""" + def func1(): + raise ValueError("hello") + def entry(): + func1() + """) + excinfo = py.test.raises(ValueError, mod.entry) + p = FormattedExcinfo(style="no") + p.repr_traceback_entry(excinfo.traceback[-2]) + + p = FormattedExcinfo(style="no") + reprentry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo) + lines = reprentry.lines + assert lines[0] == 'E ValueError: hello' + assert not lines[1:] + + def test_repr_traceback_tbfilter(self, importasmod): + mod = importasmod(""" + def f(x): + raise ValueError(x) + def entry(): + f(0) + """) + excinfo = py.test.raises(ValueError, mod.entry) + p = FormattedExcinfo(tbfilter=True) + reprtb = p.repr_traceback(excinfo) + assert len(reprtb.reprentries) == 2 + p = FormattedExcinfo(tbfilter=False) + reprtb = p.repr_traceback(excinfo) + assert len(reprtb.reprentries) == 3 + + def test_traceback_short_no_source(self, importasmod, monkeypatch): + mod = importasmod(""" + def func1(): + raise ValueError("hello") + def entry(): + func1() + """) + excinfo = py.test.raises(ValueError, mod.entry) + from py._code.code import Code + monkeypatch.setattr(Code, 'path', 'bogus') + excinfo.traceback[0].frame.code.path = "bogus" + p = FormattedExcinfo(style="short") + reprtb = p.repr_traceback_entry(excinfo.traceback[-2]) + lines = reprtb.lines + last_p = FormattedExcinfo(style="short") + last_reprtb = last_p.repr_traceback_entry(excinfo.traceback[-1], excinfo) + last_lines = last_reprtb.lines + monkeypatch.undo() + basename = py.path.local(mod.__file__).basename + assert lines[0] == ' func1()' + + assert last_lines[0] == ' raise ValueError("hello")' + assert last_lines[1] == 'E ValueError: hello' + + def test_repr_traceback_and_excinfo(self, importasmod): + mod = importasmod(""" + def f(x): + raise ValueError(x) + def entry(): + f(0) + """) + excinfo = py.test.raises(ValueError, mod.entry) + + for style in ("long", "short"): + p = FormattedExcinfo(style=style) + reprtb = p.repr_traceback(excinfo) + assert len(reprtb.reprentries) == 2 + assert reprtb.style == style + assert not reprtb.extraline + repr = p.repr_excinfo(excinfo) + assert repr.reprtraceback + assert len(repr.reprtraceback.reprentries) == len(reprtb.reprentries) + assert repr.reprcrash.path.endswith("mod.py") + assert repr.reprcrash.message == "ValueError: 0" + + def test_repr_traceback_with_invalid_cwd(self, importasmod, monkeypatch): + mod = importasmod(""" + def f(x): + raise ValueError(x) + def entry(): + f(0) + """) + excinfo = py.test.raises(ValueError, mod.entry) + + p = FormattedExcinfo() + def raiseos(): + raise OSError(2) + monkeypatch.setattr(py.std.os, 'getcwd', raiseos) + assert p._makepath(__file__) == __file__ + reprtb = p.repr_traceback(excinfo) + + def test_repr_excinfo_addouterr(self, importasmod): + mod = importasmod(""" + def entry(): + raise ValueError() + """) + excinfo = py.test.raises(ValueError, mod.entry) + repr = excinfo.getrepr() + repr.addsection("title", "content") + twmock = TWMock() + repr.toterminal(twmock) + assert twmock.lines[-1] == "content" + assert twmock.lines[-2] == ("-", "title") + + def test_repr_excinfo_reprcrash(self, importasmod): + mod = importasmod(""" + def entry(): + raise ValueError() + """) + excinfo = py.test.raises(ValueError, mod.entry) + repr = excinfo.getrepr() + assert repr.reprcrash.path.endswith("mod.py") + assert repr.reprcrash.lineno == 3 + assert repr.reprcrash.message == "ValueError" + assert str(repr.reprcrash).endswith("mod.py:3: ValueError") + + def test_repr_traceback_recursion(self, importasmod): + mod = importasmod(""" + def rec2(x): + return rec1(x+1) + def rec1(x): + return rec2(x-1) + def entry(): + rec1(42) + """) + excinfo = py.test.raises(RuntimeError, mod.entry) + + for style in ("short", "long", "no"): + p = FormattedExcinfo(style="short") + reprtb = p.repr_traceback(excinfo) + assert reprtb.extraline == "!!! Recursion detected (same locals & position)" + assert str(reprtb) + + def test_tb_entry_AssertionError(self, importasmod): + # probably this test is a bit redundant + # as py/magic/testing/test_assertion.py + # already tests correctness of + # assertion-reinterpretation logic + mod = importasmod(""" + def somefunc(): + x = 1 + assert x == 2 + """) + excinfo = py.test.raises(AssertionError, mod.somefunc) + + p = FormattedExcinfo() + reprentry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo) + lines = reprentry.lines + assert lines[-1] == "E assert 1 == 2" + + def test_reprexcinfo_getrepr(self, importasmod): + mod = importasmod(""" + def f(x): + raise ValueError(x) + def entry(): + f(0) + """) + excinfo = py.test.raises(ValueError, mod.entry) + + for style in ("short", "long", "no"): + for showlocals in (True, False): + repr = excinfo.getrepr(style=style, showlocals=showlocals) + assert isinstance(repr, ReprExceptionInfo) + assert repr.reprtraceback.style == style + + def test_reprexcinfo_unicode(self): + from py._code.code import TerminalRepr + class MyRepr(TerminalRepr): + def toterminal(self, tw): + tw.line(py.builtin._totext("я", "utf-8")) + x = py.builtin._totext(MyRepr()) + assert x == py.builtin._totext("я", "utf-8") + + def test_toterminal_long(self, importasmod): + mod = importasmod(""" + def g(x): + raise ValueError(x) + def f(): + g(3) + """) + excinfo = py.test.raises(ValueError, mod.f) + excinfo.traceback = excinfo.traceback.filter() + repr = excinfo.getrepr() + tw = TWMock() + repr.toterminal(tw) + assert tw.lines[0] == "" + tw.lines.pop(0) + assert tw.lines[0] == " def f():" + assert tw.lines[1] == "> g(3)" + assert tw.lines[2] == "" + assert tw.lines[3].endswith("mod.py:5: ") + assert tw.lines[4] == ("_ ", None) + assert tw.lines[5] == "" + assert tw.lines[6] == " def g(x):" + assert tw.lines[7] == "> raise ValueError(x)" + assert tw.lines[8] == "E ValueError: 3" + assert tw.lines[9] == "" + assert tw.lines[10].endswith("mod.py:3: ValueError") + + def test_toterminal_long_missing_source(self, importasmod, tmpdir): + mod = importasmod(""" + def g(x): + raise ValueError(x) + def f(): + g(3) + """) + excinfo = py.test.raises(ValueError, mod.f) + tmpdir.join('mod.py').remove() + excinfo.traceback = excinfo.traceback.filter() + repr = excinfo.getrepr() + tw = TWMock() + repr.toterminal(tw) + assert tw.lines[0] == "" + tw.lines.pop(0) + assert tw.lines[0] == "> ???" + assert tw.lines[1] == "" + assert tw.lines[2].endswith("mod.py:5: ") + assert tw.lines[3] == ("_ ", None) + assert tw.lines[4] == "" + assert tw.lines[5] == "> ???" + assert tw.lines[6] == "E ValueError: 3" + assert tw.lines[7] == "" + assert tw.lines[8].endswith("mod.py:3: ValueError") + + def test_toterminal_long_incomplete_source(self, importasmod, tmpdir): + mod = importasmod(""" + def g(x): + raise ValueError(x) + def f(): + g(3) + """) + excinfo = py.test.raises(ValueError, mod.f) + tmpdir.join('mod.py').write('asdf') + excinfo.traceback = excinfo.traceback.filter() + repr = excinfo.getrepr() + tw = TWMock() + repr.toterminal(tw) + assert tw.lines[0] == "" + tw.lines.pop(0) + assert tw.lines[0] == "> ???" + assert tw.lines[1] == "" + assert tw.lines[2].endswith("mod.py:5: ") + assert tw.lines[3] == ("_ ", None) + assert tw.lines[4] == "" + assert tw.lines[5] == "> ???" + assert tw.lines[6] == "E ValueError: 3" + assert tw.lines[7] == "" + assert tw.lines[8].endswith("mod.py:3: ValueError") + + def test_toterminal_long_filenames(self, importasmod): + mod = importasmod(""" + def f(): + raise ValueError() + """) + excinfo = py.test.raises(ValueError, mod.f) + tw = TWMock() + path = py.path.local(mod.__file__) + old = path.dirpath().chdir() + try: + repr = excinfo.getrepr(abspath=False) + repr.toterminal(tw) + line = tw.lines[-1] + x = py.path.local().bestrelpath(path) + if len(x) < len(str(path)): + assert line == "mod.py:3: ValueError" + + repr = excinfo.getrepr(abspath=True) + repr.toterminal(tw) + line = tw.lines[-1] + assert line == "%s:3: ValueError" %(path,) + finally: + old.chdir() + + @py.test.mark.multi(reproptions=[ + {'style': style, 'showlocals': showlocals, + 'funcargs': funcargs, 'tbfilter': tbfilter + } for style in ("long", "short", "no") + for showlocals in (True, False) + for tbfilter in (True, False) + for funcargs in (True, False)]) + def test_format_excinfo(self, importasmod, reproptions): + mod = importasmod(""" + def g(x): + raise ValueError(x) + def f(): + g(3) + """) + excinfo = py.test.raises(ValueError, mod.f) + tw = py.io.TerminalWriter(stringio=True) + repr = excinfo.getrepr(**reproptions) + repr.toterminal(tw) + assert tw.stringio.getvalue() + + + def test_native_style(self): + excinfo = self.excinfo_from_exec(""" + assert 0 + """) + repr = excinfo.getrepr(style='native') + assert "assert 0" in str(repr.reprcrash) + s = str(repr) + assert s.startswith('Traceback (most recent call last):\n File') + assert s.endswith('\nAssertionError: assert 0') + assert 'exec (source.compile())' in s + # python 2.4 fails to get the source line for the assert + if py.std.sys.version_info >= (2, 5): + assert s.count('assert 0') == 2 + + def test_traceback_repr_style(self, importasmod): + mod = importasmod(""" + def f(): + g() + def g(): + h() + def h(): + i() + def i(): + raise ValueError() + """) + excinfo = py.test.raises(ValueError, mod.f) + excinfo.traceback = excinfo.traceback.filter() + excinfo.traceback[1].set_repr_style("short") + excinfo.traceback[2].set_repr_style("short") + r = excinfo.getrepr(style="long") + tw = TWMock() + r.toterminal(tw) + for line in tw.lines: print (line) + assert tw.lines[0] == "" + assert tw.lines[1] == " def f():" + assert tw.lines[2] == "> g()" + assert tw.lines[3] == "" + assert tw.lines[4].endswith("mod.py:3: ") + assert tw.lines[5] == ("_ ", None) + assert tw.lines[6].endswith("in g") + assert tw.lines[7] == " h()" + assert tw.lines[8].endswith("in h") + assert tw.lines[9] == " i()" + assert tw.lines[10] == ("_ ", None) + assert tw.lines[11] == "" + assert tw.lines[12] == " def i():" + assert tw.lines[13] == "> raise ValueError()" + assert tw.lines[14] == "E ValueError" + assert tw.lines[15] == "" + assert tw.lines[16].endswith("mod.py:9: ValueError") diff --git a/tests/wpt/web-platform-tests/tools/py/testing/code/test_source.py b/tests/wpt/web-platform-tests/tools/py/testing/code/test_source.py new file mode 100644 index 00000000000..830de2c95de --- /dev/null +++ b/tests/wpt/web-platform-tests/tools/py/testing/code/test_source.py @@ -0,0 +1,651 @@ +from py.code import Source +import py +import sys + +from py._code.source import _ast +if _ast is not None: + astonly = py.test.mark.nothing +else: + astonly = py.test.mark.xfail("True", reason="only works with AST-compile") + +failsonjython = py.test.mark.xfail("sys.platform.startswith('java')") + +def test_source_str_function(): + x = Source("3") + assert str(x) == "3" + + x = Source(" 3") + assert str(x) == "3" + + x = Source(""" + 3 + """, rstrip=False) + assert str(x) == "\n3\n " + + x = Source(""" + 3 + """, rstrip=True) + assert str(x) == "\n3" + +def test_unicode(): + try: + unicode + except NameError: + return + x = Source(unicode("4")) + assert str(x) == "4" + co = py.code.compile(unicode('u"\xc3\xa5"', 'utf8'), mode='eval') + val = eval(co) + assert isinstance(val, unicode) + +def test_source_from_function(): + source = py.code.Source(test_source_str_function) + assert str(source).startswith('def test_source_str_function():') + +def test_source_from_method(): + class TestClass: + def test_method(self): + pass + source = py.code.Source(TestClass().test_method) + assert source.lines == ["def test_method(self):", + " pass"] + +def test_source_from_lines(): + lines = ["a \n", "b\n", "c"] + source = py.code.Source(lines) + assert source.lines == ['a ', 'b', 'c'] + +def test_source_from_inner_function(): + def f(): + pass + source = py.code.Source(f, deindent=False) + assert str(source).startswith(' def f():') + source = py.code.Source(f) + assert str(source).startswith('def f():') + +def test_source_putaround_simple(): + source = Source("raise ValueError") + source = source.putaround( + "try:", """\ + except ValueError: + x = 42 + else: + x = 23""") + assert str(source)=="""\ +try: + raise ValueError +except ValueError: + x = 42 +else: + x = 23""" + +def test_source_putaround(): + source = Source() + source = source.putaround(""" + if 1: + x=1 + """) + assert str(source).strip() == "if 1:\n x=1" + +def test_source_strips(): + source = Source("") + assert source == Source() + assert str(source) == '' + assert source.strip() == source + +def test_source_strip_multiline(): + source = Source() + source.lines = ["", " hello", " "] + source2 = source.strip() + assert source2.lines == [" hello"] + +def test_syntaxerror_rerepresentation(): + ex = py.test.raises(SyntaxError, py.code.compile, 'xyz xyz') + assert ex.value.lineno == 1 + assert ex.value.offset in (4,7) # XXX pypy/jython versus cpython? + assert ex.value.text.strip(), 'x x' + +def test_isparseable(): + assert Source("hello").isparseable() + assert Source("if 1:\n pass").isparseable() + assert Source(" \nif 1:\n pass").isparseable() + assert not Source("if 1:\n").isparseable() + assert not Source(" \nif 1:\npass").isparseable() + assert not Source(chr(0)).isparseable() + +class TestAccesses: + source = Source("""\ + def f(x): + pass + def g(x): + pass + """) + def test_getrange(self): + x = self.source[0:2] + assert x.isparseable() + assert len(x.lines) == 2 + assert str(x) == "def f(x):\n pass" + + def test_getline(self): + x = self.source[0] + assert x == "def f(x):" + + def test_len(self): + assert len(self.source) == 4 + + def test_iter(self): + l = [x for x in self.source] + assert len(l) == 4 + +class TestSourceParsingAndCompiling: + source = Source("""\ + def f(x): + assert (x == + 3 + + 4) + """).strip() + + def test_compile(self): + co = py.code.compile("x=3") + d = {} + exec (co, d) + assert d['x'] == 3 + + def test_compile_and_getsource_simple(self): + co = py.code.compile("x=3") + exec (co) + source = py.code.Source(co) + assert str(source) == "x=3" + + def test_compile_and_getsource_through_same_function(self): + def gensource(source): + return py.code.compile(source) + co1 = gensource(""" + def f(): + raise KeyError() + """) + co2 = gensource(""" + def f(): + raise ValueError() + """) + source1 = py.std.inspect.getsource(co1) + assert 'KeyError' in source1 + source2 = py.std.inspect.getsource(co2) + assert 'ValueError' in source2 + + def test_getstatement(self): + #print str(self.source) + ass = str(self.source[1:]) + for i in range(1, 4): + #print "trying start in line %r" % self.source[i] + s = self.source.getstatement(i) + #x = s.deindent() + assert str(s) == ass + + def test_getstatementrange_triple_quoted(self): + #print str(self.source) + source = Source("""hello(''' + ''')""") + s = source.getstatement(0) + assert s == str(source) + s = source.getstatement(1) + assert s == str(source) + + @astonly + def test_getstatementrange_within_constructs(self): + source = Source("""\ + try: + try: + raise ValueError + except SomeThing: + pass + finally: + 42 + """) + assert len(source) == 7 + # check all lineno's that could occur in a traceback + #assert source.getstatementrange(0) == (0, 7) + #assert source.getstatementrange(1) == (1, 5) + assert source.getstatementrange(2) == (2, 3) + assert source.getstatementrange(3) == (3, 4) + assert source.getstatementrange(4) == (4, 5) + #assert source.getstatementrange(5) == (0, 7) + assert source.getstatementrange(6) == (6, 7) + + def test_getstatementrange_bug(self): + source = Source("""\ + try: + x = ( + y + + z) + except: + pass + """) + assert len(source) == 6 + assert source.getstatementrange(2) == (1, 4) + + def test_getstatementrange_bug2(self): + source = Source("""\ + assert ( + 33 + == + [ + X(3, + b=1, c=2 + ), + ] + ) + """) + assert len(source) == 9 + assert source.getstatementrange(5) == (0, 9) + + def test_getstatementrange_ast_issue58(self): + source = Source("""\ + + def test_some(): + for a in [a for a in + CAUSE_ERROR]: pass + + x = 3 + """) + assert getstatement(2, source).lines == source.lines[2:3] + assert getstatement(3, source).lines == source.lines[3:4] + + @py.test.mark.skipif("sys.version_info < (2,6)") + def test_getstatementrange_out_of_bounds_py3(self): + source = Source("if xxx:\n from .collections import something") + r = source.getstatementrange(1) + assert r == (1,2) + + def test_getstatementrange_with_syntaxerror_issue7(self): + source = Source(":") + py.test.raises(SyntaxError, lambda: source.getstatementrange(0)) + + @py.test.mark.skipif("sys.version_info < (2,6)") + def test_compile_to_ast(self): + import ast + source = Source("x = 4") + mod = source.compile(flag=ast.PyCF_ONLY_AST) + assert isinstance(mod, ast.Module) + compile(mod, "<filename>", "exec") + + def test_compile_and_getsource(self): + co = self.source.compile() + py.builtin.exec_(co, globals()) + f(7) + excinfo = py.test.raises(AssertionError, "f(6)") + frame = excinfo.traceback[-1].frame + stmt = frame.code.fullsource.getstatement(frame.lineno) + #print "block", str(block) + assert str(stmt).strip().startswith('assert') + + def test_compilefuncs_and_path_sanity(self): + def check(comp, name): + co = comp(self.source, name) + if not name: + expected = "codegen %s:%d>" %(mypath, mylineno+2+1) + else: + expected = "codegen %r %s:%d>" % (name, mypath, mylineno+2+1) + fn = co.co_filename + assert fn.endswith(expected) + + mycode = py.code.Code(self.test_compilefuncs_and_path_sanity) + mylineno = mycode.firstlineno + mypath = mycode.path + + for comp in py.code.compile, py.code.Source.compile: + for name in '', None, 'my': + yield check, comp, name + + def test_offsetless_synerr(self): + py.test.raises(SyntaxError, py.code.compile, "lambda a,a: 0", mode='eval') + +def test_getstartingblock_singleline(): + class A: + def __init__(self, *args): + frame = sys._getframe(1) + self.source = py.code.Frame(frame).statement + + x = A('x', 'y') + + l = [i for i in x.source.lines if i.strip()] + assert len(l) == 1 + +def test_getstartingblock_multiline(): + class A: + def __init__(self, *args): + frame = sys._getframe(1) + self.source = py.code.Frame(frame).statement + + x = A('x', + 'y' \ + , + 'z') + + l = [i for i in x.source.lines if i.strip()] + assert len(l) == 4 + +def test_getline_finally(): + def c(): pass + excinfo = py.test.raises(TypeError, """ + teardown = None + try: + c(1) + finally: + if teardown: + teardown() + """) + source = excinfo.traceback[-1].statement + assert str(source).strip() == 'c(1)' + +def test_getfuncsource_dynamic(): + source = """ + def f(): + raise ValueError + + def g(): pass + """ + co = py.code.compile(source) + py.builtin.exec_(co, globals()) + assert str(py.code.Source(f)).strip() == 'def f():\n raise ValueError' + assert str(py.code.Source(g)).strip() == 'def g(): pass' + + +def test_getfuncsource_with_multine_string(): + def f(): + c = '''while True: + pass +''' + assert str(py.code.Source(f)).strip() == "def f():\n c = '''while True:\n pass\n'''" + + +def test_deindent(): + from py._code.source import deindent as deindent + assert deindent(['\tfoo', '\tbar', ]) == ['foo', 'bar'] + + def f(): + c = '''while True: + pass +''' + import inspect + lines = deindent(inspect.getsource(f).splitlines()) + assert lines == ["def f():", " c = '''while True:", " pass", "'''"] + + source = """ + def f(): + def g(): + pass + """ + lines = deindent(source.splitlines()) + assert lines == ['', 'def f():', ' def g():', ' pass', ' '] + +@py.test.mark.xfail("sys.version_info[:3] < (2,7,0) or " + "((3,0) <= sys.version_info[:2] < (3,2))") +def test_source_of_class_at_eof_without_newline(tmpdir): + # this test fails because the implicit inspect.getsource(A) below + # does not return the "x = 1" last line. + source = py.code.Source(''' + class A(object): + def method(self): + x = 1 + ''') + path = tmpdir.join("a.py") + path.write(source) + s2 = py.code.Source(tmpdir.join("a.py").pyimport().A) + assert str(source).strip() == str(s2).strip() + +if True: + def x(): + pass + +def test_getsource_fallback(): + from py._code.source import getsource + expected = """def x(): + pass""" + src = getsource(x) + assert src == expected + +def test_idem_compile_and_getsource(): + from py._code.source import getsource + expected = "def x(): pass" + co = py.code.compile(expected) + src = getsource(co) + assert src == expected + +def test_findsource_fallback(): + from py._code.source import findsource + src, lineno = findsource(x) + assert 'test_findsource_simple' in str(src) + assert src[lineno] == ' def x():' + +def test_findsource(): + from py._code.source import findsource + co = py.code.compile("""if 1: + def x(): + pass +""") + + src, lineno = findsource(co) + assert 'if 1:' in str(src) + + d = {} + eval(co, d) + src, lineno = findsource(d['x']) + assert 'if 1:' in str(src) + assert src[lineno] == " def x():" + + +def test_getfslineno(): + from py.code import getfslineno + + def f(x): + pass + + fspath, lineno = getfslineno(f) + + assert fspath.basename == "test_source.py" + assert lineno == py.code.getrawcode(f).co_firstlineno-1 # see findsource + + class A(object): + pass + + fspath, lineno = getfslineno(A) + + _, A_lineno = py.std.inspect.findsource(A) + assert fspath.basename == "test_source.py" + assert lineno == A_lineno + + assert getfslineno(3) == ("", -1) + class B: + pass + B.__name__ = "B2" + assert getfslineno(B)[1] == -1 + +def test_code_of_object_instance_with_call(): + class A: + pass + py.test.raises(TypeError, lambda: py.code.Source(A())) + class WithCall: + def __call__(self): + pass + + code = py.code.Code(WithCall()) + assert 'pass' in str(code.source()) + + class Hello(object): + def __call__(self): + pass + py.test.raises(TypeError, lambda: py.code.Code(Hello)) + + +def getstatement(lineno, source): + from py._code.source import getstatementrange_ast + source = py.code.Source(source, deindent=False) + ast, start, end = getstatementrange_ast(lineno, source) + return source[start:end] + +def test_oneline(): + source = getstatement(0, "raise ValueError") + assert str(source) == "raise ValueError" + +def test_comment_and_no_newline_at_end(): + from py._code.source import getstatementrange_ast + source = Source(['def test_basic_complex():', + ' assert 1 == 2', + '# vim: filetype=pyopencl:fdm=marker']) + ast, start, end = getstatementrange_ast(1, source) + assert end == 2 + +def test_oneline_and_comment(): + source = getstatement(0, "raise ValueError\n#hello") + assert str(source) == "raise ValueError" + +def test_comments(): + source = '''def test(): + "comment 1" + x = 1 + # comment 2 + # comment 3 + + assert False + +""" +comment 4 +""" +''' + for line in range(2,6): + assert str(getstatement(line, source)) == ' x = 1' + for line in range(6,10): + assert str(getstatement(line, source)) == ' assert False' + assert str(getstatement(10, source)) == '"""' + +def test_comment_in_statement(): + source = '''test(foo=1, + # comment 1 + bar=2) +''' + for line in range(1,3): + assert str(getstatement(line, source)) == \ + 'test(foo=1,\n # comment 1\n bar=2)' + +def test_single_line_else(): + source = getstatement(1, "if False: 2\nelse: 3") + assert str(source) == "else: 3" + +def test_single_line_finally(): + source = getstatement(1, "try: 1\nfinally: 3") + assert str(source) == "finally: 3" + +def test_issue55(): + source = ('def round_trip(dinp):\n assert 1 == dinp\n' + 'def test_rt():\n round_trip("""\n""")\n') + s = getstatement(3, source) + assert str(s) == ' round_trip("""\n""")' + + +def XXXtest_multiline(): + source = getstatement(0, """\ +raise ValueError( + 23 +) +x = 3 +""") + assert str(source) == "raise ValueError(\n 23\n)" + +class TestTry: + pytestmark = astonly + source = """\ +try: + raise ValueError +except Something: + raise IndexError(1) +else: + raise KeyError() +""" + + def test_body(self): + source = getstatement(1, self.source) + assert str(source) == " raise ValueError" + + def test_except_line(self): + source = getstatement(2, self.source) + assert str(source) == "except Something:" + + def test_except_body(self): + source = getstatement(3, self.source) + assert str(source) == " raise IndexError(1)" + + def test_else(self): + source = getstatement(5, self.source) + assert str(source) == " raise KeyError()" + +class TestTryFinally: + source = """\ +try: + raise ValueError +finally: + raise IndexError(1) +""" + + def test_body(self): + source = getstatement(1, self.source) + assert str(source) == " raise ValueError" + + def test_finally(self): + source = getstatement(3, self.source) + assert str(source) == " raise IndexError(1)" + + + +class TestIf: + pytestmark = astonly + source = """\ +if 1: + y = 3 +elif False: + y = 5 +else: + y = 7 +""" + + def test_body(self): + source = getstatement(1, self.source) + assert str(source) == " y = 3" + + def test_elif_clause(self): + source = getstatement(2, self.source) + assert str(source) == "elif False:" + + def test_elif(self): + source = getstatement(3, self.source) + assert str(source) == " y = 5" + + def test_else(self): + source = getstatement(5, self.source) + assert str(source) == " y = 7" + +def test_semicolon(): + s = """\ +hello ; pytest.skip() +""" + source = getstatement(0, s) + assert str(source) == s.strip() + +def test_def_online(): + s = """\ +def func(): raise ValueError(42) + +def something(): + pass +""" + source = getstatement(0, s) + assert str(source) == "def func(): raise ValueError(42)" + +def XXX_test_expression_multiline(): + source = """\ +something +''' +'''""" + result = getstatement(1, source) + assert str(result) == "'''\n'''" + |