timApp.plugin package#

Subpackages#

Submodules#

timApp.plugin.exportdata module#

class timApp.plugin.exportdata.ExportData(plugin: str, data: Any, save: bool)[source]#

Bases: object

data: Any#
plugin: str#
save: bool#
class timApp.plugin.exportdata.WithExportData(exportdata: list[timApp.plugin.exportdata.ExportData])[source]#

Bases: object

exportdata: list[timApp.plugin.exportdata.ExportData]#
class timApp.plugin.exportdata.WithOutData(outdata: timApp.plugin.exportdata.WithExportData)[source]#

Bases: object

outdata: timApp.plugin.exportdata.WithExportData#

timApp.plugin.jsrunner module#

exception timApp.plugin.jsrunner.JsRunnerError[source]#

Bases: Exception

class timApp.plugin.jsrunner.JsRunnerParams(code: str, data: Any, error_text: str = '', caller: str = '')[source]#

Bases: object

caller: str = ''#
code: str#
data: Any#
error_text: str = ''#
timApp.plugin.jsrunner.jsrunner_run(params: timApp.plugin.jsrunner.JsRunnerParams) tuple[Any, str][source]#

Run JavaScript code in jsrunner.

timApp.plugin.plugin module#

class timApp.plugin.plugin.CachedPluginFinder(doc_map: dict[int, timApp.document.docinfo.DocInfo], curr_user: timApp.document.usercontext.UserContext, view_ctx: timApp.document.viewcontext.ViewContext, cache: dict[str, timApp.plugin.plugin.Plugin | None] = <factory>)[source]#

Bases: object

cache: dict[str, timApp.plugin.plugin.Plugin | None]#
curr_user: timApp.document.usercontext.UserContext#
doc_map: dict[int, timApp.document.docinfo.DocInfo]#
find(task_id: timApp.plugin.taskid.TaskId) timApp.plugin.plugin.Plugin | None[source]#
view_ctx: timApp.document.viewcontext.ViewContext#
class timApp.plugin.plugin.InlinePlugin(task_id: timApp.plugin.taskid.TaskId | None, values: dict, plugin_type: str, p_range: tuple[int, int], par: Optional[timApp.document.docparagraph.DocParagraph] = None)[source]#

Bases: timApp.plugin.plugin.Plugin

get_container_class()[source]#
get_wrapper_tag()[source]#
class timApp.plugin.plugin.Plugin(task_id: timApp.plugin.taskid.TaskId | None, values: dict, plugin_type: str, par: timApp.document.docparagraph.DocParagraph)[source]#

Bases: object

allow_styles_field()[source]#
answer_limit() int | None[source]#
answer_limit_key = 'answerLimit'#
deadline(default=None)[source]#
deadline_key = 'deadline'#
property fake_task_id#
static from_global_par(global_par_id: timApp.document.editing.globalparid.GlobalParId, user_ctx: timApp.document.usercontext.UserContext, view_ctx: timApp.document.viewcontext.ViewContext) tuple['Plugin', timApp.document.docinfo.DocInfo][source]#
static from_paragraph(par: timApp.document.docparagraph.DocParagraph, view_ctx: timApp.document.viewcontext.ViewContext, user: Optional[timApp.document.usercontext.UserContext] = None)[source]#
static from_task_id(task_id: str, user_ctx: timApp.document.usercontext.UserContext, view_ctx: timApp.document.viewcontext.ViewContext, cached_doc: Optional[timApp.document.docinfo.DocInfo] = None) tuple['Plugin', timApp.document.docinfo.DocInfo][source]#
get_answerbrowser_type()[source]#
get_container_class()[source]#
get_content_field_name()[source]#
get_final_output()[source]#
get_info(users: Iterable[timApp.user.user.User], old_answers: int, look_answer: bool = False, valid: bool = True)[source]#
get_wrapper_tag()[source]#
is_answer_valid(old_answers: int, tim_info: dict) tuple[bool, str][source]#

