Python 重构此函数以将其认知复杂度从 19 降低到允许的 15

kil*_*omo 0 python python-2.7 sonarlint

我从 sonarlint 看到这条消息,并试图找出如何降低此功能的认知复杂性。提前感谢任何帮助。

import os
import json
import click
import hcl

cfn = [".json", ".template", ".yaml", ".yml"]
tf  = ["tf"]

def file_handler(dir):
    for root, dirs, files in os.walk(dir):
        for file in files:
            if file.endswith(tuple(cfn)):
                with open(os.path.join(root, file), 'r') as fin:
                    try:
                        file = fin.read()
                        if "AWSTemplateFormatVersion" in file:
                            data = json.dumps(file)
                            print(data)

                    except ValueError as e:
                        raise SystemExit(e)

            elif file.endswith(tuple(tf)):
                with open(os.path.join(root, file), 'r') as file:
                    try:
                        obj  = hcl.load(file)
                        data = json.dumps(obj)
                        print(data)
                    except ValueError as e:
                        raise SystemExit(e)
    return data
Run Code Online (Sandbox Code Playgroud)

Pet*_*ood 9

提取函数以生成文件路径:

def _file_paths(directory):
    for root, dirs, filenames in os.walk(directory):
        for filename in filenames:
            file_path = os.path.join(root, filename)
            if os.path.isfile(file_path):
                yield file_path
Run Code Online (Sandbox Code Playgroud)

统一异常处理:

from contextlib import contextmanager

@contextmanager
def _translate_error(from_error, to_error):
    try:
        yield
    except from_error as error:
        raise to_error(error)
Run Code Online (Sandbox Code Playgroud)

提取函数来处理文件类型:

def _handle_cfn(file_object):
    file_contents = file_object.read()
    if "AWSTemplateFormatVersion" in file_contents:
        data = json.dumps(file_contents)
        print(data)


def _handle_tf(file_object):
    obj  = hcl.load(file_oject)
    data = json.dumps(obj)
    print(data)
Run Code Online (Sandbox Code Playgroud)

当文件扩展名不匹配时创建一个空处理程序:

def _null_handler(file_object):
    pass
Run Code Online (Sandbox Code Playgroud)

将文件扩展名映射到处理程序:

_extension_handlers = {'.json': _handle_cfn,
            '.template': _handle_cfn,
            '.yaml': _handle_cfn,
            '.yml': _handle_cfn,
            '.tf': _handle_tf}
Run Code Online (Sandbox Code Playgroud)

把它放在一起:

import os
import json
import click
import hcl

def file_handler(dir):
    for file_path in _file_paths(dir):
        base, extension = os.path.splitext(file_path)
        handler = _extension_handlers.get(extension, _null_handler)
        with open(file_path) as file_object:
            with _translate_error(ValueError, SystemExit):
                handler(file_object)
Run Code Online (Sandbox Code Playgroud)

您可以通过提取处理每个文件的函数来进一步:

def _handle_file(file_path):
    base, extension = os.path.splitext(file_path)
    handler = _extension_handlers.get(extension, _null_handler)
    with open(file_path) as file_object:
        with _translate_error(ValueError, SystemExit):
            handler(file_object)
Run Code Online (Sandbox Code Playgroud)

那么你的主要功能是:

def file_handler(dir):
    for file_path in _file_paths(dir):
        _handle_file(file_path)
Run Code Online (Sandbox Code Playgroud)