gomyck-tools 1.2.2__py3-none-any.whl → 1.2.4__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.
ctools/bottle_web_base.py CHANGED
@@ -112,7 +112,7 @@ def params_resolve(func):
112
112
  elif request.method == 'POST':
113
113
  content_type = request.get_header('content-type')
114
114
  if content_type == 'application/json':
115
- params = request.json
115
+ params = request.json or {}
116
116
  return func(params=DictWrapper(params), *args, **kwargs)
117
117
  elif content_type and 'multipart/form-data' in content_type:
118
118
  form_data = request.forms.decode()
@@ -1,8 +1,11 @@
1
+ import sys
1
2
  from socketserver import ThreadingMixIn
2
3
  from wsgiref.simple_server import WSGIServer, WSGIRequestHandler, make_server
3
4
 
4
5
  from bottle import ServerAdapter, Bottle, template, static_file
5
6
 
7
+ from ctools import sys_info
8
+
6
9
  """
7
10
  app = bottle_web_base.init_app('子模块写 context_path, 主模块就不用写任何东西')
8
11
 
@@ -43,6 +46,7 @@ class CBottle:
43
46
 
44
47
  def run(self):
45
48
  http_server = WSGIRefServer(port=self.port)
49
+ print('Click the link below to open the service homepage %s' % '\n \t\t http://localhost:%s \n \t\t http://%s:%s' % (self.port, sys_info.get_local_ipv4(), self.port), file=sys.stderr)
46
50
  self.bottle.run(server=http_server, quiet=self.quiet)
47
51
 
48
52
  def set_index(self, path, **kwargs):
ctools/database.py CHANGED
@@ -31,7 +31,13 @@ def _init():
31
31
  Base = declarative_base()
32
32
 
33
33
  # 密码里的@ 要替换成 %40
34
- # sqlite connect_args={"check_same_thread": False} sqlite:///{}.format(db_url)
34
+
35
+ # sqlite connect_args={"check_same_thread": False} db_url=sqlite:///{}.format(db_url)
36
+ # sqlite 数据库, 初始化之后, 优化一下配置
37
+ # $ sqlite3 app.db
38
+ # > PRAGMA journal_mode=WAL; 设置事务的模式, wal 允许读写并发, 但是会额外创建俩文件
39
+ # > PRAGMA synchronous=NORMAL; 设置写盘策略, 默认是 FULL, 日志,数据都落, 设置成 NORMAL, 日志写完就算事务完成
40
+
35
41
  def init_db(db_url: str, db_key: str='default', connect_args: dict={}, default_schema: str=None, pool_size: int=5, max_overflow: int=25, echo: bool=False):
36
42
  if db_url.startswith('mysql'):
37
43
  import pymysql
@@ -63,7 +69,8 @@ def _create_connection(db_url: str, pool_size: int=5, max_overflow: int=25, conn
63
69
  def generate_custom_id():
64
70
  return str(string_tools.get_snowflake_id())
65
71
 
66
- class BaseMixin:
72
+ class BaseMixin(Base):
73
+ __abstract__ = True
67
74
  obj_id = Column(Integer, primary_key=True, default=generate_custom_id)
68
75
  # ext1 = Column(String)
69
76
  # ext2 = Column(String)
ctools/metrics.py CHANGED
@@ -1,29 +1,34 @@
1
1
  import os
2
2
  import threading
3
+ import time
3
4
  from enum import Enum
4
5
 
5
- from prometheus_client import Counter, Gauge, Summary, Histogram
6
-
7
- from ctools import call, cjson, sys_log
8
- from ctools.application import Server
6
+ from prometheus_client import Counter, Gauge, Summary, Histogram, start_http_server
7
+ from ctools import call, cjson, sys_log, work_path
9
8
 
10
9
  log = sys_log.flog
11
10
 
12
- metrics = {}
11
+ _metrics_port = 8011
12
+ _persistent_json = {}
13
13
  _metrics_initial = {}
14
- persistent_json = {}
15
- temp_metrics_json = {}
16
- is_metrics_init: bool = True
17
14
  _lock = threading.Lock()
18
15
 
19
16
 
17
+ # 认证中间件
18
+ # @app.before_request
19
+ # def check_authentication():
20
+ # auth = request.authorization
21
+ # if not auth or auth.username != USERNAME or auth.password != PASSWORD:
22
+ # return Response(
23
+ # "Unauthorized", 401, {"WWW-Authenticate": 'Basic realm="Login Required"'}
24
+ # )
25
+
20
26
  class MetricType(Enum):
21
27
  COUNTER = 'counter'
22
28
  GAUGE = 'gauge'
23
29
  SUMMARY = 'summary'
24
30
  HISTOGRAM = 'histogram'
25
31
 
26
-
27
32
  class Metric:
28
33
  def __init__(self, metric_type: MetricType, metric_key: str, metric_labels: [],
29
34
  persistent: bool = False, buckets: [] = None, reset: bool = False, desc: str = ""):
@@ -47,60 +52,51 @@ class Metric:
47
52
  raise Exception('metric type not found')
48
53
  _metrics_initial[metric_key] = self
49
54
 
50
-
51
55
  @call.once
52
- def init():
53
- global is_metrics_init
54
- global temp_metrics_json
55
- persistent_path = os.path.join(Server.indicatorsPath, 'persistent.json')
56
- if os.path.exists(persistent_path):
56
+ def init(reset_persistent: bool = False):
57
+ persistent_path = os.path.join(work_path.get_current_path(), 'persistent.json')
58
+ if os.path.exists(persistent_path) and not reset_persistent:
57
59
  with open(persistent_path, 'r') as persistent_file:
58
- global persistent_json
60
+ global _persistent_json
59
61
  try:
60
62
  content = persistent_file.readline()
61
- # log.info("persistent初始化: %s" % content)
62
- persistent_json = cjson.loads(content)
63
+ log.info("persistent初始化: %s" % content)
64
+ _persistent_json = cjson.loads(content)
63
65
  except Exception:
64
66
  log.error('persistent.json is not valid json!!!!!')
65
- persistent_json = {}
67
+ _persistent_json = {}
66
68
  _init_all_metrics()
67
- for key, item in persistent_json.items():
69
+ for key, item in _persistent_json.items():
68
70
  metrics_key = key.split("-")[0]
69
71
  if '_labels' in key or metrics_key not in _metrics_initial: continue
70
- opt(metrics_key, persistent_json[key + '_labels'], persistent_json[key])
72
+ opt(metrics_key, _persistent_json[key + '_labels'], _persistent_json[key])
71
73
  persistent_metrics()
72
- is_metrics_init = False
74
+ start_http_server(port=_metrics_port)
73
75
 
74
-
75
- @call.schd(60, start_by_call=True)
76
+ @call.schd(5, start_by_call=True)
76
77
  def persistent_metrics():
77
- if persistent_json and not _lock.locked():
78
- with open(os.path.join(Server.indicatorsPath, 'persistent.json'), 'w') as persistent_file:
79
- persistent_file.write(cjson.dumps(persistent_json))
78
+ if _persistent_json and not _lock.locked():
79
+ log.info('begin persistent metrics to file...')
80
+ with open(os.path.join(work_path.get_current_path(), 'persistent.json'), 'w') as persistent_file:
81
+ persistent_file.write(cjson.dumps(_persistent_json))
80
82
  persistent_file.flush()
81
83
 
82
-
83
84
  def opt(metric_key: str, label_values: [], metric_value: int):
84
85
  _lock.acquire(timeout=5)
85
86
  try:
86
87
  persistent_key = "%s-%s" % (metric_key, "_".join(map(str, label_values)))
87
- metric_entity: Metric = metrics.get(persistent_key)
88
- if not metric_entity:
89
- metric_entity = metrics[persistent_key] = _metrics_initial[metric_key]
90
-
88
+ metric_entity: Metric = _metrics_initial[metric_key]
91
89
  if metric_entity.persistent:
92
- if not is_metrics_init and not metric_entity.reset and persistent_key in persistent_json:
93
- persistent_json[persistent_key] += metric_value
90
+ if not metric_entity.reset and persistent_key in _persistent_json:
91
+ _persistent_json[persistent_key] += metric_value
94
92
  else:
95
- persistent_json[persistent_key] = metric_value
96
- persistent_json[persistent_key + '_labels'] = label_values
93
+ _persistent_json[persistent_key] = metric_value
94
+ _persistent_json[persistent_key + '_labels'] = label_values
97
95
 
98
- if persistent_json[persistent_key] < 0:
99
- persistent_json[persistent_key] = 0
96
+ if _persistent_json[persistent_key] < 0:
97
+ _persistent_json[persistent_key] = 0
100
98
  metric_value = 0
101
99
 
102
- temp_metrics_json[persistent_key] = metric_value
103
-
104
100
  if metric_entity.metric_type == MetricType.COUNTER or metric_entity.metric_type == MetricType.GAUGE:
105
101
  if label_values is None or len(label_values) == 0:
106
102
  if metric_entity.metric_type == MetricType.COUNTER and metric_entity.reset:
@@ -123,4 +119,15 @@ def opt(metric_key: str, label_values: [], metric_value: int):
123
119
  _lock.release()
124
120
 
125
121
  def _init_all_metrics():
126
- Metric(MetricType.COUNTER, 'demo123123', ['asdasd', 'sdfsdf'], persistent=True)
122
+ Metric(MetricType.GAUGE, 'data_reported_time', ['asdasd', 'sdfsdf'], persistent=True, reset=True)
123
+ Metric(MetricType.GAUGE, 'data_received_time', ['asdasd', 'sdfsdf'], persistent=True, reset=True)
124
+ Metric(MetricType.GAUGE, 'data_insert_time', ['asdasd', 'sdfsdf'], persistent=True, reset=True)
125
+
126
+ if __name__ == '__main__':
127
+ init()
128
+ import random
129
+ while True:
130
+ opt('data_reported_time', ['123', '123'], random.randint(1, 10))
131
+ opt('data_received_time', ['123', '123'], random.randint(1, 10))
132
+ opt('data_insert_time', ['123', '123'], random.randint(1, 10))
133
+ time.sleep(1)
ctools/string_tools.py CHANGED
@@ -1,24 +1,20 @@
1
- import hashlib
2
- import random
3
- import uuid
4
- from typing import Union
5
-
6
- import chardet
7
-
8
1
  from ctools.snow_id import SnowId
9
2
 
10
3
  idWorker = SnowId(1, 2, 0)
11
4
 
12
- def get_random_str(size: int = 10):
13
- return "".join(random.sample('abcdefghijklmnopqrstuvwxyz0123456789', size))
5
+ def get_random_str(size: int = 10) -> str:
6
+ import random
7
+ return "".join(random.sample('abcdefghjklmnpqrstuvwxyz123456789', size))
14
8
 
15
- def get_uuid():
9
+ def get_uuid() -> str:
10
+ import uuid
16
11
  return str(uuid.uuid1()).replace("-", "")
17
12
 
18
13
  def get_snowflake_id():
19
14
  return idWorker.get_id()
20
15
 
21
- def decode_bytes(bytes_str: Union[bytes, bytearray]):
16
+ def decode_bytes(bytes_str):
17
+ import chardet
22
18
  res_str = ""
23
19
  if bytes_str:
24
20
  detect = chardet.detect(bytes_str)
@@ -41,6 +37,7 @@ def decode_bytes(bytes_str: Union[bytes, bytearray]):
41
37
 
42
38
 
43
39
  def check_sum(content: str):
40
+ import hashlib
44
41
  try:
45
42
  algorithm = hashlib.sha256()
46
43
  algorithm.update(content.encode())
@@ -78,7 +75,7 @@ def dict_to_params(obj: dict):
78
75
  if k == 'varname':
79
76
  continue
80
77
  v = str(v)
81
- if not is_list(v) and not is_digit(v) and not is_bool(v) and not is_obj(k):
78
+ if not is_list(v) and not is_digit(v) and not is_bool(v):
82
79
  if k == "path" and v[:4] != "http":
83
80
  v = "r'%s'" % v
84
81
  else:
ctools/sys_info.py CHANGED
@@ -1,20 +1,16 @@
1
- import getpass
2
1
  import hashlib
3
2
  import os
4
3
  import platform
5
- import socket
6
- import uuid
7
- from bottle import request
8
4
 
9
5
  from ctools import cjson, sm_tools, work_path
10
6
 
11
7
  MACHINE_KEY = b'EnrGffoorbFyTYoS0902YyT1Fhehj4InpbezIDUuPOg='
12
8
 
13
-
14
9
  class MachineInfo:
15
10
  machine_code = None
16
11
 
17
12
  def get_user():
13
+ import getpass
18
14
  return getpass.getuser()
19
15
 
20
16
  def get_machine_code():
@@ -72,27 +68,46 @@ def get_origin_machine_code():
72
68
 
73
69
 
74
70
  def get_hash_machine_code(origin_code):
71
+ import uuid
75
72
  code = origin_code + uuid.uuid1().hex
76
73
  machine_code = hashlib.md5(code.encode()).hexdigest()
77
74
  return machine_code.upper()
78
75
 
76
+ def get_public_ip():
77
+ import requests
78
+ try:
79
+ response = requests.get("https://api.ipify.org?format=json")
80
+ ip = response.json()["ip"]
81
+ return ip
82
+ except Exception as e:
83
+ return f"Failed to get public IP: {e}"
79
84
 
80
85
  def get_local_ipv4():
81
- ip = socket.gethostname()
86
+ import psutil
87
+ import socket
88
+ interfaces = psutil.net_if_addrs()
89
+ for interface, addresses in interfaces.items():
90
+ for address in addresses:
91
+ if address.family == socket.AF_INET and not address.address.startswith("127."):
92
+ return address.address
93
+ print("Failed to get local IPv4 address, try another way...")
94
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
82
95
  try:
83
- ip = socket.gethostbyname_ex(ip)[2][-1]
96
+ s.connect(("8.8.8.8", 80))
97
+ ip = s.getsockname()[0]
84
98
  except Exception:
85
- pass
99
+ ip = '127.0.0.1'
100
+ finally:
101
+ s.close()
86
102
  return ip
87
103
 
88
-
89
104
  def get_remote_ipv4():
105
+ from bottle import request
90
106
  try:
91
107
  return request.remote_route[0]
92
108
  except:
93
109
  return '127.0.0.1'
94
110
 
95
-
96
111
  def get_proc_pid_by(cmdline):
97
112
  import psutil
98
113
  """
