1try:
2    try:
3        import uio as io
4        import usys as sys
5    except ImportError:
6        import io
7        import sys
8except ImportError:
9    print("SKIP")
10    raise SystemExit
11
12if hasattr(sys, "print_exception"):
13    print_exception = sys.print_exception
14else:
15    import traceback
16
17    print_exception = lambda e, f: traceback.print_exception(None, e, sys.exc_info()[2], file=f)
18
19
20def print_exc(e):
21    buf = io.StringIO()
22    print_exception(e, buf)
23    s = buf.getvalue()
24    for l in s.split("\n"):
25        # uPy on pyboard prints <stdin> as file, so remove filename.
26        if l.startswith("  File "):
27            l = l.split('"')
28            print(l[0], l[2])
29        # uPy and CPy tracebacks differ in that CPy prints a source line for
30        # each traceback entry. In this case, we know that offending line
31        # has 4-space indent, so filter it out.
32        elif not l.startswith("    "):
33            print(l)
34
35
36# basic exception message
37try:
38    raise Exception("msg")
39except Exception as e:
40    print("caught")
41    print_exc(e)
42
43# exception message with more than 1 source-code line
44def f():
45    g()
46
47
48def g():
49    raise Exception("fail")
50
51
52try:
53    f()
54except Exception as e:
55    print("caught")
56    print_exc(e)
57
58# Test that an exception propagated through a finally doesn't have a traceback added there
59try:
60    try:
61        f()
62    finally:
63        print("finally")
64except Exception as e:
65    print("caught")
66    print_exc(e)
67
68# Test that re-raising an exception doesn't add traceback info
69try:
70    try:
71        f()
72    except Exception as e:
73        print("reraise")
74        print_exc(e)
75        raise
76except Exception as e:
77    print("caught")
78    print_exc(e)
79
80# Here we have a function with lots of bytecode generated for a single source-line, and
81# there is an error right at the end of the bytecode.  It should report the correct line.
82def f():
83    f([1, 2], [1, 2], [1, 2], {1: 1, 1: 1, 1: 1, 1: 1, 1: 1, 1: 1, 1: f.X})
84    return 1
85
86
87try:
88    f()
89except Exception as e:
90    print_exc(e)
91
92# Test non-stream object passed as output object, only valid for uPy
93if hasattr(sys, "print_exception"):
94    try:
95        sys.print_exception(Exception, 1)
96        had_exception = False
97    except OSError:
98        had_exception = True
99    assert had_exception
100