gomyck-tools 1.4.1__py3-none-any.whl → 1.4.2__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.
Files changed (64) hide show
  1. ctools/__init__.py +21 -0
  2. ctools/ai/env_config.py +18 -1
  3. ctools/ai/llm_chat.py +8 -8
  4. ctools/ai/llm_client.py +26 -24
  5. ctools/ai/mcp/mcp_client.py +33 -17
  6. ctools/ai/tools/json_extract.py +3 -2
  7. ctools/ai/tools/quick_tools.py +68 -21
  8. ctools/ai/tools/tool_use_xml_parse.py +2 -1
  9. ctools/ai/tools/xml_extract.py +3 -0
  10. ctools/application.py +19 -17
  11. ctools/auto/browser_element.py +11 -3
  12. ctools/auto/plan_area.py +2 -2
  13. ctools/auto/pty_process.py +0 -1
  14. ctools/auto/screenshot.py +3 -4
  15. ctools/auto/win_canvas.py +10 -4
  16. ctools/auto/win_control.py +8 -4
  17. ctools/call.py +18 -22
  18. ctools/cdate.py +43 -2
  19. ctools/cid.py +3 -4
  20. ctools/cipher/aes_util.py +2 -2
  21. ctools/cipher/b64.py +2 -0
  22. ctools/cipher/czip.py +3 -1
  23. ctools/cipher/rsa.py +6 -1
  24. ctools/cipher/sign.py +1 -0
  25. ctools/cipher/sm_util.py +3 -0
  26. ctools/cjson.py +5 -0
  27. ctools/cron_lite.py +10 -4
  28. ctools/database/database.py +37 -17
  29. ctools/dict_wrapper.py +1 -0
  30. ctools/ex.py +1 -0
  31. ctools/geo/coord_trans.py +94 -94
  32. ctools/geo/douglas_rarefy.py +13 -9
  33. ctools/metrics.py +6 -0
  34. ctools/office/cword.py +7 -7
  35. ctools/office/word_fill.py +1 -4
  36. ctools/path_info.py +29 -0
  37. ctools/pools/process_pool.py +6 -1
  38. ctools/pools/thread_pool.py +6 -2
  39. ctools/similar.py +3 -0
  40. ctools/stream/ckafka.py +11 -5
  41. ctools/stream/credis.py +29 -21
  42. ctools/stream/mqtt_utils.py +2 -2
  43. ctools/sys_info.py +8 -0
  44. ctools/sys_log.py +3 -0
  45. ctools/util/cftp.py +4 -2
  46. ctools/util/http_util.py +1 -0
  47. ctools/util/image_process.py +1 -1
  48. ctools/util/snow_id.py +3 -2
  49. ctools/web/__init__.py +2 -2
  50. ctools/web/aio_web_server.py +19 -9
  51. ctools/web/api_result.py +3 -2
  52. ctools/web/bottle_web_base.py +15 -2
  53. ctools/web/bottle_webserver.py +14 -8
  54. ctools/web/bottle_websocket.py +4 -0
  55. ctools/web/ctoken.py +5 -1
  56. ctools/web/download_util.py +1 -1
  57. ctools/web/params_util.py +4 -0
  58. ctools/web/upload_util.py +1 -1
  59. {gomyck_tools-1.4.1.dist-info → gomyck_tools-1.4.2.dist-info}/METADATA +2 -1
  60. gomyck_tools-1.4.2.dist-info/RECORD +82 -0
  61. gomyck_tools-1.4.1.dist-info/RECORD +0 -82
  62. {gomyck_tools-1.4.1.dist-info → gomyck_tools-1.4.2.dist-info}/WHEEL +0 -0
  63. {gomyck_tools-1.4.1.dist-info → gomyck_tools-1.4.2.dist-info}/licenses/LICENSE +0 -0
  64. {gomyck_tools-1.4.1.dist-info → gomyck_tools-1.4.2.dist-info}/top_level.txt +0 -0
