Last active
December 10, 2015 00:09
-
-
Save mistydemeo/4349132 to your computer and use it in GitHub Desktop.
Python 2.7.3: fix shutil.copystat() for nfs, etc.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# HG changeset patch | |
# User Ned Deily <[email protected]> | |
# Date 1336697149 25200 | |
# Node ID e12efebc3ba6fb2f5b2a787d894e479d19721271 | |
# Parent 63bde882e311ad1970c97c4ad3dbddf2d1e4be15 | |
Issue #14662: Prevent shutil failures on OS X when destination does not | |
support chflag operations. (Patch by Hynek Schlawack) | |
diff --git a/Lib/shutil.py b/Lib/shutil.py | |
--- a/Lib/shutil.py | |
+++ b/Lib/shutil.py | |
@@ -102,8 +102,10 @@ def copystat(src, dst): | |
try: | |
os.chflags(dst, st.st_flags) | |
except OSError, why: | |
- if (not hasattr(errno, 'EOPNOTSUPP') or | |
- why.errno != errno.EOPNOTSUPP): | |
+ for err in 'EOPNOTSUPP', 'ENOTSUP': | |
+ if hasattr(errno, err) and why.errno == getattr(errno, err): | |
+ break | |
+ else: | |
raise | |
def copy(src, dst): | |
diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py | |
--- a/Lib/test/test_shutil.py | |
+++ b/Lib/test/test_shutil.py | |
@@ -7,6 +7,7 @@ import sys | |
import stat | |
import os | |
import os.path | |
+import errno | |
from os.path import splitdrive | |
from distutils.spawn import find_executable, spawn | |
from shutil import (_make_tarball, _make_zipfile, make_archive, | |
@@ -339,6 +340,35 @@ class TestShutil(unittest.TestCase): | |
shutil.rmtree(TESTFN, ignore_errors=True) | |
shutil.rmtree(TESTFN2, ignore_errors=True) | |
+ @unittest.skipUnless(hasattr(os, 'chflags') and | |
+ hasattr(errno, 'EOPNOTSUPP') and | |
+ hasattr(errno, 'ENOTSUP'), | |
+ "requires os.chflags, EOPNOTSUPP & ENOTSUP") | |
+ def test_copystat_handles_harmless_chflags_errors(self): | |
+ tmpdir = self.mkdtemp() | |
+ file1 = os.path.join(tmpdir, 'file1') | |
+ file2 = os.path.join(tmpdir, 'file2') | |
+ self.write_file(file1, 'xxx') | |
+ self.write_file(file2, 'xxx') | |
+ | |
+ def make_chflags_raiser(err): | |
+ ex = OSError() | |
+ | |
+ def _chflags_raiser(path, flags): | |
+ ex.errno = err | |
+ raise ex | |
+ return _chflags_raiser | |
+ old_chflags = os.chflags | |
+ try: | |
+ for err in errno.EOPNOTSUPP, errno.ENOTSUP: | |
+ os.chflags = make_chflags_raiser(err) | |
+ shutil.copystat(file1, file2) | |
+ # assert others errors break it | |
+ os.chflags = make_chflags_raiser(errno.EOPNOTSUPP + errno.ENOTSUP) | |
+ self.assertRaises(OSError, shutil.copystat, file1, file2) | |
+ finally: | |
+ os.chflags = old_chflags | |
+ | |
@unittest.skipUnless(zlib, "requires zlib") | |
def test_make_tarball(self): | |
# creating something to tar | |
diff --git a/Modules/errnomodule.c b/Modules/errnomodule.c | |
--- a/Modules/errnomodule.c | |
+++ b/Modules/errnomodule.c | |
@@ -783,6 +783,9 @@ initerrno(void) | |
#ifdef WSAN | |
inscode(d, ds, de, "WSAN", WSAN, "Error WSAN"); | |
#endif | |
+#ifdef ENOTSUP | |
+ inscode(d, ds, de, "ENOTSUP", ENOTSUP, "Operation not supported"); | |
+#endif | |
Py_DECREF(de); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment