sources for representation.py [rev. unknown]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
""" This file intends to gather all methods of representing
failures/tracebacks etc. which should be used among
all terminal-based reporters. This methods should be general,
to allow further use outside the pylib
"""
import py
from py.__.code import safe_repr
class Presenter(object):
    """ Class used for presentation of various objects,
    sharing common output style
    """
    def __init__(self, out, config):
        """ out is a file-like object (we can write to it)
        """
        assert hasattr(out, 'write')
        self.out = out
        self.config = config
    def repr_source(self, source, marker=">", marker_location=-1):
        """ This one represents piece of source with possible
        marker at requested position
        """
        if isinstance(source, str):
            # why the hell, string is iterable?
            source = source.split("\n")
        if marker_location < 0:
            marker_location += len(source)
            if marker_location < 0:
                marker_location = 0
        if marker_location >= len(source):
            marker_location = len(source) - 1
        for i in range(len(source)):
            if i == marker_location:
                prefix = marker + "   "
            else:
                prefix = "    "
            self.out.line(prefix + source[i])
    def repr_item_info(self, item):
        """ This method represents py.test.collect.Item info (path and module)
        """
        root = item.fspath 
        modpath = item._getmodpath() 
        try: 
            fn, lineno = item._getpathlineno() 
        except TypeError: 
            assert isinstance(item.parent, py.test.collect.Generator) 
            # a generative test yielded a non-callable 
            fn, lineno = item.parent._getpathlineno() 
        if root == fn:
            self.out.sep("_", "entrypoint: %s" %(modpath))
        else:
            self.out.sep("_", "entrypoint: %s %s" %(root.basename, modpath))
    def repr_failure_explanation(self, excinfo, source):
        try:
            s = str(source.getstatement(len(source)-1))
        except KeyboardInterrupt: 
            raise 
        except:
            try:
                s = str(source[-1])
            except IndexError:
                s = "<Cannot get source>"
        indent = " " * (4 + (len(s) - len(s.lstrip())))
        # get the real exception information out 
        lines = excinfo.exconly(tryshort=True).split('\n')
        self.out.line('>' + indent[:-1] + lines.pop(0))
        for x in lines:
            self.out.line(indent + x)
    def getentrysource(self, entry):
        try:
            source = entry.getsource()
        except py.error.ENOENT:
            source = py.code.Source("[failure to get at sourcelines from %r]\n" % entry)
        return source.deindent()
    def repr_locals(self, f_locals):
        if self.config.option.showlocals:
            self.out.sep('- ', 'locals')
            for name, value in f_locals.items():
                if name == '__builtins__': 
                    self.out.line("__builtins__ = <builtins>")
                else:
                    # This formatting could all be handled by the _repr() function, which is 
                    # only repr.Repr in disguise, so is very configurable.
                    str_repr = safe_repr._repr(value)
                    if len(str_repr) < 70 or not isinstance(value,
                                                (list, tuple, dict)):
                        self.out.line("%-10s = %s" %(name, str_repr))
                    else:
                        self.out.line("%-10s =\\" % (name,))
                        py.std.pprint.pprint(value, stream=self.out)
    def repr_failure_tblong(self, item, excinfo, traceback, out_err_reporter):
        if not self.config.option.nomagic and excinfo.errisinstance(RuntimeError):
            recursionindex = traceback.recursionindex()
        else:
            recursionindex = None
        last = traceback[-1]
        first = traceback[0]
        for index, entry in py.builtin.enumerate(traceback): 
            if entry == first:
                if item: 
                    self.repr_item_info(item) 
                    self.out.line()
            else: 
                self.out.line("")
            source = self.getentrysource(entry)
            firstsourceline = entry.getfirstlinesource()
            marker_location = entry.lineno - firstsourceline
            if entry == last: 
                self.repr_source(source, 'E', marker_location)
                self.repr_failure_explanation(excinfo, source) 
            else:
                self.repr_source(source, '>', marker_location)
            self.out.line("") 
            self.out.line("[%s:%d]" %(entry.path, entry.lineno+1))
            self.repr_locals(entry.locals)
            # trailing info 
            if entry == last:
                out_err_reporter() 
                self.out.sep("_")
            else: 
                self.out.sep("_ ")
                if index == recursionindex:
                    self.out.line("Recursion detected (same locals & position)")
                    self.out.sep("!")
                    break 
    def repr_failure_tbshort(self, item, excinfo, traceback, out_err_reporter):
        # print a Python-style short traceback
        if not self.config.option.nomagic and excinfo.errisinstance(RuntimeError):
            recursionindex = traceback.recursionindex()
        else:
            recursionindex = None
        last = traceback[-1]
        first = traceback[0]
        self.out.line()
        for index, entry in py.builtin.enumerate(traceback):
            path = entry.path.basename
            firstsourceline = entry.getfirstlinesource()
            relline = entry.lineno - firstsourceline
            self.out.line('  File "%s", line %d, in %s' % (
                path, entry.lineno+1, entry.name))
            try:
                source = entry.getsource().lines
            except py.error.ENOENT:
                source = ["?"]
            else:
                try:
                    if len(source) > 1:
                        source = source[relline]
                except IndexError:
                    source = []
            if entry == last:
                if source:
                    self.repr_source(source, 'E')
                self.repr_failure_explanation(excinfo, source) 
            else:
                if source:
                    self.repr_source(source, ' ')
            self.repr_locals(entry.locals) 
            # trailing info 
            if entry == last:
                out_err_reporter()
                self.out.sep("_")
            else: 
                if index == recursionindex:
                    self.out.line("Recursion detected (same locals & position)")
                    self.out.sep("!")
                    break 
    # the following is only used by the combination '--pdb --tb=no'
    repr_failure_tbno = repr_failure_tbshort