[Python-checkins] r80230 - in python/branches/py3k: Doc/library/shutil.rst Lib/shutil.py Lib/test/test_shutil.py Misc/NEWS
tarek.ziade
python-checkins at python.org
Tue Apr 20 00:30:51 CEST 2010
Author: tarek.ziade
Date: Tue Apr 20 00:30:51 2010
New Revision: 80230
Log:
Fixed #1540112: now shutil.copytree will let you provide your own copy() function
Modified:
python/branches/py3k/Doc/library/shutil.rst
python/branches/py3k/Lib/shutil.py
python/branches/py3k/Lib/test/test_shutil.py
python/branches/py3k/Misc/NEWS
Modified: python/branches/py3k/Doc/library/shutil.rst
==============================================================================
--- python/branches/py3k/Doc/library/shutil.rst (original)
+++ python/branches/py3k/Doc/library/shutil.rst Tue Apr 20 00:30:51 2010
@@ -87,7 +87,7 @@
match one of the glob-style *patterns* provided. See the example below.
-.. function:: copytree(src, dst, symlinks=False, ignore=None)
+.. function:: copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2)
Recursively copy an entire directory tree rooted at *src*. The destination
directory, named by *dst*, must not already exist; it will be created as well
@@ -111,9 +111,14 @@
If exception(s) occur, an :exc:`Error` is raised with a list of reasons.
- The source code for this should be considered an example rather than the
- ultimate tool.
-
+ If *copy_function* is given, it must be a callable that will be used
+ to copy each file. It will be called with the source path and the
+ destination path as arguments. By default, :func:`copy2` is used, but any
+ function that supports the same signature (like :func:`copy`) can be used.
+
+ .. versionchanged:: 3.2
+ Added the *copy_function* argument to be able to provide a custom copy
+ function.
.. function:: rmtree(path, ignore_errors=False, onerror=None)
Modified: python/branches/py3k/Lib/shutil.py
==============================================================================
--- python/branches/py3k/Lib/shutil.py (original)
+++ python/branches/py3k/Lib/shutil.py Tue Apr 20 00:30:51 2010
@@ -147,8 +147,8 @@
return set(ignored_names)
return _ignore_patterns
-def copytree(src, dst, symlinks=False, ignore=None):
- """Recursively copy a directory tree using copy2().
+def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2):
+ """Recursively copy a directory tree.
The destination directory must not already exist.
If exception(s) occur, an Error is raised with a list of reasons.
@@ -170,7 +170,10 @@
list of names relative to the `src` directory that should
not be copied.
- XXX Consider this example code rather than the ultimate tool.
+ The optional copy_function argument is a callable that will be used
+ to copy each file. It will be called with the source path and the
+ destination path as arguments. By default, copy2() is used, but any
+ function that supports the same signature (like copy()) can be used.
"""
names = os.listdir(src)
@@ -191,10 +194,10 @@
linkto = os.readlink(srcname)
os.symlink(linkto, dstname)
elif os.path.isdir(srcname):
- copytree(srcname, dstname, symlinks, ignore)
+ copytree(srcname, dstname, symlinks, ignore, copy_function)
else:
# Will raise a SpecialFileError for unsupported file types
- copy2(srcname, dstname)
+ copy_function(srcname, dstname)
# catch the Error from the recursive copytree so that we can
# continue with other files
except Error as err:
Modified: python/branches/py3k/Lib/test/test_shutil.py
==============================================================================
--- python/branches/py3k/Lib/test/test_shutil.py (original)
+++ python/branches/py3k/Lib/test/test_shutil.py Tue Apr 20 00:30:51 2010
@@ -74,6 +74,7 @@
d = tempfile.mkdtemp()
self.tempdirs.append(d)
return d
+
def test_rmtree_errors(self):
# filename is guaranteed not to exist
filename = tempfile.mktemp()
@@ -140,11 +141,12 @@
self.assertRaises(OSError, shutil.rmtree, path)
os.remove(path)
+ def _write_data(self, path, data):
+ f = open(path, "w")
+ f.write(data)
+ f.close()
+
def test_copytree_simple(self):
- def write_data(path, data):
- f = open(path, "w")
- f.write(data)
- f.close()
def read_data(path):
f = open(path)
@@ -154,11 +156,9 @@
src_dir = tempfile.mkdtemp()
dst_dir = os.path.join(tempfile.mkdtemp(), 'destination')
-
- write_data(os.path.join(src_dir, 'test.txt'), '123')
-
+ self._write_data(os.path.join(src_dir, 'test.txt'), '123')
os.mkdir(os.path.join(src_dir, 'test_dir'))
- write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456')
+ self._write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456')
try:
shutil.copytree(src_dir, dst_dir)
@@ -187,11 +187,6 @@
def test_copytree_with_exclude(self):
- def write_data(path, data):
- f = open(path, "w")
- f.write(data)
- f.close()
-
def read_data(path):
f = open(path)
data = f.read()
@@ -204,16 +199,18 @@
src_dir = tempfile.mkdtemp()
try:
dst_dir = join(tempfile.mkdtemp(), 'destination')
- write_data(join(src_dir, 'test.txt'), '123')
- write_data(join(src_dir, 'test.tmp'), '123')
+ self._write_data(join(src_dir, 'test.txt'), '123')
+ self._write_data(join(src_dir, 'test.tmp'), '123')
os.mkdir(join(src_dir, 'test_dir'))
- write_data(join(src_dir, 'test_dir', 'test.txt'), '456')
+ self._write_data(join(src_dir, 'test_dir', 'test.txt'), '456')
os.mkdir(join(src_dir, 'test_dir2'))
- write_data(join(src_dir, 'test_dir2', 'test.txt'), '456')
+ self._write_data(join(src_dir, 'test_dir2', 'test.txt'), '456')
os.mkdir(join(src_dir, 'test_dir2', 'subdir'))
os.mkdir(join(src_dir, 'test_dir2', 'subdir2'))
- write_data(join(src_dir, 'test_dir2', 'subdir', 'test.txt'), '456')
- write_data(join(src_dir, 'test_dir2', 'subdir2', 'test.py'), '456')
+ self._write_data(join(src_dir, 'test_dir2', 'subdir', 'test.txt'),
+ '456')
+ self._write_data(join(src_dir, 'test_dir2', 'subdir2', 'test.py'),
+ '456')
# testing glob-like patterns
@@ -339,6 +336,21 @@
shutil.rmtree(TESTFN, ignore_errors=True)
shutil.rmtree(TESTFN2, ignore_errors=True)
+ def test_copytree_special_func(self):
+
+ src_dir = self.mkdtemp()
+ dst_dir = os.path.join(self.mkdtemp(), 'destination')
+ self._write_data(os.path.join(src_dir, 'test.txt'), '123')
+ os.mkdir(os.path.join(src_dir, 'test_dir'))
+ self._write_data(os.path.join(src_dir, 'test_dir', 'test.txt'), '456')
+
+ copied = []
+ def _copy(src, dst):
+ copied.append((src, dst))
+
+ shutil.copytree(src_dir, dst_dir, copy_function=_copy)
+ self.assertEquals(len(copied), 2)
+
@unittest.skipUnless(zlib, "requires zlib")
def test_make_tarball(self):
# creating something to tar
@@ -728,6 +740,7 @@
finally:
shutil.rmtree(TESTFN, ignore_errors=True)
+
def test_main():
support.run_unittest(TestShutil, TestMove)
Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS (original)
+++ python/branches/py3k/Misc/NEWS Tue Apr 20 00:30:51 2010
@@ -318,6 +318,9 @@
Library
-------
+- Issue #1540112: Now allowing the choice of a copy function in
+ shutil.copytree.
+
- Issue #4814: timeout parameter is now applied also for connections resulting
from PORT/EPRT commands.
More information about the Python-checkins
mailing list