
    >i׭                    |   d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	m	Z	m
Z
mZ ddlmZ ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZmZmZ ddlmZ ddlmZmZ ddlm Z  ddl!m"Z" ddl#m$Z$ ddl%m&Z& ddl'm(Z(m)Z) ddl*m+Z+m,Z, ddl-m.Z. ddl/m0Z0  e$e1      Z2ejf                  D  ci c]  } | dvs e4|       d c} Z5de5d<   dZ6d Z7 G d de8      Z9 G d de8      Z: G d  d!e8      Z; G d" d#e8      Z< G d$ d%e0jz                        Z= G d& d'e0j|                        Z> G d( d)e0j~                        Z?yc c} w )*ar  Amazon SQS transport module for Kombu.

This package implements an AMQP-like interface on top of Amazons SQS service,
with the goal of being optimized for high performance and reliability.

The default settings for this module are focused now on high performance in
task queue situations where tasks are small, idempotent and run very fast.

SQS Features supported by this transport
========================================
Long Polling
------------
https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-long-polling.html

Long polling is enabled by setting the `wait_time_seconds` transport
option to a number > 1.  Amazon supports up to 20 seconds.  This is
enabled with 10 seconds by default.

Batch API Actions
-----------------
https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-batch-api.html

The default behavior of the SQS Channel.drain_events() method is to
request up to the 'prefetch_count' messages on every request to SQS.
These messages are stored locally in a deque object and passed back
to the Transport until the deque is empty, before triggering a new
API call to Amazon.

This behavior dramatically speeds up the rate that you can pull tasks
from SQS when you have short-running tasks (or a large number of workers).

When a Celery worker has multiple queues to monitor, it will pull down
up to 'prefetch_count' messages from queueA and work on them all before
moving on to queueB.  If queueB is empty, it will wait up until
'polling_interval' expires before moving back and checking on queueA.

Message Attributes
-----------------
https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-metadata.html

SQS supports sending message attributes along with the message body.
To use this feature, you can pass a 'message_attributes' as keyword argument
to `basic_publish` method.

Other Features supported by this transport
==========================================
Predefined Queues
-----------------
The default behavior of this transport is to use a single AWS credential
pair in order to manage all SQS queues (e.g. listing queues, creating
queues, polling queues, deleting messages).

If it is preferable for your environment to use multiple AWS credentials, you
can use the 'predefined_queues' setting inside the 'transport_options' map.
This setting allows you to specify the SQS queue URL and AWS credentials for
each of your queues. For example, if you have two queues which both already
exist in AWS) you can tell this transport about them as follows:

.. code-block:: python

    transport_options = {
      'predefined_queues': {
        'queue-1': {
          'url': 'https://sqs.us-east-1.amazonaws.com/xxx/aaa',
          'access_key_id': 'a',
          'secret_access_key': 'b',
          'backoff_policy': {1: 10, 2: 20, 3: 40, 4: 80, 5: 320, 6: 640}, # optional
          'backoff_tasks': ['svc.tasks.tasks.task1'] # optional
        },
        'queue-2.fifo': {
          'url': 'https://sqs.us-east-1.amazonaws.com/xxx/bbb.fifo',
          'access_key_id': 'c',
          'secret_access_key': 'd',
          'backoff_policy': {1: 10, 2: 20, 3: 40, 4: 80, 5: 320, 6: 640}, # optional
          'backoff_tasks': ['svc.tasks.tasks.task2'] # optional
        },
      }
    'sts_role_arn': 'arn:aws:iam::<xxx>:role/STSTest', # optional
    'sts_token_timeout': 900, # optional
    'sts_token_buffer_time': 0, # optional, added in 5.6.0
    }

Note that FIFO and standard queues must be named accordingly (the name of
a FIFO queue must end with the .fifo suffix).

backoff_policy & backoff_tasks are optional arguments. These arguments
automatically change the message visibility timeout, in order to have
different times between specific task retries. This would apply after
task failure.

AWS STS authentication is supported, by using sts_role_arn, and
sts_token_timeout. sts_role_arn is the assumed IAM role ARN we are trying
to access with. sts_token_timeout is the token timeout, defaults (and minimum)
to 900 seconds. After the mentioned period, a new token will be created.

.. versionadded:: 5.6.0
    sts_token_buffer_time (seconds) is the time by which you want to refresh your token
    earlier than its actual expiration time, defaults to 0 (no time buffer will be added),
    should be less than sts_token_timeout.



If you authenticate using Okta_ (e.g. calling |gac|_), you can also specify
a 'session_token' to connect to a queue. Note that those tokens have a
limited lifetime and are therefore only suited for short-lived tests.

.. _Okta: https://www.okta.com/
.. _gac: https://github.com/Nike-Inc/gimme-aws-creds#readme
.. |gac| replace:: ``gimme-aws-creds``


Client config
-------------
In some cases you may need to override the botocore config. You can do it
as follows:

.. code-block:: python

    transport_option = {
      'client-config': {
          'connect_timeout': 5,
       },
    }

For a complete list of settings you can adjust using this option see
https://botocore.amazonaws.com/v1/documentation/api/latest/reference/config.html

Features
========
* Type: Virtual
* Supports Direct: Yes
* Supports Topic: Yes
* Supports Fanout: Yes
* Supports Priority: No
* Supports TTL: No
    )annotationsN)datetime	timedeltatimezone)JSONDecodeError)Empty)Any)Config)ClientError)ensure_promisepromise	transform)get_event_loop)boto3
exceptions)AsyncSQSConnection)AsyncMessage)
get_logger)
scheduling)bytes_to_strsafe_str)dumpsloads)cached_property   )virtualz-_._   -   .   
   c                <    	 t        |       S # t        $ r | cY S w xY w)z5Try to convert x' to int, or return x' if that fails.)int
ValueError)xs    o/var/www/html/wine-match-dev/backend/winematch-backend/venv/lib/python3.12/site-packages/kombu/transport/SQS.py	maybe_intr&      s$    1v s   
 c                      e Zd ZdZy)UndefinedQueueExceptionzAPredefined queues are being used and an undefined queue was used.N__name__
__module____qualname____doc__     r%   r(   r(      s    Kr/   r(   c                      e Zd ZdZy)InvalidQueueExceptionz@Predefined queues are being used and configuration is not valid.Nr)   r.   r/   r%   r1   r1      s    Jr/   r1   c                      e Zd ZdZy)AccessDeniedQueueExceptionzRaised when access to the AWS queue is denied.

    This may occur if the permissions are not correctly set or the
    credentials are invalid.
    Nr)   r.   r/   r%   r3   r3      s    r/   r3   c                      e Zd ZdZy)DoesNotExistQueueExceptionz"The specified queue doesn't exist.Nr)   r.   r/   r%   r5   r5      s    ,r/   r5   c                  6     e Zd ZdZd fd	Zd Zd Zd Z xZS )QoSz5Quality of Service guarantees implementation for SQS.c                    t         |   ||       | j                  |      \  }}}}|r|r|r|r| j                  ||||       y y y y y )N)requeue)superreject1_extract_backoff_policy_configuration_and_messageapply_backoff_policy)selfdelivery_tagr9   routing_keymessagebackoff_tasksbackoff_policy	__class__s          r%   r;   z
QoS.reject   s`    |W5BB 	<Wm^ 7}%%\>=J :H}7;r/   c                   	 | j                   |   }|j                  d   }|r|sy| j                  j                  j                  |i       }|j                  d      }|j                  d      }||||fS # t        $ r Y yw xY w)Nr@   )NNNNrB   rC   )
_delivereddelivery_infoKeyErrorchannelpredefined_queuesget)r>   r?   rA   r@   queue_configrB   rC   s          r%   r<   z5QoS._extract_backoff_policy_configuration_and_message   s    	*ool3G!//>K ')||5599+rJ$((9%))*:;G]NBB  	*)	*s   A3 3	A?>A?c                    | j                   j                  |   }| j                  |      \  }}|r|sy |j                  |      }||v r3|0| j                   j	                  |      }	|	j                  |||       y y y )NQueueUrlReceiptHandleVisibilityTimeout)rI   _queue_cache'extract_task_name_and_number_of_retriesrK   sqschange_message_visibility)
r>   r@   r?   rC   rB   	queue_url	task_namenumber_of_retriespolicy_valuecs
             r%   r=   zQoS.apply_backoff_policy   s    LL--k:	88F 	%	$ 1%))*;<%,*B  -A''"*". (  +C%r/   c                    | j                   |   }|j                  }|d   }t        |j                  d   d   d   d         }||fS )NtaskrG   sqs_message
AttributesApproximateReceiveCount)rF   headersr"   
properties)r>   r?   rA   message_headersrW   rX   s         r%   rS   z+QoS.extract_task_name_and_number_of_retries   sa    //,/!//#F+	/>+--FHI +++r/   F)	r*   r+   r,   r-   r;   r<   r=   rS   __classcell__rD   s   @r%   r7   r7      s    ?JC ,r/   r7   c                      e Zd ZdZdZdZdZdZdZi Z	dZ
i Zi Z e       ZeZ ej"                  d      Z fdZd	 Zd
 Z fdZ fdZdBdZd ZefdZd Zd Zd Zd Zd Z d Z!d Z"d Z#	 	 dC	 	 	 	 	 dDdZ$e%dfdZ&d Z'dEdZ(d Z)e%fdZ*dEdZ+dCdZ,d  Z-	 dCd!Z.	 dF fd"	Z/dG fd#	Z0d$ Z1d% Z2 fd&Z3	 dEd'Z4dEd(Z5d) Z6dHd*Z7d+ Z8d, Z9dEd-Z:e;d.        Z<e;d/        Z=e>d0        Z?e>d1        Z@e>d2        ZAe>d3        ZBe>d4        ZCe>d5        ZDe>d6        ZEe>d7        ZFe>d8        ZGe>dId9       ZHe>d:        ZIe>d;        ZJe;dJd<       ZKdKd=ZLd> ZMd? ZNd@ ZOdA ZP xZQS )LChannelzSQS Channel.z	us-east-1i  r    zkombu%(vhost)sNs@   ^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$c                    t         t        d      t        |   |i | | j	                          | j                  | j                         |j                  d      xs
 t               | _	        y )Nzboto3 is not installedhub)
r   ImportErrorr:   __init___validate_predifined_queues_update_queue_cachequeue_name_prefixrK   r   ri   )r>   argskwargsrD   s      r%   rk   zChannel.__init__  s`    =677$)&)((* 	  !7!78::e$8(8r/   c                   | j                   j                         D ]n  \  }}|d   j                  d      }|j                  d      }|r|st        dj	                  |d               |rO|sRt        dj	                  ||d                y)zCheck that standard and FIFO queues are named properly.

        AWS requires FIFO queues to have a name
        that ends with the .fifo suffix.
        url.fifoz6Queue with url '{}' must have a name ending with .fifoz.Queue with name '{}' is not a FIFO queue: '{}'N)rJ   itemsendswithr1   format)r>   
