From acc592426fa468c8542f09fd54a0c24b43e7a1d5 Mon Sep 17 00:00:00 2001 From: erjemin Date: Tue, 22 Jul 2025 13:12:07 +0300 Subject: [PATCH] =?UTF-8?q?add:=20=D1=82=D0=B5=D1=81=D1=82=D1=8B=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20unbreakables.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- etpgrf/__init__.py | 2 +- etpgrf/unbreakables.py | 2 +- main.py | 8 ++-- requirement.txt | 7 +++ tests/__init__.py | 1 + tests/test_unbreakables.py | 90 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 tests/__init__.py create mode 100644 tests/test_unbreakables.py diff --git a/etpgrf/__init__.py b/etpgrf/__init__.py index 1208e02..67d34e7 100644 --- a/etpgrf/__init__.py +++ b/etpgrf/__init__.py @@ -1,5 +1,5 @@ """ -Typography - библиотека для экранной типографики текста с поддержкой HTML. +etpgrf - библиотека для экранной типографики текста с поддержкой HTML. Основные возможности: - Автоматическая расстановка переносов diff --git a/etpgrf/unbreakables.py b/etpgrf/unbreakables.py index e55da5d..97bf41d 100644 --- a/etpgrf/unbreakables.py +++ b/etpgrf/unbreakables.py @@ -49,7 +49,7 @@ _EN_UNBREAKABLE_WORDS = frozenset([ 'a', 'an', 'as', 'at', 'by', 'in', 'is', 'it', 'of', 'on', 'or', 'so', 'to', 'if', # 3-4 letter words 'for', 'from', 'into', 'that', 'then', 'they', 'this', 'was', 'were', 'what', 'when', 'with', - 'not', 'but', 'which', + 'not', 'but', 'which', 'the' ]) # --- Настройки логирования --- diff --git a/main.py b/main.py index 5aebb84..3059b40 100644 --- a/main.py +++ b/main.py @@ -28,7 +28,7 @@ if __name__ == '__main__': print(result, "\n\n") # Определяем пользовательские правила типографа - typo_ru = etpgrf.Typographer(langs='ru', mode='mixed', hyphenation=hyphen_settings) + typo_ru = etpgrf.Typographer(langs='ru', mode='unicode', hyphenation=hyphen_settings) result = typo_ru.process(text="Какой-то длинный текст для проверки переносов. Перпердикюляция!") print(result, "\n\n") @@ -80,15 +80,15 @@ if __name__ == '__main__': "Later, over coffee, Anna joked, “I told the tailor, ‘Make it so I never want to take it off.’ " "Looks like they succeeded!") etpgrf.defaults.etpgrf_settings.hyphenation.MAX_UNHYPHENATED_LEN = 6 - typo_en = etpgrf.Typographer(langs='en', mode='mixed', hyphenation=True) + typo_en = etpgrf.Typographer(langs='en', hyphenation=True) result = typo_en.process(text=txt) print(result, "\n\n--------------\n\n") # Проверяем если есть HTML-тегов txt = ("

As they walked down the street, Anna noticed how the coat’s tailored cut moved gracefully with her." - " The consideration of every detail - from the choice of fabric to the delicate embroidery - made it" + " The consideration of every detail - from the choice of fabric to the delicate embroidery - made it" " clear that this was no ordinary coat.

") - typo_en = etpgrf.Typographer(langs='en', mode='mixed', process_html=True, hyphenation=True) + typo_en = etpgrf.Typographer(langs='en', process_html=True, hyphenation=True) result = typo_en.process(text=txt) print(result, "\n\n--------------\n\n") diff --git a/requirement.txt b/requirement.txt index f4e1d3e..dc1ceeb 100644 --- a/requirement.txt +++ b/requirement.txt @@ -4,3 +4,10 @@ beautifulsoup4==4.13.4 soupsieve==2.7 typing_extensions==4.14.1 +pytest==8.4.1 +exceptiongroup==1.3.0 +iniconfig==2.1.0 +packaging==25.0 +pluggy==1.6.0 +Pygments==2.19.2 +tomli==2.2.1 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..eb22de3 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +# Тесты etpgrf - библиотеки для экранной типографики текста с поддержкой HTML. \ No newline at end of file diff --git a/tests/test_unbreakables.py b/tests/test_unbreakables.py new file mode 100644 index 0000000..75d00ee --- /dev/null +++ b/tests/test_unbreakables.py @@ -0,0 +1,90 @@ +# tests/test_unbreakables.py +import pytest +from etpgrf import Unbreakables + + +# Список русских слов, которые должны "приклеиваться" к следующему слову. +RUSSIAN_PREPOSITIONS_TO_TEST = [ + # Предлоги (только короткие... длинные, типа `ввиду`, `ввиду` и т.п., могут быть "висячими") + 'в', 'без', 'до', 'из', 'к', 'на', 'по', 'о', 'от', 'перед', 'при', 'через', 'с', 'у', 'за', 'над', + 'об', 'под', 'про', 'для', 'ко', 'со', 'без', 'то', 'во', 'из-за', 'из-под', 'как' + # Союзы (без сложных, тип `как будто`, `как если бы`, `за то` и т.п.) + 'и', 'а', 'но', 'да', 'как', + # Частицы + 'не', 'ни', + # Местоимения + 'я', 'ты', 'он', 'мы', 'вы', 'им', 'их', 'ей', 'ею', + # Устаревшие или специфичные + 'сей', 'сия', 'сие', +] + +@pytest.mark.parametrize("word", RUSSIAN_PREPOSITIONS_TO_TEST) +def test_russian_prepositions_are_unbreakable(word): + """ + Проверяет ПОВЕДЕНИЕ: короткие слова "приклеиваются" к следующему. Для русского языка. Параметризованный тест + """ + # Arrange (подготовка) + unbreakables_ru = Unbreakables(langs='ru') + input_text = f"Проверка {word} тестирование." + expected_text = f"Проверка {word}\u00A0тестирование." + # Act (действие, которое выполняем) + actual_text = unbreakables_ru.process(input_text) + # Assert (утверждение, что результат соответствует ожиданиям) + assert actual_text == expected_text + + +# Список английских слов, которые должны "приклеиваться" к следующему слову. +ENGLISH_PREPOSITIONS_TO_TEST = [ + 'a', 'an', 'as', 'at', 'by', 'in', 'is', 'it', 'of', 'on', 'or', 'so', 'to', 'if', + 'for', 'from', 'into', 'that', 'then', 'they', 'this', 'was', 'were', 'what', 'when', 'with', + 'not', 'but', 'which', 'the' +] + +@pytest.mark.parametrize("word", ENGLISH_PREPOSITIONS_TO_TEST) +def test_english_prepositions_are_unbreakable(word): + """ + Проверяет ПОВЕДЕНИЕ: короткие слова "приклеиваются" к следующему. Для английского языка. Параметризованный тест + """ + # Arrange (подготовка) + unbreakables_en = Unbreakables(langs='en') + input_text = f"Training {word} test." + expected_text = f"Training {word}\u00A0test." + # Act (действие, которое выполняем) + actual_text = unbreakables_en.process(input_text) + # Assert (утверждение, что результат соответствует ожиданиям) + assert actual_text == expected_text + + +# Смешанный тест для русского и английского языков +def test_mix_prepositions_are_unbreakable(): + """ + Проверяет ПОВЕДЕНИЕ: короткие слова "приклеиваются" к следующему. Для смешанного русско-английского текста. + """ + # Arrange (подготовка) + unbreakables_mix = Unbreakables(langs='ru+en') + input_text = f"Для the Guardian он написал блестящую статью." + expected_text = f"Для\u00A0the\u00A0Guardian он\u00A0написал блестящую статью." + # Act (действие, которое выполняем) + actual_text = unbreakables_mix.process(input_text) + # Assert (утверждение, что результат соответствует ожиданиям) + assert actual_text == expected_text + + +# Список русских постпозитивных частиц, которые должны "приклеиваться" к предыдущему слову. +RUSSIAN_POSTPOSITIVE_PARTICLES_TO_TEST = [ + 'ли', 'ль', 'же', 'ж', 'бы', 'б' +] + +@pytest.mark.parametrize("word", RUSSIAN_POSTPOSITIVE_PARTICLES_TO_TEST) +def test_russian_postpositive_particle(word): + """ + Проверяет ПОВЕДЕНИЕ: русские постпозитивные частицы "приклеиваются" к предыдущему слову. + """ + # Arrange + unbreakables_ru = Unbreakables(langs='ru') + input_text = f"Отчего {word} не поспать?" + expected_text = f"Отчего\u00A0{word} не\u00A0поспать?" + # Act + actual_text = unbreakables_ru.process(input_text) + # Assert + assert actual_text == expected_text \ No newline at end of file