Changelog

26.0.0 (unreleased)

Python support

  • Dropped support for end-of-life Python 3.6, 3.7, 3.8 and 3.9. (Python 3.5 was already flagged as removed in the 21.2.0 notes.)

  • Added support for Python 3.10, 3.11, 3.12, 3.13 and 3.14.

  • Fixed Python 3.12+ compatibility: replaced the removed configparser.SafeConfigParser with configparser.ConfigParser in ldaptor.config, and stopped a recursive addCleanup call in test_config that failed under 3.12’s stricter cleanup semantics.

Tooling

  • Modernized CI for tox 4; dropped tox-wheel / tox-gh-actions; switched the release env from pep517 to build.

  • Modernized the Read the Docs config and slimmed the docs extras for Python 3.13.

  • Fixed check-manifest by including SECURITY.md and untracking uv.lock.

  • Raised the Twisted[tls] runtime floor from 17.9.0 (2017) to 24.7.0, aligning with modern Twisted’s Python-version matrix and shortening the distance users have to travel to pick up any future security release (e.g. the pending DNS name-decompression DoS in twisted.names.dns.Name.decode, which is still upstream — bump again once Twisted publishes the fix).

  • Raised the sdist/wheel build floors to setuptools>=68.0.0 and wheel>=0.42.0. ldaptor’s MANIFEST.in is entirely ASCII so it is not affected by the setuptools NFC/NFD-normalization advisory, but keeping the build toolchain modern is cheap.