@@ -111,7 +126,6 @@ def get_proc_pid_by(cmdline):
111
126
  pass
112
127
  return pid_list
113
128
 
114
-
115
129
  def get_os_architecture():
116
130
  if '64' in platform.machine():
117
131
  return '64'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gomyck-tools
3
- Version: 1.2.2
3
+ Version: 1.2.4
4
4
  Summary: A ctools for python development by hao474798383
5
5
  Home-page: https://blog.gomyck.com
6
6
  Author: gomyck
@@ -27,5 +27,6 @@ Requires-Dist: paho-mqtt ~=2.1.0
27
27
  Requires-Dist: fuzzywuzzy ~=0.18.0
28
28
  Requires-Dist: pymysql ~=1.1.1
29
29
  Requires-Dist: pyzipper ==0.3.6
30
+ Requires-Dist: prometheus-client ==0.21.1
30
31
 
31
32
  this package is for python development
@@ -4,8 +4,8 @@ ctools/api_result.py,sha256=BLoJiTHFAIFRPCc4zer7NHTsRQFMY1TH-qmxSMk8iLU,1208
4
4
  ctools/application.py,sha256=DcuSt2m8cDuSftx6eKfJ5gA6_F9dDlzkj0K86EG4F7s,15884
5
5
  ctools/b64.py,sha256=_BdhX3p3-MaSSlU2wivN5qPxQfacR3VRBr1WC456tU0,194
