• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

abravalheri / validate-pyproject / 11034501584

25 Sep 2024 01:49PM CUT coverage: 97.823% (-0.2%) from 97.976%
11034501584

push

github

abravalheri
Prevent Github action for ignoring files for cache

551 of 571 branches covered (96.5%)

Branch coverage included in aggregate %.

932 of 945 relevant lines covered (98.62%)

5.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/validate_pyproject/pre_compile/cli.py
1
# ruff: noqa: C408
2
# Unnecessary `dict` call (rewrite as a literal)
3

4
import json
6✔
5
import logging
6✔
6
import sys
6✔
7
from functools import partial, wraps
6✔
8
from pathlib import Path
6✔
9
from types import MappingProxyType
6✔
10
from typing import Any, Dict, List, Mapping, NamedTuple, Sequence
6✔
11

12
from .. import cli
6✔
13
from ..plugins import PluginWrapper
6✔
14
from ..plugins import list_from_entry_points as list_plugins_from_entry_points
6✔
15
from ..remote import RemotePlugin, load_store
6✔
16
from . import pre_compile
6✔
17

18
if sys.platform == "win32":  # pragma: no cover
19
    from subprocess import list2cmdline as arg_join
20
else:  # pragma: no cover
21
    from shlex import join as arg_join
22

23

24
_logger = logging.getLogger(__package__)
6✔
25

26

27
def JSON_dict(name: str, value: str) -> Dict[str, Any]:
6✔
28
    try:
6✔
29
        return ensure_dict(name, json.loads(value))
6✔
30
    except json.JSONDecodeError as ex:
6✔
31
        raise ValueError(f"Invalid JSON: {value}") from ex
6✔
32

33

34
META: Dict[str, dict] = {
6✔
35
    "output_dir": dict(
36
        flags=("-O", "--output-dir"),
37
        default=".",
38
        type=Path,
39
        help="Path to the directory where the files for embedding will be generated "
40
        "(default: current working directory)",
41
    ),
42
    "main_file": dict(
43
        flags=("-M", "--main-file"),
44
        default="__init__.py",
45
        help="Name of the file that will contain the main `validate` function"
46
        "(default: `%(default)s`)",
47
    ),
48
    "replacements": dict(
49
        flags=("-R", "--replacements"),
50
        default="{}",
51
        type=wraps(JSON_dict)(partial(JSON_dict, "replacements")),
52
        help="JSON string (don't forget to quote) representing a map between strings "
53
        "that should be replaced in the generated files and their replacement, "
54
        "for example: \n"
55
        '-R \'{"from packaging import": "from .._vendor.packaging import"}\'',
56
    ),
57
    "tool": dict(
58
        flags=("-t", "--tool"),
59
        action="append",
60
        dest="tool",
61
        help="External tools file/url(s) to load, of the form name=URL#path",
62
    ),
63
    "store": dict(
64
        flags=("--store",),
65
        help="Load a pyproject.json file and read all the $ref's into tools "
66
        "(see https://json.schemastore.org/pyproject.json)",
67
    ),
68
}
69

70

71
def ensure_dict(name: str, value: Any) -> dict:
6✔
72
    if not isinstance(value, dict):
6✔
73
        msg = f"`{value.__class__.__name__}` given (value = {value!r})."
6✔
74
        raise ValueError(f"`{name}` should be a dict. {msg}")
6✔
75
    return value
6✔
76

77

78
class CliParams(NamedTuple):
6✔
79
    plugins: List[PluginWrapper]
6✔
80
    output_dir: Path = Path(".")
6✔
81
    main_file: str = "__init__.py"
6✔
82
    replacements: Mapping[str, str] = MappingProxyType({})
6✔
83
    loglevel: int = logging.WARNING
6✔
84
    tool: Sequence[str] = ()
6✔
85
    store: str = ""
6✔
86

87

88
def parser_spec(plugins: Sequence[PluginWrapper]) -> Dict[str, dict]:
6✔
89
    common = ("version", "enable", "disable", "verbose", "very_verbose")
6✔
90
    cli_spec = cli.__meta__(plugins)
6✔
91
    meta = {k: v.copy() for k, v in META.items()}
6✔
92
    meta.update({k: cli_spec[k].copy() for k in common})
6✔
93
    return meta
6✔
94

95

96
def run(args: Sequence[str] = ()) -> int:
6✔
97
    args = args if args else sys.argv[1:]
6✔
98
    cmd = f"python -m {__package__} " + arg_join(args)
6✔
99
    plugins = list_plugins_from_entry_points()
6✔
100
    desc = 'Generate files for "pre-compiling" `validate-pyproject`'
6✔
101
    prms = cli.parse_args(args, plugins, desc, parser_spec, CliParams)
6✔
102
    cli.setup_logging(prms.loglevel)
6✔
103

104
    tool_plugins = [RemotePlugin.from_str(t) for t in prms.tool]
6✔
105
    if prms.store:
6✔
106
        tool_plugins.extend(load_store(prms.store))
6✔
107

108
    pre_compile(
6✔
109
        prms.output_dir,
110
        prms.main_file,
111
        cmd,
112
        prms.plugins,
113
        prms.replacements,
114
        extra_plugins=tool_plugins,
115
    )
116
    return 0
6✔
117

118

119
main = cli.exceptions2exit()(run)
6✔
120

121

122
if __name__ == "__main__":
123
    main()
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc