
    kh(                         d Z h dZh dZdZ G d de      ZddefdZg ddfd	Zg ddfd
Z	e
dk(  rddlZ ej                          yy)aH  
Convert user-provided internal UFO names to spec-compliant filenames.

This module implements the algorithm for converting between a "user name" -
something that a user can choose arbitrarily inside a font editor - and a file
name suitable for use in a wide range of operating systems and filesystems.

The `UFO 3 specification <http://unifiedfontobject.org/versions/ufo3/conventions/>`_
provides an example of an algorithm for such conversion, which avoids illegal
characters, reserved file names, ambiguity between upper- and lower-case
characters, and clashes with existing files.

This code was originally copied from
`ufoLib <https://github.com/unified-font-object/ufoLib/blob/8747da7/Lib/ufoLib/filenames.py>`_
by Tal Leming and is copyright (c) 2005-2016, The RoboFab Developers:

-	Erik van Blokland
-	Tal Leming
-	Just van Rossum
>/   * 	
"()+/:<>?[\]|>   clock$auxconnulprncom1com2com3com4com5com6com7com8com9lpt1lpt2lpt3lpt4lpt5lpt6lpt7lpt8lpt9   c                       e Zd Zy)NameTranslationErrorN)__name__
__module____qualname__     l/var/www/pru.catia.catastroantioquia-mas.com/tasa/lib/python3.12/site-packages/fontTools/ufoLib/filenames.pyrJ   rJ   k   s    rO   rJ    userNamec                 D   t        | t              st        d      t        |      }t        |      }|s| d   dk(  rd| dd z   } g }| D ]6  }|t        v rd}n||j                         k7  r|dz  }|j                  |       8 dj                  |      } t        |z
  |z
  }| d| } g }	| j                  d      D ].  }
|
j                         t        v rd|
z   }
|	j                  |
       0 dj                  |	      } || z   |z   }|j                         |v rt        | |||      }|S )a  Converts from a user name to a file name.

    Takes care to avoid illegal characters, reserved file names, ambiguity between
    upper- and lower-case characters, and clashes with existing files.

    Args:
            userName (str): The input file name.
            existing: A case-insensitive list of all existing file names.
            prefix: Prefix to be prepended to the file name.
            suffix: Suffix to be appended to the file name.

    Returns:
            A suitable filename.

    Raises:
            NameTranslationError: If no suitable name could be generated.

    Examples::

            >>> userNameToFileName("a") == "a"
            True
            >>> userNameToFileName("A") == "A_"
            True
            >>> userNameToFileName("AE") == "A_E_"
            True
            >>> userNameToFileName("Ae") == "A_e"
            True
            >>> userNameToFileName("ae") == "ae"
            True
            >>> userNameToFileName("aE") == "aE_"
            True
            >>> userNameToFileName("a.alt") == "a.alt"
            True
            >>> userNameToFileName("A.alt") == "A_.alt"
            True
            >>> userNameToFileName("A.Alt") == "A_.A_lt"
            True
            >>> userNameToFileName("A.aLt") == "A_.aL_t"
            True
            >>> userNameToFileName(u"A.alT") == "A_.alT_"
            True
            >>> userNameToFileName("T_H") == "T__H_"
            True
            >>> userNameToFileName("T_h") == "T__h"
            True
            >>> userNameToFileName("t_h") == "t_h"
            True
            >>> userNameToFileName("F_F_I") == "F__F__I_"
            True
            >>> userNameToFileName("f_f_i") == "f_f_i"
            True
            >>> userNameToFileName("Aacute_V.swash") == "A_acute_V_.swash"
            True
            >>> userNameToFileName(".notdef") == "_notdef"
            True
            >>> userNameToFileName("con") == "_con"
            True
            >>> userNameToFileName("CON") == "C_O_N_"
            True
            >>> userNameToFileName("con.alt") == "_con.alt"
            True
            >>> userNameToFileName("alt.con") == "alt._con"
            True
    z(The value for userName must be a string.    ._   NrQ   )
isinstancestr
ValueErrorlenillegalCharacterslowerappendjoinmaxFileNameLengthsplitreservedFileNameshandleClash1)rR   existingprefixsuffixprefixLengthsuffixLengthfilteredUserName	charactersliceLengthpartspartfullNames               rP   userNameToFileNamero   o   sF   D h$CDDv;Lv;L hqkS(!"% +	))I)//++I	*+ ww'(H#l2\AK%HEs# ::<,,:DT xxH 6)H~~8#(FFCOrO   c                 f   t        |      }t        |      }|t        |       z   |z   dz   t        kD  r"|t        |       z   |z   dz   }t        |z
  }| d| } d}d}	|H| t        |	      j                  d      z   }
||
z   |z   }|j	                         |vr|}n|	dz  }	|	dk\  rn|H|t        |||      }|S )aC  A helper function that resolves collisions with existing names when choosing a filename.

    This function attempts to append an unused integer counter to the filename.

        Args:
                userName (str): The input file name.
                existing: A case-insensitive list of all existing file names.
                prefix: Prefix to be prepended to the file name.
                suffix: Suffix to be appended to the file name.

        Returns:
                A suitable filename.

        >>> prefix = ("0" * 5) + "."
        >>> suffix = "." + ("0" * 10)
        >>> existing = ["a" * 5]

        >>> e = list(existing)
        >>> handleClash1(userName="A" * 5, existing=e,
        ...		prefix=prefix, suffix=suffix) == (
        ... 	'00000.AAAAA000000000000001.0000000000')
        True

        >>> e = list(existing)
        >>> e.append(prefix + "aaaaa" + "1".zfill(15) + suffix)
        >>> handleClash1(userName="A" * 5, existing=e,
        ...		prefix=prefix, suffix=suffix) == (
        ... 	'00000.AAAAA000000000000002.0000000000')
        True

        >>> e = list(existing)
        >>> e.append(prefix + "AAAAA" + "2".zfill(15) + suffix)
        >>> handleClash1(userName="A" * 5, existing=e,
        ...		prefix=prefix, suffix=suffix) == (
        ... 	'00000.AAAAA000000000000001.0000000000')
        True
       NrW   l   I5 )r[   r`   rY   zfillr]   handleClash2)rR   rd   re   rf   rg   rh   lrk   	finalNamecounternamern   s               rP   rc   rc      s    P v;Lv;Lc(m#l2R7:KK3x=(<7"<'!+L[)IG

#g,,,R00D=6)>>8+ IqLGo% 
  66:	rO   c                     t         t        |      z
  t        |      z
  }t        d|z        }d}d}|4|t        |      z   |z   }|j	                         | vr|}n|dz  }||k\  rn|4|t        d      |S )ak  A helper function that resolves collisions with existing names when choosing a filename.

    This function is a fallback to :func:`handleClash1`. It attempts to append an unused integer counter to the filename.

        Args:
                userName (str): The input file name.
                existing: A case-insensitive list of all existing file names.
                prefix: Prefix to be prepended to the file name.
                suffix: Suffix to be appended to the file name.

        Returns:
                A suitable filename.

        Raises:
                NameTranslationError: If no suitable name could be generated.

        Examples::

          >>> prefix = ("0" * 5) + "."
          >>> suffix = "." + ("0" * 10)
          >>> existing = [prefix + str(i) + suffix for i in range(100)]

          >>> e = list(existing)
          >>> handleClash2(existing=e, prefix=prefix, suffix=suffix) == (
          ... 	'00000.100.0000000000')
          True

          >>> e = list(existing)
          >>> e.remove(prefix + "1" + suffix)
          >>> handleClash2(existing=e, prefix=prefix, suffix=suffix) == (
          ... 	'00000.1.0000000000')
          True

          >>> e = list(existing)
          >>> e.remove(prefix + "2" + suffix)
          >>> handleClash2(existing=e, prefix=prefix, suffix=suffix) == (
          ... 	'00000.2.0000000000')
          True
    9NrW   zNo unique name could be found.)r`   r[   intrY   r]   rJ   )rd   re   rf   	maxLengthmaxValueru   rv   rn   s           rP   rs   rs     s    R "CK/#f+=I3?#HIG

CL(61>>8+ IqLGh 
 "#CDDrO   __main__rT   N)rN   rQ   rQ   )__doc__r\   rb   r`   	ExceptionrJ   rY   ro   rc   rs   rK   doctesttestmodrN   rO   rP   <module>r      sz   :0 b 2  	9 	e eP %'r" ?D R ;| zGOO rO   