ctools/auto/plan_area.py CHANGED
@@ -63,8 +63,8 @@ class PlanAreaTools:
63
63
 
64
64
  def mouse_left_move(self, event):
65
65
  self.x, self.y = event.x, event.y
66
- self.xcenter = self.xstart + int((self.x-self.xstart)/2)-2
67
- self.ycenter = self.ystart + int((self.y-self.ystart)/2)-2
66
+ self.xcenter = self.xstart + int((self.x - self.xstart) / 2) - 2
67
+ self.ycenter = self.ystart + int((self.y - self.ystart) / 2) - 2
68
68
 
69
69
  self.pos_label.config(text=self.pos_div_text % (self.x, self.y))
70
70
  self.pos_div.geometry(f"+{self.x + 10}+{self.y + 10}")
@@ -70,4 +70,3 @@ class PtyTools:
70
70
 
71
71
  def close(self):
72
72
  self._process.close(force=True)
73
-
ctools/auto/screenshot.py CHANGED
@@ -65,7 +65,7 @@ class ScreenshotTools:
65
65
  def change_center_point(self, event):
66
66
  offset_x = event.x + self.xstart - self.xcenter - 2
67
67
  offset_y = event.y + self.ystart - self.ycenter - 2
68
- self.center_div.geometry(f"+{self.xstart+event.x-2}+{self.ystart+event.y-2}")
68
+ self.center_div.geometry(f"+{self.xstart + event.x - 2}+{self.ystart + event.y - 2}")
69
69
  self.center_offset = (offset_x, offset_y)
70
70
 
71
71
  def mouse_left_down(self, event):
@@ -86,8 +86,8 @@ class ScreenshotTools:
86
86
 
87
87
  def mouse_left_move(self, event):
88
88
  self.x, self.y = event.x, event.y
89
- self.xcenter = self.xstart + int((self.x-self.xstart)/2)-2
90
- self.ycenter = self.ystart + int((self.y-self.ystart)/2)-2
89
+ self.xcenter = self.xstart + int((self.x - self.xstart) / 2) - 2
90
+ self.ycenter = self.ystart + int((self.y - self.ystart) / 2) - 2
91
91
 
92
92
  self.pos_label.config(text=self.pos_div_text % (self.x, self.y))
93
93
  self.pos_div.geometry(f"+{self.x + 10}+{self.y + 10}")
@@ -125,4 +125,3 @@ def screenshot():
125
125
  st = ScreenshotTools()
126
126
  st.start()
127
127
  return st.screenshot_path, st.center_offset
128
-
ctools/auto/win_canvas.py CHANGED
@@ -4,12 +4,14 @@ from multiprocessing import Process, Queue
4
4
  data_queue: Queue = None
5
5
  canvas_process: Process = None
6
6
 
7
+
7
8
  class MSGType:
8
- BOTTOM = 'bottom' #置于底部
9
- DRAW = 'draw' #绘制矩形
9
+ BOTTOM = 'bottom' # 置于底部
10
+ DRAW = 'draw' # 绘制矩形
11
+
10
12
 
11
13
  class CanvasInfo:
12
- def __init__(self,title: str='', points: list=None, msg_type: MSGType=MSGType.DRAW):
14
+ def __init__(self, title: str = '', points: list = None, msg_type: MSGType = MSGType.DRAW):
13
15
  self.msg_type = msg_type
14
16
  # 标题
15
17
  self.title = title
@@ -17,9 +19,11 @@ class CanvasInfo:
17
19
  # [(100, 100), (200, 100), (200, 150), (100, 150)]
18
20
  self.points = points
19
21
 
22
+
20
23
  def on_ctrl_click(event):
21
24
  print("Ctrl+Left Click detected")
22
25
 
26
+
23
27
  class RecorderTool(tk.Tk):
24
28
  def __init__(self, data: Queue):
25
29
  super().__init__()
