Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
424246fb
Kaydet (Commit)
424246fb
authored
May 12, 2012
tarafından
Antoine Pitrou
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #14082: shutil.copy2() now copies extended attributes, if possible.
Patch by Hynek Schlawack.
üst
4d688e32
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
141 additions
and
22 deletions
+141
-22
shutil.rst
Doc/library/shutil.rst
+3
-3
shutil.py
Lib/shutil.py
+31
-0
support.py
Lib/test/support.py
+29
-0
test_os.py
Lib/test/test_os.py
+1
-19
test_shutil.py
Lib/test/test_shutil.py
+74
-0
NEWS
Misc/NEWS
+3
-0
No files found.
Doc/library/shutil.rst
Dosyayı görüntüle @
424246fb
...
@@ -102,14 +102,14 @@ Directory and files operations
...
@@ -102,14 +102,14 @@ Directory and files operations
.. function:: copy2(src, dst[, symlinks=False])
.. function:: copy2(src, dst[, symlinks=False])
Similar to :func:`shutil.copy`, but metadata is copied as well -- in fact,
Similar to :func:`shutil.copy`, but metadata is copied as well. This is
this is just :func:`shutil.copy` followed by :func:`copystat`. This is
similar to the Unix command :program:`cp -p`. If *symlinks* is true,
similar to the Unix command :program:`cp -p`. If *symlinks* is true,
symbolic links won't be followed but recreated instead -- this resembles
symbolic links won't be followed but recreated instead -- this resembles
GNU's :program:`cp -P`.
GNU's :program:`cp -P`.
.. versionchanged:: 3.3
.. versionchanged:: 3.3
Added *symlinks* argument.
Added *symlinks* argument, try to copy extended file system attributes
too (currently Linux only).
.. function:: ignore_patterns(\*patterns)
.. function:: ignore_patterns(\*patterns)
...
...
Lib/shutil.py
Dosyayı görüntüle @
424246fb
...
@@ -166,6 +166,36 @@ def copystat(src, dst, symlinks=False):
...
@@ -166,6 +166,36 @@ def copystat(src, dst, symlinks=False):
else
:
else
:
raise
raise
if
hasattr
(
os
,
'listxattr'
):
def
_copyxattr
(
src
,
dst
,
symlinks
=
False
):
"""Copy extended filesystem attributes from `src` to `dst`.
Overwrite existing attributes.
If the optional flag `symlinks` is set, symlinks won't be followed.
"""
if
symlinks
:
listxattr
=
os
.
llistxattr
removexattr
=
os
.
lremovexattr
setxattr
=
os
.
lsetxattr
getxattr
=
os
.
lgetxattr
else
:
listxattr
=
os
.
listxattr
removexattr
=
os
.
removexattr
setxattr
=
os
.
setxattr
getxattr
=
os
.
getxattr
for
attr
in
listxattr
(
src
):
try
:
setxattr
(
dst
,
attr
,
getxattr
(
src
,
attr
))
except
OSError
as
e
:
if
e
.
errno
not
in
(
errno
.
EPERM
,
errno
.
ENOTSUP
,
errno
.
ENODATA
):
raise
else
:
def
_copyxattr
(
*
args
,
**
kwargs
):
pass
def
copy
(
src
,
dst
,
symlinks
=
False
):
def
copy
(
src
,
dst
,
symlinks
=
False
):
"""Copy data and mode bits ("cp src dst").
"""Copy data and mode bits ("cp src dst").
...
@@ -193,6 +223,7 @@ def copy2(src, dst, symlinks=False):
...
@@ -193,6 +223,7 @@ def copy2(src, dst, symlinks=False):
dst
=
os
.
path
.
join
(
dst
,
os
.
path
.
basename
(
src
))
dst
=
os
.
path
.
join
(
dst
,
os
.
path
.
basename
(
src
))
copyfile
(
src
,
dst
,
symlinks
=
symlinks
)
copyfile
(
src
,
dst
,
symlinks
=
symlinks
)
copystat
(
src
,
dst
,
symlinks
=
symlinks
)
copystat
(
src
,
dst
,
symlinks
=
symlinks
)
_copyxattr
(
src
,
dst
,
symlinks
=
symlinks
)
def
ignore_patterns
(
*
patterns
):
def
ignore_patterns
(
*
patterns
):
"""Function that can be used as copytree() ignore parameter.
"""Function that can be used as copytree() ignore parameter.
...
...
Lib/test/support.py
Dosyayı görüntüle @
424246fb
...
@@ -1696,6 +1696,35 @@ def skip_unless_symlink(test):
...
@@ -1696,6 +1696,35 @@ def skip_unless_symlink(test):
msg
=
"Requires functional symlink implementation"
msg
=
"Requires functional symlink implementation"
return
test
if
ok
else
unittest
.
skip
(
msg
)(
test
)
return
test
if
ok
else
unittest
.
skip
(
msg
)(
test
)
_can_xattr
=
None
def
can_xattr
():
global
_can_xattr
if
_can_xattr
is
not
None
:
return
_can_xattr
if
not
hasattr
(
os
,
"setxattr"
):
can
=
False
else
:
try
:
with
open
(
TESTFN
,
"wb"
)
as
fp
:
try
:
os
.
fsetxattr
(
fp
.
fileno
(),
b
"user.test"
,
b
""
)
# Kernels < 2.6.39 don't respect setxattr flags.
kernel_version
=
platform
.
release
()
m
=
re
.
match
(
"2.6.(
\
d{1,2})"
,
kernel_version
)
can
=
m
is
None
or
int
(
m
.
group
(
1
))
>=
39
except
OSError
:
can
=
False
finally
:
unlink
(
TESTFN
)
_can_xattr
=
can
return
can
def
skip_unless_xattr
(
test
):
"""Skip decorator for tests that require functional extended attributes"""
ok
=
can_xattr
()
msg
=
"no non-broken extended attribute support"
return
test
if
ok
else
unittest
.
skip
(
msg
)(
test
)
def
patch
(
test_instance
,
object_to_patch
,
attr_name
,
new_value
):
def
patch
(
test_instance
,
object_to_patch
,
attr_name
,
new_value
):
"""Override 'object_to_patch'.'attr_name' with 'new_value'.
"""Override 'object_to_patch'.'attr_name' with 'new_value'.
...
...
Lib/test/test_os.py
Dosyayı görüntüle @
424246fb
...
@@ -1810,25 +1810,7 @@ class TestSendfile(unittest.TestCase):
...
@@ -1810,25 +1810,7 @@ class TestSendfile(unittest.TestCase):
raise
raise
def
supports_extended_attributes
():
@support.skip_unless_xattr
if
not
hasattr
(
os
,
"setxattr"
):
return
False
try
:
with
open
(
support
.
TESTFN
,
"wb"
)
as
fp
:
try
:
os
.
fsetxattr
(
fp
.
fileno
(),
b
"user.test"
,
b
""
)
except
OSError
:
return
False
finally
:
support
.
unlink
(
support
.
TESTFN
)
# Kernels < 2.6.39 don't respect setxattr flags.
kernel_version
=
platform
.
release
()
m
=
re
.
match
(
"2.6.(
\
d{1,2})"
,
kernel_version
)
return
m
is
None
or
int
(
m
.
group
(
1
))
>=
39
@unittest.skipUnless
(
supports_extended_attributes
(),
"no non-broken extended attribute support"
)
class
ExtendedAttributeTests
(
unittest
.
TestCase
):
class
ExtendedAttributeTests
(
unittest
.
TestCase
):
def
tearDown
(
self
):
def
tearDown
(
self
):
...
...
Lib/test/test_shutil.py
Dosyayı görüntüle @
424246fb
...
@@ -311,6 +311,67 @@ class TestShutil(unittest.TestCase):
...
@@ -311,6 +311,67 @@ class TestShutil(unittest.TestCase):
finally
:
finally
:
os
.
chflags
=
old_chflags
os
.
chflags
=
old_chflags
@support.skip_unless_xattr
def
test_copyxattr
(
self
):
tmp_dir
=
self
.
mkdtemp
()
src
=
os
.
path
.
join
(
tmp_dir
,
'foo'
)
write_file
(
src
,
'foo'
)
dst
=
os
.
path
.
join
(
tmp_dir
,
'bar'
)
write_file
(
dst
,
'bar'
)
# no xattr == no problem
shutil
.
_copyxattr
(
src
,
dst
)
# common case
os
.
setxattr
(
src
,
'user.foo'
,
b
'42'
)
os
.
setxattr
(
src
,
'user.bar'
,
b
'43'
)
shutil
.
_copyxattr
(
src
,
dst
)
self
.
assertEqual
(
os
.
listxattr
(
src
),
os
.
listxattr
(
dst
))
self
.
assertEqual
(
os
.
getxattr
(
src
,
'user.foo'
),
os
.
getxattr
(
dst
,
'user.foo'
))
# check errors don't affect other attrs
os
.
remove
(
dst
)
write_file
(
dst
,
'bar'
)
os_error
=
OSError
(
errno
.
EPERM
,
'EPERM'
)
def
_raise_on_user_foo
(
fname
,
attr
,
val
):
if
attr
==
'user.foo'
:
raise
os_error
else
:
orig_setxattr
(
fname
,
attr
,
val
)
try
:
orig_setxattr
=
os
.
setxattr
os
.
setxattr
=
_raise_on_user_foo
shutil
.
_copyxattr
(
src
,
dst
)
self
.
assertEqual
([
'user.bar'
],
os
.
listxattr
(
dst
))
finally
:
os
.
setxattr
=
orig_setxattr
@support.skip_unless_symlink
@support.skip_unless_xattr
@unittest.skipUnless
(
hasattr
(
os
,
'geteuid'
)
and
os
.
geteuid
()
==
0
,
'root privileges required'
)
def
test_copyxattr_symlinks
(
self
):
# On Linux, it's only possible to access non-user xattr for symlinks;
# which in turn require root privileges. This test should be expanded
# as soon as other platforms gain support for extended attributes.
tmp_dir
=
self
.
mkdtemp
()
src
=
os
.
path
.
join
(
tmp_dir
,
'foo'
)
src_link
=
os
.
path
.
join
(
tmp_dir
,
'baz'
)
write_file
(
src
,
'foo'
)
os
.
symlink
(
src
,
src_link
)
os
.
setxattr
(
src
,
'trusted.foo'
,
b
'42'
)
os
.
lsetxattr
(
src_link
,
'trusted.foo'
,
b
'43'
)
dst
=
os
.
path
.
join
(
tmp_dir
,
'bar'
)
dst_link
=
os
.
path
.
join
(
tmp_dir
,
'qux'
)
write_file
(
dst
,
'bar'
)
os
.
symlink
(
dst
,
dst_link
)
shutil
.
_copyxattr
(
src_link
,
dst_link
,
symlinks
=
True
)
self
.
assertEqual
(
os
.
lgetxattr
(
dst_link
,
'trusted.foo'
),
b
'43'
)
self
.
assertRaises
(
OSError
,
os
.
getxattr
,
dst
,
'trusted.foo'
)
shutil
.
_copyxattr
(
src_link
,
dst
,
symlinks
=
True
)
self
.
assertEqual
(
os
.
getxattr
(
dst
,
'trusted.foo'
),
b
'43'
)
@support.skip_unless_symlink
@support.skip_unless_symlink
def
test_copy_symlinks
(
self
):
def
test_copy_symlinks
(
self
):
tmp_dir
=
self
.
mkdtemp
()
tmp_dir
=
self
.
mkdtemp
()
...
@@ -369,6 +430,19 @@ class TestShutil(unittest.TestCase):
...
@@ -369,6 +430,19 @@ class TestShutil(unittest.TestCase):
if
hasattr
(
os
,
'lchflags'
)
and
hasattr
(
src_link_stat
,
'st_flags'
):
if
hasattr
(
os
,
'lchflags'
)
and
hasattr
(
src_link_stat
,
'st_flags'
):
self
.
assertEqual
(
src_link_stat
.
st_flags
,
dst_stat
.
st_flags
)
self
.
assertEqual
(
src_link_stat
.
st_flags
,
dst_stat
.
st_flags
)
@support.skip_unless_xattr
def
test_copy2_xattr
(
self
):
tmp_dir
=
self
.
mkdtemp
()
src
=
os
.
path
.
join
(
tmp_dir
,
'foo'
)
dst
=
os
.
path
.
join
(
tmp_dir
,
'bar'
)
write_file
(
src
,
'foo'
)
os
.
setxattr
(
src
,
'user.foo'
,
b
'42'
)
shutil
.
copy2
(
src
,
dst
)
self
.
assertEqual
(
os
.
getxattr
(
src
,
'user.foo'
),
os
.
getxattr
(
dst
,
'user.foo'
))
os
.
remove
(
dst
)
@support.skip_unless_symlink
@support.skip_unless_symlink
def
test_copyfile_symlinks
(
self
):
def
test_copyfile_symlinks
(
self
):
tmp_dir
=
self
.
mkdtemp
()
tmp_dir
=
self
.
mkdtemp
()
...
...
Misc/NEWS
Dosyayı görüntüle @
424246fb
...
@@ -23,6 +23,9 @@ Core and Builtins
...
@@ -23,6 +23,9 @@ Core and Builtins
Library
Library
-------
-------
- Issue #14082: shutil.copy2() now copies extended attributes, if possible.
Patch by Hynek Schlawack.
- Issue #13959: Make importlib.abc.FileLoader.load_module()/get_filename() and
- Issue #13959: Make importlib.abc.FileLoader.load_module()/get_filename() and
importlib.machinery.ExtensionFileLoader.load_module() have their single
importlib.machinery.ExtensionFileLoader.load_module() have their single
argument be optional. Allows for the replacement (and thus deprecation) of
argument be optional. Allows for the replacement (and thus deprecation) of
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment