
    U%j)              	      h   d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	  e	e
      j                         j                  Zedz  Zedz  Zedz  Zed	z  Zg d
Zg dZg dZdddddddddZdZg dZdZdZd&dZd'dZd(dZd)dZd*dZd+dZd,dZ d,d Z!d,d!Z"d-d"Z#d-d#Z$d.d$Z%e&d%k(  r e%        yy)/z7Validate the EQIX quarterly-results production package.    )annotationsN)Decimal)Pathzextract_eqix_quarterly.pyzeqix_source_manifest.csvzeqix_rows.csvzeqix_verification_report.md)companyperiodmetric_name	raw_valuenormalized_valueunitvalue_qualifierownership_basisforecast_or_actual
is_derived
source_urlsource_locationsource_snippetsnippet_support_status
confidencecaveat)2Q243Q244Q241Q252Q253Q254Q251Q26)capex_actualsfuture_capacity_pipelinerevenue_conversion)648falseThree Months Ended)724r"   r#   )987r"   r#   )750r"   r#   )989trueSix Months Ended)1136r(   Nine Months Ended)1436r"   zTotal Capital Expenditures)1256r"   r#   )r)   r+   zTwelve Months Ended)r   r   source_typesource_familyr   stable_locationexpected_tables_sectionsbasis_caveats)z%https://d1io3yog0oux5.cloudfront.net/zhttps://investor.equinix.com/zhttps://www.sec.gov/)zdatacenterdynamics.comzdatacenterfrontier.comzsemianalysis.comzthebuildout.comzwikipedia.orgc                    t        |       N)AssertionError)messages    n/home/dev/research_loop/runs/auto-continue-20260607T140730Z-repair-loop01/artifacts/validate_eqix_quarterly.pyfailr8   L   s    

!!    c                    | 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)pathhandles     r7   read_csvrE   P   s:    	2	0 ,FCNN6*+, , ,s	   <Ac                   | j                  dd      j                  dd      j                  dd      j                  dd      j                  dd      j                  dd      j                  dd      j                         }t        |      S )	N,r;   $()~GWMW)replacestripr   )valuecleaneds     r7   numberrR   U   sq    c2	b		b		b		b		r		r		  7r9   c                    | j                  t              st        d|         | j                         t	        fdt
        D              rt        d|         y y )Nznon-primary URL prefix: c              3  &   K   | ]  }|v  
 y wr4    ).0markerlowereds     r7   	<genexpr>z'validate_primary_url.<locals>.<genexpr>g   s     