Determines whether the currently posted answer should be considered valid.

Parameters
  • old_answers – The number of old answers for this task for the current user.

  • tim_info – The tim_info structure returned by the plugin or empty object.

Returns

True if the answer should be considered valid, False otherwise.

is_automd_enabled(default=False)[source]#
is_cached() bool[source]#
is_lazy() bool[source]#
is_new_task() bool[source]#
is_timed() bool[source]#
limit_defaults = {'mcq': 1, 'mcq2': 1, 'mmcq': 1, 'mmcq2': 1}#
max_points(default=None) str | None[source]#
points_multiplier(default=1)[source]#
points_rule()[source]#
points_rule_key = 'pointsRule'#
render_json() dict[str, Any][source]#
save(max_attr_width: Optional[float] = None) None[source]#
set_access_end_for_user(user: Optional[timApp.user.user.User] = None)[source]#

Changes access_end_for_user to match the end of user’s plugin access

set_output(output: str)[source]#
set_render_options(answer: tuple[timApp.answer.answer.Answer, int] | None, options: timApp.plugin.plugin.PluginRenderOptions)[source]#
set_value(key: str, value)[source]#
show_points()[source]#
starttime(default=None)[source]#
starttime_key = 'starttime'#
to_paragraph(max_attr_width: Optional[float] = None) timApp.document.docparagraph.DocParagraph[source]#
user_max_points(default=None)[source]#
user_min_points(default=None)[source]#
validate_points(points: str | float | None)[source]#
wrap_draggable(html_str: str, doc_task_id: str) str[source]#
class timApp.plugin.plugin.PluginRenderOptions(user_ctx: timApp.document.usercontext.UserContext, do_lazy: bool, user_print: bool, preview: bool, target_format: timApp.printing.printsettings.PrintFormat, output_format: timApp.plugin.pluginOutputFormat.PluginOutputFormat, review: bool, wraptype: timApp.plugin.plugin.PluginWrap, viewmode: bool)[source]#

Bases: object

do_lazy: bool#
property is_html#
output_format: timApp.plugin.pluginOutputFormat.PluginOutputFormat#
preview: bool#
review: bool#
target_format: timApp.printing.printsettings.PrintFormat#
user_ctx: timApp.document.usercontext.UserContext#
user_print: bool#
viewmode: bool#
wraptype: timApp.plugin.plugin.PluginWrap#
class timApp.plugin.plugin.PluginWrap(value)[source]#

Bases: enum.Enum

An enumeration.

Full = 3#
NoLoader = 2#
Nothing = 1#
exception timApp.plugin.plugin.TaskNotFoundException[source]#

Bases: timApp.plugin.pluginexception.PluginException

The exception that is thrown when a task cannot be found.

timApp.plugin.plugin.expand_macros_for_plugin(par: timApp.document.docparagraph.DocParagraph, macros, env: timApp.markdown.autocounters.TimSandboxedEnvironment)[source]#
timApp.plugin.plugin.finalize_inline_yaml(p_yaml: str | None)[source]#
timApp.plugin.plugin.find_inline_plugins(block: timApp.document.docparagraph.DocParagraph, macroinfo: timApp.document.macroinfo.MacroInfo) Generator[tuple[timApp.plugin.taskid.UnvalidatedTaskId, str | None, tuple[int, int], str], None, None][source]#
timApp.plugin.plugin.find_inline_plugins_from_str(md) Generator[tuple[timApp.plugin.taskid.UnvalidatedTaskId, str | None, tuple[int, int], str], None, None][source]#
timApp.plugin.plugin.find_plugin_from_document(d: timApp.document.document.Document, task_id: timApp.plugin.taskid.TaskId, u: timApp.document.usercontext.UserContext, view_ctx: timApp.document.viewcontext.ViewContext) timApp.plugin.plugin.Plugin[source]#
timApp.plugin.plugin.find_task_ids(blocks: list[timApp.document.docparagraph.DocParagraph], view_ctx: timApp.document.viewcontext.ViewContext, user_ctx: timApp.document.usercontext.UserContext, check_access=True) tuple[list[timApp.plugin.taskid.TaskId], int, list[timApp.plugin.taskid.TaskId]][source]#

