
    AHj^H                       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	Z	ddl
Z
ddlZddlZddlmZmZmZmZ ddlmZ ddlmZmZmZm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" ddl#m$Z$  ed      Z% ede&      Z' ejP                  e)      Z* G d de      Z+d9dZ,d:dZ-d;dZ.d<dZ/ddd=dZ0dZ1d>dZ2d?dZ3d@dZ4dAdZ5dBdZ6dCd Z7dDd!Z8dEd"Z9d#Z:dFd$Z;dGd%Z<dHd&Z=edId'       Z>edJd(       Z>edKd)       Z>edLd*       Z>edMd+       Z>d, Z>dNd-Z?dOdPd.Z@dQd/ZAdRd0ZBdSd1ZCd2 ZDdTd3ZEdOdUd4ZF	 dO	 	 	 	 	 	 	 	 	 dVd5ZGdWd6ZHdXd7ZIdYd8ZJy)Zz
Miscellaneous helper functions.

The formatter for ANSI colored console output is heavily based on Pygments
terminal colorizing code, originally by Georg Brandl.
    )annotationsN)Callable	GeneratorIterableSequence)Enum)TYPE_CHECKINGAnyTypeVaroverload)ResponseError   )TimeoutFormatError)RedisJobQueue
BaseWorker_T_O)boundc                       e Zd ZdZdZdZdZdZy)Platformz0Enum representing the operating system platform.windowsmaclinuxothersN)__name__
__module____qualname____doc__WINDOWSMACLINUXOTHERS     @/root/tools/cai/cai_env/lib/python3.12/site-packages/rq/utils.pyr   r   0   s    :G
CEFr)   r   c                    t         j                  j                         } | j                  d      rt        j
                  S | dk(  rt        j                  S | j                  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/   s    r*   get_platformr2   9   sd     ||!!#H5!	X	||			W	%~~r)   c                   t        j                  |       r| j                  | j                  fS t        j                  |       st        j
                  |       rd| j                   d| j                   fS t        | t              rdt        |       fS t        j                  |       st        | d      r| 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)funcs    r*   resolve_function_referencerB   O   s     }}dmm++			D	!W%6%6t%<($*;*;)<===	D#	WT]""__T"wtZ'@ZDTFKLLr)   c                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) object

    Returns:
        object (list): The list without None values
    r(   )lstitems     r*   compactrF   j   s     !5TD$4D555s   c                    t        | t              r| j                  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;   bytesdecoder<   
ValueErrortype)vs    r*   r=   r=   v   sB     !Uxx  	As	=a455r)   F)decode_valuesc                   |r6| j                         D ci c]  \  }}t        |      t        |       c}}S | j                         D ci c]  \  }}t        |      | c}}S c c}}w c c}}w )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]
    )itemsr=   )hrM   krL   s       r*   decode_redis_hashrR      sZ     34779=41a
GAJ&==&'ggi0daGAJM00 >0s   A&A,z<not JSON serializable>c                d    	 t        j                  |       S # t        t        f$ r	 t        cY S w xY w)zCReturn JSON string if serializable, otherwise a placeholder string.)jsondumpsr@   rJ   NOT_JSON_SERIALIZABLE)values    r*   safe_json_dumpsrX      s0    %zz%  z" %$$%s    //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|        t        ||      S # t
        $ r# |j                  d|j                                Y nw xY wt        |      r# t        $ r t        d|        w xY w#  t        d|       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)
    r4   Nr   zInvalid attribute name: )splitlenjoin	importlibimport_moduleImportErrorinsertpop__builtins__KeyErrorrJ   r?   getattr)	name	name_bitsmodule_name_bitsattribute_bitsmodulemodule_nameattribute_nameattribute_owner_nameattribute_owners	            r*   import_attributero      sn   & 

3I'0"~	"nF

	=((#34K,,[9F ~	@%% XXn-Nv~&v~..#'')N88N3F!&*>? ?N33D6:;;?N33/  	=!!!%5%9%9%;<	= 
  	@7v>??	@F3N3CDEEs)   &C D )D2 )DDD/2Ec                    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   )ro   r;   rK   rJ   workerr   
