]> granicus.if.org Git - python/commitdiff
Issue #15118: Change return value of os.uname() and os.times() from
authorLarry Hastings <larry@hastings.org>
Sun, 24 Jun 2012 11:33:36 +0000 (04:33 -0700)
committerLarry Hastings <larry@hastings.org>
Sun, 24 Jun 2012 11:33:36 +0000 (04:33 -0700)
plain tuples to immutable iterable objects with named attributes
(structseq objects).

Doc/library/os.rst
Lib/ctypes/__init__.py
Lib/ctypes/util.py
Lib/platform.py
Lib/test/test__locale.py
Lib/test/test_locale.py
Lib/test/test_sysconfig.py
Lib/uuid.py
Misc/NEWS
Modules/posixmodule.c

index 59b1d10bafd929a7252c82207c99307ac07b72ae..9556be6319a6996862f21260b1d8113df8657ed1 100644 (file)
@@ -570,15 +570,31 @@ process and user.
       single: gethostname() (in module socket)
       single: gethostbyaddr() (in module socket)
 
-   Return a 5-tuple containing information identifying the current operating
-   system.  The tuple contains 5 strings: ``(sysname, nodename, release, version,
-   machine)``.  Some systems truncate the nodename to 8 characters or to the
+   Returns information identifying the current operating system.
+   The return value is an object with five attributes:
+
+   * :attr:`sysname` - operating system name
+   * :attr:`nodename` - name of machine on network (implementation-defined)
+   * :attr:`release` - operating system release
+   * :attr:`version` - operating system version
+   * :attr:`machine` - hardware identifier
+
+   For backwards compatibility, this object is also iterable, behaving
+   like a five-tuple containing :attr:`sysname`, :attr:`nodename`,
+   :attr:`release`, :attr:`version`, and :attr:`machine`
+   in that order.
+
+   Some systems truncate :attr:`nodename` to 8 characters or to the
    leading component; a better way to get the hostname is
    :func:`socket.gethostname`  or even
    ``socket.gethostbyaddr(socket.gethostname())``.
 
    Availability: recent flavors of Unix.
 
+   .. versionchanged:: 3.3
+      Return type changed from a tuple to a tuple-like object
+      with named attributes.
+
 
 .. function:: unsetenv(key)
 
@@ -2801,15 +2817,31 @@ written in Python, such as a mail server's external command delivery program.
 
 .. function:: times()
 
-   Return a 5-tuple of floating point numbers indicating accumulated (processor
-   or other) times, in seconds.  The items are: user time, system time,
-   children's user time, children's system time, and elapsed real time since a
-   fixed point in the past, in that order.  See the Unix manual page
+   Returns the current global process times.
+   The return value is an object with five attributes:
+
+   * :attr:`user` - user time
+   * :attr:`system` - system time
+   * :attr:`children_user` - user time of all child processes
+   * :attr:`children_system` - system time of all child processes
+   * :attr:`elapsed` - elapsed real time since a fixed point in the past
+
+   For backwards compatibility, this object also behaves like a five-tuple
+   containing :attr:`user`, :attr:`system`, :attr:`children_user`,
+   :attr:`children_system`, and :attr:`elapsed` in that order.
+
+   See the Unix manual page
    :manpage:`times(2)` or the corresponding Windows Platform API documentation.
-   On Windows, only the first two items are filled, the others are zero.
+   On Windows, only :attr:`user` and :attr:`system` are known; the other
+   attributes are zero.
+   On OS/2, only :attr:`elapsed` is known; the other attributes are zero.
 
    Availability: Unix, Windows.
 
+   .. versionchanged:: 3.3
+      Return type changed from a tuple to a tuple-like object
+      with named attributes.
+
 
 .. function:: wait()
 
index 111209a9535a5d0ef3e221725e929f7bda6e3ada..f0bd66a17c86c92e1983d06b8d4fde4643c05ac1 100644 (file)
@@ -26,7 +26,7 @@ if _os.name == "posix" and _sys.platform == "darwin":
     # libraries.  OS X 10.3 is Darwin 7, so we check for
     # that.
 
-    if int(_os.uname()[2].split('.')[0]) < 8:
+    if int(_os.uname().release.split('.')[0]) < 8:
         DEFAULT_MODE = RTLD_GLOBAL
 
 from _ctypes import FUNCFLAG_CDECL as _FUNCFLAG_CDECL, \
index 61eb09454b85c1bf150c8d2c689c6c1a1cb8a5b0..5555b2e41febe32f60c3095195563c088c77ee5c 100644 (file)
@@ -171,9 +171,9 @@ elif os.name == "posix":
         def _findSoname_ldconfig(name):
             import struct
             if struct.calcsize('l') == 4:
-                machine = os.uname()[4] + '-32'
+                machine = os.uname().machine + '-32'
             else:
-                machine = os.uname()[4] + '-64'
+                machine = os.uname().machine + '-64'
             mach_map = {
                 'x86_64-64': 'libc6,x86-64',
                 'ppc64-64': 'libc6,64bit',
index 45546599b4e835fd8ba316b91d42fc65279fca7a..b7dbcca78aa3e67d0859cccda6a9bf88b715a764 100755 (executable)
@@ -700,7 +700,7 @@ def _mac_ver_xml():
     pl = plistlib.readPlist(fn)
     release = pl['ProductVersion']
     versioninfo=('', '', '')
-    machine = os.uname()[4]
+    machine = os.uname().machine
     if machine in ('ppc', 'Power Macintosh'):
         # for compatibility with the gestalt based code
         machine = 'PowerPC'
index f7f1abdab2088b930a1914f5af736e14e88ead8a..dab1565fbe2a7d0d82fafdc5944e7ec115b46a0a 100644 (file)
@@ -12,7 +12,7 @@ from platform import uname
 from test.support import run_unittest
 
 if uname()[0] == "Darwin":
-    maj, min, mic = [int(part) for part in uname()[2].split(".")]
+    maj, min, mic = [int(part) for part in uname().release.split(".")]
     if (maj, min, mic) < (8, 0, 0):
         raise unittest.SkipTest("locale support broken for OS X < 10.4")
 
index 7fdb6dafdd0030f0c12bc3a11145411c912a3e85..51a7bca4b622e17c1c67f647097b9ba63cf73830 100644 (file)
@@ -11,7 +11,7 @@ def get_enUS_locale():
     if sys.platform == 'darwin':
         import os
         tlocs = ("en_US.UTF-8", "en_US.ISO8859-1", "en_US")
-        if int(os.uname()[2].split('.')[0]) < 10:
+        if int(os.uname().release.split('.')[0]) < 10:
             # The locale test work fine on OSX 10.6, I (ronaldoussoren)
             # haven't had time yet to verify if tests work on OSX 10.5
             # (10.4 is known to be bad)
index 3cb63ed8c4b517329be16e06e53e0fa4adadc64f..aa5d5828242971f36ef2b83f31474742abfa151b 100644 (file)
@@ -14,7 +14,6 @@ from sysconfig import (get_paths, get_platform, get_config_vars,
                        _get_default_scheme, _expand_vars,
                        get_scheme_names, get_config_var, _main)
 
-
 class TestSysConfig(unittest.TestCase):
 
     def setUp(self):
@@ -26,7 +25,7 @@ class TestSysConfig(unittest.TestCase):
             self._uname = os.uname()
         else:
             self.uname = None
-            self._uname = None
+            self._set_uname(('',)*5)
         os.uname = self._get_uname
         # saving the environment
         self.name = os.name
@@ -70,7 +69,7 @@ class TestSysConfig(unittest.TestCase):
         super(TestSysConfig, self).tearDown()
 
     def _set_uname(self, uname):
-        self._uname = uname
+        self._uname = os.uname_result(uname)
 
     def _get_uname(self):
         return self._uname
index 5684ad7aceece0a916103ad460478d9973d5167a..0df0743c4c50ef28045944c759d92694a00f6ed3 100644 (file)
@@ -440,7 +440,7 @@ try:
     import sys
     if sys.platform == 'darwin':
         import os
-        if int(os.uname()[2].split('.')[0]) >= 9:
+        if int(os.uname().release.split('.')[0]) >= 9:
             _uuid_generate_random = _uuid_generate_time = None
 
     # On Windows prior to 2000, UuidCreate gives a UUID containing the
index 6f3b85d76330bf3755eae1c99fba9252155ad0cb..d4edb95cf740220551eb05115d75d1250d03e970 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -55,6 +55,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #15118: Change return value of os.uname() and os.times() from
+  plain tuples to immutable iterable objects with named attributes
+  (structseq objects).
+
 - Speed up _decimal by another 10-15% by caching the thread local context
   that was last accessed. In the pi benchmark (64-bit platform, prec=9),
   _decimal is now only 1.5x slower than float.
index 6da030a371da6cf890637d8c9919e3b8a7495abc..6cd8d883f6f54ab8eda40e798526eacbb03a29f9 100644 (file)
@@ -4299,28 +4299,76 @@ exit:
 }
 
 
