
    3 dv%                        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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 Zd Zd	 Zd
 fdZd'dZd'dZd(dZd Zd  ed          D             h dz
  Zed eD             z  Zd Zd)dZd Zd Zd Z d Z! e"ed          rd Z#nd Z# G d  d!e          Z$d"eeef         d#efd$Z% G d% d&e          Z&dS )*zP
This module contains essential stuff that should've come with Python itself ;)
    N)partialwraps)chain)AsyncGeneratorAsyncIterableIterableUnionas_async_generatorc                 :    t          t          |                     S )a  flatten(sequence) -> list

    Returns a single, flat list which contains all elements retrieved
    from the sequence and all recursively contained sub-sequences
    (iterables).

    Examples:
    >>> [1, 2, [3,4], (5,6)]
    [1, 2, [3, 4], (5, 6)]
    >>> flatten([[[1,2,3], (42,None)], [4,5], [6], 7, (8,9,10)])
    [1, 2, 3, 42, None, 4, 5, 6, 7, 8, 9, 10]
    >>> flatten(["foo", "bar"])
    ['foo', 'bar']
    >>> flatten(["foo", ["baz", 42], "bar"])
    ['foo', 'baz', 42, 'bar']
    )listiflattenxs    3lib/python3.11/site-packages/scrapy/utils/python.pyflattenr      s    "     c              #   h   K   | D ],}t          |          rt          |          D ]}|V  (|V  -dS )z[iflatten(sequence) -> iterator

    Similar to ``.flatten()``, but returns iterator insteadN)is_listliker   )r   elel_s      r   r   r   $   sa         r?? 	||  				 HHHH r   c                 \    t          | d          ot          | t          t          f           S )a`  
    >>> is_listlike("foo")
    False
    >>> is_listlike(5)
    False
    >>> is_listlike(b"foo")
    False
    >>> is_listlike([b"foo"])
    True
    >>> is_listlike((b"foo",))
    True
    >>> is_listlike({})
    True
    >>> is_listlike(set())
    True
    >>> is_listlike((x for x in range(3)))
    True
    >>> is_listlike(range(5))
    True
    __iter__)hasattr
isinstancestrbytesr   s    r   r   r   0   s*    * 1j!!E*Qe*E*E&EEr   c                     | S N r   s    r   <lambda>r!   H   s     r   c                     t                      }g }| D ]<} ||          }||v r|                    |           |                    |           =|S )z;efficient function to uniquify a list preserving item order)setaddappend)list_keyseenresultitemseenkeys         r   uniquer,   H   sg    55DF  #d))d? 	dMr   strictc                     t          | t                    r| S t          | t          t          f          s$t          dt	          |           j                   |d}|                     ||          S )z|Return the unicode representation of a bytes object ``text``. If
    ``text`` is already an unicode object, return it as-is.z3to_unicode must receive a bytes or str object, got Nutf-8)r   r   r   	TypeErrortype__name__decodetextencodingerrorss      r   
to_unicoder8   U   s     $ dUCL)) 
1::.1 1
 
 	
  ;;x(((r   c                     t          | t                    r| S t          | t                    s$t          dt	          |           j                   |d}|                     ||          S )ziReturn the binary representation of ``text``. If ``text``
    is already a bytes object, return it as-is.z1to_bytes must receive a str or bytes object, got Nr/   )r   r   r   r0   r1   r2   encoder4   s      r   to_bytesr;   d   sv     $ dC   
X4::CVXX
 
 	
  ;;x(((r      c                    fd}t          | t                    rt          j        |           }  |            D ]O\  }}d |                     |          D             }|r)|d                                         \  }}||z   ||z   fc S PdS )a  
    This function does a reverse search in a text using a regular expression
    given in the attribute 'pattern'.
    Since the re module does not provide this functionality, we have to find for
    the expression into chunks of text extracted from the end (for the sake of efficiency).
    At first, a chunk of 'chunk_size' kilobytes is extracted from the end, and searched for
    the pattern. If the pattern is not found, another chunk is extracted, and another
    search is performed.
    This process continues until a match is found, or until the whole file is read.
    In case the pattern wasn't found, None is returned, otherwise it returns a tuple containing
    the start position of the match, and the ending (regarding the entire text).
    c               3   t   K   t                    } 	 | dz  z  } | dk    rn| d          | fV  dfV  d S )NTr<   r   )len)offset
chunk_sizer5   s    r   _chunk_iterzre_rsearch.<locals>._chunk_iter   sf      T	*j4''F{ =&))))		*
 Qir   c                     g | ]}|S r    r    ).0matchs     r   
<listcomp>zre_rsearch.<locals>.<listcomp>   s    >>>U5>>>r   N)r   r   recompilefinditerspan)	patternr5   rA   rB   chunkr@   matchesstartends	    ``      r   
re_rsearchrQ   r   s          '3 &*W%%$ 0 0v>>g&6&6u&=&=>>> 	0 ))++JE3E>6C<////	0 4r   c                 f     t          j                    t                      fd            }|S )zkDecorator to cache the result of a method (without arguments) using a
    weak reference to its object
    c                 :    | vr | g|R i || <   |          S r   r    )selfargskwargscachemethods      r   
new_methodz(memoizemethod_noargs.<locals>.new_method   s=    u 	8 &777777E$KT{r   )weakrefWeakKeyDictionaryr   )rX   rY   rW   s   ` @r   memoizemethod_noargsr\      sJ     %''E
6]]     ]
 r   c                 F    h | ]}t          t          |                    S r    )r;   chr)rD   is     r   	<setcomp>r`      s&    444QQ  444r       >          	   
   c                 ,    h | ]}t          |          S r    )ord)rD   chs     r   r`   r`      s    000RR000r   c                     t          | t                    s%t          dt          |           j         d          t          d | D                       S )z~Returns ``True`` if the given ``data`` argument (a ``bytes`` object)
    does not contain unprintable control characters.
    zdata must be bytes, got ''c              3   (   K   | ]}|t           vV  d S r   )_BINARYCHARS)rD   cs     r   	<genexpr>z!binary_is_text.<locals>.<genexpr>   s'      33q$333333r   )r   r   r0   r1   r2   all)datas    r   binary_is_textrq      sW     dE"" LJDJJ4GJJJKKK33d333333r   Fc                     t          j                   r%t          j                   }|j        |j        z   }n(t          j                   rt           j        d          S t          j                   rt           j	        d          S t          j
                   rg S t           t                    r: fdt           j                  t           j                  d         D             S t           d          rBt          j                   rg S t#           dd          dk    rg S t           j        d          S t'          t)                      d          |r|                    d           |S )z+Return the argument name list of a callableTc                 4    g | ]}j         r	|j         v |S r    )keywords)rD   r   funcs     r   rF   z!get_func_args.<locals>.<listcomp>   sB     
 
 
M
 '(4=&8

 
 
r   N__call__r2    is not callabler   )inspect
isfunctiongetfullargspecrU   
kwonlyargsisclassget_func_args__init__ismethod__func__ismethoddescriptorr   r   ru   r?   r   	isroutinegetattrrv   r0   r1   pop)ru   	stripselfspec	func_argss   `   r   r}   r}      s   $ 9%d++I/					 9T]D111		$		 9T]D111		#D	)	) 9		D'	"	" 9
 
 
 
