##// END OF EJS Templates
#7548: Fixed handling of != operator. Added tests.
#7548: Fixed handling of != operator. Added tests.

File last commit:

r16980:d2acc300
r20148:09a21620
Show More
text.py
783 lines | 22.8 KiB | text/x-python | PythonLexer
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 # encoding: utf-8
"""
Utilities for working with strings and text.
Thomas Kluyver
Only include inheritance diagram where it's useful.
r8795
Inheritance diagram:
.. inheritance-diagram:: IPython.utils.text
:parts: 3
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 """
#-----------------------------------------------------------------------------
Matthias BUSSONNIER
update copyright to 2011/20xx-2011...
r5390 # Copyright (C) 2008-2011 The IPython Development Team
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 #
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
import os
import re
Jonathan Frederic
Moved format date into common space
r12399 import sys
MinRK
wrap helpstring output to 80 cols
r4020 import textwrap
MinRK
add EvalFormatter for batch system (PBS) launcher templates...
r4004 from string import Formatter
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
from IPython.external.path import path
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388 from IPython.testing.skipdoctest import skip_doctest_py3, skip_doctest
Thomas Kluyver
More Python 3 compatibility fixes.
r4732 from IPython.utils import py3compat
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
Jonathan Frederic
Function -> variable
r12402 #-----------------------------------------------------------------------------
# Declarations
#-----------------------------------------------------------------------------
# datetime.strftime date format for ipython
if sys.platform == 'win32':
Jonathan Frederic
Woops, removed old function call
r12403 date_format = "%B %d, %Y"
Jonathan Frederic
Function -> variable
r12402 else:
Jonathan Frederic
Woops, removed old function call
r12403 date_format = "%B %-d, %Y"
Jonathan Frederic
Function -> variable
r12402
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 #-----------------------------------------------------------------------------
# Code
#-----------------------------------------------------------------------------
class LSString(str):
"""String derivative with a special access attributes.
These are normal strings, but with the special attributes:
.l (or .list) : value as list (split on newlines).
.n (or .nlstr): original value (the string itself).
.s (or .spstr): value as whitespace-separated string.
.p (or .paths): list of path objects
Any values which require transformations are computed only once and
cached.
Such strings are very useful to efficiently interact with the shell, which
typically only understands whitespace-separated options for commands."""
def get_list(self):
try:
return self.__list
except AttributeError:
self.__list = self.split('\n')
return self.__list
l = list = property(get_list)
def get_spstr(self):
try:
return self.__spstr
except AttributeError:
self.__spstr = self.replace('\n',' ')
return self.__spstr
s = spstr = property(get_spstr)
def get_nlstr(self):
return self
n = nlstr = property(get_nlstr)
def get_paths(self):
try:
return self.__paths
except AttributeError:
self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
return self.__paths
p = paths = property(get_paths)
Brian Granger
Refactor of prompts and the displayhook....
r2781 # FIXME: We need to reimplement type specific displayhook and then add this
# back as a custom printer. This should also be moved outside utils into the
# core.
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
Brian Granger
Refactor of prompts and the displayhook....
r2781 # def print_lsstring(arg):
# """ Prettier (non-repr-like) and more informative printer for LSString """
# print "LSString (.p, .n, .l, .s available). Value:"
# print arg
Bernardo B. Marques
remove all trailling spaces
r4872 #
#
Brian Granger
Refactor of prompts and the displayhook....
r2781 # print_lsstring = result_display.when_type(LSString)(print_lsstring)
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
class SList(list):
"""List derivative with a special access attributes.
These are normal lists, but with the special attributes:
Thomas Kluyver
Various minor docs fixes
r13592 * .l (or .list) : value as list (the list itself).
* .n (or .nlstr): value as a string, joined on newlines.
* .s (or .spstr): value as a string, joined on spaces.
* .p (or .paths): list of path objects
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
Any values which require transformations are computed only once and
cached."""
def get_list(self):
return self
l = list = property(get_list)
def get_spstr(self):
try:
return self.__spstr
except AttributeError:
self.__spstr = ' '.join(self)
return self.__spstr
s = spstr = property(get_spstr)
def get_nlstr(self):
try:
return self.__nlstr
except AttributeError:
self.__nlstr = '\n'.join(self)
return self.__nlstr
n = nlstr = property(get_nlstr)
def get_paths(self):
try:
return self.__paths
except AttributeError:
self.__paths = [path(p) for p in self if os.path.exists(p)]
return self.__paths
p = paths = property(get_paths)
def grep(self, pattern, prune = False, field = None):
""" Return all strings matching 'pattern' (a regex or callable)
This is case-insensitive. If prune is true, return all items
NOT matching the pattern.
If field is specified, the match must occur in the specified
whitespace-separated field.
Examples::
a.grep( lambda x: x.startswith('C') )
a.grep('Cha.*log', prune=1)
a.grep('chm', field=-1)
"""
def match_target(s):
if field is None:
return s
parts = s.split()
try:
tgt = parts[field]
return tgt
except IndexError:
return ""
Thomas Kluyver
Replace references to unicode and basestring
r13353 if isinstance(pattern, py3compat.string_types):
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
else:
pred = pattern
if not prune:
return SList([el for el in self if pred(match_target(el))])
else:
return SList([el for el in self if not pred(match_target(el))])
def fields(self, *fields):
""" Collect whitespace-separated fields from string list
Allows quick awk-like usage of string lists.
Example data (in var a, created by 'a = !ls -l')::
Thomas Kluyver
Various minor docs fixes
r13592
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
Thomas Kluyver
Various minor docs fixes
r13592 * ``a.fields(0)`` is ``['-rwxrwxrwx', 'drwxrwxrwx+']``
* ``a.fields(1,0)`` is ``['1 -rwxrwxrwx', '6 drwxrwxrwx+']``
(note the joining by space).
* ``a.fields(-1)`` is ``['ChangeLog', 'IPython']``
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
IndexErrors are ignored.
Without args, fields() just split()'s the strings.
"""
if len(fields) == 0:
return [el.split() for el in self]
res = SList()
for el in [f.split() for f in self]:
lineparts = []
for fd in fields:
try:
lineparts.append(el[fd])
except IndexError:
pass
if lineparts:
res.append(" ".join(lineparts))
return res
def sort(self,field= None, nums = False):
""" sort by specified fields (see fields())
Example::
Thomas Kluyver
Fix docstrings in utils.text
r13807
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 a.sort(1, nums = True)
Sorts a by second field, in numerical order (so that 21 > 3)
"""
#decorate, sort, undecorate
if field is not None:
dsu = [[SList([line]).fields(field), line] for line in self]
else:
dsu = [[line, line] for line in self]
if nums:
for i in range(len(dsu)):
numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
try:
n = int(numstr)
except ValueError:
n = 0;
dsu[i][0] = n
dsu.sort()
return SList([t[1] for t in dsu])
Brian Granger
Refactor of prompts and the displayhook....
r2781 # FIXME: We need to reimplement type specific displayhook and then add this
# back as a custom printer. This should also be moved outside utils into the
# core.
# def print_slist(arg):
# """ Prettier (non-repr-like) and more informative printer for SList """
# print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
# if hasattr(arg, 'hideonce') and arg.hideonce:
# arg.hideonce = False
# return
Bernardo B. Marques
remove all trailling spaces
r4872 #
Thomas Kluyver
Remove utils.io.nlprint
r9474 # nlprint(arg) # This was a nested list printer, now removed.
Bernardo B. Marques
remove all trailling spaces
r4872 #
Brian Granger
Refactor of prompts and the displayhook....
r2781 # print_slist = result_display.when_type(SList)(print_slist)
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
MinRK
allow utils.text.indent to [optionally] flatten existing indentation.
r3943 def indent(instr,nspaces=4, ntabs=0, flatten=False):
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 """Indent a string a given number of spaces or tabstops.
indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
allow utils.text.indent to [optionally] flatten existing indentation.
r3943 Parameters
----------
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
allow utils.text.indent to [optionally] flatten existing indentation.
r3943 instr : basestring
The string to be indented.
nspaces : int (default: 4)
The number of spaces to be indented.
ntabs : int (default: 0)
The number of tabs to be indented.
flatten : bool (default: False)
Whether to scrub existing indentation. If True, all lines will be
aligned to the same indentation. If False, existing indentation will
be strictly increased.
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
allow utils.text.indent to [optionally] flatten existing indentation.
r3943 Returns
-------
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
allow utils.text.indent to [optionally] flatten existing indentation.
r3943 str|unicode : string indented by ntabs and nspaces.
Bernardo B. Marques
remove all trailling spaces
r4872
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 """
MinRK
allow utils.text.indent to [optionally] flatten existing indentation.
r3943 if instr is None:
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 return
ind = '\t'*ntabs+' '*nspaces
MinRK
allow utils.text.indent to [optionally] flatten existing indentation.
r3943 if flatten:
pat = re.compile(r'^\s*', re.MULTILINE)
else:
pat = re.compile(r'^', re.MULTILINE)
outstr = re.sub(pat, ind, instr)
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 if outstr.endswith(os.linesep+ind):
return outstr[:-len(ind)]
else:
return outstr
def list_strings(arg):
"""Always return a list of strings, given a string or list of strings
as input.
Thomas Kluyver
Squash a couple more Sphinx warnings
r13914 Examples
--------
Thomas Kluyver
Fix docstrings in utils.text
r13807 ::
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
In [7]: list_strings('A single string')
Out[7]: ['A single string']
In [8]: list_strings(['A single string in a list'])
Out[8]: ['A single string in a list']
In [9]: list_strings(['A','list','of','strings'])
Out[9]: ['A', 'list', 'of', 'strings']
"""
Thomas Kluyver
Replace references to unicode and basestring
r13353 if isinstance(arg, py3compat.string_types): return [arg]
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 else: return arg
def marquee(txt='',width=78,mark='*'):
"""Return the input string centered in a 'marquee'.
Thomas Kluyver
Squash a couple more Sphinx warnings
r13914 Examples
--------
Thomas Kluyver
Fix docstrings in utils.text
r13807 ::
Brian Granger
Work to address the review comments on Fernando's branch....
r2498
In [16]: marquee('A test',40)
Out[16]: '**************** A test ****************'
In [17]: marquee('A test',40,'-')
Out[17]: '---------------- A test ----------------'
In [18]: marquee('A test',40,' ')
Out[18]: ' A test '
"""
if not txt:
return (mark*width)[:width]
Thomas Kluyver
More Python 3 compatibility fixes.
r4732 nmark = (width-len(txt)-2)//len(mark)//2
Brian Granger
Work to address the review comments on Fernando's branch....
r2498 if nmark < 0: nmark =0
marks = mark*nmark
return '%s %s %s' % (marks,txt,marks)
Brian Granger
Complete reorganization of InteractiveShell....
r2761 ini_spaces_re = re.compile(r'^(\s+)')
def num_ini_spaces(strng):
"""Return the number of initial spaces in a string"""
ini_spaces = ini_spaces_re.match(strng)
if ini_spaces:
return ini_spaces.end()
else:
return 0
Fernando Perez
Continue restructuring info system, move some standalone code to utils.
r2929
def format_screen(strng):
"""Format a string for screen printing.
This removes some latex-type format codes."""
# Paragraph continue
par_re = re.compile(r'\\$',re.MULTILINE)
strng = par_re.sub('',strng)
return strng
Fernando Perez
Add robust email-quote-stripping function to text utilities.
r7713
MinRK
wrap helpstring output to 80 cols
r4020 def dedent(text):
"""Equivalent of textwrap.dedent that ignores unindented first line.
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
wrap helpstring output to 80 cols
r4020 This means it will still dedent strings like:
'''foo
is a bar
'''
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
wrap helpstring output to 80 cols
r4020 For use in wrap_paragraphs.
"""
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
wrap helpstring output to 80 cols
r4020 if text.startswith('\n'):
# text starts with blank line, don't ignore the first line
return textwrap.dedent(text)
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
wrap helpstring output to 80 cols
r4020 # split first line
splits = text.split('\n',1)
if len(splits) == 1:
# only one line
return textwrap.dedent(text)
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
wrap helpstring output to 80 cols
r4020 first, rest = splits
# dedent everything but the first line
rest = textwrap.dedent(rest)
return '\n'.join([first, rest])
Fernando Perez
Add robust email-quote-stripping function to text utilities.
r7713
MinRK
wrap helpstring output to 80 cols
r4020 def wrap_paragraphs(text, ncols=80):
"""Wrap multiple paragraphs to fit a specified width.
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
wrap helpstring output to 80 cols
r4020 This is equivalent to textwrap.wrap, but with support for multiple
paragraphs, as separated by empty lines.
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
wrap helpstring output to 80 cols
r4020 Returns
-------
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
wrap helpstring output to 80 cols
r4020 list of complete paragraphs, wrapped to fill `ncols` columns.
"""
paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE)
text = dedent(text).strip()
paragraphs = paragraph_re.split(text)[::2] # every other entry is space
out_ps = []
indent_re = re.compile(r'\n\s+', re.MULTILINE)
for p in paragraphs:
Bernardo B. Marques
remove all trailling spaces
r4872 # presume indentation that survives dedent is meaningful formatting,
MinRK
wrap helpstring output to 80 cols
r4020 # so don't fill unless text is flush.
if indent_re.search(p) is None:
# wrap paragraph
p = textwrap.fill(p, ncols)
out_ps.append(p)
return out_ps
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
wrap helpstring output to 80 cols
r4020
Fernando Perez
Add robust email-quote-stripping function to text utilities.
r7713 def long_substr(data):
"""Return the longest common substring in a list of strings.
Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python
"""
substr = ''
if len(data) > 1 and len(data[0]) > 0:
for i in range(len(data[0])):
for j in range(len(data[0])-i+1):
if j > len(substr) and all(data[0][i:i+j] in x for x in data):
substr = data[0][i:i+j]
Bradley M. Froehle
Fix: longest_substr([]) -> ''...
r8147 elif len(data) == 1:
Fernando Perez
Fix logic for longest_substring when only one input....
r7715 substr = data[0]
Fernando Perez
Add robust email-quote-stripping function to text utilities.
r7713 return substr
def strip_email_quotes(text):
"""Strip leading email quotation characters ('>').
Fernando Perez
Add full docstring to strip_email_quotes
r7719
Removes any combination of leading '>' interspersed with whitespace that
appears *identically* in all lines of the input text.
Parameters
----------
text : str
Examples
--------
Simple uses::
In [2]: strip_email_quotes('> > text')
Out[2]: 'text'
Fernando Perez
Fix newlines embedded in docstring for correct display and doctests.
r7720 In [3]: strip_email_quotes('> > text\\n> > more')
Out[3]: 'text\\nmore'
Fernando Perez
Add full docstring to strip_email_quotes
r7719
Note how only the common prefix that appears in all lines is stripped::
Fernando Perez
Fix newlines embedded in docstring for correct display and doctests.
r7720 In [4]: strip_email_quotes('> > text\\n> > more\\n> more...')
Out[4]: '> text\\n> more\\nmore...'
Fernando Perez
Add full docstring to strip_email_quotes
r7719
So if any line has no quote marks ('>') , then none are stripped from any
of them ::
Fernando Perez
Fix newlines embedded in docstring for correct display and doctests.
r7720 In [5]: strip_email_quotes('> > text\\n> > more\\nlast different')
Out[5]: '> > text\\n> > more\\nlast different'
Fernando Perez
Add robust email-quote-stripping function to text utilities.
r7713 """
lines = text.splitlines()
matches = set()
for line in lines:
prefix = re.match(r'^(\s*>[ >]*)', line)
if prefix:
matches.add(prefix.group(1))
else:
break
else:
prefix = long_substr(list(matches))
if prefix:
strip = len(prefix)
text = '\n'.join([ ln[strip:] for ln in lines])
return text
Thomas Kluyver
Move strip_ansi function to utils
r16980 def strip_ansi(source):
"""
Remove ansi escape codes from text.
Parameters
----------
source : str
Source to remove the ansi from
"""
return re.sub(r'\033\[(\d|;)+?m', '', source)
Fernando Perez
Add robust email-quote-stripping function to text utilities.
r7713
MinRK
add EvalFormatter for batch system (PBS) launcher templates...
r4004 class EvalFormatter(Formatter):
"""A String Formatter that allows evaluation of simple expressions.
Thomas Kluyver
Copy EvalFormatter and FullEvalFormatter from prompt-manager branch.
r5353
Note that this version interprets a : as specifying a format string (as per
standard string formatting), so if slicing is required, you must explicitly
create a slice.
MinRK
add EvalFormatter for batch system (PBS) launcher templates...
r4004 This is to be used in templating cases, such as the parallel batch
script templates, where simple arithmetic on arguments is useful.
Bernardo B. Marques
remove all trailling spaces
r4872
MinRK
add EvalFormatter for batch system (PBS) launcher templates...
r4004 Examples
--------
Thomas Kluyver
Fix docstrings in utils.text
r13807 ::
In [1]: f = EvalFormatter()
In [2]: f.format('{n//4}', n=8)
Out[2]: '2'
In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello")
Out[3]: 'll'
Thomas Kluyver
Copy EvalFormatter and FullEvalFormatter from prompt-manager branch.
r5353 """
def get_field(self, name, args, kwargs):
v = eval(name, kwargs)
return v, name
Bernardo B. Marques
remove all trailling spaces
r4872
Thomas Kluyver
Add comment about string formatting changes in Python 3.4
r14002 #XXX: As of Python 3.4, the format string parsing no longer splits on a colon
# inside [], so EvalFormatter can handle slicing. Once we only support 3.4 and
# above, it should be possible to remove FullEvalFormatter.
Fernando Perez
Add full docstring to strip_email_quotes
r7719
Thomas Kluyver
Use DollarFormatter to fill in names in ! shell calls....
r5355 @skip_doctest_py3
Thomas Kluyver
Copy EvalFormatter and FullEvalFormatter from prompt-manager branch.
r5353 class FullEvalFormatter(Formatter):
"""A String Formatter that allows evaluation of simple expressions.
Any time a format key is not found in the kwargs,
it will be tried as an expression in the kwargs namespace.
Note that this version allows slicing using [1:2], so you cannot specify
a format string. Use :class:`EvalFormatter` to permit format strings.
Examples
--------
Thomas Kluyver
Fix docstrings in utils.text
r13807 ::
In [1]: f = FullEvalFormatter()
In [2]: f.format('{n//4}', n=8)
Out[2]: u'2'
In [3]: f.format('{list(range(5))[2:4]}')
Out[3]: u'[2, 3]'
MinRK
add EvalFormatter for batch system (PBS) launcher templates...
r4004
Thomas Kluyver
Fix docstrings in utils.text
r13807 In [4]: f.format('{3*2}')
Out[4]: u'6'
MinRK
add EvalFormatter for batch system (PBS) launcher templates...
r4004 """
MinRK
update EvalFormatter to allow arbitrary expressions...
r4654 # copied from Formatter._vformat with minor changes to allow eval
# and replace the format_spec code with slicing
def _vformat(self, format_string, args, kwargs, used_args, recursion_depth):
if recursion_depth < 0:
raise ValueError('Max string recursion exceeded')
result = []
for literal_text, field_name, format_spec, conversion in \
self.parse(format_string):
# output the literal text
if literal_text:
result.append(literal_text)
# if there's a field, output it
if field_name is not None:
# this is some markup, find the object and do
Thomas Kluyver
Copy EvalFormatter and FullEvalFormatter from prompt-manager branch.
r5353 # the formatting
MinRK
update EvalFormatter to allow arbitrary expressions...
r4654
Thomas Kluyver
Copy EvalFormatter and FullEvalFormatter from prompt-manager branch.
r5353 if format_spec:
MinRK
update EvalFormatter to allow arbitrary expressions...
r4654 # override format spec, to allow slicing:
field_name = ':'.join([field_name, format_spec])
# eval the contents of the field for the object
# to be formatted
obj = eval(field_name, kwargs)
# do any conversion on the resulting object
obj = self.convert_field(obj, conversion)
# format the object and append to the result
Thomas Kluyver
Copy EvalFormatter and FullEvalFormatter from prompt-manager branch.
r5353 result.append(self.format_field(obj, ''))
MinRK
update EvalFormatter to allow arbitrary expressions...
r4654
Thomas Kluyver
Use DollarFormatter to fill in names in ! shell calls....
r5355 return u''.join(py3compat.cast_unicode(s) for s in result)
MinRK
update EvalFormatter to allow arbitrary expressions...
r4654
Fernando Perez
Add full docstring to strip_email_quotes
r7719
Thomas Kluyver
Use DollarFormatter to fill in names in ! shell calls....
r5355 @skip_doctest_py3
Thomas Kluyver
Add DollarFormatter and tests.
r5354 class DollarFormatter(FullEvalFormatter):
"""Formatter allowing Itpl style $foo replacement, for names and attribute
access only. Standard {foo} replacement also works, and allows full
evaluation of its arguments.
Examples
--------
Thomas Kluyver
Fix docstrings in utils.text
r13807 ::
In [1]: f = DollarFormatter()
In [2]: f.format('{n//4}', n=8)
Out[2]: u'2'
In [3]: f.format('23 * 76 is $result', result=23*76)
Out[3]: u'23 * 76 is 1748'
In [4]: f.format('$a or {b}', a=1, b=2)
Out[4]: u'1 or 2'
Thomas Kluyver
Add DollarFormatter and tests.
r5354 """
Thomas Kluyver
Allow 2033 to get literal $ in shell commands.
r5365 _dollar_pattern = re.compile("(.*?)\$(\$?[\w\.]+)")
Thomas Kluyver
Add DollarFormatter and tests.
r5354 def parse(self, fmt_string):
for literal_txt, field_name, format_spec, conversion \
in Formatter.parse(self, fmt_string):
# Find $foo patterns in the literal text.
continue_from = 0
Thomas Kluyver
Allow 2033 to get literal $ in shell commands.
r5365 txt = ""
Thomas Kluyver
Add DollarFormatter and tests.
r5354 for m in self._dollar_pattern.finditer(literal_txt):
new_txt, new_field = m.group(1,2)
Thomas Kluyver
Allow 2033 to get literal $ in shell commands.
r5365 # $$foo --> $foo
if new_field.startswith("$"):
txt += new_txt + new_field
else:
yield (txt + new_txt, new_field, "", None)
txt = ""
Thomas Kluyver
Add DollarFormatter and tests.
r5354 continue_from = m.end()
# Re-yield the {foo} style pattern
Thomas Kluyver
Allow 2033 to get literal $ in shell commands.
r5365 yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
MinRK
add EvalFormatter for batch system (PBS) launcher templates...
r4004
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387 #-----------------------------------------------------------------------------
# Utils to columnize a list of string
#-----------------------------------------------------------------------------
Fernando Perez
Add full docstring to strip_email_quotes
r7719
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387 def _chunks(l, n):
"""Yield successive n-sized chunks from l."""
Thomas Kluyver
Fix references to xrange
r13356 for i in py3compat.xrange(0, len(l), n):
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387 yield l[i:i+n]
Fernando Perez
Add full docstring to strip_email_quotes
r7719
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388 def _find_optimal(rlist , separator_size=2 , displaywidth=80):
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387 """Calculate optimal info to columnize a list of string"""
for nrow in range(1, len(rlist)+1) :
Thomas Kluyver
Fix tests in utils
r13373 chk = list(map(max,_chunks(rlist, nrow)))
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387 sumlength = sum(chk)
ncols = len(chk)
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388 if sumlength+separator_size*(ncols-1) <= displaywidth :
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387 break;
return {'columns_numbers' : ncols,
'optimal_separator_width':(displaywidth - sumlength)/(ncols-1) if (ncols -1) else 0,
'rows_numbers' : nrow,
'columns_width' : chk
}
Fernando Perez
Add full docstring to strip_email_quotes
r7719
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387 def _get_or_default(mylist, i, default=None):
"""return list item number, or default if don't exist"""
if i >= len(mylist):
return default
else :
return mylist[i]
Fernando Perez
Add full docstring to strip_email_quotes
r7719
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388 @skip_doctest
Matthias BUSSONNIER
new completer for qtconsole...
r7393 def compute_item_matrix(items, empty=None, *args, **kwargs) :
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388 """Returns a nested list, and info to columnize items
Thomas Kluyver
Miscellaneous docs fixes
r9244 Parameters
----------
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388
Thomas Kluyver
Fix docstrings in utils.text
r13807 items
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388 list of strings to columize
Matthias BUSSONNIER
new completer for qtconsole...
r7393 empty : (default None)
default value to fill list if needed
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388 separator_size : int (default=2)
How much caracters will be used as a separation between each columns.
displaywidth : int (default=80)
The width of the area onto wich the columns should enter
Thomas Kluyver
Miscellaneous docs fixes
r9244 Returns
-------
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387
Thomas Kluyver
Fix docstrings in utils.text
r13807 strings_matrix
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388
nested list of string, the outer most list contains as many list as
rows, the innermost lists have each as many element as colums. If the
total number of elements in `items` does not equal the product of
rows*columns, the last element of some lists are filled with `None`.
Thomas Kluyver
Fix docstrings in utils.text
r13807 dict_info
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388 some info to make columnize easier:
Thomas Kluyver
Fix docstrings in utils.text
r13807 columns_numbers
number of columns
rows_numbers
number of rows
columns_width
list of with of each columns
optimal_separator_width
best separator width between columns
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388
Thomas Kluyver
Miscellaneous docs fixes
r9244 Examples
--------
Thomas Kluyver
Fix docstrings in utils.text
r13807 ::
In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l']
...: compute_item_matrix(l,displaywidth=12)
Out[1]:
([['aaa', 'f', 'k'],
['b', 'g', 'l'],
['cc', 'h', None],
['d', 'i', None],
['eeeee', 'j', None]],
{'columns_numbers': 3,
'columns_width': [5, 1, 1],
'optimal_separator_width': 2,
'rows_numbers': 5})
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387 """
Thomas Kluyver
Fix tests in utils
r13373 info = _find_optimal(list(map(len, items)), *args, **kwargs)
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387 nrow, ncol = info['rows_numbers'], info['columns_numbers']
Matthias BUSSONNIER
add option to choose for empty
r7392 return ([[ _get_or_default(items, c*nrow+i, default=empty) for c in range(ncol) ] for i in range(nrow) ], info)
MinRK
add EvalFormatter for batch system (PBS) launcher templates...
r4004
Fernando Perez
Add full docstring to strip_email_quotes
r7719
Fernando Perez
Move columnization code out of GUI code so we can test it better.
r4537 def columnize(items, separator=' ', displaywidth=80):
""" Transform a list of strings into a single string with columns.
Parameters
----------
items : sequence of strings
The strings to process.
separator : str, optional [default is two spaces]
The string that separates columns.
displaywidth : int, optional [default is 80]
Width of the display in number of characters.
Bernardo B. Marques
remove all trailling spaces
r4872
Fernando Perez
Move columnization code out of GUI code so we can test it better.
r4537 Returns
-------
The formatted string.
"""
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387 if not items :
Fernando Perez
Move columnization code out of GUI code so we can test it better.
r4537 return '\n'
Matthias BUSSONNIER
fix docstring, and debug leftover
r7388 matrix, info = compute_item_matrix(items, separator_size=len(separator), displaywidth=displaywidth)
Matthias BUSSONNIER
re-write columnize, with intermediate step....
r7387 fmatrix = [filter(None, x) for x in matrix]
sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['columns_width'])])
return '\n'.join(map(sjoin, fmatrix))+'\n'
Martín Gaitán
adding get_text_list helper inspired in django's one
r12919
Martín Gaitán
generalizing get_text_list helper
r12925 def get_text_list(list_, last_sep=' and ', sep=", ", wrap_item_with=""):
Martín Gaitán
adding get_text_list helper inspired in django's one
r12919 """
Return a string with a natural enumeration of items
>>> get_text_list(['a', 'b', 'c', 'd'])
'a, b, c and d'
Martín Gaitán
generalizing get_text_list helper
r12925 >>> get_text_list(['a', 'b', 'c'], ' or ')
Martín Gaitán
adding get_text_list helper inspired in django's one
r12919 'a, b or c'
Martín Gaitán
generalizing get_text_list helper
r12925 >>> get_text_list(['a', 'b', 'c'], ', ')
'a, b, c'
>>> get_text_list(['a', 'b'], ' or ')
Martín Gaitán
adding get_text_list helper inspired in django's one
r12919 'a or b'
>>> get_text_list(['a'])
'a'
>>> get_text_list([])
''
>>> get_text_list(['a', 'b'], wrap_item_with="`")
'`a` and `b`'
Martín Gaitán
generalizing get_text_list helper
r12925 >>> get_text_list(['a', 'b', 'c', 'd'], " = ", sep=" + ")
'a + b + c = d'
Martín Gaitán
adding get_text_list helper inspired in django's one
r12919 """
if len(list_) == 0:
return ''
if wrap_item_with:
list_ = ['%s%s%s' % (wrap_item_with, item, wrap_item_with) for
item in list_]
if len(list_) == 1:
return list_[0]
Martín Gaitán
generalizing get_text_list helper
r12925 return '%s%s%s' % (
sep.join(i for i in list_[:-1]),
last_sep, list_[-1])