Run file¶
When the student have submit his/her code, INGInious starts a new Docker container with the right environment for the task (as given in the .task file). Inside this container is launched a script, called run, that you have to provide in the directory of your task.
Here is a simple example of a run file, compatible with the default environment, that simply returns that the student’s code is OK:
#!/bin/bash
feedback-result success
The run script is simply an executable application (a bash script, a python script, or a compiled executable runnable by the container). INGInious’ default containers provides commands (also available as python libraries) to interact with the backend.
By default, the script is run inside the container in the /task directory, by a non-root user. You can modify the container to change this (and everything else).
Feedback commands¶
feedback-result¶
The feedback-result command sets the submission result of a task, or a problem, and uses the following syntax :
feedback-result [-i|--id PROBLEM_ID] RESULT
The execution result can be of different types:
- success : the student succeeded the task
- failed : there are error in the student answer
- timeout : the tests timed out
- overflow :there was a memory/disk overflow
- crash : the tests crashed
For instance, the following command will inform that the student succeeded:
feedback-result success
In Python : the equivalent command can be directly obtained with:
from inginious import feedback
feedback.set_global_result("success") # Set global result to success
feedback.set_problem_result("failed", "q1") # Set 'q1' subproblem result to failed
feedback-grade¶
The feedback-grade command sets the submission grade and uses the following syntax:
feedback-grade GRADE
If no grade is specified, the result score will be binary. This means that a failed submission will give a 0.0% score to the student, while a successful submission will give a 100.0% score to the student. For instance, the following command will give an 87.8% grade to the student:
feedback-grade 87.8
In Python : the equivalent command can be directly obtained with:
from inginious import feedback
feedback.set_grade(87.8) # Set the grade to 87.8%
feedback-msg-tpl¶
The feedback-msg-tpl sets the feedback message associated to the task or a subproblem, using a Jinja2 <http://jinja.pocoo.org/docs/2.9/> template.
It needs the name of a template. The command attempt to use a translated version of the template first; given that you give TPLNAME as first argument to the command, feedback-msg-tpl will attempt to find the template, by search in this order:
- [local_dir]/TPLNAME.XX_XX.tpl
- [task_dir]/lang/XX_XX/TPLNAME.tpl (preferred way)
- [local_dir]/TPLNAME.tpl
Once found, the template is parsed using Jinja2 <http://jinja.pocoo.org/docs/2.9/>, which allows you to send parameters to the template. These parameters should be given in the command line, in the form name=value:
feedback-msg-tpl TPLNAME option1=value1 option2=value2
Inside your template, you can use these parameters like this:
Option 1 was {{ option1 }} and the option 2 was {{ option 2 }}
Which will return
Option 1 was value1 and the option 2 was value2
See the Jinja2 documentation to discover all possibilities.
Your template must return a valid RestructuredText.
Optional parameters:
-a, --append | append to current feedback, if not specified, replace the current feedback. |
-i, --id PROBLEM_ID | |
problem id to which associate the feedback, leave empty for the whole task. |
feedback-msg¶
The feedback-msg command sets the feedback message associated to the task or a subproblem. It has several optional parameters:
-a, --append | append to current feedback, if not specified, replace the current feedback. |
-i, --id PROBLEM_ID | |
problem id to which associate the feedback, leave empty for the whole task. | |
-e, --escape | interprets backslash escapes |
-m, --message MESSAGE | |
feedback message |
If the message is not specified, the feedback message is read from stdin. For instance, the command can be used as follows:
feedback-msg -ae -m "This is the correct answer.\n\nWell done!"
In Python : the equivalent command can be directly obtained with:
from inginious import feedback
feedback.set_global_feedback("Well done !") # Set global feedback text to `Well done !`
feedback.set_problem_feedback("This is not correct.", "q1") # Set 'q1' problem feedback to `This is not correct.`
feedback-custom¶
The feedback-custom command sets a pair of key/value custom feedback, mainly used with plugins, and uses the following syntax :
feedback-custom [-j|--json] key value
The --json
parameter indicates if value
must be parsed as a JSON string.
Please refer to the plugin documentation to know which value you have to set for key
and value
parameters.
For instance, the following command set the value 56
to the score
key:
feedback-custom score 56
In Python : the equivalent command can be directly obtained with:
from inginious import feedback
feedback.set_custom_value("score", 56) # Set the `score` key to value 56
tag-set¶
The tag-set command sets the value of the tag specified by the tag identifier to True
or False
. It uses the
following syntax:
tag-set tag value
For instance, the following command set the value of the my_tag
tag to True
:
tag-set my_tag true
In Python : the equivalent command can be directly obtained with:
from inginious import feedback
feedback.feedback.set_tag("my_tag", True) # Sets the skill/misconception tag as True
tag¶
The tag command defines a new unexpected tag to appear in the submission feedback. It uses the followig syntax:
tag value
For instance, the following command defines a new A new tag
tag that will appear in the submission feedback:
tag "A new tag"
In Python : the equivalent command can be directly obtained with:
from inginious import feedback
feedback.tag("A new tag") # Sets a new unexpected tag
reStructuredText helper commands¶
Several helper commands are available to format the feedback text, which format is reStructuredText.
rst-code¶
The rst-code command generates a code-block with the specified code snippet and language to enable syntax highlighting. It has the following parameters:
-l, --language LANGUAGE | |
snippet language, leave empty to disable syntax highlighting | |
-e, --escape | interprets backslash escapes |
-c, --code CODE | |
snippet code |
If the code parameter is not specified, it is read on standard input. The result is written on standard output. For instance, the command can be used as follows:
cat test.java | rst-code -l java | feedback-msg -a
In Python : the equivalent command can be directly obtained with:
from inginious import rst
codeblock = rst.get_codeblock("java", "int a = 42;") # Java codeblock with `int a = 42;` code
feedback.set_global_feedback(codeblock, True) # Appends the codeblock to the global feedback
rst-image¶
The rst-image command generates a raw reStructuredText block containing the image to display. It has the following syntax
rst-image [-f|--format FORMAT] FILEPATH
The optional format parameter is used to specify the image format (jpg, png,…) if this is not explicitly specified the the image filename. The output is written on the standard output. For instance, the command can be used as follows:
rst-image generated.png | feedback -a
In Python : the equivalent command can be directly obtained with:
from inginious import rst
imgblock = rst.get_imageblock("smiley.png") # RST block with image
feedback.set_global_feedback(imgblock, True) # Appends the image block to the global feedback
rst-msgblock¶
The rst-msgblock command is used to generate a reStructuredText admonition in a specific colour according to the message type. It has the following optional parameters:
-c, --class CSS_CLASS | |
Bootstrap alert CSS class:
| |
-e, --escape | interprets backslash escapes |
-t, --title TITLE | |
message title | |
-m, --message MESSAGE | |
message text |
If the message parameter is not set, the message is read from standard input. For instance, the command can be used as follows:
rst-msgblock -c info -m "This is a note" | feedback -ae
In Python : the equivalent command can be directly obtained with:
from inginious import rst
admonition = rst.get_admonition("success", "Yeah!", "Well done!") # RST message block of class "success" and title "Yeah!"
feedback.set_global_feedback(admonition, True) # Appends the block to the global feedback
rst-indent¶
The rst-indent command is used to handle the indentation of the given text. It has the following optional arguments:
-e, --escape | interprets backslash escapes |
-c, --indent-char INDENT_CHAR | |
indentation char, default = tabulation | |
-a, --amount AMOUNT | |
amount of indentation, default = 1 | |
-m, --message MESSAGE | |
message text |
If the message parameter is not set, the text is read from standard input. The amount of indentation can be negative to de-indent the text. For instance, the command can be used as follows, to add an image to the feedback, inside a list item, for instance :
rst-image generated.png | rst-indent | feedback -a
In Python : the equivalent command can be directly obtained with:
from inginious import rst
rawhtml = rst.indent_block(1, "<p>A paragraph!</p>", "\t") # Indent the HTML code with 1 unit of tabulations
feedback.set_global_feedback(".. raw::\n\n" + rawhtml, True) # Appends the block to the global feedback
Input commands¶
getinput¶
The getinput command returns the input given by the student for a specific problem id. For example, for the problem id “pid”, the command to run is:
getinput pid
When a problem is defined with several boxes, the argument becomes pid/bid where “pid”
stands for the problem id and “bid” for “box id”. If the problem is a file upload, the problem id can be appended
with :filename
or :value
to retrieve its filename or value.
Note that getinput can also retrieve the username/group of the user that submitted the task. You simply have to run
getinput @username
If the submission is made as a user, it will contain the username. It it’s made as a group, it will contain the list of the user’s usernames in the group, joined with ‘,’.
The four letter code of the student’s language (for example en_US or fr_FR) can also be retrieved using
getinput @lang
Note that plugins are free to add new @-prefixed fields to the available input using the new_submission hook.
In Python : the equivalent command can be directly obtained with:
from inginious import input
thecode = input.get_input("q1") # Fetch the code for problem `q1`
parsetemplate¶
The parsetemplate command injects the input given by the student in a template. The command has this form:
parsetemplate [-o|--output outputfile] template
where template is the file to parse. Output file is the destination file. If the -o option is not given, the template will be replaced.
The markup in the templates is very simple: @prefix@problemid@suffix@. Prefix allows to correct the indentation when needed (this is useful in Python).
Example of template file (in java)
public class Main
{
public static void main(String[] args)
{
@ @problem_one@@
}
}
To access the filename and text content of a submitted file, the problemid can be followed by a :filename or :value suffix.
In Python : the equivalent command can be directly obtained with:
from inginious import input
thecode = input.parse_template("student.c") # Parse the `student.c` template file
thecode = input.parse_template("template.c", "student.c") # Parse the `template.c` template file and save the parsed file into `student.c`
run_student¶
run_student allows the run file to start, at will, sub-containers. This makes you able to secure the grading, making sure the untrusted code made by the student don’t interact with yours.
The sub-container is launched with a different user who has read-write accesses to the task student
subdirectory. Only the changes made in that directory will remain in the main container.
run_student is fully configurable; you can change the container image (environment), set new timeouts, new memory limits, … And you can call it as many time as you want.
--container CONTAINER | |
Name of the container to use. The default is the same as the current container. | |
--time TIME | Timeout (in CPU time) for the container. The default is the same as the current container. |
--hard-time TIME | |
Hard timeout for the container (in real time). The default is three times the value indicated for –time. | |
--memory MEMORY | |
Maximum memory for the container, in Megabytes. The default is the same as the current container. | |
--share-network | |
Share the network stack of the grading container with the student container. This is not the case by default. If the container container has network access, this will also be the case for the student! |
Beyond these optionals args, run_student also takes an additional (mandatory) arguments: the command to be run in the new container.
More technically, please note that:
- run_student proxies stdin, stdout, stderr, most signals and the return value
- There are special return values:
- 252 means that the command was killed due to an out-of-memory
- 253 means that the command timed out
- 254 means that an error occurred while running the proxy
archive¶
archive allows you to put some data in an archive that will be returned to the frontend and stored in the database for future reading. You can put there debug data, for example.
The command takes some arguments, which are all optional:
-o, --outsubdir DIRECTORY | |
will put the file (specified with -a or -r)in the specified sub-directory in the output archive | |
-a, --add FILEPATH | |
add the file to the archive | |
-r, --remove FILEPATH | |
remove the file from the archive |