diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 82ddc6a2f8..ca2302109c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -39,6 +39,14 @@ jobs: pip --version pip install --upgrade setuptools>=74 wheel + - name: Fix user Scripts missing from PATH + if: matrix.architecture == 'x86' + run: | + # Work around https://github.com/actions/setup-python/issues/1005 + $ScriptsPath = python -c "import sysconfig,os; print(sysconfig.get_path('scripts', f'{os.name}_user'))" + echo $ScriptsPath + Add-Content $env:GITHUB_PATH $ScriptsPath + - name: Build and install run: pip install . -v --user @@ -49,18 +57,17 @@ jobs: - name: Generate PyWin32.chm help file run: python AutoDuck/make.py - # Smokescreen test to validate it doesn't crash and dlls can be found + # Smokescreen test to validate postinstall doesn't crash, dlls can be found, and both pathless invocation methods work - name: Run postinstall install/remove run: | $UserSite = "$(python -m site --user-site)" - cd "$UserSite/.." - python Scripts/pywin32_postinstall.py -install -destination "$UserSite" - python Scripts/pywin32_postinstall.py -remove -destination "$UserSite" + python -m win32.scripts.pywin32_postinstall -install -destination "$UserSite" + pywin32_postinstall -remove -destination "$UserSite" - name: Run tests # Run the tests directly from the source dir so support files (eg, .wav files etc) # can be found - they aren't installed into the Python tree. - run: python pywin32_testall.py -v -skip-adodbapi + run: python win32/scripts/pywin32_testall.py -v -skip-adodbapi - name: Build wheels run: pip wheel . -v --wheel-dir=dist diff --git a/CHANGES.txt b/CHANGES.txt index 1b73ff072d..1e5e4807e0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -14,6 +14,9 @@ https://mhammond.github.io/pywin32_installers.html . Coming in build 309, as yet unreleased -------------------------------------- +* The postinstall script is now available as a console script. You can invoke it in one of two new methods: (#2408, @Avasam) + 1. `python -m pywin32_postinstall -install` (recommended) + 2. `pywin32_postinstall -install` (shorter but you don't have control over which python environment is used) * Changed the implementation of 'com_record' to a subclassable Python type (2437#, #2361, @geppi) * Removed param `hIcon` from `win32comext.shell.ShellExecuteEx`. It was unusable since Windows Vista (#2423, @Avasam) * Fixed `nbios.NCBStruct` packing (#2406, @Avasam) diff --git a/README.md b/README.md index b7df68361f..71ae9b0299 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ There is a post-install script (see below) which should *not* be run inside virt it should only be run in "global" installs. For unreleased changes, you can download builds made by [github actions](https://github.com/mhammond/pywin32/actions/) - -choose any "workflow" from the `main` branch and download its "artifacts") +choose any "workflow" from the `main` branch and download its "artifacts" ### Installing globally @@ -61,10 +61,14 @@ Outside of a virtual environment you might want to install COM objects, services this by executing: ```shell -python Scripts/pywin32_postinstall.py -install +python -m pywin32_postinstall -install ``` -From the root of your Python installation. +or (shorter but you don't have control over which python environment is used) + +```shell +pywin32_postinstall -install +``` If you do this with normal permissions it will be global for your user (a few files will be copied to the root of your Python install and some changes made to HKCU). If you execute this from @@ -103,7 +107,13 @@ It usually means one of 2 things: So you should run it again: ```shell - python Scripts/pywin32_postinstall.py -install + python -m pywin32_postinstall -install + ``` + + or (shorter but you don't have control over which python environment is used) + + ```shell + pywin32_postinstall -install ``` This will make some small attempts to cleanup older conflicting installs. diff --git a/setup.py b/setup.py index a119d11cd1..50c824ab39 100644 --- a/setup.py +++ b/setup.py @@ -2085,7 +2085,18 @@ def convert_optional_data_files(files): license="PSF", classifiers=classifiers, cmdclass=cmdclass, - scripts=["pywin32_postinstall.py", "pywin32_testall.py"], + # This adds the scripts under Python3XX/Scripts, but doesn't actually do much + scripts=[ + "win32/scripts/pywin32_postinstall.py", + "win32/scripts/pywin32_testall.py", + ], + # This shortcuts `python -m win32.scripts.some_script` to just `some_script` + entry_points={ + "console_scripts": [ + "pywin32_postinstall = win32.scripts.pywin32_postinstall:main", + "pywin32_testall = win32.scripts.pywin32_testall:main", + ] + }, ext_modules=ext_modules, package_dir={ "win32com": "com/win32com", diff --git a/pywin32_postinstall.py b/win32/scripts/pywin32_postinstall.py similarity index 99% rename from pywin32_postinstall.py rename to win32/scripts/pywin32_postinstall.py index e90e354d9f..295818a825 100644 --- a/pywin32_postinstall.py +++ b/win32/scripts/pywin32_postinstall.py @@ -655,10 +655,11 @@ def main(): * Typical usage: - > python pywin32_postinstall.py -install + > python -m pywin32_postinstall -install - This should be run automatically after installation, - but if it fails you can run it again. + * or (shorter but you don't have control over which python environment is used) + + > pywin32_postinstall -install Given EXE installers are no longer provided, and wheel installs can't run postinstall scripts, diff --git a/pywin32_testall.py b/win32/scripts/pywin32_testall.py similarity index 92% rename from pywin32_testall.py rename to win32/scripts/pywin32_testall.py index 2aa92098cb..345d6413fe 100644 --- a/pywin32_testall.py +++ b/win32/scripts/pywin32_testall.py @@ -7,10 +7,8 @@ # locate the dirs based on where this script is - it may be either in the # source tree, or in an installed Python 'Scripts' tree. -this_dir = os.path.dirname(__file__) -site_packages = [ - site.getusersitepackages(), -] + site.getsitepackages() +project_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) +site_packages = [site.getusersitepackages()] + site.getsitepackages() failures = [] @@ -45,7 +43,7 @@ def find_and_run(possible_locations, extras): def main(): import argparse - code_directories = [this_dir] + site_packages + code_directories = [project_root] + site_packages parser = argparse.ArgumentParser( description="A script to trigger tests in all subprojects of PyWin32." @@ -89,10 +87,7 @@ def main(): # win32com maybes = [ os.path.join(directory, "win32com", "test", "testall.py") - for directory in [ - os.path.join(this_dir, "com"), - ] - + site_packages + for directory in [os.path.join(project_root, "com")] + site_packages ] extras = remains + ["1"] # only run "level 1" tests in CI find_and_run(maybes, extras)