Install & Compatibility
Where this runs
tested against v21.2.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.474s · 76.3MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 5.9s · import 0.462s · 77MB
79MB installed
● package 79MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
LDAPServer
✓ from ldaptor.protocols.ldap.ldapserver import LDAPServer
Twisted-based LDAP server — most searched ldaptor symbol
LDAPClient
✓ from ldaptor.protocols.ldap.ldapclient import LDAPClient
ldapconnector
✓ from ldaptor.protocols.ldap import ldapconnector
reactor, defer
✓ from twisted.internet import reactor, defer
This quickstart demonstrates how to connect to an LDAP server, bind with credentials, and perform a basic search operation using Ldaptor and Twisted's asynchronous reactor. The example uses environment variables for sensitive connection details, falling back to defaults if not set. Remember to replace placeholder values with your actual LDAP server details.
import os
from twisted.internet import reactor, defer
from ldaptor.protocols.ldap import ldapclient, ldapsyntax, ldapconnector
@defer.inlineCallbacks
def example():
# Note: For production, load sensitive data securely (e.g., from environment variables).
# It is recommended to use byte strings for ldaptor objects.
server_ip = os.environ.get('LDAP_SERVER_IP', '127.0.0.1').encode('utf-8')
basedn = os.environ.get('LDAP_BASE_DN', 'dc=example,dc=com').encode('utf-8')
binddn = os.environ.get('LDAP_BIND_DN', 'cn=admin,dc=example,dc=com').encode('utf-8')
bindpw = os.environ.get('LDAP_BIND_PASSWORD', 'secret').encode('utf-8')
query = os.environ.get('LDAP_QUERY', '(objectClass=*)').encode('utf-8')
# Create an LDAP client creator
c = ldapconnector.LDAPClientCreator(reactor, ldapclient.LDAPClient)
# Define overrides for connecting to the LDAP server
overrides = {basedn: (server_ip, 389)}
# Connect to the LDAP server
client = yield c.connect(basedn, overrides=overrides)
print(f"Connected to LDAP server at {server_ip.decode('utf-8')}")
# Bind to the LDAP server
yield client.bind(binddn, bindpw)
print(f"Bound as {binddn.decode('utf-8')}")
# Perform a search
o = ldapsyntax.LDAPEntry(client, basedn)
results = yield o.search(filterText=query)
print(f"Found {len(results)} entries for query '{query.decode('utf-8')}'")
# Print LDIF for each result
for entry in results:
print(entry.getLDIF())
print("LDAP operations complete.")
if __name__ == '__main__':
df = example()
df.addErrback(lambda err: err.printTraceback())
df.addCallback(lambda _: reactor.stop())
reactor.run()
ldaptor --version
Errors
Common errors & fixes
ImportError: cannot import name 'LDAPServer' from 'ldaptor'
LDAPServer is in ldaptor.protocols.ldap.ldapserver, not top-level
fixfrom ldaptor.protocols.ldap.ldapserver import LDAPServer
AttributeError: module 'ldaptor' has no attribute 'LDAPClient'
LDAPClient is in ldaptor.protocols.ldap.ldapclient, not top-level
fixfrom ldaptor.protocols.ldap.ldapclient import LDAPClient
ModuleNotFoundError: No module named 'ldaptor'
ldaptor not installed
twisted.internet.error.ConnectionRefusedError: Connection was refused by other side
LDAP server not running or wrong host/port
fixVerify LDAP server is running on target host and port 389
SyntaxError: invalid syntax — raise ldaperrors.LDAPEntryAlreadyExists, dn
Python 2 raise syntax used in Python 3
fixraise ldaperrors.LDAPEntryAlreadyExists(dn)
Upgrade
Version history
21.2.0latest on PyPI · released Feb 28, 2021
Audit
Dependencies
Twisted[tls]requiredCore asynchronous networking framework dependency for client/server protocols.
pyparsingrequiredUsed for parsing LDAP filters and other protocol elements.
passliboptionalUsed for Samba password manipulation; optional if not using Samba features.
zope.interfacerequiredRequired for registering implementers of Twisted interfaces.
sixrequiredHistorically used for Python 2/3 compatibility; listed as a dependency in PyPI for 21.2.0.