Python undent
It's been way too long since I had a Python-related entry in here.
(That's what intense startup-style fuller-than-full-time Ruby work
will do for ya!)
I occasionally attend
BayPIGgies meetings,
and there's been a discussion yesterday and today on their
e-mail list about recipes to help integrate Python's
multi-line triple-quoted strings with Python's indentation-based
syntax. I had just read Hal Fulton's book
The Ruby Way, and
seen his "margin" method for multiline strings.
So, with that inspiration and with the idea that a simple
regular expression substitution ought to be able to do the
job, Here's what I came up with:
# Shortest version: Sets the M flag inside the pattern:
import re
def undent (str):
return re.sub( r'(?m)^\s*\S(.*)$', r'\1', str.rstrip() )
It works at runtime (so it isn't suitable for use inside
frequently-called or performance-critical routines), and it
isn't as strict as the
Python cookbook example that Michael Bernstein
mentioned, but it's short, easy to understand, and a bit
easier to use (less cluttered-looking at usage
site) than Chad's more efficient compile-time version.
For a slightly more efficient version, you can
pre-compile the regex pattern, although that pollutes the
global namespace. Since the compile can set the M (Multi-line)
flag separately, you no longer need the "(?m)" inside the
pattern.
import re
undent_pat = re.compile( r'^\s*\S(.*)$', re.M )
def undent (str):
return undent_pat.sub( r'\1', str.rstrip() )
Here's an example of what its usage looks like:
def getCustomerInfo(cust_id):
sql = undent( '''\
|select customers.name as name,
| sum(invoices.amount) as amount_total,
| blah as blah
| from customers
| etc...
''')
The output from that is
select customers.name as name,
sum(invoices.amount) as amount_total,
blah as blah
from customers
etc...
(The "s" of "select" is in the first column of the resulting string.)
Maybe I ought to add this to that cookbook entry.
1:01:19 AM