Skip to content

Commit fc020d0

Browse files
committed
Merge Michael's work from the CVS repository on SourceForge
This includes changes from the 2.5.2 and (unfinished) 2.5.3 branches, excluding those that do extensive code reformatting. The list of those follows. (Commit IDs correspond to 'cvs' tracking branch in pyldap.) Changes left out: b837b54 stripped trailing spaces from C source files ef16f9f module ldapurl now almost PEP-8 compliant 6680752 module ldif now almost PEP-8 compliant 5880eb5 PyBytes_ instead of PyString_ and PyInt_FromLong/PyLong_FromLong shim 2d423bd PEP-8 for ldap.cidict 5c11c36 announce more modules with PEP-8 compliance 637daad PEP-8 for ldap.modlist 8692df7 PEP-8 for ldap.filter ab130d9 a bit of PEP-8 for ldap.dn c4388b5 a bit of PEP-8 for ldap.functions fa1f5e4 a bit of PEP-8 for ldap.__init__ feb1e57 ldap.ldapobject: PEP-8 and pylint b5e0c3c ldap.ldapobject: wrapped all lines exceeding 100 chars 956c961 ldap.ldapobject split into module-package 13ae211 moved SimpleLDAPObject to separate sub-module ldap.ldapobject.simple 07c771a added ldap.ldapobject.reconnect.__all__ f8d636a added ldap.ldapobject.simple f01e2a5 cleanup up setup.py 9a7c52e correctly set -D in setup.py 37983e2 do not use pprint, avoid filter() c81418e import ... as 39903aa announce changes in setup.py 73c357e started 2.5.3 03cbc30 ldap.async: PEP-8 and pylint e19d0c2 (cvs) ldap.schema.tokenizer: PEP-8 and pylint From the first one (b837b54: stripped trailing spaces from C source files), the code for adding _ldap.__version__ is kept.
2 parents 6b1063e + 3141ce0 commit fc020d0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1360
-659
lines changed

CHANGES

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,34 @@
1+
----------------------------------------------------------------
2+
Released 2.5.2 2017-11-20
3+
4+
Changes since 2.5.1:
5+
6+
Modules/
7+
* PyBytes_ instead of PyString_ and added PyInt_FromLong compat macro
8+
* moved code from version.c to ldapmodule.c
9+
* removed obsolete back-ward compability constants from common.h
10+
* build checks whether LDAP_API_VERSION is OpenLDAP 2.4.x
11+
* _ldap.__author__ and _ldap.__license__ also set from ldap.pkginfo
12+
* assume C extension API for Python 2.7+
13+
14+
Lib/
15+
* removed all dependencies on modules string and types
16+
* removed use of .has_key()
17+
* removed class ldap.ldapobject.NonblockingLDAPObject
18+
* new global constant ldap.LIBLDAP_API_INFO
19+
* right after importing _ldap there is a call into libldap to initialize it
20+
* method .decodeControlValue() of SSSResponseControl and VLVResponseControl
21+
does not set class attribute result_code anymore
22+
* always use bytes() for UUID() constructor in ldap.syncrepl
23+
* module ldif now uses functions b64encode() and b64decode()
24+
* fixed pickling and restoring of ReconnectLDAPObject
25+
26+
Tests/
27+
* scripts do not directly call SlapdTestCase.setUpClass() anymore
28+
* added LDIF test with folded, base64-encoded attribute
29+
* added more tests for sub-module ldap.dn
30+
* added tests for ldap.syncrepl (thanks to Karl Kornel)
31+
132
----------------------------------------------------------------
233
Released 2.5.1 2017-11-12
334

Demo/Lib/ldap/async/ldifwriter.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
This example translates the naming context of data read from
88
input, sanitizes some attributes, maps/removes object classes,
99
maps/removes attributes., etc. It's far from being complete though.
10-
11-
Python compability note:
12-
Tested on Python 2.0+, should run on Python 1.5.x.
1310
"""
1411

1512
import sys,ldap,ldap.async

Demo/Lib/ldap/async/sizelimit.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
This example translates the naming context of data read from
99
input, sanitizes some attributes, maps/removes object classes,
1010
maps/removes attributes., etc. It's far from being complete though.
11-
12-
Python compability note:
13-
Tested on Python 2.0+, should run on Python 1.5.x.
1411
"""
1512

1613
import sys,ldap,ldap.async

Demo/Lib/ldif/ldifcopy.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
This example translates the naming context of data read from
88
input, sanitizes some attributes, maps/removes object classes,
99
maps/removes attributes., etc. It's far from being complete though.
10-
11-
Python compability note:
12-
Tested on Python 2.0+, should run on Python 1.5.x.
1310
"""
1411

1512
import sys,ldif

Demo/pyasn1/syncrepl.py

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,14 @@
77
Notes:
88
99
The bound user needs read access to the attributes entryDN and entryCSN.
10-
11-
This needs the following software:
12-
Python
13-
pyasn1 0.1.4+
14-
pyasn1-modules
15-
python-ldap 2.4.10+
1610
"""
1711

1812
# Import modules from Python standard lib
19-
import shelve,signal,time,sys,logging
13+
import logging
14+
import shelve
15+
import signal
16+
import sys
17+
import time
2018

2119
# Import the python-ldap modules
2220
import ldap
@@ -25,28 +23,34 @@
2523
from ldap.ldapobject import ReconnectLDAPObject
2624
from ldap.syncrepl import SyncreplConsumer
2725

26+
logger = logging.getLogger('syncrepl')
27+
logger.setLevel(logging.DEBUG)
28+
logger.addHandler(logging.StreamHandler())
2829

2930
# Global state
3031
watcher_running = True
3132
ldap_connection = False
3233

3334

34-
class SyncReplConsumer(ReconnectLDAPObject, SyncreplConsumer):
35+
class SyncReplClient(ReconnectLDAPObject, SyncreplConsumer):
3536
"""
36-
Syncrepl Consumer interface
37+
Syncrepl Consumer Client
3738
"""
3839

3940
def __init__(self, db_path, *args, **kwargs):
4041
# Initialise the LDAP Connection first
4142
ldap.ldapobject.ReconnectLDAPObject.__init__(self, *args, **kwargs)
4243
# Now prepare the data store
43-
self.__data = shelve.open(db_path, 'c')
44+
if db_path:
45+
self.__data = shelve.open(db_path, 'c')
46+
else:
47+
self.__data = dict()
4448
# We need this for later internal use
4549
self.__presentUUIDs = dict()
4650

4751
def close_db(self):
48-
# Close the data store properly to avoid corruption
49-
self.__data.close()
52+
# Close the data store properly to avoid corruption
53+
self.__data.close()
5054

5155
def syncrepl_get_cookie(self):
5256
if 'cookie' in self.__data:
@@ -55,7 +59,8 @@ def syncrepl_get_cookie(self):
5559
def syncrepl_set_cookie(self,cookie):
5660
self.__data['cookie'] = cookie
5761

58-
def syncrepl_entry(self,dn,attributes,uuid):
62+
def syncrepl_entry(self, dn, attributes, uuid):
63+
logger.debug('dn=%r attributes=%r uuid=%r', dn, attributes, uuid)
5964
# First we determine the type of change we have here
6065
# (and store away the previous data for later if needed)
6166
previous_attributes = dict()
@@ -69,18 +74,18 @@ def syncrepl_entry(self,dn,attributes,uuid):
6974
attributes['dn'] = dn
7075
self.__data[uuid] = attributes
7176
# Debugging
72-
print 'Detected', change_type, 'of entry:', dn
77+
logger.debug('Detected %s of entry %r', change_type, dn)
7378
# If we have a cookie then this is not our first time being run,
7479
# so it must be a change
7580
if 'ldap_cookie' in self.__data:
76-
self.perform_application_sync(dn, attributes, previous_attributes)
81+
self.perform_application_sync(dn, attributes, previous_attributes)
7782

