U
    DvfUx                  
   @   s  d Z ddlZddlmZ ddlZddlZddlmZ ddl	m
Z
 dd Zdd	 Zd
d Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ Zd0d1 Z d2d3 Z!d4d5 Z"d6d7 Z#d8d9 Z$d:d; Z%d<d= Z&d>d? Z'd@dA Z(dBdC Z)dDdE Z*dFdG Z+djdHdIZ,e-e.e/fdJfe.e/fdJfe.e/fdJfe0dJfe0dJfe0dJfdKZ1dLdM Z2dkdNdOZ3e-e.e/fdJfe.e/fdJfe0dJfe0dJfe0dJfdPZ4dQdR Z5dSdT Z6dUdV Z7dWZ8e-e0dXfe.e/fdJfe.e/fdJfe.e/fdJfe.e/fdJfe.e/fdJfe.e/fdJfe0dJfdYZ9dZd[ Z:dld\d]Z;d^d_ Z<d`da Z=dbdc Z>ddZ?dedf Z@dgdh ZAeBdikrddlCZCeCD  dS )mz"Various low level data validators.    N)open)Mapping)numberTypesc                 C   s,   t | trdS dD ]}t| |s dS qdS )zY
    Some objects will likely come in that aren't
    dicts but are dict-ish enough.
    T)keysvaluesitemsF)
isinstancer   hasattr)valueattr r   ?/tmp/pip-unpacked-wheel-qlge9rch/fontTools/ufoLib/validators.pyisDictEnough   s    

r   c                 C   s
   t | |S )(
    Generic. (Added at version 2.)
    )r   )r
   typr   r   r   genericTypeValidator   s    r   c                 C   sL   t | ttfsdS t| }t|}|| r.dS | D ]}t |ts2 dS q2dS )r   FT)r   listtuplesetint)r   validValuesZ	valuesSetZvalidValuesSetr
   r   r   r   genericIntListValidator%   s    
r   c                 C   s   t | tsdS | dk rdS dS (
    Generic. (Added at version 3.)
    Fr   Tr   r   r
   r   r   r   genericNonNegativeIntValidator5   s
    
r   c                 C   s   t | tsdS | dk rdS dS r   )r   r   r   r   r   r   !genericNonNegativeNumberValidator@   s
    
r   c                 C   s   t | tsdS | D ] \}\}}|s(q|| kr dS q|  D ]}||kr@ dS q@|  D ]2\}}|| \}}|dkr~|s~q\t ||s\ dS q\dS )r   FNT)r   r   r   r   )r
   Z	prototypekeyr   requiredvZprototypeTyper   r   r   genericDictValidatorK   s"    

r!   c                 C   s   ddddg}| |kS )
    Version 2+.
    ZregularZitalicZboldzbold italicr   )r
   optionsr   r   r   "fontInfoStyleMapStyleNameValidatorm   s    r$   c           	      C   s   t | tsdS t| dkrdS ddddg}ttdftdfd}g }| D ]T}t||sZ dS |d }|d	 }t|}|s| dS t||}|s dS || qF|t	|krdS dS )

    Version 3+.
    Fr   T         )rangeMaxPPEMrangeGaspBehaviorr)   r*   )
r   r   lendictr   r!   r   r   appendsorted)	r
   ZvalidBehaviorsdictPrototypeZ	ppemOrderZrangeRecordZppemZbehaviorZppemValidityZbehaviorValidityr   r   r   )fontInfoOpenTypeGaspRangeRecordsValidatoru   s,    


r0   c           
      C   s  t | tsdS t| dksdS | ddkr0dS | d\}}|ddkrPdS |ddkrbdS |d\}}}t|dkrdS t|dkrdS t|dkrdS zt|}t|}t|}W n tk
r   Y dS X |dk s|d	krdS t||d }|dk s||krdS |d\}}}	t|dkr4dS t|dkrFdS t|	dkrXdS zt|}t|}t|	}	W n tk
r   Y dS X |d
k s|dkrdS |d
k s|dkrdS |	d
k s|	dkrdS dS )r"   F    r&   /r'   :      r      ;   T)	r   strr+   countsplitr   
ValueErrorcalendar
monthrange)
r
   datetimeyearmonthdayZmonthMaxDayhourminutesecondr   r   r   $fontInfoOpenTypeHeadCreatedValidator   sb    
rG   c                 C   sR   t | tsdS ttdftdftdftdftdfd}| D ]}t||s8 dS q8dS )r%   FT)ZnameIDZ
platformIDZ
encodingIDZ
languageIDstring)r   r   r,   r   r9   r!   )r
   r/   Z
