+
    „WÝjE  ã                  ó¢  € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIH	t	 ]P                  ! R4      tR tR R ltR R	 ltR
 R ltR R ltR7RR/R R llltR R ltR R ltR R ltR R ltR R ltR]3R]3R]3R]33tR  R! ltR" R# ltR$RR%R&/R' R( lltR) tR* R+ ltR%R,/R- R. lltR%R&/R/ R0 lltR1 R2 lt R3 R4 lt!R5 R6 lt"R# )8a~  Classic-CLI shutdown and one-shot finalize helpers: process session-id sync, deferred agent startup, exit watchdog, cleanup steps, session-finalize notifications and the terminal input-mode reset.

Split out of ``cli.py``; ``cli`` re-exports every public name and moved bodies late-bind
cli-level names through ``from cli import ...`` at call time so facade monkeypatch seams hold.
)ÚannotationsN)ÚsuppressÚclic                 ó   € ^ RI p V # )z]Late import of the ``cli`` facade: mutable CLI module state (and its test seams) lives there.N©r   r   s    ÚKC:\Users\johnn\AppData\Local\hermes\hermes-agent\hermes_cli\cli_shutdown.pyÚ_clir      s
   € ãà€Jó    c               ó    € V ^8„  d   QhRRRR/# )é   Ú
session_idÚstrÚreturnÚNone© )Úformats   "r   Ú__annotate__r      s   € ÷ 'ñ '¨ð '°ñ 'r	   c                ó"   € ^ RI Hp V! V 4       R# )zCKeep process-local session-id consumers aligned after CLI switches.)Úset_current_session_idN)Úgateway.session_contextr   )r   r   s   & r   Ú_sync_process_session_idr      s   € å>á˜:Ö&r	   c               ó   € V ^8„  d   QhRR/# ©r   r   r   r   )r   s   "r   r   r   "   s   € ÷ ñ  $ñ r	   c                 ól  € \        \        4      ;_uu_ 4        \        P                  ! 4        RRR4       \        P
                  \        P                  3 F3  p \        \        4      ;_uu_ 4        V P                  4        RRR4       K5  	  R#   + '       g   i     Li; i  + '       g   i     K]  ; i)zMBest-effort ``logging.shutdown()`` + stdout/stderr flush before ``os._exit``.N)r   Ú	ExceptionÚloggingÚshutdownÚsysÚstdoutÚstderrÚflush)Ú_streams    r   Ú_flush_logging_and_stdior"   "   sf   € ä	”)×	Õ	Ü×ÒÔ÷ 
ä—J‘J¤§
¡
Ó+ˆÜ”i× Õ Ø�M‰MŒO÷ !Ñ ó ,÷ 
×	ú÷ !× Ð ús   ˜BÁ0B"ÂB	Â"B3c               ó$   € V ^8„  d   QhRRRRRR/# )r   Únamer   ÚdefaultÚfloatr   r   )r   s   "r   r   r   +   s!   € ÷ ñ �Sð  5ð ¨Uñ r	   c                ót   €  \        \        P                  ! W4      4      #   \        \        3 d    Tu # i ; i)zB``float(os.getenv(name))``, or ``default`` when unset/unparseable.)r&   ÚosÚgetenvÚ	TypeErrorÚ
ValueError)r$   r%   s   &&r   Ú
_float_envr,   +   s4   € ðÜ”R—Y’Y˜tÓ-Ó.Ð.øÜ”zÐ"ô ØŠðús   ‚! ¡7¶7c               ó   € V ^8„  d   QhRR/# )r   r   r&   r   )r   s   "r   r   r   3   s   € ÷ 6ñ 6 ñ 6r	   c                 ó    € ^ RI Hp  V ! RR4      # )zC``HERMES_EXIT_WATCHDOG_S`` as a float (default 30; ``0`` disables).©r,   ÚHERMES_EXIT_WATCHDOG_Sg      >@)r   r,   r/   s    r   Ú_exit_watchdog_timeoutr1   3   s   € åÙÐ.°Ó5Ð5r	   Úfrom_signalFc               ó$   € V ^8„  d   QhRRRRRR/# )r   Ú	timeout_szfloat | Noner2   Úboolr   r   r   )r   s   "r   r   r   9   s'   € ÷ *Vñ *V ,ð *VÀtð *VÐX\ñ *Vr	   c               óX  a aa€ ^ RI HpHo S f   V! 4       o S ^ 8:  d   R# \        P                  P                  R4      '       d   R# VVV 3R lp\        \        4      ;_uu_ 4        \        P                  ! VRRR7      P                  4        RRR4       R#   + '       g   i     R# ; i)ug  Daemon timer that ``os._exit(0)``s after ``timeout_s`` once shutdown has begun.

