https://a.storyblok.com/f/270183/1368x665/282a97b9c0/26jul-pydantic_using_vonage_verify-blog_r1.jpg

À la recherche de la validation : la validation des données en Python avec Pydantic et Vonage Verify

Publié le July 30, 2026

Temps de lecture : 18 minutes

Cet article de blog présente Pydantic, la bibliothèque de validation de données très répandue pour Python. Il comprend une démonstration des avantages offerts par Pydantic à l'aide de la Verify API de Vonage. 

Introduction

Qu'est-ce que le « duck typing » en Python ?

Pour comprendre pourquoi Pydantic est une bibliothèque si utile, il est important de comprendre d’abord comment fonctionne le typage en Python. En programmation, le « typage » désigne les systèmes de classification et de catégorisation des données. Le typage des données détermine la manière dont on peut les manipuler – par exemple, on ne peut pas additionner le mot « deux » et le nombre 2.

Python doit une grande partie de son succès et de sa popularité à sa souplesse en matière de typage. Contrairement à la plupart des langages compilés qui exigent de déclarer explicitement les types, Python met en œuvre ce qu’on appelle le « duck-typing ». Le « duck-typing » est un système de typage dynamique qui part du principe que si un objet « marche comme un canard et cancane comme un canard, alors c'est forcément un canard ».

Plus précisément, selon la documentation Python, le « duck typing » est :

« Un style de programmation qui ne tient pas compte du type d’un objet pour déterminer s’il dispose de l’interface appropriée ; au lieu de cela, la méthode ou l’attribut est simplement appelé ou utilisé… En mettant l’accent sur les interfaces plutôt que sur des types spécifiques, un code bien conçu gagne en flexibilité en permettant la substitution polymorphe. Le « duck typing » évite les tests utilisant type() ou isinstance()

Concrètement, on peut citer comme exemple la fonction len . len() renvoie «la longueur (le nombre d’éléments) d’un objet». Dans le code ci-dessous, observez comment len() elle parvient à générer une sortie quel que soit le type d’objet avec lequel elle est appelée :

>>> example_1 = "Hello? World!"
>>> type(example_1)
<class 'str'>

>>> example_2 = [1, 3, 5, 8]
>>> type(example_2)
<class 'list'>

>>> example_3 = {"hello" : "world", "foo": "bar"}
>>> type(example_3)
<class 'dict'>

>>> len(example_1)
13                                 # 13 letters in "Hello? World!"

>>> len(example_2)
4                                  # 4 items in the list

>>> len(example_3)
2                                  # 2 key-value pairs in the dictionary

Dans un exemple de typage dynamique qui reflète davantage ce que l'on peut observer en Python dans la pratique, le code ci-dessous définit trois classes différentes de races de chiens qui peuvent chacune bark():

class Pug:
    def bark(self):
        print("The pug goes arf arf!")

class LabradorRetriever:
    def bark(self):
        print("The labrador retriever goes arf arf!")

class Wolfhound:
    def bark(self):
        print("The wolfhound goes arf arf!")

Vous pouvez créer un exemplaire de chaque race de chien et appeler bark() sur chacun d'entre eux sans erreur, car ils possèdent tous la même interface. Grâce au « duck typing », le code suivant s'exécute correctement :

>>> pets = [Pug(), LabradorRetriever(), Wolfhound()]

>>> for pet in pets:
...     pet.bark()

The pug goes arf arf!
The labrador retriever goes arf arf!
The wolfhound goes arf arf!

pet peut être de classe Pug, LabradorRetriever, ou Wolfhound et Python appellera tout de même la bark fonction sans erreur.

 Cela peut s'avérer pratique, et dans de nombreux contextes, c'est exactement ce que l'on recherche. Pour la création de scripts, la science des données et le travail exploratoire, le typage dynamique de Python est une fonctionnalité, et non un bug. Le « duck typing » vous permet d'itérer rapidement sans la contrainte des déclarations de types rigides. C'est en grande partie pour cette raison que Python est devenu le langage dominant pour les workflows d'IA et de science des données.

