diff planemo/lib/python3.7/site-packages/psutil/_psposix.py @ 1:56ad4e20f292 draft

"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
author guerler
date Fri, 31 Jul 2020 00:32:28 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/planemo/lib/python3.7/site-packages/psutil/_psposix.py	Fri Jul 31 00:32:28 2020 -0400
@@ -0,0 +1,223 @@
+# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Routines common to all posix systems."""
+
+import glob
+import os
+import signal
+import sys
+import time
+
+from ._common import memoize
+from ._common import sdiskusage
+from ._common import TimeoutExpired
+from ._common import usage_percent
+from ._compat import ChildProcessError
+from ._compat import FileNotFoundError
+from ._compat import InterruptedError
+from ._compat import PermissionError
+from ._compat import ProcessLookupError
+from ._compat import PY3
+from ._compat import unicode
+
+if sys.version_info >= (3, 4):
+    import enum
+else:
+    enum = None
+
+
+__all__ = ['pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map']
+
+
+def pid_exists(pid):
+    """Check whether pid exists in the current process table."""
+    if pid == 0:
+        # According to "man 2 kill" PID 0 has a special meaning:
+        # it refers to <<every process in the process group of the
+        # calling process>> so we don't want to go any further.
+        # If we get here it means this UNIX platform *does* have
+        # a process with id 0.
+        return True
+    try:
+        os.kill(pid, 0)
+    except ProcessLookupError:
+        return False
+    except PermissionError:
+        # EPERM clearly means there's a process to deny access to
+        return True
+    # According to "man 2 kill" possible error values are
+    # (EINVAL, EPERM, ESRCH)
+    else:
+        return True
+
+
+# Python 3.5 signals enum (contributed by me ^^):
+# https://bugs.python.org/issue21076
+if enum is not None and hasattr(signal, "Signals"):
+    Negsignal = enum.IntEnum(
+        'Negsignal', dict([(x.name, -x.value) for x in signal.Signals]))
+
+    def negsig_to_enum(num):
+        """Convert a negative signal value to an enum."""
+        try:
+            return Negsignal(num)
+        except ValueError:
+            return num
+else:
+    def negsig_to_enum(num):
+        return num
+
+
+def wait_pid(pid, timeout=None, proc_name=None,
+             _waitpid=os.waitpid,
+             _timer=getattr(time, 'monotonic', time.time),
+             _min=min,
+             _sleep=time.sleep,
+             _pid_exists=pid_exists):
+    """Wait for a process PID to terminate.
+
+    If the process terminated normally by calling exit(3) or _exit(2),
+    or by returning from main(), the return value is the positive integer
+    passed to *exit().
+
+    If it was terminated by a signal it returns the negated value of the
+    signal which caused the termination (e.g. -SIGTERM).
+
+    If PID is not a children of os.getpid() (current process) just
+    wait until the process disappears and return None.
+
+    If PID does not exist at all return None immediately.
+
+    If *timeout* != None and process is still alive raise TimeoutExpired.
+    timeout=0 is also possible (either return immediately or raise).
+    """
+    if pid <= 0:
+        raise ValueError("can't wait for PID 0")  # see "man waitpid"
+    interval = 0.0001
+    flags = 0
+    if timeout is not None:
+        flags |= os.WNOHANG
+        stop_at = _timer() + timeout
+
+    def sleep(interval):
+        # Sleep for some time and return a new increased interval.
+        if timeout is not None:
+            if _timer() >= stop_at:
+                raise TimeoutExpired(timeout, pid=pid, name=proc_name)
+        _sleep(interval)
+        return _min(interval * 2, 0.04)
+
+    # See: https://linux.die.net/man/2/waitpid
+    while True:
+        try:
+            retpid, status = os.waitpid(pid, flags)
+        except InterruptedError:
+            interval = sleep(interval)
+        except ChildProcessError:
+            # This has two meanings:
+            # - PID is not a child of os.getpid() in which case
+            #   we keep polling until it's gone
+            # - PID never existed in the first place
+            # In both cases we'll eventually return None as we
+            # can't determine its exit status code.
+            while _pid_exists(pid):
+                interval = sleep(interval)
+            return
+        else:
+            if retpid == 0:
+                # WNOHANG flag was used and PID is still running.
+                interval = sleep(interval)
+                continue
+            elif os.WIFEXITED(status):
+                # Process terminated normally by calling exit(3) or _exit(2),
+                # or by returning from main(). The return value is the
+                # positive integer passed to *exit().
+                return os.WEXITSTATUS(status)
+            elif os.WIFSIGNALED(status):
+                # Process exited due to a signal. Return the negative value
+                # of that signal.
+                return negsig_to_enum(-os.WTERMSIG(status))
+            # elif os.WIFSTOPPED(status):
+            #     # Process was stopped via SIGSTOP or is being traced, and
+            #     # waitpid() was called with WUNTRACED flag. PID is still
+            #     # alive. From now on waitpid() will keep returning (0, 0)
+            #     # until the process state doesn't change.
+            #     # It may make sense to catch/enable this since stopped PIDs
+            #     # ignore SIGTERM.
+            #     interval = sleep(interval)
+            #     continue
+            # elif os.WIFCONTINUED(status):
+            #     # Process was resumed via SIGCONT and waitpid() was called
+            #     # with WCONTINUED flag.
+            #     interval = sleep(interval)
+            #     continue
+            else:
+                # Should never happen.
+                raise ValueError("unknown process exit status %r" % status)
+
+
+def disk_usage(path):
+    """Return disk usage associated with path.
+    Note: UNIX usually reserves 5% disk space which is not accessible
+    by user. In this function "total" and "used" values reflect the
+    total and used disk space whereas "free" and "percent" represent
+    the "free" and "used percent" user disk space.
+    """
+    if PY3:
+        st = os.statvfs(path)
+    else:
+        # os.statvfs() does not support unicode on Python 2:
+        # - https://github.com/giampaolo/psutil/issues/416
+        # - http://bugs.python.org/issue18695
+        try:
+            st = os.statvfs(path)
+        except UnicodeEncodeError:
+            if isinstance(path, unicode):
+                try:
+                    path = path.encode(sys.getfilesystemencoding())
+                except UnicodeEncodeError:
+                    pass
+                st = os.statvfs(path)
+            else:
+                raise
+
+    # Total space which is only available to root (unless changed
+    # at system level).
+    total = (st.f_blocks * st.f_frsize)
+    # Remaining free space usable by root.
+    avail_to_root = (st.f_bfree * st.f_frsize)
+    # Remaining free space usable by user.
+    avail_to_user = (st.f_bavail * st.f_frsize)
+    # Total space being used in general.
+    used = (total - avail_to_root)
+    # Total space which is available to user (same as 'total' but
+    # for the user).
+    total_user = used + avail_to_user
+    # User usage percent compared to the total amount of space
+    # the user can use. This number would be higher if compared
+    # to root's because the user has less space (usually -5%).
+    usage_percent_user = usage_percent(used, total_user, round_=1)
+
+    # NB: the percentage is -5% than what shown by df due to
+    # reserved blocks that we are currently not considering:
+    # https://github.com/giampaolo/psutil/issues/829#issuecomment-223750462
+    return sdiskusage(
+        total=total, used=used, free=avail_to_user, percent=usage_percent_user)
+
+
+@memoize
+def get_terminal_map():
+    """Get a map of device-id -> path as a dict.
+    Used by Process.terminal()
+    """
+    ret = {}
+    ls = glob.glob('/dev/tty*') + glob.glob('/dev/pts/*')
+    for name in ls:
+        assert name not in ret, name
+        try:
+            ret[os.stat(name).st_rdev] = name
+        except FileNotFoundError:
+            pass
+    return ret