
    k7iLE                     F   % S r SSKrSSKrSSKrSSKrSSKJr  SSKJrJ	r	  SSKJ
r
  SSKJrJr  SSKJrJrJrJr  SS	KJrJrJrJrJr  SS
KJrJrJr  SSKJrJr  SSK J!r!J"r"J#r#J$r$  SSK%J&r&J'r'  Sr(\\)S'   \RT                  " S\RV                  " \RX                  5      S S3\RZ                  5      r.\\)S'   \RT                  " S\RV                  " \R^                  5      S S3\RZ                  5      r0\\)S'    " S S\5      r1 " S S\5      r2S\\(SSS4S\S\\   S\3S\3S\\4   S\5S \\\4      S!S4S" jjr6S\SSSS4S\S\\   S\3S\\3   S\\4   S\5S \\\4      S!\54S# jjr7S$S\(SSSSSS%4	S\S&\4S\\   S\\3   S\\4   S\\5   S'\\'   S(\\'   S \\\4      S)\5S!\4S* jjr8g)+zA
.. codeauthor:: Tsuyoshi Hombashi <tsuyoshi.hombashi@gmail.com>
    N)Sequence)PathPurePath)Pattern)FinalOptional   )AbstractSanitizerAbstractValidatorBaseFileBaseValidator)findall_to_stris_nt_abspathto_strtruncate_strvalidate_pathtype)DEFAULT_MIN_LENINVALID_CHAR_ERR_MSG_TMPLPlatform)PathTypePlatformType)ErrorAttrKeyErrorReasonInvalidCharErrorValidationError)ReservedNameHandlerValidationErrorHandler   _DEFAULT_MAX_FILENAME_LEN[s]_RE_INVALID_FILENAME_RE_INVALID_WIN_FILENAMEc                      ^  \ rS rSr\SSSSSSS4S\S\\   S\\   S\\	   S\\	   S	\\
