
    %i3N                       d Z ddlmZ ddlZddlmc mZ ddl	Z
ddlZddlmZ ddlZddlZddlmZmZ  ee      j+                         j,                  d   Zedz  dz  d	z  Zd
 Z e       Zej6                  Zej8                  Zej:                  Zej<                  Zej>                  Zej@                  Z ejB                  Z!ejD                  Z"ejF                  Z#ejH                  Z$ejJ                  Z%dZ&dZ'dZ(d"dZ)	 	 	 	 	 	 	 	 d#dZ*	 	 d$	 	 	 	 	 	 	 d%dZ+	 	 	 d&	 	 	 	 	 	 	 	 	 d'dZ,d(d)dZ-d*dZ.d*dZ/d*dZ0d*dZ1d*dZ2d*dZ3d*dZ4d*dZ5d*dZ6d*dZ7d*dZ8d*dZ9d*dZ:d*dZ;d*d Z<d*d!Z=y)+uH  IDS Phase 0.5 Lite Evaluator 회귀 테스트.

7+ 시나리오 (task-2446 Fix 4):
    1. L1 Contrast 정상 PASS / 그라데이션(분포 측정) PASS / 글리프 명도 단조 FAIL
    2. L2 Margin: 침범 0건 PASS / 침범 5건 FAIL
    3. L3 Hierarchy: 정상 비율 PASS / 헤딩=본문 동일 크기 FAIL (head/sub ratio<1.3)
    4. L4 Color Token: 4색 이내 PASS / off-token WARN / AI 퍼플 FAIL
    5. L5 Typography: Pretendard PASS / 시스템 fallback FAIL
    6. JSON Schema invalid input → SchemaValidationError
    7. mappingVersion 미일치 → SSotMismatchError
    )annotationsN)Path)Image	ImageDraw   scriptsidszlite_evaluator.pyc                 (   t         j                  j                  dt              } | | j                  t        dt               t         j                  j                  |       }|t        j                  d<   | j                  j                  |       |S )N_ids_lite_evaluatorz Cannot load lite_evaluator from )
	importlibutilspec_from_file_location
_LITE_PATHloaderRuntimeErrormodule_from_specsysmodulesexec_module)specmods     X/home/jay/workspace/.worktrees/task-2446-design/tests/scripts/ids/test_lite_evaluator.py_load_lite_moduler      sx    >>11zD |t{{*=j\JKK
..
)
)$
/C),CKK%&KKC J    i8  H   c                    t        |       ddt        t        t        dt        t        t        t        dddddd	d
dddg dddddddddg dddddddddg ddd ddddgd!	S )"u%   SSOT 적합 LayoutMeta 기본 구조.theme-fa-fintechzinsurance-fawidthheighttopbottomleftright         )baselinecolumnsguttersolid#F8F4EE)typedata	MainTitleheadline)x         r2   `   z#0B1E3F
Pretendard  333333?namerolebboxfontSizefill
fontFamily
fontWeight
lineHeightSubTitlesubhead)r2   ih  iX  P   @   z#1F1F1Fi  ?ActionButtoncta)r2   ip  i@  rD   ,   #FFFFFF)	
image_paththemePresettargetPersonamappingVersioncanvassafeAreagrid
background
components)strSSOT_MAPPING_VERSIONCANVAS_WCANVAS_HSAFE_PX)rK   s    r   
_base_metarY   A   s     *o)'.$9#wRYZ2<&	: $",!*!!	 #!+!*!!	 '+!*!!	+
) )r   c                
   d |D        \  }}}}t        fddD              }t        dt        |dz              }t        dt        |dz              }	t        dt        ||dz  z              }
t        |
      D ]O  }||	z   t        ||d|	z  z
  z  t        d	|
d	z
        z        z   }| j	                  |||	z   ||z   ||z   |	z
  g|
       Q ||dz  z   }| j	                  ||	z   |||z   |	z
  |t        d	|dz        z   g|
       y)um   bbox 내에 글리프-유사 패턴(가는 막대 strokes)을 그려 contrast 측정 가능 픽셀을 생성.c              3  2   K   | ]  }t        |        y wNint.0vs     r   	<genexpr>z#_draw_text_block.<locals>.<genexpr>w   s     'Q#a&'   c              3  `   K   | ]%  }t        j                  d       ||dz    d       ' yw)#      N)r^   lstrip)r`   ifill_hexs     r   rb   z#_draw_text_block.<locals>.<genexpr>x   s,     Q!S-a!a%8"=Qs   +.)r   rf      rf   g~jt?rk   g333333?r      r>   N)tuplemaxr^   range	rectangle)drawr<   rj   xywhfill_rgbstroke_wpadcolsri   cxcys     `           r   _draw_text_blockr}   p   s!    ($'JAq!QQyQQH1c!e)n%H
aQX
Cq#a8a<()*D4[ QWs1AG,s1dQh/??@@AGR(]AECK@xPQ 
Q!VBNN	
S"a!eck2Ax1}(=#=>X  r   c                    t        j                  dt        t        f|      }t	        j
                  |      }|r-|D ](  }|j                  dd      st        ||d   |d          * |j                  |        y)u,   단색 배경 + 텍스트 블록 PNG 합성.RGBisTextTr<   r>   N	r   newrV   rW   r   Drawgetr}   save)pathbg_hexrS   imgrr   cs         r   _render_solid_bg_imager      sj     ))EHh/
8C>>#D 	=AuuXt$ qy!F)<	= HHTNr   c           	        t        j                  t        t        dft         j                        }t        j
                  t        |dd d      t        |dd d      t        |dd d      g      }t        j
                  t        |dd d      t        |dd d      t        |dd d      g      }t        t              D ]M  }|t        dt        dz
        z  }|d|z
  z  ||z  z   j                  t         j                        ||ddddf<   O t        j                  |d      }	t        j                  |	      }
|r-|D ](  }|j                  d	d
      st        |
|d   |d          * |	j!                  |        y)uT   수직 그라데이션 배경 + 텍스트 PNG 합성. L1 분포 측정 시나리오.r   )dtyperl   rg         Nr   r   Tr<   r>   )npzerosrW   rV   uint8arrayr^   rp   ro   astyper   	fromarrayr   r   r   r}   r   )r   	start_hexend_hexrS   arrsert   tr   rr   r   s               r   _render_gradient_bg_imager      sS    ((Hh*"((
;C
#i!nb)3y1~r+BC	RSTUXZD[\]A
#galB'WQq\2)>GAaLRT@UVWA8_ >Ax!|$$QUa!e+33BHH=Aq!G> //#u
%C>>#D 	=AuuXt$ qy!F)<	= HHTNr   c                    t        j                  dt        t        fd      }t	        j
                  |      }|r-|D ](  }|j                  dd      st        ||d   |d          * |j                  |        y)u'   AI 퍼플(hue 280, sat 0.7) 배경 PNG.r   )   +      r   Tr<   r>   Nr   )r   rS   r   rr   r   s        r   _render_purple_bg_imager      sj     ))EHh/
@C>>#D 	=AuuXt$ qy!F)<	= HHTNr   c                N   | dz  }t        |      }t        |d|d          t        j                  |      j	                  d      }t        j                  |      }t        d |d   D              }d |d   D        \  }}}}	|j                  ||||z   ||	z   gd	
       t        ||d   |d          |j                  |       t        j                  t        j                  |      j	                  d            }
t        |
|      }|j                  }ddh}||v }|st        j                   d|fd||f      dt#        j$                         v st        j&                  |      rt        j(                  |      ndt        j(                  |      t        j(                  |      dz  }t        j*                  d|j,                         dz   d|iz  }t/        t        j0                  |            dx}x}}t        d |j2                  d   D              }|d   }d}||k\  }|st        j                   d|fd||f      t        j(                  |      t        j(                  |      dz  }t        j*                  |      dz   d|iz  }t/        t        j0                  |            dx}x}}y)ua   정상 케이스: 어두운 텍스트(#0B1E3F) vs 밝은 배경(#F8F4EE) → p5 ≥ 4.5 → PASS.zl1_normal.pngr-   rS   r   rS   r   c              3  2   K   | ]  }|d    dk(  s|  ywr;   rH   N r`   r   s     r   rb   z/test_l1_contrast_normal_pass.<locals>.<genexpr>        CQ&	U0BqC   c              3  2   K   | ]  }t        |        y wr\   r]   r_   s     r   rb   z/test_l1_contrast_normal_pass.<locals>.<genexpr>        .Q#a&.rc   r<         ?   rm   r>   PASSWARNinz/%(py2)s
{%(py2)s = %(py0)s.verdict
} in %(py5)sresultpy0py2py5u   L1 정상 케이스 FAIL: 
>assert %(py7)spy7Nc              3  2   K   | ]  }|d    dk(  s|  yw)r;   r1   Nr   )r`   ds     r   rb   z/test_l1_contrast_normal_pass.<locals>.<genexpr>   s       ai:6Mr   per_componentp5g      @>=z%(py1)s >= %(py4)spy1py4z
>assert %(py6)spy6)rY   r   r   openconvertr   r   nextrq   r}   r   r   asarrayevaluate_l1_contrastverdict
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_saferepr_format_assertmsgreasonAssertionError_format_explanationdetails)tmp_pathimg_pathmetar   rr   rH   rs   rt   ru   rv   r   r   @py_assert1@py_assert4@py_assert3@py_format6@py_format8headline_detail@py_assert0@py_assert2@py_format5@py_format7s                         r   test_l1_contrast_normal_passr      s    /)HhD8I$|BTU
**X

&
&u
-C>>#D
C$|,C
CC.#f+.JAq!QNNAq!a%Q'lN;T3v;F4HHX
**UZZ)11%8
9C!#t,F>>[ff-[>--[[[>-[[[[[[6[[[6[[[>[[[-[[[1KFMM?/[[[[[[[[ >>/2 O 4 8C8 C'888 C888 888C8888888888r   c           	        | dz  }t        |      }ddg dddddd	d
g|d<   t        |dd|d          t        j                  t	        j
                  |      j                  d            }t        ||d   d         }t        |      }d}||kD  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  dt        |             dz   d|iz  }	t!        t        j"                  |	            dx}x}}t%        |      t        |      dz     }
d}|
|kD  }|st        j                  d|fd|
|f      dt        j                         v st        j                  |
      rt        j                  |
      ndt        j                  |      dz  }t        j                  d|
 d       d!z   d"|iz  }t!        t        j"                  |            dx}}y)#u   그라데이션 배경에서 글리프 픽셀별 contrast 분포가 발생해야 한다.

    p5(어두운 끝)와 p95(밝은 끝)가 달라야 분포 측정이 작동.
    zl1_gradient.pngHeadliner1   )r2   d   r4   r4   r5   #000000r6   r7   r8   r9   rS   rJ   )r   r   rS   r   r   r   >)z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)slen	contrasts)r   r   py3r   u   glyph 픽셀 부족: z
>assert %(py8)spy8N   g      ?)z%(py0)s > %(py3)sr   )r   r   zp5=u    너무 낮음z
>assert %(py5)sr   )rY   r   r   r   r   r   r   _glyph_pixel_contrastsr   r   r   r   r   r   r   r   r   r   sorted)r   r   r   r   r   r   @py_assert5r   r   @py_format9r   r   @py_format4r   s                 r   &test_l1_contrast_gradient_distributionr      s   
 ++HhD (&		
D %	 **UZZ)11%8
9C&sD,>q,ABIy>ICI>CIII>CIIIIII3III3IIIIIIyIIIyIII>IIICIII#8Y8H!IIIIIIII 
		3y>R/	0B-28---2------2---2------s2$n-------r   c                <   | dz  }t        |      }|d   D ]  }d|d<   	 t        |d|d          t        j                  t	        j
                  |      j                  d            }t        ||      }|j                  }d}||k(  }|st        j                  d	|fd
||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }	t        j                  d|j                          dz   d|	iz  }
t#        t        j$                  |
            dx}x}}d |j&                  xs dfD        }t)        |      }|sddt        j                         v st        j                  t(              rt        j                  t(              ndt        j                  |      t        j                  |      dz  }t#        t        j$                  |            dx}}y)uM   배경(#888) vs 텍스트(#999) 같이 contrast 부족 → p5 < 4.5 → FAIL.z
l1_low.pngrS   z#999999r>   z#888888r   r   FAIL==z/%(py2)s
{%(py2)s = %(py0)s.verdict
} == %(py5)sr   r   u   contrast 부족인데 PASS: r   r   Nc              3  @   K   | ]  }d |j                         v   yw)contrastN)lowerr`   rs     r   rb   z=test_l1_contrast_low_glyph_brightness_fail.<locals>.<genexpr>  s     F1zQWWY&Fs    ,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}anyr   r   r   )rY   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  )r   r   r   r   r   r   r   r   r   r   r   r   s               r   *test_l1_contrast_low_glyph_brightness_failr     sd    ,&HhD, &	8I$|BTU
**UZZ)11%8
9C!#t,F>>TVT>V#TTT>VTTTTTT6TTT6TTT>TTTVTTT'CFNNCS%TTTTTTTTF1D"0EFF3FFFFFFFFF3FFF3FFFFFFFFFFFFFFr   c                P   | dz  }t        |      }t        ||d          t        |      }|j                  }d}||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }t	        j                  |j                        d	z   d
|iz  }t        t	        j                  |            dx}x}}|j                  d   }	d}|	|k(  }
|
slt	        j
                  d|
