
    %j5              	         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 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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g dZdZdZd+dZd,dZd-dZ d.dZ!d/d Z"d0d!Z#d1d"Z$d1d#Z%d1d$Z&d2d%Z'd3d&Z(d4d'Z)d2d(Z*d5d)Z+e,d*k(  r e+        yy)6z7Validate the EQIX quarterly-results production package.    )annotationsN)Decimal)Pathzextract_eqix_quarterly.pyeqix_source_manifest.csveqix_rows.csvzeqix_verification_report.mdzeqix_verification_samples.csvzeqix_validation_summary.json)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)	sample_idr   r	   r
   r   r   r   
check_typer   r   r   verdictr   r   )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-loop02/artifacts/validate_eqix_quarterly.pyfailr=   _   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     r<   read_csvrJ   c   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     r<   numberrW   h   sq    c2	b		b		b		b		r		r		  7r>   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r9    ).0markerlowereds     r<   	<genexpr>z'validate_primary_url.<locals>.<genexpr>z   s     
=6W
=s   zsecondary source rejected: )
startswithPRIMARY_URL_PREFIXESr=   loweranySECONDARY_MARKERS)urlr]   s    @r<   validate_primary_urlre   v   sO    >>./'u-.iikG

=+<
==*3%01 >r>   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: r0   r3   r4   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)	lenr=   rE   keysMANIFEST_FIELDSEXPECTED_PERIODSra   re   append)manifest_rowschecksrowperiodss       r<   validate_manifestrs   ~   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   rh   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)rj   r=   rE   rk   REQUIRED_FIELDSrm   rn   re   itemsEXPECTED_METRICSvalidate_capexvalidate_pipelinevalidate_revenue)rowsro   rp   rq   manifest_periodsmanifest_urlsr	   	by_periodfieldperiod_rowsmetricss              r<   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 : r   r   z, capex lacks required source-period context c              3  >   K   | ]  }|d    v xs |d   v   yw)r   r   NrZ   )r[   r\   rq   s     r<   r^   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_CAPEXr=   rW   r   rb   CUMULATIVE_CAPEX_MARKERSra   )rq   r	   expected_valueexpected_derivedrequired_contexthas_cumulative_markers   `     r<   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"r>   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   >   rR   projectsz:pipeline unit must be projects or explicitly caveated MW: rR   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: r=   rW   r   )rq   s    r<   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r>   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   )rq   expecteds     r<   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8r>   c                     t         j                  d      } | j                  d      dk  rt        d       dD ]  }|| vst        d|         dgS )	NrA   rC   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countr=   )texttokens     r<   validate_reportr      sg    W-Dzz%&*JK 
9 /w78
9 XXXr>   c           	        t        t              }t        |      dk  rt        dt        |              |rKt	        |d   j                               t        k7  r(t        dt	        |d   j                                       | D ch c]  }|d   |d   |d   |d   |d	   f }}d}d}|D ]  }t        D ]  }||   d
k(  st        d| d|         t        |d          |d   |d   |d   |d   |d	   f}||vrt        d|        |d   dk(  r|dz  }n|d   dk(  r|dz  }nt        d|        |d   dvst        d|         dt        |       d| dgS c c}w )N   z7verification CSV needs at least 12 sampled rows, found r   z'verification CSV field order mismatch: r   r	   r
   r   r   r@   zverification sample missing r   r   z4verification sample does not match a canonical row: r7   PASS   FAILz)verification sample has invalid verdict: r   >   r{   r|   z,verification sample has invalid confidence: zverification CSV has z# samples with required columns and z pass verdicts)rJ   SAMPLESrj   r=   rE   rk   SAMPLE_FIELDSre   )	r   samplesrq   row_keys
pass_count
fail_countsampler   keys	            r<   validate_samplesr     s   wG
7|bFs7|nUV4
)*m;6tGAJOO<M7N6OPQ  
YXM(:C<LcRdNefH  JJ J" 	GEe}"3E7"VHEF	G 	VL1298=!;%&
 hGxPQ)&!OJI&(!OJ<VHEF,'99?xHI+J. $CL>1TU_T``nopp;s   Ec                   t        t              }t        d |D              }t        d |D              }ddt        |      ||dd|dk(  rdndd	d
ddddd| d}t        j                  t        j                  |d      dz   d       y )Nc              3  2   K   | ]  }|d    dk(  sd  yw)r7   r   r   NrZ   r[   r   s     r<   r^   z write_summary.<locals>.<genexpr>;       L6y0AV0KQL   c              3  2   K   | ]  }|d    dk(  sd  yw)r7   r   r   NrZ   r   s     r<   r^   z write_summary.<locals>.<genexpr><  r   r   rh   z,auto-continue-20260607T140730Z-repair-loop02zvalidate_eqix_quarterly.pyr   r   r   )scriptexpected_exit_codestatusr   r   ru   r      )canonical_rows_filemanifest_file	row_countmetrics_per_periodrequired_fields)r   runsampled_row_countr   r   	validatorrow_packagerp      )indent
rA   r   )rJ   r   sumrj   SUMMARY
write_textjsondumps)rp   r   r   r   summarys        r<   write_summaryr   9  s    wGLWLLJLWLLJ= \  2"# *afV
 $37"#!
 %G( tzz'!4t;gNr>   c                    t        j                  t        j                  t	        t
              gt        d       t        t              } t        t              }g }|j                  t        |              |j                  t        ||              |j                  t                      |j                  t        |             t        |       |S )NT)cwdcheck)
subprocessr   sys
executablestr	EXTRACTORBASE_DIRrJ   MANIFESTROWSextendrs   r   r   r   r   )ro   r   rp   s      r<   validater   T  s    NNCNNC	N3NX&MD>DF
MM#M23
MM-m45
MM/#$
MM"4()&Mr>   c                 X    t               } t        d       | D ]  }t        d|         y )Nz'PASS: EQIX quarterly package validates.z  - )r   print)rp   r   s     r<   mainr   a  s/    ZF	
34 UGnr>   __main__)r;   r   returnNone)rH   r   r   list[dict[str, str]])rU   r   r   r   )rd   r   r   r   )ro   r   r   	list[str])r   r   ro   r   r   r   )rq   zdict[str, str]r   r   )r   r   )r   r   r   r   )rp   r   r   r   )r   r   )-__doc__
__future__r   rF   r   r   r   decimalr   pathlibr   __file__resolveparentr   r   r   r   r   r   r   r}   rm   r   r   r   rl   r   r`   rc   r=   rJ   rW   re   rs   r   r   r   r   r   r   r   r   r   __name__rZ   r>   r<   <module>r      s5   = " 
   
   >!!#**22	00/!	1	1
4
4
3
3& T V 2222/1;3	 \ 	  
 ",
2*1hN:C 	<Y$$qNO6
 zF r>   