
    i3V                        d Z ddlZddlZddlZddlmZ ddlmZmZ ddl	Z	 ee
      j                  j                  Zej                  j                  d ee             ddlmZmZmZmZmZmZmZ ddlmZmZ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#y)u/  
test_dispatch_gate.py

보리스 게이트 시스템 Phase 1 단위 테스트 (아르고스 작성, task-1838)

테스트 항목:
1. gate_instructions 동작 (GATE_INSTRUCTIONS 딕셔너리, get_gate_instructions, format_for_prompt)
2. affected_files 파싱 (_parse_affected_files)
3. affected_files 겹침 감지 (_check_affected_files_overlap)
4. Lv.2+ affected_files 미기재 경고 (_warn_missing_affected_files)
5. batch_id 완료 추적 (check_batch_completion)
6. 레벨 자동 추정 (_estimate_task_level)
7. task 레벨 파싱 (_parse_task_level)
    N)Path)	MagicMockpatch)_check_affected_files_overlap_estimate_task_level_get_ast_blast_radius_parse_affected_files_parse_task_level_warn_missing_affected_filescheck_batch_completion)GATE_INSTRUCTIONSformat_for_promptget_gate_instructionsc                   *    e Zd Zd Zd Zd Zd Zd Zy)TestGateInstructionsc                     t        d      D ]7  }|t        v sJ d| d       t        |   }dD ]  }||v rJ d| d| d        9 y)uT   모든 레벨(0-4) 딕셔너리가 존재하고 g1/g2/g3 키를 포함해야 한다.   u   레벨 u   이 GATE_INSTRUCTIONS에 없음)g1g2g3u   에 'u   ' 키 없음N)ranger   )selflevelgateskeys       I/home/jay/workspace/.worktrees/task-2116-dev1/tests/test_dispatch_gate.py$test_gate_instructions_levels_0_to_4z9TestGateInstructions.test_gate_instructions_levels_0_to_42   sp    1X 	ME--_?^/__-%e,E) Me|LwugU3%|%LL|M	M    c                 @    t        d      }|t        d   k(  sJ d       y)uX   존재하지 않는 레벨(999) 요청 시 레벨 0 딕셔너리로 폴백해야 한다.i  r   u4   unknown 레벨은 레벨 0으로 폴백되어야 함N)r   r   r   results     r   -test_gate_instructions_unknown_level_fallbackzBTestGateInstructions.test_gate_instructions_unknown_level_fallback:   s&    &s+*1--e/ee-r   c                 \    t        d      }d|vsJ d       d|v sJ d       d|v sJ d       y)	uH   Lv.0 → G1은 비어있어 스킵, G2/G3만 포함된 문자열 반환.r      [G1 설계 게이트]u%   Lv.0에서 G1은 포함되면 안 됨   [G2 구현 게이트]u$   Lv.0에서 G2가 포함되어야 함   [G3 머지 게이트]u$   Lv.0에서 G3가 포함되어야 함Nr   r    s     r   test_format_for_prompt_level_0z3TestGateInstructions.test_format_for_prompt_level_0?   sH    "1%&f4]6]]4&&0X2XX0&&0X2XX0r   c                 r    t        d      }d|v sJ d       d|v sJ d       d|v sJ d       d|v sJ d	       y
)uU   Lv.2 → G1/G2/G3 모두 포함되고 'affected_files' 텍스트가 있어야 한다.   r$   u$   Lv.2에서 G1이 포함되어야 함r%   u$   Lv.2에서 G2가 포함되어야 함r&   u$   Lv.2에서 G3가 포함되어야 함affected_filesu?   Lv.2 G1에는 'affected_files' 텍스트가 포함되어야 함Nr'   r    s     r   test_format_for_prompt_level_2z3TestGateInstructions.test_format_for_prompt_level_2F   s\    "1%&&0X2XX0&&0X2XX0&&0X2XX06)l+ll)r   c                 0    t        d      }d|v sJ d       y)uC   Lv.4 → 'Graduated Auto-Gate' 텍스트가 포함되어야 한다.   zGraduated Auto-GateuD   Lv.4 G3에는 'Graduated Auto-Gate' 텍스트가 포함되어야 함Nr'   r    s     r   test_format_for_prompt_level_4z3TestGateInstructions.test_format_for_prompt_level_4N   s     "1%$.v0vv.r   N)__name__
__module____qualname__r   r"   r(   r,   r/    r   r   r   r   1   s     Mf
Ymwr   r   c                   N    e 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y)TestParseAffectedFilesc                 @    d}t        |      }|ddgk(  s
J d|        y)uG   'affected_files: server.py, app.js' → ['server.py', 'app.js'] 파싱.z!affected_files: server.py, app.js	server.pyapp.jsu   파싱 결과 불일치: Nr	   r   	task_descr!   s      r   test_parse_affected_files_basicz6TestParseAffectedFiles.test_parse_affected_files_basicZ   s1    7	&y1+x00V4MfX2VV0r   c                 >    d}t        |      }|g k(  sJ d| d       y)uH   affected_files 라인이 없으면 빈 리스트를 반환해야 한다.uS   이 작업은 affected_files 라인이 없습니다.
단순 수정 작업입니다.u!   빈 리스트를 기대했으나 u    반환Nr9   r:   s      r   test_parse_affected_files_emptyz6TestParseAffectedFiles.test_parse_affected_files_empty`   s,    j	&y1|P@PP|r   c                 @    d}t        |      }|g dk(  s
J d|        y)uI   파일명 사이의 공백이 올바르게 처리(strip)되어야 한다.z4affected_files:  server.py ,   app.js  ,  utils.py  )r7   r8   utils.pyu   공백 처리 실패: Nr9   r:   s      r   %test_parse_affected_files_with_spacesz<TestParseAffectedFiles.test_parse_affected_files_with_spacesf   s/    J	&y1<<_@VW]V^>__<r   c                 @    d}t        |      }|ddgk(  s
J d|        y)uU   여러 줄 task_desc에서 affected_files 라인만 정확히 파싱되어야 한다.u   # task-100: 다중 파일 수정
레벨: Lv.2
affected_files: dispatch.py, config/loader.py

## 작업 내용
dispatch.py를 리팩토링합니다.
dispatch.pyzconfig/loader.pyu   다중 라인 파싱 실패: Nr9   r:   s      r   #test_parse_affected_files_multilinez:TestParseAffectedFiles.test_parse_affected_files_multilinel   s;    6 	 'y1-);<<f@]^d]e>ff<r   c                 @    d}t        |      }|ddgk(  s
J d|        y)ug   ## affected_files 섹션 형식 파싱 — 하이픈 목록을 파일 리스트로 반환해야 한다.z>## affected_files
- dispatch.py
- tests/test_dispatch_gate.py
rC   ztests/test_dispatch_gate.pyu   섹션 형식 파싱 실패: Nr9   r:   s      r   (test_parse_affected_files_section_formatz?TestParseAffectedFiles.test_parse_affected_files_section_formaty   s;    . 	
 'y1-)FGGqKhiohpIqqGr   c                 @    d}t        |      }|g dk(  s
J d|        y)u`   실제 task 파일과 유사한 전체 구조에서 섹션 형식 파싱이 동작해야 한다.u   # Task 수정 작업
## 배경
기존 파서에 버그 있음

## affected_files
- src/main.py
- src/utils/helper.py
- tests/test_main.py

## 작업 내용
파서를 수정합니다.
)zsrc/main.pyzsrc/utils/helper.pyztests/test_main.pyu$   전체 구조 섹션 파싱 실패: Nr9   r:   s      r   5test_parse_affected_files_section_format_with_contextzLTestParseAffectedFiles.test_parse_affected_files_section_format_with_context   sH    
+ 	 'y1UU  	GY}  E  ~F  XG  	GUr   c                 @    d}t        |      }|ddgk(  s
J d|        y)uX   ## affected_files 섹션은 다음 ## 헤더에서 목록 수집을 중단해야 한다.u   ## affected_files
- alpha.py
- beta.py

## 다른 섹션
이 내용은 파일 목록이 아닙니다
- 이것도 파일이 아님
zalpha.pyzbeta.pyu#   다음 헤더에서 종료 실패: Nr9   r:   s      r   7test_parse_affected_files_section_stops_at_next_headingzNTestParseAffectedFiles.test_parse_affected_files_section_stops_at_next_heading   s:    - 	 'y1*i00`4WX^W_2``0r   c                 @    d}t        |      }|ddgk(  s
J d|        y)uj   기존 인라인 형식(affected_files: ...)은 섹션 형식 추가 후에도 계속 동작해야 한다.z&affected_files: server.py, config.yamlr7   zconfig.yamlu'   인라인 형식 하위 호환 실패: Nr9   r:   s      r   ,test_parse_affected_files_inline_still_workszCTestParseAffectedFiles.test_parse_affected_files_inline_still_works   s3    <	&y1+}55i9`ag`h7ii5r   c                 <    d}t        |      }|g k(  s
J d|        y)um   ## affected_files 섹션 헤더만 있고 하이픈 목록이 없으면 빈 리스트를 반환해야 한다.u+   ## affected_files

