
    hvd                       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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Zdd	lmZ dd
lmZ erddlmZ ddlmZ ddlmZ ej.                  j0                  j3                          d*dZ G d d      Z G d d      Z G d d      Z	 	 	 	 	 	 	 d+	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d,dZ	 d-	 	 	 	 	 	 	 d.dZ	 	 	 d/	 	 	 	 	 	 	 	 	 	 	 d0dZ 	 d1	 	 	 d2dZ!	 d1	 	 	 	 	 	 	 d3dZ" G d de#      Z$ G d de$      Z% G d de$      Z& G d  d!e$      Z' G d" d#e$      Z( G d$ d%e$      Z) G d& d'e$      Z* G d( d)e$      Z+y)4aK  This module provides the main client and helper classes for interacting with the Mailjet API.

The `mailjet_rest.client` module includes the core `Client` class for managing
API requests, configuration, and error handling, as well as utility functions
and classes for building request headers, URLs, and parsing responses.

Classes:
    - Config: Manages configuration settings for the Mailjet API.
    - Endpoint: Represents specific API endpoints and provides methods for
      common HTTP operations like GET, POST, PUT, and DELETE.
    - Client: The main API client for authenticating and making requests.
    - ApiError: Base class for handling API-specific errors, with subclasses
      for more specific error types (e.g., `AuthorizationError`, `TimeoutError`).

Functions:
    - prepare_url: Prepares URLs for API requests.
    - api_call: A helper function that sends HTTP requests to the API and handles
      responses.
    - build_headers: Builds HTTP headers for the requests.
    - build_url: Constructs the full API URL based on endpoint and parameters.
    - parse_response: Parses API responses and handles error conditions.

Exceptions:
    - ApiError: Base exception for API errors, with subclasses to represent
      specific error types, such as `AuthorizationError`, `TimeoutError`,
      `ActionDeniedError`, and `ValidationError`.
    )annotationsN)datetime)timezone)Match)TYPE_CHECKING)Any)urljoin)get_version)Callable)Mapping)Responsec                l    | j                  d      }|j                         rd|j                         z   S y)ap  Replace capital letters in the input string with a dash prefix and converts them to lowercase.

    Parameters:
    key (Match[str]): A match object representing a substring from the input string. The substring should contain a single capital letter.

    Returns:
    str: A string containing a dash followed by the lowercase version of the input capital letter.
    r   - )groupisupperlower)key	char_elems     d/home/www/lekema-backend.kofcorporation.com/venv/lib/python3.12/site-packages/mailjet_rest/client.pyprepare_urlr   9   s2     		!IY__&&&    c                  l    e Zd ZU dZdZded<   dZded<   dZded<   d	 e       z   Z	ded
<   dddZ
ddZy)Configa  Configuration settings for interacting with the Mailjet API.

    This class stores and manages API configuration details, including the API URL,
    version, and user agent string. It provides methods for initializing these settings
    and generating endpoint-specific URLs and headers as required for API interactions.

    Attributes:
        DEFAULT_API_URL (str): The default base URL for Mailjet API requests.
        API_REF (str): Reference URL for Mailjet's API documentation.
        version (str): API version to use, defaulting to 'v3'.
        user_agent (str): User agent string including the package version for tracking.
    zhttps://api.mailjet.com/strDEFAULT_API_URLz%https://dev.mailjet.com/email-api/v3/API_REFv3versionzmailjet-apiv3-python/v
user_agentNc                @    ||| _         |xs | j                  | _        y)a  Initialize a new Config instance with specified or default API settings.

        This initializer sets the API version and base URL. If no version or URL
        is provided, it defaults to the predefined class values.

        Parameters:
        - version (str | None): The API version to use. If None, the default version ('v3') is used.
        - api_url (str | None): The base URL for API requests. If None, the default URL (DEFAULT_API_URL) is used.
        N)r   r   api_url)selfr   r"   s      r   __init__zConfig.__init__[   s#     "DL6$"6"6r   c                   t        | j                  | j                  dz         }d| j                  d}|j	                         dk(  rt        |d      }d|d<   nS|j	                         dk(  rt        |d      }d	|d<   n.|j	                         d
