"tokenize" — Analyseur lexical de Python
****************************************

**Code source :** Lib/tokenize.py

======================================================================

The "tokenize" module provides a lexical scanner for Python source
code, implemented in Python.  The scanner in this module returns
comments as tokens as well, making it useful for implementing "pretty-
printers", including colorizers for on-screen displays.

Pour simplifier la gestion de flux de *tokens*, tous les *tokens*
operator et delimiter, ainsi que les "Ellipsis*" sont renvoyés en
utilisant le *token* générique "OP". Le type exact peut être déterminé
en vérifiant la propriété "exact_type" du *named tuple* renvoyé par
"tokenize.tokenize()".

Avertissement:

  Note that the functions in this module are only designed to parse
  syntactically valid Python code (code that does not raise when
  parsed using "ast.parse()").  The behavior of the functions in this
  module is **undefined** when providing invalid Python code and it
  can change at any point.


Analyse Lexicale
================

Le point d'entrée principal est un *générateur* :

tokenize.tokenize(readline)

   Le générateur "tokenize()" prend un argument *readline* qui doit
   être un objet appelable exposant la même interface que la méthode
   "io.IOBase.readline()" des objets fichiers. Chaque appel a la
   fonction doit renvoyer une ligne sous forme de *bytes*.

   The generator produces 5-tuples with these members: the token type;
   the token string; a 2-tuple "(srow, scol)" of ints specifying the
   row and column where the token begins in the source; a 2-tuple
   "(erow, ecol)" of ints specifying the row and column where the
   token ends in the source; and the line on which the token was
   found. The line passed (the last tuple item) is the *physical*
   line.  The 5 tuple is returned as a *named tuple* with the field
   names: "type string start end line".

   Le *n-uplet nommé* a une propriété additionnelle appelée
   "exact_type" qui contient le type exact de l'opérateur pour les
   jetons "OP". Pour tous les autres types de jetons, "exact_type" est
   égal au champ "type" du *n*-uplet nommé.

   Modifié dans la version 3.1: prise en charge des *n*-uplets nommés.

   Modifié dans la version 3.3: prise en charge de "exact_type".

   "tokenize()" détermine le codage source du fichier en recherchant
   une nomenclature UTF-8 ou un cookie d'encodage, selon la **PEP
   263**.

tokenize.generate_tokens(readline)

   Tokenize a source reading unicode strings instead of bytes.

   Like "tokenize()", the *readline* argument is a callable returning
   a single line of input. However, "generate_tokens()" expects
   *readline* to return a str object rather than bytes.

   The result is an iterator yielding named tuples, exactly like
   "tokenize()". It does not yield an "ENCODING" token.

Toutes les constantes du module "token" sont également exportées
depuis module "tokenize".

Une autre fonction est fournie pour inverser le processus de
tokenisation. Ceci est utile pour créer des outils permettant de
codifier un script, de modifier le flux de jetons et de réécrire le
script modifié.

tokenize.untokenize(iterable)

   Convertit les jetons en code source Python. L'*iterable* doit
   renvoyer des séquences avec au moins deux éléments, le type de
   jeton et la chaîne de caractères associée. Tout élément de séquence
   supplémentaire est ignoré.

   Le script reconstruit est renvoyé sous la forme d'une chaîne
   unique. Le résultat est garanti pour que le jeton corresponde à
   l'entrée afin que la conversion soit sans perte et que les allers
   et retours soient assurés.  La garantie ne s'applique qu'au type de
   jeton et à la chaîne de jetons car l'espacement entre les jetons
   (positions des colonnes) peut changer.

   It returns bytes, encoded using the "ENCODING" token, which is the
   first token sequence output by "tokenize()". If there is no
   encoding token in the input, it returns a str instead.

"tokenize()" a besoin de détecter le codage des fichiers sources qu'il
code. La fonction utilisée pour cela est disponible :

tokenize.detect_encoding(readline)

   La fonction "detect_encoding()" est utilisée pour détecter
   l'encodage à utiliser pour décoder un fichier source Python. Il
   nécessite un seul argument, *readline*, de la même manière que le
   générateur "tokenize()".

   Il appelle *readline* au maximum deux fois et renvoie le codage
   utilisé (sous forme de chaîne) et une liste de toutes les lignes
   (non décodées à partir des octets) dans lesquelles il a été lu.

   Il détecte l'encodage par la présence d'une marqueur UTF-8 (*BOM*)
   ou d'un cookie de codage, comme spécifié dans la **PEP 263**. Si un
   *BOM* et un cookie sont présents, mais en désaccord, un
   "SyntaxError" sera levée. Notez que si le *BOM* est trouvé,
   "'utf-8-sig'" sera renvoyé comme encodage.

   Si aucun codage n'est spécifié, la valeur par défaut, "'utf-8'",
   sera renvoyée.

   Utilisez "open()" pour ouvrir les fichiers source Python : ça
   utilise "detect_encoding()" pour détecter le codage du fichier.

tokenize.open(filename)

   Ouvre un fichier en mode lecture seule en utilisant l'encodage
   détecté par "dectect_encoding()".

   Nouveau dans la version 3.2.

