[python-ldap] Yet another Python3 port (Rapha?l Barrois)

python3ldap python3ldap at gmail.com
Tue Nov 19 13:46:12 CET 2013


Hi Raphael,
I've developed a pure python3 ldap client (can be used with python2
too) that doesn't need the openldap client extension. You can find it
on https://pypi.python.org/pypi/python3-ldap.

I had the same problem with unicode, in python3 you don't have to care
too much about it, but for python2 code I left out the byte->unicode
conversion for now, because I'm not sure which is a valid approach to
the problem.

I've kept the code as clean of as possible without any "if python3
... else...  ", so I have a single codebase to manage. Let me know if
you find a valid solution for python2 and python3 "coexistence".

Bye,
Giovanni


On Mon, 18 Nov 2013 08:58:36 -0500
"Rob McBroom" <mailinglist0 at skurfer.com> wrote:

> On 14 Nov 2013, at 4:57, Rapha?l Barrois wrote:
>
> > Does this port interest you?
>
> Yes. I mean, sooner or later, we?re all going to have to be interested, right?
>

Great!

Now, let's get to the actual porting issue on which I'd like to get some input.

The current python-ldap lib (without my fixes) uses only "str" (or "bytes")
internally ? the calling code should perform the "unicode to utf-8" conversion
before sending anything, and the reverse when reading.

This is quite cumbersome for non-pure-ascii systems (e.g, outside the US), but
works not too bad for most commands where lookups, filters, etc. are pure ascii
and thus silently converted into utf-8 bytes (as requested per the LDAP RFCs).


With Python3, there is no auto-magic str/bytes conversion; we'll have
to choose the behaviour regarding input *and* output:
1. Accept only Bytes, return only Bytes
2. Accept both Bytes and Text (with auto-magic cast, as in Py2),
return Bytes (as in Py2)
2. Accept both Bytes and Text (with auto-magic cast, as in Py2), return Text
3. Accept only Text, return Text


All solutions are possible, the main issue is for users of the library.

Here is an example of the same Py2 snippet with the various options, on Py3:

>>> print(connection.search_st(
filter=u"Rapha?l Barrois".encode('utf-8'))[0]['givenName'][0].decode('utf-8'))
u"Rapha?l Barrois"

Option 1:
---------
>>> print(connection.search_st(filter="Rapha?l Barrois".encode('utf-8'))[0][b'givenName'][0].decode('utf-8'))
"Rapha?l Barrois"
# NB: We'll have to put a 'b' in front of each attribute name...

Option 2:
---------
>>> print(connection.search_st(filter="Rapha?l Barrois")[0][b'givenName'][0].decode('utf-8'))
"Rapha?l Barrois"
# Asymmetrical: we send text, and get bytes
# We need to put a 'b' in front of each attribute name...

Option 3:
---------
>>> print(connection.search_st(filter="Rapha?l Barrois")[0]['givenName'][0])
"Rapha?l Barrois"
# Not backwards compatible with Py2, where we'd receive bytes

Option 4:
---------
>>> print(connection.search_st(filter="Rapha?l Barrois")[0]['givenName'][0])
"Rapha?l Barrois"



I personally find the 4th option the cleanest, but it would break
compatibility with Py2.

What do you think?

--
Rapha?l Barrois


More information about the python-ldap mailing list