o
    /iD                     @   sL  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	m
Z
mZ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rdd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(de)ee$f fddZ*deee!  de+e! fddZ,dee-e$f de$fddZ.ddde/ee-e$f ef de0de/e$ef fddZ1de$dedef fd d!Z2de$de3d" fd#d$Z4de$de3d% fd&d'Z5de$de3d( fd)d*Z6d+e$de$fd,d-Z7d.e$de$fd/d0Z8dejfd1d2Z9d3Z:d4ejde$fd5d6Z;d7e$dejfd8d9Z<d:ede0fd;d<Z=ed:e$de+e$ fd=d>Z>ed:d%de+d% fd?d>Z>ed:ed%e$eed%e$f  f de+ed%e$f  fd@d>Z>ed:ee# de+e# fdAd>Z>ed:e#de+e# fdBd>Z>dCd> Z>de?fdDdEZ@dide3fdFdGZAdHee-e$f dejfdIdJZBdKeee?eCe$f  dee? fdLdMZDdNdOde)e?e?e?f fdPdQZEdRdS ZFdTee! dUe?de
ee! ddf fdVdWZGdidXe$dYee? de$fdZd[ZH	did\ee$ d]ed^e/eef dYee? dee$ f
d_d`ZIdaeee$d(f  de+e$ fdbdcZJdaeee$d(f  dedO fdddeZKdfe$de)e$e$f fdgdhZLdS )jz
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)TYPE_CHECKINGAnyCallableOptionalTypeVarUnionoverload)ResponseError   )TimeoutFormatError)RedisJobQueueWorker_T_O)boundreturnc                 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____name__
isfunction	isbuiltin
__module____qualname__
isinstancestras_textisclasshasattr	TypeError)func r+   H/var/www/html/flask_server/venv/lib/python3.10/site-packages/rq/utils.pyresolve_function_reference1   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>U   s    zcompact.<locals>.<listcomp>r+   )r.   r+   r+   r,   compactL   s   	r3   vc                 C   s2   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 %r)r$   bytesdecoder%   
ValueErrortype)r4   r+   r+   r,   r&   X   s
   


r&   F)decode_valueshr9   c                C   s0   |rt dd |  D S t 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$    | ]\}}t |t |fV  qd S r/   r&   r0   kr4   r+   r+   r,   	<genexpr>y   s   " z$decode_redis_hash.<locals>.<genexpr>c                 s   s     | ]\}}t ||fV  qd S r/   r;   r<   r+   r+   r,   r>   z   s    )dictitems)r:   r9   r+   r+   r,   decode_redis_hashl   s   rA   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)
    r   Nr   zInvalid attribute name: zInvalid attribute name: %s)splitlenjoin	importlibimport_moduleImportErrorinsertpop__builtins__KeyErrorr7   r(   getattr)	rB   	name_bitsmodule_name_bitsattribute_bitsmodulemodule_nameattribute_nameattribute_owner_nameattribute_ownerr+   r+   r,   import_attribute}   s<   









rW   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   )rW   r$   r8   r7   workerr   
issubclass)rB   clsr   r+   r+   r,   import_worker_class      

r\   r   c                 C   rX   )z+Import a job class from a dotted path name.zInvalid job class: r   r   )rW   r$   r8   r7   jobr   rZ   )rB   r[   r   r+   r+   r,   import_job_class   r]   r_   r   c                 C   rX   )z-Import a queue class from a dotted path name.zInvalid queue class: r   r   )rW   r$   r8   r7   queuer   rZ   )rB   r[   r   r+   r+   r,   import_queue_class   r]   ra   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   r   )ospathsependswith
startswithreplace)rb   is_file_path
normalizedr+   r+   r,   normalize_config_path   s   
rl   	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: ')rd   re   existsFileNotFoundErrorisfileIsADirectoryError)rm   r+   r+   r,   validate_absolute_path
  s
   rs   c                   C   s   t j t jjS )zReturn now in UTC)datetimenowtimezoneutcr+   r+   r+   r,   ru   %  s   ru   z%Y-%m-%dT%H:%M:%S.%fZdtc                 C   s   |  ttS r/   )strftimer&   _TIMESTAMP_FORMAT)rx   r+   r+   r,   	utcformat-  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)rt   strptimerz   r7   ri   rv   rw   )r|   parsedr+   r+   r,   utcparse1  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_
    )r$   r   r%   r   r+   r+   r,   is_nonstring_iterable:  s   	r   c                 C      d S r/   r+   r   r+   r+   r,   ensure_job_listF     r   c                 C   r   r/   r+   r   r+   r+   r,   r   H  r   c                 C   r   r/   r+   r   r+   r+   r,   r   J  r   c                 C   r   r/   r+   r   r+   r+   r,   r   L  r   c                 C   r   r/   r+   r   r+   r+   r,   r   N  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_
    )r$   r   r%   listr   r+   r+   r,   r   R  s   "c                   C   s   t t  S )zKReturns current UTC timestamp

    Returns:
        int: _description_
    )calendartimegmru   utctimetupler+   r+   r+   r,   current_timestampa  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)rN   r$   r%   rW   )holderdefault_nameoverrider+   r+   r,   backend_classj  s
   

r   date_strc                 C   s*   | st dt| trt|  S t| S )Nz#Empty string or bytestring provided)r7   r$   r5   r   r6   )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 secondsNrC   iQ i  <   r   )dr:   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".)	r$   numbersIntegralintr7   r%   lowerrM   r   )r   digitunit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))
    __rq_redis_server_versionNserverredis_versionc                 S   s   g | ]}t |qS r+   )r   )r0   ir+   r+   r,   r2     s    zget_version.<locals>.<listcomp>r      r   )   r   	   )	rN   r%   inforD   rE   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)rangerE   )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...)rE   )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+   r&   r   repr)r0   argr   r+   r,   r2     s    z#get_call_string.<locals>.<listcomp>c                    s,   g | ]\}}| d t tt|  qS )=r   r<   r   r+   r,   r2     s   , z, ())r@   sortedrF   )r   r   r   r   arg_list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   )r`   r   r$   r   rB   r%   )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)r`   r   r$   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    )rD   rE   warningswarnDeprecationWarning)r   resultjob_idexecution_idr+   r+   r,   parse_composite_key  s   
	r   r/   )M__doc__r   rt   rG   r   loggingr   rd   r   collections.abcr   r   r   typingr   r   r   r   r	   r
   r   redis.exceptionsr   
exceptionsr   redisr   r^   r   r`   r   rY   r   r   objectr   r%   ObjOrStr	getLoggerr   loggerr   r-   r   r3   r5   r&   r?   boolrA   rW   r8   r\   r_   ra   rl   rs   ru   rz   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	$
(

""
