##// END OF EJS Templates
- Add \N escape for the actual prompt number, without any coloring.
fperez -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,588 +1,595 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Classes for handling input/output prompts.
3 Classes for handling input/output prompts.
4
4
5 $Id: Prompts.py 1850 2006-10-28 19:48:13Z fptest $"""
5 $Id: Prompts.py 2192 2007-04-01 20:51:06Z fperez $"""
6
6
7 #*****************************************************************************
7 #*****************************************************************************
8 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #*****************************************************************************
12 #*****************************************************************************
13
13
14 from IPython import Release
14 from IPython import Release
15 __author__ = '%s <%s>' % Release.authors['Fernando']
15 __author__ = '%s <%s>' % Release.authors['Fernando']
16 __license__ = Release.license
16 __license__ = Release.license
17 __version__ = Release.version
17 __version__ = Release.version
18
18
19 #****************************************************************************
19 #****************************************************************************
20 # Required modules
20 # Required modules
21 import __builtin__
21 import __builtin__
22 import os
22 import os
23 import socket
23 import socket
24 import sys
24 import sys
25 import time
25 import time
26
26
27 # IPython's own
27 # IPython's own
28 from IPython import ColorANSI
28 from IPython import ColorANSI
29 from IPython.Itpl import ItplNS
29 from IPython.Itpl import ItplNS
30 from IPython.ipstruct import Struct
30 from IPython.ipstruct import Struct
31 from IPython.macro import Macro
31 from IPython.macro import Macro
32 from IPython.genutils import *
32 from IPython.genutils import *
33
33
34 #****************************************************************************
34 #****************************************************************************
35 #Color schemes for Prompts.
35 #Color schemes for Prompts.
36
36
37 PromptColors = ColorANSI.ColorSchemeTable()
37 PromptColors = ColorANSI.ColorSchemeTable()
38 InputColors = ColorANSI.InputTermColors # just a shorthand
38 InputColors = ColorANSI.InputTermColors # just a shorthand
39 Colors = ColorANSI.TermColors # just a shorthand
39 Colors = ColorANSI.TermColors # just a shorthand
40
40
41 PromptColors.add_scheme(ColorANSI.ColorScheme(
41 PromptColors.add_scheme(ColorANSI.ColorScheme(
42 'NoColor',
42 'NoColor',
43 in_prompt = InputColors.NoColor, # Input prompt
43 in_prompt = InputColors.NoColor, # Input prompt
44 in_number = InputColors.NoColor, # Input prompt number
44 in_number = InputColors.NoColor, # Input prompt number
45 in_prompt2 = InputColors.NoColor, # Continuation prompt
45 in_prompt2 = InputColors.NoColor, # Continuation prompt
46 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
46 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
47
47
48 out_prompt = Colors.NoColor, # Output prompt
48 out_prompt = Colors.NoColor, # Output prompt
49 out_number = Colors.NoColor, # Output prompt number
49 out_number = Colors.NoColor, # Output prompt number
50
50
51 normal = Colors.NoColor # color off (usu. Colors.Normal)
51 normal = Colors.NoColor # color off (usu. Colors.Normal)
52 ))
52 ))
53
53
54 # make some schemes as instances so we can copy them for modification easily:
54 # make some schemes as instances so we can copy them for modification easily:
55 __PColLinux = ColorANSI.ColorScheme(
55 __PColLinux = ColorANSI.ColorScheme(
56 'Linux',
56 'Linux',
57 in_prompt = InputColors.Green,
57 in_prompt = InputColors.Green,
58 in_number = InputColors.LightGreen,
58 in_number = InputColors.LightGreen,
59 in_prompt2 = InputColors.Green,
59 in_prompt2 = InputColors.Green,
60 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
60 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
61
61
62 out_prompt = Colors.Red,
62 out_prompt = Colors.Red,
63 out_number = Colors.LightRed,
63 out_number = Colors.LightRed,
64
64
65 normal = Colors.Normal
65 normal = Colors.Normal
66 )
66 )
67 # Don't forget to enter it into the table!
67 # Don't forget to enter it into the table!
68 PromptColors.add_scheme(__PColLinux)
68 PromptColors.add_scheme(__PColLinux)
69
69
70 # Slightly modified Linux for light backgrounds
70 # Slightly modified Linux for light backgrounds
71 __PColLightBG = __PColLinux.copy('LightBG')
71 __PColLightBG = __PColLinux.copy('LightBG')
72
72
73 __PColLightBG.colors.update(
73 __PColLightBG.colors.update(
74 in_prompt = InputColors.Blue,
74 in_prompt = InputColors.Blue,
75 in_number = InputColors.LightBlue,
75 in_number = InputColors.LightBlue,
76 in_prompt2 = InputColors.Blue
76 in_prompt2 = InputColors.Blue
77 )
77 )
78 PromptColors.add_scheme(__PColLightBG)
78 PromptColors.add_scheme(__PColLightBG)
79
79
80 del Colors,InputColors
80 del Colors,InputColors
81
81
82 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
83 def multiple_replace(dict, text):
83 def multiple_replace(dict, text):
84 """ Replace in 'text' all occurences of any key in the given
84 """ Replace in 'text' all occurences of any key in the given
85 dictionary by its corresponding value. Returns the new string."""
85 dictionary by its corresponding value. Returns the new string."""
86
86
87 # Function by Xavier Defrang, originally found at:
87 # Function by Xavier Defrang, originally found at:
88 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
88 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
89
89
90 # Create a regular expression from the dictionary keys
90 # Create a regular expression from the dictionary keys
91 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
91 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
92 # For each match, look-up corresponding value in dictionary
92 # For each match, look-up corresponding value in dictionary
93 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
93 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
94
94
95 #-----------------------------------------------------------------------------
95 #-----------------------------------------------------------------------------
96 # Special characters that can be used in prompt templates, mainly bash-like
96 # Special characters that can be used in prompt templates, mainly bash-like
97
97
98 # If $HOME isn't defined (Windows), make it an absurd string so that it can
98 # If $HOME isn't defined (Windows), make it an absurd string so that it can
99 # never be expanded out into '~'. Basically anything which can never be a
99 # never be expanded out into '~'. Basically anything which can never be a
100 # reasonable directory name will do, we just want the $HOME -> '~' operation
100 # reasonable directory name will do, we just want the $HOME -> '~' operation
101 # to become a no-op. We pre-compute $HOME here so it's not done on every
101 # to become a no-op. We pre-compute $HOME here so it's not done on every
102 # prompt call.
102 # prompt call.
103
103
104 # FIXME:
104 # FIXME:
105
105
106 # - This should be turned into a class which does proper namespace management,
106 # - This should be turned into a class which does proper namespace management,
107 # since the prompt specials need to be evaluated in a certain namespace.
107 # since the prompt specials need to be evaluated in a certain namespace.
108 # Currently it's just globals, which need to be managed manually by code
108 # Currently it's just globals, which need to be managed manually by code
109 # below.
109 # below.
110
110
111 # - I also need to split up the color schemes from the prompt specials
111 # - I also need to split up the color schemes from the prompt specials
112 # somehow. I don't have a clean design for that quite yet.
112 # somehow. I don't have a clean design for that quite yet.
113
113
114 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
114 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
115
115
116 # We precompute a few more strings here for the prompt_specials, which are
116 # We precompute a few more strings here for the prompt_specials, which are
117 # fixed once ipython starts. This reduces the runtime overhead of computing
117 # fixed once ipython starts. This reduces the runtime overhead of computing
118 # prompt strings.
118 # prompt strings.
119 USER = os.environ.get("USER")
119 USER = os.environ.get("USER")
120 HOSTNAME = socket.gethostname()
120 HOSTNAME = socket.gethostname()
121 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
121 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
122 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
122 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
123
123
124 prompt_specials_color = {
124 prompt_specials_color = {
125 # Prompt/history count
125 # Prompt/history count
126 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
126 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
127 '\\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
127 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
128 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
129 # can get numbers displayed in whatever color they want.
130 r'\N': '${self.cache.prompt_count}',
128 # Prompt/history count, with the actual digits replaced by dots. Used
131 # Prompt/history count, with the actual digits replaced by dots. Used
129 # mainly in continuation prompts (prompt_in2)
132 # mainly in continuation prompts (prompt_in2)
130 '\\D': '${"."*len(str(self.cache.prompt_count))}',
133 r'\D': '${"."*len(str(self.cache.prompt_count))}',
131 # Current working directory
134 # Current working directory
132 '\\w': '${os.getcwd()}',
135 r'\w': '${os.getcwd()}',
133 # Current time
136 # Current time
134 '\\t' : '${time.strftime("%H:%M:%S")}',
137 r'\t' : '${time.strftime("%H:%M:%S")}',
135 # Basename of current working directory.
138 # Basename of current working directory.
136 # (use os.sep to make this portable across OSes)
139 # (use os.sep to make this portable across OSes)
137 '\\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
140 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
138 # These X<N> are an extension to the normal bash prompts. They return
141 # These X<N> are an extension to the normal bash prompts. They return
139 # N terms of the path, after replacing $HOME with '~'
142 # N terms of the path, after replacing $HOME with '~'
140 '\\X0': '${os.getcwd().replace("%s","~")}' % HOME,
143 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
141 '\\X1': '${self.cwd_filt(1)}',
144 r'\X1': '${self.cwd_filt(1)}',
142 '\\X2': '${self.cwd_filt(2)}',
145 r'\X2': '${self.cwd_filt(2)}',
143 '\\X3': '${self.cwd_filt(3)}',
146 r'\X3': '${self.cwd_filt(3)}',
144 '\\X4': '${self.cwd_filt(4)}',
147 r'\X4': '${self.cwd_filt(4)}',
145 '\\X5': '${self.cwd_filt(5)}',
148 r'\X5': '${self.cwd_filt(5)}',
146 # Y<N> are similar to X<N>, but they show '~' if it's the directory
149 # Y<N> are similar to X<N>, but they show '~' if it's the directory
147 # N+1 in the list. Somewhat like %cN in tcsh.
150 # N+1 in the list. Somewhat like %cN in tcsh.
148 '\\Y0': '${self.cwd_filt2(0)}',
151 r'\Y0': '${self.cwd_filt2(0)}',
149 '\\Y1': '${self.cwd_filt2(1)}',
152 r'\Y1': '${self.cwd_filt2(1)}',
150 '\\Y2': '${self.cwd_filt2(2)}',
153 r'\Y2': '${self.cwd_filt2(2)}',
151 '\\Y3': '${self.cwd_filt2(3)}',
154 r'\Y3': '${self.cwd_filt2(3)}',
152 '\\Y4': '${self.cwd_filt2(4)}',
155 r'\Y4': '${self.cwd_filt2(4)}',
153 '\\Y5': '${self.cwd_filt2(5)}',
156 r'\Y5': '${self.cwd_filt2(5)}',
154 # Hostname up to first .
157 # Hostname up to first .
155 '\\h': HOSTNAME_SHORT,
158 r'\h': HOSTNAME_SHORT,
156 # Full hostname
159 # Full hostname
157 '\\H': HOSTNAME,
160 r'\H': HOSTNAME,
158 # Username of current user
161 # Username of current user
159 '\\u': USER,
162 r'\u': USER,
160 # Escaped '\'
163 # Escaped '\'
161 '\\\\': '\\',
164 '\\\\': '\\',
162 # Newline
165 # Newline
163 '\\n': '\n',
166 r'\n': '\n',
164 # Carriage return
167 # Carriage return
165 '\\r': '\r',
168 r'\r': '\r',
166 # Release version
169 # Release version
167 '\\v': __version__,
170 r'\v': __version__,
168 # Root symbol ($ or #)
171 # Root symbol ($ or #)
169 '\\$': ROOT_SYMBOL,
172 r'\$': ROOT_SYMBOL,
170 }
173 }
171
174
172 # A copy of the prompt_specials dictionary but with all color escapes removed,
175 # A copy of the prompt_specials dictionary but with all color escapes removed,
173 # so we can correctly compute the prompt length for the auto_rewrite method.
176 # so we can correctly compute the prompt length for the auto_rewrite method.
174 prompt_specials_nocolor = prompt_specials_color.copy()
177 prompt_specials_nocolor = prompt_specials_color.copy()
175 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
178 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
176 prompt_specials_nocolor['\\#'] = '${self.cache.prompt_count}'
179 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
177
180
178 # Add in all the InputTermColors color escapes as valid prompt characters.
181 # Add in all the InputTermColors color escapes as valid prompt characters.
179 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
182 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
180 # with a color name which may begin with a letter used by any other of the
183 # with a color name which may begin with a letter used by any other of the
181 # allowed specials. This of course means that \\C will never be allowed for
184 # allowed specials. This of course means that \\C will never be allowed for
182 # anything else.
185 # anything else.
183 input_colors = ColorANSI.InputTermColors
186 input_colors = ColorANSI.InputTermColors
184 for _color in dir(input_colors):
187 for _color in dir(input_colors):
185 if _color[0] != '_':
188 if _color[0] != '_':
186 c_name = '\\C_'+_color
189 c_name = r'\C_'+_color
187 prompt_specials_color[c_name] = getattr(input_colors,_color)
190 prompt_specials_color[c_name] = getattr(input_colors,_color)
188 prompt_specials_nocolor[c_name] = ''
191 prompt_specials_nocolor[c_name] = ''
189
192
190 # we default to no color for safety. Note that prompt_specials is a global
193 # we default to no color for safety. Note that prompt_specials is a global
191 # variable used by all prompt objects.
194 # variable used by all prompt objects.
192 prompt_specials = prompt_specials_nocolor
195 prompt_specials = prompt_specials_nocolor
193
196
194 #-----------------------------------------------------------------------------
197 #-----------------------------------------------------------------------------
195 def str_safe(arg):
198 def str_safe(arg):
196 """Convert to a string, without ever raising an exception.
199 """Convert to a string, without ever raising an exception.
197
200
198 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
201 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
199 error message."""
202 error message."""
200
203
201 try:
204 try:
202 out = str(arg)
205 out = str(arg)
203 except UnicodeError:
206 except UnicodeError:
204 try:
207 try:
205 out = arg.encode('utf_8','replace')
208 out = arg.encode('utf_8','replace')
206 except Exception,msg:
209 except Exception,msg:
207 # let's keep this little duplication here, so that the most common
210 # let's keep this little duplication here, so that the most common
208 # case doesn't suffer from a double try wrapping.
211 # case doesn't suffer from a double try wrapping.
209 out = '<ERROR: %s>' % msg
212 out = '<ERROR: %s>' % msg
210 except Exception,msg:
213 except Exception,msg:
211 out = '<ERROR: %s>' % msg
214 out = '<ERROR: %s>' % msg
212 return out
215 return out
213
216
214 class BasePrompt:
217 class BasePrompt:
215 """Interactive prompt similar to Mathematica's."""
218 """Interactive prompt similar to Mathematica's."""
216 def __init__(self,cache,sep,prompt,pad_left=False):
219 def __init__(self,cache,sep,prompt,pad_left=False):
217
220
218 # Hack: we access information about the primary prompt through the
221 # Hack: we access information about the primary prompt through the
219 # cache argument. We need this, because we want the secondary prompt
222 # cache argument. We need this, because we want the secondary prompt
220 # to be aligned with the primary one. Color table info is also shared
223 # to be aligned with the primary one. Color table info is also shared
221 # by all prompt classes through the cache. Nice OO spaghetti code!
224 # by all prompt classes through the cache. Nice OO spaghetti code!
222 self.cache = cache
225 self.cache = cache
223 self.sep = sep
226 self.sep = sep
224
227
225 # regexp to count the number of spaces at the end of a prompt
228 # regexp to count the number of spaces at the end of a prompt
226 # expression, useful for prompt auto-rewriting
229 # expression, useful for prompt auto-rewriting
227 self.rspace = re.compile(r'(\s*)$')
230 self.rspace = re.compile(r'(\s*)$')
228 # Flag to left-pad prompt strings to match the length of the primary
231 # Flag to left-pad prompt strings to match the length of the primary
229 # prompt
232 # prompt
230 self.pad_left = pad_left
233 self.pad_left = pad_left
231 # Set template to create each actual prompt (where numbers change)
234 # Set template to create each actual prompt (where numbers change)
232 self.p_template = prompt
235 self.p_template = prompt
233 self.set_p_str()
236 self.set_p_str()
234
237
235 def set_p_str(self):
238 def set_p_str(self):
236 """ Set the interpolating prompt strings.
239 """ Set the interpolating prompt strings.
237
240
238 This must be called every time the color settings change, because the
241 This must be called every time the color settings change, because the
239 prompt_specials global may have changed."""
242 prompt_specials global may have changed."""
240
243
241 import os,time # needed in locals for prompt string handling
244 import os,time # needed in locals for prompt string handling
242 loc = locals()
245 loc = locals()
243 self.p_str = ItplNS('%s%s%s' %
246 self.p_str = ItplNS('%s%s%s' %
244 ('${self.sep}${self.col_p}',
247 ('${self.sep}${self.col_p}',
245 multiple_replace(prompt_specials, self.p_template),
248 multiple_replace(prompt_specials, self.p_template),
246 '${self.col_norm}'),self.cache.user_ns,loc)
249 '${self.col_norm}'),self.cache.user_ns,loc)
247
250
248 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
251 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
249 self.p_template),
252 self.p_template),
250 self.cache.user_ns,loc)
253 self.cache.user_ns,loc)
251
254
252 def write(self,msg): # dbg
255 def write(self,msg): # dbg
253 sys.stdout.write(msg)
256 sys.stdout.write(msg)
254 return ''
257 return ''
255
258
256 def __str__(self):
259 def __str__(self):
257 """Return a string form of the prompt.
260 """Return a string form of the prompt.
258
261
259 This for is useful for continuation and output prompts, since it is
262 This for is useful for continuation and output prompts, since it is
260 left-padded to match lengths with the primary one (if the
263 left-padded to match lengths with the primary one (if the
261 self.pad_left attribute is set)."""
264 self.pad_left attribute is set)."""
262
265
263 out_str = str_safe(self.p_str)
266 out_str = str_safe(self.p_str)
264 if self.pad_left:
267 if self.pad_left:
265 # We must find the amount of padding required to match lengths,
268 # We must find the amount of padding required to match lengths,
266 # taking the color escapes (which are invisible on-screen) into
269 # taking the color escapes (which are invisible on-screen) into
267 # account.
270 # account.
268 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
271 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
269 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
272 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
270 return format % out_str
273 return format % out_str
271 else:
274 else:
272 return out_str
275 return out_str
273
276
274 # these path filters are put in as methods so that we can control the
277 # these path filters are put in as methods so that we can control the
275 # namespace where the prompt strings get evaluated
278 # namespace where the prompt strings get evaluated
276 def cwd_filt(self,depth):
279 def cwd_filt(self,depth):
277 """Return the last depth elements of the current working directory.
280 """Return the last depth elements of the current working directory.
278
281
279 $HOME is always replaced with '~'.
282 $HOME is always replaced with '~'.
280 If depth==0, the full path is returned."""
283 If depth==0, the full path is returned."""
281
284
282 cwd = os.getcwd().replace(HOME,"~")
285 cwd = os.getcwd().replace(HOME,"~")
283 out = os.sep.join(cwd.split(os.sep)[-depth:])
286 out = os.sep.join(cwd.split(os.sep)[-depth:])
284 if out:
287 if out:
285 return out
288 return out
286 else:
289 else:
287 return os.sep
290 return os.sep
288
291
289 def cwd_filt2(self,depth):
292 def cwd_filt2(self,depth):
290 """Return the last depth elements of the current working directory.
293 """Return the last depth elements of the current working directory.
291
294
292 $HOME is always replaced with '~'.
295 $HOME is always replaced with '~'.
293 If depth==0, the full path is returned."""
296 If depth==0, the full path is returned."""
294
297
295 cwd = os.getcwd().replace(HOME,"~").split(os.sep)
298 cwd = os.getcwd().replace(HOME,"~").split(os.sep)
296 if '~' in cwd and len(cwd) == depth+1:
299 if '~' in cwd and len(cwd) == depth+1:
297 depth += 1
300 depth += 1
298 out = os.sep.join(cwd[-depth:])
301 out = os.sep.join(cwd[-depth:])
299 if out:
302 if out:
300 return out
303 return out
301 else:
304 else:
302 return os.sep
305 return os.sep
303
306
304 class Prompt1(BasePrompt):
307 class Prompt1(BasePrompt):
305 """Input interactive prompt similar to Mathematica's."""
308 """Input interactive prompt similar to Mathematica's."""
306
309
307 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
310 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
308 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
311 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
309
312
310 def set_colors(self):
313 def set_colors(self):
311 self.set_p_str()
314 self.set_p_str()
312 Colors = self.cache.color_table.active_colors # shorthand
315 Colors = self.cache.color_table.active_colors # shorthand
313 self.col_p = Colors.in_prompt
316 self.col_p = Colors.in_prompt
314 self.col_num = Colors.in_number
317 self.col_num = Colors.in_number
315 self.col_norm = Colors.in_normal
318 self.col_norm = Colors.in_normal
316 # We need a non-input version of these escapes for the '--->'
319 # We need a non-input version of these escapes for the '--->'
317 # auto-call prompts used in the auto_rewrite() method.
320 # auto-call prompts used in the auto_rewrite() method.
318 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
321 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
319 self.col_norm_ni = Colors.normal
322 self.col_norm_ni = Colors.normal
320
323
321 def __str__(self):
324 def __str__(self):
322 self.cache.prompt_count += 1
325 self.cache.prompt_count += 1
323 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
326 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
324 return str_safe(self.p_str)
327 return str_safe(self.p_str)
325
328
326 def auto_rewrite(self):
329 def auto_rewrite(self):
327 """Print a string of the form '--->' which lines up with the previous
330 """Print a string of the form '--->' which lines up with the previous
328 input string. Useful for systems which re-write the user input when
331 input string. Useful for systems which re-write the user input when
329 handling automatically special syntaxes."""
332 handling automatically special syntaxes."""
330
333
331 curr = str(self.cache.last_prompt)
334 curr = str(self.cache.last_prompt)
332 nrspaces = len(self.rspace.search(curr).group())
335 nrspaces = len(self.rspace.search(curr).group())
333 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
336 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
334 ' '*nrspaces,self.col_norm_ni)
337 ' '*nrspaces,self.col_norm_ni)
335
338
336 class PromptOut(BasePrompt):
339 class PromptOut(BasePrompt):
337 """Output interactive prompt similar to Mathematica's."""
340 """Output interactive prompt similar to Mathematica's."""
338
341
339 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
342 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
340 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
343 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
341 if not self.p_template:
344 if not self.p_template:
342 self.__str__ = lambda: ''
345 self.__str__ = lambda: ''
343
346
344 def set_colors(self):
347 def set_colors(self):
345 self.set_p_str()
348 self.set_p_str()
346 Colors = self.cache.color_table.active_colors # shorthand
349 Colors = self.cache.color_table.active_colors # shorthand
347 self.col_p = Colors.out_prompt
350 self.col_p = Colors.out_prompt
348 self.col_num = Colors.out_number
351 self.col_num = Colors.out_number
349 self.col_norm = Colors.normal
352 self.col_norm = Colors.normal
350
353
351 class Prompt2(BasePrompt):
354 class Prompt2(BasePrompt):
352 """Interactive continuation prompt."""
355 """Interactive continuation prompt."""
353
356
354 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
357 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
355 self.cache = cache
358 self.cache = cache
356 self.p_template = prompt
359 self.p_template = prompt
357 self.pad_left = pad_left
360 self.pad_left = pad_left
358 self.set_p_str()
361 self.set_p_str()
359
362
360 def set_p_str(self):
363 def set_p_str(self):
361 import os,time # needed in locals for prompt string handling
364 import os,time # needed in locals for prompt string handling
362 loc = locals()
365 loc = locals()
363 self.p_str = ItplNS('%s%s%s' %
366 self.p_str = ItplNS('%s%s%s' %
364 ('${self.col_p2}',
367 ('${self.col_p2}',
365 multiple_replace(prompt_specials, self.p_template),
368 multiple_replace(prompt_specials, self.p_template),
366 '$self.col_norm'),
369 '$self.col_norm'),
367 self.cache.user_ns,loc)
370 self.cache.user_ns,loc)
368 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
371 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
369 self.p_template),
372 self.p_template),
370 self.cache.user_ns,loc)
373 self.cache.user_ns,loc)
371
374
372 def set_colors(self):
375 def set_colors(self):
373 self.set_p_str()
376 self.set_p_str()
374 Colors = self.cache.color_table.active_colors
377 Colors = self.cache.color_table.active_colors
375 self.col_p2 = Colors.in_prompt2
378 self.col_p2 = Colors.in_prompt2
376 self.col_norm = Colors.in_normal
379 self.col_norm = Colors.in_normal
377 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
380 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
378 # updated their prompt_in2 definitions. Remove eventually.
381 # updated their prompt_in2 definitions. Remove eventually.
379 self.col_p = Colors.out_prompt
382 self.col_p = Colors.out_prompt
380 self.col_num = Colors.out_number
383 self.col_num = Colors.out_number
381
384
382
385
383 #-----------------------------------------------------------------------------
386 #-----------------------------------------------------------------------------
384 class CachedOutput:
387 class CachedOutput:
385 """Class for printing output from calculations while keeping a cache of
388 """Class for printing output from calculations while keeping a cache of
386 reults. It dynamically creates global variables prefixed with _ which
389 reults. It dynamically creates global variables prefixed with _ which
387 contain these results.
390 contain these results.
388
391
389 Meant to be used as a sys.displayhook replacement, providing numbered
392 Meant to be used as a sys.displayhook replacement, providing numbered
390 prompts and cache services.
393 prompts and cache services.
391
394
392 Initialize with initial and final values for cache counter (this defines
395 Initialize with initial and final values for cache counter (this defines
393 the maximum size of the cache."""
396 the maximum size of the cache."""
394
397
395 def __init__(self,shell,cache_size,Pprint,
398 def __init__(self,shell,cache_size,Pprint,
396 colors='NoColor',input_sep='\n',
399 colors='NoColor',input_sep='\n',
397 output_sep='\n',output_sep2='',
400 output_sep='\n',output_sep2='',
398 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
401 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
399
402
400 cache_size_min = 3
403 cache_size_min = 3
401 if cache_size <= 0:
404 if cache_size <= 0:
402 self.do_full_cache = 0
405 self.do_full_cache = 0
403 cache_size = 0
406 cache_size = 0
404 elif cache_size < cache_size_min:
407 elif cache_size < cache_size_min:
405 self.do_full_cache = 0
408 self.do_full_cache = 0
406 cache_size = 0
409 cache_size = 0
407 warn('caching was disabled (min value for cache size is %s).' %
410 warn('caching was disabled (min value for cache size is %s).' %
408 cache_size_min,level=3)
411 cache_size_min,level=3)
409 else:
412 else:
410 self.do_full_cache = 1
413 self.do_full_cache = 1
411
414
412 self.cache_size = cache_size
415 self.cache_size = cache_size
413 self.input_sep = input_sep
416 self.input_sep = input_sep
414
417
415 # we need a reference to the user-level namespace
418 # we need a reference to the user-level namespace
416 self.shell = shell
419 self.shell = shell
417 self.user_ns = shell.user_ns
420 self.user_ns = shell.user_ns
418 # and to the user's input
421 # and to the user's input
419 self.input_hist = shell.input_hist
422 self.input_hist = shell.input_hist
420 # and to the user's logger, for logging output
423 # and to the user's logger, for logging output
421 self.logger = shell.logger
424 self.logger = shell.logger
422
425
423 # Set input prompt strings and colors
426 # Set input prompt strings and colors
424 if cache_size == 0:
427 if cache_size == 0:
425 if ps1.find('%n') > -1 or ps1.find('\\#') > -1: ps1 = '>>> '
428 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
426 if ps2.find('%n') > -1 or ps2.find('\\#') > -1: ps2 = '... '
429 or ps1.find(r'\N') > -1:
430 ps1 = '>>> '
431 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
432 or ps2.find(r'\N') > -1:
433 ps2 = '... '
427 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
434 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
428 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
435 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
429 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
436 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
430
437
431 self.color_table = PromptColors
438 self.color_table = PromptColors
432 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
439 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
433 pad_left=pad_left)
440 pad_left=pad_left)
434 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
441 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
435 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
442 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
436 pad_left=pad_left)
443 pad_left=pad_left)
437 self.set_colors(colors)
444 self.set_colors(colors)
438
445
439 # other more normal stuff
446 # other more normal stuff
440 # b/c each call to the In[] prompt raises it by 1, even the first.
447 # b/c each call to the In[] prompt raises it by 1, even the first.
441 self.prompt_count = 0
448 self.prompt_count = 0
442 # Store the last prompt string each time, we need it for aligning
449 # Store the last prompt string each time, we need it for aligning
443 # continuation and auto-rewrite prompts
450 # continuation and auto-rewrite prompts
444 self.last_prompt = ''
451 self.last_prompt = ''
445 self.Pprint = Pprint
452 self.Pprint = Pprint
446 self.output_sep = output_sep
453 self.output_sep = output_sep
447 self.output_sep2 = output_sep2
454 self.output_sep2 = output_sep2
448 self._,self.__,self.___ = '','',''
455 self._,self.__,self.___ = '','',''
449 self.pprint_types = map(type,[(),[],{}])
456 self.pprint_types = map(type,[(),[],{}])
450
457
451 # these are deliberately global:
458 # these are deliberately global:
452 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
459 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
453 self.user_ns.update(to_user_ns)
460 self.user_ns.update(to_user_ns)
454
461
455 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
462 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
456 if p_str is None:
463 if p_str is None:
457 if self.do_full_cache:
464 if self.do_full_cache:
458 return cache_def
465 return cache_def
459 else:
466 else:
460 return no_cache_def
467 return no_cache_def
461 else:
468 else:
462 return p_str
469 return p_str
463
470
464 def set_colors(self,colors):
471 def set_colors(self,colors):
465 """Set the active color scheme and configure colors for the three
472 """Set the active color scheme and configure colors for the three
466 prompt subsystems."""
473 prompt subsystems."""
467
474
468 # FIXME: the prompt_specials global should be gobbled inside this
475 # FIXME: the prompt_specials global should be gobbled inside this
469 # class instead. Do it when cleaning up the whole 3-prompt system.
476 # class instead. Do it when cleaning up the whole 3-prompt system.
470 global prompt_specials
477 global prompt_specials
471 if colors.lower()=='nocolor':
478 if colors.lower()=='nocolor':
472 prompt_specials = prompt_specials_nocolor
479 prompt_specials = prompt_specials_nocolor
473 else:
480 else:
474 prompt_specials = prompt_specials_color
481 prompt_specials = prompt_specials_color
475
482
476 self.color_table.set_active_scheme(colors)
483 self.color_table.set_active_scheme(colors)
477 self.prompt1.set_colors()
484 self.prompt1.set_colors()
478 self.prompt2.set_colors()
485 self.prompt2.set_colors()
479 self.prompt_out.set_colors()
486 self.prompt_out.set_colors()
480
487
481 def __call__(self,arg=None):
488 def __call__(self,arg=None):
482 """Printing with history cache management.
489 """Printing with history cache management.
483
490
484 This is invoked everytime the interpreter needs to print, and is
491 This is invoked everytime the interpreter needs to print, and is
485 activated by setting the variable sys.displayhook to it."""
492 activated by setting the variable sys.displayhook to it."""
486
493
487 # If something injected a '_' variable in __builtin__, delete
494 # If something injected a '_' variable in __builtin__, delete
488 # ipython's automatic one so we don't clobber that. gettext() in
495 # ipython's automatic one so we don't clobber that. gettext() in
489 # particular uses _, so we need to stay away from it.
496 # particular uses _, so we need to stay away from it.
490 if '_' in __builtin__.__dict__:
497 if '_' in __builtin__.__dict__:
491 try:
498 try:
492 del self.user_ns['_']
499 del self.user_ns['_']
493 except KeyError:
500 except KeyError:
494 pass
501 pass
495 if arg is not None:
502 if arg is not None:
496 cout_write = Term.cout.write # fast lookup
503 cout_write = Term.cout.write # fast lookup
497 # first handle the cache and counters
504 # first handle the cache and counters
498
505
499 # do not print output if input ends in ';'
506 # do not print output if input ends in ';'
500 if self.input_hist[self.prompt_count].endswith(';\n'):
507 if self.input_hist[self.prompt_count].endswith(';\n'):
501 return
508 return
502 # don't use print, puts an extra space
509 # don't use print, puts an extra space
503 cout_write(self.output_sep)
510 cout_write(self.output_sep)
504 outprompt = self.shell.hooks.generate_output_prompt()
511 outprompt = self.shell.hooks.generate_output_prompt()
505 if self.do_full_cache:
512 if self.do_full_cache:
506 cout_write(outprompt)
513 cout_write(outprompt)
507
514
508 if isinstance(arg,Macro):
515 if isinstance(arg,Macro):
509 print 'Executing Macro...'
516 print 'Executing Macro...'
510 # in case the macro takes a long time to execute
517 # in case the macro takes a long time to execute
511 Term.cout.flush()
518 Term.cout.flush()
512 self.shell.runlines(arg.value)
519 self.shell.runlines(arg.value)
513 return None
520 return None
514
521
515 # and now call a possibly user-defined print mechanism
522 # and now call a possibly user-defined print mechanism
516 manipulated_val = self.display(arg)
523 manipulated_val = self.display(arg)
517
524
518 # user display hooks can change the variable to be stored in
525 # user display hooks can change the variable to be stored in
519 # output history
526 # output history
520
527
521 if manipulated_val is not None:
528 if manipulated_val is not None:
522 arg = manipulated_val
529 arg = manipulated_val
523
530
524 # avoid recursive reference when displaying _oh/Out
531 # avoid recursive reference when displaying _oh/Out
525 if arg is not self.user_ns['_oh']:
532 if arg is not self.user_ns['_oh']:
526 self.update(arg)
533 self.update(arg)
527
534
528 if self.logger.log_output:
535 if self.logger.log_output:
529 self.logger.log_write(repr(arg),'output')
536 self.logger.log_write(repr(arg),'output')
530 cout_write(self.output_sep2)
537 cout_write(self.output_sep2)
531 Term.cout.flush()
538 Term.cout.flush()
532
539
533 def _display(self,arg):
540 def _display(self,arg):
534 """Default printer method, uses pprint.
541 """Default printer method, uses pprint.
535
542
536 Do ip.set_hook("result_display", my_displayhook) for custom result
543 Do ip.set_hook("result_display", my_displayhook) for custom result
537 display, e.g. when your own objects need special formatting.
544 display, e.g. when your own objects need special formatting.
538 """
545 """
539
546
540 return self.shell.hooks.result_display(arg)
547 return self.shell.hooks.result_display(arg)
541
548
542 # Assign the default display method:
549 # Assign the default display method:
543 display = _display
550 display = _display
544
551
545 def update(self,arg):
552 def update(self,arg):
546 #print '***cache_count', self.cache_count # dbg
553 #print '***cache_count', self.cache_count # dbg
547 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
554 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
548 warn('Output cache limit (currently '+
555 warn('Output cache limit (currently '+
549 `self.cache_size`+' entries) hit.\n'
556 `self.cache_size`+' entries) hit.\n'
550 'Flushing cache and resetting history counter...\n'
557 'Flushing cache and resetting history counter...\n'
551 'The only history variables available will be _,__,___ and _1\n'
558 'The only history variables available will be _,__,___ and _1\n'
552 'with the current result.')
559 'with the current result.')
553
560
554 self.flush()
561 self.flush()
555 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
562 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
556 # we cause buggy behavior for things like gettext).
563 # we cause buggy behavior for things like gettext).
557 if '_' not in __builtin__.__dict__:
564 if '_' not in __builtin__.__dict__:
558 self.___ = self.__
565 self.___ = self.__
559 self.__ = self._
566 self.__ = self._
560 self._ = arg
567 self._ = arg
561 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
568 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
562
569
563 # hackish access to top-level namespace to create _1,_2... dynamically
570 # hackish access to top-level namespace to create _1,_2... dynamically
564 to_main = {}
571 to_main = {}
565 if self.do_full_cache:
572 if self.do_full_cache:
566 new_result = '_'+`self.prompt_count`
573 new_result = '_'+`self.prompt_count`
567 to_main[new_result] = arg
574 to_main[new_result] = arg
568 self.user_ns.update(to_main)
575 self.user_ns.update(to_main)
569 self.user_ns['_oh'][self.prompt_count] = arg
576 self.user_ns['_oh'][self.prompt_count] = arg
570
577
571 def flush(self):
578 def flush(self):
572 if not self.do_full_cache:
579 if not self.do_full_cache:
573 raise ValueError,"You shouldn't have reached the cache flush "\
580 raise ValueError,"You shouldn't have reached the cache flush "\
574 "if full caching is not enabled!"
581 "if full caching is not enabled!"
575 # delete auto-generated vars from global namespace
582 # delete auto-generated vars from global namespace
576
583
577 for n in range(1,self.prompt_count + 1):
584 for n in range(1,self.prompt_count + 1):
578 key = '_'+`n`
585 key = '_'+`n`
579 try:
586 try:
580 del self.user_ns[key]
587 del self.user_ns[key]
581 except: pass
588 except: pass
582 self.user_ns['_oh'].clear()
589 self.user_ns['_oh'].clear()
583
590
584 if '_' not in __builtin__.__dict__:
591 if '_' not in __builtin__.__dict__:
585 self.user_ns.update({'_':None,'__':None, '___':None})
592 self.user_ns.update({'_':None,'__':None, '___':None})
586 import gc
593 import gc
587 gc.collect() # xxx needed?
594 gc.collect() # xxx needed?
588
595
@@ -1,85 +1,85 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Release data for the IPython project.
2 """Release data for the IPython project.
3
3
4 $Id: Release.py 2160 2007-03-19 05:40:59Z fperez $"""
4 $Id: Release.py 2192 2007-04-01 20:51:06Z fperez $"""
5
5
6 #*****************************************************************************
6 #*****************************************************************************
7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
8 #
8 #
9 # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray
9 # Copyright (c) 2001 Janko Hauser <jhauser@zscout.de> and Nathaniel Gray
10 # <n8gray@caltech.edu>
10 # <n8gray@caltech.edu>
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #*****************************************************************************
14 #*****************************************************************************
15
15
16 # Name of the package for release purposes. This is the name which labels
16 # Name of the package for release purposes. This is the name which labels
17 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
17 # the tarballs and RPMs made by distutils, so it's best to lowercase it.
18 name = 'ipython'
18 name = 'ipython'
19
19
20 # For versions with substrings (like 0.6.16.svn), use an extra . to separate
20 # For versions with substrings (like 0.6.16.svn), use an extra . to separate
21 # the new substring. We have to avoid using either dashes or underscores,
21 # the new substring. We have to avoid using either dashes or underscores,
22 # because bdist_rpm does not accept dashes (an RPM) convention, and
22 # because bdist_rpm does not accept dashes (an RPM) convention, and
23 # bdist_deb does not accept underscores (a Debian convention).
23 # bdist_deb does not accept underscores (a Debian convention).
24
24
25 revision = '2159'
25 revision = '2191'
26
26
27 #version = '0.7.3'
27 #version = '0.7.3'
28
28
29 version = '0.7.4.svn.r' + revision.rstrip('M')
29 version = '0.7.4.svn.r' + revision.rstrip('M')
30
30
31 description = "An enhanced interactive Python shell."
31 description = "An enhanced interactive Python shell."
32
32
33 long_description = \
33 long_description = \
34 """
34 """
35 IPython provides a replacement for the interactive Python interpreter with
35 IPython provides a replacement for the interactive Python interpreter with
36 extra functionality.
36 extra functionality.
37
37
38 Main features:
38 Main features:
39
39
40 * Comprehensive object introspection.
40 * Comprehensive object introspection.
41
41
42 * Input history, persistent across sessions.
42 * Input history, persistent across sessions.
43
43
44 * Caching of output results during a session with automatically generated
44 * Caching of output results during a session with automatically generated
45 references.
45 references.
46
46
47 * Readline based name completion.
47 * Readline based name completion.
48
48
49 * Extensible system of 'magic' commands for controlling the environment and
49 * Extensible system of 'magic' commands for controlling the environment and
50 performing many tasks related either to IPython or the operating system.
50 performing many tasks related either to IPython or the operating system.
51
51
52 * Configuration system with easy switching between different setups (simpler
52 * Configuration system with easy switching between different setups (simpler
53 than changing $PYTHONSTARTUP environment variables every time).
53 than changing $PYTHONSTARTUP environment variables every time).
54
54
55 * Session logging and reloading.
55 * Session logging and reloading.
56
56
57 * Extensible syntax processing for special purpose situations.
57 * Extensible syntax processing for special purpose situations.
58
58
59 * Access to the system shell with user-extensible alias system.
59 * Access to the system shell with user-extensible alias system.
60
60
61 * Easily embeddable in other Python programs.
61 * Easily embeddable in other Python programs.
62
62
63 * Integrated access to the pdb debugger and the Python profiler.
63 * Integrated access to the pdb debugger and the Python profiler.
64
64
65 The latest development version is always available at the IPython subversion
65 The latest development version is always available at the IPython subversion
66 repository_.
66 repository_.
67
67
68 .. _repository: http://ipython.scipy.org/svn/ipython/ipython/trunk#egg=ipython-dev
68 .. _repository: http://ipython.scipy.org/svn/ipython/ipython/trunk#egg=ipython-dev
69 """
69 """
70
70
71 license = 'BSD'
71 license = 'BSD'
72
72
73 authors = {'Fernando' : ('Fernando Perez','fperez@colorado.edu'),
73 authors = {'Fernando' : ('Fernando Perez','fperez@colorado.edu'),
74 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
74 'Janko' : ('Janko Hauser','jhauser@zscout.de'),
75 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
75 'Nathan' : ('Nathaniel Gray','n8gray@caltech.edu'),
76 'Ville' : ('Ville Vainio','vivainio@gmail.com')
76 'Ville' : ('Ville Vainio','vivainio@gmail.com')
77 }
77 }
78
78
79 url = 'http://ipython.scipy.org'
79 url = 'http://ipython.scipy.org'
80
80
81 download_url = 'http://ipython.scipy.org/dist'
81 download_url = 'http://ipython.scipy.org/dist'
82
82
83 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
83 platforms = ['Linux','Mac OSX','Windows XP/2000/NT','Windows 95/98/ME']
84
84
85 keywords = ['Interactive','Interpreter','Shell']
85 keywords = ['Interactive','Interpreter','Shell']
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now