
    jM4                    f   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ZddlmZ ddlmZ ddlZ ee      j%                         j&                  j&                  j&                  Zej*                  j-                  d ee             ddlZddlmZ ddlmZ ddlmZ dd	lmZ  dd
lm!Z" ddlm#Z$  G d d      Z% G d d      Z& G d d      Z' G d d      Z( G d d      Z) G d d      Z* G d d      Z+ G d d      Z, G d d      Z- G d d      Z. G d  d!      Z/ G d" d#      Z0 G d$ d%      Z1y)&u\  dev7 — Phase ε dispatch 모듈 분리 회귀 테스트 (task-2388).

dispatch.py 4336줄을 dispatch/ 패키지 6 모듈(facade) 로 분리한 결과를 검증한다.

12 단위 테스트 + 5 검증 시나리오:
  1-2. task_id: 4-layer fix 동작 + 동시성 race 0
  3-4. metadata: frontmatter 파싱 + legacy fallback
  5-6. prompt: build_prompt 동작 + 슬림 라인 수
  7-8. retry: status 가드 + archived/escalated 박제
  9-10. core: argparse 진입 + cancel 동작
  11. audit: ALLOWED_COMMANDS / facade 노출
  12. integration: 패키지 import + 외부 호환 동작 회귀 0

  S1. facade 6 모듈 import 모두 동작
  S2. dispatch.py 호환 shim 동작 (--help)
  S3. 외부 mock 호환 (subprocess, logger, WORKSPACE)
  S4. dispatch namespace 모든 함수 노출
  S5. 본체 변경 없음 (dispatch/__init__.py == 원본 dispatch.py)
    )annotationsN)Path)patch)audit)core)prompt)retry)task_id)_statec                      e Zd Zd Zd Zd Zy)TestTaskIdFacadec                	   d}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}d}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}d}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}d	}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}d
}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}y)uC   task_id facade가 task-2380 fix 함수 5개를 모두 노출한다.generate_task_id5assert %(py5)s
{%(py5)s = %(py0)s(%(py1)s, %(py3)s)
}hasattrdispatch_task_idpy0py1py3py5N_resolve_main_workspace_compute_next_id_from_timers_sync_counter_if_neededget_dispatch_time)	r   r   @py_builtinslocals
@pytest_ar_should_repr_global_name	_safereprAssertionError_format_explanationself@py_assert2@py_assert4@py_format6s       T/home/jay/workspace/.worktrees/task-2644-dev1/tests/dev7/test_dispatch_modularize.py'test_facade_exports_task_2380_functionsz8TestTaskIdFacade.test_facade_exports_task_2380_functions0   sx   );<w');<<<<<<<<w<<<w<<<<<<'<<<'<<<);<<<<<<<<<<)BCw')BCCCCCCCCwCCCwCCCCCC'CCC'CCC)BCCCCCCCCCC)GHw')GHHHHHHHHwHHHwHHHHHH'HHH'HHH)GHHHHHHHHHH)BCw')BCCCCCCCCwCCCwCCCCCC'CCC'CCC)BCCCCCCCCCC)<=w')<========w===w======'==='===)<==========    c                   t         j                  }t        j                  }||u }|st        j                  d|fd||f      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}t         j                  }t        j                  }||u }|st        j                  d|fd	||f      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)
uB   facade의 함수가 dispatch namespace의 함수와 동일 객체.is)z^%(py2)s
{%(py2)s = %(py0)s.generate_task_id
} is %(py6)s
{%(py6)s = %(py4)s.generate_task_id
}r   dispatchr   py2py4py6assert %(py8)spy8N)zl%(py2)s
{%(py2)s = %(py0)s._resolve_main_workspace
} is %(py6)s
{%(py6)s = %(py4)s._resolve_main_workspace
})r   r   r.   r   _call_reprcomparer   r   r   r    r!   r"   r   r$   @py_assert1@py_assert5@py_assert3@py_format7@py_format9s         r(   "test_facade_identity_with_dispatchz3TestTaskIdFacade.test_facade_identity_with_dispatch8   s:   00MH4M4MM04MMMMM04MMMMMMMMMMMMM0MMMMMMHMMMHMMM4MMMMMMMM77[8;[;[[7;[[[[[7;[[[[[[[[[[[[[7[[[[[[8[[[8[[[;[[[[[[[[r*   c           	        |dz  }|j                  t        j                  dddiddiddidi             t        j                  |      }d}||k(  }|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z   d|iz  }t        t        j                  |            dx}}y)u/   task-2380: 4자리 정수 외 변종 ID 무시.task-timers.jsontasksstatusdone)z	task-2386ztask-9.1z
task-200.1iS	  ==)z%(py0)s == %(py3)sresultr   r   zExpected 2387, got 
>assert %(py5)sr   N)
write_textjsondumpsr   r   r   r5   r   r   r   r    _format_assertmsgr!   r"   )r$   tmp_path
timer_filerD   r%   r7   @py_format4r'   s           r(   (test_compute_next_id_filters_variant_idsz9TestTaskIdFacade.test_compute_next_id_filters_variant_ids=   s     22
djj&/%v.'0*
  	 ">>zJ=v~===v======v===v======!4VH=======r*   N)__name__
__module____qualname__r)   r<   rN    r*   r(   r   r   /   s    >\
>r*   r   c                      e Zd Zd Zy)TestTaskIdConcurrencyc                   ddl }|j                  t        j                        }d}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd	|iz  }t        t	        j                  |            dx}}d
}||v }|st	        j
                  d|fd||f      t	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      nddz  }dd	|iz  }t        t	        j                  |            dx}}y)u8   generate_task_id의 코드에 fcntl.flock 호출 보존.r   Nzfcntl.flockinz%(py1)s in %(py3)ssrcr   r   assert %(py5)sr   LOCK_EX)inspect	getsourcer.   r   r   r5   r    r   r   r   r!   r"   )r$   r]   rY   @py_assert0r%   rM   r'   s          r(    test_generate_task_id_uses_flockz6TestTaskIdConcurrency.test_generate_task_id_uses_flockO   s     9 9:#}####}###}################yCyCyCCr*   N)rO   rP   rQ   r`   rR   r*   r(   rT   rT   N   s     r*   rT   c                      e Zd Zd Zd Zy)TestMetadataIntegrationc                   d}t        j                  |      }d}||u}|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}d	}||v }|st        j                  d
|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}d}|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-   allowed_resources YAML 파싱 (audit 영역).zx## allowed_resources

```yaml
allowed_resources:
  paths:
    - "src/**"
  commands:
    - "pytest"
  ttl_hours: 24
```
N)is not)z%(py0)s is not %(py3)srD   rE   r[   r   pathsrV   rX   rZ   zsrc/**)z%(py1)s in %(py4)sr   r1   assert %(py6)sr2   
r.   _parse_allowed_resourcesr   r5   r   r   r   r    r!   r"   )r$   	task_descrD   r%   r7   rM   r'   r_   r9   @py_format5r:   s              r(   !test_parse_allowed_resources_yamlz9TestMetadataIntegration.test_parse_allowed_resources_yaml[   s   
	 229=!!vT!!!!vT!!!!!!v!!!v!!!T!!!!!!! w&    w&   w      &   &       *6'?*x?****x?***x***?*******r*   c                x   t        j                  d      }d}||u }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}y)	u%   yaml 블록이 없으면 None 반환.zplain text without yamlNr,   z%(py0)s is %(py3)srD   rE   r[   r   rh   )r$   rD   r%   r7   rM   r'   s         r(   2test_parse_allowed_resources_no_block_returns_nonezJTestMetadataIntegration.test_parse_allowed_resources_no_block_returns_nonem   sk    223LMv~vvvr*   N)rO   rP   rQ   rl   ro   rR   r*   r(   rb   rb   Z   s    +$r*   rb   c                      e Zd Zd Zd Zy)TestPromptFacadec                D   d}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}t        j                  }t        j                  }||u }|st	        j                  d|fd||f      dt        j                         v st	        j
                  t              rt	        j                  t              ndt	        j                  |      d	t        j                         v st	        j
                  t              rt	        j                  t              nd	t	        j                  |      d
z  }dd|iz  }t        t	        j                  |            dx}x}}y)u.   prompt facade가 build_prompt를 노출한다.build_promptr   r   dispatch_promptr   Nr,   )zV%(py2)s
{%(py2)s = %(py0)s.build_prompt
} is %(py6)s
{%(py6)s = %(py4)s.build_prompt
}r.   r/   r3   r4   )r   rt   r   r   r   r   r    r!   r"   rs   r.   r5   	r$   r%   r&   r'   r7   r8   r9   r:   r;   s	            r(    test_facade_exports_build_promptz1TestPromptFacade.test_facade_exports_build_promptw   s   (67w77777777w777w7777777777777777777777++Dx/D/DD+/DDDDD+/DDDDDDDDDDDDD+DDDDDDxDDDxDDD/DDDDDDDDr*   c                    t        j                  t              5  t        j                  ddd       ddd       y# 1 sw Y   yxY w)uD   unknown team_id에 대해 sys.exit 호출 (task-2386 정상 동작).zinvalid-teamtestztask-1)team_idrj   r
   N)pytestraises
SystemExitr.   rs   )r$   s    r(   $test_build_prompt_unknown_team_exitsz5TestPromptFacade.test_build_prompt_unknown_team_exits|   s:    ]]:& 	!!&  	 	 	s	   <AN)rO   rP   rQ   rv   r}   rR   r*   r(   rq   rq   v   s    E
r*   rq   c                      e Zd Zd Zd Zd Zy)TestRetryFacadec                D   d}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}t        j                  }t        j                  }||u }|st	        j                  d|fd||f      dt        j                         v st	        j
                  t              rt	        j                  t              ndt	        j                  |      d	t        j                         v st	        j
                  t              rt	        j                  t              nd	t	        j                  |      d
z  }dd|iz  }t        t	        j                  |            dx}x}}y)u1   retry facade가 _set_task_status를 노출한다._set_task_statusr   r   dispatch_retryr   Nr,   )z^%(py2)s
{%(py2)s = %(py0)s._set_task_status
} is %(py6)s
{%(py6)s = %(py4)s._set_task_status
}r.   r/   r3   r4   )r   r   r   r   r   r   r    r!   r"   r   r.   r5   ru   s	            r(   #test_facade_exports_set_task_statusz3TestRetryFacade.test_facade_exports_set_task_status   s   '9:w~'9::::::::w:::w::::::~:::~:::'9::::::::::..K(2K2KK.2KKKKK.2KKKKKKK~KKK~KKK.KKKKKK(KKK(KKK2KKKKKKKKr*   c                   |dz  }|j                   j                  dd       |dz  j                  dd       |dz  dz  }|j                  t        j                  ddddiii             |j                  t        d	|       t        j                  dd
      }d}||u }|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z   d|iz  }	t        t        j                   |	            dx}}y)u:   task-2387: archived 상태는 영구 박제. False 반환.r>   Tparentsexist_okmemoryr?   ztask-archivedr@   archived	WORKSPACErunningFr,   rn   rD   rE   u(   archived는 변경 차단 (False) 반환rF   r   N)parentmkdirrG   rH   rI   setattrr.   r   r   r5   r   r   r   r    rJ   r!   r"   )
r$   rK   monkeypatchrL   actual_timerrD   r%   r7   rM   r'   s
             r(   $test_set_task_status_blocks_archivedz4TestRetryFacade.test_set_task_status_blocks_archived   s    22
t<	H	##D4#@(*-??

o*'=>,
 ! 	 	Hk8<**?IFJvJJJvJJJJJJvJJJvJJJJJJ JJJJJJJr*   c                8   |dz  j                  dd       |dz  dz  }|j                  t        j                  ddddiii             |j	                  t
        d	|       t        j                  dd
      }d}||u }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}y)u-   task-2387: escalated 상태도 영구 박제.r   Tr   r>   r?   ztask-escr@   	escalatedr   r   Fr,   rn   rD   rE   r[   r   N)r   rG   rH   rI   r   r.   r   r   r5   r   r   r   r    r!   r"   )	r$   rK   r   r   rD   r%   r7   rM   r'   s	            r(   %test_set_task_status_blocks_escalatedz5TestRetryFacade.test_set_task_status_blocks_escalated   s    	H	##D4#@(*-??

j8["9:,
 ! 	 	Hk8<**:yAvvvvr*   N)rO   rP   rQ   r   r   r   rR   r*   r(   r   r      s    L
K
r*   r   c                      e Zd Zd Zd Zd Zy)TestCoreFacadec                   d}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}d}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}d}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}t        j                  }t        j                  }||u }|st	        j                  d	|fd
||f      dt        j                         v st	        j
                  t              rt	        j                  t              ndt	        j                  |      dt        j                         v st	        j
                  t              rt	        j                  t              ndt	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}y)u4   core facade가 main / dispatch / cancel_task 노출.mainr   r   dispatch_corer   Nr.   cancel_taskr,   )zF%(py2)s
{%(py2)s = %(py0)s.main
} is %(py6)s
{%(py6)s = %(py4)s.main
}r/   r3   r4   )r   r   r   r   r   r   r    r!   r"   r   r.   r5   ru   s	            r(   (test_facade_exports_main_dispatch_cancelz7TestCoreFacade.test_facade_exports_main_dispatch_cancel   s   &,-w}f--------w---w------}---}---f----------&01w}j11111111w111w111111}111}111j1111111111&34w}m44444444w444w444444}444}444m4444444444!!2X]]2!]2222!]222222}222}222!222222X222X222]2222222r*   c                   t        j                  t        j                  t	        t
        dz        dgddd      }|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  }dd|iz  }t        t        j                  |            dx}x}}d}|j                  }||v }|st        j                  d|fd||f      t        j                  |      d	t        j                         v st        j                  |      rt        j                  |      nd	t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)uC   dispatch.py shim이 --help 정상 출력 (script 진입점 동작).dispatch.pyz--helpT   )capture_outputtexttimeoutr   rB   )z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)srD   )r   r0   r   assert %(py7)spy7Nu   작업 위임 디스패처rV   )z.%(py1)s in %(py5)s
{%(py5)s = %(py3)s.stdout
}r   r   r   )
subprocessrunsys
executablestr
_WORKSPACE
returncoder   r5   r   r   r   r    r!   r"   stdout)	r$   rD   r7   r&   r9   r'   @py_format8r_   r%   s	            r(   test_dispatch_py_shim_helpz)TestCoreFacade.test_dispatch_py_shim_help   s   ^^Sm!;<hG	
   %A% A%%%% A%%%%%%v%%%v%%% %%%A%%%%%%%+<v}}<+}<<<<+}<<<+<<<<<<v<<<v<<<}<<<<<<<r*   c                .   t        j                  d      }|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:   cancel_task가 잘못된 ID에 대해 error status 반환.z	not-validr@   errorrB   )z%(py1)s == %(py4)srf   rg   r2   N)r.   r   r   r5   r    r!   r"   )r$   rD   r_   r9   r%   rk   r:   s          r(   )test_cancel_task_invalid_id_returns_errorz8TestCoreFacade.test_cancel_task_invalid_id_returns_error   sd    %%k2h*7*7****7******7*******r*   N)rO   rP   rQ   r   r   r   rR   r*   r(   r   r      s    3	=+r*   r   c                      e Zd Zd Zd Zy)TestAuditFacadec                   d}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}d}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}d}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}d	}t        t        |      }|sd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t	        j                  |      t	        j                  |      dz  }t        t	        j                  |            dx}}y)
u8   audit facade가 ALLOWED_COMMANDS + 핵심 함수 노출.ALLOWED_COMMANDSr   r   dispatch_auditr   N_save_capability_snapshot_check_affected_files_overlap_validate_composite_teams)	r   r   r   r   r   r   r    r!   r"   r#   s       r(   +test_facade_exports_constants_and_functionsz;TestAuditFacade.test_facade_exports_constants_and_functions   s   '9:w~'9::::::::w:::w::::::~:::~:::'9::::::::::'BCw~'BCCCCCCCCwCCCwCCCCCC~CCC~CCC'BCCCCCCCCCC'FGw~'FGGGGGGGGwGGGwGGGGGG~GGG~GGG'FGGGGGGGGGG'BCw~'BCCCCCCCCwCCCwCCCCCC~CCC~CCC'BCCCCCCCCCCr*   c                X   t         j                  }t        j                  }||u }|st        j                  d|fd||f      dt        j                         v st        j                  t               rt        j                  t               ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)	u8   ALLOWED_COMMANDS가 dispatch namespace와 동일 객체.r,   )z^%(py2)s
{%(py2)s = %(py0)s.ALLOWED_COMMANDS
} is %(py6)s
{%(py6)s = %(py4)s.ALLOWED_COMMANDS
}r   r.   r/   r3   r4   N)r   r   r.   r   r5   r   r   r   r    r!   r"   r6   s         r(   test_audit_constants_identityz-TestAuditFacade.test_audit_constants_identity   s    ..K(2K2KK.2KKKKK.2KKKKKKK~KKK~KKK.KKKKKK(KKK(KKK2KKKKKKKKr*   N)rO   rP   rQ   r   r   rR   r*   r(   r   r      s    DLr*   r   c                      e Zd Zd Zd Zy)TestIntegrationRegressionc                   dD ]=  }t        t        |      }|s%t        j                  d| d      dz   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                  |      dz  }t        t        j                  |            d	}@ y	)
uI   dispatch namespace가 분리된 영역의 모든 핵심 함수를 노출.)r   r   r   r   _patch_timer_metadatars   _resolve_resume_inject_project_map_contextr   r   _is_insuro_server_change_inject_platform_rules_auto_inject_affected_filesr   r.   r   r   z	dispatch.u    누락z7
>assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}r   r.   name)r   r   r0   r1   N)
r   r.   r   rJ   r   r   r   r    r!   r"   )r$   r   r9   rk   s       r(   #test_dispatch_namespace_exports_allz=TestIntegrationRegression.test_dispatch_namespace_exports_all   s    
 	FD 8T*E*EEivW,EEEEEEE7EEE7EEEEEE8EEE8EEEEEETEEETEEE*EEEEEE	Fr*   c                   ddl m}  |       }d|_        t        d|      5  t	        j
                  dd      }ddd       d	}|v }|st        j                  d
|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}y# 1 sw Y   xY w)uT   외부 테스트 호환: patch('dispatch.subprocess.run')이 audit 함수에 영향.r   )	MagicMockzsrc/foo.py
src/bar.py
zdispatch.subprocess.run)return_valueu#   테스트 `Sample` 클래스 수정z
/workspaceNz!## affected_files (auto-detected)rV   rX   rD   rZ   r[   r   )unittest.mockr   r   r   r.   r   r   r5   r    r   r   r   r!   r"   )	r$   rK   r   mock_resultrD   r_   r%   rM   r'   s	            r(   )test_external_test_compat_subprocess_mockzCTestIntegrationRegression.test_external_test_compat_subprocess_mock   s    +k7,;G 	995|F	 3<2f<<<<2f<<<2<<<<<<f<<<f<<<<<<<		 	s   C''C0N)rO   rP   rQ   r   r   rR   r*   r(   r   r      s    F$
=r*   r   c                      e Zd Zd Zy)TestScenarioS1FacadeImportsc                $    ddl m}m}m}m}m}m} y)u%   6 모듈 facade 모두 import 가능.r   )r   r   r   r   r	   r
   N)r.   r   r   r   r   r	   r
   )r$   r   r   r   r   r	   r
   s          r(   test_all_six_facades_importablez;TestScenarioS1FacadeImports.test_all_six_facades_importable   s    HHHr*   N)rO   rP   rQ   r   rR   r*   r(   r   r      s    Ir*   r   c                      e Zd Zd Zy)TestScenarioS2ShimCompatc                   t         dz  j                         }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)u5   dispatch.py shim이 dispatch.core.main으로 routing.r   zfrom dispatch.core import mainrV   rX   	shim_textrZ   r[   r   Nzif __name__ == "__main__")
r   	read_textr   r5   r    r   r   r   r!   r"   )r$   r   r_   r%   rM   r'   s         r(   test_shim_routes_to_mainz1TestScenarioS2ShimCompat.test_shim_routes_to_main  s    -/::<	/</9<<<</9<<</<<<<<<9<<<9<<<<<<<*7*i7777*i777*777777i777i7777777r*   N)rO   rP   rQ   r   rR   r*   r(   r   r     s    8r*   r   c                      e Zd Zd Zy)TestScenarioS3MockCompatc                   ddl }d}t        j                  }||v }|st        j                  d|fd||f      t        j
                  |      dt        j                         v st        j                  t              rt        j
                  t              ndt        j
                  |      dz  }dd	|iz  }t        t        j                  |            dx}x}}y)
uH   patch('dispatch.logger') 적용 시 dispatch namespace 함수에 반영.r   NloggerrV   )z0%(py1)s in %(py5)s
{%(py5)s = %(py3)s.__dict__
}r.   r   r   r   )r]   r.   __dict__r   r5   r    r   r   r   r!   r"   )r$   r]   r_   r&   r%   r'   r   s          r(   $test_mock_dispatch_logger_propagatesz=TestScenarioS3MockCompat.test_mock_dispatch_logger_propagates  sw    ,8,,,x,,,,,x,,,,x,,,,,,8,,,8,,,,,,,,,,,r*   N)rO   rP   rQ   r   rR   r*   r(   r   r     s    -r*   r   c                      e Zd Zd Zy)TestScenarioS4NamespaceParityc           
        t        t              D cg c]/  }|j                  d      st        t	        t        |d            r|1 }}t        |      }d}||k\  }|st        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  }d	d
|iz  }t        t        j                  |            dx}x}}yc c}w )u=   분리 후 dispatch namespace에 핵심 함수 30+개 노출._N   )>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)slenpublic_funcs)r   r   r   r2   r3   r4   )dirr.   
startswithcallablegetattrr   r   r5   r   r   r   r    r!   r"   )r$   nr   r%   r8   r&   r:   r;   s           r(   (test_dispatch_has_minimum_function_countzFTestScenarioS4NamespaceParity.test_dispatch_has_minimum_function_count  s     8}
<<$'(At2L)M 
 

 < %A% A%%%% A%%%%%%s%%%s%%%%%%<%%%<%%% %%%A%%%%%%%
s   4EN)rO   rP   rQ   r   rR   r*   r(   r   r     s    &r*   r   c                      e Zd Zd Zy)TestScenarioS5BodyUnchangedc                   t         dz  dz  j                         j                  d      }d}||k  }d}||k  }|r|st        j                  d||fd|||f      t        j
                  |      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}x}x}}y)uO   dispatch/__init__.py가 원본 dispatch.py 4336줄과 동일 라인 수 (±10).r.   z__init__.py
i  i  )<=r   )z%(py1)s <= %(py4)sz%(py4)s <= %(py6)s
init_lines)r   r1   r2   u   init.py 라인 수 u    (예상 ~4336)z
>assert %(py8)sr4   N)r   r   countr   r5   r    r   r   r   rJ   r!   r"   )r$   r   r_   r%   r8   r9   r:   r;   s           r(    test_init_py_size_matches_legacyz<TestScenarioS5BodyUnchanged.test_init_py_size_matches_legacy*  s     :-=HHJPPQUV
\tz)\T\zT)\\\\tzT\\\t\\\\\\z\\\z\\\T\\\-@O+\\\\\\\\r*   N)rO   rP   rQ   r   rR   r*   r(   r   r   )  s    ]r*   r   )2__doc__
__future__r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   rH   r   r   pathlibr   r   r   rz   __file__resolver   r   pathinsertr   r.   r   r   r   r   r   rt   r	   r   r
   r   r   dispatch_stater   rT   rb   rq   r   r   r   r   r   r   r   r   r   rR   r*   r(   <module>r      s   ( #     
    (^##%,,33::
 3z? #  , * . , 0 -> >>    8 & H+ +8
L 
L = =FI I8 8- -& &] ]r*   