api-automation-test/ApiAutomationTest/app/__init__.py

224 lines
9.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# coding=utf-8
from flask import Flask
import logging
import os
from concurrent_log_handler import ConcurrentRotatingFileHandler
from queue import Queue
from logging.handlers import QueueHandler, QueueListener
import click
from app.config import Config, proj_dir
from app.extensions import (db, migrate, login_manager, mail, csrf, bootstrap, session_id_manager,
socketio, dispatcher_scheduler)
from app import models
from app.template_global import (render_to_json, sort_by_order_in_module, sort_by_order_in_logic_controller,
can_show, is_forbidden, get_latest_reports, get_case_from_id, get_tool_from_id,
calc_percent, url_for_static)
from app.cores.ws import register_all_user_socket
def create_app(config_class=Config):
app = Flask(import_name=__name__)
app.config.from_object(obj=config_class)
register_logging(app)
register_extensions(app)
register_blueprints(app)
register_shell_context(app)
register_template_global(app)
register_template_context_processor(app)
register_before_first_request_funcs(app)
register_cli(app)
return app
def register_blueprints(app: Flask):
from app.routes.auth import bp as auth_bp
app.register_blueprint(blueprint=auth_bp, url_prefix='/auth')
from app.routes.main import bp as main_bp
app.register_blueprint(blueprint=main_bp)
from app.routes.case import bp as case_bp
app.register_blueprint(blueprint=case_bp, url_prefix='/case')
from app.routes.project import bp as project_bp
app.register_blueprint(blueprint=project_bp, url_prefix='/project')
from app.routes.module import bp as module_bp
app.register_blueprint(blueprint=module_bp, url_prefix='/module')
from app.routes.logic_controller import bp as logic_controller_bp
app.register_blueprint(blueprint=logic_controller_bp, url_prefix='/logic_controller')
from app.routes.scene import bp as scene_bp
app.register_blueprint(blueprint=scene_bp, url_prefix='/scene')
from app.routes.report import bp as report_bp
app.register_blueprint(blueprint=report_bp, url_prefix='/report')
from app.routes.setting import bp as settings_bp
app.register_blueprint(blueprint=settings_bp)
from app.routes.error import bp as errors_bp
app.register_blueprint(blueprint=errors_bp, url_prefix='/error')
from app.routes.ajax import bp as ajax_bp
app.register_blueprint(blueprint=ajax_bp, url_prefix='/ajax')
from app.utils import bp as util_bp
app.register_blueprint(blueprint=util_bp, url_prefix='/util')
def register_extensions(app: Flask):
db.init_app(app=app)
migrate.init_app(app=app, db=db)
login_manager.init_app(app=app)
mail.init_app(app=app)
csrf.init_app(app=app)
bootstrap.init_app(app=app)
socketio.init_app(app=app)
session_id_manager.init_app(app=app)
dispatcher_scheduler.init_app(app=app)
def register_shell_context(app: Flask):
from app.models import (db, User, EmailSetting, Case, HTTPCase, HTTPCaseParameter, HTTPCaseExpectation,
HTTPCaseFileUpload, Project, Module, Scene, Dispatcher, DispatcherDetail, Report,
ReportCaseData, ReportCaseExpectationData, SubElementInLogicController,
ReportToolData, ReportScriptToolData, ReportTimerToolData, ReportVariableDefinitionToolData,
ReportVariableDefinitionToolListData, Tool)
from app.email import send_email
from app.utils.util import get_project_id_from_current_element
@app.shell_context_processor
def make_shell_context():
return {
'db': db,
'User': User,
'send_email': send_email,
'EmailSetting': EmailSetting,
'Case': Case,
'HTTPCase': HTTPCase,
'HTTPCaseParameter': HTTPCaseParameter,
'HTTPCaseExpectation': HTTPCaseExpectation,
'HTTPCaseFileUpload': HTTPCaseFileUpload,
'Project': Project,
'Module': Module,
'Scene': Scene,
'Tool': Tool,
'Dispatcher': Dispatcher,
'DispatcherDetail': DispatcherDetail,
'SubElementInLogicController': SubElementInLogicController,
'ReportToolData': ReportToolData,
'ReportScriptToolData': ReportScriptToolData,
'ReportTimerToolData': ReportTimerToolData,
'ReportVariableDefinitionToolData': ReportVariableDefinitionToolData,
'ReportVariableDefinitionToolListData': ReportVariableDefinitionToolListData,
'get_project_id_from_current_element': get_project_id_from_current_element,
}
def register_logging(app: Flask):
# 日志记录
if not os.path.exists(os.path.join(proj_dir, 'logs')):
os.mkdir(os.path.join(proj_dir, 'logs'))
# 改用ConcurrentRotatingFileHandler避免出现多进程时出现文件争用情况
file_handler = ConcurrentRotatingFileHandler(filename=os.path.join(proj_dir, 'logs', 'webserver.log'),
maxBytes=1024 * 1024 * 10,
backupCount=10)
file_sys_handler = ConcurrentRotatingFileHandler(filename=os.path.join(proj_dir, 'logs', 'webserver_sys.log'),
maxBytes=1024 * 1024 * 10,
backupCount=10)
stream_handler = logging.StreamHandler()
formater = logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
)
file_handler.setFormatter(formater)
file_sys_handler.setFormatter(formater)
stream_handler.setFormatter(formater)
file_handler.setLevel(logging.INFO)
file_sys_handler.setLevel(logging.DEBUG)
stream_handler.setLevel(logging.DEBUG)
logger_queue = Queue(-1)
logger_queue_handler = QueueHandler(logger_queue)
logger_queue_listener = QueueListener(logger_queue,
file_sys_handler, file_handler, stream_handler,
respect_handler_level=True)
logger_queue_listener.start()
# app.logger
for handler in app.logger.handlers:
app.logger.removeHandler(handler)
app.logger.addHandler(logger_queue_handler)
app.logger.setLevel(logging.INFO)
app.logger.propagate = False # 记录消息将不会传递给当前记录器的祖先记录器的处理器
app.logger.info("WebServer 服务已启动")
# 框架默认logger指定输出handler(包含了http请求日志、定时任务job日志、socket日志)
logger = logging.getLogger()
logger.addHandler(logger_queue_handler)
logger.setLevel(logging.DEBUG)
def register_template_global(app: Flask):
# 注册jinja全局函数
app.add_template_global(render_to_json, 'render_to_json')
app.add_template_global(sort_by_order_in_module, 'sort_by_order_in_module')
app.add_template_global(can_show, 'can_show')
app.add_template_global(sort_by_order_in_logic_controller, 'sort_by_order_in_logic_controller')
app.add_template_global(get_latest_reports, 'get_latest_reports')
app.add_template_global(is_forbidden, 'is_forbidden')
app.add_template_global(get_case_from_id, 'get_case_from_id')
app.add_template_global(get_tool_from_id, 'get_tool_from_id')
app.add_template_global(calc_percent, 'calc_percent')
app.add_template_global(url_for_static, 'url_for_static')
def register_template_context_processor(app: Flask):
# 注册jinja模板上下文
@app.context_processor
def context_processor():
return {
'version': app.config['AAT_VERSION'],
}
def register_before_first_request_funcs(app: Flask):
# 在app实例拉起后第一个请求处理前进行一些准备工作
# 注册所有用户socket
app.before_first_request_funcs.append(register_all_user_socket)
def register_cli(app: Flask):
"""注册命令"""
@app.cli.command(short_help='初始化当前项目.')
def init():
from flask_migrate import init, migrate, upgrade
click.echo('[flask init] 开始初始化数据库.')
click.echo('[flask init] init.')
init()
click.echo('[flask init] migrate.')
migrate(message='init db')
click.echo('[flask init] upgrade.')
upgrade()
click.echo('[flask init] add user admin.')
from app.models import User
User.add(username='admin', password='admin', email='admin@example.com')
click.echo('[flask init] 已完成数据库初始化.')
@app.cli.command(short_help='测试邮件服务.')
@click.option('--receiver', '-r', help='收件人邮箱.')
def email_test(receiver: str):
from app.email import send_email
import traceback
if receiver is None or receiver.strip() == '':
click.echo('[flask email-test] 请输入收件人邮箱 eg: flask email-test -r zhangsan@test.com')
return
click.echo('[flask email-test] 开始测试email服务.')
click.echo('[flask email-test] 收件人邮箱: %s.' % receiver)
try:
send_email(
subject="[ApiAutomationTest] 通知",
sender=app.config['ADMINS'][0],
recipients=[receiver],
text_body='您已收到来自ApiAutomationTest的邮件.',
async_send=False,
)
except Exception:
click.echo('[flask email-test] 邮件发送失败,失败原因: \n%s' % traceback.format_exc())
else:
click.echo('[flask email-test] 测试邮件已发送,请查看收件邮箱.')