ryry-cli 1.0__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.
ryry/ryry_widget.py ADDED
@@ -0,0 +1,398 @@
1
+ import os
2
+ import json
3
+ import sys
4
+ import shutil
5
+ import zipfile
6
+ import pkg_resources
7
+ import threading
8
+ import time
9
+ import requests
10
+ import random
11
+ import subprocess
12
+ import platform
13
+ import re
14
+ from pkg_resources import get_distribution
15
+ import socket
16
+
17
+ from pathlib import Path
18
+ from ryry import store
19
+ from ryry import ryry_webapi
20
+ from ryry import upload
21
+ from ryry import taskUtils
22
+ from ryry import utils
23
+
24
+ def compare_versions(version1, version2):
25
+ if len(version1) <= 0:
26
+ version1 = "0"
27
+ if len(version2) <= 0:
28
+ version2 = "0"
29
+ v1 = list(map(int, version1.split('.')))
30
+ v2 = list(map(int, version2.split('.')))
31
+ while len(v1) < len(v2):
32
+ v1.append(0)
33
+ while len(v2) < len(v1):
34
+ v2.append(0)
35
+ for i in range(len(v1)):
36
+ if v1[i] < v2[i]:
37
+ return -1
38
+ elif v1[i] > v2[i]:
39
+ return 1
40
+ return 0
41
+
42
+ def _remote_package_version(py_package):
43
+ remote_version = ""
44
+ result = subprocess.run(f"pip index versions {py_package} -i https://pypi.python.org/simple/",
45
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
46
+ ss = result.stdout.decode(encoding="utf8", errors="ignore").split("\n")
47
+ for s in ss:
48
+ if "LATEST:" in s.strip():
49
+ remote_version = s.replace("LATEST:", "").strip()
50
+ return remote_version
51
+
52
+ #real time version get
53
+ def _local_package_version(py_package):
54
+ find_str = "grep"
55
+ if platform.system() == 'Windows':
56
+ find_str = "findstr"
57
+ local_version = ""
58
+ result = subprocess.run(f"pip list | {find_str} {py_package}",
59
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
60
+ ss = result.stdout.decode(encoding="utf8", errors="ignore").split("\n")
61
+ for s in ss:
62
+ s = re.sub(r'\s+', ' ', s)
63
+ sl = s.strip().split(" ")
64
+ if len(sl) == 2:
65
+ if py_package.strip() == sl[0].strip():
66
+ local_version = sl[1].strip()
67
+ return local_version
68
+
69
+ def _pypi_folder_name(name):
70
+ import re
71
+ return re.sub(r"[/,\-\s]", "", name)
72
+
73
+ def GetWidgetConfig(path):
74
+ #search h5 folder first, netxt search this folder
75
+ if os.path.exists(path):
76
+ for filename in os.listdir(path):
77
+ pathname = os.path.join(path, filename)
78
+ if (os.path.isfile(pathname)) and filename in ["config.json", "config.json.py"]:
79
+ with open(pathname, 'r', encoding='UTF-8') as f:
80
+ return json.load(f)
81
+ for filename in os.listdir(path):
82
+ pathname = os.path.join(path, filename)
83
+ if (os.path.isfile(pathname)) and filename in ["config.json", "config.json.py"]:
84
+ with open(pathname, 'r', encoding='UTF-8') as f:
85
+ return json.load(f)
86
+ return {}
87
+
88
+ def folderIsH5(path):
89
+ configFileExist = False
90
+ iconFileExist = False
91
+ htmlFileExist = False
92
+ for filename in os.listdir(path):
93
+ pathname = os.path.join(path, filename)
94
+ if (os.path.isfile(pathname)) and filename == "config.json":
95
+ configFileExist = True
96
+ if (os.path.isfile(pathname)) and filename == "icon.png":
97
+ iconFileExist = True
98
+ if (os.path.isfile(pathname)) and filename == "index.html":
99
+ htmlFileExist = True
100
+ return configFileExist and iconFileExist and htmlFileExist
101
+
102
+ def PathIsEmpty(path):
103
+ return len(os.listdir(path)) == 0
104
+
105
+ def replaceIfNeed(dstDir, name, subfix):
106
+ newsubfix = subfix + ".py"
107
+ if name.find(newsubfix) != -1:
108
+ os.rename(os.path.join(dstDir, name), os.path.join(dstDir, name.replace(newsubfix, subfix)))
109
+
110
+ def copyWidgetTemplate(root, name):
111
+ templateDir = os.path.join(os.path.dirname(os.path.abspath(__file__)), name)#sys.prefix
112
+ dstDir = root
113
+ for item in os.listdir(templateDir):
114
+ source = os.path.join(templateDir, item)
115
+ destination = os.path.join(dstDir, item)
116
+ if os.path.isdir(source):
117
+ shutil.copytree(source, destination)
118
+ else:
119
+ shutil.copy2(source, destination)
120
+ shutil.rmtree(os.path.join(dstDir, "__pycache__"))
121
+ os.remove(os.path.join(dstDir, "__init__.py"))
122
+ for filename in os.listdir(dstDir):
123
+ replaceIfNeed(dstDir, filename, ".json")
124
+ replaceIfNeed(dstDir, filename, ".js")
125
+ replaceIfNeed(dstDir, filename, ".png")
126
+ replaceIfNeed(dstDir, filename, ".html")
127
+
128
+ def setWidgetData(root, widgetid):
129
+ data = GetWidgetConfig(root)
130
+ data["widget_id"] = widgetid
131
+ data["name"] = "Demo"
132
+ data["version"] = "1.0"
133
+ data["device_keys"] = [
134
+ utils.generate_unique_id()
135
+ ]
136
+ data["cmd"] = os.path.join(root, "main.py")
137
+ with open(os.path.join(root, "config.json"), 'w') as f:
138
+ json.dump(data, f)
139
+
140
+ def createWidget(root):
141
+ if PathIsEmpty(root) == False:
142
+ print("current folder is not empty, create widget fail!")
143
+ return
144
+
145
+ widgetid = ryry_webapi.CreateWidgetUUID()
146
+ if len(widgetid) == 0:
147
+ print("create widget fail! ryry server is not avalid")
148
+ return
149
+
150
+ copyWidgetTemplate(root, "script_template")
151
+ setWidgetData(root, widgetid)
152
+ addWidgetToEnv(root, True)
153
+ print("create widget success")
154
+
155
+ def CheckWidgetDataInPath(path):
156
+ data = GetWidgetConfig(path)
157
+ if "widget_id" not in data:
158
+ print("folder is not widget")
159
+ return False
160
+
161
+ if "widget_id" in data:
162
+ widget_id = data["widget_id"]
163
+ if len(widget_id) == 0:
164
+ print("widget_id is empty!")
165
+ return False
166
+
167
+ return True
168
+
169
+ def addWidgetToEnv(root, mute=False):
170
+ #maybe pip package
171
+ try:
172
+ package = pkg_resources.get_distribution(root)
173
+ local_version = package.version
174
+ name = package.project_name
175
+ version = package.version
176
+ root = os.path.join(package.location, _pypi_folder_name(name))
177
+ except:
178
+ pass
179
+
180
+ if CheckWidgetDataInPath(root) == False:
181
+ return
182
+ data = GetWidgetConfig(root)
183
+ widget_id = data["widget_id"]
184
+ mainPythonPath = os.path.join(root, "main.py")
185
+ store.insertWidget(widget_id, mainPythonPath)
186
+ if mute == False:
187
+ print(f"add {widget_id.ljust(len(widget_id)+4)} {mainPythonPath}")
188
+
189
+ def remove(args):
190
+ widget_id = args
191
+ if os.path.exists(args):
192
+ #find widgetid in args path
193
+ data = GetWidgetConfig(args)
194
+ if "widget_id" not in data:
195
+ print(f"path {args} is not widget folder!")
196
+ return
197
+ widget_id = data["widget_id"]
198
+ # if ryry_webapi.DeleteWidget(widget_id):
199
+ store.removeWidget(widget_id)
200
+ print(f"widget:{widget_id} is removed with local")
201
+
202
+ def enable(args):
203
+ widget_id = args
204
+ if os.path.exists(args):
205
+ #find widgetid in args path
206
+ data = GetWidgetConfig(args)
207
+ if "widget_id" not in data:
208
+ print(f"path {args} is not widget folder!")
209
+ return
210
+ widget_id = data["widget_id"]
211
+ store.enableWidget(widget_id)
212
+ print(f"widget:{widget_id} updated")
213
+
214
+ def disable(args):
215
+ widget_id = args
216
+ if os.path.exists(args):
217
+ #find widgetid in args path
218
+ data = GetWidgetConfig(args)
219
+ if "widget_id" not in data:
220
+ print(f"path {args} is not widget folder!")
221
+ return
222
+ widget_id = data["widget_id"]
223
+ store.disableWidget(widget_id)
224
+ print(f"widget:{widget_id} updated")
225
+
226
+ def getTaskCount(args):
227
+ widget_id = args
228
+ if os.path.exists(args):
229
+ #find widgetid in args path
230
+ data = GetWidgetConfig(args)
231
+ if "widget_id" not in data:
232
+ print(f"path {args} is not widget folder!")
233
+ return
234
+ widget_id = data["widget_id"]
235
+ datas = ryry_webapi.GetTaskCount(widget_id)
236
+ for it in datas:
237
+ if it["widgetUUID"] == widget_id:
238
+ return it["taskCount"]
239
+ return -1
240
+
241
+ def publishWidget(package_folder):
242
+ if CheckWidgetDataInPath(package_folder) == False:
243
+ return
244
+
245
+ data = GetWidgetConfig(package_folder)
246
+ widget_id = data["widget_id"]
247
+ name = data["name"]
248
+ local_version = data["version"]
249
+ user_id = utils.generate_unique_id()
250
+
251
+ #override setting
252
+ remote_version = _remote_package_version(name)
253
+ if compare_versions(remote_version, local_version) >= 0:
254
+ print(f"version {local_version} must be larger than {remote_version}, publish abandon")
255
+ return
256
+
257
+ #if in h5&script parent folder, add env path
258
+ if len(package_folder) > 0:
259
+ addWidgetToEnv(package_folder, True)
260
+
261
+ #package python to private pip server
262
+ requirements_txts = [
263
+ os.path.join(package_folder, "requirements.txt")
264
+ ]
265
+ requirements = ""
266
+ for requirements_txt in requirements_txts:
267
+ if os.path.exists(requirements_txt):
268
+ with open(requirements_txt, "r", encoding="UTF-8") as f:
269
+ ss = f.readlines()
270
+ for s in ss:
271
+ reals = s.replace("\n","").replace(" ","")
272
+ if ";" in reals:
273
+ requirements += f"'{reals[:reals.index(';')]}',"
274
+ elif "#" not in reals:
275
+ requirements += f"'{reals}',"
276
+ pip_dir = os.path.join(os.path.dirname(package_folder), "tmp")
277
+ if os.path.exists(pip_dir):
278
+ shutil.rmtree(pip_dir)
279
+ os.makedirs(pip_dir)
280
+ source_folder_name = _pypi_folder_name(name)
281
+ pip_source_dir = os.path.join(pip_dir, source_folder_name)
282
+ shutil.copytree(package_folder, pip_source_dir)
283
+ config_json_file = os.path.join(pip_source_dir, "config.json")
284
+ if os.path.exists(config_json_file):
285
+ with open(config_json_file, 'r') as f:
286
+ cc = json.load(f)
287
+ cc["py_package"] = name
288
+ if os.path.exists(os.path.join(pip_source_dir, "__init__.py")) == False:
289
+ with open(os.path.join(pip_source_dir, "__init__.py"), 'w') as f:
290
+ f.write("")
291
+ #get datafile
292
+ data_file_config = {}
293
+ for root,dirs,files in os.walk(package_folder):
294
+ for file in files:
295
+ if file.find(".") <= 0:
296
+ continue
297
+ ext = file[file.rindex("."):]
298
+ if ext in [ ".json", ".txt", ".md" ]:
299
+ dir_path = os.path.relpath(root, package_folder)
300
+ file_path = os.path.join(dir_path, file)
301
+ file_path = os.path.normpath(file_path).replace("\\", "/")
302
+ k = dir_path.replace("\\", "/")
303
+ if k in data_file_config:
304
+ data_file_config[k].append(file_path)
305
+ else:
306
+ data_file_config[k] = [file_path]
307
+ package_data_str = ""
308
+ for k in data_file_config:
309
+ for p in data_file_config[k]:
310
+ package_data_str += f"'{p}',"
311
+ setup_py = os.path.join(pip_dir, "setup.py")
312
+ with open(setup_py, 'w') as f:
313
+ f.write(f'''import setuptools, os, sys, subprocess, datetime
314
+
315
+ setuptools.setup(
316
+ name="{name}",
317
+ version="{local_version}",
318
+ author="{user_id}",
319
+ author_email="{user_id}@dalipen.com",
320
+ description="ryry widget",
321
+ long_description="privide by ryry-cli",
322
+ long_description_content_type="text/markdown",
323
+ url="https://ryryai.com/#/",
324
+ packages=setuptools.find_packages(),
325
+ classifiers=[
326
+ "Programming Language :: Python :: 3",
327
+ "License :: OSI Approved :: MIT License",
328
+ "Operating System :: OS Independent",
329
+ ],
330
+ py_modules=[],
331
+ install_requires=[
332
+ {requirements}
333
+ ],
334
+ package_data={{
335
+ '{name}':[{package_data_str}]
336
+ }},
337
+ entry_points={{
338
+ 'console_scripts':[
339
+ '{name} = {source_folder_name}.main:main'
340
+ ]
341
+ }},
342
+ python_requires='>=3.4',
343
+ )
344
+ ''')
345
+ try:
346
+ #build
347
+ subprocess.run(f"python {setup_py} sdist bdist_wheel", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=pip_dir, encoding="utf-8")
348
+ #uninstall
349
+ subprocess.run(f"pip uninstall {name} -y", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, encoding="utf-8")
350
+ #install
351
+ whl = utils.firstExitWithDir(os.path.join(pip_dir, "dist"), "whl")
352
+ subprocess.run(f"pip install {whl} --extra-index-url https://pypi.python.org/simple/", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, encoding="utf-8")
353
+ #upload
354
+ ryry_webapi.uploadWidget(widget_id, name, whl, ".whl", local_version)
355
+ print(f"发布 {name}_{local_version} -> 成功")
356
+ except Exception as ex:
357
+ print(ex)
358
+ finally:
359
+ shutil.rmtree(pip_dir)
360
+
361
+ def widgetUpdateNotify(widgetName, oldver, newver):
362
+ device_id = utils.generate_unique_id()
363
+ machine_name = socket.gethostname()
364
+ ver = get_distribution("ryry-cli").version
365
+ taskUtils.notifyWechatRobot({
366
+ "msgtype": "text",
367
+ "text": {
368
+ "content": f"机器<{machine_name}[{device_id}]>[{ver}] widget:[{widgetName}]升级版本[{oldver}]->[{newver}]"
369
+ }
370
+ })
371
+
372
+ def UpdateWidgetFromPypi():
373
+ map = store.widgetMap()
374
+ for it in map:
375
+ is_block = False
376
+ if isinstance(map[it], (dict)):
377
+ is_block = map[it]["isBlock"]
378
+ path = map[it]["path"]
379
+ else:
380
+ path = map[it]
381
+ path = os.path.dirname(path)
382
+ if is_block == False and os.path.exists(path):
383
+ data = GetWidgetConfig(path)
384
+ if "py_package" in data and len(data["py_package"]) > 0:
385
+ try:
386
+ py_package = data["py_package"]
387
+ remote_version = _remote_package_version(py_package)
388
+ local_version = _local_package_version(py_package)
389
+ if compare_versions(remote_version, local_version) > 0:
390
+ #update
391
+ subprocess.run(f"pip uninstall {py_package}", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
392
+ subprocess.run(f"pip install -U {py_package} -i https://pypi.python.org/simple/ --extra-index-url https://pypi.python.org/simple/",
393
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
394
+ widgetUpdateNotify(py_package, local_version, remote_version)
395
+ except Exception as ex:
396
+ print(ex)
397
+ continue
398
+
File without changes
@@ -0,0 +1,25 @@
1
+ ##################################################
2
+ # do not change this file, real File is [run.py] #
3
+ ##################################################
4
+ import argparse, json, os
5
+ from run import *
6
+
7
+ parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
8
+ parser.add_argument("--run", type=str, default=None, help=("input param file path"))
9
+ parser.add_argument("--out", type=str, default=None, help=("output file path"))
10
+ cmd_opts = parser.parse_args()
11
+
12
+ def main(cmd_opts):
13
+ if cmd_opts.run == None or cmd_opts.out == None:
14
+ print("args fail!")
15
+ return
16
+
17
+ if os.path.exists(cmd_opts.run):
18
+ with open(cmd_opts.run, 'r', encoding='UTF-8') as f:
19
+ data = json.load(f)
20
+ result = runTask(data)
21
+ with open(cmd_opts.out, 'w') as f:
22
+ json.dump(result, f)
23
+
24
+ if __name__ == '__main__':
25
+ main(cmd_opts)
@@ -0,0 +1,22 @@
1
+ import json
2
+ import sys
3
+
4
+ def runTask(data):
5
+ #write program in here
6
+
7
+ return {
8
+ "result" : [
9
+ {
10
+ "type" : "text", #text audio image video
11
+ "content": [
12
+ "hello world"
13
+ ],
14
+ "extension" : {
15
+ "info": "",
16
+ "cover_url": ""
17
+ }
18
+ }
19
+ ],
20
+ "status" : 0, #0 is success
21
+ "message" : ""
22
+ }
ryry/server_func.py ADDED
@@ -0,0 +1,74 @@
1
+ import time
2
+ from threading import Thread
3
+
4
+ from ryry import ryry_webapi
5
+ from ryry import store
6
+ from ryry import taskUtils
7
+
8
+ class TaskThread(Thread):
9
+ params = False
10
+ idx = 0
11
+ call_back = None
12
+ def __init__(self, idx, func, func_id, params, callback):
13
+ super().__init__()
14
+ self.idx = idx
15
+ self.func = func
16
+ self.widgetid = func_id
17
+ self.params = params
18
+ self.call_back = callback
19
+ if self.call_back == None:
20
+ raise Exception("need callback function")
21
+ self.start()
22
+ def run(self):
23
+ self.checking = False
24
+ self.result = False, "Unknow"
25
+ if self.widgetid == None:
26
+ self.widgetid = ryry_webapi.findWidget(self.func)
27
+ if len(self.widgetid) > 0:
28
+ checkUUID = ryry_webapi.createTask(self.widgetid, self.params)
29
+ checking = True
30
+ checkCount = 0
31
+ while checking or checkCount > 6000:
32
+ finish, success, data = ryry_webapi.checkTask(checkUUID)
33
+ if finish:
34
+ checking = False
35
+ if success:
36
+ self.call_back(self.idx, data)
37
+ return
38
+ checkCount += 1
39
+ time.sleep(0.1)
40
+ else:
41
+ print(f"widget {self.func}-{self.widgetid} not found")
42
+ self.call_back(self.idx, None)
43
+
44
+ class Task:
45
+ thread_data = {}
46
+
47
+ def __init__(self, func: str, multi_params: list[dict], fromUUID=None, func_id=None):
48
+ realTaskUUID = fromUUID
49
+ if realTaskUUID == None or len(realTaskUUID) <= 0:
50
+ realTaskUUID = taskUtils.taskInfoWithFirstTask()
51
+
52
+ def _callback(idx, data):
53
+ self.thread_data[str(idx)]["result"] = data
54
+ idx = 0
55
+ for param in multi_params:
56
+ param["fromUUID"] = realTaskUUID
57
+ self.thread_data[str(idx)] = {
58
+ "thread" : TaskThread(idx, func, func_id, param, _callback),
59
+ "result" : None
60
+ }
61
+ idx+=1
62
+
63
+ def call(self):
64
+ for t in self.thread_data.keys():
65
+ self.thread_data[t]["thread"].join()
66
+ result = []
67
+ for t in self.thread_data.keys():
68
+ result.append(self.thread_data[t]["result"])
69
+ return result
70
+
71
+
72
+ results = Task("Demo", [{
73
+ "func": "你好"
74
+ }], "").call()
ryry/store.py ADDED
@@ -0,0 +1,161 @@
1
+ import os
2
+ import json
3
+
4
+ def singleton(cls):
5
+ _instance = {}
6
+
7
+ def inner():
8
+ if cls not in _instance:
9
+ _instance[cls] = cls()
10
+ return _instance[cls]
11
+ return inner
12
+
13
+ @singleton
14
+ class Store(object):
15
+
16
+ def __init__(self):
17
+ self.path = os.path.join(os.path.dirname(os.path.abspath(__file__)), f"data.json")
18
+
19
+ if not os.path.exists(self.path):
20
+ with open(self.path, 'w') as f:
21
+ json.dump({}, f)
22
+
23
+ def read(self):
24
+ with open(self.path, 'r') as f:
25
+ data = json.load(f)
26
+
27
+ return data
28
+
29
+ def write(self, data):
30
+ with open(self.path, 'w') as f:
31
+ json.dump(data, f)
32
+
33
+ def token():
34
+ sp = Store()
35
+ read_data = sp.read()
36
+ if "token" in read_data:
37
+ return read_data["token"]
38
+ else:
39
+ return ""
40
+
41
+ #============================== widget ================================
42
+ def isCreateWidget():
43
+ sp = Store()
44
+ read_data = sp.read()
45
+ if "isCreateWidget" in read_data:
46
+ return read_data["isCreateWidget"]
47
+ else:
48
+ return False
49
+
50
+ def finishCreateWidget():
51
+ sp = Store()
52
+ read_data = sp.read()
53
+ read_data["isCreateWidget"] = False
54
+ sp.write(read_data)
55
+
56
+ def widgetMap():
57
+ sp = Store()
58
+ read_data = sp.read()
59
+ if "widgets" in read_data:
60
+ return read_data["widgets"]
61
+ else:
62
+ return {}
63
+
64
+ def insertWidget(widget_id, path):
65
+ sp = Store()
66
+ read_data = sp.read()
67
+ if "widgets" not in read_data:
68
+ read_data["widgets"] = {}
69
+ widgetsMap = read_data["widgets"]
70
+ widgetsMap[widget_id] = {
71
+ "isBlock": False,
72
+ "path" : path
73
+ }
74
+ for k in list(widgetsMap.keys()):
75
+ if isinstance(widgetsMap[k], (dict)):
76
+ if os.path.exists(widgetsMap[k]["path"]) == False:
77
+ del widgetsMap[k]
78
+ else:
79
+ if os.path.exists(widgetsMap[k]) == False:
80
+ del widgetsMap[k]
81
+ sp.write(read_data)
82
+
83
+ def removeWidget(widget_id):
84
+ sp = Store()
85
+ read_data = sp.read()
86
+ if "widgets" not in read_data:
87
+ read_data["widgets"] = {}
88
+ widgetsMap = read_data["widgets"]
89
+ if widget_id in widgetsMap:
90
+ del widgetsMap[widget_id]
91
+ sp.write(read_data)
92
+
93
+ def disableWidget(widget_id):
94
+ sp = Store()
95
+ read_data = sp.read()
96
+ if "widgets" not in read_data:
97
+ read_data["widgets"] = {}
98
+ widgetsMap = read_data["widgets"]
99
+ if widget_id in widgetsMap:
100
+ if isinstance(widgetsMap[widget_id], (dict)):
101
+ widgetsMap[widget_id]["isBlock"] = True
102
+ else:
103
+ path = widgetsMap[widget_id]
104
+ widgetsMap[widget_id] = {
105
+ "isBlock": True,
106
+ "path" : path
107
+ }
108
+ sp.write(read_data)
109
+
110
+ def enableWidget(widget_id):
111
+ sp = Store()
112
+ read_data = sp.read()
113
+ if "widgets" not in read_data:
114
+ read_data["widgets"] = {}
115
+ widgetsMap = read_data["widgets"]
116
+ if widget_id in widgetsMap:
117
+ if isinstance(widgetsMap[widget_id], (dict)):
118
+ widgetsMap[widget_id]["isBlock"] = False
119
+ else:
120
+ path = widgetsMap[widget_id]
121
+ widgetsMap[widget_id] = {
122
+ "isBlock": False,
123
+ "path" : path
124
+ }
125
+ sp.write(read_data)
126
+
127
+ #============================== device id ================================
128
+
129
+ def writeDeviceInfo(data):
130
+ sp = Store()
131
+ read_data = sp.read()
132
+ read_data["deviceInfo"] = data
133
+ sp.write(read_data)
134
+
135
+ def readDeviceInfo():
136
+ sp = Store()
137
+ read_data = sp.read()
138
+ if "deviceInfo" in read_data:
139
+ return read_data["deviceInfo"]
140
+ else:
141
+ return {}
142
+
143
+ def is_multithread():
144
+ return get_multithread() > 1
145
+
146
+ def get_multithread():
147
+ env_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "multi_thread.config")
148
+ try:
149
+ with open(env_file, 'r', encoding='UTF-8') as f:
150
+ n = int(f.read())
151
+ return n
152
+ except:
153
+ return 1
154
+
155
+ def save_multithread(n):
156
+ file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "multi_thread.config")
157
+ try:
158
+ with open(file, 'w') as f:
159
+ f.write(str(n))
160
+ except:
161
+ pass