Skip to content

Commit 57e59d3

Browse files
Fix: Ensure deterministic file ordering in iter_package_files (#269)
### Summary Fixed non-deterministic file ordering in the `iter_package_files` function by adding explicit sorting of package files. This change ensures consistent behavior across builds and prevents issues caused by unordered file iteration. ### Changes Made - Applied `sorted()` to file listings in both Python versions (<3.11 and >=3.11). - Guaranteed that files are processed in a consistent, lexicographic order. ### Why This Fix? - Prevents non-deterministic builds caused by unordered file iteration. - Improves build reproducibility and enables better caching in CI/CD pipelines. - Simplifies code by enforcing consistent ordering within the function, reducing the need for manual sorting in callers. ### Testing - Rebuilt the project multiple times and verified that output files are now consistent across builds. - Compared generated artifacts (e.g., `.json` files) to confirm deterministic ordering. ### Impact - No functional changes to how files are processed, only improves determinism. - Safer and more reliable builds, especially in CI environments. Closes #265
1 parent a353d10 commit 57e59d3

1 file changed

Lines changed: 2 additions & 2 deletions

File tree

src/shiv/builder.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@
3131
# N.B.: `importlib.resources.{contents,is_resource,path}` are deprecated in 3.11 and gone in 3.13.
3232
if sys.version_info < (3, 11):
3333
def iter_package_files(package: Union[str, ModuleType]) -> Iterator[Tuple[Path, str]]:
34-
for bootstrap_file in importlib_resources.contents(bootstrap):
34+
for bootstrap_file in sorted(importlib_resources.contents(package)):
3535
if importlib_resources.is_resource(bootstrap, bootstrap_file):
3636
with importlib_resources.path(bootstrap, bootstrap_file) as path:
3737
yield (path, bootstrap_file)
3838
else:
3939
def iter_package_files(package: Union[str, ModuleType]) -> Iterator[Tuple[Path, str]]:
40-
for resource in importlib_resources.files(package).iterdir():
40+
for resource in sorted(importlib_resources.files(package).iterdir(), key=lambda r: r.name):
4141
if resource.is_file():
4242
with importlib_resources.as_file(resource) as path:
4343
yield (path, resource.name)

0 commit comments

Comments
 (0)