
    %j?              
      
   U d 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	  e	e
      j                         j                  Zedz  Zedz  Zg dZdZd	Zd
Z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dddZded<   ddddd Zd0d!Zd1d"Zd2d#Zd3d$Zd4d%Z	 	 	 	 	 	 	 	 d5d&Zd6d'Zd7d(Z	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d8d)Z	 	 	 	 	 	 	 	 d9d*Z 	 	 	 	 	 	 d:d+Z!	 	 	 	 	 	 d;d,Z"eef	 	 	 	 	 d<d-Z#d=d.Z$e%d/k(  r e$        yy)>a  Microsoft forecast-vintage extractor.

Reads source_manifest.csv, fetches primary SEC/IR HTML, and parses capex actuals
from cash-flow statements plus FY2026 capex-guidance vintages from earnings-call
prepared remarks. Microsoft does not disclose MW/GW; normalized_gw is blank.
    )annotationsN)Pathzsource_manifest.csvzforecast_vintage.csv)companytickeras_of_periodtarget_periodmetric_name	raw_valuenormalized_gwunitforecast_or_actual
is_derived
source_urlsource_locationsource_snippetsnippet_support_status
confidencecaveatzrMicrosoft does not disclose data-center MW/GW. Row tracks USD capex proxy only; normalized_gw intentionally blank.zCMSFT-forecast-vintage-extractor/1.0 (research; contact@example.com)g%C#P@z77.5z3Q4 FY2025 earnings call prepared remarks (Amy Hood)zCapital expenditure growth, as we shared last quarter, will moderate compared to FY25 with a greater mix of short-lived assets.1mediumu   Microsoft gives qualitative FY2026 capex growth guidance only. Implied ~$77.5B derived as FY2025 actual $64.551B × 1.20 (~20% YoY, interpretation of 'moderate' vs FY2025's 45% growth). Not MW/GW capacity.)r
   r   r   r   r   r   z96.8z3Q1 FY2026 earnings call prepared remarks (Amy Hood)zqTherefore, total spend will increase sequentially, and we now expect the FY26 growth rate to be higher than FY25.u   FY2026 capex guide revised upward qualitatively. Implied ~$96.8B derived as FY2025 $64.551B × 1.50 (~50% YoY, above FY2025's 45% growth rate). Not MW/GW capacity.z3Q2 FY2026 earnings call prepared remarks (Amy Hood)zzNo new full-year FY2026 numeric capex guide at FQ2; vintage carries forward Q1 FY2026 implied ~$96.8B. Not MW/GW capacity.z3Q3 FY2026 earnings call prepared remarks (Amy Hood)zzNo new full-year FY2026 numeric capex guide at FQ3; vintage carries forward Q1 FY2026 implied ~$96.8B. Not MW/GW capacity.)msft_fy2025_q4_earnings_webcastmsft_fy2026_q1_earnings_webcastmsft_fy2026_q2_earnings_webcastmsft_fy2026_q3_earnings_webcastzdict[str, dict[str, str]]CALL_GUIDANCE         )sec_10ksec_10qofficial_ir_releaseearnings_call_webcastc                    | j                  dd      5 }t        t        j                  |            cd d d        S # 1 sw Y   y xY w)N utf-8newlineencoding)openlistcsv
DictReader)manifest_pathhandles     e/home/dev/research_loop/runs/gw-forecast-production-001-loop03/artifacts/production/MSFT/extractor.pyload_manifestr0   v   s=    			B		9 ,VCNN6*+, , ,s	   <Ac                    t         j                  j                  | dt        i      }t         j                  j	                  |d      5 }|j                         j                  dd      cd d d        S # 1 sw Y   y xY w)Nz
User-Agent)headersZ   )timeoutr%   replace)errors)urllibrequestRequest
USER_AGENTurlopenreaddecode)urlr8   responses      r/   
fetch_htmlr@   {   sk    nn$$S<2L$MG					4 A}}%%gi%@A A As   	!A44A=c                    t        | j                  dd            }|dz  dj                  d      j                  d      S )N,r$   i  z.3f0.)intr5   rstrip)rawvalues     r/   billions_from_millionsrI      s<    C$%Edl3'',33C88    c           	         g }t        j                  d|       D ];  }|j                  t        |j	                  d      j                  dd                   = |S )Nz;PaymentsToAcquirePropertyPlantAndEquipment"[^>]*>([0-9,]+)<r   rB   r$   )refinditerappendrE   groupr5   )htmlvaluesmatchs      r/   parse_capex_valuesrS      sT    FF < 	c%++a.00b9:;	<
 MrJ   c                    t        |       }|dk(  r|r|d   d}t        |      d| dfS |dk(  r|r|d   d}t        |      d| dfS y )NFY2025r   rB   %Additions to property and equipment ()FY2024)rS   rI   )rP   fiscal_year_labelrQ   rG   s       r/   extract_annual_capexrZ      sw    %FH$1%c*.STWSXXY,ZZZH$1%c*.STWSXXY,ZZZrJ   c                   t        |       }|sy |s|d   d}t        |      d| dd|d   fS t        |      dk\  r#|!|d   }||z
  }|d}t        |      d| dd|fS |!|d   }||z
  }|d}t        |      d| dd|fS y )	Nr   rB   rV   rW   rC   r   r   r   )rS   rI   len)rP   derivedprior_ytd_millionsrQ   rG   current_ytdquarters          r/   extract_quarterly_capexra      s    
  %F1"3'3C5:1I	
 	
 6{a.:Qi 22"3'3C5:	
 	
 %Qi 22"3'3C5:	
 	
 rJ   c                z    t        |       }|sy t        |      dk\  r|d   d}n|d   d}t        |      d| dfS )Nr   r   rB   r   z)Additions to property and equipment YTD (rW   )rS   r\   rI   )rP   labelrQ   rG   s       r/   extract_ytd_capexrd      sU    %F
