From ccde1eef64ff98b1957fdd5e1c7991c6e777d4c1 Mon Sep 17 00:00:00 2001 From: Adrien Ferrand Date: Thu, 7 Jan 2021 01:17:34 +0100 Subject: [PATCH] Enable Python 3.8 for Certbot on Windows (#8465) Now that we have a new pipstrap script with recent version of pip, dependencies for Windows can be resolved correctly on Python 3.8. This PR enables tests on Python 3.8, and package Certbot for Windows on Python 3.8 also. I do not move up to Python 3.9 since some dependencies (`cryptography`, `pynacl`) do not provide wheels for Python 3.9 yet on Windows, which would require a complete C++ build system to compile them. * Enable windows tests on Python 3.8 and package it on Python 3.8 also. * Upgrade pynsist, nsis and pywin32, remove old workarounds Co-authored-by: Brad Warren --- .../templates/jobs/packaging-jobs.yml | 2 +- .../templates/jobs/standard-tests-jobs.yml | 8 ++-- certbot/setup.py | 2 +- tools/dev_constraints.txt | 4 +- windows-installer/construct.py | 33 ++------------- windows-installer/template.nsi | 40 ++++++++++++++----- 6 files changed, 41 insertions(+), 48 deletions(-) diff --git a/.azure-pipelines/templates/jobs/packaging-jobs.yml b/.azure-pipelines/templates/jobs/packaging-jobs.yml index 900be9b2f..28255919f 100644 --- a/.azure-pipelines/templates/jobs/packaging-jobs.yml +++ b/.azure-pipelines/templates/jobs/packaging-jobs.yml @@ -56,7 +56,7 @@ jobs: steps: - task: UsePythonVersion@0 inputs: - versionSpec: 3.7 + versionSpec: 3.8 architecture: x86 addToPath: true - script: python windows-installer/construct.py diff --git a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml index 39cd628bc..957a4c0b4 100644 --- a/.azure-pipelines/templates/jobs/standard-tests-jobs.yml +++ b/.azure-pipelines/templates/jobs/standard-tests-jobs.yml @@ -16,13 +16,13 @@ jobs: IMAGE_NAME: vs2017-win2016 PYTHON_VERSION: 3.6 TOXENV: py36 - windows-py37-cover: + windows-py38-cover: IMAGE_NAME: vs2017-win2016 - PYTHON_VERSION: 3.7 - TOXENV: py37-cover + PYTHON_VERSION: 3.8 + TOXENV: py38-cover windows-integration-certbot: IMAGE_NAME: vs2017-win2016 - PYTHON_VERSION: 3.7 + PYTHON_VERSION: 3.8 TOXENV: integration-certbot linux-oldest-tests-1: IMAGE_NAME: ubuntu-18.04 diff --git a/certbot/setup.py b/certbot/setup.py index ea87d2301..d2a372ce7 100644 --- a/certbot/setup.py +++ b/certbot/setup.py @@ -59,7 +59,7 @@ install_requires = [ # However environment markers are supported only with setuptools >= 36.2. # So this dependency is not added for old Linux distributions with old setuptools, # in order to allow these systems to build certbot from sources. -pywin32_req = 'pywin32>=227' # do not forget to edit pywin32 dependency accordingly in windows-installer/construct.py +pywin32_req = 'pywin32>=300' # do not forget to edit pywin32 dependency accordingly in windows-installer/construct.py setuptools_known_environment_markers = (LooseVersion(setuptools_version) >= LooseVersion('36.2')) if setuptools_known_environment_markers: install_requires.append(pywin32_req + " ; sys_platform == 'win32'") diff --git a/tools/dev_constraints.txt b/tools/dev_constraints.txt index 967596ded..e54ebea92 100644 --- a/tools/dev_constraints.txt +++ b/tools/dev_constraints.txt @@ -91,7 +91,7 @@ pylint==2.4.3 # If pynsist version is upgraded, our NSIS template windows-installer/template.nsi # must be upgraded if necessary using the new built-in one from pynsist. pynacl==1.3.0 -pynsist==2.4 +pynsist==2.6 pytest==3.2.5 pytest-cov==2.5.1 pytest-forked==0.2 @@ -101,7 +101,7 @@ pytest-rerunfailures==4.2 python-dateutil==2.8.1 python-digitalocean==1.11 python-dotenv==0.14.0 -pywin32==227 +pywin32==300 PyYAML==5.3.1 repoze.sphinx.autointerface==0.8 requests-file==1.4.2 diff --git a/windows-installer/construct.py b/windows-installer/construct.py index 1ce4811ac..0684b3c25 100644 --- a/windows-installer/construct.py +++ b/windows-installer/construct.py @@ -9,10 +9,10 @@ import sys import tempfile import time -PYTHON_VERSION = (3, 7, 4) +PYTHON_VERSION = (3, 8, 6) PYTHON_BITNESS = 32 -PYWIN32_VERSION = 227 # do not forget to edit pywin32 dependency accordingly in setup.py -NSIS_VERSION = '3.04' +PYWIN32_VERSION = 300 # do not forget to edit pywin32 dependency accordingly in setup.py +NSIS_VERSION = '3.06.1' def main(): @@ -98,32 +98,6 @@ def _copy_assets(build_path, repo_path): def _generate_pynsist_config(repo_path, build_path): print('Generate pynsist configuration') - pywin32_paths_file = os.path.join(build_path, 'pywin32_paths.py') - - # Pywin32 uses non-standard folders to hold its packages. We need to instruct pynsist bootstrap - # explicitly to add them into sys.path. This is done with a custom "pywin32_paths.py" that is - # referred in the pynsist configuration as an "extra_preamble". - # Reference example: https://github.com/takluyver/pynsist/tree/master/examples/pywebview - with open(pywin32_paths_file, 'w') as file_h: - file_h.write('''\ -pkgdir = os.path.join(os.path.dirname(installdir), 'pkgs') - -sys.path.extend([ - os.path.join(pkgdir, 'win32'), - os.path.join(pkgdir, 'win32', 'lib'), -]) - -# Preload pywintypes and pythoncom -pwt = os.path.join(pkgdir, 'pywin32_system32', 'pywintypes{0}{1}.dll') -pcom = os.path.join(pkgdir, 'pywin32_system32', 'pythoncom{0}{1}.dll') -import warnings -with warnings.catch_warnings(): - warnings.simplefilter("ignore") - import imp -imp.load_dynamic('pywintypes', pwt) -imp.load_dynamic('pythoncom', pcom) -'''.format(PYTHON_VERSION[0], PYTHON_VERSION[1])) - installer_cfg_path = os.path.join(build_path, 'installer.cfg') certbot_pkg_path = os.path.join(repo_path, 'certbot') @@ -158,7 +132,6 @@ files=run.bat [Command certbot] entry_point=certbot.main:main -extra_preamble=pywin32_paths.py '''.format(certbot_version=certbot_version, installer_suffix='win_amd64' if PYTHON_BITNESS == 64 else 'win32', python_bitness=PYTHON_BITNESS, diff --git a/windows-installer/template.nsi b/windows-installer/template.nsi index 50a03865f..64bceb065 100644 --- a/windows-installer/template.nsi +++ b/windows-installer/template.nsi @@ -1,7 +1,7 @@ -; This NSIS template is based on the built-in one in pynsist 2.3. +; This NSIS template is based on the built-in one in pynsist 2.6. ; Added lines are enclosed within "CERTBOT CUSTOM BEGIN/END" comments. ; If pynsist is upgraded, this template must be updated if necessary using the new built-in one. -; Original file can be found here: https://github.com/takluyver/pynsist/blob/2.4/nsist/pyapp.nsi +; Original file can be found here: https://github.com/takluyver/pynsist/blob/2.6/nsist/pyapp.nsi !define PRODUCT_NAME "[[ib.appname]]" !define PRODUCT_VERSION "[[ib.version]]" @@ -14,9 +14,14 @@ ; Marker file to tell the uninstaller that it's a user installation !define USER_INSTALL_MARKER _user_install_marker - + SetCompressor lzma +!if "${NSIS_PACKEDVERSION}" >= 0x03000000 + Unicode true + ManifestDPIAware true +!endif + ; CERTBOT CUSTOM BEGIN ; Administrator privileges are required to insert a new task in Windows Scheduler. ; Also comment out some options to disable ability to choose AllUsers/CurrentUser install mode. @@ -35,9 +40,10 @@ SetCompressor lzma !define MULTIUSER_INSTALLMODE_FUNCTION correct_prog_files [% endif %] !include MultiUser.nsh +!include FileFunc.nsh [% block modernui %] -; Modern UI installer stuff +; Modern UI installer stuff !include "MUI2.nsh" !define MUI_ABORTWARNING !define MUI_ICON "[[icon]]" @@ -67,6 +73,8 @@ Name "${PRODUCT_NAME} (beta) ${PRODUCT_VERSION}" OutFile "${INSTALLER_NAME}" ShowInstDetails show +Var cmdLineInstallDir + Section -SETTINGS SetOutPath "$INSTDIR" SetOverwrite ifnewer @@ -96,14 +104,14 @@ Section "!${PRODUCT_NAME}" sec_app File "[[ file ]]" [% endfor %] [% endfor %] - + ; Install directories [% for dir, destination in ib.install_dirs %] SetOutPath "[[ pjoin(destination, dir) ]]" File /r "[[dir]]\*.*" [% endfor %] [% endblock install_files %] - + [% block install_shortcuts %] ; Install shortcuts ; The output path becomes the working directory for shortcuts @@ -127,7 +135,6 @@ Section "!${PRODUCT_NAME}" sec_app [% block install_commands %] [% if has_commands %] DetailPrint "Setting up command-line launchers..." - nsExec::ExecToLog '[[ python ]] -Es "$INSTDIR\_assemble_launchers.py" [[ python ]] "$INSTDIR\bin"' StrCmp $MultiUser.InstallMode CurrentUser 0 AddSysPathSystem ; Add to PATH for current user @@ -139,7 +146,7 @@ Section "!${PRODUCT_NAME}" sec_app AddedSysPath: [% endif %] [% endblock install_commands %] - + ; Byte-compile Python files. DetailPrint "Byte-compiling Python modules..." nsExec::ExecToLog '[[ python ]] -m compileall -q "$INSTDIR\pkgs"' @@ -238,12 +245,25 @@ Function .onMouseOverSection [% block mouseover_messages %] StrCmp $0 ${sec_app} "" +2 SendMessage $R0 ${WM_SETTEXT} 0 "STR:${PRODUCT_NAME}" - + [% endblock mouseover_messages %] FunctionEnd Function .onInit + ; Multiuser.nsh breaks /D command line parameter. Parse /INSTDIR instead. + ; Cribbing from https://nsis-dev.github.io/NSIS-Forums/html/t-299280.html + ${GetParameters} $0 + ClearErrors + ${GetOptions} '$0' "/INSTDIR=" $1 + IfErrors +2 ; Error means flag not found + StrCpy $cmdLineInstallDir $1 + ClearErrors + !insertmacro MULTIUSER_INIT + + ; If cmd line included /INSTDIR, override the install dir set by MultiUser + StrCmp $cmdLineInstallDir "" +2 + StrCpy $INSTDIR $cmdLineInstallDir FunctionEnd Function un.onInit @@ -257,4 +277,4 @@ Function correct_prog_files StrCmp $MultiUser.InstallMode AllUsers 0 +2 StrCpy $INSTDIR "$PROGRAMFILES64\${MULTIUSER_INSTALLMODE_INSTDIR}" FunctionEnd -[% endif %] \ No newline at end of file +[% endif %]