Metadata-Version: 2.4
Name: wheel_axle
Version: 0.0.14
Summary: Axle is Python wheel enhancement library
Home-page: https://github.com/karellen/wheel-axle
Author: Karellen, Inc.
Author-email: supervisor@karellen.co
Maintainer: Arcadiy Ivanov
Maintainer-email: arcadiy@karellen.co
License: Apache License, Version 2.0
Project-URL: Bug Tracker, https://github.com/karellen/wheel-axle/issues
Project-URL: Documentation, https://github.com/karellen/wheel-axle/
Project-URL: Source Code, https://github.com/karellen/wheel-axle/
Keywords: wheel packaging setuptools bdist_wheel symlink postinstall
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.15
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: System :: Archiving :: Packaging
Classifier: Topic :: Software Development :: Build Tools
Classifier: Intended Audience :: Developers
Classifier: Development Status :: 4 - Beta
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: wheel>=0.37.0
Requires-Dist: wheel-axle-runtime<1.0,>=0.0.12
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: maintainer
Dynamic: maintainer-email
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# Wheel Axle - Python Wheel enhancement library

[![Gitter](https://img.shields.io/gitter/room/karellen/Lobby?logo=gitter)](https://app.gitter.im/#/room/#karellen_Lobby:gitter.im)
[![Build Status](https://img.shields.io/github/actions/workflow/status/karellen/wheel-axle/build.yml?branch=master)](https://github.com/karellen/wheel-axle/actions/workflows/build.yml)
[![Coverage Status](https://img.shields.io/coveralls/github/karellen/wheel-axle/master?logo=coveralls)](https://coveralls.io/r/karellen/wheel-axle?branch=master)

[![Wheel Axle Version](https://img.shields.io/pypi/v/wheel-axle?logo=pypi)](https://pypi.org/project/wheel-axle/)
[![Wheel Axle Python Versions](https://img.shields.io/pypi/pyversions/wheel-axle?logo=pypi)](https://pypi.org/project/wheel-axle/)

[![Wheel Axle Downloads Per Day](https://img.shields.io/pypi/dd/wheel-axle?logo=pypi)](https://pypistats.org/packages/wheel-axle)
[![Wheel Axle Downloads Per Week](https://img.shields.io/pypi/dw/wheel-axle?logo=pypi)](https://pypistats.org/packages/wheel-axle)
[![Wheel Axle Downloads Per Month](https://img.shields.io/pypi/dm/wheel-axle?logo=pypi)](https://pypistats.org/packages/wheel-axle)

## Problem

1. Python wheel does not support symlinks.
2. Python wheel does not support overwriting in a convenient way:
    * whether the distribution is pure-Python
    * distribution ABI tag
    * extend Python tag override capability

## Solution

**WARNING: THIS IS EXPERIMENTAL BETA SOFTWARE. THERE ARE NO WARRANTIES OF ANY KIND. USE AT YOUR OWN RISK.
ADDITIONAL INCLUDED DISCLAIMERS ALSO APPLY.**

Wheel-Axle (`axle`, `bdist_axle`) is a drop-in replacement/augmentation utility for `wheel` (`bdist_wheel`)
that extends and builds spec-compliant wheels.

During the build, `axle` is able to capture and record in the Python wheel the symlinks in the following
schema paths (locations):

* purelib
* platlib
* scripts
* headers
* data

Additionally, `Axle` is able to customize the Python wheel tags via additional command line options.

While the generated Python wheel is fully spec-compliant, additional symlink functionality is not possible without its
companion library [Wheel Axle Runtime](https://github.com/karellen/wheel-axle-runtime). Thus, every Python wheel
generated by the `bdist_axle` automatically becomes dependent on `wheel-axle-runtime` that provides
post-install logic required.

## Implementation

The body of the library is as ugly and messy as `distutils`/`setuptools` are, and consists of, mainly, in
hacking/overwriting various `setuptools` commands to detect, handle and record symlinks and their targets. Once that
problem is solved, the list of symlinks is recorded in the `.dist-info/symlinks.txt`
in the following CSV format:

1. symlink name
2. symlink target
3. a boolean (0 or 1) flag indicating whether the target is a directory

**NOTE: Symlinks may be relative, absolute and/or broken. Symlink targets are recorded verbatim (even when broken) and
are NOT otherwise interpreted. THIS IS INTENTIONAL. Please
see [Wheel Axle Runtime Security Notice](https://github.com/karellen/wheel-axle-runtime#security)
for additional information.**

Two special startup files are also added to the distribution, and whichever one the running interpreter honors
triggers the post-install logic via [wheel-axle-runtime](https://github.com/karellen/wheel-axle-runtime):

* `<distribution name and version>.pth`, whose `import` line `site` executes up to Python 3.17
* `<distribution name and version>.start`, a [PEP 829](https://peps.python.org/pep-0829/) startup entry point file
  honored from Python 3.15 on, whose mere presence also suppresses the `import` line of the matching `.pth`

The two files deliberately call different entry points. The `.start` file names
`wheel_axle.runtime:start`, which only exists in `wheel-axle-runtime` 0.0.12 and later, while the `.pth` file
keeps calling `wheel_axle.runtime.finalize`, which every published runtime provides. Because Python 3.15 is
the first version to honor a `.start` file, and also the first version supported by 0.0.12, the generated
wheel scopes that floor with an environment marker:

```
Requires-Dist: wheel-axle-runtime<1.0; python_version < "3.15"
Requires-Dist: wheel-axle-runtime<1.0,>=0.0.12; python_version >= "3.15"
```

This keeps a wheel installable on every interpreter it otherwise supports. A `py3-none-any` wheel built on a
recent Python still installs on Python 3.9, where the marker leaves the requirement unbounded and the newest
runtime compatible with that interpreter is selected, while Python 3.15 and later are guaranteed a runtime
that can resolve the `.start` entry point even when an older one is already installed.

**NOTE: wheels built by `bdist_axle` before 0.0.13 only carry the `.pth` file. Its `import` line reads the `fullname`
local of `site`, which the initial PEP 829 implementation renamed, and which was restored before Python 3.15.0 was
released. Those wheels therefore keep working on Python 3.15 proper; only the 3.15 pre-releases carrying the rename
fail, and there the failure is a `NameError` traceback at every interpreter startup with the symlinks left uncreated.
Rebuilding with `bdist_axle` 0.0.14 or later is still recommended, because PEP 829 stops executing `.pth` `import`
lines altogether in Python 3.18 and only a `.start` file works from then on. Please see the
[Wheel Axle Runtime compatibility notes](https://github.com/karellen/wheel-axle-runtime#compatibility) for details.**

**NOTE: `bdist_axle` 0.0.13 requires `wheel-axle-runtime>=0.0.12` unconditionally, which makes the wheels it builds
uninstallable on Python 3.9. Use 0.0.14 or later.**

## Usage

`python setup.py bdist_wheel <arguments>` can be replaced with `python setup.py bdist_axle <arguments>`. The replacement
is drop-in.

Additional functionality is available via the following options:

```commandline
  --python-tag        Python implementation compatibility tag (default: 'py3')
  --root-is-pure      set to manually override whether the wheel is
                      pure (default: None)
  --abi-tag           set to override ABI tag (default: None)
  --require-libpython set to indicate the package requires libpython in the
                       exec_prefix/platlib
```

Using `--python-tag`, `--root-is-pure` and `--abi-tag` allows you to create wheels that carry platform-dependent data
while otherwise containing pure-Python libraries.
