@@ -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,38 +137,46 @@ 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
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; "
157
+ "please choose an explicit "
158
+ "option for bytes_mode on your LDAP connection" .format (arg_name ))
145
159
else :
146
- if self .bytes_mode_hardfail :
147
160
raise TypeError (
148
161
"All provided fields *must* be bytes when bytes mode is on; "
149
162
"got type '{}' for '{}'." .format (type (value ).__name__ , arg_name )
150
163
)
151
- else :
152
- _raise_byteswarning (
153
- "Received non-bytes value for '{}' with default (disabled) bytes mode; "
154
- "please choose an explicit "
155
- "option for bytes_mode on your LDAP connection" .format (arg_name ))
156
- return value .encode ('utf-8' )
164
+ return value .encode ('utf-8' )
157
165
else :
158
- if not isinstance (value , text_type ):
166
+ if isinstance (value , unicode ):
167
+ return value .encode ('utf-8' )
168
+ elif self .bytes_strictness == 'silent' :
169
+ pass
170
+ elif self .bytes_strictness == 'warn' :
171
+ _raise_byteswarning (
172
+ "Received non-text value for '{}' with bytes_mode off and "
173
+ "bytes_strictness='warn'" .format (arg_name ))
174
+ else :
159
175
raise TypeError (
160
176
"All provided fields *must* be text when bytes mode is off; "
161
177
"got type '{}' for '{}'." .format (type (value ).__name__ , arg_name )
162
178
)
163
- assert not isinstance (value , bytes )
164
- return value .encode ('utf-8' )
179
+ return value
165
180
166
181
def _bytesify_modlist (self , arg_name , modlist , with_opcode ):
167
182
"""Adapt a modlist according to bytes_mode.
@@ -1064,7 +1079,7 @@ class ReconnectLDAPObject(SimpleLDAPObject):
1064
1079
def __init__ (
1065
1080
self ,uri ,
1066
1081
trace_level = 0 ,trace_file = None ,trace_stack_limit = 5 ,bytes_mode = None ,
1067
- retry_max = 1 ,retry_delay = 60.0
1082
+ bytes_strictness = None , retry_max = 1 , retry_delay = 60.0
1068
1083
):
1069
1084
"""
1070
1085
Parameters like SimpleLDAPObject.__init__() with these
@@ -1078,7 +1093,9 @@ def __init__(
1078
1093
self ._uri = uri
1079
1094
self ._options = []
1080
1095
self ._last_bind = None
1081
- SimpleLDAPObject .__init__ (self ,uri ,trace_level ,trace_file ,trace_stack_limit ,bytes_mode )
1096
+ SimpleLDAPObject .__init__ (self , uri , trace_level , trace_file ,
1097
+ trace_stack_limit , bytes_mode ,
1098
+ bytes_strictness = bytes_strictness )
1082
1099
self ._reconnect_lock = ldap .LDAPLock (desc = 'reconnect lock within %s' % (repr (self )))
1083
1100
self ._retry_max = retry_max
1084
1101
self ._retry_delay = retry_delay
@@ -1097,6 +1114,11 @@ def __getstate__(self):
1097
1114
1098
1115
def __setstate__ (self ,d ):
1099
1116
"""set up the object from pickled data"""
1117
+ hardfail = d .get ('bytes_mode_hardfail' )
1118
+ if hardfail :
1119
+ d .setdefault ('bytes_strictness' , 'error' )
1120
+ else :
1121
+ d .setdefault ('bytes_strictness' , 'warn' )
1100
1122
self .__dict__ .update (d )
1101
1123
self ._last_bind = getattr (SimpleLDAPObject , self ._last_bind [0 ]), self ._last_bind [1 ], self ._last_bind [2 ]
1102
1124
self ._ldap_object_lock = self ._ldap_lock ()
0 commit comments