
    s,g.                        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mZ ddl	m
Z
mZmZmZmZmZmZmZmZ e
rddlmZ ddlmZ ddlmZ dd	lmZ  ej6                  e      Zd
ee   dee   fdZdeee f   de fdZ!dee ef   fdZ"de dedef   fdZ#dej                  fdZ$dZ%dej                  de fdZ&de dej                  fdZ'd6defdZ(dede)fdZ*dedefdZ+de,fdZ-d7defdZ.d ee   deej                     fd!Z/d"eee,e0e f      dee,   fd#Z1d$d%dee,e,e,f   fd&Z2d' Z3d(ee   d)e,fd*Z4d7d+e d,ee,   de fd-Z5	 d7d.ee    d/ed0eeef   d,ee,   dee    f
d1Z6d2eee d3f      dee    fd4Z7d2eee d3f      ded%   fd5Z8y)8z
Miscellaneous helper functions.

The formatter for ANSI colored console output is heavily based on Pygments
terminal colorizing code, originally by Georg Brandl.
    N)Iterable)	TYPE_CHECKINGAnyCallableDictListOptionalTupleTypeUnion)Redis   Queue)ResponseError)TimeoutFormatErrorlstreturnc                 2    | D cg c]  }||	 c}S c c}w )zExcludes `None` values from a list-like object.

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

    Returns:
        object (list): The list without None values
     )r   items     b/var/www/trellinator.diamondhoofcare.com/public_html/venv/lib/python3.12/site-packages/rq/utils.pycompactr      s     !5TD$4D555s   vc                     t        | t              r| j                  d      S t        | t              r| S t	        dt        |       z        )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)
isinstancebytesdecodestr
ValueErrortype)r   s    r   as_textr"   )   sA     !Uxx  	As	*T!W455    c                 ,     t         f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

    Returns:
        Dict[str, Any]: The decoded Redis data (Dictionary)
    c              3   >   K   | ]  }t        |      |   f  y wN)r"   ).0khs     r   	<genexpr>z$decode_redis_hash.<locals>.<genexpr>G   s     .qQqT".s   )dict)r)   s   `r   decode_redis_hashr,   =   s     .A...r#   name.c                    | j                  d      }|dd |d   g}}d}t        |      r(	 dj                  |      }t        j                  |      }	 |
	 t        |    S dj                  |      }t        ||      rt        ||      S |j                         }dj                  |      }	 t        ||      }t        ||      st        d| z        t        ||      S # t
        $ r# |j                  d|j                                Y nw xY wt        |      r# t        $ r t        d| z        w xY w#  t        d|z        xY w)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)
    .Nr   zInvalid attribute name: %s)splitlenjoin	importlibimport_moduleImportErrorinsertpop__builtins__KeyErrorr    hasattrgetattr)	r-   	name_bitsmodule_name_bitsattribute_bitsmodulemodule_nameattribute_nameattribute_owner_nameattribute_owners	            r   import_attributerE   J   sg   & 

3I'0"~	"nF

	=((#34K,,[9F ~	B%% XXn-Nv~&v~..#'')N88N3H!&*>? ?N35<==?N33/  	=!!!%5%9%9%;<	= 
  	B9D@AA	BH5FGGs)   &C D )D2 )DDD/2Ec                  p    t         j                   j                  t         j                  j                        S )zReturn now in UTC)datetimenowtimezoneutcr   r#   r   rH   rH      s%      !2!2!6!677r#   %Y-%m-%dT%H:%M:%S.%fZdtc                 @     | j                   t        t                    S r&   )strftimer"   _TIMESTAMP_FORMAT)rL   s    r   	utcformatrP      s    2;;w0122r#   stringc                    	 t         j                   j                  | t              S # t        $ rU 	 t         j                   j                  | d      cY S # t        $ r% t         j                   j                  | d      cY cY S w xY ww xY w)NrK   z%Y-%m-%dT%H:%M:%SZ)rG   strptimerO   r    )rQ   s    r   utcparserT      s~    L  ))&2CDD L	L$$--f6MNN 	L$$--f6JKK	L	Ls,   #& 	BAB)B ;B?B  Biterablec                 N    || D ]  }|s|c S  |S | D ]  } ||      s|c S  |S )a  Return first element of `iterable` that evaluates true, else return None
    (or an optional default value).

    >>> first([0, False, None, [], (), 42])
    42

    >>> first([0, False, None, [], ()]) is None
    True

    >>> first([0, False, None, [], ()], default='ohai')
    'ohai'

    >>> import re
    >>> m = first(re.match(regex, 'abc') for regex in ['b.*', 'a(.*)'])
    >>> m.group(1)
    'bc'

    The optional `key` argument specifies a one-argument predicate function
    like that used for `filter()`.  The `key` argument, if supplied, must be
    in keyword form.  For example:

    >>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0)
    4

    Args:
        iterable (t.Iterable): _description_
        default (_type_, optional): _description_. Defaults to None.
        key (_type_, optional): _description_. Defaults to None.

    Returns:
        _type_: _description_
    r   )rU   defaultkeyels       r   firstrZ      sL    B { 	B		 N	  	B2w		 Nr#   objc                 H    t        | t              xr 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[   s    r   is_nonstring_iterabler^      s      c8$AZS-A)AAr#   c                 "    t        |       r| S | gS )zWhen passed an iterable of objects, does nothing, otherwise, it returns
    a list with just that object in it.

    Args:
        obj (Any): _description_

    Returns:
        List: _description_
    )r^   r]   s    r   ensure_listr`      s     (,373%7r#   c                      t        j                  t        j                  j                  t        j                  j
                        j                               S )zKReturns current UTC timestamp

    Returns:
        int: _description_
    )calendartimegmrG   rH   rI   rJ   utctimetupler   r#   r   current_timestampre      s9     ??8,,001B1B1F1FGTTVWWr#   c                 X    |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_
    )r<   r   r   rE   )holderdefault_nameoverrides      r   backend_classrj      s1     v|,,	Hc	"))r#   date_strc                 :    | sy t        | j                               S r&   )rT   r   )rk   s    r   str_to_daterm      s    )**r#   timeoutc                 <   t        | t        j                        s| 	 t        |       } | S | S # t        $ re t        | t
              sJ | dd | dd j                         }}ddddd}	 t        |      ||   z  } Y | S # t        t        f$ r t        d      w xY ww xY w)	zGTransfer all kinds of timeout format to an integer representing secondsNr0   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intr    r   lowerr:   r   )rn   digitunitunit_seconds       r   parse_timeoutr{      s    gw//0W5H	'lG N7N  	gs+++!#2,(<(<(>4E %DrBKe*{4'88 N ) (+ 	s   - :B(A<<BB