6
6
  ctools/bashPath.py,sha256=BCN_EhYzqvwsxYso81omMNd3SbEociwSOyb9kLvu8V4,337
7
- ctools/bottle_web_base.py,sha256=7hXCh2gkw2Nct6U_jweW_5qCtGB6iXcgmsnMVr4_pzE,4898
8
- ctools/bottle_webserver.py,sha256=8w1oj6_P09an6Pdnr5dH9ClBiD-A6k27IBCSvqVfcTs,2550
7
+ ctools/bottle_web_base.py,sha256=pP4lgaVVZZQBMg-9QZJ145kDv4F-hdSCSfH4BDeqyWU,4904
8
+ ctools/bottle_webserver.py,sha256=hyTJrfJHAh4XXQ3zPMoF6lmdJ8FTatEpEASPfGrAa2s,2779
9
9
  ctools/bottle_websocket.py,sha256=wjsjKVE_tlon0hYfnzBT0Sis6yNPe318vKgTfzWYbfQ,1903
10
10
  ctools/browser_element_tools.py,sha256=IFR_tWu5on0LxhuC_4yT6EOjwCsC-juIoU8KQRDqR7E,9952
11
11
  ctools/call.py,sha256=BCr8wzt5qd70okv8IZn-9-EpjywleZgvA3u1vfZ_Kt8,1581
