inginious.frontend package¶
Package that implements a webapp for INGInious
Subpackages¶
- inginious.frontend.pages package
- Subpackages
- inginious.frontend.pages.api package
- inginious.frontend.pages.course_admin package
- Submodules
- inginious.frontend.pages.course_admin.audience_edit module
- inginious.frontend.pages.course_admin.danger_zone module
- inginious.frontend.pages.course_admin.settings module
- inginious.frontend.pages.course_admin.student_list module
CourseStudentListPageCourseStudentListPage.GET_AUTH()CourseStudentListPage.POST_AUTH()CourseStudentListPage.get_audiences_params()CourseStudentListPage.get_requested_field_user_info()CourseStudentListPage.get_student_list_params()CourseStudentListPage.get_user_lists()CourseStudentListPage.methodsCourseStudentListPage.page()CourseStudentListPage.post_audiences()CourseStudentListPage.post_groups()CourseStudentListPage.post_student_list()CourseStudentListPage.update_group()
- inginious.frontend.pages.course_admin.submission module
- inginious.frontend.pages.course_admin.task_edit module
- inginious.frontend.pages.course_admin.task_edit_file module
CourseTaskFileUploadCourseTaskFilesCourseTaskFiles.GET_AUTH()CourseTaskFiles.POST_AUTH()CourseTaskFiles.action_create()CourseTaskFiles.action_delete()CourseTaskFiles.action_download()CourseTaskFiles.action_edit()CourseTaskFiles.action_edit_save()CourseTaskFiles.action_rename()CourseTaskFiles.action_upload()CourseTaskFiles.get_task_filelist()CourseTaskFiles.methodsCourseTaskFiles.show_tab_file()CourseTaskFiles.verify_path()
- inginious.frontend.pages.course_admin.task_list module
- inginious.frontend.pages.course_admin.utils module
- Submodules
- inginious.frontend.pages.group module
- inginious.frontend.pages.course module
- inginious.frontend.pages.index module
- inginious.frontend.pages.maintenance module
- inginious.frontend.pages.tasks module
- inginious.frontend.pages.utils module
- Subpackages
- inginious.frontend.plugins package
- Subpackages
- Submodules
- inginious.frontend.plugins.demo module
- inginious.frontend.plugins.contests module
- inginious.frontend.plugins.git_repo module
- inginious.frontend.plugins.simple_grader module
- inginious.frontend.tests package
Submodules¶
inginious.frontend.accessible_time module¶
Contains AccessibleTime, class that represents the period of time when a course/task is accessible
- class inginious.frontend.accessible_time.AccessibleTime(val=None)[source]¶
Bases:
objectrepresents the period of time when a course/task is accessible
- after_start(when=None)[source]¶
Returns True if the task/course is or have been accessible in the past
- get_soft_end_date()[source]¶
Return a datetime object, representing the soft deadline for accessibility
- get_start_date()[source]¶
Return a datetime object, representing the date when the task/course become accessible
- get_std_end_date()[source]¶
If the date is custom, return the end datetime in ISO format. Else, returns “”.
- get_std_soft_end_date()[source]¶
If the date is custom, return the soft datetime in ISO format. Else, returns “”.
inginious.frontend.arch_helper module¶
- inginious.frontend.arch_helper.create_arch(configuration, context)[source]¶
Helper that can start a simple complete INGInious arch locally if needed, or a client to a remote backend. Intended to be used on command line, makes uses of exit() and the logger inginious.frontend. :type configuration: :param configuration: configuration dict :type context: :param context: a ZMQ context :param is_testing: boolean :return: a Client object
inginious.frontend.app module¶
Starts the webapp
inginious.frontend.courses module¶
A course class with some modification for users
- class inginious.frontend.courses.Course(courseid, content)[source]¶
Bases:
objectA course with some modification for users
- classmethod get(courseid)[source]¶
Fetch a course with id courseid from the specified course filesystem
- Return type:
- get_access_control_accept()[source]¶
Returns either True (accept) or False (deny), depending on the control type used to verify that users can register to the course
- get_access_control_list()[source]¶
Returns the list of all users/emails/binding methods/… (see get_access_control_method) allowed by the AC list
- Return type:
List[str]
- get_access_control_method()[source]¶
Returns either None, “username”, “binding”, or “email”, depending on the method used to verify that users can register to the course
- get_accessibility(plugin_override=True)[source]¶
Return the AccessibleTime object associated with the accessibility of this course
- classmethod get_all()[source]¶
Returns a dictionnary with courseid=>Course mapping
- Return type:
dict[str,Course]
- get_archiving_date()[source]¶
Returns the date at which the course was archived as a string (None if not archived)
- get_registration_accessibility()[source]¶
Return the AccessibleTime object associated with the registration
- get_registration_password()[source]¶
Returns the password needed for registration (None if there is no password)
- is_open_to_non_staff()[source]¶
Returns true if the course is accessible by users that are not administrator of this course
- is_password_needed_for_registration()[source]¶
Returns true if a password is needed for registration
- is_user_accepted_by_access_control(user_info)[source]¶
Returns True if the user is allowed by the ACL
- lti_config()[source]¶
LTI Tool config dictionary. Specs are at https://github.com/dmitry-viskov/pylti1.3/blob/master/README.rst?plain=1#L70-L98
- lti_platform_instances_ids()[source]¶
Set of LTI Platform instance ids registered for this course.
- Return type:
Iterable[str]
inginious.frontend.installer module¶
Custom installer for the web app
inginious.frontend.parsable_text module¶
Tools to parse text
- class inginious.frontend.parsable_text.CustomAdmonition(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)[source]¶
Bases:
CustomBaseAdmonitionA custom admonition with a specific class if needed
- node_class¶
alias of
admonition
- required_arguments = 1¶
Number of required directive arguments.
- class inginious.frontend.parsable_text.CustomBaseAdmonition(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)[source]¶
Bases:
BaseAdmonitionA custom admonition that can have a title
- option_spec = {'class': <function class_option>, 'name': <function unchanged>, 'title': <function unchanged>}¶
Mapping of option names to validator functions.
- class inginious.frontend.parsable_text.EmptiableCodeBlock(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)[source]¶
Bases:
CodeBlock
- class inginious.frontend.parsable_text.HiddenUntilDirective(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine)[source]¶
Bases:
Directive,object- has_content = True¶
May the directive have content?
- option_spec = {}¶
Mapping of option names to validator functions.
- optional_arguments = 1¶
Number of optional arguments after the required arguments.
- required_arguments = 1¶
Number of required directive arguments.
- class inginious.frontend.parsable_text.ParsableText(content, mode='rst', show_everything=False)[source]¶
Bases:
objectAllow to parse a string with different parsers
inginious.frontend.plugins.plugin_manager module¶
Plugin Manager
- class inginious.frontend.plugins.plugin_manager.PluginManager[source]¶
Bases:
objectRegisters an manage plugins. The init method inits only the Hook Manager; you have to call the method load() to start the plugins
- add_hook(name, callback, prio=0)[source]¶
Add a new hook that can be called with the call_hook function. prio is the priority. Higher priority hooks are called before lower priority ones. This function does not enforce a particular order between hooks with the same priorities.
- add_page(pattern, classname_or_viewfunc)[source]¶
Add a new page to the web application. Only available after that the Plugin Manager is loaded
- add_template_prefix(prefix, folder)[source]¶
Adds a template folder served for all templates prefixed by indicated prefix :type prefix:
str:param prefix: prefix the template folder is served from. :type folder:str:param folder: abolute path to the template folder.
- call_hook(name, **kwargs)[source]¶
Call all hooks registered with this name. Returns a list of the returns values of the hooks (in the order the hooks were added)
- call_hook_recursive(name, **kwargs)[source]¶
Call all hooks registered with this name. Each hook receives as arguments the return value of the previous hook call, or the initial params for the first hook. As such, each hook must return a dictionary with the received (eventually modified) args. Returns the modified args.
- load(client, flask_app, user_manager, submission_manager, config)[source]¶
Loads the plugin manager. Must be done after the initialisation of the client
- register_auth_method(auth_method)[source]¶
Registers a new authentication method :type auth_method:
AuthMethod:param auth_method: a AuthMethod-based class
inginious.frontend.submission_manager module¶
Manages submissions
- class inginious.frontend.submission_manager.WebAppSubmissionManager(client, user_manager, lti_score_publishers)[source]¶
Bases:
objectManages submissions. Communicates with the database and the client.
- add_job(course, task, inputdata, task_dispenser, debug=False)[source]¶
Add a job in the queue and returns a submission id. :type task: :param task: Task instance :type task: inginious.frontend.tasks.Task :type inputdata: :param inputdata: the input as a dictionary :type inputdata: dict :type debug: :param debug: If debug is true, more debug data will be saved :type debug: bool or string :returns: the new submission id and the removed submission id
- get_available_environments()[source]¶
:return a list of available environments
- Return type:
Dict[str,List[str]]
- get_feedback_from_submission(submission, only_feedback=False, show_everything=False)[source]¶
Get the input of a submission. If only_input is False, returns the full submissions with a dictionnary object at the key “input”. Else, returns only the dictionnary.
If show_everything is True, feedback normally hidden is shown.
- get_input_from_submission(submission, only_input=False)[source]¶
Get the input of a submission. If only_input is False, returns the full submissions with a dictionnary object at the key “input”. Else, returns only the dictionnary.
- get_job_queue_info(jobid)[source]¶
Get job queue info :type jobid: :param jobid: the JOB id (not the submission id!). You should retrieve it before calling this function by calling
get_submission(...)["job_id"]. :return: If the submission is in the queue, then returns a tuple (nb tasks before running (or-1if running), approx wait time in seconds) Else, returns None
- get_job_queue_snapshot()[source]¶
Get a snapshot of the remote backend job queue. May be a cached version. May not contain recent jobs. May return None if no snapshot is available
- Returns:
a tuple of two lists (None, None):
jobs_running: a list of tuples in the form (job_id, is_current_client_job, info, launcher, started_at, max_time) wherejob_id is a job id. It may be from another client.
is_current_client_job is a boolean indicating if the client that asked the request has started the job
agent_name is the agent name
info is “courseid/taskid”
launcher is the name of the launcher, which may be anything
started_at the time (in seconds since UNIX epoch) at which the job started
max_time the maximum time that can be used, or -1 if no timeout is set
jobs_waiting: a list of tuples in the form (job_id, is_current_client_job, info, launcher, max_time) wherejob_id is a job id. It may be from another client.
is_current_client_job is a boolean indicating if the client that asked the request has started the job
info is “courseid/taskid”
launcher is the name of the launcher, which may be anything
max_time the maximum time that can be used, or -1 if no timeout is set
- get_submission_archive(course, submissions, sub_folders, archive_file=None, simplify=False)[source]¶
- Parameters:
course – the course object linked to the submission
submissions – a list of submissions
sub_folders –
a list of folders in which to place the submission. For example, [“taskid”, “submissionid”] place each submission inside a folder taskid/submissionid/ (with taskid replaced with the actual task id, the same being true for submissionid). The possible values are: - “taskid”: replaced by the task id - “submissionid”: replaced by the submission id - “audience”: replaced by the name of the audience “audiencedesc_(audienceid)” - “group”: replaced by the list of username who submitted - “username”: replaced by the username Some of these (like “username” and “audience”) are not unique for a submission. If they are multiple answers possible, the files are duplicated at multiple locations.
For example: given a submission #9083081 by the group [“a”, “b”], and a sub_folders value of [“username”, “submissionid”], the archive will contain two folders: - a/9083081/ - b/9083081/
- Returns:
a file-like object containing a tgz archive of all the submissions
- is_done(submissionid_or_submission, user_check=True)[source]¶
Tells if a submission is done and its result is available
- kill_running_submission(submissionid, user_check=True)[source]¶
Attempt to kill the remote job associated with this submission id. :type submissionid: :param submissionid: :type user_check: :param user_check: Check if the current user owns this submission :return: True if the message asking to kill the job was sent, False if an error occurred
- replay_job(course, task, submission, task_dispenser, copy=False, debug=False)[source]¶
Replay a submission: add the same job in the queue, keeping submission id, submission date and input data :type submission: :param submission: Submission to replay :type copy: :param copy: If copy is true, the submission will be copied to admin submissions before replay :type debug: :param debug: If debug is true, more debug data will be saved
inginious.frontend.task_problems module¶
Displayable problems
- class inginious.frontend.task_problems.DisplayableCodeProblem(problemid, content, translations, taskfs)[source]¶
Bases:
CodeProblem,DisplayableProblemA basic class to display all BasicCodeProblem derivatives
- class inginious.frontend.task_problems.DisplayableCodeSingleLineProblem(problemid, content, translations, taskfs)[source]¶
Bases:
CodeSingleLineProblem,DisplayableProblemA displayable single code line problem
- class inginious.frontend.task_problems.DisplayableFileProblem(problemid, content, translations, taskfs)[source]¶
Bases:
FileProblem,DisplayableProblemA displayable code problem
- class inginious.frontend.task_problems.DisplayableMatchProblem(problemid, content, translations, taskfs)[source]¶
Bases:
MatchProblem,DisplayableProblemA displayable match problem
- class inginious.frontend.task_problems.DisplayableMultipleChoiceProblem(problemid, content, translations, taskfs)[source]¶
Bases:
MultipleChoiceProblem,DisplayableProblemA displayable multiple choice problem
- class inginious.frontend.task_problems.DisplayableProblem(problemid, content, translations, taskfs)[source]¶
Bases:
ProblemBasic problem
inginious.frontend.tasks module¶
Classes modifying basic tasks, problems and boxes classes
- class inginious.frontend.tasks.Task(courseid, taskid, content)[source]¶
Bases:
objectA task that stores additional context information, specific to the web app
- classmethod get(courseid, taskid)[source]¶
Fetch a task with id taskid from the specified course filesystem
- get_environment_parameters()[source]¶
Returns the raw environment parameters, which is a dictionnary that is envtype dependent.
- get_environment_type()[source]¶
Returns the environment type in which the agent have to launch this task
inginious.frontend.user_manager module¶
Manages users data and session
- class inginious.frontend.user_manager.AuthMethod[source]¶
Bases:
object- abstract callback(auth_storage)[source]¶
- Parameters:
auth_storage – The session auth method storage dict
- Returns:
User tuple and , or None, if failed
- class inginious.frontend.user_manager.UserInfo(realname, email, username, bindings, language, code_indentation, activated)¶
Bases:
tuple- activated¶
Alias for field number 6
- bindings¶
Alias for field number 3
- code_indentation¶
Alias for field number 5
- email¶
Alias for field number 1
- language¶
Alias for field number 4
- realname¶
Alias for field number 0
- username¶
Alias for field number 2
- class inginious.frontend.user_manager.UserManager(superadmins)[source]¶
Bases:
object- activate_user(activate_hash)[source]¶
Active a user based on his/her activation hash :type activate_hash: :param activate_hash: The activation hash of a user :return A boolean if the user was found and updated
- auth_user(username, password, do_connect=True)[source]¶
Authenticate the user in database :type username: :param username: Username/Login :type password: :param password: User password :type do_connect: :param do_connect: indicates if the user must be connected after authentification, True by default :return: Returns a dict representing the user, or None if the authentication was not successful
- bind_user(auth_id, user)[source]¶
Add a binding method to a user :type auth_id: :param auth_id: The binding method id :type user: :param user: User object :return: Boolean if method has been add
- connect_user(user)[source]¶
Opens a session for the user
- :param usera dict representing the user, it contains the data of the user.
It must at least contain the following fields: - realname - email - username
- course_is_open_to_user(course, username=None, lti=None, return_reason=False)[source]¶
Checks if a user is can access a course
- Parameters:
course – a Course object
username – The username of the user that we want to check. If None, uses session.username
lti –
indicates if the user is currently in a LTI session or not.
None to ignore the check
True to indicate the user is in a LTI session
False to indicate the user is not in a LTI session
”auto” to enable the check and take the information from the current session
return_reason –
instead of False, returns a string indicating for which reason the course is not open to the user. Reasons may be :
”closed” if the course is not open
”unregistered_not_previewable” user is not registered and course is not previewable
”lti_only” the current session is not a LTI session and this course requires at LTI session
”lti_not_registered” this LTI course can be accessed outside an LTI session only if the user register first via the LTI interface
- Returns:
True if the user can access the course, False (or the reason if return_reason is True) otherwise
- course_is_user_registered(course, username=None)[source]¶
Checks if a user is registered
- Parameters:
course – a Course object
username – The username of the user that we want to check. If None, uses session.username
- Returns:
True if the user is registered, False else
- course_register_user(course, username=None, password=None, force=False)[source]¶
Register a user to the course
- Parameters:
course – a Course object
username – The username of the user that we want to register. If None, uses session.username
password – Password for the course. Needed if course.is_password_needed_for_registration() and force != True
force – Force registration
- Returns:
True if the registration succeeded, False else
- course_unregister_user(course_id, username=None)[source]¶
Unregister a user to the course :type course_id: :param course_id: a course id :type username: :param username: The username of the user that we want to unregister. If None, uses session.username
- create_user(values)[source]¶
Create a new user :type values: :param values: Dictionary of fields :return: An error message if something went wrong else None
- delete_user(username, confirmation_email=None)[source]¶
Delete a user based on username :type username: :param username: the username of the user :type confirmation_email: :param confirmation_email: An email to confirm suppression. May be None :return a boolean if a user was deleted
- get_auth_method(auth_method_id)[source]¶
:param the auth method id, as provided by get_auth_methods_inputs() :return: AuthMethod if it exists, otherwise None
- get_course_audiences_per_student(course)[source]¶
Returns a dictionnary mapping student -> list of audiences it belongs to, for a given course
- get_course_cache(username, course)[source]¶
- Parameters:
username – The username
course – A Course object
- Returns:
a dict containing info about the course, in the form:
{"task_tried": 0, "total_tries": 0, "task_succeeded": 0, "task_grades":{"task_1": 100.0, "task_2": 0.0, ...}}
Note that only the task already seen at least one time will be present in the dict task_grades.
- get_course_caches(usernames, course)[source]¶
- Parameters:
usernames (
list[str]) – List of username for which we want info. If usernames is None, data from all users will be returned.course – A Course object
- Returns:
Returns data of the specified users for a specific course. users is a list of username.
The returned value is a dict:
{"username": {"task_tried": 0, "total_tries": 0, "task_succeeded": 0, "task_grades":{"task_1": 100.0, "task_2": 0.0, ...}}}
Note that only the task already seen at least one time will be present in the dict task_grades.
- get_course_registered_users(course, with_admins=True)[source]¶
Get all the users registered to a course :type course: :param course: a Course object :type with_admins: :param with_admins: include admins? :return: a list of usernames that are registered to the course
- get_course_user_group(course, username=None)[source]¶
Returns the audience whose username belongs to :type course: :param course: a Course object :type username: :param username: The username of the user that we want to register. If None, uses session.username :return: the audience description
- get_task_cache(username, courseid, taskid)[source]¶
Shorthand for get_task_caches([username], courseid, taskid)[username]
- get_task_caches(usernames, courseid, taskid)[source]¶
- Parameters:
usernames – List of username for which we want info. If usernames is None, data from all users will be returned.
courseid – the course id
taskid – the task id
- Returns:
A dict in the form:
{ "username": { "courseid": courseid, "taskid": taskid, "tried": 0, "succeeded": False, "grade": 0.0 } }
- get_user_api_key(username, create=True)[source]¶
Get the API key of a given user. API keys are generated on demand. :type username: :param username: :type create: :param create: Create the API key if none exists yet :return: the API key assigned to the user, or None if none exists and create is False.
- get_user_email(username)[source]¶
- Parameters:
username
- Returns:
the email of the user if it can be found, None else
- get_user_info(username)[source]¶
- Parameters:
username
- Return type:
Optional[UserInfo]- Returns:
a tuple (realname, email) if the user can be found, None else
- get_user_realname(username)[source]¶
- Parameters:
username
- Returns:
the real name of the user if it can be found, None else
- get_users_info(usernames, limit=0, skip=0)[source]¶
- Parameters:
usernames – a list of usernames
:param limit A limit of users requested :param skip A quantity of users to skip :rtype:
Dict[str,Optional[UserInfo]] :return: a dict, in the form {username: val}, where val is either None if the user cannot be found, or a UserInfo. If the list of usernames is empty, return an empty dict.
- has_admin_rights_on_course(course, username=None, include_superadmins=True)[source]¶
Check if a user can be considered as having admin rights for a course :type course: inginious.frontend.courses.Course :type username: :param username: the username. If None, the username of the currently logged in user is taken :type include_superadmins: :param include_superadmins: Boolean indicating if superadmins should be taken into account :return: True if the user has admin rights, False else
- has_staff_rights_on_course(course, username=None, include_superadmins=True)[source]¶
Check if a user can be considered as having staff rights for a course :type course: inginious.frontend.courses.Course :type username: :param username: the username. If None, the username of the currently logged in user is taken :type include_superadmins: :param include_superadmins: Boolean indicating if superadmins should be taken into account :return: True if the user has staff rights, False else
- classmethod hash_password(content)[source]¶
Encapsulates the other password hashing functions :type content: :param content: a str input :return a hash of str input
- classmethod hash_password_argon2id(content)[source]¶
- Parameters:
content – a str input
:return a hash of str input
- classmethod hash_password_sha512(content)[source]¶
- Parameters:
content – a str input
:return a hash of str input
- register_auth_method(auth_method)[source]¶
Registers an authentication method :type auth_method: :param auth_method: an AuthMethod object
- revoke_binding(username, binding_id)[source]¶
Revoke a binding method for a user :type binding_id: :param binding_id: The binding method id :type username: :param username: username of the user :return: Boolean if error occurred and message if necessary
- classmethod sanitize_email(email)[source]¶
Sanitize an email address and put the bar part of an address foo@bar in lower case.
- Return type:
str
- task_can_user_submit(course, task, username=None, only_check=None, lti=None)[source]¶
returns true if the user can submit his work for this task :param only_check : only checks for ‘groups’, ‘tokens’, or None if all checks :type lti: :param lti: indicates if the user is currently in a LTI session or not. - None to ignore the check - True to indicate the user is in a LTI session - False to indicate the user is not in a LTI session - “auto” to enable the check and take the information from the current session
- task_is_visible_by_user(course, task, username=None, lti=None)[source]¶
Returns true if the task is visible and can be accessed by the user
- Parameters:
lti –
indicates if the user is currently in a LTI session or not.
None to ignore the check
True to indicate the user is in a LTI session
False to indicate the user is not in a LTI session
”auto” to enable the check and take the information from the current session
- update_user_stats(username, task, submission, result_str, grade, state, newsub, task_dispenser)[source]¶
Update stats with a new submission
- user_is_superadmin(username=None)[source]¶
- Parameters:
username – the username. If None, the username of the currently logged in user is taken
- Returns:
True if the user is superadmin, False else
- user_saw_task(username, courseid, taskid)[source]¶
Set in the database that the user has viewed this task