exception tokenize.TokenError

   Déclenché lorsque soit une *docstring* soit une expression qui
   pourrait être divisée sur plusieurs lignes n'est pas complété dans
   le fichier, par exemple :

      """Beginning of
      docstring

   ou :

      [1,
       2,
       3

Notez que les chaînes à simple guillemet non fermés ne provoquent pas
le déclenchement d'une erreur. Ils sont tokenisés comme "ERRORTOKEN",
suivi de la tokenisation de leur contenu.


Utilisation en ligne de commande.
=================================

Nouveau dans la version 3.3.

Le module "tokenize" peut être exécuté en tant que script à partir de
la ligne de commande. C'est aussi simple que :

   python -m tokenize [-e] [filename.py]

Les options suivantes sont acceptées :

-h, --help

   Montre ce message d'aide et quitte

-e, --exact

   Affiche les noms de jetons en utilisant le même type.

Si "filename.py" est spécifié, son contenu est tokenisé vers *stdout*.
Sinon, la tokenisation est effectuée sur ce qui est fourni sur
*stdin*.


Exemples
========

Exemple d'un script qui transforme les littéraux de type *float* en
type *Decimal* :

   from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP
   from io import BytesIO

   def decistmt(s):
       """Substitute Decimals for floats in a string of statements.

       >>> from decimal import Decimal
       >>> s = 'print(+21.3e-5*-.1234/81.7)'
       >>> decistmt(s)
       "print (+Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7'))"

       The format of the exponent is inherited from the platform C library.
       Known cases are "e-007" (Windows) and "e-07" (not Windows).  Since
       we're only showing 12 digits, and the 13th isn't close to 5, the
       rest of the output should be platform-independent.

       >>> exec(s)  #doctest: +ELLIPSIS
       -3.21716034272e-0...7

       Output from calculations with Decimal should be identical across all
       platforms.

       >>> exec(decistmt(s))
       -3.217160342717258261933904529E-7
       """
       result = []
       g = tokenize(BytesIO(s.encode('utf-8')).readline)  # tokenize the string
       for toknum, tokval, _, _, _ in g:
           if toknum == NUMBER and '.' in tokval:  # replace NUMBER tokens
               result.extend([
                   (NAME, 'Decimal'),
                   (OP, '('),
                   (STRING, repr(tokval)),
                   (OP, ')')
               ])
           else:
               result.append((toknum, tokval))
       return untokenize(result).decode('utf-8')

Exemple de tokenisation à partir de la ligne de commande. Le script :

   def say_hello():
       print("Hello, World!")

   say_hello()

sera tokenisé à la sortie suivante où la première colonne est la plage
des coordonnées de la ligne/colonne où se trouve le jeton, la deuxième
colonne est le nom du jeton, et la dernière colonne est la valeur du
jeton (le cas échéant)

   $ python -m tokenize hello.py
   0,0-0,0:            ENCODING       'utf-8'
   1,0-1,3:            NAME           'def'
   1,4-1,13:           NAME           'say_hello'
   1,13-1,14:          OP             '('
   1,14-1,15:          OP             ')'
   1,15-1,16:          OP             ':'
   1,16-1,17:          NEWLINE        '\n'
   2,0-2,4:            INDENT         '    '
   2,4-2,9:            NAME           'print'
   2,9-2,10:           OP             '('
   2,10-2,25:          STRING         '"Hello, World!"'
   2,25-2,26:          OP             ')'
   2,26-2,27:          NEWLINE        '\n'
   3,0-3,1:            NL             '\n'
   4,0-4,0:            DEDENT         ''
   4,0-4,9:            NAME           'say_hello'
   4,9-4,10:           OP             '('
   4,10-4,11:          OP             ')'
   4,11-4,12:          NEWLINE        '\n'
   5,0-5,0:            ENDMARKER      ''

Les noms exacts des types de jeton peuvent être affichés en utilisant
l’option : "-e" :

   $ python -m tokenize -e hello.py
   0,0-0,0:            ENCODING       'utf-8'
   1,0-1,3:            NAME           'def'
   1,4-1,13:           NAME           'say_hello'
   1,13-1,14:          LPAR           '('
   1,14-1,15:          RPAR           ')'
   1,15-1,16:          COLON          ':'
   1,16-1,17:          NEWLINE        '\n'
   2,0-2,4:            INDENT         '    '
   2,4-2,9:            NAME           'print'
   2,9-2,10:           LPAR           '('
   2,10-2,25:          STRING         '"Hello, World!"'
   2,25-2,26:          RPAR           ')'
   2,26-2,27:          NEWLINE        '\n'
   3,0-3,1:            NL             '\n'
   4,0-4,0:            DEDENT         ''
   4,0-4,9:            NAME           'say_hello'
   4,9-4,10:           LPAR           '('
   4,10-4,11:          RPAR           ')'
   4,11-4,12:          NEWLINE        '\n'
   5,0-5,0:            ENDMARKER      ''

Example of tokenizing a file programmatically, reading unicode strings
instead of bytes with "generate_tokens()":

   import tokenize

   with tokenize.open('hello.py') as f:
       tokens = tokenize.generate_tokens(f.readline)
       for token in tokens:
           print(token)

Or reading bytes directly with "tokenize()":

   import tokenize

   with open('hello.py', 'rb') as f:
       tokens = tokenize.tokenize(f.readline)
       for token in tokens:
           print(token)
