
    O=d                        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m	Z	m
Z
 ddlZddlmZ dZ G d d          Zd	d
dddddZi ddddddddddddddddddddddddddd d!d"d#d$d%d&d'i d(d'd)d'd*d'd+d,d-d,d.d,d/d,d0d1d2d1d3d1d4d1d5d6d7d6d8d6d9d6d:d;d<d=i d>d?d@d?dAd?dBd?dCd?dDd?dEdFdGdFdHdFdIdFdJdFdKdFdLdMdNdMdOdMdPdMdQdRdRdRdRdSdTdTdUdVdWdXdYdZdZd[Zd\Zd]Zd^Zd_Zd`ZdaZdbZdcZeez   ez   ez   ez   ZddZdeZdfZdgZdhZ diZ!djZ"dkZ#eez   e z   e!z   Z$dlZ%dme$ dnZ&dme dnZ'doZ(dme dnZ)dme dnZ*dpe e$ e( e e e" dnZ+dqZ,dre' dse, dtZ-dpe dnZ.duZ/dvZ0dme" dnZ1dwZ2dre* dse+ dtZ3dre1 dse+ dtZ4dre% dxZ5dre% dyZ6e- dzZ7dme# d{Z8dre2 dre. dse/ dse0 dte8 e7 d|Z9d}Z:d~Z;e8e7z   e9z   Z<dre) dse/ dse0 dte< Z=dZ>d?                    g de1 dze* de5 de& dse1 de4 de6 de& dse1 e3 de1 dze3 de5 dse1 de6 dse; dse: dse( de= d          Z@ ee          ZA ee@          ZB ee          ZC ejD        e>          ZE ejD        e%          ZF ejD        d          ZGd ZHddZId ZJd ZKd ZLd ZMd ZNd ZOd ZPddZQd ZRd ZSd ZTd ZUd ZVd ZWd ZXddZ?d ZYd ZZd Z[d Z\ddZ]ddZ^ddZ_ddZ`ddZad ZbddZcddZdd Zed ZfddZgddZh	 ddZiddZjddZkd ZlddZmddZnddZod ZpefdZqd ZrddZsd Ztd Zud Zvd Zwd ZxdÄ ZydĄ Zzdń Z{dƄ Z|dǄ Z}dȄ Z~ddɄZddʄZdd˄Zdd̈́Zd΄ Zdτ ZdЄ ZddфZd҄ ZddӄZdԄ ZdՄ Zdք Zdׄ ZdS )z,
String functions.

.. versionadded:: 1.1.0
    N)	parse_qsl	urlencodeurlsplit
