
    \eU                        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 ddl	m
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ddddd Zd! ej                  d"      fd# ej                  d$      fd ej                  d%      fd&Zd'Zd(Z ej                  d)      Z ej                  d*      Zg d+Zi Zi Zi Zd,gZg d-Zd.gZeD ]  Zg ee<   g ee<   g ee<   eD ]E  Z ej                  ed/eiz  ej6                  ej8                  z        Zee   j=                  e       G eD ]E  Z ej                  ed/eiz  ej6                  ej8                  z        Zee   j=                  e       G eD ]E  Z ej                  ed/eiz  ej6                  ej8                  z        Zee   j=                  e       G  d0 Zd<d1Z d2 Z!d=d3Z"d>d4Z#d?d5Z$d?d6Z%d7 Z&d@d8Z'dAd9Z(dBd:Z)d; Z*y)Cz.
System-level utilities and helper functions.
    N)_)encodeutilsk   KKiM   MiG   GiT   TiP   PiE   EiZ   ZiY   Yi	   
   )RRiQQi   z,(^[-+]?\d*\.?\d+)([KMGTPEZYRQ]i?)?(b|bit|B)$  z*(^[-+]?\d*\.?\d+)([kMGTPEZYRQ])?(b|bit|B)$z-(^[-+]?\d*\.?\d+)([kKMGTPEZYRQ]i?)?(b|bit|B)$)IECSImixed)1ttrueonyyes)0ffalseoffnnoz[^\w\s-]z[-\s]+)#	adminpass
admin_passpasswordadmin_password
auth_tokennew_passauth_passwordsecret_uuidsecretsys_pswdtokenconfigdrivechappasswordencrypted_keyprivate_key	fernetkeysslkey
passphrasecephclusterfsidoctaviaheartbeatkeyrabbitcookiecephmanilaclientkeypacemakerremoteauthkeydesignaterndckeycephadminkeyheatauthencryptionkeycephclientkeykeystonecredentialbarbicansimplecryptokek
cephrgwkeyswifthashsuffixmigrationsshkey
cephmdskey
cephmonkey
chapsecretz$(%(key)s[0-9]*\s*[=]\s*)[^\s^\'^\"]+)
z.(%(key)s[0-9]*\s*[=]\s*[\"\'])[^\"\']*([\"\'])z((%(key)s[0-9]*\s*[=]\s*[\"])[^\"]*([\"])z((%(key)s[0-9]*\s*[=]\s*[\'])[^\']*([\'])z((%(key)s[0-9]*\s+[\"\'])[^\"\']*([\"\'])z-([-]{2}%(key)s[0-9]*\s+)[^\'^\"^=^\s]+([\s]*)z((<%(key)s[0-9]*>)[^<]*(</%(key)s[0-9]*>)z8([\"\']%(key)s[0-9]*[\"\']\s*:\s*[\"\'])[^\"\']*([\"\'])z=([\'"][^"\']*%(key)s[0-9]*[\'"]\s*:\s*u?[\'"])[^\"\']*([\'"])zQ([\'"][^\'"]*%(key)s[0-9]*[\'"]\s*,\s*\'--?[A-z]+\'\s*,\s*u?[\'"])[^\"\']*([\'"])z&(%(key)s[0-9]*\s*--?[A-z]+\s*)\S+(\s*)zJ([\'\"][^\"\']*%(key)s[0-9]*[\'\"]\s*:\s*u?[\'\"].*[\'\"])[^\"\']*([\'\"])keyc                 *    t        t        |             S )zInterpret a string as a boolean and return either 1 or 0.

    Any string value in:

        ('True', 'true', 'On', 'on', '1')

    is interpreted as a boolean True.

    Useful for JSON-decoded stuff and config file parsing
    )intbool_from_string)subjects    5/usr/lib/python3/dist-packages/oslo_utils/strutils.pyint_from_bool_as_stringr^      s     ())    c                 T   t        | t              r| S t        | t              st        |       } | j                         j	                         }|t
        v ry|t        v ry|rHdj                  d t        t
        t        z         D              }t        d      | |dz  }t        |      |S )a  Interpret a subject as a boolean.

    A subject can be a boolean, a string or an integer. Boolean type value
    will be returned directly, otherwise the subject will be converted to
    a string. A case-insensitive match is performed such that strings
    matching 't','true', 'on', 'y', 'yes', or '1' are considered True and,
    when `strict=False`, anything else returns the value specified by
    'default'.

    Useful for JSON-decoded stuff and config file parsing.

    If `strict=True`, unrecognized values, including None, will raise a
    ValueError which is useful when parsing values passed in from an API call.
    Strings yielding False are 'f', 'false', 'off', 'n', 'no', or '0'.
    TFz, c              3   &   K   | ]	  }d |z    yw)z'%s'N ).0ss     r]   	<genexpr>z#bool_from_string.<locals>.<genexpr>   s      FFQJFs   zCUnrecognized value '%(val)s', acceptable values are: %(acceptable)s)val
