Retour au catalogue
Season 9 20 Épisodes 1h 8m 2026

Pydantic: Data Validation

v2.12 — Édition 2026. Une plongée au cœur de Pydantic v2.12, la bibliothèque de validation de données la plus utilisée pour Python, de l'utilisation de base aux fonctionnalités avancées telles que les core schemas personnalisés et l'observabilité avec Logfire.

Validation des données Fondamentaux de Python
Pydantic: Data Validation
Lecture en cours
Click play to start
0:00
0:00
1
La philosophie de Pydantic : Les Type Hints comme validation
Cet épisode présente le principe fondamental de Pydantic. Vous apprendrez comment les type hints de Python peuvent être utilisés pour imposer des schémas et comment le cœur en Rust permet d'obtenir d'immenses gains de performances.
3m 10s
2
L'anatomie d'un BaseModel
Plongez dans BaseModel, l'abstraction fondamentale de Pydantic. Vous apprendrez comment l'instanciation valide les données, comment les types des champs sont forcés et comment les erreurs de validation sont remontées.
3m 29s
3
Contraintes de Field et le motif Annotated
Apprenez à imposer des limites au-delà des types de base. Vous découvrirez comment utiliser la fonction Field et la construction de typage Annotated pour ajouter des contraintes telles que des minimums et des longueurs maximales.
3m 32s
4
Les alias de Field pour la validation et la sérialisation
Résolvez les conflits de conventions de nommage entre les API externes et le code Python interne. Vous apprendrez à découpler les noms de vos attributs Python des clés JSON en utilisant des alias de validation et de sérialisation.
3m 30s
5
Coercition des données vs Strict Mode
Prenez le contrôle de la tendance de Pydantic à forcer la conversion des données. Vous apprendrez à imposer des correspondances de types exactes en activant le Strict Mode au niveau du champ ou du modèle.
3m 43s
6
Observabilité en conditions réelles avec Logfire
Apportez de la transparence à vos pipelines de données. Vous apprendrez à intégrer Pydantic avec Logfire pour surveiller les validations réussies et échouées en temps réel.
3m 21s
7
Valider des types arbitraires avec TypeAdapter
Apprenez à valider des primitives et des listes autonomes sans créer de BaseModel. Vous découvrirez comment TypeAdapter transforme n'importe quel type Python en une véritable cible de validation.
3m 29s
8
Les types Union et la validation intelligente
Comprenez les complexités de la validation des types Union. Vous apprendrez comment le Smart Mode de Pydantic évalue l'exactitude et les champs valides pour choisir la meilleure correspondance.
3m 12s
9
Outil de pointe : Les Discriminated Unions
Boostez vos performances de validation. Vous apprendrez à utiliser les Discriminated Unions pour indiquer à Pydantic exactement quel schéma appliquer en fonction d'un champ spécifique.
3m 15s
10
Pré-traitement avec les Before et Wrap Validators
Gérez les données entrantes désordonnées avant qu'elles ne touchent votre schéma. Vous apprendrez à utiliser les validateurs de champs Before et Wrap pour nettoyer les entrées brutes avant que Pydantic ne les évalue.
3m 28s
11
Post-traitement avec les After et Plain Validators
Appliquez des règles de logique métier strictes. Vous apprendrez à utiliser les After Validators pour vérifier les données déjà analysées, et les Plain Validators pour court-circuiter entièrement Pydantic.
3m 14s
12
Hooks de validation au niveau du modèle
Validez les interactions entre plusieurs champs. Vous apprendrez à utiliser le décorateur model_validator pour appliquer des règles qui dépendent de l'ensemble du payload.
3m 12s
13
Sérialisation : Exporter des données en toute sécurité
Contrôlez la façon dont vos données quittent le système. Vous apprendrez les différences entre l'exportation vers des dicts Python et des chaînes JSON, et comment exclure les champs non définis ou par défaut.
3m 34s
14
Personnaliser la logique de sérialisation
Modifiez la façon dont vos types sont représentés à la sortie. Vous apprendrez à écrire des sérialiseurs personnalisés de Field et de Model pour muter les données pendant la phase d'exportation.
3m 41s
15
Générer un JSON Schema à partir de modèles
Transformez vos modèles en contrats d'API auto-documentés. Vous apprendrez à générer des JSON Schemas conformes à OpenAPI et à injecter des exemples directement dans le schéma.
3m 44s
16
RootModel : Quand votre payload n'est pas un dictionnaire
Gérez gracieusement les payloads JSON non standard. Vous découvrirez comment RootModel vous permet d'analyser des tableaux et des primitives au niveau racine tout en conservant les pouvoirs du BaseModel.
3m 08s
17
Dataclasses standards vs Dataclasses Pydantic
Apportez la validation à vos classes Python natives. Vous apprendrez quand utiliser le décorateur dataclass de Pydantic pour moderniser des bases de code existantes sans tout réécrire.
3m 33s
18
Ajustement fin de la configuration du modèle
Contrôlez la rigueur de l'ensemble de votre modèle. Vous apprendrez à utiliser le ConfigDict pour interdire les attributs supplémentaires, geler les instances et valider les assignations.
3m 02s
19
Configuration d'application avec Pydantic Settings
Gérez vos variables d'environnement comme un pro. Vous apprendrez comment le paquet pydantic-settings automatise l'analyse des secrets, des fichiers dot-env et des préfixes.
3m 21s
20
Sous le capot : Core Schemas personnalisés
C'est le dernier épisode de la série ! Prenez le contrôle ultime du moteur de validation. Vous apprendrez à écrire une méthode __get_pydantic_core_schema__ pour apprendre au cœur en Rust à gérer des objets Python complètement étrangers.
3m 30s

Épisodes

1

La philosophie de Pydantic : Les Type Hints comme validation

3m 10s

Cet épisode présente le principe fondamental de Pydantic. Vous apprendrez comment les type hints de Python peuvent être utilisés pour imposer des schémas et comment le cœur en Rust permet d'obtenir d'immenses gains de performances.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Validation de données, épisode 1 sur 20. La plupart des librairies de data validation t'obligent à apprendre un tout nouveau domain-specific language juste pour définir un schema. Mais et si la syntaxe built-in de Python suffisait déjà à faire respecter tes règles ? La philosophie de Pydantic : les Type Hints comme validation, résout exactement cette tension. Avant de voir comment ça marche, on doit dissiper une confusion courante. Pydantic n'est pas un static type checker comme mypy. Mypy analyse ton code source avant que tu le lances pour attraper les erreurs de logique. Pydantic opère au runtime. Il prend des données non fiables qui viennent de l'extérieur, comme un payload JSON d'une requête API, et les force à se conformer aux types que tu as définis, pile au moment où ton programme s'exécute. La philosophie de base ici, c'est la simplicité. Tu définis un data model en utilisant les type annotations standard de Python. Tu crées une class qui représente un utilisateur, et tu déclares que le user ID est un integer, et que la date d'inscription est un objet datetime. C'est tout ton schema. Tu n'écris pas de fonctions de validation custom, et tu n'importes pas de field types propriétaires. Quand un dictionnaire un peu brouillon arrive d'un formulaire web, tu le passes simplement à ta class. Pydantic l'intercepte et garantit que l'objet qui en résulte respecte strictement ces types. Voici l'idée clé. Pydantic est fondamentalement une librairie de parsing, pas juste une barrière de validation stricte. Si un utilisateur soumet un formulaire web où le user ID est la string quarante-deux, Pydantic va reconnaître que ton modèle attend un integer. Il convertit automatiquement cette string en un integer Python natif. Il essaie de faire correspondre les données à ton schema avant de lever une erreur. Ça gère la data coercion fastidieuse, pour que tu n'aies pas à écrire de logique de parsing manuelle pour chaque input field. Valider et convertir chaque donnée entrante au runtime, ça a l'air intrinsèquement lent, surtout en Python. Pour résoudre ça, la logique d'exécution ne tourne pas vraiment en Python. Pydantic délègue le gros du travail à un core engine dédié, écrit entièrement en Rust. Ce design t'offre la developer experience rapide de l'écriture en pur Python, combinée à la vitesse d'exécution brute du code système compilé. Prends l'exemple d'une background task qui parse un énorme fichier JSON où chaque record contient une adresse web. Si tu écris du code pur Python pour boucler sur des milliers de dictionnaires, extraire chaque string, charger une librairie d'expressions régulières et vérifier que chaque string est une URL valide, ton process va ramer. Pydantic gère ça de manière transparente. Tu as juste à annoter le field de l'adresse comme un type URL et à passer le JSON brut à ton modèle. Le moteur Rust fonce à travers le texte, en parsant et en validant les formats à des vitesses que le Python natif ne peut pas égaler. La vraie puissance de cette approche, c'est que l'autocomplete de ton éditeur, tes outils d'analyse statique et ta validation au runtime partagent tous exactement la même source de vérité, qui est tes type hints standard. Si tu trouves ces épisodes utiles et que tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon. C'est tout pour celui-ci. Merci d'avoir écouté, et keep building !
2

L'anatomie d'un BaseModel

3m 29s

