[Python-checkins] bpo-47086: Remove .chm from Windows installer and add HTML docs (GH-32038)

zooba webhook-mailer at python.org
Mon Mar 21 21:09:03 EDT 2022


https://github.com/python/cpython/commit/3751b6b030b4a3b88959b4f3c4ef2e58d325e497
commit: 3751b6b030b4a3b88959b4f3c4ef2e58d325e497
branch: main
author: Steve Dower <steve.dower at python.org>
committer: zooba <steve.dower at microsoft.com>
date: 2022-03-22T01:08:37Z
summary:

bpo-47086: Remove .chm from Windows installer and add HTML docs (GH-32038)

files:
A Misc/NEWS.d/next/Windows/2022-03-21-20-45-01.bpo-47086.bIuKlF.rst
D Tools/msi/doc/doc_files.wxs
D Tools/msi/doc/doc_no_files.wxs
M .azure-pipelines/windows-release.yml
M .azure-pipelines/windows-release/gpg-sign.yml
M .azure-pipelines/windows-release/msi-steps.yml
M .azure-pipelines/windows-release/stage-build.yml
M .azure-pipelines/windows-release/stage-publish-pythonorg.yml
M PC/layout/support/filesets.py
M PC/layout/support/options.py
M Tools/msi/README.txt
M Tools/msi/build.bat
M Tools/msi/buildrelease.bat
M Tools/msi/bundle/Default.wxl
M Tools/msi/common.wxs
M Tools/msi/doc/doc.wixproj
M Tools/msi/doc/doc.wxs
M Tools/msi/msi.props
M Tools/msi/uploadrelease.ps1

diff --git a/.azure-pipelines/windows-release.yml b/.azure-pipelines/windows-release.yml
index 096ecadc79eb7..581f48ba22882 100644
--- a/.azure-pipelines/windows-release.yml
+++ b/.azure-pipelines/windows-release.yml
@@ -43,13 +43,17 @@ parameters:
 # Eventually when we stop releasing anything that old, we can drop this
 # argument (and make it implicitly always 'true')
 - name: ARM64TclTk
-  displayName: "Use Tcl/Tk for ARM64"
+  displayName: "Use Tcl/Tk for ARM64 (3.11 and later)"
   type: boolean
   default: true
 - name: DoPGO
   displayName: "Run PGO"
   type: boolean
   default: true
+- name: DoCHM
+  displayName: "Produce compiled help document (pre-3.11)"
+  type: boolean
+  default: false
 - name: DoLayout
   displayName: "Produce full layout artifact"
   type: boolean
@@ -86,6 +90,7 @@ variables:
   ${{ if ne(parameters.SigningCertificate, 'Unsigned') }}:
     SigningCertificate: ${{ parameters.SigningCertificate }}
   SigningDescription: ${{ parameters.SigningDescription }}
+  DoCHM: ${{ parameters.DoCHM }}
   DoLayout: ${{ parameters.DoLayout }}
   DoMSIX: ${{ parameters.DoMSIX }}
   DoNuget: ${{ parameters.DoNuget }}
diff --git a/.azure-pipelines/windows-release/gpg-sign.yml b/.azure-pipelines/windows-release/gpg-sign.yml
index 0855af8d703df..04206d23e4996 100644
--- a/.azure-pipelines/windows-release/gpg-sign.yml
+++ b/.azure-pipelines/windows-release/gpg-sign.yml
@@ -3,12 +3,14 @@ parameters:
   GPGPassphrase: $(GPGPassphrase)
   Files: '*'
   WorkingDirectory: $(Build.BinariesDirectory)
+  Condition: succeeded()
 
 steps:
 - task: DownloadSecureFile at 1
   name: gpgkey
   inputs:
     secureFile: ${{ parameters.GPGKeyFile }}
+  condition: ${{ parameters.Condition }}
   displayName: 'Download GPG key'
 
 - powershell: |
@@ -18,6 +20,7 @@ steps:
         gpg/gpg2.exe -ba --batch --passphrase ${{ parameters.GPGPassphrase }} $_
         "Made signature for $_"
     }
+  condition: ${{ parameters.Condition }}
   displayName: 'Generate GPG signatures'
   workingDirectory: ${{ parameters.WorkingDirectory }}
 
