diff --git a/source/hug/hug.png b/source/hug/hug.png new file mode 100644 index 00000000..f4bb7b11 Binary files /dev/null and b/source/hug/hug.png differ diff --git a/source/hug/index.rst b/source/hug/index.rst index d474afe5..ecc49cf0 100644 --- a/source/hug/index.rst +++ b/source/hug/index.rst @@ -1,9 +1,17 @@ .. _hug-tutorial: + ======= ``hug`` ======= + +.. image:: hug.png + :scale: 50% + :align: center + :alt: hug + + Par Charles Ombang Ndo [#co]_ Introduction @@ -17,10 +25,11 @@ possibles et les normes d'utilisation. La plupart des applications actuelles offrent ces *web services* plus connues sous RESTful web service. Dans l'univers Python, la bibliothèque hug_ est un outil assez puissant -permettant d'implémenter une API. L'utilisation de la technologie ``hug`` pour +permettant d'implémenter une API. L'utilisation de la technologie hug_ pour créer des APIs en Python est motivée par de nombreux avantages qui seront détaillés dans un chapitre dédié. + RESTful web service et ``hug`` ------------------------------ @@ -36,10 +45,14 @@ tout le temps les mêmes. Le concept RESTful web service repose sur les ressources qui sont représentées par les `URLs`. Le client envoie des requêtes via ces URLs au moyen des méthodes du protocole HTTP, ce sont les verbes: -- GET: récupération de données, -- POST: ajout de données -- PUT: modifications de données -- DELETE: suppression de données. + + + - GET: récupération de données, + - POST: ajout de données + - PUT: modifications de données + - DELETE: suppression de données. + + Les formats d'échanges sont nombreux. Dans ce chapitre, nous resterons sur du :ref:`JSON `. @@ -48,10 +61,11 @@ Pourquoi choisir ``hug`` ------------------------ Les très célèbres frameworks que sont Flask_ et Django_ sont bousculés par les -performances qu'apportent hug. hug permet d'écrire une API de manière -simplifiée. Les API implémentées dans d'autres frameworks peuvent l'être en +performances qu'apportent hug_. La bibliothèque hug_ permet d'écrire une API de manière +simplifiée. Les APIs implémentées dans d'autres frameworks peuvent l'être en quelques lignes avec hug. hug supporte le versioning, il permet la -documentation par le code et hug intègre la validation des données. +documentation par le code et il intègre la validation des données. + Fonctionnement ============== @@ -87,9 +101,11 @@ L'exécution du code ci-dessus via la commande. $ hug -f somme.py hug_ lance le serveur sur le port 8000. En entrant l'adresse -``http://localhost:8000`` on a une réponse au format JSON. Dans notre exemple +``http://localhost:8000`` on a une réponse au format :ref:`JSON `. Dans notre exemple + on obtient: + .. code-block:: json { @@ -118,15 +134,21 @@ on obtient: } } -On peut remarquer que la documentation est très claire, la clé `overview` nous renseigne sur l'objectif de notre API, La clé usage renseigne sur le type de données renvoyées par l'API, dans notre cas, la ligne de code @hug.get() indique qu'il s'agit d'une requête GET. La suite du bloc JSON ci-dessus nous renseigne sur les paramètres des l'API, leurs types et le format de retour. -Maintenant pour voir le résultat de notre (petite) API, il suffit d'entrer dans le navigateur l'adresse suivante localhost:8000/somme?val1=..&val2= .. il suffit de passer les valeurs aux paramètres. +On peut remarquer que la documentation est très claire, la clé overview nous renseigne sur l'objectif de notre API, La clé usage renseigne sur le type de données renvoyées par l'API, dans notre cas, la ligne de code ``@hug.get()`` indique qu'il s'agit d'une requête GET. La suite du bloc :ref:`JSON ` ci-dessus nous renseigne sur les paramètres de l'API, leurs types et le format de retour. + +Maintenant pour voir le résultat de notre (petite) API, il suffit d'entrer dans le navigateur l'adresse suivante: +``localhost:8000/somme?val1=..&val2= ..`` et de passer les valeurs aux paramètres. +Important: Les APIs écrit avec hug_ peuvent être accédées depuis la console, pour cela, il suffit de rajouter ``@hug.cli()`` +comme nous l'avons fait avec ``@hug.get()``. -hug et le versioning + +Hug et les versions ==================== -Comme souligné auparavant, hug supporte et gère très bien le versioning. On peut avoir plusieurs versions de l'API dans la même application. +Comme souligné auparavant, hug_ supporte et gère très bien le versioning. On peut avoir plusieurs versions de l'API dans la même application. + .. code-block:: python3 @@ -144,7 +166,8 @@ Comme souligné auparavant, hug supporte et gère très bien le versioning. On p return "Echo: {text}".format(**locals()) -Le code ci-dessus montre la façon dont hug gère le versioning. Il suffit pour cela d'ajouter dans la méthode GET les versions que l'on veut. C'est une fois de plus assez claire, simple et compréhensible. + +Le code ci-dessus montre la façon dont hug_ gère le versioning. Il suffit pour cela d'ajouter dans la méthode GET les versions que l'on veut. C'est une fois de plus assez claire, simple et compréhensible. On peut déduire du code précédent que l'on a 4 versions. Pour le vérifier, il suffit de mettre dans le navigateur l'adresse http://localhost:8000, on a alors la documentation au format JSON suivante: @@ -179,46 +202,50 @@ On peut déduire du code précédent que l'on a 4 versions. Pour le vérifier, i } } -Si on compare ce rendu JSON au précédent, on remarque la présence du champ + +Si on compare ce rendu :ref:`JSON ` au précédent, on remarque la présence du champ ``version``. La clé ``version`` de valeur 4 indique la version actuelle de l'API et la clé ``versions`` prend en valeur un tableau listant les différentes versions de notre API. Pour tester le bon fonctionnement du versioning, on peut écrire -. Dans cette URL, on spécifie la version +http://localhost:8000/v1/echo?text=toto. Dans cette URL, on spécifie la version que l'on souhaite utiliser, ici la version v1. En sortie on aura ``toto``, ce qui correspond bien à la sortie attendue de la version 1. En changeant dans l'URL juste la version en la remplaçant par v2, v2 ou v4, la sortie est naturellement celle attendue suivant la version indiquée ``Echo:toto``. -*Type annotation* et validation -=============================== +Validation automatique des données +================================== Il est possible d'ajouter des fonctions aux paramètres de nos méthodes, pour -expliciter comment ils sont validés et transcris en type python, on parle de -type annotation. ``argument:type``. L'avantage de l'utilisation d'une telle +expliciter comment ils sont validés et transcris en type python. Pour cela, il suffit +de mettre les arguments sous la forme suivante: ``argument:type``. L'avantage de l'utilisation d'une telle spécification est de clairement indiquer au niveau de la documentation le type -de données attendues. +de données attendues. Ceci est connu sous le terme annotations_ en python. .. code-block:: python3 - """Test des types annotations""" + """Test de la validation automatique des données""" import hug @hug.get() def annota(text:int): return text -Le code ci-dessus montre l'utilisation des annotations. l'argument de la -fonction ``annota(...)`` est suivi du type int soit text::int. On comprend + +Le code ci-dessus montre comment valider les données automatiquement. L'argument de la +fonction ``annota(...)`` est suivi du type int soit ``text::int``. On comprend aisément que l'argument text est de type int. Vérifions la sortie suivant -l'adresse +l'adresse . + + .. code-block:: json { "404": "The API call you tried to make was not defined. Here's a definition of the API to help you get going :)", "documentation": { - "overview": "Test des types annotations", + "overview": "Test de la validation automatique des données", "handlers": { "/annota": { "GET": { @@ -237,10 +264,11 @@ l'adresse } } + On voit bien dans le bloc inputs la clé type, on peut clairement voir que l'entrée est de type int. -Si on entre l'adresse on a en retour +Si on entre l'adresse http://localhost:8000/annota?text=salut on a en retour une belle erreur comme celle ci-dessous: .. code-block:: json @@ -251,8 +279,10 @@ une belle erreur comme celle ci-dessous: } } -Il est important de noter que les annotations permettent implicitement de faire -la validation automatique des données. + +Cette technique qu'apporte la bibliothèque hug_ permet de valider les données automatiquement. Cela est fait +implicitement. + Les directives @@ -260,7 +290,7 @@ Les directives Les directives sont globalement des arguments enregistrés pour fournir automatiquement des valeurs. Un exemple serait meilleur pour expliquer le rôle -des directives. hug possède des directives prédéfinies, mais il donne la +des directives. hug_ possède des directives prédéfinies, mais il donne la possibilité de créer des directives personnalisées. .. code-block:: python3 @@ -337,38 +367,76 @@ comme le montre le code ci-dessous .. code-block:: python3 - @hug.format.content_type('file/text') + @hug.format.content_type('text/plain') def format_as_text(data, request=None, response=None): return str(content).encode('utf-8') + +Le format par défaut est le :ref:`JSON `. L'une des technique pour définir un nouveau format par défaut est +``hug.API(__name__).http.output_format = hug.`` par exemple format_cible ``output_format.html`` -.. warning:: +Si on souhaite un format pour une url spécifique et pas toutes les urls, par exemple pour notre méthode somme, on +veut que le format soit en ``html`` on fera: - le ``Content-Type`` nommé ``file/text`` n'existe pas. Ce n'est pas donc pas - un exemple utilisable en l'état. - .. Yoan +.. code-block:: python3 -Le Routing + """Simple application effectuant une somme de deux nombres""" + import hug + + @hug.get(output = hug.output = hug.output_format.html) + def somme(val1, val2): + """Retourne la somme des deux nombres passés en paramètre""" + return "

{}

".format(val1 + val2) + + +donc il suffit de spécifier le format dans le get ``@hug.get(output = hug.output = hug.)``. + +Le routage ---------- C'est la notion qu'on retrouve dans la plupart des frameworks. Il s'agit de -définir des chemins, urls d'accès aux données. `La documentation officielle -`_ détaille la notion de *Routing* -de façon plus élaborée et plus large. +définir des chemins, urls d'accès aux données. Le mécanisme est simplifié, il y'a plusieurs manières +de faire le routage avec la bibliothèque hug_. -.. oui, car vous n'en parlez pas. +Exemple, on crée une route vers notre méthode somme du fichier ``somme.py`` -Les APIs écrit avec ``hug`` peuvent être accédées depuis la ligne de commande, pour -cela, il suffit de rajouter ``@hug.cli()`` comme nous l'avons fait avec -``@hug.get()``. +.. code-block:: python3 -.. quel rapport avec le routing? + """Simple application effectuant une somme de deux nombres""" + import hug + + @hug.get('/ajout') + def somme(val1:int, val2:int): + """Retourne la somme des deux nombres passés en paramètre""" + return val1 + val2 + +Avant pour exécuter la méthode somme on entrait l'adresse suivante: http://localhost:8000/somme?val1=..&val2=.. +Avec la route indiquée dans ``@hug.get()`` (/ajout) il suffit de remplace dans l'adresse précédente /somme par /ajout +http://localhost:8000/ajout?val1=..&val2=... + +Suivant la taille du projet, l'ajout des routes avec la méthode get peut surcharger le code. Il existe donc une solution, +on peut avoir un fichier dans lequel nos méthodes sont déclarées et un second pour créer des routes. + +Dans un autre fichier on va importer la méthode somme du fichier somme.py et créer une route + +.. code-block:: python3 + + import hug + import somme + + api = hug.API(__name__) + hug.get('/ajout')(somme.somme) + + Le résultat est le même toujours en entrant cette url http://localhost:8000/ajout?val1=..&val2=.. + + Un avantage du routage est qu'il permet de bien nommer les urls. + Conclusion ========== -La bibliothèque hug_ offre un moyen très simplifié d'écrire des API REST. +La bibliothèque hug_ offre un moyen très simplifié d'écrire des APIs REST. La syntaxe est assez claire, la documentation bien élaborée depuis le code, le *versioning* est réalisé en une seule ligne de code. @@ -386,3 +454,5 @@ Bibliographie .. _hug: http://www.hug.rest/ .. _Flask: http://flask.pocoo.org/ .. _Django: https://www.djangoproject.com/ +.. _annotations: http://sametmax.com/les-annotations-en-python-3/ + diff --git a/source/in b/source/in new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/source/in @@ -0,0 +1,2 @@ + + diff --git a/source/index.rst b/source/index.rst index 2c01afb3..275598fb 100644 --- a/source/index.rst +++ b/source/index.rst @@ -91,6 +91,57 @@ Annexes .. toctree:: :maxdepth: 1 + builtins/index.rst + dunders/index.rst + super/index.rst + fstrings/index.rst + email/index.rst + abc/index.rst + collections/index.rst + csv/index.rst + hashlib/index.rst + io/index.rst + itertools/index.rst + json/index.rst + math/index.rst + multiprocessing/index.rst + re/index.rst + secrets/index.rst + statistics/index.rst + random/index.rst + unittest/index.rst + + colorama/index.rst + hug/index.rst + pillow/index.rst + pygame/index.rst + pytest/index.rst + sphinx/index.rst + watchdog/index.rst + +À propos de ce livre +==================== + +:Auteurs: + - Adrien Mendes , + - André Neto Da Silva , + - Anthony Fleury , + - Axel Rieben + - Cédric Pahud , + - Dany Chea , + - Dylan Santos de Pinho , + - Julien Feuillade , + - Killian Castella , + - Maël Pedretti , + - Pedro Costa , + - Quentin Vaucher , + - Sylvain Renaud , + - Guillaume Noguera , + - Yoan Blanc +:Date: 2017-03-16 +:Licence: + :ref:`licence` +======= misc/about misc/contrib licence \ No newline at end of file