import re
import os
import sys
import argparse
FILE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx']
parser = argparse.ArgumentParser(description='Detects invalid dependencies of a module')
parser.add_argument('-r', '--root', required=True, help='Path to the directory of the whole project')
parser.add_argument('-m', '--module', required=True, help='Path to the directory of the target module')
def get_path_from_import_line(import_line):
matches = re.findall('[\'"](.+?)[\'"]', import_line)
if len(matches) == 0:
return None
path = matches[0]
if not path.startswith('.'):
return None
return path
def get_absolute_path_from_import_path(filepath, import_path):
dir_path = os.path.dirname(filepath)
absolute_import_path = os.path.join(dir_path, import_path)
return os.path.normpath(absolute_import_path)
def get_imports(filepath):
if os.path.splitext(filepath)[1] not in FILE_EXTENSIONS:
return []
imports = []
with open(filepath, 'r') as fin:
for i, code_line in enumerate(fin.readlines()):
import_matches = re.findall('} from [\'"].+?[\'"];', code_line)
if len(import_matches) == 0:
continue
import_relative_path = get_path_from_import_line(import_matches[0])
if import_relative_path is not None:
imports.append({
'line_number': i + 1,
'path': get_absolute_path_from_import_path(filepath, import_relative_path)
})
return imports
def is_importing_from_module_subdir(module_path, import_path):
return import_path.startswith(module_path)
def is_importing_from_module(module_path, import_path):
return import_path == module_path
def main(root_path, module_path):
check_passed = True
# Check that all external imports only import from the module's index file
for dir_path, _, files in os.walk(root_path):
if os.path.normpath(dir_path).startswith(module_path):
continue
for file in files:
filepath = os.path.join(dir_path, file)
imports = get_imports(filepath)
errors = []
for import_item in imports:
if is_importing_from_module_subdir(module_path, import_item['path']) and not is_importing_from_module(module_path, import_item['path']):
errors.append(import_item)
if len(errors) > 0:
print(f'Incorrect imports from module subdir in {filepath}:')
for import_item in errors:
print(f" Line {import_item['line_number']}: '{import_item['path']}' should be '{module_path}'")
check_passed = False
print()
# Check that there are files in the module that import something from outside the module
for dir_path, _, files in os.walk(module_path):
break
for file in files:
filepath = os.path.join(dir_path, file)
imports = get_imports(filepath)
errors = []
for import_item in imports:
if not is_importing_from_module_subdir(module_path, import_item['path']):
errors.append(import_item)
if len(errors) > 0:
print(f'Invalid external imports from module file {filepath}:')
for import_item in errors:
print(f" Line {import_item['line_number']}: '{import_item['path']}'")
check_passed = False
print()
if not check_passed:
sys.exit('Script failed: Not all imports are correct.')
print('All imports are correct.')
if __name__ == '__main__':
args = parser.parse_args()
main(
os.path.normpath(args.root),
os.path.normpath(args.module)
)
Comments
0 B
|👍
/👎