Skip to content

Commit 7c406f5

Browse files
committed
add 'change_into_dir' named argument to 'extract_file' + print deprecation warning if it's not specified
1 parent 7fa6c42 commit 7c406f5

File tree

5 files changed

+85
-14
lines changed

5 files changed

+85
-14
lines changed

easybuild/framework/easyblock.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1911,7 +1911,9 @@ def extract_step(self):
19111911
"""
19121912
for src in self.src:
19131913
self.log.info("Unpacking source %s" % src['name'])
1914-
srcdir = extract_file(src['path'], self.builddir, cmd=src['cmd'], extra_options=self.cfg['unpack_options'])
1914+
srcdir = extract_file(src['path'], self.builddir, cmd=src['cmd'],
1915+
extra_options=self.cfg['unpack_options'], change_into_dir=False)
1916+
change_dir(srcdir)
19151917
if srcdir:
19161918
self.src[self.src.index(src)]['finalpath'] = srcdir
19171919
else:

easybuild/framework/extensioneasyblock.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ def run(self, unpack_src=False):
103103
# unpack file if desired
104104
if unpack_src:
105105
targetdir = os.path.join(self.master.builddir, remove_unwanted_chars(self.name))
106-
self.ext_dir = extract_file("%s" % self.src, targetdir, extra_options=self.unpack_options)
106+
self.ext_dir = extract_file(self.src, targetdir, extra_options=self.unpack_options,
107+
change_into_dir=False)
108+
change_dir(self.ext_dir)
107109

108110
if self.start_dir and os.path.isdir(self.start_dir):
109111
self.log.debug("Using start_dir: %s", self.start_dir)

easybuild/tools/filetools.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ def change_dir(path):
372372
return cwd
373373

374374

375-
def extract_file(fn, dest, cmd=None, extra_options=None, overwrite=False, forced=False):
375+
def extract_file(fn, dest, cmd=None, extra_options=None, overwrite=False, forced=False, change_into_dir=None):
376376
"""
377377
Extract file at given path to specified directory
378378
:param fn: path to file to extract
@@ -381,8 +381,16 @@ def extract_file(fn, dest, cmd=None, extra_options=None, overwrite=False, forced
381381
:param extra_options: extra options to pass to extract command
382382
:param overwrite: overwrite existing unpacked file
383383
:param forced: force extraction in (extended) dry run mode
384+
:param change_into_dir: change into resulting directory;
385+
None (current default) implies True, but this is deprecated,
386+
this named argument should be set to False or True explicitely
387+
(in a future major release, default will be changed to False)
384388
:return: path to directory (in case of success)
385389
"""
390+
if change_into_dir is None:
391+
_log.deprecated("extract_file function was called without specifying value for change_into_dir", '5.0')
392+
change_into_dir = True
393+
386394
if not os.path.isfile(fn) and not build_option('extended_dry_run'):
387395
raise EasyBuildError("Can't extract file %s: no such file", fn)
388396

@@ -392,8 +400,8 @@ def extract_file(fn, dest, cmd=None, extra_options=None, overwrite=False, forced
392400
abs_dest = os.path.abspath(dest)
393401

394402
# change working directory
395-
_log.debug("Unpacking %s in directory %s.", fn, abs_dest)
396-
change_dir(abs_dest)
403+
_log.debug("Unpacking %s in directory %s", fn, abs_dest)
404+
cwd = change_dir(abs_dest)
397405

398406
if not cmd:
399407
cmd = extract_cmd(fn, overwrite=overwrite)
@@ -408,7 +416,18 @@ def extract_file(fn, dest, cmd=None, extra_options=None, overwrite=False, forced
408416

409417
run.run_cmd(cmd, simple=True, force_in_dry_run=forced)
410418

411-
return find_base_dir()
419+
# note: find_base_dir also changes into the base dir!
420+
base_dir = find_base_dir()
421+
422+
# if changing into obtained directory is not desired,
423+
# change back to where we came from (unless that was a non-existing directory)
424+
if not change_into_dir:
425+
if cwd is None:
426+
_log.warning("Can't change back to non-existing directory after extracting %s in %s", fn, dest)
427+
else:
428+
change_dir(cwd)
429+
430+
return base_dir
412431

413432

414433
def which(cmd, retain_all=False, check_perms=True, log_ok=True, log_error=True):
@@ -1186,7 +1205,8 @@ def apply_patch(patch_file, dest, fn=None, copy=False, level=None, use_git_am=Fa
11861205
workdir = tempfile.mkdtemp(prefix='eb-patch-')
11871206
_log.debug("Extracting the patch to: %s", workdir)
11881207
# extracting the patch
1189-
apatch_dir = extract_file(apatch, workdir)
1208+
apatch_dir = extract_file(apatch, workdir, change_into_dir=False)
1209+
change_dir(apatch_dir)
11901210
apatch = os.path.join(apatch_dir, apatch_name)
11911211

11921212
if level is None and build_option('extended_dry_run'):

easybuild/tools/github.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
from easybuild.framework.easyconfig.parser import EasyConfigParser
5151
from easybuild.tools.build_log import EasyBuildError, print_msg, print_warning
5252
from easybuild.tools.config import build_option
53-
from easybuild.tools.filetools import apply_patch, copy_dir, copy_easyblocks, copy_framework_files
53+
from easybuild.tools.filetools import apply_patch, change_dir, copy_dir, copy_easyblocks, copy_framework_files
5454
from easybuild.tools.filetools import det_patched_files, download_file, extract_file
5555
from easybuild.tools.filetools import get_easyblock_class_name, mkdir, read_file, symlink, which, write_file
5656
from easybuild.tools.py2vs3 import HTTPError, URLError, ascii_letters, urlopen
@@ -360,7 +360,9 @@ def download_repo(repo=GITHUB_EASYCONFIGS_REPO, branch='master', account=GITHUB_
360360
download_file(base_name, url, target_path, forced=True)
361361
_log.debug("%s downloaded to %s, extracting now" % (base_name, path))
362362

363-
extracted_path = os.path.join(extract_file(target_path, path, forced=True), extracted_dir_name)
363+
base_dir = extract_file(target_path, path, forced=True, change_into_dir=False)
364+
change_dir(base_dir)
365+
extracted_path = os.path.join(base_dir, extracted_dir_name)
364366

365367
# check if extracted_path exists
366368
if not os.path.isdir(extracted_path):

test/framework/filetools.py

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,7 +1327,8 @@ def test_apply_patch(self):
13271327
""" Test apply_patch """
13281328
testdir = os.path.dirname(os.path.abspath(__file__))
13291329
tmpdir = self.test_prefix
1330-
path = ft.extract_file(os.path.join(testdir, 'sandbox', 'sources', 'toy', 'toy-0.0.tar.gz'), tmpdir)
1330+
toy_tar_gz = os.path.join(testdir, 'sandbox', 'sources', 'toy', 'toy-0.0.tar.gz')
1331+
path = ft.extract_file(toy_tar_gz, tmpdir, change_into_dir=False)
13311332
toy_patch_fn = 'toy-0.0_fix-silly-typo-in-printf-statement.patch'
13321333
toy_patch = os.path.join(testdir, 'sandbox', 'sources', 'toy', toy_patch_fn)
13331334

@@ -1597,19 +1598,24 @@ def test_change_dir(self):
15971598

15981599
def test_extract_file(self):
15991600
"""Test extract_file"""
1601+
cwd = os.getcwd()
1602+
16001603
testdir = os.path.dirname(os.path.abspath(__file__))
16011604
toy_tarball = os.path.join(testdir, 'sandbox', 'sources', 'toy', 'toy-0.0.tar.gz')
16021605

16031606
self.assertFalse(os.path.exists(os.path.join(self.test_prefix, 'toy-0.0', 'toy.source')))
1604-
path = ft.extract_file(toy_tarball, self.test_prefix)
1607+
path = ft.extract_file(toy_tarball, self.test_prefix, change_into_dir=False)
16051608
self.assertTrue(os.path.exists(os.path.join(self.test_prefix, 'toy-0.0', 'toy.source')))
16061609
self.assertTrue(os.path.samefile(path, self.test_prefix))
1610+
# still in same directory as before if change_into_dir is set to False
1611+
self.assertTrue(os.path.samefile(os.getcwd(), cwd))
16071612
shutil.rmtree(os.path.join(path, 'toy-0.0'))
16081613

16091614
toy_tarball_renamed = os.path.join(self.test_prefix, 'toy_tarball')
16101615
shutil.copyfile(toy_tarball, toy_tarball_renamed)
16111616

1612-
path = ft.extract_file(toy_tarball_renamed, self.test_prefix, cmd="tar xfvz %s")
1617+
path = ft.extract_file(toy_tarball_renamed, self.test_prefix, cmd="tar xfvz %s", change_into_dir=False)
1618+
self.assertTrue(os.path.samefile(os.getcwd(), cwd))
16131619
self.assertTrue(os.path.exists(os.path.join(self.test_prefix, 'toy-0.0', 'toy.source')))
16141620
self.assertTrue(os.path.samefile(path, self.test_prefix))
16151621
shutil.rmtree(os.path.join(path, 'toy-0.0'))
@@ -1622,17 +1628,56 @@ def test_extract_file(self):
16221628
init_config(build_options=build_options)
16231629

16241630
self.mock_stdout(True)
1625-
path = ft.extract_file(toy_tarball, self.test_prefix)
1631+
path = ft.extract_file(toy_tarball, self.test_prefix, change_into_dir=False)
16261632
txt = self.get_stdout()
16271633
self.mock_stdout(False)
1634+
self.assertTrue(os.path.samefile(os.getcwd(), cwd))
16281635

16291636
self.assertTrue(os.path.samefile(path, self.test_prefix))
16301637
self.assertFalse(os.path.exists(os.path.join(self.test_prefix, 'toy-0.0')))
16311638
self.assertTrue(re.search('running command "tar xzf .*/toy-0.0.tar.gz"', txt))
16321639

1633-
path = ft.extract_file(toy_tarball, self.test_prefix, forced=True)
1640+
path = ft.extract_file(toy_tarball, self.test_prefix, forced=True, change_into_dir=False)
16341641
self.assertTrue(os.path.exists(os.path.join(self.test_prefix, 'toy-0.0', 'toy.source')))
16351642
self.assertTrue(os.path.samefile(path, self.test_prefix))
1643+
self.assertTrue(os.path.samefile(os.getcwd(), cwd))
1644+
1645+
build_options['extended_dry_run'] = False
1646+
init_config(build_options=build_options)
1647+
1648+
ft.remove_dir(os.path.join(self.test_prefix, 'toy-0.0'))
1649+
1650+
# a deprecation warning is printed (which is an error in this context)
1651+
# if the 'change_into_dir' named argument was left unspecified
1652+
error_pattern = "extract_file function was called without specifying value for change_into_dir"
1653+
self.assertErrorRegex(EasyBuildError, error_pattern, ft.extract_file, toy_tarball, self.test_prefix)
1654+
self.allow_deprecated_behaviour()
1655+
1656+
# make sure we're not in self.test_prefix now (checks below assumes so)
1657+
self.assertFalse(os.path.samefile(os.getcwd(), self.test_prefix))
1658+
1659+
# by default, extract_file changes to directory in which source file was unpacked
1660+
self.mock_stderr(True)
1661+
path = ft.extract_file(toy_tarball, self.test_prefix)
1662+
stderr = self.get_stderr().strip()
1663+
self.mock_stderr(False)
1664+
self.assertTrue(os.path.samefile(path, self.test_prefix))
1665+
self.assertTrue(os.path.samefile(os.getcwd(), self.test_prefix))
1666+
regex = re.compile("^WARNING: .*extract_file function was called without specifying value for change_into_dir")
1667+
self.assertTrue(regex.search(stderr), "Pattern '%s' found in: %s" % (regex.pattern, stderr))
1668+
1669+
ft.change_dir(cwd)
1670+
self.assertFalse(os.path.samefile(os.getcwd(), self.test_prefix))
1671+
1672+
# no deprecation warning when change_into_dir is set to True
1673+
self.mock_stderr(True)
1674+
path = ft.extract_file(toy_tarball, self.test_prefix, change_into_dir=True)
1675+
stderr = self.get_stderr().strip()
1676+
self.mock_stderr(False)
1677+
1678+
self.assertTrue(os.path.samefile(path, self.test_prefix))
1679+
self.assertTrue(os.path.samefile(os.getcwd(), self.test_prefix))
1680+
self.assertFalse(stderr)
16361681

16371682
def test_remove(self):
16381683
"""Test remove_file, remove_dir and join remove functions."""

0 commit comments

Comments
 (0)