##// END OF EJS Templates
Remove unused code
Thomas Kluyver -
Show More
@@ -1,393 +1,392 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 The :class:`~IPython.core.application.Application` object for the command
5 5 line :command:`ipython` program.
6 6
7 7 Authors
8 8 -------
9 9
10 10 * Brian Granger
11 11 * Fernando Perez
12 12 * Min Ragan-Kelley
13 13 """
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Copyright (C) 2008-2011 The IPython Development Team
17 17 #
18 18 # Distributed under the terms of the BSD License. The full license is in
19 19 # the file COPYING, distributed as part of this software.
20 20 #-----------------------------------------------------------------------------
21 21
22 22 #-----------------------------------------------------------------------------
23 23 # Imports
24 24 #-----------------------------------------------------------------------------
25 25
26 26 from __future__ import absolute_import
27 27
28 28 import logging
29 29 import os
30 30 import sys
31 31
32 32 from IPython.config.loader import (
33 33 Config, PyFileConfigLoader, ConfigFileNotFound
34 34 )
35 35 from IPython.config.application import boolean_flag, catch_config_error
36 36 from IPython.core import release
37 37 from IPython.core import usage
38 38 from IPython.core.completer import IPCompleter
39 39 from IPython.core.crashhandler import CrashHandler
40 40 from IPython.core.formatters import PlainTextFormatter
41 41 from IPython.core.history import HistoryManager
42 42 from IPython.core.prompts import PromptManager
43 43 from IPython.core.application import (
44 44 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
45 45 )
46 46 from IPython.core.magics import ScriptMagics
47 47 from IPython.core.shellapp import (
48 48 InteractiveShellApp, shell_flags, shell_aliases
49 49 )
50 50 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
51 from IPython.lib import inputhook
52 51 from IPython.utils import warn
53 52 from IPython.utils.path import get_ipython_dir, check_for_old_config
54 53 from IPython.utils.traitlets import (
55 54 Bool, List, Dict, CaselessStrEnum
56 55 )
57 56
58 57 #-----------------------------------------------------------------------------
59 58 # Globals, utilities and helpers
60 59 #-----------------------------------------------------------------------------
61 60
62 61 #: The default config file name for this application.
63 62 default_config_file_name = u'ipython_config.py'
64 63
65 64 _examples = """
66 65 ipython --pylab # start in pylab mode
67 66 ipython --pylab=qt # start in pylab mode with the qt4 backend
68 67 ipython --log-level=DEBUG # set logging to DEBUG
69 68 ipython --profile=foo # start with profile foo
70 69
71 70 ipython qtconsole # start the qtconsole GUI application
72 71 ipython help qtconsole # show the help for the qtconsole subcmd
73 72
74 73 ipython console # start the terminal-based console application
75 74 ipython help console # show the help for the console subcmd
76 75
77 76 ipython notebook # start the IPython notebook
78 77 ipython help notebook # show the help for the notebook subcmd
79 78
80 79 ipython profile create foo # create profile foo w/ default config files
81 80 ipython help profile # show the help for the profile subcmd
82 81
83 82 ipython locate # print the path to the IPython directory
84 83 ipython locate profile foo # print the path to the directory for profile `foo`
85 84 """
86 85
87 86 #-----------------------------------------------------------------------------
88 87 # Crash handler for this application
89 88 #-----------------------------------------------------------------------------
90 89
91 90 class IPAppCrashHandler(CrashHandler):
92 91 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
93 92
94 93 def __init__(self, app):
95 94 contact_name = release.author
96 95 contact_email = release.author_email
97 96 bug_tracker = 'https://github.com/ipython/ipython/issues'
98 97 super(IPAppCrashHandler,self).__init__(
99 98 app, contact_name, contact_email, bug_tracker
100 99 )
101 100
102 101 def make_report(self,traceback):
103 102 """Return a string containing a crash report."""
104 103
105 104 sec_sep = self.section_sep
106 105 # Start with parent report
107 106 report = [super(IPAppCrashHandler, self).make_report(traceback)]
108 107 # Add interactive-specific info we may have
109 108 rpt_add = report.append
110 109 try:
111 110 rpt_add(sec_sep+"History of session input:")
112 111 for line in self.app.shell.user_ns['_ih']:
113 112 rpt_add(line)
114 113 rpt_add('\n*** Last line of input (may not be in above history):\n')
115 114 rpt_add(self.app.shell._last_input_line+'\n')
116 115 except:
117 116 pass
118 117
119 118 return ''.join(report)
120 119
121 120 #-----------------------------------------------------------------------------
122 121 # Aliases and Flags
123 122 #-----------------------------------------------------------------------------
124 123 flags = dict(base_flags)
125 124 flags.update(shell_flags)
126 125 frontend_flags = {}
127 126 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
128 127 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
129 128 'Turn on auto editing of files with syntax errors.',
130 129 'Turn off auto editing of files with syntax errors.'
131 130 )
132 131 addflag('banner', 'TerminalIPythonApp.display_banner',
133 132 "Display a banner upon starting IPython.",
134 133 "Don't display a banner upon starting IPython."
135 134 )
136 135 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
137 136 """Set to confirm when you try to exit IPython with an EOF (Control-D
138 137 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
139 138 you can force a direct exit without any confirmation.""",
140 139 "Don't prompt the user when exiting."
141 140 )
142 141 addflag('term-title', 'TerminalInteractiveShell.term_title',
143 142 "Enable auto setting the terminal title.",
144 143 "Disable auto setting the terminal title."
145 144 )
146 145 classic_config = Config()
147 146 classic_config.InteractiveShell.cache_size = 0
148 147 classic_config.PlainTextFormatter.pprint = False
149 148 classic_config.PromptManager.in_template = '>>> '
150 149 classic_config.PromptManager.in2_template = '... '
151 150 classic_config.PromptManager.out_template = ''
152 151 classic_config.InteractiveShell.separate_in = ''
153 152 classic_config.InteractiveShell.separate_out = ''
154 153 classic_config.InteractiveShell.separate_out2 = ''
155 154 classic_config.InteractiveShell.colors = 'NoColor'
156 155 classic_config.InteractiveShell.xmode = 'Plain'
157 156
158 157 frontend_flags['classic']=(
159 158 classic_config,
160 159 "Gives IPython a similar feel to the classic Python prompt."
161 160 )
162 161 # # log doesn't make so much sense this way anymore
163 162 # paa('--log','-l',
164 163 # action='store_true', dest='InteractiveShell.logstart',
165 164 # help="Start logging to the default log file (./ipython_log.py).")
166 165 #
167 166 # # quick is harder to implement
168 167 frontend_flags['quick']=(
169 168 {'TerminalIPythonApp' : {'quick' : True}},
170 169 "Enable quick startup with no config files."
171 170 )
172 171
173 172 frontend_flags['i'] = (
174 173 {'TerminalIPythonApp' : {'force_interact' : True}},
175 174 """If running code from the command line, become interactive afterwards.
176 175 Note: can also be given simply as '-i.'"""
177 176 )
178 177 flags.update(frontend_flags)
179 178
180 179 aliases = dict(base_aliases)
181 180 aliases.update(shell_aliases)
182 181
183 182 #-----------------------------------------------------------------------------
184 183 # Main classes and functions
185 184 #-----------------------------------------------------------------------------
186 185
187 186
188 187 class LocateIPythonApp(BaseIPythonApplication):
189 188 description = """print the path to the IPython dir"""
190 189 subcommands = Dict(dict(
191 190 profile=('IPython.core.profileapp.ProfileLocate',
192 191 "print the path to an IPython profile directory",
193 192 ),
194 193 ))
195 194 def start(self):
196 195 if self.subapp is not None:
197 196 return self.subapp.start()
198 197 else:
199 198 print self.ipython_dir
200 199
201 200
202 201 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
203 202 name = u'ipython'
204 203 description = usage.cl_usage
205 204 default_config_file_name = default_config_file_name
206 205 crash_handler_class = IPAppCrashHandler
207 206 examples = _examples
208 207
209 208 flags = Dict(flags)
210 209 aliases = Dict(aliases)
211 210 classes = List()
212 211 def _classes_default(self):
213 212 """This has to be in a method, for TerminalIPythonApp to be available."""
214 213 return [
215 214 InteractiveShellApp, # ShellApp comes before TerminalApp, because
216 215 self.__class__, # it will also affect subclasses (e.g. QtConsole)
217 216 TerminalInteractiveShell,
218 217 PromptManager,
219 218 HistoryManager,
220 219 ProfileDir,
221 220 PlainTextFormatter,
222 221 IPCompleter,
223 222 ScriptMagics,
224 223 ]
225 224
226 225 subcommands = Dict(dict(
227 226 qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
228 227 """Launch the IPython Qt Console."""
229 228 ),
230 229 notebook=('IPython.frontend.html.notebook.notebookapp.NotebookApp',
231 230 """Launch the IPython HTML Notebook Server."""
232 231 ),
233 232 profile = ("IPython.core.profileapp.ProfileApp",
234 233 "Create and manage IPython profiles."
235 234 ),
236 235 kernel = ("IPython.zmq.ipkernel.IPKernelApp",
237 236 "Start a kernel without an attached frontend."
238 237 ),
239 238 console=('IPython.frontend.terminal.console.app.ZMQTerminalIPythonApp',
240 239 """Launch the IPython terminal-based Console."""
241 240 ),
242 241 locate=('IPython.frontend.terminal.ipapp.LocateIPythonApp',
243 242 LocateIPythonApp.description
244 243 ),
245 244 ))
246 245
247 246 # *do* autocreate requested profile, but don't create the config file.
248 247 auto_create=Bool(True)
249 248 # configurables
250 249 ignore_old_config=Bool(False, config=True,
251 250 help="Suppress warning messages about legacy config files"
252 251 )
253 252 quick = Bool(False, config=True,
254 253 help="""Start IPython quickly by skipping the loading of config files."""
255 254 )
256 255 def _quick_changed(self, name, old, new):
257 256 if new:
258 257 self.load_config_file = lambda *a, **kw: None
259 258 self.ignore_old_config=True
260 259
261 260 display_banner = Bool(True, config=True,
262 261 help="Whether to display a banner upon starting IPython."
263 262 )
264 263
265 264 # if there is code of files to run from the cmd line, don't interact
266 265 # unless the --i flag (App.force_interact) is true.
267 266 force_interact = Bool(False, config=True,
268 267 help="""If a command or file is given via the command-line,
269 268 e.g. 'ipython foo.py"""
270 269 )
271 270 def _force_interact_changed(self, name, old, new):
272 271 if new:
273 272 self.interact = True
274 273
275 274 def _file_to_run_changed(self, name, old, new):
276 275 if new:
277 276 self.something_to_run = True
278 277 if new and not self.force_interact:
279 278 self.interact = False
280 279 _code_to_run_changed = _file_to_run_changed
281 280 _module_to_run_changed = _file_to_run_changed
282 281
283 282 # internal, not-configurable
284 283 interact=Bool(True)
285 284 something_to_run=Bool(False)
286 285
287 286 def parse_command_line(self, argv=None):
288 287 """override to allow old '-pylab' flag with deprecation warning"""
289 288
290 289 argv = sys.argv[1:] if argv is None else argv
291 290
292 291 if '-pylab' in argv:
293 292 # deprecated `-pylab` given,
294 293 # warn and transform into current syntax
295 294 argv = argv[:] # copy, don't clobber
296 295 idx = argv.index('-pylab')
297 296 warn.warn("`-pylab` flag has been deprecated.\n"
298 297 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
299 298 sub = '--pylab'
300 299 if len(argv) > idx+1:
301 300 # check for gui arg, as in '-pylab qt'
302 301 gui = argv[idx+1]
303 302 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
304 303 sub = '--pylab='+gui
305 304 argv.pop(idx+1)
306 305 argv[idx] = sub
307 306
308 307 return super(TerminalIPythonApp, self).parse_command_line(argv)
309 308
310 309 @catch_config_error
311 310 def initialize(self, argv=None):
312 311 """Do actions after construct, but before starting the app."""
313 312 super(TerminalIPythonApp, self).initialize(argv)
314 313 if self.subapp is not None:
315 314 # don't bother initializing further, starting subapp
316 315 return
317 316 if not self.ignore_old_config:
318 317 check_for_old_config(self.ipython_dir)
319 318 # print self.extra_args
320 319 if self.extra_args and not self.something_to_run:
321 320 self.file_to_run = self.extra_args[0]
322 321 self.init_path()
323 322 # create the shell
324 323 self.init_shell()
325 324 # and draw the banner
326 325 self.init_banner()
327 326 # Now a variety of things that happen after the banner is printed.
328 327 self.init_gui_pylab()
329 328 self.init_extensions()
330 329 self.init_code()
331 330
332 331 def init_shell(self):
333 332 """initialize the InteractiveShell instance"""
334 333 # Create an InteractiveShell instance.
335 334 # shell.display_banner should always be False for the terminal
336 335 # based app, because we call shell.show_banner() by hand below
337 336 # so the banner shows *before* all extension loading stuff.
338 337 self.shell = TerminalInteractiveShell.instance(config=self.config,
339 338 display_banner=False, profile_dir=self.profile_dir,
340 339 ipython_dir=self.ipython_dir)
341 340 self.shell.configurables.append(self)
342 341
343 342 def init_banner(self):
344 343 """optionally display the banner"""
345 344 if self.display_banner and self.interact:
346 345 self.shell.show_banner()
347 346 # Make sure there is a space below the banner.
348 347 if self.log_level <= logging.INFO: print
349 348
350 349 def _pylab_changed(self, name, old, new):
351 350 """Replace --pylab='inline' with --pylab='auto'"""
352 351 if new == 'inline':
353 352 warn.warn("'inline' not available as pylab backend, "
354 353 "using 'auto' instead.")
355 354 self.pylab = 'auto'
356 355
357 356 def start(self):
358 357 if self.subapp is not None:
359 358 return self.subapp.start()
360 359 # perform any prexec steps:
361 360 if self.interact:
362 361 self.log.debug("Starting IPython's mainloop...")
363 362 self.shell.mainloop()
364 363 else:
365 364 self.log.debug("IPython not interactive...")
366 365
367 366
368 367 def load_default_config(ipython_dir=None):
369 368 """Load the default config file from the default ipython_dir.
370 369
371 370 This is useful for embedded shells.
372 371 """
373 372 if ipython_dir is None:
374 373 ipython_dir = get_ipython_dir()
375 374 profile_dir = os.path.join(ipython_dir, 'profile_default')
376 375 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
377 376 try:
378 377 config = cl.load_config()
379 378 except ConfigFileNotFound:
380 379 # no config found
381 380 config = Config()
382 381 return config
383 382
384 383
385 384 def launch_new_instance():
386 385 """Create and run a full blown IPython instance"""
387 386 app = TerminalIPythonApp.instance()
388 387 app.initialize()
389 388 app.start()
390 389
391 390
392 391 if __name__ == '__main__':
393 392 launch_new_instance()
@@ -1,850 +1,824 b''
1 1 # encoding: utf-8
2 2 """
3 3 Utilities for working with strings and text.
4 4
5 5 Inheritance diagram:
6 6
7 7 .. inheritance-diagram:: IPython.utils.text
8 8 :parts: 3
9 9 """
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2008-2011 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21
22 22 import __main__
23 23
24 24 import os
25 25 import re
26 import shutil
27 26 import sys
28 27 import textwrap
29 28 from string import Formatter
30 29
31 30 from IPython.external.path import path
32 31 from IPython.testing.skipdoctest import skip_doctest_py3, skip_doctest
33 32 from IPython.utils import py3compat
34 33 from IPython.utils.io import nlprint
35 34 from IPython.utils.data import flatten
36 35
37 36 #-----------------------------------------------------------------------------
38 37 # Code
39 38 #-----------------------------------------------------------------------------
40 39
41 40 def unquote_ends(istr):
42 41 """Remove a single pair of quotes from the endpoints of a string."""
43 42
44 43 if not istr:
45 44 return istr
46 45 if (istr[0]=="'" and istr[-1]=="'") or \
47 46 (istr[0]=='"' and istr[-1]=='"'):
48 47 return istr[1:-1]
49 48 else:
50 49 return istr
51 50
52 51
53 52 class LSString(str):
54 53 """String derivative with a special access attributes.
55 54
56 55 These are normal strings, but with the special attributes:
57 56
58 57 .l (or .list) : value as list (split on newlines).
59 58 .n (or .nlstr): original value (the string itself).
60 59 .s (or .spstr): value as whitespace-separated string.
61 60 .p (or .paths): list of path objects
62 61
63 62 Any values which require transformations are computed only once and
64 63 cached.
65 64
66 65 Such strings are very useful to efficiently interact with the shell, which
67 66 typically only understands whitespace-separated options for commands."""
68 67
69 68 def get_list(self):
70 69 try:
71 70 return self.__list
72 71 except AttributeError:
73 72 self.__list = self.split('\n')
74 73 return self.__list
75 74
76 75 l = list = property(get_list)
77 76
78 77 def get_spstr(self):
79 78 try:
80 79 return self.__spstr
81 80 except AttributeError:
82 81 self.__spstr = self.replace('\n',' ')
83 82 return self.__spstr
84 83
85 84 s = spstr = property(get_spstr)
86 85
87 86 def get_nlstr(self):
88 87 return self
89 88
90 89 n = nlstr = property(get_nlstr)
91 90
92 91 def get_paths(self):
93 92 try:
94 93 return self.__paths
95 94 except AttributeError:
96 95 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
97 96 return self.__paths
98 97
99 98 p = paths = property(get_paths)
100 99
101 100 # FIXME: We need to reimplement type specific displayhook and then add this
102 101 # back as a custom printer. This should also be moved outside utils into the
103 102 # core.
104 103
105 104 # def print_lsstring(arg):
106 105 # """ Prettier (non-repr-like) and more informative printer for LSString """
107 106 # print "LSString (.p, .n, .l, .s available). Value:"
108 107 # print arg
109 108 #
110 109 #
111 110 # print_lsstring = result_display.when_type(LSString)(print_lsstring)
112 111
113 112
114 113 class SList(list):
115 114 """List derivative with a special access attributes.
116 115
117 116 These are normal lists, but with the special attributes:
118 117
119 118 .l (or .list) : value as list (the list itself).
120 119 .n (or .nlstr): value as a string, joined on newlines.
121 120 .s (or .spstr): value as a string, joined on spaces.
122 121 .p (or .paths): list of path objects
123 122
124 123 Any values which require transformations are computed only once and
125 124 cached."""
126 125
127 126 def get_list(self):
128 127 return self
129 128
130 129 l = list = property(get_list)
131 130
132 131 def get_spstr(self):
133 132 try:
134 133 return self.__spstr
135 134 except AttributeError:
136 135 self.__spstr = ' '.join(self)
137 136 return self.__spstr
138 137
139 138 s = spstr = property(get_spstr)
140 139
141 140 def get_nlstr(self):
142 141 try:
143 142 return self.__nlstr
144 143 except AttributeError:
145 144 self.__nlstr = '\n'.join(self)
146 145 return self.__nlstr
147 146
148 147 n = nlstr = property(get_nlstr)
149 148
150 149 def get_paths(self):
151 150 try:
152 151 return self.__paths
153 152 except AttributeError:
154 153 self.__paths = [path(p) for p in self if os.path.exists(p)]
155 154 return self.__paths
156 155
157 156 p = paths = property(get_paths)
158 157
159 158 def grep(self, pattern, prune = False, field = None):
160 159 """ Return all strings matching 'pattern' (a regex or callable)
161 160
162 161 This is case-insensitive. If prune is true, return all items
163 162 NOT matching the pattern.
164 163
165 164 If field is specified, the match must occur in the specified
166 165 whitespace-separated field.
167 166
168 167 Examples::
169 168
170 169 a.grep( lambda x: x.startswith('C') )
171 170 a.grep('Cha.*log', prune=1)
172 171 a.grep('chm', field=-1)
173 172 """
174 173
175 174 def match_target(s):
176 175 if field is None:
177 176 return s
178 177 parts = s.split()
179 178 try:
180 179 tgt = parts[field]
181 180 return tgt
182 181 except IndexError:
183 182 return ""
184 183
185 184 if isinstance(pattern, basestring):
186 185 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
187 186 else:
188 187 pred = pattern
189 188 if not prune:
190 189 return SList([el for el in self if pred(match_target(el))])
191 190 else:
192 191 return SList([el for el in self if not pred(match_target(el))])
193 192
194 193 def fields(self, *fields):
195 194 """ Collect whitespace-separated fields from string list
196 195
197 196 Allows quick awk-like usage of string lists.
198 197
199 198 Example data (in var a, created by 'a = !ls -l')::
200 199 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
201 200 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
202 201
203 202 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
204 203 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
205 204 (note the joining by space).
206 205 a.fields(-1) is ['ChangeLog', 'IPython']
207 206
208 207 IndexErrors are ignored.
209 208
210 209 Without args, fields() just split()'s the strings.
211 210 """
212 211 if len(fields) == 0:
213 212 return [el.split() for el in self]
214 213
215 214 res = SList()
216 215 for el in [f.split() for f in self]:
217 216 lineparts = []
218 217
219 218 for fd in fields:
220 219 try:
221 220 lineparts.append(el[fd])
222 221 except IndexError:
223 222 pass
224 223 if lineparts:
225 224 res.append(" ".join(lineparts))
226 225
227 226 return res
228 227
229 228 def sort(self,field= None, nums = False):
230 229 """ sort by specified fields (see fields())
231 230
232 231 Example::
233 232 a.sort(1, nums = True)
234 233
235 234 Sorts a by second field, in numerical order (so that 21 > 3)
236 235
237 236 """
238 237
239 238 #decorate, sort, undecorate
240 239 if field is not None:
241 240 dsu = [[SList([line]).fields(field), line] for line in self]
242 241 else:
243 242 dsu = [[line, line] for line in self]
244 243 if nums:
245 244 for i in range(len(dsu)):
246 245 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
247 246 try:
248 247 n = int(numstr)
249 248 except ValueError:
250 249 n = 0;
251 250 dsu[i][0] = n
252 251
253 252
254 253 dsu.sort()
255 254 return SList([t[1] for t in dsu])
256 255
257 256
258 257 # FIXME: We need to reimplement type specific displayhook and then add this
259 258 # back as a custom printer. This should also be moved outside utils into the
260 259 # core.
261 260
262 261 # def print_slist(arg):
263 262 # """ Prettier (non-repr-like) and more informative printer for SList """
264 263 # print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
265 264 # if hasattr(arg, 'hideonce') and arg.hideonce:
266 265 # arg.hideonce = False
267 266 # return
268 267 #
269 268 # nlprint(arg)
270 269 #
271 270 # print_slist = result_display.when_type(SList)(print_slist)
272 271
273 272
274 273 def esc_quotes(strng):
275 274 """Return the input string with single and double quotes escaped out"""
276 275
277 276 return strng.replace('"','\\"').replace("'","\\'")
278 277
279 278
280 279 def qw(words,flat=0,sep=None,maxsplit=-1):
281 280 """Similar to Perl's qw() operator, but with some more options.
282 281
283 282 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
284 283
285 284 words can also be a list itself, and with flat=1, the output will be
286 285 recursively flattened.
287 286
288 287 Examples:
289 288
290 289 >>> qw('1 2')
291 290 ['1', '2']
292 291
293 292 >>> qw(['a b','1 2',['m n','p q']])
294 293 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
295 294
296 295 >>> qw(['a b','1 2',['m n','p q']],flat=1)
297 296 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
298 297 """
299 298
300 299 if isinstance(words, basestring):
301 300 return [word.strip() for word in words.split(sep,maxsplit)
302 301 if word and not word.isspace() ]
303 302 if flat:
304 303 return flatten(map(qw,words,[1]*len(words)))
305 304 return map(qw,words)
306 305
307 306
308 307 def qwflat(words,sep=None,maxsplit=-1):
309 308 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
310 309 return qw(words,1,sep,maxsplit)
311 310
312 311
313 312 def qw_lol(indata):
314 313 """qw_lol('a b') -> [['a','b']],
315 314 otherwise it's just a call to qw().
316 315
317 316 We need this to make sure the modules_some keys *always* end up as a
318 317 list of lists."""
319 318
320 319 if isinstance(indata, basestring):
321 320 return [qw(indata)]
322 321 else:
323 322 return qw(indata)
324 323
325 324
326 325 def grep(pat,list,case=1):
327 326 """Simple minded grep-like function.
328 327 grep(pat,list) returns occurrences of pat in list, None on failure.
329 328
330 329 It only does simple string matching, with no support for regexps. Use the
331 330 option case=0 for case-insensitive matching."""
332 331
333 332 # This is pretty crude. At least it should implement copying only references
334 333 # to the original data in case it's big. Now it copies the data for output.
335 334 out=[]
336 335 if case:
337 336 for term in list:
338 337 if term.find(pat)>-1: out.append(term)
339 338 else:
340 339 lpat=pat.lower()
341 340 for term in list:
342 341 if term.lower().find(lpat)>-1: out.append(term)
343 342
344 343 if len(out): return out
345 344 else: return None
346 345
347 346
348 347 def dgrep(pat,*opts):
349 348 """Return grep() on dir()+dir(__builtins__).
350 349
351 350 A very common use of grep() when working interactively."""
352 351
353 352 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
354 353
355 354
356 355 def idgrep(pat):
357 356 """Case-insensitive dgrep()"""
358 357
359 358 return dgrep(pat,0)
360 359
361 360
362 361 def igrep(pat,list):
363 362 """Synonym for case-insensitive grep."""
364 363
365 364 return grep(pat,list,case=0)
366 365
367 366
368 367 def indent(instr,nspaces=4, ntabs=0, flatten=False):
369 368 """Indent a string a given number of spaces or tabstops.
370 369
371 370 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
372 371
373 372 Parameters
374 373 ----------
375 374
376 375 instr : basestring
377 376 The string to be indented.
378 377 nspaces : int (default: 4)
379 378 The number of spaces to be indented.
380 379 ntabs : int (default: 0)
381 380 The number of tabs to be indented.
382 381 flatten : bool (default: False)
383 382 Whether to scrub existing indentation. If True, all lines will be
384 383 aligned to the same indentation. If False, existing indentation will
385 384 be strictly increased.
386 385
387 386 Returns
388 387 -------
389 388
390 389 str|unicode : string indented by ntabs and nspaces.
391 390
392 391 """
393 392 if instr is None:
394 393 return
395 394 ind = '\t'*ntabs+' '*nspaces
396 395 if flatten:
397 396 pat = re.compile(r'^\s*', re.MULTILINE)
398 397 else:
399 398 pat = re.compile(r'^', re.MULTILINE)
400 399 outstr = re.sub(pat, ind, instr)
401 400 if outstr.endswith(os.linesep+ind):
402 401 return outstr[:-len(ind)]
403 402 else:
404 403 return outstr
405 404
406 def native_line_ends(filename,backup=1):
407 """Convert (in-place) a file to line-ends native to the current OS.
408
409 If the optional backup argument is given as false, no backup of the
410 original file is left. """
411
412 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
413
414 bak_filename = filename + backup_suffixes[os.name]
415
416 original = open(filename).read()
417 shutil.copy2(filename,bak_filename)
418 try:
419 new = open(filename,'wb')
420 new.write(os.linesep.join(original.splitlines()))
421 new.write(os.linesep) # ALWAYS put an eol at the end of the file
422 new.close()
423 except:
424 os.rename(bak_filename,filename)
425 if not backup:
426 try:
427 os.remove(bak_filename)
428 except:
429 pass
430
431 405
432 406 def list_strings(arg):
433 407 """Always return a list of strings, given a string or list of strings
434 408 as input.
435 409
436 410 :Examples:
437 411
438 412 In [7]: list_strings('A single string')
439 413 Out[7]: ['A single string']
440 414
441 415 In [8]: list_strings(['A single string in a list'])
442 416 Out[8]: ['A single string in a list']
443 417
444 418 In [9]: list_strings(['A','list','of','strings'])
445 419 Out[9]: ['A', 'list', 'of', 'strings']
446 420 """
447 421
448 422 if isinstance(arg,basestring): return [arg]
449 423 else: return arg
450 424
451 425
452 426 def marquee(txt='',width=78,mark='*'):
453 427 """Return the input string centered in a 'marquee'.
454 428
455 429 :Examples:
456 430
457 431 In [16]: marquee('A test',40)
458 432 Out[16]: '**************** A test ****************'
459 433
460 434 In [17]: marquee('A test',40,'-')
461 435 Out[17]: '---------------- A test ----------------'
462 436
463 437 In [18]: marquee('A test',40,' ')
464 438 Out[18]: ' A test '
465 439
466 440 """
467 441 if not txt:
468 442 return (mark*width)[:width]
469 443 nmark = (width-len(txt)-2)//len(mark)//2
470 444 if nmark < 0: nmark =0
471 445 marks = mark*nmark
472 446 return '%s %s %s' % (marks,txt,marks)
473 447
474 448
475 449 ini_spaces_re = re.compile(r'^(\s+)')
476 450
477 451 def num_ini_spaces(strng):
478 452 """Return the number of initial spaces in a string"""
479 453
480 454 ini_spaces = ini_spaces_re.match(strng)
481 455 if ini_spaces:
482 456 return ini_spaces.end()
483 457 else:
484 458 return 0
485 459
486 460
487 461 def format_screen(strng):
488 462 """Format a string for screen printing.
489 463
490 464 This removes some latex-type format codes."""
491 465 # Paragraph continue
492 466 par_re = re.compile(r'\\$',re.MULTILINE)
493 467 strng = par_re.sub('',strng)
494 468 return strng
495 469
496 470
497 471 def dedent(text):
498 472 """Equivalent of textwrap.dedent that ignores unindented first line.
499 473
500 474 This means it will still dedent strings like:
501 475 '''foo
502 476 is a bar
503 477 '''
504 478
505 479 For use in wrap_paragraphs.
506 480 """
507 481
508 482 if text.startswith('\n'):
509 483 # text starts with blank line, don't ignore the first line
510 484 return textwrap.dedent(text)
511 485
512 486 # split first line
513 487 splits = text.split('\n',1)
514 488 if len(splits) == 1:
515 489 # only one line
516 490 return textwrap.dedent(text)
517 491
518 492 first, rest = splits
519 493 # dedent everything but the first line
520 494 rest = textwrap.dedent(rest)
521 495 return '\n'.join([first, rest])
522 496
523 497
524 498 def wrap_paragraphs(text, ncols=80):
525 499 """Wrap multiple paragraphs to fit a specified width.
526 500
527 501 This is equivalent to textwrap.wrap, but with support for multiple
528 502 paragraphs, as separated by empty lines.
529 503
530 504 Returns
531 505 -------
532 506
533 507 list of complete paragraphs, wrapped to fill `ncols` columns.
534 508 """
535 509 paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE)
536 510 text = dedent(text).strip()
537 511 paragraphs = paragraph_re.split(text)[::2] # every other entry is space
538 512 out_ps = []
539 513 indent_re = re.compile(r'\n\s+', re.MULTILINE)
540 514 for p in paragraphs:
541 515 # presume indentation that survives dedent is meaningful formatting,
542 516 # so don't fill unless text is flush.
543 517 if indent_re.search(p) is None:
544 518 # wrap paragraph
545 519 p = textwrap.fill(p, ncols)
546 520 out_ps.append(p)
547 521 return out_ps
548 522
549 523
550 524 def long_substr(data):
551 525 """Return the longest common substring in a list of strings.
552 526
553 527 Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python
554 528 """
555 529 substr = ''
556 530 if len(data) > 1 and len(data[0]) > 0:
557 531 for i in range(len(data[0])):
558 532 for j in range(len(data[0])-i+1):
559 533 if j > len(substr) and all(data[0][i:i+j] in x for x in data):
560 534 substr = data[0][i:i+j]
561 535 elif len(data) == 1:
562 536 substr = data[0]
563 537 return substr
564 538
565 539
566 540 def strip_email_quotes(text):
567 541 """Strip leading email quotation characters ('>').
568 542
569 543 Removes any combination of leading '>' interspersed with whitespace that
570 544 appears *identically* in all lines of the input text.
571 545
572 546 Parameters
573 547 ----------
574 548 text : str
575 549
576 550 Examples
577 551 --------
578 552
579 553 Simple uses::
580 554
581 555 In [2]: strip_email_quotes('> > text')
582 556 Out[2]: 'text'
583 557
584 558 In [3]: strip_email_quotes('> > text\\n> > more')
585 559 Out[3]: 'text\\nmore'
586 560
587 561 Note how only the common prefix that appears in all lines is stripped::
588 562
589 563 In [4]: strip_email_quotes('> > text\\n> > more\\n> more...')
590 564 Out[4]: '> text\\n> more\\nmore...'
591 565
592 566 So if any line has no quote marks ('>') , then none are stripped from any
593 567 of them ::
594 568
595 569 In [5]: strip_email_quotes('> > text\\n> > more\\nlast different')
596 570 Out[5]: '> > text\\n> > more\\nlast different'
597 571 """
598 572 lines = text.splitlines()
599 573 matches = set()
600 574 for line in lines:
601 575 prefix = re.match(r'^(\s*>[ >]*)', line)
602 576 if prefix:
603 577 matches.add(prefix.group(1))
604 578 else:
605 579 break
606 580 else:
607 581 prefix = long_substr(list(matches))
608 582 if prefix:
609 583 strip = len(prefix)
610 584 text = '\n'.join([ ln[strip:] for ln in lines])
611 585 return text
612 586
613 587
614 588 class EvalFormatter(Formatter):
615 589 """A String Formatter that allows evaluation of simple expressions.
616 590
617 591 Note that this version interprets a : as specifying a format string (as per
618 592 standard string formatting), so if slicing is required, you must explicitly
619 593 create a slice.
620 594
621 595 This is to be used in templating cases, such as the parallel batch
622 596 script templates, where simple arithmetic on arguments is useful.
623 597
624 598 Examples
625 599 --------
626 600
627 601 In [1]: f = EvalFormatter()
628 602 In [2]: f.format('{n//4}', n=8)
629 603 Out [2]: '2'
630 604
631 605 In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello")
632 606 Out [3]: 'll'
633 607 """
634 608 def get_field(self, name, args, kwargs):
635 609 v = eval(name, kwargs)
636 610 return v, name
637 611
638 612
639 613 @skip_doctest_py3
640 614 class FullEvalFormatter(Formatter):
641 615 """A String Formatter that allows evaluation of simple expressions.
642 616
643 617 Any time a format key is not found in the kwargs,
644 618 it will be tried as an expression in the kwargs namespace.
645 619
646 620 Note that this version allows slicing using [1:2], so you cannot specify
647 621 a format string. Use :class:`EvalFormatter` to permit format strings.
648 622
649 623 Examples
650 624 --------
651 625
652 626 In [1]: f = FullEvalFormatter()
653 627 In [2]: f.format('{n//4}', n=8)
654 628 Out[2]: u'2'
655 629
656 630 In [3]: f.format('{list(range(5))[2:4]}')
657 631 Out[3]: u'[2, 3]'
658 632
659 633 In [4]: f.format('{3*2}')
660 634 Out[4]: u'6'
661 635 """
662 636 # copied from Formatter._vformat with minor changes to allow eval
663 637 # and replace the format_spec code with slicing
664 638 def _vformat(self, format_string, args, kwargs, used_args, recursion_depth):
665 639 if recursion_depth < 0:
666 640 raise ValueError('Max string recursion exceeded')
667 641 result = []
668 642 for literal_text, field_name, format_spec, conversion in \
669 643 self.parse(format_string):
670 644
671 645 # output the literal text
672 646 if literal_text:
673 647 result.append(literal_text)
674 648
675 649 # if there's a field, output it
676 650 if field_name is not None:
677 651 # this is some markup, find the object and do
678 652 # the formatting
679 653
680 654 if format_spec:
681 655 # override format spec, to allow slicing:
682 656 field_name = ':'.join([field_name, format_spec])
683 657
684 658 # eval the contents of the field for the object
685 659 # to be formatted
686 660 obj = eval(field_name, kwargs)
687 661
688 662 # do any conversion on the resulting object
689 663 obj = self.convert_field(obj, conversion)
690 664
691 665 # format the object and append to the result
692 666 result.append(self.format_field(obj, ''))
693 667
694 668 return u''.join(py3compat.cast_unicode(s) for s in result)
695 669
696 670
697 671 @skip_doctest_py3
698 672 class DollarFormatter(FullEvalFormatter):
699 673 """Formatter allowing Itpl style $foo replacement, for names and attribute
700 674 access only. Standard {foo} replacement also works, and allows full
701 675 evaluation of its arguments.
702 676
703 677 Examples
704 678 --------
705 679 In [1]: f = DollarFormatter()
706 680 In [2]: f.format('{n//4}', n=8)
707 681 Out[2]: u'2'
708 682
709 683 In [3]: f.format('23 * 76 is $result', result=23*76)
710 684 Out[3]: u'23 * 76 is 1748'
711 685
712 686 In [4]: f.format('$a or {b}', a=1, b=2)
713 687 Out[4]: u'1 or 2'
714 688 """
715 689 _dollar_pattern = re.compile("(.*?)\$(\$?[\w\.]+)")
716 690 def parse(self, fmt_string):
717 691 for literal_txt, field_name, format_spec, conversion \
718 692 in Formatter.parse(self, fmt_string):
719 693
720 694 # Find $foo patterns in the literal text.
721 695 continue_from = 0
722 696 txt = ""
723 697 for m in self._dollar_pattern.finditer(literal_txt):
724 698 new_txt, new_field = m.group(1,2)
725 699 # $$foo --> $foo
726 700 if new_field.startswith("$"):
727 701 txt += new_txt + new_field
728 702 else:
729 703 yield (txt + new_txt, new_field, "", None)
730 704 txt = ""
731 705 continue_from = m.end()
732 706
733 707 # Re-yield the {foo} style pattern
734 708 yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
735 709
736 710 #-----------------------------------------------------------------------------
737 711 # Utils to columnize a list of string
738 712 #-----------------------------------------------------------------------------
739 713
740 714 def _chunks(l, n):
741 715 """Yield successive n-sized chunks from l."""
742 716 for i in xrange(0, len(l), n):
743 717 yield l[i:i+n]
744 718
745 719
746 720 def _find_optimal(rlist , separator_size=2 , displaywidth=80):
747 721 """Calculate optimal info to columnize a list of string"""
748 722 for nrow in range(1, len(rlist)+1) :
749 723 chk = map(max,_chunks(rlist, nrow))
750 724 sumlength = sum(chk)
751 725 ncols = len(chk)
752 726 if sumlength+separator_size*(ncols-1) <= displaywidth :
753 727 break;
754 728 return {'columns_numbers' : ncols,
755 729 'optimal_separator_width':(displaywidth - sumlength)/(ncols-1) if (ncols -1) else 0,
756 730 'rows_numbers' : nrow,
757 731 'columns_width' : chk
758 732 }
759 733
760 734
761 735 def _get_or_default(mylist, i, default=None):
762 736 """return list item number, or default if don't exist"""
763 737 if i >= len(mylist):
764 738 return default
765 739 else :
766 740 return mylist[i]
767 741
768 742
769 743 @skip_doctest
770 744 def compute_item_matrix(items, empty=None, *args, **kwargs) :
771 745 """Returns a nested list, and info to columnize items
772 746
773 747 Parameters
774 748 ----------
775 749
776 750 items :
777 751 list of strings to columize
778 752 empty : (default None)
779 753 default value to fill list if needed
780 754 separator_size : int (default=2)
781 755 How much caracters will be used as a separation between each columns.
782 756 displaywidth : int (default=80)
783 757 The width of the area onto wich the columns should enter
784 758
785 759 Returns
786 760 -------
787 761
788 762 Returns a tuple of (strings_matrix, dict_info)
789 763
790 764 strings_matrix :
791 765
792 766 nested list of string, the outer most list contains as many list as
793 767 rows, the innermost lists have each as many element as colums. If the
794 768 total number of elements in `items` does not equal the product of
795 769 rows*columns, the last element of some lists are filled with `None`.
796 770
797 771 dict_info :
798 772 some info to make columnize easier:
799 773
800 774 columns_numbers : number of columns
801 775 rows_numbers : number of rows
802 776 columns_width : list of with of each columns
803 777 optimal_separator_width : best separator width between columns
804 778
805 779 Examples
806 780 --------
807 781
808 782 In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l']
809 783 ...: compute_item_matrix(l,displaywidth=12)
810 784 Out[1]:
811 785 ([['aaa', 'f', 'k'],
812 786 ['b', 'g', 'l'],
813 787 ['cc', 'h', None],
814 788 ['d', 'i', None],
815 789 ['eeeee', 'j', None]],
816 790 {'columns_numbers': 3,
817 791 'columns_width': [5, 1, 1],
818 792 'optimal_separator_width': 2,
819 793 'rows_numbers': 5})
820 794
821 795 """
822 796 info = _find_optimal(map(len, items), *args, **kwargs)
823 797 nrow, ncol = info['rows_numbers'], info['columns_numbers']
824 798 return ([[ _get_or_default(items, c*nrow+i, default=empty) for c in range(ncol) ] for i in range(nrow) ], info)
825 799
826 800
827 801 def columnize(items, separator=' ', displaywidth=80):
828 802 """ Transform a list of strings into a single string with columns.
829 803
830 804 Parameters
831 805 ----------
832 806 items : sequence of strings
833 807 The strings to process.
834 808
835 809 separator : str, optional [default is two spaces]
836 810 The string that separates columns.
837 811
838 812 displaywidth : int, optional [default is 80]
839 813 Width of the display in number of characters.
840 814
841 815 Returns
842 816 -------
843 817 The formatted string.
844 818 """
845 819 if not items :
846 820 return '\n'
847 821 matrix, info = compute_item_matrix(items, separator_size=len(separator), displaywidth=displaywidth)
848 822 fmatrix = [filter(None, x) for x in matrix]
849 823 sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['columns_width'])])
850 824 return '\n'.join(map(sjoin, fmatrix))+'\n'
General Comments 0
You need to be logged in to leave comments. Login now