connectionr   c                 t   	 t        | dd      st        | j                  d      d         }|j                  d      dd D cg c]  }t	        |       }}t        |      dk  r |j                  d       t        |      dk  r t        | dt        |             t        | d      S c c}w # t        $ r Y yw xY 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_versionr/      r   )   r   	   )
r<   r   infor1   rv   r2   appendsetattrtupler   )r|   version_striversion_partss       r   get_versionr     s    z#>Ejooh7HIK-8->->s-CBQ-GHSVHMHm$q($$Q' m$q(+m$
 z#>?? I  s*   A B+ B&/B+ !B+ &B+ +	B76B7c                     |  |z   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bs     r   ceildivr   2  s     R1W:r#   a_listsegment_sizec              #   V   K   t        dt        |       |      D ]  }| |||z      yw)zSplits a list into multiple smaller lists having size `segment_size`

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

    Yields:
        list: The splitted listed
    r   N)ranger2   )r   r   r   s      r   
split_listr   ?  s6      1c&k<0 +Q\)**+s   ')data
max_lengthc                 :    || S t        |       |kD  r| d| dz   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...)r2   )r   r   s     r   truncate_long_stringr   M  s1     *-d)j*@D*%JdJr#   	func_nameargskwargsc                 r   | y|D cg c]   }t        t        t        |      |            " }}|j                         D cg c]3  \  }}dj	                  |t        t        t        |      |                  5 }}}|t        |      z  }dj                  |      }dj	                  | |      S c c}w c c}}w )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 funtion 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.
    Nz{0}={1}z, z{0}({1}))r"   r   repritemsformatsortedr3   )	r   r   r   r   argarg_listr(   r   list_kwargss	            r   get_call_stringr   \  s    " PTU,T#Y
CDUHUgmgsgsguv_c_`bc9##Aw/CDGZ/X'YZvKv{##H99XDY-- Vvs   %B.8B3queues_or_namesr   c                     ddl m} g }| D ]D  }t        ||      r|j                  |j                         +|j                  t        |             F |S )z6Given a list of strings or queues, returns queue namesr   r   )queuer   r   r   r-   r   )r   r   namesqueue_or_names       r   parse_namesr   y  sM    E( -mU+LL++,LL]+,	-
 Lr#   c                 R    ddl m} | D ]  }t        ||      s|j                  c S  y)z7Given a list of strings or queues, returns a connectionr   r   N)r   r   r   r|   )r   r   r   s      r   get_connection_from_queuesr     s/    ( ,mU+ +++, r#   )NNr&   )9__doc__rb   rG   rL   r4   loggingrt   collections.abcr   typingr   r   r   r   r   r	   r
   r   r   redisr   r   r   redis.exceptionsr   
exceptionsr   	getLogger__name__loggerr   r   r   r"   r,   rE   rH   rO   rP   rT   rZ   boolr^   r`   rv   re   rj   rm   floatr{   r   r   r   r   r   r   r   r   r#   r   <module>r      s         $ Y Y Y * *			8	$	6c 	6tCy 	66uUCZ  6S 6(
/DcN 
/243 248CH#5 24j8X 8
 , 3"++ 3# 3LS LR[[ L*H *Z	Bs 	Bt 	B
8S 
8T 
8X3 X$ &+(5/ +hr{{.C +8E#uc/$:;  *G c3m(< <
+tCy + +Ks K K K  ^b.}.$'.15c3h.MUVY].c].:
eCL&9!: 
tCy 
U3<5H0I hW^N_ r#   