10

I am trying to take Redhat kickstart files and modify them in python before using them in a server setup. My app uses python to curl the original kickstart file from my Redhat Satellite server then I'm doing a string replace on certain values in the kickstart file. When I curl the file in python it comes back as a multi-line string, which is what I need in order for redhat kickstart to interpret the file correctly. But when I return the string variable through one of these frameworks (web2py, bottle, flask) something is happening and it is not returning it as a multi-line string, I need it to preserve the exact format of the original file besides the areas I change. I don't want to put my kickstart files in templates because I manage them through satellite, if I curl the file from satellite then it picks up any modifications without needing to go into the template ever time. Then in a template or something I either return the string without a template or in a template file I only pass 1 variable to the template as the entire kickstart file.

@route('/kickstart/<name>')
def kickstart(name):

    ks = vula.kickstarter.kickstart.Kickstarter()
    ks_file = ks.getKickstartFile()

    return pystache.render('{{kickstart}}', {'kickstart': ks_file})

Here is the method in my vula package. It returns the file exactly the way I need it. But again something is happening between this and returning this value through the framework.

def getKickstartFile(self):

    response = urllib2.urlopen('https://my-satellite-server/core-kickstarter')
    ks_file = response.read()

    return ks_file

I started off using Bottle as a framework but I found a statement that says they are not capable of returning multi-line strings, so scratch that. I moved over to Flask but currently Flask is doing the same thing. I am still learning python and possibly I'm doing something wrong, but I need any help possible to get this working correctly. I would like to output a multi-line string. I understand that you use either

""" or '''

for multi-line strings, but even after you do that and send it through a framework it will still print to the screen as one continuous line. What am I doing wrong? As a vary last resort I will be forced to put the kickstart files into templates if I cannot output multi-line strings.

3
  • How do you check final output? In console or via web with browser? If via web of course you won't see new lines, becouse it should be <br> and not \n, but in your case of course you don't need <br>, you just don't see new lines but as for console it should be fine... Commented Jun 25, 2013 at 21:18
  • Ensure that the mime type of the response is what you expect. By default Flask will send responses as HTML, sounds like in your case you want plain text. Commented Jun 26, 2013 at 1:07
  • Yeah you guys are right. I didn't think about the content type. I have just recently started learning python and using some of these frameworks, so some times I don't look in the right places for my answers. Commented Jun 26, 2013 at 13:21

2 Answers 2

13

Both Bottle and Flask can handle multi-line strings just fine. Your issue is that your data is being interpreted as text/html by default and in HTML any combination of whitespace is collapsed into a single space when displayed. In order to ensure that your data comes back exactly as you sent it you'll want to set the Content-Type header to text/plain.

In Flask:

# If you want *all* your responses to be text/plain
# then this is what you want
@app.after_request
def treat_as_plain_text(response):
    response.headers["content-type"] = "text/plain"
    return response

# If you want only *this* route to respond
# with Content-Type=text/plain
@app.route("/plain-text")
def a_plain_text_route():
    response = make_response(getKickstartFile())
    response.headers["content-type"] = "text/plain"
    return response

In Bottle:

@route("/plain-text")
def plain_text():
    response.content_type = "text/plain"
    return """This
              multi-line string
              will show up
              just fine"""
Sign up to request clarification or add additional context in comments.

1 Comment

After reading your post I was able to find the documentation in Flask explaining this. Thanks for the help.
5

Sean's answer is the correct way to go, but if you just want to test something you could use the xmp tag:

@app.route("/"):
def hello():
    return """<xmp>
              Hello,
              Multiline!
              </xmp>"""

decorator version

You could also create your own decorator for this:

from functools import wraps

def multiline(fn):
    @wraps(fn)
    def _fn(*args, **kwargs):
        return "<xmp>" + fn(*args, **kwargs) + "</xmp>"
    return _fn

Then you can do:

    @app.route("/"):
    @multiline
    def hello():
    return """Hello,
              Multiline!"""

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.