Skip to content

[ENHANCEMENT] PL Parser : parser les valeurs Python avec l'opérateur = #485

Description

@ddoyen

@nimdanor

Je reprends dans cette issue une proposition de modification du parser pl qui avait été discutée là (#380) et qui semblait avoir fait consensus.

Actuellement, le parser pl possède un opérateur = et un opérateur % pour affecter des valeurs aux clés. L'opérateur = lit la valeur comme une chaîne et l'opérateur % lit la valeur comme une valeur JSON.

On peut donc faire ce genre d'affectation.

# Affecte la chaîne "toto" dans mystr
mystr = toto

# Affecte le booléen true dans mybool
mybool % true

# Affecte la chaîne  "toto"  dans mystr2
mystr2 % "toto"

Mais la syntaxe des expressions JSON est légèrement différente des expressions Python correspondantes :

  • true/false vs True/False
  • null vs None
  • simple quotes non acceptées en JSON pour délimiter les chaînes

Et, en pratique, on est amené à jongler avec les deux syntaxes pour les clés (selon qu'on les définit dans le source PL ou dans un script Python), ce qui est perturbant, surtout pour les néophytes.

Nous proposions donc d'abandonner l'opérateur % et de modifier l'opérateur = de la façon suivante : le parser essaie d'interpréter ce qui est à droite de l'opérateur = comme une valeur Python et, s'il n'y arrive pas, il l'interprète comme une chaîne.

On pourrait donc écrire des affectations de ce genre.

mybool = False

mynull  = None

mystr1 = 'toto'

mystr2 = toto

En pratique, ça semble assez simple à faire. Il suffit de changer quelques lignes dans apps/loader/parsers/pl.py

Au lieu de...

if op == '=':
    self.dic_add_key(key, value)
elif op == '%':
    try:
        self.dic_add_key(key, json.loads(value))
    except json.decoder.JSONDecodeError:
        raise SyntaxErrorPL(join(self.directory.root, self.path),
                            line,
                            self.lineno,
                            message="Invalid JSON syntax starting ")

...il faudrait en gros faire ça

if op == '=':
    try:
        self.dic_add_key(key, ast.literal_eval(value))
    except:
        self.dic_add_key(key, value)

Questions en suspens.

  • Est-ce que c'est une bonne pratique de passer silencieusement vers une interprétation chaîne si on n'arrive pas à faire l'interprétation Python ? Ca masque d'éventuelles erreurs de syntaxe Python de la part de l'utilisateur. Je sais que Dominique aime bien ce mode où on écrit des chaînes sans quotes... :-) Perso, ça me dérange pas de mettre explicitement des quotes pour les chaînes. Sachant qu'on a déjà l'opérateur == ... == pour entrer du texte brut.

  • ast.literal_eval est capable de parser plus de types que les types JSON (tuples et sets notamment). Au moment où le dictionnaire Python de l'exercice va être converti en JSON, ça peut être problématique. Les tuples vont être convertis en array (comme les listes). Les sets vont peut-être déclencher des erreurs de conversion (à vérifier). Bref, il faudrait réfléchir à la façon de traiter ça de manière cohérente et robuste (soit au niveau du parsing, soit au niveau du dump Python->JSON).

Metadata

Metadata

Labels

EnhancementNew feature or request

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions