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 |
|
|
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, |
|
|
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, |
|
|
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 |
|
|
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