| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1905,6 +1905,11 @@ features: | |||
| 1905 | 1905 | * :attr:`st_creator` | |
| 1906 | 1906 | * :attr:`st_type` | |
| 1907 | 1907 | ||
| 1908 | + On Windows systems, the following attribute is also available: | ||
| 1909 | + | ||
| 1910 | + * :attr:`st_file_attributes` - Windows file attribute bits (see the | ||
| 1911 | + ``FILE_ATTRIBUTE_*`` constants in the :mod:`stat` module) | ||
| 1912 | + | ||
| 1908 | 1913 | .. note:: | |
| 1909 | 1914 | ||
| 1910 | 1915 | The exact meaning and resolution of the :attr:`st_atime`, | |
@@ -1958,6 +1963,9 @@ features: | |||
| 1958 | 1963 | and the :attr:`st_atime_ns`, :attr:`st_mtime_ns`, | |
| 1959 | 1964 | and :attr:`st_ctime_ns` members. | |
| 1960 | 1965 | ||
| 1966 | + .. versionadded:: 3.5 | ||
| 1967 | + Added the :attr:`st_file_attributes` member on Windows. | ||
| 1968 | + | ||
| 1961 | 1969 | ||
| 1962 | 1970 | .. function:: stat_float_times([newvalue]) | |
| 1963 | 1971 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -126,7 +126,7 @@ Example:: | |||
| 126 | 126 | if __name__ == '__main__': | |
| 127 | 127 | walktree(sys.argv[1], visitfile) | |
| 128 | 128 | ||
| 129 | - An additional utility function is provided to covert a file's mode in a human | ||
| 129 | + An additional utility function is provided to convert a file's mode in a human | ||
| 130 | 130 | readable string: | |
| 131 | 131 | ||
| 132 | 132 | .. function:: filemode(mode) | |
@@ -399,3 +399,29 @@ The following flags can be used in the *flags* argument of :func:`os.chflags`: | |||
| 399 | 399 | The file is a snapshot file. | |
| 400 | 400 | ||
| 401 | 401 | See the \*BSD or Mac OS systems man page :manpage:`chflags(2)` for more information. | |
| 402 | + | ||
| 403 | + On Windows, the following file attribute constants are available for use when | ||
| 404 | + testing bits in the ``st_file_attributes`` member returned by :func:`os.stat`. | ||
| 405 | + See the `Windows API documentation | ||
| 406 | + <http://msdn.microsoft.com/en-us/library/windows/desktop/gg258117.aspx>`_ | ||
| 407 | + for more detail on the meaning of these constants. | ||
| 408 | + | ||
| 409 | + .. data:: FILE_ATTRIBUTE_ARCHIVE | ||
| 410 | + FILE_ATTRIBUTE_COMPRESSED | ||
| 411 | + FILE_ATTRIBUTE_DEVICE | ||
| 412 | + FILE_ATTRIBUTE_DIRECTORY | ||
| 413 | + FILE_ATTRIBUTE_ENCRYPTED | ||
| 414 | + FILE_ATTRIBUTE_HIDDEN | ||
| 415 | + FILE_ATTRIBUTE_INTEGRITY_STREAM | ||
| 416 | + FILE_ATTRIBUTE_NORMAL | ||
| 417 | + FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | ||
| 418 | + FILE_ATTRIBUTE_NO_SCRUB_DATA | ||
| 419 | + FILE_ATTRIBUTE_OFFLINE | ||
| 420 | + FILE_ATTRIBUTE_READONLY | ||
| 421 | + FILE_ATTRIBUTE_REPARSE_POINT | ||
| 422 | + FILE_ATTRIBUTE_SPARSE_FILE | ||
| 423 | + FILE_ATTRIBUTE_SYSTEM | ||
| 424 | + FILE_ATTRIBUTE_TEMPORARY | ||
| 425 | + FILE_ATTRIBUTE_VIRTUAL | ||
| 426 | + | ||
| 427 | + .. versionadded:: 3.5 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -176,6 +176,15 @@ ipaddress | |||
| 176 | 176 | network objects from existing addresses (contributed by Peter Moody | |
| 177 | 177 | and Antoine Pitrou in :issue:`16531`). | |
| 178 | 178 | ||
| 179 | + os | ||
| 180 | + -- | ||
| 181 | + | ||
| 182 | + * :class:`os.stat_result` now has a ``st_file_attributes`` field on Windows, | ||
| 183 | + containing the ``dwFileAttributes`` member of the | ||
| 184 | + ``BY_HANDLE_FILE_INFORMATION`` structure returned by | ||
| 185 | + ``GetFileInformationByHandle()`` (contributed by Ben Hoyt in | ||
| 186 | + :issue:`21719`). | ||
| 187 | + | ||
| 179 | 188 | shutil | |
| 180 | 189 | ------ | |
| 181 | 190 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -148,6 +148,29 @@ def filemode(mode): | |||
| 148 | 148 | perm.append("-") | |
| 149 | 149 | return "".join(perm) | |
| 150 | 150 | ||
| 151 | + | ||
| 152 | + # Windows FILE_ATTRIBUTE constants for interpreting os.stat()'s | ||
| 153 | + # "st_file_attributes" member | ||
| 154 | + | ||
| 155 | + FILE_ATTRIBUTE_ARCHIVE = 32 | ||
| 156 | + FILE_ATTRIBUTE_COMPRESSED = 2048 | ||
| 157 | + FILE_ATTRIBUTE_DEVICE = 64 | ||
| 158 | + FILE_ATTRIBUTE_DIRECTORY = 16 | ||
| 159 | + FILE_ATTRIBUTE_ENCRYPTED = 16384 | ||
| 160 | + FILE_ATTRIBUTE_HIDDEN = 2 | ||
| 161 | + FILE_ATTRIBUTE_INTEGRITY_STREAM = 32768 | ||
| 162 | + FILE_ATTRIBUTE_NORMAL = 128 | ||
| 163 | + FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192 | ||
| 164 | + FILE_ATTRIBUTE_NO_SCRUB_DATA = 131072 | ||
| 165 | + FILE_ATTRIBUTE_OFFLINE = 4096 | ||
| 166 | + FILE_ATTRIBUTE_READONLY = 1 | ||
| 167 | + FILE_ATTRIBUTE_REPARSE_POINT = 1024 | ||
| 168 | + FILE_ATTRIBUTE_SPARSE_FILE = 512 | ||
| 169 | + FILE_ATTRIBUTE_SYSTEM = 4 | ||
| 170 | + FILE_ATTRIBUTE_TEMPORARY = 256 | ||
| 171 | + FILE_ATTRIBUTE_VIRTUAL = 65536 | ||
| 172 | + | ||
| 173 | + | ||
| 151 | 174 | # If available, use C implementation | |
| 152 | 175 | try: | |
| 153 | 176 | from _stat import * | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -530,6 +530,28 @@ def test_15261(self): | |||
| 530 | 530 | os.stat(r) | |
| 531 | 531 | self.assertEqual(ctx.exception.errno, errno.EBADF) | |
| 532 | 532 | ||
| 533 | + def check_file_attributes(self, result): | ||
| 534 | + self.assertTrue(hasattr(result, 'st_file_attributes')) | ||
| 535 | + self.assertTrue(isinstance(result.st_file_attributes, int)) | ||
| 536 | + self.assertTrue(0 <= result.st_file_attributes <= 0xFFFFFFFF) | ||
| 537 | + | ||
| 538 | + @unittest.skipUnless(sys.platform == "win32", | ||
| 539 | + "st_file_attributes is Win32 specific") | ||
| 540 | + def test_file_attributes(self): | ||
| 541 | + # test file st_file_attributes (FILE_ATTRIBUTE_DIRECTORY not set) | ||
| 542 | + result = os.stat(self.fname) | ||
| 543 | + self.check_file_attributes(result) | ||
| 544 | + self.assertEqual( | ||
| 545 | + result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY, | ||
| 546 | + 0) | ||
| 547 | + | ||
| 548 | + # test directory st_file_attributes (FILE_ATTRIBUTE_DIRECTORY set) | ||
| 549 | + result = os.stat(support.TESTFN) | ||
| 550 | + self.check_file_attributes(result) | ||
| 551 | + self.assertEqual( | ||
| 552 | + result.st_file_attributes & stat.FILE_ATTRIBUTE_DIRECTORY, | ||
| 553 | + stat.FILE_ATTRIBUTE_DIRECTORY) | ||
| 554 | + | ||
| 533 | 555 | from test import mapping_tests | |
| 534 | 556 | ||
| 535 | 557 | class EnvironTests(mapping_tests.BasicTestMappingProtocol): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,5 +1,6 @@ | |||
| 1 | 1 | import unittest | |
| 2 | 2 | import os | |
| 3 | + import sys | ||
| 3 | 4 | from test.support import TESTFN, import_fresh_module | |
| 4 | 5 | ||
| 5 | 6 | c_stat = import_fresh_module('stat', fresh=['_stat']) | |
@@ -52,6 +53,26 @@ class TestFilemode: | |||
| 52 | 53 | 'S_IWOTH': 0o002, | |
| 53 | 54 | 'S_IXOTH': 0o001} | |
| 54 | 55 | ||
| 56 | + # defined by the Windows API documentation | ||
| 57 | + file_attributes = { | ||
| 58 | + 'FILE_ATTRIBUTE_ARCHIVE': 32, | ||
| 59 | + 'FILE_ATTRIBUTE_COMPRESSED': 2048, | ||
| 60 | + 'FILE_ATTRIBUTE_DEVICE': 64, | ||
| 61 | + 'FILE_ATTRIBUTE_DIRECTORY': 16, | ||
| 62 | + 'FILE_ATTRIBUTE_ENCRYPTED': 16384, | ||
| 63 | + 'FILE_ATTRIBUTE_HIDDEN': 2, | ||
| 64 | + 'FILE_ATTRIBUTE_INTEGRITY_STREAM': 32768, | ||
| 65 | + 'FILE_ATTRIBUTE_NORMAL': 128, | ||
| 66 | + 'FILE_ATTRIBUTE_NOT_CONTENT_INDEXED': 8192, | ||
| 67 | + 'FILE_ATTRIBUTE_NO_SCRUB_DATA': 131072, | ||
| 68 | + 'FILE_ATTRIBUTE_OFFLINE': 4096, | ||
| 69 | + 'FILE_ATTRIBUTE_READONLY': 1, | ||
| 70 | + 'FILE_ATTRIBUTE_REPARSE_POINT': 1024, | ||
| 71 | + 'FILE_ATTRIBUTE_SPARSE_FILE': 512, | ||
| 72 | + 'FILE_ATTRIBUTE_SYSTEM': 4, | ||
| 73 | + 'FILE_ATTRIBUTE_TEMPORARY': 256, | ||
| 74 | + 'FILE_ATTRIBUTE_VIRTUAL': 65536} | ||
| 75 | + | ||
| 55 | 76 | def setUp(self): | |
| 56 | 77 | try: | |
| 57 | 78 | os.remove(TESTFN) | |
@@ -185,6 +206,14 @@ def test_module_attributes(self): | |||
| 185 | 206 | self.assertTrue(callable(func)) | |
| 186 | 207 | self.assertEqual(func(0), 0) | |
| 187 | 208 | ||
| 209 | + @unittest.skipUnless(sys.platform == "win32", | ||
| 210 | + "FILE_ATTRIBUTE_* constants are Win32 specific") | ||
| 211 | + def test_file_attribute_constants(self): | ||
| 212 | + for key, value in sorted(self.file_attributes.items()): | ||
| 213 | + self.assertTrue(hasattr(self.statmod, key), key) | ||
| 214 | + modvalue = getattr(self.statmod, key) | ||
| 215 | + self.assertEqual(value, modvalue, key) | ||
| 216 | + | ||
| 188 | 217 | ||
| 189 | 218 | class TestFilemodeCStat(TestFilemode, unittest.TestCase): | |
| 190 | 219 | statmod = c_stat | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -580,6 +580,7 @@ Alan Hourihane | |||
| 580 | 580 | Ken Howard | |
| 581 | 581 | Brad Howes | |
| 582 | 582 | Mike Hoy | |
| 583 | + Ben Hoyt | ||
| 583 | 584 | Chih-Hao Huang | |
| 584 | 585 | Christian Hudon | |
| 585 | 586 | Lawrence Hudson | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -103,6 +103,9 @@ Core and Builtins | |||
| 103 | 103 | Library | |
| 104 | 104 | ------- | |
| 105 | 105 | ||
| 106 | + - Issue #21719: Added the ``st_file_attributes`` field to os.stat_result on | ||
| 107 | + Windows. | ||
| 108 | + | ||
| 106 | 109 | - Issue #21722: The distutils "upload" command now exits with a non-zero | |
| 107 | 110 | return code when uploading fails. Patch by Martin Dengler. | |
| 108 | 111 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -27,9 +27,21 @@ extern "C" { | |||
| 27 | 27 | #endif /* HAVE_SYS_STAT_H */ | |
| 28 | 28 | ||
| 29 | 29 | #ifdef MS_WINDOWS | |
| 30 | + #include <windows.h> | ||
| 30 | 31 | typedef unsigned short mode_t; | |
| 32 | + | ||
| 33 | + /* FILE_ATTRIBUTE_INTEGRITY_STREAM and FILE_ATTRIBUTE_NO_SCRUB_DATA | ||
| 34 | + are not present in VC2010, so define them manually */ | ||
| 35 | + #ifndef FILE_ATTRIBUTE_INTEGRITY_STREAM | ||
| 36 | + # define FILE_ATTRIBUTE_INTEGRITY_STREAM 0x8000 | ||
| 37 | + #endif | ||
| 38 | + | ||
| 39 | + #ifndef FILE_ATTRIBUTE_NO_SCRUB_DATA | ||
| 40 | + # define FILE_ATTRIBUTE_NO_SCRUB_DATA 0x20000 | ||
| 31 | 41 | #endif | |
| 32 | 42 | ||
| 43 | + #endif /* MS_WINDOWS */ | ||
| 44 | + | ||
| 33 | 45 | /* From Python's stat.py */ | |
| 34 | 46 | #ifndef S_IMODE | |
| 35 | 47 | # define S_IMODE 07777 | |
@@ -473,6 +485,10 @@ ST_SIZE\n\ | |||
| 473 | 485 | ST_ATIME\n\ | |
| 474 | 486 | ST_MTIME\n\ | |
| 475 | 487 | ST_CTIME\n\ | |
| 488 | + \n" | ||
| 489 | + | ||
| 490 | + "FILE_ATTRIBUTE_*: Windows file attribute constants\n\ | ||
| 491 | + (only present on Windows)\n\ | ||
| 476 | 492 | "); | |
| 477 | 493 | ||
| 478 | 494 | ||
@@ -555,6 +571,26 @@ PyInit__stat(void) | |||
| 555 | 571 | if (PyModule_AddIntConstant(m, "ST_MTIME", 8)) return NULL; | |
| 556 | 572 | if (PyModule_AddIntConstant(m, "ST_CTIME", 9)) return NULL; | |
| 557 | 573 | ||
| 574 | + #ifdef MS_WINDOWS | ||
| 575 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_ARCHIVE)) return NULL; | ||
| 576 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_COMPRESSED)) return NULL; | ||
| 577 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_DEVICE)) return NULL; | ||
| 578 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_DIRECTORY)) return NULL; | ||
| 579 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_ENCRYPTED)) return NULL; | ||
| 580 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_HIDDEN)) return NULL; | ||
| 581 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_INTEGRITY_STREAM)) return NULL; | ||
| 582 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_NORMAL)) return NULL; | ||
| 583 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)) return NULL; | ||
| 584 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_NO_SCRUB_DATA)) return NULL; | ||
| 585 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_OFFLINE)) return NULL; | ||
| 586 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_READONLY)) return NULL; | ||
| 587 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_REPARSE_POINT)) return NULL; | ||
| 588 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_SPARSE_FILE)) return NULL; | ||
| 589 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_SYSTEM)) return NULL; | ||
| 590 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_TEMPORARY)) return NULL; | ||
| 591 | + if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_VIRTUAL)) return NULL; | ||
| 592 | + #endif | ||
| 593 | + | ||
| 558 | 594 | return m; | |
| 559 | 595 | } | |
| 560 | 596 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1417,6 +1417,7 @@ win32_wchdir(LPCWSTR path) | |||
| 1417 | 1417 | Therefore, we implement our own stat, based on the Win32 API directly. | |
| 1418 | 1418 | */ | |
| 1419 | 1419 | #define HAVE_STAT_NSEC 1 | |
| 1420 | + #define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1 | ||
| 1420 | 1421 | ||
| 1421 | 1422 | struct win32_stat{ | |
| 1422 | 1423 | unsigned long st_dev; | |
@@ -1433,6 +1434,7 @@ struct win32_stat{ | |||
| 1433 | 1434 | int st_mtime_nsec; | |
| 1434 | 1435 | time_t st_ctime; | |
| 1435 | 1436 | int st_ctime_nsec; | |
| 1437 | + unsigned long st_file_attributes; | ||
| 1436 | 1438 | }; | |
| 1437 | 1439 | ||
| 1438 | 1440 | static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */ | |
@@ -1497,6 +1499,7 @@ attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, stru | |||
| 1497 | 1499 | /* now set the bits that make this a symlink */ | |
| 1498 | 1500 | result->st_mode |= S_IFLNK; | |
| 1499 | 1501 | } | |
| 1502 | + result->st_file_attributes = info->dwFileAttributes; | ||
| 1500 | 1503 | ||
| 1501 | 1504 | return 0; | |
| 1502 | 1505 | } | |
@@ -1960,6 +1963,9 @@ static PyStructSequence_Field stat_result_fields[] = { | |||
| 1960 | 1963 | #endif | |
| 1961 | 1964 | #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME | |
| 1962 | 1965 | {"st_birthtime", "time of creation"}, | |
| 1966 | + #endif | ||
| 1967 | + #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES | ||
| 1968 | + {"st_file_attributes", "Windows file attribute bits"}, | ||
| 1963 | 1969 | #endif | |
| 1964 | 1970 | {0} | |
| 1965 | 1971 | }; | |
@@ -2000,6 +2006,12 @@ static PyStructSequence_Field stat_result_fields[] = { | |||
| 2000 | 2006 | #define ST_BIRTHTIME_IDX ST_GEN_IDX | |
| 2001 | 2007 | #endif | |
| 2002 | 2008 | ||
| 2009 | + #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES | ||
| 2010 | + #define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1) | ||
| 2011 | + #else | ||
| 2012 | + #define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX | ||
| 2013 | + #endif | ||
| 2014 | + | ||
| 2003 | 2015 | static PyStructSequence_Desc stat_result_desc = { | |
| 2004 | 2016 | "stat_result", /* name */ | |
| 2005 | 2017 | stat_result__doc__, /* doc */ | |
@@ -2267,6 +2279,10 @@ _pystat_fromstructstat(STRUCT_STAT *st) | |||
| 2267 | 2279 | PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, | |
| 2268 | 2280 | PyLong_FromLong((long)st->st_flags)); | |
| 2269 | 2281 | #endif | |
| 2282 | + #ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES | ||
| 2283 | + PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX, | ||
| 2284 | + PyLong_FromUnsignedLong(st->st_file_attributes)); | ||
| 2285 | + #endif | ||
| 2270 | 2286 | ||
| 2271 | 2287 | if (PyErr_Occurred()) { | |
| 2272 | 2288 | Py_DECREF(v); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments