Skip to content

Commit a8b2748

Browse files
committed
Support None for set_option(OPT_NETWORK_TIMEOUT)
The setter for network timeout and timeout options now support None as value. None is mapped to infinity. Closes: python-ldap#95 Signed-off-by: Christian Heimes <cheimes@redhat.com>
1 parent 084ffe0 commit a8b2748

File tree

3 files changed

+73
-27
lines changed

3 files changed

+73
-27
lines changed

Doc/reference/ldap.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ following option identifiers are defined as constants:
157157
.. py:data:: OPT_NETWORK_TIMEOUT
158158
159159
.. versionchanged:: 3.0
160-
A timeout of ``-1`` resets timeout to infinity.
160+
A timeout of ``-1`` or ``None`` resets timeout to infinity.
161161

162162
.. py:data:: OPT_PROTOCOL_VERSION
163163
@@ -184,7 +184,7 @@ following option identifiers are defined as constants:
184184
.. py:data:: OPT_TIMEOUT
185185
186186
.. versionchanged:: 3.0
187-
A timeout of ``-1`` resets timeout to infinity.
187+
A timeout of ``-1`` or ``None`` resets timeout to infinity.
188188

189189
.. py:data:: OPT_URI
190190
@@ -1125,6 +1125,8 @@ These attributes are mutable unless described as read-only.
11251125
This option is mapped to option constant :py:const:`OPT_NETWORK_TIMEOUT`
11261126
and used in the underlying OpenLDAP client lib.
11271127

1128+
.. versionchanged:: 3.0.0
1129+
A timeout of ``-1`` or ``None`` resets timeout to infinity.
11281130

11291131
.. py:attribute:: LDAPObject.protocol_version -> int
11301132

Modules/options.c

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -136,26 +136,42 @@ LDAP_set_option(LDAPObject *self, int option, PyObject *value)
136136
break;
137137
case LDAP_OPT_TIMEOUT:
138138
case LDAP_OPT_NETWORK_TIMEOUT:
139-
/* Float valued timeval options */
140-
if (!PyArg_Parse(value, "d:set_option", &doubleval))
141-
return 0;
142-
if (doubleval >= 0) {
143-
set_timeval_from_double( &tv, doubleval );
144-
ptr = &tv;
145-
} else if (doubleval == -1) {
146-
/* -1 is infinity timeout */
147-
tv.tv_sec = -1;
148-
tv.tv_usec = 0;
149-
ptr = &tv;
150-
} else {
139+
/* Float valued timeval options, 'd' also handles int/long */
140+
if (!PyArg_Parse(value, "d:set_option", &doubleval)) {
141+
/* clear error and try again with None */
142+
PyErr_Clear();
143+
if (PyNone_Check(value)) {
144+
/* None is mapped to infinity timeout */
145+
doubleval = -1;
146+
}
147+
else {
151148
PyErr_Format(
152-
PyExc_ValueError,
153-
"timeout must be >= 0 or -1 for infinity, got %d",
154-
option
149+
PyExc_TypeError,
150+
"A float or None is expected for timeout, got %.100s",
151+
Py_TYPE(value)->tp_name
155152
);
156153
return 0;
157154
}
158-
break;
155+
}
156+
157+
if (doubleval >= 0) {
158+
set_timeval_from_double( &tv, doubleval );
159+
ptr = &tv;
160+
} else if (doubleval == -1) {
161+
/* -1 is infinity timeout */
162+
tv.tv_sec = -1;
163+
tv.tv_usec = 0;
164+
ptr = &tv;
165+
} else {
166+
PyErr_Format(
167+
PyExc_ValueError,
168+
"timeout must be >= 0 or -1/None for infinity, got %d",
169+
option
170+
);
171+
return 0;
172+
}
173+
break;
174+
159175
case LDAP_OPT_SERVER_CONTROLS:
160176
case LDAP_OPT_CLIENT_CONTROLS:
161177
if (!LDAPControls_from_object(value, &controls))

Tests/t_ldap_options.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@ def get_option(self, option):
3838
def set_option(self, option, value):
3939
raise NotImplementedError()
4040

41-
def _check_option(self, option, value, expected=SENTINEL,
42-
nonevalue=None):
41+
def _check_option(self, option, value, expected=SENTINEL):
4342
old = self.get_option(option)
4443
try:
4544
self.set_option(option, value)
@@ -49,10 +48,7 @@ def _check_option(self, option, value, expected=SENTINEL,
4948
else:
5049
self.assertEqual(new, expected)
5150
finally:
52-
self.set_option(
53-
option,
54-
old if old is not None else nonevalue
55-
)
51+
self.set_option(option, old)
5652
self.assertEqual(self.get_option(option), old)
5753

5854
def test_invalid(self):
@@ -62,12 +58,20 @@ def test_invalid(self):
6258
self.set_option(-1, '')
6359

6460
def _test_timeout(self, option):
65-
self._check_option(option, 10.5, nonevalue=-1)
66-
self._check_option(option, 0, nonevalue=-1)
61+
self._check_option(option, 10.5)
62+
self._check_option(option, 0)
6763
with self.assertRaises(ValueError):
68-
self._check_option(option, -5, nonevalue=-1)
64+
self._check_option(option, -5)
6965
with self.assertRaises(TypeError):
7066
self.set_option(option, object)
67+
old = self.get_option(option)
68+
try:
69+
self.set_option(option, None)
70+
self.assertEqual(self.get_option(option), None)
71+
self.set_option(option, -1)
72+
self.assertEqual(self.get_option(option), None)
73+
finally:
74+
self.set_option(option, old)
7175

7276
def test_timeout(self):
7377
self._test_timeout(ldap.OPT_TIMEOUT)
@@ -149,6 +153,30 @@ def get_option(self, option):
149153
def set_option(self, option, value):
150154
return self.conn.set_option(option, value)
151155

156+
def test_network_timeout_attribute(self):
157+
option = ldap.OPT_NETWORK_TIMEOUT
158+
old = self.get_option(option)
159+
try:
160+
self.assertEqual(self.conn.network_timeout, old)
161+
162+
self.conn.network_timeout = 5
163+
self.assertEqual(self.conn.network_timeout, 5)
164+
self.assertEqual(self.get_option(option), 5)
165+
166+
self.conn.network_timeout = -1
167+
self.assertEqual(self.conn.network_timeout, None)
168+
self.assertEqual(self.get_option(option), None)
169+
170+
self.conn.network_timeout = 10.5
171+
self.assertEqual(self.conn.network_timeout, 10.5)
172+
self.assertEqual(self.get_option(option), 10.5)
173+
174+
self.conn.network_timeout = None
175+
self.assertEqual(self.conn.network_timeout, None)
176+
self.assertEqual(self.get_option(option), None)
177+
finally:
178+
self.set_option(option, old)
179+
152180
# test is failing with:
153181
# pyasn1.error.SubstrateUnderrunError: Short octet stream on tag decoding
154182
@unittest.expectedFailure

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

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

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


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy