22 :copyright: © 2020 by the Lin team.
33 :license: MIT, see LICENSE for more details.
44"""
5- import json
65import os
76import re
87import subprocess
1312"""
1413插件初始化流程:
15141、输入要初始化的插件名称。(多个用空格隔开,*表示初始化所有)
16- 2、python依赖的自动检测和安装
17- 2、将插件的配置写入到项目setting .py中
15+ 2、python依赖的安装
16+ 2、将插件的配置写入到项目app/config/__init__ .py中
18173、将model中的模型插入到数据库中
19184、如果有需要,将初始数据插入到数据表中
2019"""
@@ -55,12 +54,6 @@ def generate_path(self):
5554 }
5655
5756 def auto_install_rely (self ):
58- try :
59- DependenciesResolve (app , self .path_info )
60- except Exception as e :
61- raise Exception ("安装插件依赖时发生错误!\n Error:" + str (e ))
62- from subprocess import CalledProcessError
63-
6457 for name in self .path_info :
6558 print ("正在初始化插件" + name + "..." )
6659 filename = "requirements.txt"
@@ -70,31 +63,14 @@ def auto_install_rely(self):
7063 if os .path .exists (file_path ):
7164 if (os .path .getsize (file_path )) == 0 :
7265 continue
73- print ("正在安装" + name + "插件的依赖..." )
74-
75- try :
76- # 使用try except来判断使用pip管理包还是pipenv管理包,首选pipenv
77- ret = self .__execute_cmd (cmd = "pipenv install -r " + file_path )
78-
79- if ret :
80- print (success_msg )
81- else :
82- exit (fail_msg )
83-
84- except CalledProcessError :
85- try :
86- ret = self .__execute_cmd (cmd = "pip install -r " + file_path )
66+ print ("正在安装" + name + "插件的依赖,请耐心等待..." )
8767
88- if ret :
89- print (success_msg )
90- else :
91- exit (fail_msg )
68+ ret = self .__execute_cmd (cmd = "pip install -r " + file_path )
9269
93- except Exception as e :
94- exit ((str (e )) + "\n " + fail_msg )
95-
96- except Exception as e :
97- exit ((str (e )) + "\n " + fail_msg )
70+ if ret :
71+ print (success_msg )
72+ else :
73+ exit (fail_msg )
9874
9975 def auto_write_setting (self ):
10076 print ("正在自动写入配置文件..." )
@@ -146,15 +122,19 @@ def _generate_setting(self, name, info_mod):
146122
147123 def __update_setting (self , new_setting ):
148124 # 得到现存的插件配置
149- old_setting = self .app .config .get ("PLUGIN_PATH" )
125+ old_setting = self .app .config .get ("PLUGIN_PATH" , dict () )
150126 final_setting = self .__cal_setting (new_setting , old_setting )
151127
152128 sub_str = "PLUGIN_PATH = " + self .__format_setting (final_setting )
153129
154- setting_path = self .app .config .root_path + "/config/setting .py"
130+ setting_path = self .app .config .root_path + "/config/__init__ .py"
155131 with open (setting_path , "r" , encoding = "UTF-8" ) as f :
156132 content = f .read ()
157133 pattern = "PLUGIN_PATH = \{([\s\S]*)\}+.*?"
134+ if len (re .findall (pattern , content )) == 0 :
135+ content += """
136+ PLUGIN_PATH = {}
137+ """
158138 result = re .sub (pattern , sub_str , content )
159139
160140 with open (setting_path , "w+" , encoding = "UTF-8" ) as f :
@@ -218,159 +198,6 @@ def __cal_setting(new_setting, old_setting):
218198
219199 return final_setting
220200
221-
222- class DependenciesResolve :
223- def __init__ (self , app_obj , path ):
224- self .app = app_obj
225- self .path_info = path
226- # 主项目的依赖关系列表
227- self .root_graph = []
228- # 所有插件的依赖关系列表
229- self .plugin_graph = []
230- # 生成主项目和插件依赖关系列表
231- self .generate_graph ()
232- self .check_dependencies ()
233-
234- def generate_graph (self ):
235- try :
236- p = subprocess .Popen (["pipenv" , "graph" , "--json" ], stdout = subprocess .PIPE )
237-
238- r = p .communicate ()[0 ].decode ("utf-8" )
239- self .root_graph = json .loads (r )
240-
241- except subprocess .CalledProcessError as e :
242- exit ("pipenv指令未安装,请先使用pip安装命令\n Error" + str (e ))
243-
244- except Exception as e :
245- exit ("pipenv 错误,请检测你的pipenv配置!\n Error:" + str (e ))
246-
247- self .__generate_plugin_graph ()
248-
249- def check_dependencies (self ):
250- for package in self .root_graph :
251- # 验证顶级包是否符合规范
252- self .__check_top_dependencies (package ["package" ])
253-
254- # 验证子包是否符合规范
255- self .__check_sub_dependencies (package ["dependencies" ])
256-
257- def __generate_plugin_graph (self ):
258- for name , val in self .path_info .items ():
259- # 首先去校验插件依赖于住项目的依赖是否存在冲突
260- plugin_path = (
261- self .path_info [name ]["plugin_path" ].replace ("." , "/" ).replace ("app" , "" )
262- )
263- requirements_path = (
264- self .app .config .root_path + plugin_path + "/requirements.txt"
265- )
266- with open (requirements_path , "r" , encoding = "UTF-8" ) as f :
267- while True :
268-
269- # 正则匹配requirements的每一行的信息
270- line = f .readline ()
271- if not line :
272- break
273-
274- pattern = "(.*?)(==|<=|>=|!=|>|<)(.*)"
275- search_obj = re .search (pattern , line )
276- if search_obj :
277-
278- package_name = search_obj .group (1 )
279- condition = search_obj .group (2 )
280- version = search_obj .group (3 )
281- key = search_obj .group (1 ).lower ()
282-
283- plugin_package = dict ({"package" : {}})
284- plugin_package ["package" ]["key" ] = key
285- plugin_package ["package" ]["package_name" ] = package_name
286- plugin_package ["package" ]["version" ] = version
287- plugin_package ["package" ]["condition" ] = condition
288- plugin_package ["package" ]["plugin_name" ] = name
289- self .plugin_graph .append (plugin_package )
290-
291- def __check_top_dependencies (self , top_package ):
292- for plugin_package in self .plugin_graph :
293- top_version = top_package ["installed_version" ]
294- plugin_version = plugin_package ["package" ]["version" ]
295- if (
296- top_package ["key" ] == plugin_package ["package" ]["key" ]
297- and top_version != plugin_version
298- ):
299- err_msg = (
300- "由于项目主目录已经存在在包"
301- ""
302- + top_package ["package_name" ]
303- + ",但 "
304- + plugin_package ["package" ]["plugin_name" ]
305- + " 插件尝试重复安装不同版本,请尝试手动去掉该插件的requirements.txt中的包"
306- )
307- raise Exception (err_msg )
308-
309- def __check_sub_dependencies (self , dep_package ):
310- # 判断插件中要安装的依赖,是否符合主项目已安装的依赖规定的范围
311- for dependence in dep_package :
312- required_version = dependence ["required_version" ]
313- dep_name = dependence ["key" ]
314-
315- if required_version != None :
316- version_infos = required_version .split ("," )
317- for version_info in version_infos :
318- pattern = "(>=|<=|!=|==|<|>)(.*)"
319- search_obj = re .search (pattern , version_info )
320- condition = search_obj .group (1 )
321- version = int (search_obj .group (2 ).replace ("." , "" ))
322-
323- for plugin_package in self .plugin_graph :
324- name = plugin_package ["package" ]["key" ]
325- if dep_name == name :
326- plugin_package_version = int (
327- plugin_package ["package" ]["version" ].replace ("." , "" )
328- )
329- err_msg = (
330- plugin_package ["package" ]["plugin_name" ]
331- + "插件的依赖 "
332- + name
333- + " 与主项目依赖版本发生冲突! 请自行手动解决"
334- )
335- if condition == ">=" :
336- if plugin_package_version >= version :
337- pass
338- else :
339- raise Exception (err_msg )
340-
341- elif condition == "==" :
342- if plugin_package_version == version :
343- pass
344- else :
345- raise Exception (err_msg )
346-
347- elif condition == "!=" :
348- if plugin_package_version != version :
349- pass
350- else :
351- raise Exception (err_msg )
352-
353- elif condition == "<=" :
354- if plugin_package_version <= version :
355- pass
356- else :
357- raise Exception (err_msg )
358-
359- elif condition == "<" :
360- if plugin_package_version < version :
361- pass
362- else :
363- raise Exception (err_msg )
364-
365- elif condition == ">" :
366- if plugin_package_version > version :
367- pass
368- else :
369- raise Exception (err_msg )
370- else :
371- pass
372-
373-
374201def init ():
375202 plugin_name = input ("请输入要初始化的插件名,如果多个插件请使用空格分隔插件名,输入*表示初始化所有插件:\n " )
376203 PluginInit (plugin_name )
0 commit comments