diff --git a/constructor/construct.py b/constructor/construct.py index 210c157c5..9cad94a1e 100644 --- a/constructor/construct.py +++ b/constructor/construct.py @@ -746,10 +746,10 @@ def yamlize(data, directory, content_filter): if ('{{' not in data) and ('{%' not in data): raise UnableToParse(original=e) try: - from constructor.jinja import render_jinja + from constructor.jinja import render_jinja_for_input_file except ImportError as ex: raise UnableToParseMissingJinja2(original=ex) - data = render_jinja(data, directory, content_filter) + data = render_jinja_for_input_file(data, directory, content_filter) return yaml.load(data) diff --git a/constructor/header.sh b/constructor/header.sh index fc7434435..351cbad06 100644 --- a/constructor/header.sh +++ b/constructor/header.sh @@ -1,28 +1,28 @@ #!/bin/sh # -# Created by constructor __CONSTRUCTOR_VERSION__ +# Created by constructor {{ constructor_version }} # -# NAME: __NAME__ -# VER: __VERSION__ -# PLAT: __PLAT__ -# MD5: __MD5__ +# NAME: {{ installer_name }} +# VER: {{ installer_version }} +# PLAT: {{ installer_platform }} +# MD5: {{ installer_md5 }} set -eu -#if osx +{%- if osx %} unset DYLD_LIBRARY_PATH DYLD_FALLBACK_LIBRARY_PATH -#else +{%- else %} export OLD_LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-}" unset LD_LIBRARY_PATH -#endif +{%- endif %} if ! echo "$0" | grep '\.sh$' > /dev/null; then printf 'Please run using "bash"/"dash"/"sh"/"zsh", but not "." or "source".\n' >&2 - return 1 + exit 1 fi -#if osx and min_osx_version -min_osx_version="__MIN_OSX_VERSION__" +{%- if osx and min_osx_version %} +min_osx_version="{{ min_osx_version }}" system_osx_version="${CONDA_OVERRIDE_OSX:-$(SYSTEM_VERSION_COMPAT=0 sw_vers -productVersion)}" # shellcheck disable=SC2183 disable=SC2046 int_min_osx_version="$(printf "%02d%02d%02d" $(echo "$min_osx_version" | sed 's/\./ /g'))" @@ -32,9 +32,8 @@ if [ "$int_system_osx_version" -lt "$int_min_osx_version" ]; then echo "Installer requires macOS >=${min_osx_version}, but system has ${system_osx_version}." exit 1 fi -#endif -#if linux and min_glibc_version -min_glibc_version="__MIN_GLIBC_VERSION__" +{%- elif linux and min_glibc_version %} +min_glibc_version="{{ min_glibc_version }}" system_glibc_version="${CONDA_OVERRIDE_GLIBC:-}" if [ "${system_glibc_version}" = "" ]; then case "$(ldd --version 2>&1)" in @@ -67,36 +66,28 @@ if [ "$int_system_glibc_version" -lt "$int_min_glibc_version" ]; then echo "Installer requires GLIBC >=${min_glibc_version}, but system has ${system_glibc_version}." exit 1 fi -#endif +{%- endif %} # Export variables to make installer metadata available to pre/post install scripts # NOTE: If more vars are added, make sure to update the examples/scripts tests too -_SCRIPT_ENV_VARIABLES_='' # Templated extra environment variable(s) -export INSTALLER_NAME='__NAME__' -export INSTALLER_VER='__VERSION__' -export INSTALLER_PLAT='__PLAT__' +{{ script_env_variables }} +export INSTALLER_NAME='{{ installer_name }}' +export INSTALLER_VER='{{ installer_version }}' +export INSTALLER_PLAT='{{ installer_platform }}' export INSTALLER_TYPE="SH" THIS_DIR=$(DIRNAME=$(dirname "$0"); cd "$DIRNAME"; pwd) THIS_FILE=$(basename "$0") THIS_PATH="$THIS_DIR/$THIS_FILE" -PREFIX="__DEFAULT_PREFIX__" -#if batch_mode -BATCH=1 -#else -BATCH=0 -#endif +PREFIX="{{ default_prefix }}" +BATCH={{ 1 if batch_mode else 0 }} FORCE=0 -#if keep_pkgs -KEEP_PKGS=1 -#else -KEEP_PKGS=0 -#endif +KEEP_PKGS={{ 1 if keep_pkgs else 0 }} SKIP_SCRIPTS=0 -#if enable_shortcuts == "true" +{%- if enable_shortcuts == "true" %} SKIP_SHORTCUTS=0 -#endif +{%- endif %} TEST=0 REINSTALL=0 USAGE=" @@ -104,41 +95,41 @@ usage: $0 [options] Installs ${INSTALLER_NAME} ${INSTALLER_VER} -#if batch_mode +{%- if batch_mode %} -i run install in interactive mode -#else +{%- else %} -b run install in batch mode (without manual intervention), it is expected the license terms (if any) are agreed upon -#endif +{%- endif %} -f no error if install prefix already exists -h print this help message and exit -#if not keep_pkgs +{%- if not keep_pkgs %} -k do not clear the package cache after installation -#endif -#if check_path_spaces +{%- endif %} +{%- if check_path_spaces %} -p PREFIX install prefix, defaults to $PREFIX, must not contain spaces. -#else +{%- else %} -p PREFIX install prefix, defaults to $PREFIX -#endif +{%- endif %} -s skip running pre/post-link/install scripts -#if enable_shortcuts == 'true' +{%- if enable_shortcuts == 'true' %} -m disable the creation of menu items / shortcuts -#endif +{%- endif %} -u update an existing installation -#if has_conda +{%- if has_conda %} -t run package tests after installation (may install conda-build) -#endif +{%- endif %} " # We used to have a getopt version here, falling back to getopts if needed # However getopt is not standardized and the version on Mac has different # behaviour. getopts is good enough for what we need :) # More info: https://unix.stackexchange.com/questions/62950/ -#if enable_shortcuts == "true" +{%- if enable_shortcuts == "true" %} while getopts "bifhkp:smut" x; do -#else +{%- else %} while getopts "bifhkp:sut" x; do -#endif +{%- endif %} case "$x" in h) printf "%s\\n" "$USAGE" @@ -162,19 +153,19 @@ while getopts "bifhkp:sut" x; do s) SKIP_SCRIPTS=1 ;; -#if enable_shortcuts == "true" +{%- if enable_shortcuts == "true" %} m) SKIP_SHORTCUTS=1 ;; -#endif +{%- endif %} u) FORCE=1 ;; -#if has_conda +{%- if has_conda %} t) TEST=1 ;; -#endif +{%- endif %} ?) printf "ERROR: did not recognize option '%s', please try -h\\n" "$x" exit 1 @@ -194,7 +185,7 @@ fi if [ "$BATCH" = "0" ] # interactive mode then -#if x86 and not x86_64 +{%- if x86 and not x86_64 %} if [ "$(uname -m)" = "x86_64" ]; then printf "WARNING:\\n" printf " Your system is x86_64, but you are trying to install an x86 (32-bit)\\n" @@ -212,9 +203,7 @@ then exit 2 fi fi -#endif - -#if x86_64 +{%- elif x86_64 %} if [ "$(uname -m)" != "x86_64" ]; then printf "WARNING:\\n" printf " Your operating system appears not to be 64-bit, but you are trying to\\n" @@ -229,9 +218,7 @@ then exit 2 fi fi -#endif - -#if ppc64le +{%- elif ppc64le %} if [ "$(uname -m)" != "ppc64le" ]; then printf "WARNING:\\n" printf " Your machine hardware does not appear to be Power8 (little endian), \\n" @@ -246,9 +233,7 @@ then exit 2 fi fi -#endif - -#if s390x +{%- elif s390x %} if [ "$(uname -m)" != "s390x" ]; then printf "WARNING:\\n" printf " Your machine hardware does not appear to be s390x (big endian), \\n" @@ -263,9 +248,7 @@ then exit 2 fi fi -#endif - -#if aarch64 +{%- elif aarch64 %} if [ "$(uname -m)" != "aarch64" ]; then printf "WARNING:\\n" printf " Your machine hardware does not appear to be aarch64, \\n" @@ -280,9 +263,9 @@ then exit 2 fi fi -#endif +{%- endif %} -#if osx +{%- if osx %} if [ "$(uname)" != "Darwin" ]; then printf "WARNING:\\n" printf " Your operating system does not appear to be macOS, \\n" @@ -297,9 +280,7 @@ then exit 2 fi fi -#endif - -#if linux +{%- elif linux %} if [ "$(uname)" != "Linux" ]; then printf "WARNING:\\n" printf " Your operating system does not appear to be Linux, \\n" @@ -314,11 +295,11 @@ then exit 2 fi fi -#endif +{%- endif %} printf "\\n" printf "Welcome to %s %s\\n" "${INSTALLER_NAME}" "${INSTALLER_VER}" -#if has_license +{%- if has_license %} printf "\\n" printf "In order to continue the installation process, please review the license\\n" printf "agreement.\\n" @@ -330,7 +311,7 @@ then pager="more" fi "$pager" <<'EOF' -__LICENSE__ +{{ license }} EOF printf "\\n" printf "Do you accept the license terms? [yes|no]\\n" @@ -349,7 +330,7 @@ EOF printf "The license agreement wasn't approved, aborting installation.\\n" exit 2 fi -#endif +{%- endif %} printf "\\n" printf "%s will now be installed into this location:\\n" "${INSTALLER_NAME}" @@ -362,7 +343,7 @@ EOF printf "[%s] >>> " "$PREFIX" read -r user_prefix if [ "$user_prefix" != "" ]; then -#if check_path_spaces is True +{%- if check_path_spaces %} case "$user_prefix" in *\ * ) printf "ERROR: Cannot install into directories with spaces\\n" >&2 @@ -372,20 +353,20 @@ EOF eval PREFIX="$user_prefix" ;; esac -#else +{%- else %} PREFIX="$user_prefix" -#endif +{%- endif %} fi fi # !BATCH -#if check_path_spaces is True +{%- if check_path_spaces %} case "$PREFIX" in *\ * ) printf "ERROR: Cannot install into directories with spaces\\n" >&2 exit 1 ;; esac -#endif +{%- endif %} if [ "$FORCE" = "0" ] && [ -e "$PREFIX" ]; then printf "ERROR: File or directory already exists: '%s'\\n" "$PREFIX" >&2 @@ -395,7 +376,7 @@ elif [ "$FORCE" = "1" ] && [ -e "$PREFIX" ]; then REINSTALL=1 fi -total_installation_size_kb="__TOTAL_INSTALLATION_SIZE_KB__" +total_installation_size_kb="{{ total_installation_size_kb }}" total_installation_size_mb="$(( total_installation_size_kb / 1024 ))" if ! mkdir -p "$PREFIX"; then printf "ERROR: Could not create directory: '%s'.\\n" "$PREFIX" >&2 @@ -445,20 +426,16 @@ last_line=$(grep -anm 1 '^@@END_HEADER@@' "$THIS_PATH" | sed 's/:.*//') # the start of the first payload, in bytes, indexed from zero boundary0=$(head -n "${last_line}" "${THIS_PATH}" | wc -c | sed 's/ //g') # the start of the second payload / the end of the first payload, plus one -boundary1=$(( boundary0 + __FIRST_PAYLOAD_SIZE__ )) +boundary1=$(( boundary0 + {{ first_payload_size }} )) # the end of the second payload, plus one -boundary2=$(( boundary1 + __SECOND_PAYLOAD_SIZE__ )) +boundary2=$(( boundary1 + {{ second_payload_size }} )) # verify the MD5 sum of the tarball appended to this header -#if osx -MD5=$(extract_range "${boundary0}" "${boundary2}" | md5) -#else -MD5=$(extract_range "${boundary0}" "${boundary2}" | md5sum -) -#endif +MD5=$(extract_range "${boundary0}" "${boundary2}" | {{ "md5" if osx else "md5sum -" }}) -if ! echo "$MD5" | grep __MD5__ >/dev/null; then +if ! echo "$MD5" | grep {{ installer_md5 }} >/dev/null; then printf "WARNING: md5sum mismatch of tar archive\\n" >&2 - printf "expected: __MD5__\\n" >&2 + printf "expected: {{ installer_md5 }}\\n" >&2 printf " got: %s\\n" "$MD5" >&2 fi @@ -483,13 +460,13 @@ mkdir -p "$TMP" # micromamba needs an existing pkgs_dir to operate even offline, # but we haven't created $PREFIX/pkgs yet... give it a temp location # shellcheck disable=SC2050 -if [ "__VIRTUAL_SPECS__" != "" ]; then - echo "Checking virtual specs compatibility:" __VIRTUAL_SPECS__ +{%- if virtual_specs %} + echo "Checking virtual specs compatibility:" {{ virtual_specs }} CONDA_QUIET="$BATCH" \ CONDA_SOLVER="classic" \ CONDA_PKGS_DIRS="$(mktemp -d)" \ - "$CONDA_EXEC" create --dry-run --prefix "$PREFIX/envs/_virtual_specs_checks" --offline __VIRTUAL_SPECS__ __NO_RCS_ARG__ -fi + "$CONDA_EXEC" create --dry-run --prefix "$PREFIX/envs/_virtual_specs_checks" --offline {{ virtual_specs }} {{ no_rcs_arg }} +{%- endif %} # Create $PREFIX/.nonadmin if the installation didn't require superuser permissions if [ "$(id -u)" -ne 0 ]; then @@ -498,7 +475,7 @@ fi # the second binary payload: the tarball of packages printf "Unpacking payload ...\n" -extract_range $boundary1 $boundary2 | \ +extract_range "${boundary1}" "${boundary2}" | \ CONDA_QUIET="$BATCH" "$CONDA_EXEC" constructor --extract-tarball --prefix "$PREFIX" PRECONDA="$PREFIX/preconda.tar.bz2" @@ -509,26 +486,22 @@ rm -f "$PRECONDA" CONDA_QUIET="$BATCH" \ "$CONDA_EXEC" constructor --prefix "$PREFIX" --extract-conda-pkgs || exit 1 -#The templating doesn't support nested if statements -#if has_pre_install +{%- if has_pre_install %} if [ "$SKIP_SCRIPTS" = "1" ]; then export INST_OPT='--skip-scripts' printf "WARNING: skipping pre_install.sh by user request\\n" >&2 else export INST_OPT='' -#endif -#if has_pre_install and direct_execute_pre_install + {%- if direct_execute_pre_install %} if ! "$PREFIX/pkgs/pre_install.sh"; then -#endif -#if has_pre_install and not direct_execute_pre_install + {%- else %} if ! sh "$PREFIX/pkgs/pre_install.sh"; then -#endif -#if has_pre_install + {%- endif %} printf "ERROR: executing pre_install.sh failed\\n" >&2 exit 1 fi fi -#endif +{%- endif %} MSGS="$PREFIX/.messages.txt" touch "$MSGS" @@ -544,33 +517,30 @@ test -d ~/.conda || mkdir -p ~/.conda >/dev/null 2>/dev/null || test -d ~/.conda printf "\nInstalling base environment...\n\n" -#if enable_shortcuts == "true" +{%- if enable_shortcuts == "true" %} if [ "$SKIP_SHORTCUTS" = "1" ]; then shortcuts="--no-shortcuts" else - shortcuts="__SHORTCUTS__" + shortcuts="{{ shortcuts }}" fi -#endif -#if enable_shortcuts == "false" +{%- elif enable_shortcuts == "false" %} shortcuts="--no-shortcuts" -#endif -#if enable_shortcuts == "incompatible" +{%- elif enable_shortcuts == "incompatible" %} shortcuts="" -#endif +{%- endif %} # shellcheck disable=SC2086 CONDA_ROOT_PREFIX="$PREFIX" \ -CONDA_REGISTER_ENVS="__REGISTER_ENVS__" \ +CONDA_REGISTER_ENVS="{{ register_envs }}" \ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ -CONDA_CHANNELS="__CHANNELS__" \ +CONDA_CHANNELS="{{ channels }}" \ CONDA_PKGS_DIRS="$PREFIX/pkgs" \ CONDA_QUIET="$BATCH" \ -"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" $shortcuts __NO_RCS_ARG__ || exit 1 +"$CONDA_EXEC" install --offline --file "$PREFIX/pkgs/env.txt" -yp "$PREFIX" $shortcuts {{ no_rcs_arg }} || exit 1 rm -f "$PREFIX/pkgs/env.txt" -#The templating doesn't support nested if statements -#if has_conda +{%- if has_conda %} mkdir -p "$PREFIX/envs" for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do env_name=$(basename "${env_pkgs}") @@ -584,10 +554,9 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do env_channels=$(cat "${env_pkgs}channels.txt") rm -f "${env_pkgs}channels.txt" else - env_channels="__CHANNELS__" + env_channels="{{ channels }}" fi -#endif -#if has_conda and enable_shortcuts == "true" + {%- if enable_shortcuts == "true" %} if [ "$SKIP_SHORTCUTS" = "1" ]; then env_shortcuts="--no-shortcuts" else @@ -595,28 +564,25 @@ for env_pkgs in "${PREFIX}"/pkgs/envs/*/; do env_shortcuts=$(cat "${env_pkgs}shortcuts.txt") rm -f "${env_pkgs}shortcuts.txt" fi -#endif -#if has_conda and enable_shortcuts == "false" + {%- elif enable_shortcuts == "false" %} env_shortcuts="--no-shortcuts" -#endif -#if has_conda and enable_shortcuts == "incompatible" + {%- elif enable_shortcuts == "incompatible" %} env_shortcuts="" -#endif -#if has_conda + {%- endif %} # shellcheck disable=SC2086 CONDA_ROOT_PREFIX="$PREFIX" \ - CONDA_REGISTER_ENVS="__REGISTER_ENVS__" \ + CONDA_REGISTER_ENVS="{{ register_envs }}" \ CONDA_SAFETY_CHECKS=disabled \ CONDA_EXTRA_SAFETY_CHECKS=no \ CONDA_CHANNELS="$env_channels" \ CONDA_PKGS_DIRS="$PREFIX/pkgs" \ CONDA_QUIET="$BATCH" \ - "$CONDA_EXEC" install --offline --file "${env_pkgs}env.txt" -yp "$PREFIX/envs/$env_name" $env_shortcuts __NO_RCS_ARG__ || exit 1 + "$CONDA_EXEC" install --offline --file "${env_pkgs}env.txt" -yp "$PREFIX/envs/$env_name" $env_shortcuts {{ no_rcs_arg }} || exit 1 rm -f "${env_pkgs}env.txt" done -#endif +{%- endif %} -__INSTALL_COMMANDS__ +{{ install_commands }} POSTCONDA="$PREFIX/postconda.tar.bz2" CONDA_QUIET="$BATCH" \ @@ -627,23 +593,20 @@ export TMP="$TMP_BACKUP" #The templating doesn't support nested if statements -#if has_post_install +{%- if has_post_install %} if [ "$SKIP_SCRIPTS" = "1" ]; then printf "WARNING: skipping post_install.sh by user request\\n" >&2 else -#endif -#if has_post_install and direct_execute_post_install + {%- if direct_execute_post_install %} if ! "$PREFIX/pkgs/post_install.sh"; then -#endif -#if has_post_install and not direct_execute_post_install + {%- else %} if ! sh "$PREFIX/pkgs/post_install.sh"; then -#endif -#if has_post_install + {%- endif %} printf "ERROR: executing post_install.sh failed\\n" >&2 exit 1 fi fi -#endif +{%- endif %} if [ -f "$MSGS" ]; then cat "$MSGS" @@ -658,7 +621,7 @@ else fi cat <<'EOF' -__CONCLUSION_TEXT__ +{{ conclusion_text }} EOF if [ "${PYTHONPATH:-}" != "" ]; then @@ -671,14 +634,8 @@ if [ "${PYTHONPATH:-}" != "" ]; then fi if [ "$BATCH" = "0" ]; then -#if initialize_conda is True and initialize_by_default is True - DEFAULT=yes -#endif -#if initialize_conda is True and initialize_by_default is False - DEFAULT=no -#endif - -#if has_conda and initialize_conda is True +{%- if has_conda and initialize_conda %} + DEFAULT={{ 'yes' if initialize_by_default else 'no' }} # Interactive mode. printf "Do you wish to update your shell profile to automatically initialize conda?\\n" @@ -721,13 +678,13 @@ if [ "$BATCH" = "0" ]; then esac fi fi -#endif +{%- endif %} printf "Thank you for installing %s!\\n" "${INSTALLER_NAME}" fi # !BATCH -#if has_conda +{%- if has_conda %} if [ "$TEST" = "1" ]; then printf "INFO: Running package tests in a subshell\\n" NFAILS=0 @@ -760,7 +717,7 @@ if [ "$TEST" = "1" ]; then exit $NFAILS fi fi -#endif +{%- endif %} exit 0 # shellcheck disable=SC2317 diff --git a/constructor/jinja.py b/constructor/jinja.py index 41f65ee2a..2d46d861f 100644 --- a/constructor/jinja.py +++ b/constructor/jinja.py @@ -1,8 +1,9 @@ import os -from jinja2 import BaseLoader, Environment, FileSystemLoader, TemplateError +from jinja2 import BaseLoader, Environment, FileSystemLoader, StrictUndefined, TemplateError -from constructor.exceptions import UnableToParse +from . import __version__ +from .exceptions import UnableToParse # adapted from conda-build @@ -25,7 +26,7 @@ def get_source(self, environment, template): # adapted from conda-build -def render_jinja(data, directory, content_filter): +def render_jinja_for_input_file(data, directory, content_filter): loader = FilteredLoader(FileSystemLoader(directory), content_filter) env = Environment(loader=loader) env.globals['environ'] = os.environ.copy() @@ -36,3 +37,13 @@ def render_jinja(data, directory, content_filter): except TemplateError as ex: raise UnableToParse(original=ex) return rendered + + +def render_template(text, **kwargs): + env = Environment(keep_trailing_newline=True, undefined=StrictUndefined) + env.globals["constructor_version"] = __version__ + try: + template = env.from_string(text) + return template.render(**kwargs) + except TemplateError as ex: + raise UnableToParse(original=ex) from ex diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl index 3bb66380e..4e2722194 100644 --- a/constructor/nsis/main.nsi.tmpl +++ b/constructor/nsis/main.nsi.tmpl @@ -7,11 +7,11 @@ Unicode true -#if enable_debugging is True +{%- if enable_debugging %} # Special logging build needed for ENABLE_LOGGING # See https://nsis.sourceforge.io/Special_Builds !define ENABLE_LOGGING -#endif +{%- endif %} # Comes from https://nsis.sourceforge.io/Logging:Enable_Logs_Quickly !define LogSet "!insertmacro LogSetMacro" @@ -67,26 +67,26 @@ var /global StdOutHandleSet !include "Utils.nsh" -!define NAME __NAME__ -!define VERSION __VERSION__ -!define COMPANY __COMPANY__ -!define ARCH __ARCH__ -!define PLATFORM __PLATFORM__ -!define CONSTRUCTOR_VERSION __CONSTRUCTOR_VERSION__ -!define PY_VER __PY_VER__ -!define PYVERSION_JUSTDIGITS __PYVERSION_JUSTDIGITS__ -!define PYVERSION __PYVERSION__ -!define PYVERSION_MAJOR __PYVERSION_MAJOR__ -!define DEFAULT_PREFIX __DEFAULT_PREFIX__ -!define DEFAULT_PREFIX_DOMAIN_USER __DEFAULT_PREFIX_DOMAIN_USER__ -!define DEFAULT_PREFIX_ALL_USERS __DEFAULT_PREFIX_ALL_USERS__ -!define PRE_INSTALL_DESC __PRE_INSTALL_DESC__ -!define POST_INSTALL_DESC __POST_INSTALL_DESC__ -!define ENABLE_SHORTCUTS __ENABLE_SHORTCUTS__ -!define SHOW_REGISTER_PYTHON __SHOW_REGISTER_PYTHON__ -!define SHOW_ADD_TO_PATH __SHOW_ADD_TO_PATH__ +!define NAME {{ installer_name }} +!define VERSION {{ installer_version }} +!define COMPANY {{ company }} +!define ARCH {{ arch }} +!define PLATFORM {{ installer_platform }} +!define CONSTRUCTOR_VERSION {{ constructor_version }} +!define PY_VER {{ py_ver }} +!define PYVERSION_JUSTDIGITS {{ pyversion_justdigits }} +!define PYVERSION {{ pyversion }} +!define PYVERSION_MAJOR {{ pyversion_major }} +!define DEFAULT_PREFIX {{ default_prefix }} +!define DEFAULT_PREFIX_DOMAIN_USER {{ default_prefix_domain_user }} +!define DEFAULT_PREFIX_ALL_USERS {{ default_prefix_all_users }} +!define PRE_INSTALL_DESC {{ pre_install_desc }} +!define POST_INSTALL_DESC {{ post_install_desc }} +!define ENABLE_SHORTCUTS {{ enable_shortcuts }} +!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 UNINSTALL_NAME "{{ UNINSTALL_NAME }}" !define UNINSTREG "SOFTWARE\Microsoft\Windows\CurrentVersion\ \Uninstall\${UNINSTALL_NAME}" @@ -130,7 +130,7 @@ CRCCheck On # Basic options Name "${PRODUCT_NAME}" -OutFile __OUTFILE__ +OutFile {{ outfile }} ShowInstDetails "hide" ShowUninstDetails "hide" # This installer contains tar.bz2 files, which are already compressed @@ -147,33 +147,33 @@ VIAddVersionKey "CompanyName" "${COMPANY}" VIAddVersionKey "LegalCopyright" "(c) ${COMPANY}" VIAddVersionKey "FileDescription" "${NAME} Installer" VIAddVersionKey "Comments" "Created by constructor ${CONSTRUCTOR_VERSION}" -VIProductVersion __VIPV__ +VIProductVersion {{ vipv }} BrandingText /TRIMLEFT "${COMPANY}" # Interface configuration -!define MUI_ICON __ICONFILE__ -!define MUI_UNICON __ICONFILE__ +!define MUI_ICON {{ iconfile }} +!define MUI_UNICON {{ iconfile }} !define MUI_HEADERIMAGE -!define MUI_HEADERIMAGE_BITMAP __HEADERIMAGE__ -!define MUI_HEADERIMAGE_UNBITMAP __HEADERIMAGE__ +!define MUI_HEADERIMAGE_BITMAP {{ headerimage }} +!define MUI_HEADERIMAGE_UNBITMAP {{ headerimage }} !define MUI_ABORTWARNING !define MUI_FINISHPAGE_NOAUTOCLOSE !define MUI_UNFINISHPAGE_NOAUTOCLOSE -!define MUI_WELCOMEFINISHPAGE_BITMAP __WELCOMEIMAGE__ -!define MUI_UNWELCOMEFINISHPAGE_BITMAP __WELCOMEIMAGE__ +!define MUI_WELCOMEFINISHPAGE_BITMAP {{ welcomeimage }} +!define MUI_UNWELCOMEFINISHPAGE_BITMAP {{ welcomeimage }} #!define MUI_CUSTOMFUNCTION_GUIINIT GuiInit # Pages #!define MUI_PAGE_CUSTOMFUNCTION_SHOW OnStartup -#if custom_welcome +{%- if custom_welcome %} # Custom welcome file(s) -@CUSTOM_WELCOME_FILE@ -#else +{{ CUSTOM_WELCOME_FILE }} +{%- else %} !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipPageIfUACInnerInstance !insertmacro MUI_PAGE_WELCOME -#endif +{%- endif %} !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipPageIfUACInnerInstance -!insertmacro MUI_PAGE_LICENSE __LICENSEFILE__ +!insertmacro MUI_PAGE_LICENSE {{ licensefile }} Page Custom InstModePage_Create InstModePage_Leave !define MUI_PAGE_CUSTOMFUNCTION_PRE DisableBackButtonIfUACInnerInstance !define MUI_PAGE_CUSTOMFUNCTION_LEAVE OnDirectoryLeave @@ -182,22 +182,22 @@ Page Custom InstModePage_Create InstModePage_Leave Page Custom mui_AnaCustomOptions_Show !insertmacro MUI_PAGE_INSTFILES -#if post_install_pages is True -@POST_INSTALL_PAGES@ -#endif +{%- if post_install_pages %} +{{ POST_INSTALL_PAGES }} +{%- endif %} -#if with_conclusion_text is True -!define MUI_FINISHPAGE_TITLE __CONCLUSION_TITLE__ +{%- if with_conclusion_text %} +!define MUI_FINISHPAGE_TITLE {{ conclusion_title }} !define MUI_FINISHPAGE_TITLE_3LINES -!define MUI_FINISHPAGE_TEXT __CONCLUSION_TEXT__ -#endif +!define MUI_FINISHPAGE_TEXT {{ conclusion_text }} +{%- endif %} -#if custom_conclusion +{%- if custom_conclusion %} # Custom conclusion file(s) -@CUSTOM_CONCLUSION_FILE@ +{{ CUSTOM_CONCLUSION_FILE }} #else !insertmacro MUI_PAGE_FINISH -#endif +{%- endif %} !insertmacro MUI_UNPAGE_WELCOME @@ -269,12 +269,7 @@ FunctionEnd $\n\ /InstallationType=AllUsers [default: JustMe]$\n\ /AddToPath=[0|1] [default: 0]$\n\ -#if keep_pkgs is True - /KeepPkgCache=[0|1] [default: 1]$\n\ -#endif -#if keep_pkgs is False - /KeepPkgCache=[0|1] [default: 0]$\n\ -#endif + /KeepPkgCache=[0|1] [default: {{ 1 if keep_pkgs else 0 }}]$\n\ /RegisterPython=[0|1] [default: AllUsers: 1, JustMe: 0]$\n\ /NoRegistry=[0|1] [default: AllUsers: 0, JustMe: 0]$\n\ /NoScripts=[0|1] [default: 0]$\n\ @@ -332,7 +327,7 @@ FunctionEnd ClearErrors ${GetOptions} $ARGV "/KeepPkgCache=" $ARGV_KeepPkgCache ${If} ${Errors} - StrCpy $ARGV_KeepPkgCache "@KEEP_PKGS@" + StrCpy $ARGV_KeepPkgCache "{{ 1 if keep_pkgs else 0 }}" ${EndIf} ClearErrors @@ -550,13 +545,13 @@ Function .onInit Push $R2 InitPluginsDir - @TEMP_EXTRA_FILES@ + {{ TEMP_EXTRA_FILES }} !insertmacro ParseCommandLineArgs # Select the correct registry to look at, depending # on whether it's a 32-bit or 64-bit installer - SetRegView @BITS@ -#if win64 + SetRegView {{ BITS }} +{%- if win64 %} # If we're a 64-bit installer, make sure it's 64-bit Windows ${IfNot} ${RunningX64} MessageBox MB_OK|MB_ICONEXCLAMATION \ @@ -566,7 +561,7 @@ Function .onInit /SD IDOK Abort ${EndIf} -#endif +{%- endif %} !insertmacro UAC_PageElevation_OnInit ${If} ${UAC_IsInnerInstance} @@ -669,9 +664,9 @@ Function .onInit ${IfNot} ${UAC_IsAdmin} MessageBox MB_ICONSTOP "Installation for all users requires an elevated prompt." Abort - ${EndIF} - ${EndIF} - ${EndIF} + ${EndIf} + ${EndIf} + ${EndIf} ; /D was not used, add default based on install type ${If} $InstDir == "" @@ -692,44 +687,23 @@ 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_conda is True and initialize_by_default is True +{%- if initialize_conda %} + {%- if initialize_by_default %} ${If} $InstMode == ${JUST_ME} StrCpy $Ana_AddToPath_State ${BST_CHECKED} - ${EndIF} -#endif -#if initialize_conda is True and initialize_by_default is False + ${EndIf} + {%- else %} StrCpy $Ana_AddToPath_State ${BST_UNCHECKED} -#endif -#if register_python is True and register_python_default is True - StrCpy $Ana_RegisterSystemPython_State ${BST_CHECKED} -#endif -#if register_python is True and register_python_default is False - StrCpy $Ana_RegisterSystemPython_State ${BST_UNCHECKED} -#endif -#if check_path_length is True - StrCpy $CheckPathLength "1" -#endif -#if check_path_length is False - StrCpy $CheckPathLength "0" -#endif -#if keep_pkgs is True - StrCpy $Ana_ClearPkgCache_State ${BST_UNCHECKED} -#endif -#if keep_pkgs is False - StrCpy $Ana_ClearPkgCache_State ${BST_CHECKED} -#endif -#if pre_install_exists is True - StrCpy $Ana_PreInstall_State ${BST_CHECKED} -#endif -#if pre_install_exists is False - StrCpy $Ana_PreInstall_State ${BST_UNCHECKED} -#endif -#if post_install_exists is True - StrCpy $Ana_PostInstall_State ${BST_CHECKED} -#endif -#if post_install_exists is False - StrCpy $Ana_PostInstall_State ${BST_UNCHECKED} -#endif + {%- endif %} +{%- endif %} + +{%- if register_python %} + StrCpy $Ana_RegisterSystemPython_State {{ '${BST_CHECKED}' if register_python_default else '${BST_UNCHECKED}' }} +{%- endif %} + StrCpy $CheckPathLength "{{ 1 if check_path_length else 0 }}" + StrCpy $Ana_ClearPkgCache_State {{ '${BST_UNCHECKED}' if keep_pkgs else '${BST_CHECKED}' }} + StrCpy $Ana_PreInstall_State {{ '${BST_CHECKED}' if pre_install_exists else '${BST_UNCHECKED}' }} + StrCpy $Ana_PostInstall_State {{ '${BST_CHECKED}' if post_install_exists else '${BST_UNCHECKED}' }} Call OnInit_Release @@ -842,7 +816,7 @@ Function un.onInit # Select the correct registry to look at, depending # on whether it's a 32-bit or 64-bit installer - SetRegView @BITS@ + SetRegView {{ BITS }} # Since the switch to a dual-mode installer (All Users/Just Me), the # uninstaller will inherit the requested execution level of the main @@ -1021,22 +995,22 @@ Function OnDirectoryLeave StrCpy $R7 "$\n" ${EndIf} StrCpy $R8 "'Destination Folder' contains $R0 space$R1.$R7This can cause problems with several conda packages.$R7" -#if check_path_spaces is True +{%- if check_path_spaces %} StrCpy $R8 "$R8Please remove the space$R1 from the destination folder." StrCpy $R9 "Error" -#else +{%- else %} StrCpy $R8 "$R8Please consider removing the space$R1." StrCpy $R9 "Warning" -#endif +{%- endif %} # Show message box then take the user back to the Directory page. ${If} ${Silent} ${Print} "::$R9:: $R8" ${Else} MessageBox MB_OK|MB_ICONINFORMATION "$R9: $R8" /SD IDOK ${EndIf} -#if check_path_spaces is True +{%- if check_path_spaces %} abort -#endif +{%- endif %} NoSpaces: Pop $R7 Pop $R8 @@ -1177,8 +1151,8 @@ Section "Install" ${EndIf} SetOutPath "$INSTDIR\Lib" - File "@NSIS_DIR@\_nsis.py" - File "@NSIS_DIR@\_system_path.py" + File "{{ NSIS_DIR }}\_nsis.py" + File "{{ NSIS_DIR }}\_system_path.py" # Resolve INSTDIR so that paths and registry keys do not contain '..' or similar strings. # $0 is empty if the directory doesn't exist, but the File commands should have created it already. @@ -1189,13 +1163,13 @@ Section "Install" ${EndIf} StrCpy $INSTDIR $0 -#if has_license +{%- if has_license %} SetOutPath "$INSTDIR" - File __LICENSEFILE__ + File {{ licensefile }} ${Print} "By continuing this installation you are accepting this license agreement:" - ${Print} "$INSTDIR\@LICENSEFILENAME@" + ${Print} "$INSTDIR\{{ LICENSEFILENAME }}" ${Print} "Please run the installer in GUI mode to read the details.$\n" -#endif +{%- endif %} ${Print} "${NAME} will now be installed into this location:" ${Print} "$INSTDIR$\n" @@ -1211,14 +1185,14 @@ Section "Install" # A conda-meta\history file is required for a valid conda prefix SetOutPath "$INSTDIR\conda-meta" - File __CONDA_HISTORY__ + File {{ conda_history }} SetOutPath "$INSTDIR" - File __CONDA_EXE__ - File __PRE_UNINSTALL__ + File {{ conda_exe }} + File {{ pre_uninstall }} # Copy extra files (code generated on winexe.py) - @EXTRA_FILES@ + {{ EXTRA_FILES }} ${If} $InstMode = ${JUST_ME} SetOutPath "$INSTDIR" @@ -1227,16 +1201,16 @@ Section "Install" ${EndIf} SetOutPath "$INSTDIR\pkgs" - File __URLS_FILE__ - File __URLS_TXT_FILE__ -#if pre_install_exists is True - File __PRE_INSTALL__ -#endif - File __POST_INSTALL__ - File /nonfatal /r __INDEX_CACHE__ - File /r __REPODATA_RECORD__ - - @SCRIPT_ENV_VARIABLES@ + File {{ urls_file }} + File {{ urls_txt_file }} +{%- if pre_install_exists %} + File {{ pre_install }} +{%- endif %} + File {{ post_install }} + File /nonfatal /r {{ index_cache }} + File /r {{ repodata_record }} + + {{ SCRIPT_ENV_VARIABLES }} System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_SAFETY_CHECKS", "disabled").r0' System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_EXTRA_SAFETY_CHECKS", "no").r0' System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_ROOT_PREFIX", "$INSTDIR")".r0' @@ -1256,22 +1230,22 @@ Section "Install" System::Call 'kernel32::SetEnvironmentVariable(t,t)i("INSTALLER_UNATTENDED", "0").r0' ${EndIf} - ${If} '@VIRTUAL_SPECS@' != '' + ${If} '{{ VIRTUAL_SPECS }}' != '' # We need to specify CONDA_SOLVER=classic for conda-standalone # to work around this bug in conda-libmamba-solver: # https://github.com/conda/conda-libmamba-solver/issues/480 System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_SOLVER", "classic").r0' SetDetailsPrint TextOnly - ${Print} "Checking virtual specs compatibility: @VIRTUAL_SPECS_DEBUG@" - push '"$INSTDIR\_conda.exe" create --dry-run --prefix "$INSTDIR\envs\_virtual_specs_checks" --offline @VIRTUAL_SPECS@ @NO_RCS_ARG@' - push 'Failed to check virtual specs: @VIRTUAL_SPECS_DEBUG@' + ${Print} "Checking virtual specs compatibility: {{ VIRTUAL_SPECS_DEBUG }}" + push '"$INSTDIR\_conda.exe" create --dry-run --prefix "$INSTDIR\envs\_virtual_specs_checks" --offline {{ VIRTUAL_SPECS }} {{ NO_RCS_ARG }}' + push 'Failed to check virtual specs: {{ VIRTUAL_SPECS_DEBUG }}' push 'WithLog' call AbortRetryNSExecWait SetDetailsPrint both System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_SOLVER", "").r0' ${EndIf} - @PKG_COMMANDS@ + {{ PKG_COMMANDS }} SetDetailsPrint TextOnly ${Print} "Setting up the package cache..." @@ -1301,19 +1275,19 @@ Section "Install" call AbortRetryNSExecWait NoPreInstall: - @SETUP_ENVS@ + {{ SETUP_ENVS }} - @WRITE_CONDARC@ + {{ WRITE_CONDARC }} - AddSize @SIZE@ + AddSize {{ SIZE }} -#if has_conda is True +{%- if has_conda %} ${Print} "Initializing conda directories..." push '"$INSTDIR\pythonw.exe" -E -s "$INSTDIR\Lib\_nsis.py" mkdirs' push 'Failed to initialize conda directories' push 'WithLog' call AbortRetryNSExecWait -#endif +{%- endif %} ${If} $Ana_PostInstall_State = ${BST_CHECKED} ${Print} "Running post install..." @@ -1325,7 +1299,7 @@ Section "Install" ${If} $Ana_ClearPkgCache_State = ${BST_CHECKED} ${Print} "Clearing package cache..." - push '"$INSTDIR\_conda.exe" clean --all --force-pkgs-dirs --yes @NO_RCS_ARG@' + push '"$INSTDIR\_conda.exe" clean --all --force-pkgs-dirs --yes {{ NO_RCS_ARG }}' push 'Failed to clear package cache' push 'WithLog' call AbortRetryNSExecWait @@ -1334,7 +1308,7 @@ Section "Install" ${If} $Ana_AddToPath_State = ${BST_CHECKED} ${Print} "Adding to PATH..." push '"$INSTDIR\pythonw.exe" -E -s "$INSTDIR\Lib\_nsis.py" addpath ${PYVERSION} ${NAME} ${VERSION} ${ARCH}' - push 'Failed to add @NAME@ to the system PATH' + push 'Failed to add {{ NAME }} to the system PATH' push 'WithLog' call AbortRetryNSExecWait ${EndIf} @@ -1413,7 +1387,7 @@ Section "Uninstall" # Remove menu items, path entries System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_ROOT_PREFIX", "$INSTDIR")".r0' - @UNINSTALL_MENUS@ + {{ UNINSTALL_MENUS }} # ensure that MSVC runtime DLLs are on PATH during uninstallation ReadEnvStr $0 PATH @@ -1503,10 +1477,10 @@ Section "Uninstall" SectionEnd -!if '@SIGNTOOL_COMMAND@' != '' +!if '{{ SIGNTOOL_COMMAND }}' != '' # Signing for installer and uninstaller; nsis 3.08 required for uninstfinalize! # "= 0" comparison required to prevent both tasks running in parallel, which would cause signtool to fail # %1 is replaced by the installer and uninstaller paths, respectively - !finalize '@SIGNTOOL_COMMAND@ "%1"' = 0 - !uninstfinalize '@SIGNTOOL_COMMAND@ "%1"' = 0 + !finalize '{{ SIGNTOOL_COMMAND }} "%1"' = 0 + !uninstfinalize '{{ SIGNTOOL_COMMAND }} "%1"' = 0 !endif diff --git a/constructor/osx/check_shortcuts.sh b/constructor/osx/check_shortcuts.sh index b592b2443..c15adceed 100644 --- a/constructor/osx/check_shortcuts.sh +++ b/constructor/osx/check_shortcuts.sh @@ -4,7 +4,7 @@ set -eux # $2 is the install location, which is ~ by default # but which the user can change. -PREFIX="$2/__NAME_LOWER__" +PREFIX="$2/{{ pkg_name_lower }}" PREFIX=$(cd "$PREFIX"; pwd) # If the UI selected the "Create shortcuts" option diff --git a/constructor/osx/checks_before_install.sh b/constructor/osx/checks_before_install.sh index 54fabc43d..51468c52e 100644 --- a/constructor/osx/checks_before_install.sh +++ b/constructor/osx/checks_before_install.sh @@ -9,7 +9,7 @@ # so the only way to prevent an action is to abort and start again from the beginning. set -euo pipefail -PREFIX="$2/__NAME_LOWER__" +PREFIX="$2/{{ pkg_name_lower }}" echo "PREFIX=$PREFIX" if [[ -e "$PREFIX" ]]; then diff --git a/constructor/osx/clean_cache.sh b/constructor/osx/clean_cache.sh index 23c8fc908..d056ce99b 100644 --- a/constructor/osx/clean_cache.sh +++ b/constructor/osx/clean_cache.sh @@ -6,6 +6,6 @@ # but which the user can change. set -eux -PREFIX="$2/__NAME_LOWER__" +PREFIX="$2/{{ pkg_name_lower }}" PREFIX=$(cd "$PREFIX"; pwd) rm -rf "$PREFIX/pkgs" diff --git a/constructor/osx/prepare_installation.sh b/constructor/osx/prepare_installation.sh index d33d3b7af..dd5309ab9 100644 --- a/constructor/osx/prepare_installation.sh +++ b/constructor/osx/prepare_installation.sh @@ -8,17 +8,17 @@ set -euo pipefail notify() { # shellcheck disable=SC2050 -if [ "__PROGRESS_NOTIFICATIONS__" = "True" ]; then +{%- if progress_notifications %} osascript </dev/null || : -__WRITE_CONDARC__ +{{ write_condarc }} if ! "$PREFIX/bin/python" -V; then echo "ERROR running Python" diff --git a/constructor/osx/run_user_script.sh b/constructor/osx/run_user_script.sh index ca325f9d5..ae3516039 100644 --- a/constructor/osx/run_user_script.sh +++ b/constructor/osx/run_user_script.sh @@ -8,17 +8,17 @@ set -euo pipefail notify() { # shellcheck disable=SC2050 -if [ "__PROGRESS_NOTIFICATIONS__" = "True" ]; then +{%- if progress_notifications %} osascript <=0.11.14,<0.19 - conda-standalone # >=23.11.0 - pillow >=3.1 # [osx or win] + - jinja2 diff --git a/news/892-jinja b/news/892-jinja new file mode 100644 index 000000000..ea494c598 --- /dev/null +++ b/news/892-jinja @@ -0,0 +1,19 @@ +### Enhancements + +* Use Jinja for templating logic. (#892) + +### Bug fixes + +* + +### Deprecations + +* `constructor.utils.preprocess` and `constructor.utils.fill_template` are deprecated. (#892) + +### Docs + +* + +### Other + +* diff --git a/pyproject.toml b/pyproject.toml index f1bb954a9..6c80b2811 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ dependencies = [ "conda >=4.6", "ruamel.yaml >=0.11.14,<0.19", "pillow >=3.1 ; platform_system=='Windows' or platform_system=='Darwin'", + "jinja2", ] [project.scripts] diff --git a/recipe/meta.yaml b/recipe/meta.yaml index 4158f0dbf..e89e93a27 100644 --- a/recipe/meta.yaml +++ b/recipe/meta.yaml @@ -23,6 +23,7 @@ requirements: - python # >=3.8 - ruamel.yaml >=0.11.14,<0.19 - conda-standalone + - jinja2 - pillow >=3.1 # [win or osx] - nsis >=3.08 # [win] run_constrained: # [unix] diff --git a/tests/test_header.py b/tests/test_header.py index 539d01e0a..8e452387f 100644 --- a/tests/test_header.py +++ b/tests/test_header.py @@ -1,4 +1,3 @@ -import itertools import subprocess import sys import tempfile @@ -13,8 +12,9 @@ else: # Tests with OSX_DIR are skipped, but a placeholder is needed for pytest OSX_DIR = "" +from constructor import __version__ +from constructor.jinja import render_template from constructor.shar import read_header_template -from constructor.utils import preprocess @lru_cache @@ -39,90 +39,6 @@ def run_shellcheck(script): return findings, p.returncode -def test_linux_template_processing(): - template = read_header_template() - errors = [] - for ( - osx, - direct_execute_post_install, - direct_execute_pre_install, - batch_mode, - keep_pkgs, - has_conda, - has_license, - initialize_conda, - initialize_by_default, - has_post_install, - has_pre_install, - enable_shortcuts, - check_path_spaces, - arch, - min_glibc_version, - min_osx_version, - ) in itertools.product( - [False, True], - [False, True], - [False, True], - [False, True], - [False, True], - [False, True], - [False, True], - [False, True], - [False, True], - [False, True], - [False, True], - [False, True], - [False, True], - ["x86", "x86_64", " ppc64le", "s390x", "aarch64"], - [None, "2.17"], - [None, "10.13"], - ): - params = { - "has_license": has_license, - "osx": osx, - "batch_mode": batch_mode, - "keep_pkgs": keep_pkgs, - "has_conda": has_conda, - "x86": arch == "x86", - "x86_64": arch == "x86_64", - "ppc64le": arch == "ppc64le", - "s390x": arch == "s390x", - "aarch64": arch == "aarch64", - "linux": not osx, - "has_pre_install": has_pre_install, - "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, - "enable_shortcuts": enable_shortcuts, - "check_path_spaces": check_path_spaces, - "min_glibc_version": min_glibc_version, - "min_osx_version": min_osx_version, - } - processed = preprocess(template, params) - for template_string in ["#if", "#else", "#endif"]: - if template_string in processed: - errors.append( - f"Found '{template_string}' after processing header.sh with '{params}'." - ) - - assert not errors - - -@pytest.mark.skipif(sys.platform != "darwin", reason="Only on MacOS") -@pytest.mark.parametrize("arch", ["x86_64", "arm64"]) -@pytest.mark.parametrize("check_path_spaces", [False, True]) -@pytest.mark.parametrize("script", sorted(Path(OSX_DIR).glob("*.sh"))) -def test_osxpkg_scripts_template_processing(arch, check_path_spaces, script): - with script.open() as f: - data = f.read() - processed = preprocess(data, {"arch": arch, "check_path_spaces": check_path_spaces}) - assert "#if" not in processed - assert "#else" not in processed - assert "#endif" not in processed - - @pytest.mark.skipif(sys.platform != "darwin", reason="Only on MacOS") @pytest.mark.skipif(available_command("shellcheck") is False, reason="requires shellcheck") @pytest.mark.parametrize("arch", ["x86_64", "arm64"]) @@ -133,12 +49,26 @@ def test_osxpkg_scripts_template_processing(arch, check_path_spaces, script): def test_osxpkg_scripts_shellcheck(arch, check_path_spaces, script): with script.open() as f: data = f.read() - processed = preprocess( + processed = render_template( data, - { - "arch": arch, - "check_path_spaces": check_path_spaces, - }, + arch=arch, + check_path_spaces=check_path_spaces, + pkg_name_lower="example", + installer_name="Example", + installer_version="1.2.3", + installer_platform="osx-64", + channels="conda-forge", + write_condarc="", + path_exists_error_text="Error", + progress_notifications=True, + pre_or_post="pre", + constructor_version=__version__, + shortcuts="", + enable_shortcuts=True, + register_envs=True, + virtual_specs="__osx>=10.13", + no_rcs_arg="", + script_env_variables="", ) findings, returncode = run_shellcheck(processed) @@ -183,9 +113,9 @@ def test_template_shellcheck( min_osx_version, ): template = read_header_template() - processed = preprocess( + processed = render_template( template, - { + **{ "has_license": has_license, "osx": osx, "batch_mode": batch_mode, @@ -207,6 +137,24 @@ def test_template_shellcheck( "enable_shortcuts": enable_shortcuts, "min_glibc_version": min_glibc_version, "min_osx_version": min_osx_version, + "first_payload_size": "1024", + "second_payload_size": "512", + "constructor_version": __version__, + "installer_name": "Example", + "installer_version": "1.2.3", + "installer_platform": "linux-64", + "installer_md5": "a0098a2c837f4cf50180cfc0a041b2af", + "script_env_variables": "", # TODO: Fill this in with actual value + "default_prefix": "/opt/Example", + "license": "Some text", + "total_installation_size_kb": "1024", + "virtual_specs": "__glibc>=2.17", + "shortcuts": "", + "register_envs": "1", + "channels": "conda-forge", + "no_rcs_arg": "", + "install_commands": "", # TODO: Fill this in with actual value + "conclusion_text": "Something", }, ) diff --git a/tests/test_utils.py b/tests/test_utils.py index b66d11738..fc3f9fc50 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,6 +1,6 @@ from os import sep -from constructor.utils import fill_template, make_VIProductVersion, normalize_path, preprocess +from constructor.utils import make_VIProductVersion, normalize_path def test_make_VIProductVersion(): @@ -14,72 +14,9 @@ def test_make_VIProductVersion(): assert f('x') == '0.0.0.0' -def test_fill_template(): - template = """\ -My name is __NAME__! -I am __AGE__ years old. -Sincerely __NAME__ -""" - res = """\ -My name is Hugo! -I am 44 years old. -Sincerely Hugo -""" - info = {'NAME': 'Hugo', 'AGE': '44', 'SEX': 'male'} - assert fill_template(template, info) == res - - -def test_preprocess(): - code = """\ -A -#if True - always True - another line -#endif -B -#if False - never see this -#endif -C -#if x == 0 - x = 0 -#else - x != 0 -#endif -D -#if x != 0 - x != 0 -#endif -E -""" - res = """\ -A - always True - another line -B -C - x != 0 -D - x != 0 -E -""" - assert preprocess(code, dict(x=1)) == res - - def test_normalize_path(): path = "//test//test/test".replace('/', sep) assert normalize_path(path) == "/test/test/test".replace('/', sep) path = "test///test/test".replace('/', sep) assert normalize_path(path) == "test/test/test".replace('/', sep) - - -def main(): - test_make_VIProductVersion() - test_fill_template() - test_preprocess() - test_normalize_path() - - -if __name__ == '__main__': - main()