timApp.admin package#

Submodules#

timApp.admin.answer_cli module#

class timApp.admin.answer_cli.AnswerDeleteResult(useranswer: int, answersaver: int, annotation: int, annotationcomment: int, answer: int)[source]#

Bases: object

annotation: int#
annotationcomment: int#
answer: int#
answersaver: int#
useranswer: int#
class timApp.admin.answer_cli.DeleteResult(total: int, deleted: int, adr: timApp.admin.answer_cli.AnswerDeleteResult)[source]#

Bases: object

adr: timApp.admin.answer_cli.AnswerDeleteResult#
deleted: int#
property remaining: int#
total: int#
timApp.admin.answer_cli.collect_docs(item: timApp.item.item.Item) Sequence[timApp.document.docinfo.DocInfo][source]#
timApp.admin.answer_cli.delete_answers_with_ids(ids: list[int], verbose: bool = False) timApp.admin.answer_cli.AnswerDeleteResult[source]#
timApp.admin.answer_cli.delete_old_answers(d: timApp.document.docinfo.DocInfo, tasks: list[str]) timApp.admin.answer_cli.DeleteResult[source]#

timApp.admin.associate_old_uploads module#

timApp.admin.associate_old_uploads.associate_document(d: timApp.document.docinfo.DocInfo, search_opt: timApp.admin.search_in_documents.SearchArgumentsBasic, del_anon: Optional[Callable[[timApp.upload.uploadedfile.UploadedFile], None]] = None) int[source]#
timApp.admin.associate_old_uploads.associate_old_uploads() None[source]#

Associates old uploads with documents and removes access for those uploads from anonymous users. This means only document viewers will be able to view the uploaded files, as it is with new uploads.

timApp.admin.associate_old_uploads.main() None[source]#
timApp.admin.associate_old_uploads.search_and_print(d: timApp.document.docinfo.DocInfo, _args: timApp.admin.util.BasicArguments) int[source]#

timApp.admin.change_group_email module#

timApp.admin.change_group_email.change_email() None[source]#

timApp.admin.cli module#

timApp.admin.cli.register_clis(app: flask.app.Flask) None[source]#

timApp.admin.datetimetype module#

class timApp.admin.datetimetype.DateTimeType[source]#

Bases: click.types.ParamType

A better datetime type to use with Click.

convert(value: Any, param: Any, ctx: Any) datetime.datetime[source]#

Convert the value to the correct type. This is not called if the value is None (the missing value).

This must accept string values from the command line, as well as values that are already the correct type. It may also convert other compatible types.

The param and ctx arguments may be None in certain situations, such as when converting prompt input.

If the value cannot be converted, call fail() with a descriptive message.

Parameters
  • value – The value to convert.

  • param – The parameter that is using this type to convert its value. May be None.

  • ctx – The current context that arrived at this value. May be None.

name: str = 'datetime'#

the descriptive name of this type

timApp.admin.find_nested_areas module#

timApp.admin.find_nested_areas.find_nested_areas(d: timApp.document.docinfo.DocInfo, _args: timApp.admin.util.DryrunnableArguments) int[source]#

timApp.admin.fix_hashes module#

timApp.admin.fix_hashes.fix_hashes(doc: timApp.document.docinfo.DocInfo, args: timApp.admin.util.DryrunnableArguments) int[source]#

Due to bugs, the computed hashes in a paragraph file or paragraph list may be incorrect. This fixes them.

Parameters
  • doc – The document to fix.

  • args – The arguments.

timApp.admin.fix_imagex_freehanddata module#

timApp.admin.fix_imagex_freehanddata.fix_imagex_freehanddata(doc: timApp.document.docinfo.DocInfo, args: timApp.admin.util.DryrunnableArguments) int[source]#

Fixes invalid imagex freeHandData. An invalid entry in freeHandData looks like:

{'color': '#ff0', 'lines': [[None, None]], 'w': 3}
Parameters
  • doc – The document to fix.

  • args – The arguments.

timApp.admin.fix_missing_multiline_endings module#

Due to 03d73c1f728c4ac38c599cc8d6b711b5fe816684, it is always mandatory to terminate a custom multiline YAML value. This script adds any missing ones.

timApp.admin.fix_missing_multiline_endings.fix_multiline_endings(doc: timApp.document.docinfo.DocInfo, args: timApp.admin.util.DryrunnableArguments) int[source]#

timApp.admin.fix_orphan_documents module#

timApp.admin.fix_orphan_documents.fix_orphans_without_docentry() None[source]#

Finds all documents (in Block table) that do not have a DocEntry and creates a DocEntry for them under ‘orphans’ directory.

timApp.admin.fix_orphan_documents.move_docs_without_block(dry_run: bool) None[source]#

Moves all documents from tim_files/docs to tim_files/orphans that don’t have a Block entry in database.

timApp.admin.fix_settings_references module#

Due to b3fc1c622309e8474183ed5ef5ea7bace2479c4d, settings attribute is always required even when referencing other settings paragraphs. This adds missing settings attributes where it is missing.

timApp.admin.fix_settings_references.fix_settings_references(d: timApp.document.docinfo.DocInfo, args: timApp.admin.util.DryrunnableArguments) int[source]#

timApp.admin.fix_translation_settings module#

Due to 6c77b8756d2060dea1c3d920a743263dcb740461, all settings paragraphs are synchronized to the translated document from the original one. Existing translated documents need to be fixed, which is what this script does.

timApp.admin.fix_translation_settings.fix_translation(d: timApp.document.docinfo.DocInfo, args: timApp.admin.util.DryrunnableArguments) int[source]#

timApp.admin.global_notification module#

Defines routes for handling a global notification message that is visible to all users until it is removed or TIM is restarted.

timApp.admin.global_notification.inject_global_notifications() dict[source]#

“Injects global notification message (if the file exists) to all templates.

timApp.admin.global_notification.remove_global_notification() flask.wrappers.Response[source]#
timApp.admin.global_notification.set_global_notification(message: str) flask.wrappers.Response[source]#

timApp.admin.import_accounts module#

exception timApp.admin.import_accounts.ImportException[source]#

Bases: Exception

timApp.admin.import_accounts.import_accounts_impl(file: str, password: str | None) tuple[list[timApp.user.user.User], list[timApp.user.user.User]][source]#

timApp.admin.import_document module#

Imports a document that has been exported with /download/<doc_id>?format=json route.

timApp.admin.import_document.main() None[source]#

timApp.admin.item_cli module#

timApp.admin.language_cli module#

Enables adding Languages to TIM’s database from the command line

timApp.admin.language_cli.add_all_supported_languages(log: bool = False) None[source]#

Add all supported languages to the database. Supported languages are defined in the configuration variable LANGUAGES in timAppdefaultconfig.py.

This separate function allows adding all the languages at the db-initialization.

Returns

None.

timApp.admin.migrate_to_postgre module#

timApp.admin.migrate_to_postgre.migrate_table(sq3c, pgc, old_table: str, new_table: Optional[str] = None, placeholders: Optional[dict[str, str]] = None, id_column: str | None = 'id', extra_clause='', new_columns=None)[source]#
timApp.admin.migrate_to_postgre.perform_migration(sqlite_path: str, postgre_path: str)[source]#
timApp.admin.migrate_to_postgre.update_seq_val(pgc, tablename, id_col_name='id')[source]#

timApp.admin.replace_in_documents module#

class timApp.admin.replace_in_documents.AttrModification(search_result: timApp.admin.search_in_documents.SearchResult, par: timApp.document.docparagraph.DocParagraph, name: str, value: str, was_already: bool, mod_type: str = 'add')[source]#

Bases: object

property error: str | None#
format_match(args: timApp.admin.replace_in_documents.ReplaceArgumentsCLI) str[source]#
mod_type: str = 'add'#
name: str#
par: timApp.document.docparagraph.DocParagraph#
search_result: timApp.admin.search_in_documents.SearchResult#
value: str#
was_already: bool#
class timApp.admin.replace_in_documents.ReplaceArguments(*, dryrun: bool = False, term: str = '', regex: bool = False, format: str = '{0}', onlyfirst: Optional[int] = None, filter_attr: Optional[str] = None, to: Optional[str] = None, add_attr: Optional[str] = None)[source]#

Bases: timApp.admin.util.DryrunnableOnly, timApp.admin.search_in_documents.SearchArgumentsBasic

Arguments for a replacement operation.

add_attr: str | None#
to: str | None#
class timApp.admin.replace_in_documents.ReplaceArgumentsCLI(*, dryrun: bool = False, term: str = '', regex: bool = False, format: str = '{0}', onlyfirst: Optional[int] = None, filter_attr: Optional[str] = None, to: Optional[str] = None, add_attr: Optional[str] = None, progress: bool, doc: str, folder: str, urlpath: Optional[str] = None)[source]#

Bases: timApp.admin.replace_in_documents.ReplaceArguments, timApp.admin.util.BasicArguments

Command-line arguments for a replacement operation.

class timApp.admin.replace_in_documents.ReplacementResult(*, search_result: timApp.admin.search_in_documents.SearchResult, replacement: str, error: Optional[str] = None)[source]#

Bases: object

Represents a single replacement in a DocParagraph.

error: str#
format_match(args: timApp.admin.replace_in_documents.ReplaceArgumentsCLI) str[source]#
get_new_markdown() str[source]#

Gets the new markdown after applying the replacement string.

NOTE: This replaces ALL occurrences currently.

get_replacement() tuple[str, str][source]#
get_replacement_desc() str[source]#
replacement: str#
search_result: timApp.admin.search_in_documents.SearchResult#
timApp.admin.replace_in_documents.min_replacement_length(x: str) str[source]#
timApp.admin.replace_in_documents.perform_replace(d: timApp.document.docinfo.DocInfo, args: timApp.admin.replace_in_documents.ReplaceArguments) Generator[timApp.admin.replace_in_documents.ReplacementResult | timApp.admin.replace_in_documents.AttrModification, None, None][source]#

Performs a search-and-replace operation for the specified document, yielding list of ReplacementResult or AttrModification.

Parameters
  • args – The replacement arguments. If args.dryrun is True, no actual replacement will occur.

  • d – The document to process.

timApp.admin.replace_in_documents.replace_and_print(d: timApp.document.docinfo.DocInfo, args: timApp.admin.replace_in_documents.ReplaceArgumentsCLI) int[source]#

Same as perform_replace(), but prints the matches according to the provided format.

timApp.admin.routes module#

class timApp.admin.routes.ExceptionRouteModel(db_error: bool = False)[source]#

Bases: object

db_error: bool = False#
timApp.admin.routes.restart_server() flask.wrappers.Response[source]#

Restarts the server by sending HUP signal to Gunicorn.

timApp.admin.routes.search_users(term: str) flask.wrappers.Response[source]#
timApp.admin.routes.throw_ex(m: timApp.admin.routes.ExceptionRouteModel) flask.wrappers.Response[source]#

timApp.admin.search_in_documents module#

class timApp.admin.search_in_documents.SearchArgumentsBase(*, progress: bool, doc: str, folder: str, urlpath: Optional[str] = None, term: str = '', regex: bool = False, format: str = '{0}', onlyfirst: Optional[int] = None, filter_attr: Optional[str] = None)[source]#

Bases: timApp.admin.util.BasicArguments, timApp.admin.search_in_documents.SearchArgumentsBasic

class timApp.admin.search_in_documents.SearchArgumentsBasic(*, term: str = '', regex: bool = False, format: str = '{0}', onlyfirst: Optional[int] = None, filter_attr: Optional[str] = None)[source]#

Bases: object

Arguments for a search operation.

filter_attr: str | None#

If given, only search the paragraphs that have the specified attribute and value.

format: str#

Format string to print matches.

onlyfirst: int | None#

If given, only search the first x paragraphs from each document.

regex: bool#

If true, interpret term as a regular expression.

term: str#

The search term.

