ldappool 3.0.0__tar.gz → 3.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ldappool-3.0.0 → ldappool-3.1.0}/.zuul.yaml +2 -1
- {ldappool-3.0.0 → ldappool-3.1.0}/AUTHORS +7 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/ChangeLog +26 -0
- ldappool-3.1.0/PKG-INFO +107 -0
- ldappool-3.1.0/doc/requirements.txt +3 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/ldappool/__init__.py +8 -23
- {ldappool-3.0.0 → ldappool-3.1.0}/ldappool/tests/test_ldapconnection.py +40 -0
- ldappool-3.1.0/ldappool.egg-info/PKG-INFO +107 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/ldappool.egg-info/SOURCES.txt +2 -1
- ldappool-3.1.0/ldappool.egg-info/pbr.json +1 -0
- ldappool-3.1.0/pyproject.toml +33 -0
- ldappool-3.1.0/releasenotes/notes/remove-py38-4a1a65ec118db41f.yaml +5 -0
- ldappool-3.1.0/requirements.txt +6 -0
- ldappool-3.1.0/setup.cfg +7 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/test-requirements.txt +2 -3
- {ldappool-3.0.0 → ldappool-3.1.0}/tox.ini +7 -6
- ldappool-3.0.0/MANIFEST.in +0 -4
- ldappool-3.0.0/PKG-INFO +0 -104
- ldappool-3.0.0/doc/requirements.txt +0 -7
- ldappool-3.0.0/ldappool.egg-info/PKG-INFO +0 -104
- ldappool-3.0.0/ldappool.egg-info/pbr.json +0 -1
- ldappool-3.0.0/requirements.txt +0 -2
- ldappool-3.0.0/setup.cfg +0 -34
- {ldappool-3.0.0 → ldappool-3.1.0}/.stestr.conf +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/CHANGES.rst +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/CONTRIBUTORS +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/README.rst +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/bindep.txt +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/doc/Makefile +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/doc/source/conf.py +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/doc/source/index.rst +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/ldappool/tests/__init__.py +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/ldappool/tests/test_ldappool.py +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/ldappool.egg-info/dependency_links.txt +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/ldappool.egg-info/not-zip-safe +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/ldappool.egg-info/requires.txt +1 -1
- {ldappool-3.0.0 → ldappool-3.1.0}/ldappool.egg-info/top_level.txt +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/releasenotes/notes/drop-py-2-7-9d318d5c72f59f77.yaml +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/releasenotes/source/_static/.placeholder +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/releasenotes/source/conf.py +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/releasenotes/source/index.rst +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/releasenotes/source/unreleased.rst +0 -0
- {ldappool-3.0.0 → ldappool-3.1.0}/setup.py +0 -0
|
@@ -9,6 +9,10 @@ Colleen Murphy <comurphy@suse.com>
|
|
|
9
9
|
Corey Bryant <corey.bryant@canonical.com>
|
|
10
10
|
Dirk Mueller <dirk@dmllr.de>
|
|
11
11
|
Doug Hellmann <doug@doughellmann.com>
|
|
12
|
+
Ghanshyam Mann <gmann@ghanshyammann.com>
|
|
13
|
+
Hervé Beraud <hberaud@redhat.com>
|
|
14
|
+
Jimmy McCrory <jimmy.mccrory@gmail.com>
|
|
15
|
+
LiZekun <2954674728@qq.com>
|
|
12
16
|
Lorenzo M. Catucci <lorenzo@sancho.ccd.uniroma2.it>
|
|
13
17
|
Monty Taylor <mordred@inaugust.com>
|
|
14
18
|
Morgan Fainberg <morgan.fainberg@gmail.com>
|
|
@@ -17,6 +21,9 @@ Nick Wilburn <senior.crepe@gmail.com>
|
|
|
17
21
|
Samriddhi Jain <j.samriddhi13@gmail.com>
|
|
18
22
|
Stephen Finucane <stephenfin@redhat.com>
|
|
19
23
|
Steve Martinelli <s.martinelli@gmail.com>
|
|
24
|
+
Sven Kieske <kieske@osism.tech>
|
|
25
|
+
Takashi Kajinami <kajinamit@oss.nttdata.com>
|
|
26
|
+
Takashi Kajinami <tkajinam@redhat.com>
|
|
20
27
|
Tarek Ziade <tarek@ziade.org>
|
|
21
28
|
Tarek Ziade <ziade.tarek@gmail.com>
|
|
22
29
|
Tarek Ziadé <tarek@mozilla.com>
|
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
CHANGES
|
|
2
2
|
=======
|
|
3
3
|
|
|
4
|
+
3.1.0
|
|
5
|
+
-----
|
|
6
|
+
|
|
7
|
+
* Declare Python 3.15 support
|
|
8
|
+
* Simplify tox.ini
|
|
9
|
+
* Remove Python 3.10 support
|
|
10
|
+
* Migrate setup configuration to pyproject.toml
|
|
11
|
+
* Remove MANIFEST.in
|
|
12
|
+
* Drop flake8-docstrings
|
|
13
|
+
* add pyproject.toml to support pip 23.1
|
|
14
|
+
* Add note about requirements lower bounds
|
|
15
|
+
* Remove Python 3.8 support
|
|
16
|
+
* Retry or failover when using TLS
|
|
17
|
+
* Remove old excludes
|
|
18
|
+
* Bump hacking
|
|
19
|
+
* Update python classifier in setup.cfg
|
|
20
|
+
* Remove deprecated pbr options
|
|
21
|
+
* fix small typo in BackendError class
|
|
22
|
+
* Remove usage of six library
|
|
23
|
+
* Fix pep8 gate
|
|
24
|
+
* setup.cfg: Replace dashes by underscores
|
|
25
|
+
* Use TOX\_CONSTRAINTS\_FILE
|
|
26
|
+
* Update python testing as per zed cycle testing runtime
|
|
27
|
+
* Update CI to use unversioned jobs template
|
|
28
|
+
|
|
4
29
|
3.0.0
|
|
5
30
|
-----
|
|
6
31
|
|
|
7
32
|
* Remove lower-constraints, uncap PrettyTable
|
|
33
|
+
* Stop to use the \_\_future\_\_ module
|
|
8
34
|
* Switch to newer openstackdocstheme and reno versions
|
|
9
35
|
* Cleanup py27 support
|
|
10
36
|
* Update hacking for Python3
|
ldappool-3.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ldappool
|
|
3
|
+
Version: 3.1.0
|
|
4
|
+
Summary: A simple connector pool for python-ldap.
|
|
5
|
+
Author-email: OpenStack <openstack-discuss@lists.openstack.org>
|
|
6
|
+
License-Expression: MPL-2.0
|
|
7
|
+
Project-URL: Homepage, https://opendev.org/openstack/ldappool
|
|
8
|
+
Project-URL: Repository, https://opendev.org/openstack/ldappool
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Classifier: Programming Language :: Python
|
|
12
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Description-Content-Type: text/x-rst
|
|
21
|
+
Requires-Dist: python-ldap>=3.0.0
|
|
22
|
+
Requires-Dist: PrettyTable>=0.7.2
|
|
23
|
+
Dynamic: requires-dist
|
|
24
|
+
|
|
25
|
+
ldappool
|
|
26
|
+
========
|
|
27
|
+
|
|
28
|
+
A simple connector pool for python-ldap.
|
|
29
|
+
|
|
30
|
+
The pool keeps LDAP connectors alive and let you reuse them,
|
|
31
|
+
drastically reducing the time spent to initiate a ldap connection.
|
|
32
|
+
|
|
33
|
+
The pool has useful features like:
|
|
34
|
+
|
|
35
|
+
- transparent reconnection on failures or server restarts
|
|
36
|
+
- configurable pool size and connectors timeouts
|
|
37
|
+
- configurable max lifetime for connectors
|
|
38
|
+
- a context manager to simplify acquiring and releasing a connector
|
|
39
|
+
|
|
40
|
+
**You need python-ldap in order to use this library**
|
|
41
|
+
|
|
42
|
+
Quickstart
|
|
43
|
+
::::::::::
|
|
44
|
+
|
|
45
|
+
To work with the pool, you just need to create it, then use it as a
|
|
46
|
+
context manager with the *connection* method::
|
|
47
|
+
|
|
48
|
+
from ldappool import ConnectionManager
|
|
49
|
+
|
|
50
|
+
cm = ConnectionManager('ldap://localhost')
|
|
51
|
+
|
|
52
|
+
with cm.connection('uid=adminuser,ou=logins,dc=mozilla', 'password') as conn:
|
|
53
|
+
.. do something with conn ..
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
The connector returned by *connection* is a LDAPObject, that's binded to the
|
|
57
|
+
server. See https://pypi.org/project/python-ldap/ for details on how to use a connector.
|
|
58
|
+
|
|
59
|
+
It is possible to check the state of the pool by representing the pool as a string::
|
|
60
|
+
|
|
61
|
+
from ldappool import ConnectionManager
|
|
62
|
+
|
|
63
|
+
cm = ConnectionManager('ldap://localhost', size=2)
|
|
64
|
+
|
|
65
|
+
.. do something with cm ..
|
|
66
|
+
|
|
67
|
+
print(cm)
|
|
68
|
+
|
|
69
|
+
This will result in output similar to this table::
|
|
70
|
+
|
|
71
|
+
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
72
|
+
| Slot (2 max) | Connected | Active | URI | Lifetime (600 max) | Bind DN |
|
|
73
|
+
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
74
|
+
| 1 | connected | inactive | ldap://localhost | 0.00496101379395 | uid=tuser,dc=example,dc=test |
|
|
75
|
+
| 2 | connected | inactive | ldap://localhost | 0.00532603263855 | uid=tuser,dc=example,dc=test |
|
|
76
|
+
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
ConnectionManager options
|
|
80
|
+
:::::::::::::::::::::::::
|
|
81
|
+
|
|
82
|
+
Here are the options you can use when instanciating the pool:
|
|
83
|
+
|
|
84
|
+
- **uri**: ldap server uri **[mandatory]**
|
|
85
|
+
- **bind**: default bind that will be used to bind a connector.
|
|
86
|
+
**default: None**
|
|
87
|
+
- **passwd**: default password that will be used to bind a connector.
|
|
88
|
+
**default: None**
|
|
89
|
+
- **size**: pool size. **default: 10**
|
|
90
|
+
- **retry_max**: number of attempts when a server is down. **default: 3**
|
|
91
|
+
- **retry_delay**: delay in seconds before a retry. **default: .1**
|
|
92
|
+
- **use_tls**: activate TLS when connecting. **default: False**
|
|
93
|
+
- **timeout**: connector timeout. **default: -1**
|
|
94
|
+
- **use_pool**: activates the pool. If False, will recreate a connector
|
|
95
|
+
each time. **default: True**
|
|
96
|
+
|
|
97
|
+
The **uri** option will accept a comma or whitespace separated list of LDAP
|
|
98
|
+
server URIs to allow for failover behavior when connection errors are
|
|
99
|
+
encountered. Connections will be attempted against the servers in order,
|
|
100
|
+
with **retry_max** attempts per URI before failing over to the next server.
|
|
101
|
+
|
|
102
|
+
The **connection** method takes two options:
|
|
103
|
+
|
|
104
|
+
- **bind**: bind used to connect. If None, uses the pool default's.
|
|
105
|
+
**default: None**
|
|
106
|
+
- **passwd**: password used to connect. If None, uses the pool default's.
|
|
107
|
+
**default: None**
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
# ***** END LICENSE BLOCK *****
|
|
36
36
|
""" LDAP Connection Pool.
|
|
37
37
|
"""
|
|
38
|
-
import codecs
|
|
39
38
|
from contextlib import contextmanager
|
|
40
39
|
import logging
|
|
41
40
|
from threading import RLock
|
|
@@ -45,29 +44,26 @@ import ldap
|
|
|
45
44
|
from ldap.ldapobject import ReconnectLDAPObject
|
|
46
45
|
from prettytable import PrettyTable
|
|
47
46
|
import re
|
|
48
|
-
import six
|
|
49
|
-
from six import PY2
|
|
50
47
|
|
|
51
48
|
log = logging.getLogger(__name__)
|
|
52
|
-
_utf8_encoder = codecs.getencoder('utf-8')
|
|
53
49
|
|
|
54
50
|
|
|
55
51
|
def utf8_encode(value):
|
|
56
52
|
"""Encode a basestring to UTF-8.
|
|
57
53
|
|
|
58
|
-
If the
|
|
59
|
-
|
|
54
|
+
If the value is string, encode it to UTF-8, if the value is
|
|
55
|
+
bytes then assume it's already encoded. Otherwise raise a TypeError.
|
|
60
56
|
|
|
61
57
|
:param value: A basestring
|
|
62
58
|
:returns: UTF-8 encoded version of value
|
|
63
59
|
:raises TypeError: If value is not basestring
|
|
64
60
|
"""
|
|
65
|
-
if isinstance(value,
|
|
66
|
-
return
|
|
67
|
-
elif isinstance(value,
|
|
61
|
+
if isinstance(value, str):
|
|
62
|
+
return value.encode('utf-8')
|
|
63
|
+
elif isinstance(value, bytes):
|
|
68
64
|
return value
|
|
69
65
|
else:
|
|
70
|
-
raise TypeError("bytes or
|
|
66
|
+
raise TypeError("bytes or str expected, got %s"
|
|
71
67
|
% type(value).__name__)
|
|
72
68
|
|
|
73
69
|
|
|
@@ -77,7 +73,7 @@ class MaxConnectionReachedError(Exception):
|
|
|
77
73
|
|
|
78
74
|
class BackendError(Exception):
|
|
79
75
|
def __init__(self, msg, backend):
|
|
80
|
-
self.
|
|
76
|
+
self.backend = backend
|
|
81
77
|
Exception.__init__(self, msg)
|
|
82
78
|
|
|
83
79
|
|
|
@@ -169,9 +165,6 @@ class ConnectionManager(object):
|
|
|
169
165
|
return len(self._pool)
|
|
170
166
|
|
|
171
167
|
def _match(self, bind, passwd):
|
|
172
|
-
if passwd is not None:
|
|
173
|
-
if PY2:
|
|
174
|
-
passwd = utf8_encode(passwd)
|
|
175
168
|
with self._pool_lock:
|
|
176
169
|
inactives = []
|
|
177
170
|
|
|
@@ -219,12 +212,7 @@ class ConnectionManager(object):
|
|
|
219
212
|
def _bind(self, conn, bind, passwd):
|
|
220
213
|
# let's bind
|
|
221
214
|
if self.use_tls:
|
|
222
|
-
|
|
223
|
-
conn.start_tls_s()
|
|
224
|
-
except Exception:
|
|
225
|
-
raise BackendError('Could not activate TLS on established '
|
|
226
|
-
'connection with %s' % self.uri,
|
|
227
|
-
backend=conn)
|
|
215
|
+
conn.start_tls_s()
|
|
228
216
|
|
|
229
217
|
if bind is not None:
|
|
230
218
|
conn.simple_bind_s(bind, passwd)
|
|
@@ -242,9 +230,6 @@ class ConnectionManager(object):
|
|
|
242
230
|
:raises BackendError: If unable to connect to LDAP
|
|
243
231
|
"""
|
|
244
232
|
connected = False
|
|
245
|
-
if passwd is not None:
|
|
246
|
-
if PY2:
|
|
247
|
-
passwd = utf8_encode(passwd)
|
|
248
233
|
|
|
249
234
|
# If multiple server URIs have been provided, loop through
|
|
250
235
|
# each one in turn in case of connection failures (server down,
|
|
@@ -96,11 +96,25 @@ def _bind_fails_invalid_credentials_failover(self, who='', cred='', **kw):
|
|
|
96
96
|
raise ldap.INVALID_CREDENTIALS('LDAP connection invalid')
|
|
97
97
|
|
|
98
98
|
|
|
99
|
+
def _bind_fails_tls_failover(self, who='', cred='', **kw):
|
|
100
|
+
# Raise backend error unless the URI is 'ldap://GOOD'
|
|
101
|
+
if self._uri == 'ldap://GOOD':
|
|
102
|
+
self.connected = True
|
|
103
|
+
self.who = who
|
|
104
|
+
self.cred = cred
|
|
105
|
+
return 1
|
|
106
|
+
else:
|
|
107
|
+
raise ldappool.BackendError
|
|
108
|
+
|
|
109
|
+
|
|
99
110
|
def _start_tls_s(self):
|
|
111
|
+
# Raise a server down error if the URI is 'ldap://BAD'
|
|
100
112
|
if self.start_tls_already_called_flag:
|
|
101
113
|
raise ldap.LOCAL_ERROR
|
|
102
114
|
else:
|
|
103
115
|
self.start_tls_already_called_flag = True
|
|
116
|
+
if self._uri == 'ldap://BAD':
|
|
117
|
+
raise ldap.SERVER_DOWN('LDAP connection invalid')
|
|
104
118
|
|
|
105
119
|
|
|
106
120
|
class TestLDAPConnection(unittest.TestCase):
|
|
@@ -323,3 +337,29 @@ class TestLDAPConnection(unittest.TestCase):
|
|
|
323
337
|
pass
|
|
324
338
|
else:
|
|
325
339
|
raise AssertionError()
|
|
340
|
+
|
|
341
|
+
def test_simple_bind_fails_tls_failover(self):
|
|
342
|
+
unbinds = []
|
|
343
|
+
|
|
344
|
+
def _unbind(self):
|
|
345
|
+
unbinds.append(1)
|
|
346
|
+
|
|
347
|
+
# the binding to any server other than 'ldap://GOOD' fails
|
|
348
|
+
# with ldap.SERVER_DOWN
|
|
349
|
+
ldappool.StateConnector.simple_bind_s = _bind_fails_tls_failover
|
|
350
|
+
ldappool.StateConnector.unbind_s = _unbind
|
|
351
|
+
uri = 'ldap://BAD,ldap://GOOD'
|
|
352
|
+
dn = 'uid=adminuser,ou=logins,dc=mozilla'
|
|
353
|
+
passwd = 'adminuser'
|
|
354
|
+
cm = ldappool.ConnectionManager(uri, dn, passwd, use_pool=True,
|
|
355
|
+
size=2, use_tls=True)
|
|
356
|
+
self.assertEqual(len(cm), 0)
|
|
357
|
+
|
|
358
|
+
try:
|
|
359
|
+
with cm.connection('dn', 'pass') as conn:
|
|
360
|
+
# Ensure we failed over to the second URI
|
|
361
|
+
self.assertTrue(conn.active)
|
|
362
|
+
self.assertEqual(conn._uri, 'ldap://GOOD')
|
|
363
|
+
pass
|
|
364
|
+
except Exception:
|
|
365
|
+
raise AssertionError()
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ldappool
|
|
3
|
+
Version: 3.1.0
|
|
4
|
+
Summary: A simple connector pool for python-ldap.
|
|
5
|
+
Author-email: OpenStack <openstack-discuss@lists.openstack.org>
|
|
6
|
+
License-Expression: MPL-2.0
|
|
7
|
+
Project-URL: Homepage, https://opendev.org/openstack/ldappool
|
|
8
|
+
Project-URL: Repository, https://opendev.org/openstack/ldappool
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Classifier: Programming Language :: Python
|
|
12
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Description-Content-Type: text/x-rst
|
|
21
|
+
Requires-Dist: python-ldap>=3.0.0
|
|
22
|
+
Requires-Dist: PrettyTable>=0.7.2
|
|
23
|
+
Dynamic: requires-dist
|
|
24
|
+
|
|
25
|
+
ldappool
|
|
26
|
+
========
|
|
27
|
+
|
|
28
|
+
A simple connector pool for python-ldap.
|
|
29
|
+
|
|
30
|
+
The pool keeps LDAP connectors alive and let you reuse them,
|
|
31
|
+
drastically reducing the time spent to initiate a ldap connection.
|
|
32
|
+
|
|
33
|
+
The pool has useful features like:
|
|
34
|
+
|
|
35
|
+
- transparent reconnection on failures or server restarts
|
|
36
|
+
- configurable pool size and connectors timeouts
|
|
37
|
+
- configurable max lifetime for connectors
|
|
38
|
+
- a context manager to simplify acquiring and releasing a connector
|
|
39
|
+
|
|
40
|
+
**You need python-ldap in order to use this library**
|
|
41
|
+
|
|
42
|
+
Quickstart
|
|
43
|
+
::::::::::
|
|
44
|
+
|
|
45
|
+
To work with the pool, you just need to create it, then use it as a
|
|
46
|
+
context manager with the *connection* method::
|
|
47
|
+
|
|
48
|
+
from ldappool import ConnectionManager
|
|
49
|
+
|
|
50
|
+
cm = ConnectionManager('ldap://localhost')
|
|
51
|
+
|
|
52
|
+
with cm.connection('uid=adminuser,ou=logins,dc=mozilla', 'password') as conn:
|
|
53
|
+
.. do something with conn ..
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
The connector returned by *connection* is a LDAPObject, that's binded to the
|
|
57
|
+
server. See https://pypi.org/project/python-ldap/ for details on how to use a connector.
|
|
58
|
+
|
|
59
|
+
It is possible to check the state of the pool by representing the pool as a string::
|
|
60
|
+
|
|
61
|
+
from ldappool import ConnectionManager
|
|
62
|
+
|
|
63
|
+
cm = ConnectionManager('ldap://localhost', size=2)
|
|
64
|
+
|
|
65
|
+
.. do something with cm ..
|
|
66
|
+
|
|
67
|
+
print(cm)
|
|
68
|
+
|
|
69
|
+
This will result in output similar to this table::
|
|
70
|
+
|
|
71
|
+
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
72
|
+
| Slot (2 max) | Connected | Active | URI | Lifetime (600 max) | Bind DN |
|
|
73
|
+
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
74
|
+
| 1 | connected | inactive | ldap://localhost | 0.00496101379395 | uid=tuser,dc=example,dc=test |
|
|
75
|
+
| 2 | connected | inactive | ldap://localhost | 0.00532603263855 | uid=tuser,dc=example,dc=test |
|
|
76
|
+
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
ConnectionManager options
|
|
80
|
+
:::::::::::::::::::::::::
|
|
81
|
+
|
|
82
|
+
Here are the options you can use when instanciating the pool:
|
|
83
|
+
|
|
84
|
+
- **uri**: ldap server uri **[mandatory]**
|
|
85
|
+
- **bind**: default bind that will be used to bind a connector.
|
|
86
|
+
**default: None**
|
|
87
|
+
- **passwd**: default password that will be used to bind a connector.
|
|
88
|
+
**default: None**
|
|
89
|
+
- **size**: pool size. **default: 10**
|
|
90
|
+
- **retry_max**: number of attempts when a server is down. **default: 3**
|
|
91
|
+
- **retry_delay**: delay in seconds before a retry. **default: .1**
|
|
92
|
+
- **use_tls**: activate TLS when connecting. **default: False**
|
|
93
|
+
- **timeout**: connector timeout. **default: -1**
|
|
94
|
+
- **use_pool**: activates the pool. If False, will recreate a connector
|
|
95
|
+
each time. **default: True**
|
|
96
|
+
|
|
97
|
+
The **uri** option will accept a comma or whitespace separated list of LDAP
|
|
98
|
+
server URIs to allow for failover behavior when connection errors are
|
|
99
|
+
encountered. Connections will be attempted against the servers in order,
|
|
100
|
+
with **retry_max** attempts per URI before failing over to the next server.
|
|
101
|
+
|
|
102
|
+
The **connection** method takes two options:
|
|
103
|
+
|
|
104
|
+
- **bind**: bind used to connect. If None, uses the pool default's.
|
|
105
|
+
**default: None**
|
|
106
|
+
- **passwd**: password used to connect. If None, uses the pool default's.
|
|
107
|
+
**default: None**
|
|
@@ -4,9 +4,9 @@ AUTHORS
|
|
|
4
4
|
CHANGES.rst
|
|
5
5
|
CONTRIBUTORS
|
|
6
6
|
ChangeLog
|
|
7
|
-
MANIFEST.in
|
|
8
7
|
README.rst
|
|
9
8
|
bindep.txt
|
|
9
|
+
pyproject.toml
|
|
10
10
|
requirements.txt
|
|
11
11
|
setup.cfg
|
|
12
12
|
setup.py
|
|
@@ -28,6 +28,7 @@ ldappool/tests/__init__.py
|
|
|
28
28
|
ldappool/tests/test_ldapconnection.py
|
|
29
29
|
ldappool/tests/test_ldappool.py
|
|
30
30
|
releasenotes/notes/drop-py-2-7-9d318d5c72f59f77.yaml
|
|
31
|
+
releasenotes/notes/remove-py38-4a1a65ec118db41f.yaml
|
|
31
32
|
releasenotes/source/conf.py
|
|
32
33
|
releasenotes/source/index.rst
|
|
33
34
|
releasenotes/source/unreleased.rst
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"git_version": "de45796", "is_release": true}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["pbr>=6.1.1"]
|
|
3
|
+
build-backend = "pbr.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ldappool"
|
|
7
|
+
description = "A simple connector pool for python-ldap."
|
|
8
|
+
authors = [
|
|
9
|
+
{name = "OpenStack", email = "openstack-discuss@lists.openstack.org"},
|
|
10
|
+
]
|
|
11
|
+
readme = {file = "README.rst", content-type = "text/x-rst"}
|
|
12
|
+
license = "MPL-2.0"
|
|
13
|
+
dynamic = ["version", "dependencies"]
|
|
14
|
+
requires-python = ">=3.11"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"Operating System :: POSIX :: Linux",
|
|
18
|
+
"Programming Language :: Python",
|
|
19
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Programming Language :: Python :: 3.14",
|
|
25
|
+
"Programming Language :: Python :: 3.15",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://opendev.org/openstack/ldappool"
|
|
30
|
+
Repository = "https://opendev.org/openstack/ldappool"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools.packages.find]
|
|
33
|
+
include = ["ldappool*"]
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Requirements lower bounds listed here are our best effort to keep them up to
|
|
2
|
+
# date but we do not test them so no guarantee of having them all correct. If
|
|
3
|
+
# you find any incorrect lower bounds, let us know or propose a fix.
|
|
4
|
+
|
|
5
|
+
python-ldap>=3.0.0 # PSF
|
|
6
|
+
PrettyTable>=0.7.2
|
ldappool-3.1.0/setup.cfg
ADDED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
hacking>=
|
|
2
|
-
flake8-docstrings==0.2.1.post1 # MIT
|
|
1
|
+
hacking>=6.1.0,<6.2.0 # Apache-2.0
|
|
3
2
|
|
|
4
|
-
coverage
|
|
3
|
+
coverage>=4.0 # Apache-2.0
|
|
5
4
|
fixtures>=3.0.0 # Apache-2.0/BSD
|
|
6
5
|
stestr>=2.0.0 # Apache-2.0
|
|
7
6
|
testresources>=2.0.0 # Apache-2.0/BSD
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
[tox]
|
|
2
|
-
minversion =
|
|
2
|
+
minversion = 4.28.0
|
|
3
3
|
skipsdist = True
|
|
4
4
|
envlist = pep8,cover,docs,releasenotes
|
|
5
|
-
ignore_basepython_conflict = true
|
|
6
5
|
|
|
7
6
|
[testenv]
|
|
8
|
-
basepython = python3
|
|
9
7
|
usedevelop = True
|
|
10
8
|
setenv =
|
|
11
9
|
OS_STDOUT_NOCAPTURE=False
|
|
12
10
|
OS_STDERR_NOCAPTURE=False
|
|
13
11
|
PYTHONDONTWRITEBYTECODE=1
|
|
12
|
+
constraints =
|
|
13
|
+
{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
|
|
14
14
|
deps =
|
|
15
|
-
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
|
|
16
15
|
-r{toxinidir}/requirements.txt
|
|
17
16
|
-r{toxinidir}/test-requirements.txt
|
|
18
17
|
commands =
|
|
@@ -41,21 +40,23 @@ commands =
|
|
|
41
40
|
# D103: Missing docstring in public function
|
|
42
41
|
# D104: Missing docstring in public package
|
|
43
42
|
# D105: Missing docstring in magic method
|
|
43
|
+
# D107: Missing docstring in __init__
|
|
44
44
|
# D200: One-line docstring should fit on one line with quotes
|
|
45
45
|
# D210: No whitespaces allowed surrounding docstring text
|
|
46
46
|
# D401: First line should be in imperative mood
|
|
47
|
-
ignore = D100,D101,D102,D104,D105,D200,D210,D401
|
|
47
|
+
ignore = D100,D101,D102,D104,D105,D107,D200,D210,D401
|
|
48
48
|
show-source = True
|
|
49
49
|
exclude = .venv,.tox,dist,doc,*egg,build
|
|
50
50
|
|
|
51
51
|
[testenv:docs]
|
|
52
|
+
skip_install = true
|
|
52
53
|
deps =
|
|
53
|
-
-c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
|
|
54
54
|
-r{toxinidir}/doc/requirements.txt
|
|
55
55
|
commands=
|
|
56
56
|
sphinx-build -W -b html doc/source doc/build/html
|
|
57
57
|
|
|
58
58
|
[testenv:releasenotes]
|
|
59
|
+
skip_install = true
|
|
59
60
|
deps = {[testenv:docs]deps}
|
|
60
61
|
commands =
|
|
61
62
|
sphinx-build -W -b html releasenotes/source releasenotes/build/html
|
ldappool-3.0.0/MANIFEST.in
DELETED
ldappool-3.0.0/PKG-INFO
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 1.2
|
|
2
|
-
Name: ldappool
|
|
3
|
-
Version: 3.0.0
|
|
4
|
-
Summary: A simple connector pool for python-ldap.
|
|
5
|
-
Home-page: https://opendev.org/openstack/ldappool
|
|
6
|
-
Author: OpenStack
|
|
7
|
-
Author-email: openstack-discuss@lists.openstack.org
|
|
8
|
-
License: UNKNOWN
|
|
9
|
-
Description: ldappool
|
|
10
|
-
========
|
|
11
|
-
|
|
12
|
-
A simple connector pool for python-ldap.
|
|
13
|
-
|
|
14
|
-
The pool keeps LDAP connectors alive and let you reuse them,
|
|
15
|
-
drastically reducing the time spent to initiate a ldap connection.
|
|
16
|
-
|
|
17
|
-
The pool has useful features like:
|
|
18
|
-
|
|
19
|
-
- transparent reconnection on failures or server restarts
|
|
20
|
-
- configurable pool size and connectors timeouts
|
|
21
|
-
- configurable max lifetime for connectors
|
|
22
|
-
- a context manager to simplify acquiring and releasing a connector
|
|
23
|
-
|
|
24
|
-
**You need python-ldap in order to use this library**
|
|
25
|
-
|
|
26
|
-
Quickstart
|
|
27
|
-
::::::::::
|
|
28
|
-
|
|
29
|
-
To work with the pool, you just need to create it, then use it as a
|
|
30
|
-
context manager with the *connection* method::
|
|
31
|
-
|
|
32
|
-
from ldappool import ConnectionManager
|
|
33
|
-
|
|
34
|
-
cm = ConnectionManager('ldap://localhost')
|
|
35
|
-
|
|
36
|
-
with cm.connection('uid=adminuser,ou=logins,dc=mozilla', 'password') as conn:
|
|
37
|
-
.. do something with conn ..
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
The connector returned by *connection* is a LDAPObject, that's binded to the
|
|
41
|
-
server. See https://pypi.org/project/python-ldap/ for details on how to use a connector.
|
|
42
|
-
|
|
43
|
-
It is possible to check the state of the pool by representing the pool as a string::
|
|
44
|
-
|
|
45
|
-
from ldappool import ConnectionManager
|
|
46
|
-
|
|
47
|
-
cm = ConnectionManager('ldap://localhost', size=2)
|
|
48
|
-
|
|
49
|
-
.. do something with cm ..
|
|
50
|
-
|
|
51
|
-
print(cm)
|
|
52
|
-
|
|
53
|
-
This will result in output similar to this table::
|
|
54
|
-
|
|
55
|
-
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
56
|
-
| Slot (2 max) | Connected | Active | URI | Lifetime (600 max) | Bind DN |
|
|
57
|
-
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
58
|
-
| 1 | connected | inactive | ldap://localhost | 0.00496101379395 | uid=tuser,dc=example,dc=test |
|
|
59
|
-
| 2 | connected | inactive | ldap://localhost | 0.00532603263855 | uid=tuser,dc=example,dc=test |
|
|
60
|
-
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
ConnectionManager options
|
|
64
|
-
:::::::::::::::::::::::::
|
|
65
|
-
|
|
66
|
-
Here are the options you can use when instanciating the pool:
|
|
67
|
-
|
|
68
|
-
- **uri**: ldap server uri **[mandatory]**
|
|
69
|
-
- **bind**: default bind that will be used to bind a connector.
|
|
70
|
-
**default: None**
|
|
71
|
-
- **passwd**: default password that will be used to bind a connector.
|
|
72
|
-
**default: None**
|
|
73
|
-
- **size**: pool size. **default: 10**
|
|
74
|
-
- **retry_max**: number of attempts when a server is down. **default: 3**
|
|
75
|
-
- **retry_delay**: delay in seconds before a retry. **default: .1**
|
|
76
|
-
- **use_tls**: activate TLS when connecting. **default: False**
|
|
77
|
-
- **timeout**: connector timeout. **default: -1**
|
|
78
|
-
- **use_pool**: activates the pool. If False, will recreate a connector
|
|
79
|
-
each time. **default: True**
|
|
80
|
-
|
|
81
|
-
The **uri** option will accept a comma or whitespace separated list of LDAP
|
|
82
|
-
server URIs to allow for failover behavior when connection errors are
|
|
83
|
-
encountered. Connections will be attempted against the servers in order,
|
|
84
|
-
with **retry_max** attempts per URI before failing over to the next server.
|
|
85
|
-
|
|
86
|
-
The **connection** method takes two options:
|
|
87
|
-
|
|
88
|
-
- **bind**: bind used to connect. If None, uses the pool default's.
|
|
89
|
-
**default: None**
|
|
90
|
-
- **passwd**: password used to connect. If None, uses the pool default's.
|
|
91
|
-
**default: None**
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
Platform: UNKNOWN
|
|
95
|
-
Classifier: Intended Audience :: Developers
|
|
96
|
-
Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
|
|
97
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
98
|
-
Classifier: Programming Language :: Python
|
|
99
|
-
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
100
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
101
|
-
Classifier: Programming Language :: Python :: 3
|
|
102
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
103
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
104
|
-
Requires-Python: >=3.6
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
# The order of packages is significant, because pip processes them in the order
|
|
2
|
-
# of appearance. Changing the order has an impact on the overall integration
|
|
3
|
-
# process, which may cause wedges in the gate later.
|
|
4
|
-
|
|
5
|
-
openstackdocstheme>=2.2.1 # Apache-2.0
|
|
6
|
-
reno>=3.1.0 # Apache-2.0
|
|
7
|
-
sphinx>=2.0.0,!=2.1.0 # BSD
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 1.2
|
|
2
|
-
Name: ldappool
|
|
3
|
-
Version: 3.0.0
|
|
4
|
-
Summary: A simple connector pool for python-ldap.
|
|
5
|
-
Home-page: https://opendev.org/openstack/ldappool
|
|
6
|
-
Author: OpenStack
|
|
7
|
-
Author-email: openstack-discuss@lists.openstack.org
|
|
8
|
-
License: UNKNOWN
|
|
9
|
-
Description: ldappool
|
|
10
|
-
========
|
|
11
|
-
|
|
12
|
-
A simple connector pool for python-ldap.
|
|
13
|
-
|
|
14
|
-
The pool keeps LDAP connectors alive and let you reuse them,
|
|
15
|
-
drastically reducing the time spent to initiate a ldap connection.
|
|
16
|
-
|
|
17
|
-
The pool has useful features like:
|
|
18
|
-
|
|
19
|
-
- transparent reconnection on failures or server restarts
|
|
20
|
-
- configurable pool size and connectors timeouts
|
|
21
|
-
- configurable max lifetime for connectors
|
|
22
|
-
- a context manager to simplify acquiring and releasing a connector
|
|
23
|
-
|
|
24
|
-
**You need python-ldap in order to use this library**
|
|
25
|
-
|
|
26
|
-
Quickstart
|
|
27
|
-
::::::::::
|
|
28
|
-
|
|
29
|
-
To work with the pool, you just need to create it, then use it as a
|
|
30
|
-
context manager with the *connection* method::
|
|
31
|
-
|
|
32
|
-
from ldappool import ConnectionManager
|
|
33
|
-
|
|
34
|
-
cm = ConnectionManager('ldap://localhost')
|
|
35
|
-
|
|
36
|
-
with cm.connection('uid=adminuser,ou=logins,dc=mozilla', 'password') as conn:
|
|
37
|
-
.. do something with conn ..
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
The connector returned by *connection* is a LDAPObject, that's binded to the
|
|
41
|
-
server. See https://pypi.org/project/python-ldap/ for details on how to use a connector.
|
|
42
|
-
|
|
43
|
-
It is possible to check the state of the pool by representing the pool as a string::
|
|
44
|
-
|
|
45
|
-
from ldappool import ConnectionManager
|
|
46
|
-
|
|
47
|
-
cm = ConnectionManager('ldap://localhost', size=2)
|
|
48
|
-
|
|
49
|
-
.. do something with cm ..
|
|
50
|
-
|
|
51
|
-
print(cm)
|
|
52
|
-
|
|
53
|
-
This will result in output similar to this table::
|
|
54
|
-
|
|
55
|
-
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
56
|
-
| Slot (2 max) | Connected | Active | URI | Lifetime (600 max) | Bind DN |
|
|
57
|
-
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
58
|
-
| 1 | connected | inactive | ldap://localhost | 0.00496101379395 | uid=tuser,dc=example,dc=test |
|
|
59
|
-
| 2 | connected | inactive | ldap://localhost | 0.00532603263855 | uid=tuser,dc=example,dc=test |
|
|
60
|
-
+--------------+-----------+----------+------------------+--------------------+------------------------------+
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
ConnectionManager options
|
|
64
|
-
:::::::::::::::::::::::::
|
|
65
|
-
|
|
66
|
-
Here are the options you can use when instanciating the pool:
|
|
67
|
-
|
|
68
|
-
- **uri**: ldap server uri **[mandatory]**
|
|
69
|
-
- **bind**: default bind that will be used to bind a connector.
|
|
70
|
-
**default: None**
|
|
71
|
-
- **passwd**: default password that will be used to bind a connector.
|
|
72
|
-
**default: None**
|
|
73
|
-
- **size**: pool size. **default: 10**
|
|
74
|
-
- **retry_max**: number of attempts when a server is down. **default: 3**
|
|
75
|
-
- **retry_delay**: delay in seconds before a retry. **default: .1**
|
|
76
|
-
- **use_tls**: activate TLS when connecting. **default: False**
|
|
77
|
-
- **timeout**: connector timeout. **default: -1**
|
|
78
|
-
- **use_pool**: activates the pool. If False, will recreate a connector
|
|
79
|
-
each time. **default: True**
|
|
80
|
-
|
|
81
|
-
The **uri** option will accept a comma or whitespace separated list of LDAP
|
|
82
|
-
server URIs to allow for failover behavior when connection errors are
|
|
83
|
-
encountered. Connections will be attempted against the servers in order,
|
|
84
|
-
with **retry_max** attempts per URI before failing over to the next server.
|
|
85
|
-
|
|
86
|
-
The **connection** method takes two options:
|
|
87
|
-
|
|
88
|
-
- **bind**: bind used to connect. If None, uses the pool default's.
|
|
89
|
-
**default: None**
|
|
90
|
-
- **passwd**: password used to connect. If None, uses the pool default's.
|
|
91
|
-
**default: None**
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
Platform: UNKNOWN
|
|
95
|
-
Classifier: Intended Audience :: Developers
|
|
96
|
-
Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
|
|
97
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
98
|
-
Classifier: Programming Language :: Python
|
|
99
|
-
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
100
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
101
|
-
Classifier: Programming Language :: Python :: 3
|
|
102
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
103
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
104
|
-
Requires-Python: >=3.6
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"git_version": "322e0d7", "is_release": true}
|
ldappool-3.0.0/requirements.txt
DELETED
ldappool-3.0.0/setup.cfg
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
[metadata]
|
|
2
|
-
name = ldappool
|
|
3
|
-
summary = A simple connector pool for python-ldap.
|
|
4
|
-
description-file =
|
|
5
|
-
README.rst
|
|
6
|
-
author = OpenStack
|
|
7
|
-
author-email = openstack-discuss@lists.openstack.org
|
|
8
|
-
home-page = https://opendev.org/openstack/ldappool
|
|
9
|
-
python-requires = >=3.6
|
|
10
|
-
classifier =
|
|
11
|
-
Intended Audience :: Developers
|
|
12
|
-
License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
|
|
13
|
-
Operating System :: POSIX :: Linux
|
|
14
|
-
Programming Language :: Python
|
|
15
|
-
Programming Language :: Python :: Implementation :: CPython
|
|
16
|
-
Programming Language :: Python :: 3 :: Only
|
|
17
|
-
Programming Language :: Python :: 3
|
|
18
|
-
Programming Language :: Python :: 3.6
|
|
19
|
-
Programming Language :: Python :: 3.7
|
|
20
|
-
|
|
21
|
-
[files]
|
|
22
|
-
packages =
|
|
23
|
-
ldappool
|
|
24
|
-
|
|
25
|
-
[pbr]
|
|
26
|
-
autodoc_tree_index_modules = True
|
|
27
|
-
autodoc_tree_excludes =
|
|
28
|
-
setup.py
|
|
29
|
-
ldappool/tests/
|
|
30
|
-
|
|
31
|
-
[egg_info]
|
|
32
|
-
tag_build =
|
|
33
|
-
tag_date = 0
|
|
34
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|