diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -586,6 +586,23 @@ Thus ``2.1.0a3`` is hexversion ``0x020100a3``. + +.. data:: implementation + + A "named" tuple containing the information about the currently running + Python implementation. Depending on the implementation of Python, the + tuple may contain any number of fields describing the implementation. + However, the first two fields will always be *name* and *version*. + + *name* is the implementation's common name, like ``'CPython'``. + + *version* is a version tuple, in the format of :data:`sys.version_info`, + which represents the version of the Python implementation, **not** the + version of the Python specification it implements. + + .. versionadded:: 3.3 + + .. data:: int_info A :term:`struct sequence` that holds information about Python's internal diff --git a/Python/sysmodule.c b/Python/sysmodule.c --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1261,6 +1261,7 @@ float_info -- a struct sequence with information about the float implementation.\n\ float_repr_style -- string indicating the style of repr() output for floats\n\ hexversion -- version information encoded as a single integer\n\ +implementation -- Python implementation information as a named tuple\n\ int_info -- a struct sequence with information about the int implementation.\n\ maxsize -- the largest supported length of containers.\n\ maxunicode -- the value of the largest Unicode codepoint\n\ @@ -1454,6 +1455,49 @@ return version_info; } +PyDoc_STRVAR(impl_info__doc__, +"sys.implementation\n\ +\n\ +Python implementation information as a named tuple."); + +static PyTypeObject ImplInfoType; + +static PyStructSequence_Field impl_info_fields[] = { + {"name", "The implementation's name"}, + {"version", "Implementation version (as opposed to the Python version)"}, + {0} +}; + +static PyStructSequence_Desc impl_info_desc = { + "sys.implementation", /* name */ + impl_info__doc__, /* doc */ + impl_info_fields, /* fields */ + 2 +}; + +static PyObject * +make_impl_info(PyObject *version_info) +{ + PyObject *impl_info; + int pos = 0; + + impl_info = PyStructSequence_New(&ImplInfoType); + if (impl_info == NULL) { + return NULL; + } + + PyStructSequence_SET_ITEM(impl_info, pos++, + PyUnicode_FromString("CPython")); + Py_INCREF(version_info); + PyStructSequence_SET_ITEM(impl_info, pos++, version_info); + + if (PyErr_Occurred()) { + Py_CLEAR(impl_info); + return NULL; + } + return impl_info; +} + static struct PyModuleDef sysmodule = { PyModuleDef_HEAD_INIT, "sys", @@ -1469,7 +1513,7 @@ PyObject * _PySys_Init(void) { - PyObject *m, *v, *sysdict; + PyObject *m, *v, *sysdict, *version_info; char *s; m = PyModule_Create(&sysmodule); @@ -1585,11 +1629,20 @@ /* version_info */ if (VersionInfoType.tp_name == 0) PyStructSequence_InitType(&VersionInfoType, &version_info_desc); - SET_SYS_FROM_STRING("version_info", make_version_info()); + version_info = make_version_info(); + SET_SYS_FROM_STRING("version_info", version_info); /* prevent user from creating new instances */ VersionInfoType.tp_init = NULL; VersionInfoType.tp_new = NULL; + /* implementation */ + if (ImplInfoType.tp_name == 0) + PyStructSequence_InitType(&ImplInfoType, &impl_info_desc); + SET_SYS_FROM_STRING("implementation", make_impl_info(version_info)); + /* prevent user from creating new instances */ + ImplInfoType.tp_init = NULL; + ImplInfoType.tp_new = NULL; + /* flags */ if (FlagsType.tp_name == 0) PyStructSequence_InitType(&FlagsType, &flags_desc);