Plongez dans BaseModel, l'abstraction fondamentale de Pydantic. Vous apprendrez comment l'instanciation valide les données, comment les types des champs sont forcés et comment les erreurs de validation sont remontées.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Validation des données, épisode 2 sur 20. On parle souvent de validation de données, mais si tu regardes Pydantic de plus près, son objectif principal est en réalité la coercion. Il garantit la structure de ton output, et non de ton input. C'est l'anatomie d'un BaseModel qui rend cette distinction possible. La classe BaseModel est la fondation de Pydantic. Pour définir un schéma, tu crées une classe Python standard et tu hérites de BaseModel. Une fois que c'est fait, Pydantic transforme ta classe en un conteneur de données strict. Tu définis la forme de tes données en utilisant les type hints standard de Python. Tu n'as pas besoin de fonctions propriétaires pour déclarer une string ou un nombre. Tu écris simplement le nom de l'attribut, deux points, et le type Python attendu. Prends l'exemple d'un modèle User. À l'intérieur de la classe, tu définis un seul champ nommé id, et tu le types comme un integer. Tu pourrais aussi ajouter un champ name typé comme une string. C'est toute la définition. Voici l'idée clé. Le vrai travail se fait au moment où tu instancies le modèle. Tu crées une instance en passant tes données sous forme de keyword arguments, qui correspondent aux noms des champs que tu as définis. Quand tu fais ça, Pydantic intercepte les données avant que l'objet ne soit complètement initialisé. Il compare les valeurs entrantes avec tes type hints. C'est là que la coercion se produit. Si tu passes l'integer un-deux-trois dans le champ id, Pydantic l'accepte immédiatement. Mais suppose que tu reçoives des données d'une requête web ou d'un fichier texte, et que tu passes la string "123" dans ce même champ. Pydantic ne lance pas instantanément une erreur. Il reconnaît que le type cible est un integer et tente de convertir la string. Comme les caractères peuvent être castés en nombre en toute sécurité, Pydantic effectue la conversion silencieusement. L'objet est créé, et le champ id stocke un vrai integer Python, pas une string. Ce comportement prouve que Pydantic est essentiellement une librairie de parsing. Il transforme les données entrantes pour qu'elles correspondent au schéma strict que tu as défini. Bien sûr, cette conversion a des limites logiques. Si tu instancies le modèle User et que tu passes la string "not an int" au champ id, Pydantic tente la conversion et échoue. Quand la coercion est impossible, Pydantic lève une ValidationError. Cette erreur interrompt l'exécution immédiatement. Un détail crucial à propos de la ValidationError est que Pydantic évalue tous les champs avant de la lever. Si ton modèle a plusieurs champs avec des données invalides, l'exception contiendra les détails de tous les échecs, plutôt que de s'arrêter à la toute première erreur. L'erreur pointe les champs exacts qui ont causé le problème, les valeurs spécifiques fournies, et les raisons pour lesquelles le parsing a échoué. Une fois que tes données passent l'instanciation avec succès, l'objet résultant est garanti de correspondre à tes type hints. Tu accèdes aux données exactement comme pour n'importe quel objet Python standard, en utilisant la dot notation. Si tu as assigné l'instance à une variable appelée user, tu tapes simplement user dot id pour récupérer l'integer. Il n'y a pas besoin de méthodes getter ou setter. Tu interagis avec un objet propre et fortement typé. La vraie valeur de l'héritage de BaseModel n'est pas seulement qu'il rejette les mauvais inputs, mais qu'il normalise en toute sécurité des données externes imprévisibles vers un état interne hautement prévisible. Merci pour ton écoute. Prends soin de toi, et salut à tous.
3

Contraintes de Field et le motif Annotated

3m 32s

Apprenez à imposer des limites au-delà des types de base. Vous découvrirez comment utiliser la fonction Field et la construction de typage Annotated pour ajouter des contraintes telles que des minimums et des longueurs maximales.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Data Validation, épisode 3 sur 20. Les type hints standards te disent qu'un field est un integer, mais ils ne peuvent pas te dire qu'il doit être supérieur à zéro. Quand un âge négatif ou un username de dix mille caractères passe les frontières de ton application, le type checking de base ne suffit plus pour protéger ton backend. Pour imposer des limites strictes à tes données, tu as besoin des Field Constraints et du pattern Annotated. Dans Pydantic, les constraints te permettent de restreindre les valeurs autorisées pour un type spécifique. Au lieu d'écrire des fonctions de validation custom pour chaque petite règle, tu peux définir des limites mathématiques ou structurelles directement sur le field. Pour les types numériques, tu peux imposer des limites supérieures ou inférieures en utilisant des paramètres comme g-t et l-t. Pour les strings, tu peux restreindre la taille de l'input en utilisant max length et min length. Pour appliquer ces règles, Pydantic fournit une fonction utilitaire appelée Field. La façon classique dont les développeurs appliquaient ces constraints, c'était en assignant un appel à la fonction Field comme valeur par défaut d'un attribut de modèle. Par exemple, tu déclarais un attribut age, tu lui donnais un type hint d'integer, et tu le mettais égal à Field, en passant g-t égal zéro. Cette structure fonctionne, mais elle introduit de la friction. Si tu as besoin d'un integer positif sur quinze modèles différents, tu vas écrire exactement la même assignation de Field quinze fois. Pire, comme la fonction Field occupe l'emplacement d'assignation de la valeur par défaut sur le modèle, ça complique les choses quand tu veux vraiment assigner un vrai integer par défaut à cet attribut. Voici l'idée clé. Tu n'as pas du tout besoin de lier tes règles de validation à l'assignation de l'attribut. Tu peux les intégrer directement dans la définition du type elle-même en utilisant typing dot Annotated de Python. Annotated est une feature de la standard library qui te permet d'attacher des métadonnées arbitraires à un type hint de base. Pydantic est spécifiquement conçu pour regarder à l'intérieur d'un type Annotated, trouver toutes les fonctions Field que tu as fournies, et extraire leurs règles de validation automatiquement. Quand tu utilises Annotated, tu lui passes deux informations distinctes. Premièrement, tu fournis le type Python de base, comme un integer ou une string. Deuxièmement, tu fournis les métadonnées, qui dans notre cas sont la fonction Field de Pydantic contenant tes constraints. Créons un type age réutilisable pour voir comment ça se passe. Tu définis une nouvelle variable dans ton code appelée PositiveInt. Tu l'assignes à Annotated. À l'intérieur d'Annotated, tu passes integer comme type de base, suivi d'une virgule, et ensuite la fonction Field avec g-t égal zéro. Tu viens de créer une type constraint custom et réutilisable. Maintenant, chaque fois que tu définis un modèle user ou un modèle employee, tu ajoutes simplement un type hint PositiveInt à ton field age. Tu n'as pas besoin d'appeler la fonction Field sur l'attribut du modèle. Cette approche sépare tes définitions de type des structures de tes modèles. Tes modèles restent incroyablement propres, et se lisent juste comme des classes Python standards sans superflu. Si ta business logic change plus tard et que tu as soudainement besoin qu'un field age soit supérieur à dix-huit au lieu de zéro, tu mets à jour la définition de PositiveInt à un seul et unique endroit. Cette constraint mise à jour se répercute instantanément sur tous les modèles qui l'utilisent. En plus, comme Annotated est une feature native de Python, les static type checkers comprennent parfaitement que ton PositiveInt custom est au final évalué comme un integer standard. En découplant les métadonnées de validation de l'emplacement de la valeur par défaut, le pattern Annotated transforme les field constraints, qui étaient du boilerplate répétitif, en une bibliothèque partagée de domain types stricts et réutilisables. Merci d'avoir passé quelques minutes avec moi. À la prochaine, à plus.
4

Les alias de Field pour la validation et la sérialisation

3m 30s

Résolvez les conflits de conventions de nommage entre les API externes et le code Python interne. Vous apprendrez à découpler les noms de vos attributs Python des clés JSON en utilisant des alias de validation et de sérialisation.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Data Validation, épisode 4 sur 20. Est-ce que tu t'es déjà retrouvé obligé de nommer une variable Python en camel case juste pour parser le payload d'une API externe ? Tu sais que ça casse les conventions de nommage standard de Python, mais le JSON entrant impose la clé. La solution à ça, ce sont les Field Aliases pour la validation et la sérialisation. Quand tu ingères des données, les clés de ce payload ne correspondent souvent pas à la façon dont tu veux structurer ton code Python. Si un service tiers envoie un profil utilisateur avec la clé user N majuscule name, tu veux mapper ça vers une variable standard en snake case appelée user underscore name. Pydantic gère cette couche de traduction en utilisant la fonction Field, et plus précisément via ses arguments alias. L'approche la plus simple, c'est l'argument alias de base. Quand tu déclares ton attribut de modèle, tu lui assignes un Field et tu définis le paramètre alias sur la string attendue par le monde extérieur. Si tu définis l'alias sur la version camel case, Pydantic utilise cette string exacte pour la lecture et l'écriture. Lors de la validation des données entrantes, il cherche la clé en camel case. Quand tu sérialises ensuite le modèle pour le dumper à nouveau en JSON, il écrit la clé en camel case. Ton code Python interne opère entièrement sur l'attribut en snake case, complètement isolé de la convention de nommage externe. Ça, ça gère les données symétriques, où le format d'input et le format d'output sont identiques. Maintenant, la deuxième partie de tout ça, ce sont les données asymétriques. Que se passe-t-il quand tu consommes des données provenant d'un système legacy qui utilise une certaine convention de nommage, mais que tu dois les servir à un nouveau client qui en utilise une autre ? C'est là que tu sépares la logique en utilisant des validation aliases et des serialization aliases. Ce sont des arguments distincts que tu passes à la fonction Field. Un validation alias dicte strictement ce que Pydantic cherche lors de la création du modèle. Si tu fournis un validation alias, Pydantic va l'utiliser pour extraire la valeur du payload entrant, en écrasant tout alias de base que tu aurais pu définir. À l'inverse, un serialization alias ne contrôle que la phase d'output. Quand tu appelles une méthode pour dumper le modèle dans un dictionnaire ou une string JSON, Pydantic utilise le serialization alias comme clé d'output. Voici l'idée clé. Tu peux définir un seul Field avec trois identités distinctes. Le validation alias attrape la string d'input un peu brouillonne de l'API legacy. L'attribut Python contient la variable propre en snake case que tu utilises dans ta logique métier. Enfin, le serialization alias définit la clé standardisée et bien propre qui est envoyée à ton frontend. Parfois, le problème n'est pas une convention de nommage rigide, mais plutôt une convention incohérente. Tu peux recevoir des payloads où l'identifiant utilisateur est parfois en camel case, et parfois en un seul mot sans espaces. Pour gérer ça, Pydantic propose un utilitaire appelé alias choices. Au lieu de passer une seule string au validation alias, tu passes cet utilitaire qui contient une liste de strings. Pendant la validation, Pydantic scanne le payload entrant pour chaque string, dans l'ordre que tu as fourni. Dès qu'il trouve une clé correspondante, il extrait la valeur, l'assigne à ton attribut Python, et ignore le reste. En séparant la façon dont les données sont parsées de la façon dont elles sont exportées, les alias découplent le design interne de ton objet Python des contraintes de nommage arbitraires du monde extérieur. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
5

Coercition des données vs Strict Mode

3m 43s

Prenez le contrôle de la tendance de Pydantic à forcer la conversion des données. Vous apprendrez à imposer des correspondances de types exactes en activant le Strict Mode au niveau du champ ou du modèle.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Validation des données, épisode 5 sur 20. La tendance de Pydantic à vouloir transformer la string "123" en integer est une killer feature, jusqu'à ce qu'elle masque silencieusement un bug de data-type dans ton payload JSON. Tu t'attends à des nombres, tu reçois des strings, et ton application continue tranquillement jusqu'à ce qu'un système strict en aval crashe. Le mécanisme qui contrôle ce comportement, c'est la Data Coercion, et pour la dompter, tu dois comprendre le Strict Mode. Par défaut, Pydantic tourne dans ce que la documentation appelle le lax mode. Dans ce mode, Pydantic agit comme un data parser plutôt que comme un simple type checker. Il essaie activement de faire de la coercion, c'est-à-dire de convertir les données entrantes vers le type que tu as déclaré. Si tu définis un field comme un integer, et que le payload d'entrée fournit la string "123", Pydantic évalue la string, extrait le nombre valide et le transforme en un vrai integer. Ce comportement est super utile quand tu traites des inputs utilisateur venant de formulaires web ou de query parameters, où chaque valeur entrante est fondamentalement une string. Cependant, quand tu construis des APIs machine-to-machine, la conversion silencieuse est souvent dangereuse. Si un client promet d'envoyer un integer mais envoie une string à la place, il brise le contrat de l'API. Le lax mode masque cette violation. C'est là qu'intervient le strict mode. Le strict mode désactive la type coercion automatique. Quand tu l'actives, Pydantic exige que le data type entrant corresponde exactement à ton type annotation. Passe la string "123" à un field integer strict, et Pydantic la rejette immédiatement avec une validation error. Ça force la source de données à respecter le schema. Tu as deux façons d'appliquer le strict mode : globalement sur tout un model, ou localement sur des fields spécifiques. Pour l'imposer globalement, tu modifies la configuration du model. En passant le flag de configuration strict à true, chaque field de ce model arrête de faire de la coercion de types. Un field boolean n'acceptera qu'une valeur boolean true ou false, pas la string "true" ni l'integer 1. Un field integer n'acceptera que des integers. Voici le point clé. Le strict mode global est souvent trop rigide pour des applications réelles où les données arrivent de sources mixtes. En général, tu veux verrouiller quelques identifiants critiques tout en laissant le reste du model flexible. Pour faire ça, Pydantic permet un strict mode local. Tu peux imposer le strict mode sur un field individuel en utilisant des types spécialisés fournis par la library, comme StrictInt, StrictStr ou StrictBool. Si tu définis un field user ID avec StrictInt, ce field spécifique rejettera les représentations de nombres sous forme de string, pendant que le reste de ton model continuera de tourner en lax mode. Tu peux aussi faire ça en passant un flag strict directement dans la fonction de définition du field pour n'importe quel type standard. Prends l'exemple d'un service qui traite un payload JSON pour une transaction financière. Le payload contient un account ID. S'il est défini comme un integer normal, un payload qui envoie l'account ID sous forme de string "123" passe sans problème. Pydantic corrige le data type en mémoire. Si tu mets à jour ce field pour utiliser StrictInt, exactement le même payload JSON échoue à la validation. Le client reçoit une erreur explicite indiquant que l'input doit être un integer valide, ce qui permet d'attraper la violation de contrat à la frontière du système avant qu'elle ne pollue ta database. Le strict mode transforme Pydantic : d'un parser utile qui nettoie des inputs brouillons, il devient un validateur rigide qui garantit les data contracts. Merci de m'avoir écouté. Prenez soin de vous, tout le monde.
6

Observabilité en conditions réelles avec Logfire

3m 21s

Apportez de la transparence à vos pipelines de données. Vous apprendrez à intégrer Pydantic avec Logfire pour surveiller les validations réussies et échouées en temps réel.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Validation des données, épisode 6 sur 20. Quand un payload complexe échoue à la validation en production, la stack trace standard seule te dit rarement exactement pourquoi les données ont été rejetées. Tu sais qu'une request a échoué, mais tu es complètement aveugle aux vraies valeurs entrantes qui causent le crash. C'est exactement le problème que résout l'observabilité en conditions réelles avec Logfire. Logfire est une plateforme d'observabilité créée par l'équipe Pydantic, et elle propose une intégration directe avec Pydantic lui-même. Le but est de te donner de la visibilité sur ce que ta couche de validation de données fait réellement en production. Au lieu de traiter la validation comme une boîte noire qui lève parfois des exceptions, cette intégration transforme chaque check de validation en télémétrie trackée. Prends l'exemple d'un background worker qui traite les inscriptions d'utilisateurs depuis une message queue. Des centaines d'événements arrivent chaque seconde. Soudain, une inscription échoue avec une erreur de validation. Sans une bonne instrumentation, tes logs affichent un crash générique. Tu dois fouiller dans le payload brut de la queue pour comprendre que l'utilisateur a renseigné un âge de moins cinq. Pour corriger ça, tu importes le package Logfire et tu appelles une seule fonction nommée instrument underscore pydantic. Tu places ça juste après l'initialisation de ton client Logfire. À partir de ce moment-là, tes modèles Pydantic sont complètement observables. Tu n'as pas besoin de changer la façon dont tu définis tes modèles ou comment tu les instancies. Voici le point clé. Une fois instrumenté, à chaque fois que Pydantic valide des données, Logfire crée automatiquement un span. Un span est tout simplement l'enregistrement chronométré d'une opération. Si le payload d'inscription est parfaitement valide, Logfire enregistre un span réussi qui montre exactement combien de temps la validation a pris. C'est super utile si tu as des validateurs custom complexes et que tu as besoin de surveiller les goulots d'étranglement de performance. Si le payload est invalide, Pydantic lève une erreur de validation. Logfire attrape cet événement et attache les détails à la trace. Il capture le modèle spécifique impliqué et les champs exacts qui ont déclenché l'échec. Quand tu regardes ton dashboard d'observabilité, tu ne vois pas juste un message d'erreur générique. Tu vois les valeurs exactes qui ont été rejetées, comme cet âge négatif ou une string d'email malformée. Le setup est entièrement automatisé. Premièrement, configure le client. Deuxièmement, appelle la fonction instrument. Troisièmement, laisse ton worker traiter les données. Quand le worker essaie de parser une mauvaise string JSON dans ton modèle d'inscription, la télémétrie capture automatiquement le contexte de l'échec. Tu n'écris absolument aucun bloc d'exception custom pour logger la mauvaise entrée. Parce que Logfire comprend Pydantic nativement, il respecte tes structures de données. Il connaît la différence entre un champ manquant et une erreur de type, et il formate cette télémétrie pour que tu puisses la requêter plus tard. Tu peux filtrer tes metrics pour savoir exactement combien de fois le champ email a échoué à la validation sur tout ton cluster de workers aujourd'hui. La vraie valeur de cette intégration, c'est qu'elle élève la validation de données d'un simple check de code à un événement d'observabilité de premier plan, en transformant les rejets de données silencieux en télémétrie structurée et exploitable. Si tu veux soutenir l'émission, tu peux nous trouver en cherchant DevStoriesEU sur Patreon. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de coder !
7

Valider des types arbitraires avec TypeAdapter

3m 29s

