Ë
    °õÍj©-  ã                  ó   — d dl mZ d dlmZ d dlZd dl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Zd dlmZ  e	e«      j!                  «       j"                  Zedz  Zej)                  «       r6 ee«      ej,                  vr"ej,                  j/                  d  ee«      «       edz  dz  Zed	z  Zed
z  Zedz  Zdedz  dfdedz  dfdedz  dfgZd#d„Zd$d„Zd%d„Zd&d„Z d'd„Z!d#d„Z"d(d)d„Z#d#d„Z$e%dk(  r[ ejL                  d¬«      Z'e'jQ                  dd d!¬"«       e'jS                  «       Z* e+e*jX                  r e«       «      ‚ e$«       «      ‚y)*é    )Úannotations)ÚdatetimeN)ÚPath)ÚAnyÚvendorÚreportsÚ	dashboardzupdate_status.jsonz.daily_update.lockÚlogsu   M1 æ•°æ�®åˆ·æ–°z	run_m1.pyi0*  u   M2 å› å­�ç ”ç©¶zrun_m2_research.pyu   çœ‹æ�¿ç”Ÿæˆ�zrun_dashboard.pyi„  c            
     óØ  — dD � cg c]$  } t         j                  j                  | «      �Œ#| ‘Œ& }} t        dz  dz  gd„ t        D «       ¢}|D �cg c]  }|j                  «       rŒt        |«      ‘Œ  }}i }g }g }	 t        j                  j                  dt        t        dz  «      «       ddl
m}  |t        dz  dz  «      }	t        |	j                  «      t        |	j                  dz  d	z  d
z  «      t        |	j                  dz  dz  d
z  «      t        |	j                  dz  dz  «      t        |	j                  «      dœ}|	j                  |	j                  dz  d	z  d
z  |	j                  dz  dz  d
z  |	j                  dz  dz  |	j                  g}
|
D �cg c]  }|j                  «       rŒt        |«      ‘Œ  }}|	j                  j                  «       s|j                  d|	j                  › �«       |	j                   j                  «       s+|	j"                  j                  «       s|j                  d«       t        j&                  t        j(                  j+                  «       d   t        t        «      |||||| xr | xr | dœ	}t-        t/        j0                  |dd¬«      «       |d   rdS dS c c} w c c}w c c}w # t$        $ r}|j                  d|› �«       Y d }~Œ¬d }~ww xY w)N)ÚpandasÚnumpyÚpyarrowÚduckdbÚconfigzlocal_paths.tomlc              3  ó(   K  — | ]
  \  }}}|–— Œ y ­w©N© )Ú.0Ú_Úscripts      ú+C:\FundamentalWorkbench\run_daily_update.pyÚ	<genexpr>z$check_environment.<locals>.<genexpr>    s   è ø€ Ð=`ÑY_ÉÈÈFÐTU¼fÑY_ùs   ‚r   Úsrc)Úload_settingsÚvipdocÚshÚldayÚszÚcw)ÚtdxRootÚshDailyÚszDailyÚfinanceÚgbbqu0   åŽ†å�²å��ç§°è¾…åŠ©ç›®å½•ä¸�å­˜åœ¨ï¼ˆå�¯é€‰ï¼‰ï¼šu?   æ—¢æ— åŽ†å�²è´¢åŠ¡å¤‡ç”¨æ–‡ä»¶ï¼Œä¹Ÿæ— å·²ç”Ÿæˆ�çš„è´¢åŠ¡ç¼“å­˜u   é…�ç½®æ— æ³•è¯»å�–ï¼š)	ÚpythonÚpythonVersionÚprojectRootÚmissingModulesÚmissingPathsÚsourcePathsÚmissingSourcePathsÚwarningsÚreadyFé   ©Úensure_asciiÚindentr-   é   )Ú	importlibÚutilÚ	find_specÚROOTÚSTAGESÚexistsÚstrÚsysÚpathÚinsertÚfundamental_mvp.configr   Útdx_rootÚ	gbbq_pathÚlegacy_data_dirÚappendÚlegacy_finance_parquetÚfinancial_pit_pathÚ	ExceptionÚ
executableÚversionÚsplitÚprintÚjsonÚdumps)ÚnameÚmissing_modulesÚrequired_pathsr;   Úmissing_pathsÚsource_pathsÚmissing_source_pathsr,   r   ÚsettingsÚrequired_sourcesÚerrorÚresults                r   Úcheck_environmentrU      sÄ  € Ù(PÓ{Ñ(P ÔT]×TbÑTb×TlÑTlÐmqÓTrÑTz’tÐ(P€OÐ{Ü˜X‘oÐ(:Ñ:ÐaÑ=`ÕY_Ó=`Ða€NÙ+9ÓO©> 4ÀÇÁÅ”S˜•Y¨>€MÐOØ#%€LØ&(ÐØ€HðEÜ�‰�‰˜œ3œt e™|Ó,Ô-Ý8á ¤¨¡Ð3EÑ!EÓFˆä˜8×,Ñ,Ó-Ü˜8×,Ñ,¨xÑ7¸$Ñ>ÀÑGÓHÜ˜8×,Ñ,¨xÑ7¸$Ñ>ÀÑGÓHÜ˜8×,Ñ,¨xÑ7¸$Ñ>Ó?Ü˜×*Ñ*Ó+ñ
ˆð ×ÑØ×Ñ Ñ(¨4Ñ/°&Ñ8Ø×Ñ Ñ(¨4Ñ/°&Ñ8Ø×Ñ Ñ(¨4Ñ/Ø×Ñð
Ðñ 7GÓ\Ñ6F¨dÈdÏkÉkÍm¤ D¥	Ð6FÐÐ\Ø×'Ñ'×.Ñ.Ô0Ø�O‰OÐNÈx×OgÑOgÐNhÐiÔjØ×.Ñ.×5Ñ5Ô7À×@[Ñ@[×@bÑ@bÔ@dØ�O‰OÐ]Ô^ô —.‘.ÜŸ™×*Ñ*Ó,¨QÑ/Üœ4“yØ)Ø%Ø#Ø2ØØ$Ð$ÒW¨]Ð):ÒWÐCWÐ?Wñ
€Fô 
Œ$�*‰*�V¨%¸Ô
:Ô;Ø�w’ˆ1Ð& QÐ&ùòY |ùâOùò.  ]øô
 ò EØ×#Ñ#Ð&;¸E¸7Ð$C×DÑDûðEúsH   …$J3ªJ3ÁJ8Á$J8Á:DK ÆJ=Æ,J=Æ9A?K Ê=K Ë	K)ËK$Ë$K)c                 óf   — t        j                  «       j                  «       j                  d¬«      S )NÚseconds)Útimespec)r   ÚnowÚ
astimezoneÚ	isoformatr   ó    r   Ú_nowr]   N   s%   € Ü�<‰<‹>×$Ñ$Ó&×0Ñ0¸)Ð0ÓDÐDr\   c                óî   — | j                   j                  dd¬«       | j                  | j                  › d�«      }|j	                  t        j                  |dd¬«      d¬«       |j                  | «       y )	NT©ÚparentsÚexist_okz.tmpFr.   r/   úutf-8©Úencoding)ÚparentÚmkdirÚ	with_namerK   Ú
write_textrI   rJ   Úreplace)r;   ÚvalueÚ	temporarys      r   Ú_write_json_atomicrl   R   sa   € Ø‡K�K×Ñ˜d¨TÐÔ2Ø—‘ $§)¡) ¨DÐ1Ó2€IØ×ÑœŸ™ E¸ÀaÔHÐSZÐÔ[Ø×Ñ�dÕr\   c                 óä   — 	 t         j                  dd¬«      } d| vry	 t        | j	                  dd«      d   j	                  «       d   «      S # t        $ r Y yw xY w# t
        t        f$ r Y yw xY w)zDPID recorded in the lock file, or None when it is absent/unreadable.rb   ri   ©rd   ÚerrorsNúpid=r2   r   )Ú	LOCK_PATHÚ	read_textÚOSErrorÚintrG   Ú
IndexErrorÚ
ValueError)Útexts    r   Ú_lock_owner_pidrx   Y   sƒ   € ðÜ×"Ñ"¨G¸IÐ"ÓFˆð �TÑØðÜ�4—:‘:˜f aÓ(¨Ñ+×1Ñ1Ó3°AÑ6Ó7Ð7øô ò Ùðûô œ
Ð#ò Ùðús"   ‚A Ÿ.A Á	AÁAÁA/Á.A/c                óä  — | r| dk  ryt         j                  dk(  r™dd l}d}d}|j                  j                  }|j                  |d| «      }|sy	 |j                  «       }|j                  ||j                  |«      «      s	 |j                  |«       y|j                  |k(  |j                  |«       S 	 t        j                  | d«       y# |j                  |«       w xY w# t        $ r Y yw xY w)Nr   FÚnti   i  T)ÚosrK   ÚctypesÚwindllÚkernel32ÚOpenProcessÚc_ulongÚGetExitCodeProcessÚbyrefÚCloseHandlerj   Úkillrs   )Úpidr|   Ú!PROCESS_QUERY_LIMITED_INFORMATIONÚSTILL_ACTIVEr~   ÚhandleÚcodes          r   Ú
_pid_aliverŠ   g   så   € Ù�#˜’(ØÜ	‡w�w�$‚Ûà,2Ð)ØˆØ—=‘=×)Ñ)ˆØ×%Ñ%Ð&GÈÐPSÓTˆÙØð	)Ø—>‘>Ó#ˆDØ×.Ñ.¨v°v·|±|ÀDÓ7IÔJØð × Ñ  Õ(ð —:‘: Ñ-à× Ñ  Õ(ðÜ
�‰��QŒØøð × Ñ  Õ(ûô ò Ùðús$   Á1C ÂC Â6C# ÃC Ã#	C/Ã.C/c                 ó0  — t         j                  dd¬«       	 t        j                  t        t        j
                  t        j                  z  t        j                  z  «      S # t        $ �r( t        «       } t        j                  «       t        j                  «       j                  z
  }| �kt        | «      s`t        j                  «        t        j                  t        t        j
                  t        j                  z  t        j                  z  «      cY S |dk  r| rd| › d�nd}t        d|› �«      ‚t        j                  «        t        j                  t        t        j
                  t        j                  z  t        j                  z  «      cY S w xY w)NTr_   i`T  u   ï¼ˆpid=u   ï¼‰Ú u   å·²æœ‰æ—¥æ›´ä»»åŠ¡åœ¨è¿�è¡Œ)ÚDASHBOARD_DIRrf   r{   Úopenrq   ÚO_CREATÚO_EXCLÚO_WRONLYÚFileExistsErrorrx   ÚtimeÚstatÚst_mtimerŠ   ÚunlinkÚRuntimeError)ÚownerÚage_secondsÚhelds      r   Ú_acquire_lockr›   �   s  € Ü×Ñ ¨tÐÔ4ðHÜ�w‰w”y¤"§*¡*¬r¯y©yÑ"8¼2¿;¹;Ñ"FÓGÐGøÜó HÜÓ!ˆÜ—i‘i“k¤I§N¡NÓ$4×$=Ñ$=Ñ=ˆð
 Ð¤Z°Ô%6Ü×ÑÔÜ—7‘7œ9¤b§j¡j´2·9±9Ñ&<¼r¿{¹{Ñ&JÓKÒKØ˜+Ò%Ù+0�W˜U˜G 3Ñ'°bˆDÜÐ!<¸T¸FÐCÓDÐDÜ×ÑÔÜ�w‰w”y¤"§*¡*¬r¯y©yÑ"8¼2¿;¹;Ñ"FÓGÒGðHús   ™A	A# Á#B2FÄA;FÆFc                óf  — 	 | j                  dd¬«      j                  «       }g }t        || d «      D ]7  }|j	                  «       }|r|j                  d«      rŒ'|j                  |«       Œ9 |D ]  }d|v sd|v sŒd	|v sŒ|c S  |D ]  }t        d
„ |D «       «      sŒ|c S  y# t        $ r Y yw xY w)a?  Best-effort: pull the most informative line from a stage's output.

    The stage output ends with a Python traceback, whose final line is normally the
    exception message. This lets the status file carry an actionable reason instead
    of only "stage failed with exit code 1".

    Two noise sources are handled deliberately:
      * our own bracketed markers, e.g. "[2026-10-13T17:09:17+08:00] END ..."
      * multi-line engine errors (DuckDB) that end with a bare caret pointing at the
        offending token -- taking the literal last line would yield just "^".
    rb   ri   rn   rŒ   NÚ[ÚErrorrD   Ú:c              3  ó<   K  — | ]  }|j                  «       –— Œ y ­wr   )Úisalnum)r   Úchs     r   r   z#_last_error_line.<locals>.<genexpr>²   s   è ø€ Ð+¡d ˆr�z‰z�|¡dùs   ‚)rr   Ú
splitlinesrs   ÚreversedÚstripÚ
startswithrA   Úany)r;   ÚlimitÚlinesÚ
candidatesÚlinerw   s         r   Ú_last_error_liner¬   –   sÇ   € ðØ—‘¨¸	�ÓB×MÑMÓOˆð €JÜ˜ ˜v˜w˜Ö(ˆØ�z‰z‹|ˆÙ�t—‘ sÔ+ØØ×Ñ˜$Õð	 )ó ˆØ�t‰O˜{¨dÒ2¸¸tºØŠKð ó ˆÜÑ+¡dÓ+Õ+ØŠKð ð øô! ò Ùðús   ‚!B$ Â$	B0Â/B0c                 óV  — t         j                  dd¬«       t        «       } t         dt        j                  «       d›d�z  }d| d ddt        |«      d	œ}	 t        «       }t        j                  |dt        j                  «       › d| › �j                  d«      «       t        j                  |«       t!        t"        |«       	 |j%                  dd¬«      5 }|j                  d| › d�«       t'        t(        d¬«      D �]  \  }\  }}}	|j+                  |d|› �|t-        t(        «      dœ«       t!        t"        |«       t/        j0                  «       }
|j                  dt        «       › d|› d�«       |j3                  «        t5        j6                  t        j8                  t        |«      gt:        |t4        j<                  ddd|	i t        j>                  ¥dt        j@                  jC                  t        tD        «      t        t:        dz  «      t        j>                  jG                  dd«      g«      jI                  t        j@                  «      dœ¥d¬ «
      }tK        t/        j0                  «       |
z
  d«      }|jL                  d!k7  rtO        |«      nd}|j                  dt        «       › d"|› d#|jL                  › d$|› d%�	«       |j3                  «        |jL                  d!k7  s�Œê|› d&|jL                  › �}|r|› d'|› �}t        |«      ‚ 	 d d d «       |j+                  d(t        «       d)d*t-        t(        «      t-        t(        «      d+œ«       tP        d,z  }|jS                  «       rMtU        jV                  |jY                  d¬«      «      }|jG                  d-«      |d-<   |jG                  d.«      |d.<   t!        t"        |«       t        |d/   «       	 tZ        jS                  «       rtZ        j]                  «        y!y!# t        $ r.}t        t        |«      t        j                  ¬
«       Y d }~yd }~ww xY w# 1 sw Y   �Œ-xY w# t4        j^                  $ r’}|j+                  d0t        «       |d1   |d1   › d2�t        |«      d3œ«       t!        t"        |«       t        |d/   t        j                  ¬
«       Y d }~tZ        jS                  «       rtZ        j]                  «        yyd }~wt`        $ rw |j+                  d4t        «       d5d6œ«       t!        t"        |«       t        |d/   t        j                  ¬
«       Y tZ        jS                  «       rtZ        j]                  «        y7y7tb        $ r‹}|j+                  d0t        «       |› d8�te        |«      d9œ«       t!        t"        |«       t        |d/   t        j                  ¬
«       Y d }~tZ        jS                  «       rtZ        j]                  «        yyd }~ww xY w# tZ        jS                  «       rtZ        j]                  «        w w xY w):NTr_   Úupdate_z%Y%m%d_%H%M%Sz.logÚrunningu   å‡†å¤‡æ›´æ–°u   æ—¥åº¦ç ”ç©¶æ•°æ�®æ­£åœ¨æ›´æ–°)ÚstateÚ	startedAtÚcompletedAtÚstageÚmessageÚlogPath)Úfiler.   rp   z	 started=rb   Úwrc   r�   u   ] æ—¥åº¦æ›´æ–°å¼€å§‹
r2   )Ústartu   æ­£åœ¨æ‰§è¡Œ )r³   r´   Ú
stageIndexÚ
stageCountz
[z] START Ú
ri   r   Ú
PYTHONPATHrŒ   )ÚPYTHONIOENCODINGr¼   F)	ÚcwdÚstdoutÚstderrrw   rd   ro   ÚtimeoutÚenvÚcheckr   z] END z exit=z
 duration=zs
u    å¤±è´¥ï¼Œé€€å‡ºç � u   ï¼šÚsuccessu   æ›´æ–°å®Œæˆ�u&   M1ã€�M2 ä¸Žç ”ç©¶çœ‹æ�¿å·²å…¨éƒ¨æ›´æ–°)r°   r²   r³   r´   r¹   rº   zversion.jsonÚrunIdrF   r´   Úfailedr³   u    è¶…æ—¶ï¼Œæ—§çœ‹æ�¿ä»�å�¯ç”¨)r°   r²   r³   r´   rS   Ú	cancelledu$   æ›´æ–°å·²å�–æ¶ˆï¼Œæ—§çœ‹æ�¿ä»�å�¯ç”¨)r°   r²   r´   é‚   u   ï¼›æ—§çœ‹æ�¿ä»�å�¯ç”¨)r°   r²   r´   rS   )3ÚLOG_DIRrf   r]   r   rY   r9   r›   r—   rH   r:   rÀ   r{   ÚwriteÚgetpidÚencodeÚcloserl   ÚSTATUS_PATHrŽ   Ú	enumerater7   ÚupdateÚlenr“   Ú	monotonicÚflushÚ
subprocessÚrunrE   r6   ÚSTDOUTÚenvironÚpathsepÚjoinÚ
VENDOR_DIRÚgetÚrstripÚroundÚ
returncoder¬   r�   r8   rI   Úloadsrr   rq   r–   ÚTimeoutExpiredÚKeyboardInterruptrD   Úrepr)Ú
started_atÚlog_pathÚstatusÚlock_fdrS   ÚlogÚindexÚ
stage_nameÚscript_pathÚtimeout_secondsÚstage_startedrT   ÚdurationÚfailure_detailr´   Úversion_pathrF   s                    r   Úmainrð   ·   sY  € Ü‡M�M˜$¨€MÔ.Ü“€JÜ˜7¤8§<¡<£>°-Ð"@ÀÐEÑE€HàØØØØ3Ü�x“=ñ€FðÜ“/ˆô
 ‡H�HˆW˜œRŸY™Y›[˜M¨°:°,Ð?×FÑFÀwÓOÔPÜ‡H�HˆWÔÜ”{ FÔ+ðHØ�]‰]˜3¨ˆ]Ô1°SØ�I‰I˜˜*˜Ð%;Ð<Ô=ÜENÌvÐ]^×E_ÐE_ÑA�ÑA˜
 K°Ø—‘¨
ÀÈzÈlÐ?[Ðkpô  ADô  EKó  ALñ  Mô  NÜ"¤;°Ô7Ü $§¡Ó 0�Ø—	‘	˜C¤£˜x x°
¨|¸2Ð>Ô?Ø—	‘	”Ü#Ÿ™Ü—^‘^¤S¨Ó%5Ð6ÜØÜ%×,Ñ,ØØ$Ø$Ø+ðÜŸ*™*ðà,3Ü&(§j¡j§o¡oÜ ¤›_¬c´$¸±,Ó.?ÄÇÁÇÁÐP\Ð^`ÓAaÐbó'ç ™&¤§¡Ó,òð  ô!�ô$ !¤§¡Ó!1°MÑ!AÀ1ÓE�ð @F×?PÑ?PÐTUÒ?UÔ!1°(Ô!;Ð[]�Ø—	‘	˜C¤£˜x v¨j¨\¸À×@QÑ@QÐ?RÐR\Ð]eÐ\fÐfiÐjÔkØ—	‘	”Ø×$Ñ$¨Ô)Ø!+ Ð,@À×ARÑARÐ@SÐT�GÙ%Ø%, I¨S°Ð0@Ð"A˜Ü& wÓ/Ð/ñE F`÷ 2ðL 	�‰ØÜ›6Ø#Ø?Üœf›+Üœf›+ñ
ô 	ô % ~Ñ5ˆØ×ÑÔ Ü—j‘j ×!7Ñ!7ÀÐ!7Ó!IÓJˆGØ%Ÿk™k¨'Ó2ˆF�7‰OØ '§¡¨IÓ 6ˆF�9ÑÜœ;¨Ô/Üˆf�YÑÔ Øô" ×ÑÔÜ×ÑÕð øô_ ò ÜŒc�%‹jœsŸz™zÕ*Üûðú÷ 2Ñ1ûôl ×$Ñ$ò Ø�‰ ¼»È&ÐQXÉ/ÐioÐpwÑixÐhyð  zVð  gWô  beð  fkó  blñ  mô  	nÜœ;¨Ô/Üˆf�YÑ¤c§j¡jÕ1Ûô ×ÑÔÜ×ÑÕð ûô ò Ø�‰ ¼D»FÐOuÑvÔwÜœ;¨Ô/Üˆf�YÑ¤c§j¡jÕ1Øô ×ÑÔÜ×ÑÕð ô ò Ø�‰ ¼»ÈuÈgÐUjÐLkÔvzð  |Aó  wBñ  Cô  	DÜœ;¨Ô/Üˆf�YÑ¤c§j¡jÕ1Ûä×ÑÔÜ×ÑÕð ûðûô ×ÑÔÜ×ÑÕð úsƒ   Á
O> ÃQ ÃHP8Ë&&P8ÌCQ Ï>	P5Ð$P0Ð0P5Ð8QÐ=Q ÑW:ÑAS%Ò7W= Ó%AW:Ô<W= Õ'W:Õ/AW5×W= ×5W:×:W= ×=+X(Ú__main__u(   åˆ·æ–° M1/M2 æ•°æ�®å¹¶é‡�å»ºç ”ç©¶çœ‹æ�¿)Údescriptionz--checkÚ
store_trueu&   ä»…æ£€æŸ¥ Python çŽ¯å¢ƒå’Œå¿…éœ€æ–‡ä»¶)ÚactionÚhelp)Úreturnrt   )rö   r9   )r;   r   rj   zdict[str, Any]rö   ÚNone)rö   ú
int | None)r…   rø   rö   Úbool)éP   )r;   r   r¨   rt   rö   r9   )-Ú
__future__r   r   ÚargparseÚimportlib.utilr3   rI   r{   Úpathlibr   rÔ   r:   r“   Útypingr   Ú__file__Úresolvere   r6   rÚ   r8   r9   r;   r<   r�   rÎ   rq   rÉ   r7   rU   r]   rl   rx   rŠ   r›   r¬   rð   Ú__name__ÚArgumentParserÚparserÚadd_argumentÚ
parse_argsÚ	argumentsÚ
SystemExitrÃ   r   r\   r   Ú<module>r	     sr  ðÝ "å Û Û Û Û 	Ý Û Û 
Û Ý ñ ˆHƒ~×ÑÓ×&Ñ&€Ø�H‰_€
Ø×ÑÔ™3˜z›?°#·(±(Ñ:Ø‡H�H‡O�O�A‘s˜:“Ô'Ø�yÑ  ;Ñ.€ØÐ2Ñ2€ØÐ0Ñ0€	Ø
˜&Ñ
 €à˜˜{Ñ*¨KÐ8Ø˜Ð3Ñ3°[ÐAØ�TÐ.Ñ.°Ð8ð
€ó-'ó`Eóóóó4Hô*óB_ðD ˆzÒØ$ˆX×$Ñ$Ð1[Ô\€FØ
×Ñ˜	¨,Ð=eÐÔfØ×!Ñ!Ó#€IÙ
¨I¯OªOÑ&Ó(Ó
HÐHÁÃÓ
HÐHð	 r\   