7883
def syncrepl_delete(self,uuids):
7984
# Make sure we know about the UUID being deleted, just in case...
8085
uuids = [uuid for uuid in uuids if uuid in self.__data]
8186
# Delete all the UUID values we know of
8287
for uuid in uuids:
83-
print 'Detected deletion of entry:', self.__data[uuid]['dn']
88+
logger.debug('Detected deletion of entry %r', self.__data[uuid]['dn'])
8489
del self.__data[uuid]
8590

8691
def syncrepl_present(self,uuids,refreshDeletes=False):
@@ -105,78 +110,80 @@ def syncrepl_present(self,uuids,refreshDeletes=False):
105110
self.__presentUUIDs[uuid] = True
106111

107112
def syncrepl_refreshdone(self):
108-
print 'Initial synchronization is now done, persist phase begins'
113+
logger.info('Initial synchronization is now done, persist phase begins')
109114

110115
def perform_application_sync(self,dn,attributes,previous_attributes):
111-
print 'Performing application sync for:', dn
116+
logger.info('Performing application sync for %r', dn)
112117
return True
113118

114119

115120
# Shutdown handler
116121
def commenceShutdown(signum, stack):
117122
# Declare the needed global variables
118123
global watcher_running, ldap_connection
119-
print 'Shutting down!'
124+
logger.warn('Shutting down!')
120125

121126
# We are no longer running
122127
watcher_running = False
123128

124129
# Tear down the server connection
125-
if( ldap_connection ):
126-
ldap_connection.close_db()
127-
ldap_connection.unbind_s()
128-
del ldap_connection
130+
if ldap_connection:
131+
ldap_connection.close_db()
132+
ldap_connection.unbind_s()
133+
del ldap_connection
129134

130135
# Shutdown
131136
sys.exit(0)
132137

133138
# Time to actually begin execution
134139
# Install our signal handlers
135-
signal.signal(signal.SIGTERM,commenceShutdown)
136-
signal.signal(signal.SIGINT,commenceShutdown)
140+
signal.signal(signal.SIGTERM, commenceShutdown)
141+
signal.signal(signal.SIGINT, commenceShutdown)
137142

138143

139144
try:
140-
ldap_url = ldapurl.LDAPUrl(sys.argv[1])
141-
database_path = sys.argv[2]
145+
ldap_url = ldapurl.LDAPUrl(sys.argv[1])
146+
database_path = sys.argv[2]
142147
except IndexError,e:
143-
print 'Usage:'
144-
print sys.argv[0], '<LDAP URL> <pathname of database>'
145-
print sys.argv[0], '\'ldap://127.0.0.1/cn=users,dc=test'\
146-
'?*'\
147-
'?sub'\
148-
'?(objectClass=*)'\
149-
'?bindname=uid=admin%2ccn=users%2cdc=test,'\
150-
'X-BINDPW=password\' db.shelve'
148+
print (
149+
'Usage:\n'
150+
'{script_name} <LDAP URL> <pathname of database>\n'
151+
'{script_name} "ldap://127.0.0.1/cn=users,dc=test'
152+
'?*'
153+
'?sub'
154+
'?(objectClass=*)'
155+
'?bindname=uid=admin%2ccn=users%2cdc=test,'
156+
'X-BINDPW=password" db.shelve'
157+
).format(script_name=sys.argv[0])
151158
sys.exit(1)
152159
except ValueError,e:
153-
print 'Error parsing command-line arguments:',str(e)
154-
sys.exit(1)
160+
print 'Error parsing command-line arguments:', str(e)
161+
sys.exit(1)
155162

156163
while watcher_running:
157-
print 'Connecting to LDAP server now...'
164+
logger.info('Connecting to %s now...', ldap_url.initializeUrl())
158165
# Prepare the LDAP server connection (triggers the connection as well)
159-
ldap_connection = SyncReplConsumer(database_path, ldap_url.initializeUrl())
166+
ldap_connection = SyncReplClient(database_path, ldap_url.initializeUrl())
160167

