From 9a0bfecfea73807857b9e50b3f9c230568d9dbd9 Mon Sep 17 00:00:00 2001 From: Florian Best Date: Tue, 8 Jul 2025 11:24:36 +0200 Subject: [PATCH 1/2] test(t_ldapobject): test pickling unbound connection Issue #587 --- Tests/t_ldapobject.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Tests/t_ldapobject.py b/Tests/t_ldapobject.py index ada5f990..ecf163b7 100644 --- a/Tests/t_ldapobject.py +++ b/Tests/t_ldapobject.py @@ -617,12 +617,20 @@ def test103_reconnect_get_state(self): ) def test104_reconnect_restore(self): - l1 = self.ldap_object_class(self.server.ldap_uri) + l0 = self.ldap_object_class(self.server.ldap_uri) + + l0_state = pickle.dumps(l0) + del l0 + l1 = pickle.loads(l0_state) + self.assertEqual(l1.whoami_s(), '') + bind_dn = 'cn=user1,'+self.server.suffix l1.simple_bind_s(bind_dn, 'user1_pw') + self.assertEqual(l1.whoami_s(), 'dn:'+bind_dn) l1_state = pickle.dumps(l1) del l1 + l2 = pickle.loads(l1_state) self.assertEqual(l2.whoami_s(), 'dn:'+bind_dn) From 8f1616d42a686ec2d278d651d70198e0fb91bc35 Mon Sep 17 00:00:00 2001 From: Florian Best Date: Tue, 8 Jul 2025 11:28:14 +0200 Subject: [PATCH 2/2] fix(ldapobject): allow pickling with unbound connection Issue #587 --- Lib/ldap/ldapobject.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/ldap/ldapobject.py b/Lib/ldap/ldapobject.py index 7a9c17f6..aee5bec7 100644 --- a/Lib/ldap/ldapobject.py +++ b/Lib/ldap/ldapobject.py @@ -877,7 +877,10 @@ def __getstate__(self): for k,v in self.__dict__.items() if k not in self.__transient_attrs__ } - state['_last_bind'] = self._last_bind[0].__name__, self._last_bind[1], self._last_bind[2] + if self._last_bind is None: + state['_last_bind'] = None + else: + state['_last_bind'] = self._last_bind[0].__name__, self._last_bind[1], self._last_bind[2] return state def __setstate__(self,d): @@ -888,7 +891,8 @@ def __setstate__(self,d): else: d.setdefault('bytes_strictness', 'warn') self.__dict__.update(d) - self._last_bind = getattr(SimpleLDAPObject, self._last_bind[0]), self._last_bind[1], self._last_bind[2] + if self._last_bind is not None: + self._last_bind = getattr(SimpleLDAPObject, self._last_bind[0]), self._last_bind[1], self._last_bind[2] self._ldap_object_lock = self._ldap_lock() self._reconnect_lock = ldap.LDAPLock(desc='reconnect lock within %s' % (repr(self))) # XXX cannot pickle file, use default trace file