packages.py 15.4 KB
Newer Older
J
jiang 已提交
1
#!/usr/bin/python3
2
"""
J
jiang 已提交
3 4 5
Description: Get package information and modify package information
functions: get_packages, buildep_packages, sub_packages, get_single_package,
 update_single_package, update_maintaniner_info
6
"""
7
import math
8

9

10
from flask import current_app, jsonify
11
from sqlalchemy import text
12 13 14 15 16 17
from sqlalchemy.exc import SQLAlchemyError, DisconnectionError


from packageship.application.apps.package.function.constants import ResponseCode
from packageship.application.apps.package.serialize import AllPackInfoSchema
from packageship.application.apps.package.serialize import SinglePackInfoSchema
18
from packageship.libs.dbutils import DBHelper
G
gongzt 已提交
19
from packageship.application.models.package import SrcPack
20 21
from packageship.application.models.package import PackagesMaintainer
from packageship.application.models.package import PackagesIssue
G
gongzt 已提交
22 23 24
from packageship.application.models.package import SrcRequires
from packageship.application.models.package import BinPack
from packageship.application.models.package import BinProvides
25
from packageship.libs.exception import Error
26
from packageship.application.models.package import Packages
27 28


29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
def get_all_package_info(tablename, pagenum, pagesize,
                         srcname, maintainner, maintainlevel):
    """
    Args:
        tablename: Table Name
        pagenum: Page number
        pagesize: Current page display quantity

    Returns:
        package info

    Attributes:
        SQLAlchemyError: sqlalchemy error
        DisconnectionError: Cannot connect to database error
        Error: Error
    """
    try:
        with DBHelper(db_name="lifecycle") as database_name:
            if tablename not in database_name.engine.table_names():
                response = ResponseCode.response_json(
                    ResponseCode.TABLE_NAME_NOT_EXIST)
                response['total_count'] = None
                response['total_page'] = None
                return jsonify(response)
            cls_model = Packages.package_meta(tablename)
            # If srcname is empty, it will query all the information in the
            # library
            package_info_set_one = database_name.session.query(cls_model).outerjoin(
                PackagesMaintainer, cls_model.name == PackagesMaintainer.name)
            if srcname:
                package_info_set_one = package_info_set_one.filter(
                    cls_model.name.like('%{srcname}%'.format(srcname=srcname)))
            if maintainner:
                package_info_set_one = package_info_set_one.filter(
                    PackagesMaintainer.maintainer == maintainner)
            if maintainlevel:
                package_info_set_one = package_info_set_one.filter(
                    PackagesMaintainer.maintainlevel == maintainlevel)
            package_info_set = package_info_set_one.limit(
                int(pagesize)).offset((int(pagenum) - 1) * int(pagesize)).all()
            packageinfo_dicts = AllPackInfoSchema(
                many=True).dump(package_info_set)
            total_count = package_info_set_one.count()
            total_page = math.ceil(total_count / int(pagesize))
            packageinfo_dicts = parsing_dictionary_issuse(packageinfo_dicts)
            packageinfo_dicts = parsing_dictionary_maintainner(
                packageinfo_dicts)
            response = ResponseCode.response_json(
                ResponseCode.SUCCESS, packageinfo_dicts)
            response["total_count"] = total_count
            response["total_page"] = total_page
            return response
    except (SQLAlchemyError, DisconnectionError, Error) as error:
        current_app.logger.error(error)
        response = ResponseCode.response_json(
            ResponseCode.TABLE_NAME_NOT_EXIST)
        response["total_count"] = None
        response["total_page"] = None
        return jsonify(response)


def parsing_dictionary_issuse(packageinfo_dicts):
J
jiang 已提交
91
    """
92

J
jiang 已提交
93
    Args:
94 95
        packageinfo_dicts: package info dict

J
jiang 已提交
96
    Returns:
97
        packageinfo_dicts
J
jiang 已提交
98
    """
99 100 101 102 103 104 105 106 107
    with DBHelper(db_name="lifecycle") as database_name:
        for packageinfo_dict in packageinfo_dicts:
            issue_count = database_name.session.query(PackagesIssue).filter_by(
                pkg_name=packageinfo_dict.get("name")).count()
            packageinfo_dict["issue"] = issue_count
        return packageinfo_dicts


def parsing_dictionary_maintainner(packageinfo_dicts):
108
    """
109
    parsing dictionary maintainner
110 111

    Args:
112 113
        packageinfo_dicts:

114
    Returns:
115
        packageinfo_dicts
116
    """
117 118 119 120 121 122 123 124 125 126 127
    with DBHelper(db_name="lifecycle") as database_name:
        for packageinfo_dict in packageinfo_dicts:
            maintainer_obj = database_name.session.query(PackagesMaintainer).filter_by(
                name=packageinfo_dict.get("name")).first()
            if maintainer_obj is None:
                packageinfo_dict["maintainer"] = None
                packageinfo_dict["maintainlevel"] = None
            else:
                packageinfo_dict["maintainer"] = maintainer_obj.maintainer
                packageinfo_dict["maintainlevel"] = maintainer_obj.maintainlevel
        return packageinfo_dicts
