Ajout de filter.py, qui contient un parseur de filtres.
This commit is contained in:
parent
12b8166e82
commit
a629e4c82f
1 changed files with 244 additions and 0 deletions
244
filter.py
Normal file
244
filter.py
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
#/usr/bin/env python
|
||||||
|
# -*- coding: utf8 -*-
|
||||||
|
|
||||||
|
def human_to_ldap(filtre):
|
||||||
|
"""
|
||||||
|
Transforme les filtres "human readables" en
|
||||||
|
filtres respectant la syntaxe LDAP.
|
||||||
|
"""
|
||||||
|
# Piles, quand on croise une parenthèse ouvrante
|
||||||
|
# on change de pile
|
||||||
|
stacks = {0:''}
|
||||||
|
|
||||||
|
# Position dans la pile
|
||||||
|
pos = 0
|
||||||
|
|
||||||
|
# operateur \in {&, |, &|, }
|
||||||
|
operateur = ""
|
||||||
|
|
||||||
|
# La pile externe, qu'on merge à la pile en cours quand c'est utile.
|
||||||
|
ext_stack = ""
|
||||||
|
|
||||||
|
# Élement de la forme paiement=2012 ou retour de la pile
|
||||||
|
# supérieure (quand on croise une parenthèse fermante, la
|
||||||
|
# pile est dumpée dans argument)
|
||||||
|
# Est systématiquement dumpé dans ext_stack quand on croise
|
||||||
|
# un opérateur.
|
||||||
|
argument = ""
|
||||||
|
|
||||||
|
# Y a-t-il un ! dans la salle ?
|
||||||
|
neg = False
|
||||||
|
|
||||||
|
# Quand on quitte une pile parenthésée, on veut savoir quel était
|
||||||
|
# l'opérateur actif avant, pour que le comportement de la fonction
|
||||||
|
# soit défini.
|
||||||
|
anciens_operateurs = []
|
||||||
|
|
||||||
|
for char in filtre:
|
||||||
|
if char == "(":
|
||||||
|
|
||||||
|
# Une nouvelle stack ne démarre que si le dernier argument a été dumpé
|
||||||
|
# dans l'ext stack (si ce n'est pas le cas quand on respecte la syntaxe
|
||||||
|
# des filtres, la fonction est mal codée, donc on plante).
|
||||||
|
if argument != "":
|
||||||
|
raise ValueError('Argument entammé non terminé !')
|
||||||
|
|
||||||
|
# Un dumpe ext_stack dans la stack en cours.
|
||||||
|
stacks[pos] += "%s" % (ext_stack)
|
||||||
|
|
||||||
|
# On augmente le conteur de la stack
|
||||||
|
pos = pos + 1
|
||||||
|
|
||||||
|
# On (ré)?initialise la stack
|
||||||
|
stacks[pos] = ''
|
||||||
|
|
||||||
|
# On stocke l'opérateur en cours dans la stack inférieure dans
|
||||||
|
# une liste.
|
||||||
|
anciens_operateurs.append(operateur)
|
||||||
|
|
||||||
|
# On flush operateur
|
||||||
|
operateur = ""
|
||||||
|
|
||||||
|
# On flush ext_stack, l'environnement est enfin propre pour
|
||||||
|
# bosser dans la nouvelle pile.
|
||||||
|
ext_stack = ""
|
||||||
|
|
||||||
|
elif char == ")":
|
||||||
|
# Cas classique
|
||||||
|
if operateur == "|":
|
||||||
|
ext_stack += "(%s)" % argument
|
||||||
|
|
||||||
|
# Moins classique, &| est un opérateur servant à dire qu'on
|
||||||
|
# a déjà croisé un | dans la stack en cours, le cas échéant,
|
||||||
|
# celui-ci doit être pris en compte, pour respecter la
|
||||||
|
# priorité du &. Dans ce cas seulement, une parenthèse
|
||||||
|
# est ouverte et non fermée (cf elif char == '&' cas
|
||||||
|
# operateur == "|"), on la ferme ici.
|
||||||
|
elif operateur == "&|":
|
||||||
|
argument += ")"
|
||||||
|
ext_stack += "(%s)" % argument
|
||||||
|
|
||||||
|
# Classique
|
||||||
|
elif operateur == "&":
|
||||||
|
ext_stack += "(%s)" % argument
|
||||||
|
|
||||||
|
# Pas d'opérateur, pas de parenthèse superflue.
|
||||||
|
else:
|
||||||
|
ext_stack += "%s" % argument
|
||||||
|
|
||||||
|
# On passe la stack en argument, les parenthèses
|
||||||
|
# l'encadrant seront placées d'un qu'un opérateur
|
||||||
|
# sera croisé.
|
||||||
|
argument = "%s%s" % (stacks[pos], ext_stack)
|
||||||
|
|
||||||
|
# Ménage
|
||||||
|
stacks[pos] = ""
|
||||||
|
ext_stack = ""
|
||||||
|
pos = pos - 1
|
||||||
|
|
||||||
|
# Retour à l'opérateur de la stack précédente.
|
||||||
|
operateur = anciens_operateurs.pop()
|
||||||
|
|
||||||
|
elif char == "|":
|
||||||
|
if not argument:
|
||||||
|
raise ValueError('Aucun argument')
|
||||||
|
|
||||||
|
# Ce cas permet d'éviter une répétition de la forme :
|
||||||
|
# (|(a)(|(b)(c))), quand on est déjà dans un ou, on
|
||||||
|
# rajoute juste l'argument suivant sans remettre de
|
||||||
|
# symbole.
|
||||||
|
if operateur == "|":
|
||||||
|
# neg est True si on a croisé un ! dans la chaîne.
|
||||||
|
# À améliorer pour qu'il ne marche que pour !=
|
||||||
|
if neg:
|
||||||
|
argument = "!(%s)" % argument
|
||||||
|
neg = False
|
||||||
|
|
||||||
|
# Ajout à la stack externe de l'argument
|
||||||
|
ext_stack += "(%s)" % argument
|
||||||
|
argument = ""
|
||||||
|
|
||||||
|
elif operateur == "&":
|
||||||
|
if neg:
|
||||||
|
argument = "!(%s)" % argument
|
||||||
|
neg = False
|
||||||
|
|
||||||
|
ext_stack += "(%s)" % argument
|
||||||
|
|
||||||
|
# | prend le relais sur &, on dumpe ext_stack et on commence une nouvelle
|
||||||
|
# chaîne qui sera ajoutée à droite. Le ou va tout à gauche de la stack
|
||||||
|
# en cours, pour s'appliquer sur tout son contenu.
|
||||||
|
stacks[pos] = "%s(%s%s)" % (char, stacks[pos], ext_stack)
|
||||||
|
ext_stack = ""
|
||||||
|
argument = ""
|
||||||
|
operateur = "|"
|
||||||
|
|
||||||
|
# C'est un & dans un |, donc on ferme juste la chaîne
|
||||||
|
# des &, d'où la parenthèse fermante en trop.
|
||||||
|
elif operateur == "&|":
|
||||||
|
if neg:
|
||||||
|
argument = "!(%s)" % argument
|
||||||
|
neg = False
|
||||||
|
|
||||||
|
ext_stack += "(%s)" % argument
|
||||||
|
argument = ""
|
||||||
|
stacks[pos] = "%s%s)" % (stacks[pos], ext_stack)
|
||||||
|
ext_stack = ""
|
||||||
|
operateur = "|"
|
||||||
|
|
||||||
|
# Pas encore d'opérateur annoncé
|
||||||
|
elif operateur == "":
|
||||||
|
if neg:
|
||||||
|
argument = "!(%s)" % argument
|
||||||
|
neg = False
|
||||||
|
|
||||||
|
ext_stack += "%s" % argument
|
||||||
|
argument = ""
|
||||||
|
|
||||||
|
# ouverture
|
||||||
|
stacks[pos] = "%s(%s%s)" % (char, stacks[pos], ext_stack)
|
||||||
|
ext_stack = ""
|
||||||
|
operateur = "|"
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise TypeError('Erreur d\'opérateur.')
|
||||||
|
|
||||||
|
elif char == "&":
|
||||||
|
if not argument:
|
||||||
|
raise ValueError('Aucun argument')
|
||||||
|
|
||||||
|
if operateur == "&":
|
||||||
|
if neg:
|
||||||
|
argument = "!(%s)" % argument
|
||||||
|
neg = False
|
||||||
|
|
||||||
|
ext_stack += "(%s)" % argument
|
||||||
|
argument = ""
|
||||||
|
|
||||||
|
# Le cas spécial, on ouvre un & après un |, donc pour respecter
|
||||||
|
# la priorité de &, on démarre une nouvelle chaîne, mais dans
|
||||||
|
# l'ext_stack (contrairement à char == '|', operateur == "&")
|
||||||
|
elif operateur == "|":
|
||||||
|
if neg:
|
||||||
|
argument = "!(%s)" % argument
|
||||||
|
neg = False
|
||||||
|
|
||||||
|
ext_stack += "(%s(%s)" % (char, argument)
|
||||||
|
argument = ""
|
||||||
|
operateur = "&|"
|
||||||
|
|
||||||
|
# On était déjà dans un &|...
|
||||||
|
elif operateur == "&|":
|
||||||
|
if neg:
|
||||||
|
argument = "!(%s)" % argument
|
||||||
|
neg = False
|
||||||
|
|
||||||
|
ext_stack += "(%s)" % argument
|
||||||
|
argument = ""
|
||||||
|
|
||||||
|
# Comme ci-dessus
|
||||||
|
elif operateur == "":
|
||||||
|
if neg:
|
||||||
|
argument = "!(%s)" % argument
|
||||||
|
neg = False
|
||||||
|
|
||||||
|
ext_stack += "%s" % argument
|
||||||
|
argument = ""
|
||||||
|
|
||||||
|
stacks[pos] = "%s(%s%s)" % (char, stacks[pos], ext_stack)
|
||||||
|
ext_stack = ""
|
||||||
|
operateur = "&"
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise TypeError('Erreur d\'opérateur.')
|
||||||
|
|
||||||
|
elif char == "!":
|
||||||
|
neg = True
|
||||||
|
|
||||||
|
# Remplissage d'argument
|
||||||
|
else:
|
||||||
|
argument += char
|
||||||
|
|
||||||
|
# Décommenter pour débug.
|
||||||
|
# En modifiant un peu, encore plus utile pour savoir ce qu'il
|
||||||
|
# fait à chaque étape !
|
||||||
|
#print stacks
|
||||||
|
#print pos, argument, ext_stack, operateur
|
||||||
|
|
||||||
|
if pos > 0:
|
||||||
|
raise Exception("Tu ne sais pas parenthéser, crétin.")
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Comme parenthèse fermante.
|
||||||
|
if neg:
|
||||||
|
argument = "!(%s)" % argument
|
||||||
|
if operateur == "&|":
|
||||||
|
argument += ')'
|
||||||
|
ext_stack += "(%s)" % argument
|
||||||
|
|
||||||
|
argument = ""
|
||||||
|
stacks[pos] = "(%s%s)" % (stacks[pos], ext_stack)
|
||||||
|
ext_stack = ""
|
||||||
|
|
||||||
|
# On retourne la pile de plus haut niveau
|
||||||
|
return stacks[0]
|
Loading…
Add table
Add a link
Reference in a new issue