diff --git a/app.py b/app.py index c47f7c9..2cce77a 100644 --- a/app.py +++ b/app.py @@ -1,1298 +1,1299 @@ import babel import copy import decorator import flask from flask.typing import ResponseReturnValue as RRV import jinja2 import json from markupsafe import Markup import mwapi # type: ignore import mwoauth # type: ignore import os import random import re import requests import requests_oauthlib # type: ignore import stat import string import toolforge from typing import cast, Any, Optional, Tuple, TypedDict import unicodedata import werkzeug import yaml from flask_utils import OrderedFlask, TagOrderedMultiDict, TagImmutableOrderedMultiDict, SetJSONProvider from language import lang_lex2int, lang_int2html, lang_int2babel -from language_info import autonym, label, fallbacks +from language_info import label from matching import match_template_to_lexeme_data, match_lexeme_forms_to_template, match_template_entity_to_lexeme_entity, MatchedTemplate, MatchedTemplateForm from mwapi_utils import T272319RetryingSession from parse_tpsv import parse_lexemes, FirstFieldNotLexemeIdError, FirstFieldLexemeIdError, WrongNumberOfFieldsError from templates import templates, templates_without_redirects, Template, TemplateForm import tool_translations_config from toolforge_i18n.formatters import I18nFormatter +from toolforge_i18n.language_info import autonym, fallbacks from toolforge_i18n.translations import load_translations from wikibase_types import Lexeme, LexemeForm, LexemeLemmas, Statements, Term app = OrderedFlask(__name__) app.session_interface.serializer.register(TagOrderedMultiDict, index=0) app.session_interface.serializer.register(TagImmutableOrderedMultiDict, index=0) app.json = SetJSONProvider(app) app.add_template_filter(lang_lex2int) app.add_template_filter(lang_int2html) app.add_template_filter(lang_int2babel) user_agent = toolforge.set_user_agent('lexeme-forms', email='mail@lucaswerkmeister.de') @decorator.decorator def read_private(func, *args, **kwargs): try: f = args[0] fd = f.fileno() except AttributeError: pass except IndexError: pass else: mode = os.stat(fd).st_mode if (stat.S_IRGRP | stat.S_IROTH) & mode: raise ValueError(f'{getattr(f, "name", "config file")} is readable to others, ' 'must be exclusively user-readable!') return func(*args, **kwargs) has_config = app.config.from_file('config.yaml', load=read_private(yaml.safe_load), silent=True) if has_config: consumer_token = mwoauth.ConsumerToken(app.config['OAUTH']['consumer_key'], app.config['OAUTH']['consumer_secret']) else: print('config.yaml file not found, assuming local development setup') app.secret_key = 'fake' translations = load_translations(tool_translations_config.config) class BoundTemplate(MatchedTemplate): lexeme_id: str lexeme_revision: str class EditedTemplateForm(TemplateForm): value: str class Duplicate(TypedDict): id: str uri: str # TODO use display (w.wiki/5Tna) to have terms as label/description label: str description: str forms_count: str senses_count: str @decorator.decorator def enableCORS(func, *args, **kwargs): rv = func(*args, **kwargs) response = flask.make_response(rv) response.headers['Access-Control-Allow-Origin'] = '*' return response @app.before_request def init_interface_language_code(): legacy_language_codes = { # any pair here can be removed after a while, see b762a62db6 'yue': 'zh-hant', # PR #187, 2023-11-12 } if 'uselang' in flask.request.args: flask.g.interface_language_code = flask.request.args['uselang'] elif flask.session.get('interface_language_code') in translations | legacy_language_codes: flask.g.interface_language_code = flask.session['interface_language_code'] if flask.g.interface_language_code in legacy_language_codes: flask.g.interface_language_code = legacy_language_codes[flask.g.interface_language_code] flask.session['interface_language_code'] = flask.g.interface_language_code if flask.g.interface_language_code not in translations: flask.g.interface_language_code = 'en' else: flask.g.interface_language_code = flask.request.accept_languages\ .best_match(translations.keys(), 'en') flask.g.html_language_codes = [] @app.template_global() def push_html_lang(language_code: str) -> Markup: html_language_code = lang_int2html(language_code) flask.g.html_language_codes.append(html_language_code) return Markup(r'lang="{}" dir="{}"').format(html_language_code, text_direction(language_code)) @app.template_global() def pop_html_lang(language_code: str) -> Markup: html_language_code = lang_int2html(language_code) assert flask.g.html_language_codes.pop() == html_language_code return Markup(r'') @app.after_request def assert_html_lang_empty(response: werkzeug.Response) -> werkzeug.Response: assert flask.g.html_language_codes == [] return response @app.after_request def denyFrame(response: werkzeug.Response) -> werkzeug.Response: """Disallow embedding the tool’s pages in other websites. If other websites can embed this tool’s pages, e. g. in