Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow/python/framework/traceable_stack.py: 41%

41 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-03 07:57 +0000

1# Copyright 2015 The TensorFlow Authors. All Rights Reserved. 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14# ============================================================================== 

15"""A simple stack that associates filename and line numbers with each object.""" 

16 

17import inspect 

18 

19 

20class TraceableObject(object): 

21 """Wrap an object together with its the code definition location.""" 

22 

23 # Return codes for the set_filename_and_line_from_caller() method. 

24 SUCCESS, HEURISTIC_USED, FAILURE = (0, 1, 2) 

25 

26 def __init__(self, obj, filename=None, lineno=None): 

27 self.obj = obj 

28 self.filename = filename 

29 self.lineno = lineno 

30 

31 def set_filename_and_line_from_caller(self, offset=0): 

32 """Set filename and line using the caller's stack frame. 

33 

34 If the requested stack information is not available, a heuristic may 

35 be applied and self.HEURISTIC USED will be returned. If the heuristic 

36 fails then no change will be made to the filename and lineno members 

37 (None by default) and self.FAILURE will be returned. 

38 

39 Args: 

40 offset: Integer. If 0, the caller's stack frame is used. If 1, 

41 the caller's caller's stack frame is used. Larger values are 

42 permissible but if out-of-range (larger than the number of stack 

43 frames available) the outermost stack frame will be used. 

44 

45 Returns: 

46 TraceableObject.SUCCESS if appropriate stack information was found, 

47 TraceableObject.HEURISTIC_USED if the offset was larger than the stack, 

48 and TraceableObject.FAILURE if the stack was empty. 

49 """ 

50 retcode = self.SUCCESS 

51 frame = inspect.currentframe() 

52 # Offset is defined in "Args" as relative to the caller. We are one frame 

53 # beyond the caller. 

54 for _ in range(offset + 1): 

55 parent = frame.f_back 

56 if parent is None: 

57 # If the offset is too large then we use the largest offset possible. 

58 retcode = self.HEURISTIC_USED 

59 break 

60 frame = parent 

61 self.filename = frame.f_code.co_filename 

62 self.lineno = frame.f_lineno 

63 return retcode 

64 

65 def copy_metadata(self): 

66 """Return a TraceableObject like this one, but without the object.""" 

67 return self.__class__(None, filename=self.filename, lineno=self.lineno) 

68 

69 

70class TraceableStack(object): 

71 """A stack of TraceableObjects.""" 

72 

73 def __init__(self, existing_stack=None): 

74 """Constructor. 

75 

76 Args: 

77 existing_stack: [TraceableObject, ...] If provided, this object will 

78 set its new stack to a SHALLOW COPY of existing_stack. 

79 """ 

80 self._stack = existing_stack[:] if existing_stack else [] 

81 

82 def push_obj(self, obj, offset=0): 

83 """Add object to the stack and record its filename and line information. 

84 

85 Args: 

86 obj: An object to store on the stack. 

87 offset: Integer. If 0, the caller's stack frame is used. If 1, 

88 the caller's caller's stack frame is used. 

89 

90 Returns: 

91 TraceableObject.SUCCESS if appropriate stack information was found, 

92 TraceableObject.HEURISTIC_USED if the stack was smaller than expected, 

93 and TraceableObject.FAILURE if the stack was empty. 

94 """ 

95 traceable_obj = TraceableObject(obj) 

96 self._stack.append(traceable_obj) 

97 # Offset is defined in "Args" as relative to the caller. We are 1 frame 

98 # beyond the caller and need to compensate. 

99 return traceable_obj.set_filename_and_line_from_caller(offset + 1) 

100 

101 def pop_obj(self): 

102 """Remove last-inserted object and return it, without filename/line info.""" 

103 return self._stack.pop().obj 

104 

105 def peek_top_obj(self): 

106 """Return the most recent stored object.""" 

107 return self._stack[-1].obj 

108 

109 def peek_objs(self): 

110 """Return iterator over stored objects ordered newest to oldest.""" 

111 return (t_obj.obj for t_obj in reversed(self._stack)) 

112 

113 def peek_traceable_objs(self): 

114 """Return iterator over stored TraceableObjects ordered newest to oldest.""" 

115 return reversed(self._stack) 

116 

117 def __len__(self): 

118 """Return number of items on the stack, and used for truth-value testing.""" 

119 return len(self._stack) 

120 

121 def copy(self): 

122 """Return a copy of self referencing the same objects but in a new list. 

123 

124 This method is implemented to support thread-local stacks. 

125 

126 Returns: 

127 TraceableStack with a new list that holds existing objects. 

128 """ 

129 return TraceableStack(self._stack)