Участник:BsivkoBot/Оформление параметров шаблонов

Описание

Мотивация

Тематическое обсуждение: Обсуждение_Википедии:Шаблоны_цитирования_CS1/2#Переводчик_«cite_journal»_на_шаблон_«статья»

Есть ряд требований к оформлению полей ряда шаблонов, которые не всегда соблюдаются и могут быть исправлены автоматически. Например, для указания диапазонов страниц зачастую используется знак «-» вместо «—», или знак копируется из других языковых разделов и не изменяется. Подобное исправление делает викификатор, но его функциональностью не все пользуются. Если для рядовых участников это мало касается, то если статья номинируется на статусную, то это требует исправления всех недочётов, включая и этот. Как следствие, это приводит к муторной работе участников, снижает их мотивацию и продуктивность. Эти же действия можно делать автоматически, для чего и поставлена задача боту.

Вторая задача — перевод страниц в полный формат. В англоязычных источниках устречается опускание лидирующих цифр для второго числа, то есть 2542-77 означает на самом деле 2542-2577.

Третья задача — после копирования ссылок из англовики остаются английские наименования языков для поля «язык». Например, язык=French после language=French. Это же поле для шаблонов ({{статья}}, {{публикация}}, {{книга}}) используется по двухбуквенному формату ISO 639, т.е. в виде язык=fr. Задача заключается в распознавании таких случаев и преобразовании в ISO 639.

Четвёртая задача — удаление префиксов в полях страниц, приведение к общему формату на уровне стандартов.

Пятая задача — в шаблоне {{книга}} приведение формата страниц, томов, столбцов к общему варианту. Связано с обновлением и рефакторингом шаблона — параметры указываются одинаково, а форма представления зависит от языка.

Шестая задача — удаление замыкающих точек в значниях параметров заглавия шаблонов-ссылок. В них точки избыточны, так как сам шаблон их проставляет. Если в конце заглавия находится «?», «…» или «!», то проставляется параметр nodot.

Седьмая задача — избавление шаблона книги от ссылок на архивы, так как шаблон не поддерживает archiveurl. (выключена до достижения консенсуса)

Восьмая задача — правка идентификаторов сносок ref=harv; при копипасте из англовики попадает значение параметра как гарвардской ссылки, которая свою поддержку в англовики. В русскоязычном разделе это не поддерживается. При выправке необходимо согласовать действие с {{sfn}} и его аналогами ({{sfnp}}). Первое делается по имени автора и под него попадает большинство случаев. Т.о. производится замена ref=harv на первое имя автора.

Девятая задача — в ряде шаблонов ссылки офорвляются через соответствующие параметры (например, в {{книга}} через «ссылка» или «ссылка часть»). Однако частыми являются случаи, когда в например заглавии прописывают конструкцию вида [ссылка текст]. Идея заключается переносе ссылки из такой конструкции в параметр шаблона.

10-я задача — по требованиям шаблонов месяц должен указываться числом (и далее он конвертируется согласно настройкам языка). Соответственно, бот может перевести это для известных значений (например, «март» → «3»).

11-я задача: приведение {{!}} к бесшаблонному варианту | или #124; для часто встречаемых шаблонов (для всех случаев такое делать нельзя).

12-я задача — перевод ссылок с http на https для тех сайтов, которые сменили протокол. То есть, если сохранилась ссылка http, сайт на неё отвечает переходом на https, то нужна замена. В этом случае пользователям при переходе по такой ссылке понадобится меньше времени на согласование соединения. Если сайт отвечает другой ссылкой (меняется не только протокол, за исключением www.), то тогда замену производить нельзя (могут сломаться архивы).

Реализация

Бот перебирает следующие шаблоны и их параметры:

  • {{статья}}: «страницы», «том», «номер», «выпуск»;
  • {{публикация}}: «страницы», «столбцы», «номер», «серия выпуск», «серия номер», «подсерия номер»;
  • {{книга}}: «страницы»;

Если в указанных полях обнаруживаются символы «-» или «-», то они заменяются на «—».

Вторая задача — перевод в полный формат страниц, последние диапазоны которых записаны только значащими цифрами. Здесь перебирает следующие шаблоны и их параметры:

Если в указанных полях:

  • попадает под маску «число1—число2»;
  • «число1» равно 100 или больше;
  • «число2» больше «число1»;
  • длина «число2» больше длины «число1» (в цифрах);

То: берутся лидирующие цифры первого числа (количество цифр «число1» минус количество цифр «число2») и записываются во второе.

Третья задача: преобразование англоязычных названий языков на формат ISO 639 для полей «язык». Перебираются следующие шаблоны и их параметры:

Если там обнаруживаются соответствующие названия языков, то преобразуются в формат ISO 639.

Четвёртая задача: удаление префиксов «p.» «С.» «pp.» и т.д. из полей страниц. Перебираются следующие шаблоны и их параметры:

Пятая задача: приведение параметров шаблона {{книга}} к общему варианту. Следующая обработка:

  • "pages", "allpages", "seite", "alleseiten" в "страницы";
  • "volume", "band" в "том";
  • "columns", "kolonnen" в "столбцы".

Шестая задача: удаление последних точек в заглавиях шаблонов-ссылок. В том числе, обрабатываются «?» и «!» с простановкой nodot. Обрабатываются:

Седьмая задача: сканируются статьи проблемной категории. Если обнаруживается параметр archiveurl у шаблона {{книга}}, то он копируется наверх ссылка и удаляется; параметр archivedate удаляется.

Восьмая задача: правка идентификаторов сносок ref=harv. Сканируются все {{книга}}, {{статья}}, и если обнаруживается такой параметр с таким значением, то заменяется на первое имя автора.

Девятая задача:

  • для проверяемых шаблонов {{книга}}, {{статья}}, {{БРЭ}} переносимые ссылки: «заглавие» → «ссылка», «том» → «ссылка том», «часть» → «ссылка часть».
  • для {{публикация}} переносимые ссылки: «заглавие» → «ссылка», «том заглавие»/«том» → «том ссылка», «часть» → «часть ссылка», «часть оригинал» → «часть оригинал ссылка», , «оригинал» → «оригинал ссылка», «выпуск заглавие»/«выпуск» → «выпуск ссылка», «номер заглавие»/«номер» → «номер ссылка», «книга заглавие»/«книга» → «книга ссылка», «раздел заглавие»/«раздел» → «раздел ссылка».

10-я задача:

  • Для шаблонов {{книга}}, {{статья}} и {{публикация}}.
  • Параметр «месяц».
  • Конвертируются русскоязычные и англоязычные названия месяцев.

11-я задача:

  • Параметры шаблонов: "книга", "статья", "публикация", "citation" "cite web", "cite news", "cite encyclopedia", "cite dictionary", "citation", "cite book", "cite press release", "cite conference", "cite report", "cite thesis", "cite tweet", "cite AV media", "cite AV media notes", "cite video", "cite document", "cite newspaper", "cite press", "cite episode", "cite interview", "cite".
  • Если это ссылка вида [[ссылка{{!}}текст]], то преобразование к [[ссылка|текст]]; иначе замена на #124;.

12-я задача:

  • перебор всех параметров шаблонов списка 'url', 'ссылка', 'часть ссылка', 'том ссылка', 'часть оригинал ссылка', 'оригинал ссылка', 'ссылка том', 'выпуск ссылка', 'книга ссылка', 'номер ссылка', 'раздел ссылка', 'ссылка часть', 'издание ссылка'; кроме того, обработке подвергаются ссылки формата [http ..]
  • если в значении есть URL с протоколом, то пробуется обработка; https не затрагивается;
  • если при запросе на сервер меняется только протокол на https и может быть смена www., то производится замена;
  • замена производится по всему тексту статьи (для затрагивания архивных ссылок и ссылок в других шаблонах).

Исходный код

import mwparserfromhell
import re

from bot_logging.log import log_warning_json
from processing.common import template_name_matches
from template_params_standard_adjusting.final_dot_in_title import final_dot_in_title
from template_params_standard_adjusting.https_fixes import fix_http_by_request
from template_params_standard_adjusting.language_name import convert_language_from_name_to_iso_vary
from text_processing.languages import lang_to_iso_639
from text_processing.space_chars import get_end_space_chars, get_begin_space_chars
from wiki_requests.redirects import get_redirects_to_template
from wiki_template_processing.endings_format import detect_format_endings, process_leading_and_ending_param_values

TASK_DESCRIPTION_PARAMS_ADJUSTING = u"оформление параметров шаблонов"


def has_latin(text):
    return bool(re.search('[a-zA-Z]', text))


def dehype(text):
    if "<!--" in text:
        return text

    return text.replace("-", "—").replace("–", "—")


def detect_and_fix_ending(text):
    x = re.match("([0-9]+)—([0-9]+)", text.strip())

    if x is None:
        return text

    ending = get_end_space_chars(text)

    first_str = str(x.group(1))
    first = int(x.group(1))
    last_str = str(x.group(2))
    last = int(x.group(2))

    if first < 100:
        return text

    if last > first:
        return text

    if len(last_str) >= len(first_str):
        return text

    need_to_replace = len(first_str) - len(last_str)
    text = first_str + "—" + first_str[:need_to_replace] + last_str + ending

    return text