6{a11!#&*STWSXXY(ZZZrJ   c                    | d   | d   | d   fS Nr   r   r	    )rows    r/   row_keyri      s    _!5s=7IJJrJ   c       
        ~    i d| d   d| d   d| d   d|d|d|dd	d
dd|d|d| d   d|d|d|d|	d|
S )Nr   r   r   periodr   r	   r
   r   r$   r   USD_billionsr   r   r   r   r   r   r   r   rg   )manifest_rowr   r	   r
   r   r   r   r   r   r   r   s              r/   base_rowrn      s    <	*,x( 	X. 		
 	{ 	Y 	 	 	0 	j 	l<0 	? 	. 	!"8 	j  	&! rJ   c                   | d   j                  d      D ch c]  }|j                          }}| d   }| d   }g }|dk(  rXd|vr|S t        j                  |      }|s|S |j	                  t        | dd|d	   d
|d   |d   |d   d|d   |d                |S | d   }	|j                  |	      }
|
t        |	      }
|
||	<   d|v r|dk(  r| d   dk(  r<t        |
d      }|r.|\  }}|j	                  t        | dd|ddd|ddt                     | d   dk(  r<t        |
d      }|r.|\  }}|j	                  t        | dd|ddd|ddt                     d |v r| d   }d!d"d#j                  ||      }t        |
|      }|rk|\  }}t        |
      }t        |      d$k\  r|d%   n|d&   }|||j                  d'      d&   <   |j	                  t        | |d |dd| d(   |ddt                     d)|v sd*|v rwd*|v }| d   j                  d'      d&   }|j                  |      }t        |
||+      }|r;|\  }}}}|||<   |j	                  t        | | d   d|d|| d(   |ddt                     |S c c}w ),Nextractable_metrics;document_type	source_idr"   capex_guidance_fy2026FY2026capex_guidancer
   forecastr   r   r   verified_primaryr   r   )
r   r	   r
   r   r   r   r   r   r   r   r   capex_actual_fyr   rk   z
FY2024-FQ4rX   capex_actualactualrC   zQConsolidated Statements of Cash Flows; FY2024 additions to property and equipmenthighz
FY2025-FQ4rU   zQConsolidated Statements of Cash Flows; FY2025 additions to property and equipmentcapex_actual_ytdz	FY2026-H1z	FY2026-9M)z
FY2026-FQ2z
FY2026-FQ3r   r   r   -expected_sectioncapex_actual_quartercapex_actual_quarter_derived)r]   r^   )splitstripr   getrN   rn   r@   rZ   GW_PROXY_CAVEATrd   rS   r\   ra   )rm   
html_cache	ytd_statemmetricsdoc_typers   rowscallr>   rP   parsedrH   snippetrk   	ytd_labelrQ   ytd_millionsr]   fiscal_year	prior_ytdr   s                         r/   extract_from_manifest_rowr      sC   
 #//D"E"K"KC"PQQqwwyQGQO,H[)I!#D**"'1K  +K&,{+#-- $%6 7#$45'9-H~	
 
