Aller au contenu

Décorateur de Notification Personnalisé

Apprise prend en charge des gestionnaires de notification légers, basés sur des fichiers via le décorateur @notify(). C’est idéal lorsque vous voulez une intégration rapide sans créer puis publier un plugin Apprise complet.

Le système de décorateurs fonctionne en important un module Python et en collectant toute fonction enregistrée avec @notify(). Ces fonctions sont ensuite exposées comme des schémas Apprise.

Utilisez un gestionnaire basé sur décorateur lorsque :

  • vous avez besoin d’une intégration rapide et locale dans un environnement personnel ou maîtrisé ;
  • vous voulez relier Apprise à une automatisation locale, à des scripts ou à un service privé ;
  • vous ne voulez pas maintenir le cycle de vie complet d’un plugin (tests, packaging, cadence de publication).

Évitez cette approche lorsque :

  • vous voulez intégrer le service directement dans Apprise (contribution upstream) ;
  • vous avez besoin d’un parsing strict, de modèles, de reconstruction native d’URL, de batch ou d’une logique de retry robuste ;
  • vous avez besoin d’une stabilité à long terme, d’une distribution publique ou d’un usage tiers.

Le système de décorateur nécessite d’importer un module Python pour découvrir les fonctions décorées. Importer un module exécute du code au moment de l’import.

Cela signifie :

  • tout code défini à la portée du module sera exécuté, pas seulement la fonction décorée ;
  • tous les imports internes au module seront exécutés ;
  • des effets de bord, accès fichiers, appels réseau ou sous-processus peuvent se produire au chargement.

N’utilisez des gestionnaires basés sur décorateur qu’avec du code de confiance dans des environnements contrôlés. Ne pointez pas Apprise vers un emplacement partagé ou non fiable sur le système de fichiers.

Voici la règle pratique.

CapacitéDécorateur @notify()Plugin Apprise complet
Temps d’implémentationMinutesHeures à jours
Packaging et distributionFichier localPyPI, paquets système, contribution amont
Modèles d’URL et validationMinimalPatterns intégrés (jetons, args et parsing strict)
Confidentialité dans url()ManuelStandardisée (PrivacyMode.Secret)
Reconstruction native d’URLRareAttendue quand c’est faisable
Support des pièces jointesÀ implémenter vous-mêmePatterns intégrés (AppriseAttachment)
Limitation de débit / retriesÀ implémenter vous-mêmeStandardisé (throttle(), helpers de requêtes)
TestabilitéAd hocPatterns intégrés (AppriseURLTester, erreurs standardisées)
Idéal pourAutomatisation privéeServices amont et usage public

Si votre gestionnaire a vocation à être réutilisé, devient critique pour le métier ou requiert un parsing d’URL solide, un vrai plugin Apprise est généralement plus adapté.

Au minimum, vous devez définir un schéma unique et une fonction Python.

from apprise.decorators import notify
# Associe 'foobar://' à cette fonction et écrit sur stdout
@notify(on="foobar")
def my_wrapper(body, title, notify_type, *args, **kwargs):
print(f"{notify_type}: {title} - {body}")

Une fois chargé, Apprise peut déclencher cette fonction avec :

Fenêtre de terminal
apprise -b "Hello world" foobar://

Une fonction décorée doit renvoyer :

  • True pour indiquer un succès ;
  • False pour indiquer un échec ;
  • None (ou aucun return), ce qui est traité comme un succès.

Les échecs remontent à Apprise et affectent le statut global de la notification.

Votre fonction wrapper peut accepter les paramètres suivants.

ParamètreRequisDescription
bodyOuiCorps de la notification
titleNonTitre de la notification
notify_typeNonL’une des valeurs info, success, warning, failure
body_formatNontext, html ou markdown
metaNonMétadonnées d’URL analysées et fusionnées
attachNonListe d’objets AppriseAttachment
Voir Pièces jointes pour lire, valider et transmettre des fichiers depuis un décorateur.
*argsOuiRequis pour la compatibilité future
**kwargsOuiRequis pour la compatibilité future

Incluez toujours *args et **kwargs afin de rester compatible avec les futures versions d’Apprise.

Un wrapper minimal peut ressembler à ceci :

from apprise.decorators import notify
@notify(on="foobar")
def my_wrapper(body, *args, **kwargs):
print(body)

Le paramètre meta fournit une vue entièrement analysée et fusionnée de :

  1. l’URL de déclaration du décorateur ;
  2. l’URL d’initialisation fournie par l’utilisateur.

Exemple de structure :

{
"schema": "foobar",
"url": "foobar://user:pass@host:80/path?key=value",
"host": "host",
"user": "user",
"password": "pass",
"port": 80,
"path": "/",
"fullpath": "/path",
"query": "key=value",
"qsd": {"key": "value"},
"asset": AppriseAsset(),
"tag": set(),
}

Seuls les champs présents dans l’URL sont inclus. Au minimum, schema, url, asset et tag sont toujours présents.

Le décorateur peut précharger des valeurs par défaut en spécifiant une URL complète.

@notify(on="foobar://localhost:234?notify_on_complete=0")
def my_wrapper(body, meta, *args, **kwargs):
pass

Les utilisateurs peuvent surcharger ces valeurs à l’exécution :

Fenêtre de terminal
apprise -b "override" foobar://example.com?notify_on_complete=1

Résultat fusionné :

{
"schema": "foobar",
"url": "foobar://example.com:234?notify_on_complete=1",
"host": "example.com",
"port": 234,
"qsd": {
"notify_on_complete": "1"
}
}

Cet exemple ajoute une ligne horodatée à la fin d’un fichier lorsqu’il est appelé. Utilisation : demo://

apprise/plugins/mylogger.py
from apprise.decorators import notify
import logging
@notify(on="demo")
def my_wrapper(body, title, notify_type, *args, **kwargs):
# Configurer le système de logs
logging.basicConfig(
filename='/tmp/my-demo.log',
level=logging.DEBUG, filemode='w',
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# Créer une instance de logger
logger = logging.getLogger(__name__)
# Journaliser un message simple au niveau INFO
logger.info("f{title} - {body}")

Les valeurs par défaut définies dans le décorateur persistent tant qu’elles ne sont pas explicitement surchargées.

En interne, le décorateur :

  • enregistre un wrapper dynamique NotifyBase ;
  • lie votre fonction au schéma ;
  • impose l’unicité du schéma ;
  • prend automatiquement en charge les pièces jointes et le stockage persistant.

Si un schéma existe déjà, Apprise journalise un avertissement et ignore l’enregistrement.

Par défaut, Apprise scanne :

  • Linux et macOS :
    • ~/.apprise/plugins
    • ~/.config/apprise/plugins
  • Windows :
    • %APPDATA%/Apprise/plugins
    • %LOCALAPPDATA%/Apprise/plugins

Surcharge possible avec :

Fenêtre de terminal
apprise -P /custom/plugin/path -b "test" foobar://

Fournissez les chemins de plugins via AppriseAsset :

from apprise import Apprise, AppriseAsset
asset = AppriseAsset(plugin_paths=[
"/path/to/plugins",
"/path/to/plugin.py",
])
aobj = Apprise(asset=asset)
aobj.add("foobar://")
aobj.notify("Hello")

Règles de scan des répertoires :

  • les fichiers et répertoires cachés sont ignorés ;
  • un répertoire avec __init__.py charge uniquement ce fichier ;
  • un répertoire sans __init__.py charge tous les fichiers .py à ce niveau ;
  • le scan n’est pas récursif.

  • les schémas doivent être uniques ;
  • gardez les modules sûrs à importer ; n’effectuez pas d’appels réseau ni de traitements longs au moment de l’import ;
  • validez et nettoyez les valeurs meta avant de les utiliser ;
  • préférez les listes blanches à l’exécution dynamique ;
  • placez les secrets dans des variables d’environnement ou des coffres à secrets, pas dans les URL ;
  • si vous avez besoin d’un parsing fort, de batch, de pièces jointes ou d’une contribution amont, écrivez un plugin complet à la place.

L’API de décorateur Apprise offre un moyen rapide et flexible d’étendre Apprise avec une logique personnalisée tout en conservant l’interface familière en schema://. Elle convient parfaitement aux workflows internes, aux hooks d’automatisation et aux systèmes fortement intégrés.

Questions ou commentaires ?

Documentation

Vous avez repéré une faute de frappe ou une erreur ? Signalez-la ou proposez une correction .

Problèmes Techniques

Vous rencontrez un problème avec le code ? Ouvrez un ticket sur GitHub :

Conçu avec amour depuis le Canada