add: логгер
This commit is contained in:
parent
b593c0148b
commit
70ddf17c9f
@ -1,6 +1,6 @@
|
||||
| in progress // в процессе разработки |
|
||||
|--------------------------------------|
|
||||
| ------5 |
|
||||
| -------6 |
|
||||
|
||||
# Типограф для Web
|
||||
|
||||
|
@ -10,6 +10,7 @@ Typography - библиотека для экранной типографики
|
||||
"""
|
||||
__version__ = "0.1.0"
|
||||
|
||||
import etpgrf.defaults
|
||||
from etpgrf.typograph import Typographer
|
||||
from etpgrf.hyphenation import Hyphenator
|
||||
import etpgrf.defaults
|
||||
import etpgrf.logger
|
||||
|
@ -1,6 +1,15 @@
|
||||
# etpgrf/defaults.py -- Настройки по умолчанию для типографа etpgrf
|
||||
import logging
|
||||
from etpgrf.config import LANG_RU, MODE_MIXED
|
||||
|
||||
class LoggingDefaults:
|
||||
LEVEL = logging.DEBUG
|
||||
FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
# Можно добавить ещё настройки, если понадобятся:
|
||||
# FORMAT: str = '%(asctime)s - %(name)s - %(levelname)s - %(module)s.%(funcName)s:%(lineno)d - %(message)s'
|
||||
# FILE_PATH: str | None = None # Путь к файлу лога, если None - не пишем в файл
|
||||
|
||||
|
||||
class HyphenationDefaults:
|
||||
"""
|
||||
Настройки по умолчанию для Hyphenator etpgrf.
|
||||
@ -16,6 +25,7 @@ class EtpgrfDefaultSettings:
|
||||
def __init__(self):
|
||||
self.LANGS: list[str] | str = LANG_RU
|
||||
self.MODE: str = MODE_MIXED
|
||||
self.logging_settings = LoggingDefaults()
|
||||
self.hyphenation = HyphenationDefaults()
|
||||
# self.quotes = EtpgrfQuoteDefaults()
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import regex
|
||||
import logging
|
||||
from etpgrf.config import LANG_RU, LANG_RU_OLD, LANG_EN, SHY_ENTITIES, MODE_UNICODE
|
||||
from etpgrf.defaults import etpgrf_settings
|
||||
from etpgrf.comutil import parse_and_validate_mode, parse_and_validate_langs
|
||||
@ -16,7 +17,11 @@ _RU_OLD_CONSONANTS_UPPER = frozenset(['Ѳ', # Фита (согласная)
|
||||
_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'])
|
||||
|
||||
# --- Настройки логирования ---
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# --- Класс Hyphenator (расстановка переносов) ---
|
||||
class Hyphenator:
|
||||
"""Правила расстановки переносов для разных языков.
|
||||
"""
|
||||
@ -41,8 +46,10 @@ class Hyphenator:
|
||||
self._load_language_resources_for_hyphenation()
|
||||
# Определяем символ переноса в зависимости от режима
|
||||
self._split_code: str = SHY_ENTITIES['SHY'][0] if self.mode == MODE_UNICODE else SHY_ENTITIES['SHY'][1]
|
||||
print(f"========={self.max_unhyphenated_len}===========")
|
||||
|
||||
# ...
|
||||
logger.debug(f"Hyphenator `__init__`. Langs: {self.langs}, Mode: {self.mode},"
|
||||
f" Max unhyphenated_len: {self.max_unhyphenated_len},"
|
||||
f" Min chars_per_part: {self.min_chars_per_part}")
|
||||
|
||||
def _load_language_resources_for_hyphenation(self):
|
||||
# Определяем наборы гласных, согласных и т.д. в зависимости языков.
|
||||
@ -100,13 +107,13 @@ class Hyphenator:
|
||||
if len(word) <= self.max_unhyphenated_len or not any(self._is_vow(c) for c in word):
|
||||
# Если слово короткое или не содержит гласных, перенос не нужен
|
||||
return word
|
||||
print("слово:", word, " // mode:", self.mode, " // langs:", self.langs)
|
||||
logger.debug(f"Hyphenator: word: `{word}` // langs: {self.langs} // mode: {self.mode} // max_unhyphenated_len: {self.max_unhyphenated_len} // min_tail_len: {self.min_chars_per_part}")
|
||||
# 2. ОБНАРУЖЕНИЕ ЯЗЫКА И ПОДКЛЮЧЕНИЕ ЯЗЫКОВОЙ ЛОГИКИ
|
||||
# Поиск вхождения букв строки (слова) через `frozenset` -- O(1). Это быстрее регулярного выражения -- O(n)
|
||||
# 2.1. Проверяем RU и RU_OLD (правила одинаковые, но разные наборы букв)
|
||||
if (LANG_RU in self.langs or LANG_RU_OLD in self.langs) and frozenset(word.upper()) <= self._ru_alphabet_upper:
|
||||
# Пользователь подключил русскую логику, и слово содержит только русские буквы
|
||||
print(f"#### Applying Russian rules to: {word}")
|
||||
logger.debug(f"`{word}` -- use `{LANG_RU}` or `{LANG_RU_OLD}` rules")
|
||||
# Поиск допустимой позиции для переноса около заданного индекса
|
||||
def find_hyphen_point_ru(word_segment: str, start_idx: int) -> int:
|
||||
vow_indices = [i for i, char_w in enumerate(word_segment) if self._is_vow(char_w)]
|
||||
@ -153,7 +160,7 @@ class Hyphenator:
|
||||
# 2.2. Проверяем EN
|
||||
elif LANG_EN in self.langs and frozenset(word.upper()) <= self._en_alphabet_upper:
|
||||
# Пользователь подключил английскую логику, и слово содержит только английские буквы
|
||||
print(f"#### Applying English rules to: {word}") # Для отладки
|
||||
logger.debug(f"`{word}` -- use `{LANG_EN}` rules")
|
||||
# --- Начало логики для английского языка (заглушка) ---
|
||||
# ПРИМЕЧАНИЕ: Это очень упрощенная заглушка.
|
||||
def find_hyphen_point_en(word_segment: str) -> int:
|
||||
@ -175,7 +182,7 @@ class Hyphenator:
|
||||
return split_word_en(word)
|
||||
else:
|
||||
# кстати "слова" в которых есть пробелы или другие разделители, тоже попадают сюда
|
||||
print("!!!!ФИГНЯ")
|
||||
logger.debug(f"`{word}` -- use `UNDEFINE` rules")
|
||||
return word
|
||||
|
||||
|
||||
@ -195,11 +202,8 @@ class Hyphenator:
|
||||
hyphenated_word = self.hyp_in_word(word_to_process)
|
||||
|
||||
# ============= Для отладки (слова в которых появились переносы) ==================
|
||||
print(f"hyp_in_text: '{word_to_process}'", end="")
|
||||
if word_to_process != hyphenated_word:
|
||||
print(f" -> '{hyphenated_word}'")
|
||||
else:
|
||||
print(" (no change)")
|
||||
logger.debug(f"hyp_in_text: '{word_to_process}' -> '{hyphenated_word}'")
|
||||
|
||||
return hyphenated_word
|
||||
|
||||
|
121
etpgrf/logger.py
Normal file
121
etpgrf/logger.py
Normal file
@ -0,0 +1,121 @@
|
||||
# etpgrf/logging_settings.py
|
||||
import logging
|
||||
from etpgrf.defaults import etpgrf_settings # Импортируем наш объект настроек по умолчанию
|
||||
|
||||
# --- Корневой логгер для всей библиотеки etpgrf ---
|
||||
# Имя логгера "etpgrf" позволит пользователям настраивать
|
||||
# логирование для всех частей библиотеки.
|
||||
# Например, logging.getLogger("etpgrf").setLevel(logging.DEBUG)
|
||||
# или logging.getLogger("etpgrf.hyphenation").setLevel(logging.INFO)
|
||||
_etpgrf_init_logger = logging.getLogger("etpgrf")
|
||||
|
||||
|
||||
# --- Настройка корневого логгера ---
|
||||
def setup_library_logging():
|
||||
"""
|
||||
Настраивает корневой логгер для библиотеки etpgrf.
|
||||
Эту функцию следует вызывать один раз (например, при импорте
|
||||
основного модуля библиотеки или при первом обращении к логгеру).
|
||||
"""
|
||||
# Проверяем инициализацию хандлеров логера, чтобы случайно не добавлять хендлеры многократно
|
||||
if not _etpgrf_init_logger.hasHandlers():
|
||||
log_level_to_set = logging.WARNING # Значение по умолчанию
|
||||
log_format_to_set = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' # Формат по умолчанию
|
||||
|
||||
fin_message: str | None = None
|
||||
if hasattr(etpgrf_settings, 'logging_settings'):
|
||||
if hasattr(etpgrf_settings.logging_settings, 'LEVEL'):
|
||||
log_level_to_set = etpgrf_settings.logging_settings.LEVEL
|
||||
if hasattr(etpgrf_settings.logging_settings, 'FORMAT') and etpgrf_settings.logging_settings.FORMAT:
|
||||
log_format_to_set = etpgrf_settings.logging_settings.FORMAT
|
||||
else:
|
||||
# Этого не должно происходить, если defaults.py настроен правильно
|
||||
fin_message= "ПРЕДУПРЕЖДЕНИЕ: etpgrf_settings.logging_settings не найдены при начальной настройке логгера."
|
||||
|
||||
_etpgrf_init_logger.setLevel(log_level_to_set) # Устанавливаем уровень логирования
|
||||
console_handler = logging.StreamHandler() # Создаем хендлер вывода в консоль
|
||||
console_handler.setLevel(log_level_to_set) # Уровень для хендлера тоже
|
||||
formatter = logging.Formatter(log_format_to_set) # Создаем форматтер для вывода
|
||||
console_handler.setFormatter(formatter) # Устанавливаем форматтер для хендлера
|
||||
_etpgrf_init_logger.addHandler(console_handler) # Добавляем хендлер в логгер
|
||||
if fin_message is not None:
|
||||
# Если есть сообщение об отсутствии настроек в `etpgrf_settings`, выводим его
|
||||
_etpgrf_init_logger.warning(fin_message)
|
||||
_etpgrf_init_logger.debug(f"Корневой логгер 'etpgrf' инициализирован."
|
||||
f" Уровень: {logging.getLevelName(_etpgrf_init_logger.getEffectiveLevel())}")
|
||||
|
||||
|
||||
# --- Динамическое изменение уровня логирования ---
|
||||
def update_etpgrf_log_level_from_settings():
|
||||
"""
|
||||
Обновляет уровень логирования для корневого логгера `etpgrf` и его
|
||||
обработчиков, читая значение из `etpgrf_settings.logging_settings.LEVEL`.
|
||||
"""
|
||||
# Проверяем, что настройки логирования и уровень существуют в `defaults.etpgrf_settings`
|
||||
if not hasattr(etpgrf_settings, 'logging_settings') or \
|
||||
not hasattr(etpgrf_settings.logging_settings, 'LEVEL'):
|
||||
_etpgrf_init_logger.warning("Невозможно обновить уровень логгера: `etpgrf_settings.logging_settings.LEVEL`"
|
||||
" не найден.")
|
||||
return
|
||||
|
||||
new_level = etpgrf_settings.logging_settings.LEVEL
|
||||
_etpgrf_init_logger.setLevel(new_level)
|
||||
for handler in _etpgrf_init_logger.handlers:
|
||||
handler.setLevel(new_level) # Устанавливаем уровень для каждого хендлера
|
||||
|
||||
_etpgrf_init_logger.info(f"Уровень логирования `etpgrf` динамически обновлен на:"
|
||||
f" {logging.getLevelName(_etpgrf_init_logger.getEffectiveLevel())}")
|
||||
|
||||
|
||||
# --- Динамическое изменение формата логирования ---
|
||||
def update_etpgrf_log_format_from_settings():
|
||||
"""
|
||||
Обновляет формат логирования для обработчиков корневого логгера etpgrf,
|
||||
читая значение из etpgrf_settings.logging_settings.FORMAT.
|
||||
"""
|
||||
if not hasattr(etpgrf_settings, 'logging_settings') or \
|
||||
not hasattr(etpgrf_settings.logging_settings, 'FORMAT') or \
|
||||
not etpgrf_settings.logging_settings.FORMAT:
|
||||
_etpgrf_init_logger.warning("Невозможно обновить формат логгера: `etpgrf_settings.logging_settings.FORMAT`"
|
||||
" не найден или пуст.")
|
||||
return
|
||||
|
||||
new_format_string = etpgrf_settings.logging_settings.FORMAT
|
||||
new_formatter = logging.Formatter(new_format_string)
|
||||
|
||||
for handler in _etpgrf_init_logger.handlers:
|
||||
handler.setFormatter(new_formatter) # Применяем новый форматтер к каждому хендлеру
|
||||
|
||||
_etpgrf_init_logger.info(f"Формат логирования для 'etpgrf' динамически обновлен на: '{new_format_string}'")
|
||||
|
||||
|
||||
# --- Инициализация логгера при первом импорте ---
|
||||
setup_library_logging()
|
||||
|
||||
|
||||
# --- Предоставление логгеров для модулей ---
|
||||
def get_logger(name: str) -> logging.Logger:
|
||||
"""
|
||||
Возвращает логгер для указанного имени.
|
||||
Обычно используется как logging.getLogger(__name__) в модулях.
|
||||
Имя будет дочерним по отношению к "etpgrf", например, "etpgrf.hyphenation".
|
||||
"""
|
||||
# Убедимся, что имя логгера начинается с "etpgrf." для правильной иерархии,
|
||||
# если только это не сам корневой логгер.
|
||||
if not name.startswith("etpgrf") and name != "etpgrf":
|
||||
# Это может быть __name__ из модуля верхнего уровня, использующего библиотеку. В этом случае мы не хотим
|
||||
# делать его дочерним от "etpgrf" насильно. Просто вернем логгер с именем...
|
||||
# Либо можно настроить, что все логгеры, получаемые через эту функцию, должны быть частью иерархии "etpgrf"...
|
||||
# Для простоты оставим так:
|
||||
pass # logging_settings = logging.getLogger(name)
|
||||
# Более правильный подход для модулей ВНУТРИ библиотеки etpgrf: они должны вызывать `logging.getLogger(__name__)`
|
||||
# напрямую. Тогда эта функция `get_logger()` может быть и не нужна, если модули ничего не делают кроме:
|
||||
# import logging
|
||||
# logging_settings = logging.getLogger(__name__)
|
||||
#
|
||||
# Однако, если нужно централизованно получать логгеры, можно сделать, чтобы `get_logger()` всегда возвращал
|
||||
# дочерний логгер:
|
||||
# if not name.startswith("etpgrf."):
|
||||
# name = f"etpgrf.{name}"
|
||||
return logging.getLogger(name)
|
||||
|
@ -1,6 +1,9 @@
|
||||
from etpgrf.comutil import parse_and_validate_mode, parse_and_validate_langs
|
||||
|
||||
from etpgrf.hyphenation import Hyphenator
|
||||
import logging
|
||||
|
||||
# --- Настройки логирования ---
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# --- Основной класс Typographer ---
|
||||
@ -17,7 +20,6 @@ class Typographer:
|
||||
self.langs: frozenset[str] = parse_and_validate_langs(langs)
|
||||
# B. --- Обработка и валидация параметра mode ---
|
||||
self.mode: str = parse_and_validate_mode(mode)
|
||||
print("Typographer: langs:", self.langs, "// mode:", self.mode) # Для отладки
|
||||
# C. --- Инициализация правила переноса ---
|
||||
# Предпосылка: если вызвали типограф, значит, мы хотим обрабатывать текст и переносы тоже нужно расставлять.
|
||||
# А для специальных случаев, когда переносы не нужны, пусть не ленятся и делают `hyphenation=False`.
|
||||
@ -35,6 +37,7 @@ class Typographer:
|
||||
# 4. Если hyphenation что-то неведомое, то игнорируем его и правило переноса выключено
|
||||
self.hyphenation = None
|
||||
# D. --- Конфигурация других правил---
|
||||
logger.debug(f"Typographer `__init__`: langs: {self.langs}, mode: {self.mode}, hyphenation: {self.hyphenation}")
|
||||
|
||||
|
||||
# Конвейер для обработки текста
|
||||
|
7
main.py
7
main.py
@ -1,11 +1,14 @@
|
||||
import etpgrf
|
||||
|
||||
import logging
|
||||
|
||||
if __name__ == '__main__':
|
||||
# --- Пример использования ---
|
||||
print("\n--- Пример использования класса---\n")
|
||||
|
||||
etpgrf.defaults.etpgrf_settings.hyphenation.MAX_UNHYPHENATED_LEN = 8
|
||||
etpgrf.defaults.etpgrf_settings.logging_settings.LEVEL = logging.DEBUG
|
||||
etpgrf.logger.update_etpgrf_log_level_from_settings() # Обновляем уровень логирования из настроек
|
||||
etpgrf.defaults.etpgrf_settings.logging_settings.FORMAT = '%(asctime)s - %(name)s = %(levelname)s - %(message)s'
|
||||
etpgrf.logger.update_etpgrf_log_format_from_settings() # Обновляем формат логирования из настроек
|
||||
|
||||
# Определяем пользовательские правила переносов
|
||||
hyphen_settings = etpgrf.Hyphenator(langs='ru', max_unhyphenated_len=8)
|
||||
|
Loading…
x
Reference in New Issue
Block a user