summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2020-04-24 12:57:27 +0200
committerGiampaolo Rodola <g.rodola@gmail.com>2020-04-24 12:57:27 +0200
commitbce65960fecded14345520656e8cd456f5ca81d0 (patch)
treeae4dc31674e3d7c26699feb1c8544e308afe90bf
parent10d6950d9cd4c1fcc4b913c768a51f3a53bbac21 (diff)
parent6242f7411b882d525e5d267de4bcda1079934ea2 (diff)
downloadpsutil-bce65960fecded14345520656e8cd456f5ca81d0.tar.gz
Merge branch 'master' of github.com:giampaolo/psutil
-rw-r--r--psutil/_compat.py121
-rw-r--r--psutil/_pslinux.py2
-rw-r--r--psutil/_pswindows.py4
-rw-r--r--psutil/tests/__init__.py6
-rwxr-xr-xpsutil/tests/test_contracts.py3
-rwxr-xr-xpsutil/tests/test_memory_leaks.py5
6 files changed, 111 insertions, 30 deletions
diff --git a/psutil/_compat.py b/psutil/_compat.py
index 64a5761e..145fb71d 100644
--- a/psutil/_compat.py
+++ b/psutil/_compat.py
@@ -2,7 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-"""Module which provides compatibility with older Python versions."""
+"""Module which provides compatibility with older Python versions.
+This is more future-compatible rather than the opposite (prefer latest
+Python 3 way of doing things).
+"""
import collections
import contextlib
@@ -10,19 +13,33 @@ import errno
import functools
import os
import sys
+import types
+
+__all__ = [
+ # constants
+ "PY3",
+ # builtins
+ "long", "range", "super", "unicode", "basestring",
+ # literals
+ "u", "b",
+ # collections module
+ "lru_cache", "redirect_stderr",
+ # shutil module
+ "which", "get_terminal_size",
+ # python 3 exceptions
+ "FileNotFoundError", "PermissionError", "ProcessLookupError",
+ "InterruptedError", "ChildProcessError", "FileExistsError"]
-__all__ = ["PY3", "long", "xrange", "unicode", "basestring", "u", "b",
- "lru_cache", "which", "get_terminal_size", "redirect_stderr",
- "FileNotFoundError", "PermissionError", "ProcessLookupError",
- "InterruptedError", "ChildProcessError", "FileExistsError"]
PY3 = sys.version_info[0] == 3
+_SENTINEL = object()
if PY3:
long = int
xrange = range
unicode = str
basestring = str
+ range = range
def u(s):
return s
@@ -31,7 +48,7 @@ if PY3:
return s.encode("latin-1")
else:
long = long
- xrange = xrange
+ range = xrange
unicode = unicode
basestring = basestring
@@ -42,6 +59,70 @@ else:
return s
+# --- builtins
+
+
+# Python 3 super().
+# Taken from "future" package.
+# Credit: Ryan Kelly
+if PY3:
+ super = super
+else:
+ _builtin_super = super
+
+ def super(type_=_SENTINEL, type_or_obj=_SENTINEL, framedepth=1):
+ """Like Python 3 builtin super(). If called without any arguments
+ it attempts to infer them at runtime.
+ """
+ if type_ is _SENTINEL:
+ f = sys._getframe(framedepth)
+ try:
+ # Get the function's first positional argument.
+ type_or_obj = f.f_locals[f.f_code.co_varnames[0]]
+ except (IndexError, KeyError):
+ raise RuntimeError('super() used in a function with no args')
+ try:
+ # Get the MRO so we can crawl it.
+ mro = type_or_obj.__mro__
+ except (AttributeError, RuntimeError):
+ try:
+ mro = type_or_obj.__class__.__mro__
+ except AttributeError:
+ raise RuntimeError('super() used in a non-newstyle class')
+ for type_ in mro:
+ # Find the class that owns the currently-executing method.
+ for meth in type_.__dict__.values():
+ # Drill down through any wrappers to the underlying func.
+ # This handles e.g. classmethod() and staticmethod().
+ try:
+ while not isinstance(meth, types.FunctionType):
+ if isinstance(meth, property):
+ # Calling __get__ on the property will invoke
+ # user code which might throw exceptions or
+ # have side effects
+ meth = meth.fget
+ else:
+ try:
+ meth = meth.__func__
+ except AttributeError:
+ meth = meth.__get__(type_or_obj, type_)
+ except (AttributeError, TypeError):
+ continue
+ if meth.func_code is f.f_code:
+ break # found
+ else:
+ # Not found. Move onto the next class in MRO.
+ continue
+ break # found
+ else:
+ raise RuntimeError('super() called outside a method')
+
+ # Dispatch to builtin super().
+ if type_or_obj is not _SENTINEL:
+ return _builtin_super(type_, type_or_obj)
+ return _builtin_super(type_)
+
+
# --- exceptions
@@ -57,9 +138,7 @@ else:
# src/future/types/exceptions/pep3151.py
import platform
- _singleton = object()
-
- def instance_checking_exception(base_exception=Exception):
+ def _instance_checking_exception(base_exception=Exception):
def wrapped(instance_checker):
class TemporaryClass(base_exception):
@@ -86,30 +165,30 @@ else:
return wrapped
- @instance_checking_exception(EnvironmentError)
+ @_instance_checking_exception(EnvironmentError)
def FileNotFoundError(inst):
- return getattr(inst, 'errno', _singleton) == errno.ENOENT
+ return getattr(inst, 'errno', _SENTINEL) == errno.ENOENT
- @instance_checking_exception(EnvironmentError)
+ @_instance_checking_exception(EnvironmentError)
def ProcessLookupError(inst):
- return getattr(inst, 'errno', _singleton) == errno.ESRCH
+ return getattr(inst, 'errno', _SENTINEL) == errno.ESRCH
- @instance_checking_exception(EnvironmentError)
+ @_instance_checking_exception(EnvironmentError)
def PermissionError(inst):
- return getattr(inst, 'errno', _singleton) in (
+ return getattr(inst, 'errno', _SENTINEL) in (
errno.EACCES, errno.EPERM)
- @instance_checking_exception(EnvironmentError)
+ @_instance_checking_exception(EnvironmentError)
def InterruptedError(inst):
- return getattr(inst, 'errno', _singleton) == errno.EINTR
+ return getattr(inst, 'errno', _SENTINEL) == errno.EINTR
- @instance_checking_exception(EnvironmentError)
+ @_instance_checking_exception(EnvironmentError)
def ChildProcessError(inst):
- return getattr(inst, 'errno', _singleton) == errno.ECHILD
+ return getattr(inst, 'errno', _SENTINEL) == errno.ECHILD
- @instance_checking_exception(EnvironmentError)
+ @_instance_checking_exception(EnvironmentError)
def FileExistsError(inst):
- return getattr(inst, 'errno', _singleton) == errno.EEXIST
+ return getattr(inst, 'errno', _SENTINEL) == errno.EEXIST
if platform.python_implementation() != "CPython":
try:
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
index aca5fd7d..3e3caace 100644
--- a/psutil/_pslinux.py
+++ b/psutil/_pslinux.py
@@ -846,7 +846,7 @@ class Connections:
# old version - let's keep it, just in case...
# ip = ip.decode('hex')
# return socket.inet_ntop(socket.AF_INET6,
- # ''.join(ip[i:i+4][::-1] for i in xrange(0, 16, 4)))
+ # ''.join(ip[i:i+4][::-1] for i in range(0, 16, 4)))
ip = base64.b16decode(ip)
try:
# see: https://github.com/giampaolo/psutil/issues/201
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index 99d5d714..c1707db7 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -30,8 +30,8 @@ from ._common import usage_percent
from ._compat import long
from ._compat import lru_cache
from ._compat import PY3
+from ._compat import range
from ._compat import unicode
-from ._compat import xrange
from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS
from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS
from ._psutil_windows import HIGH_PRIORITY_CLASS
@@ -1060,7 +1060,7 @@ class Process(object):
@wrap_exceptions
def cpu_affinity_get(self):
def from_bitmask(x):
- return [i for i in xrange(64) if (1 << i) & x]
+ return [i for i in range(64) if (1 << i) & x]
bitmask = cext.proc_cpu_affinity_get(self.pid)
return from_bitmask(bitmask)
diff --git a/psutil/tests/__init__.py b/psutil/tests/__init__.py
index f3358806..d7dd42b2 100644
--- a/psutil/tests/__init__.py
+++ b/psutil/tests/__init__.py
@@ -41,16 +41,16 @@ from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._common import bytes2human
-from psutil._common import supports_ipv6
from psutil._common import print_color
+from psutil._common import supports_ipv6
from psutil._compat import ChildProcessError
from psutil._compat import FileExistsError
from psutil._compat import FileNotFoundError
from psutil._compat import PY3
+from psutil._compat import range
from psutil._compat import u
from psutil._compat import unicode
from psutil._compat import which
-from psutil._compat import xrange
if sys.version_info < (2, 7):
import unittest2 as unittest # requires "pip install unittest2"
@@ -869,7 +869,7 @@ class TestMemoryLeak(unittest.TestCase):
return (diff, ncalls)
def _call_ntimes(self, fun, times):
- return self._itercall(fun, xrange(times))[0]
+ return self._itercall(fun, range(times))[0]
def _call_for(self, fun, secs):
def iterator(secs):
diff --git a/psutil/tests/test_contracts.py b/psutil/tests/test_contracts.py
index 312f17d9..51ac3609 100755
--- a/psutil/tests/test_contracts.py
+++ b/psutil/tests/test_contracts.py
@@ -27,6 +27,7 @@ from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._compat import long
+from psutil._compat import range
from psutil.tests import create_sockets
from psutil.tests import enum
from psutil.tests import get_kernel_version
@@ -620,7 +621,7 @@ class TestFetchAllProcesses(unittest.TestCase):
def cpu_affinity(self, ret, proc):
self.assertIsInstance(ret, list)
assert ret != [], ret
- cpus = range(psutil.cpu_count())
+ cpus = list(range(psutil.cpu_count()))
for n in ret:
self.assertIsInstance(n, int)
self.assertIn(n, cpus)
diff --git a/psutil/tests/test_memory_leaks.py b/psutil/tests/test_memory_leaks.py
index b0b4af1b..3d37f35e 100755
--- a/psutil/tests/test_memory_leaks.py
+++ b/psutil/tests/test_memory_leaks.py
@@ -29,6 +29,7 @@ from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._compat import ProcessLookupError
+from psutil._compat import super
from psutil.tests import CIRRUS
from psutil.tests import create_sockets
from psutil.tests import get_test_subprocess
@@ -283,7 +284,7 @@ class TestTerminatedProcessLeaks(TestProcessObjectLeaks):
@classmethod
def setUpClass(cls):
- super(TestTerminatedProcessLeaks, cls).setUpClass()
+ super().setUpClass()
p = get_test_subprocess()
cls.proc = psutil.Process(p.pid)
cls.proc.kill()
@@ -291,7 +292,7 @@ class TestTerminatedProcessLeaks(TestProcessObjectLeaks):
@classmethod
def tearDownClass(cls):
- super(TestTerminatedProcessLeaks, cls).tearDownClass()
+ super().tearDownClass()
reap_children()
def _call(self, fun):