Cependant, la donne change considérablement dans le code backend de production. Une application Flask ou Django sans types déclarés peut compliquer la maintenance et le débogage. Avec le « duck-typing » de Python, les incompatibilités de types se manifestent sous forme d’erreurs d’exécution cryptiques plutôt que d’échecs clairs et détectables dès le début. Le problème devient encore plus aigu lorsque les applications dépendent de types de données spécifiques pour fonctionner comme prévu, par exemple lors de l’utilisation d’API, du traitement de fichiers de configuration ou de la gestion des entrées utilisateur. 

Par exemple, si vous avez défini la classe suivante :

class Sphynx:
    def meow(self):
        print("The sphynx goes meow meow!")

Puis j'ai mis à jour le code d'exemple pour y inclure une instance de Sphynx dans la liste des pets à parcourir, vous obtiendrez une erreur :

>>> pets = [Pug(), LabradorRetriever(), Sphynx()]

>>> for pet in pets:
...     pet.bark()
...     

The pug goes arf arf!
The labrador retriever goes arf arf!
Traceback (most recent call last):
  File "<python-input-74>", line 2, in <module>
    pet.bark()
    ^^^^^^^^
AttributeError: 'Sphynx' object has no attribute 'bark'

Comme l'illustre cet exemple, dans certains contextes, la flexibilité du « duck typing » peut devenir un inconvénient. Par exemple, un type incorrect transmis à un appel d'API peut ne pas générer d'erreur avant que la requête ne soit déjà en cours d'exécution, ce qui peut vous coûter de l'argent pour un appel facturable qui était voué à l'échec dès le départ.

Une façon de résoudre certains des problèmes liés au typage dynamique consiste à utiliser les indicateurs de typede Python.

Que sont les annotations de type ?

Une indication de type est une annotation de code qui «spécifie le type attendu pour une variable, un attribut de classe, un paramètre de fonction ou une valeur de retour». Par conséquent, une annotation de type fait référence à la manière dont les indications de type sont utilisées syntaxiquement en Python.

Le code suivant est un exemple simple d'utilisation de l'annotation de type :

def greeting(name: str) -> str:
    return 'Hello ' + name

Dans cet exemple, l'indicateur de type est str et l'annotation de type est le name: str et -> str . L'annotation de type nous indique que le type attendu du paramètre name est une chaîne de caractères et que le type de retour attendu de la fonction greeting est une chaîne de caractères.

En ajoutant des annotations de type à l'exemple Pug pourrait ressembler à ceci :

class Pug:
    def init(self, name: str) -> None:
        self.name: str = name

    def bark(self) -> None:
        print(f"The pug {self.name} goes arf arf!")

Et si nous mettons à jour notre pets code d'itération pour y inclure l'annotation de type, cela pourrait ressembler à ceci :

def make_dogs_bark(pets: List[Pug | LabradorRetriever | Wolfhound ]) -> None:
    for pet in pets:
        pet.bark() 

make_dogs_bark([Pug(), LabradorRetriever(), Sphynx()])

Comme leur nom l'indique, il s'agit simplement de suggestions de typage. Elles contribuent à rendre le code plus lisible et plus facile à maintenir, mais elles ne sont pas imposées par l’interpréteur Python. Nous pourrions utiliser un outil supplémentaire tel que mypy pour vérifier les types et obtenir une erreur comme celle-ci :

error: List item 2 has incompatible type "Sphynx"; expected "Pug | LabradorRetriever | Wolfhound"  [list-item]

Cela devrait être effectué dans une étape supplémentaire : rien n'empêche ce code de s'exécuter et de générer une erreur lors de l'exécution.

En quête de reconnaissance

Pour éviter les erreurs lors de l'exécution – comme un appel d'API avec des données incorrectes –, vous pouvez de valider les données de votre requête avant de l’envoyer. Dans l’exemple de code, nous pourrions définir une sorte de validation pour nous assurer que chaque élément de la liste pets puisse bark():

def make_dogs_bark_safely(dogs):
    """Manual validation in the function"""
    for dog in dogs:
        if not hasattr(dog, 'bark') or not callable(getattr(dog, 'bark')):
            raise TypeError(f"Invalid dog type: {type(dog).__name__}")
        dog.bark()