diff --git a/.azure-pipelines/windows-release/msi-steps.yml b/.azure-pipelines/windows-release/msi-steps.yml
index c3c2c43032c00..79fc6f5ed292d 100644
--- a/.azure-pipelines/windows-release/msi-steps.yml
+++ b/.azure-pipelines/windows-release/msi-steps.yml
@@ -21,8 +21,6 @@ steps:
     inputs:
       sourceFolder: $(Build.BinariesDirectory)\doc
       targetFolder: $(Build.SourcesDirectory)\Doc\build
-      contents: |
-        htmlhelp\*.chm
 
   - task: DownloadPipelineArtifact at 1
     displayName: 'Download artifact: bin_win32'
diff --git a/.azure-pipelines/windows-release/stage-build.yml b/.azure-pipelines/windows-release/stage-build.yml
index 2745d79dd069c..26f4317750436 100644
--- a/.azure-pipelines/windows-release/stage-build.yml
+++ b/.azure-pipelines/windows-release/stage-build.yml
@@ -5,7 +5,6 @@ jobs:
 - job: Build_Docs
   displayName: Docs build
   pool:
-    #name: 'Windows Release'
     vmImage: windows-2022
 
   workspace:
@@ -21,14 +20,10 @@ jobs:
 
   - script: Doc\make.bat htmlhelp
     displayName: 'Build CHM docs'
+    condition: and(succeeded(), eq(variables['DoCHM'], 'true'))
     env:
       BUILDDIR: $(Build.BinariesDirectory)\Doc
 
-  #- powershell: |
-  #    mkdir -Force "$(Build.BinariesDirectory)\Doc\htmlhelp"
-  #    iwr "https://www.python.org/ftp/python/3.8.0/python380.chm" -OutFile "$(Build.BinariesDirectory)\Doc\htmlhelp\python390a0.chm"
-  #  displayName: 'Cheat at building CHM docs'
-
   - task: CopyFiles at 2
     displayName: 'Assemble artifact: Doc'
     inputs:
@@ -44,6 +39,7 @@ jobs:
       targetPath: $(Build.ArtifactStagingDirectory)\Doc
       artifactName: doc
 
+
 - job: Build_Python
   displayName: Python build
 
diff --git a/.azure-pipelines/windows-release/stage-publish-pythonorg.yml b/.azure-pipelines/windows-release/stage-publish-pythonorg.yml
index 953f728ade381..ee50e4e8aa0db 100644
--- a/.azure-pipelines/windows-release/stage-publish-pythonorg.yml
+++ b/.azure-pipelines/windows-release/stage-publish-pythonorg.yml
@@ -87,7 +87,13 @@ jobs:
   - template: ./gpg-sign.yml
     parameters:
       GPGKeyFile: 'python-signing.key'
-      Files: 'doc\htmlhelp\*.chm, msi\*\*, embed\*.zip'
+      Files: 'msi\*\*, embed\*.zip'
+
+  - template: ./gpg-sign.yml
+    parameters:
+      GPGKeyFile: 'python-signing.key'
+      Files: 'doc\htmlhelp\*.chm'
+      Condition: and(succeeded(), eq(variables['DoCHM'], 'true'))
 
   - powershell: >
       $(Build.SourcesDirectory)\Tools\msi\uploadrelease.ps1
diff --git a/Misc/NEWS.d/next/Windows/2022-03-21-20-45-01.bpo-47086.bIuKlF.rst b/Misc/NEWS.d/next/Windows/2022-03-21-20-45-01.bpo-47086.bIuKlF.rst
new file mode 100644
index 0000000000000..b73e1870c6de2
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2022-03-21-20-45-01.bpo-47086.bIuKlF.rst
@@ -0,0 +1,2 @@
+The installer for Windows now includes documentation as loose HTML files
+rather than a single compiled :file:`.chm` file.
diff --git a/PC/layout/support/filesets.py b/PC/layout/support/filesets.py
index 47f727c057844..3f63f686a9fab 100644
--- a/PC/layout/support/filesets.py
+++ b/PC/layout/support/filesets.py
@@ -93,6 +93,8 @@ def _return_true(f):
 
 
 def rglob(root, patterns, condition=None):
+    if not os.path.isdir(root):
+        return
     if isinstance(patterns, tuple):
         for p in patterns:
             yield from _rglob(root, p, condition or _return_true)
diff --git a/PC/layout/support/options.py b/PC/layout/support/options.py
index 9faf20c0fdc7a..e8310293159e4 100644
--- a/PC/layout/support/options.py
+++ b/PC/layout/support/options.py
@@ -80,7 +80,7 @@ def public(f):
             "venv",
             "dev",
             "symbols",
