diff --git a/CONSTRUCT.md b/CONSTRUCT.md index 3605ca40..8efc797b 100644 --- a/CONSTRUCT.md +++ b/CONSTRUCT.md @@ -468,6 +468,13 @@ _type:_ string
If `header_image` is not provided, use this text when generating the image (Windows only). Defaults to `name`. +## `initialize_conda` + +_required:_ no
+_type:_ boolean
+Add an option to the installer so the user can choose whether to run `conda init` +after the install. See also `initialize_by_default`. + ## `initialize_by_default` _required:_ no
@@ -476,6 +483,13 @@ Whether to add the installation to the PATH environment variable. The default is true for GUI installers (msi, pkg) and False for shell installers. The user is able to change the default during interactive installation. +## `register_python` + +_required:_ no
+_type:_ boolean
+Whether to offer the user an option to register the installed Python instance as the +system's default Python. (Windows only) + ## `register_python_default` _required:_ no
diff --git a/constructor/construct.py b/constructor/construct.py index 67ba94b3..3420992f 100644 --- a/constructor/construct.py +++ b/constructor/construct.py @@ -370,12 +370,22 @@ ('header_image_text', False, str, ''' If `header_image` is not provided, use this text when generating the image (Windows only). Defaults to `name`. +'''), + + ('initialize_conda', False, bool, ''' +Add an option to the installer so the user can choose whether to run `conda init` +after the install. See also `initialize_by_default`. '''), ('initialize_by_default', False, bool, ''' Whether to add the installation to the PATH environment variable. The default is true for GUI installers (msi, pkg) and False for shell installers. The user is able to change the default during interactive installation. +'''), + + ('register_python', False, bool, ''' +Whether to offer the user an option to register the installed Python instance as the +system's default Python. (Windows only) '''), ('register_python_default', False, bool, ''' diff --git a/constructor/header.sh b/constructor/header.sh index 6d78b6ff..987563be 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -575,13 +575,14 @@ if [ "$PYTHONPATH" != "" ]; then fi if [ "$BATCH" = "0" ]; then -#if initialize_by_default is True +#if initialize_conda is True and initialize_by_default is True DEFAULT=yes -#else +#endif +#if initialize_conda is True and initialize_by_default is False DEFAULT=no #endif -#if has_conda +#if has_conda and initialize_conda is True # Interactive mode. printf "Do you wish the installer to initialize __NAME__\\n" diff --git a/constructor/nsis/OptionsDialog.nsh b/constructor/nsis/OptionsDialog.nsh index c75788eb..a0e0086d 100644 --- a/constructor/nsis/OptionsDialog.nsh +++ b/constructor/nsis/OptionsDialog.nsh @@ -70,50 +70,65 @@ Function mui_AnaCustomOptions_Show Pop $mui_AnaCustomOptions.CreateShortcuts ${NSD_SetState} $mui_AnaCustomOptions.CreateShortcuts $Ana_CreateShortcuts_State ${NSD_OnClick} $mui_AnaCustomOptions.CreateShortcuts CreateShortcuts_OnClick - - ${If} $InstMode = ${JUST_ME} - StrCpy $1 "my" - ${Else} - StrCpy $1 "the system" + + # We will use $5 as the y axis accumulator, starting at 12u + IntOp $5 0 + 12 + + ${If} "${SHOW_ADD_TO_PATH}" == "yes" + ${If} $InstMode = ${JUST_ME} + StrCpy $1 "my" + ${Else} + StrCpy $1 "the system" + ${EndIf} + ${NSD_CreateCheckbox} 0 "$5u" 100% 11u "Add ${NAME} to $1 &PATH environment variable" + Pop $mui_AnaCustomOptions.AddToPath + ${NSD_SetState} $mui_AnaCustomOptions.AddToPath $Ana_AddToPath_State + ${NSD_OnClick} $mui_AnaCustomOptions.AddToPath AddToPath_OnClick + IntOp $5 $5 + 12 + ${NSD_CreateLabel} 5% "$5u" 90% 29u \ + "NOT recommended; adding ${NAME} to the PATH can lead to conflicts with other \ + applications. Instead, use the Commmand Prompt and Powershell menus added to the \ + $\"Anaconda${PYVERSION_MAJOR} (${ARCH})$\" folder of the Windows Start Menu." + Pop $Ana_AddToPath_Label + # add offset + IntOp $5 $5 + 29 ${EndIf} - ${NSD_CreateCheckbox} 0 12u 100% 11u "Add ${NAME} to $1 &PATH environment variable" - Pop $mui_AnaCustomOptions.AddToPath - ${NSD_SetState} $mui_AnaCustomOptions.AddToPath $Ana_AddToPath_State - ${NSD_OnClick} $mui_AnaCustomOptions.AddToPath AddToPath_OnClick - ${NSD_CreateLabel} 5% 24u 90% 29u \ - "NOT recommended; adding ${NAME} to the PATH can lead to conflicts with other \ - applications. Instead, use the Commmand Prompt and Powershell menus added to the \ - $\"Anaconda${PYVERSION_MAJOR} (${ARCH})$\" folder of the Windows Start Menu." - Pop $Ana_AddToPath_Label - - ${If} $InstMode = ${JUST_ME} - StrCpy $1 "my default" - ${Else} - StrCpy $1 "the system" + + ${If} "${SHOW_REGISTER_PYTHON}" == "yes" + ${If} $InstMode = ${JUST_ME} + StrCpy $1 "my default" + ${Else} + StrCpy $1 "the system" + ${EndIf} + ${NSD_CreateCheckbox} 0 "$5u" 100% 11u "&Register ${NAME} as $1 Python ${PY_VER}" + Pop $mui_AnaCustomOptions.RegisterSystemPython + ${NSD_SetState} $mui_AnaCustomOptions.RegisterSystemPython $Ana_RegisterSystemPython_State + ${NSD_OnClick} $mui_AnaCustomOptions.RegisterSystemPython RegisterSystemPython_OnClick + IntOp $5 $5 + 12 + ${NSD_CreateLabel} 5% "$5u" 90% 20u \ + "Recommended. Allows other programs, such as VSCode, PyCharm, etc. to automatically \ + detect ${NAME} as the primary Python ${PY_VER} on the system." + IntOp $5 $5 + 20 + Pop $Ana_RegisterSystemPython_Label ${EndIf} - ${NSD_CreateCheckbox} 0 53u 100% 11u "&Register ${NAME} as $1 Python ${PY_VER}" - Pop $mui_AnaCustomOptions.RegisterSystemPython - ${NSD_SetState} $mui_AnaCustomOptions.RegisterSystemPython $Ana_RegisterSystemPython_State - ${NSD_OnClick} $mui_AnaCustomOptions.RegisterSystemPython RegisterSystemPython_OnClick - ${NSD_CreateLabel} 5% 65u 90% 20u \ - "Recommended. Allows other programs, such as VSCode, PyCharm, etc. to automatically \ - detect ${NAME} as the primary Python ${PY_VER} on the system." - Pop $Ana_RegisterSystemPython_Label - - ${NSD_CreateCheckbox} 0 85u 100% 11u "Clear the package cache upon completion" + + + ${NSD_CreateCheckbox} 0 "$5u" 100% 11u "Clear the package cache upon completion" Pop $mui_AnaCustomOptions.ClearPkgCache ${NSD_SetState} $mui_AnaCustomOptions.ClearPkgCache $Ana_ClearPkgCache_State ${NSD_OnClick} $mui_AnaCustomOptions.ClearPkgCache ClearPkgCache_OnClick - ${NSD_CreateLabel} 5% 97u 90% 11u \ + IntOp $5 $5 + 11 + ${NSD_CreateLabel} 5% "$5u" 90% 11u \ "Recommended. Recovers some disk space without harming functionality." Pop $Ana_ClearPkgCache_Label ${If} "${POST_INSTALL_DESC}" != "" - ${NSD_CreateCheckbox} 0 108u 100% 11u "Run the post-install script" + ${NSD_CreateCheckbox} 0 "$5u" 100% 11u "Run the post-install script" Pop $mui_AnaCustomOptions.PostInstall ${NSD_SetState} $mui_AnaCustomOptions.PostInstall $Ana_PostInstall_State ${NSD_OnClick} $mui_AnaCustomOptions.PostInstall PostInstall_OnClick - ${NSD_CreateLabel} 5% 120u 90% 20u "Recommended. ${POST_INSTALL_DESC}" + IntOp $5 $5 + 12 + ${NSD_CreateLabel} 5% "$5u" 90% 20u "Recommended. ${POST_INSTALL_DESC}" Pop $Ana_PostInstall_Label ${EndIf} diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index 444f515c..49d657c0 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -55,6 +55,8 @@ Unicode "true" !define DEFAULT_PREFIX_ALL_USERS __DEFAULT_PREFIX_ALL_USERS__ !define POST_INSTALL_DESC __POST_INSTALL_DESC__ !define MENU_PKGS "@MENU_PKGS@" +!define SHOW_REGISTER_PYTHON __SHOW_REGISTER_PYTHON__ +!define SHOW_ADD_TO_PATH __SHOW_ADD_TO_PATH__ !define PRODUCT_NAME "${NAME} ${VERSION} (${ARCH})" !define UNINSTALL_NAME "@UNINSTALL_NAME@" !define UNINSTREG "SOFTWARE\Microsoft\Windows\CurrentVersion\ @@ -583,16 +585,16 @@ Function .onInit Call mui_AnaCustomOptions_InitDefaults # Override custom options with explicitly given values from contruct.yaml. # If initialize_by_default (register_python_default) is None, do nothing. -#if initialize_by_default is True +#if initialize_conda is True and initialize_by_default is True StrCpy $Ana_AddToPath_State ${BST_CHECKED} #endif -#if initialize_by_default is False +#if initialize_conda is True and initialize_by_default is False StrCpy $Ana_AddToPath_State ${BST_UNCHECKED} #endif -#if register_python_default is True +#if register_python is True and register_python_default is True StrCpy $Ana_RegisterSystemPython_State ${BST_CHECKED} #endif -#if register_python_default is False +#if register_python is True and register_python_default is False StrCpy $Ana_RegisterSystemPython_State ${BST_UNCHECKED} #endif #if check_path_length is True diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py index c432c48e..f57f931b 100644 --- a/constructor/osxpkg.py +++ b/constructor/osxpkg.py @@ -404,11 +404,13 @@ def create(info, verbose=False): pkgbuild_script('postinstall', info, abspath(info['post_install'])) names.append('postinstall') # The script to run conda init - pkgbuild_script('pathupdate', info, 'update_path.sh') - names.append('pathupdate') + if info.get('initialize_conda', True): + pkgbuild_script('pathupdate', info, 'update_path.sh') + names.append('pathupdate') # The script to clear the package cache - pkgbuild_script('cacheclean', info, 'clean_cache.sh') - names.append('cacheclean') + if not info.get('keep_pkgs'): + pkgbuild_script('cacheclean', info, 'clean_cache.sh') + names.append('cacheclean') # The default distribution file needs to be modified, so we create # it to a temporary location, edit it, and supply it to the final call. diff --git a/constructor/shar.py b/constructor/shar.py index 438cd3c3..27627feb 100644 --- a/constructor/shar.py +++ b/constructor/shar.py @@ -56,6 +56,7 @@ def get_header(conda_exec, tarball, info): ppd['has_%s' % key] = bool(key in info) if key in info: ppd['direct_execute_%s' % key] = has_shebang(info[key]) + ppd['initialize_conda'] = info.get('initialize_conda', True) ppd['initialize_by_default'] = info.get('initialize_by_default', None) ppd['has_conda'] = info['_has_conda'] install_lines = list(add_condarc(info)) diff --git a/constructor/winexe.py b/constructor/winexe.py index 429febbc..d4bb667c 100644 --- a/constructor/winexe.py +++ b/constructor/winexe.py @@ -159,6 +159,8 @@ def make_nsi(info, dir_path, extra_files=()): join('%ALLUSERSPROFILE%', name.lower())), 'POST_INSTALL_DESC': info['post_install_desc'], + 'SHOW_REGISTER_PYTHON': "yes" if info.get("register_python", True) else "no", + 'SHOW_ADD_TO_PATH': "yes" if info.get("initialize_conda", True) else "no", 'OUTFILE': info['_outpath'], 'VIPV': make_VIProductVersion(info['version']), 'ICONFILE': '@icon.ico', @@ -190,7 +192,9 @@ def make_nsi(info, dir_path, extra_files=()): data = read_nsi_tmpl(info) ppd = ns_platform(info['_platform']) + ppd['initialize_conda'] = info.get('initialize_conda', True) ppd['initialize_by_default'] = info.get('initialize_by_default', None) + ppd['register_python'] = info.get('register_python', True) ppd['register_python_default'] = info.get('register_python_default', None) ppd['check_path_length'] = info.get('check_path_length', None) ppd['check_path_spaces'] = info.get('check_path_spaces', True) diff --git a/examples/customize_controls/construct.yaml b/examples/customize_controls/construct.yaml new file mode 100644 index 00000000..d7c0eea8 --- /dev/null +++ b/examples/customize_controls/construct.yaml @@ -0,0 +1,13 @@ +name: NoCondaOptions +version: X +installer_type: all + +channels: + - http://repo.anaconda.com/pkgs/main/ + +specs: + - python + - conda + +register_python: False +initialize_conda: False diff --git a/tests/test_header.py b/tests/test_header.py index 46604d49..9d972056 100644 --- a/tests/test_header.py +++ b/tests/test_header.py @@ -9,12 +9,13 @@ @pytest.mark.parametrize('keep_pkgs', [False, True]) @pytest.mark.parametrize('has_conda', [False, True]) @pytest.mark.parametrize('has_license', [False, True]) +@pytest.mark.parametrize('initialize_conda', [False, True]) @pytest.mark.parametrize('initialize_by_default', [False, True]) @pytest.mark.parametrize('has_post_install', [False, True]) @pytest.mark.parametrize('has_pre_install', [False, True]) @pytest.mark.parametrize('arch', ['x86', 'x86_64', ' ppc64le', 's390x', 'aarch64']) def test_linux_template_processing( - osx, arch, has_pre_install, has_post_install, + osx, arch, has_pre_install, has_post_install, initialize_conda, initialize_by_default, has_license, has_conda, keep_pkgs, batch_mode, direct_execute_pre_install, direct_execute_post_install): template = read_header_template() @@ -34,6 +35,7 @@ def test_linux_template_processing( 'direct_execute_pre_install': direct_execute_pre_install, 'has_post_install': has_post_install, 'direct_execute_post_install': direct_execute_post_install, + 'initialize_conda': initialize_conda, 'initialize_by_default': initialize_by_default, }) assert '#if' not in processed