def detect_and_fix_ending_processing(template, names_to_process):
    for param in template.params:
        if str(param.name).strip() in names_to_process:
            param.value = detect_and_fix_ending(str(param.value))

    return


def hyphen_processing(template, names_to_process, title, template_name):
    changed = False
    for param in template.params:
        if str(param.name).strip() in names_to_process:
            old = str(param.value)

            if has_latin(old):
                continue

            if "<!--" in old:
                data = {}
                data['template'] = template_name
                data['value'] = old
                log_warning_json(title, 'hypen comment detected', data)
                continue

            param.value = dehype(str(param.value))
            if str(param.value) != old:
                changed = True

    return changed


def language_processing(template, names_to_process):
    changed = False
    for param in template.params:
        if str(param.name).strip() in names_to_process:
            old = str(param.value)
            param.value = convert_language_from_name_to_iso_vary(str(param.value))

            if str(param.value).strip() != "":
                begin = get_begin_space_chars(param.value)
                end = get_end_space_chars(param.value)
                param.value = begin + lang_to_iso_639(param.value) + end

            if str(param.value) != old:
                changed = True

    return changed


def final_dots_processing(template, name_mapping):
    ending = detect_format_endings(template)
    changed = False
    for param in template.params:
        param_name = str(param.name).strip()
        if param_name in name_mapping.keys():
            old = str(param.value)
            param.value = final_dot_in_title(str(param.value))
            if str(param.value) != old:
                changed = True
                param.value = str(param.value).strip() + ending

            old_stripped = old.strip()
            if len(old_stripped) > 0:
                if old_stripped[len(old_stripped) - 1] in ['!', '?', '…']:
                    nodot_name = "nodot"
                    if name_mapping[param_name]:
                        nodot_name = name_mapping[param_name]
                    if not template.has(nodot_name):
                        template.add(nodot_name, '1')
                        changed = True

    return changed


def pp_cut(value):
    ending = get_end_space_chars(value)

    result = value.strip()

    cut_prefixes = ["p.", "pp.", "P.", "PP.", "С.", "С.", "c.", "С.", "СС.", "сс.", "cc.", "CC.", "стр."]
    for element in cut_prefixes:
        if result[:len(element)] == element:
            return result[len(element):].strip() + ending

    return value


def to_pages_universal(template):
    if not template.has("язык"):
        return False

    changed = False
    for param in template.params:
        if str(param.name).strip() in ["pages", "seite"]:
            param.name = "страницы"
            changed = True
        if str(param.name).strip() in ["allpages", "alleseiten"]:
            param.name = "страниц"
            changed = True
        if str(param.name).strip() in ["volume", "band"]:
            param.name = "том"
            changed = True
        if str(param.name).strip() in ["columns", "kolonnen"]:
            param.name = "столбцы"
            changed = True

    return changed


def pages_pp_cut(template, names_to_process):
    changed = False
    for param in template.params:
        if str(param.name).strip() in names_to_process:
            old = str(param.value)
            param.value = pp_cut(str(param.value))
            if str(param.value) != old:
                changed = True

    return changed


# process all article
def book_archiveurl(template):
    need_to_commit = False

    url = None
    if template.has("archivedate"):
        template.remove("archivedate")
        need_to_commit = True
    if template.has("deadlink"):
        template.remove("deadlink")
        need_to_commit = True
    if template.has("archiveurl"):
        url = str(template.get("archiveurl").value).strip()
        template.remove("archiveurl")
        need_to_commit = True

    if url:
        if template.has("ссылка"):
            template.get("ссылка").value = url
        else:
            template.add("ссылка", url)

    return need_to_commit


def article_param_names(template):
    changed = False
    if template.has("язык"):

        if template.has("pages"):
            changed = True
            template.get("pages").name = "страницы"

        if template.has("volume"):
            changed = True
            template.get("volume").name = "том"

        if template.has("seite"):
            changed = True
            template.get("seite").name = "страницы"

        if template.has("band"):
            changed = True
            template.get("band").name = "том"

    return changed


def harv_ref(template, title):
    if not template.has('ref'):
        return False
    if str(template.get('ref').value).strip() != 'harv':
        return False
    if not template.has('автор'):
        return False

    author_value = str(template.get('автор').value).strip()
    if len(author_value) < 3:
        return False

    prefixes = ['\'\'', '[[', '{{Нп3', ':en:', '|']
    for prefix in prefixes:
        if author_value[:len(prefix)] == prefix:
            author_value = author_value[len(prefix):]

    pos = 0
    while True:
        if author_value[pos] in [' ', ',', ',', ';', '\t', '\n']:
            break
        pos += 1
        if pos >= len(author_value):
            break

    data = {}
    data['template'] = str(template.name)
    data['to'] = author_value[:pos]
    data['from'] = str(template.get('ref').value)
    log_warning_json(title, 'ref harv converted', data)

    template.get('ref').value = author_value[:pos]

    return True


def month_to_number(template):
    mapping = {
        'январь': 1,
        'февраль': 2,
        'март': 3,
        'апрель': 4,
        'май': 5,
        'июнь': 6,
        'июль': 7,
        'август': 8,
        'сентябрь': 9,
        'октябрь': 10,
        'ноябрь': 11,
        'декабрь': 12,
        'january': 1,
        'february': 2,
        'march': 3,
        'april': 4,
        'may': 5,
        'june': 6,
        'july': 7,
        'august': 8,
        'september': 9,
        'october': 10,
        'november': 11,
        'december': 12
    }

    if template.has('месяц'):
        value = str(template.get("месяц").value).strip().lower()
        if value in mapping.keys():
            template.get("месяц").value = mapping[value]
            return True
    return False


def fix_http(template, pairs={}):
    if template.has('deadlink'):
        value = str(template.get('deadlink').value)
        if value == '200':
            template.get('deadlink').value = 'no'
            return True
        if value != 'no':
            return False

    commit = False
    params = ['url', 'ссылка', 'часть ссылка', 'том ссылка', 'часть оригинал ссылка', 'оригинал ссылка', 'ссылка том',
              'выпуск ссылка', 'книга ссылка', 'номер ссылка', 'раздел ссылка', 'ссылка часть', 'издание ссылка']
    for param in params:
        if template.has(param):
            value = str(template.get(param).value)
            if "http" not in value:
                continue
            url, process = fix_http_by_request(value)
            if process:
                template.get(param).value = url
                commit = True
                pairs[value] = url
                continue

    return commit


def fix_http_old_link(text, pairs={}):
    i = 0
    while True:
        pos = text.find("[http://", i)
        if pos == -1:
            break

        last = text.find("]", pos)
        if last == -1:
            break

        url_last = text.find(" ", pos)
        if url_last == -1:
            break

        url = text[pos + 1:url_last]

        new_url, process = fix_http_by_request(url)
        if process:
            pairs[url] = new_url
        i = last

    return text


def article_hyphen_processing(text, title="unknown"):
    parsed = mwparserfromhell.parse(text)

    output = str(parsed)

    need_to_commit = False

    book_names = get_redirects_to_template("Шаблон:книга")
    for index, item in enumerate(book_names):
        if book_names[index][:7] == "Шаблон:": book_names[index] = book_names[index][7:]

    article_names = get_redirects_to_template("Шаблон:статья")
    for index, item in enumerate(article_names):
        if article_names[index][:7] == "Шаблон:": article_names[index] = article_names[index][7:]

    publication_names = get_redirects_to_template("Шаблон:публикация")
    for index, item in enumerate(publication_names):
        if publication_names[index][:7] == "Шаблон:": publication_names[index] = publication_names[index][7:]

    pairs = {}

    for template in parsed.filter_templates():

        need_to_commit |= fix_http(template, pairs)

        if (template_name_matches(template, article_names) or
                template_name_matches(template, book_names) or
                template_name_matches(template, publication_names)):
            need_to_commit |= language_processing(template, ["язык"])
            need_to_commit |= pages_pp_cut(template, ["страницы"])
            need_to_commit |= month_to_number(template)

        if template_name_matches(template, article_names):
            need_to_commit |= hyphen_processing(template, ["страницы", "том", "номер", "выпуск"], title,
                                                template_name="статья")
            need_to_commit |= final_dots_processing(template, {"заглавие": 'nodot'})
            need_to_commit |= article_param_names(template)
            need_to_commit |= harv_ref(template, title)
            detect_and_fix_ending_processing(template, ["страницы"])
            if need_to_commit:
                process_leading_and_ending_param_values(template)
        elif template_name_matches(template, book_names):
            need_to_commit |= final_dots_processing(template, {"заглавие": 'nodot', "заглавие2": 'nodot2'})
            need_to_commit |= hyphen_processing(template, ["страницы"], title, template_name="книга")
            need_to_commit |= to_pages_universal(template)
            # need_to_commit |= book_archiveurl(template)
            need_to_commit |= harv_ref(template, title)
            detect_and_fix_ending_processing(template, ["страницы"])
            if need_to_commit:
                process_leading_and_ending_param_values(template)
        elif template_name_matches(template, publication_names):
            need_to_commit |= final_dots_processing(template, {"заглавие": 'nodot', 'часть': 'часть nodot',
                                                               'издание': 'издание nodot'})
            need_to_commit |= hyphen_processing(
                template,
                ["страницы", "столбцы", "номер", "серия выпуск", "серия номер", "подсерия номер"], title,
                template_name="публикация")
            detect_and_fix_ending_processing(template, ["страницы"])
            if need_to_commit:
                process_leading_and_ending_param_values(template)
        elif template.name.matches("cite web"):
            need_to_commit |= final_dots_processing(template, {"заглавие": 'nodot'})
            need_to_commit |= language_processing(template, ["language", "lang"])
        elif template.name.matches("Cite web"):
            need_to_commit |= final_dots_processing(template, {"заглавие": 'nodot'})
            need_to_commit |= language_processing(template, ["language", "lang"])
        elif template.name.matches("cite news"):
            need_to_commit |= final_dots_processing(template, {"заглавие": 'nodot'})
            need_to_commit |= language_processing(template, ["language", "lang"])
        elif template.name.matches("cite encyclopedia"):
            need_to_commit |= language_processing(template, ["language", "lang"])

    if need_to_commit:
        output = str(parsed)

    output = fix_http_old_link(output, pairs)

    for key in pairs.keys():
        output = output.replace(key, pairs[key])

    return output

language_name.py:

import pycountry


def convert_language_from_name_to_iso_vary(name):

    new_name = convert_language_from_name_to_iso_strict(name)
    if new_name != name:
        return new_name.lower()

    lead_upper = str(name[0]).upper() + name[1:]
    new_name = convert_language_from_name_to_iso_strict(lead_upper)
    if new_name != name:
        return new_name.lower()

    return name


def convert_language_from_name_to_iso_strict(name):
    try:
        language = pycountry.languages.get(name=name)
        iso = language.alpha_2
        return iso
    except:
        return name

final_dot_in_title.py:

def final_dot_in_title(value):
    if value is None or len(value) == 0:
        return value

    counter = 0
    s = value.rstrip()
    i = len(s) - 1
    while (i >= 0):
        if s[i] != '.':
            break
        counter += 1
        i -= 1

    if counter == 0:
        return value

    if counter == 1:
        return s[:len(s) - 1]

    if counter == 2:
        return s[:len(s) - 2]

    if counter >= 3:
        return s[:len(s) - counter] + "…"

remove_old_link.py:

from copy import copy

import mwparserfromhell

from processing.common import template_name_matches
from wiki_requests.redirects import get_redirects_to_template


def remove_old_link(text):
    http_pos = text.find('[http')
    if http_pos == -1:
        return text, None

    last = text.find(']', http_pos)
    if last == -1:
        return text, None

    str_cut = text[http_pos:last + 1]
    first_space = str_cut.find(' ')
    url = str_cut[1:first_space]
    title = str_cut[first_space + 1:len(str_cut) - 1]
    text = text[:http_pos] + title + text[last + 1:]
    return text, url


def remove_old_link_book(text, title):
    names = copy(get_redirects_to_template("Шаблон:книга"))
    names.extend(get_redirects_to_template("Шаблон:статья"))
    names.extend(get_redirects_to_template("Шаблон:БРЭ"))
    for index, item in enumerate(names):
        if names[index][:7] == "Шаблон:": names[index] = names[index][7:]

    publication_names = get_redirects_to_template("Шаблон:публикация")
    for index, item in enumerate(publication_names):
        if publication_names[index][:7] == "Шаблон:": publication_names[index] = publication_names[index][7:]

    parsed = mwparserfromhell.parse(text)
    for template in parsed.filter_templates():
        if template_name_matches(template, names):
            mapping = {
                "заглавие": "ссылка",
                "часть": "ссылка часть",
                "том": "ссылка том",
            }

            for key in mapping:
                try_remove_old_link_one_param(template, key, mapping[key])

        if template_name_matches(template, publication_names):
            mapping = {
                "заглавие": "ссылка",
                "том заглавие": "том ссылка",
                "часть": "часть ссылка",
                "часть оригинал": "часть оригинал ссылка",
                "оригинал": "оригинал ссылка",
                "том": "том ссылка",
                "выпуск": "выпуск ссылка",
                "выпуск заглавие": "выпуск ссылка",
                "книга": "книга ссылка",
                "книга заглавие": "книга ссылка",
                "номер": "номер ссылка",
                "номер заглавие": "номер ссылка",
                "раздел заглавие": "раздел ссылка",
                "раздел": "раздел ссылка"
            }

            for key in mapping:
                try_remove_old_link_one_param(template, key, mapping[key])

    output = str(parsed)
    text = output

    return text


def try_remove_old_link_one_param(template, check_name, url_name):
    if template.has(check_name):
        part = str(template.get(check_name).value)
        new_part, url = remove_old_link(part)
        if url:
            template.get(check_name).value = new_part
            if template.has(url_name):
                template.get(url_name).value = url
            else:
                template.add(url_name, url)

proc124.py:

def proc124_v2(text):
    parsed = mwparserfromhell.parse(text)

    names = ["книга", "статья", "публикация", "citation" "cite web", "cite news", "cite encyclopedia",
             "cite dictionary", "citation", "cite book", "cite press release", "cite conference", "cite report",
             "cite thesis", "cite tweet", "cite AV media", "cite AV media notes", "cite video", "cite document",
             "cite newspaper", "cite press", "cite episode", "cite interview", "cite", ]
    all_names = []
    for name in names:
        all_names += get_redirects_to_template("Шаблон:" + name)

    all_names = [element.lower() for element in all_names]

    for template in parsed.ifilter_templates():
        if str((template.name).strip()) in all_names:
            for param in template.params:
                value = str(template.get(param.name).value)
                pos = 0
                while "]]" in value and "[[" in value and "{{!}}" in value:
                    first  = value.find("[[", pos)
                    if first == -1:
                        break
                    last = value.find("]]", first)
                    if last == -1:
                        break
                    if first > last:
                        break
                    pos = last
                    internal = value[first:last]
                    internal = internal.replace("{{!}}", "|")
                    value = value[:first] + internal + value[last:]

                value = value.replace("{{!}}", "|")
                template.get(param.name).value = value

    output = str(parsed)
    return output

http_fixes.py:

import requests

from bot_logging.log import log_char
from wiki_requests.redirects import get_website_access, add_website_access


def fix_url(url):
    return str(url).replace("www.", "").replace("http://", "https://")


def fix_http_by_request(url):
    website_name = parse_website_to_server_url(url)
    access = get_website_access(website_name)
    if access:
        log_char("*")
        if access == "dead":
            return url, False
        if access == "https":
            return fix_url(url), True
        if access == "http":
            return url, False

    try:
        if "http:/" not in url:
            return url, False
        response = requests.get(url, timeout=15)
        log_char(".")
        s = fix_url(url)
        process = False
        if str(response.url).startswith(s):
            add_website_access(website_name, "https")
            process = True
        else:
            add_website_access(website_name, "http")
        return str(s), process
    except Exception as e:
        add_website_access(website_name, "dead")
        return url, False


def parse_website_to_server_url(url):
    first = url.find("://")
    if first == -1:
        return None
    last = url.find("/", first + 3)
    if last == -1:
        return url
    return url[:last]

Тестирование

from template_params_standard_adjusting.hyphen import dehype, article_hyphen_processing, detect_and_fix_ending


def test_dehype():
    assert dehype('{cite}') == '{cite}'
    assert dehype('{cite}-') == '{cite}—'
    assert dehype('1.1-1.2') == '1.1—1.2'
    assert dehype('5-6-7') == '5—6—7'
    assert dehype('473–81') == '473—81'

    assert dehype('5-6 <!-- comment -->') == '5-6 <!-- comment -->'

    return


def test_detect_and_fix_ending():
    assert detect_and_fix_ending('{cite}') == '{cite}'
    assert detect_and_fix_ending('{cite}-') == '{cite}-'
    assert detect_and_fix_ending('1.1-1.2') == '1.1-1.2'
    assert detect_and_fix_ending('473—81') == '473—481'
    assert detect_and_fix_ending('12345—67') == '12345—12367'
    assert detect_and_fix_ending('473—81\n') == '473—481\n'
    assert detect_and_fix_ending('5—17; discussion 517—8') == '5—17; discussion 517—8'
    assert detect_and_fix_ending(';115—7;') == ';115—7;'

    return


def test_article_hyphen_processing():

    text = "{{персона|имя}} {{2000}}"

    assert article_hyphen_processing(text, title="test") == text

    text = "{{статья|страницы=2-5}}"
    assert article_hyphen_processing(text, title="test") == "{{статья|страницы=2—5}}"

    text = "{{книга|страницы=2-5|том=2-5|ссылка=100|archiveurl=123|archivedate=2000|deadlink=да}}"
    assert article_hyphen_processing(text, title="test") == "{{книга|страницы=2—5 |том=2-5 |ссылка=123}}"

    text = "{{публикация|подсерия номер=2-5| номер \n=2-5}}"
    assert article_hyphen_processing(text, title="test") == "{{публикация|подсерия номер=2—5 | номер \n=2—5}}"

    text = "{{статья|страницы=p. 5|автор=John}}"
    assert article_hyphen_processing(text, title="test") == "{{статья|страницы=5 |автор=John}}"

#    text = "{{книга|страницы=С. 5|автор=John}}"
#    assert article_hyphen_processing(text, title="test") == "{{книга|страницы=5|автор=John}}"

    text = "{{публикация|страницы=PP. 5-10|автор=John}}"
    assert article_hyphen_processing(text, title="test") == "{{публикация|страницы=5—10 |автор=John}}"

    text = "{{публикация\n|страницы=PP. 5-10\n|автор=John\n}}"
    assert article_hyphen_processing(text, title="test") == "{{публикация\n|страницы=5—10\n|автор=John\n}}"

    text = "{{публикация\n|страницы= 5—10\n|автор=John\n}}"
    assert article_hyphen_processing(text, title="test") == "{{публикация\n|страницы= 5—10\n|автор=John\n}}"

    text = article_hyphen_processing("{{статья\n|страницы= 5—10\n|автор=John|ref=harv\n}}", title="test")
    assert "ref=John" in text

    text = article_hyphen_processing("{{книга\n|страницы= 5—10\n|автор=John, Conor|ref=harv\n}}", title="test")
    assert "ref=John" in text

    text = article_hyphen_processing("{{статья\n|страницы= 5—10\n|автор=John, Conor\n|ref=harv}}", title="test")
    assert "ref=John\n" in text

    text = article_hyphen_processing("{{книга |заглавие=War and the World: Military Power and the Fate of Continents, 1450-2000 |год=2008 |издательство=[[Издательство Йельского университета|Yale University Press]] |ссылка=https://books.google.com/books?id=xpI_YYtvlCAC&printsec=frontcover&source=gbs_ge_summary_r&cad=0#v=onepage&q&f=false |isbn=0300147694 |ref=harv |язык=en |автор=[[Блэк, Джереми|Black, Jeremy]]}}", title="test")
    assert "Блэк" in text
    assert "Блэк," not in text

    text = article_hyphen_processing("{{книга\n|страницы= CMA-5, CMA=10\n|автор=John, Conor|ref=harv\n}}", title="test")
    assert "CMA-5" in text

    text = article_hyphen_processing("{{книга\n|заглавие= ABC?\n}}", title="test")
    assert "nodot" in text

    text = article_hyphen_processing("{{публикация\n|заглавие= ABC\n|часть=123!}}", title="test")
    assert "часть nodot" in text

    text = article_hyphen_processing("{{книга\n|заглавие= ABC|месяц= Апрель\n}}", title="test")
    assert "=4" in text

    return

test_language_name.py:

from template_params_standard_adjusting.langauage_name import convert_language_from_name_to_iso_vary


def test_convert_language_from_name_to_iso_vary():

    assert convert_language_from_name_to_iso_vary('{cite}') == '{cite}'
    assert convert_language_from_name_to_iso_vary('Russian') == 'ru'
    assert convert_language_from_name_to_iso_vary('japanese') == 'ja'
    assert convert_language_from_name_to_iso_vary('French') == 'fr'

    return

test_final_dot_in_title.py:

from template_params_standard_adjusting.final_dot_in_title import final_dot_in_title


def test_final_dot_in_title():

    assert final_dot_in_title('{cite}') == '{cite}'
    assert final_dot_in_title('.') == ''
    assert final_dot_in_title('ABC.') == 'ABC'
    assert final_dot_in_title('. ') == ''
    assert final_dot_in_title('...') == '…'
    assert final_dot_in_title('..') == ''
    assert final_dot_in_title('....') == '…'
    assert final_dot_in_title('ASD....') == 'ASD…'
    assert final_dot_in_title('QWE..') == 'QWE'
    assert final_dot_in_title('QWE  ') == 'QWE  '
    assert final_dot_in_title('QWE. ') == 'QWE'

    return

proc124.py:

