Conventions de Code
Conventions de Code
Ces conventions sont adaptées des Contribution Guidelines du framework Frappe. Dokos étant basé sur Frappe/ERPNext, nous suivons les mêmes standards pour assurer la cohérence et faciliter les contributions croisées.
Le code source de Dokos est disponible sur GitLab.
Standards de Code
Messages utilisateur
Tous les textes affichés à l'utilisateur doivent être traduisibles:
- En Python:
_("texte") - En JavaScript:
__("texte")
frappe.msgprint(_("Invoice {0} submitted").format(self.name))
frappe.msgprint(__("Invoice {0} created", [doc.name]));
Écrivez le texte source en anglais. La traduction française se fait dans le fichier fr.po (voir Traductions).
Longueur des fonctions
Une fonction fait une seule chose. Au-delà d'une quarantaine de lignes, elle en fait généralement plusieurs : découpez-la en fonctions nommées selon ce qu'elles font.
- Plus d'un niveau d'indentation
- Des "paragraphes" séparés par des lignes vides
Indentation
Utilisez des tabulations, pas des espaces. Le formateur ruff format du dépôt applique cette règle (indent-style = "tab"), avec des guillemets doubles et des lignes de 110 caractères au plus.
Les chaînes multi-lignes et expressions doivent être indentées de façon cohérente:
D = frappe.qb.DocType("Accounting Dimension")
query = frappe.qb.from_(D).select(D.label, D.fieldname, D.document_type).where(D.disabled == 0).run(as_dict=1)
Dimension = frappe.qb.DocType("Accounting Dimension")
query = (
frappe.qb.from_(Dimension)
.select(
Dimension.label,
Dimension.fieldname,
Dimension.document_type,
)
.where(Dimension.disabled == 0)
)
results = query.run(as_dict=1)
Ordre des fonctions
La fonction appelante doit être placée en haut, les fonctions appelées en dessous:
def fa():
fb()
fc()
def fb():
pass
def fc():
pass
Conditions multiples
Évitez de regrouper plusieurs conditions sur une seule ligne. Séparez-les pour améliorer la lisibilité.
Logique métier
Toute la logique métier doit être implémentée côté serveur (Python). Lors des appels REST API, seul le code Python s'exécute. Le JavaScript est réservé à l'amélioration de l'expérience utilisateur.
Commentaires
Un commentaire explique pourquoi, jamais ce que fait le code. Gardez un commentaire court pour un contournement qui n'est pas évident.
N'écrivez pas l'historique de la correction dans le code (« correction du ticket 123 », « on vérifie maintenant… ») : il va dans la description de la merge request. Une docstring est utile quand elle donne à l'appelant une information que la signature ne donne pas, par exemple une limite ou un effet de bord.
Le marqueur @dokos est la seule exception (voir la section « Spécificités Dokos » plus bas).
APIs dépréciées
Évitez ces APIs obsolètes:
cur_frm- Utilisez le paramètrefrmdes handlersget_query- Utilisezset_queryadd_fetch- Utilisez les Link fields avecfetch_from
Sécurité du Code
Injections SQL
frappe.db.sql(). Utilisez le Query Builder (frappe.qb) ou les méthodes ORM. Du code ancien utilise encore frappe.db.sql() : remplacez-le quand vous le modifiez.# RECOMMANDÉ - Query Builder
from frappe.query_builder import DocType
User = DocType('User')
query = (
frappe.qb.from_(User)
.select(User.name, User.email)
.where(User.name == user)
)
result = query.run(as_dict=True)
# RECOMMANDÉ - Méthodes ORM (cas simples)
frappe.get_all('User',
fields=['name', 'email'],
filters={'name': user}
)
frappe.db.get_value('User', user, ['name', 'email'])
Avantages du Query Builder :
- Protection contre les injections SQL : paramétrage automatique des valeurs
- Compatibilité cross-database : même syntaxe pour MariaDB et PostgreSQL
- API Python typée : objets Field et Function au lieu de chaînes de caractères
Création de documents
Les méthodes whitelistées acceptant des dictionnaires peuvent contourner les permissions. Ajoutez des vérifications explicites:
@frappe.whitelist()
def create_document(values: dict):
frappe.only_for('System Manager')
if values['doctype'] not in ('ToDo', 'Note', 'Task'):
frappe.throw(_('Type de document invalide'))
doc = frappe.get_doc(values).insert()
return doc
Injection de code
- Évitez
eval()etexec() - Utilisez uniquement
frappe.safe_evaloufrappe.utils.safe_exec.safe_exec
Traversée de répertoires
Ne permettez jamais aux utilisateurs de contrôler les chemins de fichiers. Utilisez l'API du DocType "File".
Permissions par défaut
frappe.get_doc()ne vérifie PAS les permissions par défaut- Préférez
frappe.get_list()àfrappe.get_all()pour appliquer les permissions - Vérifiez explicitement les permissions dans les méthodes whitelistées:
@frappe.whitelist()
def get_document(doctype: str, name: str):
doc = frappe.get_doc(doctype, name)
doc.check_permission("read")
return doc
Validation des types
Annotez les arguments des méthodes whitelistées. Dodock vérifie leur type à chaque appel HTTP et refuse une valeur du mauvais type:
@frappe.whitelist()
def get_user(name: str):
doc = frappe.get_doc("User", name)
doc.check_permission("read")
return doc
Checklist Merge Request
Adapté de Pull Request Checklist - Frappe/ERPNext
Branches cibles
- Créez votre branche depuis la dernière version de
developdu projet Dokos (dokos/dokos,dokos/dodock…), et non depuisfrappe/erpnextoufrappe/frappe. - Ouvrez la merge request vers
develop. Ne ciblez jamaisv5: c'est la branche des versions publiées. - Gardez uniquement vos commits sur la branche. Rebasez-la sur
developau lieu d'y fusionner une autre branche.
Pour qu'une correction arrive dans une version publiée, indiquez-le dans la description. Un mainteneur pose le libellé de rétroportage :
| Libellé | Usage |
|---|---|
backport-v5-fix | Correction de bug pour la version stable actuelle. |
backport-v5-dev | Évolution pour la prochaine version mineure. |
Un contributeur externe ne peut pas poser de libellé : écrivez celui que vous souhaitez dans la description.
Messages de commit
Format Conventional Commits: type(scope): description
| Type | Description |
|---|---|
feat | Nouvelle fonctionnalité |
fix | Correction de bug |
docs | Documentation uniquement |
refactor | Refactoring sans changement fonctionnel |
test | Ajout ou modification de tests |
Vérifications avant soumission
- Tous les tests passent
- Hooks pre-commit installés (
pre-commit installetpre-commit install --hook-type commit-msg) :ruff,ruff-format,prettier,eslint,commitlint - Documentation mise à jour si nécessaire
- Screenshots ou GIF pour les changements d'interface
- Laissez cochée l'option GitLab qui autorise les commits des membres pouvant fusionner
Description de la merge request
Un relecteur doit comprendre la modification en vingt secondes :
<une ligne : ce qui ne fonctionnait pas, vu par l'utilisateur>
- <ce qui change, vu par l'utilisateur>
- <comment vous l'avez testé : étapes ou test lancé, ou « non testé »>
- Rétroportage : <backport-v5-fix | backport-v5-dev | aucun>
Closes #<ticket>
Une merge request contient une seule correction ou une seule fonctionnalité.
Contenu à éviter
N'incluez pas de changements automatisés (linters de masse, corrections IA non revues) sans validation manuelle.
Spécificités Dokos
Dokos et Dodock sont des copies (forks) d'ERPNext et de Frappe. Un robot reporte chaque jour les pull requests de Frappe et d'ERPNext dans ces dépôts, sur des branches nommées ft-pr-<numéro>. Un report peut écraser une modification Dokos sans le signaler. Les règles ci-dessous permettent aux mainteneurs de repérer et de garder les modifications Dokos.
Marqueur @dokos
Un fichier qui existe aussi dans frappe/erpnext ou frappe/frappe est du code hérité. C'est aussi le cas de l'interface banking/. Marquez chaque ligne ajoutée ou modifiée dans ces fichiers :
| Langage | Marqueur |
|---|---|
| Python | # @dokos en fin de ligne, ou # @dokos: <raison> au-dessus d'un bloc |
| JavaScript, TypeScript | // @dokos ou // @dokos: <raison> |
| JSX | {/* @dokos: <raison> */} |
| Vue (template), HTML | <!-- @dokos: <raison> --> |
Ne marquez pas le code des modules ou des applications qui n'existent que dans Dokos.
Données client
Tous les dépôts Dokos sont publics. Ne mettez aucune donnée client dans un commit, une merge request, un ticket, un commentaire de code ou un test : nom de site ou de domaine, nom de société, de fournisseur ou de client, nom de personne, adresse, numéro SIREN, SIRET ou de TVA, identifiant de document réel. Utilisez des noms inventés dans les tests et les exemples.
Assistants IA
Le fichier AGENTS.md du dépôt Dokos reprend ces règles en anglais. Dans Dodock, elles sont dans DOKOS_AGENTS.md. Donnez ce fichier à votre assistant de code. Relisez toujours ce qu'il produit avant d'ouvrir la merge request.
Références
Ces conventions sont dérivées de la documentation officielle Frappe/ERPNext:
- Contribution Guidelines
- Coding Standards
- Code Security Guidelines
- Pull Request Checklist
- AGENTS.md de Frappe : la méthode de travail attendue sur une modification
- Guide de relecture de Frappe : ce que vérifie le relecteur
Pour contribuer à Dokos: GitLab Dokos