<s> import ast <EOL> import os <EOL> from tests . unit import test <EOL> class DDTDecoratorChecker ( ast . NodeVisitor ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . classes = [ ] <EOL> self . errors = { } <EOL> @ classmethod <EOL> def _get_name ( cls , node ) : <EOL> if isinstance ( node , ast . Name ) : <EOL> return node . id <EOL> if isinstance ( node , ast . Attribute ) : <EOL> return cls . _get_name ( node . value ) + "<STR_LIT:.>" + node . attr <EOL> return "<STR_LIT>" <EOL> def _is_ddt ( self , cls_node ) : <EOL> return "<STR_LIT>" in ( self . _get_name ( d ) <EOL> for d in cls_node . decorator_list ) <EOL> def visit_ClassDef ( self , node ) : <EOL> self . classes . append ( node ) <EOL> self . generic_visit ( node ) <EOL> self . classes . pop ( ) <EOL> def visit_FunctionDef ( self , node ) : <EOL> if not self . classes : <EOL> return <EOL> cls = self . classes [ - <NUM_LIT:1> ] <EOL> if cls . name in self . errors : <EOL> return <EOL> for decorator in node . decorator_list : <EOL> if not isinstance ( decorator , ast . Call ) : <EOL> continue <EOL> funcname = self . _get_name ( decorator . func ) <EOL> if funcname . startswith ( "<STR_LIT>" ) : <EOL> if not self . _is_ddt ( cls ) : <EOL> msg = ( "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> cls . name ) <EOL> self . errors [ cls . name ] = { <EOL> "<STR_LIT>" : node . lineno , <EOL> "<STR_LIT:message>" : msg <EOL> } <EOL> class DDTDecoratorCheckerTestCase ( test . TestCase ) : <EOL> tests_path = os . path . join ( os . path . dirname ( __file__ ) ) <EOL> def test_ddt_class_decorator ( self ) : <EOL> """<STR_LIT>""" <EOL> errors = [ ] <EOL> for dirname , dirnames , filenames in os . walk ( self . tests_path ) : <EOL> for filename in filenames : <EOL> if not ( filename . startswith ( "<STR_LIT>" ) and <EOL> filename . endswith ( "<STR_LIT>" ) ) : <EOL> continue <EOL> filename = os . path . relpath ( os . path . join ( dirname , filename ) ) <EOL> with open ( filename , "<STR_LIT:rb>" ) as fh : <EOL> try : <EOL> tree = ast . parse ( fh . read ( ) , filename ) <EOL> except TypeError as err : <EOL> errors . append ( { "<STR_LIT:message>" : str ( err ) , <EOL> "<STR_LIT:filename>" : filename , <EOL> "<STR_LIT>" : - <NUM_LIT:1> } ) <EOL> visitor = DDTDecoratorChecker ( ) <EOL> visitor . visit ( tree ) <EOL> errors . extend ( <EOL> dict ( filename = filename , ** error ) <EOL> for error in visitor . errors . values ( ) ) <EOL> if errors : <EOL> msg = [ "<STR_LIT>" ] <EOL> for error in errors : <EOL> msg . extend ( [ <EOL> "<STR_LIT>" % { <EOL> "<STR_LIT:message>" : error [ "<STR_LIT:message>" ] , <EOL> "<STR_LIT:filename>" : error [ "<STR_LIT:filename>" ] , <EOL> "<STR_LIT>" : error [ "<STR_LIT>" ] } , <EOL> "<STR_LIT>" ] ) <EOL> self . fail ( "<STR_LIT:\n>" . join ( msg ) ) </s>