urlunsplit   )UNSET)B
camel_case
capitalizechop
chop_rightcharscleancount_substrdeburrdecapitalize	ends_withensure_ends_withensure_starts_withescapeescape_reg_exp
has_substr
human_caseinsert_substrjoin
kebab_caselines
lower_caselower_firstnumber_formatpadpad_end	pad_startpascal_casepredecessorprunequotereg_exp_js_matchreg_exp_js_replacereg_exp_replacerepeatreplacereplace_endreplace_startseparator_caseseries_phraseseries_phrase_serialslugify
snake_casesplit
start_casestarts_with
strip_tagssubstr_leftsubstr_left_endsubstr_rightsubstr_right_end	successorsurround	swap_case
title_caseto_lowerto_uppertrimtrim_end
trim_starttruncateunescapeunquote
upper_caseupper_firsturlwordsc                   $    e Zd ZdZd Zd Zd ZdS )JSRegExpz
    Javascript-style regular expression pattern.

    Converts a Javascript-style regular expression to the equivalent Python version.
    c                     |dd                               dd          \  }}d|v | _        d|v | _        | j        rt          j        nd}t          j        ||          | _        d S )Nr   /gir   flags)rsplit_global_ignore_casereIcompilepattern)selfreg_exprY   optionsrR   s        8D:\Sites\api_v1\venv\Lib\site-packages\pydash/strings.py__init__zJSRegExp.__init__`   sh    "122;--c155g~7N)0qz'777    c                     | j         r| j                            |          }n4| j                            |          }|r|                                g}ng }|S )z*Return list of regular expression matches.)rT   rY   findallsearchgroup)rZ   textresultsress       r]   findzJSRegExp.findi   s[    < 	l**400GG,%%d++C 99;;-r_   c                 R    | j         rdnd}| j                            |||          S )z8Replace parts of text that match the regular expression.r   r   count)rT   rY   sub)rZ   rd   replrj   s       r]   r+   zJSRegExp.replaceu   s/    \(q|d%888r_   N)__name__
__module____qualname____doc__r^   rg   r+    r_   r]   rL   rL   Y   sK         8 8 8
 
 
9 9 9 9 9r_   rL   z&amp;z&lt;z&gt;z&quot;z&#39;z&#96;)&<>"'`   ÀA   Á   Â   Ã   Ä   Å   àa   á   â   ã   ä   å   ÇC   çc   ÐD   ðd   ÈE   É   Ê   Ë   èe   é   ê   ë   ÌrW      Í   Î   Ï   ìrP      í   î   ï   ÑN   ñn   ÒO   Ó   Ô   Õ   Ö   Ø   òo   ó   ô   õ   ö   ø   ÙU   Ú   Û   Ü   ùuYyAeaeThthss )   ú   û   ü   Ý   ý   ÿ   Æ   æ   Þ   þ   ß   ×   ÷z/[^ -/:-@[-`{-]+/gu
   /[À-ÿ]/gz\ud800-\udfffz\u0300-\u036fz\ufe20-\ufe2fz\u20d0-\u20ffz\u1ab0-\u1affz\u1dc0-\u1dffz\u2700-\u27bfza-z\xdf-\xf6\xf8-\xffz\xac\xb1\xd7\xf7z$\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xbfz\u2000-\u206fz \t\x0b\f\xa0\ufeff\n\r\u2028\u2029\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000zA-Z\xc0-\xd6\xd8-\xdez\ufe0e\ufe0fu   ['’][]z\dz[^z\ud83c[\udffb-\udfff]z(?:|)z(?:\ud83c[\udde6-\uddff]){2}z[\ud800-\udbff][\udc00-\udfff]z\u200dz(?:d|ll|m|re|s|t|ve))?z(?:D|LL|M|RE|S|T|VE))??z]?z)*z-\d*(?:1st|2nd|3rd|(?![123])\dth)(?=\b|[A-Z_])z-\d*(?:1ST|2ND|3RD|(?![123])\dTH)(?=\b|[a-z_])zB[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ] rN   +z(?=z|$)|z+|z/gz
<\/?[^>]+>c                     d                     d t          |           D                       } | dd                                         | dd         z   S )aA  
    Converts `text` to camel case.

    Args:
        text (str): String to convert.

    Returns:
        str: String converted to camel case.

    Example:

        >>> camel_case('FOO BAR_bAz')
        'fooBarBAz'

    .. versionadded:: 1.1.0

    .. versionchanged:: 5.0.0
        Improved unicode word support.
    r   c              3   >   K   | ]}|                                 V  d S N)title.0words     r]   	<genexpr>zcamel_case.<locals>.<genexpr>0  s*      ==D4::<<======r_   Nr   r   
compounderlowerrd   s    r]   r	   r	     sQ    ( 77==Jt,<,<=====D8>>d122h&&r_   Tc                     t          j        |           } |r|                                 n&| dd                                         | dd         z   S )a  
    Capitalizes the first character of `text`.

    Args:
        text (str): String to capitalize.
        strict (bool, optional): Whether to cast rest of string to lower case. Defaults to ``True``.

    Returns:
        str: Capitalized string.

    Example:

        >>> capitalize('once upon a TIME')
        'Once upon a time'
        >>> capitalize('once upon a TIME', False)
        'Once upon a TIME'

    .. versionadded:: 1.1.0

    .. versionchanged:: 3.0.0
        Added `strict` option.
    Nr   )pyd	to_stringr
   upperrd   stricts     r]   r
   r
   4  sL    . =D &G4??D!HNN,<,<tABBx,GGr_   c                 D    t          t          j        |                     S )a  
    Split `text` into a list of single characters.

    Args:
        text (str): String to split up.

    Returns:
        list: List of individual characters.

    Example:

        >>> chars('onetwo')
        ['o', 'n', 'e', 't', 'w', 'o']

    .. versionadded:: 3.0.0
    )listr   r   r   s    r]   r   r   O  s    " d##$$$r_   c                       g S t          j                    dk    r g}n+ fdt          dt                               D             }|S )ad  
    Break up `text` into intervals of length `step`.

    Args:
        text (str): String to chop.
        step (int): Interval to chop `text`.

    Returns:
        list: List of chopped characters. If `text` is `None` an empty list is returned.

    Example:

        >>> chop('abcdefg', 3)
        ['abc', 'def', 'g']

    .. versionadded:: 3.0.0
    Nr   c                 *    g | ]}||z            S rq   rq   )r   rP   steprd   s     r]   
<listcomp>zchop.<locals>.<listcomp>}  s&    III!4AH%IIIr_   )r   r   rangelen)rd   r   choppeds   `` r]   r   r   c  sd    $ |	=Dqyy&IIIIIuQD		4/H/HIIINr_   c                       g S t          j                    dk    r g}n7t                      fdt          d          D             ddd         }|S )aA  
    Like :func:`chop` except `text` is chopped from right.

    Args:
        text (str): String to chop.
        step (int): Interval to chop `text`.

    Returns:
        list: List of chopped characters.

    Example:

        >>> chop_right('abcdefg', 3)
        ['a', 'bcd', 'efg']

    .. versionadded:: 3.0.0
    Nr   c                 2    g | ]}|z    |z
           S rq   rq   )r   rP   r   rd   text_lens     r]   r   zchop_right.<locals>.<listcomp>  s-    VVV4!d(hl23VVVr_   )r   r   r   r   )rd   r   r   r   s   `` @r]   r   r     s}    $ |	=Dqyy&t99VVVVVVU1hPT=U=UVVVW[W[Y[W[\Nr_   c                     t          j        |           } d                    t          j        |                                                     S )z
    Trim and replace multiple spaces with a single space.

    Args:
        text (str): String to clean.

    Returns:
        str: Cleaned string.

    Example:

        >>> clean('a  b   c    d')
        'a b c d'

    .. versionadded:: 3.0.0
    r   )r   r   r   compactr3   r   s    r]   r   r     s7    " =D88CK

--...r_   c                     | |dS t          j        |           } t          j        |          }|                     |          S )aM  
    Count the occurrences of `subtext` in `text`.

    Args:
        text (str): Source string to count from.
        subtext (str): String to count.

    Returns:
        int: Number of occurrences of `subtext` in `text`.

    Example:

        >>> count_substr('aabbccddaabbccdd', 'bc')
        2

    .. versionadded:: 3.0.0
    Nr   )r   r   rj   rd   subtexts     r]   r   r     sB    $ |wq=DmG$$G::gr_   c                 b    t          j        |           } t                              | d           S )u:  
    Deburrs `text` by converting latin-1 supplementary letters to basic latin letters.

    Args:
        text (str): String to deburr.

    Returns:
        str: Deburred string.

    Example:

        >>> deburr('déjà vu')
        '...
        >>> 'deja vu'
        'deja vu'

    .. versionadded:: 2.0.0
    c                     t                               |                                 |                                           S r   )DEBURRED_LETTERSgetrc   )matchs    r]   <lambda>zdeburr.<locals>.<lambda>  s'    ,00NN r_   )r   r   JS_RE_LATIN1r+   r   s    r]   r   r     s4    & =DNN  r_   c                 x    t          j        |           } | dd                                         | dd         z   S )a  
    Decaptitalizes the first character of `text`.

    Args:
        text (str): String to decapitalize.

    Returns:
        str: Decapitalized string.

    Example:

        >>> decapitalize('FOO BAR')
        'fOO BAR'

    .. versionadded:: 3.0.0
    Nr   r   r   r   r   s    r]   r   r     s8    " =D8>>d122h&&r_   c                     t          j        |          }t          j        |           } |t          |           }| d|                             |          S )a  
    Checks if `text` ends with a given target string.

    Args:
        text (str): String to check.
        target (str): String to check for.
        position (int, optional): Position to search from. Defaults to end of `text`.

    Returns:
        bool: Whether `text` ends with `target`.

    Example:

        >>> ends_with('abc def', 'def')
        True
        >>> ends_with('abc def', 4)
        False

    .. versionadded:: 1.1.0
    N)r   r   r   endswithrd   targetpositions      r]   r   r      sO    * ]6""F=Dt99		?##F+++r_   c                     t          j        |           } t          j        |          }|                     |          r| S |  | S )a  
    Append a given suffix to a string, but only if the source string does not end with that suffix.

    Args:
        text (str): Source string to append `suffix` to.
        suffix (str): String to append to the source string if the source string does not end with
            `suffix`.

    Returns:
        str: source string possibly extended by `suffix`.

    Example:

        >>> ensure_ends_with('foo bar', '!')
        'foo bar!'
        >>> ensure_ends_with('foo bar!', '!')
        'foo bar!'

    .. versionadded:: 2.4.0
    )r   r   r  )rd   suffixs     r]   r   r     sL    * =D]6""F}}V Fr_   c                     t          j        |           } t          j        |          }|                     |          r| S | |  S )aG  
    Prepend a given prefix to a string, but only if the source string does not start with that
    prefix.

    Args:
        text (str): Source string to prepend `prefix` to.
        prefix (str): String to prepend to the source string if the source string does not start
            with `prefix`.

    Returns:
        str: source string possibly prefixed by `prefix`

    Example:

        >>> ensure_starts_with('foo bar', 'Oh my! ')
        'Oh my! foo bar'
        >>> ensure_starts_with('Oh my! foo bar', 'Oh my! ')
        'Oh my! foo bar'

    .. versionadded:: 2.4.0
    r   r   
startswith)rd   prefixs     r]   r   r   :  sL    , =D]6""Fv dr_   c                 h    t          j        |           } d                    d | D                       S )a  
    Converts the characters ``&``, ``<``, ``>``, ``"``, ``'``, and ``\``` in `text` to their
    corresponding HTML entities.

    Args:
        text (str): String to escape.

    Returns:
        str: HTML escaped string.

    Example:

        >>> escape('"1 > 2 && 3 < 4"')
        '&quot;1 &gt; 2 &amp;&amp; 3 &lt; 4&quot;'

    .. versionadded:: 1.0.0

    .. versionchanged:: 1.1.0
        Moved function to :mod:`pydash.strings`.
    r   c              3   L   K   | ]}t                               ||          V   d S r   )HTML_ESCAPESr   )r   chars     r]   r   zescape.<locals>.<genexpr>o  s2      AAD<##D$//AAAAAAr_   )r   r   r   r   s    r]   r   r   W  s6    * =D 77AADAAAAAAr_   c                 R    t          j        |           } t          j        |           S )aF  
    Escapes the RegExp special characters in `text`.

    Args:
        text (str): String to escape.

    Returns:
        str: RegExp escaped string.

    Example:

        >>> escape_reg_exp('[()]')
        '\\[\\(\\)\\]'

    .. versionadded:: 1.1.0

    .. versionchanged:: 4.0.0
        Removed alias ``escape_re``
    )r   r   rV   r   r   s    r]   r   r   r  s!    ( =D9T??r_   c                     t          j        |           } t          j        |          }|                     |          dk    S )ao  
    Returns whether `subtext` is included in `text`.

    Args:
        text (str): String to search.
        subtext (str): String to search for.

    Returns:
        bool: Whether `subtext` is found in `text`.

    Example:

        >>> has_substr('abcdef', 'bc')
        True
        >>> has_substr('abcdef', 'bb')
        False

    .. versionadded:: 3.0.0
    r   )r   r   rg   r   s     r]   r   r     s9    ( =DmG$$G99W""r_   c                     t          j        |                                                               dd                              dd                                                                          S )a  
    Converts `text` to human case which has only the first letter capitalized and each word
    separated by a space.

    Args:
        text (str): String to convert.

    Returns:
        str: String converted to human case.

    Example:

        >>> human_case('abc-def_hij lmn')
        'Abc def hij lmn'
        >>> human_case('user_id')
        'User'

    .. versionadded:: 3.0.0

    .. versionchanged:: 5.0.0
        Improved unicode word support.
    z_id$r   _r   )r   chainr2   r)   r+   r
   valuer   s    r]   r   r     sM    0 		$			$	$	c				r_   c                     t          j        |           } t          j        |          }| d|         |z   | |d         z   S )ap  
    Insert `subtext` in `text` starting at position `index`.

    Args:
        text (str): String to add substring to.
        index (int): String index to insert into.
        subtext (str): String to insert.

    Returns:
        str: Modified string.

    Example:

        >>> insert_substr('abcdef', 3, '--')
        'abc--def'

    .. versionadded:: 3.0.0
    Nr   r   )rd   indexr   s      r]   r   r     sB    & =DmG$$G<'!DL00r_   c                     t          j        |                              t          j        | pdt           j                            S )a/  
    Joins an iterable into a string using `separator` between each element.

    Args:
        array (iterable): Iterable to implode.
        separator (str, optional): Separator to using when joining. Defaults to ``''``.

    Returns:
        str: Joined string.

    Example:

        >>> join(['a', 'b', 'c']) == 'abc'
        True
        >>> join([1, 2, 3, 4], '&') == '1&2&3&4'
        True
        >>> join('abcdef', '-') == 'a-b-c-d-e-f'
        True

    .. versionadded:: 2.0.0

    .. versionchanged:: 4.0.0
        Removed alias ``implode``.
    rq   )r   r   r   map_)array	separators     r]   r   r     s4    2 =##((%+2s})M)MNNNr_   c                 Z    d                     d t          |           D                       S )aX  
    Converts `text` to kebab case (a.k.a. spinal case).

    Args:
        text (str): String to convert.

    Returns:
        str: String converted to kebab case.

    Example:

        >>> kebab_case('a b c_d-e!f')
        'a-b-c-d-e-f'

    .. versionadded:: 1.1.0

    .. versionchanged:: 5.0.0
        Improved unicode word support.
    -c              3   B   K   | ]}||                                 V  d S r   r   r   s     r]   r   zkebab_case.<locals>.<genexpr>  /      FFTFDJJLLFFFFFFr_   r   r   r   s    r]   r   r     s-    ( 88FFZ-=-=FFFFFFr_   c                 R    t          j        |           } |                                 S )z
    Split lines in `text` into an array.

    Args:
        text (str): String to split.

    Returns:
        list: String split by lines.

    Example:

        >>> lines('a\nb\r\nc')
        ['a', 'b', 'c']

    .. versionadded:: 3.0.0
    )r   r   
splitlinesr   s    r]   r   r     s#    " =D??r_   c                 j    d                     t          |                                                     S )a  
    Converts string to lower case as space separated words.

    Args:
        text (str): String to convert.

    Returns:
        str: String converted to lower case as space separated words.

    Example:

        >>> lower_case('fooBar')
        'foo bar'
        >>> lower_case('--foo-Bar--')
        'foo bar'
        >>> lower_case('/?*Foo10/;"B*Ar')
        'foo 10 b ar'

    .. versionadded:: 4.0.0

    .. versionchanged:: 5.0.0
        Improved unicode word support.
    r   r   r   s    r]   r   r   $  *    0 88Jt$$%%++---r_   c                 P    | dd                                          | dd         z   S )a  
    Converts the first character of string to lower case.

    Args:
        text (str): String passed in by the user.

    Returns:
        str: String in which the first character is converted to lower case.

    Example:

        >>> lower_first('FRED')
        'fRED'
        >>> lower_first('Foo Bar')
        'foo Bar'
        >>> lower_first('1foobar')
        '1foobar'
        >>> lower_first(';foobar')
        ';foobar'

    .. versionadded:: 4.0.0
    Nr   r!  r   s    r]   r   r   ?  )    . 8>>d122h&&r_   .,c                 p   d|dd}	 |                     |                               d          }|d         }|dgz   d         }|                    t          |ddd	         d
                    ddd	         }|                    t	          j        ||g                    }n# t          $ r d}Y nw xY w|S )ac  
    Format a number to scale with custom decimal and order separators.

    Args:
        number (int|float): Number to format.
        scale (int, optional): Number of decimals to include. Defaults to ``0``.
        decimal_separator (str, optional): Decimal separator to use. Defaults to ``'.'``.
        order_separator (str, optional): Order separator to use. Defaults to ``','``.

    Returns:
        str: Formatted number as string.

    Example:

        >>> number_format(1234.5678)
        '1,235'
        >>> number_format(1234.5678, 2, ',', '.')
        '1.234,57'

    .. versionadded:: 3.0.0
    z{0:.r   zf}r*  r   r   r   Nr      )formatr3   r   r   r   r   
ValueError)	numberscaledecimal_separatororder_separatorfmt	num_partsint_partdec_partrd   s	            r]   r   r   Y  s    . %



CIJJv&&,,S11	 Q<$a( #''Xddd^Q(?(?@@2F %%ck8X2F&G&GHH     Ks   (B$ $B32B3c                 .   t          j        |           } t          |           }||k    r| S ||z
  dz  }t          t	          j        |                    }t          t	          j        |                    }t          d||          }|d|         | z   |z   S )a  
    Pads `text` on the left and right sides if it is shorter than the given padding length. The
    `chars` string may be truncated if the number of padding characters can't be evenly divided by
    the padding length.

    Args:
        text (str): String to pad.
        length (int): Amount to pad.
        chars (str, optional): Characters to pad with. Defaults to ``" "``.

    Returns:
        str: Padded string.

    Example:

        >>> pad('abc', 5)
        ' abc '
        >>> pad('abc', 6, 'x')
        'xabcxx'
        >>> pad('abc', 5, '...')
        '.abc.'

    .. versionadded:: 1.1.0

    .. versionchanged:: 3.0.0
        Fix handling of multiple `chars` so that padded string isn't over padded.
    g       @r   N)r   r   r   intmathfloorceilr!   )rd   lengthr   r   midleft_len	right_lens          r]   r    r      s    : =D4yyH6H
#C4:c??##HDIcNN##IB	5))E(d"U**r_   c                     t          j        |           } t          |t          |           f          }| t	          ||          z   d|         S )a~  
    Pads `text` on the right side if it is shorter than the given padding length. The `chars` string
    may be truncated if the number of padding characters can't be evenly divided by the padding
    length.

    Args:
        text (str): String to pad.
        length (int): Amount to pad.
        chars (str, optional): Characters to pad with. Defaults to ``" "``.

    Returns:
        str: Padded string.

    Example:

        >>> pad_end('abc', 5)
        'abc  '
        >>> pad_end('abc', 5, '.')
        'abc..'

    .. versionadded:: 1.1.0

    .. versionchanged:: 4.0.0
        Renamed from ``pad_right`` to ``pad_end``.
    Nr   r   maxr   r*   rd   r=  r   s      r]   r!   r!     sI    6 =D&#d))$%%F6%((('6'22r_   c                     t          j        |           } t          |t          |                     }t	          ||          | z   | d         S )a  
    Pads `text` on the left side if it is shorter than the given padding length. The `chars` string
    may be truncated if the number of padding characters can't be evenly divided by the padding
    length.

    Args:
        text (str): String to pad.
        length (int): Amount to pad.
        chars (str, optional): Characters to pad with. Defaults to ``" "``.

    Returns:
        str: Padded string.

    Example:

        >>> pad_start('abc', 5)
        '  abc'
        >>> pad_start('abc', 5, '.')
        '..abc'

    .. versionadded:: 1.1.0

    .. versionchanged:: 4.0.0
        Renamed from ``pad_left`` to ``pad_start``.
    NrB  rD  s      r]   r"   r"     sH    6 =DT##F5&!!D(6'((33r_   c                     t          j        |           } |r|                                 } t          t	          |           d          S )a
  
    Like :func:`camel_case` except the first letter is capitalized.

    Args:
        text (str): String to convert.
        strict (bool, optional): Whether to cast rest of string to lower case. Defaults to ``True``.

    Returns:
        str: String converted to class case.

    Example:

        >>> pascal_case('FOO BAR_bAz')
        'FooBarBaz'
        >>> pascal_case('FOO BAR_bAz', False)
        'FooBarBAz'

    .. versionadded:: 3.0.0

    .. versionchanged:: 5.0.0
        Improved unicode word support.
    Fr   )r   r   r   r
   r	   r   s     r]   r#   r#     sC    . =D zz||j&&u5555r_   c                 h    t          j        |           } t          t          |           dz
            S )aS  
    Return the predecessor character of `char`.

    Args:
        char (str): Character to find the predecessor of.

    Returns:
        str: Predecessor character.

    Example:

        >>> predecessor('c')
        'b'
        >>> predecessor('C')
        'B'
        >>> predecessor('3')
        '2'

    .. versionadded:: 3.0.0
    r   r   r   chrordr  s    r]   r$   r$     +    * =Ds4yy1}r_   ...c                    t          j        |           } t          |           }t          |          }||k    r| S d }t          | d|dz            d|          }t	          j        d|dd                   rt          |dd          }n|dd	                                         }t          |          }||z   |k    r| d|         |z   } | S )
aI  
    Like :func:`truncate` except it ensures that the pruned string doesn't exceed the original
    length, i.e., it avoids half-chopped words when truncating. If the pruned text + `omission` text
    is longer than the original text, then the original text is returned.

    Args:
        text (str): String to prune.
        length (int, optional): Target prune length. Defaults to ``0``.
        omission (str, optional): Omission text to append to the end of the pruned string. Defaults
            to ``'...'``.

    Returns:
        str: Pruned string.

    Example:

        >>> prune('Fe fi fo fum', 5)
        'Fe fi...'
        >>> prune('Fe fi fo fum', 6)
        'Fe fi...'
        >>> prune('Fe fi fo fum', 7)
        'Fe fi...'
        >>> prune('Fe fi fo fum', 8, ',,,')
        'Fe fi fo,,,'

    .. versionadded:: 3.0.0
    c                     |                      d          }|                                |                                k    rdn|S )Nr   r   )rc   r   r   )r   r  s     r]   rl   zprune.<locals>.replJ  s5    {{1~~jjlldjjll22ss<r_   Nr   z.(?=\W*\w*$)z\w\wz\s*\S+$r   r   )r   r   r   r)   rV   r   rstrip)rd   r=  omissionr   omission_lenrl   r   subtext_lens           r]   r%   r%   &  s    8 =D4yyHx==L6= = = d<VaZ<0/4HHG	x&& ( "':r:: #2#,%%''g,,K 	l"x//L[L!H,Kr_   ru   c                 "    t          | |          S )a  
    Quote a string with another string.

    Args:
        text (str): String to be quoted.
        quote_char (str, optional): the quote character. Defaults to ``"``.

    Returns:
        str: the quoted string.

    Example:

        >>> quote('To be or not to be')
        '"To be or not to be"'
        >>> quote('To be or not to be', "'")
        "'To be or not to be'"

    .. versionadded:: 2.4.0
    )r<   )rd   
quote_chars     r]   r&   r&   c  s    ( D*%%%r_   c                 n    t          j        |           } t          |                              |           S )a  
    Return list of matches using Javascript style regular expression.

    Args:
        text (str): String to evaluate.
        reg_exp (str): Javascript style regular expression.

    Returns:
        list: List of matches.

    Example:

        >>> reg_exp_js_match('aaBBcc', '/bb/')
        []
        >>> reg_exp_js_match('aaBBcc', '/bb/i')
        ['BB']
        >>> reg_exp_js_match('aaBBccbb', '/bb/i')
        ['BB']
        >>> reg_exp_js_match('aaBBccbb', '/bb/gi')
        ['BB', 'bb']

    .. versionadded:: 2.0.0

    .. versionchanged:: 3.0.0
        Reordered arguments to make `text` first.

    .. versionchanged:: 4.0.0
        Renamed from ``js_match`` to ``reg_exp_js_match``.
    )r   r   rL   rg   )rd   r[   s     r]   r'   r'   z  s/    < =DG!!$'''r_   c                     t          j        |           } t          j        |          st          j        |          }t          |                              | |          S )a6  
    Replace `text` with `repl` using Javascript style regular expression to find matches.

    Args:
        text (str): String to evaluate.
        reg_exp (str): Javascript style regular expression.
        repl (str|callable): Replacement string or callable.

    Returns:
        str: Modified string.

    Example:

        >>> reg_exp_js_replace('aaBBcc', '/bb/', 'X')
        'aaBBcc'
        >>> reg_exp_js_replace('aaBBcc', '/bb/i', 'X')
        'aaXcc'
        >>> reg_exp_js_replace('aaBBccbb', '/bb/i', 'X')
        'aaXccbb'
        >>> reg_exp_js_replace('aaBBccbb', '/bb/gi', 'X')
        'aaXccX'

    .. versionadded:: 2.0.0

    .. versionchanged:: 3.0.0
        Reordered arguments to make `text` first.

    .. versionchanged:: 4.0.0
        Renamed from ``js_replace`` to ``reg_exp_js_replace``.
    )r   r   is_functionrL   r+   )rd   r[   rl   s      r]   r(   r(     sR    > =D?4   #}T""G$$T4000r_   Fc                 X    |t          j        |           S t          | ||||d          S )a  
    Replace occurrences of regex `pattern` with `repl` in `text`. Optionally, ignore case when
    replacing. Optionally, set `count` to limit number of replacements.

    Args:
        text (str): String to replace.
        pattern (str|typing.Pattern): Pattern to find and replace.
        repl (str): String to substitute `pattern` with.
        ignore_case (bool, optional): Whether to ignore case when replacing. Defaults to ``False``.
        count (int, optional): Maximum number of occurrences to replace. Defaults to ``0`` which
            replaces all.

    Returns:
        str: Replaced string.

    Example:

        >>> reg_exp_replace('aabbcc', 'b', 'X')
        'aaXXcc'
        >>> reg_exp_replace('aabbcc', 'B', 'X', ignore_case=True)
        'aaXXcc'
        >>> reg_exp_replace('aabbcc', 'b', 'X', count=1)
        'aaXbcc'
        >>> reg_exp_replace('aabbcc', '[ab]', 'X')
        'XXXXcc'

    .. versionadded:: 3.0.0

    .. versionchanged:: 4.0.0
        Renamed from ``re_replace`` to ``reg_exp_replace``.
    NF)ignore_caserj   r   )r   r   r+   )rd   rY   rl   r\  rj   s        r]   r)   r)     s6    @ }T"""4$KuUZ[[[[r_   c                 J    t          j        |           t          |          z  S )a"  
    Repeats the given string `n` times.

    Args:
        text (str): String to repeat.
        n (int, optional): Number of times to repeat the string.

    Returns:
        str: Repeated string.

    Example:

        >>> repeat('.', 5)
        '.....'

    .. versionadded:: 1.1.0
    )r   r   r9  )rd   r   s     r]   r*   r*     s    $ =Q''r_   c                    t          j        |           } || S t          j        |          st          j        |          }|rt          j        nd}t          |t          j                  r|}	nxt          j        |          }|rt          j        |          }|r|	                    d          sd|z   }|r|
                    d          s|dz  }t          j        ||          }	|	                    || |          S )a*  
    Replace occurrences of `pattern` with `repl` in `text`. Optionally, ignore case when replacing.
    Optionally, set `count` to limit number of replacements.

    Args:
        text (str): String to replace.
        pattern (str|typing.Pattern): Pattern to find and replace.
        repl (str): String to substitute `pattern` with.
        ignore_case (bool, optional): Whether to ignore case when replacing. Defaults to ``False``.
        count (int, optional): Maximum number of occurrences to replace. Defaults to ``0`` which
            replaces all.
        escape (bool, optional): Whether to escape `pattern` when searching. This is needed if a
            literal replacement is desired when `pattern` may contain special regular expression
            characters. Defaults to ``True``.
        from_start (bool, optional): Whether to limit replacement to start of string.
        from_end (bool, optional): Whether to limit replacement to end of string.

    Returns:
        str: Replaced string.

    Example:

        >>> replace('aabbcc', 'b', 'X')
        'aaXXcc'
        >>> replace('aabbcc', 'B', 'X', ignore_case=True)
        'aaXXcc'
        >>> replace('aabbcc', 'b', 'X', count=1)
        'aaXbcc'
        >>> replace('aabbcc', '[ab]', 'X')
        'aabbcc'
        >>> replace('aabbcc', '[ab]', 'X', escape=False)
        'XXXXcc'

    .. versionadded:: 3.0.0

    .. versionchanged:: 4.1.0
        Added ``from_start`` and ``from_end`` arguments.

    .. versionchanged:: 5.0.0
        Added support for ``pattern`` as ``typing.Pattern`` object.
    Nr   ^$rQ   ri   )r   r   rZ  rV   
IGNORECASE
isinstancetypingPatternr   r  r  rX   rk   )
rd   rY   rl   r\  rj   r   
from_startfrom_endrR   pats
             r]   r+   r+     s   X =D?4   #}T""(/BMMaE'6>** /-(( 	)i((G 	$g0055 	$GmG 	G,,S11 	sNGj...774U7+++r_   c                 ,    t          | ||||d          S )aI  
    Like :func:`replace` except it only replaces `text` with `repl` if `pattern` mathces the end of
    `text`.

    Args:
        text (str): String to replace.
        pattern (str|typing.Pattern): Pattern to find and replace.
        repl (str): String to substitute `pattern` with.
        ignore_case (bool, optional): Whether to ignore case when replacing. Defaults to ``False``.
        escape (bool, optional): Whether to escape `pattern` when searching. This is needed if a
            literal replacement is desired when `pattern` may contain special regular expression
            characters. Defaults to ``True``.

    Returns:
        str: Replaced string.

    Example:

        >>> replace_end('aabbcc', 'b', 'X')
        'aabbcc'
        >>> replace_end('aabbcc', 'c', 'X')
        'aabbcX'

    .. versionadded:: 4.1.0
    T)r\  r   rf  r+   rd   rY   rl   r\  r   s        r]   r,   r,   E  s     4 4$KY]^^^^r_   c                 ,    t          | ||||d          S )aO  
    Like :func:`replace` except it only replaces `text` with `repl` if `pattern` mathces the start
    of `text`.

    Args:
        text (str): String to replace.
        pattern (str|typing.Pattern): Pattern to find and replace.
        repl (str): String to substitute `pattern` with.
        ignore_case (bool, optional): Whether to ignore case when replacing. Defaults to ``False``.
        escape (bool, optional): Whether to escape `pattern` when searching. This is needed if a
            literal replacement is desired when `pattern` may contain special regular expression
            characters. Defaults to ``True``.

    Returns:
        str: Replaced string.

    Example:

        >>> replace_start('aabbcc', 'b', 'X')
        'aabbcc'
        >>> replace_start('aabbcc', 'a', 'X')
        'Xabbcc'

    .. versionadded:: 4.1.0
    T)r\  r   re  ri  rj  s        r]   r-   r-   b  s     4 4$K[_````r_   c                 Z    |                     d t          |           D                       S )a  
    Splits `text` on words and joins with `separator`.

    Args:
        text (str): String to convert.
        separator (str): Separator to join words with.

    Returns:
        str: Converted string.

    Example:

        >>> separator_case('a!!b___c.d', '-')
        'a-b-c-d'

    .. versionadded:: 3.0.0

    .. versionchanged:: 5.0.0
        Improved unicode word support.
    c              3   B   K   | ]}||                                 V  d S r   r!  r   s     r]   r   z!separator_case.<locals>.<genexpr>  s/      GG4$G$**,,GGGGGGr_   )r   rJ   )rd   r  s     r]   r.   r.     s+    * >>GG5;;GGGGGGr_   ,  and c                    t          j        |                               t           j                                                                                  } t          |           }t          j        |          }t          j        |          }|dk    r|r|                                |z   }|dk    r)| dd         |                    | dd                   gz   } |                    |           S )az  
    Join items into a grammatical series phrase, e.g., ``"item1, item2, item3 and item4"``.

    Args:
        items (list): List of string items to join.
        separator (str, optional): Item separator. Defaults to ``', '``.
        last_separator (str, optional): Last item separator. Defaults to ``' and '``.
        serial (bool, optional): Whether to include `separator` with `last_separator` when number of
            items is greater than 2. Defaults to ``False``.

    Returns:
        str: Joined string.

    Example:

        >>> series_phrase(['apples', 'bananas', 'peaches'])
        'apples, bananas and peaches'
        >>> series_phrase(['apples', 'bananas', 'peaches'], serial=True)
        'apples, bananas, and peaches'
        >>> series_phrase(['apples', 'bananas', 'peaches'], '; ', ', or ')
        'apples; bananas, or peaches'


    .. versionadded:: 3.0.0
       NrQ  )	r   r  mapr   r   r  r   rR  r   )itemsr  last_separatorserial
item_counts        r]   r/   r/     s    4 Ie  //7799??AAEUJi((I]>22NA~~&~"))++n<Qcrc
n11%*==>>>>%   r_   c                 (    t          | ||d          S )a  
    Join items into a grammatical series phrase using a serial separator, e.g., ``"item1, item2,
    item3, and item4"``.

    Args:
        items (list): List of string items to join.
        separator (str, optional): Item separator. Defaults to ``', '``.
        last_separator (str, optional): Last item separator. Defaults to ``' and '``.

    Returns:
        str: Joined string.

    Example:

        >>> series_phrase_serial(['apples', 'bananas', 'peaches'])
        'apples, bananas, and peaches'

    .. versionadded:: 3.0.0
    T)ru  )r/   )rs  r  rt  s      r]   r0   r0     s    ( 	>$GGGGr_   r  c                     t          j        dt          j        |                                         dd                              d          }t          ||          S )up  
    Convert `text` into an ASCII slug which can be used safely in URLs. Incoming `text` is converted
    to unicode and noramlzied using the ``NFKD`` form. This results in some accented characters
    being converted to their ASCII "equivalent" (e.g. ``é`` is converted to ``e``). Leading and
    trailing whitespace is trimmed and any remaining whitespace or other special characters without
    an ASCII equivalent are replaced with ``-``.

    Args:
        text (str): String to slugify.
        separator (str, optional): Separator to use. Defaults to ``'-'``.

    Returns:
        str: Slugified string.

    Example:

        >>> slugify('This is a slug.') == 'this-is-a-slug'
        True
        >>> slugify('This is a slug.', '+') == 'this+is+a+slug'
        True

    .. versionadded:: 3.0.0

    .. versionchanged:: 5.0.0
        Improved unicode word support.
    NFKDasciiignoreutf8)unicodedata	normalizer   r   encodedecoder.   )rd   r  
normalizeds      r]   r1   r1     sT    8 	fcmD&9&9::AA'8TT[[\bcc  *i000r_   c                 Z    d                     d t          |           D                       S )a  
    Converts `text` to snake case.

    Args:
        text (str): String to convert.

    Returns:
        str: String converted to snake case.

    Example:

        >>> snake_case('This is Snake Case!')
        'this_is_snake_case'

    .. versionadded:: 1.1.0

    .. versionchanged:: 4.0.0
        Removed alias ``underscore_case``.

    .. versionchanged:: 5.0.0
        Improved unicode word support.
    r  c              3   B   K   | ]}||                                 V  d S r   r!  r   s     r]   r   zsnake_case.<locals>.<genexpr>  r"  r_   r#  r   s    r]   r2   r2     s-    . 88FFZ-=-=FFFFFFr_   c                     t          j        |           } |t          u r|                                 }n'|r|                     |          }nt	          |           }|S )ay  
    Splits `text` on `separator`. If `separator` not provided, then `text` is split on whitespace.
    If `separator` is falsey, then `text` is split on every character.

    Args:
        text (str): String to explode.
        separator (str, optional): Separator string to split on. Defaults to ``NoValue``.

    Returns:
        list: Split string.

    Example:

        >>> split('one potato, two potatoes, three potatoes, four!')
        ['one', 'potato,', 'two', 'potatoes,', 'three', 'potatoes,', 'four!']
        >>> split('one potato, two potatoes, three potatoes, four!', ',')
        ['one potato', ' two potatoes', ' three potatoes', ' four!']

    .. versionadded:: 2.0.0

    .. versionchanged:: 3.0.0
        Changed `separator` default to ``NoValue`` and supported splitting on whitespace by default.

    .. versionchanged:: 4.0.0
        Removed alias ``explode``.
    )r   r   r   r3   r   )rd   r  rets      r]   r3   r3     sX    6 =DEjjll	 jj##DkkJr_   c                 Z    d                     d t          |           D                       S )a9  
    Convert `text` to start case.

    Args:
        text (str): String to convert.

    Returns:
        str: String converted to start case.

    Example:

        >>> start_case("fooBar")
        'Foo Bar'

    .. versionadded:: 3.1.0

    .. versionchanged:: 5.0.0
        Improved unicode word support.
    r   c              3   8   K   | ]}t          |d           V  dS )FrG  Nr
   r   s     r]   r   zstart_case.<locals>.<genexpr>N  s/      PPtJtE222PPPPPPr_   r#  r   s    r]   r4   r4   :  s-    ( 88PPz$?O?OPPPPPPr_   c                     t          j        |           } t          j        |          }| |d                             |          S )a  
    Checks if `text` starts with a given target string.

    Args:
        text (str): String to check.
        target (str): String to check for.
        position (int, optional): Position to search from. Defaults to beginning of `text`.

    Returns:
        bool: Whether `text` starts with `target`.

    Example:

        >>> starts_with('abcdef', 'a')
        True
        >>> starts_with('abcdef', 'b')
        False
        >>> starts_with('abcdef', 'a', 1)
        False

    .. versionadded:: 1.1.0
    Nr
  r  s      r]   r5   r5   Q  s>    . =D]6""F		?%%f---r_   c                 \    t                               dt          j        |                     S )a  
    Removes all HTML tags from `text`.

    Args:
        text (str): String to strip.

    Returns:
        str: String without HTML tags.

    Example:

        >>> strip_tags('<a href="#">Some link</a>')
        'Some link'

    .. versionadded:: 3.0.0
    r   )RE_HTML_TAGSrk   r   r   r   s    r]   r6   r6   m  s$    " Bd 3 3444r_   c                 h    t          j        |           } |r|                     |          d         n| S )a  
    Searches `text` from left-to-right for `subtext` and returns a substring consisting of the
    characters in `text` that are to the left of `subtext` or all string if no match found.

    Args:
        text (str): String to partition.
        subtext (str): String to search for.

    Returns:
        str: Substring to left of `subtext`.

    Example:

        >>> substr_left('abcdefcdg', 'cd')
        'ab'

    .. versionadded:: 3.0.0
    r   r   r   	partitionr   s     r]   r7   r7     s4    & =D)0:4>>'""1%%d:r_   c                 l    t          j        |           } |r|                     |          d         p| n| S )a  
    Searches `text` from right-to-left for `subtext` and returns a substring consisting of the
    characters in `text` that are to the left of `subtext` or all string if no match found.

    Args:
        text (str): String to partition.
        subtext (str): String to search for.

    Returns:
        str: Substring to left of `subtext`.

    Example:

        >>> substr_left_end('abcdefcdg', 'cd')
        'abcdef'

    .. versionadded:: 3.0.0
    r   r   r   
rpartitionr   s     r]   r8   r8     s7    & =D29C4??7##A&.$tCr_   c                 l    t          j        |           } |r|                     |          d         p| n| S )a  
    Searches `text` from right-to-left for `subtext` and returns a substring consisting of the
    characters in `text` that are to the right of `subtext` or all string if no match found.

    Args:
        text (str): String to partition.
        subtext (str): String to search for.

    Returns:
        str: Substring to right of `subtext`.

    Example:

        >>> substr_right('abcdefcdg', 'cd')
        'efcdg'

    .. versionadded:: 3.0.0
    rq  r  r   s     r]   r9   r9     s7    & =D18B4>>'""1%-dBr_   c                 h    t          j        |           } |r|                     |          d         n| S )a  
    Searches `text` from left-to-right for `subtext` and returns a substring consisting of the
    characters in `text` that are to the right of `subtext` or all string if no match found.

    Args:
        text (str): String to partition.
        subtext (str): String to search for.

    Returns:
        str: Substring to right of `subtext`.

    Example:

        >>> substr_right_end('abcdefcdg', 'cd')
        'g'

    .. versionadded:: 3.0.0
    rq  r  r   s     r]   r:   r:     s4    & =D*1;4??7##A&&t;r_   c                 h    t          j        |           } t          t          |           dz             S )aG  
    Return the successor character of `char`.

    Args:
        char (str): Character to find the successor of.

    Returns:
        str: Successor character.

    Example:

        >>> successor('b')
        'c'
        >>> successor('B')
        'C'
        >>> successor('2')
        '3'

    .. versionadded:: 3.0.0
    r   rI  rL  s    r]   r;   r;     rM  r_   c                 b    t          j        |           } t          j        |          }| |  | S )aq  
    Surround a string with another string.

    Args:
        text (str): String to surround with `wrapper`.
        wrapper (str): String by which `text` is to be surrounded.

    Returns:
        str: Surrounded string.

    Example:

        >>> surround('abc', '"')
        '"abc"'
        >>> surround('abc', '!')
        '!abc!'

    .. versionadded:: 2.4.0
    r  )rd   wrappers     r]   r<   r<     s8    ( =DmG$$G&t&W&&&r_   c                 R    t          j        |           } |                                 S )z
    Swap case of `text` characters.

    Args:
        text (str): String to swap case.

    Returns:
        str: String with swapped case.

    Example:

        >>> swap_case('aBcDeF')
        'AbCdEf'

    .. versionadded:: 3.0.0
    )r   r   swapcaser   s    r]   r=   r=     s!    " =D==??r_   c                     t          j        |           } d                    d t          j        d|           D                       S )z
    Convert `text` to title case.

    Args:
        text (str): String to convert.

    Returns:
        str: String converted to title case.

    Example:

        >>> title_case("bob's shop")
        "Bob's Shop"

    .. versionadded:: 3.0.0
    r   c              3   >   K   | ]}|                                 V  d S r   r  r   s     r]   r   ztitle_case.<locals>.<genexpr>7  s,      FF$DOO%%FFFFFFr_   )r   r   r   rV   r3   r   s    r]   r>   r>   $  s@    " =D88FF"(32E2EFFFFFFr_   c                 N    t          j        |                                           S )au  
    Converts the given :attr:`text` to lower text.

    Args:
        text (str): String to convert.

    Returns:
        str: String converted to lower case.

    Example:

        >>> to_lower('--Foo-Bar--')
        '--foo-bar--'
        >>> to_lower('fooBar')
        'foobar'
        >>> to_lower('__FOO_BAR__')
        '__foo_bar__'

    .. versionadded:: 4.0.0
    r  r   s    r]   r?   r?   :       * =$$&&&r_   c                 N    t          j        |                                           S )au  
    Converts the given :attr:`text` to upper text.

    Args:
        text (str): String to convert.

    Returns:
        str: String converted to upper case.

    Example:

        >>> to_upper('--Foo-Bar--')
        '--FOO-BAR--'
        >>> to_upper('fooBar')
        'FOOBAR'
        >>> to_upper('__FOO_BAR__')
        '__FOO_BAR__'

    .. versionadded:: 4.0.0
    )r   r   r   r   s    r]   r@   r@   R  r  r_   c                 T    t          j        |           } |                     |          S )aO  
    Removes leading and trailing whitespace or specified characters from `text`.

    Args:
        text (str): String to trim.
        chars (str, optional): Specific characters to remove.

    Returns:
        str: Trimmed string.

    Example:

        >>> trim('  abc efg\r\n ')
        'abc efg'

    .. versionadded:: 1.1.0
    )r   r   striprd   r   s     r]   rA   rA   j  s%    & =D::er_   c                 T    t          j        |           } |                     |          S )a  
    Removes trailing whitespace or specified characters from `text`.

    Args:
        text (str): String to trim.
        chars (str, optional): Specific characters to remove.

    Returns:
        str: Trimmed string.

    Example:

        >>> trim_end('  abc efg\r\n ')
        '  abc efg'

    .. versionadded:: 1.1.0

    .. versionchanged:: 4.0.0
        Renamed from ``trim_right`` to ``trim_end``.
    )r   r   rR  r  s     r]   rB   rB     %    * =D;;ur_   c                 T    t          j        |           } |                     |          S )a  
    Removes leading  whitespace or specified characters from `text`.

    Args:
        text (str): String to trim.
        chars (str, optional): Specific characters to remove.

    Returns:
        str: Trimmed string.

    Example:

        >>> trim_start('  abc efg\r\n ')
        'abc efg\r\n '

    .. versionadded:: 1.1.0

    .. versionchanged:: 4.0.0
        Renamed from ``trim_left`` to ``trim_start``.
    )r   r   lstripr  s     r]   rC   rC     r  r_      c                    t          j        |           } t          |           |k    r| S t          |          }||z
  }| d|         } t          |           }t          j        |          r|                     |          }nFt          j        |          r2d}|                    |           D ]}|}||                                }| d|         |z   S )a`  
    Truncates `text` if it is longer than the given maximum string length. The last characters of
    the truncated string are replaced with the omission string which defaults to ``...``.

    Args:
        text (str): String to truncate.
        length (int, optional): Maximum string length. Defaults to ``30``.
        omission (str, optional): String to indicate text is omitted.
        separator (mixed, optional): Separator pattern to truncate to.

    Returns:
        str: Truncated string.

    Example:

        >>> truncate('hello world', 5)
        'he...'
        >>> truncate('hello world', 5, '..')
        'hel..'
        >>> truncate('hello world', 10)
        'hello w...'
        >>> truncate('hello world', 10, separator=' ')
        'hello...'

    .. versionadded:: 1.1.0

    .. versionchanged:: 4.0.0
        Removed alias ``trunc``.
    N)r   r   r   	is_stringrfind
is_reg_expfinditerstart)	rd   r=  rS  r  rT  r   	trunc_lenlastr   s	            r]   rD   rD     s    < =D
4yyFx==L$H		?DD		I
}Y %JJy))					"	" %''-- 	 	EDD

I

h&&r_   c                 R    t          j        |           } t          j        |           S )a  
    The inverse of :func:`escape`. This method converts the HTML entities ``&amp;``, ``&lt;``,
    ``&gt;``, ``&quot;``, ``&#39;``, and ``&#96;`` in `text` to their corresponding characters.

    Args:
        text (str): String to unescape.

    Returns:
        str: HTML unescaped string.

    Example:

        >>> results = unescape('&quot;1 &gt; 2 &amp;&amp; 3 &lt; 4&quot;')
        >>> results == '"1 > 2 && 3 < 4"'
        True

    .. versionadded:: 1.0.0

    .. versionchanged:: 1.1.0
        Moved to :mod:`pydash.strings`.
    )r   r   htmlrE   r   s    r]   rE   rE     s#    , =D=r_   c                 j    d                     t          |                                                     S )a  
    Converts string to upper case, as space separated words.

    Args:
        text (str): String to be converted to uppercase.

    Returns:
        str: String converted to uppercase, as space separated words.

    Example:

        >>> upper_case('--foo-bar--')
        'FOO BAR'
        >>> upper_case('fooBar')
        'FOO BAR'
        >>> upper_case('/?*Foo10/;"B*Ar')
        'FOO 10 B AR'

    .. versionadded:: 4.0.0

    .. versionchanged:: 5.0.0
        Improved unicode word support.
    r   )r   r   r   r   s    r]   rG   rG     r'  r_   c                 P    | dd                                          | dd         z   S )a  
    Converts the first character of string to upper case.

    Args:
        text (str): String passed in by the user.

    Returns:
        str: String in which the first character is converted to upper case.

    Example:

        >>> upper_first('fred')
        'Fred'
        >>> upper_first('foo bar')
        'Foo bar'
        >>> upper_first('1foobar')
        '1foobar'
        >>> upper_first(';foobar')
        ';foobar'

    .. versionadded:: 4.0.0
    Nr   )r   r   s    r]   rH   rH     r)  r_   c                 ^    t          j        |           } | dd         }| | | | k    r|} | S )a  
    Unquote `text` by removing `quote_char` if `text` begins and ends with it.

    Args:
        text (str): String to unquote.
        quote_char (str, optional): Quote character to remove. Defaults to `"`.

    Returns:
        str: Unquoted string.

    Example:

        >>> unquote('"abc"')
        'abc'
        >>> unquote('"abc"', '#')
        '"abc"'
        >>> unquote('#abc', '#')
        '#abc'
        >>> unquote('#abc#', '#')
        'abc'

    .. versionadded:: 3.0.0
    r   r   r  )rd   rW  inners      r]   rF   rF   8  sE    0 =D2JE*1e1Z1111Kr_   c            
         t          j        |                                                               t           j                                                  } g }t          |          }| D ]R}t          |          \  }}}}}t          |          }||z  }|	                    t          |||d|f                     St          dg|R  }t          |          \  }}}}}t          |          }t          |||||f          S )a-  
    Combines a series of URL paths into a single URL. Optionally, pass in keyword arguments to
    append query parameters.

    Args:
        paths (str): URL paths to combine.

    Keyword Args:
        params (str, optional): Query parameters.

    Returns:
        str: URL string.

    Example:

        >>> link = url('a', 'b', ['c', 'd'], '/', q='X', y='Z')
        >>> path, params = link.split('?')
        >>> path == 'a/b/c/d/'
        True
        >>> set(params.split('&')) == set(['q=X', 'y=Z'])
        True

    .. versionadded:: 2.2.0
    r   rN   )r   r  flatten_deeprr  r   r  flatten_url_paramsr   r   appendr   delimitedpathjoinr   )	pathsparams
