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.\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,76 @@ return version_info; } +PyDoc_STRVAR(impl_info__doc__, +"sys.implementation\n\ +\n\ +Implementation-specific 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)"}, + {"hexversion", "Implementation version in hexadecimal format"}, + {"cache_tag", "PEP 3147 cache tag"}, + {0} +}; + +static PyStructSequence_Desc impl_info_desc = { + "sys.implementation", /* name */ + impl_info__doc__, /* doc */ + impl_info_fields, /* fields */ + 4 +}; + +static PyObject * +make_impl_info(PyObject *version_info) +{ + int pos = 0; + PyObject *impl_info, *value; + + impl_info = PyStructSequence_New(&ImplInfoType); + if (impl_info == NULL) { + return NULL; + } + +#define NAME "cpython" +#define QUOTE(arg) #arg +#define STRIFY(name) QUOTE(name) +#define MAJOR STRIFY(PY_MAJOR_VERSION) +#define MINOR STRIFY(PY_MINOR_VERSION) +#define TAG NAME "-" MAJOR MINOR + value = PyUnicode_FromString(NAME); + if (value == NULL) + goto error; + PyStructSequence_SET_ITEM(impl_info, pos++, value); + + Py_INCREF(version_info); + PyStructSequence_SET_ITEM(impl_info, pos++, version_info); + + value = PyLong_FromLong(PY_VERSION_HEX); + if (value == NULL) + goto error; + PyStructSequence_SET_ITEM(impl_info, pos++, value); + + value = PyUnicode_FromString(TAG); + if (value == NULL) + goto error; + PyStructSequence_SET_ITEM(impl_info, pos++, value); +#undef NAME +#undef QUOTE +#undef STRIFY +#undef MAJOR +#undef MINOR +#undef TAG + + return impl_info; + +error: + Py_CLEAR(impl_info); + return NULL; +} + static struct PyModuleDef sysmodule = { PyModuleDef_HEAD_INIT, "sys", @@ -1469,7 +1540,7 @@ PyObject * _PySys_Init(void) { - PyObject *m, *v, *sysdict; + PyObject *m, *v, *sysdict, *version_info; char *s; m = PyModule_Create(&sysmodule); @@ -1585,11 +1656,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);