=6W
=s   zsecondary source rejected: )
startswithPRIMARY_URL_PREFIXESr8   loweranySECONDARY_MARKERS)urlrX   s    @r7   validate_primary_urlr`   c   sO    >>./'u-.iikG

=+<
==*3%01 >r9   c                   g }t        |       dk7  rt        dt        |               | r.t        | d   j                               t        k7  rt        d       | D cg c]  }|d   	 }}|t
        k7  rt        d|        | D ]p  }|d   dk7  rt        d	|        |d
   r
|d   r|d   st        d|        |d   dv r&d|d   j                         vrt        d|d           t        |d          r |j                  d       |S c c}w )N   z.manifest must have one row per quarter; found r   zmanifest field order changedr   z#manifest period coverage mismatch: r   EQIXzunexpected manifest company: r.   r1   r2   z,manifest missing required provenance field: >   r   r   
cumulativez.manifest must flag cumulative capex basis for r   zEmanifest has 8 primary-source rows with period-specific basis caveats)	lenr8   r@   keysMANIFEST_FIELDSEXPECTED_PERIODSr\   r`   append)manifest_rowschecksrowperiodss       r7   validate_manifestrn   k   s0   F
=Q=c->P=QRSmA.3356/I+,(56s8}6G6""27)<= 0y>V#067=!-G)HPSTcPd?uEFx=,,SEYE_E_Ea1aA#h-QRS./0 MMYZM 7s   D	c                   g }|D ch c]  }|d   	 }}|D ch c]  }|d   	 }}t        |       dk7  rt        dt        |               | r.t        | d   j                               t        k7  rt        d       t
        D ci c]  }|g  }}| D ]  }|d   |vrt        d|d           ||d      j                  |       t        D ]%  }||   dk(  st        d	| d
|d    d|d           ' |d   dk7  rt        d|        |d   |vrt        d|d           t        |d          |d   |vrd|d   vrt        d|d           |d   dvrt        d|        |d   dvst        d|         |j                         D ]1  \  }}	|	D cg c]  }|d   	 }
}|
t        k7  s"t        | d|
        3 | D ]O  }|d   dk(  rt        |       |d   dk(  rt        |       +|d   dk(  rt        |       ?t        d|d           Q |j                  d       |j                  d       |j                  d        |S c c}w c c}w c c}w c c}w )!Nr   r      z5row count must be 24 (8 quarters x 3 metrics); found r   z<canonical row field order does not match the 16-field schemazunexpected row period: r;   zmissing z in  r   r   rc   zunexpected row company: z!row period absent from manifest: earnings_presentationz?row URL is not manifest URL or explicit presentation fallback: r   >   exactdirectpartialzbad snippet support status: r   >   highmediumzbad confidence label: z metrics/order mismatch: r   r   r    zunexpected metric: zJcanonical output has 24 rows, 8-quarter coverage, and required field orderz4capex rows pass quarterly-vs-cumulative basis checksz:metric units and bases are separated with retained caveats)re   r8   r@   rf   REQUIRED_FIELDSrh   ri   r`   itemsEXPECTED_METRICSvalidate_capexvalidate_pipelinevalidate_revenue)rowsrj   rk   rl   manifest_periodsmanifest_urlsr   	by_periodfieldperiod_rowsmetricss              r7   validate_rowsr      s   F1>?#H??2?@3S&@M@
4yBDSYKPQT!W\\^$7KLK[1\&"*1\I1\ 1x=	)*3x=/:;#h- '',$ 	QE5zRxwd3x=/3};M:NOP	Q y>V#+C512x= 004S]ODES./|M16MUXYeUf6fRSVWcSdRefg'(0NN/u56|$66)#/0%1(  )0 @1<=#3}%==&&F84WI>?@
  =}03#==c"#77S!&s='9&:;<= MM^_
MMHI
MMNOM_ @@ 2], >s   II
IIc                     d   }t         |   \  }}} d   dk7  rt        d          d   dk7  rt        d          d   d	k7  rt        d
         t         d         t         d         k7  rt        d         t         d         t        |      k7  rt        | d| d d            d   |k7  rt        | d| d         | d   vr| d   vrt        | d| d         t	         fdt
        D              }|r d   dk7  r|dk7  rt        d          d   dk(  r%d d   j                         vrt        d         y y y )Nr   r   actual_capex_spendz&capex not classified as actual spend: r   USD_millionszcapex unit mismatch: r    consolidated_company_capex_tablezcapex basis mismatch: r	   r
   zcapex raw/normalized mismatch: z  capex expected quarterly value z, found r   z capex derived flag should be z: r   r   z, capex lacks required source-period context c              3  >   K   | ]  }|d    v xs |d   v   yw)r   r   NrU   )rV   rW   rl   s     r7   rY   z!validate_capex.<locals>.<genexpr>   s7        	#'((KFc:J6K,KK s   r(   r   zHcumulative capex source cannot be used as non-derived quarterly actual: lessz7derived capex row lacks arithmetic support in snippet: )EXPECTED_CAPEXr8   rR   r   r]   CUMULATIVE_CAPEX_MARKERSr\   )rl   r   expected_valueexpected_derivedrequired_contexthas_cumulative_markers   `     r7   r{   r{      s   ]F9G9O6N$&6
 $885cU;<
6{n$$SE*+
!CC%cU+,c+6#.@*A#BB.se45c$%&'.*AAx77GxPSTfPgOhij
<,,x56F5Gr#OPs#455:JRUVfRg:gxCDTCUUWX[W\]^  .   \!2f!<6AQWX[W\]^
<F"vS9I5J5P5P5R'RFseLM (S"r9   c                   | d   dk7  rt        d|         | d   dvrt        d|         | d   dk(  rk| d   d	k7  rt        d
|         d| d   vrd| d   vrt        d|         t        | d         t        d      z  t        | d         k7  rt        d|         y y t        | d         t        | d         k7  rt        d|         y y )Nr   forecast_pipeline_estimatez2pipeline row not classified as forecast estimate: r   >   rM   projectsz:pipeline unit must be projects or explicitly caveated MW: rM   r   approximatez%MW pipeline row must be approximate: znot MW live capacityr   znot live energized capacityz,MW pipeline row lacks live-capacity caveat: r	     r
   z!GW to MW normalization mismatch: z,project-count pipeline conversion mismatch: r8   rR   r   )rl   s    r7   r|   r|      s   
 $@@A#GH
6{,,I#OP
6{d !]28>?!X6;X`cdl`m;m?uEF#k"#gdm3vcBT>U7VV4SE:; W	K 	!VC0B,C%D	D;C5AB 
Er9   c                
   | d   dk7  rt        d|         | d   dk7  rt        d|         t        | d         t        d      z  }|t        | d	         k7  rt        d
|         d| d   vrd| d   vrt        d|         y y y )Nr   actual_reported_quarterz!revenue classification mismatch: r   USD_billionsz6revenue unit should be USD_billions after conversion: r	   r   r
   z2revenue millions-to-billions conversion mismatch: znormalized to USD billionsr   zsummary uses USD billionsz%revenue row lacks conversion caveat: r   )rl   expecteds     r7   r}   r}      s    
 $==067