Fixes

  • The Deferred returned from send_multiResponse and send_multiResponse_ex is now fired after the final response is handled (#239).

  • Fixed TypeError in MatchMixin substring / wildcard searches when comparing str attribute values against bytes filter values; substring, initial and final match values are now accepted as either str or bytes (#244).

  • Fixed asText on LDAP filters producing bytes (and raising TypeError: can only concatenate str (not "bytes") to str when formatting a filter for display); asText now consistently returns str for all filter types, including LDAPFilter_extensibleMatch (#226).

  • Fixed LDAPEntry.toWire including the objectClass attribute twice when the attribute key was stored as bytes rather than str (#220).

  • pureber.berDecodeObject now raises UnknownBERTag for unregistered top-level tags instead of writing to stdout and returning None. Twisted then tears down the transport, so a plaintext LDAP server accessed over TLS (or any other framing mismatch) fails fast rather than hanging the client. Also removes a stray print from production code (#170, #240, #243).

  • SearchByTreeWalkingMixin.search now waits for the underlying subtree iterator’s Deferred before firing its own. Previously the iterator’s Deferred was silently discarded, so back ends whose children / subtree methods actually behaved asynchronously returned an empty result set (#62).

  • SearchByTreeWalkingMixin.search now honors sizeLimit, truncating the result set to the requested number of matches. Early termination of the tree walk itself would require an interruptible iterator, which the current mixin does not expose, so the whole tree is still walked – but the network/client cost is bounded (#234).

  • delta.Modification.asLDAP no longer returns wire-encoded bytes; it returns the BERSequence object that LDAPModifyRequest.modification and ModifyOp.fromLDAP already document and expect. This fixes ValueError: too many values to unpack (expected 2) when round-tripping ModifyOp -> asLDAP -> fromLDAP (#223).

  • LDAPModifyDNRequest with deleteoldrdn=False is now honored by the server: the old RDN’s attribute value is retained on the moved entry alongside the new RDN value, per RFC 4511 section 4.9. The in-memory back end grew a deleteOldRDN kwarg on move and the client-side ldapsyntax.LDAPEntry.move grew the same flag so callers can request either behaviour (#89).

  • LDAPClient.unbind now returns a Deferred that fires with the connection-lost reason once the transport has actually been closed, which matters for TLS teardown. A new LDAPClient.notifyOnDisconnect() helper lets callers register additional disconnect Deferreds without initiating an unbind (#225).

  • asText on filters produced by parseFilter (whose .value fields are str rather than the wire-decoded bytes) no longer raises AttributeError: 'str' object has no attribute 'decode'. All ten remaining .value.decode() sites in pureldap.py now go through to_unicode so both str-constructed and wire-decoded filters render (#248, follow-up to #226).

  • MergedLDAPServer no longer hangs or crashes when a backend disconnects. It hooks each backend’s notifyOnDisconnect (see #225), prunes dead backends from self.clients, skips them when dispatching a request, and drops the expected-response count on every outstanding merge so a lost backend can never block completion. LDAPClientTestDriver in ldaptor.testutil grew a matching notifyOnDisconnect so tests can exercise this path (#231).

Docs

  • Rewrote the ldaptor_with_upn_bind example: the custom handle_LDAPBindRequest now delegates to the stock LDAPServer.handle_LDAPBindRequest after resolving a UPN-style BIND DN, instead of copy-pasting the base-class logic. Docstrings explain the UPN shape and the fall-through cases (#161).

21.2.0 (2021-02-28)

  • fix ModuleNotFoundError: No module named 'cStringIO' in ldaptor-ldap2pdns.

  • move scripts to console_scripts entry_points

  • replace deprecated calls to base64.decodestring and base64.encodestring.

  • This will be the last Ldaptor release to support Python 3.5.

20.1.1 (2020-10-02)

  • Updated the object representations of pureber and pureldap containers to directly pass on their contained item object representations. Previously they always passed on the repr after decoding to str with utf-8.

20.1.0 (2020-09-30)

  • Dropped support for Python 2

  • removed Travis CI

20.0.0 (2020-09-30)

  • The next release v20.1.0 will drop support for Python 2, and require Python~=3.5

  • PyPI release is now done via GitHub Action

  • the ldaptor whl is now built with pep517.

  • the ldaptor whl is tested with tox. The sdist is now untested, deprecated and should only be used for compatability with very old packaging tools.

  • the setup.py file is deprecated and will be removed in a future release.

  • SASL Bind without credentials caused list index out of range. Issue #157.

  • ldaptor.protocols.ldap.ldapserver.LDAPServer.handle_LDAPSearchRequest now returns an LDAPSearchResultEntry without any attributes when there is no match between the requested attributes and the entrie’s attributes. Issue #166.

Release 19.1 (2019-09-09)

  • Basic implementation of ldaptor.protocols.pureldap.LDAPSearchResultReference.

  • Explicit ldaptor.protocols.ldap.ldaperrors classes declaration was made to allow syntax highlighting for this module.

  • Example of using LDAP server with the database. Employees are store in the database table and retrieved on server initialization.

  • ldaptor.protocols.pureldap.LDAPPasswordModifyRequest string representation now contains userIdentity, oldPasswd and newPasswd attributes. Password attributes are represented as asterisks.

  • ldaptor.protocols.pureldap.LDAPBindRequest string representation is now using asterisks to represent auth attribute.

  • DeprecationWarning stacklevel was set to mark the caller of the deprecated methods of the ldaptor._encoder classes.

  • NotImplementedError for ldaptor.protocols.pureldap.LDAPSearchResultReference was fixed.

  • Regression bug with LDAPException instances was fixed (ldaptor.protocols.ldap.ldapclient exceptions failed to get their string representations).

  • StartTLS regression bug was fixed: ldaptor.protocols.pureldap.LDAPStartTLSRequest.oid and ldaptor.protocols.pureldap.LDAPStartTLSResponse.oid must be of bytes type.

  • ldaptor.protocols.pureldap and ldaptor.protocols.pureber string representations were fixed: LDAPResult(resultCode=0, matchedDN=’uid=user’) instead of LDAPResult(resultCode=0, matchedDN=”b’uid=user’”).

  • ldaptor.protocols.pureldap.LDAPMatchingRuleAssertion initialization for Python 3 was failed for bytes arguments.

  • ldaptor.protocols.pureldap.LDAPExtendedResponse custom tag parameter was not used.

  • ldaptor._encoder.to_bytes() was fixed under Python 3 to return integers as their numeric representation rather than a sequence of null bytes.

Release 19.0 (2019-03-05)

  • Ability to logically compare ldaptor.protocols.pureldap.LDAPFilter_and and ldaptor.protocols.pureldap.LDAPFilter_or objects with ==.

  • Ability to customize ldaptor.protocols.pureldap.LDAPFilter_* object’s encoding of values when using asText.

  • New client recipe- adding an entry to the DIT.

  • Ability to use paged search control for LDAP clients.

  • New client recipie- using the paged search control.

  • Using modern classmethod decorator instead of old-style method call.

  • Usage of zope.interfaces was updated in preparation for python3 port.

  • toWire method is used to get bytes representation of ldaptor classes instead of __str__ which is deprecated now.

  • Code was updated to pass python3 -m compileall in preparation for py3 port.

  • Code is linted under python 3 in preparation for py3 port.

  • Continuous test are executed only against latest related Twisted and latest Twisted trunk branch.

  • The local development environment was updated to produce overall and diff coverage reports in HTML format.

  • six package is now a direct dependency in preparation for the Python 3 port, and has replaced the ldaptor.compat module.

  • Remove Python 3.3 from tox as it is EOL.

  • Add API documentation for LDAPAttributeSet and startTLS.

  • Quick start and cookbook examples were moved to separate files and made agnostic to the Python version.

  • dependency on pyCrypto replaced with pure python passlib.

  • replace direct dependency on pyOpenSSL with Twisted[tls]

  • DN matching is now case insensitive.

  • Proxies now terminate the connection to the proxied server in case a client immediately closes the connection.

  • asText() implemented for LDAPFilter_extensibleMatch

  • Children of ldaptor.inmemory.ReadOnlyInMemoryLDAPEntry subclass instances are added as the same class instances.

  • Redundant attributes keys sorting was removed from ldaptor.entry.BaseLDAPEntry methods.

Release 16.0 (2016-06-07)

  • Make meta data introspectable

  • Added proxybase.py, an LDAP proxy that is easier to hook into.

  • When parsing LDAPControls, criticality may not exist while controlValue still does

  • Requested attributes can also be passed as ‘*’ symbol

  • Numerous small bug fixes.

  • Additional documentation

  • Updated Travis-CI, Tox and other bits for better coverage.

Release 14.0 (2014-10-31)

Ldaptor has a new version schema. As a first-party library we now follow Twisted’s example.

  • Ldaptor’s original author Tommi Virtanen changed the license to the MIT (Expat) license.

  • ldaptor.md4 has been replaced by a 3-clause BSD version.

  • Ldaptor client and server: None

  • Everything having to do with webui and Nevow have been removed.

  • Travis CI is now used for continuous integration.

  • Test coverage is now measured. We’re currently at around 75%.

  • tox is used now to test ldaptor on all combinations of pypy, Python 2.6, Python 2.7 and Twisted versions from 10.0 until 14.0.

  • A few ordering bugs that were exposed by that and are fixed now.

  • ldaptor.protocols.pureldap.LDAPExtendedRequest now has additional tests.

  • The new ldaptor.protocols.pureldap.LDAPAbandonRequest adds support for abandoning requests.

  • ldaptor.protocols.pureldap.LDAPBindRequest has basic SASL support now. Higher-level APIs like ldapclient don’t expose it yet though.

  • ldaptor.protocols.ldap.ldapclient’s now uses log.msg for it’s debug listing instead of the non-Twisted log.debug.

  • String literal exceptions have been replaced by real Exceptions.

  • “bin/ldaptor-ldap2passwd –help” now does not throws an exception anymore (debian bug #526522).

  • ldaptor.delta.Modification and ldaptor.protocols.ldap.ldapsyntax.PasswordSetAggregateError that are used for adding contacts now handle unicode arguments properly.

  • ldaptor.protocols.pureldap.LDAPExtendedRequest’s constructor now handles STARTTLS in accordance to RFC2251 so the constructor of ldaptor.protocols.pureldap.LDAPStartTLSRequest doesn’t fail anymore.

  • ldaptor.protocols.ldap.ldapserver.BaseLDAPServer now uses the correct exception module in dataReceived.

  • ldaptor.protocols.ldap.ldaperrors.LDAPException: “Fix deprecated exception error”

  • bin/ldaptor-find-server now imports dns from the correct twisted modules.

  • bin/ldaptor-find-server now only prints SRV records.

  • ldaptor.protocols.ldap.ldapsyntax.LDAPEntryWithClient now correctly propagates errors on search(). The test suite has been adapted appropriately.

  • ldaptor.protocols.ldap.ldapconnector.LDAPConnector now supports specifying a local address when connecting to a server.

  • The new ldaptor.protocols.pureldap.LDAPSearchResultReference now prevents ldaptor from choking on results containing SearchResultReference (usually from Active Directory servers). It is currently only a stub and silently ignored.

  • hashlib and built-in set() are now used instead of deprecated modules.

  • Added, updated and reworked documentation using Sphinx. Dia is required for converting diagrams to svg/png, this might change in the future.

  • Dia is now invoked correctly for diagram generation in a headless environment.

  • The documentation is now hosted on https://ldaptor.readthedocs.org/.

Prehistory

All versions up to and including 0.0.43 didn’t have a changelog.