161168
# Now we login to the LDAP server
162169
try:
163170
ldap_connection.simple_bind_s(ldap_url.who, ldap_url.cred)
164-
except ldap.INVALID_CREDENTIALS, e:
165-
print 'Login to LDAP server failed: ', str(e)
171+
except ldap.INVALID_CREDENTIALS, err:
172+
logger.error('Login to LDAP server failed: %s', err)
166173
sys.exit(1)
167174
except ldap.SERVER_DOWN:
168-
print 'LDAP server is down, going to retry.'
175+
logger.warn('LDAP server is down, going to retry.')
169176
time.sleep(5)
170177
continue
171178

172179
# Commence the syncing
173-
print 'Commencing sync process'
180+
logger.debug('Commencing sync process')
174181
ldap_search = ldap_connection.syncrepl_search(
175-
ldap_url.dn or '',
176-
ldap_url.scope or ldap.SCOPE_SUBTREE,
177-
mode = 'refreshAndPersist',
178-
attrlist=ldap_url.attrs,
179-
filterstr = ldap_url.filterstr or '(objectClass=*)'
182+
ldap_url.dn or '',
183+
ldap_url.scope or ldap.SCOPE_SUBTREE,
184+
mode = 'refreshAndPersist',
185+
attrlist=ldap_url.attrs,
186+
filterstr = ldap_url.filterstr or '(objectClass=*)'
180187
)
181188

182189
try:
@@ -185,10 +192,9 @@ def commenceShutdown(signum, stack):
185192
except KeyboardInterrupt:
186193
# User asked to exit
187194
commenceShutdown(None, None)
188-
pass
189-
except Exception, e:
195+
except Exception, err:
190196
# Handle any exception
191197
if watcher_running:
192-
print 'Encountered a problem, going to retry. Error:', str(e)
198+
logger.exception('Unhandled exception, going to retry: %s', err)
199+
logger.info('Going to retry after 5 secs')
193200
time.sleep(5)
194-
pass

