Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
76755cb
restore shipping help file
Avasam Nov 19, 2024
4b2e319
Add change entry
Avasam Nov 19, 2024
eddee6d
Update pywin32_postinstall.py
Avasam Nov 19, 2024
7a7035c
Update setup.py
Avasam Nov 19, 2024
5e6f8fa
Merge branch 'main' into restore-shipping-help-file
Avasam Dec 14, 2024
0bcde8a
Merge branch 'main' into restore-shipping-help-file
Avasam Jan 4, 2025
0003fad
Merge branch 'main' into restore-shipping-help-file
Avasam Jan 7, 2025
ad18195
post-merge fix
Avasam Jan 7, 2025
2a36e8a
add some debug logging
Avasam Jan 8, 2025
d4cbc1e
Merge branch 'restore-shipping-help-file' of https://github.com/Avasa…
Avasam Jan 8, 2025
d812230
Merge branch 'main' of https://github.com/mhammond/pywin32 into resto…
Avasam Mar 10, 2025
afa048b
Fix some typos
Avasam Mar 10, 2025
45ff7c9
Merge branch 'main' of https://github.com/mhammond/pywin32 into resto…
Avasam Mar 18, 2025
71702b5
Merge branch 'main' into restore-shipping-help-file
Avasam Mar 19, 2025
e1536ce
Missing subprocess import after merge
Avasam Mar 19, 2025
d0fc388
Merge branch 'restore-shipping-help-file' of https://github.com/Avasa…
Avasam Mar 19, 2025
6b5e473
Support cross-compilation
Avasam Mar 27, 2025
a6e4ba6
Merge branch 'main' of https://github.com/mhammond/pywin32 into resto…
Avasam Mar 27, 2025
c04737b
Merge branch 'main' of https://github.com/mhammond/pywin32 into resto…
Avasam Jun 18, 2025
8dac3c0
Merge branch 'main' into restore-shipping-help-file
Avasam Jun 24, 2025
3a15b0b
Merge branch 'main' into restore-shipping-help-file
Avasam Jul 22, 2025
91ab839
Merge branch 'main' of https://github.com/mhammond/pywin32 into resto…
Avasam Jul 24, 2025
c3a7444
Merge branch 'main' into restore-shipping-help-file
Avasam Dec 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ on:
push:
branches:
- main
pull_request: # Temporary just for test
branches:
- main

jobs:
generate:
Expand All @@ -26,17 +23,16 @@ jobs:
python-version: "3.9"
activate-environment: true

# We still need to install pywin32 because
# AutoDuck/py2d.py currently relies on runtime imports for introspection
# Downloading latest release is faster than re-building
# We install pywin32's latest release just to avoid re-building
# We could instead try to use a GitHub artifact
- name: Install latest release
run: uv pip install --upgrade pywin32

- name: Generate PyWin32.chm help file
run: python AutoDuck/make.py
- name: Set Python user site directory
run: python -c "import os,site; open(os.environ['GITHUB_ENV'], 'a').write(f'USER_DIR={site.USER_SITE}\n')"

- name: Decompile help file into HTML
run: hh -decompile site PyWin32.chm
- name: Decompile shipped help file into HTML
run: hh -decompile site ${env:USER_DIR}\PyWin32.chm

- name: Rename root HTML file
run: mv site\PyWin32.HTML site\index.html
Expand Down
7 changes: 0 additions & 7 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,6 @@ jobs:
- name: Build and install
run: pip install . -v --user

# This needs to happen *after* installing pywin32 since
# AutoDuck/py2d.py currently relies on runtime imports for introspection
# This isn't included in the wheel (TODO: could we?)
# and only serves as a PR test for the docs.yaml workflow
- name: Generate PyWin32.chm help file
run: python AutoDuck/make.py

# Smokescreen test to validate postinstall doesn't crash, dlls can be found, and both pathless invocation methods work
- name: Run postinstall install/remove
run: |
Expand Down
85 changes: 68 additions & 17 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
import platform
import re
import shutil
import subprocess
import sys
import sysconfig
import winreg
from collections.abc import Iterable, MutableSequence
from pathlib import Path
Expand Down Expand Up @@ -503,6 +505,59 @@ def _build_scintilla(self):
os.path.join(self.build_lib, "pythonwin"),
)

def _build_helpfile(self) -> None:
"""
Since AutoDuck/py2d.py relies on import,
this must be done after all extensions are built,
and we can't build a helpfile when cross-compiling.

We can't just add to sys.path to point to the build folder,
because this uses subprocesses,
so we create a temporary .pth file instead.
"""
if self.plat_name != sysconfig.get_platform():
return