def test_proc124_v2():
    assert proc124_v2("{{!}}") == "{{!}}"
    assert proc124_v2("[[a{{!}}a]]") == "[[a{{!}}a]]"
    assert proc124_v2("{{aa|a=[[a{{!}}a]]}}") == "{{aa|a=[[a{{!}}a]]}}"
    assert proc124_v2("{{aa|a={{!}}}}") == "{{aa|a={{!}}}}"
    assert proc124_v2("{{книга|a=[[a{{!}}a]]}}") == "{{книга|a=[[a|a]]}}"
    assert proc124_v2("{{книга|a=[[a{{!}}a]] abc {{!}}}}") == "{{книга|a=[[a|a]] abc |}}"
    assert proc124_v2("{{статья|a={{!}}}}") == "{{статья|a=|}}"
    assert proc124_v2("{{bt-ruslat|Беззубки{{!}}беззубок|Anodonta}}") == "{{bt-ruslat|Беззубки{{!}}беззубок|Anodonta}}"
    assert proc124_v2(
        "{{bt-latrus|Hyla|aut=Laurenti, 1768|Квакши (род){{!}}Квакши}}") == "{{bt-latrus|Hyla|aut=Laurenti, 1768|Квакши (род){{!}}Квакши}}"

test_http_fixes.py:

from template_params_standard_adjusting.https_fixes import parse_website_to_server_url, fix_http_by_request
from wiki_requests.redirects import save_all_cache


def test_parse_website_to_server_url():
    assert parse_website_to_server_url("") == None
    assert parse_website_to_server_url("google.com") == None
    assert parse_website_to_server_url("http://google.com") == "http://google.com"
    assert parse_website_to_server_url("http://google.com/asb") == "http://google.com"
    assert parse_website_to_server_url("https://google.com") == "https://google.com"
    assert parse_website_to_server_url("https://google.com/asb") == "https://google.com"


def test_fix_http_by_request():
    url, process = fix_http_by_request("http://regnum.ru")
    assert process == True
    assert url == "https://regnum.ru"

    url, process = fix_http_by_request("https://www.regnum.ru/")
    assert process == False

    url, process = fix_http_by_request("http://www.cawater-info.net/library/rus/hist/resources-amudarya/index.htm#97")
    assert process == False

    url, process = fix_http_by_request("http://www.gamecubicle.com/features-mario-units_sold_sales.htm")
    assert process == False

    url, process = fix_http_by_request("https://www.ethno-kavkaz.narod.ru/ETHNO-CAUCASUS.files/Abkhazia59.png")
    assert process == False

    # URL changes
    url, process = fix_http_by_request("http://www.stroypuls.ru/detail.php?ID=34800")
    assert process == False

Состояние и развитие

  • Тестируется. Пробный запуск после тестирования. 13:31, 24 ноября 2018 (UTC)
  • Пример обработки диапазонов страниц: так. 19:07, 24 ноября 2018 (UTC)
  • Исправлен перенос строк для обработки диапазонов страниц. 19:07, 24 ноября 2018 (UTC)
  • Добавлена третья задача с тестированием. Пример1 и Пример2. 17:00, 26 ноября 2018 (UTC)
  • Из-за ошибочной обработки (потеря данных) для второй задачи (диапазоны цифр) проверка по маске заменена на более строгую. Bsivko (обс.) 10:31, 27 ноября 2018 (UTC)
  • Добавлено удаление префиксов в номерах страниц. Пример. Bsivko (обс.) 19:56, 5 января 2019 (UTC)
  • Исправление: если изменение параметра приводит только к отсечению пробельных символов (в рамках шаблона), то такая правка не проводится. Bsivko (обс.) 16:51, 31 марта 2019 (UTC)
  • Добавление пятой задачи — обработка параметров книги. Bsivko (обс.) 16:30, 4 июня 2019 (UTC)
  • Добавление шестой задачи — обработка замыкающих точек в заглавиях шаблонов-ссылок. Bsivko (обс.) 17:38, 2 ноября 2019 (UTC)
  • Добавление 7-й и 8-й задачи — 7) обработка archiveurl шаблона {{книга}} и 8) ref=harv. Bsivko (обс.) 15:06, 3 января 2020 (UTC)
  • Добавление 9-й задачи - перенос ссылок в параметры шаблонов. Bsivko (обс.) 14:28, 13 апреля 2020 (UTC)
  • Добавление в 6-ю задачу добавления параметра nodot для заглавий, заканчивающихся на «?» или «!». Bsivko (обс.) 00:06, 15 апреля 2020 (UTC)
  • Обновление параметров для 9-й задачи. Bsivko (обс.) 14:20, 16 апреля 2020 (UTC)
  • Добавление 10-й задачи — конвертации месяцев. Bsivko (обс.) 14:25, 16 апреля 2020 (UTC)
  • Добавление 11-й задачи: преобразований {{!}}. Bsivko (обс.) 11:50, 19 апреля 2020 (UTC)
  • Добавление 12-й задачи: правки перехода протокола httphttps. Bsivko (обс.) 11:50, 19 апреля 2020 (UTC)

Обсуждение