File: helper.py

package info (click to toggle)
python-deadlib 3.13.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,636 kB
  • sloc: python: 25,254; makefile: 11
file content (108 lines) | stat: -rw-r--r-- 3,096 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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
from __future__ import annotations

from argparse import ArgumentParser, Namespace
import glob
import json
from pathlib import Path
import subprocess
import sys
from typing import cast

from packaging.requirements import Requirement

if sys.version_info >= (3, 11):
    import tomllib
else:
    import tomli as tomllib


PROJECT_DIR = Path(__file__).parents[1]
DEFAULT_EXCLUDES: list[str] = []


def list_test_folders(exclude_folders: list[str] | None) -> int:
    """List all folders with tests"""
    exclude_folders = exclude_folders or []
    exclude_folders.extend(DEFAULT_EXCLUDES)
    res = 0
    for exclude in exclude_folders:
        if not (PROJECT_DIR / exclude).is_dir():
            print(f"'{exclude}' is not a valid folder")
            res = 1
    if res:
        return 1

    excludes = tuple(exclude_folders)
    test_folders = [
        folder.partition("/")[0]
        for folder in glob.glob("*/tests")
        if not folder.startswith(excludes)
    ]
    print(json.dumps(sorted(test_folders)))
    return 0


def install_local_requirements(name: str, installed_pkgs: set[str] | None = None) -> int:
    """Install local requirements recursively."""
    installed_pkgs = installed_pkgs or set()

    reqs_folder = PROJECT_DIR / name
    content = tomllib.loads(
        (reqs_folder / "pyproject.toml").read_text()
    )
    dependencies = [
        deps
        for req in content["project"].get("dependencies", [])
        if (deps := Requirement(req).name).startswith("standard-")
    ]
    for deps in dependencies:
        if deps in installed_pkgs:
            continue
        if install_local_requirements(deps.removeprefix("standard-"), installed_pkgs):
            return 1
    p = subprocess.run(["pip", "install", reqs_folder], stdout=sys.stdout, stderr=sys.stderr)
    return p.returncode


class ListTestFoldersArgs(Namespace):
    exclude: list[str] | None


class InstallLocalReqsArgs(Namespace):
    folder: str


def main(argv: list[str] | None = None) -> int:
    parser = ArgumentParser()
    subparsers = parser.add_subparsers(title="Subcommands", required=True)

    parser_test_folders = subparsers.add_parser("list-test-folders")
    parser_test_folders.set_defaults(action="list-test-folders")
    parser_test_folders.add_argument(
        "--exclude",
        action="append",
        help="Root folders to exclude from search",
    )

    parser_local_reqs = subparsers.add_parser("install-local-requirements")
    parser_local_reqs.set_defaults(action="install-local-requirements")
    parser_local_reqs.add_argument(
        "folder",
        metavar="FOLDER",
        help="Current deadlib backport to install",
    )

    argv = argv or sys.argv[1:]
    args = parser.parse_args(argv)

    if args.action == "list-test-folders":
        args = cast(ListTestFoldersArgs, args)
        return list_test_folders(args.exclude)
    if args.action == "install-local-requirements":
        args = cast(InstallLocalReqsArgs, args)
        return install_local_requirements(args.folder)
    return 0


if __name__ == "__main__":
    sys.exit(main())