[Python-modules-commits] [python-ldap3] 01/06: Import python-ldap3_0.9.9.1.orig.tar.gz

Brian May bam at moszumanska.debian.org
Tue Oct 13 22:48:38 UTC 2015


This is an automated email from the git hooks/post-receive script.

bam pushed a commit to branch master
in repository python-ldap3.

commit ef86c9e1d446d67f44f7fc719fdd0e9d1400d8ad
Author: Brian May <bam at debian.org>
Date:   Wed Oct 14 09:24:35 2015 +1100

    Import python-ldap3_0.9.9.1.orig.tar.gz
---
 PKG-INFO                                     |    2 +-
 _version.json                                |    2 +-
 ldap3.egg-info/PKG-INFO                      |    2 +-
 ldap3.egg-info/SOURCES.txt                   |    2 +
 ldap3/__init__.py                            |   55 +
 ldap3/abstract/attrDef.py                    |    7 +-
 ldap3/abstract/operationalAttribute.py       |    1 +
 ldap3/core/connection.py                     |   12 +-
 ldap3/core/server.py                         |   11 +-
 ldap3/extend/__init__.py                     |    2 +-
 ldap3/extend/novell/partition_entry_count.py |    2 +-
 ldap3/extend/novell/replicaInfo.py           |    2 +-
 ldap3/extend/operation.py                    |    5 +-
 ldap3/operation/add.py                       |  139 +-
 ldap3/operation/bind.py                      |  279 ++--
 ldap3/operation/delete.py                    |   94 +-
 ldap3/operation/extended.py                  |   40 +-
 ldap3/operation/search.py                    | 1022 +++++++------
 ldap3/protocol/formatters/formatters.py      |    2 +
 ldap3/protocol/formatters/standard.py        |   16 +-
 ldap3/protocol/oid.py                        | 2125 +++++++++++++-------------
 ldap3/protocol/{oid.py => oid2.py}           |    8 +-
 ldap3/protocol/rfc4511.py                    | 2001 ++++++++++++------------
 ldap3/protocol/rfc4512.py                    |   27 +-
 ldap3/protocol/sasl/kerberos.py              |    8 +-
 ldap3/strategy/async.py                      |   11 +-
 ldap3/strategy/base.py                       | 1429 +++++++++--------
 ldap3/strategy/sync.py                       |  420 ++---
 ldap3/utils/asn1.py                          |  223 +++
 ldap3/utils/ciDict.py                        |  210 ++-
 ldap3/utils/conv.py                          |    4 +-
 ldap3/utils/log.py                           |    4 +-
 ldap3/version.py                             |   10 +-
 test/testAbstractionSearch.py                |   10 +-
 test/testCheckNames.py                       |    4 +-
 test/testLDIF-change.py                      |    4 +-
 test/testOfflineSchema.py                    |    2 +-
 test/testSchema.py                           |    2 +-
 test/testSearchOperation.py                  |  382 ++---
 test/testTls.py                              |    6 +-
 40 files changed, 4557 insertions(+), 4030 deletions(-)

diff --git a/PKG-INFO b/PKG-INFO
index cb01e9d..08a1512 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: ldap3
-Version: 0.9.8.8
+Version: 0.9.9.1
 Summary: A strictly RFC 4511 conforming LDAP V3 pure Python client. Same codebase for Python 2, Python3, PyPy and PyPy 3
 Home-page: https://github.com/cannatag/ldap3
 Author: Giovanni Cannata
diff --git a/_version.json b/_version.json
index 441208c..8f046a2 100644
--- a/_version.json
+++ b/_version.json
@@ -6,6 +6,6 @@
     "url": "https://github.com/cannatag/ldap3",
     "description": "A strictly RFC 4511 conforming LDAP V3 pure Python client. Same codebase for Python 2, Python3, PyPy and PyPy 3",
     "author": "Giovanni Cannata",
-    "version": "0.9.8.8",
+    "version": "0.9.9.1",
     "license": "LGPL v3"
 }
diff --git a/ldap3.egg-info/PKG-INFO b/ldap3.egg-info/PKG-INFO
index cb01e9d..08a1512 100644
--- a/ldap3.egg-info/PKG-INFO
+++ b/ldap3.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: ldap3
-Version: 0.9.8.8
+Version: 0.9.9.1
 Summary: A strictly RFC 4511 conforming LDAP V3 pure Python client. Same codebase for Python 2, Python3, PyPy and PyPy 3
 Home-page: https://github.com/cannatag/ldap3
 Author: Giovanni Cannata
diff --git a/ldap3.egg-info/SOURCES.txt b/ldap3.egg-info/SOURCES.txt
index 4cd0805..80e610e 100644
--- a/ldap3.egg-info/SOURCES.txt
+++ b/ldap3.egg-info/SOURCES.txt
@@ -54,6 +54,7 @@ setup.py
 ./ldap3/protocol/microsoft.py
 ./ldap3/protocol/novell.py
 ./ldap3/protocol/oid.py
+./ldap3/protocol/oid2.py
 ./ldap3/protocol/rfc2696.py
 ./ldap3/protocol/rfc2849.py
 ./ldap3/protocol/rfc3062.py
@@ -82,6 +83,7 @@ setup.py
 ./ldap3/strategy/reusable.py
 ./ldap3/strategy/sync.py
 ./ldap3/utils/__init__.py
+./ldap3/utils/asn1.py
 ./ldap3/utils/ciDict.py
 ./ldap3/utils/conv.py
 ./ldap3/utils/dn.py
