##// 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 454 ((?P<sep>[\-:])
455 455 ((?P<endsess>~?\d+)/)?
456 456 (?P<end>\d+))?
457 """, re.VERBOSE)
457 $""", re.VERBOSE)
458 458
459 459 def extract_hist_ranges(ranges_str):
460 460 """Turn a string of history ranges into 3-tuples of (session, start, stop).
@@ -7,8 +7,13 b''
7 7 # the file COPYING, distributed as part of this software.
8 8 #*****************************************************************************
9 9
10 import re
11 import sys
12
10 13 import IPython.utils.io
11 14
15 coding_declaration = re.compile(r"#\s*coding[:=]\s*([-\w.]+)")
16
12 17 class Macro(object):
13 18 """Simple class to store the value of macros as strings.
14 19
@@ -20,9 +25,24 b' class Macro(object):'
20 25
21 26 def __init__(self,code):
22 27 """store the macro value, as a single string which can be executed"""
23 self.value = code.rstrip()+'\n'
24
28 lines = []
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 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 46 return self.value
27 47
28 48 def __repr__(self):
@@ -28,6 +28,7 b' import textwrap'
28 28 from cStringIO import StringIO
29 29 from getopt import getopt,GetoptError
30 30 from pprint import pformat
31 from xmlrpclib import ServerProxy
31 32
32 33 # cProfile was added in Python2.5
33 34 try:
@@ -1962,7 +1963,8 b' Currently the magic system has the following functions:\\n"""'
1962 1963
1963 1964 @testdec.skip_doctest
1964 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 1969 Usage:\\
1968 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 2016 You can view a macro's contents by explicitly printing it with:
2015 2017
2016 2018 'print macro_name'.
2017
2018 For one-off cases which DON'T contain magic function calls in them you
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]"""
2019
2020 """
2023 2021
2024 2022 opts,args = self.parse_options(parameter_s,'r',mode='list')
2025 2023 if not args: # List existing macros
@@ -2028,18 +2026,22 b' Currently the magic system has the following functions:\\n"""'
2028 2026 if len(args) == 1:
2029 2027 raise UsageError(
2030 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 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 2037 macro = Macro(lines)
2036 2038 self.shell.define_macro(name, macro)
2037 2039 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
2038 print 'Macro contents:'
2040 print '=== Macro contents: ==='
2039 2041 print macro,
2040 2042
2041 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 2046 Usage:\\
2045 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 2060 it asks for confirmation before overwriting existing files."""
2059 2061
2060 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 2064 if not fname.endswith('.py'):
2063 2065 fname += '.py'
2064 2066 if os.path.isfile(fname):
@@ -2066,30 +2068,54 b' Currently the magic system has the following functions:\\n"""'
2066 2068 if ans.lower() not in ['y','yes']:
2067 2069 print 'Operation cancelled.'
2068 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 2078 with open(fname,'w') as f:
2071 2079 f.write("# coding: utf-8\n")
2072 f.write(cmds.encode("utf-8"))
2080 f.write(cmds)
2073 2081 print 'The following commands were written to file `%s`:' % fname
2074 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 2111 def magic_pastebin(self, parameter_s = ''):
2077 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 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 2119 id = pbserver.pastes.newPaste("python", code)
2094 2120 return "http://paste.pocoo.org/show/" + id
2095 2121
General Comments 0
You need to be logged in to leave comments. Login now