nameRecordr   r   r   $fontInfoOpenTypeNameRecordsValidator   s    

rI   c                 C   s   t | tsdS | dk rdS dS )r"   Fr   Tr   r   r   r   r   'fontInfoOpenTypeOS2WeightClassValidator   s
    
rJ   c                 C   s*   t | tsdS | dk rdS | dkr&dS dS )r"   Fr&   	   Tr   r   r   r   r   &fontInfoOpenTypeOS2WidthClassValidator   s    
rL   c                 C   s@   t | ttfsdS t| dkr"dS | D ]}t |ts& dS q&dS )z
    Version 2.
    F
   Tr   r   r   r+   r   r   r
   r   r   r   *fontInfoVersion2OpenTypeOS2PanoseValidator   s    
rP   c                 C   sN   t | ttfsdS t| dkr"dS | D ]"}t |ts: dS |dk r& dS q&dS )r%   FrM   r   TrN   rO   r   r   r   *fontInfoVersion3OpenTypeOS2PanoseValidator  s    
rQ   c                 C   sp   t | ttfsdS t| dkr"dS | D ]}t |ts& dS q&| \}}|dk sT|dkrXdS |dk sh|dkrldS dS )r"   Fr'   r         TrN   )r   r
   ZclassIDZ
subclassIDr   r   r   'fontInfoOpenTypeOS2FamilyClassValidator  s    
rT   c                 C   sP   t | ttfsdS t| dkr"dS t| d r2dS | D ]}t |ts6 dS q6dS )r"   FrR   r'   Tr   r   r   r+   r   rO   r   r   r    fontInfoPostscriptBluesValidator+  s    
rV   c                 C   sP   t | ttfsdS t| dkr"dS t| d r2dS | D ]}t |ts6 dS q6dS )r"   FrM   r'   TrU   rO   r   r   r   %fontInfoPostscriptOtherBluesValidator;  s    
rW   c                 C   s@   t | ttfsdS t| dkr"dS | D ]}t |ts& dS q&dS )r"   Fr6   TrU   rO   r   r   r    fontInfoPostscriptStemsValidatorK  s    
rX   c                 C   s   t tdd}| |krdS dS )r"   r&      FT)r   range)r
   r   r   r   r   .fontInfoPostscriptWindowsCharacterSetValidatorY  s    r[   c                 C   s    t tdfd}t| |sdS dS )r%   T)idF)r,   r9   r!   r
   r/   r   r   r   %fontInfoWOFFMetadataUniqueIDValidatorc  s    
