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/__init__.py +0 -0
- ryry/constant.py +5 -0
- ryry/main.py +300 -0
- ryry/ryry_server_socket.py +180 -0
- ryry/ryry_service.py +220 -0
- ryry/ryry_webapi.py +251 -0
- ryry/ryry_widget.py +398 -0
- ryry/script_template/__init__.py +0 -0
- ryry/script_template/main.py +25 -0
- ryry/script_template/run.py +22 -0
- ryry/server_func.py +74 -0
- ryry/store.py +161 -0
- ryry/task.py +203 -0
- ryry/taskUtils.py +283 -0
- ryry/upload.py +139 -0
- ryry/utils.py +358 -0
- ryry_cli-1.0.dist-info/LICENSE +7 -0
- ryry_cli-1.0.dist-info/METADATA +72 -0
- ryry_cli-1.0.dist-info/RECORD +22 -0
- ryry_cli-1.0.dist-info/WHEEL +5 -0
- ryry_cli-1.0.dist-info/entry_points.txt +2 -0
- ryry_cli-1.0.dist-info/top_level.txt +3 -0
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
|