k7  r| j                  dk7  rt        |d      }||j                  d      d   j	                         z  }||fS )a  Retrieve the API endpoint URL and headers for a given key.

        This method builds the URL and headers required for specific API interactions.
        The URL is adjusted based on the API version, and additional headers are
        appended depending on the endpoint type. Specific keys modify content-type
        for endpoints expecting CSV or plain text.

        Parameters:
        - key (str): The name of the API endpoint, which influences URL structure and header configuration.

        Returns:
        - tuple[str, dict[str, str]]: A tuple containing the constructed URL and headers required for the specified endpoint.

        Examples:
            For the "contactslist_csvdata" key, a URL pointing to 'DATA/' and a
            'Content-type' of 'text/plain' is returned.
            For the "batchjob_csverror" key, a URL with 'DATA/' and a 'Content-type'
            of 'text/csv' is returned.
        /application/json)Content-typez
User-agentcontactslist_csvdatazDATA/
text/plainr(   batchjob_csverrortext/csvsendv4zREST/_r   )r	   r"   r   r    r   split)r#   r   urlheaderss       r   __getitem__zConfig.__getitem__i   s    , dllDLL3$67.//#
 99;00#w'C&2GN#YY[//#w'C&0GN#YY[F"t||t';#w'Csyy~a &&((G|r   NN)r   
str | Noner"   r5   returnNone)r   r   r6   ztuple[str, dict[str, str]])__name__
__module____qualname____doc__r   __annotations__r   r   r
   r    r$   r3    r   r   r   r   H   sB     6OS5:GS:GS.>J>7$r   r   c                      e Zd ZdZ	 d
	 	 	 	 	 	 	 	 	 ddZ	 	 	 d	 	 	 	 	 	 	 	 	 ddZ	 	 d	 	 	 	 	 	 	 ddZ	 	 	 d	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ	dd	Z
y)Endpointa  A class representing a specific Mailjet API endpoint.

    This class provides methods to perform HTTP requests to a given API endpoint,
    including GET, POST, PUT, and DELETE requests. It manages URL construction,
    headers, and authentication for interacting with the endpoint.

    Attributes:
    - _url (str): The base URL of the endpoint.
    - headers (dict[str, str]): The headers to be included in API requests.
    - _auth (tuple[str, str] | None): The authentication credentials.
    - action (str | None): The specific action to be performed on the endpoint.

    Methods:
    - _get: Internal method to perform a GET request.
    - get_many: Performs a GET request to retrieve multiple resources.
    - get: Performs a GET request to retrieve a specific resource.
    - create: Performs a POST request to create a new resource.
    - update: Performs a PUT request to update an existing resource.
    - delete: Performs a DELETE request to delete a resource.
    Nc                B    ||||f\  | _         | _        | _        | _        y)aD  Initialize a new Endpoint instance.

        Args:
            url (str): The base URL for the endpoint.
            headers (dict[str, str]): Headers for API requests.
            auth (tuple[str, str] | None): Authentication credentials.
            action (str | None): Action to perform on the endpoint, if any.
        N)_urlr2   _authaction)r#   r1   r2   authrC   s        r   r$   zEndpoint.__init__   s#     <?v;U8	4<T[r   c           	     z    t        | j                  d| j                  f| j                  | j                  |||d|S )ae  Perform an internal GET request to the endpoint.

        Constructs the URL with the provided filters and action_id to retrieve
        specific data from the API.

        Parameters:
        - filters (Mapping[str, str | Any] | None): Filters to be applied in the request.
        - action_id (str | None): The specific action ID for the endpoint to be performed.
        - id (str | None): The ID of the specific resource to be retrieved.
        - **kwargs (Any): Additional keyword arguments to be passed to the API call.

        Returns:
        - Response: The response object from the API call.
        get)r2   rC   	action_idfiltersresource_id)api_callrB   rA   r2   rC   )r#   rH   rG   idkwargss        r   _getzEndpoint._get   sJ    * JJII

 LL;;

 

 
	
