##// END OF EJS Templates
Refactor code-finding logic, and use it for %save and %macro as well.
Thomas Kluyver -
Show More
@@ -454,7 +454,7 b' range_re = re.compile(r"""'
454 ((?P<sep>[\-:])
454 ((?P<sep>[\-:])
455 ((?P<endsess>~?\d+)/)?
455 ((?P<endsess>~?\d+)/)?
456 (?P<end>\d+))?
456 (?P<end>\d+))?
457 """, re.VERBOSE)
457 $""", re.VERBOSE)
458
458
459 def extract_hist_ranges(ranges_str):
459 def extract_hist_ranges(ranges_str):
460 """Turn a string of history ranges into 3-tuples of (session, start, stop).
460 """Turn a string of history ranges into 3-tuples of (session, start, stop).
@@ -7,8 +7,13 b''
7 # the file COPYING, distributed as part of this software.
7 # the file COPYING, distributed as part of this software.
8 #*****************************************************************************
8 #*****************************************************************************
9
9
10 import re
11 import sys
12
10 import IPython.utils.io
13 import IPython.utils.io
11
14
15 coding_declaration = re.compile(r"#\s*coding[:=]\s*([-\w.]+)")
16
12 class Macro(object):
17 class Macro(object):
13 """Simple class to store the value of macros as strings.
18 """Simple class to store the value of macros as strings.
14
19
@@ -20,9 +25,24 b' class Macro(object):'
20
25
21 def __init__(self,code):
26 def __init__(self,code):
22 """store the macro value, as a single string which can be executed"""
27 """store the macro value, as a single string which can be executed"""
23 self.value = code.rstrip()+'\n'
28 lines = []
24
29 enc = None
30 for line in code.splitlines():
31 coding_match = coding_declaration.match(line)
32 if coding_match:
33 enc = coding_match.group(1)
34 else:
35 lines.append(line)
36 code = "\n".join(lines)
37 if isinstance(code, bytes):
38 code = code.decode(enc or sys.getdefaultencoding())
39 self.value = code + '\n'
40
25 def __str__(self):
41 def __str__(self):
42 enc = sys.stdin.encoding or sys.getdefaultencoding()
43 return self.value.encode(enc, "replace")
44
45 def __unicode__(self):
26 return self.value
46 return self.value
27
47
28 def __repr__(self):
48 def __repr__(self):
@@ -28,6 +28,7 b' import textwrap'
28 from cStringIO import StringIO
28 from cStringIO import StringIO
29 from getopt import getopt,GetoptError
29 from getopt import getopt,GetoptError
30 from pprint import pformat
30 from pprint import pformat
31 from xmlrpclib import ServerProxy
31
32
32 # cProfile was added in Python2.5
33 # cProfile was added in Python2.5
33 try:
34 try:
@@ -1962,7 +1963,8 b' Currently the magic system has the following functions:\\n"""'
1962
1963
1963 @testdec.skip_doctest
1964 @testdec.skip_doctest
1964 def magic_macro(self,parameter_s = ''):
1965 def magic_macro(self,parameter_s = ''):
1965 """Define a set of input lines as a macro for future re-execution.
1966 """Define a macro for future re-execution. It can take ranges of history,
1967 filenames or string objects.
1966
1968
1967 Usage:\\
1969 Usage:\\
1968 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1970 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
@@ -2014,12 +2016,8 b' Currently the magic system has the following functions:\\n"""'
2014 You can view a macro's contents by explicitly printing it with:
2016 You can view a macro's contents by explicitly printing it with:
2015
2017
2016 'print macro_name'.
2018 'print macro_name'.
2017
2019
2018 For one-off cases which DON'T contain magic function calls in them you
2020 """
2019 can obtain similar results by explicitly executing slices from your
2020 input history with:
2021
2022 In [60]: exec In[44:48]+In[49]"""
2023
2021
2024 opts,args = self.parse_options(parameter_s,'r',mode='list')
2022 opts,args = self.parse_options(parameter_s,'r',mode='list')
2025 if not args: # List existing macros
2023 if not args: # List existing macros
@@ -2028,18 +2026,22 b' Currently the magic system has the following functions:\\n"""'
2028 if len(args) == 1:
2026 if len(args) == 1:
2029 raise UsageError(
2027 raise UsageError(
2030 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
2028 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
2031 name, ranges = args[0], " ".join(args[1:])
2029 name, codefrom = args[0], " ".join(args[1:])
2032
2030
2033 #print 'rng',ranges # dbg
2031 #print 'rng',ranges # dbg
2034 lines = self.extract_input_lines(ranges,'r' in opts)
2032 try:
2033 lines = self._get_some_code(codefrom, 'r' in opts)
2034 except (ValueError, TypeError) as e:
2035 print e.args[0]
2036 return
2035 macro = Macro(lines)
2037 macro = Macro(lines)
2036 self.shell.define_macro(name, macro)
2038 self.shell.define_macro(name, macro)
2037 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
2039 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
2038 print 'Macro contents:'
2040 print '=== Macro contents: ==='
2039 print macro,
2041 print macro,
2040
2042
2041 def magic_save(self,parameter_s = ''):
2043 def magic_save(self,parameter_s = ''):
2042 """Save a set of lines to a given filename.
2044 """Save a set of lines or a macro to a given filename.
2043
2045
2044 Usage:\\
2046 Usage:\\
2045 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
2047 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
@@ -2058,7 +2060,7 b' Currently the magic system has the following functions:\\n"""'
2058 it asks for confirmation before overwriting existing files."""
2060 it asks for confirmation before overwriting existing files."""
2059
2061
2060 opts,args = self.parse_options(parameter_s,'r',mode='list')
2062 opts,args = self.parse_options(parameter_s,'r',mode='list')
2061 fname,ranges = args[0], " ".join(args[1:])
2063 fname, codefrom = args[0], " ".join(args[1:])
2062 if not fname.endswith('.py'):
2064 if not fname.endswith('.py'):
2063 fname += '.py'
2065 fname += '.py'
2064 if os.path.isfile(fname):
2066 if os.path.isfile(fname):
@@ -2066,30 +2068,54 b' Currently the magic system has the following functions:\\n"""'
2066 if ans.lower() not in ['y','yes']:
2068 if ans.lower() not in ['y','yes']:
2067 print 'Operation cancelled.'
2069 print 'Operation cancelled.'
2068 return
2070 return
2069 cmds = self.extract_input_lines(ranges, 'r' in opts)
2071 try:
2072 cmds = self._get_some_code(codefrom, 'r' in opts)
2073 except (TypeError, ValueError) as e:
2074 print e.args[0]
2075 return
2076 if isinstance(cmds, unicode):
2077 cmds = cmds.encode("utf-8")
2070 with open(fname,'w') as f:
2078 with open(fname,'w') as f:
2071 f.write("# coding: utf-8\n")
2079 f.write("# coding: utf-8\n")
2072 f.write(cmds.encode("utf-8"))
2080 f.write(cmds)
2073 print 'The following commands were written to file `%s`:' % fname
2081 print 'The following commands were written to file `%s`:' % fname
2074 print cmds
2082 print cmds
2083
2084 def _get_some_code(self, target, raw=True):
2085 """Utility function to get a code string, either from a range of
2086 history lines, a filename, or an expression evaluating to a string or a
2087 Macro in the user namespace.
2088
2089 ValueError is raised if none are found, and TypeError if it evaluates to
2090 an object of another type. In each case, .args[0] is a printable
2091 message."""
2092 code = self.extract_input_lines(target, raw=raw) # Grab history
2093 if code:
2094 return code
2095 if os.path.isfile(target): # Read file
2096 return open(target, "r").read()
2097
2098 try: # User namespace
2099 codeobj = eval(target, self.shell.user_ns)
2100 except Exception:
2101 raise ValueError(("'%s' was not found in history, as a file, nor in"
2102 " the user namespace.") % target)
2103 if isinstance(codeobj, basestring):
2104 return codeobj
2105 elif isinstance(codeobj, Macro):
2106 return codeobj.value
2107
2108 raise TypeError("%s is neither a string nor a macro." % target,
2109 codeobj)
2075
2110
2076 def magic_pastebin(self, parameter_s = ''):
2111 def magic_pastebin(self, parameter_s = ''):
2077 """Upload code to the 'Lodge it' paste bin, returning the URL."""
2112 """Upload code to the 'Lodge it' paste bin, returning the URL."""
2113 try:
2114 code = self._get_some_code(parameter_s)
2115 except (ValueError, TypeError) as e:
2116 print e.args[0]
2117 return
2078 pbserver = ServerProxy('http://paste.pocoo.org/xmlrpc/')
2118 pbserver = ServerProxy('http://paste.pocoo.org/xmlrpc/')
2079 code = self.extract_input_lines(parameter_s)
2080 if not code:
2081 try:
2082 codeobj = eval(parameter_s, self.shell.user_ns)
2083 except Exception:
2084 codeobj = None
2085 if isinstance(codeobj, str):
2086 code = codeobj
2087 elif isinstance(codeobj, Macro):
2088 code = codeobj.value
2089 else:
2090 print parameter_s, ("was not recognised as a history range, nor"
2091 " as a string or macro.")
2092 return
2093 id = pbserver.pastes.newPaste("python", code)
2119 id = pbserver.pastes.newPaste("python", code)
2094 return "http://paste.pocoo.org/show/" + id
2120 return "http://paste.pocoo.org/show/" + id
2095
2121
General Comments 0
You need to be logged in to leave comments. Login now