Apprenez à valider des primitives et des listes autonomes sans créer de BaseModel. Vous découvrirez comment TypeAdapter transforme n'importe quel type Python en une véritable cible de validation.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Validation des données, épisode 7 sur 20. Parfois, tu as juste besoin de valider une simple liste de strings qui vient d'une requête API, mais créer une classe de model entière juste pour contenir cette seule liste, ça fait vraiment overkill. Tu ne veux pas d'un objet wrapper, tu veux juste la liste validée. La solution à ça, c'est de valider des types arbitraires avec TypeAdapter. Dans Pydantic, le workflow standard tourne autour de la définition d'une classe qui hérite du base model. Ce model te donne accès à des méthodes puissantes pour parser et sérialiser les données. Mais Pydantic est parfaitement capable de valider des types Python standards, comme un simple dictionnaire, un integer tout seul, une dataclass standard, ou un typed dict. Le truc, c'est que ces types standards ne possèdent pas nativement les méthodes de validation de Pydantic. Tu ne peux pas appeler validate sur une liste Python standard. C'est là que le type adapter entre en jeu. Il agit comme un pont, en wrappant n'importe quel type Python arbitraire et en exposant toutes les méthodes de model familières pour ce type. Prends l'exemple d'un endpoint web qui accepte un array JSON brut de strings. Avant, tu aurais peut-être créé un model factice avec un seul champ appelé items, juste pour pouvoir lui passer le payload JSON. Ça force le client à envoyer un objet JSON avec une clé items, ou ça te force à unpacker le model validé plus tard. Avec un type adapter, tu zappes complètement le model factice. D'abord, tu instancies l'adapter et tu lui passes la définition de type exacte que tu attends. Dans ce cas, tu passes le type hint Python pour une liste de strings. Ça crée un objet adapter spécifiquement configuré pour cette structure exacte. Maintenant, tu as accès aux méthodes de validation standards. Tu prends le payload JSON brut de ton endpoint et tu le passes à la méthode validate json sur ton instance d'adapter. Pydantic parse la byte string brute, vérifie que c'est bien un array JSON, vérifie que chaque élément à l'intérieur est une string, et renvoie une liste Python standard. Si le payload contient un integer ou un booléen, ça lève une validation error exactement comme le ferait un model classique. Voici le point clé. L'adapter ne se limite pas à une simple validation. Il reflète complètement l'API core d'un model standard. Ça veut dire que tu peux aussi l'utiliser pour sérialiser des données. Si tu as un dictionnaire complexe ou une dataclass Python standard et que tu as besoin de le reconvertir en string JSON, tu passes ces données à la méthode dump json sur ton adapter. Il applique exactement les mêmes règles de sérialisation, custom encoders et formatage que Pydantic applique aux models classiques. Cette fonctionnalité est particulièrement utile quand tu travailles avec des typed dicts. Un typed dict fournit un typage structurel pour les dictionnaires Python standards, mais il fait zéro validation au runtime. En passant un typed dict à un adapter, tu obtiens une application complète de la structure du dictionnaire au runtime. Ça garantit que toutes les clés requises sont présentes et que les valeurs correspondent aux types attendus, sans convertir le dictionnaire en une instance d'objet. L'output reste un simple dictionnaire. Instancier un adapter demande à Pydantic de construire des schémas de validation internes. Comme ce processus de setup prend un peu de temps de calcul, tu devrais créer tes instances d'adapter au niveau du module plutôt que de les reconstruire dans une fonction à chaque fois qu'un endpoint est appelé. Définis l'adapter une seule fois en haut de ton fichier, et réutilise-le pour plusieurs requêtes. Le type adapter te donne toute la puissance du moteur de validation core pour n'importe quel type Python standard, en gardant tes structures de données propres et sans classes wrapper inutiles. C'est tout pour aujourd'hui. Merci d'avoir écouté, va construire un truc cool.
8

Les types Union et la validation intelligente

3m 12s

Comprenez les complexités de la validation des types Union. Vous apprendrez comment le Smart Mode de Pydantic évalue l'exactitude et les champs valides pour choisir la meilleure correspondance.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Data Validation, épisode 8 sur 20. Quand un field est annoté comme une Union d'un string ou d'un integer, et que tu passes l'integer 123, quelle validation Pydantic tente-t-il vraiment en premier ? Si tu penses qu'il lit juste ton code de gauche à droite, tu risques d'être surpris quand tes données se comportent différemment de ce que tu attendais. C'est ce qui nous amène aux Union Types et à la Smart Validation. Un Union Type permet à un seul field d'accepter plusieurs data types distincts. Valider des Unions est intrinsèquement complexe parce que Pydantic essaie activement de coercer les données vers le type demandé. Un integer peut facilement devenir un string, et un string contenant des chiffres peut être parsé en un integer. Si le moteur de validation prenait simplement le premier match qu'il trouve, ton output changerait entièrement en fonction de l'ordre arbitraire dans lequel tu as listé les types dans ton code. Ce comportement rigide existe bel et bien, et ça s'appelle le mode Left to Right. Dans ce mode, le système évalue l'input par rapport au premier type défini dans l'Union. Si la validation réussit, il s'arrête immédiatement. Si elle échoue, il passe au deuxième type. Si ton field est typé comme string ou integer, dans cet ordre, et que tu passes l'integer 123, le mode Left to Right évalue la condition string en premier. Parce que l'integer 123 peut être facilement coercé en string 123, la validation passe. Ton integer est silencieusement converti en string uniquement parce que string a été écrit en premier. Voici le point clé. Par défaut, Pydantic évite ce piège en utilisant le Smart Mode. Au lieu de s'arrêter au premier match passable, le Smart Mode évalue l'input par rapport à tous les types possibles dans l'Union. Il compare ensuite les validations réussies et choisit le meilleur match en fonction de critères de scoring spécifiques. Le critère principal pour les types simples, c'est l'exactitude. Le Smart Mode pénalise lourdement la coercion de données. Pour en revenir à notre scénario précédent avec un field typé comme string ou integer. Quand tu passes l'integer 123, le Smart Mode teste les deux options. Il reconnaît que l'input peut être coercé en un string valide, mais il voit aussi que l'input est déjà un match parfait et exact pour un integer. Parce qu'un match exact a toujours un meilleur score qu'un match coercé, le Smart Mode renvoie correctement l'integer 123, peu importe quel type a été écrit en premier dans l'Union. Quand ton Union contient des data models complexes plutôt que des types basiques, le Smart Mode se base sur une métrique différente. Il compte le nombre de fields valides définis. Le moteur évalue le dictionnaire d'input par rapport à chaque model dans l'Union. Il calcule combien de fields dans l'input mappent exactement aux fields définis de chaque model. Le model qui absorbe avec succès le plus grand nombre d'input fields sans lever d'erreurs de validation est déclaré vainqueur. Ça empêche un model plus petit et moins spécifique d'avaler des données qui étaient clairement destinées à un model plus grand et plus détaillé dans la même Union. La Smart Validation garantit que tes données conservent leur forme originale précise à chaque fois que c'est possible, te protégeant des erreurs de coercion silencieuses qui sont notoirement difficiles à traquer en production. Merci d'avoir écouté, happy coding tout le monde !
9

Outil de pointe : Les Discriminated Unions

3m 15s

Boostez vos performances de validation. Vous apprendrez à utiliser les Discriminated Unions pour indiquer à Pydantic exactement quel schéma appliquer en fonction d'un champ spécifique.

Télécharger
Bonjour, c'est Alex de DEV STORIES DOT EU. Pydantic : Validation des données, épisode 9 sur 20. Valider un payload entrant contre vingt data models différents par tâtonnement, c'est un cauchemar pour les performances. Quand ton système reçoit un event générique, deviner quel schema appliquer gaspille des cycles CPU et génère des messages d'erreur super confus quand la validation échoue. Tu peux complètement éviter de jouer aux devinettes en utilisant un outil surpuissant : les Discriminated Unions. Une union standard dit à Pydantic qu'un field peut correspondre à plusieurs models différents. Par défaut, Pydantic prend la data entrante et la teste contre le premier model. Si ça échoue, il essaie le deuxième, et ainsi de suite. Ce parsing séquentiel est inefficace. Les Discriminated Unions résolvent ça en utilisant un tag explicite. Imagine que tu développes un pipeline d'analytics qui reçoit différents types d'events, comme un event click, un event scroll et un event purchase. Chaque event demande des fields différents. Le model click a peut-être besoin d'un ID d'élément, alors que le model purchase a besoin d'un montant de transaction. Pour configurer une Discriminated Union, tu ajoutes un field partagé à chaque model de ce groupe. Tu pourrais appeler ce field event type. Ensuite, tu assignes un type literal string à ce field. Le model click impose que le event type soit exactement la string click. Le model purchase impose strictement la string purchase. Ensuite, tu crées ton model de payload principal. Ce model a un seul field event, défini comme une union de tes models d'events spécifiques. C'est là que tu configures le discriminator. Tu enveloppes la définition de l'union dans une configuration de field Pydantic, et tu assignes la string event type à l'argument discriminator. Voici le point clé. Quand un payload arrive, Pydantic ne teste plus les models un par un. Il regarde directement la key event type dans la data entrante. Si la valeur est purchase, Pydantic route immédiatement tout le payload vers le model purchase. C'est un lookup direct. Si le montant de la transaction est manquant, le message d'erreur dit clairement qu'un field requis pour un event purchase est manquant, au lieu de générer un énorme pavé de texte qui explique pourquoi la data n'a pas matché avec tous les types d'events possibles. Ça, ça couvre une structure propre où chaque payload partage une key de premier niveau. Parfois, tu gères de la data tierce non structurée où le tag d'identification est imbriqué dans un autre objet, ou bien le bon model dépend de la présence de keys spécifiques plutôt que d'une seule valeur dédiée. Pour ces situations, Pydantic propose des callable discriminators. Au lieu de passer un nom de field en string à l'argument discriminator, tu passes une fonction custom. Cette fonction reçoit la data d'entrée brute, non validée. Tu écris la logique dans cette fonction pour inspecter le dictionary brut, trouver l'indice qui détermine le type de data, et retourner un simple tag en string qui représente le bon model. Pydantic exécute ta fonction en premier, récupère le tag en string, et l'utilise pour router la data vers le model précis dans l'union. Utiliser une Discriminated Union transforme la validation, qui passe d'un jeu de devinettes séquentiel à un lookup précis en temps constant. Merci d'avoir écouté, bonne journée à tous !
10

Pré-traitement avec les Before et Wrap Validators

3m 28s

Gérez les données entrantes désordonnées avant qu'elles ne touchent votre schéma. Vous apprendrez à utiliser les validateurs de champs Before et Wrap pour nettoyer les entrées brutes avant que Pydantic ne les évalue.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Validation des données, épisode 10 sur 20. Parfois, tes données entrantes sont tellement en vrac que le parsing standard échoue dès qu'elles touchent ton model. Tu dois intercepter et nettoyer l'input brut avant même que le framework n'essaie de le lire. C'est exactement ce que le pre-processing avec les validateurs Before et Wrap te permet de faire. Normalement, Pydantic fait un super boulot pour convertir automatiquement les données dans le bon type. Mais si la structure de base des données est complètement fausse, la conversion échoue immédiatement. Un validateur Before est conçu pour ce problème. C'est une fonction attachée à un champ qui s'exécute avant que Pydantic ne fasse son propre type checking ou sa conversion. Elle reçoit l'input brut, intact, exactement comme il a été passé au model. Imagine un scénario où ton model définit un champ qui exige strictement une liste d'entiers. Mais tu consommes une API externe qui envoie incorrectement ces données sous la forme d'une seule string continue de nombres séparés par des virgules, comme la string un virgule deux virgule trois. Pydantic s'attend à un array, voit une seule string, et la rejette avec une erreur de validation. Tu corriges ça en écrivant un validateur Before. À l'intérieur de ta fonction de validation, tu regardes l'input brut. Tu vérifies si la valeur est une string. Si c'est le cas, tu split cette string à chaque virgule, ce qui crée une liste de strings individuelles. Tu n'as pas besoin de convertir ces caractères en entiers toi-même. Tu retournes simplement la liste nouvellement créée. Pydantic prend le relais à partir de là. Il voit la liste qu'il attendait, lance sa coercition interne standard, et transforme ces valeurs de type string en entiers pour toi. Tu as juste eu besoin de corriger la forme structurelle des données. Ça couvre les inputs qui s'exécutent avant la logique principale. Le niveau de contrôle suivant, c'est le validateur Wrap. Les validateurs Wrap sont l'outil de validation le plus flexible que Pydantic propose. Au lieu de juste s'exécuter avant l'étape de validation, un validateur Wrap encapsule littéralement le moteur de validation interne de Pydantic pour ce champ. Quand tu écris un validateur Wrap, ta fonction reçoit deux arguments. Le premier, c'est l'input brut, tout comme le validateur Before. Le deuxième argument est une fonction handler. Ce handler représente la logique de validation et de coercition au cœur de Pydantic. C'est là que ça devient intéressant. Tu décides exactement quand, ou même si, cette fonction handler s'exécute. Le flux logique est entièrement entre tes mains. Tu peux inspecter l'input brut et le modifier. Ensuite, tu appelles explicitement le handler, en lui passant tes données nettoyées. Pydantic lance son type checking interne sur ce que tu as fourni et renvoie la valeur entièrement parsée à ton validateur. Tu peux ensuite modifier à nouveau cette valeur parsée avant de la passer au model final. Comme tu contrôles quand le handler s'exécute, tu peux le placer dans un bloc try except standard. Si la validation interne de Pydantic lève une erreur, tu la catch directement là, dans le validateur Wrap. Tu peux logger l'erreur, modifier les données et réessayer, ou juste retourner une valeur par défaut safe. Tu peux même écrire une logique qui skip complètement le handler pour certains inputs spécifiques, en contournant totalement la validation standard. Les validateurs Before nettoient les mauvaises formes d'input pour que Pydantic puisse les lire, tandis que les validateurs Wrap te donnent une autorité totale sur tout le cycle de vie de la validation autour d'un seul champ. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
11

Post-traitement avec les After et Plain Validators

3m 14s

Appliquez des règles de logique métier strictes. Vous apprendrez à utiliser les After Validators pour vérifier les données déjà analysées, et les Plain Validators pour court-circuiter entièrement Pydantic.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Data Validation, épisode 11 sur 20. Vérifier si une string correspond à un format d'email, c'est simple. Mais vérifier que les données respectent une logique métier stricte, comme faire des requêtes croisées avec un système externe ou appliquer des règles mathématiques spécifiques, ça demande un endroit sûr pour exécuter du code custom. C'est exactement ce que permet le post-processing avec les validateurs After et Plain. Quand tu définis un champ dans un model Pydantic, la librairie vérifie automatiquement l'input par rapport au type hint. Mais les types ont leurs limites. Un integer reste un integer, qu'il vaille un ou un million. Pour imposer des règles qui vont au-delà des types de base, tu ajoutes des fonctions de validation custom. Pydantic te permet d'injecter ces fonctions dans le lifecycle de validation. Le point d'injection le plus courant, c'est le validateur After. Comme son nom l'indique, il s'exécute après que Pydantic a terminé son parsing interne et sa type coercion. Et voici le point clé. Quand ta fonction custom reçoit les données dans un validateur After, Pydantic garantit que les données correspondent déjà au type du champ. Tu n'as pas besoin d'écrire du code boilerplate pour gérer la conversion de type ou catcher des types de données inattendus. Imagine un scénario où tu dois t'assurer qu'un champ integer est un nombre pair. Tu définis un model avec un champ typé comme un integer. Ensuite, tu écris une fonction custom qui prend une valeur en argument. Vu que tu configures cette fonction comme un validateur After, tu sais que la valeur est absolument un integer. Tu utilises simplement l'opérateur modulo pour vérifier si diviser la valeur par deux laisse un reste. Si le reste n'est pas zéro, tu raises une ValueError Python standard avec un message custom. Si le reste est zéro, tu return la valeur. Pydantic prend cette valeur retournée et l'assigne au model. La division du travail est propre. Pydantic impose le type, et toi, tu imposes la règle métier. Parfois, le parsing par défaut de Pydantic te gêne. C'est là qu'intervient le validateur Plain. Un validateur Plain remplace complètement la validation interne de Pydantic pour un champ spécifique. Pydantic s'écarte et passe l'input brut, non validé, directement à ta fonction custom. Tu utilises un validateur Plain quand les règles de coercion standards ne correspondent pas à ton use case, ou quand tu gères une structure de données très custom que Pydantic ne comprend pas nativement. Dans ce scénario, ta fonction est responsable de tout. Elle reçoit l'input brut, fait le type checking nécessaire, convertit les données et applique la logique métier. Si quelque chose échoue, ta fonction doit raise une ValueError ou une AssertionError. Si elle réussit, elle return la valeur finale et propre pour le model. Tu attaches ces deux validateurs aux champs en utilisant des decorators Pydantic sur des class methods, ou en les ajoutant comme metadata directement dans le type hint via des annotations. Le choix entre les deux dépend de la quantité de travail que tu veux faire toi-même. Utilise un validateur After quand tu veux que Pydantic fasse le gros du travail de conversion de type, et opte pour un validateur Plain uniquement quand tu as besoin d'un contrôle absolu sur le parsing de l'input brut depuis zéro. Merci de ton écoute — à la prochaine.
12

Hooks de validation au niveau du modèle

3m 12s

Validez les interactions entre plusieurs champs. Vous apprendrez à utiliser le décorateur model_validator pour appliquer des règles qui dépendent de l'ensemble du payload.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Data Validation, épisode 12 sur 20. Valider des champs de manière isolée fonctionne parfaitement, jusqu'au moment où ta logique métier exige que le champ B ne soit défini que si le champ A a une valeur spécifique. Quand l'intégrité des données repose sur l'interaction de plusieurs champs, tu as besoin de Model-Level Validation Hooks. Dans Pydantic, tu gères les champs interdépendants en utilisant le décorateur model validator. Contrairement aux field validators qui se concentrent sur une seule donnée entrante, un model validator examine toute la structure de données en une seule fois. Pydantic propose trois modes pour ce décorateur : before, after, et wrap. Ils déterminent exactement à quel moment ta logique personnalisée s'exécute pendant le cycle de vie du parsing. Appliquons ça à un model d'inscription utilisateur standard. Tu as deux champs : password et password repeat. Une vérification au niveau du champ peut vérifier la longueur ou la complexité, mais elle ne peut pas comparer les deux. Pour ça, tu utilises un model validator en mode after. Le mode after s'exécute une fois que Pydantic a parsé et validé avec succès tous les champs individuels. À ce stade, ta fonction de validation reçoit le model instancié lui-même. Tu écris simplement une logique qui vérifie si l'attribut password du model est égal à son attribut password repeat. S'ils sont différents, tu lèves une ValueError. Voici le point essentiel. Quand tu utilises le mode after, ta fonction doit explicitement retourner l'instance du model, généralement appelée self, à la fin de la méthode. Si tu oublies de retourner self, Pydantic va ignorer tes données validées et ne rien retourner. Parfois, tu as besoin d'intercepter les données plus tôt. C'est là qu'intervient le mode before. Un model validator en mode before s'exécute avant que Pydantic ne tente le moindre parsing ou type coercion. Au lieu d'une instance de model typée, ta fonction reçoit l'input brut, qui est généralement un dictionnaire. Tu utilises ce mode quand la structure des données brutes est en désordre et a besoin d'être ajustée avant même que la validation standard ne puisse commencer. Par exemple, si des requêtes d'une API legacy envoient des configurations de mot de passe dans un dictionnaire imbriqué, un before validator peut extraire ces strings et les aplatir dans les clés de premier niveau que ton model Pydantic attend. La fonction retourne ensuite le dictionnaire modifié, en le passant à la suite de la chain. Le troisième mode est wrap. C'est pour avoir un contrôle total sur le cycle de vie de la validation. Un wrap validator prend les données d'input brutes et une fonction handler. Tu exécutes ta logique de pre-processing, tu appelles explicitement le handler pour déclencher la validation interne de Pydantic, puis tu exécutes un post-processing sur le résultat. Tu utilises ça quand tu as besoin d'attraper des erreurs de validation internes de Pydantic, de les logger dans un système externe, et peut-être de retourner un message d'erreur modifié ou un objet de fallback par défaut. Choisir le bon mode est juste une question de timing. Utilise before pour formater l'input brut, after pour comparer des champs fortement typés, et wrap pour contrôler l'exécution de la validation elle-même. Si tu trouves ces épisodes utiles et que tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon. C'est tout pour cet épisode. À la prochaine !
13

