Skip to content

Commit e148184

Browse files
tiranencukou
authored andcommitted
Make bytes mode TypeError more useful
Make bytes mode TypeError more useful It's a bit hard to understand where the TypeError excactly comes from. The exception now contains the argument name. #165 Signed-off-by: Christian Heimes <cheimes@redhat.com>
1 parent dfbe523 commit e148184

6 files changed

Lines changed: 90 additions & 42 deletions

File tree

Lib/ldap/ldapobject.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,10 @@ def _bytesify_input(self, arg_name, value):
144144
return value
145145
else:
146146
if self.bytes_mode_hardfail:
147-
raise TypeError("All provided fields *must* be bytes when bytes mode is on; got %r" % (value,))
147+
raise TypeError(
148+
"All provided fields *must* be bytes when bytes mode is on; "
149+
"got type '{}' for '{}'.".format(type(value).__name__, arg_name)
150+
)
148151
else:
149152
_raise_byteswarning(
150153
"Received non-bytes value for '{}' with default (disabled) bytes mode; "
@@ -153,7 +156,10 @@ def _bytesify_input(self, arg_name, value):
153156
return value.encode('utf-8')
154157
else:
155158
if not isinstance(value, text_type):
156-
raise TypeError("All provided fields *must* be text when bytes mode is off; got %r" % (value,))
159+
raise TypeError(
160+
"All provided fields *must* be text when bytes mode is off; "
161+
"got type '{}' for '{}'.".format(type(value).__name__, arg_name)
162+
)
157163
assert not isinstance(value, bytes)
158164
return value.encode('utf-8')
159165

Modules/LDAPObject.c

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,16 @@ Tuple_to_LDAPMod( PyObject* tup, int no_op )
108108
Py_ssize_t i, len, nstrs;
109109

110110
if (!PyTuple_Check(tup)) {
111-
LDAPerror_TypeError("expected a tuple", tup);
111+
LDAPerror_TypeError("Tuple_to_LDAPMod(): expected a tuple", tup);
112112
return NULL;
113113
}
114114

115115
if (no_op) {
116-
if (!PyArg_ParseTuple( tup, "sO", &type, &list ))
116+
if (!PyArg_ParseTuple( tup, "sO:Tuple_to_LDAPMod", &type, &list ))
117117
return NULL;
118118
op = 0;
119119
} else {
120-
if (!PyArg_ParseTuple( tup, "isO", &op, &type, &list ))
120+
if (!PyArg_ParseTuple( tup, "isO:Tuple_to_LDAPMod", &op, &type, &list ))
121121
return NULL;
122122
}
123123

@@ -161,7 +161,7 @@ Tuple_to_LDAPMod( PyObject* tup, int no_op )
161161
if (item == NULL)
162162
goto error;
163163
if (!PyBytes_Check(item)) {
164-
LDAPerror_TypeError("expected a byte string in the list", item);
164+
LDAPerror_TypeError("Tuple_to_LDAPMod(): expected a byte string in the list", item);
165165
goto error;
166166
}
167167
lm->mod_bvalues[i]->bv_len = PyBytes_Size(item);
@@ -206,14 +206,14 @@ List_to_LDAPMods( PyObject *list, int no_op ) {
206206
PyObject *item;
207207

208208
if (!PySequence_Check(list)) {
209-
LDAPerror_TypeError("expected list of tuples", list);
209+
LDAPerror_TypeError("List_to_LDAPMods(): expected list of tuples", list);
210210
return NULL;
211211
}
212212

213213
len = PySequence_Length(list);
214214

215215
if (len < 0) {
216-
LDAPerror_TypeError("expected list of tuples", list);
216+
LDAPerror_TypeError("List_to_LDAPMods(): expected list of tuples", list);
217217
return NULL;
218218
}
219219

@@ -262,7 +262,7 @@ attrs_from_List( PyObject *attrlist, char***attrsp) {
262262
#endif
263263
/* caught by John Benninghoff <johnb@netscape.com> */
264264
LDAPerror_TypeError(
265-
"expected *list* of strings, not a string", attrlist);
265+
"attrs_from_List(): expected *list* of strings, not a string", attrlist);
266266
goto error;
267267
} else {
268268
PyObject *item = NULL;
@@ -291,15 +291,15 @@ attrs_from_List( PyObject *attrlist, char***attrsp) {
291291
#if PY_MAJOR_VERSION == 2
292292
/* Encoded in Python to UTF-8 */
293293
if (!PyBytes_Check(item)) {
294-
LDAPerror_TypeError("expected bytes in list", item);
294+
LDAPerror_TypeError("attrs_from_List(): expected bytes in list", item);
295295
goto error;
296296
}
297297
if (PyBytes_AsStringAndSize(item, &str, &strlen) == -1) {
298298
goto error;
299299
}
300300
#else
301301
if (!PyUnicode_Check(item)) {
302-
LDAPerror_TypeError("expected string in list", item);
302+
LDAPerror_TypeError("attrs_from_List(): expected string in list", item);
303303
goto error;
304304
}
305305
str = PyUnicode_AsUTF8AndSize(item, &strlen);
@@ -361,7 +361,7 @@ l_ldap_unbind_ext( LDAPObject* self, PyObject* args )
361361

362362
int ldaperror;
363363

364-
if (!PyArg_ParseTuple( args, "|OO", &serverctrls, &clientctrls)) return NULL;
364+
if (!PyArg_ParseTuple( args, "|OO:unbind_ext", &serverctrls, &clientctrls)) return NULL;
365365
if (not_valid(self)) return NULL;
366366

367367
if (!PyNone_Check(serverctrls)) {
@@ -404,7 +404,7 @@ l_ldap_abandon_ext( LDAPObject* self, PyObject* args )
404404

405405
int ldaperror;
406406

407-
if (!PyArg_ParseTuple( args, "i|OO", &msgid, &serverctrls, &clientctrls)) return NULL;
407+
if (!PyArg_ParseTuple( args, "i|OO:abandon_ext", &msgid, &serverctrls, &clientctrls)) return NULL;
408408
if (not_valid(self)) return NULL;
409409

410410
if (!PyNone_Check(serverctrls)) {
@@ -449,7 +449,7 @@ l_ldap_add_ext( LDAPObject* self, PyObject *args )
449449
int ldaperror;
450450
LDAPMod **mods;
451451

452-
if (!PyArg_ParseTuple( args, "sO|OO", &dn, &modlist, &serverctrls, &clientctrls )) return NULL;
452+
if (!PyArg_ParseTuple( args, "sO|OO:add_ext", &dn, &modlist, &serverctrls, &clientctrls )) return NULL;
453453
if (not_valid(self)) return NULL;
454454

455455
mods = List_to_LDAPMods( modlist, 1 );
@@ -499,7 +499,7 @@ l_ldap_simple_bind( LDAPObject* self, PyObject* args )
499499
LDAPControl** client_ldcs = NULL;
500500
struct berval cred;
501501

502-
if (!PyArg_ParseTuple( args, "zz#|OO", &who, &cred.bv_val, &cred_len, &serverctrls, &clientctrls )) return NULL;
502+
if (!PyArg_ParseTuple( args, "zz#|OO:simple_bind", &who, &cred.bv_val, &cred_len, &serverctrls, &clientctrls )) return NULL;
503503
cred.bv_len = (ber_len_t) cred_len;
504504

505505
if (not_valid(self)) return NULL;
@@ -649,7 +649,7 @@ l_ldap_sasl_bind_s( LDAPObject* self, PyObject* args )
649649
struct berval *servercred;
650650
int ldaperror;
651651

652-
if (!PyArg_ParseTuple(args, "zzz#OO", &dn, &mechanism, &cred.bv_val, &cred_len, &serverctrls, &clientctrls ))
652+
if (!PyArg_ParseTuple(args, "zzz#OO:sasl_bind_s", &dn, &mechanism, &cred.bv_val, &cred_len, &serverctrls, &clientctrls ))
653653
return NULL;
654654

655655
if (not_valid(self)) return NULL;
@@ -713,9 +713,9 @@ l_ldap_sasl_interactive_bind_s( LDAPObject* self, PyObject* args )
713713
* "i" otherwise.
714714
*/
715715
#if (PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION < 3)
716-
if (!PyArg_ParseTuple(args, "sOOOi", &who, &SASLObject, &serverctrls, &clientctrls, &sasl_flags ))
716+
if (!PyArg_ParseTuple(args, "sOOOi:sasl_interactive_bind_s", &who, &SASLObject, &serverctrls, &clientctrls, &sasl_flags ))
717717
#else
718-
if (!PyArg_ParseTuple(args, "sOOOI", &who, &SASLObject, &serverctrls, &clientctrls, &sasl_flags ))
718+
if (!PyArg_ParseTuple(args, "sOOOI:sasl_interactive_bind_s", &who, &SASLObject, &serverctrls, &clientctrls, &sasl_flags ))
719719
#endif
720720
return NULL;
721721

@@ -780,7 +780,7 @@ l_ldap_cancel( LDAPObject* self, PyObject* args )
780780

781781
int ldaperror;
782782

783-
if (!PyArg_ParseTuple( args, "i|OO", &cancelid, &serverctrls, &clientctrls)) return NULL;
783+
if (!PyArg_ParseTuple( args, "i|OO:cancel", &cancelid, &serverctrls, &clientctrls)) return NULL;
784784
if (not_valid(self)) return NULL;
785785

786786
if (!PyNone_Check(serverctrls)) {
@@ -826,7 +826,7 @@ l_ldap_compare_ext( LDAPObject* self, PyObject *args )
826826
Py_ssize_t value_len;
827827
struct berval value;
828828

829-
if (!PyArg_ParseTuple( args, "sss#|OO", &dn, &attr, &value.bv_val, &value_len, &serverctrls, &clientctrls )) return NULL;
829+
if (!PyArg_ParseTuple( args, "sss#|OO:compare_ext", &dn, &attr, &value.bv_val, &value_len, &serverctrls, &clientctrls )) return NULL;
830830
value.bv_len = (ber_len_t) value_len;
831831

832832
if (not_valid(self)) return NULL;
@@ -871,7 +871,7 @@ l_ldap_delete_ext( LDAPObject* self, PyObject *args )
871871
int msgid;
872872
int ldaperror;
873873

874-
if (!PyArg_ParseTuple( args, "s|OO", &dn, &serverctrls, &clientctrls )) return NULL;
874+
if (!PyArg_ParseTuple( args, "s|OO:delete_ext", &dn, &serverctrls, &clientctrls )) return NULL;
875875
if (not_valid(self)) return NULL;
876876

877877
if (!PyNone_Check(serverctrls)) {
@@ -916,7 +916,7 @@ l_ldap_modify_ext( LDAPObject* self, PyObject *args )
916916
int ldaperror;
917917
LDAPMod **mods;
918918

919-
if (!PyArg_ParseTuple( args, "sO|OO", &dn, &modlist, &serverctrls, &clientctrls )) return NULL;
919+
if (!PyArg_ParseTuple( args, "sO|OO:modify_ext", &dn, &modlist, &serverctrls, &clientctrls )) return NULL;
920920
if (not_valid(self)) return NULL;
921921

922922
mods = List_to_LDAPMods( modlist, 0 );
@@ -969,7 +969,7 @@ l_ldap_rename( LDAPObject* self, PyObject *args )
969969
int msgid;
970970
int ldaperror;
971971

972-
if (!PyArg_ParseTuple( args, "ss|ziOO", &dn, &newrdn, &newSuperior, &delold, &serverctrls, &clientctrls ))
972+
if (!PyArg_ParseTuple( args, "ss|ziOO:rename", &dn, &newrdn, &newSuperior, &delold, &serverctrls, &clientctrls ))
973973
return NULL;
974974
if (not_valid(self)) return NULL;
975975

@@ -1022,7 +1022,7 @@ l_ldap_result4( LDAPObject* self, PyObject *args )
10221022
char **refs = NULL;
10231023
LDAPControl **serverctrls = 0;
10241024

1025-
if (!PyArg_ParseTuple( args, "|iidiii", &msgid, &all, &timeout, &add_ctrls, &add_intermediates, &add_extop ))
1025+
if (!PyArg_ParseTuple( args, "|iidiii:result4", &msgid, &all, &timeout, &add_ctrls, &add_intermediates, &add_extop ))
10261026
return NULL;
10271027
if (not_valid(self)) return NULL;
10281028

@@ -1162,7 +1162,7 @@ l_ldap_search_ext( LDAPObject* self, PyObject* args )
11621162
int msgid;
11631163
int ldaperror;
11641164

1165-
if (!PyArg_ParseTuple( args, "sis|OiOOdi",
1165+
if (!PyArg_ParseTuple( args, "sis|OiOOdi:search_ext",
11661166
&base, &scope, &filter, &attrlist, &attrsonly,
11671167
&serverctrls, &clientctrls, &timeout, &sizelimit )) return NULL;
11681168
if (not_valid(self)) return NULL;
@@ -1224,7 +1224,7 @@ l_ldap_whoami_s( LDAPObject* self, PyObject* args )
12241224

12251225
int ldaperror;
12261226

1227-
if (!PyArg_ParseTuple( args, "|OO", &serverctrls, &clientctrls)) return NULL;
1227+
if (!PyArg_ParseTuple( args, "|OO:whoami_s", &serverctrls, &clientctrls)) return NULL;
12281228
if (not_valid(self)) return NULL;
12291229

12301230
if (!PyNone_Check(serverctrls)) {
@@ -1265,7 +1265,7 @@ l_ldap_start_tls_s( LDAPObject* self, PyObject* args )
12651265
{
12661266
int ldaperror;
12671267

1268-
if (!PyArg_ParseTuple( args, "" )) return NULL;
1268+
if (!PyArg_ParseTuple( args, ":start_tls_s" )) return NULL;
12691269
if (not_valid(self)) return NULL;
12701270

12711271
LDAP_BEGIN_ALLOW_THREADS( self );
@@ -1331,7 +1331,7 @@ l_ldap_passwd( LDAPObject* self, PyObject *args )
13311331
int msgid;
13321332
int ldaperror;
13331333

1334-
if (!PyArg_ParseTuple( args, "z#z#z#|OO", &user.bv_val, &user_len, &oldpw.bv_val, &oldpw_len, &newpw.bv_val, &newpw_len, &serverctrls, &clientctrls ))
1334+
if (!PyArg_ParseTuple( args, "z#z#z#|OO:passwd", &user.bv_val, &user_len, &oldpw.bv_val, &oldpw_len, &newpw.bv_val, &newpw_len, &serverctrls, &clientctrls ))
13351335
return NULL;
13361336

13371337
user.bv_len = (ber_len_t) user_len;
@@ -1387,7 +1387,7 @@ l_ldap_extended_operation( LDAPObject* self, PyObject *args )
13871387
int msgid;
13881388
int ldaperror;
13891389

1390-
if (!PyArg_ParseTuple( args, "sz#|OO", &reqoid, &reqvalue.bv_val, &reqvalue.bv_len, &serverctrls, &clientctrls ))
1390+
if (!PyArg_ParseTuple( args, "sz#|OO:extended_operation", &reqoid, &reqvalue.bv_val, &reqvalue.bv_len, &serverctrls, &clientctrls ))
13911391
return NULL;
13921392

13931393
if (not_valid(self)) return NULL;

Modules/functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ l_ldap_initialize(PyObject* unused, PyObject *args)
1616
LDAP *ld = NULL;
1717
int ret;
1818

19-
if (!PyArg_ParseTuple(args, "s", &uri))
19+
if (!PyArg_ParseTuple(args, "s:initialize", &uri))
2020
return NULL;
2121

2222
Py_BEGIN_ALLOW_THREADS

Modules/ldapcontrol.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ Tuple_to_LDAPControl( PyObject* tup )
7272
Py_ssize_t len;
7373

7474
if (!PyTuple_Check(tup)) {
75-
LDAPerror_TypeError("expected a tuple", tup);
75+
LDAPerror_TypeError("Tuple_to_LDAPControl(): expected a tuple", tup);
7676
return NULL;
7777
}
7878

79-
if (!PyArg_ParseTuple( tup, "sbO", &oid, &iscritical, &bytes ))
79+
if (!PyArg_ParseTuple( tup, "sbO:Tuple_to_LDAPControl", &oid, &iscritical, &bytes ))
8080
return NULL;
8181

8282
lc = PyMem_NEW(LDAPControl, 1);
@@ -106,7 +106,7 @@ Tuple_to_LDAPControl( PyObject* tup )
106106
berbytes.bv_val = PyBytes_AsString(bytes);
107107
}
108108
else {
109-
LDAPerror_TypeError("expected bytes", bytes);
109+
LDAPerror_TypeError("Tuple_to_LDAPControl(): expected bytes", bytes);
110110
LDAPControl_DEL(lc);
111111
return NULL;
112112
}
@@ -128,7 +128,7 @@ LDAPControls_from_object(PyObject* list, LDAPControl ***controls_ret)
128128
PyObject* item;
129129

130130
if (!PySequence_Check(list)) {
131-
LDAPerror_TypeError("expected a list", list);
131+
LDAPerror_TypeError("LDAPControls_from_object(): expected a list", list);
132132
return 0;
133133
}
134134

Tests/t_cext.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -784,10 +784,16 @@ def assertInvalidControls(self, func, *args, **kwargs):
784784
# last two args are serverctrls, clientctrls
785785
with self.assertRaises(TypeError) as e:
786786
func(*(args + (object, None) + post))
787-
self.assertEqual(e.exception.args, ('expected a list', object))
787+
self.assertEqual(
788+
e.exception.args,
789+
('LDAPControls_from_object(): expected a list', object)
790+
)
788791
with self.assertRaises(TypeError) as e:
789792
func(*(args + (None, object) + post))
790-
self.assertEqual(e.exception.args, ('expected a list', object))
793+
self.assertEqual(
794+
e.exception.args,
795+
('LDAPControls_from_object(): expected a list', object)
796+
)
791797

792798
def test_invalid_controls(self):
793799
l = self._open_conn()

Tests/t_ldapobject.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,48 @@ def test_reject_bytes_base(self):
106106
base = self.server.suffix
107107
l = self._ldap_conn
108108

109-
with self.assertRaises(TypeError):
110-
l.search_s(base.encode('utf-8'), ldap.SCOPE_SUBTREE, '(cn=Foo*)', ['*'])
111-
with self.assertRaises(TypeError):
112-
l.search_s(base, ldap.SCOPE_SUBTREE, b'(cn=Foo*)', ['*'])
113-
with self.assertRaises(TypeError):
114-
l.search_s(base, ldap.SCOPE_SUBTREE, '(cn=Foo*)', [b'*'])
109+
with self.assertRaises(TypeError) as e:
110+
l.search_s(
111+
base.encode('utf-8'), ldap.SCOPE_SUBTREE, '(cn=Foo*)', ['*']
112+
)
113+
if PY2:
114+
self.assertIn(
115+
u"got type 'str' for 'base'", text_type(e.exception)
116+
)
117+
elif sys.version_info >= (3, 5, 0):
118+
# Python 3.4.x does not include 'search_ext()' in message
119+
self.assertEqual(
120+
"search_ext() argument 1 must be str, not bytes",
121+
text_type(e.exception)
122+
)
123+
124+
with self.assertRaises(TypeError) as e:
125+
l.search_s(
126+
base, ldap.SCOPE_SUBTREE, b'(cn=Foo*)', ['*']
127+
)
128+
if PY2:
129+
self.assertIn(
130+
u"got type 'str' for 'filterstr'", text_type(e.exception)
131+
)
132+
elif sys.version_info >= (3, 5, 0):
133+
self.assertEqual(
134+
"search_ext() argument 3 must be str, not bytes",
135+
text_type(e.exception)
136+
)
137+
138+
with self.assertRaises(TypeError) as e:
139+
l.search_s(
140+
base, ldap.SCOPE_SUBTREE, '(cn=Foo*)', [b'*']
141+
)
142+
if PY2:
143+
self.assertIn(
144+
u"got type 'str' for 'attrlist'", text_type(e.exception)
145+
)
146+
elif sys.version_info >= (3, 5, 0):
147+
self.assertEqual(
148+
('attrs_from_List(): expected string in list', b'*'),
149+
e.exception.args
150+
)
115151

116152
def test_search_keys_are_text(self):
117153
base = self.server.suffix

0 commit comments

Comments
 (0)