class timApp.admin.search_in_documents.SearchArgumentsCLI(*, progress: bool, doc: str, folder: str, urlpath: Optional[str] = None, term: str = '', regex: bool = False, format: str = '{0}', onlyfirst: Optional[int] = None, filter_attr: Optional[str] = None, docsonly: bool, exported: bool)[source]#

Bases: timApp.admin.search_in_documents.SearchArgumentsBase

Command-line arguments for a search operation.

docsonly: bool#
exported: bool#
class timApp.admin.search_in_documents.SearchResult(doc: timApp.document.docinfo.DocInfo, par: timApp.document.docparagraph.DocParagraph, match_pattern: Match[str], num_results: int, num_pars: int, num_pars_found: int)[source]#

Bases: NamedTuple

A single search result.

doc: timApp.document.docinfo.DocInfo#

The document where the match occurred.

format_match(args: timApp.admin.search_in_documents.SearchArgumentsBase) str[source]#
match_pattern: Match[str]#

The match object.

num_pars: int#

The number of paragraphs processed so far.

num_pars_found: int#

The number of paragraphs found so far.

num_results: int#

The number of found results so far.

par: timApp.document.docparagraph.DocParagraph#

The paragraph where the match occurred.

timApp.admin.search_in_documents.create_basic_search_argparser(desc: str, is_readonly: bool = True, require_term: bool = True) argparse.ArgumentParser[source]#
timApp.admin.search_in_documents.main() None[source]#
timApp.admin.search_in_documents.matches_attr_filter(p: timApp.document.docparagraph.DocParagraph, key: str | None, value: str | None) bool[source]#
timApp.admin.search_in_documents.search(d: timApp.document.docinfo.DocInfo, args: timApp.admin.search_in_documents.SearchArgumentsBasic, use_exported: bool) Generator[timApp.admin.search_in_documents.SearchResult, None, None][source]#

Performs a search operation for the specified document, yielding list of SearchResult.

Parameters
  • args – The search arguments.

  • d – The document to process.

  • use_exported – Whether to search in the exported form of paragraphs.

timApp.admin.search_in_documents.search_and_print(d: timApp.document.docinfo.DocInfo, args: timApp.admin.search_in_documents.SearchArgumentsCLI) int[source]#

Same as search(), but prints the matches according to the provided format.

timApp.admin.sisu_cli module#

timApp.admin.timitemtype module#

class timApp.admin.timitemtype.TimDocumentType[source]#

Bases: click.types.ParamType

TIM document.

convert(value: Any, param: Any, ctx: Any) timApp.item.item.Item[source]#

Convert the value to the correct type. This is not called if the value is None (the missing value).

This must accept string values from the command line, as well as values that are already the correct type. It may also convert other compatible types.

The param and ctx arguments may be None in certain situations, such as when converting prompt input.

If the value cannot be converted, call fail() with a descriptive message.

Parameters
  • value – The value to convert.

  • param – The parameter that is using this type to convert its value. May be None.

  • ctx – The current context that arrived at this value. May be None.

name: str = 'timdocument'#

the descriptive name of this type

class timApp.admin.timitemtype.TimItemType[source]#

Bases: click.types.ParamType

TIM item.

convert(value: Any, param: Any, ctx: Any) timApp.item.item.Item[source]#

Convert the value to the correct type. This is not called if the value is None (the missing value).

This must accept string values from the command line, as well as values that are already the correct type. It may also convert other compatible types.

The param and ctx arguments may be None in certain situations, such as when converting prompt input.

If the value cannot be converted, call fail() with a descriptive message.

Parameters
  • value – The value to convert.

  • param – The parameter that is using this type to convert its value. May be None.

  • ctx – The current context that arrived at this value. May be None.

name: str = 'timitem'#

the descriptive name of this type

timApp.admin.translationservice_cli module#

Enables adding TranslationServices to TIM’s database from the command line.

timApp.admin.translationservice_cli.add_all_tr_services_to_session(log: bool = False) None[source]#

Add all supported translation services to be commited to database. Note: session.commit must be called afterwards to save the changes!

Supported translation services must be implemented and are also listed in the configuration variable MACHINE_TRANSLATORS in timApp.defaultconfig.py.

This separate function allows adding all the translation services also at the db-initialization on first TIM-startup.

Returns

None.

timApp.admin.user_cli module#

class timApp.admin.user_cli.MergeResult(primary: timApp.user.user.User, secondary: timApp.user.user.User, owned_lectures: int = 0, lectureanswers: int = 0, messages: int = 0, answers: int = 0, annotations: int = 0, velps: int = 0, readparagraphs: int = 0, notes: int = 0, accesses: int = 0, groups: int = 0, contacts: int = 0)[source]#

Bases: object

accesses: int = 0#
annotations: int = 0#
answers: int = 0#
contacts: int = 0#
groups: int = 0#
lectureanswers: int = 0#
messages: int = 0#
notes: int = 0#
owned_lectures: int = 0#
primary: timApp.user.user.User#
readparagraphs: int = 0#
secondary: timApp.user.user.User#
velps: int = 0#
timApp.admin.user_cli.create_user_info_set(u: timApp.user.user.User) set[str][source]#

Returns a set of strings constructed from various parts of user info. This set is meant to be intersected with another user to determine whether they have anything in common.

timApp.admin.user_cli.do_import_passwords(csvfile: _io.TextIOWrapper, verify: bool) None[source]#
timApp.admin.user_cli.do_merge_users(u_prim: timApp.user.user.User, u_sec: timApp.user.user.User, force=False) timApp.admin.user_cli.MergeResult[source]#
timApp.admin.user_cli.do_soft_delete(u: timApp.user.user.User) None[source]#
timApp.admin.user_cli.find_and_merge_users(primary: str, secondary: str) timApp.admin.user_cli.MergeResult[source]#
timApp.admin.user_cli.find_and_soft_delete(name: str) None[source]#
timApp.admin.user_cli.find_duplicate_accounts_by_email() list[tuple[timApp.user.user.User, set[timApp.user.user.User]]][source]#
timApp.admin.user_cli.has_anything_in_common(u1: timApp.user.user.User, u2: timApp.user.user.User) bool[source]#

timApp.admin.util module#

class timApp.admin.util.BasicArguments(*, progress: bool, doc: str, folder: str, urlpath: Optional[str] = None)[source]#

Bases: object

doc: str#
folder: str#
progress: bool#
urlpath: str | None#
class timApp.admin.util.DryrunnableArguments(*, progress: bool, doc: str, folder: str, urlpath: Optional[str] = None, dryrun: bool = False)[source]#

Bases: timApp.admin.util.BasicArguments, timApp.admin.util.DryrunnableOnly

class timApp.admin.util.DryrunnableOnly(*, dryrun: bool = False)[source]#

Bases: object

dryrun: bool#
timApp.admin.util.commit_if_not_dry(dry_run: bool) None[source]#
timApp.admin.util.create_argparser(description: str, readonly: bool = False) argparse.ArgumentParser[source]#
timApp.admin.util.enum_docs(folder: Optional[timApp.folder.folder.Folder] = None) Generator[timApp.document.docinfo.DocInfo, None, None][source]#
timApp.admin.util.enum_pars(item: Optional[Union[timApp.folder.folder.Folder, timApp.document.docinfo.DocInfo]] = None) Generator[tuple[timApp.document.docinfo.DocInfo, timApp.document.docparagraph.DocParagraph], None, None][source]#
timApp.admin.util.get_url_for_match(args: timApp.admin.util.BasicArguments, d: timApp.document.docinfo.DocInfo, p: timApp.document.docparagraph.DocParagraph) str[source]#
timApp.admin.util.iterate_pars_skip_exceptions(d: timApp.document.docinfo.DocInfo) Generator[timApp.document.docparagraph.DocParagraph, None, None][source]#
timApp.admin.util.print_match(args: timApp.admin.util.DryrunnableArguments, d: timApp.document.docinfo.DocInfo, p: timApp.document.docparagraph.DocParagraph, msg: str) None[source]#
timApp.admin.util.process_items(func: Callable[[timApp.document.docinfo.DocInfo, timApp.admin.util.T], int], parser: argparse.ArgumentParser) None[source]#

Module contents#