Backstop for a cleanup step wedged on network I/O and for interpreter teardown
blocked joining non-daemon threads (ThreadPoolExecutor's atexit join). The daemon
timer survives ``Py_FinalizeEx``'s joins. ``HERMES_EXIT_WATCHDOG_S=0`` disables.

1. 2. Interpreter teardown blocked joining non-daemon threads â€” stdlib ``ThreadPoolExecutor`` workers
are joined unconditionally by ``concurrent.futures``' atexit hook even after ``shutdown(wait=False)``,
so one tool thread wedged on a socket held the process open forever (#27563 class).
)r1   r"   NÚPYTEST_CURRENT_TESTc                 óŠ  <€ \         P                  ! S4       S'       d   \        4       P                  '       d   R #  \        P                  RS4       S! 4        \        \        4      ;_uu_ 4        ^ RIH	p  V ! RR7       R R R 4       \        P                  ! ^ 4       R #   \         d     L[i ; i  + '       g   i     L9; i)Nui   Exit watchdog fired after %.0fs â€” forcing process exit (a cleanup step or non-daemon thread is wedged).)Úkill_live_foreground_processesT)Únow)ÚtimeÚsleepr   Ú_cleanup_in_progressÚloggerÚwarningr   r   Útools.environments.baser9   r(   Ú_exit)r9   r"   r2   r4   s    €€€r   Ú	_watchdogÚ%_arm_exit_watchdog.<locals>._watchdogM   s‰   ø€ Ü�
Š
�9Ôçœ4›6×6×6Ð6Ùð	Ü�N‰NðCàôñ 	!Ô"ä”i× Õ ÝNÙ*¨tÕ4÷ !ô 	�Š�Žøô ô 	Ùð	ú÷ !× ús   ½B! Á1B2Â!B/Â.B/Â2C	Tzexit-watchdog)ÚtargetÚdaemonr$   )r   r1   r"   r(   ÚenvironÚgetr   r   Ú	threadingÚThreadÚstart)r4   r2   r1   rB   r"   s   fd  @r   Ú_arm_exit_watchdogrK   9   st   ú€ ÷ EØÒÙ*Ó,ˆ	Ø�A„~Ùä	‡z�z‡~�~Ð+×,Ò,Ù÷ô* 
”)×	Õ	Ü×Ò 	°$¸_ÔM×SÑSÔU÷ 
×	×	Ò	ús   Á&(BÂB)	c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   f   s   € ÷ )ñ )¨dñ )r	   c                ó4  € V '       d   \        V R4      '       g   R# \        V RR4      pVeE   \        VR4      '       d3   \        \        4      ;_uu_ 4        VP	                  ^
R7       RRR4       \        V RR4      p\        V RR4      ;'       g    Rp\        V\        4      '       d4   \        P                  R	V\        V4      4       V P                  V4       R# \        P                  R
V4       V P                  4        R#   + '       g   i     L¥; i)zVMemory-provider shutdown (on_session_end + shutdown_all) at the real session boundary.Úshutdown_memory_providerNÚ_memory_managerÚflush_pending)ÚtimeoutÚ_session_messagesr   ú	<unknown>zECLI cleanup calling memory shutdown for session %s with %d message(s)zOCLI cleanup calling memory shutdown for session %s without session message list)ÚhasattrÚgetattrr   r   rP   Ú
isinstanceÚlistr>   ÚinfoÚlenrN   )ÚagentÚ_mmÚ_session_msgsÚ_sids   &   r   Ú_shutdown_agent_memory_providerr^   f   sÚ   € ç”g˜eÐ%?×@Ò@Ùô �%Ð*¨DÓ
1€CØ
‚œ7 3¨×8Ò8Ü”i× Õ Ø×Ñ bÐÔ)÷ !ô ˜EÐ#6¸Ó=€MÜ�5˜,¨Ó-×<Ð<°€Dô �-¤×&Ò&Ü�‰Ð[Ð]aÔcfÐgtÓcuÔvØ×&Ñ& }Ö5ä�‰ÐeÐgkÔlØ×&Ñ&Ö(÷ !× ús   ÁDÄD	c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r      s   € ÷ 5ñ 5˜Tñ 5r	   c                 óx   € ^ RI Hp  \        4       P                  e   V ! \        4       P                  R7       R# R# )é    ©Ústop_listeningN)Úowner)Útools.wake_wordrc   r   Ú_cli_wake_ownerrb   s    r   Ú_stop_cli_wake_wordrg      s(   € Ý.Üƒv×ÑÒ)ÙœT›V×3Ñ3×4ñ *r	   c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   …   s   € ÷ )ñ ) dñ )r	   c                 ó$   € ^ RI Hp  V ! RR7       R# )ra   ©Úinterrupt_allzCLI shutdown)ÚreasonN)Útools.async_delegationrk   rj   s    r   Ú_interrupt_async_delegationsrn   …   s   € Ý4Ù˜×(r	   c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   Š   s   € ÷ ñ ˜tñ r	   c                 ó    € ^ RI Hp  V ! 4        R# )ra   ©Úshutdown_mcp_serversN)Útools.mcp_tool_lifecyclerr   rq   s    r   Ú_shutdown_mcp_serversrt   Š   s   € Ý=ÙÖr	   c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   �   s   € ÷ ñ  dñ r	   c                 ó    € ^ RI Hp  V ! 4        R# )ra   ©Úshutdown_cached_clientsN)Úagent.auxiliary_clientrx   rw   s    r   Ú_shutdown_cached_aux_clientsrz   �   s   € å>ÙÖr	   rg   Ú_cleanup_all_terminalsÚ_cleanup_all_browsersrz   c               ó   € V ^8„  d   QhRR/# )r   r   r5   r   )r   s   "r   r   r   Ÿ   s   € ÷ +ñ +¨ñ +r	   c                ó$   € ^ RI Hp \        W4      # )z¿A gateway-backed session ends in the gateway: the viewer's ``end_session`` (``session.detach
{end_reason}``) makes the owner run finalize and the memory commit (gateway/session_viewer_close).)ÚGatewayAgent)Úhermes_cli.gateway_agentr   rV   )rZ   r   s   & r   Ú_gateway_owns_session_endr�   Ÿ   s   € õ 6Ü�eÓ*Ð*r	   c               ó    € V ^8„  d   QhRRRR/# )r   r   ú
str | Noner   r5   r   )r   s   "r   r   r   ¦   s   € ÷ Qñ Q°jð QÀTñ Qr	   c                óü   € \        \        4       P                  4      '       d   R # V e   V \        4       P                  9   d   R # \        4       P                  '       g   R# V f   R # V \        4       P                  9  # )FT)r�   r   Ú_active_agent_refÚ_handed_off_session_idsÚ,_single_query_finalize_attempted_session_ids)r   s   &r   Ú%_should_emit_cleanup_session_finalizerˆ   ¦   s_   € Ü ¤£×!9Ñ!9×:Ò:Ùð Ò *´³×0NÑ0NÔ"NÙÜ‹6×>×>Ð>ÙØÒÙØœT›V×PÑPÑPÐPr	   Úplatformrl   r   c               ó(   € V ^8„  d   QhRRRRRRRR/# )r   r   rƒ   r‰   r   rl   r   z	list[str]r   )r   s   "r   r   r   µ   s*   € ÷ ñ ¨Jð À#ð ÐWZð Ðluñ r	   c           
     óž   € \        \        4      ;_uu_ 4        ^ RIHpHp V! V! WVR7      4      uuRRR4       #   + '       g   i     . # ; i)zWFire on_session_finalize; return the plugin messages meant for the user (never raises).)Úfinalize_sessionÚsession_end_messages©r   r‰   rl   N)r   r   Úhermes_cli.lifecyclerŒ   r�   )r   r‰   rl   rŒ   r�   s   $$$  r   Ú_notify_session_finalizer�   µ   s7   € ä	”)×	Õ	ßOÙ#Ñ$4À
ÐflÔ$mÓn÷ 
×	×	Ñ	ð €Iús	   ˜;»A	c                ód   € \        V RR4      pT\        VRR4      ;'       g    \        V RR4      3# )zO``(agent, session_id)`` for a one-shot run; the agent's id wins over the CLI's.rZ   Nr   )rU   )r   rZ   s   & r   Ú_oneshot_agent_and_sessionr’   ½   s6   € ä�C˜ $Ó'€EØ”'˜% ¨tÓ4×XÐX¼ÀÀ\ÐSWÓ8XÐXÐXr	   c               ó    € V ^8„  d   QhRRRR/# ©r   rl   r   r   r   r   )r   s   "r   r   r   Ã   s   € ÷ 
ñ 
¸sð 
ÐPTñ 
r	   c                óâ   € \        \        4      ;_uu_ 4        ^ RIHp T! RRTRRRRR\	        V RR4      R	\	        V R	R4      ;'       g    R
RV/VB  RRR4       R#   + '       g   i     R# ; i)zHBest-effort ``on_session_end`` hook for a turn cut short (never raises).)Úinvoke_hookr   Ú	completedFÚinterruptedTÚmodelNr‰   r   rl   )Úon_session_end)r   r   r�   r–   rU   )rZ   r   rl   ÚextraÚ_invoke_hooks   &&&, r   Ú_invoke_interrupted_session_endr�   Ã   s   € ä	”)×	Õ	ÝDÙñ 	
Ø)3ð	
Ø?Dð	
ØRVð	
ä˜% ¨$Ó/ð	
ä:AÀ%ÈÐUYÓ:Z×:cÐ:cÐ^cð	
ð ð	
ð #ò	
÷ 
×	×	Ò	ús   ˜;AÁA.	Úkeyboard_interruptc               ó    € V ^8„  d   QhRRRR/# r”   r   )r   s   "r   r   r   Î   s   € ÷ ñ °#ð ÐQUñ r	   c               óP  € ^ RI HpHp V! V 4      w  rEVf   R# \        \        4      ;_uu_ 4        VP                  VP                  RR4      4       RRR4       V\        4       P                  9   g   \        V4      '       d   R# V'       d'   \        \        4      ;_uu_ 4        WPn
        RRR4       T! YET\        VRR4      ;'       g    R\        VRR4      ;'       g    R\        VRR4      ;'       g    RR	7       R#   + '       g   i     L¸; i  + '       g   i     Lq; i)
zEBest-effort on_session_end hook for interrupted non-interactive runs.)r�   r’   NÚ_Ú Ú_current_task_idÚ Ú_current_turn_idÚ_current_api_request_id)Útask_idÚturn_idÚapi_request_id)r   r�   r’   r   r   Ú	interruptÚreplacer   r†   r�   r   rU   )r   rl   r�   r’   rZ   r   s   &$    r   Ú_emit_interrupted_session_endr¬   Î   sÚ   € çOÙ2°3Ó7Ñ€EØ‚}Ùä	”)×	Õ	Ø�‰˜Ÿ™ s¨CÓ0Ô1÷ 
ð ”T“V×3Ñ3Ô3Ô7PÐQV×7WÒ7WÙßÜ”i× Õ Ø'ŒN÷ !ñ $Ø˜6Ü˜Ð1°2Ó6×<Ð<¸"Ü˜Ð1°2Ó6×<Ð<¸"Ü˜uÐ&?ÀÓD×JÐJÈ÷	÷ 
×	ú÷ !× ús   °"DÂ%DÄD	ÄD%	c               ó    € V ^8„  d   QhRRRR/# r”   r   )r   s   "r   r   r   ç   s   € ÷ Lñ L¸#ð LÈtñ Lr	   c               óÖ  € ^ RI HpHp V! V 4      w  rEV\        4       P                  9   d   R# V\        4       P
                  9   g   \        V4      '       d   R#  T! T\        VRR4      ;'       g    RVR7       F  p\        V\        P                  RR7       K!  	  \        4       P                  P                  V4       R#   \        4       P                  P                  T4       i ; i)ra   )r�   r’   Nr‰   r   rŽ   T)Úfiler    )r   r�   r’   r   r‡   r†   r�   rU   Úprintr   r   Úadd)r   rl   r�   r’   rZ   r   Úmessages   &$     r   Ú%_notify_single_query_session_finalizer³   ç   s¶   € ßHÙ2°3Ó7Ñ€EØ”T“V×HÑHÔHÙð ”T“V×3Ñ3Ô3Ô7PÐQV×7WÒ7WÙðLá/Ø%´¸¸zÈ4Ó0P×0YÐ0YÐTYÐbh÷jˆGä�'¤§
