From fd411c608c5a3cfb7e46ea26fa244d9ab4f5c307 Mon Sep 17 00:00:00 2001 From: Arnon Yaari Date: Wed, 17 Oct 2018 12:27:30 +0300 Subject: [PATCH] Fix #1329: [AIX] disable some functions based on availability in libperfstat --- psutil/_psaix.py | 29 +++++++++++++++++------------ psutil/_psutil_aix.c | 16 ++++++++++++++++ psutil/tests/__init__.py | 7 ++++--- psutil/tests/test_contracts.py | 2 ++ psutil/tests/test_memory_leaks.py | 2 ++ psutil/tests/test_misc.py | 7 ++++--- psutil/tests/test_posix.py | 2 ++ psutil/tests/test_system.py | 3 +++ 8 files changed, 50 insertions(+), 18 deletions(-) diff --git a/psutil/_psaix.py b/psutil/_psaix.py index 7ba212dbf..6ab9efb57 100644 --- a/psutil/_psaix.py +++ b/psutil/_psaix.py @@ -42,6 +42,8 @@ HAS_THREADS = hasattr(cext, "proc_threads") +HAS_NET_IO_COUNTERS = hasattr(cext, "net_io_counters") +HAS_PROC_IO_COUNTERS = hasattr(cext, "proc_io_counters") PAGE_SIZE = os.sysconf('SC_PAGE_SIZE') AF_LINK = cext_posix.AF_LINK @@ -212,7 +214,9 @@ def disk_partitions(all=False): net_if_addrs = cext_posix.net_if_addrs -net_io_counters = cext.net_io_counters + +if HAS_NET_IO_COUNTERS: + net_io_counters = cext.net_io_counters def net_connections(kind, _pid=-1): @@ -561,14 +565,15 @@ def num_ctx_switches(self): def wait(self, timeout=None): return _psposix.wait_pid(self.pid, timeout, self._name) - @wrap_exceptions - def io_counters(self): - try: - rc, wc, rb, wb = cext.proc_io_counters(self.pid) - except OSError: - # if process is terminated, proc_io_counters returns OSError - # instead of NSP - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - raise - return _common.pio(rc, wc, rb, wb) + if HAS_PROC_IO_COUNTERS: + @wrap_exceptions + def io_counters(self): + try: + rc, wc, rb, wb = cext.proc_io_counters(self.pid) + except OSError: + # if process is terminated, proc_io_counters returns OSError + # instead of NSP + if not pid_exists(self.pid): + raise NoSuchProcess(self.pid, self._name) + raise + return _common.pio(rc, wc, rb, wb) diff --git a/psutil/_psutil_aix.c b/psutil/_psutil_aix.c index 898da6b26..adb65b170 100644 --- a/psutil/_psutil_aix.c +++ b/psutil/_psutil_aix.c @@ -13,7 +13,9 @@ * * Known limitations: * - psutil.Process.io_counters read count is always 0 + * - psutil.Process.io_counters may not be available on older AIX versions * - psutil.Process.threads may not be available on older AIX versions + # - psutil.net_io_counters may not be available on older AIX versions * - reading basic process info may fail or return incorrect values when * process is starting (see IBM APAR IV58499 - fixed in newer AIX versions) * - sockets and pipes may not be counted in num_fds (fixed in newer AIX @@ -172,6 +174,7 @@ psutil_proc_name_and_args(PyObject *self, PyObject *args) { #ifdef CURR_VERSION_THREAD + /* * Retrieves all threads used by process returning a list of tuples * including thread id, user time and system time. @@ -237,9 +240,12 @@ psutil_proc_threads(PyObject *self, PyObject *args) { free(threadt); return NULL; } + #endif +#ifdef CURR_VERSION_PROCESS + static PyObject * psutil_proc_io_counters(PyObject *self, PyObject *args) { long pid; @@ -263,6 +269,8 @@ psutil_proc_io_counters(PyObject *self, PyObject *args) { procinfo.outBytes); } +#endif + /* * Return process user and system CPU times as a Python tuple. @@ -469,6 +477,8 @@ psutil_disk_partitions(PyObject *self, PyObject *args) { } +#if defined(CURR_VERSION_NETINTERFACE) && CURR_VERSION_NETINTERFACE >= 3 + /* * Return a list of tuples for network I/O statistics. */ @@ -538,6 +548,8 @@ psutil_net_io_counters(PyObject *self, PyObject *args) { return NULL; } +#endif + static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args) { @@ -878,8 +890,10 @@ PsutilMethods[] = {"proc_threads", psutil_proc_threads, METH_VARARGS, "Return process threads"}, #endif +#ifdef CURR_VERSION_PROCESS {"proc_io_counters", psutil_proc_io_counters, METH_VARARGS, "Get process I/O counters."}, +#endif {"proc_num_ctx_switches", psutil_proc_num_ctx_switches, METH_VARARGS, "Get process I/O counters."}, @@ -898,8 +912,10 @@ PsutilMethods[] = "Return system virtual memory usage statistics"}, {"swap_mem", psutil_swap_mem, METH_VARARGS, "Return stats about swap memory, in bytes"}, +#if defined(CURR_VERSION_NETINTERFACE) && CURR_VERSION_NETINTERFACE >= 3 {"net_io_counters", psutil_net_io_counters, METH_VARARGS, "Return a Python dict of tuples for network I/O statistics."}, +#endif {"net_connections", psutil_net_connections, METH_VARARGS, "Return system-wide connections"}, {"net_if_stats", psutil_net_if_stats, METH_VARARGS, diff --git a/psutil/tests/__init__.py b/psutil/tests/__init__.py index 437588a6f..33a04895f 100644 --- a/psutil/tests/__init__.py +++ b/psutil/tests/__init__.py @@ -160,21 +160,22 @@ # --- support +HAS_CONNECTIONS_UNIX = POSIX and not SUNOS HAS_CPU_AFFINITY = hasattr(psutil.Process, "cpu_affinity") HAS_CPU_FREQ = hasattr(psutil, "cpu_freq") -HAS_CONNECTIONS_UNIX = POSIX and not SUNOS HAS_ENVIRON = hasattr(psutil.Process, "environ") -HAS_PROC_IO_COUNTERS = hasattr(psutil.Process, "io_counters") HAS_IONICE = hasattr(psutil.Process, "ionice") HAS_MEMORY_FULL_INFO = 'uss' in psutil.Process().memory_full_info()._fields HAS_MEMORY_MAPS = hasattr(psutil.Process, "memory_maps") +HAS_NET_IO_COUNTERS = hasattr(psutil, "net_io_counters") HAS_PROC_CPU_NUM = hasattr(psutil.Process, "cpu_num") +HAS_PROC_IO_COUNTERS = hasattr(psutil.Process, "io_counters") HAS_RLIMIT = hasattr(psutil.Process, "rlimit") -HAS_THREADS = hasattr(psutil.Process, "threads") HAS_SENSORS_BATTERY = hasattr(psutil, "sensors_battery") HAS_BATTERY = HAS_SENSORS_BATTERY and bool(psutil.sensors_battery()) HAS_SENSORS_FANS = hasattr(psutil, "sensors_fans") HAS_SENSORS_TEMPERATURES = hasattr(psutil, "sensors_temperatures") +HAS_THREADS = hasattr(psutil.Process, "threads") # --- misc diff --git a/psutil/tests/test_contracts.py b/psutil/tests/test_contracts.py index d936eaf88..b5a3b173f 100755 --- a/psutil/tests/test_contracts.py +++ b/psutil/tests/test_contracts.py @@ -33,6 +33,7 @@ from psutil.tests import check_connection_ntuple from psutil.tests import get_kernel_version from psutil.tests import HAS_CONNECTIONS_UNIX +from psutil.tests import HAS_NET_IO_COUNTERS from psutil.tests import HAS_RLIMIT from psutil.tests import HAS_SENSORS_FANS from psutil.tests import HAS_SENSORS_TEMPERATURES @@ -250,6 +251,7 @@ def test_net_if_stats(self): for ifname, _ in psutil.net_if_stats().items(): self.assertIsInstance(ifname, str) + @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported') def test_net_io_counters(self): # Duplicate of test_system.py. Keep it anyway. for ifname, _ in psutil.net_io_counters(pernic=True).items(): diff --git a/psutil/tests/test_memory_leaks.py b/psutil/tests/test_memory_leaks.py index ce0824596..f8d0d6f49 100755 --- a/psutil/tests/test_memory_leaks.py +++ b/psutil/tests/test_memory_leaks.py @@ -38,6 +38,7 @@ from psutil.tests import HAS_ENVIRON from psutil.tests import HAS_IONICE from psutil.tests import HAS_MEMORY_MAPS +from psutil.tests import HAS_NET_IO_COUNTERS from psutil.tests import HAS_PROC_CPU_NUM from psutil.tests import HAS_PROC_IO_COUNTERS from psutil.tests import HAS_RLIMIT @@ -525,6 +526,7 @@ def test_pids(self): # --- net @skip_if_linux() + @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported') def test_net_io_counters(self): self.execute(psutil.net_io_counters, nowrap=False) diff --git a/psutil/tests/test_misc.py b/psutil/tests/test_misc.py index 3056abc0a..5386a8701 100755 --- a/psutil/tests/test_misc.py +++ b/psutil/tests/test_misc.py @@ -44,6 +44,7 @@ from psutil.tests import HAS_CONNECTIONS_UNIX from psutil.tests import HAS_MEMORY_FULL_INFO from psutil.tests import HAS_MEMORY_MAPS +from psutil.tests import HAS_NET_IO_COUNTERS from psutil.tests import HAS_SENSORS_BATTERY from psutil.tests import HAS_SENSORS_FANS from psutil.tests import HAS_SENSORS_TEMPERATURES @@ -620,10 +621,10 @@ def test_cache_clear(self): wrap_numbers.cache_clear('disk_io') wrap_numbers.cache_clear('?!?') - @unittest.skipIf( - not psutil.disk_io_counters() or not psutil.net_io_counters(), - "no disks or NICs available") + @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported') def test_cache_clear_public_apis(self): + if not psutil.disk_io_counters() or not psutil.net_io_counters(): + return self.skipTest("no disks or NICs available") psutil.disk_io_counters() psutil.net_io_counters() caches = wrap_numbers.cache_info() diff --git a/psutil/tests/test_posix.py b/psutil/tests/test_posix.py index 5a8fdc173..fc4c11ddb 100755 --- a/psutil/tests/test_posix.py +++ b/psutil/tests/test_posix.py @@ -25,6 +25,7 @@ from psutil.tests import APPVEYOR from psutil.tests import get_kernel_version from psutil.tests import get_test_subprocess +from psutil.tests import HAS_NET_IO_COUNTERS from psutil.tests import mock from psutil.tests import PYTHON_EXE from psutil.tests import reap_children @@ -341,6 +342,7 @@ def test_pids(self): @unittest.skipIf(SUNOS, "unreliable on SUNOS") @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") @unittest.skipIf(not which('ifconfig'), "no ifconfig cmd") + @unittest.skipIf(not HAS_NET_IO_COUNTERS, "not supported") def test_nic_names(self): output = sh("ifconfig -a") for nic in psutil.net_io_counters(pernic=True).keys(): diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py index 8b07caff6..ab18e47f4 100755 --- a/psutil/tests/test_system.py +++ b/psutil/tests/test_system.py @@ -38,6 +38,7 @@ from psutil.tests import get_test_subprocess from psutil.tests import HAS_BATTERY from psutil.tests import HAS_CPU_FREQ +from psutil.tests import HAS_NET_IO_COUNTERS from psutil.tests import HAS_SENSORS_BATTERY from psutil.tests import HAS_SENSORS_FANS from psutil.tests import HAS_SENSORS_TEMPERATURES @@ -542,6 +543,7 @@ def find_mount_point(path): self.assertIn(mount, mounts) psutil.disk_usage(mount) + @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported') def test_net_io_counters(self): def check_ntuple(nt): self.assertEqual(nt[0], nt.bytes_sent) @@ -570,6 +572,7 @@ def check_ntuple(nt): self.assertIsInstance(key, str) check_ntuple(ret[key]) + @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported') def test_net_io_counters_no_nics(self): # Emulate a case where no NICs are installed, see: # https://github.com/giampaolo/psutil/issues/1062