22import argparse
33import os
44import re
5+ import urllib .request
56import sys
67
78
@@ -530,6 +531,11 @@ def walk(self, paths):
530531 self .warning ("Path %s does not exist" % path )
531532 self .exitcode = 1
532533
534+ def get_latest_header (self , base_dir ):
535+ target = os .path .join (base_dir , PYTHONCAPI_COMPAT_H )
536+ self .log (f"Download the file from { PYTHONCAPI_COMPAT_URL } to { target } ." )
537+ urllib .request .urlretrieve (PYTHONCAPI_COMPAT_URL , target )
538+
533539 @staticmethod
534540 def usage (parser ):
535541 parser .print_help ()
@@ -543,6 +549,12 @@ def usage(parser):
543549 print ("If a directory is passed, search for .c and .h files "
544550 "in subdirectories." )
545551
552+ def _parse_dir_path (self , path ):
553+ if os .path .isdir (path ):
554+ return path
555+ else :
556+ raise argparse .ArgumentTypeError (f"{ path } is not a valid path" )
557+
546558 def _parse_options (self , args ):
547559 parser = argparse .ArgumentParser (
548560 description = "Upgrade C extension modules to newer Python C API" )
@@ -563,11 +575,15 @@ def _parse_options(self, args):
563575 parser .add_argument (
564576 '-C' , '--no-compat' , action = "store_true" ,
565577 help = f"Don't add: { INCLUDE_PYTHONCAPI_COMPAT } " )
578+ parser .add_argument (
579+ '-d' , '--download' , metavar = 'PATH' ,
580+ help = f'Download latest pythoncapi_compat.h file to designated PATH' ,
581+ type = self ._parse_dir_path )
566582 parser .add_argument (
567583 metavar = 'file_or_directory' , dest = "paths" , nargs = '*' )
568584
569585 args = parser .parse_args (args )
570- if not args .paths :
586+ if not args .paths and not args . download :
571587 self .usage (parser )
572588 sys .exit (1 )
573589
@@ -578,15 +594,19 @@ def _parse_options(self, args):
578594 self .operations = self ._get_operations (parser )
579595
580596 def main (self ):
581- for filename in self .walk (self .args .paths ):
582- self .patch_file (filename )
597+ if self .args .paths :
598+ for filename in self .walk (self .args .paths ):
599+ self .patch_file (filename )
600+
601+ if self .args .download :
602+ path = self .args .download
603+ self .get_latest_header (path )
583604
584605 if self .pythoncapi_compat_added and not self .args .quiet :
585606 self .log ()
586607 self .log (f"{ INCLUDE_PYTHONCAPI_COMPAT } added: you may have "
587- f"to copy { PYTHONCAPI_COMPAT_H } to your project" )
588- self .log ("It can be copied from:" )
589- self .log (PYTHONCAPI_COMPAT_URL )
608+ f"to copy { PYTHONCAPI_COMPAT_H } to your project" )
609+ self .log ("Run 'python upgrade_pythoncapi.py --download <target_path>'" )
590610
591611 sys .exit (self .exitcode )
592612
0 commit comments