Skip to content

Commit

Permalink
Add attribute access for some moved constants back to fake_filesystem
Browse files Browse the repository at this point in the history
- some if these had been accessed in user code,
  which caused a regression
- add convenience function get_uid()/get_gid()
- fixes pytest-dev#809
  • Loading branch information
mrbean-bremen committed Apr 12, 2023
1 parent 1906fde commit 45c2135
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 12 deletions.
8 changes: 8 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@ The released versions correspond to PyPI releases.

## Unreleased

### Changes
* Made the user and group IDs accessible via dedicated ``get_uid`` and ``get_gid``
functions (for symmetry to ``set_uid`` / ``set_gid``)

### Fixes
* The test fixture is now included in the source distribution and installed
with the package.
* Some public constants in `fake_filesystem` that had been moved to `helpers` are
made accessible from there again (see [#809](../../issues/809)).
* Add missing fake implementations for `os.getuid` and `os.getgid` (Posix only)


## [Version 5.2.1](https://pypi.python.org/pypi/pyfakefs/5.2.1) (2023-04-11)
Support for latest Python 3.12 version.
Expand Down
2 changes: 1 addition & 1 deletion docs/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Public Modules and Classes
Fake filesystem module
----------------------
.. automodule:: pyfakefs.helpers
:members: set_uid, set_gid, reset_ids, is_root
:members: get_uid, set_uid, get_gid, set_gid, reset_ids, is_root

Fake filesystem classes
-----------------------
Expand Down
5 changes: 4 additions & 1 deletion pyfakefs/fake_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,10 @@ def __init__(
self._side_effect: Optional[Callable] = side_effect
self.name: AnyStr = name # type: ignore[assignment]
self.stat_result = FakeStatResult(
filesystem.is_windows_fs, helpers.USER_ID, helpers.GROUP_ID, helpers.now()
filesystem.is_windows_fs,
helpers.get_uid(),
helpers.get_gid(),
helpers.now(),
)
if st_mode >> 12 == 0:
st_mode |= S_IFREG
Expand Down
13 changes: 11 additions & 2 deletions pyfakefs/fake_filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,19 @@ class OSType(Enum):
PatchMode = fake_io.PatchMode

is_root = helpers.is_root
get_uid = helpers.get_uid
set_uid = helpers.set_uid
get_gid = helpers.get_gid
set_gid = helpers.set_gid
reset_ids = helpers.reset_ids

PERM_READ = helpers.PERM_READ
PERM_WRITE = helpers.PERM_WRITE
PERM_EXE = helpers.PERM_EXE
PERM_DEF = helpers.PERM_DEF
PERM_DEF_FILE = helpers.PERM_DEF_FILE
PERM_ALL = helpers.PERM_ALL


class FakeFilesystem:
"""Provides the appearance of a real directory tree for unit testing.
Expand Down Expand Up @@ -1620,10 +1629,10 @@ def get_object_from_normpath(

@staticmethod
def _can_read(target, owner_can_read):
if target.st_uid == helpers.USER_ID:
if target.st_uid == helpers.get_uid():
if owner_can_read or target.st_mode & 0o400:
return True
if target.st_gid == helpers.GROUP_ID:
if target.st_gid == get_gid():
if target.st_mode & 0o040:
return True
return target.st_mode & 0o004
Expand Down
21 changes: 21 additions & 0 deletions pyfakefs/fake_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
PERM_EXE,
PERM_DEF,
is_root,
get_uid,
get_gid,
)

if TYPE_CHECKING:
Expand Down Expand Up @@ -134,6 +136,11 @@ def dir() -> List[str]:
"removexattr",
"setxattr",
]
if sys.platform != "win32":
_dir += [
"getgid",
"getuid",
]
if use_scandir:
_dir += ["scandir"]
return _dir
Expand Down Expand Up @@ -1272,6 +1279,20 @@ def sendfile(self, fd_out: int, fd_in: int, offset: int, count: int) -> int:
return written
return 0

if sys.platform != "win32":

def getuid(self) -> int:
"""Returns the user id set in the fake filesystem.
If not changed using ``set_uid``, this is the uid of the real system.
"""
return get_uid()

def getgid(self) -> int:
"""Returns the group id set in the fake filesystem.
If not changed using ``set_gid``, this is the gid of the real system.
"""
return get_gid()

def fake_functions(self, original_functions) -> Set:
functions = set()
for fn in original_functions:
Expand Down
10 changes: 10 additions & 0 deletions pyfakefs/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
GROUP_ID = os.getgid()


def get_uid() -> int:
"""Get the global user id. Same as ``os.getuid()``"""
return USER_ID


def set_uid(uid: int) -> None:
"""Set the global user id. This is used as st_uid for new files
and to differentiate between a normal user and the root user (uid 0).
Expand All @@ -56,6 +61,11 @@ def set_uid(uid: int) -> None:
USER_ID = uid


def get_gid() -> int:
"""Get the global group id. Same as ``os.getgid()``"""
return GROUP_ID


def set_gid(gid: int) -> None:
"""Set the global group id. This is only used to set st_gid for new files,
no permission checks are performed.
Expand Down
4 changes: 2 additions & 2 deletions pyfakefs/tests/fake_filesystem_shutil_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from pathlib import Path

from pyfakefs import fake_filesystem_unittest
from pyfakefs.helpers import USER_ID, set_uid, is_root
from pyfakefs.helpers import get_uid, set_uid, is_root
from pyfakefs.tests.test_utils import RealFsTestMixin

is_windows = sys.platform == "win32"
Expand All @@ -39,7 +39,7 @@ def __init__(self, methodName="runTest"):
def setUp(self):
RealFsTestMixin.setUp(self)
self.cwd = os.getcwd()
self.uid = USER_ID
self.uid = get_uid()
set_uid(1000)
if not self.use_real_fs():
self.setUpPyfakefs()
Expand Down
32 changes: 26 additions & 6 deletions pyfakefs/tests/fake_os_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import sys
import unittest

from pyfakefs.helpers import IN_DOCKER, IS_PYPY, GROUP_ID, USER_ID
from pyfakefs.helpers import IN_DOCKER, IS_PYPY, get_uid, get_gid

from pyfakefs import fake_filesystem, fake_os, fake_open, fake_file
from pyfakefs.fake_filesystem import (
Expand Down Expand Up @@ -5403,6 +5403,26 @@ def chmod(self, path, mode):
else:
self.os.chmod(path, mode)

def test_getuid(self):
self.skip_real_fs() # won't change user in real fs
self.check_posix_only()
uid = self.os.getuid()
set_uid(uid + 10)
self.assertEqual(uid + 10, self.os.getuid())
self.assertEqual(uid + 10, get_uid())
set_uid(uid)
self.assertEqual(uid, self.os.getuid())

def test_getgid(self):
self.skip_real_fs() # won't change group in real fs
self.check_posix_only()
gid = self.os.getgid()
set_gid(gid + 10)
self.assertEqual(gid + 10, self.os.getgid())
self.assertEqual(gid + 10, get_gid())
set_gid(gid)
self.assertEqual(gid, self.os.getgid())

def test_listdir_unreadable_dir(self):
if not is_root():
self.assert_raises_os_error(errno.EACCES, self.os.listdir, self.dir_path)
Expand All @@ -5417,7 +5437,7 @@ def test_listdir_user_readable_dir(self):
def test_listdir_user_readable_dir_from_other_user(self):
self.skip_real_fs() # won't change user in real fs
self.check_posix_only()
user_id = USER_ID
user_id = get_uid()
set_uid(user_id + 1)
dir_path = self.make_path("dir1")
self.create_dir(dir_path, perm=0o600)
Expand All @@ -5431,7 +5451,7 @@ def test_listdir_user_readable_dir_from_other_user(self):

def test_listdir_group_readable_dir_from_other_user(self):
self.skip_real_fs() # won't change user in real fs
user_id = USER_ID
user_id = get_uid()
set_uid(user_id + 1)
dir_path = self.make_path("dir1")
self.create_dir(dir_path, perm=0o660)
Expand All @@ -5442,7 +5462,7 @@ def test_listdir_group_readable_dir_from_other_user(self):
def test_listdir_group_readable_dir_from_other_group(self):
self.skip_real_fs() # won't change user in real fs
self.check_posix_only()
group_id = GROUP_ID
group_id = self.os.get_gid()
set_gid(group_id + 1)
dir_path = self.make_path("dir1")
self.create_dir(dir_path, perm=0o060)
Expand All @@ -5456,7 +5476,7 @@ def test_listdir_group_readable_dir_from_other_group(self):

def test_listdir_other_readable_dir_from_other_group(self):
self.skip_real_fs() # won't change user in real fs
group_id = GROUP_ID
group_id = get_gid()
set_gid(group_id + 1)
dir_path = self.make_path("dir1")
self.create_dir(dir_path, perm=0o004)
Expand Down Expand Up @@ -5489,7 +5509,7 @@ def test_remove_unreadable_dir(self):

def test_remove_unreadable_dir_from_other_user(self):
self.skip_real_fs() # won't change user in real fs
user_id = USER_ID
user_id = get_uid()
set_uid(user_id + 1)
dir_path = self.make_path("dir1")
self.create_dir(dir_path, perm=0o000)
Expand Down

0 comments on commit 45c2135

Please sign in to comment.