# Now this fails immediately with a clear message:
pets = [Pug(), Sphynx()]

make_dogs_bark_safely(pets)
# TypeError: Invalid dog type: Sphynx

En plus de devenir rapidement fastidieux et peu maniable, ce modèle sape certains des avantages du typage dynamique inhérent à Python, tout en passant à côté de certains des avantages de l'annotation de types.

Heureusement, Pydantic permet de valider les données tout en conservant la simplicité et la rapidité du langage grâce à une syntaxe déjà intégrée.

Qu'est-ce que Pydantic ?

Pydantic est une bibliothèque de validation de données pour Python offrant les avantages suivants :

Examinons de plus près comment ces fonctionnalités s'articulent concrètement pour offrir une validation des données fiable et efficace, en parfaite adéquation avec la syntaxe et la structure de Python.

Principales fonctionnalités de validation de Pydantic

Il est important de comprendre que, dans Pydantic, le terme « validation » désigne «le processus d’instanciation d’un modèle (ou d’un autre type) qui respecte les types et les contraintes spécifiés». En d’autres termes, la validation de Pydantic s’applique au résultat de l’instanciation d’un modèle, et non aux données d’entrée. Ainsi, Pydantic lève une ValidationError lorsque les données ne peuvent pas être analysées correctement pour former une instance d’un modèle.

Modèle de base

BaseModel est au cœur de Pydantic. Vous en héritez pour définir des modèles de données comportant des champs annotés par leur type. L'une des principales méthodes pour définir un schéma dans Pydantic consiste à utiliser des modèles. Lorsque vous instanciez un BaseModel Pydantic valide automatiquement les données par rapport au schéma défini.

Grâce à Pydantic, la Pug classe se présente désormais comme suit :

class Pug(BaseModel):
    name: str
    age: int
    color: str = "fawn"

    def bark(self):
        print(f"The pug {self.name} goes arf arf!")

Si vous deviez instancier Pug, Pydantic s'assurerait que l'objet résultant soit de name de type chaîne de caractères, un age de type entier, et un color de type chaîne de caractères avec fawn comme valeur par défaut.

Indications de type et champs obligatoires

Les annotations de type permettent de contrôler la validation du schéma et la sérialisation. Les champs déclarés uniquement avec une annotation de type sont obligatoires ; ceux qui comportent des valeurs par défaut sont facultatifs.

Par Pug exemple, le name champ est annoté avec str ce qui signifie que n'importe quelle chaîne de caractères fera l'affaire, mais une chaîne doit être renseignée ; il en va de même pour le age champ. Le color champ, en revanche, propose une valeur par défaut de fawn et n’est donc pas obligatoire lors de l’instanciation d’un Pug.

Coercition de types

Pydantic peut être utilisé soit en mode strict, soit en mode lax (mode par défaut). En mode lax, la bibliothèque convertit automatiquement les données au type défini dans le schéma.

Ainsi, par exemple, si nous fournissions "5" une chaîne de caractères comme age d’un Pug, Pydantic la convertirait en entier.

Configuration du terrain

La Field fonction permet d’ajouter des métadonnées et des contraintes aux champs du schéma.

Voici quelques paramètres couramment utilisés :

  • Contraintes telles que « supérieur à » gt) et « supérieur ou égal à » ge), ainsi que min_length et max_length

  •  Alias permettant de mapper les noms des champs d'entrée et de sortie à l'aide de alias, validation_alias, et serialization_alias)

  • Mode strict pour empêcher la coercition de type sur certains champs strict=True)

Pour appliquer des contraintes au name champ pour Pug, vous utiliseriez le code suivant :

class Pug(BaseModel):
    name: str = Field(..., min_length=1, description="The pug's name")
    age: int
    color: str = "fawn"

    def bark(self):
        print(f"The pug {self.name} goes arf arf!")

Sérialisation

Les instances de modèles Pydantic peuvent être converties en dictionnaires sans avoir à écrire de code de sérialisation supplémentaire, en utilisant model_dump(). Cela facilite grandement la sérialisation au format JSON ou dans d’autres formats afin de les réutiliser ailleurs dans un projet. Par exemple, model_dump_json() sérialise directement un modèle au format JSON.

Voici un exemple illustrant la création d'une instance de Pug puis de la sérialiser à l’aide de l’une des fonctions intégrées de Pydantic :

matty_pug = Pug(name="Matty", age=14)

result = matty_pug.model_dump()

print(result)

Ce qui donnerait le résultat suivant :

{'name': 'Matty', 'age': 14, 'color': fawn}

Quel est un cas d'utilisation concret de Pydantic ?

Depuis sa création, Pydantic s'est rapidement imposé comme l'une des bibliothèques de validation de données les plus utilisées pour Python. Environ 8 000 paquets disponibles sur PyPI utilisent Pydantic, parmi lesquels (et notamment) FastAPI, huggingface, Django Ninja, SQLModel, LangChain et Vonage.

En novembre 2024, Vonage a publié une version entièrement réécrite du SDK Python de Vonage. Il n’est pas toujours facile de repartir de zéro, mais cette refonte a été l’occasion d’apporter des améliorations structurelles essentielles et d’optimiser l’interaction des utilisateurs avec le SDK.

Parmi les modifications apportées dans le cadre de cette initiative figurait l'ajout de Pydantic au SDK afin de faciliter l'appel des API Vonage et l'analyse des réponses.

Regardez la Video ci-dessous pour écouter le témoignage d'un de nos développeurs qui travaille sur le SDK Python et découvrir ce qu'il pense de l'utilisation de Pydantic.

Comment le SDK Python de Vonage utilise les modèles Pydantic

L'utilisation de modèles Pydantic pour construire les requêtes garantit la cohérence des types et facilite le passage des objets appropriés aux API Vonage. Avec la version 4 du SDK, les réponses des API sont désormais désérialisées en modèles Pydantic entièrement documentés, ce qui offre une plus grande cohérence que le renvoi de dictionnaires comme dans la version précédente. De plus, vous pouvez toujours convertir les modèles Pydantic en dictionnaires ou en chaînes JSON à l'aide de model.model_dump et model.model_dump_json respectivement.

Dans le cadre de cette démonstration, nous allons examiner la Verify API de Vonage et la manière dont elle est modélisée à l'aide de Pydantic dans le SDK.

Qu'est-ce que l'API Verify de Vonage ?

La Verify API est le produit de nouvelle génération de Vonage dédié à l'authentification à deux facteurs (2FA). Grâce à la Verify API, vous pouvez authentifier vos utilisateurs et prévenir la fraude grâce à une API simple et intuitive qui masque la complexité de la 2FA à l'échelle mondiale.

Elle va au-delà des méthodes d'authentification traditionnelles en prenant en charge un éventail plus large de canaux, notamment les canaux « over-the-top » (OTT) tels que WhatsApp, ainsi que les SMS, la voix et les e-mails. L'API prend en charge à la fois les jetons Web JSON (JWT) que l’ l'authentification de base. L’authentification de base est plus simple à mettre en place, mais ne prend pas en charge les fonctionnalités avancées telles que les listes de contrôle d’accès (ACL). Vous pouvez utiliser soit l’authentification JWT, soit l’authentification de base, mais pas les deux simultanément. Pour en savoir plus sur l’authentification, consultez la documentation.

