Improve backwards compatibility of encoding rules.
If a LDAP connection is initialized without explicitly setting ``bytes_mode`` to either True or False, show warnings instead of raising a TypeError.
This commit is contained in:
parent
4f8a38cab2
commit
b678b6883a
|
@ -88,6 +88,9 @@ class SimpleLDAPObject:
|
||||||
|
|
||||||
# Bytes mode
|
# Bytes mode
|
||||||
# ----------
|
# ----------
|
||||||
|
|
||||||
|
# By default, raise a TypeError when receiving invalid args
|
||||||
|
self.bytes_mode_hardfail = True
|
||||||
if bytes_mode is None and PY2:
|
if bytes_mode is None and PY2:
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"Under Python 2, python-ldap uses bytes by default. "
|
"Under Python 2, python-ldap uses bytes by default. "
|
||||||
|
@ -97,6 +100,8 @@ class SimpleLDAPObject:
|
||||||
stacklevel=2,
|
stacklevel=2,
|
||||||
)
|
)
|
||||||
bytes_mode = True
|
bytes_mode = True
|
||||||
|
# Disable hard failure when running in backwards compatibility mode.
|
||||||
|
self.bytes_mode_hardfail = False
|
||||||
elif bytes_mode and not PY2:
|
elif bytes_mode and not PY2:
|
||||||
raise ValueError("bytes_mode is *not* supported under Python 3.")
|
raise ValueError("bytes_mode is *not* supported under Python 3.")
|
||||||
# On by default on Py2, off on Py3.
|
# On by default on Py2, off on Py3.
|
||||||
|
@ -115,7 +120,15 @@ class SimpleLDAPObject:
|
||||||
return value
|
return value
|
||||||
elif self.bytes_mode:
|
elif self.bytes_mode:
|
||||||
if not isinstance(value, bytes):
|
if not isinstance(value, bytes):
|
||||||
raise TypeError("All provided fields *must* be bytes when bytes mode is on; got %r" % (value,))
|
if self.bytes_mode_hardfail:
|
||||||
|
raise TypeError("All provided fields *must* be bytes when bytes mode is on; got %r" % (value,))
|
||||||
|
else:
|
||||||
|
warnings.warn(
|
||||||
|
"Received non-bytes value %r with default (disabled) bytes mode; please choose an explicit "
|
||||||
|
"option for bytes_mode on your LDAP connection" % (value,),
|
||||||
|
BytesWarning,
|
||||||
|
stacklevel=6,
|
||||||
|
)
|
||||||
return value.decode('utf-8')
|
return value.decode('utf-8')
|
||||||
else:
|
else:
|
||||||
if not isinstance(value, text_type):
|
if not isinstance(value, text_type):
|
||||||
|
|
3
README
3
README
|
@ -43,7 +43,8 @@ through the ``bytes_mode`` flag to ``ldap.initialize()``.
|
||||||
When porting from ``python-ldap``, users are advised to update their code to set ``bytes_mode=False``
|
When porting from ``python-ldap``, users are advised to update their code to set ``bytes_mode=False``
|
||||||
on calls to these methods.
|
on calls to these methods.
|
||||||
Under Python 2, ``pyldap`` checks aggressively the type of provided arguments, and will raise a ``TypeError``
|
Under Python 2, ``pyldap`` checks aggressively the type of provided arguments, and will raise a ``TypeError``
|
||||||
for any invalid parameter.
|
for any invalid parameter; however, if the ``bytes_mode`` kwarg isn't provided, ``pyldap`` will only
|
||||||
|
raise warnings.
|
||||||
|
|
||||||
The typical usage is as follow; note that only the result's *values* are of the bytes type:
|
The typical usage is as follow; note that only the result's *values* are of the bytes type:
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,12 @@ class TestSearch(unittest.TestCase):
|
||||||
for value in values:
|
for value in values:
|
||||||
self.assertEqual(type(value), bytes)
|
self.assertEqual(type(value), bytes)
|
||||||
|
|
||||||
def _get_bytes_ldapobject(self):
|
def _get_bytes_ldapobject(self, explicit=True):
|
||||||
l = LDAPObject(server.get_url(), bytes_mode=True)
|
if explicit:
|
||||||
|
kwargs = {'bytes_mode': True}
|
||||||
|
else:
|
||||||
|
kwargs = {}
|
||||||
|
l = LDAPObject(server.get_url(), **kwargs)
|
||||||
l.protocol_version = 3
|
l.protocol_version = 3
|
||||||
l.set_option(ldap.OPT_REFERRALS,0)
|
l.set_option(ldap.OPT_REFERRALS,0)
|
||||||
l.simple_bind_s(self.server.get_root_dn().encode('utf-8'),
|
l.simple_bind_s(self.server.get_root_dn().encode('utf-8'),
|
||||||
|
@ -115,6 +119,15 @@ class TestSearch(unittest.TestCase):
|
||||||
for value in values:
|
for value in values:
|
||||||
self.assertEqual(type(value), bytes)
|
self.assertEqual(type(value), bytes)
|
||||||
|
|
||||||
|
@unittest.skipUnless(PY2, "no bytes_mode under Py3")
|
||||||
|
def test_unset_bytesmode_search_warns_bytes(self):
|
||||||
|
l = self._get_bytes_ldapobject(explicit=False)
|
||||||
|
base = self.server.get_dn_suffix()
|
||||||
|
|
||||||
|
l.search_s(base.encode('utf-8'), ldap.SCOPE_SUBTREE, '(cn=Foo*)', [b'*'])
|
||||||
|
l.search_s(base.encode('utf-8'), ldap.SCOPE_SUBTREE, b'(cn=Foo*)', ['*'])
|
||||||
|
l.search_s(base, ldap.SCOPE_SUBTREE, b'(cn=Foo*)', [b'*'])
|
||||||
|
|
||||||
def test_search_subtree(self):
|
def test_search_subtree(self):
|
||||||
base = self.server.get_dn_suffix()
|
base = self.server.get_dn_suffix()
|
||||||
l = self.ldap
|
l = self.ldap
|
||||||
|
|
Loading…
Reference in New Issue