From d54c48789f7b8d9bfc36530159d005f7ffb29501 Mon Sep 17 00:00:00 2001 From: Daniel Holth Date: Mon, 7 Oct 2024 16:12:35 -0400 Subject: [PATCH] use extractall(filter=) Python 3.12+ feature (#96) * pass tar_filter to suppress Python warning * edit changelog --- CHANGELOG.md | 3 +++ conda_package_streaming/extract.py | 9 ++++++++- tests/test_extract.py | 1 - 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52da214..ccb0eac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ [//]: # (current developments) * Add Python 3.12 to test matrix. +* Pass Python `tarfile.extractall(filter="fully_trusted")` in addition to + internal filtering, when available, to avoid Python 3.12+ `DeprecationWarning` + (#87) * Improve umask handling. (#106) * Add `transmute_stream(...)` to create `.conda` from `(TarFile, TarInfo)`. (#90) iterators, allowing more creative data sources than just `.tar.bz2` inputs. diff --git a/conda_package_streaming/extract.py b/conda_package_streaming/extract.py index 3d16d99..a6800e5 100644 --- a/conda_package_streaming/extract.py +++ b/conda_package_streaming/extract.py @@ -14,6 +14,7 @@ from . import exceptions, package_streaming __all__ = ["extract_stream", "extract"] +HAS_TAR_FILTER = hasattr(tarfile, "tar_filter") def extract_stream( @@ -44,7 +45,13 @@ def checked_members(): yield member try: - tar_file.extractall(path=dest_dir, members=checked_members()) + # Drop checked_members() when HAS_TAR_FILTER once we are 100% + # certain the stdlib filter maintains same permissions as + # checked_members(). + tar_args = {"path": dest_dir, "members": checked_members()} + if HAS_TAR_FILTER: + tar_args["filter"] = "fully_trusted" + tar_file.extractall(**tar_args) except OSError as e: if e.errno == ELOOP: raise exceptions.CaseInsensitiveFileSystemError() from e diff --git a/tests/test_extract.py b/tests/test_extract.py index 3665209..a2fecd4 100644 --- a/tests/test_extract.py +++ b/tests/test_extract.py @@ -167,7 +167,6 @@ def test_umask(tmp_path, mocker): mode, mode & stat_check, ) - assert not mode & stat.S_IWGRP, "%o" % mode def test_encoding():