acceptable)
isinstanceboolstrstriplowerTRUE_STRINGSFALSE_STRINGSjoinsortedr   
ValueError)r\   strictdefaultloweredrg   msgs         r]   r[   r[      s      '4 gs#g,mmo##%G,	M	!	YY F &|m'C DF F
 " #-44>&@@ or_   c                 R    t         t        z   }t        |       j                         |v S )zCheck if the provided string is a valid bool string or not.

    :param value: value to verify
    :type value: string
    :returns: true if value is boolean string, false otherwise

    .. versionadded:: 3.17
    )rm   rn   rj   rl   )valueboolstrss     r]   is_valid_boolstrry      s&     m+Hu:))r_   c                    	 t         |   \  }}|j	                  |       }|rrt        |j                  d            }|j                  d      }|j                  d      dv r|dz  }|dk(  rC|r%|j                  d      s|j                  d	k(  rd
}d}nd}nt        d      | z  }t        |      |s|}	n|t        |t        |         z  }	|rt        t        j                  |	            S |	S # t        $ r t        d      |z  }t        |      w xY w)a  Converts a string into an float representation of bytes.

    The units supported for IEC / mixed::

        Kb(it), Kib(it), Mb(it), Mib(it), Gb(it), Gib(it), Tb(it), Tib(it),
        Pb(it), Pib(it), Eb(it), Eib(it), Zb(it), Zib(it), Yb(it), Yib(it),
        Rb(it), Rib(it), Qb(it), Qib(it)

        KB, KiB, MB, MiB, GB, GiB, TB, TiB, PB, PiB, EB, EiB, ZB, ZiB,
        YB, YiB, RB, RiB, QB, QiB

    The units supported for SI ::

        kb(it), Mb(it), Gb(it), Tb(it), Pb(it), Eb(it), Zb(it), Yb(it),
        Rb(it), Qb(it)

        kB, MB, GB, TB, PB, EB, ZB, YB, RB, QB

    SI units are interpreted as power-of-ten (e.g. 1kb = 1000b).  Note
    that the SI unit system does not support capital letter 'K'

    IEC units are interpreted as power-of-two (e.g. 1MiB = 1MB =
    1024b)

    Mixed units interpret the "i" to mean IEC, and no "i" to mean SI
    (e.g. 1kb = 1000b, 1kib == 1024b).  Additionaly, mixed units
    interpret 'K' as power-of-ten.  This mode is not particuarly
    useful for new code, but can help with compatability for parsers
    such as GNU parted.

    :param text: String input for bytes size conversion.
    :param unit_system: Unit system for byte size conversion.
    :param return_int: If True, returns integer representation of text
                       in bytes. (default: decimal)
    :returns: Numerical representation of text in bytes.
    :raises ValueError: If text has an invalid value.

    zInvalid unit system: "%s"r   r
   r   )bbitr   r(   ir   r   r%   r$   zInvalid string format: %s)UNIT_SYSTEM_INFOKeyErrorr   rq   matchfloatgroupendswith