build_lib_absolute = os.path.abspath(self.build_lib)
tmp_pywin32_build_pth = (
Path(sysconfig.get_paths()["platlib"]) / "tmp_pywin32_build.pth"
)

# Delete the previous helpfile to ensure that this build worked
Path("PyWin32.chm").unlink(missing_ok=True)

# Create the temporary .pth file
with open("pywin32.pth") as path_file:
# Copy paths from pywin32.pth and expand them to absolute paths
paths = [
(
path.strip()
# support the "import pywin32_bootstrap" hack
if path.startswith("import ")
else os.path.join(build_lib_absolute, path.strip())
)
for path in path_file.readlines()
if not path.startswith("#")
] + [
# Add the build folder to python path
build_lib_absolute,
# For pythoncom.py, since it doesn't get added to the build folder
os.path.abspath("com"),
]
print("paths:", paths)
print("build_lib_absolute:", build_lib_absolute)
print("tmp_pywin32_build_pth:", tmp_pywin32_build_pth)
(Path(build_lib_absolute) / "tmp_pywin32_build.pth").write_text(
"\n".join(paths)
)
tmp_pywin32_build_pth.write_text("\n".join(paths))

# Actually generate the helpfile
subprocess.run((sys.executable, "AutoDuck/make.py"), check=True)

# Cleanup
tmp_pywin32_build_pth.unlink()

# find the VC base path corresponding to distutils paths, and
# potentially upgrade for extra include / lib paths (MFC)
def _check_vc(self):
Expand Down Expand Up @@ -666,6 +721,8 @@ def build_extensions(self):
for mfc_content in mfc_contents:
self.copy_file(mfc_content, target_dir)

self._build_helpfile()

def build_exefile(self, ext):
suffix = "_d" if self.debug else ""
logging.info("building exe '%s'", ext.name)
Expand Down Expand Up @@ -1912,20 +1969,6 @@ def convert_data_files(files: Iterable[str]):
return ret


def convert_optional_data_files(files):
ret = []
for file in files:
try:
temp = convert_data_files([file])
except RuntimeError as details:
if not str(details.args[0]).startswith("No file"):
raise
logging.info("NOTE: Optional file %s not found - skipping", file)
else:
ret.append(temp[0])
return ret


################################################################
if len(sys.argv) == 1:
# distutils will print usage - print our docstring first.
Expand Down Expand Up @@ -1997,6 +2040,12 @@ def convert_optional_data_files(files):
"Programming Language :: Python :: Implementation :: CPython",
]

is_cross_compiling = any(
not argument.endswith(sysconfig.get_platform())
for argument in sys.argv
if argument.startswith("--plat-name=")
)

dist = setup(
name="pywin32",
version=build_id,
Expand Down Expand Up @@ -2043,8 +2092,7 @@ def convert_optional_data_files(files):
},
packages=packages,
py_modules=py_modules,
data_files=convert_optional_data_files(["PyWin32.chm"])
+ convert_data_files(
data_files=convert_data_files(
[
"Pythonwin/start_pythonwin.pyw",
"pythonwin/pywin/*.cfg",
Expand Down Expand Up @@ -2129,7 +2177,10 @@ def convert_optional_data_files(files):
# Note we don't get an auto .pyc - but who cares?
("", ("com/pythoncom.py",)),
("", ("pywin32.pth",)),
],
]
+ [("", ("PyWin32.chm",))]
if not is_cross_compiling
else [],
)

# If we did any extension building, and report if we skipped any.
Expand Down
3 changes: 3 additions & 0 deletions win32/Lib/pywin32_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
try:
import pywin32_system32
except ImportError: # Python ≥3.6: replace ImportError with ModuleNotFoundError
print("pywin32_system32 import failed")
pass
else:
print("pywin32_system32 import success")

import os

# We're guaranteed only that __path__: Iterable[str]
Expand Down
5 changes: 4 additions & 1 deletion win32/scripts/pywin32_postinstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,10 @@ def RegisterHelpFile(register=True, lib_dir=None):
SetPyKeyVal("Help\\Pythonwin Reference", None, chm_file)
return chm_file
else:
print("NOTE: PyWin32.chm can not be located, so has not been registered")
print(
"NOTE: PyWin32.chm can not be located, so has not been registered. "
+ "This is expected if the wheel was cross-compiled."
)
else:
UnsetPyKeyVal("Help\\Pythonwin Reference", None, delete_key=True)
return None
Expand Down
Loading