@@ -93,7 +93,8 @@ class SimpleLDAPObject:
93
93
94
94
def __init__ (
95
95
self ,uri ,
96
- trace_level = 0 ,trace_file = None ,trace_stack_limit = 5 ,bytes_mode = None
96
+ trace_level = 0 ,trace_file = None ,trace_stack_limit = 5 ,bytes_mode = None ,
97
+ bytes_strictness = None ,
97
98
):
98
99
self ._trace_level = trace_level
99
100
self ._trace_file = trace_file or sys .stdout
@@ -107,20 +108,26 @@ def __init__(
107
108
# Bytes mode
108
109
# ----------
109
110
110
- # By default, raise a TypeError when receiving invalid args
111
- self .bytes_mode_hardfail = True
112
- if bytes_mode is None and PY2 :
113
- _raise_byteswarning (
114
- "Under Python 2, python-ldap uses bytes by default. "
115
- "This will be removed in Python 3 (no bytes for DN/RDN/field names). "
116
- "Please call initialize(..., bytes_mode=False) explicitly." )
117
- bytes_mode = True
118
- # Disable hard failure when running in backwards compatibility mode.
119
- self .bytes_mode_hardfail = False
120
- elif bytes_mode and not PY2 :
121
- raise ValueError ("bytes_mode is *not* supported under Python 3." )
122
- # On by default on Py2, off on Py3.
111
+ if PY2 :
112
+ if bytes_mode is None :
113
+ bytes_mode = True
114
+ if bytes_strictness is None :
115
+ _raise_byteswarning (
116
+ "Under Python 2, python-ldap uses bytes by default. "
117
+ "This will be removed in Python 3 (no bytes for "
118
+ "DN/RDN/field names). "
119
+ "Please call initialize(..., bytes_mode=False) explicitly." )
120
+ bytes_strictness = 'warn'
121
+ else :
122
+ if bytes_strictness is None :
123
+ bytes_strictness = 'error'
124
+ else :
125
+ if bytes_mode :
126
+ raise ValueError ("bytes_mode is *not* supported under Python 3." )
127
+ bytes_mode = False
128
+ bytes_strictness = 'error'
123
129
self .bytes_mode = bytes_mode
130
+ self .bytes_strictness = bytes_strictness
124
131
125
132
def _bytesify_input (self , arg_name , value ):
126
133
"""Adapt a value following bytes_mode in Python 2.
@@ -130,32 +137,40 @@ def _bytesify_input(self, arg_name, value):
130
137
With bytes_mode ON, takes bytes or None and returns bytes or None.
131
138
With bytes_mode OFF, takes unicode or None and returns bytes or None.
132
139
133
- This function should be applied on all text inputs (distinguished names
134
- and attribute names in modlists) to convert them to the bytes expected
135
- by the C bindings .
140
+ For the wrong argument type (unicode or bytes, respectively),
141
+ behavior depends on the bytes_strictness setting.
142
+ In all cases, bytes or None are returned (or an exception is raised) .
136
143
"""
137
144
if not PY2 :
138
145
return value
139
-
140
146
if value is None :
141
147
return value
148
+
142
149
elif self .bytes_mode :
143
150
if isinstance (value , bytes ):
144
151
return value
145
- else :
146
- if self .bytes_mode_hardfail :
147
- raise TypeError ("All provided fields *must* be bytes when bytes mode is on; got %r" % (value ,))
148
- else :
149
- _raise_byteswarning (
150
- "Received non-bytes value for '{}' with default (disabled) bytes mode; "
152
+ elif self .bytes_strictness == 'silent' :
153
+ pass
154
+ elif self .bytes_strictness == 'warn' :
155
+ _raise_byteswarning (
156
+ "Received non-bytes value for '{}' in bytes mode; "
151
157
"please choose an explicit "
152
158
"option for bytes_mode on your LDAP connection" .format (arg_name ))
153
- return value .encode ('utf-8' )
159
+ else :
160
+ raise TypeError ("All provided fields *must* be bytes when bytes mode is on; got %r" % (value ,))
161
+ return value .encode ('utf-8' )
154
162
else :
155
- if not isinstance (value , text_type ):
163
+ if isinstance (value , unicode ):
164
+ return value .encode ('utf-8' )
165
+ elif self .bytes_strictness == 'silent' :
166
+ pass
167
+ elif self .bytes_strictness == 'warn' :
168
+ _raise_byteswarning (
169
+ "Received non-text value for '{}' with bytes_mode off and "
170
+ "bytes_strictness='warn'" .format (arg_name ))
171
+ else :
156
172
raise TypeError ("All provided fields *must* be text when bytes mode is off; got %r" % (value ,))
157
- assert not isinstance (value , bytes )
158
- return value .encode ('utf-8' )
173
+ return value
159
174
160
175
def _bytesify_modlist (self , arg_name , modlist , with_opcode ):
161
176
"""Adapt a modlist according to bytes_mode.
@@ -1058,7 +1073,7 @@ class ReconnectLDAPObject(SimpleLDAPObject):
1058
1073
def __init__ (
1059
1074
self ,uri ,
1060
1075
trace_level = 0 ,trace_file = None ,trace_stack_limit = 5 ,bytes_mode = None ,
1061
- retry_max = 1 ,retry_delay = 60.0
1076
+ bytes_strictness = None , retry_max = 1 , retry_delay = 60.0
1062
1077
):
1063
1078
"""
1064
1079
Parameters like SimpleLDAPObject.__init__() with these
@@ -1072,7 +1087,9 @@ def __init__(
1072
1087
self ._uri = uri
1073
1088
self ._options = []
1074
1089
self ._last_bind = None
1075
- SimpleLDAPObject .__init__ (self ,uri ,trace_level ,trace_file ,trace_stack_limit ,bytes_mode )
1090
+ SimpleLDAPObject .__init__ (self , uri , trace_level , trace_file ,
1091
+ trace_stack_limit , bytes_mode ,
1092
+ bytes_strictness = bytes_strictness )
1076
1093
self ._reconnect_lock = ldap .LDAPLock (desc = 'reconnect lock within %s' % (repr (self )))
1077
1094
self ._retry_max = retry_max
1078
1095
self ._retry_delay = retry_delay
@@ -1091,6 +1108,11 @@ def __getstate__(self):
1091
1108
1092
1109
def __setstate__ (self ,d ):
1093
1110
"""set up the object from pickled data"""
1111
+ hardfail = d .get ('bytes_mode_hardfail' )
1112
+ if hardfail :
1113
+ d .setdefault ('bytes_strictness' , 'error' )
1114
+ else :
1115
+ d .setdefault ('bytes_strictness' , 'warn' )
1094
1116
self .__dict__ .update (d )
1095
1117
self ._last_bind = getattr (SimpleLDAPObject , self ._last_bind [0 ]), self ._last_bind [1 ], self ._last_bind [2 ]
1096
1118
self ._ldap_object_lock = self ._ldap_lock ()
0 commit comments