Context manager that removes irrelevant stack elements from traceback. * omits frames from modules that match `admin.traceback.shorten` * always keeps the first and last frame.
| 2245 | |
| 2246 | |
| 2247 | class shorten_traceback: |
| 2248 | """Context manager that removes irrelevant stack elements from traceback. |
| 2249 | |
| 2250 | * omits frames from modules that match `admin.traceback.shorten` |
| 2251 | * always keeps the first and last frame. |
| 2252 | """ |
| 2253 | |
| 2254 | __slots__ = () |
| 2255 | |
| 2256 | def __enter__(self) -> None: |
| 2257 | pass |
| 2258 | |
| 2259 | def __exit__( |
| 2260 | self, |
| 2261 | exc_type: type[BaseException] | None, |
| 2262 | exc_val: BaseException | None, |
| 2263 | exc_tb: types.TracebackType | None, |
| 2264 | ) -> None: |
| 2265 | if exc_val and exc_tb: |
| 2266 | exc_val.__traceback__ = self.shorten(exc_tb) |
| 2267 | |
| 2268 | @staticmethod |
| 2269 | def shorten(exc_tb: types.TracebackType) -> types.TracebackType: |
| 2270 | paths = config.get("admin.traceback.shorten") |
| 2271 | if not paths: |
| 2272 | return exc_tb |
| 2273 | |
| 2274 | exp = re.compile(".*(" + "|".join(paths) + ")") |
| 2275 | curr: types.TracebackType | None = exc_tb |
| 2276 | prev: types.TracebackType | None = None |
| 2277 | |
| 2278 | while curr: |
| 2279 | if prev is None: |
| 2280 | prev = curr # first frame |
| 2281 | elif not curr.tb_next: |
| 2282 | # always keep last frame |
| 2283 | prev.tb_next = curr |
| 2284 | prev = prev.tb_next |
| 2285 | elif not exp.match(curr.tb_frame.f_code.co_filename): |
| 2286 | # keep if module is not listed in config |
| 2287 | prev.tb_next = curr |
| 2288 | prev = curr |
| 2289 | curr = curr.tb_next |
| 2290 | |
| 2291 | # Uncomment to remove the first frame, which is something you don't want to keep |
| 2292 | # if it matches the regexes. Requires Python >=3.11. |
| 2293 | # if exc_tb.tb_next and exp.match(exc_tb.tb_frame.f_code.co_filename): |
| 2294 | # return exc_tb.tb_next |
| 2295 | |
| 2296 | return exc_tb |
| 2297 | |
| 2298 | |
| 2299 | def unzip(ls, nout): |
no outgoing calls