1""" 2Test flake8 errors. 3""" 4from __future__ import absolute_import, print_function, division 5from nose.plugins.skip import SkipTest 6import os 7import sys 8from fnmatch import fnmatch 9import theano 10new_flake8 = True 11try: 12 import flake8.main 13 flake8_available = True 14 try: 15 import flake8.engine 16 new_flake8 = False 17 except ImportError: 18 import flake8.api.legacy 19except ImportError: 20 flake8_available = False 21 22__authors__ = ("Saizheng Zhang") 23__copyright__ = "(c) 2016, Universite de Montreal" 24__contact__ = "Saizheng Zhang <saizhenglisa..at..gmail.com>" 25 26# We ignore: 27# - "line too long" 28# too complex to do with the C code 29# - "closing bracket does not match indentation of opening bracket's line" 30# ignored by default by pep8 31# - "'with_statement' missing" 32# - "'unicode_literals' missing" 33# - "'generator_stop' missing" 34# - "'division' present" 35# - "'absolute_import' present" 36# - "'print_function' present" 37# - "expected 2 blank lines after class or function definition"' (E305) 38# - "ambiguous variable name" (E741) 39# Redundant error code generated by flake8-future-import module 40ignore = ('E501', 'E123', 'E133', 'FI12', 'FI14', 'FI15', 'FI16', 'FI17', 41 'FI18', 'FI50', 'FI51', 'FI53', 'E305', 'E741') 42 43whitelist_flake8 = [ 44 "__init__.py", 45 "_version.py", # This is generated by versioneer 46 "tests/__init__.py", 47 "compile/__init__.py", 48 "compile/sandbox/__init__.py", 49 "compile/tests/__init__.py", 50 "gpuarray/__init__.py", 51 "gpuarray/tests/__init__.py", 52 "typed_list/__init__.py", 53 "typed_list/tests/__init__.py", 54 "tensor/__init__.py", 55 "tensor/tests/__init__.py", 56 "tensor/tests/test_utils.py", 57 "tensor/tests/test_nlinalg.py", 58 "tensor/tests/test_shared_randomstreams.py", 59 "tensor/tests/test_misc.py", 60 "tensor/tests/mlp_test.py", 61 "tensor/tests/test_opt_uncanonicalize.py", 62 "tensor/tests/test_merge.py", 63 "tensor/tests/test_gc.py", 64 "tensor/tests/test_complex.py", 65 "tensor/tests/test_io.py", 66 "tensor/tests/test_sharedvar.py", 67 "tensor/tests/test_fourier.py", 68 "tensor/tests/test_casting.py", 69 "tensor/tests/test_sort.py", 70 "tensor/tests/test_raw_random.py", 71 "tensor/tests/test_xlogx.py", 72 "tensor/tests/test_slinalg.py", 73 "tensor/tests/test_blas_c.py", 74 "tensor/tests/test_blas_scipy.py", 75 "tensor/tests/test_mpi.py", 76 "tensor/nnet/__init__.py", 77 "tensor/signal/__init__.py", 78 "tensor/signal/tests/__init__.py", 79 "scalar/__init__.py", 80 "scalar/tests/__init__.py", 81 "sandbox/__init__.py", 82 "sandbox/cuda/__init__.py", 83 "sandbox/tests/__init__.py", 84 "sandbox/gpuarray/__init__.py", 85 "sandbox/linalg/__init__.py", 86 "sandbox/linalg/tests/__init__.py", 87 "scan_module/scan_utils.py", 88 "scan_module/scan_views.py", 89 "scan_module/scan.py", 90 "scan_module/scan_perform_ext.py", 91 "scan_module/__init__.py", 92 "scan_module/tests/__init__.py", 93 "scan_module/tests/test_scan.py", 94 "scan_module/tests/test_scan_opt.py", 95 "misc/__init__.py", 96 "misc/tests/__init__.py", 97 "misc/hooks/reindent.py", 98 "misc/hooks/check_whitespace.py", 99 "sparse/__init__.py", 100 "sparse/tests/__init__.py", 101 "sparse/tests/test_utils.py", 102 "sparse/tests/test_opt.py", 103 "sparse/tests/test_basic.py", 104 "sparse/tests/test_sp2.py", 105 "sparse/sandbox/__init__.py", 106 "sparse/sandbox/test_sp.py", 107 "sparse/sandbox/sp2.py", 108 "sparse/sandbox/truedot.py", 109 "sparse/sandbox/sp.py", 110 "gof/__init__.py", 111 "d3viz/__init__.py", 112 "d3viz/tests/__init__.py", 113 "gof/tests/__init__.py", 114] 115 116 117def list_files(dir_path=theano.__path__[0], pattern='*.py', no_match=".#"): 118 """ 119 List all files under theano's path. 120 """ 121 files_list = [] 122 for (dir, _, files) in os.walk(dir_path): 123 for f in files: 124 if fnmatch(f, pattern): 125 path = os.path.join(dir, f) 126 if not f.startswith(no_match): 127 files_list.append(path) 128 return files_list 129 130 131def test_format_flake8(): 132 # Test if flake8 is respected. 133 if not flake8_available: 134 raise SkipTest("flake8 is not installed") 135 total_errors = 0 136 137 files_to_checks = [] 138 for path in list_files(): 139 rel_path = os.path.relpath(path, theano.__path__[0]) 140 if sys.platform == 'win32': 141 rel_path = rel_path.replace('\\', '/') 142 if rel_path in whitelist_flake8: 143 continue 144 else: 145 files_to_checks.append(path) 146 147 if new_flake8: 148 guide = flake8.api.legacy.get_style_guide(ignore=ignore) 149 r = guide.check_files(files_to_checks) 150 total_errors = r.total_errors 151 else: 152 for path in files_to_checks: 153 error_num = flake8.main.check_file(path, ignore=ignore) 154 total_errors += error_num 155 156 if total_errors > 0: 157 raise AssertionError("FLAKE8 Format not respected") 158 159 160def print_files_information_flake8(files): 161 """ 162 Print the list of files which can be removed from the whitelist and the 163 list of files which do not respect FLAKE8 formatting that aren't in the 164 whitelist. 165 """ 166 infracting_files = [] 167 non_infracting_files = [] 168 if not files: 169 files = list_files() 170 for path in files: 171 rel_path = os.path.relpath(path, theano.__path__[0]) 172 number_of_infractions = flake8.main.check_file(path, 173 ignore=ignore) 174 if number_of_infractions > 0: 175 if rel_path not in whitelist_flake8: 176 infracting_files.append(rel_path) 177 else: 178 if rel_path in whitelist_flake8: 179 non_infracting_files.append(rel_path) 180 print("Files that must be corrected or added to whitelist:") 181 for file in infracting_files: 182 print(file) 183 print("Files that can be removed from whitelist:") 184 for file in non_infracting_files: 185 print(file) 186 187 188def check_all_files(dir_path=theano.__path__[0], pattern='*.py'): 189 """ 190 List all .py files under dir_path (theano path), check if they follow 191 flake8 format, save all the error-formatted files into 192 theano_filelist.txt. This function is used for generating 193 the "whitelist_flake8" in this file. 194 """ 195 196 with open('theano_filelist.txt', 'a') as f_txt: 197 for (dir, _, files) in os.walk(dir_path): 198 for f in files: 199 if fnmatch(f, pattern): 200 error_num = flake8.main.check_file(os.path.join(dir, f), 201 ignore=ignore) 202 if error_num > 0: 203 path = os.path.relpath(os.path.join(dir, f), 204 theano.__path__[0]) 205 f_txt.write('"' + path + '",\n') 206 207 208if __name__ == "__main__": 209 print_files_information_flake8(sys.argv[1:]) 210