22__doc__ = """
33This tool helps with updating test files from CPython.
44
5+ Quick Upgrade
6+ -------------
7+ ./{fname} --quick-upgrade cpython/Lib/test/test_threading.py
8+ ./{fname} --quick-upgrade ../somewhere/Lib/threading.py
9+
10+ Any path containing `/Lib/` will auto-detect the target:
11+ -> Extracts patches from Lib/... (auto-detected from path)
12+ -> Applies them to the source file
13+ -> Writes result to Lib/...
14+
515Examples
616--------
7- To move the patches found in `Lib/test/foo.py` to ` ~/cpython/Lib/test/foo.py` then write the contents back to `Lib/test/foo.py`
17+ To move the patches found in `Lib/test/foo.py` to `~/cpython/Lib/test/foo.py` then write the contents back to `Lib/test/foo.py`
818
919>>> ./{fname} --from Lib/test/foo.py --to ~/cpython/Lib/test/foo.py -o Lib/test/foo.py
1020
@@ -288,6 +298,12 @@ def build_argparse() -> argparse.ArgumentParser:
288298 )
289299
290300 patches_group = parser .add_mutually_exclusive_group (required = True )
301+ patches_group .add_argument (
302+ "--quick-upgrade" ,
303+ help = "Quick upgrade: path containing /Lib/ (e.g., cpython/Lib/test/foo.py)" ,
304+ type = pathlib .Path ,
305+ metavar = "PATH" ,
306+ )
291307 patches_group .add_argument (
292308 "-p" ,
293309 "--patches" ,
@@ -301,7 +317,7 @@ def build_argparse() -> argparse.ArgumentParser:
301317 type = pathlib .Path ,
302318 )
303319
304- group = parser .add_mutually_exclusive_group (required = True )
320+ group = parser .add_mutually_exclusive_group (required = False )
305321 group .add_argument (
306322 "--to" ,
307323 help = "File to apply patches to" ,
@@ -322,6 +338,28 @@ def build_argparse() -> argparse.ArgumentParser:
322338 parser = build_argparse ()
323339 args = parser .parse_args ()
324340
341+ # Quick upgrade: auto-fill --from, --to, -o from path
342+ if args .quick_upgrade is not None :
343+ path_str = str (args .quick_upgrade )
344+ lib_marker = "/Lib/"
345+
346+ if lib_marker not in path_str :
347+ parser .error (f"--quick-upgrade path must contain '/Lib/' (got: { path_str } )" )
348+
349+ idx = path_str .index (lib_marker )
350+ lib_path = pathlib .Path (path_str [idx + 1 :])
351+
352+ args .gather_from = lib_path
353+ args .to = args .quick_upgrade
354+ if args .output == "-" :
355+ args .output = str (lib_path )
356+
357+ # Validate required arguments
358+ if args .patches is None and args .gather_from is None :
359+ parser .error ("--from or --patches is required (or use --quick-upgrade)" )
360+ if args .to is None and not args .show_patches :
361+ parser .error ("--to or --show-patches is required" )
362+
325363 if args .patches :
326364 patches = {
327365 cls_name : {
0 commit comments