summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_capi
diff options
context:
space:
mode:
authorPetr Viktorin <encukou@gmail.com>2022-11-22 07:25:43 (GMT)
committerGitHub <noreply@github.com>2022-11-22 07:25:43 (GMT)
commit4d82f628c44490d6fbc3f6998d2473d1304d891f (patch)
tree18f77c7b3b48fe7acecbb4e967e677e8420bf778 /Lib/test/test_capi
parent1bf983ce7eb8bfd17dc18102b61dfbdafe0deda2 (diff)
downloadcpython-4d82f628c44490d6fbc3f6998d2473d1304d891f.zip
cpython-4d82f628c44490d6fbc3f6998d2473d1304d891f.tar.gz
cpython-4d82f628c44490d6fbc3f6998d2473d1304d891f.tar.bz2
gh-47146: Soft-deprecate structmember.h, expose its contents via Python.h (GH-99014)
The ``structmember.h`` header is deprecated, though it continues to be available and there are no plans to remove it. There are no deprecation warnings. Old code can stay unchanged (unless the extra include and non-namespaced macros bother you greatly). Specifically, no uses in CPython are updated -- that would just be unnecessary churn. The ``structmember.h`` header is deprecated, though it continues to be available and there are no plans to remove it. Its contents are now available just by including ``Python.h``, with a ``Py`` prefix added if it was missing: - `PyMemberDef`, `PyMember_GetOne` and`PyMember_SetOne` - Type macros like `Py_T_INT`, `Py_T_DOUBLE`, etc. (previously ``T_INT``, ``T_DOUBLE``, etc.) - The flags `Py_READONLY` (previously ``READONLY``) and `Py_AUDIT_READ` (previously all uppercase) Several items are not exposed from ``Python.h``: - `T_OBJECT` (use `Py_T_OBJECT_EX`) - `T_NONE` (previously undocumented, and pretty quirky) - The macro ``WRITE_RESTRICTED`` which does nothing. - The macros ``RESTRICTED`` and ``READ_RESTRICTED``, equivalents of `Py_AUDIT_READ`. - In some configurations, ``<stddef.h>`` is not included from ``Python.h``. It should be included manually when using ``offsetof()``. The deprecated header continues to provide its original contents under the original names. Your old code can stay unchanged, unless the extra include and non-namespaced macros bother you greatly. There is discussion on the issue to rename `T_PYSSIZET` to `PY_T_SSIZE` or similar. I chose not to do that -- users will probably copy/paste that with any spelling, and not renaming it makes migration docs simpler. Co-Authored-By: Alexander Belopolsky <abalkin@users.noreply.github.com> Co-Authored-By: Matthias Braun <MatzeB@users.noreply.github.com>
Diffstat (limited to 'Lib/test/test_capi')
-rw-r--r--Lib/test/test_capi/test_structmembers.py91
1 files changed, 65 insertions, 26 deletions
diff --git a/Lib/test/test_capi/test_structmembers.py b/Lib/test/test_capi/test_structmembers.py
index 07d2f62..2cf46b2 100644
--- a/Lib/test/test_capi/test_structmembers.py
+++ b/Lib/test/test_capi/test_structmembers.py
@@ -4,32 +4,42 @@ from test.support import warnings_helper
# Skip this test if the _testcapi module isn't available.
import_helper.import_module('_testcapi')
-from _testcapi import _test_structmembersType, \
- CHAR_MAX, CHAR_MIN, UCHAR_MAX, \
- SHRT_MAX, SHRT_MIN, USHRT_MAX, \
- INT_MAX, INT_MIN, UINT_MAX, \
- LONG_MAX, LONG_MIN, ULONG_MAX, \
- LLONG_MAX, LLONG_MIN, ULLONG_MAX, \
- PY_SSIZE_T_MAX, PY_SSIZE_T_MIN
-
-ts=_test_structmembersType(False, # T_BOOL
- 1, # T_BYTE
- 2, # T_UBYTE
- 3, # T_SHORT
- 4, # T_USHORT
- 5, # T_INT
- 6, # T_UINT
- 7, # T_LONG
- 8, # T_ULONG
- 23, # T_PYSSIZET
- 9.99999,# T_FLOAT
- 10.1010101010, # T_DOUBLE
- "hi" # T_STRING_INPLACE
- )
-
-class ReadWriteTests(unittest.TestCase):
+from _testcapi import (_test_structmembersType_OldAPI,
+ _test_structmembersType_NewAPI,
+ CHAR_MAX, CHAR_MIN, UCHAR_MAX,
+ SHRT_MAX, SHRT_MIN, USHRT_MAX,
+ INT_MAX, INT_MIN, UINT_MAX,
+ LONG_MAX, LONG_MIN, ULONG_MAX,
+ LLONG_MAX, LLONG_MIN, ULLONG_MAX,
+ PY_SSIZE_T_MAX, PY_SSIZE_T_MIN,
+ )
+
+# There are two classes: one using <structmember.h> and another using
+# `Py_`-prefixed API. They should behave the same in Python
+
+def _make_test_object(cls):
+ return cls(False, # T_BOOL
+ 1, # T_BYTE
+ 2, # T_UBYTE
+ 3, # T_SHORT
+ 4, # T_USHORT
+ 5, # T_INT
+ 6, # T_UINT
+ 7, # T_LONG
+ 8, # T_ULONG
+ 23, # T_PYSSIZET
+ 9.99999,# T_FLOAT
+ 10.1010101010, # T_DOUBLE
+ "hi", # T_STRING_INPLACE
+ )
+
+
+class ReadWriteTests:
+ def setUp(self):
+ self.ts = _make_test_object(self.cls)
def test_bool(self):
+ ts = self.ts
ts.T_BOOL = True
self.assertEqual(ts.T_BOOL, True)
ts.T_BOOL = False
@@ -37,6 +47,7 @@ class ReadWriteTests(unittest.TestCase):
self.assertRaises(TypeError, setattr, ts, 'T_BOOL', 1)
def test_byte(self):
+ ts = self.ts
ts.T_BYTE = CHAR_MAX
self.assertEqual(ts.T_BYTE, CHAR_MAX)
ts.T_BYTE = CHAR_MIN
@@ -45,6 +56,7 @@ class ReadWriteTests(unittest.TestCase):
self.assertEqual(ts.T_UBYTE, UCHAR_MAX)
def test_short(self):
+ ts = self.ts
ts.T_SHORT = SHRT_MAX
self.assertEqual(ts.T_SHORT, SHRT_MAX)
ts.T_SHORT = SHRT_MIN
@@ -53,6 +65,7 @@ class ReadWriteTests(unittest.TestCase):
self.assertEqual(ts.T_USHORT, USHRT_MAX)
def test_int(self):
+ ts = self.ts
ts.T_INT = INT_MAX
self.assertEqual(ts.T_INT, INT_MAX)
ts.T_INT = INT_MIN
@@ -61,6 +74,7 @@ class ReadWriteTests(unittest.TestCase):
self.assertEqual(ts.T_UINT, UINT_MAX)
def test_long(self):
+ ts = self.ts
ts.T_LONG = LONG_MAX
self.assertEqual(ts.T_LONG, LONG_MAX)
ts.T_LONG = LONG_MIN
@@ -69,13 +83,17 @@ class ReadWriteTests(unittest.TestCase):
self.assertEqual(ts.T_ULONG, ULONG_MAX)
def test_py_ssize_t(self):
+ ts = self.ts
ts.T_PYSSIZET = PY_SSIZE_T_MAX
self.assertEqual(ts.T_PYSSIZET, PY_SSIZE_T_MAX)
ts.T_PYSSIZET = PY_SSIZE_T_MIN
self.assertEqual(ts.T_PYSSIZET, PY_SSIZE_T_MIN)
- @unittest.skipUnless(hasattr(ts, "T_LONGLONG"), "long long not present")
def test_longlong(self):
+ ts = self.ts
+ if not hasattr(ts, "T_LONGLONG"):
+ self.skipTest("long long not present")
+
ts.T_LONGLONG = LLONG_MAX
self.assertEqual(ts.T_LONGLONG, LLONG_MAX)
ts.T_LONGLONG = LLONG_MIN
@@ -91,6 +109,7 @@ class ReadWriteTests(unittest.TestCase):
self.assertEqual(ts.T_ULONGLONG, 4)
def test_bad_assignments(self):
+ ts = self.ts
integer_attributes = [
'T_BOOL',
'T_BYTE', 'T_UBYTE',
@@ -109,37 +128,57 @@ class ReadWriteTests(unittest.TestCase):
self.assertRaises(TypeError, setattr, ts, attr, nonint)
def test_inplace_string(self):
+ ts = self.ts
self.assertEqual(ts.T_STRING_INPLACE, "hi")
self.assertRaises(TypeError, setattr, ts, "T_STRING_INPLACE", "s")
self.assertRaises(TypeError, delattr, ts, "T_STRING_INPLACE")
+class ReadWriteTests_OldAPI(ReadWriteTests, unittest.TestCase):
+ cls = _test_structmembersType_OldAPI
+
+class ReadWriteTests_NewAPI(ReadWriteTests, unittest.TestCase):
+ cls = _test_structmembersType_NewAPI
-class TestWarnings(unittest.TestCase):
+class TestWarnings:
+ def setUp(self):
+ self.ts = _make_test_object(self.cls)
def test_byte_max(self):
+ ts = self.ts
with warnings_helper.check_warnings(('', RuntimeWarning)):
ts.T_BYTE = CHAR_MAX+1
def test_byte_min(self):
+ ts = self.ts
with warnings_helper.check_warnings(('', RuntimeWarning)):
ts.T_BYTE = CHAR_MIN-1
def test_ubyte_max(self):
+ ts = self.ts
with warnings_helper.check_warnings(('', RuntimeWarning)):
ts.T_UBYTE = UCHAR_MAX+1
def test_short_max(self):
+ ts = self.ts
with warnings_helper.check_warnings(('', RuntimeWarning)):
ts.T_SHORT = SHRT_MAX+1
def test_short_min(self):
+ ts = self.ts
with warnings_helper.check_warnings(('', RuntimeWarning)):
ts.T_SHORT = SHRT_MIN-1
def test_ushort_max(self):
+ ts = self.ts
with warnings_helper.check_warnings(('', RuntimeWarning)):
ts.T_USHORT = USHRT_MAX+1
+class TestWarnings_OldAPI(TestWarnings, unittest.TestCase):
+ cls = _test_structmembersType_OldAPI
+
+class TestWarnings_NewAPI(TestWarnings, unittest.TestCase):
+ cls = _test_structmembersType_NewAPI
+
if __name__ == "__main__":
unittest.main()