|
$C>>#D|#
3G#I(=!\1)$9F!'w$&.$2"'+3#&({'./A#). !\1)$9F!'w$&.$2"'+3#&({'./A#).  W$h'%%
 #ff
 	 #43#NE7'-F(+Fq(86!9fQiL.:Ifll3'*+KK "+ 2#'/"$01C$D#*+=%*  (,Jg,U0G;"8,2237:MM+.	(wS\]7=4E7J%1Ik"KK ".x"8 .#'/)$01C$D#*+=%*  K} Rs   I*c                    | D ci c]  }|d   t         j                  |d   d      ! }}i }|D ]=  }t        |      }|j                  |      }||||<   '||d      ||d      k  s9|||<   ? t        |j	                         d       S c c}w )Nr   rr   c   c                    | d   | d   | d   fS rf   rg   )rs    r/   <lambda>zdedupe_rows.<locals>.<lambda>  s    q(!O*<a>NO rJ   )key)SOURCE_PRIORITYr   ri   sortedrQ   )manifest_rows	extractedrh   priority_by_urlbestr   existings          r/   dedupe_rowsr   y  s     ! 	L?..s?/CRHHO  8:D cl88C=DI3|,-@V0WWDI O s   $Bc           	        |D ch c]  }|d   	 }}t        t              }t               }t        | d      D ]  \  }}||j                         z
  }|rt	        d| dt        |             |d   j                  d      st	        d| d      |d   |vrt	        d| d|d          |d	   d
k7  rt	        d| d      |j                  |d           t        |      dk  rt	        dt        |             | D cg c]  }|d   dk(  s|d   dk(  s| }	}t        |	      dk  rt	        dt        |	             t        |       dk  rt	        dt        |              y c c}w c c}w )Nr   r   )startzRow z missing columns: zhttps://z source_url must be httpsz source_url not in manifest: r   MSFTz ticker must be MSFTr      z$Need >=8 as_of_period vintages, got r	   rv   r   ru      z-Need >=4 FY2026 capex_guidance vintages, got    zNeed >=16 vintage rows, got )	setCANONICAL_FIELDS	enumeratekeys
ValueErrorr   
startswithaddr\   )
r   r   rh   manifest_urlsrequiredas_of_periodsidxmissingr   guidances
             r/   validate_rowsr     s    3@@3S&@M@#$H!eMd!, 
/SSXXZ'tC5(:6'?:KLMM< ++J7tC5(ABCC|M1tC5(Ec,FWEXYZZx=F"tC5(<=>>#n-.
/ =A?M@R?STUUka1]#37G#GAoL^bjLjkHk
8}qHXXYY
4y2~7D	{CDD ' A  ls   E*E/E/E/c                   t        |       }i }i }g }|D ]  }|j                  t        |||               t        ||      }t	        ||       |j
                  j                  dd       |j                  ddd      5 }t        j                  |t              }	|	j                          |	j                  |       d d d        |S # 1 sw Y   |S xY w)NT)parentsexist_okwr$   r%   r&   )
fieldnames)r0   extendr   r   r   parentmkdirr)   r+   
DictWriterr   writeheader	writerows)
r-   output_pathr   r   r   r   rm   r   r.   writers
             r/   	emit_rowsr     s     "-0M!#J "I&(I% Y2<YWXY}i0D$&TD9			#rG		< 3CD K	 Ks   >=CCc                 H   t        j                  d      } | j                  dt        t               | j                  dt        t
               | j                         }t        |j                  |j                        }t        dt        |       d|j                          y )Nz#Emit Microsoft forecast_vintage.csv)descriptionz
--manifest)typedefaultz--outputzWrote z	 rows to )argparseArgumentParseradd_argumentr   DEFAULT_MANIFESTDEFAULT_OUTPUT
parse_argsr   manifestoutputprintr\   )parserargsr   s      r/   mainr     s}    $$1VWF
49IJ

~FDT]]DKK0D	F3t9+Yt{{m
45rJ   __main__)r-   r   returnlist[dict[str, str]])r>   strr   r   )rG   r   r   r   )rP   r   r   z	list[int])rP   r   rY   r   r   tuple[str, str] | None)rP   r   r]   boolr^   z
int | Noner   z tuple[str, str, str, int] | None)rP   r   rc   r   r   r   )rh   dict[str, str]r   ztuple[str, str, str])rm   r   r   r   r	   r   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rm   r   r   r   r   zdict[str, int]r   r   )r   r   r   r   r   r   )r   r   r   r   r   None)r-   r   r   r   r   r   )r   r   )&__doc__
__future__r   r   r+   rL   urllib.requestr7   pathlibr   __file__resolver   BASE_DIRr   r   r   r   r:   FY2025_ANNUAL_CAPEX_Br   __annotations__r   r0   r@   rI   rS   rZ   ra   rd   ri   rn   r   r   r   r   r   __name__rg   rJ   r/   <module>r      s   #  
 	  >!!#**33 22 () 
 S
  PI X(  P7 "(  P7 =( P7 =([;,( ;| 	,
A9
$
$$ #$ &	$N[K   	
          DC CC C 	CL'# .E
E'E 
E8 +& (6 zF rJ   