tarfile: Handle deprecation warning for extract and extractall (#81545)
* Python 3.11.4 introduces a new parameter 'filter' in extract and extractall in tarfile. Handle deprecation warning message emitted in Python 3.12. * added probing mechanism in ansible-galaxy code to detect broken data filter implementation in tarfile. Fixes: #80832 Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com> Co-authored-by: Matt Clay <matt@mystile.com>
This commit is contained in:
parent
5a059b81c8
commit
1cc5efa77b
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
bugfixes:
|
||||
- tarfile - handle data filter deprecation warning message for extract and extractall (https://github.com/ansible/ansible/issues/80832).
|
||||
- ansible-galaxy - Enabled the ``data`` tarfile filter during role installation for Python versions that support it. A probing mechanism is used to avoid Python versions with a broken implementation.
|
|
@ -24,6 +24,7 @@ __metaclass__ = type
|
|||
|
||||
import errno
|
||||
import datetime
|
||||
import functools
|
||||
import os
|
||||
import tarfile
|
||||
import tempfile
|
||||
|
@ -45,6 +46,32 @@ from ansible.utils.display import Display
|
|||
display = Display()
|
||||
|
||||
|
||||
@functools.cache
|
||||
def _check_working_data_filter() -> bool:
|
||||
"""
|
||||
Check if tarfile.data_filter implementation is working
|
||||
for the current Python version or not
|
||||
"""
|
||||
|
||||
# Implemented the following code to circumvent broken implementation of data_filter
|
||||
# in tarfile. See for more information - https://github.com/python/cpython/issues/107845
|
||||
# deprecated: description='probing broken data filter implementation' python_version='3.11'
|
||||
ret = False
|
||||
if hasattr(tarfile, 'data_filter'):
|
||||
# We explicitly check if tarfile.data_filter is broken or not
|
||||
ti = tarfile.TarInfo('docs/README.md')
|
||||
ti.type = tarfile.SYMTYPE
|
||||
ti.linkname = '../README.md'
|
||||
|
||||
try:
|
||||
tarfile.data_filter(ti, '/foo')
|
||||
except tarfile.LinkOutsideDestinationError:
|
||||
pass
|
||||
else:
|
||||
ret = True
|
||||
return ret
|
||||
|
||||
|
||||
class GalaxyRole(object):
|
||||
|
||||
SUPPORTED_SCMS = set(['git', 'hg'])
|
||||
|
@ -391,7 +418,12 @@ class GalaxyRole(object):
|
|||
continue
|
||||
n_final_parts.append(n_part)
|
||||
member.name = os.path.join(*n_final_parts)
|
||||
role_tar_file.extract(member, to_native(self.path))
|
||||
|
||||
if _check_working_data_filter():
|
||||
# deprecated: description='extract fallback without filter' python_version='3.11'
|
||||
role_tar_file.extract(member, to_native(self.path), filter='data') # type: ignore[call-arg]
|
||||
else:
|
||||
role_tar_file.extract(member, to_native(self.path))
|
||||
|
||||
# write out the install info file for later use
|
||||
self._write_galaxy_install_info()
|
||||
|
|
|
@ -1342,7 +1342,11 @@ def test_sdist() -> None:
|
|||
except FileNotFoundError:
|
||||
raise ApplicationError(f"Missing sdist: {sdist_file.relative_to(CHECKOUT_DIR)}") from None
|
||||
|
||||
sdist.extractall(temp_dir)
|
||||
# deprecated: description='extractall fallback without filter' python_version='3.11'
|
||||
if hasattr(tarfile, 'data_filter'):
|
||||
sdist.extractall(temp_dir, filter='data') # type: ignore[call-arg]
|
||||
else:
|
||||
sdist.extractall(temp_dir)
|
||||
|
||||
pyc_glob = "*.pyc*"
|
||||
pyc_files = sorted(path.relative_to(temp_dir) for path in temp_dir.rglob(pyc_glob))
|
||||
|
|
|
@ -156,7 +156,12 @@ def publish_collection(module, collection):
|
|||
|
||||
# Extract the tarfile to sign the MANIFEST.json
|
||||
with tarfile.open(collection_path, mode='r') as collection_tar:
|
||||
collection_tar.extractall(path=os.path.join(collection_dir, '%s-%s-%s' % (namespace, name, version)))
|
||||
# deprecated: description='extractall fallback without filter' python_version='3.11'
|
||||
# Replace 'tar_filter' with 'data_filter' and 'filter=tar' with 'filter=data' once Python 3.12 is minimum requirement.
|
||||
if hasattr(tarfile, 'tar_filter'):
|
||||
collection_tar.extractall(path=os.path.join(collection_dir, '%s-%s-%s' % (namespace, name, version)), filter='tar')
|
||||
else:
|
||||
collection_tar.extractall(path=os.path.join(collection_dir, '%s-%s-%s' % (namespace, name, version)))
|
||||
|
||||
manifest_path = os.path.join(collection_dir, '%s-%s-%s' % (namespace, name, version), 'MANIFEST.json')
|
||||
signature_path = os.path.join(module.params['signature_dir'], '%s-%s-%s-MANIFEST.json.asc' % (namespace, name, version))
|
||||
|
|
|
@ -159,7 +159,11 @@ class ValidateModulesTest(SanitySingleVersion):
|
|||
temp_dir = process_scoped_temporary_directory(args)
|
||||
|
||||
with tarfile.open(path) as file:
|
||||
file.extractall(temp_dir)
|
||||
# deprecated: description='extractall fallback without filter' python_version='3.11'
|
||||
if hasattr(tarfile, 'data_filter'):
|
||||
file.extractall(temp_dir, filter='data') # type: ignore[call-arg]
|
||||
else:
|
||||
file.extractall(temp_dir)
|
||||
|
||||
cmd.extend([
|
||||
'--original-plugins', temp_dir,
|
||||
|
|
Loading…
Reference in New Issue