<quiz>
<!-- question: 41144  -->
  <question type="coderunner">
    <name>
      <text>PROTOTYPE_sql_allow_errors</text>
    </name>
    <questiontext format="html">
      <text>A variant of the original sql question type where any sqlite3 errors do not raise an exception but simply print the output from sqlite3 but with error line numbers removed.</text>
    </questiontext>
    <generalfeedback format="html">
      <text></text>
    </generalfeedback>
    <defaultgrade>1</defaultgrade>
    <penalty>0</penalty>
    <hidden>0</hidden>
    <idnumber></idnumber>
    <coderunnertype>sql_allow_errors</coderunnertype>
    <prototypetype>2</prototypetype>
    <allornothing>1</allornothing>
    <penaltyregime>10, 20, ...</penaltyregime>
    <precheck>0</precheck>
    <showsource>0</showsource>
    <answerboxlines>18</answerboxlines>
    <answerboxcolumns>100</answerboxcolumns>
    <answerpreload></answerpreload>
    <globalextra></globalextra>
    <useace>1</useace>
    <resultcolumns></resultcolumns>
    <template><![CDATA[# A variant of the original sql question type where any sqlite3
# errors do not raise an exception but simply print the output from
# sqlite3 but with error line numbers removed.
import subprocess, os, shutil, re

# Use Twig to get students answer and the columnwidth template parameter
student_answer = """{{ STUDENT_ANSWER | e('py') }}""".rstrip()
column_widths = []
{% for width in QUESTION.parameters.columnwidths %}
column_widths.append({{width}})
{% endfor %}

if not student_answer.endswith(';'):
    student_answer = student_answer + ';'
db_files = [fname for fname in os.listdir() if fname.endswith('.db')]
if len(db_files) == 0:
    raise Exception("No DB files found!")
elif len(db_files) == 1:
    db_working = db_files[0][:-3]  # Strip .db extension
else:
    raise Exception("Multiple DB files not implemented yet, sorry!")

SEPARATOR = "#<ab@17943918#@>#"
controls = [".mode column", ".headers on"]
if column_widths: # Add column width specifiers if given
    controls.append(".width " + ' '.join(str(width) for width in column_widths))
prelude = '\n'.join(controls) + '\n'

{% for TEST in TESTCASES %}
shutil.copyfile(db_files[0], db_working)  # Copy clean writeable db file
testcode = """{{ TEST.testcode | e('py') }}"""
extra = """{{ TEST.extra | e('py') }}"""
code_to_run = '\n'.join([prelude, extra, student_answer, testcode])
with open('commands', 'w') as sqlite_commands:
    sqlite_commands.write(code_to_run)

with open('commands') as cmd_input:
    text_input = cmd_input.read()
    try:
        output = subprocess.check_output(['sqlite3', db_working],
            input=text_input,
            stderr=subprocess.STDOUT,
            universal_newlines=True)
        print(output)
    except subprocess.CalledProcessError as e:
        # Remove the line number info from the error message so question
        # author can match the rest as expected output.
        output = re.sub(r"Error: near line \d+ *: *(.*)", r"Error: \1", e.output)
        print(output)

{% if not loop.last %}
print(SEPARATOR)
{% endif %}
{% endfor %}]]></template>
    <iscombinatortemplate>1</iscombinatortemplate>
    <allowmultiplestdins>0</allowmultiplestdins>
    <answer></answer>
    <validateonsave>0</validateonsave>
    <testsplitterre><![CDATA[|#<ab@17943918#@>#\n|ms]]></testsplitterre>
    <language>python3</language>
    <acelang>sql</acelang>
    <sandbox></sandbox>
    <grader>EqualityGrader</grader>
    <cputimelimitsecs></cputimelimitsecs>
    <memlimitmb>500</memlimitmb>
    <sandboxparams></sandboxparams>
    <templateparams></templateparams>
    <hoisttemplateparams>0</hoisttemplateparams>
    <twigall>0</twigall>
    <uiplugin>ace</uiplugin>
    <attachments>0</attachments>
    <attachmentsrequired>0</attachmentsrequired>
    <maxfilesize>0</maxfilesize>
    <filenamesregex></filenamesregex>
    <filenamesexplain></filenamesexplain>
    <displayfeedback>0</displayfeedback>
    <testcases>
    </testcases>
  </question>

</quiz>