r   c                ,     | j                   d||d|S )a  Perform a GET request to retrieve multiple resources.

        Parameters:
        - filters (Mapping[str, str | Any] | None): Filters to be applied in the request.
        - action_id (str | None): The specific action ID to be performed.
        - **kwargs (Any): Additional keyword arguments to be passed to the API call.

        Returns:
        - Response: The response object from the API call containing multiple resources.
        )rH   rG   r=   rM   )r#   rH   rG   rL   s       r   get_manyzEndpoint.get_many   s      tyyHIHHHr   c                .     | j                   d|||d|S )a  Perform a GET request to retrieve a specific resource.

        Parameters:
        - id (str | None): The ID of the specific resource to be retrieved.
        - filters (Mapping[str, str | Any] | None): Filters to be applied in the request.
        - action_id (str | None): The specific action ID to be performed.
        - **kwargs (Any): Additional keyword arguments to be passed to the API call.

        Returns:
        - Response: The response object from the API call containing the specific resource.
        )rK   rH   rG   r=   rO   )r#   rK   rH   rG   rL   s        r   rF   zEndpoint.get   s!    $ tyyOB9OOOr   c           
        | j                   j                  d      dk(  r,|*t        j                  ||      }|s|j	                  |      }t        | j                  d| j                  f| j                   ||| j                  ||d|S )a  Perform a POST request to create a new resource.

        Parameters:
        - data (str | bytes | dict[Any, Any] | None): The data to include in the request body.
        - filters (Mapping[str, str | Any] | None): Filters to be applied in the request.
        - id (str | None): The ID of the specific resource to be created.
        - action_id (str | None): The specific action ID to be performed.
        - ensure_ascii (bool): Whether to ensure ASCII characters in the data.
        - data_encoding (str): The encoding to be used for the data.
        - **kwargs (Any): Additional keyword arguments to be passed to the API call.

        Returns:
        - Response: The response object from the API call.
        r(   r'   ensure_asciipost)r2   rI   datarC   rG   rH   	r2   rF   jsondumpsencoderJ   rB   rA   rC   )r#   rV   rH   rK   rG   rT   data_encodingrL   s           r   createzEndpoint.create   s    0 <<N+/AAdFV::)D  {{=1JJII
 LL;;
 
 	
r   c           
        d}| j                   j                  d      dk(  r,|*t        j                  ||      }|s|j	                  |      }t        | j                  d| j                  f|| j                   || j                  ||d|S )a  Perform a PUT request to update an existing resource.

        Parameters:
        - id (str | None): The ID of the specific resource to be updated.
        - data (dict | None): The data to be sent in the request body.
        - filters (Mapping[str, str | Any] | None): Filters to be applied in the request.
        - action_id (str | None): The specific action ID to be performed.
        - ensure_ascii (bool): Whether to ensure ASCII characters in the data.
        - data_encoding (str): The encoding to be used for the data.
        - **kwargs (Any): Additional keyword arguments to be passed to the API call.

        Returns:
        - Response: The response object from the API call.
        Nr(   r'   rS   put)rI   r2   rV   rC   rG   rH   rW   )	r#   rK   rV   rH   rG   rT   r[   rL   	json_datas	            r   updatezEndpoint.update*  s    0 )-	<<N+/AAdFV

4lCI%,,];	JJII
 LL;;
 
 	
r   c                v    t        | j                  d| j                  f| j                  | j                  |d|S )a8  Perform a DELETE request to delete a resource.

        Parameters:
        - id (str | None): The ID of the specific resource to be deleted.
        - **kwargs (Any): Additional keyword arguments to be passed to the API call.

        Returns:
        - Response: The response object from the API call.
        delete)rC   r2   rI   )rJ   rB   rA   rC   r2   )r#   rK   rL   s      r   rb   zEndpoint.deleteT  sD     JJII
 ;;LL
 
 	
