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

abravalheri / validate-pyproject / 6173991897923584

11 Nov 2024 04:41PM UTC coverage: 97.859%. Remained the same
6173991897923584

Pull #218

cirrus-ci

pre-commit-ci[bot]
[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
Pull Request #218: [pre-commit.ci] pre-commit autoupdate

293 of 306 branches covered (95.75%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

941 of 955 relevant lines covered (98.53%)

6.89 hits per line

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

98.41
/src/validate_pyproject/pre_compile/__init__.py
1
import logging
7✔
2
import os
7✔
3
from importlib import metadata as _M
7✔
4
from pathlib import Path
7✔
5
from types import MappingProxyType
7✔
6
from typing import TYPE_CHECKING, Dict, Mapping, Optional, Sequence, Union
7✔
7

8
import fastjsonschema as FJS
7✔
9

10
from .. import api, dist_name, types
7✔
11

12
if TYPE_CHECKING:  # pragma: no cover
13
    from ..plugins import PluginProtocol
14

15

16
_logger = logging.getLogger(__name__)
7✔
17

18

19
TEXT_REPLACEMENTS = MappingProxyType(
7✔
20
    {
21
        "from fastjsonschema import": "from .fastjsonschema_exceptions import",
22
    }
23
)
24

25

26
def pre_compile(  # noqa: PLR0913
7✔
27
    output_dir: Union[str, os.PathLike] = ".",
28
    main_file: str = "__init__.py",
29
    original_cmd: str = "",
30
    plugins: Union[api.AllPlugins, Sequence["PluginProtocol"]] = api.ALL_PLUGINS,
31
    text_replacements: Mapping[str, str] = TEXT_REPLACEMENTS,
32
    *,
33
    extra_plugins: Sequence["PluginProtocol"] = (),
34
) -> Path:
35
    """Populate the given ``output_dir`` with all files necessary to perform
36
    the validation.
37
    The validation can be performed by calling the ``validate`` function inside the
38
    the file named with the ``main_file`` value.
39
    ``text_replacements`` can be used to
40
    """
41
    out = Path(output_dir)
7✔
42
    out.mkdir(parents=True, exist_ok=True)
7✔
43
    replacements = {**TEXT_REPLACEMENTS, **text_replacements}
7✔
44

45
    validator = api.Validator(plugins, extra_plugins=extra_plugins)
7✔
46
    header = "\n".join(NOCHECK_HEADERS)
7✔
47
    code = replace_text(validator.generated_code, replacements)
7✔
48
    _write(out / "fastjsonschema_validations.py", header + code)
7✔
49

50
    copy_fastjsonschema_exceptions(out, replacements)
7✔
51
    copy_module("extra_validations", out, replacements)
7✔
52
    copy_module("formats", out, replacements)
7✔
53
    copy_module("error_reporting", out, replacements)
7✔
54
    write_main(out / main_file, validator.schema, replacements)
7✔
55
    write_notice(out, main_file, original_cmd, replacements)
7✔
56
    (out / "__init__.py").touch()
7✔
57

58
    return out
7✔
59

60

61
def replace_text(text: str, replacements: Dict[str, str]) -> str:
7✔
62
    for orig, subst in replacements.items():
7✔
63
        text = text.replace(orig, subst)
7✔
64
    return text
7✔
65

66

67
def copy_fastjsonschema_exceptions(
7✔
68
    output_dir: Path, replacements: Dict[str, str]
69
) -> Path:
70
    code = replace_text(api.read_text(FJS.__name__, "exceptions.py"), replacements)
7✔
71
    return _write(output_dir / "fastjsonschema_exceptions.py", code)
7✔
72

73

74
def copy_module(name: str, output_dir: Path, replacements: Dict[str, str]) -> Path:
7✔
75
    code = api.read_text(api.__package__, f"{name}.py")
7✔
76
    return _write(output_dir / f"{name}.py", replace_text(code, replacements))
7✔
77

78

79
def write_main(
7✔
80
    file_path: Path, schema: types.Schema, replacements: Dict[str, str]
81
) -> Path:
82
    code = api.read_text(__name__, "main_file.template")
7✔
83
    return _write(file_path, replace_text(code, replacements))
7✔
84

85

86
def write_notice(
7✔
87
    out: Path, main_file: str, cmd: str, replacements: Dict[str, str]
88
) -> Path:
89
    if cmd:
7✔
90
        opening = api.read_text(__name__, "cli-notice.template")
7✔
91
        opening = opening.format(command=cmd)
7✔
92
    else:
93
        opening = api.read_text(__name__, "api-notice.template")
7✔
94
    notice = api.read_text(__name__, "NOTICE.template")
7✔
95
    notice = notice.format(notice=opening, main_file=main_file, **load_licenses())
7✔
96
    notice = replace_text(notice, replacements)
7✔
97

98
    return _write(out / "NOTICE", notice)
7✔
99

100

101
def load_licenses() -> Dict[str, str]:
7✔
102
    return {
7✔
103
        "fastjsonschema_license": _find_and_load_licence(_M.files("fastjsonschema")),
104
        "validate_pyproject_license": _find_and_load_licence(_M.files(dist_name)),
105
    }
106

107

108
NOCHECK_HEADERS = (
7✔
109
    "# noqa",
110
    "# ruff: noqa",
111
    "# flake8: noqa",
112
    "# pylint: skip-file",
113
    "# mypy: ignore-errors",
114
    "# yapf: disable",
115
    "# pylama:skip=1",
116
    "\n\n# *** PLEASE DO NOT MODIFY DIRECTLY: Automatically generated code *** \n\n\n",
117
)
118

119

120
def _find_and_load_licence(files: Optional[Sequence[_M.PackagePath]]) -> str:
7✔
121
    if files is None:  # pragma: no cover
122
        raise ImportError("Could not find LICENSE for package")
123
    try:
7✔
124
        return next(f for f in files if f.stem.upper() == "LICENSE").read_text("UTF-8")
7!
125
    except FileNotFoundError:  # pragma: no cover
126
        msg = (
127
            "Please make sure to install `validate-pyproject` and `fastjsonschema` "
128
            "in a NON-EDITABLE way. This is necessary due to the issue #112 in "
129
            "python/importlib_metadata."
130
        )
131
        _logger.warning(msg)
132
        raise
133

134

135
def _write(file: Path, text: str) -> Path:
7✔
136
    file.write_text(text.rstrip() + "\n", encoding="utf-8")  # POSIX convention
7✔
137
    return file
7✔
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