## 작업 내용
없음
u1   빈 섹션은 빈 리스트를 반환해야 함: Nr9   r:   s      r   ,test_parse_affected_files_section_empty_listzCTestParseAffectedFiles.test_parse_affected_files_section_empty_list   s3     	 'y1|YPQWPXYY|r   c                 @    d}t        |      }|g dk(  s
J d|        y)uV   ## affected_files 헤더 아래 쉼표 구분 인라인 값도 파싱되어야 한다.uv   ## affected_files
dashboard/wiki_engine.py, dashboard/routes_post.py, dashboard/routes_get.py

## 검증 시나리오
)dashboard/wiki_engine.pyzdashboard/routes_post.pyzdashboard/routes_get.pyu'   섹션 인라인 쉼표 파싱 실패: Nr9   r:   s      r   .test_parse_affected_files_section_inline_commazETestParseAffectedFiles.test_parse_affected_files_section_inline_comma   s@    ' 	 'y1 
 
 	> 5VH=		> 
r   c                 >    d}t        |      }|dgk(  s
J d|        y)uU   ## affected_files 아래 괄호 코멘트(예: '(신규)')가 제거되어야 한다.u?   ## affected_files
dashboard/wiki_engine.py (신규)

## 다음
rP   u    괄호 코멘트 제거 실패: Nr9   r:   s      r   5test_parse_affected_files_section_inline_with_commentzLTestParseAffectedFiles.test_parse_affected_files_section_inline_with_comment   s9     	 'y1455b9YZ`Ya7bb5r   N)r0   r1   r2   r<   r>   rA   rD   rF   rH   rJ   rL   rN   rQ   rS   r3   r   r   r5   r5   Y   sC    WQ`grG$aj	Z>	cr   r5   c                   8    e Zd ZdededefdZd Zd Zd Zd Z	y	)
TestCheckAffectedFilesOverlaptmp_pathtasksreturnc                     |dz  }|j                  dd       |dz  }|j                  t        j                  d|idd      d	
       |S uS   task-timers.json을 tmp_path/memory/ 하위에 생성하고 경로를 반환한다.memoryT)parentsexist_okztask-timers.jsonrW   Fr*   )ensure_asciiindentzutf-8)encodingmkdir
write_textjsondumpsr   rV   rW   
memory_dir
timer_files        r   _make_timer_filez.TestCheckAffectedFilesOverlap._make_timer_file   ]    (
5"44
JJ'eAF 	 	
 r   c                 j    ddl }|j                  |d|       t        dgd      }|g k(  s
J d|        y)u8   task-timers.json이 없을 때 → 빈 리스트 반환.r   N	WORKSPACEr7   ztask-999u>   타이머 파일 없을 때 빈 리스트를 기대했으나: )dispatchsetattrr   )r   rV   monkeypatchrm   r!   s        r    test_check_overlap_no_timer_filez>TestCheckAffectedFilesOverlap.test_check_overlap_no_timer_file   s@    Hk8<.}jI|f]^d]eff|r   c                     ddl }dddddgdi}| j                  ||       |j                  |d	|       t        dgd
      }t	        |      dkD  sJ d       t        d |D              s
J d|        y)ua   다른 running task가 같은 파일을 수정 중이면 경고 메시지를 반환해야 한다.r   Ntask-100running	dev2-teamr7   r@   statusteam_idr+   rl   task-200u   겹침이 감지되어야 함c              3   $   K   | ]  }d |v  
 yw)r7   Nr3   ).0ws     r   	<genexpr>zLTestCheckAffectedFilesOverlap.test_check_overlap_detected.<locals>.<genexpr>   s     4;!#4s   u0   server.py 겹침 경고가 포함되어야 함: )rm   ri   rn   r   lenanyr   rV   ro   rm   rW   r!   s         r   test_check_overlap_detectedz9TestCheckAffectedFilesOverlap.test_check_overlap_detected   s     #&#.
";
 	h.Hk8<.}jI6{Q? ??4V44q8hiohp6qq4r   c                     ddl }dddddgdi}| j                  ||       |j                  |d	|       t        d
dgd      }|g k(  s
J d|        y)uK   affected_files가 겹치지 않으면 빈 리스트를 반환해야 한다.r   Nrr   rs   rt   zother_module.pyr@   ru   rl   r7   r8   rx   u3   겹침이 없어야 하는데 경고가 반환됨: rm   ri   rn   r   r   s         r   test_check_overlap_no_conflictz<TestCheckAffectedFilesOverlap.test_check_overlap_no_conflict   st     #&#4j"A
 	h.Hk8<.X/F
S|[RSYRZ[[|r   c                     ddl }ddddgdi}| j                  ||       |j                  |d|       t        dgd      }|g k(  s
J d	|        y)
uT   현재 task_id와 동일한 엔트리는 겹침 감지에서 제외되어야 한다.r   Nrx   rs   z	dev1-teamr7   ru   rl   u3   자기 자신은 겹침에서 제외되어야 함: r   r   s         r    test_check_overlap_self_excludedz>TestCheckAffectedFilesOverlap.test_check_overlap_self_excluded  sp     #&#.-
 	h.Hk8< /}jI|[RSYRZ[[|r   N)
r0   r1   r2   r   dictri   rp   r   r   r   r3   r   r   rU   rU      s4    	 	d 	t 	gr$\"\r   rU   c                       e Zd Zd Zd Zd Zy)TestWarnMissingAffectedFilesc                 b    d}t        |d      }|J d       t        |t              sJ d       y)u<   Lv.2 + affected_files 미기재 → 경고 문자열 반환.uL   # task-100: 수정
레벨: Lv.2
작업 내용: 무언가를 수정합니다.r*   
task_levelNu2   Lv.2 + 미기재 시 경고가 반환되어야 함u    경고는 문자열이어야 함)r   
isinstancestrr:   s      r   $test_warn_missing_af_level2_no_fileszATestWarnMissingAffectedFiles.test_warn_missing_af_level2_no_files$  s;    d	-iAF!W#WW!&#&J(JJ&r   c                 :    d}t        |d      }|
J d|        y)u%   Lv.1 → None 반환 (경고 없음).u=   # task-101: 수정
레벨: Lv.1
작업 내용: 단순 수정.   r   Nu'   Lv.1에서는 경고가 없어야 함: r   r:   s      r   test_warn_missing_af_level1z8TestWarnMissingAffectedFiles.test_warn_missing_af_level1+  s*    U	-iAF~Q!HQQ~r   c                 :    d}t        |d      }|
J d|        y)u=   Lv.2 + affected_files 기재 → None 반환 (경고 없음).un   # task-102: 수정
레벨: Lv.2
affected_files: server.py, app.js
작업 내용: server.py를 수정합니다.r*   r   Nu5   affected_files가 기재되면 경고 없어야 함: r   r:   s      r   &test_warn_missing_af_level2_with_fileszCTestWarnMissingAffectedFiles.test_warn_missing_af_level2_with_files1  s3    ; 	 .iAF~_!VW]V^__~r   N)r0   r1   r2   r   r   r   r3   r   r   r   r   #  s    KR	`r   r   c                   2    e Zd ZdededefdZd Zd Zd Zy)	TestCheckBatchCompletionrV   rW   rX   c                     |dz  }|j                  dd       |dz  }|j                  t        j                  d|idd      d	
       |S rZ   ra   rf   s        r   ri   z)TestCheckBatchCompletion._make_timer_fileC  rj   r   c                    ddl }d}d|dd|dd}| j                  ||       |j                  |d|       t        |      }|d   d	u s
