-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy path__init__.py
144 lines (115 loc) · 4.61 KB
/
__init__.py
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import logging
import os
import sys
from pathlib import Path
from types import MappingProxyType
from typing import TYPE_CHECKING, Dict, Mapping, Optional, Sequence, Union
from .. import api, dist_name, types
from .._vendor import fastjsonschema as FJS
if sys.version_info[:2] >= (3, 8): # pragma: no cover
from importlib import metadata as _M
else: # pragma: no cover
import importlib_metadata as _M
if TYPE_CHECKING: # pragma: no cover
from ..plugins import PluginWrapper # noqa
_logger = logging.getLogger(__name__)
TEXT_REPLACEMENTS = MappingProxyType(
{
"from fastjsonschema import": "from .fastjsonschema_exceptions import",
"from ._vendor.fastjsonschema import": "from .fastjsonschema_exceptions import",
}
)
def pre_compile(
output_dir: Union[str, os.PathLike] = ".",
main_file: str = "__init__.py",
original_cmd: str = "",
plugins: Union[api.AllPlugins, Sequence["PluginWrapper"]] = api.ALL_PLUGINS,
text_replacements: Mapping[str, str] = TEXT_REPLACEMENTS,
) -> Path:
"""Populate the given ``output_dir`` with all files necessary to perform
the validation.
The validation can be performed by calling the ``validate`` function inside the
the file named with the ``main_file`` value.
``text_replacements`` can be used to
"""
out = Path(output_dir)
out.mkdir(parents=True, exist_ok=True)
replacements = {**TEXT_REPLACEMENTS, **text_replacements}
validator = api.Validator(plugins)
header = "\n".join(NOCHECK_HEADERS)
code = replace_text(validator.generated_code, replacements)
(out / "fastjsonschema_validations.py").write_text(header + code, "UTF-8")
copy_fastjsonschema_exceptions(out, replacements)
copy_module("extra_validations", out, replacements)
copy_module("formats", out, replacements)
copy_module("error_reporting", out, replacements)
write_main(out / main_file, validator.schema, replacements)
write_notice(out, main_file, original_cmd, replacements)
(out / "__init__.py").touch()
return out
def replace_text(text: str, replacements: Dict[str, str]) -> str:
for orig, subst in replacements.items():
text = text.replace(orig, subst)
return text
def copy_fastjsonschema_exceptions(
output_dir: Path, replacements: Dict[str, str]
) -> Path:
file = output_dir / "fastjsonschema_exceptions.py"
code = replace_text(api.read_text(FJS.__name__, "exceptions.py"), replacements)
file.write_text(code, "UTF-8")
return file
def copy_module(name: str, output_dir: Path, replacements: Dict[str, str]) -> Path:
file = output_dir / f"{name}.py"
code = api.read_text(api.__package__, f"{name}.py")
code = replace_text(code, replacements)
file.write_text(code, "UTF-8")
return file
def write_main(
file_path: Path, schema: types.Schema, replacements: Dict[str, str]
) -> Path:
code = api.read_text(__name__, "main_file.template")
code = replace_text(code, replacements)
file_path.write_text(code, "UTF-8")
return file_path
def write_notice(
out: Path, main_file: str, cmd: str, replacements: Dict[str, str]
) -> Path:
if cmd:
opening = api.read_text(__name__, "cli-notice.template")
opening = opening.format(command=cmd)
else:
opening = api.read_text(__name__, "api-notice.template")
notice = api.read_text(__name__, "NOTICE.template")
notice = notice.format(notice=opening, main_file=main_file, **load_licenses())
notice = replace_text(notice, replacements)
file = out / "NOTICE"
file.write_text(notice, "UTF-8")
return file
def load_licenses() -> Dict[str, str]:
return {
"fastjsonschema_license": api.read_text(FJS, "LICENSE"),
"validate_pyproject_license": _find_and_load_licence(_M.files(dist_name)),
}
NOCHECK_HEADERS = (
"# noqa",
"# type: ignore",
"# flake8: noqa",
"# pylint: skip-file",
"# mypy: ignore-errors",
"# yapf: disable",
"# pylama:skip=1",
"\n\n# *** PLEASE DO NOT MODIFY DIRECTLY: Automatically generated code *** \n\n\n",
)
def _find_and_load_licence(files: Optional[Sequence[_M.PackagePath]]) -> str:
if files is None: # pragma: no cover
raise ImportError("Could not find LICENSE for package")
try:
return next(f for f in files if f.stem.upper() == "LICENSE").read_text("UTF-8")
except FileNotFoundError: # pragma: no cover
msg = (
"Please make sure to install `validate-pyproject` and `fastjsonschema` "
"in a NON-EDITABLE way. This is necessary due to the issue #112 in "
"python/importlib_metadata."
)
_logger.warning(msg)
raise