jit-utils-backend 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jit_utils/__init__.py +152 -0
- jit_utils/apiAuthSign.py +73 -0
- jit_utils/barcode.py +50 -0
- jit_utils/clsTool.py +71 -0
- jit_utils/config/__init__.py +11 -0
- jit_utils/config/case.py +77 -0
- jit_utils/config/config.py +90 -0
- jit_utils/config/exception.py +17 -0
- jit_utils/config/field.py +177 -0
- jit_utils/convert.py +169 -0
- jit_utils/decorator.py +58 -0
- jit_utils/exceptions.py +113 -0
- jit_utils/forwarder.py +113 -0
- jit_utils/matchTool.py +136 -0
- jit_utils/network.py +36 -0
- jit_utils/qrcode.py +60 -0
- jit_utils/signature.py +56 -0
- jit_utils/spaceSender.py +44 -0
- jit_utils/string.py +118 -0
- jit_utils/time.py +701 -0
- jit_utils/validator.py +26 -0
- jit_utils/workday_constants.py +72 -0
- jit_utils_backend-0.0.1.dist-info/METADATA +182 -0
- jit_utils_backend-0.0.1.dist-info/RECORD +32 -0
- jit_utils_backend-0.0.1.dist-info/WHEEL +5 -0
- jit_utils_backend-0.0.1.dist-info/top_level.txt +2 -0
- tests/__init__.py +4 -0
- tests/run_tests.py +102 -0
- tests/test_package_imports.py +199 -0
- tests/test_qrcode_barcode.py +182 -0
- tests/test_string_utils.py +174 -0
- tests/test_time_utils.py +185 -0
@@ -0,0 +1,177 @@
|
|
1
|
+
# -*-coding:utf-8-*-
|
2
|
+
|
3
|
+
"""
|
4
|
+
Created on 2023/9/20
|
5
|
+
|
6
|
+
@author: 臧韬
|
7
|
+
|
8
|
+
@desc: 默认描述
|
9
|
+
"""
|
10
|
+
from commons.utils.config.exception import TlConfigException
|
11
|
+
|
12
|
+
|
13
|
+
class NoneType(object):
|
14
|
+
def __bool__(self):
|
15
|
+
return False
|
16
|
+
|
17
|
+
|
18
|
+
class AnyType(object):
|
19
|
+
pass
|
20
|
+
|
21
|
+
|
22
|
+
class Inf(float):
|
23
|
+
__instance = None
|
24
|
+
|
25
|
+
def __new__(cls, *args, **kwargs):
|
26
|
+
if cls.__instance is None:
|
27
|
+
cls.__instance = super(Inf, cls).__new__(cls, "inf")
|
28
|
+
return cls.__instance
|
29
|
+
|
30
|
+
def __gt__(self, other):
|
31
|
+
return False
|
32
|
+
|
33
|
+
def __str__(self):
|
34
|
+
return "无穷大"
|
35
|
+
|
36
|
+
def __neg__(self):
|
37
|
+
return NegInf()
|
38
|
+
|
39
|
+
def __invert__(self):
|
40
|
+
return NegInf()
|
41
|
+
|
42
|
+
def __floordiv__(self, other):
|
43
|
+
return self
|
44
|
+
|
45
|
+
def __truediv__(self, other):
|
46
|
+
return self
|
47
|
+
|
48
|
+
|
49
|
+
class NegInf(float):
|
50
|
+
__instance = None
|
51
|
+
|
52
|
+
def __new__(cls, *args, **kwargs):
|
53
|
+
if cls.__instance is None:
|
54
|
+
cls.__instance = super(NegInf, cls).__new__(cls, "-inf")
|
55
|
+
return cls.__instance
|
56
|
+
|
57
|
+
def __gt__(self, other):
|
58
|
+
return True
|
59
|
+
|
60
|
+
def __str__(self):
|
61
|
+
return "无穷小"
|
62
|
+
|
63
|
+
def __neg__(self):
|
64
|
+
return Inf()
|
65
|
+
|
66
|
+
def __invert__(self):
|
67
|
+
return Inf()
|
68
|
+
|
69
|
+
|
70
|
+
inf = Inf()
|
71
|
+
|
72
|
+
# print("<<<<<<<<<<<<<基类被加载")
|
73
|
+
|
74
|
+
|
75
|
+
class Field(object):
|
76
|
+
"""
|
77
|
+
这是一个基类字段
|
78
|
+
"""
|
79
|
+
|
80
|
+
def __init__(self, argType=AnyType, required=True, default=None, checkFunc=None, transformFunc=None):
|
81
|
+
self.argType = argType
|
82
|
+
# 当一个字段设置了默认值,那么设置成必传就没有意义
|
83
|
+
self.required = False if default else required
|
84
|
+
self.default = default
|
85
|
+
self.checkFunc = checkFunc
|
86
|
+
self.transformFunc = transformFunc
|
87
|
+
|
88
|
+
self.name = None
|
89
|
+
|
90
|
+
def check(self, value):
|
91
|
+
if self.required and value is None:
|
92
|
+
raise TlConfigException("该字段必传! field={f}".format(f=self.name))
|
93
|
+
if self.argType is not AnyType and not isinstance(value, self.argType):
|
94
|
+
raise TlConfigException(
|
95
|
+
"该参数应该传入的数据类型是={at}, 收到的数据类型={vt}! 值={v}, 字段名={f}".format(
|
96
|
+
at=self.argType.__name__, vt=type(value).__name__, v=str(value), f=self.__class__.__name__
|
97
|
+
)
|
98
|
+
)
|
99
|
+
if callable(self.checkFunc):
|
100
|
+
self.checkFunc(value)
|
101
|
+
|
102
|
+
def transform(self, value):
|
103
|
+
if value is NoneType:
|
104
|
+
return value
|
105
|
+
if callable(self.transformFunc):
|
106
|
+
try:
|
107
|
+
return self.transformFunc(value)
|
108
|
+
except Exception as e:
|
109
|
+
raise e
|
110
|
+
return value
|
111
|
+
|
112
|
+
|
113
|
+
# print("Field: {}".format(id(Field)))
|
114
|
+
|
115
|
+
|
116
|
+
class StringField(Field):
|
117
|
+
"""
|
118
|
+
字符串字段
|
119
|
+
"""
|
120
|
+
|
121
|
+
DEFAULT_MAX_LEN = 65535
|
122
|
+
DEFAULT_MIN_LEN = 0
|
123
|
+
|
124
|
+
def __init__(
|
125
|
+
self,
|
126
|
+
argType=str,
|
127
|
+
required=True,
|
128
|
+
default=None,
|
129
|
+
maxLen=DEFAULT_MAX_LEN,
|
130
|
+
minLen=DEFAULT_MIN_LEN,
|
131
|
+
transformFunc=str,
|
132
|
+
):
|
133
|
+
super(StringField, self).__init__(
|
134
|
+
argType=argType, required=required, default=default, checkFunc=self.stringCheck, transformFunc=transformFunc
|
135
|
+
)
|
136
|
+
|
137
|
+
self.maxLen = maxLen
|
138
|
+
self.minLen = minLen
|
139
|
+
|
140
|
+
def lengthCheck(self, value, maxLen, minLen):
|
141
|
+
if minLen == maxLen and len(value) != minLen:
|
142
|
+
raise TlConfigException("{name}的长度应该是 {minLen}".format(name=self.name, minLen=minLen))
|
143
|
+
if not minLen <= len(value) <= maxLen:
|
144
|
+
raise TlConfigException(
|
145
|
+
"{name}的长度必须介于 {minLen} 到 {maxLen} 之前".format(name=self.name, minLen=minLen, maxLen=maxLen)
|
146
|
+
)
|
147
|
+
|
148
|
+
def stringCheck(self, value):
|
149
|
+
self.lengthCheck(value, maxLen=self.maxLen, minLen=self.minLen)
|
150
|
+
|
151
|
+
|
152
|
+
class IntField(Field):
|
153
|
+
DEFAULT_MAX_NUM = inf
|
154
|
+
DEFAULT_MIN_NUM = -inf
|
155
|
+
|
156
|
+
def __init__(self, argType=int, required=True, maxNum=DEFAULT_MAX_NUM, minNum=DEFAULT_MIN_NUM, default=None):
|
157
|
+
super(IntField, self).__init__(
|
158
|
+
argType=argType, required=required, default=default, checkFunc=self.intCheck, transformFunc=self.toInt
|
159
|
+
)
|
160
|
+
|
161
|
+
self.maxNum = maxNum
|
162
|
+
self.minNum = minNum
|
163
|
+
|
164
|
+
def rangeCheck(self, value, maxNum, minNum):
|
165
|
+
if not minNum <= value <= maxNum:
|
166
|
+
raise TlConfigException(
|
167
|
+
"{name} 的取值范围是 {minNum} 到 {maxNum}".format(name=self.name, minNum=minNum, maxNum=maxNum)
|
168
|
+
)
|
169
|
+
|
170
|
+
def toInt(self, value):
|
171
|
+
if isinstance(value, str):
|
172
|
+
if not value.isnumeric():
|
173
|
+
raise TlConfigException("{name} 必须传入数字".format(name=self.name))
|
174
|
+
return int(value)
|
175
|
+
|
176
|
+
def intCheck(self, value):
|
177
|
+
self.rangeCheck(value=value, maxNum=self.maxNum, minNum=self.minNum)
|
jit_utils/convert.py
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
# -*-coding:utf-8-*-
|
2
|
+
"""
|
3
|
+
Created on 2022/12/27
|
4
|
+
|
5
|
+
@author: lyon
|
6
|
+
|
7
|
+
@desc:
|
8
|
+
"""
|
9
|
+
|
10
|
+
from jit.commons.utils.logger import log
|
11
|
+
|
12
|
+
|
13
|
+
class Converter(object):
|
14
|
+
|
15
|
+
def __init__(self):
|
16
|
+
self._globals = {}
|
17
|
+
|
18
|
+
def getFuncSubClasses(self, baseCls):
|
19
|
+
for subCls in baseCls.__subclasses__():
|
20
|
+
if hasattr(subCls, "function"):
|
21
|
+
self._globals[subCls.function] = subCls
|
22
|
+
self.getFuncSubClasses(subCls)
|
23
|
+
|
24
|
+
def getExprSubClasses(self, baseCls):
|
25
|
+
for subCls in baseCls.__subclasses__():
|
26
|
+
self._globals[subCls.__name__] = subCls
|
27
|
+
self.getExprSubClasses(subCls)
|
28
|
+
|
29
|
+
def eval(self, expression):
|
30
|
+
# t表达式里面有 "T(modelPath)xxx"
|
31
|
+
# 加载FUNC子类
|
32
|
+
from models.Meta import Expression
|
33
|
+
|
34
|
+
self.getExprSubClasses(Expression)
|
35
|
+
Sql = app.getElement("globals.Sql")
|
36
|
+
self._globals["Calc"] = Sql
|
37
|
+
self._globals["null"] = None
|
38
|
+
return eval(expression, self._globals)
|
39
|
+
|
40
|
+
|
41
|
+
converter = Converter()
|
42
|
+
|
43
|
+
|
44
|
+
class MemoryCompiler(object):
|
45
|
+
"""
|
46
|
+
Q表达式内存计算判断
|
47
|
+
"""
|
48
|
+
|
49
|
+
def __init__(self, expression, data=None):
|
50
|
+
self.expression = expression
|
51
|
+
self.data = data
|
52
|
+
|
53
|
+
def parse(self):
|
54
|
+
from models.Meta import Func
|
55
|
+
|
56
|
+
if isinstance(self.expression, Func):
|
57
|
+
result = FuncParser(self.expression).getMemory(self)
|
58
|
+
else:
|
59
|
+
# 根据类名选择对应的解析器(解析器需要我们自己手动去完成构建)
|
60
|
+
Parser = globals()[self.expression.__class__.__name__ + "Parser"]
|
61
|
+
result = Parser(self.expression).getMemory(self)
|
62
|
+
return result
|
63
|
+
|
64
|
+
def evalQ(self):
|
65
|
+
try:
|
66
|
+
result = self.parse()
|
67
|
+
return converter.eval("lambda x: %s" % result)(self.data)
|
68
|
+
except Exception as e:
|
69
|
+
log.error(e)
|
70
|
+
return False
|
71
|
+
|
72
|
+
|
73
|
+
class ExpressionParser(object):
|
74
|
+
|
75
|
+
def __init__(self, *args, **kwargs):
|
76
|
+
self.quoteCache = {"*": "*"}
|
77
|
+
|
78
|
+
def getMemory(self, compiler):
|
79
|
+
raise NotImplementedError
|
80
|
+
|
81
|
+
|
82
|
+
class QParser(ExpressionParser):
|
83
|
+
"""
|
84
|
+
Q表达式解析
|
85
|
+
"""
|
86
|
+
|
87
|
+
def __init__(self, q):
|
88
|
+
super(QParser, self).__init__(q)
|
89
|
+
self.q = q
|
90
|
+
|
91
|
+
def getMemory(self, compiler):
|
92
|
+
from models.Meta import QAND, QOR, getLookup
|
93
|
+
|
94
|
+
result = []
|
95
|
+
if self.q.sourceExpressions:
|
96
|
+
# 嵌套结构
|
97
|
+
for expr in self.q.sourceExpressions:
|
98
|
+
if isinstance(expr, (QAND, QOR)):
|
99
|
+
result.append(expr())
|
100
|
+
else:
|
101
|
+
result.append(self.__class__(expr).getMemory(compiler))
|
102
|
+
else:
|
103
|
+
# 非嵌套结构
|
104
|
+
lookup = getLookup(self.q.compareName)
|
105
|
+
if lookup:
|
106
|
+
result.append(LookupParser(lookup(self.q.lhs, self.q.rhs)).getMemory(compiler))
|
107
|
+
return "({})".format(" ".join(result))
|
108
|
+
|
109
|
+
|
110
|
+
class LookupParser(ExpressionParser):
|
111
|
+
|
112
|
+
def __init__(self, lookup):
|
113
|
+
super(LookupParser, self).__init__(lookup)
|
114
|
+
self.lookup = lookup
|
115
|
+
|
116
|
+
def getMemory(self, compiler):
|
117
|
+
ls = MemoryCompiler(self.lookup.lhs, compiler.data).parse()
|
118
|
+
rs = MemoryCompiler(self.lookup.rhs, compiler.data).parse()
|
119
|
+
if "{ls}" in self.lookup.memory:
|
120
|
+
return self.lookup.memory.format(ls=ls, rs=rs)
|
121
|
+
return "(%s %s %s)" % (ls, self.lookup.memory, rs)
|
122
|
+
|
123
|
+
|
124
|
+
class FuncParser(ExpressionParser):
|
125
|
+
|
126
|
+
def __init__(self, func):
|
127
|
+
super(FuncParser, self).__init__(func)
|
128
|
+
self.func = func
|
129
|
+
|
130
|
+
def getMemory(self, compiler):
|
131
|
+
exps = [str(MemoryCompiler(exp, compiler.data).parse()) for exp in self.func.sourceExpressions]
|
132
|
+
return "%s(%s)" % (self.func.memory, ", ".join(exps))
|
133
|
+
|
134
|
+
|
135
|
+
class FParser(ExpressionParser):
|
136
|
+
|
137
|
+
def __init__(self, f):
|
138
|
+
super(FParser, self).__init__(f)
|
139
|
+
self.f = f
|
140
|
+
|
141
|
+
def getMemory(self, compiler):
|
142
|
+
"""
|
143
|
+
如果有数据, 就返回值
|
144
|
+
没有, 就返回 x.字段
|
145
|
+
"""
|
146
|
+
# TODO: 暂时先只做一层
|
147
|
+
return repr(compiler.data.get(self.f.fieldId, "x.%s" % self.f.fieldId))
|
148
|
+
|
149
|
+
|
150
|
+
class ValueParser(ExpressionParser):
|
151
|
+
|
152
|
+
def __init__(self, value):
|
153
|
+
super(ValueParser, self).__init__(value)
|
154
|
+
self.value = value
|
155
|
+
|
156
|
+
def getMemory(self, compiler):
|
157
|
+
return repr(self.value.value)
|
158
|
+
|
159
|
+
|
160
|
+
class CombinedExpressionParser(ExpressionParser):
|
161
|
+
|
162
|
+
def __init__(self, combine):
|
163
|
+
super(CombinedExpressionParser, self).__init__(combine)
|
164
|
+
self.combine = combine
|
165
|
+
|
166
|
+
def getMemory(self, compiler):
|
167
|
+
left = MemoryCompiler(self.combine.lhs, compiler.data).parse()
|
168
|
+
right = MemoryCompiler(self.combine.rhs, compiler.data).parse()
|
169
|
+
return "(%s %s %s)" % (left, self.combine.connector, right)
|
jit_utils/decorator.py
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
import inspect
|
2
|
+
import json
|
3
|
+
|
4
|
+
import requests
|
5
|
+
|
6
|
+
|
7
|
+
def forward(fullName):
|
8
|
+
def inner(func):
|
9
|
+
def wrapper(self, *args, **kwargs):
|
10
|
+
appRule = app.env.getRuleByAppId(app.appId)
|
11
|
+
# 当前APP, 不需要转发
|
12
|
+
authApp = appRule.variables.get("authApp")
|
13
|
+
if not authApp:
|
14
|
+
return func(self, *args, **kwargs)
|
15
|
+
else:
|
16
|
+
if not app.env.envEntryList:
|
17
|
+
raise Exception("无环境入口")
|
18
|
+
entry = app.domain
|
19
|
+
uri = "{}/api/{}/{}/{}".format(
|
20
|
+
entry.strip("/"), authApp.replace(".", "/"), fullName.replace(".", "/"), func.__name__
|
21
|
+
)
|
22
|
+
argDict = {}
|
23
|
+
f = inspect.getfullargspec(func)
|
24
|
+
fargs = f.args
|
25
|
+
fargs.pop(0)
|
26
|
+
for key, value in zip(fargs, args):
|
27
|
+
argDict[key] = value
|
28
|
+
if len(args) > len(f.args):
|
29
|
+
argDict[f.varargs] = args[len(f.args) - 1 :]
|
30
|
+
for key, value in kwargs.items():
|
31
|
+
argDict[key] = value
|
32
|
+
|
33
|
+
argDict = {"argDict": argDict}
|
34
|
+
|
35
|
+
# 这里headers要把Token传过去
|
36
|
+
try:
|
37
|
+
argDict = json.dumps(argDict)
|
38
|
+
response = requests.post(
|
39
|
+
uri,
|
40
|
+
data=argDict,
|
41
|
+
headers={"Content-Type": "application/json", "token": app.request.headers.get("token")},
|
42
|
+
)
|
43
|
+
print("===========================")
|
44
|
+
print(" uri: ", uri)
|
45
|
+
print(" data: ", argDict)
|
46
|
+
print(" response: ", response.text)
|
47
|
+
print("===========================")
|
48
|
+
resp = json.loads(response.text)
|
49
|
+
except Exception:
|
50
|
+
raise Exception("响应无效")
|
51
|
+
if resp["errcode"] != 0:
|
52
|
+
raise Exception(resp["errmsg"])
|
53
|
+
data = resp["data"]
|
54
|
+
return data
|
55
|
+
|
56
|
+
return wrapper
|
57
|
+
|
58
|
+
return inner
|
jit_utils/exceptions.py
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# -*-coding:utf-8-*-
|
2
|
+
"""
|
3
|
+
Created on 2025/1/13 15:54
|
4
|
+
|
5
|
+
@author: 'wuhao'
|
6
|
+
|
7
|
+
@desc:
|
8
|
+
"""
|
9
|
+
import os
|
10
|
+
import traceback
|
11
|
+
|
12
|
+
from jit.commons.utils.logger import log
|
13
|
+
from jit.errcode import ElementErrCode
|
14
|
+
|
15
|
+
|
16
|
+
class BaseElementException(object):
|
17
|
+
PREFIX = "exc"
|
18
|
+
|
19
|
+
def __init__(self, fullName, title):
|
20
|
+
self.fullName = fullName
|
21
|
+
self.title = title
|
22
|
+
|
23
|
+
def getTrace(self, exc):
|
24
|
+
trace = traceback.extract_tb(exc.__traceback__)[-1]
|
25
|
+
filename, lineno, func, text = trace
|
26
|
+
filename = filename.replace(os.environ["rootPath"], "").replace(os.sep, ".")
|
27
|
+
return filename, lineno, func, text
|
28
|
+
|
29
|
+
# def other(self,exc):
|
30
|
+
# """
|
31
|
+
# 遇到未定义的异常类型处理时调用
|
32
|
+
# :param exc:
|
33
|
+
# :return:
|
34
|
+
# """
|
35
|
+
|
36
|
+
def handleException(self, exc):
|
37
|
+
exceptionName = type(exc).__name__
|
38
|
+
log.exception(exc)
|
39
|
+
handler = getattr(self, self.PREFIX + exceptionName, None)
|
40
|
+
if handler:
|
41
|
+
code = handler(exc)
|
42
|
+
return code
|
43
|
+
# 遇到使用者为定义的异常类型处理时调用
|
44
|
+
elif hasattr(self, "other"):
|
45
|
+
code = self.other(exc)
|
46
|
+
return code
|
47
|
+
# 没定义任何处理
|
48
|
+
else:
|
49
|
+
return None
|
50
|
+
|
51
|
+
def excAttributeError(self, exc):
|
52
|
+
filename, lineno, func, text = self.getTrace(exc)
|
53
|
+
errMsg = "访问了{objName}对象不存在的属性{attrName},在文件{filename}第{lineno}行,异常代码:{text}".format(
|
54
|
+
objName=exc.obj, attrName=exc.name, filename=filename, lineno=lineno, text=text
|
55
|
+
)
|
56
|
+
code = ElementErrCode.ELEMENT_ERROR.formatReason(fullName=self.fullName, title=self.title, errMsg=errMsg)
|
57
|
+
return code
|
58
|
+
|
59
|
+
def excValueError(self, exc):
|
60
|
+
filename, lineno, func, text = self.getTrace(exc)
|
61
|
+
errMsg = "无效的值,在文件{filename}第{lineno}行,异常代码:{text}".format(
|
62
|
+
filename=filename, lineno=lineno, text=text
|
63
|
+
)
|
64
|
+
code = ElementErrCode.ELEMENT_ERROR.formatReason(fullName=self.fullName, title=self.title, errMsg=errMsg)
|
65
|
+
return code
|
66
|
+
|
67
|
+
def excTypeError(self, exc):
|
68
|
+
filename, lineno, func, text = self.getTrace(exc)
|
69
|
+
errMsg = "不支持的类型操作,在文件{filename}第{lineno}行,异常代码:{text}".format(
|
70
|
+
filename=filename, lineno=lineno, text=text
|
71
|
+
)
|
72
|
+
code = ElementErrCode.ELEMENT_ERROR.formatReason(fullName=self.fullName, title=self.title, errMsg=errMsg)
|
73
|
+
return code
|
74
|
+
|
75
|
+
def excIndexError(self, exc):
|
76
|
+
filename, lineno, func, text = self.getTrace(exc)
|
77
|
+
errMsg = "索引越界,在文件{filename}第{lineno}行,异常代码:{text}".format(
|
78
|
+
filename=filename, lineno=lineno, text=text
|
79
|
+
)
|
80
|
+
code = ElementErrCode.ELEMENT_ERROR.formatReason(fullName=self.fullName, title=self.title, errMsg=errMsg)
|
81
|
+
return code
|
82
|
+
|
83
|
+
def excKeyError(self, exc):
|
84
|
+
filename, lineno, func, text = self.getTrace(exc)
|
85
|
+
errMsg = "字典没有这个key,在文件{filename}第{lineno}行,异常代码:{text}".format(
|
86
|
+
filename=filename, lineno=lineno, text=text
|
87
|
+
)
|
88
|
+
code = ElementErrCode.ELEMENT_ERROR.formatReason(fullName=self.fullName, title=self.title, errMsg=errMsg)
|
89
|
+
return code
|
90
|
+
|
91
|
+
def excNameError(self, exc):
|
92
|
+
filename, lineno, func, text = self.getTrace(exc)
|
93
|
+
errMsg = "没有定义的变量,在文件{filename}第{lineno}行,异常代码:{text}".format(
|
94
|
+
filename=filename, lineno=lineno, text=text
|
95
|
+
)
|
96
|
+
code = ElementErrCode.ELEMENT_ERROR.formatReason(fullName=self.fullName, title=self.title, errMsg=errMsg)
|
97
|
+
return code
|
98
|
+
|
99
|
+
def excSyntaxError(self, exc):
|
100
|
+
filename, lineno, func, text = self.getTrace(exc)
|
101
|
+
errMsg = "语法错误,在文件{filename}第{lineno}行,异常代码:{text}".format(
|
102
|
+
filename=filename, lineno=lineno, text=text
|
103
|
+
)
|
104
|
+
code = ElementErrCode.ELEMENT_ERROR.formatReason(fullName=self.fullName, title=self.title, errMsg=errMsg)
|
105
|
+
return code
|
106
|
+
|
107
|
+
def excZeroDivisionError(self, exc):
|
108
|
+
filename, lineno, func, text = self.getTrace(exc)
|
109
|
+
errMsg = "除数为0,在文件{filename}第{lineno}行,异常代码:{text}".format(
|
110
|
+
filename=filename, lineno=lineno, text=text
|
111
|
+
)
|
112
|
+
code = ElementErrCode.ELEMENT_ERROR.formatReason(fullName=self.fullName, title=self.title, errMsg=errMsg)
|
113
|
+
return code
|
jit_utils/forwarder.py
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# -*-coding:utf-8-*-
|
2
|
+
"""
|
3
|
+
Created on 2024/12/11
|
4
|
+
|
5
|
+
@author: 臧韬
|
6
|
+
|
7
|
+
@desc: 默认描述
|
8
|
+
"""
|
9
|
+
|
10
|
+
import inspect
|
11
|
+
import types
|
12
|
+
|
13
|
+
|
14
|
+
class MethodForwarder(object):
|
15
|
+
"""
|
16
|
+
cls方法转换器,可以将这个函数的所有方法都转换成目标函数,可以在不修改原始类的任何代码情况进行装饰。
|
17
|
+
使用方法:
|
18
|
+
def myfunc(args, kwargs, extends):
|
19
|
+
# 目标函数
|
20
|
+
return 2
|
21
|
+
|
22
|
+
class MyClass(object):
|
23
|
+
def func(self):
|
24
|
+
return 1
|
25
|
+
|
26
|
+
@ClsForward(myFunc)
|
27
|
+
class ForwardClass(MyClass):
|
28
|
+
pass
|
29
|
+
|
30
|
+
>> MyClass().func()
|
31
|
+
1
|
32
|
+
|
33
|
+
>> ForwardClass().func()
|
34
|
+
2
|
35
|
+
|
36
|
+
特点:
|
37
|
+
1. 目标函数中如果返回了 ClsForward.DoNotForward,则会执行原来的函数或者方法
|
38
|
+
2. 目标函数的入参必须是 args, kwargs, extend
|
39
|
+
args, kwargs 是调用这个函数的参数
|
40
|
+
extend是一个字典,包含3个参数
|
41
|
+
cls -> 类对象
|
42
|
+
self -> 如果是通过实例化的对象调用的函数或方法,这里会传入实例对象
|
43
|
+
func -> 执行的函数对象,如果是类方法,则返回的绑定到这个类的method对象。如果是成员方法和静态方法,则传入的是function对象。
|
44
|
+
3. 可以在装饰器的入参中指定excludeFunc,函数名满足这个函数则不会转发
|
45
|
+
参考:
|
46
|
+
def excludeFunc(name):
|
47
|
+
return name == "view" and name.startswith("_")
|
48
|
+
|
49
|
+
@ClsForward(myFunc, excludeFunc=excludeFunc)
|
50
|
+
class ForwardClass(MyClass):
|
51
|
+
pass
|
52
|
+
|
53
|
+
这样这个类在遇到view函数和开头为下划线的函数,则不会转换。
|
54
|
+
excludeFunc是选传的,默认情况下忽略下划线开头的函数。
|
55
|
+
"""
|
56
|
+
|
57
|
+
DoNotForward = object()
|
58
|
+
|
59
|
+
def __init__(self, targetFunc, excludeFunc=None):
|
60
|
+
self.targetFunc = targetFunc
|
61
|
+
self.clss = None
|
62
|
+
self.excludeFunc = excludeFunc or self.defaultExcludeFunc
|
63
|
+
|
64
|
+
def __call__(self, clss):
|
65
|
+
self.clss = clss
|
66
|
+
|
67
|
+
for name in dir(clss):
|
68
|
+
if callable(self.excludeFunc):
|
69
|
+
if self.excludeFunc(name):
|
70
|
+
continue
|
71
|
+
func = getattr(clss, name)
|
72
|
+
if inspect.ismethod(func):
|
73
|
+
setattr(clss, name, classmethod(self.classForward(func, self.targetFunc)))
|
74
|
+
if inspect.isfunction(func):
|
75
|
+
setattr(clss, name, self.classForward(func, self.targetFunc))
|
76
|
+
return clss
|
77
|
+
|
78
|
+
def classForward(self, func, targetFunc):
|
79
|
+
|
80
|
+
def wrapper(*args, **kwargs):
|
81
|
+
# 如果是实例调用方法,args第一个会传入对象
|
82
|
+
if args and (isinstance(args[0], self.clss) or issubclass(args[0], self.clss)):
|
83
|
+
sf, *rArgs = args
|
84
|
+
rArgs = tuple(rArgs)
|
85
|
+
else:
|
86
|
+
sf = None
|
87
|
+
rArgs = args
|
88
|
+
|
89
|
+
extend = {
|
90
|
+
"clss": self.clss,
|
91
|
+
"self": sf,
|
92
|
+
"func": func,
|
93
|
+
}
|
94
|
+
result = targetFunc(rArgs, kwargs, extend)
|
95
|
+
if result is self.DoNotForward:
|
96
|
+
if sf:
|
97
|
+
if inspect.isfunction(func):
|
98
|
+
# 实例方法
|
99
|
+
return types.MethodType(func, sf)(*rArgs, **kwargs)
|
100
|
+
else:
|
101
|
+
# 类方法
|
102
|
+
return types.MethodType(func.__func__, sf)(*rArgs, **kwargs)
|
103
|
+
else:
|
104
|
+
# 静态方法
|
105
|
+
return func(*rArgs, **kwargs)
|
106
|
+
|
107
|
+
return result
|
108
|
+
|
109
|
+
return wrapper
|
110
|
+
|
111
|
+
@staticmethod
|
112
|
+
def defaultExcludeFunc(name):
|
113
|
+
return name.startswith("_")
|