Unverified Kaydet (Commit) b232df91 authored tarafından Serhiy Storchaka's avatar Serhiy Storchaka Kaydeden (comit) GitHub

bpo-31680: Add curses.ncurses_version. (GH-4217)

Use curses.ncurses_version for conditionally skipping a test.
üst 3e429dcc
...@@ -1291,6 +1291,19 @@ The :mod:`curses` module defines the following data members: ...@@ -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 ...@@ -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): ...@@ -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): ...@@ -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):
......
...@@ -4289,6 +4289,59 @@ _curses_use_default_colors_impl(PyObject *module) ...@@ -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) ...@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment