Version de développement
Cette documentation décrit la version « next » (develop), non encore publiée. Pour la version stable, basculez sur « v5 » dans l'en-tête.
Développeurs

Organiser les patches d'une application

Ranger les patches dans les sections du fichier patches.txt pour choisir à quel moment de la migration chacun s'exécute.

Organiser les patches d'une application

Un patch est un script Python qui modifie le schéma ou les données de la base pendant bench migrate. Le fichier patches.txt d'une application liste ses patches. Dodock exécute chaque patch une seule fois par site et l'enregistre dans le Journal de Patch.

Sections du fichier patches.txt

Le fichier patches.txt se divise en sections. La section d'un patch décide de son moment d'exécution :

SectionExécutionUsage
[pre_model_sync]Avant la synchronisation du schéma des DocTypesPatch qui lit l'ancien schéma (colonne renommée ou supprimée par la nouvelle version)
[post_model_sync]Après la synchronisation du schémaPatch de données qui utilise le nouveau schéma
[post_fixture_sync]Après la synchronisation des fixtures, des Champs personnalisés et des Property SettersPatch qui utilise un champ ou un DocType ajouté par une fixture ou une personnalisation

Dans une section, les patches s'exécutent dans l'ordre du fichier. Les sections [pre_model_sync] et [post_model_sync] sont obligatoires dans un fichier à sections. La section [post_fixture_sync] est facultative.

[pre_model_sync]
mon_app.patches.v2_0.renommer_ancienne_colonne

[post_model_sync]
mon_app.patches.v2_0.mettre_a_jour_statuts

[post_fixture_sync]
mon_app.patches.v2_0.remplir_remise_fidelite

Une ligne qui commence par execute: contient une instruction Python à la place d'un chemin de module :

[post_model_sync]
execute:frappe.delete_doc_if_exists("Report", "Ancien rapport")

Créer un patch

  1. Lancez la commande interactive depuis le dossier du bench :
    bench create-patch
    
  2. Choisissez l'application, puis le DocType concerné.
  3. Décrivez le patch. La description devient la docstring et propose un nom de fichier.

La commande crée le fichier dans le dossier patches du DocType. Elle ajoute aussi son chemin à la fin de patches.txt, donc dans la dernière section du fichier. Déplacez la ligne si le patch doit aller dans une autre section.

Le fichier contient une fonction execute() sans argument. Écrivez la modification dans cette fonction.

Exemple

Cet exemple est fictif. Une application ajoute à Client deux champs personnalisés par une fixture : custom_statut_fidelite (Bronze, Argent, Or) et custom_remise_fidelite. Un patch remplit la remise selon le statut.

# mon_app/patches/v2_0/remplir_remise_fidelite.py
import frappe

REMISES = {"Bronze": 5, "Argent": 10, "Or": 15}


def execute():
    for statut, remise in REMISES.items():
        frappe.db.set_value(
            "Customer",
            {"custom_statut_fidelite": statut},
            "custom_remise_fidelite",
            remise,
            update_modified=False,
        )

Le patch va dans [post_fixture_sync]. Dans [post_model_sync], les champs personnalisés n'existent pas encore lors d'une première installation de la version, et le patch échoue.

Écrire un patch sûr

  • Rendez le patch rejouable : une deuxième exécution ne doit rien casser.
  • Testez la migration sur une copie de la base avant la production.
  • Gardez le patch court. Pour un gros volume, traitez les données par lots.

Vérifier l'exécution

Ouvrez la liste Journal de Patch. Chaque patch exécuté y figure avec sa date. Avec bench migrate --skip-failing, un patch en échec y figure comme ignoré, et la migration continue. Pour interdire cela sur un patch critique, utilisez le hook never_skip_patches (voir la Référence des hooks).