Defines a trace function that jumps from one place to another.
| 1963 | # command (aka. "Set next statement"). |
| 1964 | |
| 1965 | class JumpTracer: |
| 1966 | """Defines a trace function that jumps from one place to another.""" |
| 1967 | |
| 1968 | def __init__(self, function, jumpFrom, jumpTo, event='line', |
| 1969 | decorated=False): |
| 1970 | self.code = function.__code__ |
| 1971 | self.jumpFrom = jumpFrom |
| 1972 | self.jumpTo = jumpTo |
| 1973 | self.event = event |
| 1974 | self.firstLine = None if decorated else self.code.co_firstlineno |
| 1975 | self.done = False |
| 1976 | |
| 1977 | def trace(self, frame, event, arg): |
| 1978 | if self.done: |
| 1979 | return |
| 1980 | assert lineno_matches_lasti(frame) |
| 1981 | # frame.f_code.co_firstlineno is the first line of the decorator when |
| 1982 | # 'function' is decorated and the decorator may be written using |
| 1983 | # multiple physical lines when it is too long. Use the first line |
| 1984 | # trace event in 'function' to find the first line of 'function'. |
| 1985 | if (self.firstLine is None and frame.f_code == self.code and |
| 1986 | event == 'line'): |
| 1987 | self.firstLine = frame.f_lineno - 1 |
| 1988 | if (event == self.event and self.firstLine is not None and |
| 1989 | frame.f_lineno == self.firstLine + self.jumpFrom): |
| 1990 | f = frame |
| 1991 | while f is not None and f.f_code != self.code: |
| 1992 | f = f.f_back |
| 1993 | if f is not None: |
| 1994 | # Cope with non-integer self.jumpTo (because of |
| 1995 | # no_jump_to_non_integers below). |
| 1996 | try: |
| 1997 | frame.f_lineno = self.firstLine + self.jumpTo |
| 1998 | except TypeError: |
| 1999 | frame.f_lineno = self.jumpTo |
| 2000 | self.done = True |
| 2001 | return self.trace |
| 2002 | |
| 2003 | # This verifies the line-numbers-must-be-integers rule. |
| 2004 | def no_jump_to_non_integers(output): |
no outgoing calls
searching dependent graphs…