| 1441 | self._saved_state = None |
| 1442 | |
| 1443 | def __enter__(self): |
| 1444 | imap = self._imap |
| 1445 | assert not imap._idle_responses |
| 1446 | assert not imap._idle_capture |
| 1447 | |
| 1448 | if __debug__ and imap.debug >= 4: |
| 1449 | imap._mesg(f'idle start duration={self._duration}') |
| 1450 | |
| 1451 | # Start capturing untagged responses before sending IDLE, |
| 1452 | # so we can deliver via iteration any that arrive while |
| 1453 | # the IDLE command continuation request is still pending. |
| 1454 | imap._idle_capture = True |
| 1455 | |
| 1456 | try: |
| 1457 | self._tag = imap._command('IDLE') |
| 1458 | # As with any command, the server is allowed to send us unrelated, |
| 1459 | # untagged responses before acting on IDLE. These lines will be |
| 1460 | # returned by _get_response(). When the server is ready, it will |
| 1461 | # send an IDLE continuation request, indicated by _get_response() |
| 1462 | # returning None. We therefore process responses in a loop until |
| 1463 | # this occurs. |
| 1464 | while resp := imap._get_response(): |
| 1465 | if imap.tagged_commands[self._tag]: |
| 1466 | typ, data = imap.tagged_commands.pop(self._tag) |
| 1467 | if typ == 'NO': |
| 1468 | raise imap.error(f'idle denied: {data}') |
| 1469 | raise imap.abort(f'unexpected status response: {resp}') |
| 1470 | |
| 1471 | if __debug__ and imap.debug >= 4: |
| 1472 | prompt = imap.continuation_response |
| 1473 | imap._mesg(f'idle continuation prompt: {prompt}') |
| 1474 | except BaseException: |
| 1475 | imap._idle_capture = False |
| 1476 | raise |
| 1477 | |
| 1478 | if self._duration is not None: |
| 1479 | self._deadline = time.monotonic() + self._duration |
| 1480 | |
| 1481 | self._saved_state = imap.state |
| 1482 | imap.state = 'IDLING' |
| 1483 | |
| 1484 | return self |
| 1485 | |
| 1486 | def __exit__(self, exc_type, exc_val, exc_tb): |
| 1487 | imap = self._imap |