fd|	|f      t	        j                  |	      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}	x}
}|j                  d   }	d}|	|u }
|
slt	        j
                  d|
fd|	|f      t	        j                  |	      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}	x}
}y)u1   모든 텍스트가 safe-area(72px) 안 → PASS.zl2_clean.pngrS   rS   r   r   r   r   r   r   r   Nviolation_countr   z%(py1)s == %(py4)sr   assert %(py6)sr   ssot_alignedT)is)z%(py1)s is %(py4)s)rY   r   evaluate_l2_marginr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s                r   test_l2_margin_safe_area_cleanr    sZ    .(HhD8\0BC%F>>3V3>V#333>V33333363336333>333V333V^^3333333>>+,11,1111,111,1111111111>>.)1T1)T1111)T111)111T1111111r   c                   | dz  }t        |      }t        d      D cg c]  }d| ddd|dz  z   ddgd	d
dddd c}|d<   t        ||d          t        |      }|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  |j                        dz   d|iz  }	t        t        j                  |	            dx}x}}|j                  d   }
d}|
|k(  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}
x}}yc c}w )u/   5개 컴포넌트가 safe-area 침범 → FAIL.zl2_violate.pngr   Badbody
   r   r3   <   rI   r   r6     ffffff?r9   rS   r  r   r   r   r   r   r   r   Nr  r  r   r	  r   )rY   rp   r   r  r   r   r   r   r   r   r   r   r   r   r   )r   r   r   ri   r   r   r   r   r   r   r   r   r   r   s                 r   test_l2_margin_violations_failr    sb    **HhD q  !Ia"fc2.&		
D 8\0BC%F>>3V3>V#333>V33333363336333>333V333V^^3333333>>+,11,1111,111,1111111111#s   Gc                >   | dz  }t        |      }t        ||d          t        |      }|j                  }d}||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }t	        j                  |j                        d	z   d
|iz  }t        t	        j                  |            dx}x}}|j                  d   }	d}|	|k\  }
|
slt	        j
                  d|
