| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent c6fd7de commit 730ce66
14 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -19,12 +19,12 @@ Sentinel objects | |||
| 19 | 19 | ||
| 20 | 20 | .. versionadded:: 3.15 | |
| 21 | 21 | ||
| 22 | - .. c:function:: PyObject* PySentinel_New(const char *name, const char *module_name) | ||
| 22 | + .. c:function:: PyObject* PySentinel_New(const char *name, const char *module_name, const char *repr) | ||
| 23 | 23 | ||
| 24 | 24 | Return a new :class:`sentinel` object with :attr:`~sentinel.__name__` set to | |
| 25 | 25 | *name* and :attr:`~sentinel.__module__` set to *module_name*. | |
| 26 | 26 | *name* must not be ``NULL``. If *module_name* is ``NULL``, :attr:`~sentinel.__module__` | |
| 27 | - is set to ``None``. | ||
| 27 | + is set to ``None``. If *repr* is ``NULL``, ``repr()`` returns :attr:`~sentinel.__name__`. | ||
| 28 | 28 | Return ``NULL`` with an exception set on failure. | |
| 29 | 29 | ||
| 30 | 30 | For pickling to work, *module_name* must be the name of an importable | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2040,6 +2040,7 @@ PySeqIter_New:PyObject*:seq:0: | |||
| 2040 | 2040 | PySentinel_New:PyObject*::+1: | |
| 2041 | 2041 | PySentinel_New:const char*:name:: | |
| 2042 | 2042 | PySentinel_New:const char*:module_name:: | |
| 2043 | + PySentinel_New:const char*:repr:: | ||
| 2043 | 2044 | ||
| 2044 | 2045 | PySequence_Check:int::: | |
| 2045 | 2046 | PySequence_Check:PyObject*:o:0: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1827,15 +1827,21 @@ are always available. They are listed here in alphabetical order. | |||
| 1827 | 1827 | :func:`setattr`. | |
| 1828 | 1828 | ||
| 1829 | 1829 | ||
| 1830 | - .. class:: sentinel(name, /) | ||
| 1830 | + .. class:: sentinel(name, /, *, repr=None) | ||
| 1831 | 1831 | ||
| 1832 | 1832 | Return a new unique sentinel object. *name* must be a :class:`str`, and is | |
| 1833 | - used as the returned object's representation:: | ||
| 1833 | + used by default as the returned object's representation:: | ||
| 1834 | 1834 | ||
| 1835 | 1835 | >>> MISSING = sentinel("MISSING") | |
| 1836 | 1836 | >>> MISSING | |
| 1837 | 1837 | MISSING | |
| 1838 | 1838 | ||
| 1839 | + The optional *repr* argument can be used to specify a different representation:: | ||
| 1840 | + | ||
| 1841 | + >>> MISSING = sentinel("MISSING", repr="<MISSING>") | ||
| 1842 | + >>> MISSING | ||
| 1843 | + <MISSING> | ||
| 1844 | + | ||
| 1839 | 1845 | Sentinel objects are truthy and compare equal only to themselves. They are | |
| 1840 | 1846 | intended to be compared with the :keyword:`is` operator. | |
| 1841 | 1847 | ||
@@ -1879,7 +1885,7 @@ are always available. They are listed here in alphabetical order. | |||
| 1879 | 1885 | ||
| 1880 | 1886 | .. attribute:: __module__ | |
| 1881 | 1887 | ||
| 1882 | - The name of the module where the sentinel was created. | ||
| 1888 | + The name of the module where the sentinel was created. This attribute is writable. | ||
| 1883 | 1889 | ||
| 1884 | 1890 | .. versionadded:: 3.15 | |
| 1885 | 1891 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,7 +13,8 @@ PyAPI_DATA(PyTypeObject) PySentinel_Type; | |||
| 13 | 13 | ||
| 14 | 14 | PyAPI_FUNC(PyObject *) PySentinel_New( | |
| 15 | 15 | const char *name, | |
| 16 | - const char *module_name); | ||
| 16 | + const char *module_name, | ||
| 17 | + const char *repr); | ||
| 17 | 18 | ||
| 18 | 19 | #ifdef __cplusplus | |
| 19 | 20 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -754,6 +754,7 @@ struct _Py_global_strings { | |||
| 754 | 754 | STRUCT_FOR_ID(repeat) | |
| 755 | 755 | STRUCT_FOR_ID(repl) | |
| 756 | 756 | STRUCT_FOR_ID(replace) | |
| 757 | + STRUCT_FOR_ID(repr) | ||
| 757 | 758 | STRUCT_FOR_ID(reqrefs) | |
| 758 | 759 | STRUCT_FOR_ID(require_ready) | |
| 759 | 760 | STRUCT_FOR_ID(reserved) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1956,16 +1956,33 @@ def test_sentinel(self): | |||
| 1956 | 1956 | with self.assertRaises(TypeError): | |
| 1957 | 1957 | class SubSentinel(sentinel): | |
| 1958 | 1958 | pass | |
| 1959 | + | ||
| 1960 | + def test_sentinel_attributes(self): | ||
| 1961 | + missing = sentinel("MISSING") | ||
| 1959 | 1962 | with self.assertRaises(TypeError): | |
| 1960 | 1963 | sentinel.attribute = "value" | |
| 1961 | 1964 | with self.assertRaises(AttributeError): | |
| 1962 | - missing.__name__ = "CHANGED" | ||
| 1965 | + missing.attribute = "value" | ||
| 1963 | 1966 | with self.assertRaises(AttributeError): | |
| 1964 | - missing.__module__ = "changed" | ||
| 1967 | + missing.__name__ = "CHANGED" | ||
| 1968 | + missing.__module__ = "changed" | ||
| 1969 | + self.assertEqual(missing.__module__, "changed") | ||
| 1965 | 1970 | with self.assertRaises(AttributeError): | |
| 1966 | 1971 | del missing.__name__ | |
| 1972 | + del missing.__module__ | ||
| 1967 | 1973 | with self.assertRaises(AttributeError): | |
| 1968 | - del missing.__module__ | ||
| 1974 | + missing.__module__ | ||
| 1975 | + | ||
| 1976 | + def test_sentinel_repr(self): | ||
| 1977 | + with_repr = sentinel("WITH_REPR", repr="custom") | ||
| 1978 | + without_repr = sentinel("WITHOUT_REPR", repr=None) | ||
| 1979 | + self.assertEqual(repr(with_repr), "custom") | ||
| 1980 | + self.assertEqual(repr(without_repr), "WITHOUT_REPR") | ||
| 1981 | + self.assertEqual(str(with_repr), "custom") | ||
| 1982 | + self.assertEqual(str(without_repr), "WITHOUT_REPR") | ||
| 1983 | + | ||
| 1984 | + with self.assertRaisesRegex(TypeError, "repr.*str or None"): | ||
| 1985 | + sentinel("BAD_REPR", repr=42) | ||
| 1969 | 1986 | ||
| 1970 | 1987 | def test_sentinel_pickle(self): | |
| 1971 | 1988 | for proto in range(pickle.HIGHEST_PROTOCOL + 1): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -80,6 +80,12 @@ def test_pysentinel_new(self): | |||
| 80 | 80 | self.assertEqual(no_module.__name__, "NO_MODULE") | |
| 81 | 81 | self.assertIs(no_module.__module__, None) | |
| 82 | 82 | ||
| 83 | + with_repr = _testcapi.pysentinel_new("WITH_REPR", __name__, "custom repr") | ||
| 84 | + self.assertIs(type(with_repr), sentinel) | ||
| 85 | + self.assertEqual(with_repr.__name__, "WITH_REPR") | ||
| 86 | + self.assertEqual(with_repr.__module__, __name__) | ||
| 87 | + self.assertEqual(repr(with_repr), "custom repr") | ||
| 88 | + | ||
| 83 | 89 | globals()["CAPI_SENTINEL"] = marker | |
| 84 | 90 | self.addCleanup(globals().pop, "CAPI_SENTINEL", None) | |
| 85 | 91 | self.assertIs(pickle.loads(pickle.dumps(marker)), marker) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments