|
6 | 6 | import logging
|
7 | 7 | import os
|
8 | 8 | import re
|
| 9 | +import shutil |
9 | 10 | import sys
|
10 | 11 | import typing as t
|
11 | 12 | from pathlib import Path
|
12 | 13 |
|
13 | 14 | import setuptools
|
| 15 | +from setuptools.command.egg_info import egg_info |
14 | 16 |
|
15 | 17 | try:
|
16 | 18 | from setuptools.command.editable_wheel import editable_wheel
|
@@ -107,6 +109,46 @@ def _ensure_dist_info(self):
|
107 | 109 | patch_editable_wheel_command()
|
108 | 110 |
|
109 | 111 |
|
| 112 | +def patch_egg_info_command(): |
| 113 | + """ |
| 114 | + This patch fixes the build process when pip builds a wheel from a source distribution. A source distribution built |
| 115 | + with plux will already contain an `.egg_info` directory, however during the build with pip, a new .egg-info |
| 116 | + directory is created from scratch from the python distribution configuration files (like setup.cfg or |
| 117 | + pyproject.toml). This is a problem, as building a wheel involves creating a .dist-info dir, which is populated from |
| 118 | + this new .egg-info directory. The .egg-info shipped with the source distribution is completely ignored during this |
| 119 | + process, including the `plux.json`, leading to a wheel that does not correctly contain the `entry_points.txt`. |
| 120 | +
|
| 121 | + This patch hooks into this procedure, and makes sure when this new .egg-info directory is created, we first locate |
| 122 | + the one shipped with the source distribution, locate the `plux.json` file, and copy it into the new build context. |
| 123 | + """ |
| 124 | + _run_orig = egg_info.run |
| 125 | + |
| 126 | + def _run(self): |
| 127 | + LOG.debug("Running egg_info command patch from plux") |
| 128 | + # the working directory may be something like `/tmp/pip-req-build-bwekzpi_` where the source distribution |
| 129 | + # was copied into. this happens when you `pip install <dist>` where <dist> is |
| 130 | + # some source distribution. |
| 131 | + should_read, meta_dir = _should_read_existing_egg_info() |
| 132 | + |
| 133 | + # if the .egg_info from the source distribution contains the plux file, we prepare the new .egg-info by copying |
| 134 | + # it there. everything else should be handled implicitly by the command |
| 135 | + if should_read: |
| 136 | + LOG.debug("Locating plux.json from local build context %s", meta_dir) |
| 137 | + plux_json = os.path.join(meta_dir, "plux.json") |
| 138 | + if os.path.exists(plux_json): |
| 139 | + self.mkpath(self.egg_info) # this is what egg_info.run() does but it's idempotent |
| 140 | + if not os.path.exists(os.path.join(self.egg_info, "plux.json")): |
| 141 | + LOG.debug("copying %s into temporary %s", plux_json, self.egg_info) |
| 142 | + shutil.copy(plux_json, self.egg_info) |
| 143 | + |
| 144 | + return _run_orig(self) |
| 145 | + |
| 146 | + egg_info.run = _run |
| 147 | + |
| 148 | + |
| 149 | +patch_egg_info_command() |
| 150 | + |
| 151 | + |
110 | 152 | def find_plugins(where=".", exclude=(), include=("*",)) -> EntryPointDict:
|
111 | 153 | """
|
112 | 154 | Utility for setup.py that collects all plugins from the specified path, and creates a dictionary for
|
@@ -252,7 +294,11 @@ def _is_local_build_context():
|
252 | 294 | try:
|
253 | 295 | i = sys.argv.index("--egg-base")
|
254 | 296 | except ValueError:
|
255 |
| - return False |
| 297 | + try: |
| 298 | + # this code path is for building wheels from source distributions via pip |
| 299 | + i = sys.argv.index("--output-dir") |
| 300 | + except ValueError: |
| 301 | + return False |
256 | 302 |
|
257 | 303 | if "pip-modern-metadata" in sys.argv[i + 1]:
|
258 | 304 | return True
|
|
0 commit comments