<s> import ast <EOL> import os <EOL> from . context import Context <EOL> class BaseAnalyzer ( object ) : <EOL> """<STR_LIT>""" <EOL> surround_by = <NUM_LIT:2> <EOL> def __init__ ( self , code_dict , repo_path ) : <EOL> self . _file_lines = None <EOL> self . code_dict = code_dict <EOL> self . repo_path = repo_path <EOL> def get_file_lines ( self , filepath , start , stop ) : <EOL> """<STR_LIT>""" <EOL> if self . _file_lines is None : <EOL> with open ( os . path . join ( self . repo_path , filepath ) ) as f : <EOL> self . _file_lines = f . readlines ( ) <EOL> if stop is None : <EOL> lines = self . _file_lines [ start - <NUM_LIT:1> : ] <EOL> else : <EOL> lines = self . _file_lines [ start - <NUM_LIT:1> : stop ] <EOL> for i , line in enumerate ( lines ) : <EOL> lines [ i ] = [ start + i , True , line . rstrip ( ) ] <EOL> while lines and self . is_empty_line ( lines [ - <NUM_LIT:1> ] [ - <NUM_LIT:1> ] ) : <EOL> lines . pop ( ) <EOL> if not lines : <EOL> return [ ] <EOL> stop = lines [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] <EOL> start = max ( <NUM_LIT:1> , stop - self . surround_by ) <EOL> prefix_lines = [ ] <EOL> for i , line in enumerate ( self . _file_lines [ start - <NUM_LIT:1> : stop - <NUM_LIT:1> ] , start = start ) : <EOL> prefix_lines . append ( [ i , False , line . rstrip ( ) ] ) <EOL> start = lines [ - <NUM_LIT:1> ] [ <NUM_LIT:0> ] + <NUM_LIT:1> <EOL> stop = start + self . surround_by <EOL> suffix_lines = [ ] <EOL> for i , line in enumerate ( self . _file_lines [ start - <NUM_LIT:1> : stop - <NUM_LIT:1> ] , start = start ) : <EOL> suffix_lines . append ( [ i , False , line . rstrip ( ) ] ) <EOL> return prefix_lines + lines + suffix_lines <EOL> def is_empty_line ( self , line ) : <EOL> return not line . split ( '<STR_LIT:#>' ) [ <NUM_LIT:0> ] . strip ( ) <EOL> def clear_file_lines_cache ( self ) : <EOL> self . _file_lines = None <EOL> def analyze_file ( self , filepath , code ) : <EOL> raise NotImplementedError <EOL> def analyze ( self ) : <EOL> """<STR_LIT>""" <EOL> for filepath , code in self . code_dict . items ( ) : <EOL> for result in self . analyze_file ( filepath , code ) : <EOL> yield result <EOL> self . clear_file_lines_cache ( ) <EOL> class CodeSnippet ( list ) : <EOL> """<STR_LIT>""" <EOL> def add_line ( self , lineno , text , important = True ) : <EOL> """<STR_LIT>""" <EOL> self . append ( ( lineno , important , text ) ) <EOL> class Result ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , description , path , line ) : <EOL> self . description = description <EOL> self . path = path <EOL> self . line = line <EOL> self . source = CodeSnippet ( ) <EOL> self . solution = CodeSnippet ( ) <EOL> class AttributeVisitor ( ast . NodeVisitor ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . is_usable = True <EOL> self . name = [ ] <EOL> def get_name ( self ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT:.>' . join ( self . name ) <EOL> def visit_Attribute ( self , node ) : <EOL> self . generic_visit ( node ) <EOL> self . name . append ( node . attr ) <EOL> def visit_Name ( self , node ) : <EOL> self . name . append ( node . id ) <EOL> def visit_Load ( self , node ) : <EOL> pass <EOL> def generic_visit ( self , node ) : <EOL> if not isinstance ( node , ast . Attribute ) : <EOL> self . is_usable = False <EOL> ast . NodeVisitor . generic_visit ( self , node ) <EOL> def set_lineno ( meth ) : <EOL> def decorator ( self , node ) : <EOL> self . push_lineno ( node . lineno ) <EOL> result = meth ( self , node ) <EOL> self . pop_lineno ( ) <EOL> return result <EOL> decorator . __name__ = meth . __name__ <EOL> return decorator <EOL> class ModuleVisitor ( ast . NodeVisitor ) : <EOL> """<STR_LIT>""" <EOL> interesting = { } <EOL> def __init__ ( self ) : <EOL> self . names = Context ( ) <EOL> self . lineno = [ ] <EOL> self . found = { } <EOL> def add_found ( self , name , node ) : <EOL> lineno_level = self . get_lineno_level ( ) <EOL> if lineno_level not in self . found : <EOL> self . found [ lineno_level ] = [ ] <EOL> self . found [ lineno_level ] . append ( [ name , node , self . get_lineno ( ) , None ] ) <EOL> def get_found ( self ) : <EOL> for level in self . found . values ( ) : <EOL> for found in level : <EOL> yield found <EOL> def push_lineno ( self , lineno ) : <EOL> self . lineno . append ( lineno ) <EOL> lineno_level = self . get_lineno_level ( ) <EOL> for level in self . found . keys ( ) : <EOL> if level < lineno_level : <EOL> return <EOL> for found in self . found [ level ] : <EOL> if found [ - <NUM_LIT:1> ] is None and lineno >= found [ - <NUM_LIT:2> ] : <EOL> found [ - <NUM_LIT:1> ] = max ( lineno - <NUM_LIT:1> , found [ - <NUM_LIT:2> ] ) <EOL> def pop_lineno ( self ) : <EOL> return self . lineno . pop ( ) <EOL> def get_lineno ( self ) : <EOL> return self . lineno [ - <NUM_LIT:1> ] <EOL> def get_lineno_level ( self ) : <EOL> return len ( self . lineno ) <EOL> def update_names ( self , aliases , get_path ) : <EOL> """<STR_LIT>""" <EOL> for alias in aliases : <EOL> path = get_path ( alias . name ) <EOL> if path not in self . interesting : <EOL> continue <EOL> if self . interesting [ path ] : <EOL> for attr in self . interesting [ path ] : <EOL> name = '<STR_LIT:.>' . join ( ( alias . asname or alias . name , attr ) ) <EOL> self . names [ name ] = '<STR_LIT:.>' . join ( ( path , attr ) ) <EOL> else : <EOL> name = alias . asname or alias . name <EOL> self . names [ name ] = path <EOL> @ set_lineno <EOL> def visit_Import ( self , node ) : <EOL> self . update_names ( node . names , lambda x : x ) <EOL> @ set_lineno <EOL> def visit_ImportFrom ( self , node ) : <EOL> self . update_names ( node . names , lambda x : '<STR_LIT:.>' . join ( ( node . module , x ) ) ) <EOL> @ set_lineno <EOL> def visit_FunctionDef ( self , node ) : <EOL> self . names . push ( ) <EOL> self . generic_visit ( node ) <EOL> self . names . pop ( ) <EOL> @ set_lineno <EOL> def visit_Assign ( self , node ) : <EOL> visitor = AttributeVisitor ( ) <EOL> visitor . visit ( node . value ) <EOL> if not visitor . is_usable : <EOL> self . generic_visit ( node ) <EOL> return <EOL> name = visitor . get_name ( ) <EOL> if name not in self . names : <EOL> return <EOL> for target in node . targets : <EOL> visitor = AttributeVisitor ( ) <EOL> visitor . visit ( target ) <EOL> if not visitor . is_usable : <EOL> continue <EOL> target = visitor . get_name ( ) <EOL> self . names [ target ] = self . names [ name ] <EOL> @ set_lineno <EOL> def visit_Call ( self , node ) : <EOL> self . generic_visit ( node ) <EOL> @ set_lineno <EOL> def visit_List ( self , node ) : <EOL> self . generic_visit ( node ) <EOL> @ set_lineno <EOL> def visit_Tuple ( self , node ) : <EOL> self . generic_visit ( node ) <EOL> class DeprecatedCodeVisitor ( ModuleVisitor ) : <EOL> def visit_Attribute ( self , node ) : <EOL> visitor = AttributeVisitor ( ) <EOL> visitor . visit ( node ) <EOL> if visitor . is_usable : <EOL> name = visitor . get_name ( ) <EOL> if name in self . names : <EOL> self . add_found ( self . names [ name ] , node ) <EOL> def visit_Name ( self , node ) : <EOL> if node . id in self . names : <EOL> self . add_found ( self . names [ node . id ] , node ) </s>
