Question Authors' Forum

Do not display input information

Do not display input information

by yang ningyu -
Number of replies: 6

Hello, Richard Lobb, once again:

Question type:python3

How can I not display the input information (do not display the contents of the yellow box)

Please help me, thank you!
11
In reply to yang ningyu

Re: Do not display input information

by Richard Lobb -

The python3_w_input question type replaces the standard Python input function with one that prints the prompt parameter and also echos the characters read from standard input. In full the template is:

__saved_input__ = input
def input(prompt=''):
    s = __saved_input__(prompt)
    print(s)
    return s

{{ STUDENT_ANSWER }}
SEPARATOR = "##"

{% for TEST in TESTCASES %}
{{ TEST.testcode }}
{% if not loop.last %}
print(SEPARATOR)
{% endif %}
{% endfor %}
@17943918#@>

It sounds like you want neither the prompt nor the echoed characters. So you could customise that question type to:

__saved_input__ = input
def input(prompt=''):
    s = __saved_input__()
    return s

{{ STUDENT_ANSWER }}
SEPARATOR = "##"

{% for TEST in TESTCASES %}
{{ TEST.testcode }}
{% if not loop.last %}
print(SEPARATOR)
{% endif %}
{% endfor %}
@17943918#@>
In reply to Richard Lobb

Re: Do not display input information

by yang ningyu -
Thank you very much. I can realize my request. But Python 3_ html_ gapfiller Question type,I want neither the prompt nor the echoed characters.

""" The prototype template for a python gap-filler.
"""
import subprocess, sys, json, re, html
KNOWN_PARAMS = {
    "gapfiller_ui_source": "globalextra",
    'proscribedsubstrings': [],
    'maxfieldlength': 50
}
PARAMS = json.loads("""{{ QUESTION.parameters | json_encode | e('py') }}""")
unknown_params = set(PARAMS.keys()) - set(KNOWN_PARAMS.keys())
filtered_params = [param for param in unknown_params if not param.startswith('_')]
if filtered_params:
    print("Unexpected template parameter(s):", list(sorted(filtered_params)))
for param, default in KNOWN_PARAMS.items():
    if param not in PARAMS:
        PARAMS[param] = default
PARAMS['IS_PRECHECK'] = "{{ IS_PRECHECK }}" == "1"
class TestCase:
    def __init__(self, dict_rep):
        """Construct a testcase from a dictionary representation obtained via JSON"""
        self.testcode = dict_rep['testcode']
        self.stdin = dict_rep['stdin']
        self.expected = dict_rep['expected']
        self.extra = dict_rep['extra']
        self.display = dict_rep['display']
        try:
            self.testtype = int(dict_rep['testtype'])
        except:
            self.testtype = 0
        self.hiderestiffail = bool(int(dict_rep['hiderestiffail']))
        self.useasexample = bool(int(dict_rep['useasexample']))
        self.mark = float(dict_rep['mark'])    
def get_test_cases():
    """Return an array of Test objects from the template parameter TESTCASES"""
    test_cases = [TestCase(test) for test in json.loads("""{{ TESTCASES | json_encode | e('py') }}""")]
    return test_cases
# Expand the given code by inserting the given fields into the
# given code, after splitting it with the given regular expression.
# If highlight is true, the inserted text is wrapped in a <span> element
# with yellow background.
def insert_fields(code, fields, splitter=r"\{\[.*?\]\}", highlight=False):
    global splitter_used
    splitter_used = splitter # Hack - save for re-use when displaying tests
    bits = re.split(splitter, code)
    if len(bits) != len(fields) + 1:
        print("Richard has goofed. Please report", file=sys.stderr)
        sys.exit()
    prog = bits[0]
    i = 1
    for value in fields:
        if len(value.splitlines()) > 1:
            # Indent all lines in a textarea by the indent of the first line
            indent = len(prog.splitlines()[-1])
            value_bits = value.splitlines()
            for j in range(1, len(value_bits)):
                value_bits[j] = indent * ' ' + value_bits[j]
            value = '\n'.join(value_bits) + '\n'
        if highlight:
            value = f"<span style='background-color:yellow;'>{value}</span>"
        prog += value + bits[i]
        i += 1
    return prog
def run_one_test(prog, stdin):
    with open("prog.py", "w") as src:
        print(prog, file=src)
    try:
        output = subprocess.check_output(
            ["python3", "prog.py"],
            input=stdin,
            stderr=subprocess.STDOUT,
            universal_newlines=True,
        )
    except subprocess.CalledProcessError as e:
        output = e.output + '\n' if e.output else ''
    return output
def precheck(field_values):
    """Checks field lengths and ensure no proscribed strings present"""
    errors = []
    for field in field_values:
        leader = field[0:10]
        if len(field) > 10:
            leader += '...'
        if len(field) > PARAMS['maxfieldlength']:
            errors.append(f"Field '{leader}' is too long. Maximum length is {PARAMS['maxfieldlength']}")
        for bad in PARAMS['proscribedsubstrings']:
            if bad in field:
                errors.append(f"Field '{leader}' contains the banned string '{bad}'")
    return errors
def htmlize(message):
    """An html version of the given error message"""
    return '<pre>' + html.escape(message) + '</pre>' if message else ''
def run_tests():
    global splitter_used
    tests = get_test_cases()
    test = tests[0]
    field_values = json.loads(""" {{ STUDENT_ANSWER | e('py') }}""")
    errors = precheck(field_values)
    is_precheck = PARAMS['IS_PRECHECK']
    if  is_precheck and not errors:
        prologue = "<p class='precheckresult'>Passed 🙂</p>"
    elif is_precheck and errors:
        prologue = "<p class='precheckresult'>Failed, as follows.</p>"
    elif errors:
        prologue = "<div class='coderunner-test-results bad'><h3>Pre-run checks failed</h3>\n"
    if errors:
        prologue = prologue + htmlize('\n'.join(errors))
        
    if is_precheck or errors:
        outcome = {"fraction": 0 if errors else 1, 'prologuehtml': prologue}
    elif not is_precheck:
        source = """{{ gapfiller_ui_source | e('py') }}"""
        postlude = ''
        show_test_col = any(test.testcode.strip() != '' for test in tests)
        if show_test_col:
            test_results = [["Test", "Expected", "Got", "iscorrect"]]
            column_formats = ['%h', '%s', '%s']
        else:
            test_results = [["Expected", "Got", "iscorrect"]]
            column_formats = ['%s', '%s']
        all_correct = True
        for test in tests:
            if source and source == 'test0':
                raw_prog = test.testcode
            else:
                raw_prog = """{{ QUESTION.globalextra | e('py') }}"""
            prog = insert_fields(raw_prog, field_values)
            if source != 'test0':
                prog += '\n' + test.testcode
            output = run_one_test(prog, test.stdin)
            correct = output.strip() == test.expected.strip()
            if show_test_col:
                test_col = htmlize(test.testcode)
                if source == 'test0':
                    test_col = insert_fields(test_col, field_values, splitter_used, True)
                test_results.append([test_col, test.expected, output, correct])
            else:
                test_results.append([test.expected, output, correct])
            all_correct = all_correct and correct   
        mark = 1.0 if all_correct else 0
        outcome = {
            'fraction': mark,
            'testresults': test_results,
            'epiloguehtml': postlude,
            'columnformats': column_formats,
            'showdifferences': True
        }
    
    print(json.dumps(outcome))
run_tests()


In reply to yang ningyu

Re: Do not display input information

by Richard Lobb -

You can use more-or-less the same solution. Insert the following at the start of the file prog.py

__saved_input__ = input
def input(prompt=''):
    s = __saved_input__()
    return s
In reply to Richard Lobb

Re: Do not display input information

by yang ningyu -

Sorry,I'm a beginner. I can't find  prog.py

In reply to yang ningyu

Re: Do not display input information

by Richard Lobb -

If you're just starting out with CodeRunner, I'd suggest that you try to get by using the standard question types, and slowly build your skills at programming new question types. It's usually possible to ask questions that work pretty well with the built-in question types. In this case, do you really need a gap-filler that involves the student's writing a call to input? And if so, can you not tell them that they mustn't use a prompt string?

In reply to Richard Lobb

Re:不显示输入信息

by yang ningyu -

Yes, I finally deleted the prompt. Thank you for your help. I will continue to study.


Thank you for developing such great software to help my students