Passing indented code to compile()

Michael Chermside mcherm at mcherm.com
Wed May 7 11:56:46 EDT 2003


John Wilson writes:
> I hit a problem when trying to compile some Python code embedded in an XML
> document.
> 
> For example:
> 
>         <execute globals="globals" locals="locals">
>             print "hello"
>         </execute>
   [... problems ensue in dealing with indentation ...]

At first, I was going to tell you that the solution was to turn
off the pretty-printer in your XML generator (thus eliminating
all whitespace EXCEPT that intended to be part of the python code).

But then I read
> Yes, I think I can reasonably ask people to indent according to the Python
> rules. It does not seem reasonable to ask them to start their code in the
> first column of an XML document. It makes the XML look horrid.
and
> Personally I find:
> 
>         <execute globals="globals" locals="locals">
>         <![CDATA[
>             if i < 0:
>                 content = currentContent + lastContent
>             print text + content
>         ]]>
>         </execute>
> 
> easier on the eye than:
> 
>         <execute globals="globals" locals="locals"><![CDATA[if i < 0:
>     content = currentContent + lastContent
> print text + content]]></execute>

So it turns out that indenting the code in a human-readable-and-not-
left-aligned fashion within the XML source *IS* a requirement for
you. In that case, since the problem stems from you requiring extra
leading whitespace, the solution is to constrain how it is permitted.

Here is one possible solution:
         <execute globals="globals" locals="locals">
         <![CDATA[
             |text = """this string has five spaces
             |     after the newline"""
             |if i < 0:
             |    content = currentContent + lastContent
             |print text + content
         ]]>
         </execute>
Your rule can be that text between '|' and '\n' is part of the python
program, and anything else isn't. Thus the \n and spaces before
your CDATA section begins would be ignored. So would the indent
before the | and the | itself. The non-significant whitespace
and '|' characters are easy to strip off (see below), and the 
vertical line gives the viewer an easy way to see the indentation
level. You don't have to write special code for handling things 
like triple quoted strings (as illustrated).

# Warning: untested code
import re
pat = re.compile( r"^ +\|(.*\n)" )
code_lines = []
for line in content:
    mo = pat.match(line)
    if mo:
        code_lines.append(mo.group(1))
code = "".join(code_lines)

How does that work for you?

-- Michael Chermside






More information about the Python-list mailing list