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
.. function:: copy2(src, dst[, symlinks=False])
Similar to :func:`shutil.copy`, but metadata is copied as well -- in fact,
this is just :func:`shutil.copy` followed by :func:`copystat`. This is
Similar to :func:`shutil.copy`, but metadata is copied as well. This is
similar to the Unix command :program:`cp -p`. If *symlinks* is true,
symbolic links won't be followed but recreated instead -- this resembles
GNU's :program:`cp -P`.
.. versionchanged:: 3.3
Added *symlinks* argument.
Added *symlinks* argument, try to copy extended file system attributes
too (currently Linux only).
.. function:: ignore_patterns(\*patterns)
...
...
Lib/shutil.py
Dosyayı görüntüle @
424246fb
...
...
@@ -166,6 +166,36 @@ def copystat(src, dst, symlinks=False):
else
:
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
):
"""Copy data and mode bits ("cp src dst").
...
...
@@ -193,6 +223,7 @@ def copy2(src, dst, symlinks=False):
dst
=
os
.
path
.
join
(
dst
,
os
.
path
.
basename
(
src
))
copyfile
(
src
,
dst
,
symlinks
=
symlinks
)
copystat
(
src
,
dst
,
symlinks
=
symlinks
)
_copyxattr
(
src
,
dst
,
symlinks
=
symlinks
)
def
ignore_patterns
(
*
patterns
):
"""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):
msg
=
"Requires functional symlink implementation"
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
):
"""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):
raise
def
supports_extended_attributes
():
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"
)
@support.skip_unless_xattr
class
ExtendedAttributeTests
(
unittest
.
TestCase
):
def
tearDown
(
self
):
...
...
Lib/test/test_shutil.py
Dosyayı görüntüle @
424246fb
...
...
@@ -311,6 +311,67 @@ class TestShutil(unittest.TestCase):
finally
:
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
def
test_copy_symlinks
(
self
):
tmp_dir
=
self
.
mkdtemp
()
...
...
@@ -369,6 +430,19 @@ class TestShutil(unittest.TestCase):
if
hasattr
(
os
,
'lchflags'
)
and
hasattr
(
src_link_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
def
test_copyfile_symlinks
(
self
):
tmp_dir
=
self
.
mkdtemp
()
...
...
Misc/NEWS
Dosyayı görüntüle @
424246fb
...
...
@@ -23,6 +23,9 @@ Core and Builtins
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
importlib.machinery.ExtensionFileLoader.load_module() have their single
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