[AI]
Поддержка плагинов
This commit is contained in:
@@ -15,9 +15,10 @@ def convert(
|
|||||||
style_config: Path = typer.Option("resources/style_config.yaml", "--style", "-s", help="Файл стилей"),
|
style_config: Path = typer.Option("resources/style_config.yaml", "--style", "-s", help="Файл стилей"),
|
||||||
template: Optional[Path] = typer.Option(None, "--template", "-t", help="Шаблон .dotx"),
|
template: Optional[Path] = typer.Option(None, "--template", "-t", help="Шаблон .dotx"),
|
||||||
theme: Optional[str] = typer.Option(None, "--theme", "-T", help="Название темы (gost, academic...)"),
|
theme: Optional[str] = typer.Option(None, "--theme", "-T", help="Название темы (gost, academic...)"),
|
||||||
|
plugins_dir: Optional[Path] = typer.Option(None, "--plugins", "-p", help="Папка с плагинами"),
|
||||||
verbose: bool = typer.Option(False, "--verbose", "-v", help="Включить отладочные сообщения"),
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Включить отладочные сообщения"),
|
||||||
):
|
):
|
||||||
log_level = logging.DEBUG if verbose else logging.INFO
|
log_level = logging.DEBUG if verbose else logging.INFO
|
||||||
logging.basicConfig(level=log_level, format='%(levelname)s: %(message)s')
|
logging.basicConfig(level=log_level, format='%(levelname)s: %(message)s')
|
||||||
|
|
||||||
process_document(input_dir, output_dir, style_config, template, theme)
|
process_document(input_dir, output_dir, style_config, template, theme, plugins_dir)
|
||||||
@@ -4,12 +4,18 @@ from typing import Optional
|
|||||||
from docx import Document
|
from docx import Document
|
||||||
from .style_registry import StyleRegistry
|
from .style_registry import StyleRegistry
|
||||||
from .renderer import render_markdown_to_docx
|
from .renderer import render_markdown_to_docx
|
||||||
|
from .plugin_loader import load_plugins_from_path
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def process_document(input_dir: Path, output_dir: Path, style_config_path: Path, template_path: Optional[Path] = None, theme_name: Optional[str] = None):
|
def process_document(
|
||||||
|
input_dir: Path, output_dir: Path, style_config_path: Path,
|
||||||
|
template_path: Optional[Path] = None, theme_name: Optional[str] = None,
|
||||||
|
plugins_dir: Optional[Path] = None
|
||||||
|
):
|
||||||
|
if plugins_dir and plugins_dir.exists():
|
||||||
|
load_plugins_from_path(plugins_dir)
|
||||||
if theme_name:
|
if theme_name:
|
||||||
theme_path = Path("resources/themes") / f"{theme_name}.yaml"
|
theme_path = Path("resources/themes") / f"{theme_name}.yaml"
|
||||||
if theme_path.exists():
|
if theme_path.exists():
|
||||||
|
|||||||
16
src/core/plugin_loader.py
Normal file
16
src/core/plugin_loader.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import importlib.util
|
||||||
|
from pathlib import Path
|
||||||
|
from ..handlers import register_handler
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def load_plugins_from_path(plugins_dir: Path):
|
||||||
|
"""Загружает все .py файлы из папки как плагины."""
|
||||||
|
for py_file in plugins_dir.glob("*.py"):
|
||||||
|
spec = importlib.util.spec_from_file_location(py_file.stem, py_file)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
# Теперь все @register_handler в module выполнены
|
||||||
|
logger.info(f"Загружен плагин: {py_file.name}")
|
||||||
26
tests/test_plugins.py
Normal file
26
tests/test_plugins.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_plugins():
|
||||||
|
# Создаём плагин
|
||||||
|
plugin_dir = Path("tests/plugins")
|
||||||
|
plugin_dir.mkdir(exist_ok=True)
|
||||||
|
plugin_path = plugin_dir / "test_plugin.py"
|
||||||
|
plugin_path.write_text("""
|
||||||
|
from src.handlers import register_handler
|
||||||
|
|
||||||
|
@register_handler("admonition")
|
||||||
|
def handle_admonition(node, doc, images_dir, style_reg):
|
||||||
|
p = doc.add_paragraph("Тест плагина")
|
||||||
|
""", encoding="utf-8")
|
||||||
|
|
||||||
|
# Загружаем
|
||||||
|
from src.core.plugin_loader import load_plugins_from_path
|
||||||
|
load_plugins_from_path(plugin_dir)
|
||||||
|
|
||||||
|
# Проверяем, что обработчик зарегистрирован
|
||||||
|
from src.handlers import get_handler
|
||||||
|
handler = get_handler("admonition")
|
||||||
|
assert handler is not None
|
||||||
|
|
||||||
|
plugin_path.unlink(missing_ok=True)
|
||||||
Reference in New Issue
Block a user