]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/tools/build/src/build/errors.py
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / tools / build / src / build / errors.py
1 # Status: being written afresh by Vladimir Prus
2
3 # Copyright 2007 Vladimir Prus
4 # Distributed under the Boost Software License, Version 1.0.
5 # (See accompanying file LICENSE.txt or https://www.bfgroup.xyz/b2/LICENSE.txt)
6
7 # This file is supposed to implement error reporting for Boost.Build.
8 # Experience with jam version has shown that printing full backtrace
9 # on each error is buffling. Further, for errors printed after parsing --
10 # during target building, the stacktrace does not even mention what
11 # target is being built.
12
13 # This module implements explicit contexts -- where other code can
14 # communicate which projects/targets are being built, and error
15 # messages will show those contexts. For programming errors,
16 # Python assertions are to be used.
17
18 import bjam
19 import traceback
20 import sys
21
22 def format(message, prefix=""):
23 parts = str(message).split("\n")
24 return "\n".join(prefix+p for p in parts)
25
26
27 class Context:
28
29 def __init__(self, message, nested=None):
30 self.message_ = message
31 self.nested_ = nested
32
33 def report(self, indent=""):
34 print indent + " -", self.message_
35 if self.nested_:
36 print indent + " declared at:"
37 for n in self.nested_:
38 n.report(indent + " ")
39
40 class JamfileContext:
41
42 def __init__(self):
43 raw = bjam.backtrace()
44 self.raw_ = raw
45
46 def report(self, indent=""):
47 for r in self.raw_:
48 print indent + " - %s:%s" % (r[0], r[1])
49
50 class ExceptionWithUserContext(Exception):
51
52 def __init__(self, message, context,
53 original_exception=None, original_tb=None, stack=None):
54 Exception.__init__(self, message)
55 self.context_ = context
56 self.original_exception_ = original_exception
57 self.original_tb_ = original_tb
58 self.stack_ = stack
59
60 def report(self):
61 print "error:", self.args[0]
62 if self.original_exception_:
63 print format(str(self.original_exception_), " ")
64 print
65 print " error context (most recent first):"
66 for c in self.context_[::-1]:
67 c.report()
68 print
69 if "--stacktrace" in bjam.variable("ARGV"):
70 if self.original_tb_:
71 traceback.print_tb(self.original_tb_)
72 elif self.stack_:
73 for l in traceback.format_list(self.stack_):
74 print l,
75 else:
76 print " use the '--stacktrace' option to get Python stacktrace"
77 print
78
79 def user_error_checkpoint(callable):
80 def wrapper(self, *args):
81 errors = self.manager().errors()
82 try:
83 return callable(self, *args)
84 except ExceptionWithUserContext, e:
85 raise
86 except Exception, e:
87 errors.handle_stray_exception(e)
88 finally:
89 errors.pop_user_context()
90
91 return wrapper
92
93 class Errors:
94
95 def __init__(self):
96 self.contexts_ = []
97 self._count = 0
98
99 def count(self):
100 return self._count
101
102 def push_user_context(self, message, nested=None):
103 self.contexts_.append(Context(message, nested))
104
105 def pop_user_context(self):
106 del self.contexts_[-1]
107
108 def push_jamfile_context(self):
109 self.contexts_.append(JamfileContext())
110
111 def pop_jamfile_context(self):
112 del self.contexts_[-1]
113
114 def capture_user_context(self):
115 return self.contexts_[:]
116
117 def handle_stray_exception(self, e):
118 raise ExceptionWithUserContext("unexpected exception", self.contexts_[:],
119 e, sys.exc_info()[2])
120 def __call__(self, message):
121 self._count = self._count + 1
122 raise ExceptionWithUserContext(message, self.contexts_[:],
123 stack=traceback.extract_stack())
124
125
126 def nearest_user_location():
127 """
128 Returns:
129 tuple: the filename and line number of the nearest user location
130 """
131 bt = bjam.backtrace()
132 if not bt:
133 return None
134 last = bt[-1]
135 return last[0], last[1]