o
    tBh                     @   sT  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 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 e e e ZddZdeZdfZdgZdhZ diZ!djZ"dkZ#ee e  e! 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;e8e7 e9 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ZAee@ZBeeZCeDe>ZEeDe%ZFeDdZGdd ZHdddZIdd ZJdd ZKdd ZLdd ZMdd ZNdd ZOdd ZPdddZQdd ZRdd ZSdd ZTdd ZUdd ZVdd ZWdd ZXd ddZ?dd ZYdd ZZdd Z[dd Z\d!ddZ]d"ddZ^d"ddZ_d"ddZ`dddZadd Zbd#ddńZcd$ddȄZdddʄ Zedd̄ Zfd%ddτZgd&ddфZh	͐d'ddӄZid(ddՄZjd(ddׄZkddل Zld)dd݄Zmd*dd߄Znd+ddZodd ZpefddZqdd Zrd&ddZsdd Ztdd Zudd Zvdd Zwdd Zxdd Zydd Zzdd Z{dd Z|dd Z}dd  Z~dddZdddZdddZd,dd	Zd
d Zdd Zdd Zd$ddZdd ZdddZdd Zdd Zdd Zdd 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                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	JSRegExpz
    Javascript-style regular expression pattern.

    Converts a Javascript-style regular expression to the equivalent Python version.
    c                 C   sP   |dd   dd\}}d|v | _d|v | _| jrtjnd}tj||d| _d S )Nr   /gir   flags)rsplit_global_ignore_casereIcompilepattern)selfreg_exprV   optionsrO    rZ   e/var/www/html/riverr-enterprise-integrations-main/venv/lib/python3.10/site-packages/pydash/strings.py__init__`   s
   

zJSRegExp.__init__c                 C   s<   | j r| j|}|S | j|}|r| g}|S g }|S )z*Return list of regular expression matches.)rQ   rV   findallsearchgroup)rW   textresultsresrZ   rZ   r[   findi   s   
zJSRegExp.findc                 C   s    | j rdnd}| jj|||dS )z8Replace parts of text that match the regular expression.r   r   count)rQ   rV   sub)rW   r`   replre   rZ   rZ   r[   r*   u   s   zJSRegExp.replaceN)__name__
__module____qualname____doc__r\   rc   r*   rZ   rZ   rZ   r[   rJ   Y   s
    	rJ   z&amp;z&lt;z&gt;z&quot;z&#39;z&#96;)&<>"'`   ÀA   Á   Â   Ã   Ä   Å   àa   á   â   ã   ä   å   ÇC   çc   ÐD   ðd   ÈE   É   Ê   Ë   èe   é   ê   ë   ÌrT      Í   Î   Ï   ìrM      í   î   ï   Ñ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 ] rK   +z(?=z|$)|z+|z/gz
