From ca170c19f4da1cc2bc03279c7640ea2338253aeb Mon Sep 17 00:00:00 2001 From: Valentin Samir Date: Thu, 13 Feb 2014 22:34:00 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20de=20methodes=20pour=20tester=20l'?= =?UTF-8?q?=C3=A9galit=C3=A9=20d'objets=20ou=20d'attributs,=20possibilit?= =?UTF-8?q?=C3=A9=20de=20fournir=20une=20valeur=20du=20bon=20type=20python?= =?UTF-8?q?=20=C3=A0=20un=20attribut=20test=20bool=C3=A9en=20sur=20s'attri?= =?UTF-8?q?but=20propag=C3=A9e=20=C3=A0=20sa=20valeur.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le teste d'égalité sur un attribut peut se faire avec la sérialisation de l'attribut ou le type python qui le représente. Le teste d'égalité sur les cransLdapObjet se fait sur le dn et ses attributs. De plus, on peut aussi le testé avec un chaine de caractère : "host=freebox.crans.org" == MachineCrans(...) renvoie True ssi MachineCrans(...) a l'attribut host, qu'il est globalement unique et vaut freebox.crans.org vala vala --- attributs.py | 68 ++++++++++++++++++++++++++++++++-------------------- objets.py | 39 ++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 28 deletions(-) diff --git a/attributs.py b/attributs.py index 8546f2c..050c3fb 100644 --- a/attributs.py +++ b/attributs.py @@ -125,10 +125,11 @@ def attrify(val, attr, conn, Parent=None): if isinstance(val, Attr): return val else: - if not isinstance(val, unicode): + attr_classe = AttributeFactory.get(attr, fallback=Attr) + if not isinstance(val, unicode) and (attr_classe.python_type and not isinstance(val, attr_classe.python_type)): cranslib.deprecated.usage("attrify ne devrait être appelé qu'avec des unicode (%r)" % val, level=3) val = val.decode('utf-8') - return AttributeFactory.get(attr, fallback=Attr)(val, conn, Parent) + return attr_classe(val, conn, Parent) class AttrsDict(dict): @@ -193,6 +194,7 @@ class Attr(object): unique = False #: Le nom de l'attribut dans le schéma LDAP ldap_name = None + python_type = None """La liste des droits qui suffisent à avoir le droit de modifier la valeur""" can_modify = [nounou] @@ -213,6 +215,21 @@ class Attr(object): self.parent = Parent self.parse_value(val) + def __eq__(self, item): + if isinstance(item, self.__class__): + return str(self) == str(item) + elif self.python_type and isinstance(item, self.python_type): + return self.value == item + elif isinstance(item, str): + return str(self) == item + elif isinstance(item, unicode): + return unicode(self) == item + else: + return False + + def __nonzero__(self): + return self.value.__nonzero__() + def parse_value(self, val): """Transforme l'attribut pour travailler avec notre validateur Le ldif est en dépendance car à certains endroits, il peut servir @@ -304,22 +321,28 @@ class objectClass(Attr): class intAttr(Attr): + + python_type = int + def parse_value(self, val): - if int(val) <= 0: + if self.python_type(val) <= 0: raise ValueError("Valeur entière invalide : %r" % val) - self.value = int(val) + self.value = self.python_type(val) def __unicode__(self): return unicode(self.value) class boolAttr(Attr): + + python_type = bool + def parse_value(self, val): - if val.lower() in [u'true', u'ok']: + if isinstance(val, self.python_type): + self.value = val + elif val.lower() in [u'true', u'ok']: self.value = True elif val.lower() == u'false': self.value = False - elif isinstance(val, bool): - self.value = val else: raise ValueError("%r doit être un booléen !" % val) @@ -414,7 +437,7 @@ class yearAttr(intAttr): optional = True def parse_value(self, annee): - annee = int(annee) + annee = self.python_type(annee) if annee < 1998: raise ValueError("Année invalide (%r)" % annee) self.value = annee @@ -598,6 +621,7 @@ class droits(Attr): @crans_attribute class solde(Attr): + python_type = float singlevalue = True optional = True legend = u"Solde d'impression" @@ -608,7 +632,7 @@ class solde(Attr): # on évite les dépassements, sauf si on nous dit de ne pas vérifier #if not (float(solde) >= config.impression.decouvert and float(solde) <= 1024.): # raise ValueError("Solde invalide: %r" % solde) - self.value = float(solde) + self.value = self.python_type(solde) def __unicode__(self): return u"%.2f" % self.value @@ -679,12 +703,13 @@ class ipHostNumber(Attr): category = 'base_tech' can_modify = [nounou] ldap_name = "ipHostNumber" + python_type = netaddr.IPAddress default = u'' def parse_value(self, ip): if ip == '': ip = ip4_of_rid(str(self.parent['rid'][0])) - self.value = netaddr.IPAddress(ip) + self.value = self.python_type(ip) def __unicode__(self): return unicode(self.value) @@ -699,18 +724,19 @@ class ip6HostNumber(Attr): category = 'base_tech' can_modify = [nounou] ldap_name = "ip6HostNumber" + python_type = netaddr.IPAddress default = u'' def parse_value(self, ip6): if ip6 == '': ip6 = ip6_of_mac(str(self.parent['macAddress'][0]), int(str(self.parent['rid'][0]))) - self.value = netaddr.IPAddress(ip6) + self.value = self.python_type(ip6) def __unicode__(self): return unicode(self.value) @crans_attribute -class mid(Attr): +class mid(intAttr): singlevalue = True optional = False unique = True @@ -718,14 +744,8 @@ class mid(Attr): category = 'id' ldap_name = "mid" - def parse_value(self, mid): - self.value = int(mid) - - def __unicode__(self): - return unicode(self.value) - @crans_attribute -class rid(Attr): +class rid(intAttr): singlevalue = True optional = True unique = True @@ -735,7 +755,7 @@ class rid(Attr): ldap_name = "rid" def parse_value(self, rid): - rid = int(rid) + rid = self.python_type(rid) # On veut éviter les rid qui recoupent les ipv4 finissant par # .0 ou .255 @@ -989,6 +1009,7 @@ class blacklist(Attr): category = 'info' can_modify = [nounou] ldap_name = "blacklist" + python_type = dict def parse_value(self, blacklist): bl_debut, bl_fin, bl_type, bl_comm = blacklist.split('$') @@ -1061,7 +1082,7 @@ class homepageAlias(Attr): ldap_name = "homepageAlias" @crans_attribute -class charteMA(Attr): +class charteMA(boolAttr): singlevalue = True optional = True legend= "Signale si l'adhérent a signé la charte de membres actifs" @@ -1069,11 +1090,6 @@ class charteMA(Attr): category = 'perso' ldap_name = "charteMA" - def parse_value(self, charteSignee): - if charteSignee.upper() not in [u"TRUE", u"FALSE"]: - raise ValueError("La charte MA est soit TRUE ou FALSE, pas %r" % charteSignee) - self.value = charteSignee.upper() - @crans_attribute class homeDirectory(Attr): singlevalue=True diff --git a/objets.py b/objets.py index 6f97ada..d3fa275 100644 --- a/objets.py +++ b/objets.py @@ -162,6 +162,41 @@ class CransLdapObject(object): nvals = [nldif[attr][vals.index(v)] for v in vals ] raise EnvironmentError("λv. str(Attr(v)) n'est peut-être pas une projection (ie non idempotente):", attr, nvals, vals) + def __eq__(self, obj): + if isinstance(obj, self.__class__): + if self.mode in ['w', 'rw']: + return self.dn == obj.dn and self._modifs == obj._modifs and self.attrs == obj.attrs + else: + return self.dn == obj.dn and self.attrs == obj.attrs + elif (isinstance(obj, str) or isinstance(obj, unicode)) and '=' in obj: + attr, val = obj.split('=', 1) + return attr in self.attrs.keys() and val in self[attr] + else: + return False + + def __iter__(self): + if self.mode in [ 'w', 'rw' ]: + return self._modifs.__iter__() + else: + return self.attrs.__iter__() + + def keys(self): + if self.mode in [ 'w', 'rw' ]: + return self._modifs.keys() + else: + return self.attrs.keys() + + def values(self): + if self.mode in [ 'w', 'rw' ]: + return self._modifs.values() + else: + return self.attrs.values() + + def items(self): + if self.mode in [ 'w', 'rw' ]: + return self._modifs.items() + else: + return self.attrs.items() def display(self): print printing.sprint(self) @@ -543,7 +578,7 @@ class proprio(CransLdapObject): super(proprio, self).__init__(conn, dn, mode, ldif) self._machines = None self._factures = None - if u'cransAccount' in [ unicode(o) for o in self['objectClass']]: + if u'cransAccount' in self['objectClass']: self.attribs = self.attribs + crans_account_attribs self.full = True @@ -837,7 +872,7 @@ class adherent(proprio): u"""Renvoie le nom du compte crans. S'il n'existe pas, et que uid est précisé, le crée.""" - if u'posixAccount' in [str(o) for o in self.attrs['objectClass']]: + if u'posixAccount' in self['objectClass']: return self.attrs['uid'][0] elif login: