Empaquetage et installation¶
Une extension Python est un dossier avec un plugin.json et un module
Python. Deux façons de l'installer : l'empaqueter en archive
.mteplugin et passer par l'installeur de l'éditeur (recommandé), ou
déposer le dossier à la main dans un répertoire d'extensions.
Partez du modèle
Un point de départ prêt à copier vit dans le dépôt à
Python/templates/plugin-template-python/ — trois fichiers
(plugin.json, main.py, README.md) plus un CLAUDE.md destiné à
Claude. Renommez le dossier avec le nom court de votre extension,
modifiez quatre champs de plugin.json et commencez à écrire
register(ctx). Le SDK installé livre le même modèle sous
share/MTEPluginSDK/plugin-template-python/.
Structure du dossier d'extension¶
Tout ce dont l'extension a besoin doit être dans ce dossier. Les
sous-imports fonctionnent mais doivent rester plats — les noms module à
points dans plugin.json sont une extension future.
Vous pouvez ajouter d'autres fichiers (README, LICENSE) — l'hôte ignore ce qu'il ne reconnaît pas.
Paquets .mteplugin (recommandé)¶
Zippez les fichiers de l'extension et donnez à l'archive l'extension
.mteplugin (un simple .zip marche aussi). Les deux formes sont
acceptées :
hello.mteplugin hello.mteplugin
├── plugin.json └── hello-1.0.0/ # any folder name
└── main.py ├── plugin.json
└── main.py
Le dossier enveloppant unique — résultat naturel du zippage d'un dossier —
est normalisé : l'extension s'installe toujours dans <Plugins>/<id>/,
indexée par l'id du manifeste, jamais par le nom de dossier de
l'archive. C'est aussi pourquoi installer la version 2 d'une extension
remplace la version 1 au lieu de s'installer à côté.
Installez via Préférences → Extensions → Installer… puis redémarrez l'éditeur.
N'installez que des paquets de confiance
L'installeur vérifie qu'un paquet est structurellement sain (voir
plus bas) — il ne rend pas sûre une extension non fiable. Une fois
chargée, une extension s'exécute avec le même accès à vos fichiers,
paramètres et réseau que l'éditeur, et n'est pas sandboxée. La
sonde statique register(...) n'exécute aucun code à l'installation,
mais le code de l'extension s'exécute bel et bien au prochain
lancement. Traitez un .mteplugin (et tout fichier de configuration ou
JSON livré) comme un programme inconnu : n'installez que depuis une
source de confiance. Voir Extensions pour
l'avertissement complet.
Ce que l'installeur valide¶
Le paquet est entièrement validé sur une copie jetable avant de toucher quoi que ce soit sur disque — un mauvais paquet ne peut jamais perturber une installation existante :
plugin.jsons'analyse, a unid,apiVersioncorrespond à l'éditeur,entryvaut"python"etmoduleest présent.- La liste de l'archive est sûre : pas de chemins absolus ni d'entrées
.., au plus 10 000 entrées, au plus 256 Mio décompressé, et au moins un fichier.py. - Après extraction vers un répertoire de travail, le
<module>.pydéclaré existe et déclare undef register(...)au niveau supérieur — la même sonde statique que la découverte. Aucun code Python n'est exécuté à l'installation.
Tout échec produit un message d'erreur lisible et laisse les extensions de l'éditeur intactes.
Mettre à jour et désinstaller¶
- Installer un paquet dont l'
idest déjà installé le remplace. Si cette extension est chargée, la mise à jour est mise en attente et appliquée au prochain lancement. - Désinstallez depuis la même page de Préférences ; la suppression a lieu elle aussi au prochain lancement, quand rien n'est chargé.
- Les extensions livrées (intégrées) ne peuvent pas être remplacées par un
paquet installé de même
id.
Installation à la main (dépôt de dossier)¶
L'éditeur découvre les extensions dans deux répertoires à chaque démarrage :
- Livré — à côté de l'exécutable, dans
<exe-dir>/Plugins/. Les extensions intégrées (p. ex.HelloPython) vivent ici. - Utilisateur — par utilisateur, accessible en écriture. Sous
Windows :
%LOCALAPPDATA%/MTE/Plugins/, sous macOS :~/Library/Application Support/MTE/Plugins/, sous Linux :~/.local/share/MTE/Plugins/.
Les deux répertoires sont scannés. Si le même id apparaît dans les deux,
la première occurrence gagne (le livré a priorité). Redémarrez l'éditeur
pour prendre en compte de nouveaux dossiers — le rechargement à chaud
n'est pas pris en charge.
Deux structures acceptées¶
Le scan cherche plugin.json soit directement dans le répertoire
d'extensions (en vrac), soit dans un niveau de sous-dossier immédiat
(dossier par extension) :
Plugins/
├── plugin.json # loose -- one plugin at the top level
├── main.py
└── hello/ # per-plugin folder -- one plugin
├── plugin.json
└── main.py
Le dossier par extension est la structure recommandée ; c'est la forme que produit l'installeur.
Dépendances (pyRequires)¶
plugin.json peut déclarer des exigences pip en tableau inline :
Au premier lancement de l'extension, l'éditeur provisionne un
environnement virtuel dans <AppLocalData>/PluginVenv/<id>/
(python -m venv + pip install, qui a besoin du réseau cette fois-là) et
exécute le worker de l'extension sous l'interpréteur de ce venv. Les
lancements suivants le réutilisent ; changer pyRequires reprovisionne
automatiquement (le venv porte une empreinte des exigences pour lesquelles
il a été construit).
- Les échecs de provisionnement (pas de réseau, une exigence mal écrite) laissent l'extension listée mais pas chargée, avec l'erreur pip dans le journal ; le lancement suivant réessaie.
- Désinstaller une extension supprime son venv avec le dossier de
l'extension (un venv est une donnée dérivée — il se reconstruit depuis
pyRequiresen cas de réinstallation).
Machines hors ligne / verrouillées¶
Livrez un venv pré-construit dans le paquet, comme dossier venv/ à la
racine de l'extension. Quand il est présent, il l'emporte sur tout — pip ne
s'exécute jamais. Construisez-le sur une machine de même OS/architecture,
car les venvs ne sont pas portables entre plateformes.
Vendoring (petites dépendances pur Python)¶
Pour un unique module pur Python, le vendoring dans le dossier de l'extension fonctionne toujours et évite entièrement la machinerie venv :
# main.py
import os, sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "vendor"))
import your_dep
Permissions déclarées¶
plugin.json peut porter un tableau permissions (p. ex. ["network"]).
La page de Préférences des Extensions l'affiche dans une colonne
Permissions en lecture seule, pour que les utilisateurs voient ce
qu'une extension déclare d'elle-même. C'est une déclaration, pas une
contrainte — le sandboxing est un travail futur.
Où vont les données inscriptibles¶
Le répertoire d'extensions contient du code. Les données d'exécution
(caches, configuration par utilisateur, index) vont dans un répertoire de
données par extension géré par l'hôte — ctx.data_dir() renvoie son
chemin absolu. N'écrivez PAS dans le répertoire d'extensions depuis votre
.py à l'exécution ; la désinstallation supprime tout le dossier
<Plugins>/<id>/, et les écritures faites ailleurs dans l'arbre des
extensions ne sont jamais nettoyées.
Déployer sur d'autres machines¶
Expédiez le fichier .mteplugin — il est autonome et validé à la
réception. Un zip/tarball/git-clone du dossier dans le répertoire
d'extensions par utilisateur fonctionne aussi.
Activer / désactiver¶
La page de Préférences des Extensions liste chaque extension découverte (natives + Python ensemble) avec les mêmes colonnes d'origine/état. Désactiver une extension la garde listée mais empêche l'appel de sa fabrique au démarrage — aucun worker n'est lancé. Réactivez et redémarrez pour la retrouver.