r^   c                 C   sJ   t dft dft dft dfd}t| |s,dS d| krF| ddkrFdS dS )r%   TF)nameurldirclassra   Zltrrtlr9   r!   getr]   r   r   r   #fontInfoWOFFMetadataVendorValidatorm  s    
rg   c                 C   s   t tdfd}t| |sdS t| d s,dS tdftdftdftdftdfd}| d D ]0}t||sl dS d|krX|ddkrX dS qXdS )r%   T)creditsFrh   )r_   r`   rolera   rb   ra   rc   )r,   r   r!   r+   r9   rf   )r
   r/   Zcreditr   r   r   $fontInfoWOFFMetadataCreditsValidator~  s"    

rj   c                 C   sB   t tdftdfd}t| |s"dS | d D ]}t|s* dS q*dS )r%   FT)r`   textrk   r,   r9   r   r!   fontInfoWOFFMetadataTextValuer
   r/   rk   r   r   r   (fontInfoWOFFMetadataDescriptionValidator  s    
ro   c                 C   sP   t tdftdftdfd}t| |s(dS d| krL| d D ]}t|s8 dS q8dS )r%   F)r`   rk   r\   rk   Trl   rn   r   r   r   $fontInfoWOFFMetadataLicenseValidator  s    
rp   c                 C   s<   t tdfd}t| |sdS | d D ]}t|s$ dS q$dS r%   T)rk   Frk   r,   r   r!   rm   rn   r   r   r   &fontInfoWOFFMetadataTrademarkValidator  s    
rs   c                 C   s<   t tdfd}t| |sdS | d D ]}t|s$ dS q$dS rq   rr   rn   r   r   r   &fontInfoWOFFMetadataCopyrightValidator  s    
rt   c                 C   sD   t dft dft dfd}t| |s&dS d| kr@| ddkr@dS dS )r%   TF)r_   ra   rb   ra   rc   re   r]   r   r   r   %fontInfoWOFFMetadataLicenseeValidator  s    
ru   c                 C   sJ   t dft dft dft dfd}t| |s,dS d| krF| ddkrFdS dS r%   TF)rk   languagera   rb   ra   rc   re   r]   r   r   r   rm     s    
rm   c                 C   s2   t | tsdS | sdS | D ]}t|s dS qdS )r%   FT)r   r   &fontInfoWOFFMetadataExtensionValidator)r
   	extensionr   r   r   'fontInfoWOFFMetadataExtensionsValidator  s    
rz   c                 C   sl   t tdftdftdfd}t| |s(dS d| krL| d D ]}t|s8 dS q8| d D ]}t|sT dS qTdS )r%   FT)namesr   r\   r{   r   )r,   r   r9   r!   *fontInfoWOFFMetadataExtensionNameValidator*fontInfoWOFFMetadataExtensionItemValidator)r
   r/   r_   itemr   r   r   rx     s    
rx   c                 C   sd   t tdftdftdfd}t| |s(dS | d D ]}t|s0 dS q0| d D ]}t|sL dS qLdS )r%   FT)r\   r{   r   r{   r   )r,   r9   r   r!   r|   +fontInfoWOFFMetadataExtensionValueValidator)r
   r/   r_   valr   r   r   r}     s    
r}   c                 C   sJ   t dft dft dft dfd}t| |s,dS d| krF| ddkrFdS dS rv   re   r]   r   r   r   r|     s    
r|   c                 C   sJ   t dft dft dft dfd}t| |s,dS d| krF| ddkrFdS dS rv   re   r]   r   r   r   r   (  s    
r   c                 C   sb   t | tsdS |dkrt }| D ]<}t|s2 dS |d}|dk	r ||krR dS || q dS r%   FN
identifierT)r   r   r   guidelineValidatorrf   add)r
   identifiersZguider   r   r   r   guidelinesValidator>  s    

r   F)xyangler_   colorr   c                 C   s   t | tsdS | d}| d}| d}|dkr@|dkr@dS |dksP|dkr\|dk	r\dS |dk	rx|dk	rx|dkrxdS |dk	r|dk rdS |dkrdS | d}|dk	rt|sdS | d	}|dk	rt|sdS d
S )r%   Fr   r   r   Nr   ih  r   r   T)r!   _guidelineDictPrototyperf   identifierValidatorcolorValidator)r
   r   r   r   r   r   r   r   r   r   [  s0    





r   c                 C   sb   t | tsdS |dkrt }| D ]<}t|s2 dS |d}|dk	r ||krR dS || q dS r   )r   r   r   anchorValidatorrf   r   )r
   r   anchorr   r   r   r   anchorsValidator  s    

r   )r   r   r_   r   r   c                 C   sv   t | tsdS | d}| d}|dks2|dkr6dS | d}|dk	rTt|sTdS | d}|dk	rrt|srdS dS )r%   Fr   r   Nr   r   T)r!   _anchorDictPrototyperf   r   r   )r
   r   r   r   r   r   r   r   r     s    




r   c                 C   sZ   d}d}t | tsdS | sdS t| dkr.dS | D ]"}t|}||k sN||kr2 dS q2dS )z
    Version 3+.

    >>> identifierValidator("a")
    True
    >>> identifierValidator("")
    False
    >>> identifierValidator("a" * 101)
    False
        ~   Fd   T)r   r9   r+   ord)r
   ZvalidCharactersMinZvalidCharactersMaxcr   r   r   r     s    
r   c              	   C   s   t | tsdS | d}t|dkr(dS |D ]}| }d}zt|}d}W n tk
r`   Y nX |szt|}d}W n tk
r   Y nX |s dS |dk r dS |dkr, dS q,dS )a  
    Version 3+.

    >>> colorValidator("0,0,0,0")
    True
    >>> colorValidator(".5,.5,.5,.5")
    True
    >>> colorValidator("0.5,0.5,0.5,0.5")
    True
    >>> colorValidator("1,1,1,1")
    True

    >>> colorValidator("2,0,0,0")
    False
    >>> colorValidator("0,2,0,0")
    False
    >>> colorValidator("0,0,2,0")
    False
    >>> colorValidator("0,0,0,2")
    False

    >>> colorValidator("1r,1,1,1")
    False
    >>> colorValidator("1,1g,1,1")
    False
    >>> colorValidator("1,1,1b,1")
    False
    >>> colorValidator("1,1,1,1a")
    False

    >>> colorValidator("1 1 1 1")
    False
    >>> colorValidator("1 1,1,1")
    False
    >>> colorValidator("1,1 1,1")
    False
    >>> colorValidator("1,1,1 1")
    False

    >>> colorValidator("1, 1, 1, 1")
    True
    F,r5   Tr   r&   )r   r9   r;   r+   stripr   r<   float)r
   partspartZ	convertedr   r   r   r     s4    +

