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,17 @@ 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_default_tag" : (config_bool , None , "env" ),
264+ "check_global_dir" : (config_bool , None , "env" ),
265+ },
266+
243267 # These configuration settings are intended for administrative override only
244268 # For example, if you are managing deployments that will use your own index
245269 # and/or your own builds.
@@ -419,11 +443,11 @@ def __init__(self, args, root=None):
419443 # If our command has any config, load them to override anything that
420444 # wasn't set on the command line.
421445 try :
422- cmd_config = config [self .CMD ]
446+ cmd_config = config [self .CMD . lstrip ( "*" ) ]
423447 except (AttributeError , LookupError ):
424448 pass
425449 else :
426- arg_names = frozenset (CONFIG_SCHEMA [self .CMD ])
450+ arg_names = frozenset (CONFIG_SCHEMA [self .CMD . lstrip ( "*" ) ])
427451 for k , v in cmd_config .items ():
428452 if k in arg_names and k not in _set_args :
429453 LOGGER .debug ("Overriding command option %s with %r" , k , v )
@@ -511,7 +535,7 @@ def get_log_file(self):
511535 logs_dir = Path (os .getenv ("TMP" ) or os .getenv ("TEMP" ) or os .getcwd ())
512536 from _native import datetime_as_str
513537 self ._log_file = logs_dir / "python_{}_{}_{}.log" .format (
514- self .CMD , datetime_as_str (), os .getpid ()
538+ self .CMD . strip ( "*" ) , datetime_as_str (), os .getpid ()
515539 )
516540 return self ._log_file
517541
@@ -564,8 +588,7 @@ def show_usage(cls):
564588 LOGGER .print (r )
565589
566590 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!." )
591+ LOGGER .print ("Find additional information at !B!%s!W!." , HELP_URL )
569592 LOGGER .print ()
570593
571594 @classmethod
@@ -746,6 +769,7 @@ class InstallCommand(BaseCommand):
746769 -u, --update Overwrite existing install if a newer version is available.
747770 --dry-run Choose runtime but do not install
748771 --refresh Update shortcuts and aliases for all installed versions.
772+ --configure Re-run the system configuration helper.
749773 --by-id Require TAG to exactly match the install ID. (For advanced use.)
750774 !B!<TAG> <TAG>!W! ... One or more tags to install (Company\Tag format)
751775
@@ -775,6 +799,7 @@ class InstallCommand(BaseCommand):
775799 dry_run = False
776800 refresh = False
777801 by_id = False
802+ configure = False
778803 automatic = False
779804 from_script = None
780805 enable_shortcut_kinds = None
@@ -801,9 +826,13 @@ def __init__(self, args, root=None):
801826 self .download = Path (self .download ).absolute ()
802827
803828 def execute (self ):
804- from .install_command import execute
805829 self .show_welcome ()
806- execute (self )
830+ if self .configure :
831+ cmd = FirstRun (["**first_run" , "--explicit" ], self .root )
832+ cmd .execute ()
833+ else :
834+ from .install_command import execute
835+ execute (self )
807836
808837
809838class UninstallCommand (BaseCommand ):
@@ -891,7 +920,7 @@ def execute(self):
891920
892921
893922class HelpWithErrorCommand (HelpCommand ):
894- CMD = "__help_with_error "
923+ CMD = "**help_with_error "
895924
896925 def __init__ (self , args , root = None ):
897926 # Essentially disable argument processing for this command
@@ -945,6 +974,29 @@ def __init__(self, root):
945974 super ().__init__ ([], root )
946975
947976
977+ class FirstRun (BaseCommand ):
978+ CMD = "**first_run"
979+ enabled = True
980+ explicit = False
981+ check_app_alias = True
982+ check_long_paths = True
983+ check_py_on_path = True
984+ check_any_install = True
985+ check_default_tag = True
986+ check_global_dir = True
987+
988+ def execute (self ):
989+ if not self .enabled :
990+ return
991+ from .firstrun import first_run
992+ first_run (self )
993+ if not self .explicit :
994+ show_help ([])
995+ if self .confirm and not self .ask_ny (f"View more help online? (!B!{ HELP_URL } !W!)" ):
996+ import os
997+ os .startfile (HELP_URL )
998+
999+
9481000def load_default_config (root ):
9491001 return DefaultConfig (root )
9501002
0 commit comments