change-wheel-version
change-wheel-version is a Python utility that modifies the version string within the metadata of an existing wheel (.whl) file. It's particularly useful for adding local version identifiers to custom-built wheels without altering the original package's build process. The library is active, with its latest version being 0.6.0, released in September 2024. Its release cadence is infrequent, driven by specific needs for wheel metadata manipulation.
Common errors
-
Command 'pipx' not found
cause The 'pipx' tool, which is recommended for running change-wheel-version as a standalone application, is not installed or not in your system's PATH.fixInstall pipx first: `python3 -m pip install --user pipx` and then ensure your PATH is updated, typically by running `python3 -m pipx ensurepath`. -
No such file or directory: 'dist/<your_wheel_file>.whl'
cause The specified wheel file does not exist at the provided path, or the path is incorrect. This can happen if the wheel was not built, or if the `build` command placed it in a different directory.fixVerify that your project builds successfully and generates a wheel file. Check the `dist/` directory (or wherever your build system outputs wheels) for the correct filename. Use absolute paths or ensure your current working directory is correct when running the command. -
ERROR: Invalid version: '<invalid_version_string>'
cause The version string provided to `change-wheel-version` via `--new-version` does not conform to PEP 440 (e.g., contains illegal characters, incorrect format for local versions, etc.).fixEnsure your new version string follows PEP 440 guidelines. For example, local versions should start with a `+` (e.g., `1.0.0+local.build1`). Refer to the PEP 440 specification for valid version formats.
Warnings
- gotcha change-wheel-version only alters the version string in the wheel's metadata (e.g., in the .dist-info directory and the filename). It does NOT modify any version numbers hardcoded within the Python source files inside the wheel. Developers must manually update in-code versions if desired.
- gotcha When using `change-wheel-version` without the `--output` option, the tool attempts to rename the original wheel file in place. If the new version string results in an invalid filename for the operating system or conflicts with existing files, this operation might fail or result in unexpected file names.
Install
-
pip install change-wheel-version -
pipx install change-wheel-version
Imports
- change-wheel-version
This library is primarily a command-line tool. Direct programmatic import is not a commonly exposed or documented API. It is typically executed via 'pipx run change_wheel_version' or by running the installed script.
Quickstart
import os
import subprocess
import tempfile
import shutil
# 1. Create a dummy Python project structure
project_name = "my_dummy_package"
original_version = "0.1.0"
modified_version = "0.1.0+local.123"
try:
with tempfile.TemporaryDirectory() as tmpdir:
project_dir = os.path.join(tmpdir, project_name)
os.makedirs(project_dir)
# Create setup.py
with open(os.path.join(project_dir, "setup.py"), "w") as f:
f.write(f'''
from setuptools import setup, find_packages
setup(
name='{project_name}',
version='{original_version}',
packages=find_packages(),
description='A dummy package for testing change-wheel-version',
)
''')
# Create __init__.py
os.makedirs(os.path.join(project_dir, project_name))
with open(os.path.join(project_dir, project_name, "__init__.py"), "w") as f:
f.write("__version__ = f'{original_version}'")
# Change to project directory
os.chdir(project_dir)
# 2. Build the original wheel
print(f"\nBuilding initial wheel for {project_name}-{original_version}...")
subprocess.run(["python", "-m", "build", "--wheel"], check=True, capture_output=True)
# Find the generated wheel file
dist_dir = os.path.join(project_dir, "dist")
original_wheel = [f for f in os.listdir(dist_dir) if f.endswith('.whl') and original_version in f][0]
original_wheel_path = os.path.join(dist_dir, original_wheel)
print(f"Original wheel created: {original_wheel_path}")
# 3. Use change-wheel-version to modify the wheel's version
modified_wheel_name = original_wheel.replace(original_version, modified_version)
modified_wheel_path = os.path.join(dist_dir, modified_wheel_name)
print(f"\nChanging version of {original_wheel} to {modified_version}...")
subprocess.run(
["pipx", "run", "change-wheel-version", original_wheel_path, "--new-version", modified_version],
check=True, capture_output=True
)
# The tool renames the file in place by default if --output is not specified
# So we expect the original wheel to be renamed.
if os.path.exists(original_wheel_path) and not os.path.exists(modified_wheel_path):
# Fallback if the tool doesn't rename exactly as expected based on new version, e.g. if original had build tags already
# For simplicity, we'll try to find the new file, or assume it overwrote.
# More robust would be to use --output.
print("Attempting to find the newly named wheel...")
new_wheels = [f for f in os.listdir(dist_dir) if f.endswith('.whl') and modified_version in f]
if new_wheels:
modified_wheel_path = os.path.join(dist_dir, new_wheels[0])
else:
raise FileNotFoundError("Modified wheel not found with expected version in name.")
print(f"Modified wheel: {modified_wheel_path}")
# 4. Verify the new version using 'wheel info'
print("\nVerifying the new wheel's version...")
result = subprocess.run(["pipx", "run", "wheel", "info", modified_wheel_path], capture_output=True, text=True, check=True)
print(result.stdout)
if f"Version: {modified_version}" in result.stdout:
print("\nSuccessfully changed and verified the wheel version!")
else:
print("\nFailed to verify the wheel version.")
print(f"Cleaning up temporary directory: {tmpdir}")
except subprocess.CalledProcessError as e:
print(f"Error executing command: {e.cmd}")
print(f"Stdout: {e.stdout.decode()}")
print(f"Stderr: {e.stderr.decode()}")
except FileNotFoundError as e:
print(f"File not found error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")