Skip to content

Commit 4d3cd7d

Browse files
authored
Merge pull request python-ldap#104 – Support None for set_option(OPT_NETWORK_TIMEOUT)
python-ldap#104
2 parents 31abc2e + 12f193e commit 4d3cd7d

File tree

3 files changed

+79
-29
lines changed

3 files changed

+79
-29
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
@@ -1137,6 +1137,8 @@ These attributes are mutable unless described as read-only.
11371137
This option is mapped to option constant :py:const:`OPT_NETWORK_TIMEOUT`
11381138
and used in the underlying OpenLDAP client lib.
11391139

1140+
.. versionchanged:: 3.0.0
1141+
A timeout of ``-1`` or ``None`` resets timeout to infinity.
11401142

11411143
.. py:attribute:: LDAPObject.protocol_version -> int
11421144

Modules/options.c

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -136,26 +136,44 @@ 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 {
151-
PyErr_Format(
152-
PyExc_ValueError,
153-
"timeout must be >= 0 or -1 for infinity, got %d",
154-
option
155-
);
139+
/* Float valued timeval options */
140+
if (value == Py_None) {
141+
/* None is mapped to infinity timeout */
142+
doubleval = -1;
143+
} else {
144+
/* 'd' handles int/long */
145+
if (!PyArg_Parse(value, "d:set_option", &doubleval)) {
146+
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
147+
/* TypeError: mention either float or None is expected */
148+
PyErr_Clear();
149+
PyErr_Format(
150+
PyExc_TypeError,
151+
"A float or None is expected for timeout, got %.100s",
152+
Py_TYPE(value)->tp_name
153+
);
154+
}
156155
return 0;
157156
}
158-
break;
157+
}
158+
159+
if (doubleval >= 0) {
160+
set_timeval_from_double( &tv, doubleval );
161+
ptr = &tv;
162+
} else if (doubleval == -1) {
163+
/* -1 is infinity timeout */
164+
tv.tv_sec = -1;
165+
tv.tv_usec = 0;
166+
ptr = &tv;
167+
} else {
168+
PyErr_Format(
169+
PyExc_ValueError,
170+
"timeout must be >= 0 or -1/None for infinity, got %d",
171+
option
172+
);
173+
return 0;
174+
}
175+
break;
176+
159177
case LDAP_OPT_SERVER_CONTROLS:
160178
case LDAP_OPT_CLIENT_CONTROLS:
161179
if (!LDAPControls_from_object(value, &controls))

Tests/t_ldap_options.py

Lines changed: 39 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,22 @@ 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+
with self.assertRaises(OverflowError):
68+
self._check_option(option, 10**1000)
69+
old = self.get_option(option)
70+
try:
71+
self.set_option(option, None)
72+
self.assertEqual(self.get_option(option), None)
73+
self.set_option(option, -1)
74+
self.assertEqual(self.get_option(option), None)
75+
finally:
76+
self.set_option(option, old)
7177

7278
def test_timeout(self):
7379
self._test_timeout(ldap.OPT_TIMEOUT)
@@ -149,6 +155,30 @@ def get_option(self, option):
149155
def set_option(self, option, value):
150156
return self.conn.set_option(option, value)
151157

158+
def test_network_timeout_attribute(self):
159+
option = ldap.OPT_NETWORK_TIMEOUT
160+
old = self.get_option(option)
161+
try:
162+
self.assertEqual(self.conn.network_timeout, old)
163+
164+
self.conn.network_timeout = 5
165+
self.assertEqual(self.conn.network_timeout, 5)
166+
self.assertEqual(self.get_option(option), 5)
167+
168+
self.conn.network_timeout = -1
169+
self.assertEqual(self.conn.network_timeout, None)
170+
self.assertEqual(self.get_option(option), None)
171+
172+
self.conn.network_timeout = 10.5
173+
self.assertEqual(self.conn.network_timeout, 10.5)
174+
self.assertEqual(self.get_option(option), 10.5)
175+
176+
self.conn.network_timeout = None
177+
self.assertEqual(self.conn.network_timeout, None)
178+
self.assertEqual(self.get_option(option), None)
179+
finally:
180+
self.set_option(option, old)
181+
152182
# test is failing with:
153183
# pyasn1.error.SubstrateUnderrunError: Short octet stream on tag decoding
154184
@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