PEP 750 – Approbation des chaînes de modèle (t-strings)
(peps.python.org)- La PEP 750 introduit dans Python un nouveau littéral de chaîne, les chaînes de modèle (
t"...") - Il s’agit d’une forme généralisée des f-strings, qui produit un type
Templateafin de permettre un traitement préalable combinant la chaîne et les valeurs interpolées - Cela peut être utile pour les templates web, les contrôles de sécurité, les DSL (Domain-Specific Language), etc.
Relation avec les autres PEP
- Les f-strings ont été introduites par la PEP 498, puis leur syntaxe a été étendue dans la PEP 701
- La PEP 501 proposait des chaînes de modèle généralisées (
i-string), mais elle a été mise en attente - La PEP 750 est aujourd’hui une forme simplifiée et généralisée de la PEP 501, développée à partir des idées existantes
Motivation et nécessité
- Les f-strings sont simples, mais comme elles ne permettent pas de prétraiter les valeurs interpolées, elles peuvent poser des problèmes de sécurité
- Il existe un risque de vulnérabilités telles que l’injection SQL ou les attaques XSS
- Les chaînes de modèle permettent de prétraiter les valeurs interpolées afin de les utiliser en toute sécurité
Exemple :
evil = "<script>alert('evil')</script>"template = t"<p>{evil}</p>"assert html(template) == "<p><script>alert('evil')</script></p>"
Spécification des chaînes de modèle
Littéraux de chaîne de modèle
- Définis avec le préfixe
touT - Évalués comme le type
string.templatelib.Template - Prennent en charge une syntaxe similaire aux f-strings, y compris l’imbrication
- Peuvent être combinés avec le préfixe
r(rt,tr) - Ne peuvent pas être combinés avec les préfixes
uetb - Il n’est pas possible de mélanger f-string et chaîne de modèle
Type Template
- Type immuable avec les attributs suivants :
strings: tuple de fragments de chaîneinterpolations: tuple d’objets représentant les interpolationsvalues: tuple des valeurs interpolées__iter__(): itérateur renvoyant successivement les chaînes et les interpolations
Type Interpolation
value: résultat évaluéexpression: chaîne de l’expression interpolée d’origineconversion: mode de conversion (r,s,aou None)format_spec: chaîne de format
Exemple :
name = "World"template = t"Hello {name!r}"assert template.interpolations[0].conversion == "r"
Spécificateur de débogage =
t"{value=}"est interprété commet"value={value!r}"- Les espaces sont également conservés tels quels (
t"{value = }"→"value = {value!r}")
Concaténation de chaînes de modèle
- L’opérateur
+permet de combiner unTemplateavec unstr, ou unTemplateavec un autreTemplate - Le résultat de la concaténation est toujours de type
Template - La concaténation implicite de chaînes est aussi possible (
t"Hello " t"World")
Méthodes de traitement des chaînes de modèle
Exemple : fonction de mise en minuscules/majuscules
def lower_upper(template):parts = []for s in template:if isinstance(s, str): parts.append(s.lower())else: parts.append(str(s.value).upper())
return "".join(parts)
Exemple : implémentation du même traitement qu’une f-string
- Une fonction
f()peut produire le même résultat qu’une f-string
Exemple : journalisation structurée
- Les chaînes de modèle permettent d’afficher simultanément un message de log et des valeurs structurées
- Cela peut être implémenté via
StructuredMessageou une sous-classe delogging.Formatter
Exemple : traitement de templates HTML
- La fonction
html()traite le contenu par échappement ou comme attribut selon la position d’insertion - Les templates imbriqués sont également pris en charge
Modèles d’utilisation avancés
- Utilisation recommandée du filtrage par motif structurel (instruction
match) - Les chaînes statiques peuvent servir de clés de cache, ce qui permet une mémoïsation efficace
- Il est possible d’analyser et de traiter via une représentation intermédiaire telle que l’AST
lambdaetawaitpeuvent être utilisés pour une évaluation lazy ou async
Relation entre les chaînes de modèle et les chaînes de format existantes
- Il est possible de définir des fonctions de template d’une manière proche de
.format() - Un
from_format()permettant d’analyser une chaîne externe et de la convertir enTemplateest également possible
Compatibilité, sécurité, apprentissage
- Sur les anciennes versions de Python, cela peut provoquer une erreur de syntaxe
- Du point de vue sécurité, le traitement par template améliore la sûreté
- La syntaxe, proche des f-strings, facilite l’apprentissage
Pourquoi une nouvelle approche des templates ?
- Les templates existants comme Jinja visent surtout les utilisateurs finaux ou les designers
- Il est nécessaire d’avoir une prise en charge au niveau du langage Python pour que les développeurs puissent manipuler directement les templates
- Cela permet de tirer parti d’avantages comme l’expressivité ou la vérification de types
Récapitulatif des modèles d’exemple
- Filtrage par motif structurel et appariement sur les sous-attributs
- Réutilisation des templates comme des fonctions
- Prise en charge des templates imbriqués
- Prise en charge de l’évaluation lazy/async
- Optimisation du cache grâce à la séparation statique/dynamique
Autres considérations de conception
- Un template n’est pas converti en chaîne, et
__str__()n’est pas implémentée - Les classes associées sont fournies par le module
string.templatelib TemplateetInterpolationsont comparés selon l’identité des objets- Les opérations
==et<ne sont pas prises en charge
Implémentation de référence et exemples
- Implémentation CPython
- Exemples et tests disponibles
Idées rejetées
- Utilisation de préfixes arbitraires (
my_tag"...") - Évaluation différée de toutes les expressions interpolées
- Implémentation sous forme de protocole
- Redéfinition de
__eq__et__hash__ - Restauration complète de la chaîne d’origine
- Ajout d’un type
Decoded - Prise en charge de chaînes de modèle binaires
- Fonction de spécification du type de format (
"html","sql", etc.) - Restriction de la concaténation de chaînes
- Autorisation de convertisseurs arbitraires (
!x)
3 commentaires
Je trouve que les formats les plus satisfaisants, il n’y a que JavaScript et Python. Les autres langages, bof…
Il devrait exister une manière évidente de le faire — et, de préférence, une seule.
Avis Hacker News
Il est intéressant de voir comment différents langages gèrent le formatage des chaînes de caractères
.format(), les f-strings et les t-stringsNick Humrich est l’un des auteurs ayant réécrit la PEP 501 pour introduire les t-strings, et il est très heureux de l’acceptation de cette PEP
Certains ne sont pas convaincus de la valeur d’une fonctionnalité au niveau du langage
Les f-strings sont appréciées, mais elles ont le défaut de ne pas permettre de différer l’évaluation
str.format, ce qui est peu pratiqueEn tant que mainteneur de lit-html, certains trouvent intéressante la similarité avec les tagged template literals de JavaScript
html()pourrait ne pas être nécessaireCertains espèrent que les avantages des tagged template literals de JavaScript pour l’auto-escaping HTML ou la paramétrisation SQL s’appliqueront aussi à Python
Certains ont l’impression que Python est en train de devenir PHP
string.formatleur semble être la meilleure option, et%reste acceptable puisqu’il est utilisé depuis longtempsIl y a aussi des critiques sur l’ajout constant de nouveautés au langage
Certains trouvent que cette PEP ressemble à la P1819 de C++
D’autres jugent que le code de la PEP est beaucoup trop verbeux