128 129


130
def sing_pack(srcname, tablename):
131
    """
132 133 134 135 136 137 138 139
    Query information about a single source package, including a layer
    of installation dependencies and compilation dependencies
    Args:
        srcname: The name of the source package
        tablename: The name of the table in the database

    Returns:
        single pack package info
140

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
    Attributes:
        SQLAlchemyError: sqlalchemy error
        DisconnectionError: Cannot connect to database error
        Error: Error
    """
    try:
        with DBHelper(db_name="lifecycle") as database_name:
            if tablename not in database_name.engine.table_names():
                return jsonify(
                    ResponseCode.response_json(
                        ResponseCode.TABLE_NAME_NOT_EXIST))
            cls_model = Packages.package_meta(tablename)
            package_info_obj = database_name.session.query(
                cls_model).filter_by(name=srcname).first()
            if package_info_obj is None:
                return jsonify(
                    ResponseCode.response_json(
                        ResponseCode.PACK_NAME_NOT_FOUND))
            pack_info_dict = SinglePackInfoSchema(
                many=False).dump(package_info_obj)
161
            pack_info_dict = parsing_maintainner(srcname, pack_info_dict)
162 163
            issue_count = database_name.session.query(PackagesIssue).filter_by(
                pkg_name=package_info_obj.name).count()
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
            pack_info_dict["issue"] = issue_count
            buildrequired = buildrequired_search(srcname, tablename)
            pack_info_dict["buildrequired"] = buildrequired
            subpack = _sub_pack(srcname, tablename)
            pack_info_dict["gitee_url"] = "www.gitee.com/src-openeuler/" + \
                str(srcname)
            pack_info_dict["subpack"] = subpack
            pack_info_dict.update(
                {"license": pack_info_dict.pop("rpm_license")})
            pack_info_dict.update({"pkg_name": pack_info_dict.pop("name")})
            return jsonify(
                ResponseCode.response_json(
                    ResponseCode.SUCCESS, pack_info_dict))
    except (SQLAlchemyError, DisconnectionError, Error, AttributeError) as error:
        current_app.logger.error(error)
        return jsonify(
            ResponseCode.response_json(
                ResponseCode.DIS_CONNECTION_DB))

183 184

def parsing_maintainner(srcname, pack_info_dict):
185
    """
186
    Single package query maintainer and maintainlevel
187
    Args:
188
        srcname: Source package name
189
        pack_info_dict:
190
    Returns: Dictionary of package information
191 192 193

    """
    with DBHelper(db_name="lifecycle") as database_name:
194 195
        maintainer_obj = database_name.session.query(
            PackagesMaintainer).filter_by(name=srcname).first()
196 197 198 199 200 201 202 203
        if maintainer_obj is None:
            pack_info_dict["maintainer"] = None
            pack_info_dict["maintainlevel"] = None
        else:
            pack_info_dict["maintainer"] = maintainer_obj.maintainer
            pack_info_dict["maintainlevel"] = maintainer_obj.maintainlevel
        return pack_info_dict

204 205 206 207

def buildrequired_search(srcname, tablename):
    """
    Source code package one-level compilation dependency
J
jiang 已提交
208
    Args:
209 210 211
        srcname: The name of the source package
        tablename: The name of the table in the database

J
jiang 已提交
212
    Returns:
213
        Source code package one-level compilation dependency
214
    """
215 216 217 218 219 220 221 222 223
    with DBHelper(db_name=tablename) as data_name:

        src_pack_obj = data_name.session.query(
            SrcPack).filter_by(name=srcname).first()
        if src_pack_obj is None:
            return None

        src_pack_pkgkey = src_pack_obj.pkgKey
        s_pack_requires_set = data_name.session.query(
G
gongzt 已提交
224
            SrcRequires).filter_by(pkgKey=src_pack_pkgkey).all()
225 226 227 228
        # src_requires pkykey to find the name of the dependent component
        s_pack_requires_names = [
            s_pack_requires_obj.name for s_pack_requires_obj in s_pack_requires_set]

229 230
        # Find pkgkey in BinProvides by the name of the dependent component
        b_pack_provides_set = data_name.session.query(BinProvides).filter(
G
gongzt 已提交
231
            BinProvides.name.in_(s_pack_requires_names)).all()
232 233 234
        b_pack_provides_pkg_list = [
            b_pack_provides_obj.pkgKey for b_pack_provides_obj in b_pack_provides_set]

235 236
        # Go to bin_pack to find the name by pkgkey of BinProvides
        b_bin_pack_set = data_name.session.query(BinPack).filter(
G
gongzt 已提交
237
            BinPack.pkgKey.in_(b_pack_provides_pkg_list)).all()
238
        builddep = [b_bin_pack_obj.name for b_bin_pack_obj in b_bin_pack_set]
239 240 241
        return builddep


242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
def helper(cls):
    """
    Auxiliary function
    The returned data format is converted,
    the main function is to convert a dictionary to a list

    Args:
        cls: Data before conversion
    Returns:
        Converted data
    """
    for obj in cls:
        if "provides" in obj:
            obj["provides"] = list(obj["provides"].values())
            for values_p in obj["provides"]:
                if 'requiredby' in values_p:
                    values_p['requiredby'] = list(
                        values_p['requiredby'].values())
        if "requires" in obj:
            obj["requires"] = list(obj["requires"].values())
            for values_r in obj["requires"]:
                if "providedby" in values_r:
                    values_r['providedby'] = list(
                        values_r['providedby'].values())


def _sub_pack(src_name, table_name):
269
    """
270 271
    One-level installation dependency of the source package
    to generate the binary package
J
jiang 已提交
272
    Args:
273 274 275 276 277
        srcname: The name of the source package
        tablename: The name of the table in the database
    Returns:
        One-level installation dependency of the source package to
        generate the binary package
J
jiang 已提交
278
    """
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
    with DBHelper(db_name=table_name) as database:
        sql_str = """
            SELECT DISTINCT
                b2.pkgKey AS sub_id,
                b2.name AS sub_name,
                pro.id AS sub_pro_id,
                pro.name AS sub_pro_name,
                b1.name AS sub_reqby_name
            FROM
                ( select pkgKey,name,src_name from bin_pack where src_name=:src_name) b2
                left join bin_provides pro on b2.pkgKey=pro.pkgKey
                LEFT JOIN bin_requires req ON req.name = pro.name
                LEFT JOIN bin_pack b1 ON req.pkgKey = b1.pkgKey;
                """
        res = {}
        res_pro = database.session.execute(
            text(sql_str), {"src_name": src_name}).fetchall()

        for pro_obj in res_pro:
            if pro_obj.sub_name not in res:
                res[pro_obj.sub_name] = {
                    "id": pro_obj.sub_id,
                    "name": pro_obj.sub_name,
                    "provides": {
                        pro_obj.sub_pro_name: {
                            "id": pro_obj.sub_pro_id,
                            "name": pro_obj.sub_pro_name,
                            "requiredby": {
                                pro_obj.sub_reqby_name: pro_obj.sub_reqby_name
                            } if pro_obj.sub_reqby_name else {}
                        }
                    } if pro_obj.sub_pro_name else {}
                }
            else:
                pro_info = res[pro_obj.sub_name]["provides"]
                if pro_obj.sub_pro_name in pro_info:
                    pro_info[pro_obj.sub_pro_name]["requiredby"].update(
                        {pro_obj.sub_reqby_name: pro_obj.sub_reqby_name})
                else:
                    pro_info.update(
                        {
                            pro_obj.sub_pro_name: {
                                "id": pro_obj.sub_pro_id,
                                "name": pro_obj.sub_pro_name,
                                "requiredby": {
                                    pro_obj.sub_reqby_name: pro_obj.sub_reqby_name
                                } if pro_obj.sub_reqby_name else {}
                            } if pro_obj.sub_pro_name else {}
                        }
                    )

        sql_re = """
            SELECT DISTINCT
                b2.pkgKey AS sub_id,
                b2.name AS sub_name,
                req.id AS sub_req_id,
                req.name AS sub_req_name,
                b1.name AS sub_proby_name
            FROM
                ( SELECT pkgKey, name, src_name FROM bin_pack WHERE src_name = :src_name ) b2
                LEFT JOIN bin_requires req ON b2.pkgKey = req.pkgKey
                LEFT JOIN bin_provides pro ON pro.name = req.name
                LEFT JOIN bin_pack b1 ON pro.pkgKey = b1.pkgKey;
                """
        res_req = database.session.execute(
            text(sql_re), {"src_name": src_name}).fetchall()

        for req_obj in res_req:
            sub_pkg_info = res[req_obj.sub_name]
            # if req_obj.sub_name not in sub_pkg_info:

            if "requires" not in sub_pkg_info:
                if not req_obj.sub_req_name:
                    sub_pkg_info['requires'] = {}
                else:
                    sub_pkg_info.update(
                        {
                            "requires": {
                                req_obj.sub_req_name: {
                                    "id": req_obj.sub_req_id,
                                    "name": req_obj.sub_req_name,
                                    "providedby": {
                                        req_obj.sub_proby_name: req_obj.sub_proby_name
                                    } if req_obj.sub_proby_name else {}
                                }
                            }
                        }
                    )
            else:
                req_info = sub_pkg_info["requires"]
                if req_obj.sub_req_name in req_info:
                    req_info[req_obj.sub_req_name]["providedby"].update(
                        {req_obj.sub_proby_name: req_obj.sub_proby_name})
                else:
                    req_info.update(
                        {
                            req_obj.sub_req_name: {
                                "id": req_obj.sub_req_id,
                                "name": req_obj.sub_req_name,
                                "providedby": {
                                    req_obj.sub_proby_name: req_obj.sub_proby_name
                                } if req_obj.sub_proby_name else {}
                            }
                        }
                    )
        helper([values for k, values in res.items()])
        return (list(res.values()))