Hi Phillipe
Usually I ask this sort of question in a way that requires the student to paste the entire class into the answer box. That avoid indentation hassles and if the student's answer is wrong it's easier for them and the tutors to see why.
However, you can write questions like this (and I used to do so when converting old written exams into a CodeRunner format) by writing extra code in the template that indents the student code to the required level, leaving it untouched if it's already correctly indented.
Here's what I think you had in mind:
The template for that is the following:
import sys
def __indent_line(line, extra_space):
"""Add the given amount of extra space at the start (or remove, if negative)"""
if extra_space >= 0:
return extra_space * ' ' + line
elif len(line) - len(line.lstrip()) >= -extra_space:
return line[extra_space + 1 : ]
else:
raise Exception("Line '{}' has a negative indent!".format(line))
def __indent(code, num_spaces):
"""Indent the given code by some fixed amount such that the first non-blank
line has 'num_spaces' spaces at the start.
"""
lines = code.split('\n')
non_empty_lines = [line for line in lines if line != '']
if non_empty_lines:
first = non_empty_lines[0]
current_indent = len(first) - len(first.lstrip())
reqd_indent = num_spaces - current_indent
indented_lines = [__indent_line(line, reqd_indent) for line in lines]
return '\n'.join(indented_lines) + '\n'
else:
return code # Empty
__skeleton__ = """class Car:
def __str__(self):
return "I have " + str(self.nbWheels) + " wheels"
{0} # Student code inserted here
"""
__student_answer__ = """{{ STUDENT_ANSWER | e('py') }}"""
try:
__indented__answer__ = __indent(__student_answer__, 4)
except Exception as e:
print(e, file=sys.stderr)
else:
exec(__skeleton__.format(__indented__answer__) + '\n' + """{{ TEST.testcode | e('py') }}""")
Of course, what's really need with questions of this sort is a way to pre-load the Ace-editor answer box with the skeleton code and write-protect all but the sections the student is allowed to alter. This is on my todo list, but you'll probably have to wait till the end of the year for that. Or later :-)
Richard