Skip to content

[BUG] Héritage des clés de type liste dans le parser pl #484

Description

@ddoyen

@nimdanor

Il y a un problème avec l'héritage des clés de type liste dans le parser pl.

L'héritage est traité de la façon suivante dans le parser pl. Si le fichier A.pl hérite des fichiers B.pl et C.pl, le parser produit le dictionnaire des clés de A.pl, puis il produit le dictionnaire des clés de B.pl et étend le dictionnaire des clés de A.pl, puis il produit le dictionnaire des clés de C.pl et étend à nouveau le dictionnaire des clés de A.pl (et tout ça est récursif).

La procédure d'extension d'un dictionnaire A par un dictionnaire B est la suivante.

  • toutes les clés de B qui n'existent pas dans A sont ajoutées
  • pour les clés de B qui existent aussi dans A, ça dépend du type de la valeur associée à la clé:
    • si c'est une liste, on concatène les deux valeurs
    • si c'est un dictionnaire, on fait une extension (récursivement)
    • sinon, on garde le valeur de A

Voilà la fonction qui fait cette extension (apps/loader/utils.py)

def extends_dict(target, source):
    """ Will copy every key and value of source in target if key is not present in target """
    for key, value in source.items():
        if key not in target:
            target[key] = value
        elif type(target[key]) is dict:
            extends_dict(target[key], value)
        elif type(target[key]) is list:
            target[key] += value
    
    return target

Il faut absolument supprimer cette concaténation des listes. Elle n'est pas du tout naturelle. En tant que créateur d'exercices, on pense écraser une liste par une nouvelle valeur et on se retrouve avec une concaténation.

En plus ça crée un bug dans la parsing lui-même puisque les noms des fichiers dont on hérite sont stockés dans une liste dans le dictionnaire (dic['__extends']). Cette liste subit donc des concaténations indésirables au moment des extensions, alors qu'on itère dessus !

def process_extends(dic):
    """ Extends dic with file in dic['__extends'].
        
        Return newly extended dic.
        
        Raise from loader.exceptions:
            - DirectoryNotFound if trying to load from a nonexistent directory
            - FileNotFound if the file do not exists."""
    
    warnings = []
    for item in dic['__extends']:
        try:
            directory = Directory.objects.get(name=item['directory_name'])
            ext_dic, warnings_ext = parse_file(directory, item['path'], extending=True)
            warnings += warnings_ext
            dic = extends_dict(dic, ext_dic)

apps/loader/parser.py

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions