summaryrefslogtreecommitdiff
path: root/src/setuptools_scm/_cli.py
blob: 37bbc9a8f1df14514fded368e6261279533cdb26 (plain)
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
from __future__ import annotations

import argparse
import os
import sys

from setuptools_scm import _get_version
from setuptools_scm import Configuration
from setuptools_scm._file_finders import find_files
from setuptools_scm.discover import walk_potential_roots


def main(args: list[str] | None = None) -> None:
    opts = _get_cli_opts(args)
    inferred_root: str = opts.root or "."

    pyproject = opts.config or _find_pyproject(inferred_root)

    try:
        config = Configuration.from_file(
            pyproject,
            root=(os.path.abspath(opts.root) if opts.root is not None else None),
        )
    except (LookupError, FileNotFoundError) as ex:
        # no pyproject.toml OR no [tool.setuptools_scm]
        print(
            f"Warning: could not use {os.path.relpath(pyproject)},"
            " using default configuration.\n"
            f" Reason: {ex}.",
            file=sys.stderr,
        )
        config = Configuration(inferred_root)

    version = _get_version(config)
    if version is None:
        raise SystemExit("ERROR: no version found for", opts)
    if opts.strip_dev:
        version = version.partition(".dev")[0]
    print(version)

    if opts.command == "ls":
        for fname in find_files(config.root):
            print(fname)


def _get_cli_opts(args: list[str] | None) -> argparse.Namespace:
    prog = "python -m setuptools_scm"
    desc = "Print project version according to SCM metadata"
    parser = argparse.ArgumentParser(prog, description=desc)
    # By default, help for `--help` starts with lower case, so we keep the pattern:
    parser.add_argument(
        "-r",
        "--root",
        default=None,
        help='directory managed by the SCM, default: inferred from config file, or "."',
    )
    parser.add_argument(
        "-c",
        "--config",
        default=None,
        metavar="PATH",
        help="path to 'pyproject.toml' with setuptools_scm config, "
        "default: looked up in the current or parent directories",
    )
    parser.add_argument(
        "--strip-dev",
        action="store_true",
        help="remove the dev/local parts of the version before printing the version",
    )
    sub = parser.add_subparsers(title="extra commands", dest="command", metavar="")
    # We avoid `metavar` to prevent printing repetitive information
    desc = "List files managed by the SCM"
    sub.add_parser("ls", help=desc[0].lower() + desc[1:], description=desc)
    return parser.parse_args(args)


def _find_pyproject(parent: str) -> str:
    for directory in walk_potential_roots(os.path.abspath(parent)):
        pyproject = os.path.join(directory, "pyproject.toml")
        if os.path.isfile(pyproject):
            return pyproject

    return os.path.abspath(
        "pyproject.toml"
    )  # use default name to trigger the default errors