J d
|        |d   dk(  s
J d|        |d   dk(  s
J d|        |d   g k(  s
J d|        y)uB   모든 task가 done 상태이면 complete=True, pending=[] 반환.r   Nzbatch-20260415-testdonerv   batch_id)ztask-301ztask-302rl   completeTu+   모두 완료 시 complete=True여야 함: totalr*   u   total=2여야 함: u   done=2여야 함: pendingu   pending=[]이어야 함: rm   ri   rn   r   r   rV   ro   rm   r   rW   r!   s          r   test_batch_completion_all_donez7TestCheckBatchCompletion.test_batch_completion_all_doneN  s    (#)x@#)x@
 	h.Hk8<'1j!T)a-XY_X`+aa)g!#C':6(%CC#f~"A&8$AA"i B&L*CF8(LL&r   c                 2   ddl }d}d|dd|dd|dd}| j                  ||       |j                  |d|       t        |      }|d	   d
u s
J d|        |d   dk(  s
J d|        |d   dk(  s
J d|        t	        |d         ddgk(  s
J d|        y)uZ   일부만 done 상태이면 complete=False, pending에 미완료 task가 있어야 한다.r   Nzbatch-20260415-partialr   r   rs   )ztask-401task-402task-403rl   r   Fu/   일부만 완료 시 complete=False여야 함: r      u   total=3이어야 함: r   u   done=1이어야 함: r   r   r   u   pending 목록 불일치: )rm   ri   rn   r   sortedr   s          r   test_batch_completion_partialz6TestCheckBatchCompletion.test_batch_completion_partial`  s    +#)x@#,(C#,(C

 	h.Hk8<'1j!U*f.]^d]e,ff*g!#F'=fX%FF#f~"D&;F8$DD"fY'(Z,DDkHbcibjFkkDr   c                     ddl }ddddi}| j                  ||       |j                  |d|       t        d      }|d	   dk(  s
J d
|        |d   du s
J d|        y)uJ   batch_id가 일치하는 task가 없으면 total=0, complete=False 반환.r   Nztask-501r   zother-batchr   rl   znonexistent-batch-idr   u2   매칭되는 task 없으면 total=0이어야 함: r   Fu(   total=0이면 complete=False여야 함: r   r   s         r   test_batch_completion_no_matchz7TestCheckBatchCompletion.test_batch_completion_no_matchs  s     6}E
 	h.Hk8<'(>?g!#b'YZ`Ya%bb#j!U*_.VW]V^,__*r   N)	r0   r1   r2   r   r   ri   r   r   r   r3   r   r   r   r   B  s.    	 	d 	t 	M$l&`r   r   c                   $    e Zd Zd Zd Zd Zd Zy)TestEstimateTaskLevelc                 `    g d}t        d|      \  }}|dk\  sJ d| d|        |sJ d       y)u+   affected_files 5개 → 최소 Lv.2 권장.)za.pyzb.pyzc.pyzd.pyze.pyu   일반 작업r*   u9   5개 파일이면 Lv.2 이상 권장이어야 함: level=	, reason=u   이유가 있어야 함Nr   r   filesr   reasons       r   test_estimate_level_many_filesz4TestEstimateTaskLevel.test_estimate_level_many_files  sI    8,_eDvzoVW\V]]fgmfnooz000vr   c                 h    dg}t        d|      \  }}|dk\  sJ d| d|        d|v s
J d|        y)u(   server.py 포함 → 최소 Lv.2 권장.r7   u   서버 수정r*   u<   server.py 포함 시 Lv.2 이상 권장이어야 함: level=r   u.   이유에 'server.py'가 포함되어야 함: Nr   r   s       r   test_estimate_level_server_pyz3TestEstimateTaskLevel.test_estimate_level_server_py  sZ    ,_eDvzrYZ_Y``ijpiqrrzf$_(VW]V^&__$r   c                 J    d}t        |g       \  }}|dk\  sJ d| d|        y)u7   '아키텍처' 키워드 포함 → 최소 Lv.3 권장.u;   전체 아키텍처를 변경하는 대형 작업입니다.r   uD   '아키텍처' 키워드 시 Lv.3 이상 권장이어야 함: level=r   Nr   )r   r;   r   r   s       r   (test_estimate_level_architecture_keywordz>TestEstimateTaskLevel.test_estimate_level_architecture_keyword  s;    Q	,Y;vzzabgahhqrxqyzzzr   c                 n    d}dg}t        ||      \  }}|dk(  sJ d| d|        |dk(  s
J d|       y)	u0   파일 1개, 키워드 없음 → Lv.1 (기본).u   단순 오타 수정z
readme.txtr   u*   단순 작업은 Lv.1이어야 함: level=r    u1   단순 작업은 이유가 없어야 함: reason=Nr   )r   r;   r   r   r   s        r   test_estimate_level_simplez0TestEstimateTaskLevel.test_estimate_level_simple  sZ    *	,Y>vz`GwiX^W_``z|[PQWPZ[[|r   N)r0   r1   r2   r   r   r   r   r3   r   r   r   r     s    1`{\r   r   c                       e Zd Zd Zd Zy)TestParseTaskLevelc                 <    d}t        |      }|dk(  s
J d|        y)u%   'Lv.2' 포함 task_desc → 2 반환.uD   # task-100: 수정
레벨: Lv.2
작업 내용: 중간 규모 수정.r*   u   Lv.2 파싱 실패: Nr
   r:   s      r   test_parse_task_level_lv2z,TestParseTaskLevel.test_parse_task_level_lv2  s*    \	"9-{;26(;;{r   c                 <    d}t        |      }|dk(  s
