https://github.com/python/cpython/commit/2010d45327128594aed332befa687c8aead010bc
commit: 2010d45327128594aed332befa687c8aead010bc
branch: main
author: Ronald Oussoren <[email protected]>
committer: ronaldoussoren <[email protected]>
date: 2024-01-15T12:22:43+01:00
summary:

gh-113666: Adding missing UF_ and SF_ flags to module 'stat' (#113667)

Add some constants to module 'stat' that are used on macOS.

Co-authored-by: Serhiy Storchaka <[email protected]>

files:
A Misc/NEWS.d/next/macOS/2024-01-02-22-25-21.gh-issue-113666.xKZoBm.rst
M Doc/library/stat.rst
M Lib/stat.py
M Lib/test/test_stat.py
M Modules/_stat.c

diff --git a/Doc/library/stat.rst b/Doc/library/stat.rst
index 77538514598a50..c941d5557e31b5 100644
--- a/Doc/library/stat.rst
+++ b/Doc/library/stat.rst
@@ -350,6 +350,12 @@ The following flags can also be used in the *mode* 
argument of :func:`os.chmod`:
 
 The following flags can be used in the *flags* argument of :func:`os.chflags`:
 
+.. data:: UF_SETTABLE
+
+   All user settable flags.
+
+   .. versionadded: 3.13
+
 .. data:: UF_NODUMP
 
    Do not dump the file.
@@ -374,10 +380,44 @@ The following flags can be used in the *flags* argument 
of :func:`os.chflags`:
 
    The file is stored compressed (macOS 10.6+).
 
+.. data:: UF_TRACKED
+
+   Used for handling document IDs (macOS)
+
+   .. versionadded: 3.13
+
+.. data:: UF_DATAVAULT
+
+   The file needs an entitlement for reading or writing (macOS 10.13+)
+
+   .. versionadded: 3.13
+
 .. data:: UF_HIDDEN
 
    The file should not be displayed in a GUI (macOS 10.5+).
 
+.. data:: SF_SETTABLE
+
+   All super-user changeable flags
+
+   .. versionadded: 3.13
+
+.. data:: SF_SUPPORTED
+
+   All super-user supported flags
+
+   .. availability:: macOS
+
+   .. versionadded: 3.13
+
+.. data:: SF_SYNTHETIC
+
+   All super-user read-only synthetic flags
+
+   .. availability:: macOS
+
+   .. versionadded: 3.13
+
 .. data:: SF_ARCHIVED
 
    The file may be archived.
@@ -390,6 +430,12 @@ The following flags can be used in the *flags* argument of 
:func:`os.chflags`:
 
    The file may only be appended to.
 
+.. data:: SF_RESTRICTED
+
+   The file needs an entitlement to write to (macOS 10.13+)
+
+   .. versionadded: 3.13
+
 .. data:: SF_NOUNLINK
 
    The file may not be renamed or deleted.
@@ -398,6 +444,18 @@ The following flags can be used in the *flags* argument of 
:func:`os.chflags`:
 
    The file is a snapshot file.
 
+.. data:: SF_FIRMLINK
+
+   The file is a firmlink (macOS 10.15+)
+
+   .. versionadded: 3.13
+
+.. data:: SF_DATALESS
+
+   The file is a dataless object (macOS 10.15+)
+
+   .. versionadded: 3.13
+
 See the \*BSD or macOS systems man page :manpage:`chflags(2)` for more 
information.
 
 On Windows, the following file attribute constants are available for use when
diff --git a/Lib/stat.py b/Lib/stat.py
index 52cadbf04f6c88..9167ab185944fb 100644
--- a/Lib/stat.py
+++ b/Lib/stat.py
@@ -2,6 +2,7 @@
 
 Suggested usage: from stat import *
 """
+import sys
 
 # Indices for stat struct members in the tuple returned by os.stat()
 
@@ -110,19 +111,25 @@ def S_ISWHT(mode):
 S_IXOTH = 0o0001  # execute by others
 
 # Names for file flags
-
+UF_SETTABLE  = 0x0000ffff  # owner settable flags
 UF_NODUMP    = 0x00000001  # do not dump file
 UF_IMMUTABLE = 0x00000002  # file may not be changed
 UF_APPEND    = 0x00000004  # file may only be appended to
 UF_OPAQUE    = 0x00000008  # directory is opaque when viewed through a union 
stack
 UF_NOUNLINK  = 0x00000010  # file may not be renamed or deleted
-UF_COMPRESSED = 0x00000020 # OS X: file is hfs-compressed
-UF_HIDDEN    = 0x00008000  # OS X: file should not be displayed
+UF_COMPRESSED = 0x00000020 # macOS: file is compressed
+UF_TRACKED   = 0x00000040  # macOS: used for handling document IDs
+UF_DATAVAULT = 0x00000080  # macOS: entitlement needed for I/O
+UF_HIDDEN    = 0x00008000  # macOS: file should not be displayed
+SF_SETTABLE  = 0xffff0000  # superuser settable flags
 SF_ARCHIVED  = 0x00010000  # file may be archived
 SF_IMMUTABLE = 0x00020000  # file may not be changed
 SF_APPEND    = 0x00040000  # file may only be appended to
+SF_RESTRICTED = 0x00080000 # macOS: entitlement needed for writing
 SF_NOUNLINK  = 0x00100000  # file may not be renamed or deleted
 SF_SNAPSHOT  = 0x00200000  # file is a snapshot file
+SF_FIRMLINK  = 0x00800000  # macOS: file is a firmlink
+SF_DATALESS  = 0x40000000  # macOS: file is a dataless object
 
 
 _filemode_table = (
diff --git a/Lib/test/test_stat.py b/Lib/test/test_stat.py
index a0d0f61e5a192c..d6b6dd6e741700 100644
--- a/Lib/test/test_stat.py
+++ b/Lib/test/test_stat.py
@@ -15,8 +15,10 @@ class TestFilemode:
     statmod = None
 
     file_flags = {'SF_APPEND', 'SF_ARCHIVED', 'SF_IMMUTABLE', 'SF_NOUNLINK',
-                  'SF_SNAPSHOT', 'UF_APPEND', 'UF_COMPRESSED', 'UF_HIDDEN',
-                  'UF_IMMUTABLE', 'UF_NODUMP', 'UF_NOUNLINK', 'UF_OPAQUE'}
+                  'SF_SNAPSHOT', 'SF_SETTABLE', 'SF_RESTRICTED', 'SF_FIRMLINK',
+                  'SF_DATALESS', 'UF_APPEND', 'UF_COMPRESSED', 'UF_HIDDEN',
+                  'UF_IMMUTABLE', 'UF_NODUMP', 'UF_NOUNLINK', 'UF_OPAQUE',
+                  'UF_SETTABLE', 'UF_TRACKED', 'UF_DATAVAULT'}
 
     formats = {'S_IFBLK', 'S_IFCHR', 'S_IFDIR', 'S_IFIFO', 'S_IFLNK',
                'S_IFREG', 'S_IFSOCK', 'S_IFDOOR', 'S_IFPORT', 'S_IFWHT'}
@@ -239,6 +241,18 @@ def test_module_attributes(self):
             self.assertTrue(callable(func))
             self.assertEqual(func(0), 0)
 
+    def test_flags_consistent(self):
+        self.assertFalse(self.statmod.UF_SETTABLE & self.statmod.SF_SETTABLE)
+
+        for flag in self.file_flags:
+            if flag.startswith("UF"):
+                self.assertTrue(getattr(self.statmod, flag) & 
self.statmod.UF_SETTABLE, f"{flag} not in UF_SETTABLE")
+            elif sys.platform == 'darwin' and self.statmod is c_stat and flag 
== 'SF_DATALESS':
+                self.assertTrue(self.statmod.SF_DATALESS & 
self.statmod.SF_SYNTHETIC, "SF_DATALESS not in SF_SYNTHETIC")
+                self.assertFalse(self.statmod.SF_DATALESS & 
self.statmod.SF_SETTABLE, "SF_DATALESS in SF_SETTABLE")
+            else:
+                self.assertTrue(getattr(self.statmod, flag) & 
self.statmod.SF_SETTABLE, f"{flag} notin SF_SETTABLE")
+
     @unittest.skipUnless(sys.platform == "win32",
                          "FILE_ATTRIBUTE_* constants are Win32 specific")
     def test_file_attribute_constants(self):
@@ -247,6 +261,66 @@ def test_file_attribute_constants(self):
             modvalue = getattr(self.statmod, key)
             self.assertEqual(value, modvalue, key)
 
+    @unittest.skipUnless(sys.platform == "darwin", "macOS system check")
+    def test_macosx_attribute_values(self):
+        self.assertEqual(self.statmod.UF_SETTABLE, 0x0000ffff)
+        self.assertEqual(self.statmod.UF_NODUMP, 0x00000001)
+        self.assertEqual(self.statmod.UF_IMMUTABLE, 0x00000002)
+        self.assertEqual(self.statmod.UF_APPEND, 0x00000004)
+        self.assertEqual(self.statmod.UF_OPAQUE, 0x00000008)
+        self.assertEqual(self.statmod.UF_COMPRESSED, 0x00000020)
+        self.assertEqual(self.statmod.UF_TRACKED, 0x00000040)
+        self.assertEqual(self.statmod.UF_DATAVAULT, 0x00000080)
+        self.assertEqual(self.statmod.UF_HIDDEN, 0x00008000)
+
+        if self.statmod is c_stat:
+            self.assertEqual(self.statmod.SF_SUPPORTED, 0x009f0000)
+            self.assertEqual(self.statmod.SF_SETTABLE, 0x3fff0000)
+            self.assertEqual(self.statmod.SF_SYNTHETIC, 0xc0000000)
+        else:
+            self.assertEqual(self.statmod.SF_SETTABLE, 0xffff0000)
+        self.assertEqual(self.statmod.SF_ARCHIVED, 0x00010000)
+        self.assertEqual(self.statmod.SF_IMMUTABLE, 0x00020000)
+        self.assertEqual(self.statmod.SF_APPEND, 0x00040000)
+        self.assertEqual(self.statmod.SF_RESTRICTED, 0x00080000)
+        self.assertEqual(self.statmod.SF_NOUNLINK, 0x00100000)
+        self.assertEqual(self.statmod.SF_FIRMLINK, 0x00800000)
+        self.assertEqual(self.statmod.SF_DATALESS, 0x40000000)
+
+        self.assertFalse(isinstance(self.statmod.S_IFMT, int))
+        self.assertEqual(self.statmod.S_IFIFO, 0o010000)
+        self.assertEqual(self.statmod.S_IFCHR, 0o020000)
+        self.assertEqual(self.statmod.S_IFDIR, 0o040000)
+        self.assertEqual(self.statmod.S_IFBLK, 0o060000)
+        self.assertEqual(self.statmod.S_IFREG, 0o100000)
+        self.assertEqual(self.statmod.S_IFLNK, 0o120000)
+        self.assertEqual(self.statmod.S_IFSOCK, 0o140000)
+
+        if self.statmod is c_stat:
+            self.assertEqual(self.statmod.S_IFWHT, 0o160000)
+
+        self.assertEqual(self.statmod.S_IRWXU, 0o000700)
+        self.assertEqual(self.statmod.S_IRUSR, 0o000400)
+        self.assertEqual(self.statmod.S_IWUSR, 0o000200)
+        self.assertEqual(self.statmod.S_IXUSR, 0o000100)
+        self.assertEqual(self.statmod.S_IRWXG, 0o000070)
+        self.assertEqual(self.statmod.S_IRGRP, 0o000040)
+        self.assertEqual(self.statmod.S_IWGRP, 0o000020)
+        self.assertEqual(self.statmod.S_IXGRP, 0o000010)
+        self.assertEqual(self.statmod.S_IRWXO, 0o000007)
+        self.assertEqual(self.statmod.S_IROTH, 0o000004)
+        self.assertEqual(self.statmod.S_IWOTH, 0o000002)
+        self.assertEqual(self.statmod.S_IXOTH, 0o000001)
+        self.assertEqual(self.statmod.S_ISUID, 0o004000)
+        self.assertEqual(self.statmod.S_ISGID, 0o002000)
+        self.assertEqual(self.statmod.S_ISVTX, 0o001000)
+
+        self.assertFalse(hasattr(self.statmod, "S_ISTXT"))
+        self.assertEqual(self.statmod.S_IREAD, self.statmod.S_IRUSR)
+        self.assertEqual(self.statmod.S_IWRITE, self.statmod.S_IWUSR)
+        self.assertEqual(self.statmod.S_IEXEC, self.statmod.S_IXUSR)
+
+
 
 @unittest.skipIf(c_stat is None, 'need _stat extension')
 class TestFilemodeCStat(TestFilemode, unittest.TestCase):
diff --git 
a/Misc/NEWS.d/next/macOS/2024-01-02-22-25-21.gh-issue-113666.xKZoBm.rst 
b/Misc/NEWS.d/next/macOS/2024-01-02-22-25-21.gh-issue-113666.xKZoBm.rst
new file mode 100644
index 00000000000000..4be0021eed3cc4
--- /dev/null
+++ b/Misc/NEWS.d/next/macOS/2024-01-02-22-25-21.gh-issue-113666.xKZoBm.rst
@@ -0,0 +1,5 @@
+Add the following constants to module :mod:`stat`: ``UF_SETTABLE``,
+``UF_TRACKED``, ``UF_DATAVAULT``, ``SF_SUPPORTED``, ``SF_SETTABLE``,
+``SF_SYNTHETIC``, ``SF_RESTRICTED``, ``SF_FIRMLINK`` and ``SF_DATALESS``.
+The values ``UF_SETTABLE``, ``SF_SUPPORTED``, ``SF_SETTABLE`` and
+``SF_SYNTHETIC`` are only available on macOS.
diff --git a/Modules/_stat.c b/Modules/_stat.c
index 80f8a92668976b..b43e79453f5b2f 100644
--- a/Modules/_stat.c
+++ b/Modules/_stat.c
@@ -202,6 +202,10 @@ typedef unsigned short mode_t;
 
 
 /* Names for file flags */
+#ifndef UF_SETTABLE
+#  define UF_SETTABLE 0x0000ffff
+#endif
+
 #ifndef UF_NODUMP
 #  define UF_NODUMP 0x00000001
 #endif
@@ -226,10 +230,22 @@ typedef unsigned short mode_t;
 #  define UF_COMPRESSED 0x00000020
 #endif
 
+#ifndef UF_TRACKED
+#  define UF_TRACKED 0x00000040
+#endif
+
+#ifndef UF_DATAVAULT
+#  define UF_DATAVAULT 0x00000080
+#endif
+
 #ifndef UF_HIDDEN
 #  define UF_HIDDEN 0x00008000
 #endif
 
+#ifndef SF_SETTABLE
+#  define SF_SETTABLE 0xffff0000
+#endif
+
 #ifndef SF_ARCHIVED
 #  define SF_ARCHIVED 0x00010000
 #endif
@@ -250,6 +266,30 @@ typedef unsigned short mode_t;
 #  define SF_SNAPSHOT 0x00200000
 #endif
 
+#ifndef SF_FIRMLINK
+#  define SF_FIRMLINK 0x00800000
+#endif
+
+#ifndef SF_DATALESS
+#  define SF_DATALESS 0x40000000
+#endif
+
+#if defined(__APPLE__) && !defined(SF_SUPPORTED)
+   /* On older macOS versions the definition of SF_SUPPORTED is different
+    * from that on newer versions.
+    *
+    * Provide a consistent experience by redefining.
+    *
+    * None of bit bits set in the actual SF_SUPPORTED but not in this
+    * definition are defined on these versions of macOS.
+    */
+#  undef SF_SETTABLE
+#  define SF_SUPPORTED 0x009f0000
+#  define SF_SETTABLE 0x3fff0000
+#  define SF_SYNTHETIC 0xc0000000
+#endif
+
+
 static mode_t
 _PyLong_AsMode_t(PyObject *op)
 {
@@ -467,18 +507,29 @@ S_IWOTH: write by others\n\
 S_IXOTH: execute by others\n\
 \n"
 
-"UF_NODUMP: do not dump file\n\
+"UF_SETTABLE: mask of owner changable flags\n\
+UF_NODUMP: do not dump file\n\
 UF_IMMUTABLE: file may not be changed\n\
 UF_APPEND: file may only be appended to\n\
 UF_OPAQUE: directory is opaque when viewed through a union stack\n\
 UF_NOUNLINK: file may not be renamed or deleted\n\
-UF_COMPRESSED: OS X: file is hfs-compressed\n\
-UF_HIDDEN: OS X: file should not be displayed\n\
+UF_COMPRESSED: macOS: file is hfs-compressed\n\
+UF_TRACKED: used for dealing with document IDs\n\
+UF_DATAVAULT: entitlement required for reading and writing\n\
+UF_HIDDEN: macOS: file should not be displayed\n\
+SF_SETTABLE: mask of super user changeable flags\n\
 SF_ARCHIVED: file may be archived\n\
 SF_IMMUTABLE: file may not be changed\n\
 SF_APPEND: file may only be appended to\n\
+SF_RESTRICTED: entitlement required for writing\n\
 SF_NOUNLINK: file may not be renamed or deleted\n\
 SF_SNAPSHOT: file is a snapshot file\n\
+SF_FIRMLINK: file is a firmlink\n\
+SF_DATALESS: file is a dataless object\n\
+\n\
+On macOS:\n\
+SF_SUPPORTED: mask of super user supported flags\n\
+SF_SYNTHETIC: mask of read-only synthetic flags\n\
 \n"
 
 "ST_MODE\n\
@@ -543,18 +594,32 @@ stat_exec(PyObject *module)
     ADD_INT_MACRO(module, S_IWOTH);
     ADD_INT_MACRO(module, S_IXOTH);
 
+    ADD_INT_MACRO(module, UF_SETTABLE);
     ADD_INT_MACRO(module, UF_NODUMP);
     ADD_INT_MACRO(module, UF_IMMUTABLE);
     ADD_INT_MACRO(module, UF_APPEND);
     ADD_INT_MACRO(module, UF_OPAQUE);
     ADD_INT_MACRO(module, UF_NOUNLINK);
     ADD_INT_MACRO(module, UF_COMPRESSED);
+    ADD_INT_MACRO(module, UF_TRACKED);
+    ADD_INT_MACRO(module, UF_DATAVAULT);
     ADD_INT_MACRO(module, UF_HIDDEN);
+    ADD_INT_MACRO(module, SF_SETTABLE);
     ADD_INT_MACRO(module, SF_ARCHIVED);
     ADD_INT_MACRO(module, SF_IMMUTABLE);
     ADD_INT_MACRO(module, SF_APPEND);
     ADD_INT_MACRO(module, SF_NOUNLINK);
     ADD_INT_MACRO(module, SF_SNAPSHOT);
+    ADD_INT_MACRO(module, SF_FIRMLINK);
+    ADD_INT_MACRO(module, SF_DATALESS);
+
+#ifdef SF_SUPPORTED
+    ADD_INT_MACRO(module, SF_SUPPORTED);
+#endif
+#ifdef SF_SYNTHETIC
+    ADD_INT_MACRO(module, SF_SYNTHETIC);
+#endif
+
 
     const char* st_constants[] = {
         "ST_MODE",

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to