bpo-31680: Add curses.ncurses_version. (GH-4217)
Use curses.ncurses_version for conditionally skipping a test.
This commit is contained in:
parent
3e429dcc24
commit
b232df9197
|
@ -1291,6 +1291,19 @@ The :mod:`curses` module defines the following data members:
|
||||||
A bytes object representing the current version of the module. Also available as
|
A bytes object representing the current version of the module. Also available as
|
||||||
:const:`__version__`.
|
:const:`__version__`.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: ncurses_version
|
||||||
|
|
||||||
|
A named tuple containing the three components of the ncurses library
|
||||||
|
version: *major*, *minor*, and *patch*. All values are integers. The
|
||||||
|
components can also be accessed by name, so ``curses.ncurses_version[0]``
|
||||||
|
is equivalent to ``curses.ncurses_version.major`` and so on.
|
||||||
|
|
||||||
|
Availability: if the ncurses library is used.
|
||||||
|
|
||||||
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
|
||||||
Some constants are available to specify character cell attributes.
|
Some constants are available to specify character cell attributes.
|
||||||
The exact constants available are system dependent.
|
The exact constants available are system dependent.
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,15 @@ now return ``False`` instead of raising :exc:`ValueError` or its subclasses
|
||||||
characters or bytes unrepresentable at the OS level.
|
characters or bytes unrepresentable at the OS level.
|
||||||
(Contributed by Serhiy Storchaka in :issue:`33721`.)
|
(Contributed by Serhiy Storchaka in :issue:`33721`.)
|
||||||
|
|
||||||
|
|
||||||
|
ncurses
|
||||||
|
-------
|
||||||
|
|
||||||
|
Added a new variable holding structured version information for the
|
||||||
|
underlying ncurses library: :data:`~curses.ncurses_version`.
|
||||||
|
(Contributed by Serhiy Storchaka in :issue:`31680`.)
|
||||||
|
|
||||||
|
|
||||||
pathlib
|
pathlib
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|
|
@ -368,9 +368,8 @@ class TestCurses(unittest.TestCase):
|
||||||
self.stdscr.getkey()
|
self.stdscr.getkey()
|
||||||
|
|
||||||
@requires_curses_func('unget_wch')
|
@requires_curses_func('unget_wch')
|
||||||
# XXX Remove the decorator when ncurses on OpenBSD be updated
|
@unittest.skipIf(getattr(curses, 'ncurses_version', (99,)) < (5, 8),
|
||||||
@unittest.skipIf(sys.platform.startswith("openbsd"),
|
"unget_wch is broken in ncurses 5.7 and earlier")
|
||||||
"OpenBSD's curses (v.5.7) has bugs")
|
|
||||||
def test_unget_wch(self):
|
def test_unget_wch(self):
|
||||||
stdscr = self.stdscr
|
stdscr = self.stdscr
|
||||||
encoding = stdscr.encoding
|
encoding = stdscr.encoding
|
||||||
|
@ -456,6 +455,23 @@ class MiscTests(unittest.TestCase):
|
||||||
# can be called.
|
# can be called.
|
||||||
curses.update_lines_cols()
|
curses.update_lines_cols()
|
||||||
|
|
||||||
|
@requires_curses_func('ncurses_version')
|
||||||
|
def test_ncurses_version(self):
|
||||||
|
v = curses.ncurses_version
|
||||||
|
self.assertIsInstance(v[:], tuple)
|
||||||
|
self.assertEqual(len(v), 3)
|
||||||
|
self.assertIsInstance(v[0], int)
|
||||||
|
self.assertIsInstance(v[1], int)
|
||||||
|
self.assertIsInstance(v[2], int)
|
||||||
|
self.assertIsInstance(v.major, int)
|
||||||
|
self.assertIsInstance(v.minor, int)
|
||||||
|
self.assertIsInstance(v.patch, int)
|
||||||
|
self.assertEqual(v[0], v.major)
|
||||||
|
self.assertEqual(v[1], v.minor)
|
||||||
|
self.assertEqual(v[2], v.patch)
|
||||||
|
self.assertGreaterEqual(v.major, 0)
|
||||||
|
self.assertGreaterEqual(v.minor, 0)
|
||||||
|
self.assertGreaterEqual(v.patch, 0)
|
||||||
|
|
||||||
class TestAscii(unittest.TestCase):
|
class TestAscii(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Added :data:`curses.ncurses_version`.
|
|
@ -4289,6 +4289,59 @@ _curses_use_default_colors_impl(PyObject *module)
|
||||||
}
|
}
|
||||||
#endif /* STRICT_SYSV_CURSES */
|
#endif /* STRICT_SYSV_CURSES */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef NCURSES_VERSION
|
||||||
|
|
||||||
|
PyDoc_STRVAR(ncurses_version__doc__,
|
||||||
|
"curses.ncurses_version\n\
|
||||||
|
\n\
|
||||||
|
Ncurses version information as a named tuple.");
|
||||||
|
|
||||||
|
static PyTypeObject NcursesVersionType;
|
||||||
|
|
||||||
|
static PyStructSequence_Field ncurses_version_fields[] = {
|
||||||
|
{"major", "Major release number"},
|
||||||
|
{"minor", "Minor release number"},
|
||||||
|
{"patch", "Patch release number"},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyStructSequence_Desc ncurses_version_desc = {
|
||||||
|
"curses.ncurses_version", /* name */
|
||||||
|
ncurses_version__doc__, /* doc */
|
||||||
|
ncurses_version_fields, /* fields */
|
||||||
|
3
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
make_ncurses_version(void)
|
||||||
|
{
|
||||||
|
PyObject *ncurses_version;
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
ncurses_version = PyStructSequence_New(&NcursesVersionType);
|
||||||
|
if (ncurses_version == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SetIntItem(flag) \
|
||||||
|
PyStructSequence_SET_ITEM(ncurses_version, pos++, PyLong_FromLong(flag)); \
|
||||||
|
if (PyErr_Occurred()) { \
|
||||||
|
Py_CLEAR(ncurses_version); \
|
||||||
|
return NULL; \
|
||||||
|
}
|
||||||
|
|
||||||
|
SetIntItem(NCURSES_VERSION_MAJOR)
|
||||||
|
SetIntItem(NCURSES_VERSION_MINOR)
|
||||||
|
SetIntItem(NCURSES_VERSION_PATCH)
|
||||||
|
#undef SetIntItem
|
||||||
|
|
||||||
|
return ncurses_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* NCURSES_VERSION */
|
||||||
|
|
||||||
|
|
||||||
/* List of functions defined in the module */
|
/* List of functions defined in the module */
|
||||||
|
|
||||||
static PyMethodDef PyCurses_methods[] = {
|
static PyMethodDef PyCurses_methods[] = {
|
||||||
|
@ -4426,6 +4479,30 @@ PyInit__curses(void)
|
||||||
PyDict_SetItemString(d, "__version__", v);
|
PyDict_SetItemString(d, "__version__", v);
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
|
|
||||||
|
#ifdef NCURSES_VERSION
|
||||||
|
/* ncurses_version */
|
||||||
|
if (NcursesVersionType.tp_name == NULL) {
|
||||||
|
if (PyStructSequence_InitType2(&NcursesVersionType,
|
||||||
|
&ncurses_version_desc) < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
v = make_ncurses_version();
|
||||||
|
if (v == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyDict_SetItemString(d, "ncurses_version", v);
|
||||||
|
Py_DECREF(v);
|
||||||
|
|
||||||
|
/* prevent user from creating new instances */
|
||||||
|
NcursesVersionType.tp_init = NULL;
|
||||||
|
NcursesVersionType.tp_new = NULL;
|
||||||
|
if (PyDict_DelItemString(NcursesVersionType.tp_dict, "__new__") < 0 &&
|
||||||
|
PyErr_ExceptionMatches(PyExc_KeyError))
|
||||||
|
{
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
#endif /* NCURSES_VERSION */
|
||||||
|
|
||||||
SetDictInt("ERR", ERR);
|
SetDictInt("ERR", ERR);
|
||||||
SetDictInt("OK", OK);
|
SetDictInt("OK", OK);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue