o
    i*I                     @   s  d 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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mZmZmZmZmZmZ ddlmZ ddlmZ errdd	lmZ dd
lm Z  ddl!m"Z" ddl#m$Z$ edZ%ede&dZ'ee'e(f Z)e*e+Z,G dd deZ-de-fddZ.de/ee(f fddZ0deee%  de1e% fddZ2dee3e(f de(fddZ4ddde5ee3e(f ef d e6de5e(ef fd!d"Z7d#Z8d$ede(fd%d&Z9d'e(ded(ef fd)d*Z:d'e(de;d+ fd,d-Z<d'e(de;d. fd/d0Z=d'e(de;d1 fd2d3Z>d4e(de(fd5d6Z?d7e(de(fd8d9Z@dejfd:d;ZAd<ZBd=ejde(fd>d?ZCd@e(dejfdAdBZDdCede6fdDdEZEedCe(de1e( fdFdGZFedCd.de1d. fdHdGZFedCed.e(eed.e(f  f de1ed.e(f  fdIdGZFedCee' de1e' fdJdGZFedCe'de1e' fdKdGZFdLdG ZFdeGfdMdNZHdrde;fdOdPZIdQee3e(f dejfdRdSZJdTeeeGeKe(f  deeG fdUdVZLdWdXde/eGeGeGf fdYdZZMd[d\ ZNd]ee% d^eGdeee% ddf fd_d`ZOdrdae(dbeeG de(fdcddZP	drdeee( dfedge5eef dbeeG dee( f
dhdiZQdjeee(d1f  de1e( fdkdlZRdjeee(d1f  dedX fdmdnZSdoe(de/e(e(f fdpdqZTdS )sz
Miscellaneous helper functions.

The formatter for ANSI colored console output is heavily based on Pygments
terminal colorizing code, originally by Georg Brandl.
    N)	GeneratorIterableSequence)Enum)TYPE_CHECKINGAnyCallableOptionalTypeVarUnionoverload)ResponseError   )TimeoutFormatError)RedisJobQueue
BaseWorker_T_O)boundc                   @   s    e Zd ZdZdZdZdZdZdS )Platformz0Enum representing the operating system platform.windowsmaclinuxZothersN)__name__
__module____qualname____doc__WINDOWSMACLINUXOTHERS r&   r&   ?/home/app/Keep/.python/lib/python3.10/site-packages/rq/utils.pyr   4   s    r   returnc                  C   s>   t j } | drtjS | dkrtjS | drtjS tjS )aC  Detect and return the current operating system platform.

    Returns:
        Platform: The detected platform enum value.
            - Platform.WINDOWS for Windows systems
            - Platform.MAC for macOS systems
            - Platform.LINUX for Linux systems
            - Platform.OTHERS for any other platform
    windarwinr   )	sysplatformlower
startswithr   r"   r#   r$   r%   )r,   r&   r&   r'   get_platform=   s   



r/   c                 C   s   t | r| j| jfS t | st | r d| j d| j fS t| t	r+dt
| fS t | s9t| dr9| dfS td|  )a  Resolve a function reference into instance and function name components.

    Args:
        func: The function reference to resolve - can be a method, function,
             builtin, string path, or callable class instance.

    Returns:
        A tuple of (instance, func_name) where:
        - instance: The object instance (for methods/callable instances) or None
        - func_name: The string representation of the function name/path

    Raises:
        TypeError: If func is not a valid callable or string reference.
    N.__call__z*Expected a callable or a string, but got: )inspectismethod__self__r   
isfunction	isbuiltinr   r    
isinstancestras_textisclasshasattr	TypeError)funcr&   r&   r'   resolve_function_referenceS   s   

r>   lstc                 C   s   dd | D S )zExcludes `None` values from a list-like object.

    Args:
        lst (list): A list (or list-like) object

    Returns:
        object (list): The list without None values
    c                 S   s   g | ]}|d ur|qS Nr&   ).0itemr&   r&   r'   
<listcomp>w   s    zcompact.<locals>.<listcomp>r&   )r?   r&   r&   r'   compactn   s   	rD   vc                 C   s4   t | tr
| dS t | tr| S tdt| )zConverts a bytes value to a string using `utf-8`.

    Args:
        v (Union[bytes, str]): The value (bytes or string)

    Raises:
        ValueError: If the value is not bytes or string

    Returns:
        value (str): The decoded string
    zutf-8zUnknown type )r7   bytesdecoder8   
ValueErrortype)rE   r&   r&   r'   r9   z   s
   


r9   F)decode_valueshrJ   c                C   s(   |rdd |   D S dd |   D S )a  Decodes the Redis hash, ensuring that keys are strings
    Most importantly, decodes bytes strings, ensuring the dict has str keys.

    Args:
        h (Dict[Any, Any]): The Redis hash
        decode_values (bool): If True, also decode values to strings using as_text(). Defaults to False.

    Returns:
        Dict[str, Any]: The decoded Redis data (Dictionary)
        When decode_values=True, returns Dict[str, str]
    c                 S   s   i | ]\}}t |t |qS r&   r9   rA   krE   r&   r&   r'   
<dictcomp>       z%decode_redis_hash.<locals>.<dictcomp>c                 S   s   i | ]	\}}t ||qS r&   rL   rM   r&   r&   r'   rO      s    )items)rK   rJ   r&   r&   r'   decode_redis_hash   s   rR   z<not JSON serializable>valuec              	   C   s(   zt | W S  ttfy   t Y S w )zCReturn JSON string if serializable, otherwise a placeholder string.)jsondumpsr<   rH   NOT_JSON_SERIALIZABLE)rS   r&   r&   r'   safe_json_dumps   s
   rW   name.c           	      C   s  |  d}|dd |d g}}d}t|r9zd|}t|}W n ty4   |d|  Y nw t|s|du rQzt|  W S  t	yP   t
d|  w d|}t||r`t||S | }d|}zt||}W n
   t
d| t||st
d|  t||S )a#  Returns an attribute from a dotted path name. Example: `path.to.func`.

    When the attribute we look for is a staticmethod, module name in its
    dotted path is not the last-before-end word

    E.g.: package_a.package_b.module_a.ClassA.my_static_method

    Thus we remove the bits from the end of the name until we can import it

    Args:
        name (str): The name (reference) to the path.

    Raises:
        ValueError: If no module is found or invalid attribute name.

    Returns:
        Any: An attribute (normally a Callable)
    r0   Nr   zInvalid attribute name: )splitlenjoin	importlibimport_moduleImportErrorinsertpop__builtins__KeyErrorrH   r;   getattr)	rX   Z	name_bitsZmodule_name_bitsZattribute_bitsmodulemodule_nameZattribute_nameZattribute_owner_nameZattribute_ownerr&   r&   r'   import_attribute   s<   









rg   r   c                 C   H   t | }t|tstd|  ddlm} t||s"td|  |S )z.Import a worker class from a dotted path name.zInvalid worker class: r   r   )rg   r7   rI   rH   workerr   
issubclass)rX   clsr   r&   r&   r'   import_worker_class      

rl   r   c                 C   rh   )z+Import a job class from a dotted path name.zInvalid job class: r   r   )rg   r7   rI   rH   jobr   rj   )rX   rk   r   r&   r&   r'   import_job_class   rm   ro   r   c                 C   rh   )z-Import a queue class from a dotted path name.zInvalid queue class: r   r   )rg   r7   rI   rH   queuer   rj   )rX   rk   r   r&   r&   r'   import_queue_class   rm   rq   config_pathc                 C   sf   t jj| v p
| d}|s| S | }|dr|dd }|t jjr)|dd }|t jjd}|S )a"  Normalize configuration path to dotted module path format.

    Converts file paths like 'directory/config_file.py' or 'directory.config_file'
    to dotted module paths like 'directory.config_file' for use with importlib.import_module().

    Args:
        config_path: Either a file path (e.g., 'app/cron_config.py', 'app/cron_config')
                    or a dotted module path (e.g., 'app.cron_config')

    Returns:
        A dotted module path suitable for importlib.import_module()

    Examples:
        normalize_config_path('app/cron_config.py') -> 'app.cron_config'
        normalize_config_path('app/cron_config') -> 'app.cron_config'
        normalize_config_path('app.cron_config') -> 'app.cron_config'
        normalize_config_path('/abs/path/to/config.py') -> 'abs.path.to.config'
    z.pyNr   r0   )ospathsependswithr.   replace)rr   Zis_file_path
normalizedr&   r&   r'   normalize_config_path  s   
rz   	file_pathc                 C   s<   t j| std|  dt j| std|  d| S )am  Validate that an absolute file path exists and points to a file.

    Args:
        file_path: The absolute file path to validate

    Returns:
        The same file path if validation passes (for chaining)

    Raises:
        FileNotFoundError: If the file does not exist
        IsADirectoryError: If the path points to a directory instead of a file

    Examples:
        validate_absolute_path('/path/to/config.py')  # Returns '/path/to/config.py'
        validate_absolute_path('/path/to/missing.py')  # Raises FileNotFoundError
        validate_absolute_path('/path/to/directory')   # Raises IsADirectoryError
    z!Configuration file not found at ''z7Configuration path points to a directory, not a file: ')rt   ru   existsFileNotFoundErrorisfileIsADirectoryError)r{   r&   r&   r'   validate_absolute_path7  s
   r   c                   C   s   t j t jjS )zReturn now in UTC)datetimenowtimezoneutcr&   r&   r&   r'   r   R  s   r   z%Y-%m-%dT%H:%M:%S.%fZdtc                 C   s   |  ttS r@   )strftimer9   _TIMESTAMP_FORMAT)r   r&   r&   r'   	utcformatZ  s   r   stringc                 C   sD   z	t j | t}W n ty   t j | d}Y nw |jt jjdS )Nz%Y-%m-%dT%H:%M:%SZ)tzinfo)r   strptimer   rH   rx   r   r   )r   parsedr&   r&   r'   utcparse^  s   r   objc                 C   s   t | to
t | t S )zReturns whether the obj is an iterable, but not a string

    Args:
        obj (Any): _description_

    Returns:
        bool: _description_
    )r7   r   r8   r   r&   r&   r'   is_nonstring_iterableg  s   	r   c                 C      d S r@   r&   r   r&   r&   r'   ensure_job_lists     r   c                 C   r   r@   r&   r   r&   r&   r'   r   u  r   c                 C   r   r@   r&   r   r&   r&   r'   r   w  r   c                 C   r   r@   r&   r   r&   r&   r'   r   y  r   c                 C   r   r@   r&   r   r&   r&   r'   r   {  r   c                 C   s"   t | trt | tst| S | gS )zWhen passed an iterable of objects, convert to list, otherwise, it returns
    a list with just that object in it.

    Args:
        obj (Any): _description_

    returns:
        List: _description_
    )r7   r   r8   listr   r&   r&   r'   r     s   "c                   C   s   t t  S )zKReturns current UTC timestamp

    Returns:
        int: _description_
    )calendartimegmr   utctimetupler&   r&   r&   r'   current_timestamp  s   r   c                 C   s(   |du r	t | |S t|trt|S |S )a  Get a backend class using its default attribute name or an override

    Args:
        holder (_type_): _description_
        default_name (_type_): _description_
        override (_type_, optional): _description_. Defaults to None.

    Returns:
        _type_: _description_
    N)rd   r7   r8   rg   )Zholderdefault_nameoverrider&   r&   r'   backend_class  s
   

r   date_strc                 C   s*   | st dt| trt|  S t| S )Nz#Empty string or bytestring provided)rH   r7   rF   r   rG   )r   r&   r&   r'   str_to_date  s
   
r   timeoutc                 C   s   t | tjsP| durPzt| } | W S  tyO   t | tsJ | dd | dd  }}ddddd}z
t|||  } W n ttfyL   tdw Y nw | durXt| S dS )	zGTransfer all kinds of timeout format to an integer representing secondsNrY   iQ i  <   r   )drK   mszTimeout must be an integer or a string representing an integer, or a string with format: digits + unit, unit can be "d", "h", "m", "s", such as "1h", "23m".)	r7   numbersIntegralintrH   r8   r-   rc   r   )r   digitunitZunit_secondr&   r&   r'   parse_timeout  s$   r   
connectionr   c                 C   s   z<t | dds7t| dd }dd |ddd D }t|dk r/|d	 t|dk s$t| dt| t | dW S  tyF   Y d
S w )a/  
    Returns tuple of Redis server version.
    This function also correctly handles 4 digit redis server versions.

    Args:
        connection (Redis): The Redis connection.

    Returns:
        version (Tuple[int, int, int]): A tuple representing the semantic versioning format (eg. (5, 0, 9))
    Z__rq_redis_server_versionNserverZredis_versionc                 S   s   g | ]}t |qS r&   )r   )rA   ir&   r&   r'   rC     s    zget_version.<locals>.<listcomp>r0      r   )   r   	   )	rd   r8   inforZ   r[   appendsetattrtupler   )r   version_strversion_partsr&   r&   r'   get_version  s    
r   c                 C   s   |  |  S )zCeiling division. Returns the ceiling of the quotient of a division operation

    Args:
        a (_type_): _description_
        b (_type_): _description_

    Returns:
        _type_: _description_
    r&   )abr&   r&   r'   ceildiv  s   
r   a_listsegment_sizec                 c   s.    t dt| |D ]}| |||  V  q	dS )zSplits a list into multiple smaller lists having size `segment_size`

    Args:
        a_list (Sequence[Any]): A sequence to split
        segment_size (int): The segment size to split into

    Yields:
        list: The splitted listed
    r   N)ranger[   )r   r   r   r&   r&   r'   
split_list  s   
r   data
max_lengthc                 C   s,   |du r| S t | |kr| d| d S | S )a  Truncate arguments with representation longer than max_length

    Args:
        data (str): The data to truncate
        max_length (Optional[int], optional): The max length. Defaults to None.

    Returns:
        truncated (str): The truncated string
    Nz...)r[   )r   r   r&   r&   r'   truncate_long_string  s   
 r   	func_nameargskwargsc                    sZ   | du rdS  fdd|D } fdd|  D }|t|7 }d|}|  d| dS )a  
    Returns a string representation of the call, formatted as a regular
    Python function invocation statement. If max_length is not None, truncate
    arguments with representation longer than max_length.

    Args:
        func_name (str): The function name
        args (Any): The function arguments
        kwargs (Dict[Any, Any]): The function kwargs
        max_length (int, optional): The max length. Defaults to None.

    Returns:
        str: A string representation of the function call.
    Nc                    s   g | ]}t tt| qS r&   r9   r   repr)rA   argr   r&   r'   rC   &  rP   z#get_call_string.<locals>.<listcomp>c                    s,   g | ]\}}| d t tt|  qS )=r   rM   r   r&   r'   rC   (  s   , z, ())rQ   sortedr\   )r   r   r   r   arg_listZlist_kwargsr&   r   r'   get_call_string  s   
r   queues_or_namesc                 C   sD   ddl m} g }| D ]}t||r||j q
|t| q
|S )z;Given a iterable  of strings or queues, returns queue namesr   r   )rp   r   r7   r   rX   r8   )r   r   namesqueue_or_namer&   r&   r'   parse_names/  s   
r   c                 C   s.   ddl m} | D ]}t||r|j  S qdS )z7Given a list of strings or queues, returns a connectionr   r   N)rp   r   r7   r   )r   r   r   r&   r&   r'   get_connection_from_queues<  s   

r   composite_keyc                 C   sD   |  d}t|dkrtd|  t |d dfS |\}}||fS )zMethod returns a parsed composite key.

    Args:
        composite_key (str): the composite key to parse

    Returns:
        tuple[str, str]: tuple of job id and the execution id
    :r   z4Composite key must contain job_id:execution_id, got r    )rZ   r[   warningswarnDeprecationWarning)r   resultZjob_idZexecution_idr&   r&   r'   parse_composite_keyF  s   
	r   r@   )Ur!   r   r   r]   r2   rT   loggingr   rt   r+   r   collections.abcr   r   r   enumr   typingr   r   r   r	   r
   r   r   Zredis.exceptionsr   
exceptionsr   Zredisr   rn   r   rp   r   ri   r   r   objectr   r8   ZObjOrStr	getLoggerr   loggerr   r/   r   r>   r   rD   rF   r9   dictboolrR   rV   rW   rg   rI   rl   ro   rq   rz   r   r   r   r   r   r   r   r   r   r   r   floatr   r   r   r   r   r   r   r   r   r&   r&   r&   r'   <module>   s    $

	45+	6	$
(

""
