2016-08-26 20:12:20 +03:00
|
|
|
class SourceBuilder:
|
|
|
|
"""This class should be used to build .py source files"""
|
|
|
|
|
2016-08-28 14:43:00 +03:00
|
|
|
def __init__(self, out_stream, indent_size=4):
|
2016-08-26 20:12:20 +03:00
|
|
|
self.current_indent = 0
|
|
|
|
self.on_new_line = False
|
|
|
|
self.indent_size = indent_size
|
2016-08-28 14:43:00 +03:00
|
|
|
self.out_stream = out_stream
|
2016-08-26 20:12:20 +03:00
|
|
|
|
2016-09-05 20:12:14 +03:00
|
|
|
# Was a new line added automatically before? If so, avoid it
|
|
|
|
self.auto_added_line = False
|
|
|
|
|
2016-08-26 20:12:20 +03:00
|
|
|
def indent(self):
|
2017-09-04 18:10:04 +03:00
|
|
|
"""Indents the current source code line
|
|
|
|
by the current indentation level
|
|
|
|
"""
|
2016-08-26 20:12:20 +03:00
|
|
|
self.write(' ' * (self.current_indent * self.indent_size))
|
|
|
|
|
2018-04-01 13:46:44 +03:00
|
|
|
def write(self, string, *args, **kwargs):
|
2017-09-04 18:10:04 +03:00
|
|
|
"""Writes a string into the source code,
|
|
|
|
applying indentation if required
|
|
|
|
"""
|
2016-08-26 20:12:20 +03:00
|
|
|
if self.on_new_line:
|
|
|
|
self.on_new_line = False # We're not on a new line anymore
|
2017-09-04 18:10:04 +03:00
|
|
|
# If the string was not empty, indent; Else probably a new line
|
|
|
|
if string.strip():
|
2016-08-27 12:59:23 +03:00
|
|
|
self.indent()
|
2016-08-26 20:12:20 +03:00
|
|
|
|
2018-04-01 13:46:44 +03:00
|
|
|
if args or kwargs:
|
|
|
|
self.out_stream.write(string.format(*args, **kwargs))
|
|
|
|
else:
|
|
|
|
self.out_stream.write(string)
|
2016-08-26 20:12:20 +03:00
|
|
|
|
2018-04-01 13:46:44 +03:00
|
|
|
def writeln(self, string='', *args, **kwargs):
|
2017-09-04 18:10:04 +03:00
|
|
|
"""Writes a string into the source code _and_ appends a new line,
|
|
|
|
applying indentation if required
|
|
|
|
"""
|
2018-04-01 13:46:44 +03:00
|
|
|
self.write(string + '\n', *args, **kwargs)
|
2016-08-26 20:12:20 +03:00
|
|
|
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
|
|
|
|
|
2016-09-05 20:12:14 +03:00
|
|
|
# Clear state after the user adds a new line
|
|
|
|
self.auto_added_line = False
|
|
|
|
|
2016-08-26 20:12:20 +03:00
|
|
|
def end_block(self):
|
2016-08-28 14:43:00 +03:00
|
|
|
"""Ends an indentation block, leaving an empty line afterwards"""
|
2016-08-26 20:12:20 +03:00
|
|
|
self.current_indent -= 1
|
2016-09-05 20:12:14 +03:00
|
|
|
|
|
|
|
# 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
|
2016-08-26 20:12:20 +03:00
|
|
|
|
|
|
|
def __str__(self):
|
2016-08-27 12:59:23 +03:00
|
|
|
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()
|