Make python-ldap optional for PyPI packages

python-ldap is a Python package with heavy C extensions. In order to
build python-ldap, not only OpenLDAP development headers are necessary,
but also OpenSSL, Cyrus SASL, and MIT KRB5 development headers.

A fully functional ipaclient doesn't need an LDAP driver. It talks JSON
RPC over HTTPS to a server. python-ldap is only used by ipapython.dn.DN
to convert a string to a DN with ldap_str2dn(). The function is simple
and can be wrapped with ctypes in a bunch of lines.

Related: https://pagure.io/freeipa/issue/6468
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
Christian Heimes committed 2019-04-26 12:53:23 +02:00
1 parent c314411130
commit 2a459ce0f2
8 files changed
+243 -12

No files matched your search

+1 -2
View File
@@ -70,14 +70,13 @@ if __name__ == '__main__':
"polib",
"pytest",
"pytest_multihost",
"python-ldap",
"six",
],
extras_require={
"integration": ["dbus-python", "pyyaml", "ipaserver"],
"ipaserver": ["ipaserver"],
"webui": ["selenium", "pyyaml", "ipaserver"],
"xmlrpc": ["ipaserver"],
"xmlrpc": ["ipaserver", "python-ldap"],
":python_version<'3'": ["mock"],
}
)
+57 -1
View File
@@ -1,3 +1,4 @@
import contextlib
import unittest
import pytest
@@ -5,7 +6,9 @@ import pytest
from cryptography import x509
import six
from ipapython.dn import DN, RDN, AVA
from ipapython.dn import DN, RDN, AVA, str2dn, dn2str, DECODING_ERROR
from ipapython import dn_ctypes
if six.PY3:
unicode = str
@@ -1345,5 +1348,58 @@ class TestInternationalization(unittest.TestCase):
self.assertEqual(str(dn1), b'cn=' + self.arabic_hello_utf8)
# 1: LDAP_AVA_STRING
# 4: LDAP_AVA_NONPRINTABLE
@pytest.mark.parametrize(
'dnstring,expected',
[
('', []),
('cn=bob', [[('cn', 'bob', 1)]]),
('cn=Bob', [[('cn', 'Bob', 1)]]),
(u'cn=b\xf6b', [[('cn', u'b\xf6b', 4)]]),
('cn=bob,sn=builder', [[('cn', 'bob', 1)], [('sn', 'builder', 1)]]),
(u'cn=b\xf6b,sn=builder', [
[('cn', u'b\xf6b', 4)], [('sn', 'builder', 1)]
]),
('cn=bob+sn=builder', [[('cn', 'bob', 1), ('sn', 'builder', 1)]]),
('dc=ipa,dc=example', [[('dc', 'ipa', 1)], [('dc', 'example', 1)]]),
('cn=R\\,W privilege', [[('cn', 'R,W privilege', 1)]]),
]
)
def test_str2dn2str(dnstring, expected):
dn = str2dn(dnstring)
assert dn == expected
assert dn2str(dn) == dnstring
assert dn_ctypes.str2dn(dnstring) == dn
assert dn_ctypes.dn2str(dn) == dnstring
@pytest.mark.parametrize(
'dnstring',
[
'cn',
'cn=foo,',
'cn=foo+bar',
]
)
def test_str2dn_errors(dnstring):
with pytest.raises(DECODING_ERROR):
str2dn(dnstring)
with pytest.raises(dn_ctypes.DECODING_ERROR):
dn_ctypes.str2dn(dnstring)
def test_dn2str_special():
dnstring = 'cn=R\\2cW privilege'
dnstring2 = 'cn=R\\,W privilege'
expected = [[('cn', 'R,W privilege', 1)]]
dn = str2dn(dnstring)
assert dn == expected
assert dn2str(dn) == dnstring2
assert dn_ctypes.str2dn(dnstring) == dn
assert dn_ctypes.dn2str(dn) == dnstring2
if __name__ == '__main__':
unittest.main()
+9 -5
View File
@@ -35,19 +35,14 @@ from contextlib import contextmanager
from pprint import pformat
import six
import ldap
import ldap.sasl
import ldap.modlist
import ipalib
from ipalib import api
from ipalib.plugable import Plugin
from ipalib.request import context
from ipapython.dn import DN
from ipapython.ipaldap import ldap_initialize
from ipapython.ipautil import run
try:
# not available with client-only wheel packages
from ipalib.install.kinit import kinit_keytab, kinit_password
@@ -60,6 +55,15 @@ try:
except ImportError:
paths = None
try:
# not available with optional python-ldap
import ldap
except ImportError:
pass
else:
import ldap.sasl
import ldap.modlist
from ipapython.ipaldap import ldap_initialize
if six.PY3:
unicode = str