Generic Python debugger base class. This class takes care of details of the trace facility; a derived class should implement user interaction. The standard debugger class (pdb.Pdb) is an example. The optional skip argument must be an iterable of glob-style module name patterns.
| 178 | |
| 179 | |
| 180 | class Bdb: |
| 181 | """Generic Python debugger base class. |
| 182 | |
| 183 | This class takes care of details of the trace facility; |
| 184 | a derived class should implement user interaction. |
| 185 | The standard debugger class (pdb.Pdb) is an example. |
| 186 | |
| 187 | The optional skip argument must be an iterable of glob-style |
| 188 | module name patterns. The debugger will not step into frames |
| 189 | that originate in a module that matches one of these patterns. |
| 190 | Whether a frame is considered to originate in a certain module |
| 191 | is determined by the __name__ in the frame globals. |
| 192 | """ |
| 193 | |
| 194 | def __init__(self, skip=None, backend='settrace'): |
| 195 | self.skip = set(skip) if skip else None |
| 196 | self.breaks = {} |
| 197 | self.fncache = {} |
| 198 | self.frame_trace_lines_opcodes = {} |
| 199 | self.frame_returning = None |
| 200 | self.trace_opcodes = False |
| 201 | self.enterframe = None |
| 202 | self.cmdframe = None |
| 203 | self.cmdlineno = None |
| 204 | self.code_linenos = weakref.WeakKeyDictionary() |
| 205 | self.backend = backend |
| 206 | if backend == 'monitoring': |
| 207 | self.monitoring_tracer = _MonitoringTracer() |
| 208 | elif backend == 'settrace': |
| 209 | self.monitoring_tracer = None |
| 210 | else: |
| 211 | raise ValueError(f"Invalid backend '{backend}'") |
| 212 | |
| 213 | self._load_breaks() |
| 214 | |
| 215 | def canonic(self, filename): |
| 216 | """Return canonical form of filename. |
| 217 | |
| 218 | For real filenames, the canonical form is a case-normalized (on |
| 219 | case insensitive filesystems) absolute path. 'Filenames' with |
| 220 | angle brackets, such as "<stdin>", generated in interactive |
| 221 | mode, are returned unchanged. |
| 222 | """ |
| 223 | if filename == "<" + filename[1:-1] + ">": |
| 224 | return filename |
| 225 | canonic = self.fncache.get(filename) |
| 226 | if not canonic: |
| 227 | canonic = os.path.abspath(filename) |
| 228 | canonic = os.path.normcase(canonic) |
| 229 | self.fncache[filename] = canonic |
| 230 | return canonic |
| 231 | |
| 232 | def start_trace(self): |
| 233 | if self.monitoring_tracer: |
| 234 | self.monitoring_tracer.start_trace(self.trace_dispatch) |
| 235 | else: |
| 236 | sys.settrace(self.trace_dispatch) |
| 237 |