r   N)
r1   r   r2   dict[str, str]rD   tuple[str, str] | NonerC   r5   r6   r7   NNN)
rH   Mapping[str, str | Any] | NonerG   r5   rK   r5   rL   r   r6   r   r4   )rH   rg   rG   r5   rL   r   r6   r   )
rK   r5   rH   rg   rG   r5   rL   r   r6   r   )NNNNTutf-8)rV   z#str | bytes | dict[Any, Any] | NonerH   rg   rK   r5   rG   r5   rT   boolr[   r   rL   r   r6   r   )NNNTrh   )rK   r5   rV   zdict | NonerH   rg   rG   r5   rT   ri   r[   r   rL   r   r6   r   )rK   r5   rL   r   r6   r   )r8   r9   r:   r;   r$   rM   rP   rF   r\   r`   rb   r=   r   r   r?   r?      s   4 "VV  V %	V
 V 
V& 37 $	
/
 
 	

 
 

F 37 $I/I I 	I
 
I( 26 $	PP 0P 	P
 P 
P, 5926 $!$*
1*
 0*
 	*

 *
 *
 *
 *
 
*
^ !26 $!$(
(
 (
 0	(

 (
 (
 (
 (
 
(
T
r   r?   c                  "    e Zd ZdZdddZddZy)Clienta  A client for interacting with the Mailjet API.

    This class manages authentication, configuration, and API endpoint access.
    It initializes with API authentication details and uses dynamic attribute access
    to allow flexible interaction with various Mailjet API endpoints.

    Attributes:
    - auth  (tuple[str, str] | None): A tuple containing the API key and secret for authentication.
    - config (Config): An instance of the Config class, which holds API configuration settings.

    Methods:
    - __init__: Initializes a new Client instance with authentication and configuration settings.
    - __getattr__: Handles dynamic attribute access, allowing for accessing API endpoints as attributes.
    Nc                z    || _         |j                  d      }|j                  d      }t        ||      | _        y)a  Initialize a new Client instance for API interaction.

        This method sets up API authentication and configuration. The `auth` parameter
        provides a tuple with the API key and secret. Additional keyword arguments can
        specify configuration options like API version and URL.

        Parameters:
        - auth (tuple[str, str] | None): A tuple containing the API key and secret for authentication. If None, authentication is not required.
        - **kwargs (Any): Additional keyword arguments, such as `version` and `api_url`, for configuring the client.

        Example:
            client = Client(auth=("api_key", "api_secret"), version="v3")
        r   r"   )r   r"   N)rD   rF   r   config)r#   rD   rL   r   r"   s        r   r$   zClient.__init__y  s5     	$jj3$jj3Wg>r   c                   t        j                  dt        |      }|j                  d      }|d   }d}t	        |      dkD  r|d   }|dk(  rd}|dk(  rd	}| j
                  |   \  }} t        |t        fi       |||| j                  
      S )aS  Dynamically access API endpoints as attributes.

        This method allows for flexible, attribute-style access to API endpoints.
        It constructs the appropriate endpoint URL and headers based on the attribute
        name, which it parses to identify the resource and optional sub-resources.

        Parameters:
        - name (str): The name of the attribute being accessed, corresponding to the Mailjet API endpoint.


        Returns:
        - Endpoint: An instance of the `Endpoint` class, initialized with the constructed URL, headers, action, and authentication details.
        z[A-Z]r/   r   N   csvdatazcsvdata/text:plaincsverrorzcsverror/text:csv)r1   r2   rC   rD   )	resubr   r0   lenrm   typer?   rD   )r#   name
name_regexr0   fnamerC   r1   r2   s           r   __getattr__zClient.__getattr__  s     &&;=
%++C01X!u:>1XF"-#,{{4(W+tEH;+	
 	
