2525DEFAULT_TAG  =  "3.14" 
2626
2727
28+ # TODO: Remove the /dev/ for stable release 
29+ HELP_URL  =  "https://docs.python.org/dev/using/windows" 
30+ 
31+ 
2832COPYRIGHT  =  f"""Python installation manager { __version__ }  
2933Copyright (c) Python Software Foundation. All Rights Reserved. 
3034""" 
3135
3236
37+ if  EXE_NAME .casefold () ==  "py-manager" .casefold ():
38+     EXE_NAME  =  "py" 
39+ 
40+ 
3341WELCOME  =  f"""!B!Python install manager was successfully updated to { __version__ }  .!W! 
3442""" 
3543
@@ -188,6 +196,7 @@ def execute(self):
188196        "enable-shortcut-kinds" : ("enable_shortcut_kinds" , _NEXT , config_split ),
189197        "disable-shortcut-kinds" : ("disable_shortcut_kinds" , _NEXT , config_split ),
190198        "help" : ("show_help" , True ), # nested to avoid conflict with command 
199+         "configure" : ("configure" , True ),
191200        # Set when the manager is doing an automatic install. 
192201        # Generally won't be set by manual invocation 
193202        "automatic" : ("automatic" , True ),
@@ -202,6 +211,10 @@ def execute(self):
202211        "force" : ("confirm" , False ),
203212        "help" : ("show_help" , True ), # nested to avoid conflict with command 
204213    },
214+ 
215+     "**first_run" : {
216+         "explicit" : ("explicit" , True ),
217+     },
205218}
206219
207220
@@ -240,6 +253,16 @@ def execute(self):
240253        "disable_shortcut_kinds" : (str , config_split_append ),
241254    },
242255
256+     "first_run" : {
257+         "enabled" : (config_bool , None , "env" ),
258+         "explicit" : (config_bool , None ),
259+         "check_app_alias" : (config_bool , None , "env" ),
260+         "check_long_paths" : (config_bool , None , "env" ),
261+         "check_py_on_path" : (config_bool , None , "env" ),
262+         "check_any_install" : (config_bool , None , "env" ),
263+         "check_global_dir" : (config_bool , None , "env" ),
264+     },
265+ 
243266    # These configuration settings are intended for administrative override only 
244267    # For example, if you are managing deployments that will use your own index 
245268    # and/or your own builds. 
@@ -419,11 +442,11 @@ def __init__(self, args, root=None):
419442        # If our command has any config, load them to override anything that 
420443        # wasn't set on the command line. 
421444        try :
422-             cmd_config  =  config [self .CMD ]
445+             cmd_config  =  config [self .CMD . lstrip ( "*" ) ]
423446        except  (AttributeError , LookupError ):
424447            pass 
425448        else :
426-             arg_names  =  frozenset (CONFIG_SCHEMA [self .CMD ])
449+             arg_names  =  frozenset (CONFIG_SCHEMA [self .CMD . lstrip ( "*" ) ])
427450            for  k , v  in  cmd_config .items ():
428451                if  k  in  arg_names  and  k  not  in   _set_args :
429452                    LOGGER .debug ("Overriding command option %s with %r" , k , v )
@@ -511,7 +534,7 @@ def get_log_file(self):
511534            logs_dir  =  Path (os .getenv ("TMP" ) or  os .getenv ("TEMP" ) or  os .getcwd ())
512535        from  _native  import  datetime_as_str 
513536        self ._log_file  =  logs_dir  /  "python_{}_{}_{}.log" .format (
514-             self .CMD , datetime_as_str (), os .getpid ()
537+             self .CMD . strip ( "*" ) , datetime_as_str (), os .getpid ()
515538        )
516539        return  self ._log_file 
517540
@@ -545,28 +568,13 @@ def show_usage(cls):
545568        if  usage_ljust  %  4 :
546569            usage_ljust  +=  4  -  (usage_ljust  %  4 )
547570        usage_ljust  =  max (usage_ljust , 16 ) +  1 
548-         sp  =  " "  *  usage_ljust 
549571
550572        LOGGER .print ("!G!Usage:!W!" )
551573        for  k , d  in  usage_docs :
552-             if  k .endswith ("\n " ) and  len (logging .strip_colour (k )) >=  usage_ljust :
553-                 LOGGER .print (k .rstrip ())
554-                 r  =  sp 
555-             else :
556-                 k  =  k .rstrip ()
557-                 r  =  k .ljust (usage_ljust  +  len (k ) -  len (logging .strip_colour (k )))
558-             for  b  in  d .split (" " ):
559-                 if  len (r ) >=  logging .CONSOLE_MAX_WIDTH :
560-                     LOGGER .print (r .rstrip ())
561-                     r  =  sp 
562-                 r  +=  b  +  " " 
563-             if  r .rstrip ():
564-                 LOGGER .print (r )
565- 
566-         LOGGER .print ()
567-         # TODO: Remove the /dev/ for stable release 
568-         LOGGER .print ("Find additional information at !B!https://docs.python.org/dev/using/windows!W!." )
569-         LOGGER .print ()
574+             for  s  in  logging .wrap_and_indent (d , indent = usage_ljust , hang = k .rstrip ()):
575+                 LOGGER .print (s )
576+ 
577+         LOGGER .print ("\n Find additional information at !B!%s!W!.\n " , HELP_URL )
570578
571579    @classmethod  
572580    def  help_text (cls ):
@@ -746,6 +754,7 @@ class InstallCommand(BaseCommand):
746754    -u, --update     Overwrite existing install if a newer version is available. 
747755    --dry-run        Choose runtime but do not install 
748756    --refresh        Update shortcuts and aliases for all installed versions. 
757+     --configure      Re-run the system configuration helper. 
749758    --by-id          Require TAG to exactly match the install ID. (For advanced use.) 
750759    !B!<TAG> <TAG>!W! ...  One or more tags to install (Company\Tag format) 
751760
@@ -775,6 +784,7 @@ class InstallCommand(BaseCommand):
775784    dry_run  =  False 
776785    refresh  =  False 
777786    by_id  =  False 
787+     configure  =  False 
778788    automatic  =  False 
779789    from_script  =  None 
780790    enable_shortcut_kinds  =  None 
@@ -801,9 +811,13 @@ def __init__(self, args, root=None):
801811            self .download  =  Path (self .download ).absolute ()
802812
803813    def  execute (self ):
804-         from  .install_command  import  execute 
805814        self .show_welcome ()
806-         execute (self )
815+         if  self .configure :
816+             cmd  =  FirstRun (["**first_run" , "--explicit" ], self .root )
817+             cmd .execute ()
818+         else :
819+             from  .install_command  import  execute 
820+             execute (self )
807821
808822
809823class  UninstallCommand (BaseCommand ):
@@ -867,6 +881,7 @@ class HelpCommand(BaseCommand):
867881""" 
868882
869883    _create_log_file  =  False 
884+     commands_only  =  False 
870885
871886    def  __init__ (self , args , root = None ):
872887        super ().__init__ ([self .CMD ], root )
@@ -891,7 +906,7 @@ def execute(self):
891906
892907
893908class  HelpWithErrorCommand (HelpCommand ):
894-     CMD  =  "__help_with_error " 
909+     CMD  =  "**help_with_error " 
895910
896911    def  __init__ (self , args , root = None ):
897912        # Essentially disable argument processing for this command 
@@ -945,6 +960,28 @@ def __init__(self, root):
945960        super ().__init__ ([], root )
946961
947962
963+ class  FirstRun (BaseCommand ):
964+     CMD  =  "**first_run" 
965+     enabled  =  True 
966+     explicit  =  False 
967+     check_app_alias  =  True 
968+     check_long_paths  =  True 
969+     check_py_on_path  =  True 
970+     check_any_install  =  True 
971+     check_global_dir  =  True 
972+ 
973+     def  execute (self ):
974+         if  not  self .enabled :
975+             return 
976+         from  .firstrun  import  first_run 
977+         first_run (self )
978+         if  not  self .explicit :
979+             self .show_usage ()
980+             if  self .confirm  and  not  self .ask_ny ("View online help?" ):
981+                 import  os 
982+                 os .startfile (HELP_URL )
983+ 
984+ 
948985def  load_default_config (root ):
949986    return  DefaultConfig (root )
950987
0 commit comments