Sérialisation : Exporter des données en toute sécurité

3m 34s

Contrôlez la façon dont vos données quittent le système. Vous apprendrez les différences entre l'exportation vers des dicts Python et des chaînes JSON, et comment exclure les champs non définis ou par défaut.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Data Validation, épisode 13 sur 20. Faire entrer des données valides dans ton système n'est que la moitié du travail. Quand vient le moment de renvoyer ces données à un frontend, tu remarques souvent que tes payloads sont gonflés avec des champs vides et des valeurs par défaut que l'utilisateur n'a jamais vraiment fournies. La serialization, ou le fait de dump les données de façon sécurisée, c'est comme ça que tu nettoies ce flux sortant. Une fois que tes données sont bien au chaud dans un model Pydantic, tu finis toujours par devoir les extraire pour les envoyer ailleurs. Tu as deux façons principales de faire ça. La première, c'est d'appeler model dump. Cette méthode lit ton model et renvoie un dictionary Python classique. La deuxième, c'est d'appeler model dump json. Cette méthode saute l'étape du dictionary et renvoie une string JSON complètement formatée, prête à transiter sur le réseau. La différence entre les deux va un peu plus loin qu'un simple dictionary contre une string. Tout se joue au niveau des modes de serialization. Par défaut, model dump fonctionne en mode Python. Si ton model contient un type complexe, comme un objet datetime, le dictionary qui en résulte contiendra toujours un objet datetime Python. D'un autre côté, model dump json fonctionne en mode JSON. JSON ne sait pas ce qu'est un objet datetime Python, donc Pydantic le convertit automatiquement en une représentation sous forme de string standard. Voici le point clé. Tu peux en fait forcer l'output du dictionary à utiliser le mode JSON. Si tu appelles model dump et que tu passes l'argument mode défini sur json, Pydantic renvoie un dictionary où tous les types complexes ont déjà été traduits dans des formats basiques et JSON-safe, comme des strings et des integers. Ça, ça gère les types, mais tu dois encore gérer la forme du payload. Prends l'exemple d'un model de profil utilisateur qui renvoie des données à un frontend. Le model peut définir vingt champs possibles. Un nouvel utilisateur s'inscrit et ne fournit que son nom et son email. Les dix-huit autres champs retombent sur des empty strings, des nulls, ou des URL d'avatar par défaut. Si tu dump ce model normalement, tu envoies les vingt champs au frontend. Pour corriger ça, Pydantic propose trois keyword arguments spécifiques que tu peux passer à l'une ou l'autre des méthodes dump. Le plus précis, c'est exclude unset. Quand tu mets exclude unset sur true, Pydantic traque exactement quels champs ont été remplis quand le model a été créé. Il va seulement dump le nom et l'email. Les dix-huit champs par défaut sont complètement laissés de côté dans le dictionary ou la string JSON. Ça garantit que tu ne leak jamais de données de fallback que l'utilisateur n'a pas vraiment soumises. Si tu veux un comportement légèrement différent, tu peux utiliser exclude defaults. Ce flag dit à Pydantic d'omettre tout champ qui correspond actuellement à sa valeur par défaut. Il se fiche de savoir si l'utilisateur a explicitement soumis cette valeur par défaut ou si le système l'a remplie automatiquement. Si la valeur correspond à la valeur par défaut, elle est retirée de l'output. Enfin, il y a exclude none. Mets ça sur true, et Pydantic va retirer tout champ dont la valeur est actuellement none. C'est purement une vérification de valeur, et ça ignore complètement les valeurs par défaut ou le tracking des unset. Ces flags d'exclusion te donnent un contrôle total sur ton trafic réseau et tes réponses d'API. Garde tes models internes parfaitement complets, mais utilise tes méthodes de dump pour t'assurer que tes payloads externes restent exactement aussi légers qu'ils doivent l'être. Merci d'avoir écouté. À la prochaine !
14

Personnaliser la logique de sérialisation

3m 41s

Modifiez la façon dont vos types sont représentés à la sortie. Vous apprendrez à écrire des sérialiseurs personnalisés de Field et de Model pour muter les données pendant la phase d'exportation.

Télécharger
Bonjour, ici Alex de DEV STORIES DOT EU. Pydantic : Validation des données, épisode 14 sur 20. Et si tu stockes une date en interne sous forme d'objet datetime Python, mais que ton contrat d'API frontend exige un timestamp Unix brut sous forme d'entier ? Tu pourrais boucler sur tes données juste avant de les envoyer, mais c'est brouillon et source d'erreurs. La méthode la plus propre, c'est de personnaliser la logique de sérialisation directement dans tes modèles Pydantic. Pydantic te donne des décorateurs pour intercepter le moment précis où un modèle se transforme à nouveau en dictionnaire ou en JSON. On va commencer par les field serializers. Un field serializer cible un attribut spécifique. Pour en créer un, tu écris une méthode classique dans ta classe de modèle et tu places le décorateur field serializer juste au-dessus. Tu passes au décorateur le nom du champ que tu veux modifier. Reprenons ce scénario avec le datetime. Tu as un modèle avec un attribut appelé created at, typé comme un datetime Python standard. À l'intérieur du modèle, tu crées une méthode appelée serialize created at. Le nom de la méthode n'a pas d'importance. Au-dessus, tu places le décorateur field serializer, en pointant vers le champ created at. La méthode prend la valeur du datetime en entrée. À l'intérieur de la méthode, tu appelles la fonction timestamp standard sur ce datetime et tu retournes l'entier qui en résulte. Maintenant, à chaque fois que le modèle dump ses données, Pydantic intercepte le champ created at, exécute ta méthode personnalisée, et renvoie un entier propre au lieu d'une string au format ISO. Voici le point essentiel. Les serializers fonctionnent selon deux modes distincts : plain et wrap. Le mode plain est le mode par défaut. Quand un serializer est en mode plain, Pydantic ignore complètement sa propre logique interne pour ce champ et exécute uniquement ton code personnalisé. C'est un override complet. Mais parfois, tu as besoin d'exécuter d'abord la logique par défaut, puis de modifier le résultat. Ou peut-être que tu veux attraper les erreurs liées au comportement par défaut. C'est là que tu utilises le mode wrap. Pour l'activer, tu passes mode equals wrap dans le décorateur. En mode wrap, ta méthode reçoit un second argument appelé handler. Ce handler est une référence à la logique de sérialisation interne de Pydantic. Tu peux appeler le handler pour obtenir la sortie par défaut, l'inspecter, la modifier, ou faire un fallback dessus si ta logique personnalisée échoue. Ça, c'est pour les champs individuels. Si tu as besoin de changer la structure de toute la sortie, tu utilises un model serializer. Le setup est presque identique, mais le décorateur se place au-dessus d'une méthode qui opère sur l'instance complète du modèle. Au lieu de recevoir la valeur d'un seul champ, la méthode accède aux attributs du modèle lui-même. Si tu mets un model serializer en mode plain, tu retournes une toute nouvelle structure de dictionnaire from scratch. Si tu le mets en mode wrap, ta méthode prend un argument handler, tout comme le field serializer. Tu appelles d'abord le handler pour obtenir le dictionnaire standard du modèle. Ensuite, tu peux ajouter de nouvelles clés top-level, supprimer des données privées, ou aplatir des structures imbriquées avant de retourner le dictionnaire final. L'aspect le plus puissant de ces décorateurs, c'est qu'ils découplent tes types Python internes de tes contrats d'API externes, en gardant une validation stricte à l'entrée et un formatage précis à la sortie. C'est tout pour cette fois. Merci d'avoir écouté, et continue à développer !
15

Générer un JSON Schema à partir de modèles

3m 44s

