提交 034575a4 编写于 作者: S solarhu 提交者: Gitee

!10 Add build_ dependent related codes.

Merge pull request !10 from 张涛/master
"""
Find compilation dependency of source package
"""
from packageship.application.apps.package.function.searchdb import SearchDB
from packageship.application.apps.package.function.install_depend import InstallDepend
from packageship.application.apps.package.function.constants import ResponseCode, ListNode
class BuildDepend:
"""
Find compilation dependency of source package
"""
def __init__(self, pkg_name_list, db_list, self_build=0, history_dict=None):
self.pkg_name_list = pkg_name_list
self._self_build = self_build
self.db_list = db_list
self.search_db = SearchDB(db_list)
self.result_dict = dict()
self.source_dict = dict()
self.history_dicts = history_dict if history_dict else {}
def build_depend_main(self):
"""
Entry function
:return: ResponseCode,result_dict,source_dict
"""
if not self.search_db.db_object_dict:
return ResponseCode.DIS_CONNECTION_DB, None, None
if self._self_build == 0:
code = self.build_depend(self.pkg_name_list)
if None in self.result_dict:
del self.result_dict[None]
return code, self.result_dict, None
if self._self_build == 1:
self.self_build(self.pkg_name_list)
if None in self.result_dict:
del self.result_dict[None]
# There are two reasons for the current status code to return SUCCESS
# 1, Other branches return three return values.
# Here, a place holder is needed to prevent unpacking errors during call
# 2, This function is an auxiliary function of other modules.
# The status code is not the final display status code
return ResponseCode.SUCCESS, self.result_dict, self.source_dict
return ResponseCode.PARAM_ERROR, None, None
def build_depend(self, pkg_list):
"""
@:param pkg_list:You need to find the dependent source package name
:return ResponseCode
"""
res_status, build_list = self.search_db.get_build_depend(pkg_list)
if not build_list:
return res_status if res_status == \
ResponseCode.DIS_CONNECTION_DB else \
ResponseCode.PACK_NAME_NOT_FOUND
# create root node and get next search list
search_list = self._create_node_and_get_search_list(build_list, pkg_list)
code, res_dict = \
InstallDepend(self.db_list).query_install_depend(search_list,
self.history_dicts)
if not res_dict:
return code
for k, values in res_dict.items():
if k in self.result_dict:
if ['root', None] in values[ListNode.PARENT_LIST]:
index = values[ListNode.PARENT_LIST].index(['root', None])
del values[ListNode.PARENT_LIST][index]
self.result_dict[k][ListNode.PARENT_LIST].extend(values[ListNode.PARENT_LIST])
else:
self.result_dict[k] = values
return ResponseCode.SUCCESS
def _create_node_and_get_search_list(self, build_list, pkg_list):
"""
To create root node in self.result_dict and
return the name of the source package to be found next time
@:param build_list:List of binary package names
@:param pkg_list: List of binary package names
:return the name of the source package to be found next time
"""
search_set = set()
search_list = []
for obj in build_list:
if not obj.search_name:
continue
if obj.search_name + "_src" not in self.result_dict:
self.result_dict[obj.search_name + "_src"] = [
'source',
obj.search_version,
obj.db_name,
[
['root', None]
]
]
search_set.add(obj.search_name)
if not obj.bin_name:
continue
if obj.bin_name in self.history_dicts:
self.result_dict[obj.bin_name] = [
self.history_dicts[obj.bin_name][ListNode.SOURCE_NAME],
self.history_dicts[obj.bin_name][ListNode.VERSION],
self.history_dicts[obj.bin_name][ListNode.DBNAME],
[
[obj.search_name, 'build']
]
]
else:
if obj.bin_name in search_list:
self.result_dict[obj.bin_name][ListNode.PARENT_LIST].append([
obj.search_name, 'build'
])
else:
self.result_dict[obj.bin_name] = [
obj.source_name,
obj.version,
obj.db_name,
[
[obj.search_name, 'build']
]
]
search_list.append(obj.bin_name)
if search_set and len(search_set) != len(pkg_list):
temp_set = set(pkg_list) - search_set
for name in temp_set:
self.result_dict[name + "_src"] = [
None,
None,
'NOT_FOUND',
[
['root', None]
]
]
return search_list
def self_build(self, pkg_name_li):
"""
Using recursion to find compilation dependencies
:param pkg_name_li: Source package name list
:return:
"""
if not pkg_name_li:
return
next_src_set = set()
_, bin_info_lis = self.search_db.get_build_depend(pkg_name_li)
if not bin_info_lis:
return
# generate data content
for obj in bin_info_lis:
if not obj.bin_name:
continue
if obj.bin_name not in self.result_dict:
self.result_dict[obj.bin_name] = [
obj.source_name if obj.source_name else None,
obj.version if obj.version else None,
obj.db_name if obj.db_name else "NOT_FOUND",
[
[obj.search_name, "build"]
]
]
else:
node = [obj.search_name, "build"]
node_list = self.result_dict[obj.bin_name][-1]
if node not in node_list:
node_list.append(node)
if obj.source_name and \
obj.source_name not in self.source_dict:
self.source_dict[obj.source_name] = [obj.db_name,
obj.version]
next_src_set.add(obj.source_name)
self.self_build(next_src_set)
return
......@@ -124,7 +124,7 @@ class SearchDB():
source_version = bin_obj.src_pack.version
if source_name is not None:
return ResponseCode.SUCCESS, db_name, \
source_name, source_version
source_name, source_version
except AttributeError as error_msg:
LOGGER.logger.error(error_msg)
except SQLAlchemyError as error_msg:
......@@ -132,6 +132,187 @@ class SearchDB():
return ResponseCode.DIS_CONNECTION_DB, None
return ResponseCode.PACK_NAME_NOT_FOUND, None, None, None
def get_binary_in_other_database(self, not_found_binary, db_):
"""
Binary package name data not found in the current database, go to other databases to try
@:param:not_found_build These data cannot be found in the current database
@:param:db:current database name
return:a list :[(search_name,source_name,bin_name,
bin_version,db_name,search_version,req_name),
(search_name,source_name,bin_name,
bin_version,db_name,search_version,req_name),]
changeLog:new method to look for data in other databases
"""
if not not_found_binary:
return []
return_tuple = namedtuple("return_tuple", [
"search_name",
"source_name",
"bin_name",
"version",
"db_name",
"search_version",
"req_name"
])
src_req_map = {req_: src for src, req_ in not_found_binary}
local_search_set = {req_ for _, req_ in not_found_binary}
local_dict = {k: v for k, v in self.db_object_dict.items() if k != db_}
res = []
for db_name, data_base in local_dict.items():
try:
sql_string = text("""
SELECT
t3.NAME AS source_name,
t1.NAME AS bin_name,
t1.version,
t3.version as search_version,
t2.NAME AS req_name
FROM
bin_pack t1,
pack_provides t2,
src_pack t3
WHERE
t2.{}
AND t1.id = t2.binIDkey
AND t1.srcIDkey = t3.id;
""".format(literal_column('name').in_(local_search_set)))
build_set_2 = data_base.session. \
execute(sql_string, {'name_{}'.format(i): v
for i, v in enumerate(local_search_set, 1)}).fetchall()
if not build_set_2:
continue
res.extend([return_tuple(
src_req_map.get(bin_pack.req_name),
bin_pack.source_name,
bin_pack.bin_name,
bin_pack.version,
db_name,
bin_pack.search_version,
bin_pack.req_name
) for bin_pack in build_set_2 if bin_pack.bin_name])
for obj in res:
local_search_set.remove(obj.req_name)
except AttributeError as attr_error:
current_app.logger.error(attr_error)
except SQLAlchemyError as sql_error:
current_app.logger.error(sql_error)
return res
def get_build_depend(self, source_name_li):
"""
Description: get a package build depend from database
input:
@:param: search package's name list
return: all source pkg build depend list
structure :[(search_name,source_name,bin_name,bin_version,db_name,search_version),
(search_name,source_name,bin_name,bin_version,db_name,search_version),]
changeLog: Modify SQL logic and modify return content by:zhangtao
"""
# pylint: disable=R0914
return_tuple = namedtuple("return_tuple", [
"search_name",
"source_name",
"bin_name",
"version",
"db_name",
"search_version"
])
s_name_set = set(source_name_li)
if not s_name_set:
return ResponseCode.PARAM_ERROR, None
not_found_binary = set()
build_list = []
for db_name, data_base in self.db_object_dict.items():
try:
sql_com = text("""SELECT DISTINCT
src.NAME AS search_name,
src.version AS search_version,
s2.NAME AS source_name,
pack_provides.binIDkey AS bin_id,
pack_requires.NAME AS req_name,
bin_pack.version AS version,
bin_pack.NAME AS bin_name
FROM
( SELECT id, NAME,version FROM src_pack WHERE {} ) src
LEFT JOIN pack_requires ON src.id = pack_requires.srcIDkey
LEFT JOIN pack_provides ON pack_provides.id = pack_requires.depProIDkey
LEFT JOIN bin_pack ON bin_pack.id = pack_provides.binIDkey
LEFT JOIN src_pack s1 ON s1.id = pack_requires.srcIDkey
LEFT JOIN src_pack s2 ON bin_pack.srcIDkey = s2.id;
""".format(literal_column("name").in_(s_name_set)))
build_set = data_base.session. \
execute(sql_com, {'name_{}'.format(i): v
for i, v in enumerate(s_name_set, 1)}).fetchall()
if not build_set:
continue
# When processing source package without compilation dependency
to_remove_obj_index = []
for index, b_pack in enumerate(build_set):
if not b_pack.source_name and not b_pack.req_name:
obj = return_tuple(
b_pack.search_name,
b_pack.source_name,
b_pack.bin_name,
b_pack.version,
db_name,
b_pack.search_version
)
build_list.append(obj)
to_remove_obj_index.append(index)
for i in reversed(to_remove_obj_index):
build_set.pop(i)
if not build_set:
continue
build_list.extend([
return_tuple(
bin_pack.search_name,
bin_pack.source_name,
bin_pack.bin_name,
bin_pack.version,
db_name,
bin_pack.search_version
) for bin_pack in build_set if bin_pack.bin_id and bin_pack.bin_name
])
# Component name can't find its binary package name
not_found_binary.update([(bin_pack.search_name, bin_pack.req_name)
for bin_pack in build_set if not bin_pack.bin_id])
s_name_set -= {bin_pack.search_name for bin_pack in build_set
if bin_pack.bin_id}
if not not_found_binary and not s_name_set:
return ResponseCode.SUCCESS, build_list
for obj in self.get_binary_in_other_database(not_found_binary, db_name):
build_list.append(obj)
not_found_binary.clear()
except AttributeError as attr_error:
current_app.logger.error(attr_error)
except SQLAlchemyError as sql_error:
current_app.logger.error(sql_error)
return ResponseCode.DIS_CONNECTION_DB, None
return ResponseCode.SUCCESS, build_list
def db_priority():
"""
......
......@@ -28,7 +28,9 @@ from .serialize import DeletedbSchema
from .serialize import InitSystemSchema
from .function.install_depend import InstallDepend as installdepend
from .function.build_depend import BuildDepend as builddepend
from .serialize import InstallDependSchema
from .serialize import BuildDependSchema
from .serialize import have_err_db_name
LOGGER = Log(__name__)
......@@ -294,7 +296,7 @@ class BuildDepend(Resource):
changeLog:
'''
def post(self, *args, **kwargs):
def post(self):
'''
Description: Query a package's build depend and
build depend package's install depend
......@@ -317,7 +319,42 @@ class BuildDepend(Resource):
exception:
changeLog:
'''
pass
schema = BuildDependSchema()
data = request.get_json()
if schema.validate(data):
return jsonify(
ResponseCode.response_json(ResponseCode.PARAM_ERROR)
)
pkg_name = data.get("sourceName")
db_pri = db_priority()
if not db_pri:
return jsonify(
ResponseCode.response_json(
ResponseCode.FILE_NOT_FIND_ERROR
)
)
db_list = data.get("db_list") if data.get("db_list") \
else db_pri
if have_err_db_name(db_list, db_pri):
return jsonify(
ResponseCode.response_json(ResponseCode.DB_NAME_ERROR)
)
build_ins = builddepend([pkg_name], db_list)
res_code, res_dict, _ = build_ins.build_depend_main()
return jsonify(
ResponseCode.response_json(
res_code,
data=res_dict if res_dict else None
)
)
class SelfDepend(Resource):
......
......@@ -75,7 +75,8 @@ class DBHelper():
raise DbnameNoneException(
'The connected database name is empty')
self.engine = create_engine(
self.db_type + self.db_name, encoding='utf-8', convert_unicode=True)
self.db_type + self.db_name, encoding='utf-8', convert_unicode=True,
connect_args={'check_same_thread': False})
else:
if all([self.user_name, self.passwrod, self.ip_address, self.port, self.db_name]):
# create connection object
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册