Wrap an object together with its the code definition location.
| 22 | |
| 23 | |
| 24 | class TraceableObject(object): |
| 25 | """Wrap an object together with its the code definition location.""" |
| 26 | |
| 27 | # Return codes for the set_filename_and_line_from_caller() method. |
| 28 | SUCCESS, HEURISTIC_USED, FAILURE = (0, 1, 2) |
| 29 | |
| 30 | def __init__(self, obj, filename=None, lineno=None): |
| 31 | self.obj = obj |
| 32 | self.filename = filename |
| 33 | self.lineno = lineno |
| 34 | |
| 35 | def set_filename_and_line_from_caller(self, offset=0): |
| 36 | """Set filename and line using the caller's stack frame. |
| 37 | |
| 38 | If the requested stack information is not available, a heuristic may |
| 39 | be applied and self.HEURISTIC USED will be returned. If the heuristic |
| 40 | fails then no change will be made to the filename and lineno members |
| 41 | (None by default) and self.FAILURE will be returned. |
| 42 | |
| 43 | Args: |
| 44 | offset: Integer. If 0, the caller's stack frame is used. If 1, |
| 45 | the caller's caller's stack frame is used. Larger values are |
| 46 | permissible but if out-of-range (larger than the number of stack |
| 47 | frames available) the outermost stack frame will be used. |
| 48 | |
| 49 | Returns: |
| 50 | TraceableObject.SUCCESS if appropriate stack information was found, |
| 51 | TraceableObject.HEURISTIC_USED if the offset was larger than the stack, |
| 52 | and TraceableObject.FAILURE if the stack was empty. |
| 53 | """ |
| 54 | # Offset is defined in "Args" as relative to the caller. We are one frame |
| 55 | # beyond the caller. |
| 56 | local_offset = offset + 1 |
| 57 | |
| 58 | frame_records = tf_stack.extract_stack( |
| 59 | limit=local_offset + 1) |
| 60 | if not frame_records: |
| 61 | return self.FAILURE |
| 62 | if len(frame_records) > local_offset: |
| 63 | frame = frame_records[len(frame_records) - (local_offset + 1)] |
| 64 | self.filename = frame.filename |
| 65 | self.lineno = frame.lineno |
| 66 | return self.SUCCESS |
| 67 | else: |
| 68 | # If the offset is too large then we use the largest offset possible, |
| 69 | # meaning we use the outermost stack frame at index 0. |
| 70 | frame = frame_records[0] |
| 71 | self.filename = frame.filename |
| 72 | self.lineno = frame.lineno |
| 73 | return self.HEURISTIC_USED |
| 74 | |
| 75 | def copy_metadata(self): |
| 76 | """Return a TraceableObject like this one, but without the object.""" |
| 77 | return self.__class__(None, filename=self.filename, lineno=self.lineno) |
| 78 | |
| 79 | |
| 80 | class TraceableStack(object): |