startswithpowUNIT_PREFIX_EXPONENTrZ   mathceil)
textunit_system
return_intbasereg_exru   r   	magnitudeunit_prefixress
             r]   string_to_bytesr      s   N'4f LLE%++a.)	kk!n;;q>\)NI '!;#7#7#< ))S0"%K+,t3o#d$8$EFF499S>""J?  +,{:os   C) )#Dc                 *   t        j                  | ||      } t        j                  d|       j	                  dd      j                  d      } t        j                  d|       j                         j                         } t        j                  d|       S )a  Normalize string.

    Convert to lowercase, remove non-word characters, and convert spaces
    to hyphens.

    Inspired by Django's `slugify` filter.

    :param value: Text to slugify
    :param incoming: Text's current encoding
    :param errors: Errors handling policy. See here for valid
        values http://docs.python.org/2/library/codecs.html
    :returns: slugified unicode representation of `value`
    :raises TypeError: If text is not an instance of str
    NFKDasciiignore -)r   safe_decodeunicodedata	normalizeencodedecodeSLUGIFY_STRIP_REsubrk   rl   SLUGIFY_HYPHENATE_RE)rw   incomingerrorss      r]   to_slugr     s     ##E8V<E !!&%077!6'? 
  U+11399;E##C//r_   c                 t   	 t        |       } d|z   }d|z   dz   }d}t        D ]  }|| j                         v st        |   D ]  }t        j                  |||       }  t        |   D ]  }t        j                  |||       }  t        |   D ]  }t        j                  |||       }   | S # t        $ r Y w xY w)ax  Replace password with *secret* in message.

    :param message: The string which includes security information.
    :param secret: value with which to replace passwords.
    :returns: The unicode value of message with the password fields masked.

    For example:

    >>> mask_password("'adminPass' : 'aaaaa'")
    "'adminPass' : '***'"
    >>> mask_password("'admin_pass' : 'aaaaa'")
    "'admin_pass' : '***'"
    >>> mask_password('"password" : "aaaaa"')
    '"password" : "***"'
    >>> mask_password("'original_password' : 'aaaaa'")
    "'original_password' : '***'"

    .. versionadded:: 0.2

    .. versionchanged:: 1.1
       Replace also ``'auth_token'``, ``'new_pass'`` and ``'auth_password'``
       keys.

    .. versionchanged:: 1.1.1
       Replace also ``'secret_uuid'`` key.

    .. versionchanged:: 1.5
       Replace also ``'sys_pswd'`` key.

    .. versionchanged:: 2.6
       Replace also ``'token'`` key.

    .. versionchanged:: 2.7
       Replace also ``'secret'`` key.

    .. versionchanged:: 3.4
       Replace also ``'configdrive'`` key.

    .. versionchanged:: 3.8
       Replace also ``'CHAPPASSWORD'`` key.
    z\g<1>z\g<2>)	rj   UnicodeDecodeError_SANITIZE_KEYSrl   _SANITIZE_PATTERNS_2rer   _SANITIZE_PATTERNS_1_SANITIZE_PATTERNS_WILDCARD)messager=   substitute1substitute2substitute_wildcardrX   patterns          r]   mask_passwordr   2  s    Vg, V#KV#h.K"
  H'--/!/4 @&&+w?@/4 @&&+w?@ 7s; H&&*=wGHH N1   	s   B+ +	B76B7c                    t        | t        j                  j                        st	        dt        |       z        i }| j                         D ]  \  }}t        |t        j                  j                        rt        ||      ||<   ;d}t        |t              r&t        D ]  }||j                         v s|||<   d} n |rvt        |t              rt        ||      ||<   |||<    |S )a  Replace password with *secret* in a dictionary recursively.

    :param dictionary: The dictionary which includes secret information.
    :param secret: value with which to replace secret information.
    :returns: The dictionary with string substitutions.

    A dictionary (which may contain nested dictionaries) contains
    information (such as passwords) which should not be revealed, and
    this function helps detect and replace those with the 'secret'
    provided (or `***` if none is provided).

    Substitution is performed in one of three situations:

    If the key is something that is considered to be indicative of a
    secret, then the corresponding value is replaced with the secret
    provided (or `***` if none is provided).

    If a value in the dictionary is a string, then it is masked
    using the ``mask_password()`` function.

    Finally, if a value is a dictionary, this function will
    recursively mask that dictionary as well.

    For example:

    >>> mask_dict_password({'password': 'd81juxmEW_',
    >>>                     'user': 'admin',
    >>>                     'home-dir': '/home/admin'},
    >>>                     '???')
    {'password': '???', 'user': 'admin', 'home-dir': '/home/admin'}

    For example (the value is masked using mask_password())

    >>> mask_dict_password({'password': '--password d81juxmEW_',
    >>>                     'user': 'admin',
    >>>                     'home-dir': '/home/admin'},
    >>>                     '???')
    {'password': '--password ???', 'user': 'admin',
     'home-dir': '/home/admin'}


    For example (a nested dictionary is masked):

    >>> mask_dict_password({"nested": {'password': 'd81juxmEW_',
    >>>                     'user': 'admin',
    >>>                     'home': '/home/admin'}},
    >>>                     '???')
    {"nested": {'password': '???', 'user': 'admin', 'home': '/home/admin'}}

    .. versionadded:: 3.4

    z#Expected a Mapping, got %s instead.)r=   FT)rh   collectionsabcMapping	TypeErrortypeitemsmask_dict_passwordrj   r   rl   r   )