fd|	|f      t	        j                  |	      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}	x}
}y)u>   정상 비율: head=96, sub=64, head/sub=1.5 ≥ 1.3 → PASS.zl3_pass.pngrS   r  r   r   r   r   r   r   r   Nhead_sub_ratiorF   r   r   r   r	  r   )rY   r   evaluate_l3_hierarchyr   r   r   r   r   r   r   r   r   r   r   r  s                r   test_l3_hierarchy_normal_passr  :  s    -'HhD8\0BC"4(F>>3V3>V#333>V33333363336333>333V333V^^3333333>>*+2s2+s2222+s222+222s2222222r   c                ,   | dz  }t        |      }d|d   d   d<   d|d   d   d<   |d   j                  ddg d	d
ddddd       t        ||d          t        |      }|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  |j                        dz   d|iz  }t        t        j                  |            dx}x}}d |j                  xs dj!                  d      D        }t#        |      }|sddt        j                         v st        j                  t"              rt        j                  t"              ndt        j                  |      t        j                  |      dz  }	t        t        j                  |	            dx}}y)u   heading=subhead 동일 크기 → ratio<1.3 → FAIL.

    또한 absolute_min=40 위반(fontSize=20) 추가하여 FAIL 확정.
    zl3_fail.pngrE   rS   r   r=   rl   TooSmallcaption)r2   r7   r  r   r   r   r6   r  r  r9   r  r   r   r   r   r   r   r   Nc              3  $   K   | ]  }d |v  
 yw)absolute_minNr   r   s     r   rb   z6test_l3_hierarchy_head_eq_body_fail.<locals>.<genexpr>_  s     Mq~"Ms   r   ;r  r  r  )rY   appendr   r  r   r   r   r   r   r   r   r   r   r   r   r   splitr  
r   r   r   r   r   r   r   r   r   r   s
             r   #test_l3_hierarchy_head_eq_body_failr$  E  sz   
 -'HhD(*Dq*%(*Dq*%'&		
 8\0BC"4(F>>3V3>V#333>V33333363336333>333V333V^^3333333MV]]-@b,G,G,LMM3MMMMMMMMM3MMM3MMMMMMMMMMMMMMr   c                   | dz  }t        |      }t        ||d          t        j                  t	        j
                  |      j                  d            }t        ||      }|j                  }ddh}||v }|st        j                  d|fd||f      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      t        j                  |      d
z  }t        j                  |j                         dz   d|iz  }	t#        t        j$                  |	            dx}x}}|j                   d   }
d}|
|k  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t#        t        j$                  |            dx}
x}}|j                   d   }
d}|
|k  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t#        t        j$                  |            dx}
x}}y)uE   단순 단색 배경 + 텍스트 → 색상 카운트 ≤ 4 → PASS.zl4_pass.pngrS   r  r   r   r   r   r   r   r   r   r   Ncolor_countrk   <=z%(py1)s <= %(py4)sr   r	  r   ai_purple_ratio皙?)<)z%(py1)s < %(py4)s)rY   r   r   r   r   r   r   evaluate_l4_color_tokenr   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   s                 r    test_l4_color_token_palette_passr.  g  s    -'HhD8\0BC
**UZZ)11%8
9C$S$/F>>=ff-=>--===>-======6===6===>===-===v~~=======>>-(-A-(A----(A---(---A------->>+,3t3,t3333,t333,333t3333333r   c                   | dz  }t        |      }|d   D ]  }|d   dk(  sd|d<    n t        |d|d          t        j                  t	        j
                  |      j                  d	            }t        ||      }|j                  d
   }d}||k  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                          v st        j"                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j$                  d|j                         dz   d|iz  }t        t        j                  |            dx}x}}d}|j                  d   }||v }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }
t        t        j                  |
            dx}x}}y)uQ   themePreset 팔레트에 없는 형광 핑크 텍스트 → WARN (회귀 차단).z
l4_off.pngrS   r;   r1   z#FF00AAr>   z#F0F0F0r   r   r&  rk   r'  r)  r   r	  r   Nr   r   r   r   r   u    off-token이 PASS로 통과됨: r   r   off_token_fillsr   z%(py1)s in %(py4)s)rY   r   r   r   r   r   r   r-  r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s                  r   "test_l4_color_token_off_token_warnr2  t  s    ,&HhD, V9
"!AfI 8I$|BTU
**UZZ)11%8
9C$S$/F>>-(-A-(A----(A---(---A------->>XVX>V#XXX>VXXXXXX6XXX6XXX>XXXVXXX'GGW%XXXXXXXX9'89999999999999999999999999r   c                   | dz  }t        |      }t        ||d          t        j                  t	        j
                  |      j                  d            }t        ||      }|j                  }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      d	z  }t        j                  |j                         d
z   d|iz  }	t#        t        j$                  |	            dx}x}}|j                   d   }
d}|
|kD  }|slt        j                  d|fd|
|f      t        j                  |
      t        j                  |      dz  }dd|iz  }t#        t        j$                  |            dx}
x}}d}
g }|j&                  }|}|sd}|}|
|v }|sddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }	|j)                  |	       |s+ddt        j                        iz  }|j)                  |       t        j*                  |d      i z  }t        j                  d|fd|
|f      t        j                  |
      |dz  }dd|iz  }t#        t        j$                  |            dx}
x}x}x}x}}y) uJ   AI 퍼플 배경(hue 271, sat>0.5) 캔버스 100% → 10% 초과 → FAIL.zl4_purple.pngrS   r  r   r   r   r   r   r   r   r   Nr*  r+  r   )z%(py1)s > %(py4)sr   r	  r   u	   AI 퍼플r   z#%(py7)s
{%(py7)s = %(py5)s.reason
})r   r   z%(py10)spy10rl   r   )z%(py1)s in (%(py13)s))r   py13zassert %(py15)spy15)rY   r   r   r   r   r   r   r-  r   r   r   r   r   r   r   r   r   r   r   r   r!  _format_boolop)r   r   r   r   r   r   r   r   r   r   r   r   r   r   @py_assert6@py_assert9@py_format11@py_format12@py_format14@py_format16s                       r   "test_l4_color_token_ai_purple_failr>    s    /)HhDHl1CD
**UZZ)11%8
9C$S$/F>>3V3>V#333>V33333363336333>333V333V^^3333333>>+,3t3,t3333,t333,333t3333333/6==/=/=B/B/;////////6///6///=////=///B/////////;///;////////r   c                R   | dz  }t        |      }d|d   d   d<   t        ||d          t        |      }|j                  }d}||k(  }|st	        j
                  d|fd	||f      d
t        j                         v st	        j                  |      rt	        j                  |      nd
t	        j                  |      t	        j                  |      dz  }t	        j                  |j                        dz   d|iz  }t        t	        j                  |            dx}x}}d}	|j                  d   }|	|v }
|
slt	        j
                  d|
fd|	|f      t	        j                  |	      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}	x}
}y)u$   Pretendard + 정상 weight → PASS.zl5_pass.pngNoto Sans KRrS   rl   r?   r  r   r   r   r   r   r   r   Nr6   families_seenr   r1  r   r	  r   )rY   r   evaluate_l5_typographyr   r   r   r   r   r   r   r   r   r   r   r  s                r   "test_l5_typography_pretendard_passrC    s    -'HhD*8Dq,'8\0BC#D)F>>3V3>V#333>V33333363336333>333V333V^^3333333:6>>/::<:::::<::::<:::::::::::r   c                   | dz  }t        |      }d|d   d   d<   d|d   d   d<   t        ||d          t        |      }|j                  }d	}||k(  }|st	        j
                  d
|fd||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }t	        j                  |j                        dz   d|iz  }t        t	        j                  |            dx}x}}d |j                  d   D        }t        |      }|sddt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      dz  }	t        t	        j                  |	            dx}}y)u2   시스템 fallback(굴림체 등 banned) → FAIL.zl5_fail.pngu	   굴림체rS   r   r?   u	   바탕체rl   r  r   r   r   r   r   r   r   Nc              3  *   K   | ]  }d |d   v   yw)bannedr.   Nr   r_   s     r   rb   z:test_l5_typography_system_fallback_fail.<locals>.<genexpr>  s     Rx1V9$Rs   family_violationsr  r  r  )rY   r   rB  r   r   r   r   r   r   r   r   r   r   r   r  r#  s
             r   'test_l5_typography_system_fallback_failrH    s>    -'HhD*5Dq,'*5Dq,'8\0BC#D)F>>3V3>V#333>V33333363336333>333V333V^^3333333Rfnn=P.QRR3RRRRRRRRR3RRR3RRRRRRRRRRRRRRr   c                   | dz  }t        |       t        |      dt        t        t        dt
        t
        t
        t
        dddiddg d	d