@@ -14,7 +14,7 @@ ctools/ckafka.py,sha256=EiiGCFkSbq8yRjQKVjc2_V114hKb8fJAVIOks_XbQ3w,5944
14
14
  ctools/compile_tools.py,sha256=Nybh3vnkurIKnPnubdYzigjnzFu4GaTMKPvqFdibxmE,510
15
15
  ctools/console.py,sha256=EZumuyynwteKUhUxB_XoulHswDxHd75OQB34RiZ-OBM,1807
16
16
  ctools/cron_lite.py,sha256=f9g7-64GsCxcAW-HUAvT6S-kooScl8zaJyqwHY-X_rE,8308
17
- ctools/database.py,sha256=7YzkO2tzV1KUQLHND8g9PkQwTyGd3clhgPiZ5SbC-HA,5447
17
+ ctools/database.py,sha256=M28inDYU4X69BFeVGCOwzKFtYHuQFgEm9_aoTXmrTzY,5803
18
18
  ctools/date_utils.py,sha256=qkIvn2TGQ97vUw2ppBfHE7IyCUqg0s1FzrB0BJAsaBo,868
19
19
  ctools/dict_wrapper.py,sha256=6lZUyHomdn5QdjQTg7EL1sC_I6tOlh8ofMRQT3XGQjM,398
20
20
  ctools/douglas_rarefy.py,sha256=43WRjGGsQ_o1yPEXypA1Xv_yuo90RVo7qaYGRslx5gQ,4890
@@ -26,7 +26,7 @@ ctools/html_soup.py,sha256=rnr8M3gn3gQGo-wNaNFXDjdzp8AAkv9o4yqfIIfO-zw,1567
26
26
  ctools/http_utils.py,sha256=dG26aci1_YxAyKwYqMKFw4wZAryLkDyvnQ3hURjB6Lk,768
27
27
  ctools/images_tools.py,sha256=TapXYCPqC7GesgrALecxxa_ApuT_dxUG5fqQIJF2bNY,670
28
28
  ctools/imgDialog.py,sha256=zFeyPmpnEn9Ih7-yuJJrePqW8Myj3jC9UYMTDk-umTs,1385
29
- ctools/metrics.py,sha256=vq9Fnq2fhmhS4yoHS4gO7ArKS033Eou8vpA779Uue0I,4414
29
+ ctools/metrics.py,sha256=BKNtOEskq5fvSkGX1MbAO1aG9DWjBBN9PDQZ8e-zaVM,5085
30
30
  ctools/mqtt_utils.py,sha256=ZWSZiiNJLLlkHF95S6LmRmkYt-iIL4K73VdN3b1HaHw,10702
31
31
  ctools/obj.py,sha256=GYS1B8NyjtUIh0HlK9r8avC2eGbK2SJac4C1CGnfGhI,479