queue_nameqfifo_url	fifo_names        r%   rl   z#Channel._validate_predifined_queues#  s     "3399; 	MJx((1H"++G4I	+((.qx(8  )+!6*ah7 	r/   c                :   | j                   r5| j                   j                         D ]  \  }}|d   | j                  |<    y | j                         j	                  |      }|j                  dg       D ]%  }|j                  d      d   }|| j                  |<   ' y )Nrr   )QueueNamePrefix	QueueUrls/)rJ   rt   rR   rT   list_queuesrK   split)r>   rn   rw   rx   resprr   s         r%   rm   zChannel._update_queue_cache7  s    !!!%!7!7!=!=!? 9
A01%!!*-9xxz%%6G%H88K, 	0C3+J,/Dj)	0r/   c                    |r| j                   j                  |       | j                  r| j                  |       t	        |   ||g|i |S N)_noack_queuesaddri   _loop1r:   basic_consume)r>   queueno_ackro   rp   rD   s        r%   r   zChannel.basic_consumeB  sT    ""5)88KKw$6
 
$*
 	
r/   c                    || j                   v r*| j                  |   }| j                  j                  |       t        |   |      S r   )
_consumers_tag_to_queuer   discardr:   basic_cancel)r>   consumer_tagr   rD   s      r%   r   zChannel.basic_cancelK  sC    4??*&&|4E&&u-w#L11r/   c                    | j                   r| j                  j                         s
t               | j	                  | j
                  ||       y)zReturn a single payload message from one of our queues.

        Raises
        ------
            Queue.Empty: if no messages available.
        )timeoutN)r   qoscan_consumer   _pollcycle)r>   r   callbackrp   s       r%   drain_eventszChannel.drain_eventsQ  s9     dhh&:&:&<'M 	

4::x
9r/   c                l    t        j                  | j                  | j                  t              | _        y)aA  Reset the consume cycle.

        Returns
        -------
            FairCycle: object that points to our _get_bulk() method
                rather than the standard _get() method.  This allows for
                multiple messages to be returned at once from SQS (
                based on the prefetch limit).
        N)r   	FairCycle	_get_bulk_active_queuesr   _cycler>   s    r%   _reset_cyclezChannel._reset_cycle_  s'     !**NND//
r/   c                    |j                  d      r7|dt        d        }t        t        |            j	                  |      }|dz   S t        t        |            j	                  |      S )z3Format AMQP queue name into a legal SQS queue name.rs   N)ru   lenstrr   	translate)r>   nametablepartials       r%   entity_namezChannel.entity_namem  s_    ==!>S\M*G(7+,66u=GW$$x~&0077r/   c                >    | j                  | j                  |z         S r   )r   rn   )r>   rw   s     r%   canonical_queue_namezChannel.canonical_queue_namev  s     6 6 CDDr/   c                   | j                  |      }|| j                  vr| j                  |       	 | j                  |   S # t        $ r6 | j                  rt        dj                  |            t        d| d      w xY w)z9Try to retrieve the SQS queue URL for a given queue name.<Queue with name '{}' must be defined in 'predefined_queues'.Queue with name 'z' doesn't exist in SQS)r   rR   rm   rH   rJ   r(   rv   r5   )r>   r   	sqs_qnames      r%   _resolve_queue_urlzChannel._resolve_queue_urly  s     --e4	 D---$$Y/	$$Y// 		%%-6&#% %
 -#I;.DE 		s   A ?B c                   	 | j                  |      S # t        $ rj | j                  |      }dt        | j                        i}|j                  d      rd|d<   | j                  ||      }|d   | j                  |<   |d   cY S w xY w)zEnsure a queue with given name exists in SQS.

        Arguments:
        ---------
            queue (str): the AMQP queue name
        Returns
            str: the SQS queue URL
        rQ   rs   true	FifoQueuerO   )r   r5   r   r   visibility_timeoutru   _create_queuerR   )r>   r   rp   r   
attributesr   s         r%   
_new_queuezChannel._new_queue  s    
	$**511) 	$11%8I-s43J3J/KLJ!!'**0
;'%%i<D+/
+;Di(
##	$s    A0BBc                
   | j                   ry|j                  | j                  j                  d      xs i        | j                  j                  d      }||d}|r||d<    | j	                  |      j
                  di |S )z=Create an SQS queue with a given name and nominal attributes.Nzsqs-creation-attributes