ddgd}t        j                  t              5 }t        |       ddd       d}j                  }t        |      }||v }|s
t        j                  d|fd||f      t        j                  |      dt        j                         v st        j                   t              rt        j                  t              nddt        j                         v st        j                   |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }	t#        t        j$                  |	            dx}x}x}}y# 1 sw Y   =xY w)uA   필수 필드 누락 → SchemaValidationError → 진입 차단.zschema_fail.pngr   r   r!   r)   r&   Xr1   )r   r   r3   r  r5   r   )r:   r;   r<   r=   r>   )rK   rL   rN   rO   rP   rQ   rS   NrM   r   zK%(py1)s in %(py8)s
{%(py8)s = %(py3)s(%(py6)s
{%(py6)s = %(py4)s.value
})
}rT   excr   r   r   r   r   assert %(py10)sr4  )r   rT   rU   rV   rW   rX   pytestraisesSchemaValidationErrorevaluatevaluer   r   r   r   r   r   r   r   )
r   r   bad_metarL  r   r   @py_assert7r   r   r:  s
             r   &test_schema_invalid_input_blocks_entryrV    s0    ++H8$(m).$9#wRYZQ "+!
H$ 
,	- ,#)),c)n,?n,,,,?n,,,?,,,,,,c,,,c,,,,,,#,,,#,,,),,,n,,,,,,, s   ,F33F=c                    | dz  }t        |       t        |      }d|d<   t        j                  t              5  t        |       ddd       y# 1 sw Y   yxY w)u;   themePreset enum 위반(theme-A) → SchemaValidationError.zschema_preset.pngztheme-ArL   N)r   rY   rO  rP  rQ  rR  )r   r   rT  s      r   test_schema_invalid_preset_enumrX    sU     --H8$(#H'H]	,	-   s   AAc                   | dz  }t        |      }t        ||d          d|d<   t        j                  t              5 }t        |       ddd       d}j                  }t        |      }||v }|s
t        j                  d|fd||f      t        j                  |      d	t        j                         v st        j                  t              rt        j                  t              nd	d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}x}}|j                  }
t        |
      }t         |v }|sCt        j                  d|fdt         |f      dt        j                         v st        j                  t               rt        j                  t               ndd	t        j                         v st        j                  t              rt        j                  t              nd	d
t        j                         v st        j                  |      rt        j                  |      nd
t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}
}y# 1 sw Y   xY w)uL   mappingVersion이 SSOT_MAPPING_VERSION(v1.0)이 아니면 SSotMismatchError.zmv_fail.pngrS   r  zv9.9rN   Nr   rK  rT   rL  rM  rN  r4  )zK%(py0)s in %(py7)s
{%(py7)s = %(py2)s(%(py5)s
{%(py5)s = %(py3)s.value
})
}rU   )r   r   r   r   r   zassert %(py9)spy9)rY   r   rO  rP  SSotMismatchErrorrR  rS  rT   r   r   r   r   r   r   r   r   rU   )r   r   r   rL  r   r   rU  r   r   r:  r   r8  r   r   @py_format10s                  r   *test_mapping_version_mismatch_blocks_entryr]    s    -'HhD8\0BC#D		(	) S##S^#6^####6^###6######S###S###############^#######'*yy13y>1>1111>11111111111111131113111111s111s111y111>1111111 s   K11K;c                	   | dz  }t        |      }d|d   d   d<   t        j                  dt        t        fd      }t        j                  |      }t        d |d   D              }d	 |d
   D        \  }}}}	|j                  ||||z   ||	z   gd       |d   D ]  }
t        ||
d
   |
d           |j                  |       t        |      }t        |t              }|sddt        j                         v st!        j"                  t              rt!        j$                  t              nddt        j                         v st!        j"                  |      rt!        j$                  |      nddt        j                         v st!        j"                  t              rt!        j$                  t              ndt!        j$                  |      dz  }t'        t!        j(                  |            d}|j*                  }t-        |      }d}||k(  }|s
t!        j.                  d|fd||f      dt        j                         v st!        j"                  t,              rt!        j$                  t,              nddt        j                         v st!        j"                  |      rt!        j$                  |      ndt!        j$                  |      t!        j$                  |      t!        j$                  |      dz  }dd|iz  }t'        t!        j(                  |            dx}x}x}}|j0                  }ddh}||v }|st!        j.                  d|fd||f      dt        j                         v st!        j"                  |      rt!        j$                  |      ndt!        j$                  |      t!        j$                  |      dz  }t!        j2                  |j4                        d z   d!|iz  }t'        t!        j(                  |            dx}x}}|j6                  d"   }|t8        k(  }|st!        j.                  d|fd#|t8        f      t!        j$                  |      d$t        j                         v st!        j"                  t8              rt!        j$                  t8              nd$d%z  }d&d'|iz  }t'        t!        j(                  |            dx}}y)(u4   정상 LayoutMeta → evaluate() 종합 결과 PASS.ze2e_pass.pngr@  rS   rl   r?   r   )         c              3  2   K   | ]  }|d    dk(  s|  ywr   r   r   s     r   rb   z0test_evaluate_end_to_end_pass.<locals>.<genexpr>  r   r   c              3  2   K   | ]  }t        |        y wr\   r]   r_   s     r   rb   z0test_evaluate_end_to_end_pass.<locals>.<genexpr>   r   rc   r<   r   rm   r>   z5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancer   
EvalResult)r   r   r   r   Nr   r   )zK%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.items
})
} == %(py8)sr   )r   r   r   r   r   rN  r4  r   r   r   )z/%(py2)s
{%(py2)s = %(py0)s.overall
} in %(py5)sr   r   r   rN   )z%(py1)s == %(py3)srU   )r   r   zassert %(py5)sr   )rY   r   r   rV   rW   r   r   r   rq   r}   r   rR  rd  re  r   r   r   r   r   r   r   itemsr   r   overallr   fail_reasonslayout_meta_summaryrU   )r   r   r   r   rr   rH   rs   rt   ru   rv   r   r   r   r   r   r   rU  r8  r   r:  r   r   r   r   r   s                            r   test_evaluate_end_to_end_passrj    s    .(HhD*8Dq,'
))EHh/
AC>>#D
C$|,C
CC.#f+.JAq!QNNAq!a%Q'lN;, 5qy!F)45HHXd^Ffj)))))))):))):))))))f)))f))))))j)))j))))))))))||!3|!!!!!!!!!!!!3!!!3!!!!!!v!!!v!!!|!!!!!!!!!!!!!>>Bff-B>--BBB>-BBBBBB6BBB6BBB>BBB-BBBv/B/BBBBBBBB%%&67O7;OOOOO7;OOOO7OOOOOO;OOOO;OOOOOOOOr   )rK   r   returndict)rr   zImageDraw.ImageDrawr<   zlist[float]rj   rT   rk  None)r-   N)r   r   r   rT   rS   list[dict] | Nonerk  rm  )rJ   z#1A1A1AN)
r   r   r   rT   r   rT   rS   rn  rk  rm  r\   )r   r   rS   rn  rk  rm  )r   r   rk  rm  )>__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   importlib.utilr   r   pathlibr   numpyr   rO  PILr   r   __file__resolveparents
_REPO_ROOTr   r   _litere  rQ  r[  rU   rR  r   r  r  r-  rB  r   rV   rW   rX   rY   r}   r   r   r   r   r   r  r  r  r  r$  r.  r2  r>  rC  rH  rV  rX  r]  rj  r   r   r   <module>r~     s  
 #     
     
 (^##%--a0
)#e+.AA
	 	
33 ++ 11 >>11 -- 33 77 55 55  
,^

  
	2 $(
 " 
	$ $(	
  "	
 
.	"90!.HG*	22<3ND
4:&
0$
;
S$-8 
2$Pr   