32
32
  ctools/pacth.py,sha256=MJ9Du-J9Gv62y4cZKls1jKbl5a5kL2y9bD-gzYUCveQ,2604
@@ -39,9 +39,9 @@ ctools/screenshot_tools.py,sha256=KoljfgqW5x9aLwKdIfz0vR6v-fX4XjE92HudkDxC2hE,45
39
39
  ctools/sign.py,sha256=JOkgpgsMbk7T3c3MOj1U6eiEndUG9XQ-uIX9e615A_Y,566
40
40
  ctools/sm_tools.py,sha256=CDfgupqs_nrZs-135ZvDu6QIx4aamJVdg7vuLs9_0yw,1678
41
41
  ctools/snow_id.py,sha256=hYinnRN-aOule4_9vfgXB7XnsU-56cIS3PhzAwWBc5E,2270
42
- ctools/strDiff.py,sha256=QUtXOfsRLTFozH_zByqsC39JeuG3eZtrwGVeLyaHYUI,429
43
- ctools/string_tools.py,sha256=p_O3HiqlHCgzJVXHUeeDYZK2_WrqetD0eYijQFXWkGg,1938
44
- ctools/sys_info.py,sha256=p5Erxn0Rv5HRSXlqDt7ffIWCBQU66G-sdW6doMAeAks,3627
42
+ ctools/str_diff.py,sha256=QUtXOfsRLTFozH_zByqsC39JeuG3eZtrwGVeLyaHYUI,429
43
+ ctools/string_tools.py,sha256=itK59W4Ed4rQzuyHuioNgDRUcBlfb4ZoZnwmS9cJxiI,1887
44
+ ctools/sys_info.py,sha256=NvKCuBlWHHiW4bDI4tYZUo3QusvODm1HlW6aAkrllnE,4248
45
45
  ctools/sys_log.py,sha256=oqb1S41LosdeZxtogFVgDk8R4sjiHhUeYJLCzHd728E,2805
46
46
  ctools/thread_pool.py,sha256=qb68ULHy1K7u3MC7WP49wDhmgUhgWazd9FRuFbClET4,925
47
47
  ctools/upload_tools.py,sha256=sqe6K3ZWiyY58pFE5IO5mNaS1znnS7U4c4UqY8noED4,1068
@@ -51,7 +51,7 @@ ctools/wordFill.py,sha256=dB1OLt6GLmWdkDV8H20VWbJmY4ggNNI8iHD1ocae2iM,875
51
51
  ctools/word_fill.py,sha256=xeo-P4DOjQUqd-o9XL3g66wQrE2diUPGwFywm8TdVyw,18210
52
52
  ctools/word_fill_entity.py,sha256=eX3G0Gy16hfGpavQSEkCIoKDdTnNgRRJrFvKliETZK8,985
53
53
  ctools/work_path.py,sha256=i4MTUobqNW2WMrT3mwEC_XYQ0_IhFmKoNpTX2W6A8Tc,1680
54
- gomyck_tools-1.2.2.dist-info/METADATA,sha256=CzDE6NMxpgyVbq_51yDC0b4mEE0IBkcuNI85aat7t7M,1004
55
- gomyck_tools-1.2.2.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
56
- gomyck_tools-1.2.2.dist-info/top_level.txt,sha256=-MiIH9FYRVKp1i5_SVRkaI-71WmF1sZSRrNWFU9ls3s,7
57
- gomyck_tools-1.2.2.dist-info/RECORD,,
54
+ gomyck_tools-1.2.4.dist-info/METADATA,sha256=q9kd9ZRTLTnINHKnwzRXOIcjTo8an74RmCBjW57AT0Y,1046
55
+ gomyck_tools-1.2.4.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
56
+ gomyck_tools-1.2.4.dist-info/top_level.txt,sha256=-MiIH9FYRVKp1i5_SVRkaI-71WmF1sZSRrNWFU9ls3s,7
57
+ gomyck_tools-1.2.4.dist-info/RECORD,,
File without changes