<s> import re <EOL> class LineItem ( object ) : <EOL> def __init__ ( self , line ) : <EOL> self . line = line <EOL> self . text = line . strip ( ) <EOL> self . parent = self <EOL> self . children = None <EOL> def add_children ( self , child ) : <EOL> if self . children : <EOL> self . children . append ( child ) <EOL> else : <EOL> self . children = [ child ] <EOL> def str_list ( self ) : <EOL> if self . children : <EOL> return [ self . line ] + [ i . str_list ( ) for i in self . children ] <EOL> else : <EOL> return self . line <EOL> def re_search_children ( self , linespec ) : <EOL> return HTParser ( self . str_list ( ) ) . find_objects ( linespec ) <EOL> def re_match ( self , regex , group = <NUM_LIT:1> , default = "<STR_LIT>" ) : <EOL> match = re . match ( regex , self . line ) <EOL> return match . group ( group ) if match else default <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" . format ( self . __class__ . __name__ , self . text ) <EOL> def __eq__ ( self , other ) : <EOL> return self . str_list ( ) == other . str_list ( ) <EOL> class HTParser ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , cfg ) : <EOL> self . _indent_list = [ ] <EOL> if isinstance ( cfg , list ) : <EOL> self . cfg = cfg <EOL> elif isinstance ( cfg , str ) : <EOL> self . cfg = [ x for x in cfg . splitlines ( ) if x ] <EOL> else : <EOL> raise TypeError <EOL> def _build_indent_based_list ( self ) : <EOL> self . _indent_list = [ ] <EOL> for line in self . cfg : <EOL> match = re . match ( r'<STR_LIT>' , line ) <EOL> if match : <EOL> item = ( len ( match . group ( <NUM_LIT:1> ) ) , line ) <EOL> self . _indent_list . append ( item ) <EOL> def _find_starts ( self , linespec ) : <EOL> """<STR_LIT>""" <EOL> linespec += "<STR_LIT>" <EOL> start_points = [ ] <EOL> for item in self . _indent_list : <EOL> match = re . search ( linespec , item [ <NUM_LIT:1> ] ) <EOL> if match : <EOL> entry = ( item , self . _indent_list . index ( item ) ) <EOL> start_points . append ( entry ) <EOL> return start_points <EOL> def _find_next_indent_level ( self , index ) : <EOL> current_indent_level = self . _indent_list [ index ] [ <NUM_LIT:0> ] <EOL> for item in self . _indent_list [ ( index + <NUM_LIT:1> ) : ] : <EOL> if item [ <NUM_LIT:0> ] > current_indent_level : <EOL> return item [ <NUM_LIT:0> ] <EOL> else : <EOL> return None <EOL> def find_lines ( self , linespec ) : <EOL> """<STR_LIT>""" <EOL> res = [ ] <EOL> linespec += "<STR_LIT>" <EOL> for line in self . cfg : <EOL> match = re . search ( linespec , line ) <EOL> if match : <EOL> res . append ( match . group ( <NUM_LIT:0> ) ) <EOL> return res <EOL> def find_objects ( self , linespec ) : <EOL> """<STR_LIT>""" <EOL> res = [ ] <EOL> self . _build_indent_based_list ( ) <EOL> for item , index in self . _find_starts ( linespec ) : <EOL> parent = LineItem ( item [ <NUM_LIT:1> ] ) <EOL> next_ident_level = self . _find_next_indent_level ( index ) <EOL> if next_ident_level : <EOL> for item in self . _indent_list [ ( index + <NUM_LIT:1> ) : ] : <EOL> if item [ <NUM_LIT:0> ] == next_ident_level : <EOL> parent . add_children ( LineItem ( item [ <NUM_LIT:1> ] ) ) <EOL> elif item [ <NUM_LIT:0> ] > next_ident_level : <EOL> continue <EOL> else : <EOL> break <EOL> res . append ( parent ) <EOL> return res <EOL> def find_children ( self , linespec ) : <EOL> """<STR_LIT>""" <EOL> res = [ ] <EOL> for parent in self . find_objects ( linespec ) : <EOL> res . append ( parent . line ) <EOL> res . extend ( [ child . line for child in parent . children ] ) <EOL> return res </s>