paths_listparams_listpathschemenetlocqueryfragments	            r]   rI   rI   Y  s   2 Ie))++//>>DDFFEJ$V,,K L L08-eX%  u*ffdB%IJJKKKKS.:...D,4TNN)FFD%k""EvvtUH=>>>r_   c                     t          j        |           } |t          |           rt          }nt          }nt          |          }|                    |           S )a  
    Return list of words contained in `text`.

    References:
        https://github.com/lodash/lodash/blob/master/words.js#L30

    Args:
        text (str): String to split.
        pattern (str, optional): Custom pattern to split words on. Defaults to ``None``.

    Returns:
        list: List of words.

    Example:

        >>> words('a b, c; d-e')
        ['a', 'b', 'c', 'd', 'e']
        >>> words('fred, barney, & pebbles', '/[^, ]+/g')
        ['fred', 'barney', '&', 'pebbles']

    .. versionadded:: 2.0.0

    .. versionchanged:: 3.2.0
        Added `pattern` argument.

    .. versionchanged:: 3.2.0
        Improved matching for one character words.

    .. versionchanged:: 5.0.0
        Improved unicode word support.
    )r   r   has_unicode_wordJS_RE_UNICODE_WORDSJS_RE_ASCII_WORDSrL   rg   )rd   rY   r[   s      r]   rJ   rJ     sV    @ =DD!! 	()GG'GG7##<<r_   c           
          t          t          t                              dt	          j        |                                         S )a  
    Remove single quote before passing into words() to match Lodash-style outputs.

    Required by certain functions such as kebab_case, camel_case, start_case etc.

    References:
        https://github.com/lodash/lodash/blob/4.17.15/lodash.js#L4968
    r   )rJ   r   RE_APOSrk   r   r   r   s    r]   r   r     s2     Bd(;(;<<==>>>r_   c                 T    t                               |           }t          |          S )z
    Check if the text contains unicode or requires more complex regex to handle.

    References:
        https://github.com/lodash/lodash/blob/master/words.js#L3
    )RE_HAS_UNICODE_WORDrb   bool)rd   results     r]   r  r    s#     !''--F<<r_   c                 r    d t          j        |          D             }t          |          dk    r	|d         }n{|r|d                                        r nd}|r|d                                        r nd}                      fd|D                       }d                    |||g          }|S )a  
    Join delimited path using specified delimiter.

    >>> assert delimitedpathjoin('.', '') == ''
    >>> assert delimitedpathjoin('.', '.') == '.'
    >>> assert delimitedpathjoin('.', ['', '.a']) == '.a'
    >>> assert delimitedpathjoin('.', ['a', '.']) == 'a.'
    >>> assert delimitedpathjoin('.', ['', '.a', '', '', 'b']) == '.a.b'
    >>> ret = '.a.b.c.d.e.'
    >>> assert delimitedpathjoin('.', ['.a.', 'b.', '.c', 'd', 'e.']) == ret
    >>> assert delimitedpathjoin('.', ['a', 'b', 'c']) == 'a.b.c'
    >>> ret = 'a.b.c.d.e.f'
    >>> assert delimitedpathjoin('.', ['a.b', '.c.d.', '.e.f']) == ret
    >>> ret = '.a.b.c.1.'
    >>> assert delimitedpathjoin('.', '.', 'a', 'b', 'c', 1, '.') == ret
    >>> assert delimitedpathjoin('.', []) == ''
    c                 :    g | ]}|t          j        |          S rq   r  )r   r  s     r]   r   z%delimitedpathjoin.<locals>.<listcomp>  s'    MMMTMS]4  MMMr_   r   r   r   r   c                 d    g | ],}|                               |                               -S rq   )r  )r   r  	delimiters     r]   r   z%delimitedpathjoin.<locals>.<listcomp>  s7     b b b4DJJW`LaLa bI!6!6 b b br_   )r   r  r   r  r  r   )r  r  r  leadingtrailingmiddles   `     r]   r  r    s    $ NMS-=e-D-DMMME