-            "chm",
+            "html-doc",
         ],
     },
     "embed": {
diff --git a/Tools/msi/README.txt b/Tools/msi/README.txt
index 0a4382f3e0223..8c6ec516f18e9 100644
--- a/Tools/msi/README.txt
+++ b/Tools/msi/README.txt
@@ -4,17 +4,16 @@ Quick Build Info
 For testing, the installer should be built with the Tools/msi/build.bat
 script:
 
-    build.bat [-x86] [-x64] [--doc]
+    build.bat [-x86] [-x64] [-ARM64] [--doc]
 
 For an official release, the installer should be built with the
 Tools/msi/buildrelease.bat script and environment variables:
 
-    set PYTHON=<path to Python 2.7 or 3.4>
+    set PYTHON=<path to Python 3.8 or later>
     set SPHINXBUILD=<path to sphinx-build.exe>
-    set PATH=<path to Git (git.exe)>;
-             <path to HTML Help Compiler (hhc.exe)>;%PATH%
+    set PATH=<path to Git (git.exe)>;%PATH%
 
-    buildrelease.bat [-x86] [-x64] [-D] [-B]
+    buildrelease.bat [-x86] [-x64] [-ARM64] [-D] [-B]
         [-o <output directory>] [-c <certificate name>]
 
 See the Building the Installer section for more information.
@@ -77,20 +76,17 @@ and Features | Turn Windows Features on or off) and ensure that the entry
 For testing, the installer should be built with the Tools/msi/build.bat
 script:
 
-    build.bat [-x86] [-x64] [--doc] [--test-marker] [--pack]
+    build.bat [-x86] [-x64] [-ARM64] [--doc] [--test-marker] [--pack]
 
 This script will build the required configurations of Python and
 generate an installer layout in PCbuild/(win32|amd64)/en-us.
 
-Specify -x86 and/or -x64 to build for each platform. If neither is
-specified, both platforms will be built. Currently, both the debug and
+Specify -x86, -x64 and/or -ARM64 to build for each platform. If none are
+specified, both x64 and x86 will be built. Currently, both the debug and
 release versions of Python are required for the installer.
 
-Specify --doc to build the documentation (.chm) file. If the file is not
-available, it will simply be excluded from the installer. Ensure
-%PYTHON% and %SPHINXBUILD% are set when passing this option. You may
-also set %HTMLHELP% to the Html Help Compiler (hhc.exe), or put HHC on
-your PATH or in externals/.
+Specify --doc to include the documentation files. Ensure %PYTHON% and
+%SPHINXBUILD% are set when passing this option.
 
 Specify --test-marker to build an installer that works side-by-side with
 an official Python release. All registry keys and install locations will
@@ -106,18 +102,18 @@ Tools/msi/buildrelease.bat script:
 
     set PYTHON=<path to Python 2.7 or 3.4>
     set SPHINXBUILD=<path to sphinx-build.exe>
-    set PATH=<path to Git (git.exe)>;
-             <path to HTML Help Compiler (hhc.exe)>;%PATH%
+    set PATH=<path to Git (git.exe)>;%PATH%
 
-    buildrelease.bat [-x86] [-x64] [-D] [-B]
+    buildrelease.bat [-x86] [-x64] [-ARM64] [-D] [-B]
         [-o <output directory>] [-c <certificate name>]
 
-Specify -x86 and/or -x64 to build for each platform. If neither is
-specified, both platforms will be built. Currently, both the debug and
+Specify -x86, -x64 and/or -ARM64 to build for each platform. If none are
+specified, both x64 and x86 will be built. Currently, both the debug and
 release versions of Python are required for the installer.
 
 Specify -D to skip rebuilding the documentation. The documentation is
 required for a release and the build will fail if it is not available.
+Ensure %PYTHON% and %SPHINXBUILD% are set if you omit this option.
 
 Specify -B to skip rebuilding Python. This is useful to only rebuild the
 installer layout after a previous call to buildrelease.bat.
@@ -129,10 +125,6 @@ Specify -c to choose a code-signing certificate to be used for all the
 signable binaries in Python as well as each file making up the
 installer. Official releases of Python must be signed.
 
