class SourceBuilder: """This class should be used to build .py source files""" def __init__(self, out_stream, indent_size=4): self.current_indent = 0 self.on_new_line = False self.indent_size = indent_size self.out_stream = out_stream # Was a new line added automatically before? If so, avoid it self.auto_added_line = False def indent(self): """Indents the current source code line by the current indentation level """ self.write(' ' * (self.current_indent * self.indent_size)) def write(self, string, *args, **kwargs): """Writes a string into the source code, applying indentation if required """ if self.on_new_line: self.on_new_line = False # We're not on a new line anymore # If the string was not empty, indent; Else probably a new line if string.strip(): self.indent() if args or kwargs: self.out_stream.write(string.format(*args, **kwargs)) else: self.out_stream.write(string) def writeln(self, string='', *args, **kwargs): """Writes a string into the source code _and_ appends a new line, applying indentation if required """ self.write(string + '\n', *args, **kwargs) self.on_new_line = True # If we're writing a block, increment indent for the next time if string and string[-1] == ':': self.current_indent += 1 # Clear state after the user adds a new line self.auto_added_line = False def end_block(self): """Ends an indentation block, leaving an empty line afterwards""" self.current_indent -= 1 # If we did not add a new line automatically yet, now it's the time! if not self.auto_added_line: self.writeln() self.auto_added_line = True def __str__(self): self.out_stream.seek(0) return self.out_stream.read() def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.out_stream.close()