r   rc   )rD   re   rL   r   r6   r7   )rv   r   r6   r   )r8   r9   r:   r;   r$   ry   r=   r   r   rk   rk   i  s    ?& 
r   rk   c           
     ^   t        |||	||
      }t        t        |      }	 d}|r&dj                  d |j	                         D              } |||||| |dd      }|S # t        j
                  j                  $ r t        t        j                  $ r}t        |      d}~wt        $ r  w xY w)a  Make an API call to a specified URL using the provided method, headers, and other parameters.

    Parameters:
    - auth (tuple[str, str] | None): A tuple containing the API key and secret for authentication.
    - method (str): The HTTP method to be used for the API call (e.g., 'get', 'post', 'put', 'delete').
    - url (str): The URL to which the API call will be made.
    - headers (dict[str, str]): A dictionary containing the headers to be included in the API call.
    - data (str | bytes | None): The data to be sent in the request body.
    - filters (Mapping[str, str | Any] | None): A dictionary containing filters to be applied in the request.
    - resource_id (str | None): The ID of the specific resource to be accessed.
    - timeout (int): The timeout for the API call in seconds.
    - debug (bool): A flag indicating whether debug mode is enabled.
    - action (str | None): The specific action to be performed on the resource.
    - action_id (str | None): The ID of the specific action to be performed.
    - **kwargs (Any): Additional keyword arguments to be passed to the API call.

    Returns:
    - Response | Any: The response object from the API call if the request is successful, or an exception if an error occurs.
    )methodrC   rI   rG   N&c              3  0   K   | ]  \  }}| d |   yw)=Nr=   ).0kvs      r   	<genexpr>zapi_call.<locals>.<genexpr>  s     "J$!QaS!:"Js   TF)rV   paramsr2   rD   timeoutverifystream)	build_urlgetattrrequestsjoinitems
exceptionsTimeoutTimeoutErrorRequestExceptionApiError	Exception)rD   r{   r1   r2   rV   rH   rI   r   debugrC   rG   rL   
req_methodfilters_strresponsees                   r   rJ   rJ     s    B C 6*J"&(("J'--/"JJK	
$  && $$ qk s   :A 5B,BB,c                    ddi}| j                         dk(  r|j                         dk(  rddi}n*| j                         dk(  r|j                         dk(  rddi}|r|j                  |       |S )	a  Build headers based on resource and action.

    Parameters:
    - resource (str): The name of the resource for which headers are being built.
    - action (str): The specific action being performed on the resource.
    - extra_headers (dict[str, str] | None): Additional headers to be included in the request. Defaults to None.

    Returns:
    - dict[str, str]: A dictionary containing the headers to be included in the API request.
    r(   r'   contactslistrp   r*   batchjobrq   r,   )r   r`   )resourcerC   extra_headersr2   s       r   build_headersr     so      ./ABG~~>)flln	.I!<0		Z	'FLLNj,H!:.}%Nr   c                B    |r| d| z  } |r| d| z  } |r| d| z  } | S )a  Construct a URL for making an API request.

    This function takes the base URL, method, action, resource ID, and action ID as parameters
    and constructs a URL by appending the resource ID, action, and action ID to the base URL.

    Parameters:
    url (str): The base URL for the API request.
    method (str | None): The HTTP method for the API request (e.g., 'get', 'post', 'put', 'delete').
    action (str | None): The specific action to be performed on the resource. Defaults to None.
    resource_id (str | None): The ID of the specific resource to be accessed. Defaults to None.
    action_id (str | None): The ID of the specific action to be performed. Defaults to None.

    Returns:
    str: The constructed URL for the API request.
    r&   r=   )r1   r{   rC   rI   rG   s        r   r   r     sC    , ;-  6(|Qyk?"CJr   c                   t        j                         }|j                  t         j                         t        j                  d      }| rqt        j                  t        j                        }|j                  d      }| d}t        j                  |      }|j                  |       |j                  |       t        j                  t        j                        }|j                  |       |j                  |       |S )aJ  Create and configure a logger for logging API requests.

    This function creates a logger object and configures it to handle both
    standard output (stdout) and a file if the `to_file` parameter is set to True.
    The logger is set to log at the DEBUG level and uses a custom formatter to
    include the log level and message.

    Parameters:
    to_file (bool): A flag indicating whether to log to a file. If True, logs will be written to a file.
                     Defaults to False.

    Returns:
    logging.Logger: A configured logger object for logging API requests.
    z%(levelname)s | %(message)s)tzz%Y%m%d_%H%M%Sz.log)logging	getLoggersetLevelDEBUG	Formatterr   nowr   utcstrftimeFileHandlersetFormatter
