From: Yeargan Y. <ya...@un...> - 2008-01-29 01:04:10
|
I am trying to use the asynchronous LDAP polling feature and have a question about what appears to be a timing issue. When I run the code below, I find that I must insert a sleep() before entering the while loop or I get a ValueError exception. If I sleep for around 0.01 seconds, the exception is intermittent (from my system to this server). With the sleep at 0.10 seconds or higher, I get the results I would expect from the server. I would expect that whether I sleep or not should be irrelevant. If I poll for a result and there is nothing available, then result() should return with None and not generate an exception. Is that the correct behavior? What am I missing? I provided an example of the code output including the exception itself and the sample code below. The code uses a public LDAP server and should work from anywhere. ---=[begin: sample exception]=--- Polling ... Traceback (most recent call last): File "./sample.py", line 26, in ? res = l.result(res_id, all=0, timeout=0) File "/usr/lib/python2.4/site-packages/ldap/ldapobject.py", line 405, in result res_type,res_data,res_msgid = self.result2(msgid,all,timeout) File "/usr/lib/python2.4/site-packages/ldap/ldapobject.py", line 409, in result2 res_type, res_data, res_msgid, srv_ctrls = self.result3 (msgid,all,timeout) File "/usr/lib/python2.4/site-packages/ldap/ldapobject.py", line 415, in result3 rtype, rdata, rmsgid, serverctrls = self._ldap_call (self._l.result3,msgid,all,timeout) ValueError: need more than 3 values to unpack ---=[end: sample exception]=--- ---=[begin: sample code]=--- #!/usr/bin/python import ldap,time l = ldap.initialize('ldap://ldap.utexas.edu') l.simple_bind_s() #anonymous bind base = r'ou=people,dc=directory,dc=utexas,dc=edu' scope = ldap.SCOPE_ONELEVEL filt = r'(&(uid=yw*)(objectclass=inetOrgPerson))' attrs = ['givenname'] res_id = l.search(base, scope, filt, attrs) # exception occurs without this sleep -- WHY?? #time.sleep(0.1) while 1: print print 'Polling ...' # Set all=0 to retrieve a single entry # Set timeout=0 to poll for a response res = l.result(res_id, all=0, timeout=0) if type(res) == tuple: if res[0] == ldap.RES_SEARCH_ENTRY: print 'Got LDAP ENTRY' print 'Data: ', res[1] elif res[0] == ldap.RES_SEARCH_RESULT: print 'Got LDAP RESULT' print 'Data: ', if res[1] == []: print '--empty--' else: print res[1] break #exit while loop else: print '-'*60 print '*** UNEXPECTED LDAP RESULT ***' print 'DEBUG (res): ', res print '-'*60 else: print 'DEBUG: type = ', type(res) print 'DEBUG: value = ', repr(res) continue print l.unbind_s() ---=[end: sample code]=--- Any help appreciated. Yancey |
From: <mi...@st...> - 2008-01-29 08:48:57
Attachments:
valueerror_in_result3.patch
|
Yeargan Yancey wrote: > > I am trying to use the asynchronous LDAP polling feature and have a > question about what appears to be a timing issue. When I run the code > below, I find that I must insert a sleep() before entering the while > loop or I get a ValueError exception. > [..] > File "/usr/lib/python2.4/site-packages/ldap/ldapobject.py", line 415, > in result3 > rtype, rdata, rmsgid, serverctrls = > self._ldap_call(self._l.result3,msgid,all,timeout) > ValueError: need more than 3 values to unpack Hmm, this should never happen. I guess it's caused by _ldap.result3() returning NULL for the situation where no result was received at all. I will look into it. In the meantime try if the patch to LDAPObject.py attached solves your problem. Ciao, Michael. |
From: Yeargan Y. <ya...@un...> - 2008-01-29 15:36:27
|
Hmm. That only moved the exception. File "/usr/lib/python2.4/site-packages/ldap/ldapobject.py", line =20 421, in result3 rtype, rdata, rmsgid, serverctrls =3D ldap_result ValueError: need more than 3 values to unpack I put the statement above into a try..except block and checked the =20 value when the exception occurs. This line ldap_result =3D self._ldap_call(self._l.result3,msgid,all,timeout) assigns (None,None,None) to ldap_result, a 3-tuple instead of a 4-tuple. Once data becomes available from the LDAP server, then it returns a 4-=20= tuple as expected. Yancey On Jan 29, 2008, at 2:48 AM, Michael Str=F6der wrote: > Yeargan Yancey wrote: >> >> I am trying to use the asynchronous LDAP polling feature and have a >> question about what appears to be a timing issue. When I run the code >> below, I find that I must insert a sleep() before entering the while >> loop or I get a ValueError exception. >> [..] >> File "/usr/lib/python2.4/site-packages/ldap/ldapobject.py", line =20= >> 415, >> in result3 >> rtype, rdata, rmsgid, serverctrls =3D >> self._ldap_call(self._l.result3,msgid,all,timeout) >> ValueError: need more than 3 values to unpack > > Hmm, this should never happen. I guess it's caused by _ldap.result3() > returning NULL for the situation where no result was received at =20 > all. I > will look into it. > > In the meantime try if the patch to LDAPObject.py attached solves your > problem. > > Ciao, Michael.<valueerror_in_result3.patch> |
From: Yeargan, Y. <ya...@un...> - 2008-01-29 22:51:15
|
> Hmm, which version of python-ldap is this? Did you install from source? > > Looking at function l_ldap_result3() in Modules/LDAPObject.c I > can't figure out why a 3-tuple is returned. I did not write this > code though... > > Ciao, Michael. > Not from source. This version came with SuSE Linux Enterprise Server 10. $Id: ldapobject.py,v 1.92 2005/11/03 09:09:43 stroeder Exp $ To solve my immediate need, I re-coded the function like so: def result3(self,msgid=3D_ldap.RES_ANY,all=3D1,timeout=3DNone): if timeout is None: timeout =3D self.timeout ldap_result =3D self._ldap_call(self._l.result3,msgid,all,timeout) if ldap_result =3D=3D (None,None,None): return (None,None,None,None) else: rtype, rdata, rmsgid, serverctrls =3D ldap_result decoded_serverctrls =3D DecodeControlTuples(serverctrls) return rtype, rdata, rmsgid, decoded_serverctrls Can you point me to code for "self._l.result3"? I may have time later this week to do more debugging. Yancey |
From: <mi...@st...> - 2008-01-29 23:01:31
|
Yeargan, Yancey wrote: > > Can you point me to code for "self._l.result3"? Grab the source. Best would be from CVS: http://sourceforge.net/cvs/?group_id=2072 Look at Modules/LDAPObject.c into function l_ldap_result3() (starting at line 940). Ciao, Michael. |
From: Yeargan Y. <ya...@un...> - 2008-01-30 01:10:08
|
python-ldap-2.0.11-14.2 On Jan 29, 2008, at 4:59 PM, Michael Str=F6der wrote: > Yeargan, Yancey wrote: >> >> Not from source. This version came >> with SuSE Linux Enterprise Server 10. > > What does rpm -q python-ldap say? > > Ciao, Michael. |
From: <mi...@st...> - 2008-01-29 22:41:52
|
Yeargan Yancey wrote: > Hmm. That only moved the exception. > > File "/usr/lib/python2.4/site-packages/ldap/ldapobject.py", line > 421, in result3 > rtype, rdata, rmsgid, serverctrls = ldap_result > ValueError: need more than 3 values to unpack > > I put the statement above into a try..except block and checked the > value when the exception occurs. This line > > ldap_result = self._ldap_call(self._l.result3,msgid,all,timeout) > > assigns (None,None,None) to ldap_result, a 3-tuple instead of a 4-tuple. Hmm, which version of python-ldap is this? Did you install from source? Looking at function l_ldap_result3() in Modules/LDAPObject.c I can't figure out why a 3-tuple is returned. I did not write this code though... Ciao, Michael. |
From: <mi...@st...> - 2008-01-29 22:59:26
|
Yeargan, Yancey wrote: > > Not from source. This version came > with SuSE Linux Enterprise Server 10. What does rpm -q python-ldap say? Ciao, Michael. |
From: <mi...@st...> - 2008-01-30 08:14:02
|
Yeargan Yancey wrote: > python-ldap-2.0.11-14.2 Sorry, I'm not keen on supporting this ancient version anymore. This has been released almost two years ago and I'm sure there were bugs in there. Any chance you can build 2.3.1 from source? You can generate a RPM with python setup.py bdist_rpm and install that. But you need to upgrade to OpenLDAP 2.3 for python-ldap too. Maybe it works to install this packages: http://download.opensuse.org/repositories/OpenLDAP/SLE_10/i586/ For building python-ldap you'd also need package openldap2-devel (and cyrus-sasl-devel if SASL support is wanted). Ciao, Michael. |
From: Yeargan Y. <ya...@un...> - 2008-01-30 17:17:13
|
That did the trick. It must be a bug in the older python-ldap code =20 that Novell distributes with SLES 10. OpenLDAP 2.3.32 is already =20 there, as well as SASL 2.1.21, so building python-ldap was easy. =20 Since my organization has a support contract with Novell, I will open =20= a support request and let them know of this issue. In case anyone else runs into this, RPM complained about a missing =20 dependency of "libldap.so.2". I'm not sure why, since I can see it =20 in /usr/lib, but I just used the --nodeps parameter to force the =20 install. I also relocated the files listed in the RPM from /usr/local/=20= lib to /usr/lib to replace the files supplied with SLES 10. rpm -Uvh --nodeps --relocate /usr/local/lib/python2.4/=3D/usr/lib/=20 python2.4/ python-ldap-2.3.1-0.i586.rpm Thanks Michael! Sorry to waste your time. Yancey On Jan 30, 2008, at 2:13 AM, Michael Str=F6der wrote: > Yeargan Yancey wrote: >> python-ldap-2.0.11-14.2 > > Sorry, I'm not keen on supporting this ancient version anymore. =20 > This has > been released almost two years ago and I'm sure there were bugs in > there. Any chance you can build 2.3.1 from source? You can generate a > RPM with > > python setup.py bdist_rpm > > and install that. > > But you need to upgrade to OpenLDAP 2.3 for python-ldap too. Maybe it > works to install this packages: > > http://download.opensuse.org/repositories/OpenLDAP/SLE_10/i586/ > > For building python-ldap you'd also need package openldap2-devel (and > cyrus-sasl-devel if SASL support is wanted). > > Ciao, Michael. |