<\/?[^>]+>c                 C   s4   d dd t| D } | dd  | dd  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                 s       | ]}|  V  qd S N)title.0wordrZ   rZ   r[   	<genexpr>0      zcamel_case.<locals>.<genexpr>Nr   r   
compounderlowerr`   rZ   rZ   r[   r     s   r   Tc                 C   s2   t | } |r|  S | dd  | dd  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r`   strictrZ   rZ   r[   r	   4  s   
(r	   c                 C   s   t t| 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   rZ   rZ   r[   r   O  s   r   c                    sL   du rg S t  dkrg}|S  fd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                    s   g | ]
}||   qS rZ   rZ   r   rM   stepr`   rZ   r[   
<listcomp>}  s    zchop.<locals>.<listcomp>)r   r   rangelenr`   r   choppedrZ   r   r[   r
   c  s   
 r
   c                    s\   du rg S t  dkrg}|S t fd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                    s"   g | ]}|   |  qS rZ   rZ   r   r   r`   text_lenrZ   r[   r     s   " zchop_right.<locals>.<listcomp>)r   r   r   r   r   rZ   r   r[   r     s   
(r   c                 C   s   t | } dt |  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   compactr2   r   rZ   rZ   r[   r     s   
r   c                 C   s2   | du s|du r
dS t | } t |}| |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   re   r`   subtextrZ   rZ   r[   r     s
   


r   c                 C   s   t | } t| d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                 S   s   t |  |  S r   )DEBURRED_LETTERSgetr_   )matchrZ   rZ   r[   <lambda>  s    zdeburr.<locals>.<lambda>)r   r   JS_RE_LATIN1r*   r   rZ   rZ   r[   r     s   
r   c                 C   s&   t | } | dd  | dd  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   rZ   rZ   r[   r     s   
r   c                 C   s6   t |}t | } |du r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r`   targetpositionrZ   rZ   r[   r      s
   

r   c                 C   s.   t | } t |}| |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   )r`   suffixrZ   rZ   r[   r     s
   


r   c                 C   s.   t | } t |}| |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)r`   prefixrZ   rZ   r[   r   :  s
   


r   c                 C   s   t | } d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                 s   s    | ]	}t ||V  qd S r   )HTML_ESCAPESr   )r   charrZ   rZ   r[   r   o      zescape.<locals>.<genexpr>)r   r   r   r   rZ   rZ   r[   r   W  s   
r   c                 C      t | } t| 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   rS   r   r   rZ   rZ   r[   r   r  s   

r   c                 C   s"   t | } t |}| |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   rc   r   rZ   rZ   r[   r     s   

r   c                 C   s&   t |  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   chainr1   r(   r*   r	   valuer   rZ   rZ   r[   r     s   r   c                 C   s0   t | } t |}| d| | | |d  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   )r`   indexr   rZ   rZ   r[   r     s   

r   c                 C   s   t |t | 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``.
    rZ   )r   r   r   map_)array	separatorrZ   rZ   r[   r     s   r   c                 C      d 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                 s       | ]	}|r|  V  qd S r   r   r   rZ   rZ   r[   r     r   zkebab_case.<locals>.<genexpr>r   r   r   rZ   rZ   r[   r        r   c                 C      t | } |  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   rZ   rZ   r[   r        
r   c                 C      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   rZ   rZ   r[   r   $     r   c                 C      | dd   | dd  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   rZ   rZ   r[   r   ?     r   .,c           	      C   s   d|dd}z
| | d}W n ty   d}Y |S w |d }|dg d }|t|ddd	 d
ddd	 }|t||g}|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      )formatr2   
ValueErrorr   r
   r   r   )	numberscaledecimal_separatororder_separatorfmt	num_partsr`   int_partdec_partrZ   rZ   r[   r   Y  s   $r   c                 C   sf   t | } t| }||kr| S || d }tt|}tt|}td||}|d| |  | 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    )r`   lengthr   r   midleft_len	right_lenrZ   rZ   r[   r     s   
r   c                 C   s0   t | } t|t| f}| t|| 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)   r`   r'  r   rZ   rZ   r[   r      s   
r    c                 C   s0   t | } t|t| }t|||  | 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``.
    Nr+  r-  rZ   rZ   r[   r!     s   
r!   c                 C   s&   t | } |r|  } tt| d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   rZ   rZ   r[   r"     s   
r"   c                 C   s   t | } tt| d 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   rZ   rZ   r[   r#        
r#   ...c                 C   s   t | } t| }t|}||kr| S dd }t| d|d  d|}td|dd r4t|dd	}n|dd
  }t|}|| |krN| d| | } | 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                 S   s"   |  d}| | krdS |S )Nr   r   )r_   r   r   )r   r   rZ   rZ   r[   rg   J  s   
zprune.<locals>.replNr   z.(?=\W*\w*$)z\w\wz\s*\S+$r   r   )r   r   r   r(   rS   r   rstrip)r`   r'  omissionr   omission_lenrg   r   subtext_lenrZ   rZ   r[   r$   &  s   
r$   ro   c                 C   s
   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;   )r`   
quote_charrZ   rZ   r[   r%   c  s   
r%   c                 C   s   t | } 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   rJ   rc   )r`   rX   rZ   rZ   r[   r&   z  s   
r&   c                 C   s.   t | } t |st |}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_functionrJ   r*   )r`   rX   rg   rZ   rZ   r[   r'     s   


r'   Fc                 C   s&   |du r	t | S t| ||||d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_casere   r   )r   r   r*   )r`   rV   rg   r<  re   rZ   rZ   r[   r(     s    
r(   c                 C   s   t | t| 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   r#  )r`   r   rZ   rZ   r[   r)     s   r)   c           
      C   s   t | } |du r| S t |st |}|rtjnd}t|tjr%|}	n)t |}|r1t|}|r<|	ds<d| }|rG|
dsG|d7 }tj||d}	|	j|| |d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   ^$rN   rd   )r   r   r;  rS   
IGNORECASE
isinstancetypingPatternr   r   r   rU   rf   )
r`   rV   rg   r<  re   r   
from_startfrom_endrO   patrZ   rZ   r[   r*     s"   
,



r*   c                 C      t | ||||d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   rD  r*   r`   rV   rg   r<  r   rZ   rZ   r[   r+   E     r+   c                 C   rF  )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   rC  rG  rH  rZ   rZ   r[   r,   b  rI  r,   c                 C   s   | d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                 s   r  r   r  r   rZ   rZ   r[   r     r   z!separator_case.<locals>.<genexpr>)r   rI   )r`   r  rZ   rZ   r[   r-     s   r-   ,  and c                 C   s   t | t j  } t| }t |}t |}|dkr'|r'| | }|dkr;| dd || dd g } || 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
       Nr5  )	r   r  mapr   r   r  r   r6  r   )itemsr  last_separatorserial
item_countrZ   rZ   r[   r.     s   

 
r.   c                 C   s   t | ||d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)rP  )r.   )rN  r  rO  rZ   rZ   r[   r/     s   r/   r
  c                 C   s*   t dt| 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-   )r`   r  
normalizedrZ   rZ   r[   r0     s   
r0   c                 C   r	  )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                 s   r  r   r  r   rZ   rZ   r[   r     r   zsnake_case.<locals>.<genexpr>r  r   rZ   rZ   r[   r1     s   r1   c                 C   s<   t | } |tu r|  }|S |r| |}|S 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   r2   r   )r`   r  retrZ   rZ   r[   r2     s   

r2   c                 C   r	  )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                 s   s    | ]	}t |d dV  qdS )Fr.  Nr	   r   rZ   rZ   r[   r   N  r   zstart_case.<locals>.<genexpr>r  r   rZ   rZ   r[   r3   :  r  r3   c                 C   s&   t | } t |}| |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   rZ   rZ   r[   r4   Q  s   

r4   c                 C   s   t dt| 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_TAGSrf   r   r   r   rZ   rZ   r[   r5   m  s   r5   c                 C       t | } |r| |d S | 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   rZ   rZ   r[   r6        
r6   c                 C   $   t | } |r| |d p| S | 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   rZ   rZ   r[   r7        
r7   c                 C   rb  )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
    rL  r_  r   rZ   rZ   r[   r8     re  r8   c                 C   r^  )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
    rL  rc  r   rZ   rZ   r[   r9     ra  r9   c                 C   s   t | } tt| d 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   r/  r2  rZ   rZ   r[   r:     r3  r:   c                 C   s$   t | } t |}| |  | 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  )r`   wrapperrZ   rZ   r[   r;     s   

r;   c                 C   r  )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   rZ   rZ   r[   r<     r  r<   c                 C   s&   t | } ddd t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                 s   r   r   r\  r   rZ   rZ   r[   r   7  r   ztitle_case.<locals>.<genexpr>)r   r   r   rS   r2   r   rZ   rZ   r[   r=   $  s   
r=   c                 C      t |  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   rZ   rZ   r[   r>   :     r>   c                 C   rh  )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   rZ   rZ   r[   r?   R  ri  r?   c                 C      t | } | |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r`   r   rZ   rZ   r[   r@   j  s   

r@   c                 C   rj  )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   r6  rl  rZ   rZ   r[   rA        

rA   c                 C   rj  )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   lstriprl  rZ   rZ   r[   rB     rm  rB      c           	      C   s   t | } t| |kr| S t|}|| }| d| } t| }t |r*| |}nt |rCd}|| D ]}|}q6|durC| }| d| | 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)	r`   r'  r7  r  r8  r   	trunc_lenlastr   rZ   rZ   r[   rC     s    


rC   c                 C   r   )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   htmlrD   r   rZ   rZ   r[   rD     s   

rD   c                 C   r  )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   rZ   rZ   r[   rF     r  rF   c                 C   r  )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   rZ   rZ   r[   rG     r  rG   c                 C   s2   t | } | 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  )r`   r:  innerrZ   rZ   r[   rE   8  s
   
rE   c            	   	   O   s   t |  t j } g }t|}| D ]}t|\}}}}}t|}||7 }|	t
|||d|f qt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   rK   )r   r  flatten_deeprM  r   r  flatten_url_paramsr   r   appendr   delimitedpathjoinr   )	pathsparams
paths_listparams_listpathschemenetlocqueryfragmentrZ   rZ   r[   rH   Y  s   rH   c                 C   s8   t | } |du r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.
    N)r   r   has_unicode_wordJS_RE_UNICODE_WORDSJS_RE_ASCII_WORDSrJ   rc   )r`   rV   rX   rZ   rZ   r[   rI     s   
 
rI   c                 C   s   t ttdt| 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   )rI   r   RE_APOSrf   r   r   r   rZ   rZ   r[   r     s   	r   c                 C   s   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_WORDr^   bool)r`   resultrZ   rZ   r[   r    s   
r  c                    s   dd t |D }t|dkr|d }|S |r!|d  r! nd}|r.|d  r. nd}  fd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                 S   s   g | ]	}|rt |qS rZ   r  r   r  rZ   rZ   r[   r     s    z%delimitedpathjoin.<locals>.<listcomp>r   r   r   r   c                    s    g | ]}|  r|  qS rZ   )rk  r  	delimiterrZ   r[   r     s     )r   ry  r   r   r   r   )r  r}  r  leadingtrailingmiddlerZ   r  r[   r|    s   r|  c                 C   sb   t | trt|  } g }| D ]\}}t |ttfr'|t|gt| |7 }q|||f q|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)]
    )r@  dictr   rN  tuplezipr   r{  )r~  	flattenedparamr  rZ   rZ   r[   rz    s   

rz  )Tr   )r   )r   r  r  )r   )r   r4  )ro   )Fr   )r   )Fr   TFF)FT)rJ  rK  F)rJ  rK  )r
  )ro  r4  N)rk   rw  r$  rS   rA  rV  urllib.parser   r   r   r   pydashr   helpersr   __all__rJ   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   rU   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.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rF   rG   rE   rH   rI   r   r  r|  rz  rZ   rZ   rZ   r[   <module>   sh   F"	
 !"#$%&'()*+,-./01234G
&




 !*+  ="%&I)"'
6!*0!