dictionaryr=   outr   v	k_matchedsani_keys          r]   r   r   z  s    l j+//"9"9:=z*+ , 	,
C  " 1a001'&9CF 	a* qwwy(#CF $I	
  !S!&q8A A)* Jr_   c                 n    	 t        t        |             t        |       k(  S # t        t        f$ r Y yw xY w)zCheck if a value looks like an integer with base 10.

    :param val: Value to verify
    :type val: string
    :returns: bool

    .. versionadded:: 1.1
    F)rj   rZ   r   rq   )rf   s    r]   is_int_liker     s5    3s8}C((z" s   " 44c                    || }t        | t              st        d      |z  }t        |      t	        |       }||k  rt        d      |||dz  }t        |      |r#||kD  rt        d      |||dz  }t        |      yy)a:  Check the length of specified string.

    :param value: the value of the string
    :param name: the name of the string
    :param min_length: the min_length of the string
    :param max_length: the max_length of the string
    :raises TypeError, ValueError: For any invalid input.

    .. versionadded:: 3.7
    Nz%s is not a string or unicodez=%(name)s has %(length)s characters, less than %(min_length)s.)namelength
min_lengthz=%(name)s has %(length)s characters, more than %(max_length)s.)r   r   
max_length)rh   rj   r   r   lenrq   )rw   r   r   r   ru   r   s         r]   check_string_lengthr     s     |eS!/047nZF
 " #.2f4>&@@ ofz) " #.2f4>&@@ o	 *zr_   c                    	 t        t        |             } |!| |k  rt	        d      ||dz  }t        |      |!| |kD  rt	        d      ||dz  }t        |      | S # t        t        f$ r t	        d      d|iz  }t        |      w xY w)a[  Make sure that value is a valid integer, potentially within range.

    :param value: value of the integer
    :param name: name of the integer
    :param min_value: min_value of the integer
    :param max_value: max_value of the integer
    :returns: integer
    :raises: ValueError if value is an invalid integer

    .. versionadded:: 3.33
    z!%(value_name)s must be an integer