Finds all task plugins from the given list of paragraphs and returns their ids. :param user_ctx:

timApp.plugin.plugin.get_num_value(values, key, default=None)[source]#

Gets the value either from key or -key :param values: dict where to find :param key: key to use :param default: value returned if key not found from either of key or -key :return: value for key, -key or default

timApp.plugin.plugin.get_simple_hash_from_par_and_user(block: timApp.document.docparagraph.DocParagraph, uc: timApp.document.usercontext.UserContext | None) int[source]#

Get simple int hash from TIM’s document block and user.

Parameters
  • block – TIM’s document block

  • uc – The user context.

Returns

simple hash that can be used for example as a seed for random number generator

timApp.plugin.plugin.get_value(values, key, default=None)[source]#

Gets the value either from key or -key :param values: dict where to find :param key: key to use :param default: value returned if key not found from either of key or -key :return: value for key, -key or default

timApp.plugin.plugin.load_markup_from_yaml(yaml_str: str, global_attrs: dict[str, str], plugin_type: str)[source]#
timApp.plugin.plugin.maybe_get_plugin_from_par(p: timApp.document.docparagraph.DocParagraph, task_id: timApp.plugin.taskid.TaskId, u: timApp.document.usercontext.UserContext, view_ctx: timApp.document.viewcontext.ViewContext, match_exact_document: bool = False) timApp.plugin.plugin.Plugin | None[source]#
timApp.plugin.plugin.parse_plugin_values(par: timApp.document.docparagraph.DocParagraph, global_attrs: dict[str, str], macroinfo: timApp.document.macroinfo.MacroInfo) dict[source]#
timApp.plugin.plugin.parse_plugin_values_macros(par: timApp.document.docparagraph.DocParagraph, global_attrs: dict[str, str], macros: dict[str, object], env: timApp.markdown.autocounters.TimSandboxedEnvironment) dict[source]#

Parses the markup values for a plugin paragraph, taking document attributes and macros into account.

Parameters
  • par – The plugin paragraph.

  • global_attrs – Global (Document) attributes.

  • macros – Dict of macros

  • env – macro environment

Returns

The parsed markup values.

timApp.plugin.plugin.render_template_string2(source, **context)[source]#

Renders a template from the given template source string with the given context. Template variables will be autoescaped.

Parameters
  • source – the source code of the template to be rendered

  • context – the variables that should be available in the context of the template.

timApp.plugin.plugin.render_template_string3(rtemplate, **context)[source]#

Renders a template from the given template source string with the given context. Template variables will be autoescaped.

Parameters
  • rtemplate – ready made render template

  • context – the variables that should be available in the context of the template.

timApp.plugin.pluginControl module#

Functions for dealing with plugin paragraphs.

class timApp.plugin.pluginControl.PluginPlacement(*, plugins: dict[tuple[int, int], timApp.plugin.plugin.Plugin], errors: dict[tuple[int, int], tuple[str, str]], block: timApp.document.docparagraph.DocParagraph, expanded_md: str, is_block_plugin: bool, output_format: timApp.plugin.pluginOutputFormat.PluginOutputFormat)[source]#

Bases: object

Represents the position(s) of plugin(s) in a block.

Can be either:
  • a block-level (traditional) plugin, or

  • one or more inlineplugins.

In case of a block-level plugin, the range spans the entire block’s expanded markdown.

block: timApp.document.docparagraph.DocParagraph#

The block where the plugins are.

errors: dict[tuple[int, int], tuple[str, str]]#
expanded_md: str#

Expanded markdown of the containing block.