issubclass)rf   clsr   s      r*   import_worker_classrt      sN    
4
 Cc4 1$899"c:&1$899Jr)   c                    t        |       }t        |t              st        d|        ddlm} t        ||      st        d|        |S )z+Import a job class from a dotted path name.zInvalid job class: r   r   )ro   r;   rK   rJ   jobr   rr   )rf   rs   r   s      r*   import_job_classrw      sN    
4
 Cc4 .tf566c3.tf566Jr)   c                    t        |       }t        |t              st        d|        ddlm} t        ||      st        d|        |S )z-Import a queue class from a dotted path name.zInvalid queue class: r   r   )ro   r;   rK   rJ   queuer   rr   )rf   rs   r   s      r*   import_queue_classrz      sN    
4
 Cc4 0788c5!0788Jr)   c                L   t         j                  j                  | v xs | j                  d      }|s| S | }|j                  d      r|dd }|j	                  t         j                  j                        r|dd }|j                  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   r4   )ospathsependswithr1   replace)config_pathis_file_path
normalizeds      r*   normalize_config_pathr     s    ( 77;;+-L1E1Ee1LL J 5!_
 RWW[[)^
 ##BGGKK5Jr)   c                    t         j                  j                  |       st        d|  d      t         j                  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: ')r}   r~   existsFileNotFoundErrorisfileIsADirectoryError)	file_paths    r*   validate_absolute_pathr   3  sW    $ 77>>)$"CI;a PQQ77>>)$"YZcYdde fggr)   c                 p    t         j                   j                  t         j                  j                        S )zReturn now in UTC)datetimenowtimezoneutcr(   r)   r*   r   r   N  s%      !2!2!6!677r)   z%Y-%m-%dT%H:%M:%S.%fZc                >    | j                  t        t                    S N)strftimer=   _TIMESTAMP_FORMAT)dts    r*   	utcformatr   V  s    ;;w0122r)   c                    	 t         j                   j                  | t              }|j	                  t         j
                  j                        S # t        $ r# t         j                   j                  | d      }Y Uw xY w)Nz%Y-%m-%dT%H:%M:%SZ)tzinfo)r   strptimer   rJ   r   r   r   )stringparseds     r*   utcparser   Z  sl    J""++F4EF >>!2!2!6!6>77  J""++F4HIJs   $A )A<;A<c                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<   objs    r*   is_nonstring_iterabler   c  s      c8$AZS-A)AAr)   c                     y r   r(   r   s    r*   ensure_job_listr   o      ,/r)   c                     y r   r(   r   s    r*   r   r   q  r   r)   c                     y r   r(   r   s    r*   r   r   s  s    NQr)   c                     y r   r(   r   s    r*   r   r   u  s    47r)   c                     y r   r(   r   s    r*   r   r   w  s    *-r)   c                ^    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   s    r*   r   r   {  s)     #31*S#:N49YUXTYYr)   c                 X    t        j                  t               j                               S )zKReturns current UTC timestamp

    Returns:
        int: _description_
    )calendartimegmr   utctimetupler(   r)   r*   current_timestampr     s     ??35--/00r)   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_
    )re   r;   r<   ro   )holderdefault_nameoverrides      r*   backend_classr     s1     v|,,	Hc	"))r)   c                    | st        d      t        | t              rt        | j	                               S t        |       S )Nz#Empty string or bytestring provided)rJ   r;   rH   r   rI   )date_strs    r*   str_to_dater     s8    >??h&HOO-..H%%r)   c                V   t        | t        j                        s| 	 t        |       } | S | t        |       S dS # t        $ re t        | t
              sJ | dd | dd j                         }}ddddd}	 t        |      ||   z  } n# t        t        f$ r t        d      w xY wY |w xY w)	zGTransfer all kinds of timeout format to an integer representing secondsNrZ   iQ i  <   r   )drP   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intrJ   r<   r0   rd   r   )timeoutdigitunitunit_seconds       r*   parse_timeoutr     s    gw//0W5H	'lGN #.3w<8D8  	gs+++!#2,(<(<(>4E %DrBKe*{4'88) (+  	s'   : :B(5BB(B""B('B(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_versionr4      r   )   r   	   )
re   r<   infor[   r   r\   appendsetattrtupler   )
connection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     s     R1W:r)   c              #  V   K   t        dt        |       |      D ]  }| |||z      yw)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\   )a_listsegment_sizer   s      r*   
split_listr     s6      1c&k<0 +Q\)**+s   ')c                :    || 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...)r\   )data
max_lengths     r*   truncate_long_stringr     s1     *-d)j*@D*%JdJr)   c                H   | y|D cg c]   }t        t        t        |      |            " }}|j                         D cg c](  \  }}| dt        t        t        |      |             * }}}|t	        |      z  }dj                  |      }|  d| d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 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.
    N=z, ())r=   r   reprrO   sortedr]   )		func_nameargskwargsr   argarg_listrQ   rL   list_kwargss	            r*   get_call_stringr     s    " PTU,T#Y
CDUHU[a[g[g[ijSWSTVWaS'"6tAw
"KLMNjKj{##H99XD[$q!! Vjs   %B-Bc                    ddl m} g }| D ]D  }t        ||      r|j                  |j                         +|j                  t        |             F |S )z;Given a iterable  of strings or queues, returns queue namesr   r   )ry   r   r;   r   rf   r<   )queues_or_namesr   namesqueue_or_names       r*   parse_namesr   +  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)ry   r   r;   r   )r   r   r   s      r*   get_connection_from_queuesr   8  s/    ( ,mU+ +++, r)   c                    | j                  d      }t        |      dk(  r$t        j                  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    )r[   r\   warningswarnDeprecationWarning)composite_keyresultjob_idexecution_ids       r*   parse_composite_keyr  B  s`       %F
6{a 	B=/R	
 q	2!FLL!!r)   )returnr   )r  ztuple[Any, str])rD   zIterable[_T | None]r  zlist[_T])rL   bytes | strr  r<   )rP   zdict[bytes | str, Any]rM   boolr  zdict[str, Any])rW   r
   r  r<   )rf   r<   r  zCallable[..., Any])rf   r<   r  ztype[BaseWorker])rf   r<   r  z	type[Job])rf   r<   r  ztype[Queue])r   r<   r  r<   )r   r<   r  r<   )r  datetime.datetime)r   r  r  r<   )r   r<   r  r  )r   r
   r  r  )r   r<   r  	list[str])r   r   r  z	list[Job])r   zJob | str | Sequence[Job | str]r  zlist[Job | str])r   zIterable[_O]r  list[_O])r   r   r  r  )r  r   r   )r  rK   )r   r  r  r  )r   zint | float | str | Noner  
int | None)r   r   r  ztuple[int, int, int])r   zSequence[_T]r   r   r  z#Generator[Sequence[_T], None, None])r   r<   r   r  r  r<   )
r   
str | Noner   r
   r   zdict[Any, Any]r   r  r  r	  )r   Iterable[str | Queue]r  r  )r   r
  r  zRedis | None)r   r<   r  ztuple[str, str])Kr#   
__future__r   r   r   r^   r6   rT   loggingr   r}   r.   r   collections.abcr   r   r   r   enumr   typingr	   r
   r   r   redis.exceptionsr   
exceptionsr   redisr   rv   r   ry   r   rq   r   r   objectr   	getLoggerr    loggerr   r2   rB   rF   r=   rR   rV   rX   ro   rt   rw   rz   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r(   r)   r*   <module>r     s   #        	 
  C C   + *" T]T  
		8	$t ,M6	66( KP 1" 2 %24j(V68
 , 38	B 
 / 
 /	 / 
 /	 Q 
 Q	 7 
 7	 - 
 -Z1&&9,<
+K  X\""!$".<"JT"":
"r)   