RAbraham
RAbraham

Reputation: 6306

Reduce indentation of nested functions in Python code generation

My goal is to generate functions dynamically and then save them in a file. For e.g, in my current attempt, On calling create_file

import io


def create_file():
    nested_func = make_nested_func()
    write_to_file([nested_func, a_root_func], '/tmp/code.py')


def a_root_func(x):
    pass


def make_nested_func():
    def a_nested_func(b, k):
        return b, k

    return a_nested_func


def write_to_file(code_list, path):
    import inspect
    code_str_list = [inspect.getsource(c) for c in code_list]
    with open(path, 'w') as ofh:
        for c in code_str_list:
            fh = io.StringIO(c)
            ofh.writelines(fh.readlines())
            ofh.write('\n')


create_file()

The output I want is('/tmp/code.py'):

def a_nested_func(b, k):
        return b, k

def a_root_func(x):
    pass

The output I get is('/tmp/code.py'):

    def a_nested_func(b, k):
        return b, k

def a_root_func(x):
    pass

a_nested_func is indented. How can I reduce the indentation? I can do lstrip etc. but I wonder if there is a better way.

Upvotes: 0

Views: 973

Answers (2)

Łukasz Rogalski
Łukasz Rogalski

Reputation: 23203

There's a function in built-in module, textwrap.dedent.

import textwrap
s = """
   abc
     def
"""
s2 = """
abc
  def
"""
assert textwrap.dedent(s) == s2

Upvotes: 3

Martijn Pieters
Martijn Pieters

Reputation: 1121306

Use the textwrap.dedent() function to remove the common leading whitespace:

import inspect
from textwrap import dedent

def write_to_file(code_list, path):
    code_str_list = [inspect.getsource(c) for c in code_list]
    with open(path, 'w') as ofh:
        for c in code_str_list:
            dedented = dedent(c)
            ofh.write(dedented + '\n')

Note that there is no need for a StringIO(string).readlines() dance here.

Upvotes: 3

Related Questions