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:
Raphaël Barrois 2015-07-27 21:52:39 +02:00
parent 4f8a38cab2
commit b678b6883a
3 changed files with 31 additions and 4 deletions

View File

@ -88,6 +88,9 @@ class SimpleLDAPObject:
# Bytes mode
# ----------
# By default, raise a TypeError when receiving invalid args
self.bytes_mode_hardfail = True
if bytes_mode is None and PY2:
warnings.warn(
"Under Python 2, python-ldap uses bytes by default. "
@ -97,6 +100,8 @@ class SimpleLDAPObject:
stacklevel=2,
)
bytes_mode = True
# Disable hard failure when running in backwards compatibility mode.
self.bytes_mode_hardfail = False
elif bytes_mode and not PY2:
raise ValueError("bytes_mode is *not* supported under Python 3.")
# On by default on Py2, off on Py3.
@ -115,7 +120,15 @@ class SimpleLDAPObject:
return value
elif self.bytes_mode:
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')
else:
if not isinstance(value, text_type):

3
README
View File

@ -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``
on calls to these methods.
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:

View File

@ -81,8 +81,12 @@ class TestSearch(unittest.TestCase):
for value in values:
self.assertEqual(type(value), bytes)
def _get_bytes_ldapobject(self):
l = LDAPObject(server.get_url(), bytes_mode=True)
def _get_bytes_ldapobject(self, explicit=True):
if explicit:
kwargs = {'bytes_mode': True}
else:
kwargs = {}
l = LDAPObject(server.get_url(), **kwargs)
l.protocol_version = 3
l.set_option(ldap.OPT_REFERRALS,0)
l.simple_bind_s(self.server.get_root_dn().encode('utf-8'),
@ -115,6 +119,15 @@ class TestSearch(unittest.TestCase):
for value in values:
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):
base = self.server.get_dn_suffix()
l = self.ldap