1+ import time
2+ from datetime import datetime , timezone , timedelta
13from seamapi .types import (
4+ WaitForAccessCodeFailedException ,
25 AbstractAccessCodes ,
36 AccessCode ,
47 AccessCodeId ,
@@ -126,6 +129,8 @@ def create(
126129 starts_at : Optional [str ] = None ,
127130 ends_at : Optional [str ] = None ,
128131 common_code_key : Optional [str ] = None ,
132+ wait_for_code : Optional [bool ] = False ,
133+ timeout : Optional [int ] = 300 ,
129134 ) -> AccessCode :
130135 """Creates an access code on a device.
131136
@@ -141,11 +146,17 @@ def create(
141146 Time when access code becomes effective
142147 ends_at : str, optional
143148 Time when access code ceases to be effective
149+ wait_for_code : bool, optional
150+ Poll the access code until the code is known.
151+ timeout : int, optional:
152+ Maximum polling time in seconds.
144153
145154 Raises
146155 ------
147156 Exception
148157 If the API request wasn't successful.
158+ WaitForAccessCodeFailedException
159+ If waiting for code aborts due to error or timeout.
149160
150161 Returns
151162 ------
@@ -165,18 +176,47 @@ def create(
165176 if common_code_key is not None :
166177 create_payload ["common_code_key" ] = common_code_key
167178
179+ if (wait_for_code
180+ and starts_at is not None
181+ and datetime .fromisoformat (starts_at ) > datetime .now () + timedelta (seconds = 5 )
182+ ):
183+ raise RuntimeError ("Cannot use wait_for_code with a future time bound code" )
184+
168185 res = self .seam .make_request (
169186 "POST" ,
170187 "/access_codes/create" ,
171188 json = create_payload ,
172189 )
173190
174- action_attempt = self .seam .action_attempts .poll_until_ready (
175- res ["action_attempt" ]["action_attempt_id" ]
176- )
177- success_res : Any = action_attempt .result
178-
179- return AccessCode .from_dict (success_res ["access_code" ])
191+ access_code = AccessCode .from_dict (res ["access_code" ])
192+
193+ duration = 0
194+ poll_interval = 0.25
195+ if wait_for_code :
196+ while (access_code .code is None ):
197+ if (access_code .status == "unknown" ):
198+ raise WaitForAccessCodeFailedException (
199+ "Access code status returned unknown" ,
200+ access_code_id = access_code .access_code_id
201+ )
202+ if (len (access_code .errors ) > 0 ):
203+ raise WaitForAccessCodeFailedException (
204+ "Access code returned errors" ,
205+ access_code_id = access_code .access_code_id ,
206+ errors = access_code .errors
207+ )
208+ time .sleep (poll_interval )
209+ duration += poll_interval
210+ if (duration > timeout ):
211+ raise WaitForAccessCodeFailedException (
212+ f"Gave up after waiting the maximum timeout of { timeout } seconds" ,
213+ access_code_id = access_code .access_code_id ,
214+ errors = access_code .errors
215+ )
216+
217+ access_code = access_codes .get (access_code )
218+
219+ return access_code
180220
181221 @report_error
182222 def create_multiple (
0 commit comments