
    ]MhUx                     ~   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 Zd Zd Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Z d Z!d Z"d Z#d Z$d  Z%d! Z&d" Z'd# Z(d$ Z)d% Z*d& Z+d<d'Z, e-e.e/fd(fe.e/fd(fe.e/fd(fe0d(fe0d(fe0d(f)          Z1d* Z2d<d+Z3 e-e.e/fd(fe.e/fd(fe0d(fe0d(fe0d(f,          Z4d- Z5d. Z6d/ Z7d0Z8 e-e0d1fe.e/fd(fe.e/fd(fe.e/fd(fe.e/fd(fe.e/fd(fe.e/fd(fe0d(f2          Z9d3 Z:d=d4Z;d5 Z<d6 Z=d7 Z>d8Z?d9 Z@d: ZAeBd;k    rddlCZC eCjD                     dS dS )>z"Various low level data validators.    N)open)Mapping)numberTypesc                 d    t          | t                    rdS dD ]}t          | |          s dS 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attrs     [/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/fontTools/ufoLib/validators.pyisDictEnoughr      sM    
 %!! t+  ud## 	55	4    c                 "    t          | |          S )(
    Generic. (Added at version 2.)
    )r
   )r   typs     r   genericTypeValidatorr      s     eS!!!r   c                     t          | t          t          f          sdS t          |           }t          |          }||z
  rdS | D ]}t          |t                    s dS dS )r   FT)r
   listtuplesetint)r   validValues	valuesSetvalidValuesSetr   s        r   genericIntListValidatorr   %   s{     ftUm,, uFI%%N>! u  %%% 	55	4r   c                 D    t          | t                    sdS | dk     rdS dS (
    Generic. (Added at version 3.)
    Fr   Tr
   r   r   s    r   genericNonNegativeIntValidatorr#   5   .     eS!! uqyyu4r   c                 D    t          | t                    sdS | dk     rdS dS r   )r
   r   r"   s    r   !genericNonNegativeNumberValidatorr&   @   s.     e[)) uqyyu4r   c                 8   t          | t                    sdS |                                D ]\  }\  }}|s|| vr dS |                                 D ]	}||vr dS 
|                                 D ](\  }}||         \  }}||st          ||          s dS )dS )r    FNT)r
   r   r	   r   )r   	prototypekeyr   requiredvprototypeTypes          r   genericDictValidatorr-   K   s    
 eW%% u ) 1 1  _c8 	e55  zz||  i55   ++--  Q"+C.x9X9!]++ 	55	4r   c                     g d}| |v S )
    Version 2+.
    )regularitalicboldzbold italic )r   optionss     r   "fontInfoStyleMapStyleNameValidatorr5   m   s     ;::GGr   c                    t          | t                    sdS t          |           dk    rdS g d}t          t          dft          df          }g }| D ]c}t          ||          s dS |d         }|d         }t          |          }|s dS t          ||          }|s dS |                    |           d|t          |          k    rdS dS )
    Version 3+.
    Fr   T)r            )rangeMaxPPEMrangeGaspBehaviorr;   r<   )
r
   r   lendictr   r-   r#   r   appendsorted)	r   validBehaviorsdictPrototype	ppemOrderrangeRecordppembehaviorppemValiditybehaviorValiditys	            r   )fontInfoOpenTypeGaspRangeRecordsValidatorrI   u   s    eT"" u
5zzQt!\\NsDkdD\RRRMI  #K?? 	55>*235d;; 	5528^LL 	55F9%%%%u4r   c                 R   t          | t                    sdS t          |           dk    sdS |                     d          dk    rdS |                     d          \  }}|                    d          dk    rdS |                    d          dk    rdS |                    d          \  }}}t          |          dk    rdS t          |          dk    rdS t          |          dk    rdS 	 t          |          }t          |          }t          |          }n# t          $ r Y dS w xY w|dk     s|d	k    rdS t          j        ||          d         }|dk     s||k    rdS |                    d          \  }}}	t          |          dk    rdS t          |          dk    rdS t          |	          dk    rdS 	 t          |          }t          |          }t          |	          }	n# t          $ r Y dS w xY w|d
k     s|dk    rdS |d
k     s|dk    rdS |	d
k     s|	dk    rdS dS )r/   F    r8   /r9   :      r      ;   T)	r
   strr=   countsplitr   
