<s> from cStringIO import StringIO <EOL> import compiler <EOL> import inspect <EOL> import textwrap <EOL> import tokenize <EOL> from compiler_unparse import unparse <EOL> class Comment ( object ) : <EOL> """<STR_LIT>""" <EOL> is_comment = True <EOL> def __init__ ( self , start_lineno , end_lineno , text ) : <EOL> self . start_lineno = start_lineno <EOL> self . end_lineno = end_lineno <EOL> self . text = text <EOL> def add ( self , string , start , end , line ) : <EOL> """<STR_LIT>""" <EOL> self . start_lineno = min ( self . start_lineno , start [ <NUM_LIT:0> ] ) <EOL> self . end_lineno = max ( self . end_lineno , end [ <NUM_LIT:0> ] ) <EOL> self . text += string <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . __class__ . __name__ , self . start_lineno , <EOL> self . end_lineno , self . text ) <EOL> class NonComment ( object ) : <EOL> """<STR_LIT>""" <EOL> is_comment = False <EOL> def __init__ ( self , start_lineno , end_lineno ) : <EOL> self . start_lineno = start_lineno <EOL> self . end_lineno = end_lineno <EOL> def add ( self , string , start , end , line ) : <EOL> """<STR_LIT>""" <EOL> if string . strip ( ) : <EOL> self . start_lineno = min ( self . start_lineno , start [ <NUM_LIT:0> ] ) <EOL> self . end_lineno = max ( self . end_lineno , end [ <NUM_LIT:0> ] ) <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( self . __class__ . __name__ , self . start_lineno , <EOL> self . end_lineno ) <EOL> class CommentBlocker ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . current_block = NonComment ( <NUM_LIT:0> , <NUM_LIT:0> ) <EOL> self . blocks = [ ] <EOL> self . index = { } <EOL> def process_file ( self , file ) : <EOL> """<STR_LIT>""" <EOL> for token in tokenize . generate_tokens ( file . next ) : <EOL> self . process_token ( * token ) <EOL> self . make_index ( ) <EOL> def process_token ( self , kind , string , start , end , line ) : <EOL> """<STR_LIT>""" <EOL> if self . current_block . is_comment : <EOL> if kind == tokenize . COMMENT : <EOL> self . current_block . add ( string , start , end , line ) <EOL> else : <EOL> self . new_noncomment ( start [ <NUM_LIT:0> ] , end [ <NUM_LIT:0> ] ) <EOL> else : <EOL> if kind == tokenize . COMMENT : <EOL> self . new_comment ( string , start , end , line ) <EOL> else : <EOL> self . current_block . add ( string , start , end , line ) <EOL> def new_noncomment ( self , start_lineno , end_lineno ) : <EOL> """<STR_LIT>""" <EOL> block = NonComment ( start_lineno , end_lineno ) <EOL> self . blocks . append ( block ) <EOL> self . current_block = block <EOL> def new_comment ( self , string , start , end , line ) : <EOL> """<STR_LIT>""" <EOL> prefix = line [ : start [ <NUM_LIT:1> ] ] <EOL> if prefix . strip ( ) : <EOL> self . current_block . add ( string , start , end , line ) <EOL> else : <EOL> block = Comment ( start [ <NUM_LIT:0> ] , end [ <NUM_LIT:0> ] , string ) <EOL> self . blocks . append ( block ) <EOL> self . current_block = block <EOL> def make_index ( self ) : <EOL> """<STR_LIT>""" <EOL> for prev , block in zip ( self . blocks [ : - <NUM_LIT:1> ] , self . blocks [ <NUM_LIT:1> : ] ) : <EOL> if not block . is_comment : <EOL> self . index [ block . start_lineno ] = prev <EOL> def search_for_comment ( self , lineno , default = None ) : <EOL> """<STR_LIT>""" <EOL> if not self . index : <EOL> self . make_index ( ) <EOL> block = self . index . get ( lineno , None ) <EOL> text = getattr ( block , '<STR_LIT:text>' , default ) <EOL> return text <EOL> def strip_comment_marker ( text ) : <EOL> """<STR_LIT>""" <EOL> lines = [ ] <EOL> for line in text . splitlines ( ) : <EOL> lines . append ( line . lstrip ( '<STR_LIT:#>' ) ) <EOL> text = textwrap . dedent ( '<STR_LIT:\n>' . join ( lines ) ) <EOL> return text <EOL> def get_class_traits ( klass ) : <EOL> """<STR_LIT>""" <EOL> source = inspect . getsource ( klass ) <EOL> cb = CommentBlocker ( ) <EOL> cb . process_file ( StringIO ( source ) ) <EOL> mod_ast = compiler . parse ( source ) <EOL> class_ast = mod_ast . node . nodes [ <NUM_LIT:0> ] <EOL> for node in class_ast . code . nodes : <EOL> if isinstance ( node , compiler . ast . Assign ) : <EOL> name = node . nodes [ <NUM_LIT:0> ] . name <EOL> rhs = unparse ( node . expr ) . strip ( ) <EOL> doc = strip_comment_marker ( cb . search_for_comment ( node . lineno , default = '<STR_LIT>' ) ) <EOL> yield name , rhs , doc </s>