addHandlerStreamHandlersysstdout)to_filelogger	formatterr   	date_timelog_filefile_handlerstdout_handlers           r   logging_handlerr   -  s    "  F
OOGMM"!!"?@Illhll+LL1	[%**84!!),,'**3::6N	*
n%Mr   c                   | j                         }|r |       }|j                  d| j                  j                         |j                  d| j                  j                         |j                  d| j                  j
                         |j                  d| j                         |j                  d| j                         |j                  d| j                         t        j                         j                  j                          |S )aq  Parse the response from an API request and return the JSON data.

    Parameters:
    response (Response): The response object from the API request.
    log (Callable): A function or method that logs debug information.
    debug (bool): A flag indicating whether debug mode is enabled. Defaults to False.

    Returns:
    Any: The JSON data from the API response.
    zREQUEST: %szREQUEST_HEADERS: %szREQUEST_CONTENT: %szRESPONSE: %szRESP_HEADERS: %szRESP_CODE: %s)rX   r   requestr1   r2   bodycontentstatus_coder   r   handlersclear)r   logr   rV   lgrs        r   parse_responser   R  s     ==?De		-!1!1!5!56		')9)9)A)AB		')9)9)>)>?		.("2"23		$h&6&67		/8#7#78$$**,Kr   c                      e Zd ZdZy)r   zBase class for all API-related errors.

    This exception serves as the root for all custom API error types,
    allowing for more specific error handling based on the type of API
    failure encountered.
    Nr8   r9   r:   r;   r=   r   r   r   r   r      r   r   c                      e Zd ZdZy)AuthorizationErrorzError raised for authorization failures.

    This error is raised when the API request fails due to invalid
    or missing authentication credentials.
    Nr   r=   r   r   r   r   {      r   r   c                      e Zd ZdZy)ActionDeniedErrorzError raised when an action is denied by the API.

    This exception is triggered when an action is requested but is not
    permitted, likely due to insufficient permissions.
    Nr   r=   r   r   r   r     r   r   r   c                      e Zd ZdZy)CriticalApiErrorzError raised for critical API failures.

    This error represents severe issues with the API or infrastructure
    that prevent requests from completing.
    Nr   r=   r   r   r   r     r   r   r   c                      e Zd ZdZy)ApiRateLimitErrorzError raised when the API rate limit is exceeded.

    This exception is raised when the user has made too many requests
    within a given time frame, as enforced by the API's rate limit policy.
    Nr   r=   r   r   r   r     r   r   r   c                      e Zd ZdZy)r   zError raised when an API request times out.

    This error is raised if an API request does not complete within
    the allowed timeframe, possibly due to network issues or server load.
    Nr   r=   r   r   r   r     r   r   r   c                      e Zd ZdZy)DoesNotExistErrorzError raised when a requested resource does not exist.

    This exception is triggered when a specific resource is requested
    but cannot be found in the API, indicating a potential data mismatch
    or invalid identifier.
    Nr   r=   r   r   r   r     r   r   r   c                      e Zd ZdZy)ValidationErrorzError raised for invalid input data.

    This exception is raised when the input data for an API request
    does not meet validation requirements, such as incorrect data types
    or missing fields.
    Nr   r=   r   r   r   r     r   r   r   )r   z
Match[str]r6   r   )NNN<   FNN)rD   re   r{   r   r1   r   r2   rd   rV   zstr | bytes | NonerH   rg   rI   r5   r   intr   ri   rC   r5   rG   r5   rL   r   r6   zResponse | Anyrc   )r   r   rC   r   r   zdict[str, str] | Noner6   rd   rf   )r1   r   r{   r5   rC   r5   rI   r5   rG   r5   r6   r   )F)r   ri   r6   zlogging.Logger)r   r   r   r   r   ri   r6   r   ),r;   
__future__r   rX   r   rr   r   r   r   r   typingr   r   r   requests.compatr	   mailjet_rest.utils.versionr
   collections.abcr   r   requests.modelsr   packagesurllib3disable_warningsr   r   r?   rk   rJ   r   r   r   r   r   r   r   r   r   r   r   r   r   r=   r   r   <module>r      sQ  8 #   	 
        # 2 ('( 	     * * ,E EPV
 V
rC
 C
V  $.2" @
 @@ 
@ 	@
 @ ,@ @ @ @ @ @ @ @L ,0 ) 	> " 	  	
  	@ """P 	  		@y   x  8  h r   