ValueErrorcalendar
monthrange)
r   datetimeyearmonthdaymonthMaxDayhourminuteseconds
             r   $fontInfoOpenTypeHeadCreatedValidatorrb      s^   
 eS!! uu::u{{31uS!!JD$zz#!uzz#!uzz#D%
4yyA~~u
5zzQu
3xx1}}u4yyE

#hh   uuqyyEBJJu%dE2215K
Qww###u::c??D&&
4yyA~~u
6{{au
6{{au4yyVV   uuaxx4"99uzzVb[[uzzVb[[u4s$   /-D 
D+*D+>-G, ,
G:9G:c                     t          | t                    sdS t          t          dft          dft          dft          dft          df          }| D ]}t          ||          s dS dS )r7   FT)nameID
platformID
encodingID
languageIDstring)r
   r   r>   r   rS   r-   )r   rB   
nameRecords      r   $fontInfoOpenTypeNameRecordsValidatorrj      s     eT"" uT{;;;T{  M   
#J>> 	55	4r   c                 D    t          | t                    sdS | dk     rdS dS )r/   Fr   Tr!   r"   s    r   'fontInfoOpenTypeOS2WeightClassValidatorrl      r$   r   c                 T    t          | t                    sdS | dk     rdS | dk    rdS dS )r/   Fr8   	   Tr!   r"   s    r   &fontInfoOpenTypeOS2WidthClassValidatorro      s<     eS!! uqyyuqyyu4r   c                     t          | t          t          f          sdS t          |           dk    rdS | D ]}t          |t                    s dS dS )z
    Version 2.
    F
   Tr
   r   r   r=   r   r   r   s     r   *fontInfoVersion2OpenTypeOS2PanoseValidatorrt      si     ftUm,, u
6{{bu  %%% 	55	 4r   c                     t          | t          t          f          sdS t          |           dk    rdS | D ]#}t          |t                    s dS |dk     r dS $dS )r7   Frq   r   Trr   rs   s     r   *fontInfoVersion3OpenTypeOS2PanoseValidatorrv     sy     ftUm,, u
6{{bu  %%% 	5519955  4r   c                     t          | t          t          f          sdS t          |           dk    rdS | D ]}t          |t                    s dS | \  }}|dk     s|dk    rdS |dk     s|dk    rdS dS )r/   Fr9   r         Trr   )r   r   classID
subclassIDs       r   'fontInfoOpenTypeOS2FamilyClassValidatorr|     s     ftUm,, u
6{{au  %%% 	55	 GZ{{glluA~~bu4r   c                     t          | t          t          f          sdS t          |           dk    rdS t          |           dz  rdS | D ]}t          |t                    s dS dS )r/   Frx   r9   Tr
   r   r   r=   r   rs   s     r    fontInfoPostscriptBluesValidatorr   +  ~     ftUm,, u
6{{Ru
6{{Q u  %-- 	55	4r   c                     t          | t          t          f          sdS t          |           dk    rdS t          |           dz  rdS | D ]}t          |t                    s dS dS )r/   Frq   r9   Tr~   rs   s     r   %fontInfoPostscriptOtherBluesValidatorr   ;  r   r   c                     t          | t          t          f          sdS t          |           dk    rdS | D ]}t          |t                    s dS dS )r/   FrP   Tr~   rs   s     r    fontInfoPostscriptStemsValidatorr   K  sg     ftUm,, u
6{{Ru  %-- 	55	4r   c                 L    t          t          dd                    }| |vrdS dS )r/   r8      FT)r   range)r   r   s     r   .fontInfoPostscriptWindowsCharacterSetValidatorr   Y  s.     uQ||$$KKu4r   c                 X    t          t          df          }t          | |          sdS dS )r7   T)idF)r>   rS   r-   r   rB   s     r   %fontInfoWOFFMetadataUniqueIDValidatorr   c  s4     S$K(((M}55 u4r   c                     t           dft           dft           dft           dfd}t          | |          sdS d| v r|                     d          dvrdS dS )r7   TF)nameurldirclassr   ltrrtlrS   r-   getr   s     r   #fontInfoWOFFMetadataVendorValidatorr   m  sn    
 dU|U|u	 M  }55 u~~%))E**.@@u4r   c                 T   t          t          df          }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 ]3}t          ||          s dS d|v r|                    d          dvr dS 4dS )r7   T)creditsFr   )r   r   roler   r   r   r   )r>   r   r-   r=   rS   r   )r   rB   credits      r   $fontInfoWOFFMetadataCreditsValidatorr   ~  s     $...M}55 uuY   udU|eU|u M 	"  #FM:: 	55F??vzz%00FF554r   c                     t          t          dft          df          }t          | |          sdS | d         D ]}t	          |          s dS dS )r7   FT)r   textr   r>   rS   r   r-   fontInfoWOFFMetadataTextValuer   rB   r   s      r   (fontInfoWOFFMetadataDescriptionValidatorr     si     c5\t===M}55 uf  ,T22 	55	4r   c                     t          t          dft          dft          df          }t          | |          sdS d| v r| d         D ]}t	          |          s dS dS )r7   F)r   r   r   r   Tr   r   s      r   $fontInfoWOFFMetadataLicenseValidatorr     sx     c5\u3,OOOM}55 u&M 	 	D066 uu4r   c                     t          t          df          }t          | |          sdS | d         D ]}t          |          s dS dS r7   T)r   Fr   r>   r   r-   r   r   s      r   &fontInfoWOFFMetadataTrademarkValidatorr     c     tTl+++M}55 uf  ,T22 	55	4r   c                     t          t          df          }t          | |          sdS | d         D ]}t          |          s dS dS r   r   r   s      r   &fontInfoWOFFMetadataCopyrightValidatorr     r   r   c                     t           dft           dft           dfd}t          | |          sdS d| v r|                     d          dvrdS dS )r7   TF)r   r   r   r   r   r   r   s     r   %fontInfoWOFFMetadataLicenseeValidatorr     s_     "4[#ueUUM}55 u~~%))E**.@@u4r   c                     t           dft           dft           dft           dfd}t          | |          sdS d| v r|                     d          dvrdS dS r7   TF)r   languager   r   r   r   r   r   s     r   r   r     n    
 d%LU|u	 M  }55 u~~%))E**.@@u4r   c                 j    t          | t                    sdS | sdS | D ]}t          |          s dS dS )r7   FT)r
   r   &fontInfoWOFFMetadataExtensionValidator)r   	extensions     r   'fontInfoWOFFMetadataExtensionsValidatorr     sX     eT"" u u  	5i@@ 	55	4r   c                     t          t          dft          dft          df          }t          | |          sdS d| v r| d         D ]}t	          |          s dS | d         D ]}t          |          s dS dS )r7   FT)namesr	   r   r   r	   )r>   r   rS   r-   *fontInfoWOFFMetadataExtensionNameValidator*fontInfoWOFFMetadataExtensionItemValidator)r   rB   r   items       r   r   r     s     e}T4Lc5\RRRM}55 u%'N 	 	D=dCC uug  9$?? 	55	4r   c                     t          t          dft          dft          df          }t          | |          sdS | d         D ]}t	          |          s dS | d         D ]}t          |          s dS dS )r7   FT)r   r   r   r   r   )r>   rS   r   r-   r   +fontInfoWOFFMetadataExtensionValueValidator)r   rB   r   vals       r   r   r     s     S%LtdD\RRRM}55 ug  9$?? 	55	X  :3?? 	55	4r   c                     t           dft           dft           dft           dfd}t          | |          sdS d| v r|                     d          dvrdS dS r   r   r   s     r   r   r     r   r   c                     t           dft           dft           dft           dfd}t          | |          sdS d| v r|                     d          dvrdS dS r   r   r   s     r   r   r   (  r   r   c                     t          | t                    sdS |t                      }| D ]G}t          |          s dS |                    d          }|||v r dS |                    |           HdS r7   FN
identifierT)r
   r   r   guidelineValidatorr   add)r   identifiersguider   s       r   guidelinesValidatorr   >  s     eT"" uee ( (!%(( 	55YY|,,
![((uuOOJ'''4r   F)xyangler   colorr   c                    t          | t                    sdS |                     d          }|                     d          }|                     d          }||dS |||dS |||dS ||dk     rdS |dk    rdS |                     d          }|t          |          sdS |                     d	          }|t	          |          sdS d
S )r7   Fr   r   r   Nr   ih  r   r   T)r-   _guidelineDictPrototyper   identifierValidatorcolorValidator)r   r   r   r   r   r   s         r   r   r   [  s      '>?? u		#A		#AIIgEyQYuyAI5}5=u19953;;5<((J&9*&E&EuIIgE!6!6u4r   c                     t          | t                    sdS |t                      }| D ]G}t          |          s dS |                    d          }|||v r dS |                    |           HdS r   )r
   r   r   anchorValidatorr   r   )r   r   anchorr   s       r   anchorsValidatorr     s     eT"" uee ( (v&& 	55ZZ--
![((uuOOJ'''4r   )r   r   r   r   r   c                 4   t          | t                    sdS |                     d          }|                     d          }||dS |                     d          }|t          |          sdS |                     d          }|t	          |          sdS dS )r7   Fr   r   Nr   r   T)r-   _anchorDictPrototyper   r   r   )r   r   r   r   r   s        r   r   r     s      ';<< u		#A		#AyAIu<((J&9*&E&EuIIgE!6!6u4r   c                     d}d}t          | t                    sdS | sdS t          |           dk    rdS | D ] }t          |          }||k     s||k    r dS !dS )z
    Version 3+.

    >>> identifierValidator("a")
    True
    >>> identifierValidator("")
    False
    >>> identifierValidator("a" * 101)
    False
        ~   Fd   T)r
   rS   r=   ord)r   validCharactersMinvalidCharactersMaxcs       r   r   r     s     eS!! u u
5zzCu  FF!!!Q);%;%;55 &<4r   c                 |   t          | t                    sdS |                     d          }t          |          dk    rdS |D ]w}|                                }d}	 t          |          }d}n# t          $ r Y nw xY w|s#	 t          |          }d}n# t          $ r Y nw xY w|s dS |dk     r dS |dk    r dS xd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,rO   Tr   r8   )r
   rS   rU   r=   stripr   rV   float)r   partspart	converteds       r   r   r     s   V eS!! uKKE
5zzQu  zz||		t99DII 	 	 	D	 	T{{ 		    	55!8855!8855 4s$   A//
A<;A<B
B! B!s   PNG

T)fileNamexScalexyScaleyxScaleyScalexOffsetyOffsetr   c                     t          | t                    sdS | d         sdS |                     d          }|t          |          sdS dS )r7   Fr   r   NT)r-   _imageDictPrototyper   r   )r   r   s     r   imageValidatorr   3  s\      ':;; u uIIgE!6!6u4r   c                 J   | ||J | >t          | d          5 }|                    d          }ddd           n# 1 swxY w Y   nM||dd         }n@|>|                                }|                    d          }|                    |           |t          k    rd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)r   readtellseekpngSignature)pathdatafileObjf	signatureposs         r   pngValidatorr   C  s     t/73F3F3F$ 	"q		I	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	"		!H				llnnLLOO	SL  DD:s   =AAc                 R   t          |t          j        j                  r|}nt          j                            |          }d}t          | t                    sd|fS t                      }t                      }i }| D ]}t          |t                    sd|fc S t          |          dk    sd|fc S |D ]}t          |t                    sd|fc c S  |\  }	}
|
dk    r|

                    d          s	dd|
z  fc S t          |	          dk    r dS |                    |
          s	dd	|
z  fc S |	d
k    r	|
dk    r dS |	|v r	dd|	z  fc S |                    |	           |
|v r	dd|
z  fc S |                    |
           |
||	<   d|                                v }|sdS dS )zD
    Check the validity of layercontents.plist.
    Version 3+.
    z1layercontents.plist in not in the correct format.Fr9   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baseFSosfsOSFSr   r   r=   rS   
