Skip to content

Commit 3d611c6

Browse files
committed
Fix handling of missing attribute in os.getxattr
- no tests for real OS (extended atributes not enabled in CI) - fixes #971
1 parent 9e62889 commit 3d611c6

File tree

5 files changed

+28
-20
lines changed

5 files changed

+28
-20
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ The released versions correspond to PyPI releases.
2222
(see [#965](../../issues/965))
2323
* fixed handling of `dirfd` in `os.symlink` (see [#968](../../issues/968))
2424
* add missing `follow_symlink` argument to `os.link` (see [#973](../../issues/973))
25+
* fixed handling of missing attribute in `os.getxattr` (see [#971](../../issues/971))
2526

2627
### Enhancements
2728
* added support for `O_NOFOLLOW` and `O_DIRECTORY` flags in `os.open`

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ for more information.
120120
pyfakefs.py was initially developed at Google by Mike Bland as a modest fake
121121
implementation of core Python modules. It was introduced to all of Google
122122
in September 2006. Since then, it has been enhanced to extend its
123-
functionality and usefulness. At last count, pyfakefs was used in over 2,000
123+
functionality and usefulness. At last count, pyfakefs was used in over 20,000
124124
Python tests at Google.
125125

126126
Google released pyfakefs to the public in 2011 as Google Code project

docs/usage.rst

+5-1
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ While ``pyfakefs`` can be used just with the standard Python file system
690690
functions, there are a few convenience methods in ``fake_filesystem`` that can
691691
help you setting up your tests. The methods can be accessed via the
692692
``fake_filesystem`` instance in your tests: ``Patcher.fs``, the ``fs``
693-
fixture in pytest, ``TestCase.fs`` for ``unittest``, and the ``fs`` argument
693+
fixture in pytest, ``TestCase.fs`` for ``unittest``, and the positional argument
694694
for the ``patchfs`` decorator.
695695

696696
File creation helpers
@@ -965,6 +965,10 @@ The following test works both under Windows and Linux:
965965
assert os.path.splitdrive(r"C:\foo\bar") == ("C:", r"\foo\bar")
966966
assert os.path.ismount("C:")
967967
968+
.. note:: Only behavior not relying on OS-specific functionality is emulated on another system.
969+
For example, if you use the Linux-specific functionality of extended attributes (``os.getxattr`` etc.)
970+
in your code, you have to test this under Linux.
971+
968972
Set file as inaccessible under Windows
969973
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
970974
Normally, if you try to set a file or directory as inaccessible using ``chmod`` under

pyfakefs/fake_os.py

+2
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,8 @@ def getxattr(
491491
if isinstance(attribute, bytes):
492492
attribute = attribute.decode(sys.getfilesystemencoding())
493493
file_obj = self.filesystem.resolve(path, follow_symlinks, allow_fd=True)
494+
if attribute not in file_obj.xattr:
495+
raise OSError(errno.ENODATA, "No data available", path)
494496
return file_obj.xattr.get(attribute)
495497

496498
def listxattr(

pyfakefs/tests/fake_os_test.py

+19-18
Original file line numberDiff line numberDiff line change
@@ -5496,26 +5496,25 @@ def test_empty_xattr(self):
54965496
self.assertEqual([], self.os.listxattr(self.dir_path))
54975497
self.assertEqual([], self.os.listxattr(self.file_path))
54985498

5499+
def test_getxattr_raises_for_non_existing_file(self):
5500+
with self.assertRaises(FileNotFoundError):
5501+
self.os.getxattr("bogus_path", "test")
5502+
5503+
def test_getxattr_raises_for_non_existing_attribute(self):
5504+
with self.assertRaises(OSError) as cm:
5505+
self.os.getxattr(self.file_path, "bogus")
5506+
self.assertEqual(errno.ENODATA, cm.exception.errno)
5507+
54995508
def test_setxattr(self):
5500-
self.assertRaises(TypeError, self.os.setxattr, self.file_path, "test", "value")
5501-
self.assert_raises_os_error(
5502-
errno.EEXIST,
5503-
self.os.setxattr,
5504-
self.file_path,
5505-
"test",
5506-
b"value",
5507-
self.os.XATTR_REPLACE,
5508-
)
5509+
with self.assertRaises(TypeError):
5510+
self.os.setxattr(self.file_path, "test", "value")
5511+
with self.assertRaises(FileExistsError):
5512+
self.os.setxattr(self.file_path, "test", b"value", self.os.XATTR_REPLACE)
55095513
self.os.setxattr(self.file_path, "test", b"value")
55105514
self.assertEqual(b"value", self.os.getxattr(self.file_path, "test"))
5511-
self.assert_raises_os_error(
5512-
errno.ENODATA,
5513-
self.os.setxattr,
5514-
self.file_path,
5515-
"test",
5516-
b"value",
5517-
self.os.XATTR_CREATE,
5518-
)
5515+
with self.assertRaises(OSError) as cm:
5516+
self.os.setxattr(self.file_path, "test", b"value", self.os.XATTR_CREATE)
5517+
self.assertEqual(errno.ENODATA, cm.exception.errno)
55195518

55205519
def test_removeattr(self):
55215520
self.os.removexattr(self.file_path, "test")
@@ -5525,7 +5524,9 @@ def test_removeattr(self):
55255524
self.assertEqual(b"value", self.os.getxattr(self.file_path, "test"))
55265525
self.os.removexattr(self.file_path, "test")
55275526
self.assertEqual([], self.os.listxattr(self.file_path))
5528-
self.assertIsNone(self.os.getxattr(self.file_path, "test"))
5527+
with self.assertRaises(OSError) as cm:
5528+
self.os.getxattr(self.file_path, "test")
5529+
self.assertEqual(errno.ENODATA, cm.exception.errno)
55295530

55305531
def test_default_path(self):
55315532
self.os.chdir(self.dir_path)

0 commit comments

Comments
 (0)