-#ifdef HAVE_UNAME
 PyDoc_STRVAR(posix_uname__doc__,
-"uname() -> (sysname, nodename, release, version, machine)\n\n\
-Return a tuple identifying the current operating system.");
+"uname() -> uname_result\n\n\
+Return an object identifying the current operating system.\n\
+The object behaves like a named tuple with the following fields:\n\
+  (sysname, nodename, release, version, machine)");
+
+static PyStructSequence_Field uname_result_fields[] = {
+    {"sysname",    "operating system name"},
+    {"nodename",   "name of machine on network (implementation-defined)"},
+    {"release",    "operating system release"},
+    {"version",    "operating system version"},
+    {"machine",    "hardware identifier"},
+    {NULL}
+};
+
+PyDoc_STRVAR(uname_result__doc__,
+"uname_result: Result from os.uname().\n\n\
+This object may be accessed either as a tuple of\n\
+  (sysname, nodename, release, version, machine),\n\
+or via the attributes sysname, nodename, release, version, and machine.\n\
+\n\
+See os.uname for more information.");
+
+static PyStructSequence_Desc uname_result_desc = {
+    "uname_result", /* name */
+    uname_result__doc__, /* doc */
+    uname_result_fields,
+    5
+};
 
+static PyTypeObject UnameResultType;
+
+
+#ifdef HAVE_UNAME
 static PyObject *
 posix_uname(PyObject *self, PyObject *noargs)
 {
     struct utsname u;
     int res;
+    PyObject *value;
 
     Py_BEGIN_ALLOW_THREADS
     res = uname(&u);
     Py_END_ALLOW_THREADS
     if (res < 0)
         return posix_error();
-    return Py_BuildValue("(sssss)",
-                         u.sysname,
-                         u.nodename,
-                         u.release,
-                         u.version,
-                         u.machine);
+
+    value = PyStructSequence_New(&UnameResultType);
+    if (value == NULL)
+        return NULL;
+
+#define SET(i, field) \
+    { \
+    PyObject *o = PyUnicode_DecodeASCII(field, strlen(field), NULL); \
+    if (!o) { \
+        Py_DECREF(value); \
+        return NULL; \
+    } \
+    PyStructSequence_SET_ITEM(value, i, o); \
+    } \
+
+    SET(0, u.sysname);
+    SET(1, u.nodename);
+    SET(2, u.release);
+    SET(3, u.version);
+    SET(4, u.machine);
+
+#undef SET
+
+    return value;
 }
 #endif /* HAVE_UNAME */
 
@@ -7366,6 +7414,75 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs)
 #endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
 
 
+static PyStructSequence_Field times_result_fields[] = {
+    {"user",    "user time"},
+    {"system",   "system time"},
+    {"children_user",    "user time of children"},
+    {"children_system",    "system time of children"},
+    {"elapsed",    "elapsed time since an arbitrary point in the past"},
+    {NULL}
+};
+
+PyDoc_STRVAR(times_result__doc__,
+"times_result: Result from os.times().\n\n\
+This object may be accessed either as a tuple of\n\
+  (user, system, children_user, children_system, elapsed),\n\
+or via the attributes user, system, children_user, children_system,\n\
+and elapsed.\n\
+\n\
+See os.times for more information.");
+
+static PyStructSequence_Desc times_result_desc = {
+    "times_result", /* name */
+    times_result__doc__, /* doc */
+    times_result_fields,
+    5
+};
+
+static PyTypeObject TimesResultType;
+
+
+#if defined(HAVE_TIMES) || defined(MS_WINDOWS)
+
+static PyObject *
+build_times_result(double user, double system,
+    double children_user, double children_system,
+    double elapsed)
+{
+    PyObject *value = PyStructSequence_New(&TimesResultType);
+    if (value == NULL)
+        return NULL;
+
+#define SET(i, field) \
+    { \
+    PyObject *o = PyFloat_FromDouble(field); \
+    if (!o) { \
+        Py_DECREF(value); \
+        return NULL; \
+    } \
+    PyStructSequence_SET_ITEM(value, i, o); \
+    } \
+
+    SET(0, user);
+    SET(1, system);
+    SET(2, children_user);
+    SET(3, children_system);
+    SET(4, elapsed);
+
+#undef SET
+
+    return value;
+}
+
+PyDoc_STRVAR(posix_times__doc__,
+"times() -> times_result\n\n\
+Return an object containing floating point numbers indicating process\n\
+times.  The object behaves like a named tuple with these fields:\n\
+  (utime, stime, cutime, cstime, elapsed_time)");
+
+#endif
+
+
 #ifdef HAVE_TIMES
 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
 static long
@@ -7384,7 +7501,7 @@ static PyObject *
 posix_times(PyObject *self, PyObject *noargs)
 {
     /* Currently Only Uptime is Provided -- Others Later */
-    return Py_BuildValue("ddddd",
+    return build_times_result(
                          (double)0 /* t.tms_utime / HZ */,
                          (double)0 /* t.tms_stime / HZ */,
                          (double)0 /* t.tms_cutime / HZ */,
@@ -7403,7 +7520,7 @@ posix_times(PyObject *self, PyObject *noargs)
     c = times(&t);
     if (c == (clock_t) -1)
         return posix_error();
-    return Py_BuildValue("ddddd",
+    return build_times_result(
                          (double)t.tms_utime / ticks_per_second,
                          (double)t.tms_stime / ticks_per_second,
                          (double)t.tms_cutime / ticks_per_second,
@@ -7411,11 +7528,7 @@ posix_times(PyObject *self, PyObject *noargs)
                          (double)c / ticks_per_second);
 }
 #endif /* not OS2 */
-#endif /* HAVE_TIMES */
-
-
-#ifdef MS_WINDOWS
-#define HAVE_TIMES      /* so the method table will pick it up */
+#elif defined(MS_WINDOWS)
 static PyObject *
 posix_times(PyObject *self, PyObject *noargs)
 {
@@ -7428,8 +7541,7 @@ posix_times(PyObject *self, PyObject *noargs)
        1e7 is one second in such units; 1e-7 the inverse.
        429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
     */
-    return Py_BuildValue(
-        "ddddd",
+    return build_times_result(
         (double)(user.dwHighDateTime*429.4967296 +
                  user.dwLowDateTime*1e-7),
         (double)(kernel.dwHighDateTime*429.4967296 +
@@ -7438,12 +7550,6 @@ posix_times(PyObject *self, PyObject *noargs)
         (double)0,
         (double)0);
 }
-#endif /* MS_WINDOWS */
-
-#ifdef HAVE_TIMES
-PyDoc_STRVAR(posix_times__doc__,
-"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
-Return a tuple of floating point numbers indicating process times.");
 #endif
 
 
@@ -11965,6 +12071,14 @@ INITFUNC(void)
     PyModule_AddObject(m, "sched_param", (PyObject *)&SchedParamType);
 #endif
 
+    times_result_desc.name = MODNAME ".times_result";
+    PyStructSequence_InitType(&TimesResultType, &times_result_desc);
+    PyModule_AddObject(m, "times_result", (PyObject *)&TimesResultType);
+
+    uname_result_desc.name = MODNAME ".uname_result";
+    PyStructSequence_InitType(&UnameResultType, &uname_result_desc);
+    PyModule_AddObject(m, "uname_result", (PyObject *)&UnameResultType);
+
 #ifdef __APPLE__
     /*
      * Step 2 of weak-linking support on Mac OS X.