value_namez'%(value_name)s must be >= %(min_value)d)r   	min_valuez'%(value_name)s must be <= %(max_value)d)r   	max_value)rZ   rj   rq   UnicodeEncodeErrorr   )rw   r   r   r   ru   s        r]   validate_integerr     s    CJ !29 #'i@Ao!29 #'i@AoL *+ 3 !4()os   A +B	c                    |s|}||kD  rt        t        d      ||dz        |rq| j                  d|      }|dz  }|dz  }t        |      }|d   s||k  s||kD  sd|d| v rt        t        d      t        j
                  j                  |       z        |dz  }|dz  }| j                  d|      }t        |      }|d   s!||k  s||dz   kD  sd|d| v s||dz   k(  r9||   r4t        t        d      t        j
                  j                  |       z        |d| }|j                  dg|dz
  t        |      z
  z         |S )	aA  Validate and split the given HTTP request path.

    **Examples**::

        ['a'] = _split_path('/a')
        ['a', None] = _split_path('/a', 1, 2)
        ['a', 'c'] = _split_path('/a/c', 1, 2)
        ['a', 'c', 'o/r'] = _split_path('/a/c/o/r', 1, 3, True)

    :param path: HTTP Request path to be split
    :param minsegs: Minimum number of segments to be extracted
    :param maxsegs: Maximum number of segments to be extracted
    :param rest_with_last: If True, trailing data will be returned as part
                           of last segment.  If False, and there is
                           trailing data, raises ValueError.
    :returns: list of segments with a length of maxsegs (non-existent
              segments will return as None)
    :raises: ValueError if given an invalid path

    .. versionadded:: 3.11
    z%minsegs > maxsegs: %(min)d > %(max)d))minmax/r   r   r   zInvalid path: %sN)rq   r   splitr   urllibparsequoteextend)pathminsegsmaxsegsrest_with_lastsegscounts         r]   
split_pathr     sb   , BC!(9: ; 	;zz#w'11D	Guw%'/d1Wo%Q12V\\5G5G5MMNN11zz#w'D	Guw%'A+*=d1Wo%'A+%$w-Q12V\\5G5G5MMNN'?DKK'A+D	123Kr_   c                 :   ddl }|j                  dd      |j                  |j                  d      z  }|j                  |j                  |      z   |j                  z   }	 t        |j                  |             S # |j                  $ r t        d| z        w xY w)	z{Split values by commas and quotes according to api-wg

    :param value: value to be split

    .. versionadded:: 3.17
    r   N"\)	quoteCharescCharz",)excludeCharszInvalid value: %s)	pyparsingQuotedStringWord
printablesstringStartdelimitedList	stringEndlistparseStringParseExceptionrq   )rw   ppwordgrammars       r]   split_by_commasr   L  s      	#t4
D1	2 	 nnr//55DG6G''.// 6,u4556s   "A< <B)FF)r&   F)Nrr   )z***)Nr   N)NN)r   NF)+__doc__collections.abcr   r   r   r   r   oslo_utils._i18nr   
oslo_utilsr   r   compiler~   rm   rn   r   r   r   r   r   r   _FORMAT_PATTERNS_1_FORMAT_PATTERNS_2_FORMAT_PATTERNS_WILDCARDrX   r   DOTALL
IGNORECASEr   appendr^   r[   ry   r   r   r   r   r   r   r   r   r   rb   r_   r]   <module>r      s      	    " 	! 	
 	!  	!  	!  	!  	!  	!  !" 	!#$ 

	
+ 0 *"**LMNIJ
KJBJJ8: ;  452::k* !rzz), 

O       >> A  kk 
  8C " "')$% 1Gucl2BII4MNS!((01 & 1Gucl2BII4MNS!((01 - 8Gucl2BII4MN#C(//788$*#L
*HV0LEPOd@@.b6r_   