diff --git a/ldap3/__init__.py b/ldap3/__init__.py
index 4774db1..8f0468c 100644
--- a/ldap3/__init__.py
+++ b/ldap3/__init__.py
@@ -205,6 +205,60 @@ RESULT_ASSERTION_FAILED = 122
 RESULT_AUTHORIZATION_DENIED = 123
 RESULT_E_SYNC_REFRESH_REQUIRED = 4096
 
+RESULT_CODES = {
+    RESULT_SUCCESS: 'success',
+    RESULT_OPERATIONS_ERROR: 'operationsError',
+    RESULT_PROTOCOL_ERROR: 'protocolError',
+    RESULT_TIME_LIMIT_EXCEEDED: 'timeLimitExceeded',
+    RESULT_SIZE_LIMIT_EXCEEDED: 'sizeLimitExceeded',
+    RESULT_COMPARE_FALSE: 'compareFalse',
+    RESULT_COMPARE_TRUE: 'compareTrue',
+    RESULT_AUTH_METHOD_NOT_SUPPORTED: 'authMethodNotSupported',
+    RESULT_STRONGER_AUTH_REQUIRED: 'strongerAuthRequired',
+    RESULT_REFERRAL: 'referral',
+    RESULT_ADMIN_LIMIT_EXCEEDED: 'adminLimitExceeded',
+    RESULT_UNAVAILABLE_CRITICAL_EXTENSION: 'unavailableCriticalExtension',
+    RESULT_CONFIDENTIALITY_REQUIRED: 'confidentialityRequired',
+    RESULT_SASL_BIND_IN_PROGRESS: 'saslBindInProgress',
+    RESULT_NO_SUCH_ATTRIBUTE: 'noSuchAttribute',
+    RESULT_UNDEFINED_ATTRIBUTE_TYPE: 'undefinedAttributeType',
+    RESULT_INAPPROPRIATE_MATCHING: 'inappropriateMatching',
+    RESULT_CONSTRAINT_VIOLATION: 'constraintViolation',
+    RESULT_ATTRIBUTE_OR_VALUE_EXISTS: 'attributeOrValueExists',
+    RESULT_INVALID_ATTRIBUTE_SYNTAX: 'invalidAttributeSyntax',
+    RESULT_NO_SUCH_OBJECT: 'noSuchObject',
+    RESULT_ALIAS_PROBLEM: 'aliasProblem',
+    RESULT_INVALID_DN_SYNTAX: 'invalidDNSyntax',
+    RESULT_ALIAS_DEREFERENCING_PROBLEM: 'aliasDereferencingProblem',
+    RESULT_INAPPROPRIATE_AUTHENTICATION: 'inappropriateAuthentication',
+    RESULT_INVALID_CREDENTIALS: 'invalidCredentials',
+    RESULT_INSUFFICIENT_ACCESS_RIGHTS: 'insufficientAccessRights',
+    RESULT_BUSY: 'busy',
+    RESULT_UNAVAILABLE: 'unavailable',
+    RESULT_UNWILLING_TO_PERFORM: 'unwillingToPerform',
+    RESULT_LOOP_DETECTED: 'loopDetected',
+    RESULT_NAMING_VIOLATION: 'namingViolation',
+    RESULT_OBJECT_CLASS_VIOLATION: 'objectClassViolation',
+    RESULT_NOT_ALLOWED_ON_NON_LEAF: 'notAllowedOnNonLeaf',
+    RESULT_NOT_ALLOWED_ON_RDN: 'notAllowedOnRDN',
+    RESULT_ENTRY_ALREADY_EXISTS: 'entryAlreadyExists',
+    RESULT_OBJECT_CLASS_MODS_PROHIBITED: 'objectClassModsProhibited',
+    RESULT_AFFECT_MULTIPLE_DSAS: 'affectMultipleDSAs',
+    RESULT_OTHER: 'other',
+    RESULT_LCUP_RESOURCES_EXHAUSTED: 'lcupResourcesExhausted',
+    RESULT_LCUP_SECURITY_VIOLATION: 'lcupSecurityViolation',
+    RESULT_LCUP_INVALID_DATA: 'lcupInvalidData',
+    RESULT_LCUP_UNSUPPORTED_SCHEME: 'lcupUnsupportedScheme',
+    RESULT_LCUP_RELOAD_REQUIRED: 'lcupReloadRequired',
+    RESULT_CANCELED: 'canceled',
+    RESULT_NO_SUCH_OPERATION: 'noSuchOperation',
+    RESULT_TOO_LATE: 'tooLate',
+    RESULT_CANNOT_CANCEL: 'cannotCancel',
+    RESULT_ASSERTION_FAILED: 'assertionFailed',
+    RESULT_AUTHORIZATION_DENIED: 'authorizationDenied',
+    RESULT_E_SYNC_REFRESH_REQUIRED: 'e-syncRefreshRequired'
+}
+
 # do not raise exception for (in raise_exceptions connection mode)
 DO_NOT_RAISE_EXCEPTIONS = [RESULT_SUCCESS, RESULT_COMPARE_FALSE, RESULT_COMPARE_TRUE, RESULT_REFERRAL]
 
@@ -261,6 +315,7 @@ HASHED_SALTED_SHA384 = 'SALTED_SHA384'
 HASHED_SALTED_SHA512 = 'SALTED_SHA512'
 HASHED_SALTED_MD5 = 'SALTED_MD5'
 
+
 # centralized imports
 from .version import __author__, __version__, __email__, __description__, __status__, __license__, __url__
 from .core.server import Server
diff --git a/ldap3/abstract/attrDef.py b/ldap3/abstract/attrDef.py
index 4008444..266ba40 100644
--- a/ldap3/abstract/attrDef.py
+++ b/ldap3/abstract/attrDef.py
@@ -25,6 +25,7 @@
 
 from ..core.exceptions import LDAPKeyError
 
+
 class AttrDef(object):
     """Hold the definition of an attribute
 
@@ -42,10 +43,12 @@ class AttrDef(object):
     :type default: string, integer
     :param dereference_dn: reference to an ObjectDef instance. When the attribute value contains a dn it will be searched and substituted in the entry
     :type dereference_dn: ObjectDef
+    :param description: custom attribute description
+    :type dereference_dn: string
 
     """
 
-    def __init__(self, name, key=None, validate=None, pre_query=None, post_query=None, default=NotImplemented, dereference_dn=None):
+    def __init__(self, name, key=None, validate=None, pre_query=None, post_query=None, default=NotImplemented, dereference_dn=None, description=None):
         self.name = name
         self.key = ''.join(key.split()) if key else name  # key set to name if not present
         self.validate = validate
@@ -53,6 +56,7 @@ class AttrDef(object):
         self.post_query = post_query
         self.default = default
         self.dereference_dn = dereference_dn
+        self.description = description
 
     def __repr__(self):
         r = 'AttrDef(key={0.key!r}'.format(self)
@@ -62,6 +66,7 @@ class AttrDef(object):
         r += '' if self.post_query is None else ', post_query={0.post_query!r}'.format(self)
         r += '' if self.default is None else ', default={0.default!r}'.format(self)
         r += '' if self.dereference_dn is None else ', dereference_dn={0.dereference_dn!r}'.format(self)
+        r += '' if self.description is None else ', description={0.d!r}'.format(self)
         r += ')'
 
         return r
diff --git a/ldap3/abstract/operationalAttribute.py b/ldap3/abstract/operationalAttribute.py
index f7688f4..4fd25f8 100644
--- a/ldap3/abstract/operationalAttribute.py
+++ b/ldap3/abstract/operationalAttribute.py
@@ -28,6 +28,7 @@ from os import linesep
 from .attribute import Attribute
 from ..utils.repr import to_stdout_encoding
 
+
 # noinspection PyUnresolvedReferences,PyMissingConstructor
 class OperationalAttribute(Attribute):
     """Operational attribute/values object. Include the search result of an
diff --git a/ldap3/core/connection.py b/ldap3/core/connection.py
index 80ef8f2..1eacdac 100644
--- a/ldap3/core/connection.py
+++ b/ldap3/core/connection.py
@@ -28,8 +28,6 @@ from threading import RLock
 import json
 from functools import reduce
 
-from pyasn1.codec.ber import encoder
-
 from .. import ANONYMOUS, SIMPLE, SASL, MODIFY_ADD, MODIFY_DELETE, MODIFY_REPLACE, \
     DEREF_ALWAYS, SUBTREE, ASYNC, SYNC, CLIENT_STRATEGIES, RESULT_SUCCESS, RESULT_COMPARE_TRUE, NO_ATTRIBUTES, ALL_ATTRIBUTES, \
     ALL_OPERATIONAL_ATTRIBUTES, MODIFY_INCREMENT, LDIF, SASL_AVAILABLE_MECHANISMS, \
@@ -64,7 +62,7 @@ from .exceptions import LDAPUnknownStrategyError, LDAPBindError, LDAPUnknownAuth
     LDAPObjectError
 from ..utils.conv import escape_bytes, prepare_for_stream, check_json_dict, format_json
 from ..utils.log import log, log_enabled, ERROR, BASIC, PROTOCOL, get_library_log_hide_sensitive_data
-
+from ..utils.asn1 import encoder
 try:
     from ..strategy.mockSync import MockSyncStrategy  # not used yet
     from ..strategy.mockAsync import MockAsyncStrategy  # not used yet
@@ -167,7 +165,8 @@ class Connection(object):
                  raise_exceptions=False,
                  pool_name=None,
                  pool_size=None,
-                 pool_lifetime=None):
+                 pool_lifetime=None,
+                 fast_decoder=True):
 
         self.lock = RLock()  # re-entrant lock to assure that operations in the Connection object are executed atomically in the same thread
         with self.lock:
@@ -229,6 +228,7 @@ class Connection(object):
             self.auto_range = True if auto_range else False
             self.extend = ExtendedOperationsRoot(self)
             self._entries = None
+            self.fast_decoder = fast_decoder
 
             if isinstance(server, STRING_TYPES):
                 server = Server(server)
@@ -304,7 +304,8 @@ class Connection(object):
             _format_socket_endpoints(self.socket),
             'tls not started' if not self.tls_started else('deferred start_tls' if self._deferred_start_tls else 'tls started'),
             'listening' if self.listening else 'not listening',
-            self.strategy.__class__.__name__ if hasattr(self, 'strategy') else 'No strategy'
+            self.strategy.__class__.__name__ if hasattr(self, 'strategy') else 'No strategy',
+            'internal decoder' if self.fast_decoder else 'pyasn1 decoder'
         ]
         return ' - '.join(s)
 
@@ -330,6 +331,7 @@ class Connection(object):
         r += '' if (self.pool_name is None or self.pool_name == DEFAULT_THREADED_POOL_NAME) else ', pool_name={0.pool_name!r}'.format(self)
         r += '' if self.pool_size is None else ', pool_size={0.pool_size!r}'.format(self)
         r += '' if self.pool_lifetime is None else ', pool_lifetime={0.pool_lifetime!r}'.format(self)
+        r += '' if self.fast_decoder is None else (', fast_decoder=' + 'True' if self.fast_decoder else 'False')
         r += ')'
 
         return r
diff --git a/ldap3/core/server.py b/ldap3/core/server.py
index c26df4c..df9ded9 100644
--- a/ldap3/core/server.py
+++ b/ldap3/core/server.py
@@ -134,10 +134,10 @@ class Server(object):
 
         if isinstance(allowed_referral_hosts, SEQUENCE_TYPES):
             self.allowed_referral_hosts = []
-            for refServer in allowed_referral_hosts:
-                if isinstance(refServer, tuple):
-                    if isinstance(refServer[1], bool):
-                        self.allowed_referral_hosts.append(refServer)
+            for referral_host in allowed_referral_hosts:
+                if isinstance(referral_host, tuple):
+                    if isinstance(referral_host[1], bool):
+                        self.allowed_referral_hosts.append(referral_host)
         elif isinstance(allowed_referral_hosts, tuple):
             if isinstance(allowed_referral_hosts[1], bool):
                 self.allowed_referral_hosts = [allowed_referral_hosts]
@@ -304,7 +304,8 @@ class Server(object):
                                                    'vendorName',
                                                    'vendorVersion',
                                                    'subschemaSubentry',
-                                                   '*'],  # requests all remaining attributes (other),
+                                                   '*',
+                                                   '+'],  # requests all remaining attributes (other),
                                        get_operational_attributes=True)
 
             with self.lock:
diff --git a/ldap3/extend/__init__.py b/ldap3/extend/__init__.py
index b91197f..febcab0 100644
--- a/ldap3/extend/__init__.py
+++ b/ldap3/extend/__init__.py
@@ -25,7 +25,7 @@
 
 from os import linesep
 
-from .. import SUBTREE, DEREF_ALWAYS, HASHED_NONE
+from .. import SUBTREE, DEREF_ALWAYS
 from .novell.partition_entry_count import PartitionEntryCount
 from .novell.replicaInfo import ReplicaInfo
 from .novell.listReplicas import ListReplicas
diff --git a/ldap3/extend/novell/partition_entry_count.py b/ldap3/extend/novell/partition_entry_count.py
index d5d7158..db730eb 100644
--- a/ldap3/extend/novell/partition_entry_count.py
+++ b/ldap3/extend/novell/partition_entry_count.py
@@ -23,12 +23,12 @@
 # along with ldap3 in the COPYING and COPYING.LESSER files.
 # If not, see <http://www.gnu.org/licenses/>.
 
-from pyasn1.codec.ber import decoder
 from pyasn1.type.univ import Integer
 
 from ...core.exceptions import LDAPExtensionError
 from ..operation import ExtendedOperation
 from ...protocol.rfc4511 import LDAPDN
+from ...utils.asn1 import decoder
 
 
 class PartitionEntryCount(ExtendedOperation):
diff --git a/ldap3/extend/novell/replicaInfo.py b/ldap3/extend/novell/replicaInfo.py
index da0093d..a89e2e1 100644
--- a/ldap3/extend/novell/replicaInfo.py
+++ b/ldap3/extend/novell/replicaInfo.py
@@ -26,11 +26,11 @@
 from datetime import datetime
 
 from pyasn1.type.univ import Integer
-from pyasn1.codec.ber import decoder
 
 from ...core.exceptions import LDAPExtensionError
 from ...protocol.novell import LDAPDN, ReplicaInfoRequestValue
 from ..operation import ExtendedOperation
+from ...utils.asn1 import decoder
 
 
 class ReplicaInfo(ExtendedOperation):
diff --git a/ldap3/extend/operation.py b/ldap3/extend/operation.py
index 7e0dafb..0fe6911 100644
--- a/ldap3/extend/operation.py
+++ b/ldap3/extend/operation.py
@@ -23,10 +23,9 @@
 # along with ldap3 in the COPYING and COPYING.LESSER files.
 # If not, see <http://www.gnu.org/licenses/>.
 
-from pyasn1.codec.ber import decoder
-
 from .. import RESULT_SUCCESS
 from ..core.exceptions import LDAPExtensionError
+from ..utils.asn1 import decoder
 
 
 class ExtendedOperation(object):
@@ -45,7 +44,7 @@ class ExtendedOperation(object):
     def send(self):
         if self.connection.check_names and self.connection.server.info is not None and self.connection.server.info.supported_extensions is not None:  # checks if extension is supported
             for request_name in self.connection.server.info.supported_extensions:
-                if request_name.oid == self.request_name:
+                if request_name[0] == self.request_name:
                     break
             else:
                 raise LDAPExtensionError('extension not in DSA list of supported extensions')
diff --git a/ldap3/operation/add.py b/ldap3/operation/add.py
index 23acd09..abfe855 100644
--- a/ldap3/operation/add.py
+++ b/ldap3/operation/add.py
@@ -1,69 +1,70 @@
-"""
-"""
-
-# Created on 2013.05.31
-#
-# Author: Giovanni Cannata
-#
-# Copyright 2015 Giovanni Cannata
-#
-# This file is part of ldap3.
-#
-# ldap3 is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ldap3 is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with ldap3 in the COPYING and COPYING.LESSER files.
-# If not, see <http://www.gnu.org/licenses/>.
-
-from .. import SEQUENCE_TYPES
-from ..protocol.rfc4511 import AddRequest, LDAPDN, AttributeList, Attribute, AttributeDescription, ValsAtLeast1, ResultCode
-from ..protocol.convert import referrals_to_list, attributes_to_dict, validate_attribute_value
-
-# AddRequest ::= [APPLICATION 8] SEQUENCE {
-#     entry           LDAPDN,
-#     attributes      AttributeList }
-
-
-def add_operation(dn,
-                  attributes,
-                  schema=None):
-    # attributes is a dictionary in the form 'attribute': ['val1', 'val2', 'valN']
-    attribute_list = AttributeList()
-    for pos, attribute in enumerate(attributes):
-        attribute_list[pos] = Attribute()
-        attribute_list[pos]['type'] = AttributeDescription(attribute)
-        vals = ValsAtLeast1()
-        if isinstance(attributes[attribute], SEQUENCE_TYPES):
-            for index, value in enumerate(attributes[attribute]):
-                vals.setComponentByPosition(index, validate_attribute_value(schema, attribute, value))
-        else:
-            vals.setComponentByPosition(0, validate_attribute_value(schema, attribute, attributes[attribute]))
-
-        attribute_list[pos]['vals'] = vals
-
-    request = AddRequest()
-    request['entry'] = LDAPDN(dn)
-    request['attributes'] = attribute_list
-
-    return request
-
-
-def add_request_to_dict(request):
-    return {'entry': str(request['entry']),
-            'attributes': attributes_to_dict(request['attributes'])}
-
-
-def add_response_to_dict(response):
-    return {'result': int(response[0]),
-            'description': ResultCode().getNamedValues().getName(response[0]),
-            'dn': str(response['matchedDN']),
-            'message': str(response['diagnosticMessage']),
-            'referrals': referrals_to_list(response['referral'])}
+"""
+"""
+
+# Created on 2013.05.31
+#
+# Author: Giovanni Cannata
+#
+# Copyright 2015 Giovanni Cannata
+#
+# This file is part of ldap3.
+#
+# ldap3 is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# ldap3 is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with ldap3 in the COPYING and COPYING.LESSER files.
+# If not, see <http://www.gnu.org/licenses/>.
+
+from .. import SEQUENCE_TYPES
+from ..protocol.rfc4511 import AddRequest, LDAPDN, AttributeList, Attribute, AttributeDescription, ResultCode, Vals
+from ..protocol.convert import referrals_to_list, attributes_to_dict, validate_attribute_value
+
+# AddRequest ::= [APPLICATION 8] SEQUENCE {
+#     entry           LDAPDN,
+#     attributes      AttributeList }
+
+
+def add_operation(dn,
+                  attributes,
+                  schema=None):
+    # attributes is a dictionary in the form 'attribute': ['val1', 'val2', 'valN']
+    attribute_list = AttributeList()
+    for pos, attribute in enumerate(attributes):
+        attribute_list[pos] = Attribute()
+        attribute_list[pos]['type'] = AttributeDescription(attribute)
+        # vals = ValsAtLeast1()
+        vals = Vals()  # changed from ValsAtLeast1() for allowing empty member value in groups
+        if isinstance(attributes[attribute], SEQUENCE_TYPES):
+            for index, value in enumerate(attributes[attribute]):
+                vals.setComponentByPosition(index, validate_attribute_value(schema, attribute, value))
+        else:
+            vals.setComponentByPosition(0, validate_attribute_value(schema, attribute, attributes[attribute]))
+
+        attribute_list[pos]['vals'] = vals
+
+    request = AddRequest()
+    request['entry'] = LDAPDN(dn)
+    request['attributes'] = attribute_list
+
+    return request
+
+
+def add_request_to_dict(request):
+    return {'entry': str(request['entry']),
+            'attributes': attributes_to_dict(request['attributes'])}
+
+
+def add_response_to_dict(response):
+    return {'result': int(response[0]),
+            'description': ResultCode().getNamedValues().getName(response[0]),
+            'dn': str(response['matchedDN']),
+            'message': str(response['diagnosticMessage']),
+            'referrals': referrals_to_list(response['referral'])}
diff --git a/ldap3/operation/bind.py b/ldap3/operation/bind.py
index 7e2d642..a3e1ce0 100644
--- a/ldap3/operation/bind.py
+++ b/ldap3/operation/bind.py
@@ -1,126 +1,153 @@
-"""
-"""
-
-# Created on 2013.05.31
-#
-# Author: Giovanni Cannata
-#
-# Copyright 2015 Giovanni Cannata
-#
-# This file is part of ldap3.
-#
-# ldap3 is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ldap3 is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with ldap3 in the COPYING and COPYING.LESSER files.
-# If not, see <http://www.gnu.org/licenses/>.
-
-from .. import SIMPLE, ANONYMOUS, SASL
-from ..core.exceptions import LDAPPasswordIsMandatoryError, LDAPUnknownAuthenticationMethodError
-from ..protocol.sasl.sasl import validate_simple_password
-from ..protocol.rfc4511 import Version, AuthenticationChoice, Simple, BindRequest, ResultCode, SaslCredentials, BindResponse, \
-    LDAPDN, LDAPString, Referral, ServerSaslCreds, SicilyPackageDiscovery, SicilyNegotiate, SicilyResponse
-from ..protocol.convert import authentication_choice_to_dict, referrals_to_list
-
-# BindRequest ::= [APPLICATION 0] SEQUENCE {
-#                                           version        INTEGER (1 ..  127),
-#                                           name           LDAPDN,
-#                                           authentication AuthenticationChoice }
-
-
-def bind_operation(version,
-                   authentication,
-                   name='',
-                   password=None,
-                   sasl_mechanism=None,
-                   sasl_credentials=None):
-    request = BindRequest()
-    request['version'] = Version(version)
-    if name is None:
-        name = ''
-    request['name'] = name
-    if authentication == SIMPLE:
-        if password:
-            request['authentication'] = AuthenticationChoice().setComponentByName('simple', Simple(validate_simple_password(password)))
-        else:
-            raise LDAPPasswordIsMandatoryError('password is mandatory')
-    elif authentication == SASL:
-        sasl_creds = SaslCredentials()
-        sasl_creds['mechanism'] = sasl_mechanism
-        if sasl_credentials:
-            sasl_creds['credentials'] = sasl_credentials
-        request['authentication'] = AuthenticationChoice().setComponentByName('sasl', sasl_creds)
-    elif authentication == ANONYMOUS:
-        request['name'] = ''
-        request['authentication'] = AuthenticationChoice().setComponentByName('simple', Simple(''))
-    elif authentication == 'SICILY_PACKAGE_DISCOVERY':  # https://msdn.microsoft.com/en-us/library/cc223501.aspx
-        request['name'] = ''
-        request['authentication'] = AuthenticationChoice().setComponentByName('sicilyPackageDiscovery', SicilyPackageDiscovery(''))
-    elif authentication == 'SICILY_NEGOTIATE_NTLM':  # https://msdn.microsoft.com/en-us/library/cc223501.aspx
-        request['name'] = 'NTLM'
-        request['authentication'] = AuthenticationChoice().setComponentByName('sicilyNegotiate', SicilyNegotiate(name.create_negotiate_message()))  # ntlm client in self.name
-    elif authentication == 'SICILY_RESPONSE_NTLM':  # https://msdn.microsoft.com/en-us/library/cc223501.aspx
-        name.parse_challenge_message(password)  # server_creds returned by server in password
-        server_creds = name.create_authenticate_message()
-        if server_creds:
-            request['name'] = ''
-            request['authentication'] = AuthenticationChoice().setComponentByName('sicilyResponse', SicilyResponse(server_creds))
-        else:
-            request = None
-    else:
-        raise LDAPUnknownAuthenticationMethodError('unknown authentication method')
-
-    return request
-
-
-def bind_request_to_dict(request):
-    return {'version': int(request['version']),
-            'name': str(request['name']),
-            'authentication': authentication_choice_to_dict(request['authentication'])}
-
-# BindResponse ::= [APPLICATION 1] SEQUENCE {
-#                                            COMPONENTS OF LDAPResult,
-#                                            serverSaslCreds    [7] OCTET STRING OPTIONAL }
-
-
-def bind_response_operation(result_code,
-                            matched_dn='',
-                            diagnostic_message='',
-                            referral=None,
-                            server_sasl_credentials=None):
-
-    response = BindResponse()
-    response['resultCode'] = ResultCode(result_code)
-    response['matchedDN'] = LDAPDN(matched_dn)
-    response['diagnosticMessage'] = LDAPString(diagnostic_message)
-    if referral:
-        response['referral'] = Referral(referral)
-
-    if server_sasl_credentials:
-        response['serverSaslCreds'] = ServerSaslCreds(server_sasl_credentials)
-
-    return response
-
-
-def bind_response_to_dict(response):
-    return {'result': int(response['resultCode']),
-            'description': ResultCode().getNamedValues().getName(response['resultCode']),
-            'dn': str(response['matchedDN']),
-            'message': str(response['diagnosticMessage']),
-            'referrals': referrals_to_list(response['referral']),
-            'saslCreds': bytes(response['serverSaslCreds']) if response['serverSaslCreds'] is not None else None}
-
-
-def sicily_bind_response_to_dict(response):
-    return {'result': int(response['resultCode']),
-            'description': ResultCode().getNamedValues().getName(response['resultCode']),
-            'server_creds': bytes(response['matchedDN']),
-            'error_message': str(response['diagnosticMessage'])}
+"""
+"""
+
+# Created on 2013.05.31
+#
+# Author: Giovanni Cannata
+#
+# Copyright 2015 Giovanni Cannata
+#
+# This file is part of ldap3.
+#
+# ldap3 is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# ldap3 is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with ldap3 in the COPYING and COPYING.LESSER files.
+# If not, see <http://www.gnu.org/licenses/>.
+
+from .. import SIMPLE, ANONYMOUS, SASL, RESULT_CODES
+from ..core.exceptions import LDAPPasswordIsMandatoryError, LDAPUnknownAuthenticationMethodError
+from ..protocol.sasl.sasl import validate_simple_password
+from ..protocol.rfc4511 import Version, AuthenticationChoice, Simple, BindRequest, ResultCode, SaslCredentials, BindResponse, \
+    LDAPDN, LDAPString, Referral, ServerSaslCreds, SicilyPackageDiscovery, SicilyNegotiate, SicilyResponse
+from ..protocol.convert import authentication_choice_to_dict, referrals_to_list
+
+# BindRequest ::= [APPLICATION 0] SEQUENCE {
+#                                           version        INTEGER (1 ..  127),
+#                                           name           LDAPDN,
+#                                           authentication AuthenticationChoice }
+
+
+def bind_operation(version,
+                   authentication,
+                   name='',
+                   password=None,
+                   sasl_mechanism=None,
+                   sasl_credentials=None):
+    request = BindRequest()
+    request['version'] = Version(version)
+    if name is None:
+        name = ''
+    request['name'] = name
+    if authentication == SIMPLE:
+        if password:
+            request['authentication'] = AuthenticationChoice().setComponentByName('simple', Simple(validate_simple_password(password)))
+        else:
+            raise LDAPPasswordIsMandatoryError('password is mandatory')
+    elif authentication == SASL:
+        sasl_creds = SaslCredentials()
+        sasl_creds['mechanism'] = sasl_mechanism
+        if sasl_credentials:
+            sasl_creds['credentials'] = sasl_credentials
+        request['authentication'] = AuthenticationChoice().setComponentByName('sasl', sasl_creds)
+    elif authentication == ANONYMOUS:
+        request['name'] = ''
+        request['authentication'] = AuthenticationChoice().setComponentByName('simple', Simple(''))
+    elif authentication == 'SICILY_PACKAGE_DISCOVERY':  # https://msdn.microsoft.com/en-us/library/cc223501.aspx
+        request['name'] = ''
+        request['authentication'] = AuthenticationChoice().setComponentByName('sicilyPackageDiscovery', SicilyPackageDiscovery(''))
+    elif authentication == 'SICILY_NEGOTIATE_NTLM':  # https://msdn.microsoft.com/en-us/library/cc223501.aspx
+        request['name'] = 'NTLM'
+        request['authentication'] = AuthenticationChoice().setComponentByName('sicilyNegotiate', SicilyNegotiate(name.create_negotiate_message()))  # ntlm client in self.name
+    elif authentication == 'SICILY_RESPONSE_NTLM':  # https://msdn.microsoft.com/en-us/library/cc223501.aspx
+        name.parse_challenge_message(password)  # server_creds returned by server in password
+        server_creds = name.create_authenticate_message()
+        if server_creds:
+            request['name'] = ''
+            request['authentication'] = AuthenticationChoice().setComponentByName('sicilyResponse', SicilyResponse(server_creds))
+        else:
+            request = None
+    else:
+        raise LDAPUnknownAuthenticationMethodError('unknown authentication method')
+
+    return request
+
+
+def bind_request_to_dict(request):
+    return {'version': int(request['version']),
+            'name': str(request['name']),
+            'authentication': authentication_choice_to_dict(request['authentication'])}
+
+# BindResponse ::= [APPLICATION 1] SEQUENCE {
+#                                            COMPONENTS OF LDAPResult,
+#                                            serverSaslCreds    [7] OCTET STRING OPTIONAL }
+
+
+def bind_response_operation(result_code,
+                            matched_dn='',
+                            diagnostic_message='',
+                            referral=None,
+                            server_sasl_credentials=None):
+
+    response = BindResponse()
+    response['resultCode'] = ResultCode(result_code)
+    response['matchedDN'] = LDAPDN(matched_dn)
+    response['diagnosticMessage'] = LDAPString(diagnostic_message)
+    if referral:
+        response['referral'] = Referral(referral)
+
+    if server_sasl_credentials:
+        response['serverSaslCreds'] = ServerSaslCreds(server_sasl_credentials)
+
+    return response
+
+
+def bind_response_to_dict(response):
+    return {'result': int(response['resultCode']),
+            'description': ResultCode().getNamedValues().getName(response['resultCode']),
+            'dn': str(response['matchedDN']),
+            'message': str(response['diagnosticMessage']),
+            'referrals': referrals_to_list(response['referral']),
+            'saslCreds': bytes(response['serverSaslCreds']) if response['serverSaslCreds'] is not None else None}
+
+
+def sicily_bind_response_to_dict(response):
+    return {'result': int(response['resultCode']),
+            'description': ResultCode().getNamedValues().getName(response['resultCode']),
+            'server_creds': bytes(response['matchedDN']),
+            'error_message': str(response['diagnosticMessage'])}
+
+
+def bind_response_to_dict_fast(response):
+    response_dict = dict()
+    response_dict['result'] = int(response[0][3])  # resultCode
+    response_dict['description'] = RESULT_CODES[response_dict['result']]
+    response_dict['dn'] = response[1][3].decode('utf-8')  # matchedDN
+    response_dict['message'] = response[2][3].decode('utf-8')  # diagnosticMessage
+    response_dict['referrals'] = None  # referrals
+    response_dict['saslCreds'] = None  # saslCreds
+    for r in response[3:]:
+        if r[2] == 3:  # referrals
+            response_dict['referrals'] = referrals_to_list(r[3])  # referrals
+        else:
+            response_dict['saslCreds'] = bytes(r[3])  # saslCreds
+
+    return response_dict
+
+
+def sicily_bind_response_to_dict_fast(response):
+    response_dict = dict()
+    response_dict['result'] = int(response[0][3])  # resultCode
+    response_dict['description'] = RESULT_CODES[response_dict['result']]
+    response_dict['server_creds'] = bytes(response[1][3])  # server_creds
+    response_dict['error_message'] = response[2][3].decode('utf-8')  # error_message
+
+    return response_dict
diff --git a/ldap3/operation/delete.py b/ldap3/operation/delete.py
index 0cc5c16..c854cb0 100644
--- a/ldap3/operation/delete.py
+++ b/ldap3/operation/delete.py
@@ -1,47 +1,47 @@
-"""
-"""
-
-# Created on 2013.05.31
-#
-# Author: Giovanni Cannata
-#
-# Copyright 2015 Giovanni Cannata
-#
-# This file is part of ldap3.
-#
-# ldap3 is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ldap3 is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with ldap3 in the COPYING and COPYING.LESSER files.
-# If not, see <http://www.gnu.org/licenses/>.
-
-from ..protocol.rfc4511 import DelRequest, LDAPDN, ResultCode
-from ..operation.bind import referrals_to_list
-
-# DelRequest ::= [APPLICATION 10] LDAPDN
-
-
-def delete_operation(dn):
-    request = DelRequest(LDAPDN(dn))
-
-    return request
-
-
-def delete_request_to_dict(request):
-    return {'entry': str(request)}
-
-
-def delete_response_to_dict(response):
-    return {'result': int(response[0]),
-            'description': ResultCode().getNamedValues().getName(response[0]),
-            'dn': str(response['matchedDN']),
-            'message': str(response['diagnosticMessage']),
-            'referrals': referrals_to_list(response['referral'])}
+"""
+"""
+
+# Created on 2013.05.31
+#
+# Author: Giovanni Cannata
+#
+# Copyright 2015 Giovanni Cannata
+#
+# This file is part of ldap3.
+#
+# ldap3 is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# ldap3 is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with ldap3 in the COPYING and COPYING.LESSER files.
+# If not, see <http://www.gnu.org/licenses/>.
+
+from ..protocol.rfc4511 import DelRequest, LDAPDN, ResultCode
+from ..operation.bind import referrals_to_list
+
+# DelRequest ::= [APPLICATION 10] LDAPDN
+
+
+def delete_operation(dn):
+    request = DelRequest(LDAPDN(dn))
+
+    return request
+
+
+def delete_request_to_dict(request):
+    return {'entry': str(request)}
+
+
+def delete_response_to_dict(response):
+    return {'result': int(response[0]),
+            'description': ResultCode().getNamedValues().getName(response[0]),
+            'dn': str(response['matchedDN']),
+            'message': str(response['diagnosticMessage']),
+            'referrals': referrals_to_list(response['referral'])}
diff --git a/ldap3/operation/extended.py b/ldap3/operation/extended.py
index 66f4ec3..48ab654 100644
--- a/ldap3/operation/extended.py
+++ b/ldap3/operation/extended.py
@@ -24,12 +24,12 @@
 # If not, see <http://www.gnu.org/licenses/>.
 
 from pyasn1.type.univ import OctetString
-from pyasn1.codec.ber import encoder
 from pyasn1.type.base import Asn1Item
 
+from .. import RESULT_CODES
 from ..protocol.rfc4511 import ExtendedRequest, RequestName, ResultCode, RequestValue
-from ..protocol.convert import decode_referrals
-
+from ..protocol.convert import decode_referrals, referrals_to_list
+from ..utils.asn1 import encoder
 
 # ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
 #     requestName      [0] LDAPOID,
@@ -68,3 +68,37 @@ def extended_response_to_dict(response):
 def intermediate_response_to_dict(response):
     return {'responseName': str(response['responseName']),
             'responseValue': bytes(response['responseValue']) if response['responseValue'] else bytes()}
+
+
+def extended_response_to_dict_fast(response):
+    response_dict = dict()
+    response_dict['result'] = int(response[0][3])  # resultCode
+    response_dict['description'] = RESULT_CODES[response_dict['result']]
+    response_dict['dn'] = response[1][3].decode('utf-8')  # matchedDN
+    response_dict['message'] = response[2][3].decode('utf-8')  # diagnosticMessage
+    response_dict['referrals'] = None  # referrals
+    response_dict['responseName'] = None  # referrals
+    response_dict['responseValue'] = None  # responseValue
+
+    for r in response[3:]:
+        if r[2] == 3:  # referrals
+            response_dict['referrals'] = referrals_to_list(r[3])  # referrals
+        elif r[2] == 10:  # responseName
+            response_dict['responseName'] = r[3].decode('utf-8')
+            response_dict['responseValue'] = b''  # responseValue could be empty
+
+        else:  # responseValue (11)
+            response_dict['responseValue'] = bytes(r[3])
+
+    return response_dict
+
+
+def intermediate_response_to_dict_fast(response):
+    response_dict = dict()
+    for r in response:
+        if r[2] == 0:  # responseName
+            response_dict['responseName'] = r[3].decode('utf-8')
+        else:  # responseValue (1)
+            response_dict['responseValue'] = bytes(r[3])
+
+    return response_dict
diff --git a/ldap3/operation/search.py b/ldap3/operation/search.py
index 454ae70..8e722d3 100644
--- a/ldap3/operation/search.py
+++ b/ldap3/operation/search.py
@@ -1,487 +1,535 @@
-"""
-"""
-
-# Created on 2013.06.02
-#
-# Author: Giovanni Cannata
-#
-# Copyright 2015 Giovanni Cannata
-#
-# This file is part of ldap3.
-#
-# ldap3 is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published
-# by the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ldap3 is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
... 8287 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-ldap3.git



More information about the Python-modules-commits mailing list