static from_par(block: timApp.document.docparagraph.DocParagraph, load_states: bool, macroinfo: timApp.document.macroinfo.MacroInfo, plugin_opts: timApp.plugin.plugin.PluginRenderOptions, user_ctx: timApp.document.usercontext.UserContext, view_ctx: timApp.document.viewcontext.ViewContext, settings: timApp.document.docsettings.DocSettings, answer_map: dict[str, tuple[timApp.answer.answer.Answer, int]], custom_answer: timApp.answer.answer.Answer | None, output_format: timApp.plugin.pluginOutputFormat.PluginOutputFormat) Optional[timApp.plugin.pluginControl.PluginPlacement][source]#
get_block_output(extract_plugins: bool = False) tuple[str, dict[str, str]][source]#

TODO: this did not help very much if self.is_block_plugin:

idx = next(iter(self.plugins)) p = self.plugins[idx] return p.get_final_output().strip()

get_block_plugin()[source]#
is_block_plugin: bool#

Whether this is a block-level plugin.

output_format: timApp.plugin.pluginOutputFormat.PluginOutputFormat#
plugins: dict[tuple[int, int], timApp.plugin.plugin.Plugin]#
set_error(r: tuple[int, int], err: str)[source]#
set_output(r: tuple[int, int], out: str)[source]#
class timApp.plugin.pluginControl.PluginifyResult(pars: list[timApp.document.docparagraph.DocParagraph], js_paths: list[str], css_paths: list[str], custom_answer_plugin: timApp.plugin.plugin.Plugin | None, all_plugins: list[timApp.plugin.plugin.Plugin], has_errors: bool)[source]#

Bases: object

all_plugins: list[timApp.plugin.plugin.Plugin]#
css_paths: list[str]#
custom_answer_plugin: timApp.plugin.plugin.Plugin | None#
has_errors: bool#
js_paths: list[str]#
pars: list[timApp.document.docparagraph.DocParagraph]#
timApp.plugin.pluginControl.check_task_access(errs: dict[tuple[int, int], tuple[str, str]], p_range: tuple[int, int], plugin_name: str, tid: timApp.plugin.taskid.TaskId)[source]#
timApp.plugin.pluginControl.get_all_reqs()[source]#
timApp.plugin.pluginControl.get_answers(user, task_ids, answer_map)[source]#
timApp.plugin.pluginControl.get_error_plugin(plugin_name, message, response=None, plugin_output_format: timApp.plugin.pluginOutputFormat.PluginOutputFormat = PluginOutputFormat.HTML, inline=False)[source]#
Parameters

response

timApp.plugin.pluginControl.plugin_deps(p: dict) tuple[list[str], list[str]][source]#
Parameters

p – is json of plugin requirements of the form: {“js”: [“js.js”], “css”:[“css.css”]}

timApp.plugin.pluginControl.pluginify(doc: timApp.document.document.Document, pars: list[timApp.document.docparagraph.DocParagraph], user_ctx: timApp.document.usercontext.UserContext, view_ctx: timApp.document.viewcontext.ViewContext, custom_answer: Optional[timApp.answer.answer.Answer] = None, task_id: Optional[timApp.plugin.taskid.TaskId] = None, sanitize=True, do_lazy=False, load_states=True, review=False, pluginwrap=PluginWrap.Full, output_format: timApp.plugin.pluginOutputFormat.PluginOutputFormat = PluginOutputFormat.HTML, user_print: bool = False, target_format: timApp.printing.printsettings.PrintFormat = PrintFormat.LATEX) timApp.plugin.pluginControl.PluginifyResult[source]#

“Pluginifies” the specified DocParagraphs by calling the corresponding plugin route for each plugin paragraph.

Parameters
  • view_ctx – The view context.

  • doc – Document / DocumentVersion object.

  • pars – A list of DocParagraphs to be processed.

  • user_ctx – The user context.

  • custom_answer – Optional answer that will used as the state for the plugin instead of answer database.

  • task_id – Optional taskId for plugin which will load it’s current state (returned as custom_answer_plugin) If custom_answer or task_id is specified, the expression len(blocks) MUST be 1.

  • sanitize – Whether the blocks should be sanitized before processing.

  • do_lazy – Whether to use lazy versions of the plugins.

  • output_format – Desired output format (html/md) for plugins

  • user_print – Whether the plugins should output the original values or user’s input (when exporting markdown).

  • target_format – for MD-print what exact format to use

Returns

Processed HTML blocks along with JavaScript and CSS stylesheet dependencies.

timApp.plugin.pluginOutputFormat module#

class timApp.plugin.pluginOutputFormat.PluginOutputFormat(value)[source]#

Bases: enum.Enum

An enumeration.

HTML = 'html'#
MD = 'md'#

timApp.plugin.pluginexception module#

exception timApp.plugin.pluginexception.PluginException[source]#

Bases: Exception

The exception that is thrown when an error occurs during a plugin call.

timApp.plugin.plugintype module#

class timApp.plugin.plugintype.PluginType(**kwargs)[source]#

Bases: sqlalchemy.ext.declarative.api.Model, timApp.plugin.plugintype.PluginTypeBase

get_type() str[source]#
id#
static resolve(p_type: str) timApp.plugin.plugintype.PluginType[source]#
type#
class timApp.plugin.plugintype.PluginTypeBase[source]#

Bases: object

can_give_task() bool[source]#
get_content_field_name() str[source]#
get_type() str[source]#
to_json() dict[str, Any][source]#
class timApp.plugin.plugintype.PluginTypeLazy(type: str)[source]#

Bases: timApp.plugin.plugintype.PluginTypeBase

get_type() str[source]#
resolve() timApp.plugin.plugintype.PluginType[source]#
type: str#

timApp.plugin.routes module#

timApp.plugin.routes.echo_request(filename)[source]#
timApp.plugin.routes.plugin_call(plugin, filename)[source]#
timApp.plugin.routes.plugin_tid_call(plugintype: str, task_id_ext: str)[source]#

plugin_call but with task id and markup

timApp.plugin.routes.return_resource_response(resp)[source]#
timApp.plugin.routes.view_template(plugin, template, index)[source]#

timApp.plugin.save_plugin module#

timApp.plugin.save_plugin.save_plugin(p: timApp.plugin.plugin.Plugin, max_attr_width: Optional[float] = None) None[source]#

timApp.plugin.taskid module#

class timApp.plugin.taskid.TaskId(doc_id: int | None, task_name: str, block_id_hint: str | None = None, field: str | None = None, plugin_type: str | None = None, access_specifier: timApp.plugin.taskid.TaskIdAccess | None = None)[source]#

Bases: object

access_specifier: timApp.plugin.taskid.TaskIdAccess | None = None#
block_id_hint: str | None = None#
doc_id: int | None#
property doc_task#
property doc_task_with_field#
property extended#
property extended_or_doc_task#
field: str | None = None#
property is_global#
property is_points_ref#
maybe_set_hint(hint: str)[source]#
static parse(s: str, *, require_doc_id=True, allow_block_hint=True, allow_custom_field=False, allow_type=True) timApp.plugin.taskid.TaskId[source]#
static parse_doc_id(tid: str) int[source]#
plugin_type: str | None = None#
task_name: str#
update_doc_id_from_block(par: timApp.document.docparagraph.DocParagraph)[source]#
validate()[source]#
class timApp.plugin.taskid.TaskIdAccess(value)[source]#

Bases: enum.Enum

An enumeration.

ReadOnly = 'readonly'#
ReadWrite = 'readwrite'#
class timApp.plugin.taskid.UnvalidatedTaskId(s: str)[source]#

Bases: object

s: str#
validate() timApp.plugin.taskid.TaskId[source]#

Module contents#