Skip to content

Commit 75bcef1

Browse files
authored
fix: prevent .whl files from being corrupted during pack (#1782)
1 parent e00f3f4 commit 75bcef1

4 files changed

Lines changed: 55 additions & 3 deletions

File tree

packages/uipath/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "uipath"
3-
version = "2.12.2"
3+
version = "2.12.3"
44
description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools."
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"

packages/uipath/src/uipath/_cli/_utils/_constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
DOCUMENT_EXTENSIONS = {".pdf", ".docx", ".pptx", ".xlsx", ".xls"}
2222

23-
ARCHIVE_EXTENSIONS = {".zip", ".tar", ".gz", ".rar", ".7z", ".bz2", ".xz"}
23+
ARCHIVE_EXTENSIONS = {".zip", ".tar", ".gz", ".rar", ".7z", ".bz2", ".xz", ".whl"}
2424

2525
MEDIA_EXTENSIONS = {
2626
".mp3",

packages/uipath/tests/cli/test_pack.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# type: ignore
2+
import io
23
import json
34
import os
45
import zipfile
@@ -328,6 +329,57 @@ def test_include_file_extensions(
328329
"Binary file content was corrupted during packing"
329330
)
330331

332+
def test_include_wheel_file_not_corrupted(
333+
self,
334+
runner: CliRunner,
335+
temp_dir: str,
336+
project_details: ProjectDetails,
337+
) -> None:
338+
"""Test that .whl files included via packOptions are packed byte-for-byte.
339+
340+
A .whl file is itself a zip archive full of arbitrary binary bytes. If it
341+
is not recognized as binary by the packager, it gets round-tripped through
342+
a text decode/encode (latin-1 -> UTF-8), which corrupts any byte >= 0x80
343+
and produces an invalid zip file at runtime.
344+
"""
345+
wheel_file_name = "example_pkg-1.0.0-py3-none-any.whl"
346+
347+
# Minimal valid zip (wheel) content, deliberately containing high bytes
348+
# (0x80-0xff) that would be mangled by a latin-1 -> UTF-8 round trip.
349+
buf = io.BytesIO()
350+
with zipfile.ZipFile(buf, "w") as wheel_zip:
351+
wheel_zip.writestr("example_pkg/__init__.py", bytes(range(256)) * 4)
352+
wheel_bytes = buf.getvalue()
353+
354+
pack_options = {"fileExtensionsIncluded": [".whl"]}
355+
356+
with runner.isolated_filesystem(temp_dir=temp_dir):
357+
with open("uipath.json", "w") as f:
358+
json.dump(create_uipath_json(pack_options=pack_options), f)
359+
with open("pyproject.toml", "w") as f:
360+
f.write(project_details.to_toml())
361+
with open("main.py", "w") as f:
362+
f.write("def main(input): return input")
363+
with open(wheel_file_name, "wb") as f:
364+
f.write(wheel_bytes)
365+
366+
with patch("uipath._cli.cli_init.Middlewares.next") as mock_middleware:
367+
mock_middleware.return_value = MiddlewareResult(should_continue=True)
368+
init_result = runner.invoke(cli, ["init"], env={})
369+
assert init_result.exit_code == 0
370+
371+
result = runner.invoke(cli, ["pack", "./"], env={})
372+
373+
assert result.exit_code == 0
374+
with zipfile.ZipFile(
375+
f".uipath/{project_details.name}.{project_details.version}.nupkg", "r"
376+
) as z:
377+
assert f"content/{wheel_file_name}" in z.namelist()
378+
extracted_wheel_bytes = z.read(f"content/{wheel_file_name}")
379+
assert extracted_wheel_bytes == wheel_bytes, (
380+
".whl file content was corrupted during packing"
381+
)
382+
331383
def test_include_files(
332384
self,
333385
runner: CliRunner,

packages/uipath/uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)