-Ensure %PYTHON% and %SPHINXBUILD% are set when passing this option. You
-may also set %HTMLHELP% to the Html Help Compiler (hhc.exe), or put HHC
-on your PATH or in externals/. You will also need Git (git.exe) on
-your PATH.
 
 If WiX is not found on your system, it will be automatically downloaded
 and extracted to the externals/ directory.
@@ -366,7 +358,7 @@ Within this install directory is the following approximate layout:
 .\python3x.dll  The core interpreter
 .\python3.dll   The stable ABI reference
 .\DLLs          Stdlib extensions (*.pyd) and dependencies
-.\Doc           Documentation (*.chm)
+.\Doc           Documentation (*.html)
 .\include       Development headers (*.h)
 .\Lib           Standard library
 .\Lib\test      Test suite
@@ -421,7 +413,7 @@ a semicolon.
 
 When the documentation is installed, a key "Help" is created within the
 root key, with a subkey "Main Python Documentation" with its default
-value set to the full path to the installed CHM file.
+value set to the full path to the main index.html file.
 
 
 The py.exe launcher is installed as part of a regular Python install,
diff --git a/Tools/msi/build.bat b/Tools/msi/build.bat
index ded1cfb5b2d6f..425558f99d591 100644
--- a/Tools/msi/build.bat
+++ b/Tools/msi/build.bat
@@ -48,7 +48,7 @@ if defined BUILDARM64 (
 )
 
 if defined BUILDDOC (
-    call "%PCBUILD%..\Doc\make.bat" htmlhelp
+    call "%PCBUILD%..\Doc\make.bat" html
     if errorlevel 1 exit /B %ERRORLEVEL%
 )
 
@@ -87,8 +87,8 @@ echo build.bat [-x86] [-x64] [-arm64] [--doc] [-h] [--test-marker] [--pack] [-r]
 echo.
 echo    -x86                Build x86 installers
 echo    -x64                Build x64 installers
-echo    -ARM64                Build ARM64 installers
-echo    --doc               Build CHM documentation
+echo    -ARM64              Build ARM64 installers
+echo    --doc               Build documentation
 echo    --test-marker       Build with test markers
 echo    --no-test-marker    Build without test markers (default)
 echo    --pack              Embed core MSIs into installer
diff --git a/Tools/msi/buildrelease.bat b/Tools/msi/buildrelease.bat
index d057ca675363f..0373c9f7b836a 100644
--- a/Tools/msi/buildrelease.bat
+++ b/Tools/msi/buildrelease.bat
@@ -81,7 +81,7 @@ if ERRORLEVEL 1 (echo Cannot locate MSBuild.exe on PATH or as MSBUILD variable &
 if "%SKIPBUILD%" EQU "1" goto skipdoc
 if "%SKIPDOC%" EQU "1" goto skipdoc
 
-call "%D%..\..\doc\make.bat" htmlhelp
+call "%D%..\..\doc\make.bat" html
 if errorlevel 1 exit /B %ERRORLEVEL%
 :skipdoc
 
diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl
index 70fb467ec8b19..2eddd1f749ec5 100644
--- a/Tools/msi/bundle/Default.wxl
+++ b/Tools/msi/bundle/Default.wxl
@@ -67,7 +67,7 @@ Select Customize to review current options.</String>
   <String Id="CustomBackButton">&Back</String>
   <String Id="CustomBrowseButton">B&rowse</String>
   <String Id="Include_docLabel">&Documentation</String>
-  <String Id="Include_docHelpLabel">Installs the Python documentation file.</String>
+  <String Id="Include_docHelpLabel">Installs the Python documentation files.</String>
   <String Id="Include_pipLabel">&pip</String>
   <String Id="Include_pipHelpLabel">Installs pip, which can download and install other Python packages.</String>
   <String Id="Include_tcltkLabel">tcl/tk and &IDLE</String>
diff --git a/Tools/msi/common.wxs b/Tools/msi/common.wxs
index 4554e80014a29..b819d320ee948 100644
--- a/Tools/msi/common.wxs
+++ b/Tools/msi/common.wxs
@@ -85,7 +85,9 @@
 
     <Fragment>
         <DirectoryRef Id="InstallDirectory">
-            <Directory Id="Doc" Name="Doc" />
+            <Directory Id="Doc" Name="Doc">
+                <Directory Id="Doc_html" Name="html" />
+            </Directory>
         </DirectoryRef>
     </Fragment>
 
diff --git a/Tools/msi/doc/doc.wixproj b/Tools/msi/doc/doc.wixproj
index ea9929acd05ff..83687968faebe 100644
--- a/Tools/msi/doc/doc.wixproj
+++ b/Tools/msi/doc/doc.wixproj
@@ -10,21 +10,28 @@
     </PropertyGroup>
     <Import Project="..\msi.props" />
     <PropertyGroup>
-        <DocFilename>python$(MajorVersionNumber)$(MinorVersionNumber)$(MicroVersionNumber)$(ReleaseLevelName).chm</DocFilename>
-        <IncludeDocFile>false</IncludeDocFile>
-        <IncludeDocFile Condition="$(BuildForRelease) or Exists('$(PySourcePath)Doc\build\htmlhelp\$(DocFilename)')">true</IncludeDocFile>
-    </PropertyGroup>
-    <PropertyGroup Condition="$(IncludeDocFile)">
-        <DefineConstants>$(DefineConstants);DocFilename=$(DocFilename);</DefineConstants>
+        <DocHtmlPath>$(PySourcePath)Doc\build\html\</DocHtmlPath>
+        <DocHtmlPath Condition="!HasTrailingSlash($(DocHtmlPath))">$(DocHtmlPath)\</DocHtmlPath>
     </PropertyGroup>
     <ItemGroup>
+        <LinkerBindInputPaths Include="$(DocHtmlPath)">
+            <BindName>doc_html</BindName>
+        </LinkerBindInputPaths>
         <Compile Include="doc.wxs" />
-        <Compile Include="doc_files.wxs" Condition="$(IncludeDocFile)" />
-        <Compile Include="doc_no_files.wxs" Condition="!$(IncludeDocFile)" />
     </ItemGroup>
     <ItemGroup>
         <WxlTemplate Include="*.wxl_template" />
     </ItemGroup>
-    
+    <ItemGroup>
+        <InstallFiles Include="$(DocHtmlPath)**\*"
+                      Exclude="$(DocHtmlPath)_sources\**\*">
+            <SourceBase>$(DocHtmlPath)</SourceBase>
+            <Source>!(bindpath.doc_html)</Source>
+            <TargetBase>$(DocHtmlPath)..\</TargetBase>
+            <Target_>Doc_</Target_>
+            <Group>doc_html</Group>
+        </InstallFiles>
+    </ItemGroup>
+
     <Import Project="..\msi.targets" />
 </Project>
\ No newline at end of file
diff --git a/Tools/msi/doc/doc.wxs b/Tools/msi/doc/doc.wxs
index 1d7706bb4d50a..e80fff43418bb 100644
--- a/Tools/msi/doc/doc.wxs
+++ b/Tools/msi/doc/doc.wxs
@@ -8,35 +8,31 @@
         <PropertyRef Id="UpgradeTable" />
         <PropertyRef Id="REGISTRYKEY" />
         
-        <Property Id="HHExe" Value="C:\Windows\hh.exe" />
-        <CustomAction Id="SetHHExe" Property="HHExe" Value='[WindowsFolder]\hh.exe' Execute="immediate" />
-        <InstallExecuteSequence>
-            <Custom Action="SetHHExe" Before="CostFinalize">1</Custom>
-        </InstallExecuteSequence>
-        
         <Feature Id="DefaultFeature" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
-            <ComponentGroupRef Id="doc" Primary="yes" />
+            <ComponentGroupRef Id="doc_html" Primary="yes" />
             <ComponentRef Id="OptionalFeature" />
+
+            <Component Id="doc_reg" Directory="Doc" Guid="*">
+                <RegistryKey Root="HKMU" Key="[REGISTRYKEY]">                                                 
+                    <RegistryValue Key="Help\Main Python Documentation" Type="string" Value="[#Doc_html_index.html]" KeyPath="yes" />
+                </RegistryKey>                                                                                
+            </Component>
         </Feature>
         <Feature Id="Shortcuts" AllowAdvertise="no" Title="!(loc.Title)" Description="!(loc.Description)">
-            <ComponentGroupRef Id="doc" />
+            <ComponentGroupRef Id="doc_html" />
             
-            <?ifdef DocFilename ?>
             <Component Id="doc_shortcut" Directory="MenuDir" Guid="*">
                 <RegistryKey Root="HKMU" Key="[OPTIONALFEATURESREGISTRYKEY]">
                     <RegistryValue Name="$(var.OptionalFeatureName)_shortcut" Type="string" Value="$(var.Version)" KeyPath="yes" />
                 </RegistryKey>
-                <Shortcut Id="python.chm"
-                          Target="[HHExe]"
-                          Arguments="[#python.chm]"
+                <Shortcut Id="python.html"
+                          Target="[#Doc_html_index.html]"
                           Name="!(loc.ShortcutName)"
                           Description="!(loc.ShortcutDescription)"
                           WorkingDirectory="InstallDirectory"
                           Show="maximized" />
                 <RemoveFolder Id="Remove_MenuDir" On="uninstall" />
             </Component>
-            <?endif ?>
-
         </Feature>
     </Product>
 </Wix>
diff --git a/Tools/msi/doc/doc_files.wxs b/Tools/msi/doc/doc_files.wxs
deleted file mode 100644
index fe09afe4d3c76..0000000000000
--- a/Tools/msi/doc/doc_files.wxs
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
-    <Fragment>
-        <PropertyRef Id="REGISTRYKEY" />
-        
-        <ComponentGroup Id="doc">
-            <Component Id="python.chm" Directory="Doc" Guid="*">
-                <File Id="python.chm" Name="$(var.DocFilename)" KeyPath="yes" />
-                <RegistryKey Root="HKMU" Key="[REGISTRYKEY]">
-                    <RegistryValue Key="Help\Main Python Documentation" Type="string" Value="[#python.chm]" />
-                </RegistryKey>
-            </Component>
-        </ComponentGroup>
-    </Fragment>
-</Wix>
diff --git a/Tools/msi/doc/doc_no_files.wxs b/Tools/msi/doc/doc_no_files.wxs
deleted file mode 100644
index 7ab7c2690689c..0000000000000
--- a/Tools/msi/doc/doc_no_files.wxs
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
-    <Fragment>
-        <ComponentGroup Id="doc">
-            <!--
-            This file is included when the CHM is not available.
-            
-            This way, snapshot builds can succeed without having to
-            build the docs.
-            -->
-            <Component Id="EmptyDocFolder" Directory="Doc" Guid="{22FD42DB-EC66-4B1C-B1FC-44E0CF7B2462}">
-                <CreateFolder />
-                <RemoveFolder Id="Remove_EmptyDocFolder" On="uninstall" />
-            </Component>
-        </ComponentGroup>
-    </Fragment>
-</Wix>
diff --git a/Tools/msi/msi.props b/Tools/msi/msi.props
index b5fd3d3a3da74..06aa0b8bbca27 100644
--- a/Tools/msi/msi.props
+++ b/Tools/msi/msi.props
@@ -115,9 +115,6 @@
         <LinkerBindInputPaths Include="$(PGOBuildPath);$(BuildPath)">
             <BindName></BindName>
         </LinkerBindInputPaths>
-        <LinkerBindInputPaths Include="$(PySourcePath)Doc\build\htmlhelp">
-            <BindName></BindName>
-        </LinkerBindInputPaths>
         <LinkerBindInputPaths Include="$(PySourcePath)">
             <BindName>src</BindName>
         </LinkerBindInputPaths>
diff --git a/Tools/msi/uploadrelease.ps1 b/Tools/msi/uploadrelease.ps1
index 7c825c443f228..a8669e5d65ed1 100644
--- a/Tools/msi/uploadrelease.ps1
+++ b/Tools/msi/uploadrelease.ps1
@@ -80,19 +80,19 @@ if (-not $skipupload) {
     ""
 
     if ($doc_htmlhelp) {
-        pushd $doc_htmlhelp
+        $chm = gci -EA 0 $doc_htmlhelp\python*.chm, $doc_htmlhelp\python*.chm.asc
     } else {
-        pushd $build
+        $chm = gci -EA 0 $build\python*.chm, $build\python*.chm.asc
     }
-    $chm = gci python*.chm, python*.chm.asc
-    popd
 
     $d = "$target/$($p[0])/"
     & $plink -batch $user@$server mkdir $d
     & $plink -batch $user@$server chgrp downloads $d
     & $plink -batch $user@$server chmod o+rx $d
-    & $pscp -batch $chm.FullName "$user@${server}:$d"
-    if (-not $?) { throw "Failed to upload $chm" }
+    if ($chm) {
+        & $pscp -batch $chm.FullName "$user@${server}:$d"
+        if (-not $?) { throw "Failed to upload $chm" }
+    }
 
     $dirs = gci "$build" -Directory
     if ($embed) {



More information about the Python-checkins mailing list