Fix #148051: Duplicate wheels when extension build using "paths"
Extension manifests defining both wheels and a literal paths included wheels in the ZIP file twice. Ref !148247
This commit is contained in:
@@ -4684,7 +4684,13 @@ class subcmd_author:
|
|||||||
|
|
||||||
# Manifest & wheels.
|
# Manifest & wheels.
|
||||||
if build_paths_extra:
|
if build_paths_extra:
|
||||||
build_paths.extend(build_paths_expand_iter(pkg_source_dir, build_paths_extra))
|
build_paths.extend(build_paths_expand_iter(
|
||||||
|
pkg_source_dir,
|
||||||
|
# When "paths" is set, paths before `build_paths_extra_skip_index` have been added,
|
||||||
|
# see: `PkgManifest_Build.from_dict_all_errors`.
|
||||||
|
build_paths_extra if manifest_build.paths is None else
|
||||||
|
build_paths_extra[:build_paths_extra_skip_index],
|
||||||
|
))
|
||||||
|
|
||||||
if manifest_build.paths is not None:
|
if manifest_build.paths is not None:
|
||||||
build_paths.extend(build_paths_expand_iter(pkg_source_dir, manifest_build.paths))
|
build_paths.extend(build_paths_expand_iter(pkg_source_dir, manifest_build.paths))
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ VERBOSE = os.environ.get("VERBOSE", "0") != "0"
|
|||||||
sys.path.append(os.path.join(BASE_DIR, "modules"))
|
sys.path.append(os.path.join(BASE_DIR, "modules"))
|
||||||
from http_server_context import HTTPServerContext # noqa: E402
|
from http_server_context import HTTPServerContext # noqa: E402
|
||||||
|
|
||||||
|
import python_wheel_generate # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
STATUS_NON_ERROR = {'STATUS', 'PROGRESS'}
|
STATUS_NON_ERROR = {'STATUS', 'PROGRESS'}
|
||||||
|
|
||||||
|
|
||||||
@@ -131,6 +134,12 @@ def manifest_dict_from_archive(filepath: str) -> dict[str, Any]:
|
|||||||
# Generate Repository
|
# Generate Repository
|
||||||
#
|
#
|
||||||
|
|
||||||
|
class WheelModuleParams(NamedTuple):
|
||||||
|
module_name: str
|
||||||
|
module_version: str
|
||||||
|
|
||||||
|
filename: str | None = None
|
||||||
|
|
||||||
|
|
||||||
def files_create_in_dir(basedir: str, files: FileTree) -> None:
|
def files_create_in_dir(basedir: str, files: FileTree) -> None:
|
||||||
if not os.path.isdir(basedir):
|
if not os.path.isdir(basedir):
|
||||||
@@ -153,6 +162,7 @@ def my_create_package(
|
|||||||
metadata: dict[str, Any],
|
metadata: dict[str, Any],
|
||||||
files: FileTree,
|
files: FileTree,
|
||||||
build_args_extra: tuple[str, ...],
|
build_args_extra: tuple[str, ...],
|
||||||
|
wheel_params: Sequence[WheelModuleParams] = (),
|
||||||
expected_returncode: int = 0,
|
expected_returncode: int = 0,
|
||||||
) -> Sequence[JSON_OutputElem]:
|
) -> Sequence[JSON_OutputElem]:
|
||||||
"""
|
"""
|
||||||
@@ -165,6 +175,30 @@ def my_create_package(
|
|||||||
metadata_copy = metadata.copy()
|
metadata_copy = metadata.copy()
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as temp_dir_pkg:
|
with tempfile.TemporaryDirectory() as temp_dir_pkg:
|
||||||
|
|
||||||
|
wheel_filenames = []
|
||||||
|
if wheel_params:
|
||||||
|
for w in wheel_params:
|
||||||
|
wheel_filename, wheel_filedata = python_wheel_generate.generate_from_source(
|
||||||
|
module_name=w.module_name,
|
||||||
|
version=w.module_version,
|
||||||
|
source=(
|
||||||
|
"__version__ = {!r}\n"
|
||||||
|
"print(\"The wheel has been found\")\n"
|
||||||
|
).format(w.module_version),
|
||||||
|
)
|
||||||
|
if w.filename is not None:
|
||||||
|
wheel_filename = w.filename
|
||||||
|
|
||||||
|
wheel_dir = os.path.join(temp_dir_pkg, "wheels")
|
||||||
|
os.makedirs(wheel_dir, exist_ok=True)
|
||||||
|
|
||||||
|
wheel_path = os.path.join(wheel_dir, wheel_filename)
|
||||||
|
with open(wheel_path, "wb") as fh:
|
||||||
|
fh.write(wheel_filedata)
|
||||||
|
|
||||||
|
wheel_filenames.append(wheel_filename)
|
||||||
|
|
||||||
temp_dir_pkg_manifest_toml = os.path.join(temp_dir_pkg, PKG_MANIFEST_FILENAME_TOML)
|
temp_dir_pkg_manifest_toml = os.path.join(temp_dir_pkg, PKG_MANIFEST_FILENAME_TOML)
|
||||||
with open(temp_dir_pkg_manifest_toml, "wb") as fh:
|
with open(temp_dir_pkg_manifest_toml, "wb") as fh:
|
||||||
# NOTE: escaping is not supported, this is primitive TOML writing for tests.
|
# NOTE: escaping is not supported, this is primitive TOML writing for tests.
|
||||||
@@ -185,8 +219,18 @@ def my_create_package(
|
|||||||
if (value := metadata_copy.pop("platforms", None)) is not None:
|
if (value := metadata_copy.pop("platforms", None)) is not None:
|
||||||
data_list.append("""platforms = [{:s}]\n""".format(", ".join("\"{:s}\"".format(v) for v in value)))
|
data_list.append("""platforms = [{:s}]\n""".format(", ".join("\"{:s}\"".format(v) for v in value)))
|
||||||
|
|
||||||
|
has_wheels = False
|
||||||
|
wheels_all = []
|
||||||
if (value := metadata_copy.pop("wheels", None)) is not None:
|
if (value := metadata_copy.pop("wheels", None)) is not None:
|
||||||
data_list.append("""wheels = [{:s}]\n""".format(", ".join("\"{:s}\"".format(v) for v in value)))
|
wheels_all.extend(value)
|
||||||
|
has_wheels = True
|
||||||
|
if wheel_filenames:
|
||||||
|
wheels_all.extend(["./wheels/" + wheel_filename for wheel_filename in wheel_filenames])
|
||||||
|
has_wheels = True
|
||||||
|
|
||||||
|
if has_wheels:
|
||||||
|
data_list.append("""wheels = [{:s}]\n""".format(", ".join("\"{:s}\"".format(v) for v in wheels_all)))
|
||||||
|
del has_wheels, wheels_all
|
||||||
|
|
||||||
if (value := metadata_copy.pop("build", None)) is not None:
|
if (value := metadata_copy.pop("build", None)) is not None:
|
||||||
value_copy = value.copy()
|
value_copy = value.copy()
|
||||||
@@ -471,6 +515,7 @@ class TestCLI_Build(unittest.TestCase):
|
|||||||
self,
|
self,
|
||||||
build_paths: list[str],
|
build_paths: list[str],
|
||||||
*,
|
*,
|
||||||
|
wheel_params: Sequence[WheelModuleParams] = (),
|
||||||
expected_returncode: int = 0,
|
expected_returncode: int = 0,
|
||||||
) -> tuple[str, Sequence[JSON_OutputElem]]:
|
) -> tuple[str, Sequence[JSON_OutputElem]]:
|
||||||
pkg_idname = "my_test_paths"
|
pkg_idname = "my_test_paths"
|
||||||
@@ -500,6 +545,7 @@ class TestCLI_Build(unittest.TestCase):
|
|||||||
# Include `add: {...}` so the file list can be scanned.
|
# Include `add: {...}` so the file list can be scanned.
|
||||||
"--verbose",
|
"--verbose",
|
||||||
),
|
),
|
||||||
|
wheel_params=wheel_params,
|
||||||
expected_returncode=expected_returncode,
|
expected_returncode=expected_returncode,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -524,6 +570,28 @@ class TestCLI_Build(unittest.TestCase):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_build_path_literal_with_wheel_success(self) -> None:
|
||||||
|
output_path, output_json = self._test_build_path_literal_impl(
|
||||||
|
build_paths=["__init__.py"],
|
||||||
|
wheel_params=[
|
||||||
|
WheelModuleParams(module_name="my_wheel", module_version="2.3"),
|
||||||
|
],
|
||||||
|
expected_returncode=0,
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
output_size = os.path.getsize(output_path)
|
||||||
|
self.assertEqual(
|
||||||
|
output_json, [
|
||||||
|
("STATUS", "building: my_test_paths.zip"),
|
||||||
|
("STATUS", "add: blender_manifest.toml"),
|
||||||
|
("STATUS", "add: __init__.py"),
|
||||||
|
('STATUS', 'add: wheels/my_wheel-2.3-py3-none-any.whl'),
|
||||||
|
("STATUS", "complete"),
|
||||||
|
("STATUS", "created: \"{:s}\", {:d}".format(output_path, output_size)),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
def test_build_path_literal_error_duplicate(self) -> None:
|
def test_build_path_literal_error_duplicate(self) -> None:
|
||||||
_output_path, output_json = self._test_build_path_literal_impl(
|
_output_path, output_json = self._test_build_path_literal_impl(
|
||||||
build_paths=[
|
build_paths=[
|
||||||
|
|||||||
Reference in New Issue
Block a user