Python 重构此函数以将其认知复杂度从 19 降低到允许的 15
Python Refactor this function to reduce its Cognitive Complexity from 19 to the 15 allowed
我从 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
您可以通过使用两个生成器表达式按扩展名过滤文件来删除一级缩进:
def file_handler(dir):
for root, dirs, files in os.walk(dir):
cfn_files = (file for file in files if file.endswith(tuple(cfn)))
tf_files = (file for file in files if file.endswith(tuple(tf)))
for file in cfn_files:
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)
for file in tf_files:
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
您应该考虑使用 glob
进行递归文件查找,尤其是当您知道要查找的文件扩展名时:
import glob
import json
import os
import click
import hcl
def file_handler(dir):
for extension in cfn:
# eg: /path/to/dir/**/*.json
glob_search = os.path.join(dir, "**/*{}".format(extension))
filenames = glob.glob(glob_search, recursive=True)
for filename in filenames:
with open(filename, 'r') as fin:
try:
file = fin.read()
if "AWSTemplateFormatVersion" in file:
data = json.dumps(file)
print(data)
except ValueError as e:
raise SystemExit(e)
for extension in tf:
# eg: /path/to/dir/**/*tf
glob_search = os.path.join(dir, "**/*{}".format(extension))
filenames = glob.glob(glob_search, recursive=True)
for filename in filenames:
with open(filename, 'r') as file:
try:
obj = hcl.load(file)
data = json.dumps(obj)
print(data)
except ValueError as e:
raise SystemExit(e)
仅供参考:有关使用 glob (Use a Glob() to find files recursively in Python?)
的问题
提取函数以生成文件路径:
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
统一异常处理:
from contextlib import contextmanager
@contextmanager
def _translate_error(from_error, to_error):
try:
yield
except from_error as error:
raise to_error(error)
提取处理文件类型的函数:
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)
当文件扩展名不匹配时创建空处理程序:
def _null_handler(file_object):
pass
将文件扩展名映射到处理程序:
_extension_handlers = {'.json': _handle_cfn,
'.template': _handle_cfn,
'.yaml': _handle_cfn,
'.yml': _handle_cfn,
'.tf': _handle_tf}
放在一起:
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)
您可以进一步提取处理每个文件的函数:
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)
那么你的主要功能是:
def file_handler(dir):
for file_path in _file_paths(dir):
_handle_file(file_path)
我从 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
您可以通过使用两个生成器表达式按扩展名过滤文件来删除一级缩进:
def file_handler(dir):
for root, dirs, files in os.walk(dir):
cfn_files = (file for file in files if file.endswith(tuple(cfn)))
tf_files = (file for file in files if file.endswith(tuple(tf)))
for file in cfn_files:
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)
for file in tf_files:
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
您应该考虑使用 glob
进行递归文件查找,尤其是当您知道要查找的文件扩展名时:
import glob
import json
import os
import click
import hcl
def file_handler(dir):
for extension in cfn:
# eg: /path/to/dir/**/*.json
glob_search = os.path.join(dir, "**/*{}".format(extension))
filenames = glob.glob(glob_search, recursive=True)
for filename in filenames:
with open(filename, 'r') as fin:
try:
file = fin.read()
if "AWSTemplateFormatVersion" in file:
data = json.dumps(file)
print(data)
except ValueError as e:
raise SystemExit(e)
for extension in tf:
# eg: /path/to/dir/**/*tf
glob_search = os.path.join(dir, "**/*{}".format(extension))
filenames = glob.glob(glob_search, recursive=True)
for filename in filenames:
with open(filename, 'r') as file:
try:
obj = hcl.load(file)
data = json.dumps(obj)
print(data)
except ValueError as e:
raise SystemExit(e)
仅供参考:有关使用 glob (Use a Glob() to find files recursively in Python?)
的问题提取函数以生成文件路径:
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
统一异常处理:
from contextlib import contextmanager
@contextmanager
def _translate_error(from_error, to_error):
try:
yield
except from_error as error:
raise to_error(error)
提取处理文件类型的函数:
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)
当文件扩展名不匹配时创建空处理程序:
def _null_handler(file_object):
pass
将文件扩展名映射到处理程序:
_extension_handlers = {'.json': _handle_cfn,
'.template': _handle_cfn,
'.yaml': _handle_cfn,
'.yml': _handle_cfn,
'.tf': _handle_tf}
放在一起:
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)
您可以进一步提取处理每个文件的函数:
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)
那么你的主要功能是:
def file_handler(dir):
for file_path in _file_paths(dir):
_handle_file(file_path)