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

gh-103363: Add follow_symlinks argument topathlib.Path.owner() andgroup()#107962

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
barneygale merged 10 commits intopython:mainfromkamilturek:gh-103363
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletionsDoc/library/pathlib.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1017,15 +1017,21 @@ call fails (for example because the path doesn't exist).
future Python release, patterns with this ending will match both files
and directories. Add a trailing slash to match only directories.

.. method:: Path.group()
.. method:: Path.group(*, follow_symlinks=True)

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

This method normally follows symlinks; to get the group of the symlink, add
the argument ``follow_symlinks=False``.

.. versionchanged:: 3.13
Raises :exc:`UnsupportedOperation` if the :mod:`grp` module is not
available. In previous versions, :exc:`NotImplementedError` was raised.

.. versionchanged:: 3.13
The *follow_symlinks* parameter was added.


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

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


.. method:: Path.owner()
.. method:: Path.owner(*, follow_symlinks=True)

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

This method normally follows symlinks; to get the owner of the symlink, add
the argument ``follow_symlinks=False``.

.. versionchanged:: 3.13
Raises :exc:`UnsupportedOperation` if the :mod:`pwd` module is not
available. In previous versions, :exc:`NotImplementedError` was raised.

.. versionchanged:: 3.13
The *follow_symlinks* parameter was added.


.. method:: Path.read_bytes()

Expand Down
8 changes: 5 additions & 3 deletionsDoc/whatsnew/3.13.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -270,9 +270,11 @@ pathlib
(Contributed by Barney Gale in :gh:`73435`.)

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

pdb
---
Expand Down
14 changes: 8 additions & 6 deletionsLib/pathlib.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1319,13 +1319,13 @@ def rmdir(self):
"""
self._unsupported("rmdir")

def owner(self):
def owner(self, *, follow_symlinks=True):
"""
Return the login name of the file owner.
"""
self._unsupported("owner")

def group(self):
def group(self, *, follow_symlinks=True):
"""
Return the group name of the file gid.
"""
Expand DownExpand Up@@ -1440,18 +1440,20 @@ def resolve(self, strict=False):
return self.with_segments(os.path.realpath(self, strict=strict))

if pwd:
def owner(self):
def owner(self, *, follow_symlinks=True):
"""
Return the login name of the file owner.
"""
return pwd.getpwuid(self.stat().st_uid).pw_name
uid = self.stat(follow_symlinks=follow_symlinks).st_uid
return pwd.getpwuid(uid).pw_name

if grp:
def group(self):
def group(self, *, follow_symlinks=True):
"""
Return the group name of the file gid.
"""
return grp.getgrgid(self.stat().st_gid).gr_name
gid = self.stat(follow_symlinks=follow_symlinks).st_gid
return grp.getgrgid(gid).gr_name

if hasattr(os, "readlink"):
def readlink(self):
Expand Down
73 changes: 62 additions & 11 deletionsLib/test/test_pathlib.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -41,6 +41,9 @@ def test_is_notimplemented(self):
only_posix = unittest.skipIf(os.name == 'nt',
'test requires a POSIX-compatible system')

root_in_posix = False
if hasattr(os, 'geteuid'):
root_in_posix = (os.geteuid() == 0)

#
# Tests for the pure classes.
Expand DownExpand Up@@ -2975,27 +2978,75 @@ def test_chmod_follow_symlinks_true(self):

# XXX also need a test for lchmod.

@unittest.skipUnless(pwd, "the pwd module is needed for this test")
def test_owner(self):
p = self.cls(BASE) / 'fileA'
uid = p.stat().st_uid
def _get_pw_name_or_skip_test(self, uid):
try:
name = pwd.getpwuid(uid).pw_name
return pwd.getpwuid(uid).pw_name
except KeyError:
self.skipTest(
"user %d doesn't have an entry in the system database" % uid)
self.assertEqual(name, p.owner())

@unittest.skipUnless(grp, "thegrp module is needed for this test")
deftest_group(self):
@unittest.skipUnless(pwd, "thepwd module is needed for this test")
deftest_owner(self):
p = self.cls(BASE) / 'fileA'
gid = p.stat().st_gid
expected_uid = p.stat().st_uid
expected_name = self._get_pw_name_or_skip_test(expected_uid)

self.assertEqual(expected_name, p.owner())

@unittest.skipUnless(pwd, "the pwd module is needed for this test")
@unittest.skipUnless(root_in_posix, "test needs root privilege")
def test_owner_no_follow_symlinks(self):
all_users = [u.pw_uid for u in pwd.getpwall()]
if len(all_users) < 2:
self.skipTest("test needs more than one user")

target = self.cls(BASE) / 'fileA'
link = self.cls(BASE) / 'linkA'

uid_1, uid_2 = all_users[:2]
os.chown(target, uid_1, -1)
os.chown(link, uid_2, -1, follow_symlinks=False)

expected_uid = link.stat(follow_symlinks=False).st_uid
expected_name = self._get_pw_name_or_skip_test(expected_uid)

self.assertEqual(expected_uid, uid_2)
self.assertEqual(expected_name, link.owner(follow_symlinks=False))

def _get_gr_name_or_skip_test(self, gid):
try:
name = grp.getgrgid(gid).gr_name
return grp.getgrgid(gid).gr_name
except KeyError:
self.skipTest(
"group %d doesn't have an entry in the system database" % gid)
self.assertEqual(name, p.group())

@unittest.skipUnless(grp, "the grp module is needed for this test")
def test_group(self):
p = self.cls(BASE) / 'fileA'
expected_gid = p.stat().st_gid
expected_name = self._get_gr_name_or_skip_test(expected_gid)

self.assertEqual(expected_name, p.group())

@unittest.skipUnless(grp, "the grp module is needed for this test")
@unittest.skipUnless(root_in_posix, "test needs root privilege")
def test_group_no_follow_symlinks(self):
all_groups = [g.gr_gid for g in grp.getgrall()]
if len(all_groups) < 2:
self.skipTest("test needs more than one group")

target = self.cls(BASE) / 'fileA'
link = self.cls(BASE) / 'linkA'

gid_1, gid_2 = all_groups[:2]
os.chown(target, -1, gid_1)
os.chown(link, -1, gid_2, follow_symlinks=False)

expected_gid = link.stat(follow_symlinks=False).st_gid
expected_name = self._get_pw_name_or_skip_test(expected_gid)

self.assertEqual(expected_gid, gid_2)
self.assertEqual(expected_name, link.group(follow_symlinks=False))

def test_unlink(self):
p = self.cls(BASE) / 'fileA'
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
Add *follow_symlinks* keyword-only argument to :meth:`pathlib.Path.owner`
and :meth:`~pathlib.Path.group`, defaulting to ``True``.

[8]ページ先頭

©2009-2025 Movatter.jp