Skip to content

Commit 3107e4e

Browse files
authored
Standardise on move (files, directories) (#2884)
* Add new util function (and tests) called `move`. * Change references to sh.mv to use move (as it is faster and cross-platform). * Change conditional "mv -t" to a for loop.
1 parent c6f76b9 commit 3107e4e

File tree

5 files changed

+65
-18
lines changed

5 files changed

+65
-18
lines changed

pythonforandroid/bootstrap.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from pythonforandroid.logger import (shprint, info, logger, debug)
1212
from pythonforandroid.util import (
1313
current_directory, ensure_dir, temp_directory, BuildInterruptingException,
14-
rmdir)
14+
rmdir, move)
1515
from pythonforandroid.recipe import Recipe
1616

1717

@@ -395,8 +395,8 @@ def fry_eggs(self, sitepackages):
395395
if isdir(rd) and d.endswith('.egg'):
396396
info(' ' + d)
397397
files = [join(rd, f) for f in listdir(rd) if f != 'EGG-INFO']
398-
if files:
399-
shprint(sh.mv, '-t', sitepackages, *files)
398+
for f in files:
399+
move(f, sitepackages)
400400
rmdir(d)
401401

402402

pythonforandroid/recipe.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from urllib.parse import urlparse
1919
from pythonforandroid.logger import (logger, info, warning, debug, shprint, info_main)
2020
from pythonforandroid.util import (current_directory, ensure_dir,
21-
BuildInterruptingException, rmdir)
21+
BuildInterruptingException, rmdir, move)
2222
from pythonforandroid.util import load_source as import_recipe
2323

2424

@@ -457,14 +457,14 @@ def unpack(self, arch):
457457
fileh = zipfile.ZipFile(extraction_filename, 'r')
458458
root_directory = fileh.filelist[0].filename.split('/')[0]
459459
if root_directory != basename(directory_name):
460-
shprint(sh.mv, root_directory, directory_name)
460+
move(root_directory, directory_name)
461461
elif extraction_filename.endswith(
462462
('.tar.gz', '.tgz', '.tar.bz2', '.tbz2', '.tar.xz', '.txz')):
463463
sh.tar('xf', extraction_filename)
464464
root_directory = sh.tar('tf', extraction_filename).stdout.decode(
465465
'utf-8').split('\n')[0].split('/')[0]
466466
if root_directory != basename(directory_name):
467-
shprint(sh.mv, root_directory, directory_name)
467+
move(root_directory, directory_name)
468468
else:
469469
raise Exception(
470470
'Could not extract {} download, it must be .zip, '
@@ -1166,7 +1166,7 @@ def reduce_object_file_names(self, dirn):
11661166
parts = file_basename.split('.')
11671167
if len(parts) <= 2:
11681168
continue
1169-
shprint(sh.mv, filen, join(file_dirname, parts[0] + '.so'))
1169+
move(filen, join(file_dirname, parts[0] + '.so'))
11701170

11711171

11721172
def algsum(alg, filen):

pythonforandroid/util.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from os.path import exists, join
55
from os import getcwd, chdir, makedirs, walk
66
from platform import uname
7-
from shutil import rmtree
7+
import shutil
88
from tempfile import mkdtemp
99

1010
from pythonforandroid.logger import (logger, Err_Fore, error, info)
@@ -39,7 +39,7 @@ def temp_directory():
3939
temp_dir, Err_Fore.RESET)))
4040
yield temp_dir
4141
finally:
42-
rmtree(temp_dir)
42+
shutil.rmtree(temp_dir)
4343
logger.debug(''.join((Err_Fore.CYAN, ' - temp directory deleted ',
4444
temp_dir, Err_Fore.RESET)))
4545

@@ -110,11 +110,16 @@ def rmdir(dn, ignore_errors=False):
110110
if not exists(dn):
111111
return
112112
LOGGER.debug("Remove directory and subdirectory {}".format(dn))
113-
rmtree(dn, ignore_errors)
113+
shutil.rmtree(dn, ignore_errors)
114114

115115

116116
def ensure_dir(dn):
117117
if exists(dn):
118118
return
119119
LOGGER.debug("Create directory {0}".format(dn))
120120
makedirs(dn)
121+
122+
123+
def move(source, destination):
124+
LOGGER.debug("Moving {} to {}".format(source, destination))
125+
shutil.move(source, destination)