J d|        y)u,   레벨 표기 없음 → 기본값 1 반환.u<   # task-101: 수정
레벨 표기가 없는 간단한 작업.r   u,   레벨 없을 때 기본값 1이어야 함: Nr   r:   s      r   test_parse_task_level_defaultz0TestParseTaskLevel.test_parse_task_level_default  s*    S	"9-{SJ6(SS{r   N)r0   r1   r2   r   r   r3   r   r   r   r     s    <Tr   r   c                   (    e Zd ZdZd Zd Zd Zd Zy)TestAstBlastRadiusu'   _get_ast_blast_radius 함수 테스트.c                 F    t        dgd      }|d   g k(  sJ |d   dk(  sJ y)u6   py 확장자 없는 affected_files면 빈 dict 반환.z	README.md/tmpdirect_importerstotal_affectedr   N)r   r    s     r   #test_returns_empty_when_no_py_filesz6TestAstBlastRadius.test_returns_empty_when_no_py_files  s8    &}f=()R///&'1,,,r   c                    t        j                  dddgg dgddd      }t               }d|_        ||_        d	|_        t        d
|      5  t        dgd      }ddd       dd   v sJ d|d   v sJ y# 1 sw Y   xY w)u.   AST 호출 성공 시 direct_importers 반환.data_loader.pyr7   z	routes.pyztest_data_loader.pyr   )r   callers
test_filesr   )changed_fileblast_radiusr   r   subprocess.runreturn_valuer   Nr   )rd   re   r   
returncodestdoutstderrr   r   )r   
ast_output	mock_procr!   s       r   !test_returns_importers_on_successz4TestAstBlastRadius.test_returns_importers_on_success  s    ZZ,%0+$>45"#	!
 
 K	 	%		#)< 	G*,<+=vFF	G f%78888f%78888		G 	Gs   A66A?c                     t        dt        j                  g d            5  t        dgd      }ddd       d   g k(  sJ y# 1 sw Y   xY w)	u%   AST 타임아웃 시 빈 dict 반환.r      )cmdtimeout)side_effectr   r   Nr   )r   
subprocessTimeoutExpiredr   r    s     r   test_returns_empty_on_timeoutz0TestAstBlastRadius.test_returns_empty_on_timeout  sZ    #1J1Jr[]1^_ 	G*,<+=vFF	G ()R///	G 	Gs   AAc                     t               }d|_        d|_        d|_        t	        d|      5  t        dgd      }ddd       d	   g k(  sJ y# 1 sw Y   xY w)
u,   AST 스크립트 실패 시 빈 dict 반환.r   r   errorr   r   r   r   Nr   )r   r   r   r   r   r   )r   r   r!   s      r   "test_returns_empty_on_script_errorz5TestAstBlastRadius.test_returns_empty_on_script_error  sk    K	 		"	#)< 	G*,<+=vFF	G ()R///	G 	Gs   AAN)r0   r1   r2   __doc__r   r   r   r   r3   r   r   r   r     s    1-9.0
0r   r   )$r   rd   r   syspathlibr   unittest.mockr   r   pytest__file__parent
_WORKSPACEpathinsertr   rm   r   r   r   r	   r
   r   r   prompts.gate_instructionsr   r   r   r   r5   rU   r   r   r   r   r   r3   r   r   <module>r      s      
  *  (^""))
 3z? #    w  wPsc scvG\ G\^` `>=` =`J\ \FT T"10 10r   