startswithexistsr   r   )r   ufoPathOrFileSystem
fileSystembogusFileMessageusedLayerNamesusedDirectoriescontentsentryi	layerNamedirectoryNamefoundDefaults               r   layerContentsValidatorr  ]  sv   
 %rwz22 7(

W\\"566
JeT"" '&&&UUNeeOH +, +,%&& 	+*****5zzQ***** 	/ 	/Aa%% /......./#( 	=H$$ ++I66 I#$   
 y>>QDDD  // 	M<}LLLLL(((]h-F-F  
 &&CiO    	9%%%O++B]R    	M***+x000L JII:r   c                 \   d}t          |           sd|fS i }i }|                                 D ]\  }}t          |t                    sd|fc S t          |t          t
          f          sd|fc S |s dS |                    d          r|                    d          s|                    d          st          d          t          |          k    r dS |                    d          r|}n|}|D ]6}t          |t                    sdd	|z  fc c S ||v rdd
|z  fc c S |||<   7d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
   rS   r   r   r  r=   )r   bogusFormatMessagefirstSideMappingsecondSideMapping	groupName	glyphListd	glyphNames           r   groupsValidatorr    s   X H )((( % ") ")	9)c++ 	-,,,,,)dE]33 	-,,,,, 	7666	** 	)''88 
AUAUB B 
 ''3y>>99   ##O44 &$%& ) )	!)S11 G)S      >>KiW       )):r   c                    d}t          | t                    sd|fS |                                 D ]\  }}t          |t                    sd|fc S t          |t                    sd|fc S |                                D ]?\  }}t          |t                    sd|fc c S t          |t                    sd|fc c S @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	   rS   r   )r   r  first
secondDictra   r   s         r   kerningValidatorr    s   . JdG$$ )(((!ZZ\\ 	1 	1z%%% 	-,,,,,J00 	-,,,,,'--// 	1 	1MFEfc** 10000000{33 100000001	1
 :r   z-The lib data is not in the correct format: %sc                    t          |           s#dt          |           j        z  }dt          |z  fS |                                 D ]\  }} t          |t                    sddt          |          j        d|fc S |dk    rzd}t          | t          t          f          s dt          |           j        z  }d||z  fc S | D ]9}t          |t                    s"dt          |          j        z  }d||z  fc c S :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 %sFz;The lib key is not properly formatted: expected str, found z: zpublic.glyphOrderz/public.glyphOrder is not properly formatted: %sz expected list or tuple, found %szexpected str, found %sr   )	r   type__name___bogusLibFormatMessager	   r
   rS   r   r   )r   reasonr)   bogusGlyphOrderMessager  s        r   fontLibValidatorr'  1  sR   Z  62T%[[5II,v555kkmm B B
U#s## 	599%%%ss,   
 %%%%V"edE]33 >;d5kk>RR4v=====" B B	!)S11 B5Y8PPF "86"AAAAAAAB :r   c                    t          |           s#dt          |           j        z  }dt          |z  fS |                                 D ]E\  }} t          |t                    sd|z  }dt          |z  fc S |dk    rt          |           s dS Fd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
   rS   r   )r   r%  r)   s      r   glyphLibValidatorr)  y  s    0  62T%[[5II,v555kkmm L L
U#s## 	:2S8F0699999$$$!%(( LKKK:r   __main__)N)NNN)E__doc__rW   ior   fs.baser   fs.osfscollections.abcr   fontTools.ufoLib.utilsr   r   r   r   r#   r&   r-   r5   rI   rb   rj   rl   ro   rt   rv   r|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r>   r   r   rS   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r$  r'  r)  r#  doctesttestmodr3   r   r   <module>r3     s{   ( (          # # # # # # . . . . . .
 
 
" " "         D    89 9 9x  &  
 
 
    "  &              "  0
 
 
  
 
 

 
 
	 	 	  "    "     "  ,   & $U|UU|U<

u,U|   ! ! !R   & tU|UU|U
u,U|     6  >D D DV $d4[%L% 5\5!5\5!%L% 5\5!5\5!,	 	 	       4B B BTT T Tx$ $ $V I @ @ @P# # #L zNNNGO r   