Skip to content

Commit 956c961

Browse files
author
stroeder
committed
ldap.ldapobject split into module-package
1 parent b5e0c3c commit 956c961

File tree

4 files changed

+242
-221
lines changed

4 files changed

+242
-221
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Lib/
2222
* module ldif now uses functions b64encode() and b64decode()
2323
* fixed pickling and restoring of ReconnectLDAPObject
2424
* more modules with PEP-8 compliance
25+
* ldap.ldapobject split into module-package
2526

2627
Tests/
2728
* scripts do not directly call SlapdTestCase.setUpClass() anymore

Lib/ldap/ldapobject.py renamed to Lib/ldap/ldapobject/__init__.py

Lines changed: 3 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
ldapobject.py - wraps class _ldap.LDAPObject
2+
ldap.ldapobject - wraps class _ldap.LDAPObject
33
44
See https://www.python-ldap.org/ for details.
55
"""
@@ -1091,226 +1091,8 @@ def get_naming_contexts(self):
10911091
).get('namingContexts', [])
10921092

10931093

1094-
class ReconnectLDAPObject(SimpleLDAPObject):
1095-
"""
1096-
In case of server failure (ldap.SERVER_DOWN) the implementations
1097-
of all synchronous operation methods (search_s() etc.) are doing
1098-
an automatic reconnect and rebind and will retry the very same
1099-
operation.
1100-
1101-
This is very handy for broken LDAP server implementations
1102-
(e.g. in Lotus Domino) which drop connections very often making
1103-
it impossible to have a long-lasting control flow in the
1104-
application.
1105-
"""
1106-
1107-
__transient_attrs__ = set([
1108-
'_l',
1109-
'_ldap_object_lock',
1110-
'_trace_file',
1111-
'_reconnect_lock',
1112-
'_last_bind',
1113-
])
1114-
1115-
def __init__(
1116-
self,
1117-
uri,
1118-
trace_level=0, trace_file=None, trace_stack_limit=5,
1119-
retry_max=1, retry_delay=60.0
1120-
):
1121-
"""
1122-
Parameters like SimpleLDAPObject.__init__() with these
1123-
additional arguments:
1124-
1125-
retry_max
1126-
Maximum count of reconnect trials
1127-
retry_delay
1128-
Time span to wait between two reconnect trials
1129-
"""
1130-
self._uri = uri
1131-
self._options = []
1132-
self._last_bind = None
1133-
SimpleLDAPObject.__init__(self, uri, trace_level, trace_file, trace_stack_limit)
1134-
self._reconnect_lock = ldap.LDAPLock(desc='reconnect lock within %r' % self)
1135-
self._retry_max = retry_max
1136-
self._retry_delay = retry_delay
1137-
self._start_tls = 0
1138-
self._reconnects_done = 0L
1139-
1140-
def __getstate__(self):
1141-
"""
1142-
return data representation for pickled object
1143-
"""
1144-
state = dict([
1145-
(key, val)
1146-
for key, val in self.__dict__.items()
1147-
if key not in self.__transient_attrs__
1148-
])
1149-
state['_last_bind'] = (
1150-
self._last_bind[0].__name__,
1151-
self._last_bind[1],
1152-
self._last_bind[2],
1153-
)
1154-
return state
1155-
1156-
def __setstate__(self, data):
1157-
"""
1158-
set up the object from pickled data
1159-
"""
1160-
self.__dict__.update(data)
1161-
self._last_bind = (
1162-
getattr(SimpleLDAPObject, self._last_bind[0]),
1163-
self._last_bind[1],
1164-
self._last_bind[2],
1165-
)
1166-
self._ldap_object_lock = self._ldap_lock()
1167-
self._reconnect_lock = ldap.LDAPLock(desc='reconnect lock within %r' % (self))
1168-
self._trace_file = sys.stdout
1169-
self.reconnect(self._uri)
1170-
1171-
def _store_last_bind(self, method, *args, **kwargs):
1172-
self._last_bind = (method, args, kwargs)
1173-
1174-
def _apply_last_bind(self):
1175-
if self._last_bind != None:
1176-
func, args, kwargs = self._last_bind
1177-
func(self, *args, **kwargs)
1178-
else:
1179-
# Send explicit anon simple bind request to provoke
1180-
# ldap.SERVER_DOWN in method reconnect()
1181-
SimpleLDAPObject.simple_bind_s(self, '', '')
1182-
1183-
def _restore_options(self):
1184-
"""Restore all recorded options"""
1185-
for key, val in self._options:
1186-
SimpleLDAPObject.set_option(self, key, val)
1187-
1188-
def passwd_s(self, *args, **kwargs):
1189-
return self._apply_method_s(SimpleLDAPObject.passwd_s, *args, **kwargs)
1190-
1191-
def reconnect(self, uri, retry_max=1, retry_delay=60.0):
1192-
# Drop and clean up old connection completely
1193-
# Reconnect
1194-
self._reconnect_lock.acquire()
1195-
try:
1196-
reconnect_counter = retry_max
1197-
while reconnect_counter:
1198-
counter_text = '%d. (of %d)' % (retry_max-reconnect_counter+1, retry_max)
1199-
if __debug__ and self._trace_level >= 1:
1200-
self._trace_file.write('*** Trying %s reconnect to %s...\n' % (
1201-
counter_text, uri
1202-
))
1203-
try:
1204-
# Do the connect
1205-
self._l = ldap.functions._ldap_function_call(
1206-
ldap._ldap_module_lock,
1207-
_ldap.initialize,
1208-
uri
1209-
)
1210-
self._restore_options()
1211-
# StartTLS extended operation in case this was called before
1212-
if self._start_tls:
1213-
SimpleLDAPObject.start_tls_s(self)
1214-
# Repeat last simple or SASL bind
1215-
self._apply_last_bind()
1216-
except (ldap.SERVER_DOWN, ldap.TIMEOUT), e:
1217-
if __debug__ and self._trace_level >= 1:
1218-
self._trace_file.write('*** %s reconnect to %s failed\n' % (
1219-
counter_text, uri
1220-
))
1221-
reconnect_counter = reconnect_counter-1
1222-
if not reconnect_counter:
1223-
raise e
1224-
if __debug__ and self._trace_level >= 1:
1225-
self._trace_file.write('=> delay %s...\n' % (retry_delay))
1226-
time.sleep(retry_delay)
1227-
SimpleLDAPObject.unbind_s(self)
1228-
else:
1229-
if __debug__ and self._trace_level >= 1:
1230-
self._trace_file.write(
1231-
'*** %s reconnect to %s successful => repeat last operation\n' % (
1232-
counter_text,
1233-
uri,
1234-
)
1235-
)
1236-
self._reconnects_done = self._reconnects_done + 1L
1237-
break
1238-
finally:
1239-
self._reconnect_lock.release()
1240-
return # reconnect()
1241-
1242-
def _apply_method_s(self, func, *args, **kwargs):
1243-
if not hasattr(self, '_l'):
1244-
self.reconnect(self._uri, retry_max=self._retry_max, retry_delay=self._retry_delay)
1245-
try:
1246-
return func(self, *args, **kwargs)
1247-
except ldap.SERVER_DOWN:
1248-
SimpleLDAPObject.unbind_s(self)
1249-
# Try to reconnect
1250-
self.reconnect(self._uri, retry_max=self._retry_max, retry_delay=self._retry_delay)
1251-
# Re-try last operation
1252-
return func(self, *args, **kwargs)
1253-
1254-
def set_option(self, option, invalue):
1255-
self._options.append((option, invalue))
1256-
return SimpleLDAPObject.set_option(self, option, invalue)
1257-
1258-
def bind_s(self, *args, **kwargs):
1259-
res = self._apply_method_s(SimpleLDAPObject.bind_s, *args, **kwargs)
1260-
self._store_last_bind(SimpleLDAPObject.bind_s, *args, **kwargs)
1261-
return res
1262-
1263-
def simple_bind_s(self, *args, **kwargs):
1264-
res = self._apply_method_s(SimpleLDAPObject.simple_bind_s, *args, **kwargs)
1265-
self._store_last_bind(SimpleLDAPObject.simple_bind_s, *args, **kwargs)
1266-
return res
1267-
1268-
def start_tls_s(self, *args, **kwargs):
1269-
res = self._apply_method_s(SimpleLDAPObject.start_tls_s, *args, **kwargs)
1270-
self._start_tls = 1
1271-
return res
1272-
1273-
def sasl_interactive_bind_s(self, *args, **kwargs):
1274-
"""
1275-
sasl_interactive_bind_s(who, auth) -> None
1276-
"""
1277-
res = self._apply_method_s(SimpleLDAPObject.sasl_interactive_bind_s, *args, **kwargs)
1278-
self._store_last_bind(SimpleLDAPObject.sasl_interactive_bind_s, *args, **kwargs)
1279-
return res
1280-
1281-
def sasl_bind_s(self, *args, **kwargs):
1282-
res = self._apply_method_s(SimpleLDAPObject.sasl_bind_s, *args, **kwargs)
1283-
self._store_last_bind(SimpleLDAPObject.sasl_bind_s, *args, **kwargs)
1284-
return res
1285-
1286-
def add_ext_s(self, *args, **kwargs):
1287-
return self._apply_method_s(SimpleLDAPObject.add_ext_s, *args, **kwargs)
1288-
1289-
def cancel_s(self, *args, **kwargs):
1290-
return self._apply_method_s(SimpleLDAPObject.cancel_s, *args, **kwargs)
1291-
1292-
def compare_ext_s(self, *args, **kwargs):
1293-
return self._apply_method_s(SimpleLDAPObject.compare_ext_s, *args, **kwargs)
1294-
1295-
def delete_ext_s(self, *args, **kwargs):
1296-
return self._apply_method_s(SimpleLDAPObject.delete_ext_s, *args, **kwargs)
1297-
1298-
def extop_s(self, *args, **kwargs):
1299-
return self._apply_method_s(SimpleLDAPObject.extop_s, *args, **kwargs)
1300-
1301-
def modify_ext_s(self, *args, **kwargs):
1302-
return self._apply_method_s(SimpleLDAPObject.modify_ext_s, *args, **kwargs)
1303-
1304-
def rename_s(self, *args, **kwargs):
1305-
return self._apply_method_s(SimpleLDAPObject.rename_s, *args, **kwargs)
1306-
1307-
def search_ext_s(self, *args, **kwargs):
1308-
return self._apply_method_s(SimpleLDAPObject.search_ext_s, *args, **kwargs)
1309-
1310-
def whoami_s(self, *args, **kwargs):
1311-
return self._apply_method_s(SimpleLDAPObject.whoami_s, *args, **kwargs)
1312-
1313-
13141094
# The class called LDAPObject will be used as default for
13151095
# ldap.open() and ldap.initialize()
13161096
LDAPObject = SimpleLDAPObject
1097+
1098+
from reconnect import ReconnectLDAPObject

0 commit comments

Comments
 (0)