
    Ki                     d    d Z ddlZddlZddlmZ dZdej                  dedefdZ	d	d
deddfdZ
y)a  Cancellation utilities for distinguishing internal vs external cancellation.

When cancelling asyncio tasks, we often need to distinguish between cancellations
we initiated (e.g., for timeout or cleanup) vs external cancellations (e.g., from
a shutdown signal). Python 3.9+ supports passing a message to task.cancel(msg=...)
which we use as a sentinel to identify our own cancellations.

Note on Python version differences:
- Python 3.11+: The cancel message propagates to the awaiter's CancelledError
- Python 3.10: The message is stored but does NOT propagate to the awaiter

The cancel_task() helper handles this by tracking that we initiated the cancel.
    N)Anyzdocket:cleanupexcexpected_msgreturnc                 T    t        | j                  xr | j                  d   |k(        S )a  Check if we initiated this cancellation (vs. someone cancelling us).

    When we cancel a task with task.cancel(msg), the CancelledError will have
    args[0] set to that message. External cancellations (from TaskGroup, signals,
    etc.) typically have no message or a different message.

    Note: In Python 3.10, the message does NOT propagate to the awaiter, so this
    function will return False even for our own cancellations. Use cancel_task()
    instead for reliable cross-version behavior.

    Args:
        exc: The CancelledError to check
        expected_msg: The sentinel message we used when cancelling

    Returns:
        True if the cancellation was initiated by us with the expected message
    r   )boolargs)r   r   s     `/home/jay/workspace/scripts/.codegraph-venv/lib/python3.12/site-packages/docket/_cancellation.pyis_our_cancellationr      s%    $ 8SXXa[L899    taskzasyncio.Task[Any]reasonc                    K   | j                  |       	 |  d{    y7 # t        j                  $ r/}t        ||      rY d}~yt        j
                  dk  rY d}~y d}~ww xY ww)a  Cancel a task and await its completion, suppressing our own cancellation.

    This handles Python 3.10/3.11+ compatibility: in Python 3.10, the cancel
    message doesn't propagate to the awaiter, so we can't rely on checking
    the message. Instead, we track that we initiated the cancellation.

    In Python 3.11+, we verify the message matches as an extra check.

    Args:
        task: The task to cancel
        reason: A description of why we're cancelling (e.g., CANCEL_MSG_CLEANUP)
    N)      )cancelasyncioCancelledErrorr   sysversion_info)r   r   es      r
   cancel_taskr   ,   sX      	KK


!! q&) g%sH   A'"  " A'" A$AA'AA'AA$$A')__doc__r   r   typingr   CANCEL_MSG_CLEANUPr   strr   r   r    r   r
   <module>r      sX     
  & :W33 :3 :4 :*/   r   