"49--c$)nn.>.>?
 
 
 	

 
z	"	" 9T"" 	I4T**j8 	IT]D1114::777888 ar   c                    t          j        |           st          j        |           rt          j        |           }nIt	          | d          rt          j        | j                  }nt          t          |            d          |j        pg }t          |j
                  t          |          z
  }|j
        d|         }t          t          |j
        |d         |                    }||fS )a  Returns (args, kwargs) tuple for a function
    >>> import re
    >>> get_spec(re.match)
    (['pattern', 'string'], {'flags': 0})

    >>> class Test:
    ...     def __call__(self, val):
    ...         pass
    ...     def method(self, val, flags=0):
    ...         pass

    >>> get_spec(Test)
    (['self', 'val'], {})

    >>> get_spec(Test.method)
    (['self', 'val'], {'flags': 0})

    >>> get_spec(Test().method)
    (['self', 'val'], {'flags': 0})
    rv   rw   N)rx   ry   r   rz   r   rv   r0   r1   defaultsr?   rU   dictzip)ru   r   r   firstdefaultrU   rV   s         r   get_specr      s    , $ 97#3D#9#9 9%d++	z	"	" 9%dm444::777888}"Hty>>CMM1L9]l]#D#di.99::F<r   c                     |sdS t                      t                      }}|D ]T}t          |          r ||            ||          k    r dS -t          | ||          t          |||          k    r dS UdS )zCompare two objects attributesFT)objectcallabler   )obj1obj2
attributestemp1temp2attrs         r   equal_attributesr      s      u88VXX5E  D>> 	tDzzTT$ZZ' uuT4''74u+E+EE 	55	 4r   c                     	 d |                                  D             S # t          $ r%  t          |           d | D                       cY S w xY w)zReturn a copy of ``iterable`` with all ``None`` entries removed.

    If ``iterable`` is a mapping, return a dictionary where all pairs that have
    value ``None`` have been removed.
    c                     i | ]
\  }}|||S r   r    )rD   kvs      r   
<dictcomp>z'without_none_values.<locals>.<dictcomp>  s#    CCCAQC1CCCr   c              3      K   | ]}||V  	d S r   r    )rD   r   s     r   rn   z&without_none_values.<locals>.<genexpr>  s'      DDQaDqDDDDDDr   )itemsAttributeErrorr1   )iterables    r   without_none_valuesr     sp    FCC!1!1CCCC F F FtH~~DD(DDDEEEEEFs     ,AAc                 $    | j          d| j         S )z
    Return full name of a global object.

    >>> from scrapy import Request
    >>> global_object_name(Request)
    'scrapy.http.request.Request'
    .)
__module__r2   )objs    r   global_object_namer     s     n--s|---r   pypy_version_infoc                  R    t          j                     t          j                     d S r   gccollectr    r   r   garbage_collectr     s    



r   c                  ,    t          j                     d S r   r   r    r   r   r   r   %  s    

r   c                   :    e Zd ZdZdefdZdeddfdZd Zd	 ZdS )
MutableChainzS
    Thin wrapper around itertools.chain, allowing to add iterables "in-place"
    rU   c                 8    t          j        |          | _        d S r   )r   from_iterablerp   rT   rU   s     r   r~   zMutableChain.__init__.  s    '--			r   	iterablesreturnNc                 ^    t          | j        t          j        |                    | _        d S r   )r   rp   r   rT   r   s     r   extendzMutableChain.extend1  s$    $)U%8%C%CDD			r   c                     | S r   r    rT   s    r   r   zMutableChain.__iter__4      r   c                 *    t          | j                  S r   )nextrp   r   s    r   __next__zMutableChain.__next__7  s    DIr   )	r2   r   __qualname____doc__r   r~   r   r   r   r    r   r   r   r   )  s         .h . . . .E Ed E E E E      r   r   r   r   c                 N   K   | D ]}t          |          2 3 d {V }|W V  6  d S r   r
   )r   itos      r   _async_chainr   ;  sd        )"-- 	 	 	 	 	 	 	!GGGGG .- s   #c                   Z    e Zd ZdZdeeef         fdZdeeef         ddfdZd Z	d	 Z
dS )
MutableAsyncChainz9
    Similar to MutableChain but for async iterables
    rU   c                 "    t          | | _        d S r   r   rp   r   s     r   r~   zMutableAsyncChain.__init__F  s     $'			r   r   r   Nc                 H    t          | j        t          |           | _        d S r   r   r   s     r   r   zMutableAsyncChain.extendI  s     L),DEE			r   c                     | S r   r    r   s    r   	__aiter__zMutableAsyncChain.__aiter__L  r   r   c                 D   K   | j                                          d {V S r   )rp   	__anext__r   s    r   r   zMutableAsyncChain.__anext__O  s,      Y((*********r   )r2   r   r   r   r	   r   r   r~   r   r   r   r    r   r   r   r   A  s         (eHm$;< ( ( ( (Fx'>!? FD F F F F  + + + + +r   r   )Nr-   )r<   )F)'r   r   rx   rH   sysrZ   	functoolsr   r   	itertoolsr   typingr   r   r   r	   scrapy.utils.asyncgenr   r   r   r   r,   r8   r;   rQ   r\   rangerl   rq   r}   r   r   r   r   r   r   r   r   r   r    r   r   <module>r      s    
			  				 



  $ $ $ $ $ $ $ $       A A A A A A A A A A A A 4 4 4 4 4 4  (	 	 	F F F0 "k 
 
 
 
) ) ) )) ) ) )   D   54%%))4447S7S7SS 00<000 04 4 4   <" " "J  $	F 	F 	F. . . 73#$$ 
         8   $5=)@#A n    + + + + + + + + + +r   