¡
°$×7ñjô 	‹×;Ñ;×?Ñ?À
ÖKøŒ‹×;Ñ;×?Ñ?À
ÕKús   ÁC Á2,C Ã%C(c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   ú   s   € ÷ )Cñ )C¨$ñ )Cr	   c                óÞ  € ^ RI Hp V! V 4      w  r#Ve"   V'       d   V\        4       P                  9   d   R# \	        VRR4      '       d   R#  \	        VRR4      p\        V\        4      '       d8   V'       d0   \        VR4      '       d   VP                  V\	        V RR4      4       \	        TRR4      ;'       g    \	        T RR4      pTf   R#  TP                  4         TP                  TR4       R#   \         d    \        P                  RR	R
7        Lri ; i  \         d    \        P                  RR	R
7        Lai ; i  \         d    \        P                  RR	R
7        R# i ; i)u  Durably flush + finalize the one-shot session row before exit (idempotent, best-effort).

One-shot runs get a single turn, so nothing retries a transiently-failed transcript
flush, closes the session row, or drains token deltas the kanban ``os._exit(0)``
path skips. Handed-off sessions are left alone.

- a turn whose in-loop ``_flush_messages_to_session_db`` failed under write-lock contention (e.g. a busy
multiplex gateway sharing state.db) was silently lost â€” the reply reached stdout and agent.log but the
resumed session's stored history never changed (#88583); - the resumed/created titled session row was
left dangling open (``ended_at``/``end_reason`` NULL) on every one-shot exit; - queued async
token-accounting deltas relied on interpreter-exit hooks, which the kanban SIGTERM path's
``os._exit(0)`` skips entirely.
Idempotent and best-effort: ``_persist_session`` dedupes via the per-message ``_DB_PERSISTED_MARKER``
stamps (already-written turns are not re-written) and ``end_session`` no-ops on an already-ended row.
See #88234.
©r’   NÚ_persist_disabledFrR   Ú_persist_sessionÚconversation_historyz+one-shot final session persist retry failedT©Úexc_infoÚ_session_dbz!one-shot token-count drain failedÚ	cli_closezone-shot end_session failed)r   r’   r   r†   rU   rV   rW   rT   r¸   r   r>   ÚdebugÚflush_token_countsÚend_session)r   r’   rZ   r   ÚmsgsÚdbs   &     r   Ú_flush_one_shot_session_storerÃ   ú   sD  € õ" /Ù2°3Ó7Ñ€EØ‚}ŸJ¨*¼»×8VÑ8VÔ*VÙÜˆuÐ)¨5×1Ò1ÙðSÜ�uÐ1°4Ó8ˆÜ�dœD×!Ò!§d¬w°uÐ>P×/QÒ/QØ×"Ñ" 4¬°Ð6LÈdÓ)SÔTô 
�˜ tÓ	,×	QÐ	Q´¸¸]ÈDÓ0Q€BØ	‚zÙðIØ
×ÑÔðCØ
�‰�z ;Ö/øô ô SÜ�‰ÐBÈTˆÖRðSûô ô IÜ�‰Ð8À4ˆÖHðIûô ô CÜ�‰Ð2¸Tˆ×BðCús<   Á*C6 Á9/C6 ÃD Ã"E Ã6"DÄDÄ"EÅEÅ"E,Å+E,c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   &  s   € ÷ 
ñ 
°Tñ 
r	   c                ó0  € ^ RI Hp ^ RIHp \	        V RR4      '       d   R# V! V 4      w  r4VP                  R4      pVP                  R4      '       dC   \        P                  RT;'       g    RVP                  R	4      VP                  R
4      4       R# R# )aå  Bounded linger for notify_on_complete background processes (children write to our pipes).

Waits on the whole registry: a one-shot process hosts one agent, and task_id
filtering would skip processes registered before the session id settled.

Skipped when the quiet -Q notify-resume loop already consumed the run's linger
budget: it calls wait_for_pending_completions with a shared deadline, so a
re-wait here would double-block on the same stuck notify_on_complete child.

See #90879.
r¶   )Úprocess_registryÚ_quiet_notify_linger_doneFNÚwaitedz>One-shot exit linger for session %s: completed=%s timed_out=%srS   r—   Ú	timed_out)	r   r’   Útools.process_registryrÆ   rU   Úwait_for_pending_completionsrG   r>   rX   )r   r’   rÆ   Ú_agentr§   Úresults   &     r   Ú(_wait_for_oneshot_background_completionsrÎ   &  s   € õ /Ý7äˆsÐ/°×7Ò7ÙÙ0°Ó5�O€FØ×:Ñ:¸4Ó@€FØ‡z�z�(×ÒÜ�‰ØLØ×"Ð"�{Ø�J‰J�{Ó#Ø�J‰J�{Ó#ö		
ñ r	   c               ó   € V ^8„  d   QhRR/# r   r   )r   s   "r   r   r   B  s   € ÷ :0ñ :0 4ñ :0r	   c                óü  € ^ RI p^ RI HpHpHpHpHp   V! V 4       V! V 4        T! \        V RR4      ;'       g    VP                  4       V P                  4         V! V 4       V! R	R
7       R#   \         d    \        P                  RRR7        Lxi ; i  \         d    \        P                  RRR7        Lpi ; i  T P                  4        i ; i  \         d    \        P                  RRR7        L”i ; i)uD  Settle the session, then release its lease, then linger as a bystander.

Three phases, in this order:

1. **Session-owned settlement** â€” the durable flush (transcript retry, token
   drain, ``end_session``), the finalize hook, and memory-provider session
   finalization. Providers finalize THIS session's remote state at
   ``on_session_end`` (OpenViking synchronously commits ``sessions/{sid}``,
   Supermemory flushes pending turns stamped with the session id), so this
   belongs inside ownership â€” post-release it would run while a successor
   may already be mid-turn on the session. The flush runs first: memory
   shutdown can issue aux-LLM calls and nothing after it may fail in a way
   that loses the turn (#88583). Settlement is best-effort by design:
   failures are logged and the release still happens, because the failure
   mode to avoid is an exited process pinning the lease â€” a dangling open
   row is recoverable (session_recovery reaps stale rows), a wedged lease
   is not.
2. **Ownership handoff** â€” release the active-session lease. Every turn of
   the run (main turn, kanban goal loop, notify-completion follow-ups) has
   finished and the success path has no session-owned writes left, so a
   waiting delivery may acquire and resume the session immediately:
   releasing only at process exit let an alive-but-idle one-shot refuse
   deliveries for the whole exit linger (bounded, minutes) after its turn
   had ended (#118826 / #122770).
3. **Process-only work, lease-free** â€” the bounded linger for
   notify_on_complete children (pipe drain, the boundary the one-shot path
   itself declares "NOT part of the spawner's delivery", #113608) and
   resource teardown. ``_run_cleanup``'s memory-shutdown call is idempotent
   (``_memory_provider_shutdown``), so its post-release repeat is a no-op;
   neither it nor the linger touches session rows.

Releasing between settlement and the linger is what prevents the handoff race:
a successor that acquires and reopens the session can never receive this
process's stale ``cli_close`` end-stamp, because phase 1 has already run it.
N)rÃ   r³   Ú_run_cleanupr^   rÎ   z#one-shot session store flush failedTrº   rZ   z(one-shot memory provider shutdown failedz*one-shot background completion wait failedF)Únotify_session_finalize)r   rÃ   r³   rÑ   r^   rÎ   r   r>   r¾   rU   r…   Ú_release_active_session)r   Ú
cli_modulerÃ   r³   rÑ   r^   rÎ   s   &      r   Ú_finalize_single_queryrÕ   B  s÷   € óH ÷ rõ  rð&ð	OÙ)¨#Ô.ñ 	.¨cÔ2ð	Tñ ,¬G°C¸À$Ó,G×,gÐ,gÈ:×KgÑKgÔhð 	×#Ñ#Ô%ðRÙ0°Ô5ñ ¨×/øô# ô 	OÜ�L‰LÐ>ÈˆLÖNð	Oûô ô 	TÜ�L‰LÐCÈdˆLÖSð	Tûð
 	×#Ñ#Õ%ûô ô RÜ�‰ÐAÈDˆÖQðRús\   •A1 �C ¦B ¼B ÁC Á1"BÂC ÂBÂC Â"B>Â;C Â=B>Â>C ÃCÃ"C;Ã:C;)N)#Ú__doc__Ú
__future__r   r   r(   r   rH   r;   Ú
contextlibr   Ú	getLoggerr>   r   r   r"   r,   r1   rK   r^   rg   rn   rt   rz   r   Ú_CLEANUP_STEPSr�   rˆ   r�   r’   r�   r¬   r³   rÃ   rÎ   rÕ   r   r	   r   Ú<module>rÛ      sù   ðñõ #ã Û 	Û 
Û Û Ý ð 
×	Ò	˜5Ó	!€òõ'õõõ6ñ*VÈe÷ *Vð *VõZ)õ25õ)õ
õ
ð ˜IÐ&Ð)AÀ9Ð(MØ˜iÐ(Ð+IÈ9Ð*Uð€õ+õQðÈð Ð]g÷ òYõ
ðÐ8L÷ ð2LÀ
÷ Lõ&)CõX
÷8:0r	   