1import sys
2import os.path
3import inspect
4
5
6class NopLogger:
7
8    def __init__(self):
9        pass
10
11    def write(self, data):
12        pass
13
14    def flush(self):
15        pass
16
17    def close(self):
18        pass
19
20
21class StdoutLogger:
22
23    def __init__(self):
24        pass
25
26    def write(self, data):
27        print(data)
28
29    def flush(self):
30        pass
31
32    def close(self):
33        pass
34
35
36class FileLogger:
37
38    def __init__(self, name):
39        self.file = None
40        try:
41            name = os.path.abspath(name)
42            self.file = open(name, 'a')
43        except:
44            try:
45                self.file = open('formatters.log', 'a')
46            except:
47                pass
48
49    def write(self, data):
50        if self.file is not None:
51            print(data, file=self.file)
52        else:
53            print(data)
54
55    def flush(self):
56        if self.file is not None:
57            self.file.flush()
58
59    def close(self):
60        if self.file is not None:
61            self.file.close()
62            self.file = None
63
64# to enable logging:
65# define lldb.formatters.Logger._lldb_formatters_debug_level to any number greater than 0
66# if you define it to any value greater than 1, the log will be automatically flushed after each write (slower but should make sure most of the stuff makes it to the log even if we crash)
67# if you define it to any value greater than 2, the calling function's details will automatically be logged (even slower, but provides additional details)
68# if you need the log to go to a file instead of on screen, define
69# lldb.formatters.Logger._lldb_formatters_debug_filename to a valid
70# filename
71
72
73class Logger:
74
75    def __init__(self, autoflush=False, logcaller=False):
76        global _lldb_formatters_debug_level
77        global _lldb_formatters_debug_filename
78        self.autoflush = autoflush
79        want_log = False
80        try:
81            want_log = (_lldb_formatters_debug_level > 0)
82        except:
83            pass
84        if not (want_log):
85            self.impl = NopLogger()
86            return
87        want_file = False
88        try:
89            want_file = (_lldb_formatters_debug_filename is not None and _lldb_formatters_debug_filename !=
90                         '' and _lldb_formatters_debug_filename != 0)
91        except:
92            pass
93        if want_file:
94            self.impl = FileLogger(_lldb_formatters_debug_filename)
95        else:
96            self.impl = StdoutLogger()
97        try:
98            self.autoflush = (_lldb_formatters_debug_level > 1)
99        except:
100            self.autoflush = autoflush
101        want_caller_info = False
102        try:
103            want_caller_info = (_lldb_formatters_debug_level > 2)
104        except:
105            pass
106        if want_caller_info:
107            self._log_caller()
108
109    def _log_caller(self):
110        caller = inspect.stack()[2]
111        try:
112            if caller is not None and len(caller) > 3:
113                self.write('Logging from function ' + str(caller))
114            else:
115                self.write(
116                    'Caller info not available - Required caller logging not possible')
117        finally:
118            del caller  # needed per Python docs to avoid keeping objects alive longer than we care
119
120    def write(self, data):
121        self.impl.write(data)
122        if self.autoflush:
123            self.flush()
124
125    def __rshift__(self, data):
126        self.write(data)
127
128    def flush(self):
129        self.impl.flush()
130
131    def close(self):
132        self.impl.close()
133