A stack of TraceableObjects.
| 78 | |
| 79 | |
| 80 | class TraceableStack(object): |
| 81 | """A stack of TraceableObjects.""" |
| 82 | |
| 83 | def __init__(self, existing_stack=None): |
| 84 | """Constructor. |
| 85 | |
| 86 | Args: |
| 87 | existing_stack: [TraceableObject, ...] If provided, this object will |
| 88 | set its new stack to a SHALLOW COPY of existing_stack. |
| 89 | """ |
| 90 | self._stack = existing_stack[:] if existing_stack else [] |
| 91 | |
| 92 | def push_obj(self, obj, offset=0): |
| 93 | """Add object to the stack and record its filename and line information. |
| 94 | |
| 95 | Args: |
| 96 | obj: An object to store on the stack. |
| 97 | offset: Integer. If 0, the caller's stack frame is used. If 1, |
| 98 | the caller's caller's stack frame is used. |
| 99 | |
| 100 | Returns: |
| 101 | TraceableObject.SUCCESS if appropriate stack information was found, |
| 102 | TraceableObject.HEURISTIC_USED if the stack was smaller than expected, |
| 103 | and TraceableObject.FAILURE if the stack was empty. |
| 104 | """ |
| 105 | traceable_obj = TraceableObject(obj) |
| 106 | self._stack.append(traceable_obj) |
| 107 | # Offset is defined in "Args" as relative to the caller. We are 1 frame |
| 108 | # beyond the caller and need to compensate. |
| 109 | return traceable_obj.set_filename_and_line_from_caller(offset + 1) |
| 110 | |
| 111 | def pop_obj(self): |
| 112 | """Remove last-inserted object and return it, without filename/line info.""" |
| 113 | return self._stack.pop().obj |
| 114 | |
| 115 | def peek_top_obj(self): |
| 116 | """Return the most recent stored object.""" |
| 117 | return self._stack[-1].obj |
| 118 | |
| 119 | def peek_objs(self): |
| 120 | """Return iterator over stored objects ordered newest to oldest.""" |
| 121 | return (t_obj.obj for t_obj in reversed(self._stack)) |
| 122 | |
| 123 | def peek_traceable_objs(self): |
| 124 | """Return iterator over stored TraceableObjects ordered newest to oldest.""" |
| 125 | return reversed(self._stack) |
| 126 | |
| 127 | def __len__(self): |
| 128 | """Return number of items on the stack, and used for truth-value testing.""" |
| 129 | return len(self._stack) |
| 130 | |
| 131 | def copy(self): |
| 132 | """Return a copy of self referencing the same objects but in a new list. |
| 133 | |
| 134 | This method is implemented to support thread-local stacks. |
| 135 | |
| 136 | Returns: |
| 137 | TraceableStack with a new list that holds existing objects. |