queue_tags)	QueueNamer^   tagsr   r.   )rJ   updatetransport_optionsrK   rT   create_queue)r>   rw   r   r   create_paramss        r%   r   zChannel._create_queue  s     !!""&&'@AGR	
 ++//=
 $$

 $.M&!6txxjx)66GGGr/   c                    | j                   ry| j                  |      }| j                         j                  |       | j                  j                  |d       y)zDelete queue by name.NrO   )rJ   r   rT   delete_queuerR   pop)r>   r   ro   rp   q_urls        r%   _deletezChannel._delete  sR    !!''.
 	  	
 	eT*r/   c                   | j                  |      }d|i}d|v rd|d   v r|d   j                  d      |d<   |j                  d      rLd|d   v r|d   d   |d<   nd|d<   d|d   v r|d   d   |d<   n3t        t	        j
                               |d<   nd	|d   v r|d   d	   |d	<   | j                  r#t               j                  t        |            }nt        |      }||d
<   | j                  | j                  |            }|j                  d      r%|j                  ||d   d   | j                         y |j                  di | y)zPut message onto queue.rO   ra   message_attributesMessageAttributesrs   MessageGroupIddefaultMessageDeduplicationIdDelaySecondsMessageBodyr   redeliveredr?   rN   Nr.   )r   r   ru   r   uuiduuid4sqs_base64_encodingr   encoder   rT   r   rK   rU   wait_time_secondssend_message)r>   r   rA   rp   r   bodyrZ   s          r%   _putzChannel._put  s   &e$7"#w|'<< L)--.BC *+~~g&#w|'<<-.>? +, 09F+,+w|/DD-.FG 34 8;4::<7HF34!W\%::-n= >* ##>((w8D>D $}HH444U;H<;;}%''%l3NC"&"8"8 (  ANN$V$r/   c                    |d   }| j                  |      }t        |      }| j                  |      }|| j                  v r| j	                  ||       |S | j                  ||||      S )NBody)_decode_python_message_bodyr   _prepare_json_payloadr   _delete_message_envelope_payload)r>   rA   rw   r   raw_msg_bodydecoded_bytestextpayloads           r%   _message_to_pythonzChannel._message_to_python  sq    v88FM*,,T2 +++  W5N%%gtWeDDr/   c                p    | j                  |      }|D cg c]  }| j                  |||       c}S c c}w )a  Convert a list of SQS Message objects into Payloads.

        This method handles converting SQS Message objects into
        Payloads, and appropriately updating the queue depending on
        the 'ack' settings for that queue.

        Arguments:
        ---------
            messages (SQSMessage): A list of SQS Message objects.
            queue (str): Name representing the queue they came from.

        Returns
        -------
            List: A list of Payload objects
        )r   r   )r>   messagesr   r   ms        r%   _messages_to_pythonzChannel._messages_to_python   s5      &BJKQ''5%8KKKs   3c                   | j                  |      }| j                  |      }| j                  j                  d      }| j                  j                  d      }|||xs | j                  ||d} |j
                  di |S )aM  Unified receive_message wrapper for SQS (boto3.client.SQS) with full attribute support.

        :param queue: The queue as a string
        :param max_number_of_messages: Int of max number of messages to receive.
        :param wait_time_seconds: Int of sqs wait time in seconds.
        :return: SQS client recieve_message
        r   MessageSystemAttributeNamesMessageAttributeNames)rO   MaxNumberOfMessagesWaitTimeSecondsr   r   r.   )r   rT   get_message_attributesrK   r   receive_message)	r>   r   max_number_of_messagesr   r   clientmessage_system_attribute_namesmessage_attribute_namesparamss	            r%   _receive_messagezChannel._receive_message  s     __U+&)-)D)D)H)H)*+&"&"="="A"A##% #90JD4J4J%<+I"
 &v%%///r/   c                Z   | j                         }|r| j                  || j                  |      }|j                  d      ra|d   D ]"  }t	        |d         j                         |d<   $ | j                  |d   |      D ]  }| j                  j                  ||         yt               )a;  Try to retrieve multiple messages off ``queue``.

        Where :meth:`_get` returns a single Payload object, this method
        returns a list of Payload objects.  The number of objects returned
        is determined by the total number of messages available in the queue
        and the number of messages the QoS object allows (based on the
        prefetch_count).

        Note:
        ----
            Ignores QoS limits so caller is responsible for checking
            that we are allowed to consume at least one message from the
            queue.  get_bulk will then ask QoS for an estimate of
            the number of extra messages that we can consume.

        Arguments:
        ---------
            queue (str): The queue name to pull from.

        Returns
        -------
            List[Message]
        r   r   r   Messagesr   r   N)