\      S
\S\\   SS4U 4S jjjrSS\S\S\4S jjrS\\   4S jrSrU =r$ )FileNameSanitizer   NFmax_lenfs_encodingplatformnull_value_handlerreserved_name_handleradditional_reserved_namesvalidate_after_sanitize	validatorreturnc	                    > U(       a  Un	O[        [        UUSUUS9n	[        T
U ]  UUUUUUUU	S9  U R	                  5       U l        g )NTmin_lenr(   r)   check_reservedr-   r*   )r(   r)   r+   r,   r-   r*   r.   r/   )FileNameValidatorr   super__init___get_sanitize_regexp_sanitize_regexp)selfr(   r)   r*   r+   r,   r-   r.   r/   fname_validator	__class__s             P/home/james-whalen/.local/lib/python3.13/site-packages/pathvalidate/_filename.pyr7   FileNameSanitizer.__init__    sh     'O/''#*C!O 	#1"7&?$;% 	 		
 !% 9 9 ;    valuereplacement_textc                 6    [        XR                  SS9(       + S9  U R                  R                  U[        U5      5      n[        X@R                  U R                  5      n U R                  R!                  U5        U R2                  (       a   U R                  R!                  U5        [        U[        5      (       a  [9        U5      $ U$ ! [         aP  nUR                  [        R
                  :X  a,  [        U[        5      (       a  e U R                  U5      s S nA$ e S nAff = f! [         Ga%  nUR                  [        R"                  :X  a\  U R%                  U5      nUR&                  U:w  a5  [(        R                  " [(        R*                  " UR&                  5      XT5      n S nAGN1UR                  [        R,                  :X  aS  U R                  SS9(       a?  UR/                  S5      nUR1                  S5      nUS;  a  UR1                  S5      n S nAGNUR                  [        R
                  :X  a  U R                  U5      n S nAGNS nAff = f! [         a1  n[        [        U5      [        R4                  U R6                  S9eS nAff = f)NTinclude_universalallow_whitespaces .z..z .)descriptionreasonr*   )r   _is_windowsr   rK   r   	NULL_NAME
isinstancer   _null_value_handlerr9   substrr   _fs_encodingr(   
_validatorvalidateRESERVED_NAME_reserved_name_handlerreserved_namereescapeINVALID_CHARACTERlstriprstrip_validate_after_sanitizeINVALID_AFTER_SANITIZEr*   r   )r:   r@   rA   esanitized_filenamereplacement_words         r=   sanitizeFileNameSanitizer.sanitizeD   s-   	e;K;K^b;K;c7cd "22667GUT)*<>O>OQUQ]Q]^	AOO$$%78* (((();< eX&&*++!!]  	xx;000eX..//22	  	Axx;444#'#>#>q#A ??&66)+		!//24D*& [:::t?O?O"& @P @ &8%>%>s%C" &8%>%>s%C"%[8);)B)B4)H&[222%)%=%=a%@"%	A. # % #A&==!]] sb   C #D* I 
D'AD"D'!D""D'*I5A4I/A+I /II
J',JJc                 B    U R                  SS9(       a  [        $ [        $ )NTrC   )rL   r$   r#   )r:   s    r=   r8   &FileNameSanitizer._get_sanitize_regexpw   s    d3++##r?   )r9   ) )__name__
__module____qualname____firstlineno__r   intr   rQ   r   r   r   boolr   r7   r   rb   r   r8   __static_attributes____classcell__r<   s   @r=   r&   r&      s     1%)+/?CBF=A(-15"<"< c]"< <(	"<
 %%;<"<  ((>?"< $,HSM#:"< "&"< -."< 
"< "<H1"h 1"# 1"x 1"f$gcl $ $r?   r&   c                     ^  \ rS rSr% S\" S \R                  " S\" SS5      5       5       5      -   \" S \R                  " SS5       5       5      -   r\	\
S	'   S
r\	\
S'   \S\\S4   4U 4S jj5       r\\SSSS4S\S\S\\   S\\   S\S\\\      SS4U 4S jjjrS\SS4S jrS\SS4S jrS\SS4S jrS\SS4S jrSrU =r$ )r5   ~   )CONPRNAUXzCLOCK$NULc              #   6   #    U  H  u  pUS  US 3v   M     g7f)r!   dN ).0namenums      r=   	<genexpr>FileNameValidator.<genexpr>   s!     d4cyt4(3q'"4c   )COMLPTr   
   c              #   6   #    U  H  u  pUS  US  3v   M     g7f)r!   Nrx   )ry   rz   ssds      r=   r|   r}      s*      
	 Ahs1gr~   )   ¹   ²   ³_WINDOWS_RESERVED_FILE_NAMES):_MACOS_RESERVED_FILE_NAMESr0   .c                   > [         TU ]  nU R                  5       (       a&  [        UU R                  -   U R
                  -   5      nOzU R                  5       (       a  [        XR                  -   5      nOMU R                  5       (       d  U R                  5       (       a  [        XR
                  -   5      nO[        U5      n[        [        U5      5      $ )N)r6   reserved_keywords_is_universalsetr   r   rL   	_is_posix	_is_macostuplesorted)r:   common_keywordsword_setr<   s      r=   r   #FileNameValidator.reserved_keywords   s    '3334112H
 ?-N-NNOH^^!1!1?-L-LLMH?+HVH%&&r?   NTr3   r(   r)   r*   r4   r-   c           	      *   > [         TU ]  UUUUUUS9  g )Nr2   )r6   r7   )r:   r3   r(   r)   r*   r4   r-   r<   s          r=   r7   FileNameValidator.__init__   s)     	#)&? 	 	
r?   r@   c           
         [        XR                  SS9(       + S9  [        U5      n[        UR	                  U R
                  5      5      nU R                  U5        [        R                  [        R                  [        R                  U R                  [        R                  U R
                  [        R                  U[        R                  U0nX0R                   :  a   [#        SU R                   S SUS S3/40 UD6eX0R$                  :  a   [#        SU R$                  S SUS S3/40 UD6eU R'                  U5        U R)                  U5        U R                  SS9(       a  U R+                  U5        g g )	NTrC   rE   z filename is too long: expected<=rw   z bytes, actual=z bytesz!filename is too short: expected>=)r   rL   r   lenencoderR   validate_abspathr   REASONr   INVALID_LENGTHPLATFORMr*   FS_ENCODING
BYTE_COUNTVALUEr(   r   r3   _validate_reserved_keywords/_FileNameValidator__validate_universal_filename)_FileNameValidator__validate_win_filename)r:   r@   unicode_filenamebyte_ct
err_kwargss        r=   rT   FileNameValidator.validate   su   %7G7GZ^7G7_3_`!%=&--d.?.?@A./ !;!;!!4==$$d&7&7##W 0

 \\!!6t||A6FoV]^_U``fg 	  \\!!7Q7GW^_`Vaagh 	  	(()9:**+;<d3(()9: 4r?   c                     [        SU< S3U R                  [        R                  S9nU R	                  SS9(       a  [        U5      (       a  Ue[        R                  " U5      (       a  Ueg )Nzfound an absolute path (z), expected a filename)rJ   r*   rK   TrC   )r   r*   r   FOUND_ABS_PATHrL   r   	posixpathisabs)r:   r@   errs      r=   r   "FileNameValidator.validate_abspath   se    25);QR]]--
 d3U##	??5!!I "r?   r   c                     [         R                  U5      nU(       a4  [        [        R                  " [        U5      S9[        R                  US9eg )Ninvalidr*   r@   )r#   findallr   r   formatr   r   	UNIVERSAL)r:   r   matchs      r=   __validate_universal_filename/FileNameValidator.__validate_universal_filename   sL    $,,-=>")00*51 "++&  r?   c                 R   [         R                  U5      nU(       a4  [        [        R                  " [        U5      S9[        R                  US9eUS;   a  g Sn[        R                  [        R                  [        R                  U0nUS   S;   aF  [        [        R                  " [        R                  " US   5      S94SUR	                  S5      0UD6eUS	   S
;   aF  [        [        R                  " [        R                  " US	   5      S94SUR	                  S5      0UD6eg )Nr   r   rH   z{}. Refer: https://learn.microsoft.com/en-us/troubleshoot/windows-client/shell-experience/file-folder-name-whitespace-characters)rG   rI   rJ   z<Do not end a file or directory name with a space or a periodr   rG   z2Do not start a file or directory name with a space)r$   r   r   r   r   r   r   WINDOWSr   r   r   rX   rY   )r:   r   r   KB2829981_err_tmplr   s        r=   __validate_win_filename)FileNameValidator.__validate_win_filename   s:   (001AB")00*51 "))&  {* `!!8#3#3 0


 B:-")00CSTVCW9XY.55R
   A3'")00CSTUCV9WX.55H
   (r?   rx   )rg   rh   ri   rj   r   	itertoolsproductranger   r   __annotations__r   propertyrQ   r   r   r   rk   r   r   rl   r   r7   r   rT   r   r   r   rm   rn   ro   s   @r=   r5   r5   ~   s\   .
dI4E4EnV[\]_aVb4cd
d	e
 
&..W
 
	
 !% 
 )/.'5c? ' '( '0%)+/#=A

 
 c]	

 <(
 
 $,HSM#:
 

 
$";h ";4 ";Hc d 	c 	d 	$ $ $ $r?   r5   Tfilenamer*   r3   r(   r)   r4   r-   r0   c           	      >    [        UUUUUUS9R                  U 5        g)a  Verifying whether the ``filename`` is a valid file name or not.

Args:
    filename:
        Filename to validate.
    platform:
        Target platform name of the filename.

        .. include:: platform.txt
    min_len:
        Minimum byte length of the ``filename``. The value must be greater or equal to one.
        Defaults to ``1``.
    max_len:
        Maximum byte length of the ``filename``. The value must be lower than:

            - ``Linux``: 4096
            - ``macOS``: 1024
            - ``Windows``: 260
            - ``universal``: 260

        Defaults to ``255``.
    fs_encoding:
        Filesystem encoding that is used to calculate the byte length of the filename.
        If |None|, get the encoding from the execution environment.
    check_reserved:
        If |True|, check the reserved names of the ``platform``.
    additional_reserved_names:
        Additional reserved names to check.
        Case insensitive.

Raises:
    ValidationError (ErrorReason.INVALID_LENGTH):
        If the ``filename`` is longer than ``max_len`` characters.
    ValidationError (ErrorReason.INVALID_CHARACTER):
        If the ``filename`` includes invalid character(s) for a filename:
        |invalid_filename_chars|.
        The following characters are also invalid for Windows platforms:
        |invalid_win_filename_chars|.
    ValidationError (ErrorReason.RESERVED_NAME):
        If the ``filename`` equals the reserved name by OS.
        Windows reserved name is as follows:
        ``"CON"``, ``"PRN"``, ``"AUX"``, ``"NUL"``, ``"COM[1-9]"``, ``"LPT[1-9]"``.

Example:
    :ref:`example-validate-filename`

See Also:
    `Naming Files, Paths, and Namespaces - Win32 apps | Microsoft Docs
    <https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file>`__
r*   r3   r(   r)   r4   r-   N)r5   rT   r   r*   r3   r(   r)   r4   r-   s          r=   validate_filenamer     s+    x %"; hxr?   c           	      F    [        UUUc  SOUUUUS9R                  U 5      $ )a  Check whether the ``filename`` is a valid name or not.

Args:
    filename:
        A filename to be checked.
    platform:
        Target platform name of the filename.

Example:
    :ref:`example-is-valid-filename`

See Also:
    :py:func:`.validate_filename()`
r   r   )r5   is_validr   s          r=   is_valid_filenamer   [  s5    0 o7%"; hxr?   rf   FrA   r+   r,   r.   c
           
          Ub0  [         R                  " S[        5        USL a  [        R                  n[        UUc  SOUUUUUU	S9R                  X5      $ )a	  Make a valid filename from a string.

To make a valid filename, the function does the following:

    - Replace invalid characters as file names included in the ``filename``
      with the ``replacement_text``. Invalid characters are:

        - unprintable characters
        - |invalid_filename_chars|
        - for Windows (or universal) only: |invalid_win_filename_chars|

    - Replace a value if a sanitized value is a reserved name by operating systems
      with a specified handler by ``reserved_name_handler``.

Args:
    filename: Filename to sanitize.
    replacement_text:
        Replacement text for invalid characters. Defaults to ``""``.
    platform:
        Target platform name of the filename.

        .. include:: platform.txt
    max_len:
        Maximum byte length of the ``filename``.
        Truncate the name length if the ``filename`` length exceeds this value.
        Defaults to ``255``.
    fs_encoding:
        Filesystem encoding that is used to calculate the byte length of the filename.
        If |None|, get the encoding from the execution environment.
    check_reserved:
        [Deprecated] Use 'reserved_name_handler' instead.
    null_value_handler:
        Function called when a value after sanitization is an empty string.
        You can specify predefined handlers:

            - :py:func:`~.handler.NullValueHandler.return_null_string`
            - :py:func:`~.handler.NullValueHandler.return_timestamp`
            - :py:func:`~.handler.raise_error`

        Defaults to :py:func:`.handler.NullValueHandler.return_null_string` that just return ``""``.
    reserved_name_handler:
        Function called when a value after sanitization is a reserved name.
        You can specify predefined handlers:

            - :py:meth:`~.handler.ReservedNameHandler.add_leading_underscore`
            - :py:meth:`~.handler.ReservedNameHandler.add_trailing_underscore`
            - :py:meth:`~.handler.ReservedNameHandler.as_is`
            - :py:func:`~.handler.raise_error`

        Defaults to :py:func:`.handler.add_trailing_underscore`.
    additional_reserved_names:
        Additional reserved names to sanitize.
        Case insensitive.
    validate_after_sanitize:
        Execute validation after sanitization to the file name.

Returns:
    Same type as the ``filename`` (str or PathLike object):
        Sanitized filename.

Raises:
    ValueError:
        If the ``filename`` is an invalid filename.

Example:
    :ref:`example-sanitize-filename`
zD'check_reserved' is deprecated. Use 'reserved_name_handler' instead.Fr   )r*   r(   r)   r+   r,   r-   r.   )warningswarnDeprecationWarningr   as_isr&   rb   )
r   rA   r*   r(   r)   r4   r+   r,   r-   r.   s
             r=   sanitize_filenamer   }  sg    ` !R	

 U"$7$=$=!o7-3"; 7 hx*+r?   )9__doc__r   r   rX   r   collections.abcr   pathlibr   r   r   typingr   r   _baser
   r   r   r   _commonr   r   r   r   r   _constr   r   r   _typesr   r   errorr   r   r   r   handlerr   r   r   r   compilerY   _INVALID_FILENAME_CHARSUNICODEr#   _INVALID_WIN_FILENAME_CHARSr$   r&   r5   rk   rQ   rl   r   r   r   rx   r?   r=   <module>r      s     	  $ "  " P P [ [ H H * O O @ $' 5 & jj		(223A6a8"** e  #%**		(667:!<bjj# % 
\$) \$~T Tr (,",!%9=CC|$C C 	C
 #C C  (6C 
CP (,"!!%9=|$  c]	
 #   (6 
H '+6!%%);?>B9=$)a+a+a+ |$a+ c]	a+
 #a+ TNa+ !!78a+ $$:;a+  (6a+ "a+ a+r?   