tests/test_bootstrap.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -562,10 +562,10 @@ def test_bootstrap_strip(
562562

563563
@mock.patch("pythonforandroid.bootstrap.listdir")
564564
@mock.patch("pythonforandroid.bootstrap.rmdir")
565-
@mock.patch("pythonforandroid.bootstrap.sh.mv")
565+
@mock.patch("pythonforandroid.bootstrap.move")
566566
@mock.patch("pythonforandroid.bootstrap.isdir")
567567
def test_bootstrap_fry_eggs(
568-
self, mock_isdir, mock_sh_mv, mock_rmdir, mock_listdir
568+
self, mock_isdir, mock_move, mock_rmdir, mock_listdir
569569
):
570570
mock_listdir.return_value = [
571571
"jnius",
@@ -597,7 +597,7 @@ def test_bootstrap_fry_eggs(
597597
)
598598
# check that the other mocks we made are actually called
599599
mock_isdir.assert_called()
600-
mock_sh_mv.assert_called()
600+
mock_move.assert_called()
601601

602602

603603
class TestBootstrapSdl2(GenericBootstrapTest, unittest.TestCase):

tests/test_util.py

+47-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import os
2+
from pathlib import Path
3+
from tempfile import TemporaryDirectory
24
import types
35
import unittest
46
from unittest import mock
@@ -21,20 +23,21 @@ def test_ensure_dir(self, mock_makedirs):
2123
util.ensure_dir("fake_directory")
2224
mock_makedirs.assert_called_once_with("fake_directory")
2325

24-
@mock.patch("pythonforandroid.util.rmtree")
26+
@mock.patch("shutil.rmtree")
2527
@mock.patch("pythonforandroid.util.mkdtemp")
26-
def test_temp_directory(self, mock_mkdtemp, mock_rmtree):
28+
def test_temp_directory(self, mock_mkdtemp, mock_shutil_rmtree):
29+
2730
"""
2831
Basic test for method :meth:`~pythonforandroid.util.temp_directory`. We
2932
perform this test by `mocking` the command `mkdtemp` and
30-
`rmdir` and we make sure that those functions are called in the
33+
`shutil.rmtree` and we make sure that those functions are called in the
3134
proper place.
3235
"""
3336
mock_mkdtemp.return_value = "/temp/any_directory"
3437
with util.temp_directory():
3538
mock_mkdtemp.assert_called_once()
36-
mock_rmtree.assert_not_called()
37-
mock_rmtree.assert_called_once_with("/temp/any_directory")
39+
mock_shutil_rmtree.assert_not_called()
40+
mock_shutil_rmtree.assert_called_once_with("/temp/any_directory")
3841

3942
@mock.patch("pythonforandroid.util.chdir")
4043
def test_current_directory(self, moch_chdir):
@@ -136,3 +139,42 @@ def test_util_exceptions(self):
136139
)
137140
with self.assertRaises(SystemExit):
138141
util.handle_build_exception(exc)
142+
143+
def test_move(self):
144+
with mock.patch(
145+
"pythonforandroid.util.LOGGER"
146+
) as m_logger, TemporaryDirectory() as base_dir:
147+
new_path = Path(base_dir) / "new"
148+
149+
# Set up source
150+
old_path = Path(base_dir) / "old"
151+
with open(old_path, "w") as outfile:
152+
outfile.write("Temporary content")
153+
154+
# Non existent source
155+
with self.assertRaises(FileNotFoundError):
156+
util.move(new_path, new_path)
157+
m_logger.debug.assert_called()
158+
m_logger.error.assert_not_called()
159+
m_logger.reset_mock()
160+
assert old_path.exists()
161+
assert not new_path.exists()
162+
163+
# Successful move
164+
util.move(old_path, new_path)
165+
assert not old_path.exists()
166+
assert new_path.exists()
167+
m_logger.debug.assert_called()
168+
m_logger.error.assert_not_called()
169+
m_logger.reset_mock()
170+
171+
# Move over existing:
172+
existing_path = Path(base_dir) / "existing"
173+
existing_path.touch()
174+
175+
util.move(new_path, existing_path)
176+
with open(existing_path, "r") as infile:
177+
assert infile.read() == "Temporary content"
178+
m_logger.debug.assert_called()
179+
m_logger.error.assert_not_called()
180+
m_logger.reset_mock()

0 commit comments

Comments
 (0)