Transformez vos modèles en contrats d'API auto-documentés. Vous apprendrez à générer des JSON Schemas conformes à OpenAPI et à injecter des exemples directement dans le schéma.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Validation des données, épisode 15 sur 20. Si tes schémas d'API sont déjà strictement typés en Python, devoir maintenir un fichier YAML séparé pour ta documentation OpenAPI est une énorme perte de temps. Tu te retrouves à maintenir deux sources de vérité qui finissent inévitablement par diverger. Générer du JSON Schema directement à partir de tes modèles résout ce problème de synchronisation. Chaque modèle Pydantic vient avec une méthode appelée model json schema. Quand tu appelles cette méthode, Pydantic inspecte ton modèle. Il lit les fields, les types, les valeurs par défaut et les contraintes de validation. Il traduit ensuite toute cette logique Python interne en un dictionnaire JSON Schema standard. Plus précisément, Pydantic génère le Draft 2020-12 de la spécification JSON Schema. C'est ça qui est important. Comme l'output respecte ce standard largement accepté, il est nativement compatible avec OpenAPI. Tu définis tes règles de validation strictes une seule fois en Python, et le framework fournit automatiquement la définition de schema exacte dont tes consommateurs externes ont besoin. Il n'y a aucune traduction manuelle à faire. La génération de schema standard gère parfaitement les types et les contraintes de base. Mais parfois, tu as besoin de communiquer de la business logic ou des formats spécifiques qui ne peuvent pas être déduits d'un simple type hint Python. Imagine un scénario où tu construis un modèle Configuration pour un nouveau service. Le modèle contient un field qui accepte un dictionnaire de settings custom. L'équipe frontend a besoin de savoir exactement à quoi ressemble un payload valide, plutôt que de juste savoir que c'est un objet générique. Pour résoudre ça, tu utilises une feature appelée json schema extra. Ce paramètre te permet d'injecter des metadata custom arbitraires directement dans le JSON Schema généré. Tu peux l'utiliser pour ajouter des exemples mock, des descriptions custom, ou des marqueurs de mots-clés spécifiques que ton API gateway pourrait exiger. Tu peux appliquer json schema extra à deux niveaux distincts. Tu peux l'attacher à un field individuel, ou tu peux l'appliquer au modèle entier. Pour fournir un exemple mock pour ce field settings spécifique, tu définis ton modèle Configuration. Pour l'attribut settings complexe, tu lui assignes une fonction Field. À l'intérieur de cette fonction Field, tu fournis l'argument json schema extra. Tu lui passes un dictionnaire contenant la clé JSON Schema standard nommée examples. La valeur mappée à cette clé est une liste contenant ton payload de configuration mock exact. Alternativement, si tu veux documenter le modèle entier plutôt qu'un seul field, tu définis un dictionnaire model config sur la classe. À l'intérieur de ce dictionnaire de configuration, tu fournis json schema extra avec un exemple au niveau du schema. Cette approche est super utile quand tu veux montrer comment plusieurs fields interagissent ensemble dans un request body complet. Quand tu exécutes model json schema sur ton modèle Configuration, Pydantic construit l'arbre de schema standard. Quand il atteint tes fields ou ta configuration de modèle, il merge ton dictionnaire examples custom directement dans l'output standard. Le tooling frontend lit ce schema, parse la propriété examples, et affiche immédiatement le payload mock aux développeurs. Ils savent exactement quoi envoyer, et ton code Python reste la seule source de vérité. La vraie puissance de la génération de schema Pydantic, c'est que n'importe quel outil externe construit pour l'écosystème JSON Schema peut immédiatement consommer tes règles de validation Python sans intégration custom. Merci d'avoir passé quelques minutes avec moi. À la prochaine, porte-toi bien.
16

RootModel : Quand votre payload n'est pas un dictionnaire

3m 08s

Gérez gracieusement les payloads JSON non standard. Vous découvrirez comment RootModel vous permet d'analyser des tableaux et des primitives au niveau racine tout en conservant les pouvoirs du BaseModel.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Validation de données, épisode 16 sur 20. Les modèles standards supposent que ton payload JSON entrant est un objet mappé avec des clés et des valeurs. Mais que se passe-t-il quand un endpoint doit accepter directement un array top-level, ou juste une string toute seule, sans l'encapsuler dans un dictionnaire ? C'est exactement ce que RootModel : Quand ton payload n'est pas un dictionnaire, est conçu pour gérer. Quand tu utilises un base model standard, Pydantic mappe les attributs de ta classe à des clés JSON. Si tu envoies une liste brute à un modèle standard, comme un array JSON de nombres, la validation échoue. Il s'attend à une structure de dictionnaire. Pour contourner ça, les développeurs forcent souvent le client à modifier le payload. Ils créent une clé factice, par exemple items, et encapsulent l'array dans un objet. Tu finis par tordre le design de ton API juste pour satisfaire ta librairie de validation. RootModel élimine cette friction. C'est un modèle Pydantic spécial, conçu spécifiquement pour les payloads dont la structure externe est une liste, un tuple, ou un type primitif comme un entier ou une string. Prends l'exemple d'un endpoint de bulk-delete. Tu veux que le client envoie un array JSON brut contenant des user IDs entiers, et rien d'autre. Pour gérer ça, tu importes RootModel depuis Pydantic. Tu définis une nouvelle classe, par exemple UserIdList, et tu la fais hériter de RootModel. Tu paramètres cet héritage avec une liste d'entiers. Quand l'array JSON brut arrive sur le serveur, tu le passes directement à la méthode model validate de ta classe UserIdList. Pydantic accepte l'array top-level nativement. Il itère sur le payload, s'assure que chaque élément est un entier valide, et renvoie une instance de modèle entièrement validée. Voici le point clé. Même s'il valide une liste plate, un RootModel fournit exactement la même interface qu'un modèle classique. Tu as toujours accès aux méthodes standards. Tu peux appeler model dump pour reconvertir les données en objets Python, ou model dump json pour générer une string brute. Comme il n'y a pas de champs nommés dans ton payload, tu as besoin d'un moyen d'accéder aux données une fois qu'elles sont validées. Pydantic stocke les données parsées dans un seul attribut nommé exactement root. Si tu veux boucler sur ces user IDs validés, tu itères simplement sur l'attribut root de ton instance de modèle. Ce mécanisme n'est pas restreint aux listes. Tu peux définir un RootModel pour une seule string ou un entier. Si tu reçois un payload de type string tout seul, mais que tu dois le passer par des vérifications strictes de longueur ou du pattern matching, le définir comme un RootModel de type string te permet d'attacher ces règles de validation nativement. La donnée reste une simple string dans le payload, mais gagne la protection complète du moteur de validation. Chaque fois que tu te retrouves à inventer une clé de dictionnaire juste pour que Pydantic ait quelque chose à parser, tu utilises le mauvais outil. Utilise RootModel pour adapter ta couche de validation à ton contrat d'API, plutôt que de modifier ton contrat d'API pour satisfaire ta couche de validation. Merci d'avoir écouté. Prenez soin de vous, tout le monde.
17

Dataclasses standards vs Dataclasses Pydantic

3m 33s

Apportez la validation à vos classes Python natives. Vous apprendrez quand utiliser le décorateur dataclass de Pydantic pour moderniser des bases de code existantes sans tout réécrire.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Data Validation, épisode 17 sur 20. Tu as une codebase massive construite entièrement sur des dataclasses Python standard, et tu réalises que tu as désespérément besoin de runtime validation. Tu penses peut-être que tu dois tout réécrire pour hériter d'un BaseModel. Ce n'est pas le cas. Aujourd'hui, on va comparer les dataclasses standard et les dataclasses Pydantic. La bibliothèque standard de Python fournit un décorateur dataclass qui est excellent pour réduire le boilerplate. Il écrit les méthodes d'initialisation, de représentation et d'égalité pour toi. Cependant, il fait aveuglément confiance à tes inputs. Si tu déclares un attribut age comme un integer et que tu lui passes une string, la dataclass standard accepte simplement la string. Elle fournit des type hints pour l'analyse statique, mais n'offre aucune runtime safety. Pydantic résout ce problème avec son propre décorateur dataclass. Il est conçu spécifiquement comme un drop-in replacement pour la version de la bibliothèque standard. Tu gardes exactement la même structure de classe. Tu n'ajoutes aucune base class. Il te suffit de changer ton import pour récupérer le décorateur depuis le module pydantic dot dataclasses au lieu de la bibliothèque standard. Prends cette legacy codebase construite sur des dataclasses standard. Tu trouves une dataclass qui gère un objet de configuration. Tu remplaces le décorateur standard par le décorateur Pydantic. Instantanément, à chaque fois que ton application crée cet objet de configuration, Pydantic intercepte l'initialisation. Il lit tes type hints existants et les applique. Si un type invalide est passé, Pydantic tente de le coercer. Si la coercion échoue, il lève immédiatement une validation error. Tu gagnes des assignments stricts et type-checkés, avec zéro changement structurel dans ton arbre d'héritage. Voici le point clé. Si les deux options t'offrent la validation, tu dois comprendre la différence entre une dataclass Pydantic et un BaseModel standard. Ils gèrent les données sous-jacentes différemment. Un BaseModel est fondamentalement construit autour du dictionary parsing et fournit un large éventail de built-in methods pour exporter des données. Une dataclass Pydantic reste une classe Python standard à la base, en gardant son memory footprint et son comportement traditionnels. Comme ça reste une classe standard, la façon dont Pydantic applique la validation change. Quand tu instancies une dataclass Pydantic, les arguments sont copiés. Les données passent par le core validation engine de Pydantic, qui parse et construit de nouveaux objets pour correspondre à tes type hints. Il ne fait pas juste référencer les mutable inputs d'origine que tu as fournis. Si tu passes une liste à une dataclass Pydantic, le validateur la traite, valide les éléments internes, et assigne une toute nouvelle liste à l'instance. L'input list d'origine et l'attribut sur ta dataclass ne sont plus le même objet en mémoire. Ce comportement de copie garantit que tes données respectent strictement le schema sans muter les input variables d'origine. L'utilité principale de la dataclass Pydantic est de faire le pont entre les paradigmes Python standard et une validation rigoureuse. Si tu as besoin d'un clean migration path pour du legacy code qui utilise déjà des dataclasses standard, il te suffit de remplacer le décorateur pour gagner une type safety instantanée tout en préservant toute la sémantique de tes classes existantes. Si tu apprécies le podcast et que tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon. C'est tout pour cet épisode. Merci pour ton écoute, et continue à développer !
18

Ajustement fin de la configuration du modèle

3m 02s

