Skip to content

Commit

Permalink
Remove Python 2 support
Browse files Browse the repository at this point in the history
python-ldap 3.4 will require Python 3.6 or newer.

https://github.com/python-ldap/python-ldap/pull/358

Signed-off-by: Christian Heimes <cheimes@redhat.com>
  • Loading branch information
Christian Heimes authored and GitHub committed Jun 22, 2020
1 parent 6aacd6f commit 2be2c6b
Show file tree
Hide file tree
Showing 29 changed files with 134 additions and 994 deletions.
24 changes: 4 additions & 20 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,14 @@ addons:
# Note: when updating Python versions, also change setup.py and tox.ini
matrix:
include:
- python: 2.7
env:
- TOXENV=py27
- WITH_GCOV=1
- python: 3.4
env:
- TOXENV=py34
- WITH_GCOV=1
- python: 3.5
env:
- TOXENV=py35
- WITH_GCOV=1
- python: 3.6
env:
- TOXENV=py36
- WITH_GCOV=1
- python: pypy
- python: pypy3
env:
- TOXENV=pypy
- TOXENV=pypy3
- CFLAGS_std="-std=c99"
- python: 3.7
env:
- TOXENV=py37
Expand All @@ -53,10 +42,6 @@ matrix:
- WITH_GCOV=1
dist: xenial
sudo: true
- python: 2.7
env:
- TOXENV=py2-nosasltls
- WITH_GCOV=1
- python: 3.6
env:
- TOXENV=py3-nosasltls
Expand All @@ -68,7 +53,7 @@ matrix:
env: TOXENV=doc
allow_failures:
- env:
- TOXENV=pypy
- TOXENV=pypy3

env:
global:
Expand All @@ -87,4 +72,3 @@ install:
- pip install tox-travis tox codecov

script: CFLAGS="$CFLAGS_warnings $CFLAGS_std" tox

138 changes: 20 additions & 118 deletions Doc/bytes_mode.rst
Original file line number Diff line number Diff line change
@@ -1,34 +1,12 @@
.. _text-bytes:
.. _bytes_mode:

Bytes/text management
=====================

Python 3 introduces a hard distinction between *text* (``str``) – sequences of
characters (formally, *Unicode codepoints*) – and ``bytes`` – sequences of
8-bit values used to encode *any* kind of data for storage or transmission.

Python 2 has the same distinction between ``str`` (bytes) and
``unicode`` (text).
However, values can be implicitly converted between these types as needed,
e.g. when comparing or writing to disk or the network.
The implicit encoding and decoding can be a source of subtle bugs when not
designed and tested adequately.

In python-ldap 2.x (for Python 2), bytes were used for all fields,
including those guaranteed to be text.

From version 3.0, python-ldap uses text where appropriate.
On Python 2, the :ref:`bytes mode <bytes_mode>` setting influences how text is
handled.


What's text, and what's bytes
-----------------------------

The LDAP protocol states that some fields (distinguished names, relative
distinguished names, attribute names, queries) be encoded in UTF-8.
In python-ldap, these are represented as text (``str`` on Python 3,
``unicode`` on Python 2).
In python-ldap, these are represented as text (``str`` on Python 3).

Attribute *values*, on the other hand, **MAY**
contain any type of data, including text.
Expand All @@ -38,102 +16,26 @@ Thus, attribute values are *always* treated as ``bytes``.
Encoding/decoding to other formats – text, images, etc. – is left to the caller.


.. _bytes_mode:

The bytes mode
--------------

In Python 3, text values are represented as ``str``, the Unicode text type.

In Python 2, the behavior of python-ldap 3.0 is influenced by a ``bytes_mode``
argument to :func:`ldap.initialize`:

``bytes_mode=True`` (backwards compatible):
Text values are represented as bytes (``str``) encoded using UTF-8.

``bytes_mode=False`` (future compatible):
Text values are represented as ``unicode``.

If not given explicitly, python-ldap will default to ``bytes_mode=True``,
but if a ``unicode`` value is supplied to it, it will warn and use that value.

Backwards-compatible behavior is not scheduled for removal until Python 2
itself reaches end of life.


Errors, warnings, and automatic encoding
----------------------------------------

While the type of values *returned* from python-ldap is always given by
``bytes_mode``, for Python 2 the behavior for “wrong-type” values *passed in*
can be controlled by the ``bytes_strictness`` argument to
:func:`ldap.initialize`:
Historical note
---------------

``bytes_strictness='error'`` (default if ``bytes_mode`` is specified):
A ``TypeError`` is raised.

``bytes_strictness='warn'`` (default when ``bytes_mode`` is not given explicitly):
A warning is raised, and the value is encoded/decoded
using the UTF-8 encoding.

The warnings are of type :class:`~ldap.LDAPBytesWarning`, which
is a subclass of :class:`BytesWarning` designed to be easily
:ref:`filtered out <filter-bytes-warning>` if needed.

``bytes_strictness='silent'``:
The value is automatically encoded/decoded using the UTF-8 encoding.

On Python 3, ``bytes_strictness`` is ignored and a ``TypeError`` is always
raised.

When setting ``bytes_strictness``, an explicit value for ``bytes_mode`` needs
to be given as well.


Porting recommendations
-----------------------

Since end of life of Python 2 is coming in a few years, projects are strongly
urged to make their code compatible with Python 3. General instructions for
this are provided :ref:`in Python documentation <pyporting-howto>` and in the
`Conservative porting guide`_.

.. _Conservative porting guide: https://portingguide.readthedocs.io/en/latest/


When porting from python-ldap 2.x, users are advised to update their code
to set ``bytes_mode=False``, and fix any resulting failures.

The typical usage is as follows.
Note that only the result's *values* are of the ``bytes`` type:

.. code-block:: pycon
>>> import ldap
>>> con = ldap.initialize('ldap://localhost:389', bytes_mode=False)
>>> con.simple_bind_s(u'login', u'secret_password')
>>> results = con.search_s(u'ou=people,dc=example,dc=org', ldap.SCOPE_SUBTREE, u"(cn=Raphaël)")
>>> results
[
("cn=Raphaël,ou=people,dc=example,dc=org", {
'cn': [b'Rapha\xc3\xabl'],
'sn': [b'Barrois'],
}),
]
.. _filter-bytes-warning:

Filtering warnings
------------------
Python 3 introduced a hard distinction between *text* (``str``) – sequences of
characters (formally, *Unicode codepoints*) – and ``bytes`` – sequences of
8-bit values used to encode *any* kind of data for storage or transmission.

The bytes mode warnings can be filtered out and ignored with a
simple filter.
Python 2 had the same distinction between ``str`` (bytes) and
``unicode`` (text).
However, values could be implicitly converted between these types as needed,
e.g. when comparing or writing to disk or the network.
The implicit encoding and decoding can be a source of subtle bugs when not
designed and tested adequately.

.. code-block:: python
In python-ldap 2.x (for Python 2), bytes were used for all fields,
including those guaranteed to be text.

import warnings
import ldap
From version 3.0 to 3.3, python-ldap uses text where appropriate.
On Python 2, special ``bytes_mode`` and ``bytes_strictness`` settings
influenced how text was handled.

if hasattr(ldap, 'LDAPBytesWarning'):
warnings.simplefilter('ignore', ldap.LDAPBytesWarning)
From version 3.3 on, only Python 3 is supported. The “bytes mode” settings
are deprecated and do nothing.
2 changes: 1 addition & 1 deletion Doc/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Usage
.. _pyldap: https://pypi.org/project/pyldap/


**Q**: Does it work with Python 2.6? (1.5|2.0|2.1|2.2|2.3|2.4|2.5)?
**Q**: Does it work with Python 2.7? (1.5|2.0|2.1|2.2|2.3|2.4|2.5|2.6|2.7)?

**A**: No. Old versions of python-ldap are still available from PyPI, though.

Expand Down
22 changes: 15 additions & 7 deletions Doc/reference/ldap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Functions

This module defines the following functions:

.. py:function:: initialize(uri [, trace_level=0 [, trace_file=sys.stdout [, trace_stack_limit=None, [bytes_mode=None, [bytes_strictness=None, [fileno=None]]]]]]) -> LDAPObject object
.. py:function:: initialize(uri [, trace_level=0 [, trace_file=sys.stdout [, trace_stack_limit=None, [fileno=None]]]]) -> LDAPObject object
Initializes a new connection object for accessing the given LDAP server,
and return an :class:`~ldap.ldapobject.LDAPObject` used to perform operations
Expand Down Expand Up @@ -63,10 +63,6 @@ This module defines the following functions:
*trace_file* specifies a file-like object as target of the debug log and
*trace_stack_limit* specifies the stack limit of tracebacks in debug log.

The *bytes_mode* and *bytes_strictness* arguments specify text/bytes
behavior under Python 2.
See :ref:`text-bytes` for a complete documentation.

Possible values for *trace_level* are
:py:const:`0` for no logging,
:py:const:`1` for only logging the method calls with arguments,
Expand All @@ -78,6 +74,10 @@ This module defines the following functions:
Any additional keyword arguments are passed to ``LDAPObject``.
It is also fine to instantiate a ``LDAPObject`` (or a subclass) directly.

The function additionally takes *bytes_mode* and *bytes_strictness* keyword
arguments, which are deprecated and ignored. See :ref:`bytes_mode` for
details.

.. seealso::

:rfc:`4516` - Lightweight Directory Access Protocol (LDAP): Uniform Resource Locator
Expand All @@ -86,6 +86,10 @@ This module defines the following functions:

The *fileno* argument was added.

.. deprecated:: 3.4

*bytes_mode* and *bytes_strictness* arguments are deprecated.


.. py:function:: get_option(option) -> int|string
Expand Down Expand Up @@ -730,12 +734,16 @@ Warnings

.. py:class:: LDAPBytesWarning
Raised when bytes/text mismatch in non-strict bytes mode.
This warning is deprecated. python-ldap no longer raises it.

See :ref:`bytes_mode` for details.
It used to be raised under Python 2 when bytes/text mismatch in non-strict
bytes mode. See :ref:`bytes_mode` for details.

.. versionadded:: 3.0.0

.. versionchanged:: 3.4.0

Deprecated.

.. _ldap-objects:

Expand Down
3 changes: 1 addition & 2 deletions Doc/reference/ldapurl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@

This module parses and generates LDAP URLs. It is implemented in pure Python
and does not rely on any non-standard modules. Therefore it can be used stand-
alone without the rest of the python-ldap package. Compatibility note: This
module has been solely tested on Python 2.x and above.
alone without the rest of the python-ldap package.

.. seealso::

Expand Down
2 changes: 0 additions & 2 deletions Doc/sample_workflow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ python-ldap won't affect the rest of your system::

$ python3 -m venv __venv__

(For Python 2, install `virtualenv`_ and use it instead of ``python3 -m venv``.)

.. _git: https://git-scm.com/
.. _virtualenv: https://virtualenv.pypa.io/en/stable/

Expand Down
2 changes: 1 addition & 1 deletion Lib/ldap/cidict.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"""
import warnings

from ldap.compat import MutableMapping
from collections.abc import MutableMapping
from ldap import __version__


Expand Down
Loading

0 comments on commit 2be2c6b

Please sign in to comment.