修复动态加载函数的bug

This commit is contained in:
chenyongzhiaaron 2023-08-01 17:38:04 +08:00
parent 49bee29250
commit e20a6a26cf
9 changed files with 176 additions and 136 deletions

15
.idea/git_toolbox_prj.xml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageIssueKeyValidationOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
<option name="commitMessageValidationEnabledOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
</component>
</project>

View File

@ -4,12 +4,15 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="eded71e8-6551-463d-9bd4-cdbb3ffc536c" name="更改" comment="删除多余的文件">
<list default="true" id="eded71e8-6551-463d-9bd4-cdbb3ffc536c" name="更改" comment="测试浏览记录到csv">
<change afterPath="$PROJECT_DIR$/encryption_rules/__init__.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/debug/cap.py" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/debug/requestRecord.py" beforeDir="false" afterPath="$PROJECT_DIR$/debug/requestRecord.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/debug/test15.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/filtered_requests.csv" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/common/crypto/encrypt_data.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/crypto/encrypt_data.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/utils/action.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/utils/action.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/validation/load_modules_from_folder.py" beforeDir="false" afterPath="$PROJECT_DIR$/common/validation/load_modules_from_folder.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/extensions/__init__.py" beforeDir="false" afterPath="$PROJECT_DIR$/extensions/__init__.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/extensions/sign.py" beforeDir="false" afterPath="$PROJECT_DIR$/encryption_rules/rules.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/test_script/test_executor.py" beforeDir="false" afterPath="$PROJECT_DIR$/test_script/test_executor.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -66,34 +69,13 @@
}</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="D:\app\apitest\encryption_rules" />
<recent name="D:\app\apitest\common\validation" />
<recent name="D:\app\apitest\common\log_utils" />
<recent name="D:\app\apitest\common\parsing" />
</key>
</component>
<component name="RunManager" selected="Python.http_client">
<configuration name="encryption_str" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="api_project" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/common/crypto" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/common/crypto/encryption_str.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<component name="RunManager" selected="Python.load_modules_from_folder">
<configuration name="http_client" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="api_project" />
<option name="INTERPRETER_OPTIONS" value="" />
@ -116,6 +98,50 @@
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="load_modules_from_folder" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="api_project" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/common/validation" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/common/validation/load_modules_from_folder.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="loaders" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="api_project" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/common/validation" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/common/validation/loaders.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="mysql_client" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="api_project" />
<option name="INTERPRETER_OPTIONS" value="" />
@ -138,28 +164,6 @@
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="requestRecord (1)" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="api_project" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/debug" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/debug/requestRecord.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="Unittest (test_executor.py 内)" type="tests" factoryName="Unittests" temporary="true" nameIsGenerated="true">
<module name="api_project" />
<option name="INTERPRETER_OPTIONS" value="" />
@ -177,11 +181,11 @@
</configuration>
<recent_temporary>
<list>
<item itemvalue="Python.load_modules_from_folder" />
<item itemvalue="Python.loaders" />
<item itemvalue="Python.http_client" />
<item itemvalue="Python 测试.Unittest (test_executor.py 内)" />
<item itemvalue="Python.mysql_client" />
<item itemvalue="Python.encryption_str" />
<item itemvalue="Python.requestRecord (1)" />
</list>
</recent_temporary>
</component>
@ -211,7 +215,8 @@
<workItem from="1690536254640" duration="11000" />
<workItem from="1690774476519" duration="12117000" />
<workItem from="1690855086910" duration="749000" />
<workItem from="1690855882311" duration="1790000" />
<workItem from="1690855882311" duration="1981000" />
<workItem from="1690873614157" duration="4763000" />
</task>
<task id="LOCAL-00001" summary="优化代码">
<option name="closed" value="true" />
@ -285,7 +290,15 @@
<option name="project" value="LOCAL" />
<updated>1690854560996</updated>
</task>
<option name="localTasksCounter" value="10" />
<task id="LOCAL-00010" summary="测试浏览记录到csv">
<option name="closed" value="true" />
<created>1690858708660</created>
<option name="number" value="00010" />
<option name="presentableId" value="LOCAL-00010" />
<option name="project" value="LOCAL" />
<updated>1690858708660</updated>
</task>
<option name="localTasksCounter" value="11" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@ -298,7 +311,8 @@
<MESSAGE value="增加统一自定义异常类" />
<MESSAGE value="gitignore" />
<MESSAGE value="删除多余的文件" />
<option name="LAST_COMMIT_MESSAGE" value="删除多余的文件" />
<MESSAGE value="测试浏览记录到csv" />
<option name="LAST_COMMIT_MESSAGE" value="测试浏览记录到csv" />
</component>
<component name="com.github.evgenys91.machinet.common.dslhistory.DslHistoryState">
<option name="historyDtoById">
@ -318,6 +332,8 @@
</option>
</component>
<component name="com.intellij.coverage.CoverageDataManagerImpl">
<SUITE FILE_PATH="coverage/apitest$loaders.coverage" NAME="loaders 覆盖结果" MODIFIED="1690874206675" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/common/validation" />
<SUITE FILE_PATH="coverage/apitest$load_modules_from_folder.coverage" NAME="load_modules_from_folder 覆盖结果" MODIFIED="1690882059703" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/common/validation" />
<SUITE FILE_PATH="coverage/apitest$requestRecord__1_.coverage" NAME="requestRecord (1) 覆盖结果" MODIFIED="1690531988570" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/debug" />
<SUITE FILE_PATH="coverage/apitest$Unittest__test_executor_py__.coverage" NAME="Unittest (test_executor.py 内) 覆盖结果" MODIFIED="1690850721335" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/test_script" />
<SUITE FILE_PATH="coverage/apitest$action.coverage" NAME="action 覆盖结果" MODIFIED="1689907783681" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/common" />

View File

@ -10,7 +10,7 @@
from common.crypto import logger
from common.crypto.encryption_rsa import Rsa
# from common.crypto.encryption_aes import DoAES
from extensions import sign
from encryption_rules import rules
@logger.log_decorator()
@ -21,8 +21,8 @@ class EncryptData:
def encrypts(self, headers_crypto, headers, request_data_crypto, request_data):
encryption_methods = {
"MD5": sign.md5_sign,
"sha1": sign.sha1_sign,
"MD5": rules.md5_sign,
"sha1": rules.sha1_sign,
"rsa": lambda data: Rsa(data).rsa_encrypt()
}

View File

@ -10,6 +10,7 @@
import ast
import time
from common import bif_functions
from common.crypto.encrypt_data import EncryptData
from common.database.mysql_client import MysqlClient
from common.log_utils.mylogger import MyLogger
@ -22,7 +23,7 @@ from common.validation.validator import Validator
@singleton
class Action(Extractor, LoadScript, Validator, MysqlClient):
def __init__(self, initialize_data=None, bif_functions=None, db_config=None):
def __init__(self, initialize_data=None, db_config=None):
super().__init__()
MysqlClient.__init__(self, db_config)
self.encrypt = EncryptData()

View File

@ -9,53 +9,54 @@
"""
import importlib.util
import os
import types
from common.data_extraction.dependent_parameter import DependentParameter
from common.validation import logger
# from common.environments import Environments
# from common.data_extraction.data_extractor import DataExtractor
class LoadModulesFromFolder(DependentParameter):
def __init__(self):
super().__init__()
@logger.log_decorator()
def load_modules_from_folder(self, folder_path):
def load_modules_from_folder(self, folder_or_mnodule):
"""
动态加载指定文件夹下的模块并读取其中的函数
通过访问字典的 key 可以获取到对应的函数值并调用
Args:
folder_path (str): 要加载模块的文件夹路径
Returns:
dict: 存储函数的字典键为函数名值为函数对象
动态加载文件或模块
"""
if isinstance(folder_or_mnodule, str):
folder_path = folder_or_mnodule
if not os.path.exists(folder_path): # 检查文件夹路径是否存在
raise ValueError("Folder path does not exist.")
for file_name in os.listdir(folder_path): # 遍历指定文件夹下的所有文件
module_name, ext = os.path.splitext(file_name)
if ext == '.py' and module_name != '__init__': # 如果是 Python 模块文件
if ext == '.py' and module_name != '__init__':
module_path = os.path.join(folder_path, file_name) # 获取模块文件的完整路径
spec = importlib.util.spec_from_file_location(module_name, module_path)
module = importlib.util.module_from_spec(spec)
try:
spec.loader.exec_module(module) # 加载模块文件并执行其中的代码,将函数定义添加到 module 对象中
except Exception as e:
except:
continue
# 遍历 module 对象中的所有属性,找出函数并添加到 functions 字典中
for name, obj in vars(module).items():
if callable(obj):
self.update_environments(name, obj)
elif isinstance(folder_or_mnodule, types.ModuleType):
module = folder_or_mnodule
module = importlib.reload(module)
for n, o in vars(module).items():
if callable(o):
self.update_environments(n, o)
else:
raise TypeError("folder_or_module should be either a folder path (str) or a module (types.ModuleType).")
if __name__ == '__main__':
lmff = LoadModulesFromFolder()
lmff.load_modules_from_folder(r'D:\apk_api\api-test-project\extensions')
# lmff.load_modules_from_folder(r'..\..\extensions')
import extensions as es
lmff.load_modules_from_folder(es)
print(lmff.get_environments())

View File

@ -0,0 +1,9 @@
#!/usr/bin/env python
# encoding: utf-8
"""
@author: kira
@contact: 262667641@qq.com
@file: __init__.py.py
@time: 2023/8/1 17:07
@desc:
"""

View File

@ -3,9 +3,9 @@
"""
@author: kira
@contact: 262667641@qq.com
@file: do_sign.py
@file: rules.py
@time: 2023/3/14 16:21
@desc:
@desc:自定义加密规则
"""
import json
import time

View File

@ -12,4 +12,3 @@ from common.log_utils.mylogger import MyLogger
logger = MyLogger()
from .dynamic_scaling_methods import *
from .sign import *

View File

@ -11,11 +11,10 @@ import unittest
from ddt import ddt, data
from common import bif_functions
import extensions
from common.file_handling.do_excel import DoExcel
from common.utils.action import Action
from config import Config
from extensions import dynamic_scaling_methods
test_file = Config.test_case # 获取 excel 文件路径
excel = DoExcel(test_file)
@ -26,14 +25,14 @@ test_case, databases, initialize_data, host = excel.get_excel_init_and_cases()
@ddt
class TestProjectApi(unittest.TestCase):
maxDiff = None
action = Action(initialize_data, bif_functions, databases)
action = Action(initialize_data, databases)
@classmethod
def setUpClass(cls) -> None:
pass
cls.action.load_modules_from_folder(extensions)
def setUp(self) -> None:
self.action.set_bif_fun(dynamic_scaling_methods)
pass
@data(*test_case)
def test_api(self, item):