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