makepatch 0.0.1__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- makepatch-0.2.1/.editorconfig +1 -0
- makepatch-0.2.1/.gitignore +6 -0
- makepatch-0.2.1/PKG-INFO +23 -0
- makepatch-0.2.1/pyproject.toml +48 -0
- makepatch-0.2.1/src/makepatch/__hooks__.py +7 -0
- makepatch-0.2.1/src/makepatch/__init__.py +1 -0
- makepatch-0.2.1/src/makepatch/_config.py +59 -0
- makepatch-0.2.1/src/makepatch/_types/__init__.pyi +1 -0
- makepatch-0.2.1/src/makepatch/_types/hatch.pyi +57 -0
- makepatch-0.2.1/src/makepatch/core/__init__.py +1 -0
- makepatch-0.2.1/src/makepatch/core/_patcher.py +125 -0
- makepatch-0.2.1/src/makepatch/hooks/__init__.py +1 -0
- makepatch-0.2.1/src/makepatch/hooks/_patch.py +60 -0
- makepatch-0.2.1/src/makepatch/scripts/__init__.py +28 -0
- makepatch-0.2.1/src/makepatch/scripts/_rebuild.py +78 -0
- makepatch-0.2.1/uv.lock +192 -0
- makepatch-0.0.1/PKG-INFO +0 -8
- makepatch-0.0.1/pyproject.toml +0 -26
- makepatch-0.0.1/src/makepatch/__hook__.py +0 -7
- makepatch-0.0.1/src/makepatch/__init__.py +0 -0
- makepatch-0.0.1/src/makepatch/_config.py +0 -18
- makepatch-0.0.1/src/makepatch/hooks/__init__.py +0 -1
- makepatch-0.0.1/src/makepatch/hooks/_patch.py +0 -88
- makepatch-0.0.1/src/makepatch/scripts/__init__.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
../.editorconfig
|
makepatch-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: makepatch
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Hatch build hook to easily hard-fork packages with patches!
|
|
5
|
+
Project-URL: source, https://github.com/AlphaKR93/packages/tree/main/python/makepatch
|
|
6
|
+
Project-URL: issues, https://github.com/AlphaKR93/packages/issues
|
|
7
|
+
Author-email: Alpha <dev@alpha93.kr>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Environment :: Plugins
|
|
12
|
+
Classifier: Framework :: Hatch
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
19
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
20
|
+
Requires-Python: >=3.12
|
|
21
|
+
Requires-Dist: hatchling>=1.29.0
|
|
22
|
+
Requires-Dist: pydantic>=2.13.0
|
|
23
|
+
Requires-Dist: typing-extensions>=4.15.0; python_version < '3.15'
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
build-backend = "hatchling.build"
|
|
3
|
+
requires = ["hatchling"]
|
|
4
|
+
|
|
5
|
+
[project.entry-points.hatch]
|
|
6
|
+
makepatch = "makepatch.__hooks__"
|
|
7
|
+
|
|
8
|
+
[project.scripts]
|
|
9
|
+
apply-patches = "makepatch.scripts:apply_patches"
|
|
10
|
+
rebuild-patches = "makepatch.scripts:rebuild_patches"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
[project]
|
|
14
|
+
name = "makepatch"
|
|
15
|
+
version = "0.2.1"
|
|
16
|
+
authors = [{ name = "Alpha", email = "dev@alpha93.kr" }]
|
|
17
|
+
description = "Hatch build hook to easily hard-fork packages with patches!"
|
|
18
|
+
license = "MIT"
|
|
19
|
+
requires-python = ">=3.12"
|
|
20
|
+
classifiers = [
|
|
21
|
+
"Development Status :: 4 - Beta",
|
|
22
|
+
"Intended Audience :: Developers",
|
|
23
|
+
"Environment :: Console",
|
|
24
|
+
"Environment :: Plugins",
|
|
25
|
+
"Framework :: Hatch",
|
|
26
|
+
|
|
27
|
+
"Programming Language :: Python",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
29
|
+
"Programming Language :: Python :: 3.13",
|
|
30
|
+
"Programming Language :: Python :: 3.14",
|
|
31
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
32
|
+
|
|
33
|
+
"Topic :: Software Development :: Build Tools",
|
|
34
|
+
]
|
|
35
|
+
dependencies = [
|
|
36
|
+
"hatchling>=1.29.0",
|
|
37
|
+
"pydantic>=2.13.0",
|
|
38
|
+
"typing_extensions>=4.15.0; python_version < '3.15'",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[dependency-groups]
|
|
42
|
+
dev = []
|
|
43
|
+
|
|
44
|
+
[project.urls]
|
|
45
|
+
# homepage = "https://alpha93.kr/project/python/makepatch"
|
|
46
|
+
source = "https://github.com/AlphaKR93/packages/tree/main/python/makepatch"
|
|
47
|
+
issues = "https://github.com/AlphaKR93/packages/issues"
|
|
48
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .hooks import PatcherBuildHook
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from collections.abc import Iterable
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import final, Annotated, ClassVar
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
from pydantic.json_schema import SkipJsonSchema
|
|
8
|
+
|
|
9
|
+
if __debug__ and __import__("typing").TYPE_CHECKING:
|
|
10
|
+
|
|
11
|
+
from makepatch._types.hatch import HatchHookInterface
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@final
|
|
15
|
+
class PatcherConfig(BaseModel):
|
|
16
|
+
__INTERNAL: ClassVar[object] = object()
|
|
17
|
+
__INSTANCE: ClassVar[PatcherConfig | None] = None
|
|
18
|
+
|
|
19
|
+
module_source: Annotated[str, Field(alias="module-source")]
|
|
20
|
+
excludes: Annotated[Iterable[str], Field(default_factory=frozenset)]
|
|
21
|
+
dev_excludes: Annotated[Iterable[str], Field(alias="dev-excludes", default_factory=frozenset)]
|
|
22
|
+
|
|
23
|
+
module_name: Annotated[SkipJsonSchema[str], Field(exclude=True)]
|
|
24
|
+
project_root: Annotated[SkipJsonSchema[Path], Field(exclude=True)]
|
|
25
|
+
|
|
26
|
+
def __init__(self, obj: object, /, **kwargs):
|
|
27
|
+
if obj is not self.__INTERNAL:
|
|
28
|
+
raise RuntimeError("Security error: External initialization is prohibited")
|
|
29
|
+
if "/" in kwargs["module-source"]:
|
|
30
|
+
_, kwargs["module_name"] = str(kwargs["module-source"]).rsplit(os.sep, 1)
|
|
31
|
+
else:
|
|
32
|
+
kwargs["module_name"] = kwargs["module-source"]
|
|
33
|
+
super().__init__(**kwargs)
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def from_hatch(cls, hook: HatchHookInterface, /) -> PatcherConfig:
|
|
37
|
+
if PatcherConfig.__INSTANCE:
|
|
38
|
+
raise RuntimeError(f"{cls.__name__} already initialized")
|
|
39
|
+
|
|
40
|
+
config = hook.config["options"]
|
|
41
|
+
config["project_root"] = Path(hook.root).resolve()
|
|
42
|
+
PatcherConfig.__INSTANCE = PatcherConfig(PatcherConfig.__INTERNAL, **config)
|
|
43
|
+
assert PatcherConfig.__INSTANCE
|
|
44
|
+
return PatcherConfig.__INSTANCE
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def from_pyproject(cls, root: Path, /):
|
|
48
|
+
pyproject_toml = (root / "pyproject.toml").resolve()
|
|
49
|
+
if not pyproject_toml.exists() or not pyproject_toml.is_file():
|
|
50
|
+
raise FileNotFoundError(f"{pyproject_toml} does not exist or is not a file")
|
|
51
|
+
|
|
52
|
+
import tomllib
|
|
53
|
+
try:
|
|
54
|
+
with open(pyproject_toml, 'rb') as f:
|
|
55
|
+
config = tomllib.load(f)["tool"]["hatch"]["build"]["hooks"]["makepatch"]["options"]
|
|
56
|
+
config["project_root"] = Path(root).resolve()
|
|
57
|
+
return PatcherConfig(PatcherConfig.__INTERNAL, **config)
|
|
58
|
+
except tomllib.TOMLDecodeError as e:
|
|
59
|
+
raise RuntimeError(f"Cannot parse pyproject.toml") from e
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .hatch import HatchHookInterface
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from typing import Protocol, Any
|
|
2
|
+
|
|
3
|
+
from hatchling.bridge.app import Application
|
|
4
|
+
from hatchling.metadata.core import ProjectMetadata
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class HatchHookInterface(Protocol):
|
|
8
|
+
@property
|
|
9
|
+
def app(self, /) -> Application:
|
|
10
|
+
"""
|
|
11
|
+
An instance of [Application](../utilities.md#hatchling.bridge.app.Application).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def root(self, /) -> str:
|
|
16
|
+
"""
|
|
17
|
+
The root of the project tree.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def config(self, /) -> dict[str, Any]:
|
|
22
|
+
"""
|
|
23
|
+
The cumulative hook configuration.
|
|
24
|
+
|
|
25
|
+
```toml config-example
|
|
26
|
+
[tool.hatch.build.hooks.<PLUGIN_NAME>]
|
|
27
|
+
[tool.hatch.build.targets.<TARGET_NAME>.hooks.<PLUGIN_NAME>]
|
|
28
|
+
```
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def metadata(self, /) -> ProjectMetadata:
|
|
33
|
+
...
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def directory(self, /) -> str:
|
|
37
|
+
"""
|
|
38
|
+
The build directory.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def target_name(self, /) -> str:
|
|
43
|
+
"""
|
|
44
|
+
The plugin name of the build target.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def dependencies(self, /) -> list[str]: # noqa: PLR6301
|
|
48
|
+
"""
|
|
49
|
+
A list of extra [dependencies](../../config/dependency.md) that must be installed
|
|
50
|
+
prior to builds.
|
|
51
|
+
|
|
52
|
+
!!! warning
|
|
53
|
+
- For this to have any effect the hook dependency itself cannot be dynamic and
|
|
54
|
+
must always be defined in `build-system.requires`.
|
|
55
|
+
- As the hook must be imported to call this method, imports that require these
|
|
56
|
+
dependencies must be evaluated lazily.
|
|
57
|
+
"""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from ._patcher import PatchApplier
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import subprocess
|
|
4
|
+
from typing import final
|
|
5
|
+
|
|
6
|
+
from makepatch._config import PatcherConfig
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
if __debug__ and __import__("typing").TYPE_CHECKING:
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Final
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@final
|
|
15
|
+
class PatchApplier:
|
|
16
|
+
if __debug__ and __import__("typing").TYPE_CHECKING:
|
|
17
|
+
__slots__ = (
|
|
18
|
+
"__config",
|
|
19
|
+
"__excludes",
|
|
20
|
+
"__excludes_dev",
|
|
21
|
+
"__patches",
|
|
22
|
+
"__src",
|
|
23
|
+
"__sources",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def __init__(self, config: PatcherConfig, /) -> None:
|
|
27
|
+
self.__config: Final = config
|
|
28
|
+
self.__excludes: Final = set[str]()
|
|
29
|
+
self.__excludes_dev: Final = set[str]()
|
|
30
|
+
|
|
31
|
+
# resolve patches
|
|
32
|
+
self.__patches: Final = self.__resolve_path(config.project_root / "patches")
|
|
33
|
+
|
|
34
|
+
# INTENDED: required for later use
|
|
35
|
+
self.__src: Path | None = None
|
|
36
|
+
self.__sources: Path | None = None
|
|
37
|
+
|
|
38
|
+
def setup_required(self, /):
|
|
39
|
+
return not (self.__config.project_root / "work/patched").resolve().exists()
|
|
40
|
+
|
|
41
|
+
@staticmethod
|
|
42
|
+
def __resolve_path(path: Path, /):
|
|
43
|
+
path = path.resolve()
|
|
44
|
+
if not path.exists() or not path.is_dir():
|
|
45
|
+
raise RuntimeError(f"{path} does not exist or is not a directory")
|
|
46
|
+
return path
|
|
47
|
+
|
|
48
|
+
def resolve_src(self, /):
|
|
49
|
+
"""
|
|
50
|
+
Resolves `module` src root, where the codes are placed
|
|
51
|
+
"""
|
|
52
|
+
assert not self.__src
|
|
53
|
+
if not self.__sources:
|
|
54
|
+
self.__sources = self.__resolve_path(self.__config.project_root / "work/sources")
|
|
55
|
+
assert self.__sources
|
|
56
|
+
src = self.__src = self.__resolve_path(self.__sources / self.__config.module_source)
|
|
57
|
+
|
|
58
|
+
for glob in self.__config.excludes:
|
|
59
|
+
dirname = glob.split(os.sep, 1)[0]
|
|
60
|
+
for excluded in src.rglob(glob):
|
|
61
|
+
if (rel_str := str(excluded.relative_to(src))).startswith(dirname):
|
|
62
|
+
self.__excludes.add(rel_str)
|
|
63
|
+
|
|
64
|
+
def resolve_sources(self, /):
|
|
65
|
+
"""
|
|
66
|
+
Resolves entire git sources
|
|
67
|
+
"""
|
|
68
|
+
assert not self.__sources
|
|
69
|
+
sources = self.__sources = self.__resolve_path(self.__config.project_root / "work/sources")
|
|
70
|
+
|
|
71
|
+
for glob in self.__config.dev_excludes:
|
|
72
|
+
dirname = glob.split(os.sep, 1)[0]
|
|
73
|
+
for excluded in sources.rglob(glob):
|
|
74
|
+
if (rel_str := str(excluded.relative_to(sources))).startswith(dirname):
|
|
75
|
+
self.__excludes_dev.add(rel_str)
|
|
76
|
+
|
|
77
|
+
def copy(self, dst: Path, /):
|
|
78
|
+
if self.__excludes_dev:
|
|
79
|
+
src = self.__sources
|
|
80
|
+
excludes = self.__excludes_dev
|
|
81
|
+
filter_ = lambda path: path.is_relative_to(self.__src) and (str(path.relative_to(self.__src)) in self.__excludes)
|
|
82
|
+
else:
|
|
83
|
+
src = self.__src
|
|
84
|
+
excludes = self.__excludes
|
|
85
|
+
filter_ = None
|
|
86
|
+
|
|
87
|
+
assert src and excludes
|
|
88
|
+
for src_file in src.rglob("*"):
|
|
89
|
+
if not src_file.is_file():
|
|
90
|
+
assert src_file.exists()
|
|
91
|
+
continue
|
|
92
|
+
|
|
93
|
+
rel = src_file.relative_to(src)
|
|
94
|
+
if (str(rel) in excludes) or (filter_ and filter_(src_file)):
|
|
95
|
+
continue
|
|
96
|
+
|
|
97
|
+
dst_file = dst / rel
|
|
98
|
+
if dst_file.exists():
|
|
99
|
+
raise RuntimeError(f"Failed to copy file {rel}: file exists")
|
|
100
|
+
dst_file.parent.mkdir(parents=True, exist_ok=True)
|
|
101
|
+
shutil.copy2(src_file, dst_file)
|
|
102
|
+
|
|
103
|
+
def apply(self, dst: Path, /) -> bool:
|
|
104
|
+
total = []
|
|
105
|
+
for patch in self.__patches.rglob("*.patch"):
|
|
106
|
+
rel_patch = patch.relative_to(self.__patches)
|
|
107
|
+
total.append(rel_patch)
|
|
108
|
+
|
|
109
|
+
rel_dst = rel_patch.with_suffix("") # foo.py.patch -> foo.py
|
|
110
|
+
dst_file = dst / rel_dst
|
|
111
|
+
dst_file.parent.mkdir(parents=True, exist_ok=True)
|
|
112
|
+
|
|
113
|
+
res = subprocess.run(
|
|
114
|
+
["patch", "--unified", str(dst_file), str(patch)],
|
|
115
|
+
capture_output=True,
|
|
116
|
+
text=True,
|
|
117
|
+
)
|
|
118
|
+
if res.returncode != 0:
|
|
119
|
+
print(f"Failed to apply {rel_patch}:\n\t"
|
|
120
|
+
+ "\n\t".join(res.stdout.splitlines()))
|
|
121
|
+
break
|
|
122
|
+
else:
|
|
123
|
+
print(f"Successfully applied {len(total)} patches")
|
|
124
|
+
return True
|
|
125
|
+
return False
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from ._patch import PatcherBuildHook
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from typing import override
|
|
2
|
+
|
|
3
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
4
|
+
|
|
5
|
+
import shutil
|
|
6
|
+
|
|
7
|
+
from makepatch._config import PatcherConfig
|
|
8
|
+
from makepatch.core import PatchApplier
|
|
9
|
+
|
|
10
|
+
if __debug__ and __import__("typing").TYPE_CHECKING:
|
|
11
|
+
from typing import Any, Final
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PatcherBuildHook(BuildHookInterface):
|
|
15
|
+
PLUGIN_NAME = "makepatch"
|
|
16
|
+
|
|
17
|
+
def __init__(self, /, *args, **kwargs):
|
|
18
|
+
super().__init__(*args, **kwargs)
|
|
19
|
+
self.__config: Final = PatcherConfig.from_hatch(self)
|
|
20
|
+
self.__patcher: Final = PatchApplier(self.__config)
|
|
21
|
+
|
|
22
|
+
@override
|
|
23
|
+
def initialize(self, version: str, build_data: dict[str, Any]) -> None:
|
|
24
|
+
config = self.__config
|
|
25
|
+
patcher = self.__patcher
|
|
26
|
+
|
|
27
|
+
if patcher.setup_required():
|
|
28
|
+
patcher.resolve_sources()
|
|
29
|
+
patcher.resolve_src()
|
|
30
|
+
|
|
31
|
+
dst = config.project_root / "work/patched"
|
|
32
|
+
if dst.exists():
|
|
33
|
+
if not dst.is_dir(): raise RuntimeError(f"{dst} is not a directory")
|
|
34
|
+
shutil.rmtree(dst)
|
|
35
|
+
dst.mkdir(parents=True)
|
|
36
|
+
|
|
37
|
+
patcher.copy(dst)
|
|
38
|
+
patcher.apply(dst / config.module_source)
|
|
39
|
+
self.__success = False
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
patcher.resolve_src()
|
|
43
|
+
|
|
44
|
+
dst = self.__dst = config.project_root / "src" / config.module_name
|
|
45
|
+
if dst.exists():
|
|
46
|
+
if not dst.is_dir(): raise RuntimeError(f"{dst} is not a directory")
|
|
47
|
+
shutil.rmtree(dst)
|
|
48
|
+
dst.mkdir(parents=True)
|
|
49
|
+
|
|
50
|
+
patcher.copy(dst)
|
|
51
|
+
self.__success = patcher.apply(dst)
|
|
52
|
+
|
|
53
|
+
@override
|
|
54
|
+
def finalize(self, version: str, build_data: dict[str, Any], artifact_path: str) -> None:
|
|
55
|
+
if not self.__success:
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
if not self.__dst.exists() or not self.__dst.is_dir():
|
|
59
|
+
raise RuntimeError(f"{self.__dst} does not exists or is not a directory")
|
|
60
|
+
shutil.rmtree(self.__dst)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from makepatch._config import PatcherConfig
|
|
5
|
+
from makepatch.core import PatchApplier
|
|
6
|
+
|
|
7
|
+
if __debug__ and __import__("typing").TYPE_CHECKING:
|
|
8
|
+
from typing import Final
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from ._rebuild import rebuild_patches
|
|
12
|
+
|
|
13
|
+
def init_patches():
|
|
14
|
+
root: Final = Path(__import__("os").getcwd())
|
|
15
|
+
config: Final = PatcherConfig.from_pyproject(root)
|
|
16
|
+
patcher: Final = PatchApplier(config)
|
|
17
|
+
|
|
18
|
+
patcher.resolve_sources()
|
|
19
|
+
patcher.resolve_src()
|
|
20
|
+
|
|
21
|
+
dst = root / "work" / "patched"
|
|
22
|
+
if dst.exists():
|
|
23
|
+
if not dst.is_dir(): raise RuntimeError(f"{dst} is not a directory")
|
|
24
|
+
shutil.rmtree(dst)
|
|
25
|
+
dst.mkdir(parents=True)
|
|
26
|
+
|
|
27
|
+
patcher.copy(dst)
|
|
28
|
+
exit(not patcher.apply(dst / config.module_source))
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from makepatch._config import PatcherConfig
|
|
8
|
+
|
|
9
|
+
if __debug__ and __import__("typing").TYPE_CHECKING:
|
|
10
|
+
from typing import Final
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def rebuild_patches():
|
|
14
|
+
TIMESTAMP = re.compile(r"\t\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{9} \+\d{4}")
|
|
15
|
+
ARGS = (
|
|
16
|
+
"--ignore-trailing-space",
|
|
17
|
+
"--strip-trailing-cr",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
root: Final = Path(os.getcwd())
|
|
21
|
+
config: Final = PatcherConfig.from_pyproject(root)
|
|
22
|
+
|
|
23
|
+
ref = root / "work/sources" / config.module_source
|
|
24
|
+
if not ref.exists() or not ref.is_dir():
|
|
25
|
+
raise RuntimeError(f"{ref} does not exists or is not a directory")
|
|
26
|
+
|
|
27
|
+
src = root / "work/patched" / config.module_source
|
|
28
|
+
if not ref.exists() or not ref.is_dir():
|
|
29
|
+
raise RuntimeError(f"{ref} does not exists or is not a directory")
|
|
30
|
+
|
|
31
|
+
patches = root / "patches"
|
|
32
|
+
if patches.exists():
|
|
33
|
+
if not patches.is_dir(): raise RuntimeError(f"{patches} is not a directory")
|
|
34
|
+
__import__("shutil").rmtree(patches)
|
|
35
|
+
patches.mkdir(parents=True)
|
|
36
|
+
|
|
37
|
+
excludes = set()
|
|
38
|
+
for glob in config.excludes:
|
|
39
|
+
dirname = glob.split(os.sep, 1)[0]
|
|
40
|
+
for excluded in src.rglob(glob):
|
|
41
|
+
if (rel_str := str(excluded.relative_to(src))).startswith(dirname):
|
|
42
|
+
excludes.add(rel_str)
|
|
43
|
+
|
|
44
|
+
generated = []
|
|
45
|
+
for target_file in sorted(src.rglob("*")):
|
|
46
|
+
if not target_file.is_file(): continue
|
|
47
|
+
if target_file.suffix == "pyc": continue
|
|
48
|
+
if (target_file.parent.name.startswith("__") and
|
|
49
|
+
target_file.parent.name.endswith("__")):
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
rel_file = target_file.relative_to(src)
|
|
53
|
+
if str(rel_file) in excludes: continue
|
|
54
|
+
|
|
55
|
+
edited = target_file.relative_to(root)
|
|
56
|
+
origin = (ref / rel_file).relative_to(root)
|
|
57
|
+
|
|
58
|
+
result = subprocess.run(
|
|
59
|
+
("diff", "--unified", *ARGS, "--new-file", str(origin), str(edited)),
|
|
60
|
+
capture_output=True,
|
|
61
|
+
text=True,
|
|
62
|
+
)
|
|
63
|
+
if result.returncode == 0:
|
|
64
|
+
continue
|
|
65
|
+
elif result.returncode != 1:
|
|
66
|
+
raise RuntimeError(f"Failed to generate a patch file for {edited} (return code {result.returncode}):"
|
|
67
|
+
f"\n{result.stderr}")
|
|
68
|
+
else:
|
|
69
|
+
patch = patches / rel_file.with_suffix(rel_file.suffix + ".patch")
|
|
70
|
+
patch.parent.mkdir(parents=True, exist_ok=True)
|
|
71
|
+
with open(patch, "x") as f:
|
|
72
|
+
l = result.stdout.splitlines(keepends=True)
|
|
73
|
+
l[0] = TIMESTAMP.sub("", l[0])
|
|
74
|
+
l[1] = TIMESTAMP.sub("", l[1])
|
|
75
|
+
f.write(''.join(l))
|
|
76
|
+
generated.append(patch)
|
|
77
|
+
else:
|
|
78
|
+
print(f"Successfully generated {len(generated)} patches")
|
makepatch-0.2.1/uv.lock
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 3
|
|
3
|
+
requires-python = ">=3.12"
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "annotated-types"
|
|
7
|
+
version = "0.7.0"
|
|
8
|
+
source = { registry = "https://pypi.org/simple" }
|
|
9
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" }
|
|
10
|
+
wheels = [
|
|
11
|
+
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[[package]]
|
|
15
|
+
name = "hatchling"
|
|
16
|
+
version = "1.29.0"
|
|
17
|
+
source = { registry = "https://pypi.org/simple" }
|
|
18
|
+
dependencies = [
|
|
19
|
+
{ name = "packaging" },
|
|
20
|
+
{ name = "pathspec" },
|
|
21
|
+
{ name = "pluggy" },
|
|
22
|
+
{ name = "trove-classifiers" },
|
|
23
|
+
]
|
|
24
|
+
sdist = { url = "https://files.pythonhosted.org/packages/cf/9c/b4cfe330cd4f49cff17fd771154730555fa4123beb7f292cf0098b4e6c20/hatchling-1.29.0.tar.gz", hash = "sha256:793c31816d952cee405b83488ce001c719f325d9cda69f1fc4cd750527640ea6", size = 55656, upload-time = "2026-02-23T19:42:06.539Z" }
|
|
25
|
+
wheels = [
|
|
26
|
+
{ url = "https://files.pythonhosted.org/packages/d3/8a/44032265776062a89171285ede55a0bdaadc8ac00f27f0512a71a9e3e1c8/hatchling-1.29.0-py3-none-any.whl", hash = "sha256:50af9343281f34785fab12da82e445ed987a6efb34fd8c2fc0f6e6630dbcc1b0", size = 76356, upload-time = "2026-02-23T19:42:05.197Z" },
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[[package]]
|
|
30
|
+
name = "makepatch"
|
|
31
|
+
version = "0.1.7"
|
|
32
|
+
source = { editable = "." }
|
|
33
|
+
dependencies = [
|
|
34
|
+
{ name = "hatchling" },
|
|
35
|
+
{ name = "pydantic" },
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[package.metadata]
|
|
39
|
+
requires-dist = [
|
|
40
|
+
{ name = "hatchling", specifier = ">=1.29.0" },
|
|
41
|
+
{ name = "pydantic", specifier = ">=2.13.4" },
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[package.metadata.requires-dev]
|
|
45
|
+
dev = []
|
|
46
|
+
|
|
47
|
+
[[package]]
|
|
48
|
+
name = "packaging"
|
|
49
|
+
version = "26.2"
|
|
50
|
+
source = { registry = "https://pypi.org/simple" }
|
|
51
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d7/f1/e7a6dd94a8d4a5626c03e4e99c87f241ba9e350cd9e6d75123f992427270/packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661", size = 228134, upload-time = "2026-04-24T20:15:23.917Z" }
|
|
52
|
+
wheels = [
|
|
53
|
+
{ url = "https://files.pythonhosted.org/packages/df/b2/87e62e8c3e2f4b32e5fe99e0b86d576da1312593b39f47d8ceef365e95ed/packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", size = 100195, upload-time = "2026-04-24T20:15:22.081Z" },
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[[package]]
|
|
57
|
+
name = "pathspec"
|
|
58
|
+
version = "1.1.1"
|
|
59
|
+
source = { registry = "https://pypi.org/simple" }
|
|
60
|
+
sdist = { url = "https://files.pythonhosted.org/packages/5a/82/42f767fc1c1143d6fd36efb827202a2d997a375e160a71eb2888a925aac1/pathspec-1.1.1.tar.gz", hash = "sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a", size = 135180, upload-time = "2026-04-27T01:46:08.907Z" }
|
|
61
|
+
wheels = [
|
|
62
|
+
{ url = "https://files.pythonhosted.org/packages/f1/d9/7fb5aa316bc299258e68c73ba3bddbc499654a07f151cba08f6153988714/pathspec-1.1.1-py3-none-any.whl", hash = "sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189", size = 57328, upload-time = "2026-04-27T01:46:07.06Z" },
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[[package]]
|
|
66
|
+
name = "pluggy"
|
|
67
|
+
version = "1.6.0"
|
|
68
|
+
source = { registry = "https://pypi.org/simple" }
|
|
69
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
|
|
70
|
+
wheels = [
|
|
71
|
+
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
[[package]]
|
|
75
|
+
name = "pydantic"
|
|
76
|
+
version = "2.13.4"
|
|
77
|
+
source = { registry = "https://pypi.org/simple" }
|
|
78
|
+
dependencies = [
|
|
79
|
+
{ name = "annotated-types" },
|
|
80
|
+
{ name = "pydantic-core" },
|
|
81
|
+
{ name = "typing-extensions" },
|
|
82
|
+
{ name = "typing-inspection" },
|
|
83
|
+
]
|
|
84
|
+
sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" }
|
|
85
|
+
wheels = [
|
|
86
|
+
{ url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" },
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
[[package]]
|
|
90
|
+
name = "pydantic-core"
|
|
91
|
+
version = "2.46.4"
|
|
92
|
+
source = { registry = "https://pypi.org/simple" }
|
|
93
|
+
dependencies = [
|
|
94
|
+
{ name = "typing-extensions" },
|
|
95
|
+
]
|
|
96
|
+
sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" }
|
|
97
|
+
wheels = [
|
|
98
|
+
{ url = "https://files.pythonhosted.org/packages/ce/8c/af022f0af448d7747c5154288d46b5f2bc5f17366eaa0e23e9aa04d59f3b/pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2", size = 2106158, upload-time = "2026-05-06T13:38:57.215Z" },
|
|
99
|
+
{ url = "https://files.pythonhosted.org/packages/19/95/6195171e385007300f0f5574592e467c568becce2d937a0b6804f218bc49/pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f", size = 1951724, upload-time = "2026-05-06T13:37:02.697Z" },
|
|
100
|
+
{ url = "https://files.pythonhosted.org/packages/8e/bc/f47d1ff9cbb1620e1b5b697eef06010035735f07820180e74178226b27b3/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7", size = 1975742, upload-time = "2026-05-06T13:37:09.448Z" },
|
|
101
|
+
{ url = "https://files.pythonhosted.org/packages/5b/11/9b9a5b0306345664a2da6410877af6e8082481b5884b3ddd78d47c6013ce/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7", size = 2052418, upload-time = "2026-05-06T13:37:38.234Z" },
|
|
102
|
+
{ url = "https://files.pythonhosted.org/packages/f1/b7/a65fec226f5d78fc39f4a13c4cc0c768c22b113438f60c14adc9d2865038/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712", size = 2232274, upload-time = "2026-05-06T13:38:27.753Z" },
|
|
103
|
+
{ url = "https://files.pythonhosted.org/packages/68/f0/92039db98b907ef49269a8271f67db9cb78ae2fc68062ef7e4e77adb5f61/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4", size = 2309940, upload-time = "2026-05-06T13:38:05.353Z" },
|
|
104
|
+
{ url = "https://files.pythonhosted.org/packages/5f/97/2aab507d3d00ca626e8e57c1eac6a79e4e5fbcc63eb99733ff55d1717f65/pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce", size = 2094516, upload-time = "2026-05-06T13:39:10.577Z" },
|
|
105
|
+
{ url = "https://files.pythonhosted.org/packages/22/37/a8aca44d40d737dde2bc05b3c6c07dff0de07ce6f82e9f3167aeaf4d5dea/pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987", size = 2136854, upload-time = "2026-05-06T13:40:22.59Z" },
|
|
106
|
+
{ url = "https://files.pythonhosted.org/packages/24/99/fcef1b79238c06a8cbec70819ac722ba76e02bc8ada9b0fd66eba40da01b/pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b", size = 2180306, upload-time = "2026-05-06T13:40:10.666Z" },
|
|
107
|
+
{ url = "https://files.pythonhosted.org/packages/ae/6c/fc44000918855b42779d007ae63b0532794739027b2f417321cddbc44f6a/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458", size = 2190044, upload-time = "2026-05-06T13:40:43.231Z" },
|
|
108
|
+
{ url = "https://files.pythonhosted.org/packages/6b/65/d9cadc9f1920d7a127ad2edba16c1db7916e59719285cd6c94600b0080ba/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b", size = 2329133, upload-time = "2026-05-06T13:39:57.365Z" },
|
|
109
|
+
{ url = "https://files.pythonhosted.org/packages/d0/cf/c873d91679f3a30bcf5e7ac280ce5573483e72295307685120d0d5ad3416/pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c", size = 2374464, upload-time = "2026-05-06T13:38:06.976Z" },
|
|
110
|
+
{ url = "https://files.pythonhosted.org/packages/47/bd/6f2fc8188f31bf10590f1e98e7b306336161fac930a8c514cd7bd828c7dc/pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894", size = 1974823, upload-time = "2026-05-06T13:40:47.985Z" },
|
|
111
|
+
{ url = "https://files.pythonhosted.org/packages/40/8c/985c1d41ea1107c2534abd9870e4ed5c8e7669b5c308297835c001e7a1c4/pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89", size = 2072919, upload-time = "2026-05-06T13:39:21.153Z" },
|
|
112
|
+
{ url = "https://files.pythonhosted.org/packages/c4/ba/f463d006e0c47373ca7ec5e1a261c59dc01ef4d62b2657af925fb0deee3a/pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a", size = 2027604, upload-time = "2026-05-06T13:39:03.753Z" },
|
|
113
|
+
{ url = "https://files.pythonhosted.org/packages/51/a2/5d30b469c5267a17b39dec53208222f76a8d351dfac4af661888c5aee77d/pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008", size = 2106306, upload-time = "2026-05-06T13:37:48.029Z" },
|
|
114
|
+
{ url = "https://files.pythonhosted.org/packages/c1/81/4fa520eaffa8bd7d1525e644cd6d39e7d60b1592bc5b516693c7340b50f1/pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4", size = 1951906, upload-time = "2026-05-06T13:37:17.012Z" },
|
|
115
|
+
{ url = "https://files.pythonhosted.org/packages/03/d5/fd02da45b659668b05923b17ba3a0100a0a3d5541e3bd8fcc4ecb711309e/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76", size = 1976802, upload-time = "2026-05-06T13:37:35.113Z" },
|
|
116
|
+
{ url = "https://files.pythonhosted.org/packages/21/f2/95727e1368be3d3ed485eaab7adbd7dda408f33f7a36e8b48e0144002b91/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3", size = 2052446, upload-time = "2026-05-06T13:37:12.313Z" },
|
|
117
|
+
{ url = "https://files.pythonhosted.org/packages/9c/86/5d99feea3f77c7234b8718075b23db11532773c1a0dbd9b9490215dc2eeb/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76", size = 2232757, upload-time = "2026-05-06T13:39:01.149Z" },
|
|
118
|
+
{ url = "https://files.pythonhosted.org/packages/d2/3a/508ac615935ef7588cf6d9e9b91309fdc2da751af865e02a9098de88258c/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4", size = 2309275, upload-time = "2026-05-06T13:37:41.406Z" },
|
|
119
|
+
{ url = "https://files.pythonhosted.org/packages/07/f8/41db9de19d7987d6b04715a02b3b40aea467000275d9d758ffaa31af7d50/pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a", size = 2094467, upload-time = "2026-05-06T13:39:18.847Z" },
|
|
120
|
+
{ url = "https://files.pythonhosted.org/packages/2c/e2/f35033184cb11d0052daf4416e8e10a502ea2ac006fc4f459aee872727d1/pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262", size = 2134417, upload-time = "2026-05-06T13:40:17.944Z" },
|
|
121
|
+
{ url = "https://files.pythonhosted.org/packages/7e/7b/6ceeb1cc90e193862f444ebe373d8fdf613f0a82572dde03fb10734c6c71/pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e", size = 2179782, upload-time = "2026-05-06T13:40:32.618Z" },
|
|
122
|
+
{ url = "https://files.pythonhosted.org/packages/5a/f2/c8d7773ede6af08036423a00ae0ceffce266c3c52a096c435d68c896083f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd", size = 2188782, upload-time = "2026-05-06T13:36:51.018Z" },
|
|
123
|
+
{ url = "https://files.pythonhosted.org/packages/59/31/0c864784e31f09f05cdd87606f08923b9c9e7f6e51dd27f20f62f975ce9f/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be", size = 2328334, upload-time = "2026-05-06T13:40:37.764Z" },
|
|
124
|
+
{ url = "https://files.pythonhosted.org/packages/c2/eb/4f6c8a41efa30baa755590f4141abf3a8c370fab610915733e74134a7270/pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d", size = 2372986, upload-time = "2026-05-06T13:39:34.152Z" },
|
|
125
|
+
{ url = "https://files.pythonhosted.org/packages/5b/24/b375a480d53113860c299764bfe9f349a3dc9108b3adc0d7f0d786492ebf/pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb", size = 1973693, upload-time = "2026-05-06T13:37:55.072Z" },
|
|
126
|
+
{ url = "https://files.pythonhosted.org/packages/7e/e8/cff247591966f2d22ec8c003cd7587e27b7ba7b81ab2fb888e3ab75dc285/pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292", size = 2071819, upload-time = "2026-05-06T13:38:49.139Z" },
|
|
127
|
+
{ url = "https://files.pythonhosted.org/packages/c6/1a/f4aee670d5670e9e148e0c82c7db98d780be566c6e6a97ee8035528ca0b3/pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d", size = 2027411, upload-time = "2026-05-06T13:40:45.796Z" },
|
|
128
|
+
{ url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" },
|
|
129
|
+
{ url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" },
|
|
130
|
+
{ url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" },
|
|
131
|
+
{ url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" },
|
|
132
|
+
{ url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" },
|
|
133
|
+
{ url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" },
|
|
134
|
+
{ url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" },
|
|
135
|
+
{ url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" },
|
|
136
|
+
{ url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" },
|
|
137
|
+
{ url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" },
|
|
138
|
+
{ url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" },
|
|
139
|
+
{ url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" },
|
|
140
|
+
{ url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" },
|
|
141
|
+
{ url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" },
|
|
142
|
+
{ url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" },
|
|
143
|
+
{ url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" },
|
|
144
|
+
{ url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" },
|
|
145
|
+
{ url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" },
|
|
146
|
+
{ url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" },
|
|
147
|
+
{ url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" },
|
|
148
|
+
{ url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" },
|
|
149
|
+
{ url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" },
|
|
150
|
+
{ url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" },
|
|
151
|
+
{ url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" },
|
|
152
|
+
{ url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" },
|
|
153
|
+
{ url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" },
|
|
154
|
+
{ url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" },
|
|
155
|
+
{ url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" },
|
|
156
|
+
{ url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" },
|
|
157
|
+
{ url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" },
|
|
158
|
+
{ url = "https://files.pythonhosted.org/packages/9d/1d/8987ad40f65ae1432753072f214fb5c74fe47ffbd0698bb9cbbb585664f8/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7", size = 2095527, upload-time = "2026-05-06T13:39:52.283Z" },
|
|
159
|
+
{ url = "https://files.pythonhosted.org/packages/64/d3/84c282a7eee1d3ac4c0377546ef5a1ea436ce26840d9ac3b7ed54a377507/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df", size = 1936024, upload-time = "2026-05-06T13:40:15.671Z" },
|
|
160
|
+
{ url = "https://files.pythonhosted.org/packages/d7/ca/eac61596cdeb4d7e174d3dc0bd8a6238f14f75f97a24e7b7db4c7e7340a0/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526", size = 1990696, upload-time = "2026-05-06T13:38:34.717Z" },
|
|
161
|
+
{ url = "https://files.pythonhosted.org/packages/fa/c3/7c8b240552251faf6b3a957db200fcfbbcec36763c050428b601e0c9b83b/pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0", size = 2147590, upload-time = "2026-05-06T13:39:29.883Z" },
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
[[package]]
|
|
165
|
+
name = "trove-classifiers"
|
|
166
|
+
version = "2026.5.7.17"
|
|
167
|
+
source = { registry = "https://pypi.org/simple" }
|
|
168
|
+
sdist = { url = "https://files.pythonhosted.org/packages/35/68/175e7c07c5be13200387d5c0995b0da1e198e360047c08eb17d1002fcd92/trove_classifiers-2026.5.7.17.tar.gz", hash = "sha256:a04a48f8f0a787cb996514d3969ac7608aa3c60cb15d073c1e02801e60533e80", size = 17041, upload-time = "2026-05-07T17:48:01.931Z" }
|
|
169
|
+
wheels = [
|
|
170
|
+
{ url = "https://files.pythonhosted.org/packages/7b/e3/d81b065a2d866a33a541ac63a2a4cc5737e03ce2379ac3191c98bb8867e3/trove_classifiers-2026.5.7.17-py3-none-any.whl", hash = "sha256:5ec0800de5e2ddbd7c663cb4c0c15328f132dc168813897c18866c5c7b93db33", size = 14201, upload-time = "2026-05-07T17:48:00.488Z" },
|
|
171
|
+
]
|
|
172
|
+
|
|
173
|
+
[[package]]
|
|
174
|
+
name = "typing-extensions"
|
|
175
|
+
version = "4.15.0"
|
|
176
|
+
source = { registry = "https://pypi.org/simple" }
|
|
177
|
+
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
|
178
|
+
wheels = [
|
|
179
|
+
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
[[package]]
|
|
183
|
+
name = "typing-inspection"
|
|
184
|
+
version = "0.4.2"
|
|
185
|
+
source = { registry = "https://pypi.org/simple" }
|
|
186
|
+
dependencies = [
|
|
187
|
+
{ name = "typing-extensions" },
|
|
188
|
+
]
|
|
189
|
+
sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
|
|
190
|
+
wheels = [
|
|
191
|
+
{ url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" },
|
|
192
|
+
]
|
makepatch-0.0.1/PKG-INFO
DELETED
makepatch-0.0.1/pyproject.toml
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
[project]
|
|
2
|
-
name = "makepatch"
|
|
3
|
-
version = "0.0.1"
|
|
4
|
-
description = "Hatch build hook to easily hard-fork packages with patches!"
|
|
5
|
-
requires-python = ">=3.12"
|
|
6
|
-
classifiers = [
|
|
7
|
-
"Framework :: Hatch",
|
|
8
|
-
]
|
|
9
|
-
dependencies = [
|
|
10
|
-
"hatchling>=1.29.0",
|
|
11
|
-
"pydantic>=2.13.4",
|
|
12
|
-
]
|
|
13
|
-
|
|
14
|
-
[dependency-groups]
|
|
15
|
-
dev = []
|
|
16
|
-
|
|
17
|
-
[build-system]
|
|
18
|
-
build-backend = "uv_build"
|
|
19
|
-
requires = ["uv_build>=0.11.14,<0.12"]
|
|
20
|
-
|
|
21
|
-
[project.entry-points.hatch]
|
|
22
|
-
makepatch = "makepatch.__hook__"
|
|
23
|
-
|
|
24
|
-
[project.scripts]
|
|
25
|
-
init = "makepatch.scripts:init"
|
|
26
|
-
rebuild-patches = "makepatch.scripts:rebuild_patches"
|
|
File without changes
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
from collections.abc import Iterable
|
|
2
|
-
from typing import final, Annotated
|
|
3
|
-
|
|
4
|
-
from pydantic import BaseModel, Field
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
__config = None
|
|
8
|
-
|
|
9
|
-
@final
|
|
10
|
-
class ClippyConfig(BaseModel):
|
|
11
|
-
module_source: Annotated[str, Field(alias="module-source")]
|
|
12
|
-
excludes: Annotated[Iterable[str], Field(default_factory=frozenset)]
|
|
13
|
-
dev_excludes: Annotated[Iterable[str], Field(alias="module-source", default_factory=frozenset)]
|
|
14
|
-
|
|
15
|
-
def __init__(self, /):
|
|
16
|
-
global __config
|
|
17
|
-
if __config:
|
|
18
|
-
raise RuntimeError("Configuration already initialized")
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from ._patch import ClippyPatchHook
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
from typing import override
|
|
4
|
-
|
|
5
|
-
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
6
|
-
|
|
7
|
-
import shutil, subprocess, tomllib
|
|
8
|
-
|
|
9
|
-
if __debug__ and __import__("typing").TYPE_CHECKING:
|
|
10
|
-
from typing import Any
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class ClippyPatchHook(BuildHookInterface):
|
|
14
|
-
@property
|
|
15
|
-
def __root(self):
|
|
16
|
-
return Path(self.root)
|
|
17
|
-
|
|
18
|
-
@property
|
|
19
|
-
def __config(self):
|
|
20
|
-
with open(self.__root / "pyproject.toml", "rb") as f:
|
|
21
|
-
pyproject = tomllib.load(f)
|
|
22
|
-
|
|
23
|
-
try:
|
|
24
|
-
config = pyproject["tool"]["patcher"]
|
|
25
|
-
except KeyError as e:
|
|
26
|
-
raise RuntimeError("[tool.patcher] not found in pyproject.toml") from e
|
|
27
|
-
return config["module-source"], frozenset(config.get("excludes", set()))
|
|
28
|
-
|
|
29
|
-
@override
|
|
30
|
-
def initialize(self, version: str, build_data: dict[str, Any]) -> None:
|
|
31
|
-
module_name, exclude_globs = self.__config
|
|
32
|
-
|
|
33
|
-
src = self.__root / "work" / "sources" / module_name
|
|
34
|
-
if not src.exists(): raise RuntimeError(f"{src} not exists")
|
|
35
|
-
elif not src.is_dir(): raise RuntimeError(f"{src} is not a directory")
|
|
36
|
-
|
|
37
|
-
excludes = set()
|
|
38
|
-
for glob in exclude_globs:
|
|
39
|
-
excludes |= set(str(excluded.relative_to(src)) for excluded in src.rglob(glob) if str(excluded.relative_to(src)).startswith(glob.split(os.sep)[0]))
|
|
40
|
-
|
|
41
|
-
patches = self.__root / "patches"
|
|
42
|
-
if not patches.exists(): raise RuntimeError(f"{patches} not exists")
|
|
43
|
-
elif not patches.is_dir(): raise RuntimeError(f"{patches} is not a directory")
|
|
44
|
-
|
|
45
|
-
if str(module_name).startswith("src"):
|
|
46
|
-
module_name = module_name[4:]
|
|
47
|
-
dst = self.__root / "src" / module_name
|
|
48
|
-
if dst.exists():
|
|
49
|
-
if not dst.is_dir(): raise RuntimeError(f"{dst} is not a directory")
|
|
50
|
-
shutil.rmtree(dst)
|
|
51
|
-
dst.mkdir(parents=True)
|
|
52
|
-
|
|
53
|
-
# Copy sources, skipping excludes
|
|
54
|
-
for src_file in src.rglob("*"):
|
|
55
|
-
if not src_file.is_file(): continue
|
|
56
|
-
|
|
57
|
-
rel = src_file.relative_to(src)
|
|
58
|
-
if str(rel) in excludes: continue
|
|
59
|
-
|
|
60
|
-
dst_file = dst / rel
|
|
61
|
-
dst_file.parent.mkdir(parents=True, exist_ok=True)
|
|
62
|
-
shutil.copy2(src_file, dst_file)
|
|
63
|
-
|
|
64
|
-
# Apply patches
|
|
65
|
-
for patch_file in sorted(patches.rglob("*.patch")):
|
|
66
|
-
rel_patch = patch_file.relative_to(patches)
|
|
67
|
-
# e.g. foo.py.patch → foo.py
|
|
68
|
-
target_rel = rel_patch.with_suffix("")
|
|
69
|
-
target = dst / target_rel
|
|
70
|
-
|
|
71
|
-
if not target.parent.exists():
|
|
72
|
-
target.parent.mkdir(parents=True, exist_ok=False)
|
|
73
|
-
|
|
74
|
-
result = subprocess.run(
|
|
75
|
-
["patch", "--unified", str(target), str(patch_file)],
|
|
76
|
-
capture_output=True,
|
|
77
|
-
text=True,
|
|
78
|
-
)
|
|
79
|
-
if result.returncode != 0:
|
|
80
|
-
raise RuntimeError(f"Failed to apply {rel_patch}:\n{result.stderr}")
|
|
81
|
-
|
|
82
|
-
def finalize(self, version: str, build_data: dict[str, Any], artifact_path: str) -> None:
|
|
83
|
-
module_source, _ = self.__config
|
|
84
|
-
if str(module_source).startswith("src"):
|
|
85
|
-
module_source = module_source[4:]
|
|
86
|
-
dst = self.__root / "src" / module_source
|
|
87
|
-
if dst.exists():
|
|
88
|
-
shutil.rmtree(dst)
|
|
File without changes
|