From 8807e7554410fb39e44da1320a372a81f2f2acbf Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 24 Nov 2017 22:10:34 +0100 Subject: [PATCH 1/9] Modules: Remove _ldap._forward and _ldap._reverse These were created only as: forward = {} reverse = {0: None} The only use was the function LDAPconstant, equivalent to: def LDAPconstant(i): return reverse.get(i, i) It looks like these were prepared for a better future, but python-ldap has gone for years or decades without needing to actually use them. Remove both dictionaries and the function. --- Modules/LDAPObject.c | 7 ++++++- Modules/constants.c | 29 +---------------------------- 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/Modules/LDAPObject.c b/Modules/LDAPObject.c index 3e08473..a434986 100644 --- a/Modules/LDAPObject.c +++ b/Modules/LDAPObject.c @@ -1059,7 +1059,12 @@ l_ldap_result4( LDAPObject* self, PyObject *args ) pmsg = LDAPmessage_to_python( self->ldap, msg, add_ctrls, add_intermediates ); - result_str = LDAPconstant( res_type ); + if (res_type == 0) { + result_str = Py_None; + Py_INCREF(Py_None); + } else { + result_str = PyInt_FromLong( res_type ); + } if (pmsg == NULL) { retval = NULL; diff --git a/Modules/constants.c b/Modules/constants.c index 7ed9e41..cd3877c 100644 --- a/Modules/constants.c +++ b/Modules/constants.c @@ -6,35 +6,12 @@ #include "lber.h" #include "ldap.h" -static PyObject* reverse; -static PyObject* forward; - -/* convert an result integer into a Python string */ - -PyObject* -LDAPconstant( int val ) { - PyObject *i = PyInt_FromLong( val ); - PyObject *s = PyObject_GetItem( reverse, i ); - if (s == NULL) { - PyErr_Clear(); - return i; - } - Py_DECREF(i); - return s; -} - /* initialise the module constants */ void LDAPinit_constants( PyObject* d ) { - PyObject *zero, *author,*obj; - - reverse = PyDict_New(); - forward = PyDict_New(); - - PyDict_SetItemString( d, "_reverse", reverse ); - PyDict_SetItemString( d, "_forward", forward ); + PyObject *obj; #define add_int(d, name) \ { \ @@ -91,10 +68,6 @@ LDAPinit_constants( PyObject* d ) /* reversibles */ - zero = PyInt_FromLong( 0 ); - PyDict_SetItem( reverse, zero, Py_None ); - Py_DECREF( zero ); - add_int(d,RES_BIND); add_int(d,RES_SEARCH_ENTRY); add_int(d,RES_SEARCH_RESULT); From 48a924117b3abe53a98c70d6791488b1ebafced0 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 27 Nov 2017 16:16:35 +0100 Subject: [PATCH 2/9] Refactor: Keep information about OpenLDAP constants in Python, generate C Modules/errors.{c,h} are merged into Modules/constants.{c,h} The function LDAPerror_TypeError is moved to common.{c,h}, as it's not concerned with LDAPError. Add a new Python module, ldap.constants, to keep information about all OpenLDAP constants that we know about, including those that aren't available in the OpenLDAP used. Generate a C header file, Modules/constants_generated.h, from this information. (Checking generated files into Git is better avoided, but it's much more straightforward than generating the file from setup.py.) Use proper error checking when adding the constants. --- Lib/ldap/constants.py | 402 +++++++++++++++++++++++++++++ Modules/LDAPObject.c | 1 - Modules/common.c | 12 + Modules/common.h | 2 + Modules/constants.c | 470 +++++++++++----------------------- Modules/constants.h | 9 +- Modules/constants_generated.h | 366 ++++++++++++++++++++++++++ Modules/errors.c | 249 ------------------ Modules/errors.h | 16 -- Modules/functions.c | 2 +- Modules/ldapcontrol.c | 1 - Modules/ldapmodule.c | 7 +- Modules/message.c | 1 - Modules/options.c | 2 +- setup.py | 1 - 15 files changed, 950 insertions(+), 591 deletions(-) create mode 100644 Lib/ldap/constants.py create mode 100644 Modules/constants_generated.h delete mode 100644 Modules/errors.c delete mode 100644 Modules/errors.h diff --git a/Lib/ldap/constants.py b/Lib/ldap/constants.py new file mode 100644 index 0000000..6469a30 --- /dev/null +++ b/Lib/ldap/constants.py @@ -0,0 +1,402 @@ +"""Definitions for constants exported by OpenLDAP + +This file lists all constants we know about, even those that aren't +available in the OpenLDAP version python-ldap is compiled against. + +The information serves two purposes: + +- Generate a C header with the constants +- Provide support for building documentation without compiling python-ldap + +""" + +from __future__ import print_function + +class Constant(object): + """Base class for a definition of an OpenLDAP constant + """ + + def __init__(self, name, optional=False, requirements=(), doc=None): + self.name = name + if optional: + self_requirement = 'defined(LDAP_{})'.format(self.name) + requirements = list(requirements) + [self_requirement] + self.requirements = requirements + self.doc = self.__doc__ = doc + + +class Error(Constant): + """Definition for an OpenLDAP error code + + This is a constant at the C level; in Python errors are provided as + exception classes. + """ + + c_template = 'add_err({self.name});' + + +class Int(Constant): + """Definition for an OpenLDAP integer constant""" + + c_template = 'add_int({self.name});' + + +class TLSInt(Int): + """Definition for a TLS integer constant -- requires HAVE_TLS""" + + def __init__(self, *args, **kwargs): + requrements = list(kwargs.get('requirements', ())) + kwargs['requirements'] = ['HAVE_TLS'] + requrements + super(TLSInt, self).__init__(*args, **kwargs) + + +class Feature(Constant): + """Definition for a feature: 0 or 1 based on a C #ifdef + + """ + + c_template = '\n'.join([ + '', + '#ifdef {self.c_feature}', + 'result = PyModule_AddIntConstant(m, "{self.name}", 1);', + '#else', + 'result = PyModule_AddIntConstant(m, "{self.name}", 0);', + '#endif', + 'check_result();', + '', + ]) + + + def __init__(self, name, c_feature, **kwargs): + super(Feature, self).__init__(name, **kwargs) + self.c_feature = c_feature + + +class Str(Constant): + c_template = 'add_string({self.name});' + + +API_2004 = 'LDAP_API_VERSION >= 2004' + +CONSTANTS = ( + Error('ADMINLIMIT_EXCEEDED'), + Error('AFFECTS_MULTIPLE_DSAS'), + Error('ALIAS_DEREF_PROBLEM'), + Error('ALIAS_PROBLEM'), + Error('ALREADY_EXISTS'), + Error('AUTH_METHOD_NOT_SUPPORTED'), + Error('AUTH_UNKNOWN'), + Error('BUSY'), + Error('CLIENT_LOOP'), + Error('COMPARE_FALSE'), + Error('COMPARE_TRUE'), + Error('CONFIDENTIALITY_REQUIRED'), + Error('CONNECT_ERROR'), + Error('CONSTRAINT_VIOLATION'), + Error('CONTROL_NOT_FOUND'), + Error('DECODING_ERROR'), + Error('ENCODING_ERROR'), + Error('FILTER_ERROR'), + Error('INAPPROPRIATE_AUTH'), + Error('INAPPROPRIATE_MATCHING'), + Error('INSUFFICIENT_ACCESS'), + Error('INVALID_CREDENTIALS'), + Error('INVALID_DN_SYNTAX'), + Error('INVALID_SYNTAX'), + Error('IS_LEAF'), + Error('LOCAL_ERROR'), + Error('LOOP_DETECT'), + Error('MORE_RESULTS_TO_RETURN'), + Error('NAMING_VIOLATION'), + Error('NO_MEMORY'), + Error('NO_OBJECT_CLASS_MODS'), + Error('NO_OBJECT_CLASS_MODS'), + Error('NO_RESULTS_RETURNED'), + Error('NO_SUCH_ATTRIBUTE'), + Error('NO_SUCH_OBJECT'), + Error('NOT_ALLOWED_ON_NONLEAF'), + Error('NOT_ALLOWED_ON_RDN'), + Error('NOT_SUPPORTED'), + Error('OBJECT_CLASS_VIOLATION'), + Error('OPERATIONS_ERROR'), + Error('OTHER'), + Error('PARAM_ERROR'), + Error('PARTIAL_RESULTS'), + Error('PROTOCOL_ERROR'), + Error('REFERRAL'), + Error('REFERRAL_LIMIT_EXCEEDED'), + Error('RESULTS_TOO_LARGE'), + Error('SASL_BIND_IN_PROGRESS'), + Error('SERVER_DOWN'), + Error('SIZELIMIT_EXCEEDED'), + Error('STRONG_AUTH_NOT_SUPPORTED'), + Error('STRONG_AUTH_REQUIRED'), + Error('SUCCESS'), + Error('TIMELIMIT_EXCEEDED'), + Error('TIMEOUT'), + Error('TYPE_OR_VALUE_EXISTS'), + Error('UNAVAILABLE'), + Error('UNAVAILABLE_CRITICAL_EXTENSION'), + Error('UNDEFINED_TYPE'), + Error('UNWILLING_TO_PERFORM'), + Error('USER_CANCELLED'), + Error('VLV_ERROR'), + Error('X_PROXY_AUTHZ_FAILURE'), + + Error('CANCELLED', requirements=['defined(LDAP_API_FEATURE_CANCEL)']), + Error('NO_SUCH_OPERATION', requirements=['defined(LDAP_API_FEATURE_CANCEL)']), + Error('TOO_LATE', requirements=['defined(LDAP_API_FEATURE_CANCEL)']), + Error('CANNOT_CANCEL', requirements=['defined(LDAP_API_FEATURE_CANCEL)']), + + Error('ASSERTION_FAILED', optional=True), + + Error('PROXIED_AUTHORIZATION_DENIED', optional=True), + + # simple constants + + Int('API_VERSION'), + Int('VENDOR_VERSION'), + + Int('PORT'), + Int('VERSION1'), + Int('VERSION2'), + Int('VERSION3'), + Int('VERSION_MIN'), + Int('VERSION'), + Int('VERSION_MAX'), + Int('TAG_MESSAGE'), + Int('TAG_MSGID'), + + Int('REQ_BIND'), + Int('REQ_UNBIND'), + Int('REQ_SEARCH'), + Int('REQ_MODIFY'), + Int('REQ_ADD'), + Int('REQ_DELETE'), + Int('REQ_MODRDN'), + Int('REQ_COMPARE'), + Int('REQ_ABANDON'), + + Int('TAG_LDAPDN'), + Int('TAG_LDAPCRED'), + Int('TAG_CONTROLS'), + Int('TAG_REFERRAL'), + + Int('REQ_EXTENDED'), + Int('TAG_NEWSUPERIOR', requirements=[API_2004]), + Int('TAG_EXOP_REQ_OID', requirements=[API_2004]), + Int('TAG_EXOP_REQ_VALUE', requirements=[API_2004]), + Int('TAG_EXOP_RES_OID', requirements=[API_2004]), + Int('TAG_EXOP_RES_VALUE', requirements=[API_2004]), + Int('TAG_SASL_RES_CREDS', requirements=[API_2004, 'defined(HAVE_SASL)']), + + Int('SASL_AUTOMATIC'), + Int('SASL_INTERACTIVE'), + Int('SASL_QUIET'), + + # reversibles + + Int('RES_BIND'), + Int('RES_SEARCH_ENTRY'), + Int('RES_SEARCH_RESULT'), + Int('RES_MODIFY'), + Int('RES_ADD'), + Int('RES_DELETE'), + Int('RES_MODRDN'), + Int('RES_COMPARE'), + Int('RES_ANY'), + + Int('RES_SEARCH_REFERENCE'), + Int('RES_EXTENDED'), + Int('RES_UNSOLICITED'), + + Int('RES_INTERMEDIATE'), + + # non-reversibles + + Int('AUTH_NONE'), + Int('AUTH_SIMPLE'), + Int('SCOPE_BASE'), + Int('SCOPE_ONELEVEL'), + Int('SCOPE_SUBTREE'), + Int('SCOPE_SUBORDINATE', optional=True), + Int('MOD_ADD'), + Int('MOD_DELETE'), + Int('MOD_REPLACE'), + Int('MOD_INCREMENT'), + Int('MOD_BVALUES'), + + Int('MSG_ONE'), + Int('MSG_ALL'), + Int('MSG_RECEIVED'), + + # (error constants handled above) + + Int('DEREF_NEVER'), + Int('DEREF_SEARCHING'), + Int('DEREF_FINDING'), + Int('DEREF_ALWAYS'), + Int('NO_LIMIT'), + + Int('OPT_API_INFO'), + Int('OPT_DEREF'), + Int('OPT_SIZELIMIT'), + Int('OPT_TIMELIMIT'), + Int('OPT_REFERRALS', optional=True), + Int('OPT_ERROR_NUMBER'), + Int('OPT_RESTART'), + Int('OPT_PROTOCOL_VERSION'), + Int('OPT_SERVER_CONTROLS'), + Int('OPT_CLIENT_CONTROLS'), + Int('OPT_API_FEATURE_INFO'), + Int('OPT_HOST_NAME'), + + Int('OPT_DESC'), + Int('OPT_DIAGNOSTIC_MESSAGE'), + + Int('OPT_ERROR_STRING'), + Int('OPT_MATCHED_DN'), + Int('OPT_DEBUG_LEVEL'), + Int('OPT_TIMEOUT'), + Int('OPT_REFHOPLIMIT'), + Int('OPT_NETWORK_TIMEOUT'), + Int('OPT_URI'), + + Int('OPT_DEFBASE', optional=True), + + TLSInt('OPT_X_TLS', optional=True), + TLSInt('OPT_X_TLS_CTX'), + TLSInt('OPT_X_TLS_CACERTFILE'), + TLSInt('OPT_X_TLS_CACERTDIR'), + TLSInt('OPT_X_TLS_CERTFILE'), + TLSInt('OPT_X_TLS_KEYFILE'), + TLSInt('OPT_X_TLS_REQUIRE_CERT'), + TLSInt('OPT_X_TLS_CIPHER_SUITE'), + TLSInt('OPT_X_TLS_RANDOM_FILE'), + TLSInt('OPT_X_TLS_DHFILE'), + TLSInt('OPT_X_TLS_NEVER'), + TLSInt('OPT_X_TLS_HARD'), + TLSInt('OPT_X_TLS_DEMAND'), + TLSInt('OPT_X_TLS_ALLOW'), + TLSInt('OPT_X_TLS_TRY'), + TLSInt('OPT_X_TLS_PEERCERT', optional=True), + + TLSInt('OPT_X_TLS_VERSION', optional=True), + TLSInt('OPT_X_TLS_CIPHER', optional=True), + TLSInt('OPT_X_TLS_PEERCERT', optional=True), + + # only available if OpenSSL supports it => might cause + # backward compability problems + TLSInt('OPT_X_TLS_CRLCHECK', optional=True), + + TLSInt('OPT_X_TLS_CRLFILE', optional=True), + + TLSInt('OPT_X_TLS_CRL_NONE'), + TLSInt('OPT_X_TLS_CRL_PEER'), + TLSInt('OPT_X_TLS_CRL_ALL'), + TLSInt('OPT_X_TLS_NEWCTX', optional=True), + TLSInt('OPT_X_TLS_PROTOCOL_MIN', optional=True), + TLSInt('OPT_X_TLS_PACKAGE', optional=True), + + Int('OPT_X_SASL_MECH'), + Int('OPT_X_SASL_REALM'), + Int('OPT_X_SASL_AUTHCID'), + Int('OPT_X_SASL_AUTHZID'), + Int('OPT_X_SASL_SSF'), + Int('OPT_X_SASL_SSF_EXTERNAL'), + Int('OPT_X_SASL_SECPROPS'), + Int('OPT_X_SASL_SSF_MIN'), + Int('OPT_X_SASL_SSF_MAX'), + Int('OPT_X_SASL_NOCANON', optional=True), + Int('OPT_X_SASL_USERNAME', optional=True), + Int('OPT_CONNECT_ASYNC', optional=True), + Int('OPT_X_KEEPALIVE_IDLE', optional=True), + Int('OPT_X_KEEPALIVE_PROBES', optional=True), + Int('OPT_X_KEEPALIVE_INTERVAL', optional=True), + + Int('DN_FORMAT_LDAP'), + Int('DN_FORMAT_LDAPV3'), + Int('DN_FORMAT_LDAPV2'), + Int('DN_FORMAT_DCE'), + Int('DN_FORMAT_UFN'), + Int('DN_FORMAT_AD_CANONICAL'), + # Int('DN_FORMAT_LBER'), # for testing only + Int('DN_FORMAT_MASK'), + Int('DN_PRETTY'), + Int('DN_SKIP'), + Int('DN_P_NOLEADTRAILSPACES'), + Int('DN_P_NOSPACEAFTERRDN'), + Int('DN_PEDANTIC'), + + Int('AVA_NULL'), + Int('AVA_STRING'), + Int('AVA_BINARY'), + Int('AVA_NONPRINTABLE'), + + Int('OPT_SUCCESS'), + + # XXX - these should be errors + Int('URL_ERR_BADSCOPE'), + Int('URL_ERR_MEM'), + # Int('LIBLDAP_R'), + + Feature('LIBLDAP_R', 'HAVE_LIBLDAP_R'), + Feature('SASL_AVAIL', 'HAVE_SASL'), + Feature('TLS_AVAIL', 'HAVE_TLS'), + + Str("CONTROL_MANAGEDSAIT"), + Str("CONTROL_PROXY_AUTHZ"), + Str("CONTROL_SUBENTRIES"), + Str("CONTROL_VALUESRETURNFILTER"), + Str("CONTROL_ASSERT"), + Str("CONTROL_PRE_READ"), + Str("CONTROL_POST_READ"), + Str("CONTROL_SORTREQUEST"), + Str("CONTROL_SORTRESPONSE"), + Str("CONTROL_PAGEDRESULTS"), + Str("CONTROL_SYNC"), + Str("CONTROL_SYNC_STATE"), + Str("CONTROL_SYNC_DONE"), + Str("SYNC_INFO"), + Str("CONTROL_PASSWORDPOLICYREQUEST"), + Str("CONTROL_PASSWORDPOLICYRESPONSE"), + Str("CONTROL_RELAX"), +) + + +def print_header(): + """Print the C header file to standard output""" + + print('/*') + print(' * Generated with:') + print(' * python Lib/ldap/constants.py > Modules/constants_generated.h') + print(' *') + print(' * Please do any modifications there, then re-generate this file') + print(' */') + print('') + + current_requirements = [] + + def pop_requirement(): + popped = current_requirements.pop() + print('#endif') + print() + + for definition in CONSTANTS: + while not set(current_requirements).issubset(definition.requirements): + pop_requirement() + + for requirement in definition.requirements: + if requirement not in current_requirements: + current_requirements.append(requirement) + print() + print('#if {}'.format(requirement)) + + print(definition.c_template.format(self=definition)) + + while current_requirements: + pop_requirement() + + +if __name__ == '__main__': + print_header() diff --git a/Modules/LDAPObject.c b/Modules/LDAPObject.c index a434986..f1ad0d4 100644 --- a/Modules/LDAPObject.c +++ b/Modules/LDAPObject.c @@ -5,7 +5,6 @@ #include #include -#include "errors.h" #include "constants.h" #include "LDAPObject.h" #include "ldapcontrol.h" diff --git a/Modules/common.c b/Modules/common.c index 7d3ac8b..0f0cd36 100644 --- a/Modules/common.c +++ b/Modules/common.c @@ -16,3 +16,15 @@ LDAPadd_methods( PyObject* d, PyMethodDef* methods ) Py_DECREF(f); } } + +/* Raise TypeError with custom message and object */ +PyObject* +LDAPerror_TypeError(const char *msg, PyObject *obj) { + PyObject *args = Py_BuildValue("sO", msg, obj); + if (args == NULL) { + return NULL; + } + PyErr_SetObject(PyExc_TypeError, args); + Py_DECREF(args); + return NULL; +} diff --git a/Modules/common.h b/Modules/common.h index 0eea1d9..029f234 100644 --- a/Modules/common.h +++ b/Modules/common.h @@ -24,6 +24,8 @@ #define streq( a, b ) \ ( (*(a)==*(b)) && 0==strcmp(a,b) ) +extern PyObject* LDAPerror_TypeError(const char *, PyObject *); + void LDAPadd_methods( PyObject*d, PyMethodDef*methods ); #define PyNone_Check(o) ((o) == Py_None) diff --git a/Modules/constants.c b/Modules/constants.c index cd3877c..4fd09b8 100644 --- a/Modules/constants.c +++ b/Modules/constants.c @@ -6,346 +6,184 @@ #include "lber.h" #include "ldap.h" -/* initialise the module constants */ - -void -LDAPinit_constants( PyObject* d ) -{ - PyObject *obj; +/* the base exception class */ -#define add_int(d, name) \ - { \ - PyObject *i = PyInt_FromLong(LDAP_##name); \ - PyDict_SetItemString( d, #name, i ); \ - Py_DECREF(i); \ - } +PyObject* +LDAPexception_class; - /* simple constants */ - - add_int(d,API_VERSION); - add_int(d,VENDOR_VERSION); - - add_int(d,PORT); - add_int(d,VERSION1); - add_int(d,VERSION2); - add_int(d,VERSION3); - add_int(d,VERSION_MIN); - add_int(d,VERSION); - add_int(d,VERSION_MAX); - add_int(d,TAG_MESSAGE); - add_int(d,TAG_MSGID); - - add_int(d,REQ_BIND); - add_int(d,REQ_UNBIND); - add_int(d,REQ_SEARCH); - add_int(d,REQ_MODIFY); - add_int(d,REQ_ADD); - add_int(d,REQ_DELETE); - add_int(d,REQ_MODRDN); - add_int(d,REQ_COMPARE); - add_int(d,REQ_ABANDON); - - add_int(d,TAG_LDAPDN); - add_int(d,TAG_LDAPCRED); - add_int(d,TAG_CONTROLS); - add_int(d,TAG_REFERRAL); - - add_int(d,REQ_EXTENDED); -#if LDAP_API_VERSION >= 2004 - add_int(d,TAG_NEWSUPERIOR); - add_int(d,TAG_EXOP_REQ_OID); - add_int(d,TAG_EXOP_REQ_VALUE); - add_int(d,TAG_EXOP_RES_OID); - add_int(d,TAG_EXOP_RES_VALUE); -#ifdef HAVE_SASL - add_int(d,TAG_SASL_RES_CREDS); -#endif -#endif +/* list of exception classes */ - add_int(d,SASL_AUTOMATIC); - add_int(d,SASL_INTERACTIVE); - add_int(d,SASL_QUIET); - - /* reversibles */ - - add_int(d,RES_BIND); - add_int(d,RES_SEARCH_ENTRY); - add_int(d,RES_SEARCH_RESULT); - add_int(d,RES_MODIFY); - add_int(d,RES_ADD); - add_int(d,RES_DELETE); - add_int(d,RES_MODRDN); - add_int(d,RES_COMPARE); - add_int(d,RES_ANY); - - add_int(d,RES_SEARCH_REFERENCE); - add_int(d,RES_EXTENDED); - add_int(d,RES_UNSOLICITED); - - add_int(d,RES_INTERMEDIATE); - - /* non-reversibles */ - - add_int(d,AUTH_NONE); - add_int(d,AUTH_SIMPLE); - add_int(d,SCOPE_BASE); - add_int(d,SCOPE_ONELEVEL); - add_int(d,SCOPE_SUBTREE); -#ifdef LDAP_SCOPE_SUBORDINATE - add_int(d,SCOPE_SUBORDINATE); -#endif - add_int(d,MOD_ADD); - add_int(d,MOD_DELETE); - add_int(d,MOD_REPLACE); - add_int(d,MOD_INCREMENT); - add_int(d,MOD_BVALUES); - - add_int(d,MSG_ONE); - add_int(d,MSG_ALL); - add_int(d,MSG_RECEIVED); - - /* (errors.c contains the error constants) */ - - add_int(d,DEREF_NEVER); - add_int(d,DEREF_SEARCHING); - add_int(d,DEREF_FINDING); - add_int(d,DEREF_ALWAYS); - add_int(d,NO_LIMIT); - - add_int(d,OPT_API_INFO); - add_int(d,OPT_DEREF); - add_int(d,OPT_SIZELIMIT); - add_int(d,OPT_TIMELIMIT); -#ifdef LDAP_OPT_REFERRALS - add_int(d,OPT_REFERRALS); -#endif - add_int(d,OPT_ERROR_NUMBER); - add_int(d,OPT_RESTART); - add_int(d,OPT_PROTOCOL_VERSION); - add_int(d,OPT_SERVER_CONTROLS); - add_int(d,OPT_CLIENT_CONTROLS); - add_int(d,OPT_API_FEATURE_INFO); - add_int(d,OPT_HOST_NAME); - - add_int(d,OPT_DESC); - add_int(d,OPT_DIAGNOSTIC_MESSAGE); - - add_int(d,OPT_ERROR_STRING); - add_int(d,OPT_MATCHED_DN); - add_int(d,OPT_DEBUG_LEVEL); - add_int(d,OPT_TIMEOUT); - add_int(d,OPT_REFHOPLIMIT); - add_int(d,OPT_NETWORK_TIMEOUT); - add_int(d,OPT_URI); -#ifdef LDAP_OPT_DEFBASE - add_int(d,OPT_DEFBASE); -#endif -#ifdef HAVE_TLS - add_int(d,OPT_X_TLS); -#ifdef LDAP_OPT_X_TLS_NEWCTX - add_int(d,OPT_X_TLS_CTX); -#endif - add_int(d,OPT_X_TLS_CACERTFILE); - add_int(d,OPT_X_TLS_CACERTDIR); - add_int(d,OPT_X_TLS_CERTFILE); - add_int(d,OPT_X_TLS_KEYFILE); - add_int(d,OPT_X_TLS_REQUIRE_CERT); - add_int(d,OPT_X_TLS_CIPHER_SUITE); - add_int(d,OPT_X_TLS_RANDOM_FILE); - add_int(d,OPT_X_TLS_DHFILE); - add_int(d,OPT_X_TLS_NEVER); - add_int(d,OPT_X_TLS_HARD); - add_int(d,OPT_X_TLS_DEMAND); - add_int(d,OPT_X_TLS_ALLOW); - add_int(d,OPT_X_TLS_TRY); -#ifdef LDAP_OPT_X_TLS_PEERCERT - add_int(d,OPT_X_TLS_PEERCERT); -#endif -#ifdef LDAP_OPT_X_TLS_VERSION - add_int(d,OPT_X_TLS_VERSION); -#endif -#ifdef LDAP_OPT_X_TLS_CIPHER - add_int(d,OPT_X_TLS_CIPHER); -#endif -#ifdef LDAP_OPT_X_TLS_PEERCERT - add_int(d,OPT_X_TLS_PEERCERT); -#endif -#ifdef LDAP_OPT_X_TLS_CRLCHECK - /* only available if OpenSSL supports it => might cause backward compability problems */ - add_int(d,OPT_X_TLS_CRLCHECK); -#ifdef LDAP_OPT_X_TLS_CRLFILE - add_int(d,OPT_X_TLS_CRLFILE); -#endif - add_int(d,OPT_X_TLS_CRL_NONE); - add_int(d,OPT_X_TLS_CRL_PEER); - add_int(d,OPT_X_TLS_CRL_ALL); -#endif -#ifdef LDAP_OPT_X_TLS_NEWCTX - add_int(d,OPT_X_TLS_NEWCTX); -#endif -#ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN - add_int(d,OPT_X_TLS_PROTOCOL_MIN); -#endif -#ifdef LDAP_OPT_X_TLS_PACKAGE - add_int(d,OPT_X_TLS_PACKAGE); -#endif -#endif - add_int(d,OPT_X_SASL_MECH); - add_int(d,OPT_X_SASL_REALM); - add_int(d,OPT_X_SASL_AUTHCID); - add_int(d,OPT_X_SASL_AUTHZID); - add_int(d,OPT_X_SASL_SSF); - add_int(d,OPT_X_SASL_SSF_EXTERNAL); - add_int(d,OPT_X_SASL_SECPROPS); - add_int(d,OPT_X_SASL_SSF_MIN); - add_int(d,OPT_X_SASL_SSF_MAX); -#ifdef LDAP_OPT_X_SASL_NOCANON - add_int(d,OPT_X_SASL_NOCANON); -#endif -#ifdef LDAP_OPT_X_SASL_USERNAME - add_int(d,OPT_X_SASL_USERNAME); -#endif -#ifdef LDAP_OPT_CONNECT_ASYNC - add_int(d,OPT_CONNECT_ASYNC); -#endif -#ifdef LDAP_OPT_X_KEEPALIVE_IDLE - add_int(d,OPT_X_KEEPALIVE_IDLE); -#endif -#ifdef LDAP_OPT_X_KEEPALIVE_PROBES - add_int(d,OPT_X_KEEPALIVE_PROBES); -#endif -#ifdef LDAP_OPT_X_KEEPALIVE_INTERVAL - add_int(d,OPT_X_KEEPALIVE_INTERVAL); -#endif +#define LDAP_ERROR_MIN LDAP_REFERRAL_LIMIT_EXCEEDED - add_int(d,DN_FORMAT_LDAP); - add_int(d,DN_FORMAT_LDAPV3); - add_int(d,DN_FORMAT_LDAPV2); - add_int(d,DN_FORMAT_DCE); - add_int(d,DN_FORMAT_UFN); - add_int(d,DN_FORMAT_AD_CANONICAL); - /* add_int(d,DN_FORMAT_LBER); */ /* "for testing only" */ - add_int(d,DN_FORMAT_MASK); - add_int(d,DN_PRETTY); - add_int(d,DN_SKIP); - add_int(d,DN_P_NOLEADTRAILSPACES); - add_int(d,DN_P_NOSPACEAFTERRDN); - add_int(d,DN_PEDANTIC); - - add_int(d,AVA_NULL); - add_int(d,AVA_STRING); - add_int(d,AVA_BINARY); - add_int(d,AVA_NONPRINTABLE); - - /*add_int(d,OPT_ON);*/ - obj = PyInt_FromLong(1); - PyDict_SetItemString( d, "OPT_ON", obj ); - Py_DECREF(obj); - /*add_int(d,OPT_OFF);*/ - obj = PyInt_FromLong(0); - PyDict_SetItemString( d, "OPT_OFF", obj ); - Py_DECREF(obj); - - add_int(d,OPT_SUCCESS); - - /* XXX - these belong in errors.c */ - - add_int(d,URL_ERR_BADSCOPE); - add_int(d,URL_ERR_MEM); - - /* add_int(d,LIBLDAP_R); */ -#ifdef HAVE_LIBLDAP_R - obj = PyInt_FromLong(1); +#ifdef LDAP_PROXIED_AUTHORIZATION_DENIED + #define LDAP_ERROR_MAX LDAP_PROXIED_AUTHORIZATION_DENIED #else - obj = PyInt_FromLong(0); + #ifdef LDAP_ASSERTION_FAILED + #define LDAP_ERROR_MAX LDAP_ASSERTION_FAILED + #else + #define LDAP_ERROR_MAX LDAP_OTHER + #endif #endif - PyDict_SetItemString( d, "LIBLDAP_R", obj ); - Py_DECREF(obj); - /* add_int(d,SASL); */ -#ifdef HAVE_SASL - obj = PyInt_FromLong(1); -#else - obj = PyInt_FromLong(0); -#endif - PyDict_SetItemString( d, "SASL_AVAIL", obj ); - Py_DECREF(obj); +#define LDAP_ERROR_OFFSET -LDAP_ERROR_MIN + +static PyObject* errobjects[ LDAP_ERROR_MAX-LDAP_ERROR_MIN+1 ]; - /* add_int(d,TLS); */ -#ifdef HAVE_TLS - obj = PyInt_FromLong(1); -#else - obj = PyInt_FromLong(0); -#endif - PyDict_SetItemString( d, "TLS_AVAIL", obj ); - Py_DECREF(obj); - obj = PyUnicode_FromString(LDAP_CONTROL_MANAGEDSAIT); - PyDict_SetItemString( d, "CONTROL_MANAGEDSAIT", obj ); - Py_DECREF(obj); +/* Convert a bare LDAP error number into an exception */ +PyObject* +LDAPerr(int errnum) +{ + if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX) { + PyErr_SetNone(errobjects[errnum+LDAP_ERROR_OFFSET]); + } else { + PyObject *args = Py_BuildValue("{s:i}", "errnum", errnum); + if (args == NULL) + return NULL; + PyErr_SetObject(LDAPexception_class, args); + Py_DECREF(args); + } + return NULL; +} - obj = PyUnicode_FromString(LDAP_CONTROL_PROXY_AUTHZ); - PyDict_SetItemString( d, "CONTROL_PROXY_AUTHZ", obj ); - Py_DECREF(obj); +/* Convert an LDAP error into an informative python exception */ +PyObject* +LDAPerror( LDAP *l, char *msg ) +{ + if (l == NULL) { + PyErr_SetFromErrno( LDAPexception_class ); + return NULL; + } + else { + int myerrno, errnum, opt_errnum; + PyObject *errobj; + PyObject *info; + PyObject *str; + PyObject *pyerrno; + + /* at first save errno for later use before it gets overwritten by another call */ + myerrno = errno; + + char *matched, *error; + + opt_errnum = ldap_get_option(l, LDAP_OPT_ERROR_NUMBER, &errnum); + if (opt_errnum != LDAP_OPT_SUCCESS) + errnum = opt_errnum; + + if (errnum == LDAP_NO_MEMORY) + return PyErr_NoMemory(); + + if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX) + errobj = errobjects[errnum+LDAP_ERROR_OFFSET]; + else + errobj = LDAPexception_class; + + info = PyDict_New(); + if (info == NULL) + return NULL; + + str = PyUnicode_FromString(ldap_err2string(errnum)); + if (str) + PyDict_SetItemString( info, "desc", str ); + Py_XDECREF(str); + + if (myerrno != 0) { + pyerrno = PyInt_FromLong(myerrno); + if (pyerrno) + PyDict_SetItemString( info, "errno", pyerrno ); + Py_XDECREF(pyerrno); + } + + if (ldap_get_option(l, LDAP_OPT_MATCHED_DN, &matched) >= 0 + && matched != NULL) { + if (*matched != '\0') { + str = PyUnicode_FromString(matched); + if (str) + PyDict_SetItemString( info, "matched", str ); + Py_XDECREF(str); + } + ldap_memfree(matched); + } + + if (errnum == LDAP_REFERRAL) { + str = PyUnicode_FromString(msg); + if (str) + PyDict_SetItemString( info, "info", str ); + Py_XDECREF(str); + } else if (ldap_get_option(l, LDAP_OPT_ERROR_STRING, &error) >= 0) { + if (error != NULL && *error != '\0') { + str = PyUnicode_FromString(error); + if (str) + PyDict_SetItemString( info, "info", str ); + Py_XDECREF(str); + } + ldap_memfree(error); + } + PyErr_SetObject( errobj, info ); + Py_DECREF(info); + return NULL; + } +} - obj = PyUnicode_FromString(LDAP_CONTROL_SUBENTRIES); - PyDict_SetItemString( d, "CONTROL_SUBENTRIES", obj ); - Py_DECREF(obj); +/* initialise the module constants */ - obj = PyUnicode_FromString(LDAP_CONTROL_VALUESRETURNFILTER); - PyDict_SetItemString( d, "CONTROL_VALUESRETURNFILTER", obj ); - Py_DECREF(obj); +int +LDAPinit_constants( PyObject* m ) +{ + PyObject *exc; + int result; - obj = PyUnicode_FromString(LDAP_CONTROL_ASSERT); - PyDict_SetItemString( d, "CONTROL_ASSERT", obj ); - Py_DECREF(obj); +#define check_result() { \ + if (result != 0) return -1; \ +} - obj = PyUnicode_FromString(LDAP_CONTROL_PRE_READ); - PyDict_SetItemString( d, "CONTROL_PRE_READ", obj ); - Py_DECREF(obj); + /* simple constants */ - obj = PyUnicode_FromString(LDAP_CONTROL_POST_READ); - PyDict_SetItemString( d, "CONTROL_POST_READ", obj ); - Py_DECREF(obj); + result = PyModule_AddIntConstant(m, "OPT_ON", 1); + check_result(); + result = PyModule_AddIntConstant(m, "OPT_OFF", 0); + check_result(); - obj = PyUnicode_FromString(LDAP_CONTROL_SORTREQUEST); - PyDict_SetItemString( d, "CONTROL_SORTREQUEST", obj ); - Py_DECREF(obj); + /* exceptions */ - obj = PyUnicode_FromString(LDAP_CONTROL_SORTRESPONSE); - PyDict_SetItemString( d, "CONTROL_SORTRESPONSE", obj ); - Py_DECREF(obj); + LDAPexception_class = PyErr_NewException("ldap.LDAPError", NULL, NULL); + if (LDAPexception_class == NULL) { + return -1; + } - obj = PyUnicode_FromString(LDAP_CONTROL_PAGEDRESULTS); - PyDict_SetItemString( d, "CONTROL_PAGEDRESULTS", obj ); - Py_DECREF(obj); + result = PyModule_AddObject(m, "LDAPError", LDAPexception_class); + check_result(); + Py_INCREF(LDAPexception_class); - obj = PyUnicode_FromString(LDAP_CONTROL_SYNC); - PyDict_SetItemString( d, "CONTROL_SYNC", obj ); - Py_DECREF(obj); + /* XXX - backward compatibility with pre-1.8 */ + result = PyModule_AddObject(m, "error", LDAPexception_class); + check_result(); + Py_INCREF(LDAPexception_class); - obj = PyUnicode_FromString(LDAP_CONTROL_SYNC_STATE); - PyDict_SetItemString( d, "CONTROL_SYNC_STATE", obj ); - Py_DECREF(obj); + /* Generated constants -- see Lib/ldap/constants.py */ - obj = PyUnicode_FromString(LDAP_CONTROL_SYNC_DONE); - PyDict_SetItemString( d, "CONTROL_SYNC_DONE", obj ); - Py_DECREF(obj); +#define seterrobj2(n, o) \ + PyModule_AddObject(m, #n, (errobjects[LDAP_##n+LDAP_ERROR_OFFSET] = o)) - obj = PyUnicode_FromString(LDAP_SYNC_INFO); - PyDict_SetItemString( d, "SYNC_INFO", obj ); - Py_DECREF(obj); +#define add_err(n) { \ + exc = PyErr_NewException("ldap." #n, LDAPexception_class, NULL); \ + if (exc == NULL) return -1; \ + result = seterrobj2(n, exc); \ + check_result(); \ + Py_INCREF(exc); \ +} - obj = PyUnicode_FromString(LDAP_CONTROL_PASSWORDPOLICYREQUEST); - PyDict_SetItemString( d, "CONTROL_PASSWORDPOLICYREQUEST", obj ); - Py_DECREF(obj); +#define add_int(n) { \ + result = PyModule_AddIntConstant(m, #n, LDAP_##n); \ + check_result(); \ +} - obj = PyUnicode_FromString(LDAP_CONTROL_PASSWORDPOLICYRESPONSE); - PyDict_SetItemString( d, "CONTROL_PASSWORDPOLICYRESPONSE", obj ); - Py_DECREF(obj); +#define add_string(n) { \ + result = PyModule_AddStringConstant(m, #n, LDAP_##n); \ + check_result(); \ +} - obj = PyUnicode_FromString(LDAP_CONTROL_RELAX); - PyDict_SetItemString( d, "CONTROL_RELAX", obj ); - Py_DECREF(obj); +#include "constants_generated.h" + return 0; } diff --git a/Modules/constants.h b/Modules/constants.h index eb76612..4056f90 100644 --- a/Modules/constants.h +++ b/Modules/constants.h @@ -4,9 +4,16 @@ #define __h_constants_ #include "common.h" -extern void LDAPinit_constants( PyObject* d ); +#include "lber.h" +#include "ldap.h" + +extern int LDAPinit_constants( PyObject* m ); extern PyObject* LDAPconstant( int ); +extern PyObject* LDAPexception_class; +extern PyObject* LDAPerror( LDAP*, char*msg ); +PyObject* LDAPerr(int errnum); + #ifndef LDAP_CONTROL_PAGE_OID #define LDAP_CONTROL_PAGE_OID "1.2.840.113556.1.4.319" #endif /* !LDAP_CONTROL_PAGE_OID */ diff --git a/Modules/constants_generated.h b/Modules/constants_generated.h new file mode 100644 index 0000000..27addc9 --- /dev/null +++ b/Modules/constants_generated.h @@ -0,0 +1,366 @@ +/* + * Generated with: + * python Lib/ldap/constants.py > Modules/constants_generated.h + * + * Please do any modifications there, then re-generate this file + */ + +add_err(ADMINLIMIT_EXCEEDED); +add_err(AFFECTS_MULTIPLE_DSAS); +add_err(ALIAS_DEREF_PROBLEM); +add_err(ALIAS_PROBLEM); +add_err(ALREADY_EXISTS); +add_err(AUTH_METHOD_NOT_SUPPORTED); +add_err(AUTH_UNKNOWN); +add_err(BUSY); +add_err(CLIENT_LOOP); +add_err(COMPARE_FALSE); +add_err(COMPARE_TRUE); +add_err(CONFIDENTIALITY_REQUIRED); +add_err(CONNECT_ERROR); +add_err(CONSTRAINT_VIOLATION); +add_err(CONTROL_NOT_FOUND); +add_err(DECODING_ERROR); +add_err(ENCODING_ERROR); +add_err(FILTER_ERROR); +add_err(INAPPROPRIATE_AUTH); +add_err(INAPPROPRIATE_MATCHING); +add_err(INSUFFICIENT_ACCESS); +add_err(INVALID_CREDENTIALS); +add_err(INVALID_DN_SYNTAX); +add_err(INVALID_SYNTAX); +add_err(IS_LEAF); +add_err(LOCAL_ERROR); +add_err(LOOP_DETECT); +add_err(MORE_RESULTS_TO_RETURN); +add_err(NAMING_VIOLATION); +add_err(NO_MEMORY); +add_err(NO_OBJECT_CLASS_MODS); +add_err(NO_OBJECT_CLASS_MODS); +add_err(NO_RESULTS_RETURNED); +add_err(NO_SUCH_ATTRIBUTE); +add_err(NO_SUCH_OBJECT); +add_err(NOT_ALLOWED_ON_NONLEAF); +add_err(NOT_ALLOWED_ON_RDN); +add_err(NOT_SUPPORTED); +add_err(OBJECT_CLASS_VIOLATION); +add_err(OPERATIONS_ERROR); +add_err(OTHER); +add_err(PARAM_ERROR); +add_err(PARTIAL_RESULTS); +add_err(PROTOCOL_ERROR); +add_err(REFERRAL); +add_err(REFERRAL_LIMIT_EXCEEDED); +add_err(RESULTS_TOO_LARGE); +add_err(SASL_BIND_IN_PROGRESS); +add_err(SERVER_DOWN); +add_err(SIZELIMIT_EXCEEDED); +add_err(STRONG_AUTH_NOT_SUPPORTED); +add_err(STRONG_AUTH_REQUIRED); +add_err(SUCCESS); +add_err(TIMELIMIT_EXCEEDED); +add_err(TIMEOUT); +add_err(TYPE_OR_VALUE_EXISTS); +add_err(UNAVAILABLE); +add_err(UNAVAILABLE_CRITICAL_EXTENSION); +add_err(UNDEFINED_TYPE); +add_err(UNWILLING_TO_PERFORM); +add_err(USER_CANCELLED); +add_err(VLV_ERROR); +add_err(X_PROXY_AUTHZ_FAILURE); + +#if defined(LDAP_API_FEATURE_CANCEL) +add_err(CANCELLED); +add_err(NO_SUCH_OPERATION); +add_err(TOO_LATE); +add_err(CANNOT_CANCEL); +#endif + + +#if defined(LDAP_ASSERTION_FAILED) +add_err(ASSERTION_FAILED); +#endif + + +#if defined(LDAP_PROXIED_AUTHORIZATION_DENIED) +add_err(PROXIED_AUTHORIZATION_DENIED); +#endif + +add_int(API_VERSION); +add_int(VENDOR_VERSION); +add_int(PORT); +add_int(VERSION1); +add_int(VERSION2); +add_int(VERSION3); +add_int(VERSION_MIN); +add_int(VERSION); +add_int(VERSION_MAX); +add_int(TAG_MESSAGE); +add_int(TAG_MSGID); +add_int(REQ_BIND); +add_int(REQ_UNBIND); +add_int(REQ_SEARCH); +add_int(REQ_MODIFY); +add_int(REQ_ADD); +add_int(REQ_DELETE); +add_int(REQ_MODRDN); +add_int(REQ_COMPARE); +add_int(REQ_ABANDON); +add_int(TAG_LDAPDN); +add_int(TAG_LDAPCRED); +add_int(TAG_CONTROLS); +add_int(TAG_REFERRAL); +add_int(REQ_EXTENDED); + +#if LDAP_API_VERSION >= 2004 +add_int(TAG_NEWSUPERIOR); +add_int(TAG_EXOP_REQ_OID); +add_int(TAG_EXOP_REQ_VALUE); +add_int(TAG_EXOP_RES_OID); +add_int(TAG_EXOP_RES_VALUE); + +#if defined(HAVE_SASL) +add_int(TAG_SASL_RES_CREDS); +#endif + +#endif + +add_int(SASL_AUTOMATIC); +add_int(SASL_INTERACTIVE); +add_int(SASL_QUIET); +add_int(RES_BIND); +add_int(RES_SEARCH_ENTRY); +add_int(RES_SEARCH_RESULT); +add_int(RES_MODIFY); +add_int(RES_ADD); +add_int(RES_DELETE); +add_int(RES_MODRDN); +add_int(RES_COMPARE); +add_int(RES_ANY); +add_int(RES_SEARCH_REFERENCE); +add_int(RES_EXTENDED); +add_int(RES_UNSOLICITED); +add_int(RES_INTERMEDIATE); +add_int(AUTH_NONE); +add_int(AUTH_SIMPLE); +add_int(SCOPE_BASE); +add_int(SCOPE_ONELEVEL); +add_int(SCOPE_SUBTREE); + +#if defined(LDAP_SCOPE_SUBORDINATE) +add_int(SCOPE_SUBORDINATE); +#endif + +add_int(MOD_ADD); +add_int(MOD_DELETE); +add_int(MOD_REPLACE); +add_int(MOD_INCREMENT); +add_int(MOD_BVALUES); +add_int(MSG_ONE); +add_int(MSG_ALL); +add_int(MSG_RECEIVED); +add_int(DEREF_NEVER); +add_int(DEREF_SEARCHING); +add_int(DEREF_FINDING); +add_int(DEREF_ALWAYS); +add_int(NO_LIMIT); +add_int(OPT_API_INFO); +add_int(OPT_DEREF); +add_int(OPT_SIZELIMIT); +add_int(OPT_TIMELIMIT); + +#if defined(LDAP_OPT_REFERRALS) +add_int(OPT_REFERRALS); +#endif + +add_int(OPT_ERROR_NUMBER); +add_int(OPT_RESTART); +add_int(OPT_PROTOCOL_VERSION); +add_int(OPT_SERVER_CONTROLS); +add_int(OPT_CLIENT_CONTROLS); +add_int(OPT_API_FEATURE_INFO); +add_int(OPT_HOST_NAME); +add_int(OPT_DESC); +add_int(OPT_DIAGNOSTIC_MESSAGE); +add_int(OPT_ERROR_STRING); +add_int(OPT_MATCHED_DN); +add_int(OPT_DEBUG_LEVEL); +add_int(OPT_TIMEOUT); +add_int(OPT_REFHOPLIMIT); +add_int(OPT_NETWORK_TIMEOUT); +add_int(OPT_URI); + +#if defined(LDAP_OPT_DEFBASE) +add_int(OPT_DEFBASE); +#endif + + +#if HAVE_TLS + +#if defined(LDAP_OPT_X_TLS) +add_int(OPT_X_TLS); +#endif + +add_int(OPT_X_TLS_CTX); +add_int(OPT_X_TLS_CACERTFILE); +add_int(OPT_X_TLS_CACERTDIR); +add_int(OPT_X_TLS_CERTFILE); +add_int(OPT_X_TLS_KEYFILE); +add_int(OPT_X_TLS_REQUIRE_CERT); +add_int(OPT_X_TLS_CIPHER_SUITE); +add_int(OPT_X_TLS_RANDOM_FILE); +add_int(OPT_X_TLS_DHFILE); +add_int(OPT_X_TLS_NEVER); +add_int(OPT_X_TLS_HARD); +add_int(OPT_X_TLS_DEMAND); +add_int(OPT_X_TLS_ALLOW); +add_int(OPT_X_TLS_TRY); + +#if defined(LDAP_OPT_X_TLS_PEERCERT) +add_int(OPT_X_TLS_PEERCERT); +#endif + + +#if defined(LDAP_OPT_X_TLS_VERSION) +add_int(OPT_X_TLS_VERSION); +#endif + + +#if defined(LDAP_OPT_X_TLS_CIPHER) +add_int(OPT_X_TLS_CIPHER); +#endif + + +#if defined(LDAP_OPT_X_TLS_PEERCERT) +add_int(OPT_X_TLS_PEERCERT); +#endif + + +#if defined(LDAP_OPT_X_TLS_CRLCHECK) +add_int(OPT_X_TLS_CRLCHECK); +#endif + + +#if defined(LDAP_OPT_X_TLS_CRLFILE) +add_int(OPT_X_TLS_CRLFILE); +#endif + +add_int(OPT_X_TLS_CRL_NONE); +add_int(OPT_X_TLS_CRL_PEER); +add_int(OPT_X_TLS_CRL_ALL); + +#if defined(LDAP_OPT_X_TLS_NEWCTX) +add_int(OPT_X_TLS_NEWCTX); +#endif + + +#if defined(LDAP_OPT_X_TLS_PROTOCOL_MIN) +add_int(OPT_X_TLS_PROTOCOL_MIN); +#endif + + +#if defined(LDAP_OPT_X_TLS_PACKAGE) +add_int(OPT_X_TLS_PACKAGE); +#endif + +#endif + +add_int(OPT_X_SASL_MECH); +add_int(OPT_X_SASL_REALM); +add_int(OPT_X_SASL_AUTHCID); +add_int(OPT_X_SASL_AUTHZID); +add_int(OPT_X_SASL_SSF); +add_int(OPT_X_SASL_SSF_EXTERNAL); +add_int(OPT_X_SASL_SECPROPS); +add_int(OPT_X_SASL_SSF_MIN); +add_int(OPT_X_SASL_SSF_MAX); + +#if defined(LDAP_OPT_X_SASL_NOCANON) +add_int(OPT_X_SASL_NOCANON); +#endif + + +#if defined(LDAP_OPT_X_SASL_USERNAME) +add_int(OPT_X_SASL_USERNAME); +#endif + + +#if defined(LDAP_OPT_CONNECT_ASYNC) +add_int(OPT_CONNECT_ASYNC); +#endif + + +#if defined(LDAP_OPT_X_KEEPALIVE_IDLE) +add_int(OPT_X_KEEPALIVE_IDLE); +#endif + + +#if defined(LDAP_OPT_X_KEEPALIVE_PROBES) +add_int(OPT_X_KEEPALIVE_PROBES); +#endif + + +#if defined(LDAP_OPT_X_KEEPALIVE_INTERVAL) +add_int(OPT_X_KEEPALIVE_INTERVAL); +#endif + +add_int(DN_FORMAT_LDAP); +add_int(DN_FORMAT_LDAPV3); +add_int(DN_FORMAT_LDAPV2); +add_int(DN_FORMAT_DCE); +add_int(DN_FORMAT_UFN); +add_int(DN_FORMAT_AD_CANONICAL); +add_int(DN_FORMAT_MASK); +add_int(DN_PRETTY); +add_int(DN_SKIP); +add_int(DN_P_NOLEADTRAILSPACES); +add_int(DN_P_NOSPACEAFTERRDN); +add_int(DN_PEDANTIC); +add_int(AVA_NULL); +add_int(AVA_STRING); +add_int(AVA_BINARY); +add_int(AVA_NONPRINTABLE); +add_int(OPT_SUCCESS); +add_int(URL_ERR_BADSCOPE); +add_int(URL_ERR_MEM); + +#ifdef HAVE_LIBLDAP_R +result = PyModule_AddIntConstant(m, "LIBLDAP_R", 1); +#else +result = PyModule_AddIntConstant(m, "LIBLDAP_R", 0); +#endif +check_result(); + + +#ifdef HAVE_SASL +result = PyModule_AddIntConstant(m, "SASL_AVAIL", 1); +#else +result = PyModule_AddIntConstant(m, "SASL_AVAIL", 0); +#endif +check_result(); + + +#ifdef HAVE_TLS +result = PyModule_AddIntConstant(m, "TLS_AVAIL", 1); +#else +result = PyModule_AddIntConstant(m, "TLS_AVAIL", 0); +#endif +check_result(); + +add_string(CONTROL_MANAGEDSAIT); +add_string(CONTROL_PROXY_AUTHZ); +add_string(CONTROL_SUBENTRIES); +add_string(CONTROL_VALUESRETURNFILTER); +add_string(CONTROL_ASSERT); +add_string(CONTROL_PRE_READ); +add_string(CONTROL_POST_READ); +add_string(CONTROL_SORTREQUEST); +add_string(CONTROL_SORTRESPONSE); +add_string(CONTROL_PAGEDRESULTS); +add_string(CONTROL_SYNC); +add_string(CONTROL_SYNC_STATE); +add_string(CONTROL_SYNC_DONE); +add_string(SYNC_INFO); +add_string(CONTROL_PASSWORDPOLICYREQUEST); +add_string(CONTROL_PASSWORDPOLICYRESPONSE); +add_string(CONTROL_RELAX); diff --git a/Modules/errors.c b/Modules/errors.c deleted file mode 100644 index 3c4da78..0000000 --- a/Modules/errors.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * errors that arise from ldap use - * Most errors become their own exception - * See https://www.python-ldap.org/ for details. */ - -#include "common.h" -#include "errors.h" -#include -#include - -/* the base exception class */ - -PyObject* -LDAPexception_class; - -/* list of error objects */ - -#define LDAP_ERROR_MIN LDAP_REFERRAL_LIMIT_EXCEEDED - -#ifdef LDAP_PROXIED_AUTHORIZATION_DENIED - #define LDAP_ERROR_MAX LDAP_PROXIED_AUTHORIZATION_DENIED -#else - #ifdef LDAP_ASSERTION_FAILED - #define LDAP_ERROR_MAX LDAP_ASSERTION_FAILED - #else - #define LDAP_ERROR_MAX LDAP_OTHER - #endif -#endif - -#define LDAP_ERROR_OFFSET -LDAP_ERROR_MIN - -static PyObject* errobjects[ LDAP_ERROR_MAX-LDAP_ERROR_MIN+1 ]; - - -/* Convert a bare LDAP error number into an exception */ -PyObject* -LDAPerr(int errnum) -{ - if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX) { - PyErr_SetNone(errobjects[errnum+LDAP_ERROR_OFFSET]); - } else { - PyObject *args = Py_BuildValue("{s:i}", "errnum", errnum); - if (args == NULL) - return NULL; - PyErr_SetObject(LDAPexception_class, args); - Py_DECREF(args); - } - return NULL; -} - -/* Convert an LDAP error into an informative python exception */ -PyObject* -LDAPerror( LDAP *l, char *msg ) -{ - if (l == NULL) { - PyErr_SetFromErrno( LDAPexception_class ); - return NULL; - } - else { - int myerrno, errnum, opt_errnum; - PyObject *errobj; - PyObject *info; - PyObject *str; - PyObject *pyerrno; - - /* at first save errno for later use before it gets overwritten by another call */ - myerrno = errno; - - char *matched, *error; - - opt_errnum = ldap_get_option(l, LDAP_OPT_ERROR_NUMBER, &errnum); - if (opt_errnum != LDAP_OPT_SUCCESS) - errnum = opt_errnum; - - if (errnum == LDAP_NO_MEMORY) - return PyErr_NoMemory(); - - if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX) - errobj = errobjects[errnum+LDAP_ERROR_OFFSET]; - else - errobj = LDAPexception_class; - - info = PyDict_New(); - if (info == NULL) - return NULL; - - str = PyUnicode_FromString(ldap_err2string(errnum)); - if (str) - PyDict_SetItemString( info, "desc", str ); - Py_XDECREF(str); - - if (myerrno != 0) { - pyerrno = PyInt_FromLong(myerrno); - if (pyerrno) - PyDict_SetItemString( info, "errno", pyerrno ); - Py_XDECREF(pyerrno); - } - - if (ldap_get_option(l, LDAP_OPT_MATCHED_DN, &matched) >= 0 - && matched != NULL) { - if (*matched != '\0') { - str = PyUnicode_FromString(matched); - if (str) - PyDict_SetItemString( info, "matched", str ); - Py_XDECREF(str); - } - ldap_memfree(matched); - } - - if (errnum == LDAP_REFERRAL) { - str = PyUnicode_FromString(msg); - if (str) - PyDict_SetItemString( info, "info", str ); - Py_XDECREF(str); - } else if (ldap_get_option(l, LDAP_OPT_ERROR_STRING, &error) >= 0) { - if (error != NULL && *error != '\0') { - str = PyUnicode_FromString(error); - if (str) - PyDict_SetItemString( info, "info", str ); - Py_XDECREF(str); - } - ldap_memfree(error); - } - PyErr_SetObject( errobj, info ); - Py_DECREF(info); - return NULL; - } -} - -/* Raise TypeError with custom message and object */ -PyObject* -LDAPerror_TypeError(const char *msg, PyObject *obj) { - PyObject *args = Py_BuildValue("sO", msg, obj); - if (args == NULL) { - return NULL; - } - PyErr_SetObject(PyExc_TypeError, args); - Py_DECREF(args); - return NULL; -} - - -/* initialisation */ - -void -LDAPinit_errors( PyObject*d ) { - - /* create the base exception class */ - LDAPexception_class = PyErr_NewException("ldap.LDAPError", - NULL, - NULL); - PyDict_SetItemString( d, "LDAPError", LDAPexception_class ); - - /* XXX - backward compatibility with pre-1.8 */ - PyDict_SetItemString( d, "error", LDAPexception_class ); - - /* create each LDAP error object */ - -# define seterrobj2(n,o) \ - PyDict_SetItemString( d, #n, (errobjects[LDAP_##n+LDAP_ERROR_OFFSET] = o) ) - - -# define seterrobj(n) { \ - PyObject *e = PyErr_NewException("ldap." #n, \ - LDAPexception_class, NULL); \ - seterrobj2(n, e); \ - Py_INCREF(e); \ - } - - seterrobj(ADMINLIMIT_EXCEEDED); - seterrobj(AFFECTS_MULTIPLE_DSAS); - seterrobj(ALIAS_DEREF_PROBLEM); - seterrobj(ALIAS_PROBLEM); - seterrobj(ALREADY_EXISTS); - seterrobj(AUTH_METHOD_NOT_SUPPORTED); - seterrobj(AUTH_UNKNOWN); - seterrobj(BUSY); - seterrobj(CLIENT_LOOP); - seterrobj(COMPARE_FALSE); - seterrobj(COMPARE_TRUE); - seterrobj(CONFIDENTIALITY_REQUIRED); - seterrobj(CONNECT_ERROR); - seterrobj(CONSTRAINT_VIOLATION); - seterrobj(CONTROL_NOT_FOUND); - seterrobj(DECODING_ERROR); - seterrobj(ENCODING_ERROR); - seterrobj(FILTER_ERROR); - seterrobj(INAPPROPRIATE_AUTH); - seterrobj(INAPPROPRIATE_MATCHING); - seterrobj(INSUFFICIENT_ACCESS); - seterrobj(INVALID_CREDENTIALS); - seterrobj(INVALID_DN_SYNTAX); - seterrobj(INVALID_SYNTAX); - seterrobj(IS_LEAF); - seterrobj(LOCAL_ERROR); - seterrobj(LOOP_DETECT); - seterrobj(MORE_RESULTS_TO_RETURN); - seterrobj(NAMING_VIOLATION); - seterrobj(NO_MEMORY); - seterrobj(NO_OBJECT_CLASS_MODS); - seterrobj(NO_OBJECT_CLASS_MODS); - seterrobj(NO_RESULTS_RETURNED); - seterrobj(NO_SUCH_ATTRIBUTE); - seterrobj(NO_SUCH_OBJECT); - seterrobj(NOT_ALLOWED_ON_NONLEAF); - seterrobj(NOT_ALLOWED_ON_RDN); - seterrobj(NOT_SUPPORTED); - seterrobj(OBJECT_CLASS_VIOLATION); - seterrobj(OPERATIONS_ERROR); - seterrobj(OTHER); - seterrobj(PARAM_ERROR); - seterrobj(PARTIAL_RESULTS); - seterrobj(PROTOCOL_ERROR); - seterrobj(REFERRAL); - seterrobj(REFERRAL_LIMIT_EXCEEDED); - seterrobj(RESULTS_TOO_LARGE); - seterrobj(SASL_BIND_IN_PROGRESS); - seterrobj(SERVER_DOWN); - seterrobj(SIZELIMIT_EXCEEDED); - seterrobj(STRONG_AUTH_NOT_SUPPORTED); - seterrobj(STRONG_AUTH_REQUIRED); - seterrobj(SUCCESS); - seterrobj(TIMELIMIT_EXCEEDED); - seterrobj(TIMEOUT); - seterrobj(TYPE_OR_VALUE_EXISTS); - seterrobj(UNAVAILABLE); - seterrobj(UNAVAILABLE_CRITICAL_EXTENSION); - seterrobj(UNDEFINED_TYPE); - seterrobj(UNWILLING_TO_PERFORM); - seterrobj(USER_CANCELLED); - seterrobj(VLV_ERROR); - seterrobj(X_PROXY_AUTHZ_FAILURE); - -#ifdef LDAP_API_FEATURE_CANCEL - seterrobj(CANCELLED); - seterrobj(NO_SUCH_OPERATION); - seterrobj(TOO_LATE); - seterrobj(CANNOT_CANCEL); -#endif - -#ifdef LDAP_ASSERTION_FAILED - seterrobj(ASSERTION_FAILED); -#endif - -#ifdef LDAP_PROXIED_AUTHORIZATION_DENIED - seterrobj(PROXIED_AUTHORIZATION_DENIED); -#endif - -} diff --git a/Modules/errors.h b/Modules/errors.h deleted file mode 100644 index 5bd3576..0000000 --- a/Modules/errors.h +++ /dev/null @@ -1,16 +0,0 @@ -/* See https://www.python-ldap.org/ for details. */ - -#ifndef __h_errors_ -#define __h_errors_ - -#include "common.h" -#include "lber.h" -#include "ldap.h" - -extern PyObject* LDAPexception_class; -extern PyObject* LDAPerror( LDAP*, char*msg ); -extern PyObject* LDAPerror_TypeError(const char *, PyObject *); -extern void LDAPinit_errors( PyObject* ); -PyObject* LDAPerr(int errnum); - -#endif /* __h_errors */ diff --git a/Modules/functions.c b/Modules/functions.c index ffb6765..a31be05 100644 --- a/Modules/functions.c +++ b/Modules/functions.c @@ -4,7 +4,7 @@ #include "functions.h" #include "LDAPObject.h" #include "berval.h" -#include "errors.h" +#include "constants.h" #include "options.h" /* ldap_initialize */ diff --git a/Modules/ldapcontrol.c b/Modules/ldapcontrol.c index 7e31f72..3f5b2c4 100644 --- a/Modules/ldapcontrol.c +++ b/Modules/ldapcontrol.c @@ -4,7 +4,6 @@ #include "LDAPObject.h" #include "ldapcontrol.h" #include "berval.h" -#include "errors.h" #include "lber.h" diff --git a/Modules/ldapmodule.c b/Modules/ldapmodule.c index 46c9c8a..ec3a264 100644 --- a/Modules/ldapmodule.c +++ b/Modules/ldapmodule.c @@ -2,7 +2,6 @@ #include "common.h" #include "constants.h" -#include "errors.h" #include "functions.h" #include "ldapcontrol.h" @@ -67,8 +66,10 @@ PyObject* init_ldap_module() init_pkginfo(m); - LDAPinit_constants(d); - LDAPinit_errors(d); + if (LDAPinit_constants(m) == -1) { + return NULL; + } + LDAPinit_functions(d); LDAPinit_control(d); diff --git a/Modules/message.c b/Modules/message.c index 1a289db..babbd25 100644 --- a/Modules/message.c +++ b/Modules/message.c @@ -3,7 +3,6 @@ #include "common.h" #include "message.h" #include "berval.h" -#include "errors.h" #include "ldapcontrol.h" #include "constants.h" diff --git a/Modules/options.c b/Modules/options.c index 7cf996b..ac1eab6 100644 --- a/Modules/options.c +++ b/Modules/options.c @@ -1,7 +1,7 @@ /* See https://www.python-ldap.org/ for details. */ #include "common.h" -#include "errors.h" +#include "constants.h" #include "LDAPObject.h" #include "ldapcontrol.h" #include "options.h" diff --git a/setup.py b/setup.py index 2ac63ec..9694fa5 100644 --- a/setup.py +++ b/setup.py @@ -136,7 +136,6 @@ class OpenLDAP2: 'Modules/ldapcontrol.c', 'Modules/common.c', 'Modules/constants.c', - 'Modules/errors.c', 'Modules/functions.c', 'Modules/ldapmodule.c', 'Modules/message.c', From 4587df60a331b99d695efd2470edf1853b28d8b2 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 24 Nov 2017 22:34:39 +0100 Subject: [PATCH 3/9] Doc: Convert conf.py to Unix line endings --- Doc/conf.py | 266 ++++++++++++++++++++++++++-------------------------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py index 9c322de..d40e822 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -1,133 +1,133 @@ -# -*- coding: utf-8 -*- -# -# python-ldap documentation build configuration file, created by -# sphinx-quickstart on Sat Mar 29 15:08:17 2008. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# The contents of this file are pickled, so don't put values in the namespace -# that aren't pickleable (module imports are okay, they're removed automatically). -# -# All configuration values have a default value; values that are commented out -# serve to show the default value. - -import sys - -# If your extensions are in another directory, add it here. -#sys.path.append('some/directory') - -# General configuration -# --------------------- - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['.templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General substitutions. -project = 'python-ldap' -copyright = '2008-2017, python-ldap project team' - -# The default replacements for |version| and |release|, also used in various -# other places throughout the built documents. -# -# The short X.Y version. -version = '2.5' -# The full version, including alpha/beta/rc tags. -release = '2.5.2.0' - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - - -# Options for HTML output -# ----------------------- - -# The style sheet to use for HTML and HTML Help pages. A file of that name -# must exist either in Sphinx' static/ path, or in one of the custom paths -# given in html_static_path. -html_style = 'pyramid.css' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['/usr/lib/python2.7/site-packages/sphinx/themes/pyramid/static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Content template for the index page. -#html_index = '' - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -html_use_modindex = True - -# If true, the reST sources are included in the HTML build as _sources/. -#html_copy_source = True - -# Output file base name for HTML help builder. -htmlhelp_basename = 'python-ldap-doc' - - -# Options for LaTeX output -# ------------------------ - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, document class [howto/manual]). -latex_documents = [('index', 'python-ldap.tex', 'python-ldap Documentation', - 'python-ldap project', 'manual')] - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -latex_use_modindex = True +# -*- coding: utf-8 -*- +# +# python-ldap documentation build configuration file, created by +# sphinx-quickstart on Sat Mar 29 15:08:17 2008. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed automatically). +# +# All configuration values have a default value; values that are commented out +# serve to show the default value. + +import sys + +# If your extensions are in another directory, add it here. +#sys.path.append('some/directory') + +# General configuration +# --------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['.templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General substitutions. +project = 'python-ldap' +copyright = '2008-2017, python-ldap project team' + +# The default replacements for |version| and |release|, also used in various +# other places throughout the built documents. +# +# The short X.Y version. +version = '2.5' +# The full version, including alpha/beta/rc tags. +release = '2.5.2.0' + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +html_style = 'pyramid.css' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['/usr/lib/python2.7/site-packages/sphinx/themes/pyramid/static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Content template for the index page. +#html_index = '' + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +html_use_modindex = True + +# If true, the reST sources are included in the HTML build as _sources/. +#html_copy_source = True + +# Output file base name for HTML help builder. +htmlhelp_basename = 'python-ldap-doc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +latex_documents = [('index', 'python-ldap.tex', 'python-ldap Documentation', + 'python-ldap project', 'manual')] + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +latex_use_modindex = True From 1bb84f641c16ab41a158c414df7d78fb88b1edcd Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 24 Nov 2017 22:39:20 +0100 Subject: [PATCH 4/9] Doc: Add .gitignore --- Doc/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 Doc/.gitignore diff --git a/Doc/.gitignore b/Doc/.gitignore new file mode 100644 index 0000000..a485625 --- /dev/null +++ b/Doc/.gitignore @@ -0,0 +1 @@ +/_build From e34bd6b1ee50372918b1201c2e40f7df65064e72 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 24 Nov 2017 23:07:51 +0100 Subject: [PATCH 5/9] Doc: Allow building documentation even without a compiled extension This involves a fake _ldap module and carefully bootstrapping ldap.__init__ (which imports * from _ldap). --- Doc/conf.py | 9 ++++++- Doc/fake_ldap_module_for_documentation.py | 30 +++++++++++++++++++++++ Lib/ldap/constants.py | 3 +++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 Doc/fake_ldap_module_for_documentation.py diff --git a/Doc/conf.py b/Doc/conf.py index d40e822..d81bf29 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -12,9 +12,16 @@ # serve to show the default value. import sys +import os # If your extensions are in another directory, add it here. -#sys.path.append('some/directory') +_doc_dir = os.path.dirname(__file__) +sys.path.append(_doc_dir) +sys.path.append(os.path.join(_doc_dir, '../Lib/')) +sys.path.insert(0, os.path.join(_doc_dir, '../Lib/ldap')) + +# Import fake `_ldap` module +import fake_ldap_module_for_documentation # General configuration # --------------------- diff --git a/Doc/fake_ldap_module_for_documentation.py b/Doc/fake_ldap_module_for_documentation.py new file mode 100644 index 0000000..3080781 --- /dev/null +++ b/Doc/fake_ldap_module_for_documentation.py @@ -0,0 +1,30 @@ +""" +A module that mocks `_ldap` for the purposes of generating documentation + +This module provides placeholders for the contents of `_ldap`, making it +possible to generate documentation even _ldap is not compiled. +It should also make the documentation independent of which features are +available in the system OpenLDAP library. + +The overly long module name will show up in AttributeError messages, +hinting that this is not the actual _ldap. + +See https://www.python-ldap.org/ for details. +""" + +import sys + +# Cause `import _ldap` to import this module instead of the actual `_ldap`. +sys.modules['_ldap'] = sys.modules[__name__] + +from constants import CONSTANTS +from pkginfo import __version__ + +for constant in CONSTANTS: + globals()[constant.name] = constant + +def get_option(num): + pass + +class LDAPError: + pass diff --git a/Lib/ldap/constants.py b/Lib/ldap/constants.py index 6469a30..aafa265 100644 --- a/Lib/ldap/constants.py +++ b/Lib/ldap/constants.py @@ -10,6 +10,9 @@ """ +# This module cannot import anything from ldap. +# When building documentation, it is used to initialize ldap.__init__. + from __future__ import print_function class Constant(object): From 849f36652ddbc1b336aa0b299297d11143c00a98 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 24 Nov 2017 23:28:12 +0100 Subject: [PATCH 6/9] Doc: Get the version from the Python module --- Doc/conf.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py index d81bf29..43de80a 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -23,6 +23,9 @@ # Import fake `_ldap` module import fake_ldap_module_for_documentation +# Now ldap can be used normally +from ldap import __version__ + # General configuration # --------------------- @@ -47,9 +50,9 @@ # other places throughout the built documents. # # The short X.Y version. -version = '2.5' +version = '.'.join(__version__.split('.')[:2]) # The full version, including alpha/beta/rc tags. -release = '2.5.2.0' +release = __version__ # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: From b096d31f1556435d6f6ab615cd597ec5d0ae4e74 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 24 Nov 2017 23:29:08 +0100 Subject: [PATCH 7/9] Doc: Use the default style The default should be pretty enough. --- Doc/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/conf.py b/Doc/conf.py index 43de80a..63fc24e 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -84,12 +84,12 @@ # The style sheet to use for HTML and HTML Help pages. A file of that name # must exist either in Sphinx' static/ path, or in one of the custom paths # given in html_static_path. -html_style = 'pyramid.css' +#html_style = 'pyramid.css' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['/usr/lib/python2.7/site-packages/sphinx/themes/pyramid/static'] +#html_static_path = ['/usr/lib/python2.7/site-packages/sphinx/themes/pyramid/static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. From a3675965499f3a939f7fd6848b2506d2e4ffdd46 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 27 Nov 2017 15:33:45 +0100 Subject: [PATCH 8/9] Modules: Write out error checking in constants.c --- Lib/ldap/constants.py | 5 ++--- Modules/constants.c | 30 ++++++++---------------------- Modules/constants_generated.h | 15 ++++++--------- 3 files changed, 16 insertions(+), 34 deletions(-) diff --git a/Lib/ldap/constants.py b/Lib/ldap/constants.py index aafa265..c5ac6c1 100644 --- a/Lib/ldap/constants.py +++ b/Lib/ldap/constants.py @@ -61,11 +61,10 @@ class Feature(Constant): c_template = '\n'.join([ '', '#ifdef {self.c_feature}', - 'result = PyModule_AddIntConstant(m, "{self.name}", 1);', + 'if (PyModule_AddIntConstant(m, "{self.name}", 1) != 0) return -1;', '#else', - 'result = PyModule_AddIntConstant(m, "{self.name}", 0);', + 'if (PyModule_AddIntConstant(m, "{self.name}", 0) != 0) return -1;', '#endif', - 'check_result();', '', ]) diff --git a/Modules/constants.c b/Modules/constants.c index 4fd09b8..8906581 100644 --- a/Modules/constants.c +++ b/Modules/constants.c @@ -131,18 +131,11 @@ int LDAPinit_constants( PyObject* m ) { PyObject *exc; - int result; - -#define check_result() { \ - if (result != 0) return -1; \ -} /* simple constants */ - result = PyModule_AddIntConstant(m, "OPT_ON", 1); - check_result(); - result = PyModule_AddIntConstant(m, "OPT_OFF", 0); - check_result(); + if (PyModule_AddIntConstant(m, "OPT_ON", 1) != 0) return -1; + if (PyModule_AddIntConstant(m, "OPT_OFF", 0) != 0) return -1; /* exceptions */ @@ -151,36 +144,29 @@ LDAPinit_constants( PyObject* m ) return -1; } - result = PyModule_AddObject(m, "LDAPError", LDAPexception_class); - check_result(); + if (PyModule_AddObject(m, "LDAPError", LDAPexception_class) != 0) return -1; Py_INCREF(LDAPexception_class); /* XXX - backward compatibility with pre-1.8 */ - result = PyModule_AddObject(m, "error", LDAPexception_class); - check_result(); + if (PyModule_AddObject(m, "error", LDAPexception_class) != 0) return -1; Py_INCREF(LDAPexception_class); /* Generated constants -- see Lib/ldap/constants.py */ -#define seterrobj2(n, o) \ - PyModule_AddObject(m, #n, (errobjects[LDAP_##n+LDAP_ERROR_OFFSET] = o)) - #define add_err(n) { \ exc = PyErr_NewException("ldap." #n, LDAPexception_class, NULL); \ if (exc == NULL) return -1; \ - result = seterrobj2(n, exc); \ - check_result(); \ + errobjects[LDAP_##n+LDAP_ERROR_OFFSET] = exc; \ + if (PyModule_AddObject(m, #n, exc) != 0) return -1; \ Py_INCREF(exc); \ } #define add_int(n) { \ - result = PyModule_AddIntConstant(m, #n, LDAP_##n); \ - check_result(); \ + if (PyModule_AddIntConstant(m, #n, LDAP_##n) != 0) return -1; \ } #define add_string(n) { \ - result = PyModule_AddStringConstant(m, #n, LDAP_##n); \ - check_result(); \ + if (PyModule_AddStringConstant(m, #n, LDAP_##n) != 0) return -1; \ } #include "constants_generated.h" diff --git a/Modules/constants_generated.h b/Modules/constants_generated.h index 27addc9..083ba16 100644 --- a/Modules/constants_generated.h +++ b/Modules/constants_generated.h @@ -325,27 +325,24 @@ add_int(URL_ERR_BADSCOPE); add_int(URL_ERR_MEM); #ifdef HAVE_LIBLDAP_R -result = PyModule_AddIntConstant(m, "LIBLDAP_R", 1); +if (PyModule_AddIntConstant(m, "LIBLDAP_R", 1) != 0) return -1; #else -result = PyModule_AddIntConstant(m, "LIBLDAP_R", 0); +if (PyModule_AddIntConstant(m, "LIBLDAP_R", 0) != 0) return -1; #endif -check_result(); #ifdef HAVE_SASL -result = PyModule_AddIntConstant(m, "SASL_AVAIL", 1); +if (PyModule_AddIntConstant(m, "SASL_AVAIL", 1) != 0) return -1; #else -result = PyModule_AddIntConstant(m, "SASL_AVAIL", 0); +if (PyModule_AddIntConstant(m, "SASL_AVAIL", 0) != 0) return -1; #endif -check_result(); #ifdef HAVE_TLS -result = PyModule_AddIntConstant(m, "TLS_AVAIL", 1); +if (PyModule_AddIntConstant(m, "TLS_AVAIL", 1) != 0) return -1; #else -result = PyModule_AddIntConstant(m, "TLS_AVAIL", 0); +if (PyModule_AddIntConstant(m, "TLS_AVAIL", 0) != 0) return -1; #endif -check_result(); add_string(CONTROL_MANAGEDSAIT); add_string(CONTROL_PROXY_AUTHZ); From 5cbbc49898aa26045a6bd7c2c12b3585fc6517cf Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 27 Nov 2017 15:38:15 +0100 Subject: [PATCH 9/9] Modules: Wrap macros in constants.c in `do {...} while (0)` --- Modules/constants.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/constants.c b/Modules/constants.c index 8906581..f0028a0 100644 --- a/Modules/constants.c +++ b/Modules/constants.c @@ -153,21 +153,21 @@ LDAPinit_constants( PyObject* m ) /* Generated constants -- see Lib/ldap/constants.py */ -#define add_err(n) { \ +#define add_err(n) do { \ exc = PyErr_NewException("ldap." #n, LDAPexception_class, NULL); \ if (exc == NULL) return -1; \ errobjects[LDAP_##n+LDAP_ERROR_OFFSET] = exc; \ if (PyModule_AddObject(m, #n, exc) != 0) return -1; \ Py_INCREF(exc); \ -} +} while (0) -#define add_int(n) { \ +#define add_int(n) do { \ if (PyModule_AddIntConstant(m, #n, LDAP_##n) != 0) return -1; \ -} +} while (0) -#define add_string(n) { \ +#define add_string(n) do { \ if (PyModule_AddStringConstant(m, #n, LDAP_##n) != 0) return -1; \ -} +} while (0) #include "constants_generated.h"