add: изменение настроек типографа через defaults.py

This commit is contained in:
Sergei Erjemin 2025-05-13 15:25:45 +03:00
parent f48dd5bb53
commit 5390e0583e
8 changed files with 57 additions and 28 deletions

View File

@ -1,6 +1,6 @@
| in progress // в процессе разработки | | in progress // в процессе разработки |
|--------------------------------------| |--------------------------------------|
| ----3 | | -----4 |
# Типограф для Web # Типограф для Web

View File

@ -12,4 +12,4 @@ __version__ = "0.1.0"
from etpgrf.typograph import Typographer from etpgrf.typograph import Typographer
from etpgrf.hyphenation import Hyphenator from etpgrf.hyphenation import Hyphenator
import etpgrf.config import etpgrf.defaults

View File

@ -1,5 +1,6 @@
# Общие функции для типографа etpgrf # Общие функции для типографа etpgrf
from etpgrf.config import MODE_UNICODE, MODE_MNEMONIC, MODE_MIXED, DEFAULT_MODE, DEFAULT_LANGS, SUPPORTED_LANGS from etpgrf.config import MODE_UNICODE, MODE_MNEMONIC, MODE_MIXED, SUPPORTED_LANGS
from etpgrf.defaults import etpgrf_settings
import os import os
import regex import regex
@ -18,7 +19,7 @@ def parse_and_validate_mode(
""" """
if mode_input is None: if mode_input is None:
# Если mode_input не предоставлен явно, используем режим по умолчанию # Если mode_input не предоставлен явно, используем режим по умолчанию
_mode_input = DEFAULT_MODE _mode_input = etpgrf_settings.MODE
else: else:
_mode_input = str(mode_input).lower() _mode_input = str(mode_input).lower()
@ -31,44 +32,44 @@ def parse_and_validate_mode(
def parse_and_validate_langs( def parse_and_validate_langs(
langs_input: str | list[str] | tuple[str, ...] | frozenset[str] | None = None, langs: str | list[str] | tuple[str, ...] | frozenset[str] | None = None,
) -> frozenset[str]: ) -> frozenset[str]:
""" """
Обрабатывает и валидирует входной параметр языков. Обрабатывает и валидирует входной параметр языков.
Если langs_input не предоставлен (None), используются языки по умолчанию Если langs_input не предоставлен (None), используются языки по умолчанию
(сначала из переменной окружения ETPGRF_DEFAULT_LANGS, затем внутренний дефолт). (сначала из переменной окружения ETPGRF_DEFAULT_LANGS, затем внутренний дефолт).
:param langs_input: Язык(и) для обработки. Может быть строкой (например, "ru+en"), :param langs: Язык(и) для обработки. Может быть строкой (например, "ru+en"),
списком, кортежем или frozenset. списком, кортежем или frozenset.
:return: Frozenset валидированных кодов языков в нижнем регистре. :return: Frozenset валидированных кодов языков в нижнем регистре.
:raises TypeError: Если langs_input имеет неожиданный тип. :raises TypeError: Если langs_input имеет неожиданный тип.
:raises ValueError: Если langs_input пуст после обработки или содержит неподдерживаемые коды. :raises ValueError: Если langs_input пуст после обработки или содержит неподдерживаемые коды.
""" """
_langs_input = langs_input _langs = langs
if _langs_input is None: if _langs is None:
# Если langs_input не предоставлен явно, будем выкручиваться и искать в разных местах # Если langs не предоставлен явно, будем выкручиваться и искать в разных местах
# 1. Попытка получить языки из переменной окружения системы # 1. Попытка получить языки из переменной окружения системы
env_default_langs = os.environ.get('ETPGRF_DEFAULT_LANGS') env_default_langs = os.environ.get('ETPGRF_DEFAULT_LANGS')
if env_default_langs: if env_default_langs:
# Нашли язык для библиотеки в переменных окружения # Нашли язык для библиотеки в переменных окружения
_langs_input = env_default_langs _langs = env_default_langs
# print(f"Using ETPGRF_DEFAULT_LANGS from environment: {env_default_langs}") # Для отладки # print(f"Using ETPGRF_DEFAULT_LANGS from environment: {env_default_langs}") # Для отладки
else: else:
# Если в переменной окружения нет, используем то что есть в конфиге `etpgrf/config.py` # Если в переменной окружения нет, используем то что есть в конфиге `etpgrf/config.py`
_langs_input = DEFAULT_LANGS _langs = etpgrf_settings.DEFAULT_LANGS
# print(f"Using library internal default langs: {DEFAULT_LANGS}") # Для отладки # print(f"Using library internal default langs: {DEFAULT_LANGS}") # Для отладки
if isinstance(_langs_input, str): if isinstance(_langs, str):
# Разделяем строку по любым небуквенным символам, приводим к нижнему регистру # Разделяем строку по любым небуквенным символам, приводим к нижнему регистру
# и фильтруем пустые строки # и фильтруем пустые строки
parsed_lang_codes_list = [lang.lower() for lang in regex.split(r'[^a-zA-Z]+', _langs_input) if lang] parsed_lang_codes_list = [lang.lower() for lang in regex.split(r'[^a-zA-Z]+', _langs) if lang]
elif isinstance(_langs_input, (list, tuple, frozenset)): # frozenset тоже итерируемый elif isinstance(_langs, (list, tuple, frozenset)): # frozenset тоже итерируемый
# Приводим к строке, нижнему регистру и проверяем, что строка не пустая # Приводим к строке, нижнему регистру и проверяем, что строка не пустая
parsed_lang_codes_list = [str(lang).lower() for lang in _langs_input if str(lang).strip()] parsed_lang_codes_list = [str(lang).lower() for lang in _langs if str(lang).strip()]
else: else:
raise TypeError( raise TypeError(
f"etpgrf: параметр 'langs' должен быть строкой, списком, кортежем или frozenset. Получен: {type(_langs_input)}" f"etpgrf: параметр 'langs' должен быть строкой, списком, кортежем или frozenset. Получен: {type(_langs)}"
) )
if not parsed_lang_codes_list: if not parsed_lang_codes_list:
@ -84,7 +85,7 @@ def parse_and_validate_langs(
) )
validated_langs_set.add(code) validated_langs_set.add(code)
# Эта проверка на случай, если parsed_lang_codes_list был не пуст, но все коды оказались невалидными # Эта проверка на случай если parsed_lang_codes_list был не пуст, но все коды оказались невалидными
# (хотя предыдущее исключение должно было сработать раньше для каждого невалидного кода). # (хотя предыдущее исключение должно было сработать раньше для каждого невалидного кода).
if not validated_langs_set: if not validated_langs_set:
raise ValueError("etpgrf: не предоставлено ни одного валидного кода языка.") raise ValueError("etpgrf: не предоставлено ни одного валидного кода языка.")

View File

@ -1,23 +1,22 @@
# etpgrf/conf.py # etpgrf/conf.py
# Настройки по умолчанию для типографа etpgrf # Настройки по умолчанию для типографа etpgrf
from email.header import SPACE
# Режимы "отдачи" результатов обработки # Режимы "отдачи" результатов обработки
MODE_UNICODE = "unicode" MODE_UNICODE = "unicode"
MODE_MNEMONIC = "mnemonic" MODE_MNEMONIC = "mnemonic"
MODE_MIXED = "mixed" MODE_MIXED = "mixed"
DEFAULT_MODE = MODE_MIXED # DEFAULT_MODE = MODE_MIXED
# Языки, поддерживаемые библиотекой # Языки, поддерживаемые библиотекой
LANG_RU = 'ru' # Русский LANG_RU = 'ru' # Русский
LANG_EN = 'en' # Английский LANG_EN = 'en' # Английский
SUPPORTED_LANGS = frozenset([LANG_RU, LANG_EN]) SUPPORTED_LANGS = frozenset([LANG_RU, LANG_EN])
# Язык(и) по умолчанию, если не указаны пользователем и не заданы через ETPGRF_DEFAULT_LANGS_MODULE # Язык(и) по умолчанию, если не указаны пользователем и не заданы через ETPGRF_DEFAULT_LANGS_MODULE
DEFAULT_LANGS = LANG_RU # DEFAULT_LANGS = LANG_RU
# Значения по умолчанию для параметров Hyphenator # Значения по умолчанию для параметров Hyphenator
DEFAULT_HYP_MAX_LEN = 10 # Максимальная длина слова без переносов # DEFAULT_HYP_MAX_LEN = 10 # Максимальная длина слова без переносов
DEFAULT_HYP_MIN_LEN = 3 # Минимальный "хвост" слова для переноса # DEFAULT_HYP_MIN_LEN = 3 # Минимальный "хвост" слова для переноса
# ----------------- соответствия `unicode` и `mnemonic` для типографа # ----------------- соответствия `unicode` и `mnemonic` для типографа

22
etpgrf/defaults.py Normal file
View File

@ -0,0 +1,22 @@
# etpgrf/defaults.py -- Настройки по умолчанию для типографа etpgrf
from etpgrf.config import LANG_RU, MODE_MIXED
class HyphenationDefaults:
"""
Настройки по умолчанию для Hyphenator etpgrf.
"""
MAX_UNHYPHENATED_LEN: int = 14
MIN_TAIL_LEN: int = 3
class EtpgrfDefaultSettings:
"""
Общие настройки по умолчанию для всех модулей типографа etpgrf.
"""
def __init__(self):
self.LANGS: list[str] | str = LANG_RU
self.MODE: str = MODE_MIXED
self.hyphenation = HyphenationDefaults()
# self.quotes = EtpgrfQuoteDefaults()
etpgrf_settings = EtpgrfDefaultSettings()

View File

@ -1,11 +1,17 @@
import regex import regex
from etpgrf.config import LANG_RU, LANG_EN, SHY_ENTITIES, MODE_UNICODE, DEFAULT_HYP_MAX_LEN, DEFAULT_HYP_MIN_LEN from etpgrf.config import LANG_RU, LANG_EN, SHY_ENTITIES, MODE_UNICODE
from etpgrf.defaults import etpgrf_settings
from etpgrf.comutil import parse_and_validate_mode, parse_and_validate_langs from etpgrf.comutil import parse_and_validate_mode, parse_and_validate_langs
_RU_VOWELS_UPPER = frozenset(['А', 'О', 'И', 'Е', 'Ё', 'Э', 'Ы', 'У', 'Ю', 'Я']) _RU_VOWELS_UPPER = frozenset(['А', 'О', 'И', 'Е', 'Ё', 'Э', 'Ы', 'У', 'Ю', 'Я'])
_RU_CONSONANTS_UPPER = frozenset(['Б', 'В', 'Г', 'Д', 'Ж', 'З', 'К', 'Л', 'М', 'Н', 'П', 'Р', 'С', 'Т', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ']) _RU_CONSONANTS_UPPER = frozenset(['Б', 'В', 'Г', 'Д', 'Ж', 'З', 'К', 'Л', 'М', 'Н', 'П', 'Р', 'С', 'Т', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ'])
_RU_J_SOUND_UPPER = frozenset(['Й']) _RU_J_SOUND_UPPER = frozenset(['Й'])
_RU_SIGNS_UPPER = frozenset(['Ь', 'Ъ']) _RU_SIGNS_UPPER = frozenset(['Ь', 'Ъ'])
_RU_OLD_I_DESYAT = frozenset(['І']) # И-десятеричное
_RU_OLD_YAT = frozenset(['Ѣ']) # Ять
_RU_OLD_FITA = frozenset(['Ѳ']) # Фита
_RU_OLD_IZHITSA = frozenset(['Ѵ']) # Ижица (может быть и гласной, и согласной - сложный случай!)
_EN_VOWELS_UPPER = frozenset(['A', 'E', 'I', 'O', 'U', 'Æ', 'Œ']) _EN_VOWELS_UPPER = frozenset(['A', 'E', 'I', 'O', 'U', 'Æ', 'Œ'])
_EN_CONSONANTS_UPPER = frozenset(['B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z']) _EN_CONSONANTS_UPPER = frozenset(['B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z'])
@ -17,12 +23,12 @@ class Hyphenator:
def __init__(self, def __init__(self,
langs: str | list[str] | tuple[str, ...] | frozenset[str] | None = None, langs: str | list[str] | tuple[str, ...] | frozenset[str] | None = None,
mode: str = None, # Режим обработки текста mode: str = None, # Режим обработки текста
max_unhyphenated_len: int = DEFAULT_HYP_MAX_LEN, # Максимальная длина непереносимой группы max_unhyphenated_len: int | None = None, # Максимальная длина непереносимой группы
min_chars_per_part: int = DEFAULT_HYP_MIN_LEN): # Минимальная длина после переноса (хвост, который разрешено переносить) min_tail_len: int | None = None): # Минимальная длина после переноса (хвост, который разрешено переносить)
self.langs: frozenset[str] = parse_and_validate_langs(langs) self.langs: frozenset[str] = parse_and_validate_langs(langs)
self.mode: str = parse_and_validate_mode(mode) self.mode: str = parse_and_validate_mode(mode)
self.max_unhyphenated_len = max_unhyphenated_len self.max_unhyphenated_len = etpgrf_settings.hyphenation.MAX_UNHYPHENATED_LEN if max_unhyphenated_len is None else max_unhyphenated_len
self.min_chars_per_part = min_chars_per_part self.min_chars_per_part = etpgrf_settings.hyphenation.MIN_TAIL_LEN if min_tail_len is None else min_tail_len
# Внутренние языковые ресурсы, если нужны специфично для переносов # Внутренние языковые ресурсы, если нужны специфично для переносов
self._vowels: frozenset = frozenset() self._vowels: frozenset = frozenset()

View File

@ -1,4 +1,5 @@
from etpgrf.comutil import parse_and_validate_mode, parse_and_validate_langs from etpgrf.comutil import parse_and_validate_mode, parse_and_validate_langs
from etpgrf.hyphenation import Hyphenator from etpgrf.hyphenation import Hyphenator

View File

@ -5,7 +5,7 @@ if __name__ == '__main__':
# --- Пример использования --- # --- Пример использования ---
print("\n--- Пример использования класса---\n") print("\n--- Пример использования класса---\n")
etpgrf.config.DEFAULT_HYP_MAX_LEN = 6 etpgrf.defaults.etpgrf_settings.hyphenation.MAX_UNHYPHENATED_LEN = 8
# Определяем пользовательские правила переносов # Определяем пользовательские правила переносов
hyphen_settings = etpgrf.Hyphenator(langs='ru', max_unhyphenated_len=8) hyphen_settings = etpgrf.Hyphenator(langs='ru', max_unhyphenated_len=8)