Dans les grandes lignes, la Verify API suit le processus suivant :

  1. Un utilisateur final déclenche une demande d'authentification à deux facteurs (2FA) dans une application

  2. En arrière-plan, cette demande d'authentification à deux facteurs (2FA) déclenche une requête vers la Verify API.

  3. L'API Verify envoie un mot de passe à usage unique (OTP) à l'utilisateur final via le canal configuré (SMS, appel vocal, WhatsApp ou e-mail)

  4. L'utilisateur final fournit le mot de passe à usage unique (OTP) à l'application

  5. Cela déclenche une requête Verify visant à comparer le mot de passe à usage unique (OTP) fourni par l'utilisateur final à celui généré par l'API.

  6. Le résultat de cette vérification détermine ensuite la suite des événements (l'utilisateur final est authentifié, etc.)

A diagram of the Verify V2 Request with Summary Callbacks.A diagram of the Verify V2 Request with Summary Callbacks.Une requête de vérification initiale type contient les données suivantes :

{

   "locale": "es-es",
   "channel_timeout": 180,
   "client_ref": "myPersonalRef",
   "code_length": 4,
   "code": "e4dR1Qz",
   "brand": "ACME",
   "template_id": "4ed3027d-8762-44a0-aa3f-c393717413a4",
   "workflow": [
      {
         "channel": "sms",
         "to": "44770090000"
      },
      {
         "channel": "voice",
         "to": "44770090000"
      }
   ]
}

Ce point est expliqué plus en détail ci-dessous :

Clé

Description

Obligatoire ou facultatif

paramètres régionaux

Les paramètres régionaux à utiliser pour le message de vérification

Facultatif, la valeur par défaut est en-us

channel_timeout

Le délai, en secondes, à respecter entre deux tentatives d'envoi du code de vérification

Facultatif, valeur par défaut : 180 secondes

réf_client

Un identifiant unique pour la demande de vérification

Facultatif

longueur_du_code

La longueur du code de vérification à générer

Facultatif, valeur par défaut : 4

code

Un code alphanumérique personnalisé facultatif à utiliser si vous ne souhaitez pas que Vonage génère le code

Facultatif

marque

Le nom de l'entreprise ou du service à l'origine de la demande de vérification – celui-ci apparaîtra dans le corps du SMS ou du message TTS

Obligatoire, longueur maximale de 16 caractères

template_id

Un identifiant de modèle personnalisé à utiliser – ne fonctionne que lorsque channel est sms ou rcs

Facultatif

flux de travail

La liste des canaux à utiliser dans le processus de vérification, dans l'ordre où ils apparaissent

Obligatoire, 3 éléments au maximum

Pour en savoir plus sur l'API et son fonctionnement, consultez la documentation de Vonage Verify.

Une requête réussie renvoie un 202 OK pour indiquer que la demande de vérification a été lancée. La réponse comprendra également un request_id qui est nécessaire pour mener à bien le processus de vérification :

{"request_id": "c11236f4-00bf-4b89-84ba-88b25df97315",}

Parallèlement, Vonage envoie un mot de passe à usage unique (OTP) à l'utilisateur final via le flux de travail configuré, en essayant chaque canal dans l'ordre dans lequel ils sont définis.

Une fois que l'utilisateur final a reçu le mot de passe à usage unique (OTP) et l'a saisi dans l'application, une nouvelle requête est envoyée au point de terminaison « Verify » avec le request_id en tant que paramètre de chemin https://api.nexmo.com/v2/verify/:request_id) et l’OTP dans le corps de la requête pour la code clé.

Si le code fourni correspond au code généré et envoyé par Vonage, une 200 OK réponse est renvoyée accompagnée d’un "status": "complete" .

Démonstration : comment la Verify API utilise-t-elle Pydantic ?

Le SDK Python de Vonage facilite l'intégration des API Vonage dans une application Python. L'intégration de Pydantic au SDK rend l'utilisation des API encore plus simple. Grâce à Pydantic, au lieu de découvrir une erreur après d'avoir effectué un appel API et d'avoir encouru des frais, les modèles de requête sont validés avant l’exécution, sans qu’il soit nécessaire d’écrire de code supplémentaire pour cela.

La démonstration présentée dans cet article de blog consiste en une application minimaliste d'authentification à deux facteurs (2FA) utilisant le framework FastAPI. L'utilisateur final se rend sur une page web où il saisit son adresse e-mail. À l'aide de la Verify API, l'application génère ensuite un code OTP qui est envoyé à l'adresse e-mail fournie par l'utilisateur final. L'utilisateur final saisit ce code dans l'application et, si la vérification via l'API Verify aboutit, il est récompensé par un GIF animé. 

Si vous le souhaitez, vous pouvez accéder directement au du code et utiliser le fichier README pour le faire fonctionner.

Le code suivant correspond à l'endroit où la requête « Verify » est créée :

   verify_request = VerifyRequest(
        brand=settings.verify_brand_name,
        workflow=[
            EmailChannel(to=email),
        ],
        channel_timeout=60,
        code_length=5,
    )

Si nous entrons dans l’ VerifyRequest objet, nous trouvons un modèle Pydantic :

class VerifyRequest(BaseModel):
    brand: str = Field(..., min_length=1, max_length=16)
    workflow: list[
        Union[
            SilentAuthChannel,
            SmsChannel,
            WhatsappChannel,
            VoiceChannel,
            EmailChannel,
        ]
    ]
    locale: Optional[Locale] = None
    channel_timeout: Optional[int] = Field(None, ge=15, le=900)
    client_ref: Optional[str] = Field(None, min_length=1, max_length=16)
    code_length: Optional[int] = Field(None, ge=4, le=10)
    code: Optional[str] = Field(None, pattern=r'^[a-zA-Z0-9]{4,10}$')

    @model_validator(mode='after')
    def check_silent_auth_first_if_present(self):
        if len(self.workflow) > 1:
            for i in range(1, len(self.workflow)):
                if isinstance(self.workflow[i], SilentAuthChannel):
                    raise VerifyError(
                        'If using Silent Authentication, it must be the first channel in the "workflow" list.'
                    )
        return self

Le schéma convertit la requête API en types à l'aide d'annotations Python et de la Field fonction pour définir des contraintes. Le workflow champ définit un Union type dérivé d’autres types modélisés, ce qui illustre comment les types peuvent être imbriqués.

Enfin, le model_validator(mode='after') est un décorateur Pydantic qui offre des options de configuration supplémentaires concernant la manière dont le VerifyRequest modèle doit être validé. Dans ce cas, la def check_silent_auth_first_if_present méthode est exécutée après la VerifyRequest modèle a été construit, afin de garantir que si SilentAuthChannel est incluse dans le flux de travail, elle doit figurer en premier.

Vérification par e-mail

Après avoir créé et activé un environnement virtuel, puis installé les dépendances requises conformément au fichier fichier README, vous pouvez exécuter l'application de démonstration à l'aide de la commande suivante :

fastapi dev

Cela lancera une application web sur http://127.0.0.1:8000:

A screenshot of the index page inviting the end-user to enter their email address to try out the Vonage Verify API.A screenshot of the index page inviting the end-user to enter their email address to try out the Vonage Verify API.En cliquant sur « Envoyer le code de vérification » déclenche le workflow de la Verify API. Vous devriez être redirigé vers une page Web où vous pourrez saisir le code envoyé à l'adresse e-mail que vous avez fournie :

A screenshot of the verification page inviting the end-user to enter the code they received in their email.A screenshot of the verification page inviting the end-user to enter the code they received in their email.Si vous saisissez ici le code correct, vous serez redirigé vers une page de confirmation.

En coulisses, le code utilise les modèles Pydantic du SDK pour garantir que la requête « Verify » soit correctement formée et traitée.

Vérification sans validation : tests sans Pydantic

Voyons maintenant comment Pydantic facilite l'utilisation de la Verify API.

Dans le code suivant, nous avons deux fonctions qui effectuent la même tâche : envoyer une requête vers le /verify point de terminaison. L'une des fonctions crée le corps de la requête manuellement, tandis que l'autre utilise Pydantic.

Utilisation d'un corps de requête créé manuellement :

def without_pydantic(request_payload):

    jwt_client = JwtClient(
        application_id=settings.vonage_application_id,
        private_key=settings.vonage_private_key_path,
    )

    jwt_token = jwt_client.generate_application_jwt()

    payload = {
        "brand": request_payload["brand"],
        "workflow": [
            {
                "channel": "email",
                "to": request_payload["to_email"],
            }
        ],
        "channel_timeout": request_payload["channel_timeout"],
        "code_length": request_payload["code_length"],
    }

    response = requests.post(
        "https://api.nexmo.com/v2/verify",
        headers={
            "Authorization": f"Bearer {jwt_token.decode()}",
            "Content-Type": "application/json",
        },
        json=payload,
    )

    return response

Utilisation de Pydantic :


def with_pydantic(request_payload):

    client = Vonage(
        Auth(
            application_id=settings.vonage_application_id,
            private_key=settings.vonage_private_key_path,
        )
    )

    verify_request = VerifyRequest(
        brand=request_payload["brand"],
        workflow=[EmailChannel(to=request_payload["to_email"])],
        channel_timeout=request_payload["channel_timeout"],
        code_length=request_payload["code_length"],
    )

    client.verify.start_verification(verify_request)

    last_response = client.http_client.last_response

    return last_response

Le code utilise ensuite unittest pour tester les fonctions avec test_data qui ne respectent pas les paramètres de l'API :

   test_data = {
        "brand": 12345,
        "to_email": 678910,
        "channel_timeout": "sixty",
        "code_length": "five",
    }

Exécutez les tests à l'aide de la commande suivante :

python -m unittest -v

L'exécution des tests devrait donner lieu à deux résultats différents : une erreur et un échec.

Le test de la fonction qui utilise Pydantic devrait renvoyer cette erreur :

pydantic_core._pydantic_core.ValidationError: 1 validation error for EmailChannel
to
  Input should be a valid string [type=string_type, input_value=678910, input_type=int]
    For further information visit https://errors.pydantic.dev/2.13/v/string_type

Ce qu’il faut retenir ici, c’est que le test n'a pas échoué ; il a plutôt généré une erreur parce que Pydantic a détecté un type de données incorrect avant même que que la requête ne soit envoyée. De plus, le message d’erreur lui-même fournit des informations utiles pour le débogage, contrairement à un message d’erreur de type générique. Non seulement nous savons que le type de données fourni ne répondait pas aux exigences du modèle, mais nous connaissons également le type attendu ainsi que le type qui a été transmis :

Input should be a valid string [type=string_type, input_value=678910, input_type=int]

Le test de la fonction sans Pydantic renvoie une erreur :

AssertionError: 422 != 202 : Test without Pydantic failed with: 422. Expected: 202

Cela signifie que la requête a été effectuée et que, comme l’API est définie, elle a renvoyé un 422 en raison de paramètres non valides. 

Dans ce scénario de test restreint, un seul appel API incorrect est négligeable ; à plus grande échelle, cela peut toutefois s'avérer une erreur coûteuse. L'utilisation de Pydantic pour valider un modèle de requête avant d'effectuer l'appel API permet de réduire au minimum les appels API inutiles, d'assurer une gestion plus fluide des erreurs et de faciliter le travail des développeurs.

En résumé

Pydantic offre une solution puissante et performante pour la validation des données en Python, aidant ainsi les développeurs à éviter les pièges potentiels du « duck typing ». En définissant des schémas, des contraintes et des règles de validation à l'aide des modèles Pydantic, vous pouvez garantir l'intégrité des données et détecter les erreurs avant même que les requêtes API ne soient envoyées. Cela vous évite des appels API invalides coûteux et rend la gestion des erreurs plus fluide.

Comme le montre l'intégration du SDK Python de Vonage avec la Verify API, Pydantic facilite le traitement de modèles de requêtes complexes et imbriqués, tout en préservant la lisibilité et la facilité de maintenance de votre code. Avec la version 4 du SDK, les réponses API sont désérialisées en modèles Pydantic entièrement documentés, ce qui vous offre davantage de cohérence, une meilleure prise en charge par les outils et une expérience de développement globalement plus fluide.

Lectures complémentaires et références

Vous avez une question ou souhaitez partager ce que vous construisez ?

Restez connecté et tenez-vous au courant des dernières nouvelles, astuces et événements concernant les développeurs.

Partager:

https://a.storyblok.com/f/270183/400x400/2c4345217d/liz-acosta.jpeg
Liz AcostaDéfenseur des développeurs

Liz Acosta est conseillère en développement chez Vonage. Si son parcours professionnel, d'étudiante en cinéma à spécialiste du marketing, puis ingénieur et enfin défenseur des développeurs, peut sembler peu conventionnel, il est tout à fait typique des relations avec les développeurs ! Liz aime les pizzas, les plantes, les carlins et Python.