Saltar a contenido

Empaquetado e instalación

Un plugin de Python es una carpeta con un plugin.json y un módulo de Python. Puedes instalar uno de dos formas: empaquetarlo como un archivo .mteplugin y usar el instalador del editor (recomendado), o dejar la carpeta a mano en un directorio de plugins.

Empieza por la plantilla

En el repositorio hay un punto de partida listo para copiar en Python/templates/plugin-template-python/: tres archivos (plugin.json, main.py, README.md) más un CLAUDE.md orientado a Claude. Renombra la carpeta con el nombre corto de tu plugin, edita cuatro campos de plugin.json y empieza a escribir register(ctx). El SDK instalado incluye la misma plantilla en share/MTEPluginSDK/plugin-template-python/.

Disposición de la carpeta del plugin

hello/
├── plugin.json      # required
└── main.py          # required; module name from plugin.json.module

Todo lo que el plugin necesita debe estar dentro de esta carpeta. Las subimportaciones funcionan, pero deben ser planas: los nombres de module con puntos en plugin.json son una extensión futura.

Puedes añadir archivos adicionales (README, LICENSE): el anfitrión ignora lo que no reconoce.

Paquetes .mteplugin (recomendado)

Comprime los archivos del plugin y dale al archivo comprimido la extensión .mteplugin (un .zip sin más también funciona). Se aceptan ambas formas:

hello.mteplugin              hello.mteplugin
├── plugin.json              └── hello-1.0.0/        # any folder name
└── main.py                      ├── plugin.json
                                 └── main.py

La carpeta envolvente única —el resultado natural de comprimir una carpeta— se normaliza y desaparece: el plugin se instala siempre en <Plugins>/<id>/, identificado por el id del manifiesto, nunca por el nombre de carpeta del archivo comprimido. Por eso también instalar la versión 2 de un plugin sustituye a la versión 1 en lugar de ponerse a su lado.

Instálalo mediante Preferencias → Complementos → Instalar un complemento... y reinicia el editor.

Instala solo paquetes en los que confíes

El instalador comprueba que un paquete sea estructuralmente correcto (ver más abajo); eso no hace que sea seguro ejecutar un plugin en el que no confías. Una vez cargado, un plugin se ejecuta con el mismo acceso a tus archivos, ajustes y red que el editor, y no está aislado. El sondeo estático de register(...) no ejecuta ningún código en el momento de la instalación, pero el código del plugin sí se ejecuta en el siguiente arranque. Trata un .mteplugin (y cualquier archivo de configuración o JSON que distribuya) como un programa desconocido: instálalo solo desde una fuente en la que confíes. Consulta Plugins para la advertencia completa.

Qué valida el instalador

El paquete se valida por completo contra una copia desechable antes de tocar nada en el disco: un paquete defectuoso nunca puede perturbar una instalación existente.

  1. plugin.json se analiza correctamente, tiene un id, su apiVersion coincide con la del editor, entry es "python" y module está presente.
  2. El listado del archivo comprimido es seguro: sin rutas de entrada absolutas ni con .., como mucho 10 000 entradas, como mucho 256 MiB descomprimidos y al menos un archivo .py.
  3. Tras extraerlo a un directorio temporal, el <module>.py declarado existe y declara un def register(...) de nivel superior, el mismo sondeo estático que usa la detección. No se ejecuta ningún código de Python en el momento de la instalación.

Cualquier fallo produce un diálogo de error legible y deja intactos los plugins del editor.

Actualizar y desinstalar

  • Instalar un paquete cuyo id ya está instalado lo sustituye. Si ese plugin está cargado en ese momento, la actualización se prepara y se aplica en el siguiente arranque.
  • Desinstala desde la misma página de Preferencias; la eliminación también ocurre en el siguiente arranque, cuando no hay nada cargado.
  • Los plugins incluidos (integrados) no se pueden anular con un paquete instalado que tenga el mismo id.

Instalación a mano (dejar la carpeta)

El editor detecta plugins en dos directorios en cada arranque:

  1. Incluidos — junto al ejecutable, en <exe-dir>/Plugins/. Aquí viven los plugins integrados (p. ej. HelloPython).
  2. Usuario — por usuario, con permiso de escritura. En Windows es %LOCALAPPDATA%/MTE/Plugins/, en macOS ~/Library/Application Support/MTE/Plugins/ y en Linux ~/.local/share/MTE/Plugins/.

Se examinan ambos directorios. Si el mismo id aparece en los dos, gana la primera aparición (los incluidos tienen precedencia). Reinicia el editor para que recoja las carpetas nuevas: la recarga en caliente no está admitida.

Dos disposiciones aceptables

El examen busca plugin.json bien directamente en el directorio de plugins (suelto), bien dentro de un nivel de subdirectorio inmediato (carpeta por plugin):

Plugins/
├── plugin.json         # loose -- one plugin at the top level
├── main.py
└── hello/              # per-plugin folder -- one plugin
    ├── plugin.json
    └── main.py

La carpeta por plugin es la disposición recomendada; es la forma que produce el instalador.

Dependencias (pyRequires)

plugin.json puede declarar requisitos de pip como una matriz en línea:

"pyRequires": ["requests>=2.31"]

En el primer arranque del plugin, el editor aprovisiona un entorno virtual en <AppLocalData>/PluginVenv/<id>/ (python -m venv + pip install, lo que requiere acceso a la red esa única vez) y ejecuta el trabajador del plugin bajo el intérprete de ese entorno. Los arranques posteriores lo reutilizan; cambiar pyRequires vuelve a aprovisionarlo automáticamente (el entorno lleva un sello de los requisitos para los que se construyó).

  • Los fallos de aprovisionamiento (sin red, un requisito mal escrito) dejan el plugin listado pero no cargado, con el error de pip en el registro; el siguiente arranque lo reintenta.
  • Desinstalar un plugin elimina su entorno virtual junto con la carpeta del plugin (un entorno virtual es dato derivado: se reconstruye a partir de pyRequires si alguna vez lo reinstalas).

Máquinas sin conexión o restringidas

Distribuye un entorno virtual preconstruido dentro del paquete, como una carpeta venv/ en la raíz del plugin. Cuando existe, gana sobre todo lo demás: pip no se ejecuta nunca. Constrúyelo en una máquina con el mismo sistema operativo y la misma arquitectura, porque los entornos virtuales no son portátiles entre plataformas.

Incluir el código (dependencias pequeñas de Python puro)

Para un único módulo de Python puro, incluirlo dentro de la carpeta del plugin sigue funcionando y evita por completo la maquinaria del entorno virtual:

# main.py
import os, sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "vendor"))

import your_dep

Permisos declarados

plugin.json puede llevar una matriz permissions (p. ej. ["network"]). La página de Preferencias de Plugins la muestra en una columna Permisos de solo lectura, para que los usuarios vean qué declara un plugin sobre sí mismo. Es una declaración, no una imposición: el aislamiento es trabajo futuro.

Dónde van los datos con permiso de escritura

El directorio de plugins contiene código. Los datos de tiempo de ejecución (cachés, configuración por usuario, índices) van a un directorio de datos aparte por plugin que gestiona el anfitrión; ctx.data_dir() devuelve su ruta absoluta. NO escribas en el directorio de plugins desde tu .py en tiempo de ejecución: la desinstalación elimina toda la carpeta <Plugins>/<id>/, y las escrituras hechas en otros puntos del árbol de plugins nunca se limpian.

Desplegar en otras máquinas

Distribuye el archivo .mteplugin: es autocontenido y se valida en el extremo receptor. Un zip, un tarball o un clon de git de la carpeta en el directorio de plugins por usuario también funcionan.

Activar y desactivar

La página de Preferencias de Plugins lista todos los plugins detectados (nativos y de Python, juntos) con las mismas columnas de origen y estado. Desactivar un plugin lo mantiene listado pero impide que su fábrica se invoque al arrancar: no se lanza ningún trabajador. Vuelve a activarlo y reinicia para recuperarlo.