#!/usr/bin/env python3 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								import  argparse 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								from  collections  import  defaultdict 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								import  difflib 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								import  pickle 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								from  selfdrive . car . docs  import  get_all_car_info 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								from  selfdrive . car . docs_definitions  import  Column 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								FOOTNOTE_TAG  =  " <sup> {} </sup> " 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								STAR_ICON  =  ' <a href= " ## " ><img valign= " top "  src= " https://raw.githubusercontent.com/commaai/openpilot/master/docs/assets/icon-star- {} .svg "  width= " 22 "  /></a> ' 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								COLUMNS  =  " | "  +  " | " . join ( [ column . value  for  column  in  Column ] )  +  " | " 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								COLUMN_HEADER  =  " |---|---|---| {} | " . format ( " | " . join ( [ " :---: " ]  *  ( len ( Column )  -  3 ) ) ) 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								ARROW_SYMBOL  =  " ➡️  " 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								def  load_base_car_info ( path ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  with  open ( path ,  " rb " )  as  f : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    return  pickle . load ( f ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								def  match_cars ( base_cars ,  new_cars ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  changes  =  [ ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  additions  =  [ ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  for  new  in  new_cars : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								    # Addition if no close matches or close match already used 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    # Change if close match and not already used 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    matches  =  difflib . get_close_matches ( new . name ,  [ b . name  for  b  in  base_cars ] ,  cutoff = 0. ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    if  not  len ( matches )  or  matches [ 0 ]  in  [ c [ 1 ] . name  for  c  in  changes ] : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								      additions . append ( new ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								    else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								      changes . append ( ( new ,  next ( car  for  car  in  base_cars  if  car . name  ==  matches [ 0 ] ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								  # Removal if base car not in changes 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								  removals  =  [ b  for  b  in  base_cars  if  b . name  not  in  [ c [ 1 ] . name  for  c  in  changes ] ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  return  changes ,  additions ,  removals 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								def  build_column_diff ( base_car ,  new_car ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  row_builder  =  [ ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  for  column  in  Column : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    base_column  =  base_car . get_column ( column ,  STAR_ICON ,  FOOTNOTE_TAG ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    new_column  =  new_car . get_column ( column ,  STAR_ICON ,  FOOTNOTE_TAG ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								    if  base_column  !=  new_column : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								      row_builder . append ( f " { base_column }   { ARROW_SYMBOL }   { new_column } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								      row_builder . append ( new_column ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								  return  format_row ( row_builder ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								def  format_row ( builder ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  return  " | "  +  " | " . join ( builder )  +  " | " 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								def  print_car_info_diff ( path ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  base_car_info  =  defaultdict ( list ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  new_car_info  =  defaultdict ( list ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  for  car  in  load_base_car_info ( path ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    base_car_info [ car . car_fingerprint ] . append ( car ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  for  car  in  get_all_car_info ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    new_car_info [ car . car_fingerprint ] . append ( car ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								  # Add new platforms to base cars so we can detect additions and removals in one pass 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  base_car_info . update ( { car :  [ ]  for  car  in  new_car_info  if  car  not  in  base_car_info } ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								  changes  =  defaultdict ( list ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  for  base_car_model ,  base_cars  in  base_car_info . items ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    # Match car info changes, and get additions and removals 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    new_cars  =  new_car_info [ base_car_model ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    car_changes ,  car_additions ,  car_removals  =  match_cars ( base_cars ,  new_cars ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    # Removals 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    for  car_info  in  car_removals : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								      changes [ " removals " ] . append ( format_row ( [ car_info . get_column ( column ,  STAR_ICON ,  FOOTNOTE_TAG )  for  column  in  Column ] ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    # Additions 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    for  car_info  in  car_additions : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								      changes [ " additions " ] . append ( format_row ( [ car_info . get_column ( column ,  STAR_ICON ,  FOOTNOTE_TAG )  for  column  in  Column ] ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    for  new_car ,  base_car  in  car_changes : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								      # Column changes 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								      row_diff  =  build_column_diff ( base_car ,  new_car ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								      if  ARROW_SYMBOL  in  row_diff : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								        changes [ " column " ] . append ( row_diff ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								      # Detail sentence changes 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								      if  base_car . detail_sentence  !=  new_car . detail_sentence : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								        changes [ " detail " ] . append ( f " - Sentence for  { base_car . name }  changed! \n "  + 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								                                 "   ```diff \n "  + 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								                                 f "   -  { base_car . detail_sentence } \n "  + 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								                                 f "   +  { new_car . detail_sentence } \n "  + 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								                                 "   ``` " ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  # Print diff 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								  if  any ( len ( c )  for  c  in  changes . values ( ) ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    markdown_builder  =  [ " ### ⚠️ ️  " ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								    for  title ,  category  in  ( ( " ## 🔀 Column Changes " ,  " column " ) ,  ( " ## ❌ Removed " ,  " removals " ) ,  ( " ## ➕ Added " ,  " additions " ) ,  ( " ## 📖 Detail Sentence Changes " ,  " detail " ) ) : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								      if  len ( changes [ category ] ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								        markdown_builder . append ( title ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								        if  category  not  in  ( " detail " , ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								          markdown_builder . append ( COLUMNS ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								          markdown_builder . append ( COLUMN_HEADER ) 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
								
								        markdown_builder . extend ( changes [ category ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								    print ( " \n " . join ( markdown_builder ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								if  __name__  ==  " __main__ " : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  parser  =  argparse . ArgumentParser ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  parser . add_argument ( " --path " ,  required = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  args  =  parser . parse_args ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
								
								  print_car_info_diff ( args . path )