_get_message_estimater   r   rK   r   decoder   
connection_deliverr   )r>   r   max_if_unlimitedr   	max_countr   r   msgs           r%   r   zChannel._get_bulk2  s    < ..0	(("&"8"8'0 ) D xx
#j) FA ,!F) < C C EAfIF33D4DeL 9COO,,S%89gr/   c                    | j                  || j                  d      }|j                  d      rFt        |d   d   d         j	                         }||d   d   d<   | j                  |d   |      d   S t               )z/Try to retrieve a single message off ``queue``.r   r   r   r   r   r   )r   r   rK   r   r   r   r   )r>   r   r   r   s       r%   _getzChannel._get`  s    $$"44#$ % 
 88JT*%5a%8%@AHHJD*.DQ'++D,<eDQGGgr/   c                P    | j                   j                  | j                  |       y r   )ri   	call_soon_schedule_queue)r>   r   _s      r%   r   zChannel._loop1n  s    4//7r/   c                    || j                   v rU| j                  j                         r)| j                  |t	        | j
                  |f             y | j                  |       y y N)r   )r   r   r   _get_bulk_asyncr   r   )r>   r   s     r%   r  zChannel._schedule_queueq  sX    D'''xx##%$$GDKK%$B %  E" (r/   c                t    | j                   j                         }t        |||      S t        |d      |      S )Nr   )r   can_consume_max_estimateminmax)r>   r   maxcounts      r%   r   zChannel._get_message_estimatez  sD    88446 ( 0
 	
69(A6F
 	
r/   c                x    | j                         }|r| j                  |||      S t        |      } |g        |S r  )r   
_get_asyncr   )r>   r   r   r
  s       r%   r  zChannel._get_bulk_async  s>    --/??5(X?FF!(+r/   c                    | j                  |      }| j                  |      }| j                  |||| j                  |      t	        | j
                  |||            S )Nr   )rw   rV   countr   r   )r   r   _get_from_sqsasynsqsr   _on_messages_ready)r>   r   r  r   r   qnames         r%   r  zChannel._get_async  sd    &))%0!!U||%|0''5% " 
 	
r/   c                    d|v rE|d   r?| j                   j                  }|d   D ]   }| j                  |||      } ||   |       " y y y )Nr   )r   
_callbacksr   )r>   r   r  r   	callbacksr   
msg_parseds          r%   r  zChannel._on_messages_ready  s_    !hz&:22I
+ -!44S%G
 	% ,- ';!r/   c                B    |j                  |||| j                  |      S )zwRetrieve and handle messages from SQS.

        Uses long polling and returns :class:`~vine.promises.promise`.
        )number_messagesr   r   )r   r   )r>   rw   rV   r   r  r   s         r%   r  zChannel._get_from_sqs  s/     ))	5"44 * 
 	
r/   c                h    |D ]  }|j                   j                  |d          t        |   |      S r   )rG   r   r:   _restore)r>   rA   unwanted_delivery_infounwanted_keyrD   s       r%   r  zChannel._restore  s:    2 	:L!!%%lD9	: w((r/   c                   	 | j                   j                  |      j                  }|d   }d }d|v r| j                  |d         }	 | j	                  |      j                  |d   |d          t        |   |       y # t        $ rI}|j                  d   d   d	k(  rt        |j                  d   d
         t        | -  |       Y d }~y d }~ww xY w# t        $ r t        |   |       Y y w xY w)Nr]   r@   r   	sqs_queuerP   )rO   rP   ErrorCodeAccessDeniedMessage)r   rK   rG   r   rT   delete_messager:   	basic_ackr   responser3   basic_rejectrH   )r>   r?   multiplerA   r]   r   	exceptionrD   s          r%   r$  zChannel.basic_ack  s	   	0hhll<0>>G!-0K E'11'-2HI0u%44$[1"-o"> 5  !,/  3%%g.v6.H4!**73I>  $\223  	,Gl+	,s)   *C )B 	C
?CCC10C1c                    | j                  |      }| j                  | j                  |            }|j                  |dg      }t	        |d   d         S )z)Return the number of messages in a queue.r   ApproximateNumberOfMessages)rO   AttributeNamesr^   )r   rT   r   get_queue_attributesr"   )r>   r   r   rZ   r   s        r%   _sizezChannel._size  sa    &HH444U;H<%%9: & < 4%&CDEEr/   c                    | j                  |      }d}t        d      D ]#  }|t        | j                  |            z  }|r# n | j	                  |      j                  |       |S )z'Delete all current messages in a queue.r   r    r   r   )r   ranger"   r-  rT   purge_queue)r>   r   r   sizeis        r%   _purgezChannel._purge  sk    & r 	AC

5)**D	 	u))5)9r/   c                "    t         |           y r   )r:   close)r>   rD   s    r%   r5  zChannel.close  s    r/   c                6   t         j                  j                  ||||      }| j                  | j                  nd}d|i}| j                  | j                  |d<   | j
                  j                  d      xs i }t        di |}	 |j                  dd|	i|S )	N)region_nameaws_access_key_idaws_secret_access_keyaws_session_tokenTuse_sslendpoint_urlzclient-configconfigr.   )rT   )	r   sessionSession	is_securer<  r   rK   r
   r   )
r>   regionaccess_key_idsecret_access_keysession_tokenr>  r@  client_kwargsclient_configr=  s
             r%   new_sqs_clientzChannel.new_sqs_client  s    --''+"3+	 ( 
 '+nn&@DNNd	y
 (,0,=,=M.)..22?CIr(-(w~~DFDmDDr/   c                    |%| j                   r|| j                   vrt        d| d      | j                   |   }| j                  j                  d      r| j	                  ||      S | j                  j                  d      s|| j
                  v r| j
                  |   S | j                  |j                  d| j                        |j                  d| j                  j                        |j                  d| j                  j                              x}| j
                  |<   |S | j                  | j                  S | j                  | j                  | j                  j                  | j                  j                        x}| _        |S )Nr   z)' must be defined in 'predefined_queues'.sts_role_arnrA  rB  rC  )rA  rB  rC  )rJ   r(   r   rK   _handle_sts_session_predefined_queue_clientsrG  rA  conninfouseridpassword_sqs)r>   r   rx   rZ   s       r%   rT   zChannel.sqs  s|   !7!7D222-'w // /0 0 &&u-A%%)).9//q99))--n=D:::99%@@ ++#$554;;#?*+%% /1E1E+G./ee 3T]]5K5K/M	 , A66u= H99 99++;;--.."mm44 , 
 	
DI
 r/   c                   |j                  d| j                        }t        | d      s| j                  ||      S | j                  j                  d       t        j                  t        j                        j                  d       k  r| j                  ||      S || j                  vr| j                  ||      S | j                  |   S )NrA  sts_expiration)tzinfo)rK   rA  hasattr-_new_predefined_queue_client_with_sts_sessionrQ  replacer   nowr   utcrK  )r>   r   rx   rA  s       r%   rJ  zChannel._handle_sts_session  s    x-t-.EEeVTT  (((5X\\8R8Z8Zbf8Z8ggEEeVTTD:::II%QWXX11%88r/   c                z    | j                  ||      }|r&d|cxk  r|k  rn |S |dxx   t        |      z  cc<   |S )zGenerate STS session credentials with an optional expiration buffer.

        The buffer is only applied if it is less than `token_expiry_seconds` to prevent an expired token.
        r   
Expiration)seconds)generate_sts_session_tokenr   )r>   role_arntoken_expiry_secondstoken_buffer_secondscredentialss        r%   &generate_sts_session_token_with_bufferz.Channel.generate_sts_session_token_with_buffer'  sL    
 55h@TUA(<$S?S$S %;O)PP%r/   c                4   | j                  | j                  j                  d      | j                  j                  dd      | j                  j                  dd            }|d   | _        | j	                  ||d   |d   |d	   
      x}| j
                  |<   |S )NrI  sts_token_timeouti  sts_token_buffer_timer   rY  AccessKeyIdSecretAccessKeySessionToken)rA  rB  rC  rD  )r`  r   rK   rQ  rG  rK  )r>   r   rA  	sts_credsrZ   s        r%   rT  z5Channel._new_predefined_queue_client_with_sts_session1  s    ??""&&~6""&&':C@""&&'>B
	
 (5484G4G#M2'(9:#N3	 5H 5
 	
D**51 r/   c                ^    t        j                  d      }|j                  |d|      }|d   S )NstsCelery)RoleArnRoleSessionNameDurationSecondsCredentials)r   r   assume_role)r>   r\  r]  
sts_client
sts_policys        r%   r[  z"Channel.generate_sts_session_token@  s;    \\%(
++$0 , 


 -((r/   c                r   | j                   j                  d      }| j                   j                  d      }|| j                  r|| j                  v rt	        | d      s| j                  |   S || j                  vrt        dj                  |            | j                  |   }t        | j                  |      |j                  d| j                        ||      x}| j                  |<   |S | j                  | j                  S t        | j                  |      | j                  ||      x}| _
        |S )Nr   r   rQ  r   r   rA  )sqs_connectionrA  r   r   )r   rK   rJ   _predefined_queue_async_clientsrS  r(   rv   r   rT   rA  _asynsqs)r>   r   r   r   rx   rZ   s         r%   r  zChannel.asynsqsI  s=   )-)D)D)H)H)*+&"&"="="A"A##% !7!7<<<4!12;;EBBD222-+&-! ! &&u-A"#'88%8#8554;;73Q,C	A44U; H==$== .88%80;;+I$;	
 	
DM r/   c                .    | j                   j                  S r   )r   r   r   s    r%   rL  zChannel.conninfom  s    %%%r/   c                B    | j                   j                  j                  S r   )r   r   r   r   s    r%   r   zChannel.transport_optionsq  s    %%777r/   c                T    | j                   j                  d      xs | j                  S )Nr   )r   rK   default_visibility_timeoutr   s    r%   r   zChannel.visibility_timeoutu  s*    &&**+?@ 0//	1r/   c                :    | j                   j                  di       S )z/Map of queue_name to predefined queue settings.rJ   r   rK   r   s    r%   rJ   zChannel.predefined_queuesz  s     %%))*=rBBr/   c                :    | j                   j                  dd      S )Nrn    r{  r   s    r%   rn   zChannel.queue_name_prefix  s    %%))*=rBBr/   c                     y)NFr.   r   s    r%   supports_fanoutzChannel.supports_fanout  s    r/   c                    | j                   j                  d      xs, t        j                         j                  xs | j
                  S )NrA  )r   rK   r   r?  r7  default_regionr   s    r%   rA  zChannel.region  s=    &&**84 $++$##	%r/   c                8    | j                   j                  d      S )N
regioninfor{  r   s    r%   r  zChannel.regioninfo  s    %%)),77r/   c                8    | j                   j                  d      S )Nr@  r{  r   s    r%   r@  zChannel.is_secure  s    %%))+66r/   c                8    | j                   j                  d      S Nportr{  r   s    r%   r  zChannel.port  s    %%))&11r/   c                   | j                   j                  i| j                  rdnd}| j                   j                  d| j                   j                   }nd}dj	                  || j                   j                  |      S y )Nhttpshttp:r}  z	{}://{}{})rL  hostnamer@  r  rv   )r>   schemer  s      r%   r<  zChannel.endpoint_url  sv    ==!!- $WFF}}!!-4==--./%%&&  .r/   c                N    | j                   j                  d| j                        S )Nr   )r   rK   default_wait_time_secondsr   s    r%   r   zChannel.wait_time_seconds  s)    %%))*=*.*H*HJ 	Jr/   c                :    | j                   j                  dd      S )Nr   Tr{  r   s    r%   r   zChannel.sqs_base64_encoding  s    %%))*?FFr/   c                :    | j                   j                  dd       S )Nfetch_message_attributesr{  r   s    r%   r  z Channel.fetch_message_attributes  s    %%))*DdKKr/   c                4   d}| j                   }d}d}|t        |t              rd|gdS t        |t              rJdj	                         |D cg c]  }|j	                          c}v rdgnt        t        ||gz               }nt        |t              r|j                  dg       }|j                  dd      }t        |t              rIdj	                         |D cg c]  }|j	                          c}v rdgnt        t        ||gz               }t        |t              rG|rEdj	                         |D cg c]  }|j	                          c}v rdgnt        t        |            }|rt        |      nd|rt        |      dS |gdS c c}w c c}w c c}w )a  Get the message attributes to be fetched from SQS.

        Ensures 'ApproximateReceiveCount' is included in system attributes if list is provided.
        - The number of retries is managed by SQS /
            (specifically by the ``ApproximateReceiveCount`` message attribute)
        - See: class QoS(virtual.QoS):
            (method) def extract_task_name_and_number_of_retries

        :return: A dictionary with SQS message attribute fetch config.
        r_   N)r   r   ALLr   r   )	r  
isinstancer   listlowersetdictrK   sorted)r>   APPROXIMATE_RECEIVE_COUNTfetchmessage_system_attrsmessage_attrsssystemattrss           r%   r   zChannel.get_message_attributes  s    %>!--#=Juc2)-0I/J 
 eT".3kkmSX?Ya	?Y.YE7S";!<<=> ! t$YY<bAFII5t<E&$'27++-W]C^RSAGGIC^2^wV'@&AABC % %&5+0;;=PU<V1QWWY<V+VU$ 
 ?LVM%:QU0D+,
 	
 LeJe
 	
% @Z D_
 =Ws   FF7Fc                   |j                         }| j                  j                  |      |S 	 t        j                  |d      }t        j                  |      j                  d      }||j                  d      k7  r|S 	 |j                  d       |S # t
        j                  t        f$ r |cY S w xY w# t        $ r |cY S w xY w)zOptionally decode a base64 encoded string.

        :param raw: The raw bytes object to decode.
        :return: Bytes of the optionally decoded raw input.
        T)validate   =zutf-8)strip	B64_REGEX	fullmatchbase64	b64decodebinasciir  r#   	b64encoderstripr   UnicodeDecodeError)r>   raw	candidatedecoded	reencodeds        r%   _optional_b64_decodezChannel._optional_b64_decode  s     IIK	>>##I.6J	&&y4@G $$W-44T:		((..J	NN7#  
+ 	J	 " 	J	s#   B B5 B21B25CCc                h    t        |t              r|j                         n|}| j                  |      S )zDecode the message body when needed.

        raw_body: bytes or str
        returns: bytes (decoded Base64 if it looks like Base64, otherwise raw bytes)
        )r  r   r   r  )r>   raw_bodybs      r%   r   z#Channel._decode_python_message_body  s,     ",Hc!:HOO((++r/   c                p    	 t        |      }t        |t              r|S i S # t        t        f$ r i cY S w xY w)z:Try to JSON-decode text into a dict; on failure return {}.)r   r  r  r   	TypeError)r>   r   datas      r%   r   zChannel._prepare_json_payload  s=    	;D%dD149r9+ 	I	s   ! ! 55c                p    | j                  |      }| j                  |      j                  ||d          y)z9Move the message over to the new queue URL and delete it.r   rP   N)r   r  r#  )r>   rw   rA   new_qs       r%   r   zChannel._delete_message  s3    
+:&557?+	
r/   c                    d|vr|di id}|j                  di       }|j                  di       }|j                  ||d       |d   |d<   |S )a  Prepare the payload envelope.

        Ensure we have a dict with 'body' and 'properties.delivery_info',
        then stamp on SQS-specific metadata.

        :param payload: The payload as an object
        :param raw_text: Text that will be set as the payload body.
        :param message: A kombu Message.
        :param q_url: The SQS queue URL.

        :return: Payload object.
        ra   rG   )r   ra   r]   r  rP   r?   )
setdefaultr   )r>   r   raw_textrA   r   propsdis          r%   r   zChannel._envelope_payload  ss     w& .3G
 ""<4or2 			" 
 	 !( 8nr/   )NN)r   N)r   r   r   r"   r   z
int | Noner   )r  rc   )r   )returnr"   )r  zdict[str, Any])r  bytesr  r  )Rr*   r+   r,   r-   r  ry  r  domain_formatru  rt  rO  rK  rR   r  r   r7   recompiler  rk   rl   rm   r   r   r   r   CHARS_REPLACE_TABLEr   r   r   r   r   r   r   r   r   r   SQS_MAX_MESSAGESr   r   r   r  r   r  r  r  r  r  r$  r-  r3  r5  rG  rT   rJ  r`  rT  r[  r  propertyrL  r   r   r   rJ   rn   r  rA  r  r@  r  r<  r   r   r  r   r  r   r   r   r   rd   re   s   @r%   rg   rg     s    N!% "$MH&(#D "LEM
C

_`I9(	0
2:
 ': 8E2$*H.	+'%REL, '((,	00 !$0 &	0@ $4d,\8# 6F 
	
- 59

 )E)02F 9=E$ D
9)"H & & 8 8 1 1 C C C C   % %
 8 8 7 7 2 2   J J G G L L .
 .
h6,
r/   rg   c                  :   e Zd ZdZeZdZdZdZej                  j                  ej                  ej                  fz   Z
ej                  j                  ej                  fz   ZdZdZej                  j$                  j'                  d edg            Zed	        Zy)
	TransportaJ
  SQS Transport.

    Additional queue attributes can be supplied to SQS during queue
    creation by passing an ``sqs-creation-attributes`` key in
    transport_options. ``sqs-creation-attributes`` must be a dict whose
    key-value pairs correspond with Attributes in the
    `CreateQueue SQS API`_.

    For example, to have SQS queues created with server-side encryption
    enabled using the default Amazon Managed Customer Master Key, you
    can set ``KmsMasterKeyId`` Attribute. When the queue is initially
    created by Kombu, encryption will be enabled.

    .. code-block:: python

        from kombu.transport.SQS import Transport

        transport = Transport(
            ...,
            transport_options={
                'sqs-creation-attributes': {
                    'KmsMasterKeyId': 'alias/aws/sqs',
                },
            }
        )

    .. _CreateQueue SQS API: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_CreateQueue.html#API_CreateQueue_RequestParameters

    .. versionadded:: 5.6
    Queue tags can be applied to SQS queues during creation by passing an
    ``queue_tags`` key in transport_options. ``queue_tags`` must be
    a dict of tag key-value pairs.

    .. code-block:: python

        from kombu.transport.SQS import Transport

        transport = Transport(
            ...,
            transport_options={
                'queue_tags': {
                    'Environment': 'production',
                    'Team': 'backend',
                },
            }
        )

    The ``ApproximateReceiveCount`` message attribute is fetched by this
    transport by default. Requested message attributes can be changed by
    setting ``fetch_message_attributes`` in the transport options.

    .. code-block:: python

        from kombu.transport.SQS import Transport

        transport = Transport(
            ...,
            transport_options={
                'fetch_message_attributes': ["All"],  # Get all of the MessageSystemAttributeNames (formerly AttributeNames)
            }
        )
        # Preferred - A dict specifying system and custom message attributes
        transport = Transport(
            ...,
            transport_options={
                'fetch_message_attributes': {
                    'MessageSystemAttributeNames': ["SenderId", "SentTimestamp"],
                    'MessageAttributeNames': ['S3MessageBodyKey']
                },
            }
        )
    .. _Message Attributes: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html#SQS-ReceiveMessage-request-AttributeNames

    r   r   NrT   Tdirect)asynchronousexchange_typec                    d| j                   iS r  )default_portr   s    r%   default_connection_paramsz#Transport.default_connection_params  s    ))**r/   )r*   r+   r,   r-   rg   polling_intervalr   r  r   r  connection_errorsr   BotoCoreErrorsocketerrorchannel_errorsdriver_typedriver_name
implementsextend	frozensetr  r  r.   r/   r%   r  r  =  s    IV GL++		!	!6<<0	1 
 	((J,D,D+FF  KK""--44
+ 5 J
 + +r/   r  )@r-   
__future__r   r  r  r  r  stringr   r   r   r   jsonr   r   r   typingr	   botocore.clientr
   botocore.exceptionsr   viner   r   r   kombu.asynchronousr   kombu.asynchronous.aws.extr   r   %kombu.asynchronous.aws.sqs.connectionr   "kombu.asynchronous.aws.sqs.messager   	kombu.logr   kombu.utilsr   kombu.utils.encodingr   r   kombu.utils.jsonr   r   kombu.utils.objectsr   r}  r   r*   loggerpunctuationordr  r  r&   	Exceptionr(   r1   r3   r5   r7   rg   r  )rZ   s   0r%   <module>r     s  GT #   	    2 2     " + 3 3 - 8 D ;   " 7 ) / 	H	
 !,,CFDL  ! D   Li LKI K - -0,'++ 0,fvgoo vrb+!! b+cs   +	D95D9