#!/usr/bin/env python3 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  os 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  bz2 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  urllib . parse 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  subprocess 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  tqdm 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  glob 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  tempfile  import  TemporaryDirectory 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  capnp 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  tools . lib . logreader  import  FileReader ,  LogReader 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  cereal  import  log  as  capnp_log 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  RobustLogReader ( LogReader ) : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  def  __init__ ( self ,  fn ,  canonicalize = True ,  only_union_types = False ,  sort_by_time = False ) :   # pylint: disable=super-init-not-called 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    data_version  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    _ ,  ext  =  os . path . splitext ( urllib . parse . urlparse ( fn ) . path ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    with  FileReader ( fn )  as  f : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dat  =  f . read ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ext  ==  " " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      pass 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    elif  ext  ==  " .bz2 " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      try : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dat  =  bz2 . decompress ( dat ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      except  ValueError : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        print ( " Failed to decompress, falling back to bzip2recover " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        with  TemporaryDirectory ( )  as  directory : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          # Run bzip2recovery on log 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          with  open ( os . path . join ( directory ,  ' out.bz2 ' ) ,  ' wb ' )  as  f : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            f . write ( dat ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          subprocess . check_call ( [ " bzip2recover " ,  " out.bz2 " ] ,  cwd = directory ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          # Decompress and concatenate parts 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          dat  =  b " " 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          for  n  in  sorted ( glob . glob ( f " { directory } /rec*.bz2 " ) ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            print ( f " Decompressing  { n } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            with  open ( n ,  ' rb ' )  as  f : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              dat  + =  bz2 . decompress ( f . read ( ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      raise  Exception ( f " unknown extension  { ext } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    progress  =  None 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  True : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      try : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ents  =  capnp_log . Event . read_multiple_bytes ( dat ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . _ents  =  list ( sorted ( ents ,  key = lambda  x :  x . logMonoTime )  if  sort_by_time  else  ents ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        break 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      except  capnp . lib . capnp . KjException : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  progress  is  None : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          progress  =  tqdm . tqdm ( total = len ( dat ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Cut off bytes at the end until capnp is able to read 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dat  =  dat [ : - 1 ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        progress . update ( 1 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _ts  =  [ x . logMonoTime  for  x  in  self . _ents ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . data_version  =  data_version 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    self . _only_union_types  =  only_union_types