17
17
import ldap
18
18
from ldap .controls import DecodeControlTuples , RequestControl
19
19
from ldap .extop import ExtendedRequest
20
+ from ldap .extop .passwd import PasswordModifyResponse
20
21
from ldap .ldapobject import SimpleLDAPObject , NO_UNIQUE_ENTRY
21
22
from ldap .response import (
22
23
Response ,
23
- SearchEntry , SearchReference , SearchResult ,
24
+ SearchEntry , SearchReference ,
24
25
IntermediateResponse , ExtendedResult ,
25
26
)
26
27
@@ -39,10 +40,15 @@ def __init__(self, uri: Union[LDAPUrl, str, None], **kwargs):
39
40
super ().__init__ (uri , ** kwargs )
40
41
41
42
def result (self , msgid : int = ldap .RES_ANY , * , all : int = 1 ,
42
- timeout : Optional [float ] = None ) -> Optional [list [Response ]]:
43
+ timeout : Optional [float ] = None ,
44
+ defaultIntermediateClass :
45
+ Optional [type [IntermediateResponse ]] = None ,
46
+ defaultExtendedClass : Optional [type [ExtendedResult ]] = None
47
+ ) -> Optional [list [Response ]]:
43
48
"""
44
- result([msgid: int = RES_ANY [, all: int = 1 [, timeout :
45
- Optional[float] = None]]]) -> Optional[list[Response]]
49
+ result([msgid: int = RES_ANY [, all: int = 1 [,
50
+ timeout: Optional[float] = None]]])
51
+ -> Optional[list[Response]]
46
52
47
53
This method is used to wait for and return the result of an
48
54
operation previously initiated by one of the LDAP asynchronous
@@ -94,13 +100,26 @@ def result(self, msgid: int = ldap.RES_ANY, *, all: int = 1,
94
100
95
101
results = []
96
102
for msgid , msgtype , controls , data in messages :
97
- controls = DecodeControlTuples (controls , self .resp_ctrl_classes )
103
+ if controls is not None :
104
+ controls = DecodeControlTuples (controls , self .resp_ctrl_classes )
98
105
106
+ if msgtype == ldap .RES_INTERMEDIATE :
107
+ data ['defaultClass' ] = defaultIntermediateClass
108
+ if msgtype == ldap .RES_EXTENDED :
109
+ data ['defaultClass' ] = defaultExtendedClass
99
110
m = Response (msgid , msgtype , controls , ** data )
100
111
results .append (m )
101
112
102
113
return results
103
114
115
+ def add_s (self , dn : str ,
116
+ modlist : list [tuple [str , Union [bytes , list [bytes ]]]], * ,
117
+ ctrls : RequestControls = None ) -> ldap .response .AddResult :
118
+ msgid = self .add_ext (dn , modlist , serverctrls = ctrls )
119
+ responses = self .result (msgid )
120
+ result , = responses
121
+ return result
122
+
104
123
def bind_s (self , dn : Optional [str ] = None ,
105
124
cred : Optional [AnyStr ] = None , * ,
106
125
method : int = ldap .AUTH_SIMPLE ,
@@ -126,17 +145,36 @@ def delete_s(self, dn: str, *,
126
145
result , = responses
127
146
return result
128
147
129
- def extop_s (self , oid : Optional [str ] = None ,
148
+ def extop_s (self , name : Optional [str ] = None ,
130
149
value : Optional [bytes ] = None , * ,
131
150
request : Optional [ExtendedRequest ] = None ,
132
- ctrls : RequestControls = None
151
+ ctrls : RequestControls = None ,
152
+ defaultIntermediateClass : Optional [type [IntermediateResponse ]] = None ,
153
+ defaultExtendedClass : Optional [type [ExtendedResult ]] = None
133
154
) -> list [Union [IntermediateResponse , ExtendedResult ]]:
134
155
if request is not None :
135
- oid = request .requestName
156
+ name = request .requestName
136
157
value = request .encodedRequestValue ()
137
158
138
- msgid = self .extop (oid , value , serverctrls = ctrls )
139
- return self .result (msgid )
159
+ msgid = self .extop (name , value , serverctrls = ctrls )
160
+ return self .result (msgid ,
161
+ defaultIntermediateClass = defaultIntermediateClass ,
162
+ defaultExtendedClass = defaultExtendedClass )
163
+
164
+ def modify_s (self , dn : str ,
165
+ modlist : list [tuple [str , Union [bytes , list [bytes ]]]], * ,
166
+ ctrls : RequestControls = None ) -> ldap .response .ModifyResult :
167
+ msgid = self .modify_ext (dn , modlist , serverctrls = ctrls )
168
+ responses = self .result (msgid )
169
+ result , = responses
170
+ return result
171
+
172
+ def passwd_s (self , user : Optional [str ] = None ,
173
+ oldpw : Optional [bytes ] = None , newpw : Optional [bytes ] = None ,
174
+ ctrls : RequestControls = None ) -> PasswordModifyResponse :
175
+ msgid = self .passwd (user , oldpw , newpw , serverctrls = ctrls )
176
+ res , = self .result (msgid , defaultExtendedClass = PasswordModifyResponse )
177
+ return res
140
178
141
179
def search_s (self , base : Optional [str ] = None ,
142
180
scope : int = ldap .SCOPE_SUBTREE ,
@@ -154,8 +192,11 @@ def search_s(self, base: Optional[str] = None,
154
192
attrsonly = attrsonly , serverctrls = ctrls ,
155
193
sizelimit = sizelimit , timeout = timelimit )
156
194
result = self .result (msgid , timeout = timeout )
195
+ # FIXME: we want a better way of returning a result with multiple
196
+ # messages, always useful in searches but other operations can also
197
+ # elicit those (by way of an IntermediateResponse)
157
198
result [- 1 ].raise_for_result ()
158
- return result [: - 1 ]
199
+ return result
159
200
160
201
def search_subschemasubentry_s (
161
202
self , dn : Optional [str ] = None ) -> Optional [str ]:
@@ -219,6 +260,6 @@ def find_unique_entry(self, base: Optional[str] = None,
219
260
r = self .search_s (base , scope , filter , attrlist = attrlist ,
220
261
attrsonly = attrsonly , ctrls = ctrls , timeout = timeout ,
221
262
sizelimit = 2 )
222
- if len (r ) != 1 :
263
+ if len (r ) != 2 :
223
264
raise NO_UNIQUE_ENTRY (f'No or non-unique search result for { filter } ' )
224
265
return r [0 ]
0 commit comments