patch-package-py 0.1.0__tar.gz → 0.1.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patch-package-py
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: patch 3rd party Python packages
5
5
  Project-URL: Homepage, https://github.com/nomyfan/patch-package-py
6
6
  Project-URL: Repository, https://github.com/nomyfan/patch-package-py
@@ -62,10 +62,7 @@ def cmd_apply(args):
62
62
  site_packages_dir = find_site_packages(Path.cwd() / ".venv")
63
63
 
64
64
  if not patches_dir.exists():
65
- logger.error(
66
- f"Error: Patches directory {patches_dir} does not exist",
67
- )
68
- sys.exit(1)
65
+ return
69
66
 
70
67
  if not site_packages_dir.exists():
71
68
  logger.error(
@@ -79,15 +76,8 @@ def cmd_apply(args):
79
76
  logger.info(f"No patch files found in {patches_dir}")
80
77
  return
81
78
 
82
- success_count = 0
83
79
  for patch_file in patch_files:
84
- try:
85
- apply_patch(patch_file, site_packages_dir)
86
- success_count += 1
87
- except Exception as e:
88
- logger.error(f"✗ Failed to apply {patch_file.name}: {e}")
89
-
90
- logger.info(f"Applied {success_count}/{len(patch_files)} patches successfully")
80
+ apply_patch(patch_file, site_packages_dir)
91
81
 
92
82
 
93
83
  def cli():
@@ -32,6 +32,11 @@ class Resolver:
32
32
  self, venv: Path, package_name: str
33
33
  ) -> tuple[PurePosixPath, str] | None:
34
34
  site_packages_path = find_site_packages(venv)
35
+ return self.resolve_in_site_packages(site_packages_path, package_name)
36
+
37
+ def resolve_in_site_packages(
38
+ self, site_packages_path: Path, package_name: str
39
+ ) -> tuple[PurePosixPath, str] | None:
35
40
  dist_info = list(
36
41
  site_packages_path.glob(f"{package_name.replace('-', '_')}-*.dist-info")
37
42
  )
@@ -90,12 +95,10 @@ def prepare_patch_workspace(
90
95
  venv_path = temp_dir / "venv"
91
96
 
92
97
  # Create venv with uv using current Python version
93
- subprocess.run(
94
- ["uv", "venv", str(venv_path), "--python", sys.executable], check=True
95
- )
98
+ subprocess.check_call(["uv", "venv", str(venv_path), "--python", sys.executable])
96
99
 
97
100
  # Install the package without dependencies using uv
98
- subprocess.run(
101
+ subprocess.check_call(
99
102
  [
100
103
  "uv",
101
104
  "pip",
@@ -107,7 +110,6 @@ def prepare_patch_workspace(
107
110
  venv_path / ("Scripts/python.exe" if os.name == "nt" else "bin/python")
108
111
  ),
109
112
  ],
110
- check=True,
111
113
  cwd=temp_dir,
112
114
  )
113
115
 
@@ -145,14 +147,19 @@ def prepare_patch_workspace(
145
147
  f,
146
148
  indent=2,
147
149
  )
148
- subprocess.run(["git", "init"], cwd=git_path, check=True, capture_output=True)
149
- subprocess.run(
150
+ subprocess.check_call(
151
+ ["git", "init"],
152
+ cwd=git_path,
153
+ stderr=subprocess.DEVNULL,
154
+ stdout=subprocess.DEVNULL,
155
+ )
156
+ subprocess.check_call(
150
157
  ["git", "add", "."],
151
158
  cwd=git_path,
152
- check=True,
153
- capture_output=True,
159
+ stderr=subprocess.DEVNULL,
160
+ stdout=subprocess.DEVNULL,
154
161
  )
155
- subprocess.run(
162
+ subprocess.check_call(
156
163
  [
157
164
  "git",
158
165
  "commit",
@@ -161,8 +168,8 @@ def prepare_patch_workspace(
161
168
  f"Initial commit of {package_name}=={version}",
162
169
  ],
163
170
  cwd=git_path,
164
- check=True,
165
- capture_output=True,
171
+ stderr=subprocess.DEVNULL,
172
+ stdout=subprocess.DEVNULL,
166
173
  )
167
174
 
168
175
  logger.info(
@@ -171,15 +178,12 @@ def prepare_patch_workspace(
171
178
 
172
179
 
173
180
  def commit_changes(package_name: str, version: str, site_packages_path: Path) -> None:
174
- diff_proc = subprocess.run(
181
+ diff_content = subprocess.check_output(
175
182
  ["git", "diff", "--relative"],
176
183
  cwd=site_packages_path,
177
- check=True,
178
- capture_output=True,
179
184
  text=True,
180
185
  )
181
186
 
182
- diff_content = diff_proc.stdout
183
187
  if not diff_content:
184
188
  logger.info("No changes detected, nothing to commit.")
185
189
  return
@@ -190,8 +194,9 @@ def commit_changes(package_name: str, version: str, site_packages_path: Path) ->
190
194
  with open(patch_file_path, "w") as f:
191
195
  f.write(diff_content)
192
196
 
197
+ current_site_packages = find_site_packages(Path.cwd() / ".venv")
193
198
  try:
194
- apply_patch(patch_file_path, site_packages_path)
199
+ apply_patch(patch_file_path, current_site_packages)
195
200
  except subprocess.CalledProcessError:
196
201
  logger.error(
197
202
  f"Error: failed to apply the patch after creation. There's maybe a conflict, you can try to reinstall the package and apply the patch manually via `{CLI_NAME} apply {patch_file_name}`"
@@ -201,9 +206,33 @@ def commit_changes(package_name: str, version: str, site_packages_path: Path) ->
201
206
 
202
207
 
203
208
  def apply_patch(patch_file: Path, site_packages_dir: Path) -> None:
209
+ # Parse package name and version from patch file name
210
+ patch_name = patch_file.stem # Remove .patch extension
211
+ if "+" not in patch_name:
212
+ raise ValueError(
213
+ f"Invalid patch file name format: {patch_file.name}. Expected format: package_name+version.patch"
214
+ )
215
+
216
+ package_name, version = patch_name.rsplit("+", 1)
217
+
218
+ # Verify the package exists in site_packages_dir with matching version
219
+ resolver = Resolver()
220
+ result = resolver.resolve_in_site_packages(site_packages_dir, package_name)
221
+ if result is None:
222
+ logger.warning(
223
+ f"Package '{package_name}' not found in site-packages directory, skipping..."
224
+ )
225
+ return
226
+
227
+ _, installed_version = result
228
+ if installed_version != version:
229
+ raise ValueError(
230
+ f"Version mismatch: patch is for {package_name}=={version} but installed version is {installed_version}"
231
+ )
232
+
204
233
  # First, check if the patch is already applied using dry-run
205
234
  try:
206
- subprocess.run(
235
+ subprocess.check_call(
207
236
  [
208
237
  "patch",
209
238
  "-p1",
@@ -214,17 +243,17 @@ def apply_patch(patch_file: Path, site_packages_dir: Path) -> None:
214
243
  str(patch_file.absolute()),
215
244
  ],
216
245
  cwd=site_packages_dir,
217
- check=True,
218
- capture_output=True,
246
+ stderr=subprocess.DEVNULL,
247
+ stdout=subprocess.DEVNULL,
219
248
  )
220
249
  except subprocess.CalledProcessError:
221
250
  logger.warning(
222
- f"Patch `{patch_file.stem}` appears to be already applied, skipping...",
251
+ f"Patch `{patch_name}` appears to be already applied, skipping...",
223
252
  )
224
253
  return
225
254
 
226
255
  # If dry-run succeeds, apply the patch for real
227
- subprocess.run(
256
+ subprocess.check_call(
228
257
  [
229
258
  "patch",
230
259
  "-p1",
@@ -234,5 +263,4 @@ def apply_patch(patch_file: Path, site_packages_dir: Path) -> None:
234
263
  str(patch_file.absolute()),
235
264
  ],
236
265
  cwd=site_packages_dir,
237
- check=True,
238
266
  )
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "patch-package-py"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  description = "patch 3rd party Python packages"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"
@@ -13,7 +13,7 @@ wheels = [
13
13
 
14
14
  [[package]]
15
15
  name = "patch-package-py"
16
- version = "0.1.0"
16
+ version = "0.1.2"
17
17
  source = { editable = "." }
18
18
 
19
19
  [package.dev-dependencies]