r   s   PNG

T)fileNameZxScaleZxyScaleZyxScaleZyScaleZxOffsetZyOffsetr   c                 C   s<   t | tsdS | d sdS | d}|dk	r8t|s8dS dS )r%   Fr   r   NT)r!   _imageDictPrototyperf   r   )r
   r   r   r   r   imageValidator3  s    

r   c              	   C   s   | dk	s|dk	s|dk	st | dk	rFt| d}|d}W 5 Q R X n:|dk	r\|dd }n$|dk	r| }|d}|| |tkrdS dS )zG
    Version 3+.

    This checks the signature of the image data.
    Nrb   )Fz,Image does not begin with the PNG signature.TN)AssertionErrorr   readtellseekpngSignature)pathdataZfileObjf	signatureposr   r   r   pngValidatorC  s    

r   c                 C   s~  t |tjjr|}ntj|}d}t | ts6d|fS t }t }i }| D ]}t |tsfd|f  S t|dks~d|f  S |D ]}t |t	sd|f    S q|\}	}
|
dkr|

dsdd|
 f  S t|	dkr dS ||
sdd	|
 f  S |	d
kr|
dkr dS |	|kr,dd|	 f  S ||	 |
|krPdd|
 f  S ||
 |
||	< qJd| k}|szdS dS )zD
    Check the validity of layercontents.plist.
    Version 3+.
    z1layercontents.plist in not in the correct format.Fr'   Zglyphszglyphs.z3Invalid directory name (%s) in layercontents.plist.r   )Fz(Empty layer name in layercontents.plist.z A glyphset does not exist at %s.zpublic.default)FzIThe name public.default is being used by a layer that is not the default.z1The layer name %s is used by more than one layer.z0The directory %s is used by more than one layer.)Fz1The required default glyph set is not in the UFO.r   )r   fsbaseZFSZosfsZOSFSr   r   r+   r9   
startswithexistsr   r   )r
   ZufoPathOrFileSystemZ
fileSystemZbogusFileMessageZusedLayerNamesZusedDirectoriescontentsentryiZ	layerNameZdirectoryNameZfoundDefaultr   r   r   layerContentsValidator]  s\    










r   c                 C   s  d}t | sd|fS i }i }|  D ]\}}t|tsBd|f  S t|ttfs\d|f  S |sf dS |dr$|ds|dsq$ntdt|kr dS |dr|}n|}|D ]F}t|tsdd	| f    S ||krdd
| f    S |||< qq$dS )a  
    Check the validity of the groups.
    Version 3+ (though it's backwards compatible with UFO 1 and UFO 2).

    >>> groups = {"A" : ["A", "A"], "A2" : ["A"]}
    >>> groupsValidator(groups)
    (True, None)

    >>> groups = {"" : ["A"]}
    >>> valid, msg = groupsValidator(groups)
    >>> valid
    False
    >>> print(msg)
    A group has an empty name.

    >>> groups = {"public.awesome" : ["A"]}
    >>> groupsValidator(groups)
    (True, None)

    >>> groups = {"public.kern1." : ["A"]}
    >>> valid, msg = groupsValidator(groups)
    >>> valid
    False
    >>> print(msg)
    The group data contains a kerning group with an incomplete name.
    >>> groups = {"public.kern2." : ["A"]}
    >>> valid, msg = groupsValidator(groups)
    >>> valid
    False
    >>> print(msg)
    The group data contains a kerning group with an incomplete name.

    >>> groups = {"public.kern1.A" : ["A"], "public.kern2.A" : ["A"]}
    >>> groupsValidator(groups)
    (True, None)

    >>> groups = {"public.kern1.A1" : ["A"], "public.kern1.A2" : ["A"]}
    >>> valid, msg = groupsValidator(groups)
    >>> valid
    False
    >>> print(msg)
    The glyph "A" occurs in too many kerning groups.
    z,The group data is not in the correct format.F)FzA group has an empty name.zpublic.zpublic.kern1.zpublic.kern2.zpublic.kernN.)Fz@The group data contains a kerning group with an incomplete name.z-The group data %s contains an invalid member.z1The glyph "%s" occurs in too many kerning groups.r   )r   r   r   r9   r   r   r   r+   )r
   bogusFormatMessageZfirstSideMappingZsecondSideMappingZ	groupNameZ	glyphListd	glyphNamer   r   r   groupsValidator  sB    ,