6{n$EcUKLc+&''$-7H6#0122A#GH#3x=8=X`cdl`m=m4SE:; >n8r9   c                     t         j                  d      } | j                  d      dk  rt        d       dD ]  }|| vst        d|         dgS )	Nr<   )r>   z**Primary snippet   z;verification report must sample at least 3 primary snippets)zSample AzSample BzSample CzSample DzCumulative capex controlz=2,875 is a 9M cumulative PP&E value, not 3Q25 quarterly capexzProduction gate statuszverification report missing zIverification report documents cumulative capex control and source samples)REPORT	read_textcountr8   )texttokens     r7   validate_reportr      sg    W-Dzz%&*JK 
9 /w78
9 XXXr9   c                 T   t        j                  t        j                  t	        t
              gt        d       t        t              } t        t              }g }|j                  t        |              |j                  t        ||              |j                  t                      |S )NT)cwdcheck)
subprocessrunsys
executablestr	EXTRACTORBASE_DIRrE   MANIFESTROWSextendrn   r   r   )rj   r~   rk   s      r7   validater      sp    NNCNNC	N3NX&MD>DF
MM#M23
MM-m45
MM/#$Mr9   c                 X    t               } t        d       | D ]  }t        d|         y )Nz'PASS: EQIX quarterly package validates.z  - )r   print)rk   r   s     r7   mainr   
  s/    ZF	
34 UGnr9   __main__)r6   r   returnNone)rC   r   r   list[dict[str, str]])rP   r   r   r   )r_   r   r   r   )rj   r   r   	list[str])r~   r   rj   r   r   r   )rl   zdict[str, str]r   r   )r   r   )r   r   )'__doc__
__future__r   rA   r   r   decimalr   pathlibr   __file__resolveparentr   r   r   r   r   rx   rh   rz   r   r   rg   r[   r^   r8   rE   rR   r`   rn   r   r{   r|   r}   r   r   r   __name__rU   r9   r7   <module>r      s   = " 
  
   >!!#**22	00/!	1	1& T V 2222/1;3	 \ 	 
 ",
2*1hN:C 	<Y$ zF r9   