@@ -65,10 +69,12 @@ class RecorderTool(tk.Tk):
65
69
  self.draw_red_border(canvas_info)
66
70
  self.after(10, self.check_queue)
67
71
 
72
+
68
73
  def _init_recorder(data):
69
74
  canvas_app = RecorderTool(data)
70
75
  canvas_app.mainloop()
71
76
 
77
+
72
78
  def start():
73
79
  global data_queue, canvas_process
74
80
  data_queue = Queue()
@@ -76,8 +82,8 @@ def start():
76
82
  canvas_process.start()
77
83
  return canvas_process
78
84
 
85
+
79
86
  def stop():
80
87
  canvas_process.terminate()
81
88
  canvas_process.join()
82
89
  data_queue.close()
83
-
@@ -6,9 +6,9 @@ import uiautomation as auto
6
6
  from pynput import keyboard
7
7
 
8
8
  from ctools import application
9
+ from ctools import cid
9
10
  from ctools.auto import win_canvas
10
11
  from ctools.pools import thread_pool
11
- from ctools import cid
12
12
 
13
13
  current_control = None
14
14
  ctrl_pressed = False
@@ -16,13 +16,14 @@ keyboard_listener = None
16
16
  control_json = {}
17
17
  screenshot_path = ""
18
18
 
19
+
19
20
  class ControlInfo:
20
21
  def __init__(self, ControlType, ClassName, AutomationId, Name, Depth):
21
22
  self.ControlType = ControlType
22
23
  self.ClassName = ClassName
23
24
  self.AutomationId = AutomationId
24
25
  self.Name = Name
25
- #self.Depth = Depth
26
+ # self.Depth = Depth
26
27
 
27
28
 
28
29
  def get_control_from_cursor():
@@ -36,10 +37,10 @@ def get_control_from_cursor():
36
37
  print("No control found {}".format(e))
37
38
  return
38
39
  if control:
39
- #当前控件信息
40
+ # 当前控件信息
40
41
  global current_control
41
42
  current_control = control
42
- #绘制矩形
43
+ # 绘制矩形
43
44
  canvas_info = win_canvas.CanvasInfo(control.Name, [
44
45
  (control.BoundingRectangle.left, control.BoundingRectangle.top),
45
46
  (control.BoundingRectangle.right, control.BoundingRectangle.top),
@@ -65,6 +66,7 @@ def get_control_from_cursor():
65
66
  # time.sleep(2)
66
67
  # xx.Click()
67
68
 
69
+
68
70
  def on_press(key):
69
71
  global ctrl_pressed, keyboard_listener
70
72
  if key == keyboard.Key.ctrl_l and not ctrl_pressed:
@@ -78,6 +80,7 @@ def on_press(key):
78
80
  keyboard_listener.stop()
79
81
  # pg.alert('采集成功!')
80
82
 
83
+
81
84
  def on_release(key):
82
85
  global ctrl_pressed
83
86
  if key == keyboard.Key.ctrl_l:
@@ -104,6 +107,7 @@ def get_control_json():
104
107
  time.sleep(0.5)
105
108
  return control_json, screenshot_path
106
109
 
110
+
107
111
  if __name__ == '__main__':
108
112
  a = get_control_json()
109
113
  print(a)
ctools/call.py CHANGED
@@ -3,6 +3,7 @@ import threading
3
3
  import time
4
4
  from functools import wraps
5
5
 
6
+
6
7
  # annotation
7
8
  def once(func):
8
9
  """
@@ -24,6 +25,7 @@ def once(func):
24
25
 
25
26
  return wrapper
26
27
 
28
+
27
29
  # annotation
28
30
  def init(func):
29
31
  """
@@ -38,34 +40,28 @@ def init(func):
38
40
 
39
41
  return wrapper
40
42
 
43
+
41
44
  # annotation
42
- def schd(interval_seconds, start_by_call: bool = False):
43
- start_flag = False
44
- run_flag = False
45
+ def schd(interval_seconds, start_by_call=False, run_now=False):
45
46
  scheduler = sched.scheduler(time.time, time.sleep)
46
-
47
+ lock = threading.Lock()
48
+ started = [False] # 可变对象,线程可见
49
+ print("schd delay is: ", interval_seconds)
47
50
  def decorator(func):
48
51
  @wraps(func)
49
52
  def wrapper(*args, **kwargs):
50
- nonlocal start_flag
51
- if start_by_call and not start_flag:
52
- start_flag = True
53
- threading.Thread(target=wrapper, args=args, kwargs=kwargs, daemon=True).start()
54
- return
55
-
56
53
  def job():
57
54
  func(*args, **kwargs)
58
55
  scheduler.enter(interval_seconds, 1, job)
59
-
60
- nonlocal run_flag
61
- if not run_flag:
62
- scheduler.enter(interval_seconds, 1, job)
63
- run_flag = True
64
- scheduler.run()
65
- else:
66
- func(*args, **kwargs)
67
-
68
- if not start_by_call: threading.Thread(target=wrapper, daemon=True).start()
69
- return wrapper
70
-
56
+ def start_scheduler():
57
+ with lock:
58
+ if started[0]: return
59
+ started[0] = True
60
+ if run_now: func(*args, **kwargs)
61
+ scheduler.enter(interval_seconds, 1, job)
62
+ scheduler.run()
63
+ threading.Thread(target=start_scheduler, daemon=True).start()
64
+ # 如果不是手动触发,则自动启动一次(无参数)
65
+ if not start_by_call: wrapper()
66
+ return wrapper # 如果是 start_by_call=True,返回 wrapper 让用户手动调用时带参
71
67
  return decorator
ctools/cdate.py CHANGED
@@ -1,39 +1,52 @@
1
1
  import time
2
2
  from datetime import datetime, timedelta
3
3
 
4
+ def get_month(date: str=None):
5
+ if date: return time.strftime('%Y-%m', time.strptime(date, '%Y-%m-%d'))
6
+ return time.strftime('%Y-%m', time.localtime(time.time()))
7
+
4
8
  def get_date():
5
9
  return time.strftime('%Y-%m-%d', time.localtime(time.time()))
6
10
 
11
+
7
12
  def get_time():
8
13
  return time.strftime('%H-%M-%S', time.localtime(time.time()))
9
14
 
15
+
10
16
  def get_date_time(fmt="%Y-%m-%d %H:%M:%S"):
11
17
  return time.strftime(fmt, time.localtime(time.time()))
12
18
 
19
+
13
20
  def str_to_datetime(val: str, fmt="%Y-%m-%d %H:%M:%S"):
14
21
  return time.strptime(val, fmt)
15
22
 
23
+
16
24
  def str_to_timestamp(val: str, fmt="%Y-%m-%d %H:%M:%S"):
17
25
  return time.mktime(time.strptime(val, fmt))
18
26
 
19
- def timestamp_to_str(timestamp: int=time.time(), fmt="%Y-%m-%d %H:%M:%S"):
27
+
28
+ def timestamp_to_str(timestamp: int = time.time(), fmt="%Y-%m-%d %H:%M:%S"):
20
29
  return time.strftime(fmt, time.localtime(timestamp))
21
30
 
31
+
22
32
  def get_today_start_end(now: datetime.now()):
23
33
  start = datetime(now.year, now.month, now.day, 0, 0, 0)
24
34
  end = datetime(now.year, now.month, now.day, 23, 59, 59)
25
35
  return start.strftime("%Y-%m-%d %H:%M:%S"), end.strftime("%Y-%m-%d %H:%M:%S")
26
36
 
37
+
27
38
  def get_week_start_end(now: datetime.now()):
28
39
  start = now - timedelta(days=now.weekday()) # 本周一
29
40
  end = start + timedelta(days=6) # 本周日
30
41
  return start.strftime("%Y-%m-%d 00:00:00"), end.strftime("%Y-%m-%d 23:59:59")
31
42
 
32
- def time_diff_in_seconds(sub_head: str=get_date_time(), sub_end: str=get_date_time()):
43
+
44
+ def time_diff_in_seconds(sub_head: str = get_date_time(), sub_end: str = get_date_time()):
33
45
  start_ts = str_to_timestamp(sub_head)
34
46
  end_ts = str_to_timestamp(sub_end)
35
47
  return int(start_ts - end_ts)
36
48
 
49
+
37
50
  def opt_time(base_time=None, days=0, hours=0, minutes=0, seconds=0, weeks=0, fmt="%Y-%m-%d %H:%M:%S"):
38
51
  if base_time is None:
39
52
  base_time = datetime.now()
@@ -41,3 +54,31 @@ def opt_time(base_time=None, days=0, hours=0, minutes=0, seconds=0, weeks=0, fmt
41
54
  base_time = datetime.strptime(base_time, fmt)
42
55
  new_time = base_time + timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds, weeks=weeks)
43
56
  return new_time.strftime(fmt)
57
+
58
+ def get_years_range(start_year: str, end_year: str=datetime.now().strftime("%Y")) -> set[int]:
59
+ if int(start_year) > int(end_year):
60
+ raise ValueError("起始年份不能大于结束年份")
61
+ return list(range(int(start_year), int(end_year) + 1))
62
+
63
+ def get_month_range(start: str, end: str=datetime.now().strftime("%Y-%m")) -> set[str]:
64
+ start_date = datetime.strptime(start, "%Y-%m")
65
+ end_date = datetime.strptime(end, "%Y-%m")
66
+ if start_date > end_date:
67
+ raise ValueError("起始月份不能晚于结束月份")
68
+ result = []
69
+ current = start_date
70
+ while current <= end_date:
71
+ result.append(current.strftime("%Y-%m"))
72
+ if current.month == 12:
73
+ current = current.replace(year=current.year + 1, month=1)
74
+ else:
75
+ current = current.replace(month=current.month + 1)
76
+ return result
77
+
78
+ def get_day_range(start: str, end: str=datetime.now().strftime("%Y-%m-%d")) -> set[str]:
79
+ start_date = datetime.strptime(start, "%Y-%m-%d")
80
+ end_date = datetime.strptime(end, "%Y-%m-%d")
81
+ if start_date > end_date:
82
+ raise ValueError("起始日期不能晚于结束日期")
83
+ delta = end_date - start_date
84
+ return [(start_date + timedelta(days=i)).strftime("%Y-%m-%d") for i in range(delta.days + 1)]
ctools/cid.py CHANGED
@@ -2,17 +2,16 @@ from ctools.util.snow_id import SnowId
2
2
 
3
3
  idWorker = SnowId(1, 2, 0)
4
4
 
5
+
5
6
  def get_snowflake_id():
6
7
  return idWorker.get_id()
7
8
 
9
+
8
10
  def get_random_str(size: int = 10) -> str:
9
11
  import random
10
12
  return "".join(random.sample('abcdefghjklmnpqrstuvwxyz123456789', size))
11
13
 
14
+
12
15
  def get_uuid() -> str:
13
16
  import uuid
14
17
  return str(uuid.uuid1()).replace("-", "")
15
-
16
-
17
-
18
-
ctools/cipher/aes_util.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from cryptography.fernet import Fernet
2
2
 
3
+
3
4
  def generate_key():
4
5
  """
5
6
  生成 AES key
@@ -9,6 +10,7 @@ def generate_key():
9
10
  key = Fernet.generate_key()
10
11
  return key.decode()
11
12
 
13
+
12
14
  def aes_encrypt(sec_key, plaintext):
13
15
  """
14
16
  aes加密
@@ -31,5 +33,3 @@ def aes_decrypt(sec_key, ciphertext):
31
33
  cipher = Fernet(sec_key)
32
34
  decrypted_data = cipher.decrypt(ciphertext)
33
35
  return decrypted_data.decode()
34
-
35
-
ctools/cipher/b64.py CHANGED
@@ -1,7 +1,9 @@
1
1
  import base64
2
2
 
3
+
3
4
  def encode(param: str):
4
5
  return base64.b64encode(param.encode('UTF-8')).decode('UTF-8')
5
6
 
7
+
6
8
  def decode(param: str):
7
9
  return base64.b64decode(param.encode('UTF-8')).decode('UTF-8')
ctools/cipher/czip.py CHANGED
@@ -22,6 +22,8 @@ import pyzipper
22
22
  output_directory = '/Users/haoyang/Desktop'
23
23
  compress_specific_files(files_to_compress, output_directory, zip_password, "my_files")
24
24
  """
25
+
26
+
25
27
  def create_zip_with_files(file_dict, password=None) -> io.BytesIO:
26
28
  """Compress multiple files into a single password-protected ZIP archive in memory.
27
29
  Args:
@@ -87,7 +89,7 @@ def process_directory_to_single_zip(root_dir, password=None, zip_name=None):
87
89
  if 'zip_buffer' in locals(): zip_buffer.close()
88
90
 
89
91
 
90
- def compress_specific_files(file_paths:[], output_dir:str, password=None, zip_name=None):
92
+ def compress_specific_files(file_paths: [], output_dir: str, password=None, zip_name=None):
91
93
  """Compress multiple specified files into a single ZIP archive.
92
94
  Args:
93
95
  file_paths: List of absolute file paths to compress
ctools/cipher/rsa.py CHANGED
@@ -10,6 +10,7 @@ from ctools import cjson, path_info
10
10
  ENCRYPT_CHUNK_SIZE = 245
11
11
  decrypt_CHUNK_SIZE = 512
12
12
 
13
+
13
14
  def generate_rsa_keypair(bits=2048):
14
15
  key = RSA.generate(bits)
15
16
  private_key = key.export_key() # 导出私钥
@@ -19,11 +20,13 @@ def generate_rsa_keypair(bits=2048):
19
20
  with open("public_key.pem", "wb") as f:
20
21
  f.write(public_key)
21
22
 
23
+
22
24
  def loadLicenseInfo(auth_code):
23
25
  with open(path_info.get_app_path() + '/keys/license.key', 'r') as pri:
24
26
  decrypt_message = decrypt(auth_code.strip(), pri.read())
25
27
  return cjson.loads(decrypt_message)
26
28
 
29
+
27
30
  # 加密函数
28
31
  def encrypt(msg, public_key):
29
32
  parts = b''
@@ -34,6 +37,7 @@ def encrypt(msg, public_key):
34
37
  encrypted_base64 = base64.b64encode(parts)
35
38
  return encrypted_base64.decode()
36
39
 
40
+
37
41
  # 解密函数
38
42
  def decrypt(msg, private_key):
39
43
  parts = b''
@@ -44,6 +48,7 @@ def decrypt(msg, private_key):
44
48
  parts += cipher.decrypt(encrypted_bytes[i:i + decrypt_CHUNK_SIZE])
45
49
  return parts.decode()
46
50
 
51
+
47
52
  # 验签
48
53
  def verify_sign(msg, public_key, sign):
49
54
  public_key = RSA.import_key(public_key)
@@ -55,6 +60,7 @@ def verify_sign(msg, public_key, sign):
55
60
  print('签名验证失败: {}'.format(e))
56
61
  return False
57
62
 
63
+
58
64
  # 签名
59
65
  def sign_msg(msg, private_key):
60
66
  private_key = RSA.import_key(private_key)
@@ -62,7 +68,6 @@ def sign_msg(msg, private_key):
62
68
  signature = pkcs1_15.new(private_key).sign(hash_message)
63
69
  return base64.b64encode(signature).decode()
64
70
 
65
-
66
71
  # with open(work_path.get_current_path() + '/private_key.pem', 'r') as key:
67
72
  # key = key.read()
68
73
  # sign = sign_msg(key, key)
ctools/cipher/sign.py CHANGED
@@ -14,6 +14,7 @@ def generate_signature(file_path, key: str = global_key):
14
14
  except:
15
15
  return ''
16
16
 
17
+
17
18
  def digest(value: str, key: str = global_key):
18
19
  val_hash = hashlib.sha256(value.encode()).digest()
19
20
  sign_val = hmac.new(key.encode(), val_hash, hashlib.sha256).digest()
ctools/cipher/sm_util.py CHANGED
@@ -5,6 +5,7 @@ from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
5
5
 
6
6
  sm2_crypt: sm2.CryptSM2 = None
7
7
 
8
+
8
9
  def init(private_key: str, public_key: str):
9
10
  global sm2_crypt
10
11
  if sm2_crypt is not None:
@@ -12,6 +13,7 @@ def init(private_key: str, public_key: str):
12
13
  return
13
14
  sm2_crypt = sm2.CryptSM2(private_key=private_key, public_key=public_key, asn1=True, mode=1)
14
15
 
16
+
15
17
  def sign_with_sm2(sign_data: str) -> str:
16
18
  if sm2_crypt is None: raise Exception('sm2 is not init!!!')
17
19
  return sm2_crypt.sign_with_sm3(sign_data.encode('UTF-8'))
@@ -25,6 +27,7 @@ def verify_with_sm2(sign_val: str, sign_data: str) -> bool:
25
27
  print('签名验证失败: {}'.format(e))
26
28
  return False
27
29
 
30
+
28
31
  def encrypt_with_sm2(encrypt_data: str) -> str:
29
32
  if sm2_crypt is None: raise Exception('sm2 is not init!!!')
30
33
  return base64.b64encode(sm2_crypt.encrypt(encrypt_data.encode('UTF-8'))).decode('UTF-8')
ctools/cjson.py CHANGED
@@ -6,6 +6,7 @@ jsonpickle.set_preferred_backend('json')
6
6
  jsonpickle.set_encoder_options('json', ensure_ascii=False)
7
7
  jsonpickle.set_decoder_options('json')
8
8
 
9
+
9
10
  def dumps(obj, **kwargs) -> str:
10
11
  """
11
12
  将对象转换为json字符串
@@ -17,6 +18,7 @@ def dumps(obj, **kwargs) -> str:
17
18
  if type(obj) == str: return obj
18
19
  return f'{jsonpickle.encode(obj, unpicklable=False, make_refs=False, **kwargs)}'
19
20
 
21
+
20
22
  def loads(json_str: str, **kwargs) -> dict:
21
23
  """
22
24
  将json字符串转换为对象
@@ -25,6 +27,7 @@ def loads(json_str: str, **kwargs) -> dict:
25
27
  """
26
28
  return jsonpickle.decode(json_str, **kwargs)
27
29
 
30
+
28
31
  def unify_to_str(json_str: str) -> str:
29
32
  if not str_value_keys and len(str_value_keys) == 0: return json_str
30
33
  obj = loads(json_str)
@@ -34,6 +37,7 @@ def unify_to_str(json_str: str) -> str:
34
37
  _handle_dict(obj)
35
38
  return dumps(obj)
36
39
 
40
+
37
41
  def _handle_list(data):
38
42
  for o in data:
39
43
  if isinstance(o, list):
@@ -41,6 +45,7 @@ def _handle_list(data):
41
45
  elif isinstance(o, dict):
42
46
  _handle_dict(o)
43
47
 
48
+
44
49
  def _handle_dict(data):
45
50
  for k, v in data.items():
46
51
  if isinstance(v, list):
ctools/cron_lite.py CHANGED
@@ -29,6 +29,7 @@ print(123123)
29
29
  cron_lite.start_all()
30
30
  """
31
31
 
32
+
32
33
  class SchedulerMeta:
33
34
  timer_task_name: str = None
34
35
  switch: bool = True
@@ -40,7 +41,7 @@ class SchedulerMeta:
40
41
 
41
42
  scheduler_map: Dict[str, SchedulerMeta] = {} # {timer_task_name: SchedulerMeta}
42
43
  _switch = False
43
- _info_handler = print
44
+ _info_handler = print
44
45
  _error_handler = print
45
46
  _time_zone: Optional[pytz.BaseTzInfo] = pytz.timezone("Asia/Shanghai")
46
47
 
@@ -49,6 +50,7 @@ def set_time_zone(time_zone_name: str):
49
50
  global _time_zone
50
51
  _time_zone = pytz.timezone(time_zone_name)
51
52
 
53
+
52
54
  # @annotation
53
55
  def cron_task(cron_expr: str, task_name: str = None, till_time_stamp: int = None):
54
56
  """
@@ -92,8 +94,9 @@ def reg_cron_task(cron_expr, func, params, timer_task_name=None, till_time_stamp
92
94
  :return: the real decorator
93
95
  """
94
96
  cron_expr = _convert_cron(cron_expr)
95
- assert len(cron_expr.split(" ")) in (5, 6), "Only supported <minute hour day month weekday> and <minute hour day month weekday second>"
97
+ assert len(cron_expr.split(" ")) in (5, 6), "Only supported <minute hour day month weekday> and <minute hour day month weekday second>"
96
98
  task_name = func.__name__ if timer_task_name is None else timer_task_name
99
+
97
100
  @wraps(func)
98
101
  def wrapper(*args, **kwargs):
99
102
  try:
@@ -107,6 +110,7 @@ def reg_cron_task(cron_expr, func, params, timer_task_name=None, till_time_stamp
107
110
 
108
111
  _register_next(task_name, wrapper, cron_expr, till_time_stamp, init=True)
109
112
 
113
+
110
114
  def start_all(spawn: bool = True, daemon: bool = True, info_handler=None, error_handler=None) -> Optional[threading.Thread]:
111
115
  """
112
116
  start_all starts all cron tasks registered before.
@@ -144,6 +148,7 @@ def active(timer_task_name):
144
148
  if timer_task_name in scheduler_map:
145
149
  scheduler_map.get(timer_task_name).status = True
146
150
 
151
+
147
152
  def get_switch(timer_task_name):
148
153
  switch = True
149
154
  if timer_task_name in scheduler_map:
@@ -215,6 +220,7 @@ def _run_sched(scheduler_meta: SchedulerMeta):
215
220
  return
216
221
  time.sleep(0.5)
217
222
 
223
+
218
224
  def _start(taskName: str = None):
219
225
  global _switch
220
226
  _switch = True
@@ -223,7 +229,7 @@ def _start(taskName: str = None):
223
229
  for timer_task_name, scheduler_meta in scheduler_map.items():
224
230
  if taskName is not None and timer_task_name != taskName: continue
225
231
  print("register job: ", timer_task_name, ", cron: ", scheduler_meta.cron_str)
226
- thread = threading.Thread(target=_run_sched, args=(scheduler_meta, ), daemon=True)
232
+ thread = threading.Thread(target=_run_sched, args=(scheduler_meta,), daemon=True)
227
233
  thread.start()
228
234
  taskList.append(thread)
229
235
  for task in taskList: task.join()
@@ -231,6 +237,7 @@ def _start(taskName: str = None):
231
237
  _switch = False
232
238
  scheduler_map.clear()
233
239
 
240
+
234
241
  def _convert_cron(cron_expr):
235
242
  res_cron = ""
236
243
  cron_list = cron_expr.split(" ")
@@ -242,4 +249,3 @@ def _convert_cron(cron_expr):
242
249
  else:
243
250
  res_cron = cron_expr
244
251
  return res_cron
245
-