Contrôlez la rigueur de l'ensemble de votre modèle. Vous apprendrez à utiliser le ConfigDict pour interdire les attributs supplémentaires, geler les instances et valider les assignations.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Data Validation, épisode 18 sur 20. Par défaut, Pydantic ignore silencieusement les clés JSON supplémentaires que tu lui envoies. Dans une API stricte, avaler des données inconnues sans avertissement est un risque de sécurité énorme. Pour corriger ça, tu dois affiner la configuration du modèle. Pour changer le comportement global d'un modèle, tu définis un attribut de classe nommé model config. Tu lui assignes un ConfigDict, qui est un dictionnaire typé importé directement de Pydantic. Tu places cette assignation directement dans ton modèle, à côté de tes définitions de champs. Comme ConfigDict est typé, ton éditeur de code détectera les fautes de frappe si tu essaies de passer une option de configuration invalide. Les règles que tu mets dans ce dictionnaire vont dicter comment le modèle entier parse, valide et stocke les données. Construisons un modèle de paramètres de sécurité stricts pour une application. Un client malveillant pourrait envoyer un payload JSON avec des champs inattendus, peut-être pour essayer d'injecter un flag admin ou d'écraser un paramètre caché. Par défaut, Pydantic règle le comportement des champs extra sur ignore. Il lit les champs qu'il attend, supprime silencieusement toutes les données inconnues, et crée le modèle. Pour fermer cette faille, tu ajoutes le paramètre extra à ton ConfigDict et tu mets sa valeur sur la string forbid. Maintenant, si un client envoie une clé inattendue, Pydantic lève immédiatement une erreur de validation. La requête échoue complètement, en rejetant explicitement le mauvais payload avant même que la logique de ton application ne le traite. Ça gère la frontière entre le monde extérieur et ton système. Mais que se passe-t-il à l'intérieur de ton système une fois le modèle créé ? Normalement, Pydantic valide les données uniquement pendant l'initialisation. Si un autre développeur écrit du code qui modifie un attribut sur une instance de modèle existante plus tard, Pydantic n'intervient pas. Tu pourrais accidentellement assigner une raw string à un champ integer, et le modèle l'accepterait. Pour éviter ça, tu peux définir validate assignment sur true dans ton ConfigDict. Avec ça d'activé, à chaque fois qu'un attribut est modifié en mémoire, Pydantic intercepte le changement et exécute exactement la même logique de validation qu'il utilise pendant la création. Parfois, même valider les mutations est trop permissif pour des configurations de sécurité. Tu pourrais vouloir une garantie absolue que les paramètres ne peuvent pas être modifiés en mémoire par aucune partie de ton code une fois qu'ils ont passé la vérification initiale. C'est là que ça devient intéressant. Tu peux définir le paramètre frozen sur true dans la configuration de ton modèle. Ça rend l'instance entière du modèle immuable. Si une fonction en aval essaie de mettre à jour un champ, Pydantic lève une erreur. Un modèle frozen agit exactement comme un tuple Python. Comme il ne peut pas changer, un modèle frozen est totalement sûr à partager entre différentes parties de ton application, et il peut même être utilisé en toute sécurité comme clé dans un dictionnaire Python ou un cache en mémoire. En empilant ces options de configuration dans ton ConfigDict, tu transformes un modèle, passant d'un parser de données flexible à une frontière absolue et inflexible. C'est tout pour cet épisode. Merci d'avoir écouté, et continue à développer !
19

Configuration d'application avec Pydantic Settings

3m 21s

Gérez vos variables d'environnement comme un pro. Vous apprendrez comment le paquet pydantic-settings automatise l'analyse des secrets, des fichiers dot-env et des préfixes.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Data Validation, épisode 19 sur 20. Arrête de récupérer des strings de l'operating system en croisant les doigts pour qu'elles se castent proprement en integer. Tu as probablement déjà écrit des dizaines de fichiers utilitaires qui wrappent les appels standards aux variables d'environnement, juste pour éviter qu'une valeur de configuration manquante ne fasse crasher ton application au runtime. La configuration d'application avec Pydantic Settings remplace tout ce boilerplate. Alors que le Pydantic standard gère la data validation en général, gérer les variables d'environnement nécessite d'installer le package séparé pydantic-settings. Ce package fournit une classe spécifique appelée BaseSettings. Au lieu de fetcher manuellement les variables et d'écrire une logique de parsing custom, tu déclares une classe qui hérite de BaseSettings. Tu définis tes champs de configuration exactement comme un model Pydantic standard, avec les type hints Python et les valeurs par défaut. Quand tu instancies cette classe, Pydantic lit automatiquement les variables d'environnement de ton système. Il mappe les noms de variables aux attributs de ta classe, de manière case-insensitive par défaut. Si tu as défini un champ database timeout comme un integer, et que la variable d'environnement fournit une string, Pydantic cast cette string en un véritable objet integer. Si la variable d'environnement contient du texte arbitraire au lieu d'un nombre, Pydantic lève une validation error claire immédiatement au startup de l'application. Ton programme fail fast, au lieu de crasher de manière imprévisible plus tard pendant un appel actif à la database. Dans les environnements plus larges, les noms de variables globales entrent souvent en collision. Tu peux avoir plusieurs services qui tournent sur le même host, qui cherchent tous une variable simplement nommée database URL. BaseSettings résout ça en te permettant de définir un environment prefix dans la configuration du model. Si tu définis le préfixe à app underscore, Pydantic arrête de chercher des correspondances exactes de noms de champs. À la place, pour remplir un champ nommé database URL, il cible spécifiquement la variable d'environnement app underscore database URL. Le code de ton application Python accède toujours à la propriété simplement comme database URL, cachant entièrement le préfixe de l'operating system à ta business logic. Voici le point clé. Tu n'as pas besoin d'aplatir tes objets Python juste pour lire des variables d'environnement. La configuration devient souvent complexe, nécessitant des data structures imbriquées. Tu pourrais avoir une classe settings principale qui inclut un sub-model dédié pour les database settings, et un autre pour le logging. Pydantic supporte la résolution de ces structures imbriquées en utilisant une convention en double underscore. Si ta classe settings principale a un champ appelé database, qui pointe lui-même vers un model contenant un champ timeout, Pydantic cherchera une variable d'environnement nommée database double underscore timeout. Si tu utilises un préfixe, il le prepend naturellement aussi, ce qui donne quelque chose comme app underscore database double underscore timeout. Ce mécanisme te permet de maintenir des objets de configuration hiérarchiques et strictement typés dans ton code source, tout en les mappant proprement à des variables d'environnement standards et flat. La vraie valeur de BaseSettings n'est pas juste d'éliminer le boilerplate, c'est de garantir que si ton application démarre avec succès, tout son state de configuration est pleinement présent, explicitement typé, et totalement safe à consommer. Merci d'avoir écouté, happy coding tout le monde !
20

Sous le capot : Core Schemas personnalisés

3m 30s

C'est le dernier épisode de la série ! Prenez le contrôle ultime du moteur de validation. Vous apprendrez à écrire une méthode __get_pydantic_core_schema__ pour apprendre au cœur en Rust à gérer des objets Python complètement étrangers.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Pydantic : Validation de données, épisode 20 sur 20. Tu intègres une library rigide et non documentée d'une autre équipe, et tu dois faire passer ses objets à travers ton pipeline de validation strict. L'objet n'a absolument aucune notion de Pydantic, et tu ne peux pas toucher à son code source. Quand les annotations et les validateurs simples ne suffisent pas, tu dois parler directement au moteur, et ça veut dire ouvrir le capot pour écrire des core schemas custom. Normalement, Pydantic comprend comment valider tes données en lisant les type hints. Quand tu lui passes un objet inconnu, il se prend un mur. Pour corriger ça, tu définis une méthode qui s'appelle dunder get pydantic core schema. Cette méthode agit comme une couche de traduction directe. Elle bypasse les wrappers Python de haut niveau et envoie les instructions directement à Pydantic Core, le moteur Rust sous-jacent qui gère la vraie logique de validation. Quand tu implémentes cette méthode, elle reçoit le type source et un handler. Le handler fonctionne exactement comme un middleware dans un framework web. Tu n'as pas besoin d'écrire tout le schéma de validation from scratch. Tu peux demander au handler de générer le schéma par défaut pour un type spécifique, puis wrapper ta propre logique custom autour de ce résultat. Prends l'exemple d'un wrapper de connexion à une base de données legacy. Imagine que la seule façon d'initialiser cet objet, c'est de lui passer un entier spécifique, comme un ID de connexion. Tu veux que Pydantic accepte un entier qui vient d'une requête API, le valide, et te renvoie l'objet de connexion complètement instancié. Comme tu ne peux pas modifier la classe legacy directement, tu définis un type custom en utilisant les annotations Python. À l'intérieur de cette annotation, tu fournis ta méthode core schema custom. Voici le point clé. Au lieu d'écrire des dictionnaires bruts, tu utilises le module core schema de Pydantic, qui fournit des helpers pour construire ces structures en toute sécurité. D'abord, tu demandes au handler de construire un schéma d'entier standard. Ensuite, tu construis un chain schema. Tu dis au moteur de lancer la validation d'entier standard en premier. Si l'input est vraiment un entier, le moteur le passe à une fonction Python custom que tu fournis. Cette fonction prend l'ID de connexion, initialise le wrapper de base de données legacy, et retourne l'objet. Enfin, tu ajoutes un instance check schema à la chain, pour garantir que l'output final est exactement la classe legacy que tu attends. C'est là que ça devient intéressant. Tu retournes cette structure imbriquée à Pydantic. Sous le capot, Pydantic prend ces définitions de dictionnaires imbriquées et les compile en un graphe d'exécution Rust natif. Tu as programmé le moteur Rust depuis Python, en lui disant étape par étape comment ingérer un entier brut, le valider, et construire un objet inconnu en toute sécurité et à vitesse maximale. Ça représente le niveau d'intégration le plus bas que Pydantic offre, te donnant un contrôle total sur l'arbre de validation sans sacrifier les performances. Comme c'est notre dernier épisode, je t'encourage vivement à plonger dans la documentation officielle de Pydantic et à essayer de construire un core schema custom par toi-même. C'est la meilleure façon de bien comprendre comment le moteur réfléchit vraiment. Tu peux aussi visiter dev stories dot eu pour suggérer des sujets que tu aimerais voir abordés dans de futures séries. C'est tout pour aujourd'hui. Merci d'avoir écouté — va builder un truc cool.