5zzQ Qx$Oq)<)<Y)G)GO))R %O%)*<*<Y*G*GO99R b b b b5 b b bccww233Kr_   c                 6   t          | t                    r!t          |                                           } g }| D ]]\  }}t          |t          t          f          r%|t          |gt          |          z  |          z  }F|                    ||f           ^|S )ah  
    Flatten URL params into list of tuples. If any param value is a list or tuple, then map each
    value to the param key.

    >>> params = [('a', 1), ('a', [2, 3])]
    >>> assert flatten_url_params(params) == [('a', 1), ('a', 2), ('a', 3)]
    >>> params = {'a': [1, 2, 3]}
    >>> assert flatten_url_params(params) == [('a', 1), ('a', 2), ('a', 3)]
    )rb  dictr   rs  tuplezipr   r  )r  	flattenedparamr  s       r]   r  r    s     &$ &fllnn%%I - -uedE]++ 	-eWs5zz15999IIeU^,,,,r_   )Tr   )r   )r   r*  r+  )r   )r   rN  )ru   )Fr   )r   )Fr   TFF)FT)rn  ro  F)rn  ro  )r  )r  rN  N)rp   r  r:  rV   rc  r}  urllib.parser   r   r   r   pydashr   helpersr   __all__rL   r  r   RS_ASCII_WORDS	RS_LATIN1RS_ASTRAL_RANGERS_COMBO_MARKS_RANGERE_COMBO_HALF_MARKS_RANGERS_COMBO_SYMBOLS_RANGERS_COMBO_MARKS_EXTENDED_RANGERS_COMBO_MARKS_SUPPLEMENT_RANGERS_COMBO_RANGERS_DINGBAT_RANGERS_LOWER_RANGERS_MATH_OP_RANGERS_NON_CHAR_RANGERS_PUNCTUATION_RANGERS_SPACE_RANGERS_UPPER_RANGERS_VAR_RANGERS_BREAK_RANGERS_APOSRS_BREAKRS_COMBORS_DIGIT
RS_DINGBATRS_LOWERRS_MISCRS_FITZRS_MODIFIERRS_NON_ASTRALRS_REGIONALRS_SURR_PAIRRS_UPPERRS_ZWJRS_MISC_LOWERRS_MISC_UPPERRS_OPT_CONTR_LOWERRS_OPT_CONTR_UPPER
RE_OPT_MOD
RS_OPT_VARRS_OPT_JOINRS_ORD_LOWERRS_ORD_UPPERRS_SEQRS_EMOJIRS_HAS_UNICODE_WORDr   RS_UNICODE_WORDSr  r  r   rX   r  r  r  r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rG   rH   rF   rI   rJ   r   r  r  r  rq   r_   r]   <module>r
     s      				      C C C C C C C C C C C C          CL9 9 9 9 9 9 9 9D 6XGZabbA
CA
CA CA C	A
 CA CA CA CA CA CA CA CA CA CA CA  C!A" C#A A$ C%A& C'A( C)A* C+A, C-A. C/A0 C1A2 C3A4 C5A6 C7A8 C9A: C;A< C=A> C?A@ CAAB CCAD CEA A AF CGAH CIAJ CKAL CMAN COAP CQAR CSAT CUAV CWAX CYAZ C[A\ C]A^ C_A` CaAb CcAd CeAf CgA Ah AA A A N ?	 $( - *  1 "3   $$ &	&  % ,) B ( 6 
 -!$558LL~]  ~    ~   $!$$$
 ~   ; ;. ;( ;;';)7; ; ;  %)H))w)))'_'''/3 ~   	 ,h++++++h+++++:7::: :7::: 
!!!!
\&\\]\\[\\<\\*\j\\\  BA	j	 ;	.CCCkCCLCC6CCZ 	
 	
 	
 	
 	
 	
	
 	
 	
 	
	
 	
 	
 	
/	
 	
 	
 	
4<	
 	
 	
 	
?G	
 	
 	
 	
	
 	
 	
 	
*	
 	
 	
 	
/7	
 	
 	
 	
:B	
 	
DQ	
 	
 	
 	
 		
 	
 	
 	
 !	
 	
 	
 	
 $6	
 	
 	
 	
 			
 	
 	
 	
 &		
 	
 	
 	

 		
 	
 	
 	
 		
 	
 	
 	
 		
 	
 	
 	
 		
 	
 	
 	
 	
 	
  H^,, h/00 x	"" bj!455 
"*W

rz-((' ' '0H H H H6% % %(  >  @/ / /*  6  2' ' '*, , , ,<  8  :B B B6  0# # #2  B1 1 10O O O O8G G G.  *. . .6' ' '4' ' ' 'T(+ (+ (+ (+V3 3 3 3@4 4 4 4@6 6 6 6>  2: : : :z& & & &.( ( (D"1 "1 "1J#\ #\ #\ #\L( ( ( (, ^cF, F, F, F,R_ _ _ _:a a a a:H H H0&! &! &! &!RH H H H.1 1 1 1DG G G4   $ $ $ $NQ Q Q.. . . .85 5 5(; ; ;.D D D.C C C.< < <.  2' ' '2  *G G G,' ' '0' ' '0   .   2   23' 3' 3' 3'l  4. . .6' ' '4   B'? '? '?T( ( ( (`	? 	? 	?    B    r_   