r   c                 C   s   d}t | tsd|fS |  D ]z\}}t |ts<d|f  S t |tsRd|f  S | D ]<\}}t |ts|d|f    S t |tsZd|f    S qZqdS )aA  
    Check the validity of the kerning data structure.
    Version 3+ (though it's backwards compatible with UFO 1 and UFO 2).

    >>> kerning = {"A" : {"B" : 100}}
    >>> kerningValidator(kerning)
    (True, None)

    >>> kerning = {"A" : ["B"]}
    >>> valid, msg = kerningValidator(kerning)
    >>> valid
    False
    >>> print(msg)
    The kerning data is not in the correct format.

    >>> kerning = {"A" : {"B" : "100"}}
    >>> valid, msg = kerningValidator(kerning)
    >>> valid
    False
    >>> print(msg)
    The kerning data is not in the correct format.
    z.The kerning data is not in the correct format.Fr   )r   r   r   r9   r   )r   r   firstZ
secondDictrF   r
   r   r   r   kerningValidator  s    




r   z-The lib data is not in the correct format: %sc                 C   s   t | s"dt| j }dt| fS |  D ]\}} t|tsVddt|j|f f  S |dkr*d}t| ttfsdt| j }d|| f  S | D ]0}t|tsdt|j }d|| f    S qq*dS )	a  
    Check the validity of the lib.
    Version 3+ (though it's backwards compatible with UFO 1 and UFO 2).

    >>> lib = {"foo" : "bar"}
    >>> fontLibValidator(lib)
    (True, None)

    >>> lib = {"public.awesome" : "hello"}
    >>> fontLibValidator(lib)
    (True, None)

    >>> lib = {"public.glyphOrder" : ["A", "C", "B"]}
    >>> fontLibValidator(lib)
    (True, None)

    >>> lib = "hello"
    >>> valid, msg = fontLibValidator(lib)
    >>> valid
    False
    >>> print(msg)  # doctest: +ELLIPSIS
    The lib data is not in the correct format: expected a dictionary, ...

    >>> lib = {1: "hello"}
    >>> valid, msg = fontLibValidator(lib)
    >>> valid
    False
    >>> print(msg)
    The lib key is not properly formatted: expected str, found int: 1

    >>> lib = {"public.glyphOrder" : "hello"}
    >>> valid, msg = fontLibValidator(lib)
    >>> valid
    False
    >>> print(msg)  # doctest: +ELLIPSIS
    public.glyphOrder is not properly formatted: expected list or tuple,...

    >>> lib = {"public.glyphOrder" : ["A", 1, "B"]}
    >>> valid, msg = fontLibValidator(lib)
    >>> valid
    False
    >>> print(msg)  # doctest: +ELLIPSIS
    public.glyphOrder is not properly formatted: expected str,...
    expected a dictionary, found %sFzAThe lib key is not properly formatted: expected str, found %s: %rzpublic.glyphOrderz/public.glyphOrder is not properly formatted: %sz expected list or tuple, found %szexpected str, found %sr   )	r   type__name___bogusLibFormatMessager   r   r9   r   r   )r
   reasonr   ZbogusGlyphOrderMessager   r   r   r   fontLibValidator1  s(    -

r   c                 C   sp   t | s"dt| j }dt| fS |  D ]@\}} t|tsTd| }dt| f  S |dkr*t| s* dS q*dS )a,  
    Check the validity of the lib.
    Version 3+ (though it's backwards compatible with UFO 1 and UFO 2).

    >>> lib = {"foo" : "bar"}
    >>> glyphLibValidator(lib)
    (True, None)

    >>> lib = {"public.awesome" : "hello"}
    >>> glyphLibValidator(lib)
    (True, None)

    >>> lib = {"public.markColor" : "1,0,0,0.5"}
    >>> glyphLibValidator(lib)
    (True, None)

    >>> lib = {"public.markColor" : 1}
    >>> valid, msg = glyphLibValidator(lib)
    >>> valid
    False
    >>> print(msg)
    public.markColor is not properly formatted.
    r   Fzkey (%s) should be a stringzpublic.markColor)Fz+public.markColor is not properly formatted.r   )r   r   r   r   r   r   r9   r   )r
   r   r   r   r   r   glyphLibValidatory  s    
r   __main__)N)N)NNN)E__doc__r=   ior   Zfs.baser   Zfs.osfscollections.abcr   ZfontTools.ufoLib.utilsr   r   r   r   r   r   r!   r$   r0   rG   rI   rJ   rL   rP   rQ   rT   rV   rW   rX   r[   r^   rg   rj   ro   rp   rs   rt   ru   rm   rz   rx   r}   r|   r   r   r,   r   r   r9   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   doctesttestmodr   r   r   r   <module>   s   "<






)


	K






J\+H&
