unicode value
Alain Spineux
aspineux at gmail.com
Thu May 31 14:25:55 CEST 2007
Hi I changed my code to make it more modular.
class UnicodeLDAPInterface:
ldapbaseclass=None
.... my code goes HERE
class UnicodeLDAPObject(UnicodeLDAPInterface, LDAPObject):
ldapbaseclass=LDAPObject
class UnicodeReconnectLDAPObject(UnicodeLDAPInterface, ReconnectLDAPObject):
ldapbaseclass=ReconnectLDAPObject
Here is the full code
#!/usr/bin/env python2.4
import types, datetime
import ldap, ldapurl, ldap.modlist
from ldap.ldapobject import LDAPObject
from ldap.ldapobject import ReconnectLDAPObject
def unicode2utf8(st):
"""Convert unicode (and only unicode) string into utf-8 raw string as
expected by ldap"""
if isinstance(st, types.UnicodeType):
return st.encode('utf-8')
else:
return st
def utf82unicode(st):
"""encode st into utf-8"""
return st.decode('utf-8')
def encode_modlist(modlist, no_op):
"""encode ldap modlist structure
set no_op=True for Tuple of kind (int,str,[str,...])
and False for (str, [str,...])
"""
for i, mod in enumerate(modlist):
if no_op:
attr_name, attr_values=mod
else:
op, attr_name, attr_values=mod
attr_name=unicode2utf8(attr_name)
if isinstance(attr_values, (types.ListType, types.TupleType)):
attr_values=map(unicode2utf8, attr_values)
else:
attr_values=unicode2utf8(attr_values)
if no_op:
modlist[i]=(attr_name, attr_values)
else:
modlist[i]=(op, attr_name, attr_values)
return modlist
def _print_ldap_result(ldap_result):
for dn, item in ldap_result:
print 'DN=', repr(dn)
for k, v in item.iteritems():
print '\t%s: %s' % (k, repr(v))
print
class UnicodeLDAPInterface:
ldapbaseclass=None
decoder_expiration_delay=300 # the expiration delay for an object in
self.unicode_decoder
def __init__(self, uri, **kwargs):
self.ldapbaseclass.__init__(self, uri, **kwargs)
self.unicode_decoder={} # { (msgid, expiration, decoder_data) ... }
# I use an expiration time to avoid the list to become to big when
the
# server don't answere some requests
def _set_unicode_decoder(self, msgid, value):
"""protect unicode_decoder against multi-threading
update or add the decoder
"""
self._ldap_object_lock.acquire()
try:
self.unicode_decoder[msgid]=value
finally:
self._ldap_object_lock.release()
def _remove_unicode_decoder(self, msgid):
"""protect unicode_decoder against multi-threading
remove the decoder
"""
self._ldap_object_lock.acquire()
try:
try:
del self.unicode_decoder[msgid]
except:
# ignore any errors
pass
finally:
self._ldap_object_lock.release()
def _get_unicode_decoder(self, msgid):
"""protect unicode_decoder against multi-threading
read the decoder info for msgid
"""
self._ldap_object_lock.acquire()
try:
return self.unicode_decoder[msgid]
finally:
self._ldap_object_lock.release()
def _expire_unicode_decoder(self):
"""cleanup any expired decoder"""
self._ldap_object_lock.acquire()
now=datetime.datetime.now()
for msgid in self.unicode_decoder.keys():
if self.unicode_decoder[msgid][1]<now:
del self.unicode_decoder[msgid]
self._ldap_object_lock.release()
def search_ext(self,base,scope, filterstr, attrlist, *args, **kwargs):
# base,scope,
filterstr='(objectClass=*)',attrlist=None,attrsonly=0,serverctrls=None,clientctrls=None,timeout=-1,sizelimit=0
# convert filter
filterstr_u=unicode2utf8(filterstr)
# convert arglist and keep a copy of original values for later
decoding
attrlist_u=[]
decoder={} # will keep only fields to decode
if attrlist!=None:
for attr in attrlist:
if isinstance(attr, types.UnicodeType):
attr=attr.encode('utf-8')
decoder[attr]=True
attrlist_u.append(attr)
msgid=self.ldapbaseclass.search_ext(self,base,scope, filterstr_u,
attrlist_u, *args, **kwargs)
if decoder:
timeout=kwargs.get('timeout', None)
if timeout==None or timeout<=0:
timeout=self.decoder_expiration_delay
self._set_unicode_decoder(msgid,(msgid,
datetime.datetime.now()+datetime.timedelta(seconds=timeout),
decoder))
return msgid
def result3(self, *args, **kwargs):
# kwargs=(self, msgid=_ldap.RES_ANY,all=1,timeout=None):
rtype, rdata, rmsgid,
decoded_serverctrls=self.ldapbaseclass.result3(self,
*args, **kwargs)
try:
msgid, expire, decoder=self._get_unicode_decoder(rmsgid)
except KeyError:
pass
# no decoder for this => nothing to decode
else:
if rtype not in [ ldap.RES_SEARCH_ENTRY,
ldap.RES_SEARCH_REFERENCE ]:
# this was the last result
self._remove_unicode_decoder(rmsgid)
else:
# reset the timeout
timeout=kwargs.get('timeout', None)
if timeout==None or timeout<=0:
timeout=self.expiration_delay
self._set_unicode_decoder(msgid, (msgid,
datetime.datetime.now()+datetime.timedelta(seconds=timeout), decoder))
# now decode the result
if rdata:
if rtype in [ldap.RES_SEARCH_ENTRY,
ldap.RES_SEARCH_REFERENCE, ldap.RES_SEARCH_RESULT]:
# FIXME: I dont know what is a RES_SEARCH_REFERENCE
rdata_u=[]
for i, (dn, attrs) in enumerate(rdata):
# FIXME: should I handle the 'dn' the same way
if decoder.has_key('dn'):
dn=utf82unicode(dn)
for key in attrs.keys():
if decoder.has_key(key):
attrs[key]=map(utf82unicode, attrs[key])
# print '\tITEM=', dn, attrs
rdata[i]=(dn, attrs)
self._expire_unicode_decoder()
return rtype, rdata, rmsgid, decoded_serverctrls
def add_ext(self, dn, modlist, *args, **kwargs):
# args=(self,dn,modlist,serverctrls=None,clientctrls=None)
dn=unicode2utf8(dn)
# print 'MODLIST', modlist
modlist=encode_modlist(modlist, True)
# print 'MODLIST unicode', modlist
return self.ldapbaseclass.add_ext(self, dn, modlist, *args,
**kwargs)
def modify_ext(self, dn, modlist, *args, **kwargs):
# args=(self,dn,modlist,serverctrls=None,clientctrls=None)
dn=unicode2utf8(dn)
# print 'MODLIST', modlist
modlist=encode_modlist(modlist, False)
# print 'MODLIST unicode', modlist
return self.ldapbaseclass.modify_ext(self, dn, modlist, *args,
**kwargs)
def delete_ext(self, dn, *args, **kwargs):
# args=(self,dn,serverctrls=None,clientctrls=None)
dn=unicode2utf8(dn)
return self.ldapbaseclass.delete_ext(self, dn, *args, **kwargs)
def abandon_ext(self, msgid, *args, **kwargs):
# args=(self,msgid,serverctrls=None,clientctrls=None)
result=self.ldapbaseclass.abandon_ext(self, msgid, *args, **kwargs)
self._remove_unicode_decoder(msgid)
return result
def cancel_ext(self, cancelid, *args, **kwargs):
# args=(self,msgid,serverctrls=None,clientctrls=None)
result=self.ldapbaseclass.cancel_ext(self, cancelid, *args,
**kwargs)
self._remove_unicode_decoder(cancelid)
return result
class UnicodeLDAPObject(UnicodeLDAPInterface, LDAPObject):
ldapbaseclass=LDAPObject
class UnicodeReconnectLDAPObject(UnicodeLDAPInterface, ReconnectLDAPObject):
ldapbaseclass=ReconnectLDAPObject
if __name__=='__main__':
import sys, os, time
host='localhost'
port=389
base_dn='dc=asxnet,dc=loc'
if True:
who='cn=manager,cn=internal,dc=asxnet,dc=loc'
cred='********'
else:
who='cn=nobody,cn=internal,dc=asxnet,dc=loc'
cred='iMmTWz5pJ+lwY7i6M/BU61ngo1aBLyqQhRrrKbEc'
ldap_url=ldapurl.LDAPUrl('ldap://%s:%d/%s' % (host, port, base_dn))
ldap_url.applyDefaults({
'who': who,
'cred' : cred, })
print ldap_url
#l=LDAPObject(ldap_url.initializeUrl())
#l=UnicodeLDAPObject(ldap_url.initializeUrl())
l=UnicodeReconnectLDAPObject(ldap_url.initializeUrl())
l.simple_bind_s(ldap_url.who, ldap_url.cred)
print 'Connected as', l.whoami_s()
first_name='Michael'
first_name2=u'Micha\xebl'
last_name=u'Str\xf6der'
email='michael at stroeder.com'
street=u'Hauptstra\xe1e'
country='Germany'
cn='%s %s' %(first_name, last_name)
dn='cn=%s,%s' %(cn, base_dn)
info={
u'cn' : (cn, ),
'mail' : (email, ),
'objectClass' : ('top', 'inetOrgPerson', 'kolabInetOrgPerson',),
u'sn' : (last_name, ),
u'givenName' : (first_name, ),
u'street': (street, ),
'c': (country, ),
'telephoneNumber': '+49 1111111111',
}
ldap_result=l.search_s(base_dn, ldap.SCOPE_ONELEVEL, '(cn=%s)' % (cn,) ,
info.keys())
if ldap_result:
print '== Found'
_print_ldap_result(ldap_result)
l.delete_s(dn)
print '== Deleted'
l.add_s(dn, ldap.modlist.addModlist(info))
print '== Created'
ldap_result=l.search_s(base_dn, ldap.SCOPE_ONELEVEL, '(cn=%s)' % (cn,) ,
info.keys())
_print_ldap_result(ldap_result)
l.modify_s(dn, [(ldap.MOD_REPLACE, u'givenName', first_name2),
(ldap.MOD_ADD, 'telephoneNumber', ( '+49 1234567890',
)),
])
print '==Modified'
ldap_result=l.search_s(base_dn, ldap.SCOPE_ONELEVEL, '(cn=%s)' % (cn,) ,
info.keys())
_print_ldap_result(ldap_result)
print '==Display once more'
ldap_result=l.search_s(base_dn, ldap.SCOPE_ONELEVEL, '(cn=%s)' % (cn,) ,
['*', '+', u'dn', u'givenName', u'creatorsName'] )
_print_ldap_result(ldap_result)
On 5/29/07, Alain Spineux <aspineux at gmail.com> wrote:
>
> Hi Michael
>
> When investigating about python and unicode, I read somewhere (in a PEP
> I thing) that python functions should accept and manage unicode string
> as well as normal string.Of course if these strings could contains user
> readable characters.
>
> This is not the case for python-ldap functions. Sometime when calling
> python-ldap, we don't know well the origin ( a function is not suposed
> to know its caller :-) of the arguments we are using : user input,
> web interface, mysql database, ldap result, web form,
> literal, text file, text parsing... some are unicode, other not.
> I thing python-ldap function must accept unicode arguments.
>
> As we discussed at length previously, the decoding of the result is
> less easy because, the library cannot guess alone the meaning of
> these values.
>
> I'm not supporting the idea of downloading and use the ldap
> schema. I cannot imaging a connection less application
> like a web application doing that at any request! Or keeping a cache
> for the schema ...
>
> Anyway I see 2 solutions
>
> 1. Let result() return non unicode strings. _HERE_ The user know all
> returned
> strings are normal strings utf-8 encoded and he can do the encoding
> himself. A helper function doing the job for the result structure
> should be welcome.
>
> 2. Do the conversion regarding the info provided in the query, as my
> source sample does.
>
> I answer now some of your previous comment:
>
> > > In this case maybe is it possible to use [ '*', u'givenName', u'sn' ]
> > > to convert only 'givenName' and 'sn'
>
> > But then you will not gain much! Still the application has to know which
> > attributes have to be converted. => It's not worth hiding the conversion
>
> > within python-ldap.
>
> I don't really hide the conversion, because the user has to request it
> using
> unicode field name. And second, I do more work: I keep a link between
> the msgid and the request to know with fields I have to convert and
> also destroy the link when unneeded anymore.
>
> > The only clean solution would be something involving LDAP schema
> processing!
>
> You know better than me how costly it is, in developing time, and its
> overhead for CPU and network load.
> Do you really consider to add the schema processing for unicode
> integration in the future? Or are you
> hoping that someone will send you a patch :-) ?
>
>
> I know you were not very exited by my ideas, anyway the unicode support
> for
> argument encoding is important. (this is my opinion)
> Feel free to suggest some cosmetic changes: function name, class name, the
>
> way I wrap your base class .....
>
> Keep in mind, none of my code break compatibility with existing
> application.
>
> Best regards.
>
>
>
> On 5/24/07, Alain Spineux <aspineux at gmail.com> wrote:
> >
> >
> >
> > On 5/24/07, Michael Ströder < michael at stroeder.com> wrote:
> > >
> > > Alain Spineux wrote:
> > > >
> > > > Yes but what about unknown field type ?
> > >
> > > If you really want to dive into this look in directory
> > > pylib/w2lapp/schema/ of web2ldap's source. It works for me but I did
> > > not
> > > consider this whole framework mature enough to be incorporated into
> > > python-ldap.
> >
> >
> > I dont want to look at the schema:
> >
> > Here are the sources and the results.
> > I use your more appropriate name for unicode testing :-)
> >
> >
> > #!/usr/bin/env python2.4
> >
> > import sys, os, time
> > import ldap, ldapurl, ldap.modlist
> > import types
> > import datetime
> >
> > host='localhost'
> > port=389
> > base_dn='dc=asxnet,dc=loc'
> >
> > if True:
> > who='cn=manager,cn=internal,dc=asxnet,dc=loc'
> > cred=''********'
> > else:
> > who='cn=nobody,cn=internal,dc=asxnet,dc=loc'
> > cred='iMmTWz5pJ+lwY7i6M/BU61ngo1aBLyqQhRrrKbEc'
> >
> >
> > def unicode2utf8(st):
> > """Convert unicode (and only unicode) string into utf-8 raw string
> > as expected by ldap"""
> >
> > if isinstance(st, types.UnicodeType ):
> > return st.encode('utf-8')
> > else:
> > return st
> >
> > def utf82unicode(st):
> > """encode st into utf-8"""
> > return st.decode('utf-8')
> >
> >
> > def encode_modlist(modlist, no_op):
> > """encode ldap modlist structure
> > set no_op=True for Tuple of kind (int,str,[str,...])
> > and False for (str, [str,...])
> > """
> >
> > for i, mod in enumerate(modlist):
> > if no_op:
> > attr_name, attr_values=mod
> > else:
> > op, attr_name, attr_values=mod
> >
> > attr_name=unicode2utf8(attr_name)
> > if isinstance(attr_values, ( types.ListType, types.TupleType)):
> > attr_values=map(unicode2utf8, attr_values)
> > else:
> > attr_values=unicode2utf8(attr_values)
> > if no_op:
> > modlist[i]=(attr_name, attr_values)
> > else:
> > modlist[i]=(op, attr_name, attr_values)
> >
> > return modlist
> >
> > class UnicodeLDAPObject(ldap.ldapobject.LDAPObject):
> >
> > expiration_delay=300
> >
> > def __init__(self, uri, **kwargs):
> > ldap.ldapobject.LDAPObject.__init__(self, uri, **kwargs)
> > self.unicode_decoder={} # (msgid, expiration, decoder_data)
> > # I use an expiration time to avoid the list to become to big
> > when the
> > # server don't answere any request
> >
> > def search_ext(self,base,scope, filterstr, attrlist, *args,
> > **kwargs):
> > # base,scope,
> > filterstr='(objectClass=*)',attrlist=None,attrsonly=0,serverctrls=None,clientctrls=None,timeout=-1,sizelimit=0
> >
> >
> > # convert filter
> > filterstr=unicode2utf8(filterstr)
> >
> > # convert arglist and keep a copy of original values for later
> > decoding
> >
> > u_attrlist=attrlist
> > decoder={}
> > if u_attrlist!=None:
> > attrlist=[]
> > for attr in u_attrlist:
> > if isinstance(attr, types.UnicodeType):
> > attr=attr.encode('utf-8')
> > # print 'ATTR', attr
> > decoder[attr]=True
> > attrlist.append(attr)
> >
> > msgid=ldap.ldapobject.LDAPObject.search_ext(self,base,scope,
> > filterstr, attrlist, *args, **kwargs)
> >
> > if decoder:
> > timeout=kwargs.get('timeout', None)
> > if timeout==None or timeout<=0:
> > timeout=self.expiration_delay
> > self.unicode_decoder[msgid]=(msgid, datetime.datetime.now()+datetime.timedelta(seconds=timeout), decoder)
> > return msgid
> >
> > def result3(self, *args, **kwargs):
> > # kwargs=(self, msgid=_ldap.RES_ANY,all=1,timeout=None):
> > rtype, rdata, rmsgid, decoded_serverctrls=
> > ldap.ldapobject.LDAPObject.result3(self, *args, **kwargs)
> >
> > if self.unicode_decoder.has_key(rmsgid):
> > msgid, expire, decoder=self.unicode_decoder[rmsgid]
> > if rtype not in [ ldap.RES_SEARCH_ENTRY,
> > ldap.RES_SEARCH_REFERENCE ]:
> > # this was the last result
> > del self.unicode_decoder[rmsgid]
> > else:
> > # reset the timeout
> > timeout= kwargs.get('timeout', None)
> > if timeout==None or timeout<=0:
> > timeout=self.expiration_delay
> > self.unicode_decoder[msgid]=(msgid,
> > datetime.datetime.now()+datetime.timedelta(seconds=timeout), decoder)
> >
> > # now decode the result
> > if rdata:
> > if rtype in [ldap.RES_SEARCH_ENTRY,
> > ldap.RES_SEARCH_REFERENCE, ldap.RES_SEARCH_RESULT]:
> > # FIXME: I dont know what is a RES_SEARCH_REFERENCE
> > rdata_u=[]
> > for i, (dn, attrs) in enumerate(rdata):
> > # FIXME: should I handle the 'dn' the same way
> > if decoder.has_key ('dn'):
> > dn=utf82unicode(dn)
> > for key in attrs.keys():
> > if decoder.has_key(key):
> > attrs[key]=map(utf82unicode, attrs[key])
> >
> > # print '\tITEM=', dn, attrs
> > rdata[i]=(dn, attrs)
> >
> > else:
> > # no decoder for this => nothing to decode
> > pass
> >
> > # remove other expired decoder info
> > now=datetime.datetime.now()
> > for msgid in self.unicode_decoder.keys():
> > if self.unicode_decoder[rmsgid][1]<now:
> > del self.unicode_decoder[rmsgid]
> >
> > return rtype, rdata, rmsgid, decoded_serverctrls
> >
> > def add_ext(self, dn, modlist, *args, **kwargs):
> > # args=(self,dn,modlist,serverctrls=None,clientctrls=None)
> > dn=unicode2utf8(dn)
> > # print 'MODLIST', modlist
> > modlist=encode_modlist(modlist, True)
> > # print 'MODLIST unicode', modlist
> > return ldap.ldapobject.LDAPObject.add_ext (self, dn, modlist,
> > *args, **kwargs)
> >
> > def modify_ext(self, dn, modlist, *args, **kwargs):
> > # args=(self,dn,modlist,serverctrls=None,clientctrls=None)
> > dn=unicode2utf8(dn)
> > # print 'MODLIST', modlist
> > modlist=encode_modlist(modlist, False)
> > # print 'MODLIST unicode', modlist
> > return ldap.ldapobject.LDAPObject.modify_ext(self, dn, modlist,
> > *args, **kwargs)
> >
> > def delete_ext(self, dn, *args, **kwargs):
> > # args=(self,dn,serverctrls=None,clientctrls=None)
> > dn=unicode2utf8(dn)
> > return ldap.ldapobject.LDAPObject.delete_ext(self, dn, *args,
> > **kwargs)
> >
> >
> >
> > def print_ldap_result(ldap_result):
> > for dn, item in ldap_result:
> > print 'DN=', repr(dn)
> > for k, v in item.iteritems():
> > print '\t%s: %s' % (k, repr(v))
> > print
> >
> > ldap_url=ldapurl.LDAPUrl ('ldap://%s:%d/%s' % (host, port, base_dn))
> > ldap_url.applyDefaults({
> > 'who': who,
> > 'cred' : cred, })
> > #l=ldap.ldapobject.LDAPObject(ldap_url.initializeUrl())
> > l=UnicodeLDAPObject(ldap_url.initializeUrl())
> > l.simple_bind_s(ldap_url.who, ldap_url.cred)
> > print 'Connected as', l.whoami_s()
> >
> >
> > first_name='Michael'
> > first_name2=u'Micha\xebl'
> > last_name=u'Str\xf6der'
> > email=' michael at stroeder.com'
> > street=u'Hauptstra\xe1e'
> > country='Germany'
> >
> > cn='%s %s' %(first_name, last_name)
> > dn='cn=%s,%s' %(cn, base_dn)
> > info={
> > u'cn' : (cn, ),
> > 'mail' : (email, ),
> > 'objectClass' : ('top', 'inetOrgPerson', 'kolabInetOrgPerson',),
> > u'sn' : (last_name, ),
> > u'givenName' : (first_name, ),
> > u'street': (street, ),
> > 'c': (country, ),
> > 'telephoneNumber': '+49 1111111111',
> > }
> >
> > ldap_result=l.search_s(base_dn, ldap.SCOPE_ONELEVEL , '(cn=%s)' % (cn,)
> > , info.keys())
> > if ldap_result:
> > print '== Found'
> > print_ldap_result(ldap_result)
> > l.delete_s(dn)
> > print '== Deleted'
> >
> > l.add_s(dn, ldap.modlist.addModlist (info))
> > print '== Created'
> > ldap_result=l.search_s(base_dn, ldap.SCOPE_ONELEVEL, '(cn=%s)' % (cn,) ,
> > info.keys())
> > print_ldap_result(ldap_result)
> >
> > l.modify_s(dn, [(ldap.MOD_REPLACE, u'givenName', first_name2),
> > (ldap.MOD_ADD, 'telephoneNumber', ( '+49 1234567890',
> > )),
> > ])
> >
> > print '==Modified'
> > ldap_result=l.search_s(base_dn, ldap.SCOPE_ONELEVEL, '(cn=%s)' % (cn,) ,
> > info.keys())
> > print_ldap_result(ldap_result)
> >
> > print '==Display once more'
> > ldap_result=l.search_s(base_dn, ldap.SCOPE_ONELEVEL, '(cn=%s)' % (cn,) ,
> > ['*', '+', u'dn', u'givenName', u'creatorsName'] )
> > print_ldap_result(ldap_result)
> >
> >
> >
> > =============
> >
> >
> > Connected as dn:cn=manager,cn=internal,dc=asxnet,dc=loc
> > == Found
> > DN= 'cn=Michael Str\xc3\xb6der,dc=asxnet,dc=loc'
> > telephoneNumber: ['+49 1111111111', '+49 1234567890']
> > c: ['Germany']
> > cn: [u'Michael Str\xf6der']
> > objectClass: ['top', 'inetOrgPerson', 'kolabInetOrgPerson']
> > street: [u'Hauptstra\xe1e']
> > sn: [u'Str\xf6der']
> > mail: ['michael at stroeder.com']
> > givenName: [u'Micha\xebl']
> >
> > == Deleted
> > == Created
> > DN= 'cn=Michael Str\xc3\xb6der,dc=asxnet,dc=loc'
> > telephoneNumber: ['+49 1111111111']
> > c: ['Germany']
> > cn: [u'Michael Str\xf6der']
> > objectClass: ['top', 'inetOrgPerson', 'kolabInetOrgPerson']
> > street: [u'Hauptstra\xe1e']
> > sn: [u'Str\xf6der']
> > mail: ['michael at stroeder.com ']
> > givenName: [u'Michael']
> >
> > ==Modified
> > DN= 'cn=Michael Str\xc3\xb6der,dc=asxnet,dc=loc'
> > telephoneNumber: ['+49 1111111111', '+49 1234567890']
> > c: ['Germany']
> > cn: [u'Michael Str\xf6der']
> > objectClass: ['top', 'inetOrgPerson', 'kolabInetOrgPerson']
> > street: [u'Hauptstra\xe1e']
> > sn: [u'Str\xf6der']
> > mail: [' michael at stroeder.com']
> > givenName: [u'Micha\xebl']
> >
> > ==Display more
> > DN= 'cn=Michael Str\xc3\xb6der,dc=asxnet,dc=loc'
> > telephoneNumber: ['+49 1111111111', '+49 1234567890']
> > c: ['Germany']
> > cn: [u'Michael Str\xf6der']
> > objectClass: ['top', 'inetOrgPerson', 'kolabInetOrgPerson']
> > street: [u'Hauptstra\xe1e']
> > sn: [u'Str\xf6der']
> > mail: ['michael at stroeder.com']
> > givenName: [u'Micha\xebl']
> >
> > ==Display once more
> > DN= u'cn=Michael Str\xf6der,dc=asxnet,dc=loc'
> > telephoneNumber: ['+49 1111111111', '+49 1234567890']
> > c: ['Germany']
> > entryCSN: ['20070524191126Z#000002#00#000000']
> > cn: ['Michael Str\xc3\xb6der']
> > entryDN: ['cn=Michael Str\xc3\xb6der,dc=asxnet,dc=loc']
> > createTimestamp: ['20070524191126Z']
> > objectClass: ['top', 'inetOrgPerson', 'kolabInetOrgPerson']
> > creatorsName: [u'cn=manager,cn=internal,dc=asxnet,dc=loc']
> > entryUUID: ['5099e82e-9e76-102b-830b-0da78c7bd35e']
> > hasSubordinates: ['FALSE']
> > modifiersName: ['cn=manager,cn=internal,dc=asxnet,dc=loc']
> > street: ['Hauptstra\xc3\xa1e']
> > sn: ['Str\xc3\xb6der']
> > structuralObjectClass: ['inetOrgPerson']
> > subschemaSubentry: ['cn=Subschema']
> > mail: [' michael at stroeder.com']
> > givenName: [u'Micha\xebl']
> > modifyTimestamp: ['20070524191126Z']
> >
> >
> >
> >
> >
> > --
> > --
> > Alain Spineux
> > aspineux gmail com
> > May the sources be with you
> >
>
>
>
> --
> --
> Alain Spineux
> aspineux gmail com
> May the sources be with you
>
--
--
Alain Spineux
aspineux gmail com
May the sources be with you
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ldap/attachments/20070531/03e2ae47/attachment.html>
More information about the python-ldap
mailing list