HiveNetCore.generic 源代码

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
#
# Copyright 2018 黎慧剑
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

"""
通用基础模块

@module generic
@file generic.py

"""
import sys
import os
import json
import re
# 根据当前文件路径将包路径纳入, 在非安装的情况下可以引用到
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))
from HiveNetCore.utils.global_var_tool import GlobalVarTool
from HiveNetCore.i18n import get_global_i18n


__MOUDLE__ = 'generic'  # 模块名
__DESCRIPT__ = '通用基础模块'  # 模块描述
__VERSION__ = '0.1.0'  # 版本
__AUTHOR__ = '黎慧剑'  # 作者
__PUBLISH__ = '2018.08.29'  # 发布日期


# 全局变量
# 用于存储全局变量的值
# key为全局变量名( string) , value为全局变量的值
RUNTOOL_GLOBAL_VAR_LIST = dict()


[文档]def null_fun(*args, **kwargs): """ 空函数 """ pass
[文档]class NullObj(object): """ 空对象定义类, 用于动态增加属性的使用场景 @example msg_obj = NullObj() msg_obj.text = u'动态添加属性' """ ############################# # 通用的JSON转换处理函数 ############################# def __json__(self): """ 将对象转换为json字符串 @return {string} - 转换后的json字符串 """ return json.dumps(NullObj.get_object_attr_dict(self), ensure_ascii=False) @staticmethod def __fromjson__(json_str): """ 通过json字符串获取对象实例 @param {string} json_str - json字符串 """ _json_obj = json.loads(json_str) return NullObj.get_nullobj_from_dict(_json_obj) ############################# # 内部函数 #############################
[文档] @staticmethod def get_object_attr_dict(obj, ignored_key=[]): """ 获取对象的属性清单字典( 循环递归获取) @param {object} obj - 要处理的对象 @param {list} ignored_key=[] - 忽略的属性名清单 """ if type(obj) in ( int, float, bool, complex, str, list, tuple, dict, set ): # 基本数据类型, 直接返回自身 return obj else: # 对象, 统一转换为字典格式 _dict = dict() _attr_dir = dir(obj) for _item in _attr_dir: if _item[0: 2] != '__' and _item not in ignored_key and not callable(getattr(obj, _item)): _dict[_item] = NullObj.get_object_attr_dict(getattr(obj, _item)) return _dict
[文档] @staticmethod def get_nullobj_from_dict(obj_dict): """ 通过字典对象生成NullObj实例 @param {dict} obj_dict - 字典对象 @return {NullObj} - 生成的实例 """ _obj = NullObj() for _key in obj_dict.keys(): if isinstance(obj_dict[_key], dict): # 还是字典, 继续往下一层处理 exec('_obj.%s = NullObj.get_nullobj_from_dict(obj_dict[_key])' % (_key)) else: exec('_obj.%s = obj_dict[_key]' % (_key)) return _obj
[文档]class CResult(NullObj): """ 通用错误类定义, 便于规范所有的错误信息返回判断标准, 可直接在该类的实例对象上直接添加其他返回值 @example def fun(): result = CResult('00000',u'success') result.job = 'NewJob' result.k1 = 10 return result """
[文档] def __init__(self, code='00000', msg=None, error='', trace_str='', i18n_obj=None, i18n_msg_paras=()): """ 构造函数 @param {string} code='00000' - 错误码, '00000'代表成功, 参照HiveNet的错误码规范 @param {string} msg=None - 错误信息描述, 如果i18n_obj不为None时, 该参数传入的是国际化的消息ID 注意: 如果初始化时不传入msg( 即msg=None时) , 自动通过code查找具体的错误信息, 且在i18n_obj为None时使用全局国际化对象处理国际化信息 @param {string} error=None - 发生异常时的异常类型type的字符串 @param {string} trace_str='' - 错误追踪堆栈日志, 异常时的traceback.format_exc() @param {SimpleI18N} i18n_obj=None - 国际化类的实例对象, 如不传入会尝试自动加载全局的国际化控件 @param {tuple} i18n_msg_paras=() - 与msg配套使用, 当使用国际化时, 可以传入变量, 用于替换msg中的$1占位符 """ self.code = code self.msg = msg self.i18n_msg_id = msg # 国际化记录下来的错误明细编码ID串 self.i18n_msg_paras = i18n_msg_paras # 国际化记录下来的可替换参数变量 self._i18n_obj = i18n_obj # 国际化类实例化对象 self.error = error self.trace_str = trace_str self.i18n_error_type_msg_id = '' # 国际化记录下来的错误类型ID串( 第1位的错误说明) if i18n_obj is None: # 没有传国际化对象, 尝试获取全局的国际化对象 self._i18n_obj = get_global_i18n() # 如果msg为None, 需重新设置i18n_msg_id和i18n_error_type_msg_id的值 self.__get_i18n_msg_id() # 重新设置msg self.reset_msg()
[文档] def is_success(self): """ 判断当前错误对象是否成功 """ return (self.code[0] == '0')
[文档] def reset_msg(self): """ 重新设置错误对象的msg显示值( 例如修改了国际化控件默认语言后处理) """ if self._i18n_obj is None: # 没有国际化, 只是通过i18n_msg_id重新设置值 self.msg = self.i18n_msg_id if self.msg != '': # 替换占位参数 i = 1 # 记录是第几个 for para in self.i18n_msg_paras: if self.msg.find('$' + str(i)) >= 0: # 找到需要替换才处理, 提升效率 self.msg = re.sub(r'\$' + str(i), str(para), self.msg) i = i + 1 # 补充错误类型位 if self.i18n_error_type_msg_id != '': if self.msg != '': self.msg = '%s: %s' % (self.i18n_error_type_msg_id, self.msg) else: self.msg = self.i18n_error_type_msg_id else: # 国际化处理 self.msg = '' if self.i18n_error_type_msg_id != '': self.msg = self._i18n_obj.translate(self.i18n_error_type_msg_id) if self.i18n_msg_id != '': self.msg = self.msg + ': ' if self.i18n_msg_id != '': self.msg = self.msg + \ self._i18n_obj.translate(self.i18n_msg_id, self.i18n_msg_paras)
[文档] def reset_msg_by_code(self): """ 根据错误码重置错误信息( 忽略原来的错误信息, 按HiveNet规范处理) """ # 重置 self.i18n_msg_id = None self.i18n_error_type_msg_id = None self.__get_i18n_msg_id() # 重新设置msg self.reset_msg()
[文档] def change_code(self, code='00000', msg=None, i18n_msg_paras=None): """ 改变错误码及错误信息 @param {string} code='00000' - 错误码 @param {string} msg=None - 错误信息描述, 如果i18n_obj不为None时, 该参数传入的是国际化的消息ID 注意: 如果初始化时不传入msg( 即msg=None时) , 自动通过code查找具体的错误信息, 且在i18n_obj为None时使用全局国际化对象处理国际化信息 @param {tuple} i18n_msg_paras=() - 与msg配套使用, 当使用国际化时, 可以传入变量, 用于替换msg中的$1占位符 注意: 如果初始化时不传入i18n_msg_paras( 即i18n_msg_paras=None时) , 代表不改变原来传入的占位符变量 """ self.code = code self.msg = msg self.i18n_msg_id = msg if i18n_msg_paras is not None: self.i18n_msg_paras = i18n_msg_paras # 如果msg为None, 需重新设置i18n_msg_id和i18n_error_type_msg_id的值 self.__get_i18n_msg_id() # 重新设置msg self.reset_msg()
[文档] def standard_copy_to(self, dest_obj): """ 复制结果对象的标准返回值到新对象中 简单数据类型( int、string) 只要共享地址即可, 因为对变量重新复制会指向新的地址, 不会影响原来的变量值;复杂数据类型( dict等) 要通过deepcopy方式拷贝, 避免同一内存信息改变互相影响 @param {object} dest_obj - 要复制到的CResult对象 """ dest_obj.code = self.code dest_obj.msg = self.msg dest_obj.error = self.error dest_obj.trace_str = self.trace_str dest_obj.i18n_msg_id = self.i18n_msg_id dest_obj.i18n_msg_paras = self.i18n_msg_paras dest_obj.i18n_error_type_msg_id = self.i18n_error_type_msg_id
def __get_i18n_msg_id(self): """ 获取并设置i18n_msg_id的值 """ # 尝试先装载错误码映射 _map_error_code = self.__get_map_error_code() # 获取代码表, 区分错误类型及错误明细编码 if self.code[0] in _map_error_code.keys(): self.i18n_error_type_msg_id = _map_error_code[self.code[0]] else: self.i18n_error_type_msg_id = 'unknow' # 没有定义国际化时使用未知代替 if self.i18n_msg_id is None or self.i18n_msg_id == '': # 只有原来没有设置过才通过标准错误码映射修改, 否则保持不变 if self.code[1:] in _map_error_code.keys(): self.i18n_msg_id = _map_error_code[self.code[1:]] else: self.i18n_msg_id = '' def __get_map_error_code(self): """ 获取全局的错误码映射表 """ _map_error_code = GlobalVarTool.get_global_var('HIVENET_ERROR_CODE_MAP') if _map_error_code is None: _map_file = os.path.realpath(os.path.abspath(os.path.dirname(__file__) + '/') + '/hivenet_error_code/map_error_code.json') _map_error_code = {} with open(_map_file, 'rt', encoding='utf-8') as f: _map_error_code = json.load(f) GlobalVarTool.set_global_var('HIVENET_ERROR_CODE_MAP', _map_error_code) return _map_error_code def __str__(self): """ 提供系统层级的str输出格式化字符 """ _str = '%s:\n' % (str(type(self))) # 其他属性 _attr_dir = dir(self) for _item in _attr_dir: if _item[0: 2] != '__' and not callable(getattr(self, _item)) and _item not in ['_i18n_obj', 'i18n_msg_paras', 'i18n_msg_id', 'error']: _str += ' (attr).%s=%s\n' % (_item, str(getattr(self, _item))) # __dict__上的属性 if hasattr(self, '__dict__'): for _item in self.__dict__.items(): if _item[0] not in _attr_dir and _item[0] not in ['_i18n_obj', 'i18n_msg_paras', 'i18n_msg_id', 'error']: _str += ' (dict).%s=%s\n' % (_item[0], str(_item[1])) return _str ############################# # 通用的JSON转换处理函数 ############################# def __json__(self): """ 将对象转换为json字符串 @return {string} - 转换后的json字符串 """ return json.dumps(NullObj.get_object_attr_dict(self, ignored_key=['_i18n_obj', ]), ensure_ascii=False) @staticmethod def __fromjson__(json_str): """ 通过json字符串获取对象实例 @param {string} json_str - json字符串 """ _json_obj = json.loads(json_str) _obj = CResult( code=_json_obj['code'], msg=_json_obj['msg'], error=_json_obj['error'], trace_str=_json_obj['trace_str'], i18n_msg_paras=_json_obj['i18n_msg_paras'] ) _obj.i18n_error_type_msg_id = _json_obj['i18n_error_type_msg_id'] _obj.i18n_msg_id = _json_obj['i18n_msg_id'] return _obj
if __name__ == '__main__': # 当程序自己独立运行时执行的操作 # 打印版本信息 print(('模块名: %s - %s\n' '作者: %s\n' '发布日期: %s\n' '版本: %s' % (__MOUDLE__, __DESCRIPT__, __AUTHOR__, __PUBLISH__, __VERSION__)))