File: verify_installed_packages.py

package info (click to toggle)
python-azure 20260113%2Bgit-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 786,404 kB
  • sloc: python: 6,519,100; ansic: 804; javascript: 287; sh: 204; makefile: 198; xml: 109
file content (87 lines) | stat: -rw-r--r-- 3,205 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
#!/usr/bin/env python

# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import argparse
import os
import sys
import logging
import re
from os import path

# import common_task module
root_dir = path.abspath(path.join(path.abspath(__file__), "..", "..", ".."))
common_task_path = path.abspath(path.join(root_dir, "scripts", "devops_tasks"))
sys.path.append(common_task_path)
from common_tasks import get_installed_packages


def normalize_package_name(package_name: str) -> str:
    """Apply PEP 503 normalization rules to package names

    .. see-also::

        https://peps.python.org/pep-0503/#normalized-names
        https://packaging.python.org/en/latest/specifications/name-normalization/#name-normalization
    """

    return re.sub(r"[-_.]+", "-", package_name).lower()


def verify_packages(package_file_path):
    # this method verifies packages installed on machine is matching the expected package version
    # packages.txt file expects to have list of packages and version in format <package-name>==<version>

    packages = []
    with open(package_file_path, "r") as packages_file:
        packages = packages_file.readlines()
    packages = [p.replace('\n', '') for p in packages]

    # packages.txt is created by package installation script. But this script can be reused to verify installed packages
    # Add a sanity check to ensure content in file is in expected format
    invalid_lines = [p for p in packages if '==' not in p]
    if invalid_lines:
        logging.error("packages.txt has package details in invalid format. Expected format is <package-name>==<version>")
        sys.exit(1)

    # find installed and expected packages
    installed = {}
    for p in get_installed_packages():
        if "==" in p:
            [package, version] = p.split("==")
            installed[normalize_package_name(package)] = version
    expected = {}
    for p in packages:
        [package, version] = p.split("==")
        expected[normalize_package_name(package)] = version

    missing_packages = [pkg for pkg in expected.keys() if installed.get(pkg) != expected.get(pkg)]

    if missing_packages:
        logging.error("Version is incorrect for following package[s]")
        for package in missing_packages:
            logging.error("%s, Expected[%s], Installed[%s]", package, expected[package], installed[package])
        sys.exit(1)
    else:
        logging.info("Verified package version")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Install either latest or minimum version of dependent packages."
    )

    parser.add_argument(
        "-f",
        "--packages-file",
        dest="packages_file",
        help="Path to a file that has list of packages and version to verify",
        required=True,
    )

    args = parser.parse_args()
    if os.path.exists(args.packages_file):
        verify_packages(args.packages_file)