Demo/resiter.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
written by Michael Stroeder <michael@stroeder.com>
44
55
See http://www.python-ldap.org for details.
6-
7-
Python compability note:
8-
Requires Python 2.3+
96
"""
107

118
import ldap,ldap.resiter

Demo/simplebrowse.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#
66

77
import ldap
8-
import string
98
from traceback import print_exc
109

1110
url = "ldap://ldap.openldap.org/"
@@ -71,8 +70,8 @@
7170
if arg == '-':
7271
lastdn,dn = dn,lastdn
7372
elif arg == '..':
74-
dn = string.join(ldap.explode_dn(dn)[1:], ",")
75-
dn = string.strip(dn)
73+
dn = ldap.explode_dn(dn)[1:].join(",")
74+
dn = dn.strip()
7675
else:
7776
try:
7877
i = int(arg)

Doc/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
# The short X.Y version.
4343
version = '2.5'
4444
# The full version, including alpha/beta/rc tags.
45-
release = '2.5.1.0'
45+
release = '2.5.2.0'
4646

4747
# There are two options for replacing |today|: either, you set today to some
4848
# non-false value, then it is used:

Doc/ldap-dn.rst

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ The :mod:`ldap.dn` module defines the following functions:
4949
function :func:`escape_dn_chars`.
5050

5151

52-
.. function:: explode_dn(dn [, notypes=0[, flags=0]]) -> list
52+
.. function:: explode_dn(dn [, notypes=False[, flags=0]]) -> list
5353

5454
This function takes *dn* and breaks it up into its component parts. Each part
5555
is known as an RDN (Relative Distinguished Name). The optional *notypes*
@@ -60,7 +60,7 @@ The :mod:`ldap.dn` module defines the following functions:
6060
deprecated.
6161

6262

63-
.. function:: explode_rdn(rdn [, notypes=0[, flags=0]]) -> list
63+
.. function:: explode_rdn(rdn [, notypes=False[, flags=0]]) -> list
6464

6565
This function takes a (multi-valued) *rdn* and breaks it up into a list of
6666
characteristic attributes. The optional *notypes* parameter is used to specify
@@ -85,26 +85,26 @@ Splitting a LDAPv3 DN to AVA level. Note that both examples have the same result
8585
but in the first example the non-ASCII chars are passed as is (byte buffer string)
8686
whereas in the second example the hex-encoded DN representation are passed to the function.
8787

88-
>>> ldap.dn.str2dn('cn=Michael Str\xc3\xb6der,dc=stroeder,dc=com',flags=ldap.DN_FORMAT_LDAPV3)
89-
[[('cn', 'Michael Str\xc3\xb6der', 4)], [('dc', 'stroeder', 1)], [('dc', 'com', 1)]]
90-
>>> ldap.dn.str2dn('cn=Michael Str\C3\B6der,dc=stroeder,dc=com',flags=ldap.DN_FORMAT_LDAPV3)
91-
[[('cn', 'Michael Str\xc3\xb6der', 4)], [('dc', 'stroeder', 1)], [('dc', 'com', 1)]]
88+
>>> ldap.dn.str2dn('cn=Michael Str\xc3\xb6der,dc=example,dc=com',flags=ldap.DN_FORMAT_LDAPV3)
89+
[[('cn', 'Michael Str\xc3\xb6der', 4)], [('dc', 'example', 1)], [('dc', 'com', 1)]]
90+
>>> ldap.dn.str2dn('cn=Michael Str\C3\B6der,dc=example,dc=com',flags=ldap.DN_FORMAT_LDAPV3)
91+
[[('cn', 'Michael Str\xc3\xb6der', 4)], [('dc', 'example', 1)], [('dc', 'com', 1)]]
9292

9393

9494
Splitting a LDAPv2 DN into RDN parts:
9595

96-
>>> ldap.dn.explode_dn('cn=Michael Stroeder;dc=stroeder;dc=com',flags=ldap.DN_FORMAT_LDAPV2)
97-
['cn=Michael Stroeder', 'dc=stroeder', 'dc=com']
96+
>>> ldap.dn.explode_dn('cn=John Doe;dc=example;dc=com',flags=ldap.DN_FORMAT_LDAPV2)
97+
['cn=John Doe', 'dc=example', 'dc=com']
9898

9999

100100
Splitting a multi-valued RDN:
101101

102-
>>> ldap.dn.explode_rdn('cn=Michael Stroeder+mail=michael@stroeder.com',flags=ldap.DN_FORMAT_LDAPV2)
103-
['cn=Michael Stroeder', 'mail=michael@stroeder.com']
102+
>>> ldap.dn.explode_rdn('cn=John Doe+mail=john.doe@example.com',flags=ldap.DN_FORMAT_LDAPV2)
103+
['cn=John Doe', 'mail=john.doe@example.com']
104104

105105
Splitting a LDAPv3 DN with a multi-valued RDN into its AVA parts:
106106

107107

108-
>>> ldap.dn.str2dn('cn=Michael Stroeder+mail=michael@stroeder.com,dc=stroeder,dc=com')
109-
[[('cn', 'Michael Stroeder', 1), ('mail', 'michael@stroeder.com', 1)], [('dc', 'stroeder', 1)], [('dc', 'com', 1)]]
108+
>>> ldap.dn.str2dn('cn=John Doe+mail=john.doe@example.com,dc=example,dc=com')
109+
[[('cn', 'John Doe', 1), ('mail', 'john.doe@example.com', 1)], [('dc', 'example', 1)], [('dc', 'com', 1)]]
110110

Lib/ldap/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
assert _ldap.__version__==__version__, \
2424
ImportError('ldap %s and _ldap %s version mismatch!' % (__version__,_ldap.__version__))
2525
from _ldap import *
26+
# call into libldap to initialize it right now
27+
LIBLDAP_API_INFO = _ldap.get_option(_ldap.OPT_API_INFO)
2628

2729
OPT_NAMES_DICT = {}
2830
for k,v in vars(_ldap).items():

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy