Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita1551b4

Browse files
authored
gh-103363: Add follow_symlinks argument topathlib.Path.owner() andgroup() (#107962)
1 parent2ed20d3 commita1551b4

File tree

5 files changed

+93
-24
lines changed

5 files changed

+93
-24
lines changed

‎Doc/library/pathlib.rst

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,15 +1017,21 @@ call fails (for example because the path doesn't exist).
10171017
future Python release, patterns with this ending will match both files
10181018
and directories. Add a trailing slash to match only directories.
10191019

1020-
..method::Path.group()
1020+
..method::Path.group(*, follow_symlinks=True)
10211021

1022-
Return the name of the group owning the file.:exc:`KeyError` is raised
1022+
Return the name of the group owning the file.:exc:`KeyError` is raised
10231023
if the file's gid isn't found in the system database.
10241024

1025+
This method normally follows symlinks; to get the group of the symlink, add
1026+
the argument ``follow_symlinks=False``.
1027+
10251028
..versionchanged::3.13
10261029
Raises:exc:`UnsupportedOperation` if the:mod:`grp` module is not
10271030
available. In previous versions,:exc:`NotImplementedError` was raised.
10281031

1032+
..versionchanged::3.13
1033+
The *follow_symlinks* parameter was added.
1034+
10291035

10301036
..method::Path.is_dir(*, follow_symlinks=True)
10311037

@@ -1291,15 +1297,21 @@ call fails (for example because the path doesn't exist).
12911297
'#!/usr/bin/env python3\n'
12921298

12931299

1294-
..method::Path.owner()
1300+
..method::Path.owner(*, follow_symlinks=True)
12951301

1296-
Return the name of the user owning the file.:exc:`KeyError` is raised
1302+
Return the name of the user owning the file.:exc:`KeyError` is raised
12971303
if the file's uid isn't found in the system database.
12981304

1305+
This method normally follows symlinks; to get the owner of the symlink, add
1306+
the argument ``follow_symlinks=False``.
1307+
12991308
..versionchanged::3.13
13001309
Raises:exc:`UnsupportedOperation` if the:mod:`pwd` module is not
13011310
available. In previous versions,:exc:`NotImplementedError` was raised.
13021311

1312+
..versionchanged::3.13
1313+
The *follow_symlinks* parameter was added.
1314+
13031315

13041316
..method::Path.read_bytes()
13051317

‎Doc/whatsnew/3.13.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,11 @@ pathlib
270270
(Contributed by Barney Gale in:gh:`73435`.)
271271

272272
* Add *follow_symlinks* keyword-only argument to:meth:`pathlib.Path.glob`,
273-
:meth:`~pathlib.Path.rglob`,:meth:`~pathlib.Path.is_file`, and
274-
:meth:`~pathlib.Path.is_dir`.
275-
(Contributed by Barney Gale in:gh:`77609` and:gh:`105793`.)
273+
:meth:`~pathlib.Path.rglob`,:meth:`~pathlib.Path.is_file`,
274+
:meth:`~pathlib.Path.is_dir`,:meth:`~pathlib.Path.owner`,
275+
:meth:`~pathlib.Path.group`.
276+
(Contributed by Barney Gale in:gh:`77609` and:gh:`105793`, and
277+
Kamil Turek in:gh:`107962`).
276278

277279
pdb
278280
---

‎Lib/pathlib.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,13 +1319,13 @@ def rmdir(self):
13191319
"""
13201320
self._unsupported("rmdir")
13211321

1322-
defowner(self):
1322+
defowner(self,*,follow_symlinks=True):
13231323
"""
13241324
Return the login name of the file owner.
13251325
"""
13261326
self._unsupported("owner")
13271327

1328-
defgroup(self):
1328+
defgroup(self,*,follow_symlinks=True):
13291329
"""
13301330
Return the group name of the file gid.
13311331
"""
@@ -1440,18 +1440,20 @@ def resolve(self, strict=False):
14401440
returnself.with_segments(os.path.realpath(self,strict=strict))
14411441

14421442
ifpwd:
1443-
defowner(self):
1443+
defowner(self,*,follow_symlinks=True):
14441444
"""
14451445
Return the login name of the file owner.
14461446
"""
1447-
returnpwd.getpwuid(self.stat().st_uid).pw_name
1447+
uid=self.stat(follow_symlinks=follow_symlinks).st_uid
1448+
returnpwd.getpwuid(uid).pw_name
14481449

14491450
ifgrp:
1450-
defgroup(self):
1451+
defgroup(self,*,follow_symlinks=True):
14511452
"""
14521453
Return the group name of the file gid.
14531454
"""
1454-
returngrp.getgrgid(self.stat().st_gid).gr_name
1455+
gid=self.stat(follow_symlinks=follow_symlinks).st_gid
1456+
returngrp.getgrgid(gid).gr_name
14551457

14561458
ifhasattr(os,"readlink"):
14571459
defreadlink(self):

‎Lib/test/test_pathlib.py

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ def test_is_notimplemented(self):
4141
only_posix=unittest.skipIf(os.name=='nt',
4242
'test requires a POSIX-compatible system')
4343

44+
root_in_posix=False
45+
ifhasattr(os,'geteuid'):
46+
root_in_posix= (os.geteuid()==0)
4447

4548
#
4649
# Tests for the pure classes.
@@ -2975,27 +2978,75 @@ def test_chmod_follow_symlinks_true(self):
29752978

29762979
# XXX also need a test for lchmod.
29772980

2978-
@unittest.skipUnless(pwd,"the pwd module is needed for this test")
2979-
deftest_owner(self):
2980-
p=self.cls(BASE)/'fileA'
2981-
uid=p.stat().st_uid
2981+
def_get_pw_name_or_skip_test(self,uid):
29822982
try:
2983-
name=pwd.getpwuid(uid).pw_name
2983+
returnpwd.getpwuid(uid).pw_name
29842984
exceptKeyError:
29852985
self.skipTest(
29862986
"user %d doesn't have an entry in the system database"%uid)
2987-
self.assertEqual(name,p.owner())
29882987

2989-
@unittest.skipUnless(grp,"thegrp module is needed for this test")
2990-
deftest_group(self):
2988+
@unittest.skipUnless(pwd,"thepwd module is needed for this test")
2989+
deftest_owner(self):
29912990
p=self.cls(BASE)/'fileA'
2992-
gid=p.stat().st_gid
2991+
expected_uid=p.stat().st_uid
2992+
expected_name=self._get_pw_name_or_skip_test(expected_uid)
2993+
2994+
self.assertEqual(expected_name,p.owner())
2995+
2996+
@unittest.skipUnless(pwd,"the pwd module is needed for this test")
2997+
@unittest.skipUnless(root_in_posix,"test needs root privilege")
2998+
deftest_owner_no_follow_symlinks(self):
2999+
all_users= [u.pw_uidforuinpwd.getpwall()]
3000+
iflen(all_users)<2:
3001+
self.skipTest("test needs more than one user")
3002+
3003+
target=self.cls(BASE)/'fileA'
3004+
link=self.cls(BASE)/'linkA'
3005+
3006+
uid_1,uid_2=all_users[:2]
3007+
os.chown(target,uid_1,-1)
3008+
os.chown(link,uid_2,-1,follow_symlinks=False)
3009+
3010+
expected_uid=link.stat(follow_symlinks=False).st_uid
3011+
expected_name=self._get_pw_name_or_skip_test(expected_uid)
3012+
3013+
self.assertEqual(expected_uid,uid_2)
3014+
self.assertEqual(expected_name,link.owner(follow_symlinks=False))
3015+
3016+
def_get_gr_name_or_skip_test(self,gid):
29933017
try:
2994-
name=grp.getgrgid(gid).gr_name
3018+
returngrp.getgrgid(gid).gr_name
29953019
exceptKeyError:
29963020
self.skipTest(
29973021
"group %d doesn't have an entry in the system database"%gid)
2998-
self.assertEqual(name,p.group())
3022+
3023+
@unittest.skipUnless(grp,"the grp module is needed for this test")
3024+
deftest_group(self):
3025+
p=self.cls(BASE)/'fileA'
3026+
expected_gid=p.stat().st_gid
3027+
expected_name=self._get_gr_name_or_skip_test(expected_gid)
3028+
3029+
self.assertEqual(expected_name,p.group())
3030+
3031+
@unittest.skipUnless(grp,"the grp module is needed for this test")
3032+
@unittest.skipUnless(root_in_posix,"test needs root privilege")
3033+
deftest_group_no_follow_symlinks(self):
3034+
all_groups= [g.gr_gidforgingrp.getgrall()]
3035+
iflen(all_groups)<2:
3036+
self.skipTest("test needs more than one group")
3037+
3038+
target=self.cls(BASE)/'fileA'
3039+
link=self.cls(BASE)/'linkA'
3040+
3041+
gid_1,gid_2=all_groups[:2]
3042+
os.chown(target,-1,gid_1)
3043+
os.chown(link,-1,gid_2,follow_symlinks=False)
3044+
3045+
expected_gid=link.stat(follow_symlinks=False).st_gid
3046+
expected_name=self._get_pw_name_or_skip_test(expected_gid)
3047+
3048+
self.assertEqual(expected_gid,gid_2)
3049+
self.assertEqual(expected_name,link.group(follow_symlinks=False))
29993050

30003051
deftest_unlink(self):
30013052
p=self.cls(BASE)/'fileA'
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add *follow_symlinks* keyword-only argument to:meth:`pathlib.Path.owner`
2+
and:meth:`~pathlib.Path.group`, defaulting to ``True``.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp