Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

""" 

Interactively tracing execution of a command 

""" 

from __future__ import print_function 

 

 

def trace(code, preparse=True): 

r""" 

Evaluate Sage code using the interactive tracer and return the 

result. The string ``code`` must be a valid expression 

enclosed in quotes (no assignments - the result of the expression 

is returned). In the Sage notebook this just raises a 

NotImplementedException. 

 

INPUT: 

 

 

- ``code`` - str 

 

- ``preparse`` - bool (default: True); if True, run 

expression through the Sage preparser. 

 

 

REMARKS: This function is extremely powerful! For example, if you 

want to step through each line of execution of, e.g., 

``factor(100)``, type 

 

:: 

 

sage: trace("factor(100)") # not tested 

 

then at the (Pdb) prompt type ``s`` (or ``step``), then press return 

over and over to step through every line of Python that is called 

in the course of the above computation. Type ``?`` at any time for 

help on how to use the debugger (e.g., ``l`` lists 11 lines around 

the current line; ``bt`` gives a back trace, etc.). 

 

Setting a break point: If you have some code in a file and would 

like to drop into the debugger at a given point, put the following 

code at that point in the file: 

 

``import pdb; pdb.set_trace()`` 

 

For an article on how to use the Python debugger, see 

http://www.onlamp.com/pub/a/python/2005/09/01/debugger.html 

 

TESTS: 

 

For tests we disable garbage collection, see :trac:`21258` :: 

 

sage: import gc 

sage: gc.disable() 

 

The only real way to test this is via pexpect spawning a 

sage subprocess that uses IPython:: 

 

sage: import pexpect 

sage: s = pexpect.spawn('sage') 

sage: _ = s.sendline("trace('print(factor(10))'); print(3+97)") 

sage: _ = s.expect('ipdb>', timeout=90) 

sage: _ = s.sendline("s"); _ = s.sendline("c"); 

sage: _ = s.expect('100', timeout=90) 

 

Seeing the ipdb prompt and the 2 \* 5 in the output below is a 

strong indication that the trace command worked correctly:: 

 

sage: print(s.before[s.before.find('--'):]) 

--... 

ipdb> c 

2 * 5 

 

We test what happens in notebook embedded mode:: 

 

sage: sage.plot.plot.EMBEDDED_MODE = True 

sage: trace('print(factor(10))') 

Traceback (most recent call last): 

... 

NotImplementedError: the trace command is not implemented in the Sage notebook; you must use the command line. 

 

Re-enable garbage collection:: 

 

sage: gc.enable() 

""" 

from sage.plot.plot import EMBEDDED_MODE 

if EMBEDDED_MODE: 

raise NotImplementedError("the trace command is not implemented in the Sage notebook; you must use the command line.") 

 

from IPython.core.debugger import Pdb 

pdb = Pdb() 

 

try: 

ipython = get_ipython() 

except NameError: 

raise NotImplementedError("the trace command can only be run from the Sage command-line") 

 

from sage.repl.preparse import preparse 

code = preparse(code) 

return pdb.run(code, ipython.user_ns) 

 

# this could also be useful; it drops 

# us into a debugger in an except block: 

# import pdb; pdb.post_mortem(sys.exc_info()[2])