diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/LICENSE b/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/LICENSE deleted file mode 100644 index 0bf4a7fc04a1..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola' -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name of the psutil authors nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/METADATA b/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/METADATA deleted file mode 100644 index 18b1e9280530..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/METADATA +++ /dev/null @@ -1,582 +0,0 @@ -Metadata-Version: 2.1 -Name: psutil -Version: 5.7.0 -Summary: Cross-platform lib for process and system monitoring in Python. -Home-page: https://github.com/giampaolo/psutil -Author: Giampaolo Rodola -Author-email: g.rodola@gmail.com -License: BSD -Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,pstree,monitoring,ulimit,prlimit,smem,performance,metrics,agent,observability -Platform: Platform Independent -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Console -Classifier: Environment :: Win32 (MS Windows) -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Information Technology -Classifier: Intended Audience :: System Administrators -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: Microsoft :: Windows :: Windows 10 -Classifier: Operating System :: Microsoft :: Windows :: Windows 7 -Classifier: Operating System :: Microsoft :: Windows :: Windows 8 -Classifier: Operating System :: Microsoft :: Windows :: Windows 8.1 -Classifier: Operating System :: Microsoft :: Windows :: Windows Server 2003 -Classifier: Operating System :: Microsoft :: Windows :: Windows Server 2008 -Classifier: Operating System :: Microsoft :: Windows :: Windows Vista -Classifier: Operating System :: Microsoft -Classifier: Operating System :: OS Independent -Classifier: Operating System :: POSIX :: AIX -Classifier: Operating System :: POSIX :: BSD :: FreeBSD -Classifier: Operating System :: POSIX :: BSD :: NetBSD -Classifier: Operating System :: POSIX :: BSD :: OpenBSD -Classifier: Operating System :: POSIX :: BSD -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: POSIX :: SunOS/Solaris -Classifier: Operating System :: POSIX -Classifier: Programming Language :: C -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Programming Language :: Python -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Software Development :: Libraries -Classifier: Topic :: System :: Benchmark -Classifier: Topic :: System :: Hardware :: Hardware Drivers -Classifier: Topic :: System :: Hardware -Classifier: Topic :: System :: Monitoring -Classifier: Topic :: System :: Networking :: Monitoring :: Hardware Watchdog -Classifier: Topic :: System :: Networking :: Monitoring -Classifier: Topic :: System :: Networking -Classifier: Topic :: System :: Operating System -Classifier: Topic :: System :: Systems Administration -Classifier: Topic :: Utilities -Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* -Provides-Extra: enum -Requires-Dist: enum34 ; extra == 'enum' - -| |downloads| |stars| |forks| |contributors| |coverage| |quality| -| |version| |py-versions| |packages| |license| -| |travis| |appveyor| |cirrus| |doc| |twitter| |tidelift| - -.. |downloads| image:: https://img.shields.io/pypi/dm/psutil.svg - :target: https://pepy.tech/project/psutil - :alt: Downloads - -.. |stars| image:: https://img.shields.io/github/stars/giampaolo/psutil.svg - :target: https://github.com/giampaolo/psutil/stargazers - :alt: Github stars - -.. |forks| image:: https://img.shields.io/github/forks/giampaolo/psutil.svg - :target: https://github.com/giampaolo/psutil/network/members - :alt: Github forks - -.. |contributors| image:: https://img.shields.io/github/contributors/giampaolo/psutil.svg - :target: https://github.com/giampaolo/psutil/graphs/contributors - :alt: Contributors - -.. |quality| image:: https://img.shields.io/codacy/grade/ce63e7f7f69d44b5b59682196e6fbfca.svg - :target: https://www.codacy.com/app/g-rodola/psutil?utm_source=github.com&utm_medium=referral&utm_content=giampaolo/psutil&utm_campaign=Badge_Grade - :alt: Code quality - -.. |travis| image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux,%20OSX,%20PyPy - :target: https://travis-ci.org/giampaolo/psutil - :alt: Linux tests (Travis) - -.. |appveyor| image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows - :target: https://ci.appveyor.com/project/giampaolo/psutil - :alt: Windows tests (Appveyor) - -.. |cirrus| image:: https://img.shields.io/cirrus/github/giampaolo/psutil?label=FreeBSD - :target: https://cirrus-ci.com/github/giampaolo/psutil-cirrus-ci - :alt: FreeBSD tests (Cirrus-Ci) - -.. |coverage| image:: https://img.shields.io/coveralls/github/giampaolo/psutil.svg?label=test%20coverage - :target: https://coveralls.io/github/giampaolo/psutil?branch=master - :alt: Test coverage (coverall.io) - -.. |doc| image:: https://readthedocs.org/projects/psutil/badge/?version=latest - :target: http://psutil.readthedocs.io/en/latest/?badge=latest - :alt: Documentation Status - -.. |version| image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi - :target: https://pypi.org/project/psutil - :alt: Latest version - -.. |py-versions| image:: https://img.shields.io/pypi/pyversions/psutil.svg - :target: https://pypi.org/project/psutil - :alt: Supported Python versions - -.. |packages| image:: https://repology.org/badge/tiny-repos/python:psutil.svg - :target: https://repology.org/metapackage/python:psutil/versions - :alt: Binary packages - -.. |license| image:: https://img.shields.io/pypi/l/psutil.svg - :target: https://github.com/giampaolo/psutil/blob/master/LICENSE - :alt: License - -.. |twitter| image:: https://img.shields.io/twitter/follow/grodola.svg?label=follow&style=flat&logo=twitter&logoColor=4FADFF - :target: https://twitter.com/grodola - :alt: Twitter Follow - -.. |tidelift| image:: https://tidelift.com/badges/github/giampaolo/psutil?style=flat - :target: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme - :alt: Tidelift - ------ - -Quick links -=========== - -- `Home page `_ -- `Install `_ -- `Documentation `_ -- `Download `_ -- `Forum `_ -- `StackOverflow `_ -- `Blog `_ -- `Development guide `_ -- `What's new `_ - -Summary -======= - -psutil (process and system utilities) is a cross-platform library for -retrieving information on **running processes** and **system utilization** -(CPU, memory, disks, network, sensors) in Python. -It is useful mainly for **system monitoring**, **profiling and limiting process -resources** and **management of running processes**. -It implements many functionalities offered by classic UNIX command line tools -such as *ps, top, iotop, lsof, netstat, ifconfig, free* and others. -psutil currently supports the following platforms: - -- **Linux** -- **Windows** -- **macOS** -- **FreeBSD, OpenBSD**, **NetBSD** -- **Sun Solaris** -- **AIX** - -...both **32-bit** and **64-bit** architectures. Supported Python versions are **2.6**, **2.7** and **3.4+**. `PyPy3 `__ is also known to work. - -psutil for enterprise -===================== - -.. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png - :width: 150 - :alt: Tidelift - :target: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme - -.. list-table:: - :widths: 10 150 - - * - |tideliftlogo| - - The maintainer of psutil and thousands of other packages are working - with Tidelift to deliver commercial support and maintenance for the open - source dependencies you use to build your applications. Save time, - reduce risk, and improve code health, while paying the maintainers of - the exact dependencies you use. - `Learn more `__. - - By subscribing to Tidelift you will help me (`Giampaolo Rodola`_) support - psutil future development. Alternatively consider making a small - `donation`_. - -Security -======== - -To report a security vulnerability, please use the `Tidelift security -contact`_. Tidelift will coordinate the fix and disclosure. - -Example applications -==================== - -+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/top-small.png | -| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/top.png | -+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap-small.png | -| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap.png | -+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ - -Also see `scripts directory `__ -and `doc recipes `__. - -Projects using psutil -===================== - -psutil has roughly the following monthly downloads: - -.. image:: https://img.shields.io/pypi/dm/psutil.svg - :target: https://pepy.tech/project/psutil - :alt: Downloads - -There are over -`10.000 open source projects `__ -on github which depend from psutil. -Here's some I find particularly interesting: - -- https://github.com/google/grr -- https://github.com/facebook/osquery/ -- https://github.com/nicolargo/glances -- https://github.com/Jahaja/psdash -- https://github.com/ajenti/ajenti -- https://github.com/home-assistant/home-assistant/ - - -Portings -======== - -- Go: https://github.com/shirou/gopsutil -- C: https://github.com/hamon-in/cpslib -- Rust: https://github.com/borntyping/rust-psutil -- Nim: https://github.com/johnscillieri/psutil-nim - - -Example usages -============== - -This represents pretty much the whole psutil API. - -CPU ---- - -.. code-block:: python - - >>> import psutil - >>> - >>> psutil.cpu_times() - scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0) - >>> - >>> for x in range(3): - ... psutil.cpu_percent(interval=1) - ... - 4.0 - 5.9 - 3.8 - >>> - >>> for x in range(3): - ... psutil.cpu_percent(interval=1, percpu=True) - ... - [4.0, 6.9, 3.7, 9.2] - [7.0, 8.5, 2.4, 2.1] - [1.2, 9.0, 9.9, 7.2] - >>> - >>> for x in range(3): - ... psutil.cpu_times_percent(interval=1, percpu=False) - ... - scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - >>> - >>> psutil.cpu_count() - 4 - >>> psutil.cpu_count(logical=False) - 2 - >>> - >>> psutil.cpu_stats() - scpustats(ctx_switches=20455687, interrupts=6598984, soft_interrupts=2134212, syscalls=0) - >>> - >>> psutil.cpu_freq() - scpufreq(current=931.42925, min=800.0, max=3500.0) - >>> - >>> psutil.getloadavg() # also on Windows (emulated) - (3.14, 3.89, 4.67) - -Memory ------- - -.. code-block:: python - - >>> psutil.virtual_memory() - svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304) - >>> psutil.swap_memory() - sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944) - >>> - -Disks ------ - -.. code-block:: python - - >>> psutil.disk_partitions() - [sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'), - sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')] - >>> - >>> psutil.disk_usage('/') - sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5) - >>> - >>> psutil.disk_io_counters(perdisk=False) - sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568, read_merged_count=619166, write_merged_count=812396, busy_time=4523412) - >>> - -Network -------- - -.. code-block:: python - - >>> psutil.net_io_counters(pernic=True) - {'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0), - 'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)} - >>> - >>> psutil.net_connections() - [sconn(fd=115, family=, type=, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254), - sconn(fd=117, family=, type=, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING', pid=2987), - ...] - >>> - >>> psutil.net_if_addrs() - {'lo': [snicaddr(family=, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None), - snicaddr(family=, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None), - snicaddr(family=, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)], - 'wlan0': [snicaddr(family=, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None), - snicaddr(family=, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None), - snicaddr(family=, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]} - >>> - >>> psutil.net_if_stats() - {'lo': snicstats(isup=True, duplex=, speed=0, mtu=65536), - 'wlan0': snicstats(isup=True, duplex=, speed=100, mtu=1500)} - >>> - -Sensors -------- - -.. code-block:: python - - >>> import psutil - >>> psutil.sensors_temperatures() - {'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)], - 'asus': [shwtemp(label='', current=47.0, high=None, critical=None)], - 'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0), - shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0)]} - >>> - >>> psutil.sensors_fans() - {'asus': [sfan(label='cpu_fan', current=3200)]} - >>> - >>> psutil.sensors_battery() - sbattery(percent=93, secsleft=16628, power_plugged=False) - >>> - -Other system info ------------------ - -.. code-block:: python - - >>> import psutil - >>> psutil.users() - [suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0, pid=1352), - suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0, pid=1788)] - >>> - >>> psutil.boot_time() - 1365519115.0 - >>> - -Process management ------------------- - -.. code-block:: python - - >>> import psutil - >>> psutil.pids() - [1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224, 268, 1215, 1216, 1220, 1221, 1243, 1244, - 1301, 1601, 2237, 2355, 2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, 4263, 4282, - 4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358, 4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446, - 5167, 5234, 5235, 5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071] - >>> - >>> p = psutil.Process(7055) - >>> p - psutil.Process(pid=7055, name='python', started='09:04:44') - >>> p.name() - 'python' - >>> p.exe() - '/usr/bin/python' - >>> p.cwd() - '/home/giampaolo' - >>> p.cmdline() - ['/usr/bin/python', 'main.py'] - >>> - >>> p.pid - 7055 - >>> p.ppid() - 7054 - >>> p.children(recursive=True) - [psutil.Process(pid=29835, name='python2.7', started='11:45:38'), - psutil.Process(pid=29836, name='python2.7', started='11:43:39')] - >>> - >>> p.parent() - psutil.Process(pid=4699, name='bash', started='09:06:44') - >>> p.parents() - [psutil.Process(pid=4699, name='bash', started='09:06:44'), - psutil.Process(pid=4689, name='gnome-terminal-server', started='0:06:44'), - psutil.Process(pid=1, name='systemd', started='05:56:55')] - >>> - >>> p.status() - 'running' - >>> p.username() - 'giampaolo' - >>> p.create_time() - 1267551141.5019531 - >>> p.terminal() - '/dev/pts/0' - >>> - >>> p.uids() - puids(real=1000, effective=1000, saved=1000) - >>> p.gids() - pgids(real=1000, effective=1000, saved=1000) - >>> - >>> p.cpu_times() - pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1, iowait=0.0) - >>> p.cpu_percent(interval=1.0) - 12.1 - >>> p.cpu_affinity() - [0, 1, 2, 3] - >>> p.cpu_affinity([0, 1]) # set - >>> p.cpu_num() - 1 - >>> - >>> p.memory_info() - pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0) - >>> p.memory_full_info() # "real" USS memory usage (Linux, macOS, Win only) - pfullmem(rss=10199040, vms=52133888, shared=3887104, text=2867200, lib=0, data=5967872, dirty=0, uss=6545408, pss=6872064, swap=0) - >>> p.memory_percent() - 0.7823 - >>> p.memory_maps() - [pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0), - pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0), - pmmap_grouped(path='[heap]', rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0), - pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0), - ...] - >>> - >>> p.io_counters() - pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632, read_chars=456232, write_chars=517543) - >>> - >>> p.open_files() - [popenfile(path='/home/giampaolo/monit.py', fd=3, position=0, mode='r', flags=32768), - popenfile(path='/var/log/monit.log', fd=4, position=235542, mode='a', flags=33793)] - >>> - >>> p.connections() - [pconn(fd=115, family=, type=, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'), - pconn(fd=117, family=, type=, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING')] - >>> - >>> p.num_threads() - 4 - >>> p.num_fds() - 8 - >>> p.threads() - [pthread(id=5234, user_time=22.5, system_time=9.2891), - pthread(id=5237, user_time=0.0707, system_time=1.1)] - >>> - >>> p.num_ctx_switches() - pctxsw(voluntary=78, involuntary=19) - >>> - >>> p.nice() - 0 - >>> p.nice(10) # set - >>> - >>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only) - >>> p.ionice() - pionice(ioclass=, value=0) - >>> - >>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only) - >>> p.rlimit(psutil.RLIMIT_NOFILE) - (5, 5) - >>> - >>> p.environ() - {'LC_PAPER': 'it_IT.UTF-8', 'SHELL': '/bin/bash', 'GREP_OPTIONS': '--color=auto', - 'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg', - ...} - >>> - >>> p.as_dict() - {'status': 'running', 'num_ctx_switches': pctxsw(voluntary=63, involuntary=1), 'pid': 5457, ...} - >>> p.is_running() - True - >>> p.suspend() - >>> p.resume() - >>> - >>> p.terminate() - >>> p.kill() - >>> p.wait(timeout=3) - 0 - >>> - >>> psutil.test() - USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND - root 1 0.0 0.0 24584 2240 Jun17 00:00 init - root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd - ... - giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4 - giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome - root 31763 0.0 0.0 0 0 00:05 00:00 kworker/0:1 - >>> - -Further process APIs --------------------- - -.. code-block:: python - - >>> import psutil - >>> for proc in psutil.process_iter(['pid', 'name']): - ... print(proc.info) - ... - {'pid': 1, 'name': 'systemd'} - {'pid': 2, 'name': 'kthreadd'} - {'pid': 3, 'name': 'ksoftirqd/0'} - ... - >>> - >>> psutil.pid_exists(3) - True - >>> - >>> def on_terminate(proc): - ... print("process {} terminated".format(proc)) - ... - >>> # waits for multiple processes to terminate - >>> gone, alive = psutil.wait_procs(procs_list, timeout=3, callback=on_terminate) - >>> - -Popen wrapper: - -.. code-block:: python - - >>> import psutil - >>> from subprocess import PIPE - >>> p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE) - >>> p.name() - 'python' - >>> p.username() - 'giampaolo' - >>> p.communicate() - ('hello\n', None) - >>> p.wait(timeout=2) - 0 - >>> - -Windows services ----------------- - -.. code-block:: python - - >>> list(psutil.win_service_iter()) - [, - , - , - , - ...] - >>> s = psutil.win_service_get('alg') - >>> s.as_dict() - {'binpath': 'C:\\Windows\\System32\\alg.exe', - 'description': 'Provides support for 3rd party protocol plug-ins for Internet Connection Sharing', - 'display_name': 'Application Layer Gateway Service', - 'name': 'alg', - 'pid': None, - 'start_type': 'manual', - 'status': 'stopped', - 'username': 'NT AUTHORITY\\LocalService'} - - -.. _`Giampaolo Rodola`: http://grodola.blogspot.com/p/about.html -.. _`donation`: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8 -.. _Tidelift security contact: https://tidelift.com/security -.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme - - - diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/RECORD b/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/RECORD deleted file mode 100644 index 90a918ccf197..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/RECORD +++ /dev/null @@ -1,33 +0,0 @@ -psutil/__init__.py,sha256=gkuk8_HMEBXTFl0y4l8A5QGNCjUH1T0tpF_Y8hPJCPA,87126 -psutil/_common.py,sha256=6kuDg4DKKv3OGndSXLQ3LftF_hPySIEOprC8HE49eag,26001 -psutil/_compat.py,sha256=lrMSZr32TO6y9FQw7C2xTNyKwAnPU2o11xQrA_fS_Qw,11607 -psutil/_psaix.py,sha256=u9M_jJqkiGqNgdhum9MZTbnS4pjIfdCHNr3HAYHA0GQ,18458 -psutil/_psbsd.py,sha256=LHfBJ-iKy4fuumIcSjO7b6VFOvU_d-Pzwp7Eg84rHSw,30534 -psutil/_pslinux.py,sha256=WtQtqOAhXd-zqtVPV-E0re91Vqj4DYrKQ3Mj9CfBWak,79806 -psutil/_psosx.py,sha256=kvG3GKxA-L581H_UgU_BYaZ3eMPX7qMtEBM7AGC-t10,17090 -psutil/_psposix.py,sha256=FtbNSosrJiiUb9l0gfFdTwNxUwQb6Icy4L3si0x6ZMA,6047 -psutil/_pssunos.py,sha256=c-0et4xslK83ZiTizQ9W3LH0pMZy11ATEIBbQBJ_v-g,25398 -psutil/_psutil_windows.pyd,sha256=jERIIv4AR_vfAvx8oOqkyv41JBPuMskRgnM1O8KdokE,62976 -psutil/_pswindows.py,sha256=iFcfbA5KZehjdZfe1b-cLGRdavGNryI4Zxpkqb12UjU,36839 -psutil/tests/__init__.py,sha256=uH3lPOnYc6179FxdSy4xfMeJOBvB9CZid268Pg_owC0,35141 -psutil/tests/__main__.py,sha256=bBfMPu_gPzyiA4gfAFSZLk7LyLSPTUIHQFU1kFcj_Ok,291 -psutil/tests/runner.py,sha256=l7BrTzIOdjPgNB3D3kiir8jBiK_QJKMlJSYu4Zr0_po,5188 -psutil/tests/test_aix.py,sha256=LA8PR-1vx5DN2OkjU57MsO8uzNOB0y1ScR1yx5bZJyc,4464 -psutil/tests/test_bsd.py,sha256=3zlUvefRm2fFTbyLrqM9u8NMK8CThLT7irioTGgnNts,20612 -psutil/tests/test_connections.py,sha256=U2KCl7eW6kRds8S7t8SmZ62OrVSPfdBuksHsDlk2C28,25293 -psutil/tests/test_contracts.py,sha256=BOKrRiZs625Xj3KZBzOZ8Kr6edAQgzHq0OlznoCxKzw,25355 -psutil/tests/test_linux.py,sha256=KvqJ-LiINvbQQ3y18uM2SZRKnpnH4PqlA7CqWLRIH5s,87573 -psutil/tests/test_memory_leaks.py,sha256=M5nWBv_PYfN7bIoaz6r0UqEYY79hO6wvvDfkKWFMETI,18499 -psutil/tests/test_misc.py,sha256=wqXpnXL2ycHyE1vu3GB43XTET5auTKz9VdBSjr-vdp0,38748 -psutil/tests/test_osx.py,sha256=oQIO0YReUtH0PFFAwyk8FpUqvjIiuhVPehMFS1AWJpM,9257 -psutil/tests/test_posix.py,sha256=fSi5J1LxPhA7ZocrnLnqCSBn6JUuOtBeAljBWughIf4,16537 -psutil/tests/test_process.py,sha256=JJB9VdAwKFYK-rlpvWn1NyeYasmr0nL_XetzFHHjaJU,63924 -psutil/tests/test_sunos.py,sha256=GwqWfAP46nrxWlJr-srg85cPNEU2DXvoMelAgqegfLA,1294 -psutil/tests/test_system.py,sha256=4nWe_fFRmnaB8epV7Eji_0JFnIJbvbykMgSi8LFzbKM,36162 -psutil/tests/test_unicode.py,sha256=5v1hFoOQoi9_2Wg4ZTIWY_YDd29G00-59ln9FOe8Tsg,13246 -psutil/tests/test_windows.py,sha256=cGjEspgL48Sb5BQeSG5kIU0DSeImPU1bL9cpFfNX2Tk,33666 -psutil-5.7.0.dist-info/LICENSE,sha256=JMEphFAMqgf_3OGe68BjlsXm0kS1c7xsQ49KbvjlbBs,1549 -psutil-5.7.0.dist-info/METADATA,sha256=RmX2_-V4HrxQ1p78U2Os4H5Q0ZFvF5oc0uUTUt9-sRo,25022 -psutil-5.7.0.dist-info/WHEEL,sha256=Yt_rpa18HI_NXs5dEYG1uWuZ-4QRLVJrN8TSetG3BOI,106 -psutil-5.7.0.dist-info/top_level.txt,sha256=gCNhn57wzksDjSAISmgMJ0aiXzQulk0GJhb2-BAyYgw,7 -psutil-5.7.0.dist-info/RECORD,, diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/WHEEL b/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/WHEEL deleted file mode 100644 index 2fff7c01bd13..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.34.2) -Root-Is-Purelib: false -Tag: cp27-cp27m-win_amd64 - diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/top_level.txt b/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/top_level.txt deleted file mode 100644 index a4d92cc08db6..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -psutil diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/__init__.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/__init__.py deleted file mode 100644 index 22bb46f3f9bd..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/__init__.py +++ /dev/null @@ -1,2409 +0,0 @@ -# -*- coding: utf-8 -*- - -# 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. - -"""psutil is a cross-platform library for retrieving information on -running processes and system utilization (CPU, memory, disks, network, -sensors) in Python. Supported platforms: - - - Linux - - Windows - - macOS - - FreeBSD - - OpenBSD - - NetBSD - - Sun Solaris - - AIX - -Works with Python versions from 2.6 to 3.4+. -""" - -from __future__ import division - -import collections -import contextlib -import datetime -import functools -import os -import signal -import subprocess -import sys -import threading -import time -try: - import pwd -except ImportError: - pwd = None - -from . import _common -from ._common import AccessDenied -from ._common import deprecated_method -from ._common import Error -from ._common import memoize -from ._common import memoize_when_activated -from ._common import NoSuchProcess -from ._common import TimeoutExpired -from ._common import wrap_numbers as _wrap_numbers -from ._common import ZombieProcess -from ._compat import long -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 as _PY3 - -from ._common import STATUS_DEAD -from ._common import STATUS_DISK_SLEEP -from ._common import STATUS_IDLE -from ._common import STATUS_LOCKED -from ._common import STATUS_PARKED -from ._common import STATUS_RUNNING -from ._common import STATUS_SLEEPING -from ._common import STATUS_STOPPED -from ._common import STATUS_TRACING_STOP -from ._common import STATUS_WAITING -from ._common import STATUS_WAKING -from ._common import STATUS_ZOMBIE - -from ._common import CONN_CLOSE -from ._common import CONN_CLOSE_WAIT -from ._common import CONN_CLOSING -from ._common import CONN_ESTABLISHED -from ._common import CONN_FIN_WAIT1 -from ._common import CONN_FIN_WAIT2 -from ._common import CONN_LAST_ACK -from ._common import CONN_LISTEN -from ._common import CONN_NONE -from ._common import CONN_SYN_RECV -from ._common import CONN_SYN_SENT -from ._common import CONN_TIME_WAIT -from ._common import NIC_DUPLEX_FULL -from ._common import NIC_DUPLEX_HALF -from ._common import NIC_DUPLEX_UNKNOWN - -from ._common import AIX -from ._common import BSD -from ._common import FREEBSD # NOQA -from ._common import LINUX -from ._common import MACOS -from ._common import NETBSD # NOQA -from ._common import OPENBSD # NOQA -from ._common import OSX # deprecated alias -from ._common import POSIX # NOQA -from ._common import SUNOS -from ._common import WINDOWS - -if LINUX: - # This is public API and it will be retrieved from _pslinux.py - # via sys.modules. - PROCFS_PATH = "/proc" - - from . import _pslinux as _psplatform - - from ._pslinux import IOPRIO_CLASS_BE # NOQA - from ._pslinux import IOPRIO_CLASS_IDLE # NOQA - from ._pslinux import IOPRIO_CLASS_NONE # NOQA - from ._pslinux import IOPRIO_CLASS_RT # NOQA - # Linux >= 2.6.36 - if _psplatform.HAS_PRLIMIT: - from ._psutil_linux import RLIM_INFINITY # NOQA - from ._psutil_linux import RLIMIT_AS # NOQA - from ._psutil_linux import RLIMIT_CORE # NOQA - from ._psutil_linux import RLIMIT_CPU # NOQA - from ._psutil_linux import RLIMIT_DATA # NOQA - from ._psutil_linux import RLIMIT_FSIZE # NOQA - from ._psutil_linux import RLIMIT_LOCKS # NOQA - from ._psutil_linux import RLIMIT_MEMLOCK # NOQA - from ._psutil_linux import RLIMIT_NOFILE # NOQA - from ._psutil_linux import RLIMIT_NPROC # NOQA - from ._psutil_linux import RLIMIT_RSS # NOQA - from ._psutil_linux import RLIMIT_STACK # NOQA - # Kinda ugly but considerably faster than using hasattr() and - # setattr() against the module object (we are at import time: - # speed matters). - from . import _psutil_linux - try: - RLIMIT_MSGQUEUE = _psutil_linux.RLIMIT_MSGQUEUE - except AttributeError: - pass - try: - RLIMIT_NICE = _psutil_linux.RLIMIT_NICE - except AttributeError: - pass - try: - RLIMIT_RTPRIO = _psutil_linux.RLIMIT_RTPRIO - except AttributeError: - pass - try: - RLIMIT_RTTIME = _psutil_linux.RLIMIT_RTTIME - except AttributeError: - pass - try: - RLIMIT_SIGPENDING = _psutil_linux.RLIMIT_SIGPENDING - except AttributeError: - pass - -elif WINDOWS: - from . import _pswindows as _psplatform - from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS # NOQA - from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS # NOQA - from ._psutil_windows import HIGH_PRIORITY_CLASS # NOQA - from ._psutil_windows import IDLE_PRIORITY_CLASS # NOQA - from ._psutil_windows import NORMAL_PRIORITY_CLASS # NOQA - from ._psutil_windows import REALTIME_PRIORITY_CLASS # NOQA - from ._pswindows import CONN_DELETE_TCB # NOQA - from ._pswindows import IOPRIO_VERYLOW # NOQA - from ._pswindows import IOPRIO_LOW # NOQA - from ._pswindows import IOPRIO_NORMAL # NOQA - from ._pswindows import IOPRIO_HIGH # NOQA - -elif MACOS: - from . import _psosx as _psplatform - -elif BSD: - from . import _psbsd as _psplatform - -elif SUNOS: - from . import _pssunos as _psplatform - from ._pssunos import CONN_BOUND # NOQA - from ._pssunos import CONN_IDLE # NOQA - - # This is public writable API which is read from _pslinux.py and - # _pssunos.py via sys.modules. - PROCFS_PATH = "/proc" - -elif AIX: - from . import _psaix as _psplatform - - # This is public API and it will be retrieved from _pslinux.py - # via sys.modules. - PROCFS_PATH = "/proc" - -else: # pragma: no cover - raise NotImplementedError('platform %s is not supported' % sys.platform) - - -__all__ = [ - # exceptions - "Error", "NoSuchProcess", "ZombieProcess", "AccessDenied", - "TimeoutExpired", - - # constants - "version_info", "__version__", - - "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP", - "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD", - "STATUS_WAKING", "STATUS_LOCKED", "STATUS_WAITING", "STATUS_LOCKED", - "STATUS_PARKED", - - "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", - "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", - "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", "CONN_NONE", - - "AF_LINK", - - "NIC_DUPLEX_FULL", "NIC_DUPLEX_HALF", "NIC_DUPLEX_UNKNOWN", - - "POWER_TIME_UNKNOWN", "POWER_TIME_UNLIMITED", - - "BSD", "FREEBSD", "LINUX", "NETBSD", "OPENBSD", "MACOS", "OSX", "POSIX", - "SUNOS", "WINDOWS", "AIX", - - # classes - "Process", "Popen", - - # functions - "pid_exists", "pids", "process_iter", "wait_procs", # proc - "virtual_memory", "swap_memory", # memory - "cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count", # cpu - "cpu_stats", # "cpu_freq", "getloadavg" - "net_io_counters", "net_connections", "net_if_addrs", # network - "net_if_stats", - "disk_io_counters", "disk_partitions", "disk_usage", # disk - # "sensors_temperatures", "sensors_battery", "sensors_fans" # sensors - "users", "boot_time", # others -] - - -__all__.extend(_psplatform.__extra__all__) -__author__ = "Giampaolo Rodola'" -__version__ = "5.7.0" -version_info = tuple([int(num) for num in __version__.split('.')]) - -_timer = getattr(time, 'monotonic', time.time) -AF_LINK = _psplatform.AF_LINK -POWER_TIME_UNLIMITED = _common.POWER_TIME_UNLIMITED -POWER_TIME_UNKNOWN = _common.POWER_TIME_UNKNOWN -_TOTAL_PHYMEM = None -_LOWEST_PID = None - -# Sanity check in case the user messed up with psutil installation -# or did something weird with sys.path. In this case we might end -# up importing a python module using a C extension module which -# was compiled for a different version of psutil. -# We want to prevent that by failing sooner rather than later. -# See: https://github.com/giampaolo/psutil/issues/564 -if (int(__version__.replace('.', '')) != - getattr(_psplatform.cext, 'version', None)): - msg = "version conflict: %r C extension module was built for another " \ - "version of psutil" % getattr(_psplatform.cext, "__file__") - if hasattr(_psplatform.cext, 'version'): - msg += " (%s instead of %s)" % ( - '.'.join([x for x in str(_psplatform.cext.version)]), __version__) - else: - msg += " (different than %s)" % __version__ - msg += "; you may try to 'pip uninstall psutil', manually remove %s" % ( - getattr(_psplatform.cext, "__file__", - "the existing psutil install directory")) - msg += " or clean the virtual env somehow, then reinstall" - raise ImportError(msg) - - -# ===================================================================== -# --- Utils -# ===================================================================== - - -if hasattr(_psplatform, 'ppid_map'): - # Faster version (Windows and Linux). - _ppid_map = _psplatform.ppid_map -else: - def _ppid_map(): - """Return a {pid: ppid, ...} dict for all running processes in - one shot. Used to speed up Process.children(). - """ - ret = {} - for pid in pids(): - try: - ret[pid] = _psplatform.Process(pid).ppid() - except (NoSuchProcess, ZombieProcess): - pass - return ret - - -def _assert_pid_not_reused(fun): - """Decorator which raises NoSuchProcess in case a process is no - longer running or its PID has been reused. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - if not self.is_running(): - raise NoSuchProcess(self.pid, self._name) - return fun(self, *args, **kwargs) - return wrapper - - -def _pprint_secs(secs): - """Format seconds in a human readable form.""" - now = time.time() - secs_ago = int(now - secs) - if secs_ago < 60 * 60 * 24: - fmt = "%H:%M:%S" - else: - fmt = "%Y-%m-%d %H:%M:%S" - return datetime.datetime.fromtimestamp(secs).strftime(fmt) - - -# ===================================================================== -# --- Process class -# ===================================================================== - - -class Process(object): - """Represents an OS process with the given PID. - If PID is omitted current process PID (os.getpid()) is used. - Raise NoSuchProcess if PID does not exist. - - Note that most of the methods of this class do not make sure - the PID of the process being queried has been reused over time. - That means you might end up retrieving an information referring - to another process in case the original one this instance - refers to is gone in the meantime. - - The only exceptions for which process identity is pre-emptively - checked and guaranteed are: - - - parent() - - children() - - nice() (set) - - ionice() (set) - - rlimit() (set) - - cpu_affinity (set) - - suspend() - - resume() - - send_signal() - - terminate() - - kill() - - To prevent this problem for all other methods you can: - - use is_running() before querying the process - - if you're continuously iterating over a set of Process - instances use process_iter() which pre-emptively checks - process identity for every yielded instance - """ - - def __init__(self, pid=None): - self._init(pid) - - def _init(self, pid, _ignore_nsp=False): - if pid is None: - pid = os.getpid() - else: - if not _PY3 and not isinstance(pid, (int, long)): - raise TypeError('pid must be an integer (got %r)' % pid) - if pid < 0: - raise ValueError('pid must be a positive integer (got %s)' - % pid) - self._pid = pid - self._name = None - self._exe = None - self._create_time = None - self._gone = False - self._hash = None - self._lock = threading.RLock() - # used for caching on Windows only (on POSIX ppid may change) - self._ppid = None - # platform-specific modules define an _psplatform.Process - # implementation class - self._proc = _psplatform.Process(pid) - self._last_sys_cpu_times = None - self._last_proc_cpu_times = None - # cache creation time for later use in is_running() method - try: - self.create_time() - except AccessDenied: - # We should never get here as AFAIK we're able to get - # process creation time on all platforms even as a - # limited user. - pass - except ZombieProcess: - # Zombies can still be queried by this class (although - # not always) and pids() return them so just go on. - pass - except NoSuchProcess: - if not _ignore_nsp: - msg = 'no process found with pid %s' % pid - raise NoSuchProcess(pid, None, msg) - else: - self._gone = True - # This pair is supposed to indentify a Process instance - # univocally over time (the PID alone is not enough as - # it might refer to a process whose PID has been reused). - # This will be used later in __eq__() and is_running(). - self._ident = (self.pid, self._create_time) - - def __str__(self): - try: - info = collections.OrderedDict() - except AttributeError: - info = {} # Python 2.6 - info["pid"] = self.pid - try: - info["name"] = self.name() - if self._create_time: - info['started'] = _pprint_secs(self._create_time) - except ZombieProcess: - info["status"] = "zombie" - except NoSuchProcess: - info["status"] = "terminated" - except AccessDenied: - pass - return "%s.%s(%s)" % ( - self.__class__.__module__, - self.__class__.__name__, - ", ".join(["%s=%r" % (k, v) for k, v in info.items()])) - - __repr__ = __str__ - - def __eq__(self, other): - # Test for equality with another Process object based - # on PID and creation time. - if not isinstance(other, Process): - return NotImplemented - return self._ident == other._ident - - def __ne__(self, other): - return not self == other - - def __hash__(self): - if self._hash is None: - self._hash = hash(self._ident) - return self._hash - - @property - def pid(self): - """The process PID.""" - return self._pid - - # --- utility methods - - @contextlib.contextmanager - def oneshot(self): - """Utility context manager which considerably speeds up the - retrieval of multiple process information at the same time. - - Internally different process info (e.g. name, ppid, uids, - gids, ...) may be fetched by using the same routine, but - only one information is returned and the others are discarded. - When using this context manager the internal routine is - executed once (in the example below on name()) and the - other info are cached. - - The cache is cleared when exiting the context manager block. - The advice is to use this every time you retrieve more than - one information about the process. If you're lucky, you'll - get a hell of a speedup. - - >>> import psutil - >>> p = psutil.Process() - >>> with p.oneshot(): - ... p.name() # collect multiple info - ... p.cpu_times() # return cached value - ... p.cpu_percent() # return cached value - ... p.create_time() # return cached value - ... - >>> - """ - with self._lock: - if hasattr(self, "_cache"): - # NOOP: this covers the use case where the user enters the - # context twice: - # - # >>> with p.oneshot(): - # ... with p.oneshot(): - # ... - # - # Also, since as_dict() internally uses oneshot() - # I expect that the code below will be a pretty common - # "mistake" that the user will make, so let's guard - # against that: - # - # >>> with p.oneshot(): - # ... p.as_dict() - # ... - yield - else: - try: - # cached in case cpu_percent() is used - self.cpu_times.cache_activate(self) - # cached in case memory_percent() is used - self.memory_info.cache_activate(self) - # cached in case parent() is used - self.ppid.cache_activate(self) - # cached in case username() is used - if POSIX: - self.uids.cache_activate(self) - # specific implementation cache - self._proc.oneshot_enter() - yield - finally: - self.cpu_times.cache_deactivate(self) - self.memory_info.cache_deactivate(self) - self.ppid.cache_deactivate(self) - if POSIX: - self.uids.cache_deactivate(self) - self._proc.oneshot_exit() - - def as_dict(self, attrs=None, ad_value=None): - """Utility method returning process information as a - hashable dictionary. - If *attrs* is specified it must be a list of strings - reflecting available Process class' attribute names - (e.g. ['cpu_times', 'name']) else all public (read - only) attributes are assumed. - *ad_value* is the value which gets assigned in case - AccessDenied or ZombieProcess exception is raised when - retrieving that particular process information. - """ - valid_names = _as_dict_attrnames - if attrs is not None: - if not isinstance(attrs, (list, tuple, set, frozenset)): - raise TypeError("invalid attrs type %s" % type(attrs)) - attrs = set(attrs) - invalid_names = attrs - valid_names - if invalid_names: - raise ValueError("invalid attr name%s %s" % ( - "s" if len(invalid_names) > 1 else "", - ", ".join(map(repr, invalid_names)))) - - retdict = dict() - ls = attrs or valid_names - with self.oneshot(): - for name in ls: - try: - if name == 'pid': - ret = self.pid - else: - meth = getattr(self, name) - ret = meth() - except (AccessDenied, ZombieProcess): - ret = ad_value - except NotImplementedError: - # in case of not implemented functionality (may happen - # on old or exotic systems) we want to crash only if - # the user explicitly asked for that particular attr - if attrs: - raise - continue - retdict[name] = ret - return retdict - - def parent(self): - """Return the parent process as a Process object pre-emptively - checking whether PID has been reused. - If no parent is known return None. - """ - lowest_pid = _LOWEST_PID if _LOWEST_PID is not None else pids()[0] - if self.pid == lowest_pid: - return None - ppid = self.ppid() - if ppid is not None: - ctime = self.create_time() - try: - parent = Process(ppid) - if parent.create_time() <= ctime: - return parent - # ...else ppid has been reused by another process - except NoSuchProcess: - pass - - def parents(self): - """Return the parents of this process as a list of Process - instances. If no parents are known return an empty list. - """ - parents = [] - proc = self.parent() - while proc is not None: - parents.append(proc) - proc = proc.parent() - return parents - - def is_running(self): - """Return whether this process is running. - It also checks if PID has been reused by another process in - which case return False. - """ - if self._gone: - return False - try: - # Checking if PID is alive is not enough as the PID might - # have been reused by another process: we also want to - # verify process identity. - # Process identity / uniqueness over time is guaranteed by - # (PID + creation time) and that is verified in __eq__. - return self == Process(self.pid) - except ZombieProcess: - # We should never get here as it's already handled in - # Process.__init__; here just for extra safety. - return True - except NoSuchProcess: - self._gone = True - return False - - # --- actual API - - @memoize_when_activated - def ppid(self): - """The process parent PID. - On Windows the return value is cached after first call. - """ - # On POSIX we don't want to cache the ppid as it may unexpectedly - # change to 1 (init) in case this process turns into a zombie: - # https://github.com/giampaolo/psutil/issues/321 - # http://stackoverflow.com/questions/356722/ - - # XXX should we check creation time here rather than in - # Process.parent()? - if POSIX: - return self._proc.ppid() - else: # pragma: no cover - self._ppid = self._ppid or self._proc.ppid() - return self._ppid - - def name(self): - """The process name. The return value is cached after first call.""" - # Process name is only cached on Windows as on POSIX it may - # change, see: - # https://github.com/giampaolo/psutil/issues/692 - if WINDOWS and self._name is not None: - return self._name - name = self._proc.name() - if POSIX and len(name) >= 15: - # On UNIX the name gets truncated to the first 15 characters. - # If it matches the first part of the cmdline we return that - # one instead because it's usually more explicative. - # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon". - try: - cmdline = self.cmdline() - except AccessDenied: - pass - else: - if cmdline: - extended_name = os.path.basename(cmdline[0]) - if extended_name.startswith(name): - name = extended_name - self._name = name - self._proc._name = name - return name - - def exe(self): - """The process executable as an absolute path. - May also be an empty string. - The return value is cached after first call. - """ - def guess_it(fallback): - # try to guess exe from cmdline[0] in absence of a native - # exe representation - cmdline = self.cmdline() - if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'): - exe = cmdline[0] # the possible exe - # Attempt to guess only in case of an absolute path. - # It is not safe otherwise as the process might have - # changed cwd. - if (os.path.isabs(exe) and - os.path.isfile(exe) and - os.access(exe, os.X_OK)): - return exe - if isinstance(fallback, AccessDenied): - raise fallback - return fallback - - if self._exe is None: - try: - exe = self._proc.exe() - except AccessDenied as err: - return guess_it(fallback=err) - else: - if not exe: - # underlying implementation can legitimately return an - # empty string; if that's the case we don't want to - # raise AD while guessing from the cmdline - try: - exe = guess_it(fallback=exe) - except AccessDenied: - pass - self._exe = exe - return self._exe - - def cmdline(self): - """The command line this process has been called with.""" - return self._proc.cmdline() - - def status(self): - """The process current status as a STATUS_* constant.""" - try: - return self._proc.status() - except ZombieProcess: - return STATUS_ZOMBIE - - def username(self): - """The name of the user that owns the process. - On UNIX this is calculated by using *real* process uid. - """ - if POSIX: - if pwd is None: - # might happen if python was installed from sources - raise ImportError( - "requires pwd module shipped with standard python") - real_uid = self.uids().real - try: - return pwd.getpwuid(real_uid).pw_name - except KeyError: - # the uid can't be resolved by the system - return str(real_uid) - else: - return self._proc.username() - - def create_time(self): - """The process creation time as a floating point number - expressed in seconds since the epoch, in UTC. - The return value is cached after first call. - """ - if self._create_time is None: - self._create_time = self._proc.create_time() - return self._create_time - - def cwd(self): - """Process current working directory as an absolute path.""" - return self._proc.cwd() - - def nice(self, value=None): - """Get or set process niceness (priority).""" - if value is None: - return self._proc.nice_get() - else: - if not self.is_running(): - raise NoSuchProcess(self.pid, self._name) - self._proc.nice_set(value) - - if POSIX: - - @memoize_when_activated - def uids(self): - """Return process UIDs as a (real, effective, saved) - namedtuple. - """ - return self._proc.uids() - - def gids(self): - """Return process GIDs as a (real, effective, saved) - namedtuple. - """ - return self._proc.gids() - - def terminal(self): - """The terminal associated with this process, if any, - else None. - """ - return self._proc.terminal() - - def num_fds(self): - """Return the number of file descriptors opened by this - process (POSIX only). - """ - return self._proc.num_fds() - - # Linux, BSD, AIX and Windows only - if hasattr(_psplatform.Process, "io_counters"): - - def io_counters(self): - """Return process I/O statistics as a - (read_count, write_count, read_bytes, write_bytes) - namedtuple. - Those are the number of read/write calls performed and the - amount of bytes read and written by the process. - """ - return self._proc.io_counters() - - # Linux and Windows - if hasattr(_psplatform.Process, "ionice_get"): - - def ionice(self, ioclass=None, value=None): - """Get or set process I/O niceness (priority). - - On Linux *ioclass* is one of the IOPRIO_CLASS_* constants. - *value* is a number which goes from 0 to 7. The higher the - value, the lower the I/O priority of the process. - - On Windows only *ioclass* is used and it can be set to 2 - (normal), 1 (low) or 0 (very low). - - Available on Linux and Windows > Vista only. - """ - if ioclass is None: - if value is not None: - raise ValueError("'ioclass' argument must be specified") - return self._proc.ionice_get() - else: - return self._proc.ionice_set(ioclass, value) - - # Linux only - if hasattr(_psplatform.Process, "rlimit"): - - def rlimit(self, resource, limits=None): - """Get or set process resource limits as a (soft, hard) - tuple. - - *resource* is one of the RLIMIT_* constants. - *limits* is supposed to be a (soft, hard) tuple. - - See "man prlimit" for further info. - Available on Linux only. - """ - if limits is None: - return self._proc.rlimit(resource) - else: - return self._proc.rlimit(resource, limits) - - # Windows, Linux and FreeBSD only - if hasattr(_psplatform.Process, "cpu_affinity_get"): - - def cpu_affinity(self, cpus=None): - """Get or set process CPU affinity. - If specified, *cpus* must be a list of CPUs for which you - want to set the affinity (e.g. [0, 1]). - If an empty list is passed, all egible CPUs are assumed - (and set). - (Windows, Linux and BSD only). - """ - if cpus is None: - return list(set(self._proc.cpu_affinity_get())) - else: - if not cpus: - if hasattr(self._proc, "_get_eligible_cpus"): - cpus = self._proc._get_eligible_cpus() - else: - cpus = tuple(range(len(cpu_times(percpu=True)))) - self._proc.cpu_affinity_set(list(set(cpus))) - - # Linux, FreeBSD, SunOS - if hasattr(_psplatform.Process, "cpu_num"): - - def cpu_num(self): - """Return what CPU this process is currently running on. - The returned number should be <= psutil.cpu_count() - and <= len(psutil.cpu_percent(percpu=True)). - It may be used in conjunction with - psutil.cpu_percent(percpu=True) to observe the system - workload distributed across CPUs. - """ - return self._proc.cpu_num() - - # Linux, macOS, Windows, Solaris, AIX - if hasattr(_psplatform.Process, "environ"): - - def environ(self): - """The environment variables of the process as a dict. Note: this - might not reflect changes made after the process started. """ - return self._proc.environ() - - if WINDOWS: - - def num_handles(self): - """Return the number of handles opened by this process - (Windows only). - """ - return self._proc.num_handles() - - def num_ctx_switches(self): - """Return the number of voluntary and involuntary context - switches performed by this process. - """ - return self._proc.num_ctx_switches() - - def num_threads(self): - """Return the number of threads used by this process.""" - return self._proc.num_threads() - - if hasattr(_psplatform.Process, "threads"): - - def threads(self): - """Return threads opened by process as a list of - (id, user_time, system_time) namedtuples representing - thread id and thread CPU times (user/system). - On OpenBSD this method requires root access. - """ - return self._proc.threads() - - @_assert_pid_not_reused - def children(self, recursive=False): - """Return the children of this process as a list of Process - instances, pre-emptively checking whether PID has been reused. - If *recursive* is True return all the parent descendants. - - Example (A == this process): - - A ─┐ - │ - ├─ B (child) ─┐ - │ └─ X (grandchild) ─┐ - │ └─ Y (great grandchild) - ├─ C (child) - └─ D (child) - - >>> import psutil - >>> p = psutil.Process() - >>> p.children() - B, C, D - >>> p.children(recursive=True) - B, X, Y, C, D - - Note that in the example above if process X disappears - process Y won't be listed as the reference to process A - is lost. - """ - ppid_map = _ppid_map() - ret = [] - if not recursive: - for pid, ppid in ppid_map.items(): - if ppid == self.pid: - try: - child = Process(pid) - # if child happens to be older than its parent - # (self) it means child's PID has been reused - if self.create_time() <= child.create_time(): - ret.append(child) - except (NoSuchProcess, ZombieProcess): - pass - else: - # Construct a {pid: [child pids]} dict - reverse_ppid_map = collections.defaultdict(list) - for pid, ppid in ppid_map.items(): - reverse_ppid_map[ppid].append(pid) - # Recursively traverse that dict, starting from self.pid, - # such that we only call Process() on actual children - seen = set() - stack = [self.pid] - while stack: - pid = stack.pop() - if pid in seen: - # Since pids can be reused while the ppid_map is - # constructed, there may be rare instances where - # there's a cycle in the recorded process "tree". - continue - seen.add(pid) - for child_pid in reverse_ppid_map[pid]: - try: - child = Process(child_pid) - # if child happens to be older than its parent - # (self) it means child's PID has been reused - intime = self.create_time() <= child.create_time() - if intime: - ret.append(child) - stack.append(child_pid) - except (NoSuchProcess, ZombieProcess): - pass - return ret - - def cpu_percent(self, interval=None): - """Return a float representing the current process CPU - utilization as a percentage. - - When *interval* is 0.0 or None (default) compares process times - to system CPU times elapsed since last call, returning - immediately (non-blocking). That means that the first time - this is called it will return a meaningful 0.0 value. - - When *interval* is > 0.0 compares process times to system CPU - times elapsed before and after the interval (blocking). - - In this case is recommended for accuracy that this function - be called with at least 0.1 seconds between calls. - - A value > 100.0 can be returned in case of processes running - multiple threads on different CPU cores. - - The returned value is explicitly NOT split evenly between - all available logical CPUs. This means that a busy loop process - running on a system with 2 logical CPUs will be reported as - having 100% CPU utilization instead of 50%. - - Examples: - - >>> import psutil - >>> p = psutil.Process(os.getpid()) - >>> # blocking - >>> p.cpu_percent(interval=1) - 2.0 - >>> # non-blocking (percentage since last call) - >>> p.cpu_percent(interval=None) - 2.9 - >>> - """ - blocking = interval is not None and interval > 0.0 - if interval is not None and interval < 0: - raise ValueError("interval is not positive (got %r)" % interval) - num_cpus = cpu_count() or 1 - - def timer(): - return _timer() * num_cpus - - if blocking: - st1 = timer() - pt1 = self._proc.cpu_times() - time.sleep(interval) - st2 = timer() - pt2 = self._proc.cpu_times() - else: - st1 = self._last_sys_cpu_times - pt1 = self._last_proc_cpu_times - st2 = timer() - pt2 = self._proc.cpu_times() - if st1 is None or pt1 is None: - self._last_sys_cpu_times = st2 - self._last_proc_cpu_times = pt2 - return 0.0 - - delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system) - delta_time = st2 - st1 - # reset values for next call in case of interval == None - self._last_sys_cpu_times = st2 - self._last_proc_cpu_times = pt2 - - try: - # This is the utilization split evenly between all CPUs. - # E.g. a busy loop process on a 2-CPU-cores system at this - # point is reported as 50% instead of 100%. - overall_cpus_percent = ((delta_proc / delta_time) * 100) - except ZeroDivisionError: - # interval was too low - return 0.0 - else: - # Note 1: - # in order to emulate "top" we multiply the value for the num - # of CPU cores. This way the busy process will be reported as - # having 100% (or more) usage. - # - # Note 2: - # taskmgr.exe on Windows differs in that it will show 50% - # instead. - # - # Note 3: - # a percentage > 100 is legitimate as it can result from a - # process with multiple threads running on different CPU - # cores (top does the same), see: - # http://stackoverflow.com/questions/1032357 - # https://github.com/giampaolo/psutil/issues/474 - single_cpu_percent = overall_cpus_percent * num_cpus - return round(single_cpu_percent, 1) - - @memoize_when_activated - def cpu_times(self): - """Return a (user, system, children_user, children_system) - namedtuple representing the accumulated process time, in - seconds. - This is similar to os.times() but per-process. - On macOS and Windows children_user and children_system are - always set to 0. - """ - return self._proc.cpu_times() - - @memoize_when_activated - def memory_info(self): - """Return a namedtuple with variable fields depending on the - platform, representing memory information about the process. - - The "portable" fields available on all plaforms are `rss` and `vms`. - - All numbers are expressed in bytes. - """ - return self._proc.memory_info() - - @deprecated_method(replacement="memory_info") - def memory_info_ex(self): - return self.memory_info() - - def memory_full_info(self): - """This method returns the same information as memory_info(), - plus, on some platform (Linux, macOS, Windows), also provides - additional metrics (USS, PSS and swap). - The additional metrics provide a better representation of actual - process memory usage. - - Namely USS is the memory which is unique to a process and which - would be freed if the process was terminated right now. - - It does so by passing through the whole process address. - As such it usually requires higher user privileges than - memory_info() and is considerably slower. - """ - return self._proc.memory_full_info() - - def memory_percent(self, memtype="rss"): - """Compare process memory to total physical system memory and - calculate process memory utilization as a percentage. - *memtype* argument is a string that dictates what type of - process memory you want to compare against (defaults to "rss"). - The list of available strings can be obtained like this: - - >>> psutil.Process().memory_info()._fields - ('rss', 'vms', 'shared', 'text', 'lib', 'data', 'dirty', 'uss', 'pss') - """ - valid_types = list(_psplatform.pfullmem._fields) - if memtype not in valid_types: - raise ValueError("invalid memtype %r; valid types are %r" % ( - memtype, tuple(valid_types))) - fun = self.memory_info if memtype in _psplatform.pmem._fields else \ - self.memory_full_info - metrics = fun() - value = getattr(metrics, memtype) - - # use cached value if available - total_phymem = _TOTAL_PHYMEM or virtual_memory().total - if not total_phymem > 0: - # we should never get here - raise ValueError( - "can't calculate process memory percent because " - "total physical system memory is not positive (%r)" - % total_phymem) - return (value / float(total_phymem)) * 100 - - if hasattr(_psplatform.Process, "memory_maps"): - def memory_maps(self, grouped=True): - """Return process' mapped memory regions as a list of namedtuples - whose fields are variable depending on the platform. - - If *grouped* is True the mapped regions with the same 'path' - are grouped together and the different memory fields are summed. - - If *grouped* is False every mapped region is shown as a single - entity and the namedtuple will also include the mapped region's - address space ('addr') and permission set ('perms'). - """ - it = self._proc.memory_maps() - if grouped: - d = {} - for tupl in it: - path = tupl[2] - nums = tupl[3:] - try: - d[path] = map(lambda x, y: x + y, d[path], nums) - except KeyError: - d[path] = nums - nt = _psplatform.pmmap_grouped - return [nt(path, *d[path]) for path in d] # NOQA - else: - nt = _psplatform.pmmap_ext - return [nt(*x) for x in it] - - def open_files(self): - """Return files opened by process as a list of - (path, fd) namedtuples including the absolute file name - and file descriptor number. - """ - return self._proc.open_files() - - def connections(self, kind='inet'): - """Return socket connections opened by process as a list of - (fd, family, type, laddr, raddr, status) namedtuples. - The *kind* parameter filters for connections that match the - following criteria: - - +------------+----------------------------------------------------+ - | Kind Value | Connections using | - +------------+----------------------------------------------------+ - | inet | IPv4 and IPv6 | - | inet4 | IPv4 | - | inet6 | IPv6 | - | tcp | TCP | - | tcp4 | TCP over IPv4 | - | tcp6 | TCP over IPv6 | - | udp | UDP | - | udp4 | UDP over IPv4 | - | udp6 | UDP over IPv6 | - | unix | UNIX socket (both UDP and TCP protocols) | - | all | the sum of all the possible families and protocols | - +------------+----------------------------------------------------+ - """ - return self._proc.connections(kind) - - # --- signals - - if POSIX: - def _send_signal(self, sig): - assert not self.pid < 0, self.pid - if self.pid == 0: - # see "man 2 kill" - raise ValueError( - "preventing sending signal to process with PID 0 as it " - "would affect every process in the process group of the " - "calling process (os.getpid()) instead of PID 0") - try: - os.kill(self.pid, sig) - except ProcessLookupError: - if OPENBSD and pid_exists(self.pid): - # We do this because os.kill() lies in case of - # zombie processes. - raise ZombieProcess(self.pid, self._name, self._ppid) - else: - self._gone = True - raise NoSuchProcess(self.pid, self._name) - except PermissionError: - raise AccessDenied(self.pid, self._name) - - @_assert_pid_not_reused - def send_signal(self, sig): - """Send a signal *sig* to process pre-emptively checking - whether PID has been reused (see signal module constants) . - On Windows only SIGTERM is valid and is treated as an alias - for kill(). - """ - if POSIX: - self._send_signal(sig) - else: # pragma: no cover - self._proc.send_signal(sig) - - @_assert_pid_not_reused - def suspend(self): - """Suspend process execution with SIGSTOP pre-emptively checking - whether PID has been reused. - On Windows this has the effect ot suspending all process threads. - """ - if POSIX: - self._send_signal(signal.SIGSTOP) - else: # pragma: no cover - self._proc.suspend() - - @_assert_pid_not_reused - def resume(self): - """Resume process execution with SIGCONT pre-emptively checking - whether PID has been reused. - On Windows this has the effect of resuming all process threads. - """ - if POSIX: - self._send_signal(signal.SIGCONT) - else: # pragma: no cover - self._proc.resume() - - @_assert_pid_not_reused - def terminate(self): - """Terminate the process with SIGTERM pre-emptively checking - whether PID has been reused. - On Windows this is an alias for kill(). - """ - if POSIX: - self._send_signal(signal.SIGTERM) - else: # pragma: no cover - self._proc.kill() - - @_assert_pid_not_reused - def kill(self): - """Kill the current process with SIGKILL pre-emptively checking - whether PID has been reused. - """ - if POSIX: - self._send_signal(signal.SIGKILL) - else: # pragma: no cover - self._proc.kill() - - def wait(self, timeout=None): - """Wait for process to terminate and, if process is a children - of os.getpid(), also return its exit code, else None. - On Windows there's no such limitation (exit code is always - returned). - - If the process is already terminated immediately return None - instead of raising NoSuchProcess. - - If *timeout* (in seconds) is specified and process is still - alive raise TimeoutExpired. - - To wait for multiple Process(es) use psutil.wait_procs(). - """ - if timeout is not None and not timeout >= 0: - raise ValueError("timeout must be a positive integer") - return self._proc.wait(timeout) - - -# ===================================================================== -# --- Popen class -# ===================================================================== - - -class Popen(Process): - """A more convenient interface to stdlib subprocess.Popen class. - It starts a sub process and deals with it exactly as when using - subprocess.Popen class but in addition also provides all the - properties and methods of psutil.Process class as a unified - interface: - - >>> import psutil - >>> from subprocess import PIPE - >>> p = psutil.Popen(["python", "-c", "print 'hi'"], stdout=PIPE) - >>> p.name() - 'python' - >>> p.uids() - user(real=1000, effective=1000, saved=1000) - >>> p.username() - 'giampaolo' - >>> p.communicate() - ('hi\n', None) - >>> p.terminate() - >>> p.wait(timeout=2) - 0 - >>> - - For method names common to both classes such as kill(), terminate() - and wait(), psutil.Process implementation takes precedence. - - Unlike subprocess.Popen this class pre-emptively checks whether PID - has been reused on send_signal(), terminate() and kill() so that - you don't accidentally terminate another process, fixing - http://bugs.python.org/issue6973. - - For a complete documentation refer to: - http://docs.python.org/3/library/subprocess.html - """ - - def __init__(self, *args, **kwargs): - # Explicitly avoid to raise NoSuchProcess in case the process - # spawned by subprocess.Popen terminates too quickly, see: - # https://github.com/giampaolo/psutil/issues/193 - self.__subproc = subprocess.Popen(*args, **kwargs) - self._init(self.__subproc.pid, _ignore_nsp=True) - - def __dir__(self): - return sorted(set(dir(Popen) + dir(subprocess.Popen))) - - def __enter__(self): - if hasattr(self.__subproc, '__enter__'): - self.__subproc.__enter__() - return self - - def __exit__(self, *args, **kwargs): - if hasattr(self.__subproc, '__exit__'): - return self.__subproc.__exit__(*args, **kwargs) - else: - if self.stdout: - self.stdout.close() - if self.stderr: - self.stderr.close() - try: - # Flushing a BufferedWriter may raise an error. - if self.stdin: - self.stdin.close() - finally: - # Wait for the process to terminate, to avoid zombies. - self.wait() - - def __getattribute__(self, name): - try: - return object.__getattribute__(self, name) - except AttributeError: - try: - return object.__getattribute__(self.__subproc, name) - except AttributeError: - raise AttributeError("%s instance has no attribute '%s'" - % (self.__class__.__name__, name)) - - def wait(self, timeout=None): - if self.__subproc.returncode is not None: - return self.__subproc.returncode - ret = super(Popen, self).wait(timeout) - self.__subproc.returncode = ret - return ret - - -# The valid attr names which can be processed by Process.as_dict(). -_as_dict_attrnames = set( - [x for x in dir(Process) if not x.startswith('_') and x not in - ['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait', - 'is_running', 'as_dict', 'parent', 'parents', 'children', 'rlimit', - 'memory_info_ex', 'oneshot']]) - - -# ===================================================================== -# --- system processes related functions -# ===================================================================== - - -def pids(): - """Return a list of current running PIDs.""" - global _LOWEST_PID - ret = sorted(_psplatform.pids()) - _LOWEST_PID = ret[0] - return ret - - -def pid_exists(pid): - """Return True if given PID exists in the current process list. - This is faster than doing "pid in psutil.pids()" and - should be preferred. - """ - if pid < 0: - return False - elif pid == 0 and POSIX: - # On POSIX we use os.kill() to determine PID existence. - # According to "man 2 kill" PID 0 has a special meaning - # though: it refers to <> and that is not we want - # to do here. - return pid in pids() - else: - return _psplatform.pid_exists(pid) - - -_pmap = {} -_lock = threading.Lock() - - -def process_iter(attrs=None, ad_value=None): - """Return a generator yielding a Process instance for all - running processes. - - Every new Process instance is only created once and then cached - into an internal table which is updated every time this is used. - - Cached Process instances are checked for identity so that you're - safe in case a PID has been reused by another process, in which - case the cached instance is updated. - - The sorting order in which processes are yielded is based on - their PIDs. - - *attrs* and *ad_value* have the same meaning as in - Process.as_dict(). If *attrs* is specified as_dict() is called - and the resulting dict is stored as a 'info' attribute attached - to returned Process instance. - If *attrs* is an empty list it will retrieve all process info - (slow). - """ - def add(pid): - proc = Process(pid) - if attrs is not None: - proc.info = proc.as_dict(attrs=attrs, ad_value=ad_value) - with _lock: - _pmap[proc.pid] = proc - return proc - - def remove(pid): - with _lock: - _pmap.pop(pid, None) - - a = set(pids()) - b = set(_pmap.keys()) - new_pids = a - b - gone_pids = b - a - for pid in gone_pids: - remove(pid) - - with _lock: - ls = sorted(list(_pmap.items()) + - list(dict.fromkeys(new_pids).items())) - - for pid, proc in ls: - try: - if proc is None: # new process - yield add(pid) - else: - # use is_running() to check whether PID has been reused by - # another process in which case yield a new Process instance - if proc.is_running(): - if attrs is not None: - proc.info = proc.as_dict( - attrs=attrs, ad_value=ad_value) - yield proc - else: - yield add(pid) - except NoSuchProcess: - remove(pid) - except AccessDenied: - # Process creation time can't be determined hence there's - # no way to tell whether the pid of the cached process - # has been reused. Just return the cached version. - if proc is None and pid in _pmap: - try: - yield _pmap[pid] - except KeyError: - # If we get here it is likely that 2 threads were - # using process_iter(). - pass - else: - raise - - -def wait_procs(procs, timeout=None, callback=None): - """Convenience function which waits for a list of processes to - terminate. - - Return a (gone, alive) tuple indicating which processes - are gone and which ones are still alive. - - The gone ones will have a new *returncode* attribute indicating - process exit status (may be None). - - *callback* is a function which gets called every time a process - terminates (a Process instance is passed as callback argument). - - Function will return as soon as all processes terminate or when - *timeout* occurs. - Differently from Process.wait() it will not raise TimeoutExpired if - *timeout* occurs. - - Typical use case is: - - - send SIGTERM to a list of processes - - give them some time to terminate - - send SIGKILL to those ones which are still alive - - Example: - - >>> def on_terminate(proc): - ... print("process {} terminated".format(proc)) - ... - >>> for p in procs: - ... p.terminate() - ... - >>> gone, alive = wait_procs(procs, timeout=3, callback=on_terminate) - >>> for p in alive: - ... p.kill() - """ - def check_gone(proc, timeout): - try: - returncode = proc.wait(timeout=timeout) - except TimeoutExpired: - pass - else: - if returncode is not None or not proc.is_running(): - # Set new Process instance attribute. - proc.returncode = returncode - gone.add(proc) - if callback is not None: - callback(proc) - - if timeout is not None and not timeout >= 0: - msg = "timeout must be a positive integer, got %s" % timeout - raise ValueError(msg) - gone = set() - alive = set(procs) - if callback is not None and not callable(callback): - raise TypeError("callback %r is not a callable" % callable) - if timeout is not None: - deadline = _timer() + timeout - - while alive: - if timeout is not None and timeout <= 0: - break - for proc in alive: - # Make sure that every complete iteration (all processes) - # will last max 1 sec. - # We do this because we don't want to wait too long on a - # single process: in case it terminates too late other - # processes may disappear in the meantime and their PID - # reused. - max_timeout = 1.0 / len(alive) - if timeout is not None: - timeout = min((deadline - _timer()), max_timeout) - if timeout <= 0: - break - check_gone(proc, timeout) - else: - check_gone(proc, max_timeout) - alive = alive - gone - - if alive: - # Last attempt over processes survived so far. - # timeout == 0 won't make this function wait any further. - for proc in alive: - check_gone(proc, 0) - alive = alive - gone - - return (list(gone), list(alive)) - - -# ===================================================================== -# --- CPU related functions -# ===================================================================== - - -def cpu_count(logical=True): - """Return the number of logical CPUs in the system (same as - os.cpu_count() in Python 3.4). - - If *logical* is False return the number of physical cores only - (e.g. hyper thread CPUs are excluded). - - Return None if undetermined. - - The return value is cached after first call. - If desired cache can be cleared like this: - - >>> psutil.cpu_count.cache_clear() - """ - if logical: - ret = _psplatform.cpu_count_logical() - else: - ret = _psplatform.cpu_count_physical() - if ret is not None and ret < 1: - ret = None - return ret - - -def cpu_times(percpu=False): - """Return system-wide CPU times as a namedtuple. - Every CPU time represents the seconds the CPU has spent in the - given mode. The namedtuple's fields availability varies depending on the - platform: - - - user - - system - - idle - - nice (UNIX) - - iowait (Linux) - - irq (Linux, FreeBSD) - - softirq (Linux) - - steal (Linux >= 2.6.11) - - guest (Linux >= 2.6.24) - - guest_nice (Linux >= 3.2.0) - - When *percpu* is True return a list of namedtuples for each CPU. - First element of the list refers to first CPU, second element - to second CPU and so on. - The order of the list is consistent across calls. - """ - if not percpu: - return _psplatform.cpu_times() - else: - return _psplatform.per_cpu_times() - - -try: - _last_cpu_times = cpu_times() -except Exception: - # Don't want to crash at import time. - _last_cpu_times = None - -try: - _last_per_cpu_times = cpu_times(percpu=True) -except Exception: - # Don't want to crash at import time. - _last_per_cpu_times = None - - -def _cpu_tot_time(times): - """Given a cpu_time() ntuple calculates the total CPU time - (including idle time). - """ - tot = sum(times) - if LINUX: - # On Linux guest times are already accounted in "user" or - # "nice" times, so we subtract them from total. - # Htop does the same. References: - # https://github.com/giampaolo/psutil/pull/940 - # http://unix.stackexchange.com/questions/178045 - # https://github.com/torvalds/linux/blob/ - # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/ - # cputime.c#L158 - tot -= getattr(times, "guest", 0) # Linux 2.6.24+ - tot -= getattr(times, "guest_nice", 0) # Linux 3.2.0+ - return tot - - -def _cpu_busy_time(times): - """Given a cpu_time() ntuple calculates the busy CPU time. - We do so by subtracting all idle CPU times. - """ - busy = _cpu_tot_time(times) - busy -= times.idle - # Linux: "iowait" is time during which the CPU does not do anything - # (waits for IO to complete). On Linux IO wait is *not* accounted - # in "idle" time so we subtract it. Htop does the same. - # References: - # https://github.com/torvalds/linux/blob/ - # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/cputime.c#L244 - busy -= getattr(times, "iowait", 0) - return busy - - -def _cpu_times_deltas(t1, t2): - assert t1._fields == t2._fields, (t1, t2) - field_deltas = [] - for field in _psplatform.scputimes._fields: - field_delta = getattr(t2, field) - getattr(t1, field) - # CPU times are always supposed to increase over time - # or at least remain the same and that's because time - # cannot go backwards. - # Surprisingly sometimes this might not be the case (at - # least on Windows and Linux), see: - # https://github.com/giampaolo/psutil/issues/392 - # https://github.com/giampaolo/psutil/issues/645 - # https://github.com/giampaolo/psutil/issues/1210 - # Trim negative deltas to zero to ignore decreasing fields. - # top does the same. Reference: - # https://gitlab.com/procps-ng/procps/blob/v3.3.12/top/top.c#L5063 - field_delta = max(0, field_delta) - field_deltas.append(field_delta) - return _psplatform.scputimes(*field_deltas) - - -def cpu_percent(interval=None, percpu=False): - """Return a float representing the current system-wide CPU - utilization as a percentage. - - When *interval* is > 0.0 compares system CPU times elapsed before - and after the interval (blocking). - - When *interval* is 0.0 or None compares system CPU times elapsed - since last call or module import, returning immediately (non - blocking). That means the first time this is called it will - return a meaningless 0.0 value which you should ignore. - In this case is recommended for accuracy that this function be - called with at least 0.1 seconds between calls. - - When *percpu* is True returns a list of floats representing the - utilization as a percentage for each CPU. - First element of the list refers to first CPU, second element - to second CPU and so on. - The order of the list is consistent across calls. - - Examples: - - >>> # blocking, system-wide - >>> psutil.cpu_percent(interval=1) - 2.0 - >>> - >>> # blocking, per-cpu - >>> psutil.cpu_percent(interval=1, percpu=True) - [2.0, 1.0] - >>> - >>> # non-blocking (percentage since last call) - >>> psutil.cpu_percent(interval=None) - 2.9 - >>> - """ - global _last_cpu_times - global _last_per_cpu_times - blocking = interval is not None and interval > 0.0 - if interval is not None and interval < 0: - raise ValueError("interval is not positive (got %r)" % interval) - - def calculate(t1, t2): - times_delta = _cpu_times_deltas(t1, t2) - - all_delta = _cpu_tot_time(times_delta) - busy_delta = _cpu_busy_time(times_delta) - - try: - busy_perc = (busy_delta / all_delta) * 100 - except ZeroDivisionError: - return 0.0 - else: - return round(busy_perc, 1) - - # system-wide usage - if not percpu: - if blocking: - t1 = cpu_times() - time.sleep(interval) - else: - t1 = _last_cpu_times - if t1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - t1 = cpu_times() - _last_cpu_times = cpu_times() - return calculate(t1, _last_cpu_times) - # per-cpu usage - else: - ret = [] - if blocking: - tot1 = cpu_times(percpu=True) - time.sleep(interval) - else: - tot1 = _last_per_cpu_times - if tot1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - tot1 = cpu_times(percpu=True) - _last_per_cpu_times = cpu_times(percpu=True) - for t1, t2 in zip(tot1, _last_per_cpu_times): - ret.append(calculate(t1, t2)) - return ret - - -# Use separate global vars for cpu_times_percent() so that it's -# independent from cpu_percent() and they can both be used within -# the same program. -_last_cpu_times_2 = _last_cpu_times -_last_per_cpu_times_2 = _last_per_cpu_times - - -def cpu_times_percent(interval=None, percpu=False): - """Same as cpu_percent() but provides utilization percentages - for each specific CPU time as is returned by cpu_times(). - For instance, on Linux we'll get: - - >>> cpu_times_percent() - cpupercent(user=4.8, nice=0.0, system=4.8, idle=90.5, iowait=0.0, - irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - >>> - - *interval* and *percpu* arguments have the same meaning as in - cpu_percent(). - """ - global _last_cpu_times_2 - global _last_per_cpu_times_2 - blocking = interval is not None and interval > 0.0 - if interval is not None and interval < 0: - raise ValueError("interval is not positive (got %r)" % interval) - - def calculate(t1, t2): - nums = [] - times_delta = _cpu_times_deltas(t1, t2) - all_delta = _cpu_tot_time(times_delta) - # "scale" is the value to multiply each delta with to get percentages. - # We use "max" to avoid division by zero (if all_delta is 0, then all - # fields are 0 so percentages will be 0 too. all_delta cannot be a - # fraction because cpu times are integers) - scale = 100.0 / max(1, all_delta) - for field_delta in times_delta: - field_perc = field_delta * scale - field_perc = round(field_perc, 1) - # make sure we don't return negative values or values over 100% - field_perc = min(max(0.0, field_perc), 100.0) - nums.append(field_perc) - return _psplatform.scputimes(*nums) - - # system-wide usage - if not percpu: - if blocking: - t1 = cpu_times() - time.sleep(interval) - else: - t1 = _last_cpu_times_2 - if t1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - t1 = cpu_times() - _last_cpu_times_2 = cpu_times() - return calculate(t1, _last_cpu_times_2) - # per-cpu usage - else: - ret = [] - if blocking: - tot1 = cpu_times(percpu=True) - time.sleep(interval) - else: - tot1 = _last_per_cpu_times_2 - if tot1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - tot1 = cpu_times(percpu=True) - _last_per_cpu_times_2 = cpu_times(percpu=True) - for t1, t2 in zip(tot1, _last_per_cpu_times_2): - ret.append(calculate(t1, t2)) - return ret - - -def cpu_stats(): - """Return CPU statistics.""" - return _psplatform.cpu_stats() - - -if hasattr(_psplatform, "cpu_freq"): - - def cpu_freq(percpu=False): - """Return CPU frequency as a nameduple including current, - min and max frequency expressed in Mhz. - - If *percpu* is True and the system supports per-cpu frequency - retrieval (Linux only) a list of frequencies is returned for - each CPU. If not a list with one element is returned. - """ - ret = _psplatform.cpu_freq() - if percpu: - return ret - else: - num_cpus = float(len(ret)) - if num_cpus == 0: - return None - elif num_cpus == 1: - return ret[0] - else: - currs, mins, maxs = 0.0, 0.0, 0.0 - set_none = False - for cpu in ret: - currs += cpu.current - # On Linux if /proc/cpuinfo is used min/max are set - # to None. - if LINUX and cpu.min is None: - set_none = True - continue - mins += cpu.min - maxs += cpu.max - - current = currs / num_cpus - - if set_none: - min_ = max_ = None - else: - min_ = mins / num_cpus - max_ = maxs / num_cpus - - return _common.scpufreq(current, min_, max_) - - __all__.append("cpu_freq") - - -if hasattr(os, "getloadavg") or hasattr(_psplatform, "getloadavg"): - # Perform this hasattr check once on import time to either use the - # platform based code or proxy straight from the os module. - if hasattr(os, "getloadavg"): - getloadavg = os.getloadavg - else: - getloadavg = _psplatform.getloadavg - - __all__.append("getloadavg") - - -# ===================================================================== -# --- system memory related functions -# ===================================================================== - - -def virtual_memory(): - """Return statistics about system memory usage as a namedtuple - including the following fields, expressed in bytes: - - - total: - total physical memory available. - - - available: - the memory that can be given instantly to processes without the - system going into swap. - This is calculated by summing different memory values depending - on the platform and it is supposed to be used to monitor actual - memory usage in a cross platform fashion. - - - percent: - the percentage usage calculated as (total - available) / total * 100 - - - used: - memory used, calculated differently depending on the platform and - designed for informational purposes only: - macOS: active + wired - BSD: active + wired + cached - Linux: total - free - - - free: - memory not being used at all (zeroed) that is readily available; - note that this doesn't reflect the actual memory available - (use 'available' instead) - - Platform-specific fields: - - - active (UNIX): - memory currently in use or very recently used, and so it is in RAM. - - - inactive (UNIX): - memory that is marked as not used. - - - buffers (BSD, Linux): - cache for things like file system metadata. - - - cached (BSD, macOS): - cache for various things. - - - wired (macOS, BSD): - memory that is marked to always stay in RAM. It is never moved to disk. - - - shared (BSD): - memory that may be simultaneously accessed by multiple processes. - - The sum of 'used' and 'available' does not necessarily equal total. - On Windows 'available' and 'free' are the same. - """ - global _TOTAL_PHYMEM - ret = _psplatform.virtual_memory() - # cached for later use in Process.memory_percent() - _TOTAL_PHYMEM = ret.total - return ret - - -def swap_memory(): - """Return system swap memory statistics as a namedtuple including - the following fields: - - - total: total swap memory in bytes - - used: used swap memory in bytes - - free: free swap memory in bytes - - percent: the percentage usage - - sin: no. of bytes the system has swapped in from disk (cumulative) - - sout: no. of bytes the system has swapped out from disk (cumulative) - - 'sin' and 'sout' on Windows are meaningless and always set to 0. - """ - return _psplatform.swap_memory() - - -# ===================================================================== -# --- disks/paritions related functions -# ===================================================================== - - -def disk_usage(path): - """Return disk usage statistics about the given *path* as a - namedtuple including total, used and free space expressed in bytes - plus the percentage usage. - """ - return _psplatform.disk_usage(path) - - -def disk_partitions(all=False): - """Return mounted partitions as a list of - (device, mountpoint, fstype, opts) namedtuple. - 'opts' field is a raw string separated by commas indicating mount - options which may vary depending on the platform. - - If *all* parameter is False return physical devices only and ignore - all others. - """ - return _psplatform.disk_partitions(all) - - -def disk_io_counters(perdisk=False, nowrap=True): - """Return system disk I/O statistics as a namedtuple including - the following fields: - - - read_count: number of reads - - write_count: number of writes - - read_bytes: number of bytes read - - write_bytes: number of bytes written - - read_time: time spent reading from disk (in ms) - - write_time: time spent writing to disk (in ms) - - Platform specific: - - - busy_time: (Linux, FreeBSD) time spent doing actual I/Os (in ms) - - read_merged_count (Linux): number of merged reads - - write_merged_count (Linux): number of merged writes - - If *perdisk* is True return the same information for every - physical disk installed on the system as a dictionary - with partition names as the keys and the namedtuple - described above as the values. - - If *nowrap* is True it detects and adjust the numbers which overflow - and wrap (restart from 0) and add "old value" to "new value" so that - the returned numbers will always be increasing or remain the same, - but never decrease. - "disk_io_counters.cache_clear()" can be used to invalidate the - cache. - - On recent Windows versions 'diskperf -y' command may need to be - executed first otherwise this function won't find any disk. - """ - kwargs = dict(perdisk=perdisk) if LINUX else {} - rawdict = _psplatform.disk_io_counters(**kwargs) - if not rawdict: - return {} if perdisk else None - if nowrap: - rawdict = _wrap_numbers(rawdict, 'psutil.disk_io_counters') - nt = getattr(_psplatform, "sdiskio", _common.sdiskio) - if perdisk: - for disk, fields in rawdict.items(): - rawdict[disk] = nt(*fields) - return rawdict - else: - return nt(*[sum(x) for x in zip(*rawdict.values())]) - - -disk_io_counters.cache_clear = functools.partial( - _wrap_numbers.cache_clear, 'psutil.disk_io_counters') -disk_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache" - - -# ===================================================================== -# --- network related functions -# ===================================================================== - - -def net_io_counters(pernic=False, nowrap=True): - """Return network I/O statistics as a namedtuple including - the following fields: - - - bytes_sent: number of bytes sent - - bytes_recv: number of bytes received - - packets_sent: number of packets sent - - packets_recv: number of packets received - - errin: total number of errors while receiving - - errout: total number of errors while sending - - dropin: total number of incoming packets which were dropped - - dropout: total number of outgoing packets which were dropped - (always 0 on macOS and BSD) - - If *pernic* is True return the same information for every - network interface installed on the system as a dictionary - with network interface names as the keys and the namedtuple - described above as the values. - - If *nowrap* is True it detects and adjust the numbers which overflow - and wrap (restart from 0) and add "old value" to "new value" so that - the returned numbers will always be increasing or remain the same, - but never decrease. - "disk_io_counters.cache_clear()" can be used to invalidate the - cache. - """ - rawdict = _psplatform.net_io_counters() - if not rawdict: - return {} if pernic else None - if nowrap: - rawdict = _wrap_numbers(rawdict, 'psutil.net_io_counters') - if pernic: - for nic, fields in rawdict.items(): - rawdict[nic] = _common.snetio(*fields) - return rawdict - else: - return _common.snetio(*[sum(x) for x in zip(*rawdict.values())]) - - -net_io_counters.cache_clear = functools.partial( - _wrap_numbers.cache_clear, 'psutil.net_io_counters') -net_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache" - - -def net_connections(kind='inet'): - """Return system-wide socket connections as a list of - (fd, family, type, laddr, raddr, status, pid) namedtuples. - In case of limited privileges 'fd' and 'pid' may be set to -1 - and None respectively. - The *kind* parameter filters for connections that fit the - following criteria: - - +------------+----------------------------------------------------+ - | Kind Value | Connections using | - +------------+----------------------------------------------------+ - | inet | IPv4 and IPv6 | - | inet4 | IPv4 | - | inet6 | IPv6 | - | tcp | TCP | - | tcp4 | TCP over IPv4 | - | tcp6 | TCP over IPv6 | - | udp | UDP | - | udp4 | UDP over IPv4 | - | udp6 | UDP over IPv6 | - | unix | UNIX socket (both UDP and TCP protocols) | - | all | the sum of all the possible families and protocols | - +------------+----------------------------------------------------+ - - On macOS this function requires root privileges. - """ - return _psplatform.net_connections(kind) - - -def net_if_addrs(): - """Return the addresses associated to each NIC (network interface - card) installed on the system as a dictionary whose keys are the - NIC names and value is a list of namedtuples for each address - assigned to the NIC. Each namedtuple includes 5 fields: - - - family: can be either socket.AF_INET, socket.AF_INET6 or - psutil.AF_LINK, which refers to a MAC address. - - address: is the primary address and it is always set. - - netmask: and 'broadcast' and 'ptp' may be None. - - ptp: stands for "point to point" and references the - destination address on a point to point interface - (typically a VPN). - - broadcast: and *ptp* are mutually exclusive. - - Note: you can have more than one address of the same family - associated with each interface. - """ - has_enums = sys.version_info >= (3, 4) - if has_enums: - import socket - rawlist = _psplatform.net_if_addrs() - rawlist.sort(key=lambda x: x[1]) # sort by family - ret = collections.defaultdict(list) - for name, fam, addr, mask, broadcast, ptp in rawlist: - if has_enums: - try: - fam = socket.AddressFamily(fam) - except ValueError: - if WINDOWS and fam == -1: - fam = _psplatform.AF_LINK - elif (hasattr(_psplatform, "AF_LINK") and - _psplatform.AF_LINK == fam): - # Linux defines AF_LINK as an alias for AF_PACKET. - # We re-set the family here so that repr(family) - # will show AF_LINK rather than AF_PACKET - fam = _psplatform.AF_LINK - if fam == _psplatform.AF_LINK: - # The underlying C function may return an incomplete MAC - # address in which case we fill it with null bytes, see: - # https://github.com/giampaolo/psutil/issues/786 - separator = ":" if POSIX else "-" - while addr.count(separator) < 5: - addr += "%s00" % separator - ret[name].append(_common.snicaddr(fam, addr, mask, broadcast, ptp)) - return dict(ret) - - -def net_if_stats(): - """Return information about each NIC (network interface card) - installed on the system as a dictionary whose keys are the - NIC names and value is a namedtuple with the following fields: - - - isup: whether the interface is up (bool) - - duplex: can be either NIC_DUPLEX_FULL, NIC_DUPLEX_HALF or - NIC_DUPLEX_UNKNOWN - - speed: the NIC speed expressed in mega bits (MB); if it can't - be determined (e.g. 'localhost') it will be set to 0. - - mtu: the maximum transmission unit expressed in bytes. - """ - return _psplatform.net_if_stats() - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -# Linux, macOS -if hasattr(_psplatform, "sensors_temperatures"): - - def sensors_temperatures(fahrenheit=False): - """Return hardware temperatures. Each entry is a namedtuple - representing a certain hardware sensor (it may be a CPU, an - hard disk or something else, depending on the OS and its - configuration). - All temperatures are expressed in celsius unless *fahrenheit* - is set to True. - """ - def convert(n): - if n is not None: - return (float(n) * 9 / 5) + 32 if fahrenheit else n - - ret = collections.defaultdict(list) - rawdict = _psplatform.sensors_temperatures() - - for name, values in rawdict.items(): - while values: - label, current, high, critical = values.pop(0) - current = convert(current) - high = convert(high) - critical = convert(critical) - - if high and not critical: - critical = high - elif critical and not high: - high = critical - - ret[name].append( - _common.shwtemp(label, current, high, critical)) - - return dict(ret) - - __all__.append("sensors_temperatures") - - -# Linux, macOS -if hasattr(_psplatform, "sensors_fans"): - - def sensors_fans(): - """Return fans speed. Each entry is a namedtuple - representing a certain hardware sensor. - All speed are expressed in RPM (rounds per minute). - """ - return _psplatform.sensors_fans() - - __all__.append("sensors_fans") - - -# Linux, Windows, FreeBSD, macOS -if hasattr(_psplatform, "sensors_battery"): - - def sensors_battery(): - """Return battery information. If no battery is installed - returns None. - - - percent: battery power left as a percentage. - - secsleft: a rough approximation of how many seconds are left - before the battery runs out of power. May be - POWER_TIME_UNLIMITED or POWER_TIME_UNLIMITED. - - power_plugged: True if the AC power cable is connected. - """ - return _psplatform.sensors_battery() - - __all__.append("sensors_battery") - - -# ===================================================================== -# --- other system related functions -# ===================================================================== - - -def boot_time(): - """Return the system boot time expressed in seconds since the epoch.""" - # Note: we are not caching this because it is subject to - # system clock updates. - return _psplatform.boot_time() - - -def users(): - """Return users currently connected on the system as a list of - namedtuples including the following fields. - - - user: the name of the user - - terminal: the tty or pseudo-tty associated with the user, if any. - - host: the host name associated with the entry, if any. - - started: the creation time as a floating point number expressed in - seconds since the epoch. - """ - return _psplatform.users() - - -# ===================================================================== -# --- Windows services -# ===================================================================== - - -if WINDOWS: - - def win_service_iter(): - """Return a generator yielding a WindowsService instance for all - Windows services installed. - """ - return _psplatform.win_service_iter() - - def win_service_get(name): - """Get a Windows service by *name*. - Raise NoSuchProcess if no service with such name exists. - """ - return _psplatform.win_service_get(name) - - -# ===================================================================== - - -def test(): # pragma: no cover - from ._common import bytes2human - from ._compat import get_terminal_size - - today_day = datetime.date.today() - templ = "%-10s %5s %5s %7s %7s %5s %6s %6s %6s %s" - attrs = ['pid', 'memory_percent', 'name', 'cmdline', 'cpu_times', - 'create_time', 'memory_info', 'status', 'nice', 'username'] - print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "NICE", - "STATUS", "START", "TIME", "CMDLINE")) - for p in process_iter(attrs, ad_value=None): - if p.info['create_time']: - ctime = datetime.datetime.fromtimestamp(p.info['create_time']) - if ctime.date() == today_day: - ctime = ctime.strftime("%H:%M") - else: - ctime = ctime.strftime("%b%d") - else: - ctime = '' - if p.info['cpu_times']: - cputime = time.strftime("%M:%S", - time.localtime(sum(p.info['cpu_times']))) - else: - cputime = '' - - user = p.info['username'] or '' - if not user and POSIX: - try: - user = p.uids()[0] - except Error: - pass - if user and WINDOWS and '\\' in user: - user = user.split('\\')[1] - user = user[:9] - vms = bytes2human(p.info['memory_info'].vms) if \ - p.info['memory_info'] is not None else '' - rss = bytes2human(p.info['memory_info'].rss) if \ - p.info['memory_info'] is not None else '' - memp = round(p.info['memory_percent'], 1) if \ - p.info['memory_percent'] is not None else '' - nice = int(p.info['nice']) if p.info['nice'] else '' - if p.info['cmdline']: - cmdline = ' '.join(p.info['cmdline']) - else: - cmdline = p.info['name'] - status = p.info['status'][:5] if p.info['status'] else '' - - line = templ % ( - user[:10], - p.info['pid'], - memp, - vms, - rss, - nice, - status, - ctime, - cputime, - cmdline) - print(line[:get_terminal_size()[0]]) - - -del memoize, memoize_when_activated, division, deprecated_method -if sys.version_info[0] < 3: - del num, x - -if __name__ == "__main__": - test() diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/_common.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/_common.py deleted file mode 100644 index 728d9c62585b..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/_common.py +++ /dev/null @@ -1,846 +0,0 @@ -# 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. - -"""Common objects shared by __init__.py and _ps*.py modules.""" - -# Note: this module is imported by setup.py so it should not import -# psutil or third-party modules. - -from __future__ import division, print_function - -import contextlib -import errno -import functools -import os -import socket -import stat -import sys -import threading -import warnings -from collections import defaultdict -from collections import namedtuple -from socket import AF_INET -from socket import SOCK_DGRAM -from socket import SOCK_STREAM - -try: - from socket import AF_INET6 -except ImportError: - AF_INET6 = None -try: - from socket import AF_UNIX -except ImportError: - AF_UNIX = None - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - - -# can't take it from _common.py as this script is imported by setup.py -PY3 = sys.version_info[0] == 3 - -__all__ = [ - # OS constants - 'FREEBSD', 'BSD', 'LINUX', 'NETBSD', 'OPENBSD', 'MACOS', 'OSX', 'POSIX', - 'SUNOS', 'WINDOWS', - # connection constants - 'CONN_CLOSE', 'CONN_CLOSE_WAIT', 'CONN_CLOSING', 'CONN_ESTABLISHED', - 'CONN_FIN_WAIT1', 'CONN_FIN_WAIT2', 'CONN_LAST_ACK', 'CONN_LISTEN', - 'CONN_NONE', 'CONN_SYN_RECV', 'CONN_SYN_SENT', 'CONN_TIME_WAIT', - # net constants - 'NIC_DUPLEX_FULL', 'NIC_DUPLEX_HALF', 'NIC_DUPLEX_UNKNOWN', - # process status constants - 'STATUS_DEAD', 'STATUS_DISK_SLEEP', 'STATUS_IDLE', 'STATUS_LOCKED', - 'STATUS_RUNNING', 'STATUS_SLEEPING', 'STATUS_STOPPED', 'STATUS_SUSPENDED', - 'STATUS_TRACING_STOP', 'STATUS_WAITING', 'STATUS_WAKE_KILL', - 'STATUS_WAKING', 'STATUS_ZOMBIE', 'STATUS_PARKED', - # other constants - 'ENCODING', 'ENCODING_ERRS', 'AF_INET6', - # named tuples - 'pconn', 'pcputimes', 'pctxsw', 'pgids', 'pio', 'pionice', 'popenfile', - 'pthread', 'puids', 'sconn', 'scpustats', 'sdiskio', 'sdiskpart', - 'sdiskusage', 'snetio', 'snicaddr', 'snicstats', 'sswap', 'suser', - # utility functions - 'conn_tmap', 'deprecated_method', 'isfile_strict', 'memoize', - 'parse_environ_block', 'path_exists_strict', 'usage_percent', - 'supports_ipv6', 'sockfam_to_enum', 'socktype_to_enum', "wrap_numbers", - 'bytes2human', 'conn_to_ntuple', 'debug', - # shell utils - 'hilite', 'term_supports_colors', 'print_color', -] - - -# =================================================================== -# --- OS constants -# =================================================================== - - -POSIX = os.name == "posix" -WINDOWS = os.name == "nt" -LINUX = sys.platform.startswith("linux") -MACOS = sys.platform.startswith("darwin") -OSX = MACOS # deprecated alias -FREEBSD = sys.platform.startswith("freebsd") -OPENBSD = sys.platform.startswith("openbsd") -NETBSD = sys.platform.startswith("netbsd") -BSD = FREEBSD or OPENBSD or NETBSD -SUNOS = sys.platform.startswith(("sunos", "solaris")) -AIX = sys.platform.startswith("aix") - - -# =================================================================== -# --- API constants -# =================================================================== - - -# Process.status() -STATUS_RUNNING = "running" -STATUS_SLEEPING = "sleeping" -STATUS_DISK_SLEEP = "disk-sleep" -STATUS_STOPPED = "stopped" -STATUS_TRACING_STOP = "tracing-stop" -STATUS_ZOMBIE = "zombie" -STATUS_DEAD = "dead" -STATUS_WAKE_KILL = "wake-kill" -STATUS_WAKING = "waking" -STATUS_IDLE = "idle" # Linux, macOS, FreeBSD -STATUS_LOCKED = "locked" # FreeBSD -STATUS_WAITING = "waiting" # FreeBSD -STATUS_SUSPENDED = "suspended" # NetBSD -STATUS_PARKED = "parked" # Linux - -# Process.connections() and psutil.net_connections() -CONN_ESTABLISHED = "ESTABLISHED" -CONN_SYN_SENT = "SYN_SENT" -CONN_SYN_RECV = "SYN_RECV" -CONN_FIN_WAIT1 = "FIN_WAIT1" -CONN_FIN_WAIT2 = "FIN_WAIT2" -CONN_TIME_WAIT = "TIME_WAIT" -CONN_CLOSE = "CLOSE" -CONN_CLOSE_WAIT = "CLOSE_WAIT" -CONN_LAST_ACK = "LAST_ACK" -CONN_LISTEN = "LISTEN" -CONN_CLOSING = "CLOSING" -CONN_NONE = "NONE" - -# net_if_stats() -if enum is None: - NIC_DUPLEX_FULL = 2 - NIC_DUPLEX_HALF = 1 - NIC_DUPLEX_UNKNOWN = 0 -else: - class NicDuplex(enum.IntEnum): - NIC_DUPLEX_FULL = 2 - NIC_DUPLEX_HALF = 1 - NIC_DUPLEX_UNKNOWN = 0 - - globals().update(NicDuplex.__members__) - -# sensors_battery() -if enum is None: - POWER_TIME_UNKNOWN = -1 - POWER_TIME_UNLIMITED = -2 -else: - class BatteryTime(enum.IntEnum): - POWER_TIME_UNKNOWN = -1 - POWER_TIME_UNLIMITED = -2 - - globals().update(BatteryTime.__members__) - -# --- others - -ENCODING = sys.getfilesystemencoding() -if not PY3: - ENCODING_ERRS = "replace" -else: - try: - ENCODING_ERRS = sys.getfilesystemencodeerrors() # py 3.6 - except AttributeError: - ENCODING_ERRS = "surrogateescape" if POSIX else "replace" - - -# =================================================================== -# --- namedtuples -# =================================================================== - -# --- for system functions - -# psutil.swap_memory() -sswap = namedtuple('sswap', ['total', 'used', 'free', 'percent', 'sin', - 'sout']) -# psutil.disk_usage() -sdiskusage = namedtuple('sdiskusage', ['total', 'used', 'free', 'percent']) -# psutil.disk_io_counters() -sdiskio = namedtuple('sdiskio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'read_time', 'write_time']) -# psutil.disk_partitions() -sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts']) -# psutil.net_io_counters() -snetio = namedtuple('snetio', ['bytes_sent', 'bytes_recv', - 'packets_sent', 'packets_recv', - 'errin', 'errout', - 'dropin', 'dropout']) -# psutil.users() -suser = namedtuple('suser', ['name', 'terminal', 'host', 'started', 'pid']) -# psutil.net_connections() -sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr', - 'status', 'pid']) -# psutil.net_if_addrs() -snicaddr = namedtuple('snicaddr', - ['family', 'address', 'netmask', 'broadcast', 'ptp']) -# psutil.net_if_stats() -snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu']) -# psutil.cpu_stats() -scpustats = namedtuple( - 'scpustats', ['ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls']) -# psutil.cpu_freq() -scpufreq = namedtuple('scpufreq', ['current', 'min', 'max']) -# psutil.sensors_temperatures() -shwtemp = namedtuple( - 'shwtemp', ['label', 'current', 'high', 'critical']) -# psutil.sensors_battery() -sbattery = namedtuple('sbattery', ['percent', 'secsleft', 'power_plugged']) -# psutil.sensors_fans() -sfan = namedtuple('sfan', ['label', 'current']) - -# --- for Process methods - -# psutil.Process.cpu_times() -pcputimes = namedtuple('pcputimes', - ['user', 'system', 'children_user', 'children_system']) -# psutil.Process.open_files() -popenfile = namedtuple('popenfile', ['path', 'fd']) -# psutil.Process.threads() -pthread = namedtuple('pthread', ['id', 'user_time', 'system_time']) -# psutil.Process.uids() -puids = namedtuple('puids', ['real', 'effective', 'saved']) -# psutil.Process.gids() -pgids = namedtuple('pgids', ['real', 'effective', 'saved']) -# psutil.Process.io_counters() -pio = namedtuple('pio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes']) -# psutil.Process.ionice() -pionice = namedtuple('pionice', ['ioclass', 'value']) -# psutil.Process.ctx_switches() -pctxsw = namedtuple('pctxsw', ['voluntary', 'involuntary']) -# psutil.Process.connections() -pconn = namedtuple('pconn', ['fd', 'family', 'type', 'laddr', 'raddr', - 'status']) - -# psutil.connections() and psutil.Process.connections() -addr = namedtuple('addr', ['ip', 'port']) - - -# =================================================================== -# --- Process.connections() 'kind' parameter mapping -# =================================================================== - - -conn_tmap = { - "all": ([AF_INET, AF_INET6, AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), - "tcp": ([AF_INET, AF_INET6], [SOCK_STREAM]), - "tcp4": ([AF_INET], [SOCK_STREAM]), - "udp": ([AF_INET, AF_INET6], [SOCK_DGRAM]), - "udp4": ([AF_INET], [SOCK_DGRAM]), - "inet": ([AF_INET, AF_INET6], [SOCK_STREAM, SOCK_DGRAM]), - "inet4": ([AF_INET], [SOCK_STREAM, SOCK_DGRAM]), - "inet6": ([AF_INET6], [SOCK_STREAM, SOCK_DGRAM]), -} - -if AF_INET6 is not None: - conn_tmap.update({ - "tcp6": ([AF_INET6], [SOCK_STREAM]), - "udp6": ([AF_INET6], [SOCK_DGRAM]), - }) - -if AF_UNIX is not None: - conn_tmap.update({ - "unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), - }) - - -# ===================================================================== -# --- Exceptions -# ===================================================================== - - -class Error(Exception): - """Base exception class. All other psutil exceptions inherit - from this one. - """ - __module__ = 'psutil' - - def __init__(self, msg=""): - Exception.__init__(self, msg) - self.msg = msg - - def __repr__(self): - ret = "psutil.%s %s" % (self.__class__.__name__, self.msg) - return ret.strip() - - __str__ = __repr__ - - -class NoSuchProcess(Error): - """Exception raised when a process with a certain PID doesn't - or no longer exists. - """ - __module__ = 'psutil' - - def __init__(self, pid, name=None, msg=None): - Error.__init__(self, msg) - self.pid = pid - self.name = name - self.msg = msg - if msg is None: - if name: - details = "(pid=%s, name=%s)" % (self.pid, repr(self.name)) - else: - details = "(pid=%s)" % self.pid - self.msg = "process no longer exists " + details - - def __path__(self): - return 'xxx' - - -class ZombieProcess(NoSuchProcess): - """Exception raised when querying a zombie process. This is - raised on macOS, BSD and Solaris only, and not always: depending - on the query the OS may be able to succeed anyway. - On Linux all zombie processes are querable (hence this is never - raised). Windows doesn't have zombie processes. - """ - __module__ = 'psutil' - - def __init__(self, pid, name=None, ppid=None, msg=None): - NoSuchProcess.__init__(self, msg) - self.pid = pid - self.ppid = ppid - self.name = name - self.msg = msg - if msg is None: - args = ["pid=%s" % pid] - if name: - args.append("name=%s" % repr(self.name)) - if ppid: - args.append("ppid=%s" % self.ppid) - details = "(%s)" % ", ".join(args) - self.msg = "process still exists but it's a zombie " + details - - -class AccessDenied(Error): - """Exception raised when permission to perform an action is denied.""" - __module__ = 'psutil' - - def __init__(self, pid=None, name=None, msg=None): - Error.__init__(self, msg) - self.pid = pid - self.name = name - self.msg = msg - if msg is None: - if (pid is not None) and (name is not None): - self.msg = "(pid=%s, name=%s)" % (pid, repr(name)) - elif (pid is not None): - self.msg = "(pid=%s)" % self.pid - else: - self.msg = "" - - -class TimeoutExpired(Error): - """Raised on Process.wait(timeout) if timeout expires and process - is still alive. - """ - __module__ = 'psutil' - - def __init__(self, seconds, pid=None, name=None): - Error.__init__(self, "timeout after %s seconds" % seconds) - self.seconds = seconds - self.pid = pid - self.name = name - if (pid is not None) and (name is not None): - self.msg += " (pid=%s, name=%s)" % (pid, repr(name)) - elif (pid is not None): - self.msg += " (pid=%s)" % self.pid - - -# =================================================================== -# --- utils -# =================================================================== - - -def usage_percent(used, total, round_=None): - """Calculate percentage usage of 'used' against 'total'.""" - try: - ret = (float(used) / total) * 100 - except ZeroDivisionError: - return 0.0 - else: - if round_ is not None: - ret = round(ret, round_) - return ret - - -def memoize(fun): - """A simple memoize decorator for functions supporting (hashable) - positional arguments. - It also provides a cache_clear() function for clearing the cache: - - >>> @memoize - ... def foo() - ... return 1 - ... - >>> foo() - 1 - >>> foo.cache_clear() - >>> - """ - @functools.wraps(fun) - def wrapper(*args, **kwargs): - key = (args, frozenset(sorted(kwargs.items()))) - try: - return cache[key] - except KeyError: - ret = cache[key] = fun(*args, **kwargs) - return ret - - def cache_clear(): - """Clear cache.""" - cache.clear() - - cache = {} - wrapper.cache_clear = cache_clear - return wrapper - - -def memoize_when_activated(fun): - """A memoize decorator which is disabled by default. It can be - activated and deactivated on request. - For efficiency reasons it can be used only against class methods - accepting no arguments. - - >>> class Foo: - ... @memoize - ... def foo() - ... print(1) - ... - >>> f = Foo() - >>> # deactivated (default) - >>> foo() - 1 - >>> foo() - 1 - >>> - >>> # activated - >>> foo.cache_activate(self) - >>> foo() - 1 - >>> foo() - >>> foo() - >>> - """ - @functools.wraps(fun) - def wrapper(self): - try: - # case 1: we previously entered oneshot() ctx - ret = self._cache[fun] - except AttributeError: - # case 2: we never entered oneshot() ctx - return fun(self) - except KeyError: - # case 3: we entered oneshot() ctx but there's no cache - # for this entry yet - ret = self._cache[fun] = fun(self) - return ret - - def cache_activate(proc): - """Activate cache. Expects a Process instance. Cache will be - stored as a "_cache" instance attribute.""" - proc._cache = {} - - def cache_deactivate(proc): - """Deactivate and clear cache.""" - try: - del proc._cache - except AttributeError: - pass - - wrapper.cache_activate = cache_activate - wrapper.cache_deactivate = cache_deactivate - return wrapper - - -def isfile_strict(path): - """Same as os.path.isfile() but does not swallow EACCES / EPERM - exceptions, see: - http://mail.python.org/pipermail/python-dev/2012-June/120787.html - """ - try: - st = os.stat(path) - except OSError as err: - if err.errno in (errno.EPERM, errno.EACCES): - raise - return False - else: - return stat.S_ISREG(st.st_mode) - - -def path_exists_strict(path): - """Same as os.path.exists() but does not swallow EACCES / EPERM - exceptions, see: - http://mail.python.org/pipermail/python-dev/2012-June/120787.html - """ - try: - os.stat(path) - except OSError as err: - if err.errno in (errno.EPERM, errno.EACCES): - raise - return False - else: - return True - - -@memoize -def supports_ipv6(): - """Return True if IPv6 is supported on this platform.""" - if not socket.has_ipv6 or AF_INET6 is None: - return False - try: - sock = socket.socket(AF_INET6, socket.SOCK_STREAM) - with contextlib.closing(sock): - sock.bind(("::1", 0)) - return True - except socket.error: - return False - - -def parse_environ_block(data): - """Parse a C environ block of environment variables into a dictionary.""" - # The block is usually raw data from the target process. It might contain - # trailing garbage and lines that do not look like assignments. - ret = {} - pos = 0 - - # localize global variable to speed up access. - WINDOWS_ = WINDOWS - while True: - next_pos = data.find("\0", pos) - # nul byte at the beginning or double nul byte means finish - if next_pos <= pos: - break - # there might not be an equals sign - equal_pos = data.find("=", pos, next_pos) - if equal_pos > pos: - key = data[pos:equal_pos] - value = data[equal_pos + 1:next_pos] - # Windows expects environment variables to be uppercase only - if WINDOWS_: - key = key.upper() - ret[key] = value - pos = next_pos + 1 - - return ret - - -def sockfam_to_enum(num): - """Convert a numeric socket family value to an IntEnum member. - If it's not a known member, return the numeric value itself. - """ - if enum is None: - return num - else: # pragma: no cover - try: - return socket.AddressFamily(num) - except ValueError: - return num - - -def socktype_to_enum(num): - """Convert a numeric socket type value to an IntEnum member. - If it's not a known member, return the numeric value itself. - """ - if enum is None: - return num - else: # pragma: no cover - try: - return socket.SocketKind(num) - except ValueError: - return num - - -def conn_to_ntuple(fd, fam, type_, laddr, raddr, status, status_map, pid=None): - """Convert a raw connection tuple to a proper ntuple.""" - if fam in (socket.AF_INET, AF_INET6): - if laddr: - laddr = addr(*laddr) - if raddr: - raddr = addr(*raddr) - if type_ == socket.SOCK_STREAM and fam in (AF_INET, AF_INET6): - status = status_map.get(status, CONN_NONE) - else: - status = CONN_NONE # ignore whatever C returned to us - fam = sockfam_to_enum(fam) - type_ = socktype_to_enum(type_) - if pid is None: - return pconn(fd, fam, type_, laddr, raddr, status) - else: - return sconn(fd, fam, type_, laddr, raddr, status, pid) - - -def deprecated_method(replacement): - """A decorator which can be used to mark a method as deprecated - 'replcement' is the method name which will be called instead. - """ - def outer(fun): - msg = "%s() is deprecated and will be removed; use %s() instead" % ( - fun.__name__, replacement) - if fun.__doc__ is None: - fun.__doc__ = msg - - @functools.wraps(fun) - def inner(self, *args, **kwargs): - warnings.warn(msg, category=DeprecationWarning, stacklevel=2) - return getattr(self, replacement)(*args, **kwargs) - return inner - return outer - - -class _WrapNumbers: - """Watches numbers so that they don't overflow and wrap - (reset to zero). - """ - - def __init__(self): - self.lock = threading.Lock() - self.cache = {} - self.reminders = {} - self.reminder_keys = {} - - def _add_dict(self, input_dict, name): - assert name not in self.cache - assert name not in self.reminders - assert name not in self.reminder_keys - self.cache[name] = input_dict - self.reminders[name] = defaultdict(int) - self.reminder_keys[name] = defaultdict(set) - - def _remove_dead_reminders(self, input_dict, name): - """In case the number of keys changed between calls (e.g. a - disk disappears) this removes the entry from self.reminders. - """ - old_dict = self.cache[name] - gone_keys = set(old_dict.keys()) - set(input_dict.keys()) - for gone_key in gone_keys: - for remkey in self.reminder_keys[name][gone_key]: - del self.reminders[name][remkey] - del self.reminder_keys[name][gone_key] - - def run(self, input_dict, name): - """Cache dict and sum numbers which overflow and wrap. - Return an updated copy of `input_dict` - """ - if name not in self.cache: - # This was the first call. - self._add_dict(input_dict, name) - return input_dict - - self._remove_dead_reminders(input_dict, name) - - old_dict = self.cache[name] - new_dict = {} - for key in input_dict.keys(): - input_tuple = input_dict[key] - try: - old_tuple = old_dict[key] - except KeyError: - # The input dict has a new key (e.g. a new disk or NIC) - # which didn't exist in the previous call. - new_dict[key] = input_tuple - continue - - bits = [] - for i in range(len(input_tuple)): - input_value = input_tuple[i] - old_value = old_tuple[i] - remkey = (key, i) - if input_value < old_value: - # it wrapped! - self.reminders[name][remkey] += old_value - self.reminder_keys[name][key].add(remkey) - bits.append(input_value + self.reminders[name][remkey]) - - new_dict[key] = tuple(bits) - - self.cache[name] = input_dict - return new_dict - - def cache_clear(self, name=None): - """Clear the internal cache, optionally only for function 'name'.""" - with self.lock: - if name is None: - self.cache.clear() - self.reminders.clear() - self.reminder_keys.clear() - else: - self.cache.pop(name, None) - self.reminders.pop(name, None) - self.reminder_keys.pop(name, None) - - def cache_info(self): - """Return internal cache dicts as a tuple of 3 elements.""" - with self.lock: - return (self.cache, self.reminders, self.reminder_keys) - - -def wrap_numbers(input_dict, name): - """Given an `input_dict` and a function `name`, adjust the numbers - which "wrap" (restart from zero) across different calls by adding - "old value" to "new value" and return an updated dict. - """ - with _wn.lock: - return _wn.run(input_dict, name) - - -_wn = _WrapNumbers() -wrap_numbers.cache_clear = _wn.cache_clear -wrap_numbers.cache_info = _wn.cache_info - - -def open_binary(fname, **kwargs): - return open(fname, "rb", **kwargs) - - -def open_text(fname, **kwargs): - """On Python 3 opens a file in text mode by using fs encoding and - a proper en/decoding errors handler. - On Python 2 this is just an alias for open(name, 'rt'). - """ - if PY3: - # See: - # https://github.com/giampaolo/psutil/issues/675 - # https://github.com/giampaolo/psutil/pull/733 - kwargs.setdefault('encoding', ENCODING) - kwargs.setdefault('errors', ENCODING_ERRS) - return open(fname, "rt", **kwargs) - - -def bytes2human(n, format="%(value).1f%(symbol)s"): - """Used by various scripts. See: - http://goo.gl/zeJZl - - >>> bytes2human(10000) - '9.8K' - >>> bytes2human(100001221) - '95.4M' - """ - symbols = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') - prefix = {} - for i, s in enumerate(symbols[1:]): - prefix[s] = 1 << (i + 1) * 10 - for symbol in reversed(symbols[1:]): - if n >= prefix[symbol]: - value = float(n) / prefix[symbol] - return format % locals() - return format % dict(symbol=symbols[0], value=n) - - -def get_procfs_path(): - """Return updated psutil.PROCFS_PATH constant.""" - return sys.modules['psutil'].PROCFS_PATH - - -if PY3: - def decode(s): - return s.decode(encoding=ENCODING, errors=ENCODING_ERRS) -else: - def decode(s): - return s - - -# ===================================================================== -# --- shell utils -# ===================================================================== - - -@memoize -def term_supports_colors(file=sys.stdout): - if os.name == 'nt': - return True - try: - import curses - assert file.isatty() - curses.setupterm() - assert curses.tigetnum("colors") > 0 - except Exception: - return False - else: - return True - - -def hilite(s, color="green", bold=False): - """Return an highlighted version of 'string'.""" - if not term_supports_colors(): - return s - attr = [] - colors = dict(green='32', red='91', brown='33') - colors[None] = '29' - try: - color = colors[color] - except KeyError: - raise ValueError("invalid color %r; choose between %r" % ( - list(colors.keys()))) - attr.append(color) - if bold: - attr.append('1') - return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), s) - - -def print_color(s, color="green", bold=False, file=sys.stdout): - """Print a colorized version of string.""" - if not term_supports_colors(): - print(s, file=file) - elif POSIX: - print(hilite(s, color, bold), file=file) - else: - import ctypes - - DEFAULT_COLOR = 7 - GetStdHandle = ctypes.windll.Kernel32.GetStdHandle - SetConsoleTextAttribute = \ - ctypes.windll.Kernel32.SetConsoleTextAttribute - - colors = dict(green=2, red=4, brown=6) - colors[None] = DEFAULT_COLOR - try: - color = colors[color] - except KeyError: - raise ValueError("invalid color %r; choose between %r" % ( - color, list(colors.keys()))) - if bold and color <= 7: - color += 8 - - handle_id = -12 if file is sys.stderr else -11 - GetStdHandle.restype = ctypes.c_ulong - handle = GetStdHandle(handle_id) - SetConsoleTextAttribute(handle, color) - try: - print(s, file=file) - finally: - SetConsoleTextAttribute(handle, DEFAULT_COLOR) - - -if bool(os.getenv('PSUTIL_DEBUG', 0)): - import inspect - - def debug(msg): - """If PSUTIL_DEBUG env var is set, print a debug message to stderr.""" - fname, lineno, func_name, lines, index = inspect.getframeinfo( - inspect.currentframe().f_back) - print("psutil-debug [%s:%s]> %s" % (fname, lineno, msg), - file=sys.stderr) -else: - def debug(msg): - pass diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/_compat.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/_compat.py deleted file mode 100644 index a9371382bd6e..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/_compat.py +++ /dev/null @@ -1,345 +0,0 @@ -# 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. - -"""Module which provides compatibility with older Python versions.""" - -import collections -import errno -import functools -import os -import sys - -__all__ = ["PY3", "long", "xrange", "unicode", "basestring", "u", "b", - "lru_cache", "which", "get_terminal_size", - "FileNotFoundError", "PermissionError", "ProcessLookupError", - "InterruptedError", "ChildProcessError", "FileExistsError"] - -PY3 = sys.version_info[0] == 3 - -if PY3: - long = int - xrange = range - unicode = str - basestring = str - - def u(s): - return s - - def b(s): - return s.encode("latin-1") -else: - long = long - xrange = xrange - unicode = unicode - basestring = basestring - - def u(s): - return unicode(s, "unicode_escape") - - def b(s): - return s - - -# --- exceptions - - -if PY3: - FileNotFoundError = FileNotFoundError # NOQA - PermissionError = PermissionError # NOQA - ProcessLookupError = ProcessLookupError # NOQA - InterruptedError = InterruptedError # NOQA - ChildProcessError = ChildProcessError # NOQA - FileExistsError = FileExistsError # NOQA -else: - # https://github.com/PythonCharmers/python-future/blob/exceptions/ - # src/future/types/exceptions/pep3151.py - import platform - - _singleton = object() - - def instance_checking_exception(base_exception=Exception): - def wrapped(instance_checker): - class TemporaryClass(base_exception): - - def __init__(self, *args, **kwargs): - if len(args) == 1 and isinstance(args[0], TemporaryClass): - unwrap_me = args[0] - for attr in dir(unwrap_me): - if not attr.startswith('__'): - setattr(self, attr, getattr(unwrap_me, attr)) - else: - super(TemporaryClass, self).__init__(*args, **kwargs) - - class __metaclass__(type): - def __instancecheck__(cls, inst): - return instance_checker(inst) - - def __subclasscheck__(cls, classinfo): - value = sys.exc_info()[1] - return isinstance(value, cls) - - TemporaryClass.__name__ = instance_checker.__name__ - TemporaryClass.__doc__ = instance_checker.__doc__ - return TemporaryClass - - return wrapped - - @instance_checking_exception(EnvironmentError) - def FileNotFoundError(inst): - return getattr(inst, 'errno', _singleton) == errno.ENOENT - - @instance_checking_exception(EnvironmentError) - def ProcessLookupError(inst): - return getattr(inst, 'errno', _singleton) == errno.ESRCH - - @instance_checking_exception(EnvironmentError) - def PermissionError(inst): - return getattr(inst, 'errno', _singleton) in ( - errno.EACCES, errno.EPERM) - - @instance_checking_exception(EnvironmentError) - def InterruptedError(inst): - return getattr(inst, 'errno', _singleton) == errno.EINTR - - @instance_checking_exception(EnvironmentError) - def ChildProcessError(inst): - return getattr(inst, 'errno', _singleton) == errno.ECHILD - - @instance_checking_exception(EnvironmentError) - def FileExistsError(inst): - return getattr(inst, 'errno', _singleton) == errno.EEXIST - - if platform.python_implementation() != "CPython": - try: - raise OSError(errno.EEXIST, "perm") - except FileExistsError: - pass - except OSError: - raise RuntimeError( - "broken / incompatible Python implementation, see: " - "https://github.com/giampaolo/psutil/issues/1659") - - -# --- stdlib additions - - -# py 3.2 functools.lru_cache -# Taken from: http://code.activestate.com/recipes/578078 -# Credit: Raymond Hettinger -try: - from functools import lru_cache -except ImportError: - try: - from threading import RLock - except ImportError: - from dummy_threading import RLock - - _CacheInfo = collections.namedtuple( - "CacheInfo", ["hits", "misses", "maxsize", "currsize"]) - - class _HashedSeq(list): - __slots__ = 'hashvalue' - - def __init__(self, tup, hash=hash): - self[:] = tup - self.hashvalue = hash(tup) - - def __hash__(self): - return self.hashvalue - - def _make_key(args, kwds, typed, - kwd_mark=(object(), ), - fasttypes=set((int, str, frozenset, type(None))), - sorted=sorted, tuple=tuple, type=type, len=len): - key = args - if kwds: - sorted_items = sorted(kwds.items()) - key += kwd_mark - for item in sorted_items: - key += item - if typed: - key += tuple(type(v) for v in args) - if kwds: - key += tuple(type(v) for k, v in sorted_items) - elif len(key) == 1 and type(key[0]) in fasttypes: - return key[0] - return _HashedSeq(key) - - def lru_cache(maxsize=100, typed=False): - """Least-recently-used cache decorator, see: - http://docs.python.org/3/library/functools.html#functools.lru_cache - """ - def decorating_function(user_function): - cache = dict() - stats = [0, 0] - HITS, MISSES = 0, 1 - make_key = _make_key - cache_get = cache.get - _len = len - lock = RLock() - root = [] - root[:] = [root, root, None, None] - nonlocal_root = [root] - PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 - if maxsize == 0: - def wrapper(*args, **kwds): - result = user_function(*args, **kwds) - stats[MISSES] += 1 - return result - elif maxsize is None: - def wrapper(*args, **kwds): - key = make_key(args, kwds, typed) - result = cache_get(key, root) - if result is not root: - stats[HITS] += 1 - return result - result = user_function(*args, **kwds) - cache[key] = result - stats[MISSES] += 1 - return result - else: - def wrapper(*args, **kwds): - if kwds or typed: - key = make_key(args, kwds, typed) - else: - key = args - lock.acquire() - try: - link = cache_get(key) - if link is not None: - root, = nonlocal_root - link_prev, link_next, key, result = link - link_prev[NEXT] = link_next - link_next[PREV] = link_prev - last = root[PREV] - last[NEXT] = root[PREV] = link - link[PREV] = last - link[NEXT] = root - stats[HITS] += 1 - return result - finally: - lock.release() - result = user_function(*args, **kwds) - lock.acquire() - try: - root, = nonlocal_root - if key in cache: - pass - elif _len(cache) >= maxsize: - oldroot = root - oldroot[KEY] = key - oldroot[RESULT] = result - root = nonlocal_root[0] = oldroot[NEXT] - oldkey = root[KEY] - root[KEY] = root[RESULT] = None - del cache[oldkey] - cache[key] = oldroot - else: - last = root[PREV] - link = [last, root, key, result] - last[NEXT] = root[PREV] = cache[key] = link - stats[MISSES] += 1 - finally: - lock.release() - return result - - def cache_info(): - """Report cache statistics""" - lock.acquire() - try: - return _CacheInfo(stats[HITS], stats[MISSES], maxsize, - len(cache)) - finally: - lock.release() - - def cache_clear(): - """Clear the cache and cache statistics""" - lock.acquire() - try: - cache.clear() - root = nonlocal_root[0] - root[:] = [root, root, None, None] - stats[:] = [0, 0] - finally: - lock.release() - - wrapper.__wrapped__ = user_function - wrapper.cache_info = cache_info - wrapper.cache_clear = cache_clear - return functools.update_wrapper(wrapper, user_function) - - return decorating_function - - -# python 3.3 -try: - from shutil import which -except ImportError: - def which(cmd, mode=os.F_OK | os.X_OK, path=None): - """Given a command, mode, and a PATH string, return the path which - conforms to the given mode on the PATH, or None if there is no such - file. - - `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result - of os.environ.get("PATH"), or can be overridden with a custom search - path. - """ - def _access_check(fn, mode): - return (os.path.exists(fn) and os.access(fn, mode) and - not os.path.isdir(fn)) - - if os.path.dirname(cmd): - if _access_check(cmd, mode): - return cmd - return None - - if path is None: - path = os.environ.get("PATH", os.defpath) - if not path: - return None - path = path.split(os.pathsep) - - if sys.platform == "win32": - if os.curdir not in path: - path.insert(0, os.curdir) - - pathext = os.environ.get("PATHEXT", "").split(os.pathsep) - if any(cmd.lower().endswith(ext.lower()) for ext in pathext): - files = [cmd] - else: - files = [cmd + ext for ext in pathext] - else: - files = [cmd] - - seen = set() - for dir in path: - normdir = os.path.normcase(dir) - if normdir not in seen: - seen.add(normdir) - for thefile in files: - name = os.path.join(dir, thefile) - if _access_check(name, mode): - return name - return None - - -# python 3.3 -try: - from shutil import get_terminal_size -except ImportError: - def get_terminal_size(fallback=(80, 24)): - try: - import fcntl - import termios - import struct - except ImportError: - return fallback - else: - try: - # This should work on Linux. - res = struct.unpack( - 'hh', fcntl.ioctl(1, termios.TIOCGWINSZ, '1234')) - return (res[1], res[0]) - except Exception: - return fallback diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/_psaix.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/_psaix.py deleted file mode 100644 index 994366aaa1b9..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/_psaix.py +++ /dev/null @@ -1,550 +0,0 @@ -# Copyright (c) 2009, Giampaolo Rodola' -# Copyright (c) 2017, Arnon Yaari -# All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""AIX platform implementation.""" - -import functools -import glob -import os -import re -import subprocess -import sys -from collections import namedtuple - -from . import _common -from . import _psposix -from . import _psutil_aix as cext -from . import _psutil_posix as cext_posix -from ._common import AccessDenied -from ._common import conn_to_ntuple -from ._common import get_procfs_path -from ._common import memoize_when_activated -from ._common import NIC_DUPLEX_FULL -from ._common import NIC_DUPLEX_HALF -from ._common import NIC_DUPLEX_UNKNOWN -from ._common import NoSuchProcess -from ._common import usage_percent -from ._common import ZombieProcess -from ._compat import FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 - - -__extra__all__ = ["PROCFS_PATH"] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -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 - -PROC_STATUSES = { - cext.SIDL: _common.STATUS_IDLE, - cext.SZOMB: _common.STATUS_ZOMBIE, - cext.SACTIVE: _common.STATUS_RUNNING, - cext.SSWAP: _common.STATUS_RUNNING, # TODO what status is this? - cext.SSTOP: _common.STATUS_STOPPED, -} - -TCP_STATUSES = { - cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, - cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, - cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV, - cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, - cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, - cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.TCPS_CLOSED: _common.CONN_CLOSE, - cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, - cext.TCPS_LISTEN: _common.CONN_LISTEN, - cext.TCPS_CLOSING: _common.CONN_CLOSING, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -proc_info_map = dict( - ppid=0, - rss=1, - vms=2, - create_time=3, - nice=4, - num_threads=5, - status=6, - ttynr=7) - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.Process.memory_info() -pmem = namedtuple('pmem', ['rss', 'vms']) -# psutil.Process.memory_full_info() -pfullmem = pmem -# psutil.Process.cpu_times() -scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait']) -# psutil.virtual_memory() -svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - total, avail, free, pinned, inuse = cext.virtual_mem() - percent = usage_percent((total - avail), total, round_=1) - return svmem(total, avail, percent, inuse, free) - - -def swap_memory(): - """Swap system memory as a (total, used, free, sin, sout) tuple.""" - total, free, sin, sout = cext.swap_mem() - used = total - free - percent = usage_percent(used, total, round_=1) - return _common.sswap(total, used, free, percent, sin, sout) - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return system-wide CPU times as a named tuple""" - ret = cext.per_cpu_times() - return scputimes(*[sum(x) for x in zip(*ret)]) - - -def per_cpu_times(): - """Return system per-CPU times as a list of named tuples""" - ret = cext.per_cpu_times() - return [scputimes(*x) for x in ret] - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - try: - return os.sysconf("SC_NPROCESSORS_ONLN") - except ValueError: - # mimic os.cpu_count() behavior - return None - - -def cpu_count_physical(): - cmd = "lsdev -Cc processor" - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout, stderr = [x.decode(sys.stdout.encoding) - for x in (stdout, stderr)] - if p.returncode != 0: - raise RuntimeError("%r command error\n%s" % (cmd, stderr)) - processors = stdout.strip().splitlines() - return len(processors) or None - - -def cpu_stats(): - """Return various CPU stats as a named tuple.""" - ctx_switches, interrupts, soft_interrupts, syscalls = cext.cpu_stats() - return _common.scpustats( - ctx_switches, interrupts, soft_interrupts, syscalls) - - -# ===================================================================== -# --- disks -# ===================================================================== - - -disk_io_counters = cext.disk_io_counters -disk_usage = _psposix.disk_usage - - -def disk_partitions(all=False): - """Return system disk partitions.""" - # TODO - the filtering logic should be better checked so that - # it tries to reflect 'df' as much as possible - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - # Differently from, say, Linux, we don't have a list of - # common fs types so the best we can do, AFAIK, is to - # filter by filesystem having a total size > 0. - if not disk_usage(mountpoint).total: - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -# ===================================================================== -# --- network -# ===================================================================== - - -net_if_addrs = cext_posix.net_if_addrs - -if HAS_NET_IO_COUNTERS: - net_io_counters = cext.net_io_counters - - -def net_connections(kind, _pid=-1): - """Return socket connections. If pid == -1 return system-wide - connections (as opposed to connections opened by one process only). - """ - cmap = _common.conn_tmap - if kind not in cmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in cmap]))) - families, types = _common.conn_tmap[kind] - rawlist = cext.net_connections(_pid) - ret = [] - for item in rawlist: - fd, fam, type_, laddr, raddr, status, pid = item - if fam not in families: - continue - if type_ not in types: - continue - nt = conn_to_ntuple(fd, fam, type_, laddr, raddr, status, - TCP_STATUSES, pid=pid if _pid == -1 else None) - ret.append(nt) - return ret - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - duplex_map = {"Full": NIC_DUPLEX_FULL, - "Half": NIC_DUPLEX_HALF} - names = set([x[0] for x in net_if_addrs()]) - ret = {} - for name in names: - isup, mtu = cext.net_if_stats(name) - - # try to get speed and duplex - # TODO: rewrite this in C (entstat forks, so use truss -f to follow. - # looks like it is using an undocumented ioctl?) - duplex = "" - speed = 0 - p = subprocess.Popen(["/usr/bin/entstat", "-d", name], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout, stderr = [x.decode(sys.stdout.encoding) - for x in (stdout, stderr)] - if p.returncode == 0: - re_result = re.search( - r"Running: (\d+) Mbps.*?(\w+) Duplex", stdout) - if re_result is not None: - speed = int(re_result.group(1)) - duplex = re_result.group(2) - - duplex = duplex_map.get(duplex, NIC_DUPLEX_UNKNOWN) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - localhost = (':0.0', ':0') - for item in rawlist: - user, tty, hostname, tstamp, user_process, pid = item - # note: the underlying C function includes entries about - # system boot, run level and others. We might want - # to use them in the future. - if not user_process: - continue - if hostname in localhost: - hostname = 'localhost' - nt = _common.suser(user, tty, hostname, tstamp, pid) - retlist.append(nt) - return retlist - - -# ===================================================================== -# --- processes -# ===================================================================== - - -def pids(): - """Returns a list of PIDs currently running on the system.""" - return [int(x) for x in os.listdir(get_procfs_path()) if x.isdigit()] - - -def pid_exists(pid): - """Check for the existence of a unix pid.""" - return os.path.exists(os.path.join(get_procfs_path(), str(pid), "psinfo")) - - -def wrap_exceptions(fun): - """Call callable into a try/except clause and translate ENOENT, - EACCES and EPERM in NoSuchProcess or AccessDenied exceptions. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except (FileNotFoundError, ProcessLookupError): - # ENOENT (no such file or directory) gets raised on open(). - # ESRCH (no such process) can get raised on read() if - # process is gone in meantime. - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - self._procfs_path = get_procfs_path() - - def oneshot_enter(self): - self._proc_basic_info.cache_activate(self) - self._proc_cred.cache_activate(self) - - def oneshot_exit(self): - self._proc_basic_info.cache_deactivate(self) - self._proc_cred.cache_deactivate(self) - - @wrap_exceptions - @memoize_when_activated - def _proc_basic_info(self): - return cext.proc_basic_info(self.pid, self._procfs_path) - - @wrap_exceptions - @memoize_when_activated - def _proc_cred(self): - return cext.proc_cred(self.pid, self._procfs_path) - - @wrap_exceptions - def name(self): - if self.pid == 0: - return "swapper" - # note: max 16 characters - return cext.proc_name(self.pid, self._procfs_path).rstrip("\x00") - - @wrap_exceptions - def exe(self): - # there is no way to get executable path in AIX other than to guess, - # and guessing is more complex than what's in the wrapping class - cmdline = self.cmdline() - if not cmdline: - return '' - exe = cmdline[0] - if os.path.sep in exe: - # relative or absolute path - if not os.path.isabs(exe): - # if cwd has changed, we're out of luck - this may be wrong! - exe = os.path.abspath(os.path.join(self.cwd(), exe)) - if (os.path.isabs(exe) and - os.path.isfile(exe) and - os.access(exe, os.X_OK)): - return exe - # not found, move to search in PATH using basename only - exe = os.path.basename(exe) - # search for exe name PATH - for path in os.environ["PATH"].split(":"): - possible_exe = os.path.abspath(os.path.join(path, exe)) - if (os.path.isfile(possible_exe) and - os.access(possible_exe, os.X_OK)): - return possible_exe - return '' - - @wrap_exceptions - def cmdline(self): - return cext.proc_args(self.pid) - - @wrap_exceptions - def environ(self): - return cext.proc_environ(self.pid) - - @wrap_exceptions - def create_time(self): - return self._proc_basic_info()[proc_info_map['create_time']] - - @wrap_exceptions - def num_threads(self): - return self._proc_basic_info()[proc_info_map['num_threads']] - - if HAS_THREADS: - @wrap_exceptions - def threads(self): - rawlist = cext.proc_threads(self.pid) - retlist = [] - for thread_id, utime, stime in rawlist: - ntuple = _common.pthread(thread_id, utime, stime) - retlist.append(ntuple) - # The underlying C implementation retrieves all OS threads - # and filters them by PID. At this point we can't tell whether - # an empty list means there were no connections for process or - # process is no longer active so we force NSP in case the PID - # is no longer there. - if not retlist: - # will raise NSP if process is gone - os.stat('%s/%s' % (self._procfs_path, self.pid)) - return retlist - - @wrap_exceptions - def connections(self, kind='inet'): - ret = net_connections(kind, _pid=self.pid) - # The underlying C implementation retrieves all OS connections - # and filters them by PID. At this point we can't tell whether - # an empty list means there were no connections for process or - # process is no longer active so we force NSP in case the PID - # is no longer there. - if not ret: - # will raise NSP if process is gone - os.stat('%s/%s' % (self._procfs_path, self.pid)) - return ret - - @wrap_exceptions - def nice_get(self): - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def ppid(self): - self._ppid = self._proc_basic_info()[proc_info_map['ppid']] - return self._ppid - - @wrap_exceptions - def uids(self): - real, effective, saved, _, _, _ = self._proc_cred() - return _common.puids(real, effective, saved) - - @wrap_exceptions - def gids(self): - _, _, _, real, effective, saved = self._proc_cred() - return _common.puids(real, effective, saved) - - @wrap_exceptions - def cpu_times(self): - cpu_times = cext.proc_cpu_times(self.pid, self._procfs_path) - return _common.pcputimes(*cpu_times) - - @wrap_exceptions - def terminal(self): - ttydev = self._proc_basic_info()[proc_info_map['ttynr']] - # convert from 64-bit dev_t to 32-bit dev_t and then map the device - ttydev = (((ttydev & 0x0000FFFF00000000) >> 16) | (ttydev & 0xFFFF)) - # try to match rdev of /dev/pts/* files ttydev - for dev in glob.glob("/dev/**/*"): - if os.stat(dev).st_rdev == ttydev: - return dev - return None - - @wrap_exceptions - def cwd(self): - procfs_path = self._procfs_path - try: - result = os.readlink("%s/%s/cwd" % (procfs_path, self.pid)) - return result.rstrip('/') - except FileNotFoundError: - os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD - return None - - @wrap_exceptions - def memory_info(self): - ret = self._proc_basic_info() - rss = ret[proc_info_map['rss']] * 1024 - vms = ret[proc_info_map['vms']] * 1024 - return pmem(rss, vms) - - memory_full_info = memory_info - - @wrap_exceptions - def status(self): - code = self._proc_basic_info()[proc_info_map['status']] - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(code, '?') - - def open_files(self): - # TODO rewrite without using procfiles (stat /proc/pid/fd/* and then - # find matching name of the inode) - p = subprocess.Popen(["/usr/bin/procfiles", "-n", str(self.pid)], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout, stderr = [x.decode(sys.stdout.encoding) - for x in (stdout, stderr)] - if "no such process" in stderr.lower(): - raise NoSuchProcess(self.pid, self._name) - procfiles = re.findall(r"(\d+): S_IFREG.*\s*.*name:(.*)\n", stdout) - retlist = [] - for fd, path in procfiles: - path = path.strip() - if path.startswith("//"): - path = path[1:] - if path.lower() == "cannot be retrieved": - continue - retlist.append(_common.popenfile(path, int(fd))) - return retlist - - @wrap_exceptions - def num_fds(self): - if self.pid == 0: # no /proc/0/fd - return 0 - return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))) - - @wrap_exceptions - def num_ctx_switches(self): - return _common.pctxsw( - *cext.proc_num_ctx_switches(self.pid)) - - @wrap_exceptions - def wait(self, timeout=None): - return _psposix.wait_pid(self.pid, timeout, self._name) - - 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/third_party/python/psutil-cp27-none-win_amd64/psutil/_psbsd.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/_psbsd.py deleted file mode 100644 index 49ad1e995cc1..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/_psbsd.py +++ /dev/null @@ -1,903 +0,0 @@ -# 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. - -"""FreeBSD, OpenBSD and NetBSD platforms implementation.""" - -import contextlib -import errno -import functools -import os -import xml.etree.ElementTree as ET -from collections import namedtuple -from collections import defaultdict - -from . import _common -from . import _psposix -from . import _psutil_bsd as cext -from . import _psutil_posix as cext_posix -from ._common import AccessDenied -from ._common import conn_tmap -from ._common import conn_to_ntuple -from ._common import FREEBSD -from ._common import memoize -from ._common import memoize_when_activated -from ._common import NETBSD -from ._common import NoSuchProcess -from ._common import OPENBSD -from ._common import usage_percent -from ._common import ZombieProcess -from ._compat import FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import which - - -__extra__all__ = [] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -if FREEBSD: - PROC_STATUSES = { - cext.SIDL: _common.STATUS_IDLE, - cext.SRUN: _common.STATUS_RUNNING, - cext.SSLEEP: _common.STATUS_SLEEPING, - cext.SSTOP: _common.STATUS_STOPPED, - cext.SZOMB: _common.STATUS_ZOMBIE, - cext.SWAIT: _common.STATUS_WAITING, - cext.SLOCK: _common.STATUS_LOCKED, - } -elif OPENBSD or NETBSD: - PROC_STATUSES = { - cext.SIDL: _common.STATUS_IDLE, - cext.SSLEEP: _common.STATUS_SLEEPING, - cext.SSTOP: _common.STATUS_STOPPED, - # According to /usr/include/sys/proc.h SZOMB is unused. - # test_zombie_process() shows that SDEAD is the right - # equivalent. Also it appears there's no equivalent of - # psutil.STATUS_DEAD. SDEAD really means STATUS_ZOMBIE. - # cext.SZOMB: _common.STATUS_ZOMBIE, - cext.SDEAD: _common.STATUS_ZOMBIE, - cext.SZOMB: _common.STATUS_ZOMBIE, - # From http://www.eecs.harvard.edu/~margo/cs161/videos/proc.h.txt - # OpenBSD has SRUN and SONPROC: SRUN indicates that a process - # is runnable but *not* yet running, i.e. is on a run queue. - # SONPROC indicates that the process is actually executing on - # a CPU, i.e. it is no longer on a run queue. - # As such we'll map SRUN to STATUS_WAKING and SONPROC to - # STATUS_RUNNING - cext.SRUN: _common.STATUS_WAKING, - cext.SONPROC: _common.STATUS_RUNNING, - } -elif NETBSD: - PROC_STATUSES = { - cext.SIDL: _common.STATUS_IDLE, - cext.SACTIVE: _common.STATUS_RUNNING, - cext.SDYING: _common.STATUS_ZOMBIE, - cext.SSTOP: _common.STATUS_STOPPED, - cext.SZOMB: _common.STATUS_ZOMBIE, - cext.SDEAD: _common.STATUS_DEAD, - cext.SSUSPENDED: _common.STATUS_SUSPENDED, # unique to NetBSD - } - -TCP_STATUSES = { - cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, - cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, - cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV, - cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, - cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, - cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.TCPS_CLOSED: _common.CONN_CLOSE, - cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, - cext.TCPS_LISTEN: _common.CONN_LISTEN, - cext.TCPS_CLOSING: _common.CONN_CLOSING, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -if NETBSD: - PAGESIZE = os.sysconf("SC_PAGESIZE") -else: - PAGESIZE = os.sysconf("SC_PAGE_SIZE") -AF_LINK = cext_posix.AF_LINK - -HAS_PER_CPU_TIMES = hasattr(cext, "per_cpu_times") -HAS_PROC_NUM_THREADS = hasattr(cext, "proc_num_threads") -HAS_PROC_OPEN_FILES = hasattr(cext, 'proc_open_files') -HAS_PROC_NUM_FDS = hasattr(cext, 'proc_num_fds') - -kinfo_proc_map = dict( - ppid=0, - status=1, - real_uid=2, - effective_uid=3, - saved_uid=4, - real_gid=5, - effective_gid=6, - saved_gid=7, - ttynr=8, - create_time=9, - ctx_switches_vol=10, - ctx_switches_unvol=11, - read_io_count=12, - write_io_count=13, - user_time=14, - sys_time=15, - ch_user_time=16, - ch_sys_time=17, - rss=18, - vms=19, - memtext=20, - memdata=21, - memstack=22, - cpunum=23, - name=24, -) - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.virtual_memory() -svmem = namedtuple( - 'svmem', ['total', 'available', 'percent', 'used', 'free', - 'active', 'inactive', 'buffers', 'cached', 'shared', 'wired']) -# psutil.cpu_times() -scputimes = namedtuple( - 'scputimes', ['user', 'nice', 'system', 'idle', 'irq']) -# psutil.Process.memory_info() -pmem = namedtuple('pmem', ['rss', 'vms', 'text', 'data', 'stack']) -# psutil.Process.memory_full_info() -pfullmem = pmem -# psutil.Process.cpu_times() -pcputimes = namedtuple('pcputimes', - ['user', 'system', 'children_user', 'children_system']) -# psutil.Process.memory_maps(grouped=True) -pmmap_grouped = namedtuple( - 'pmmap_grouped', 'path rss, private, ref_count, shadow_count') -# psutil.Process.memory_maps(grouped=False) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr, perms path rss, private, ref_count, shadow_count') -# psutil.disk_io_counters() -if FREEBSD: - sdiskio = namedtuple('sdiskio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'read_time', 'write_time', - 'busy_time']) -else: - sdiskio = namedtuple('sdiskio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes']) - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - """System virtual memory as a namedtuple.""" - mem = cext.virtual_mem() - total, free, active, inactive, wired, cached, buffers, shared = mem - if NETBSD: - # On NetBSD buffers and shared mem is determined via /proc. - # The C ext set them to 0. - with open('/proc/meminfo', 'rb') as f: - for line in f: - if line.startswith(b'Buffers:'): - buffers = int(line.split()[1]) * 1024 - elif line.startswith(b'MemShared:'): - shared = int(line.split()[1]) * 1024 - avail = inactive + cached + free - used = active + wired + cached - percent = usage_percent((total - avail), total, round_=1) - return svmem(total, avail, percent, used, free, - active, inactive, buffers, cached, shared, wired) - - -def swap_memory(): - """System swap memory as (total, used, free, sin, sout) namedtuple.""" - total, used, free, sin, sout = cext.swap_mem() - percent = usage_percent(used, total, round_=1) - return _common.sswap(total, used, free, percent, sin, sout) - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return system per-CPU times as a namedtuple""" - user, nice, system, idle, irq = cext.cpu_times() - return scputimes(user, nice, system, idle, irq) - - -if HAS_PER_CPU_TIMES: - def per_cpu_times(): - """Return system CPU times as a namedtuple""" - ret = [] - for cpu_t in cext.per_cpu_times(): - user, nice, system, idle, irq = cpu_t - item = scputimes(user, nice, system, idle, irq) - ret.append(item) - return ret -else: - # XXX - # Ok, this is very dirty. - # On FreeBSD < 8 we cannot gather per-cpu information, see: - # https://github.com/giampaolo/psutil/issues/226 - # If num cpus > 1, on first call we return single cpu times to avoid a - # crash at psutil import time. - # Next calls will fail with NotImplementedError - def per_cpu_times(): - """Return system CPU times as a namedtuple""" - if cpu_count_logical() == 1: - return [cpu_times()] - if per_cpu_times.__called__: - raise NotImplementedError("supported only starting from FreeBSD 8") - per_cpu_times.__called__ = True - return [cpu_times()] - - per_cpu_times.__called__ = False - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - return cext.cpu_count_logical() - - -if OPENBSD or NETBSD: - def cpu_count_physical(): - # OpenBSD and NetBSD do not implement this. - return 1 if cpu_count_logical() == 1 else None -else: - def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" - # From the C module we'll get an XML string similar to this: - # http://manpages.ubuntu.com/manpages/precise/man4/smp.4freebsd.html - # We may get None in case "sysctl kern.sched.topology_spec" - # is not supported on this BSD version, in which case we'll mimic - # os.cpu_count() and return None. - ret = None - s = cext.cpu_count_phys() - if s is not None: - # get rid of padding chars appended at the end of the string - index = s.rfind("") - if index != -1: - s = s[:index + 9] - root = ET.fromstring(s) - try: - ret = len(root.findall('group/children/group/cpu')) or None - finally: - # needed otherwise it will memleak - root.clear() - if not ret: - # If logical CPUs are 1 it's obvious we'll have only 1 - # physical CPU. - if cpu_count_logical() == 1: - return 1 - return ret - - -def cpu_stats(): - """Return various CPU stats as a named tuple.""" - if FREEBSD: - # Note: the C ext is returning some metrics we are not exposing: - # traps. - ctxsw, intrs, soft_intrs, syscalls, traps = cext.cpu_stats() - elif NETBSD: - # XXX - # Note about intrs: the C extension returns 0. intrs - # can be determined via /proc/stat; it has the same value as - # soft_intrs thought so the kernel is faking it (?). - # - # Note about syscalls: the C extension always sets it to 0 (?). - # - # Note: the C ext is returning some metrics we are not exposing: - # traps, faults and forks. - ctxsw, intrs, soft_intrs, syscalls, traps, faults, forks = \ - cext.cpu_stats() - with open('/proc/stat', 'rb') as f: - for line in f: - if line.startswith(b'intr'): - intrs = int(line.split()[1]) - elif OPENBSD: - # Note: the C ext is returning some metrics we are not exposing: - # traps, faults and forks. - ctxsw, intrs, soft_intrs, syscalls, traps, faults, forks = \ - cext.cpu_stats() - return _common.scpustats(ctxsw, intrs, soft_intrs, syscalls) - - -# ===================================================================== -# --- disks -# ===================================================================== - - -def disk_partitions(all=False): - """Return mounted disk partitions as a list of namedtuples. - 'all' argument is ignored, see: - https://github.com/giampaolo/psutil/issues/906 - """ - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -disk_usage = _psposix.disk_usage -disk_io_counters = cext.disk_io_counters - - -# ===================================================================== -# --- network -# ===================================================================== - - -net_io_counters = cext.net_io_counters -net_if_addrs = cext_posix.net_if_addrs - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - names = net_io_counters().keys() - ret = {} - for name in names: - try: - mtu = cext_posix.net_if_mtu(name) - isup = cext_posix.net_if_flags(name) - duplex, speed = cext_posix.net_if_duplex_speed(name) - except OSError as err: - # https://github.com/giampaolo/psutil/issues/1279 - if err.errno != errno.ENODEV: - raise - else: - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -def net_connections(kind): - """System-wide network connections.""" - if OPENBSD: - ret = [] - for pid in pids(): - try: - cons = Process(pid).connections(kind) - except (NoSuchProcess, ZombieProcess): - continue - else: - for conn in cons: - conn = list(conn) - conn.append(pid) - ret.append(_common.sconn(*conn)) - return ret - - if kind not in _common.conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - families, types = conn_tmap[kind] - ret = set() - if NETBSD: - rawlist = cext.net_connections(-1) - else: - rawlist = cext.net_connections() - for item in rawlist: - fd, fam, type, laddr, raddr, status, pid = item - # TODO: apply filter at C level - if fam in families and type in types: - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES, pid) - ret.add(nt) - return list(ret) - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -if FREEBSD: - - def sensors_battery(): - """Return battery info.""" - try: - percent, minsleft, power_plugged = cext.sensors_battery() - except NotImplementedError: - # See: https://github.com/giampaolo/psutil/issues/1074 - return None - power_plugged = power_plugged == 1 - if power_plugged: - secsleft = _common.POWER_TIME_UNLIMITED - elif minsleft == -1: - secsleft = _common.POWER_TIME_UNKNOWN - else: - secsleft = minsleft * 60 - return _common.sbattery(percent, secsleft, power_plugged) - - def sensors_temperatures(): - "Return CPU cores temperatures if available, else an empty dict." - ret = defaultdict(list) - num_cpus = cpu_count_logical() - for cpu in range(num_cpus): - try: - current, high = cext.sensors_cpu_temperature(cpu) - if high <= 0: - high = None - name = "Core %s" % cpu - ret["coretemp"].append( - _common.shwtemp(name, current, high, high)) - except NotImplementedError: - pass - - return ret - - def cpu_freq(): - """Return frequency metrics for CPUs. As of Dec 2018 only - CPU 0 appears to be supported by FreeBSD and all other cores - match the frequency of CPU 0. - """ - ret = [] - num_cpus = cpu_count_logical() - for cpu in range(num_cpus): - try: - current, available_freq = cext.cpu_frequency(cpu) - except NotImplementedError: - continue - if available_freq: - try: - min_freq = int(available_freq.split(" ")[-1].split("/")[0]) - except(IndexError, ValueError): - min_freq = None - try: - max_freq = int(available_freq.split(" ")[0].split("/")[0]) - except(IndexError, ValueError): - max_freq = None - ret.append(_common.scpufreq(current, min_freq, max_freq)) - return ret - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, tty, hostname, tstamp, pid = item - if pid == -1: - assert OPENBSD - pid = None - if tty == '~': - continue # reboot or shutdown - nt = _common.suser(user, tty or None, hostname, tstamp, pid) - retlist.append(nt) - return retlist - - -# ===================================================================== -# --- processes -# ===================================================================== - - -@memoize -def _pid_0_exists(): - try: - Process(0).name() - except NoSuchProcess: - return False - except AccessDenied: - return True - else: - return True - - -def pids(): - """Returns a list of PIDs currently running on the system.""" - ret = cext.pids() - if OPENBSD and (0 not in ret) and _pid_0_exists(): - # On OpenBSD the kernel does not return PID 0 (neither does - # ps) but it's actually querable (Process(0) will succeed). - ret.insert(0, 0) - return ret - - -if OPENBSD or NETBSD: - def pid_exists(pid): - """Return True if pid exists.""" - exists = _psposix.pid_exists(pid) - if not exists: - # We do this because _psposix.pid_exists() lies in case of - # zombie processes. - return pid in pids() - else: - return True -else: - pid_exists = _psposix.pid_exists - - -def is_zombie(pid): - try: - st = cext.proc_oneshot_info(pid)[kinfo_proc_map['status']] - return st == cext.SZOMB - except Exception: - return False - - -def wrap_exceptions(fun): - """Decorator which translates bare OSError exceptions into - NoSuchProcess and AccessDenied. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except ProcessLookupError: - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except OSError: - if self.pid == 0: - if 0 in pids(): - raise AccessDenied(self.pid, self._name) - else: - raise - raise - return wrapper - - -@contextlib.contextmanager -def wrap_exceptions_procfs(inst): - """Same as above, for routines relying on reading /proc fs.""" - try: - yield - except (ProcessLookupError, FileNotFoundError): - # ENOENT (no such file or directory) gets raised on open(). - # ESRCH (no such process) can get raised on read() if - # process is gone in meantime. - if not pid_exists(inst.pid): - raise NoSuchProcess(inst.pid, inst._name) - else: - raise ZombieProcess(inst.pid, inst._name, inst._ppid) - except PermissionError: - raise AccessDenied(inst.pid, inst._name) - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - def _assert_alive(self): - """Raise NSP if the process disappeared on us.""" - # For those C function who do not raise NSP, possibly returning - # incorrect or incomplete result. - cext.proc_name(self.pid) - - @wrap_exceptions - @memoize_when_activated - def oneshot(self): - """Retrieves multiple process info in one shot as a raw tuple.""" - ret = cext.proc_oneshot_info(self.pid) - assert len(ret) == len(kinfo_proc_map) - return ret - - def oneshot_enter(self): - self.oneshot.cache_activate(self) - - def oneshot_exit(self): - self.oneshot.cache_deactivate(self) - - @wrap_exceptions - def name(self): - name = self.oneshot()[kinfo_proc_map['name']] - return name if name is not None else cext.proc_name(self.pid) - - @wrap_exceptions - def exe(self): - if FREEBSD: - if self.pid == 0: - return '' # else NSP - return cext.proc_exe(self.pid) - elif NETBSD: - if self.pid == 0: - # /proc/0 dir exists but /proc/0/exe doesn't - return "" - with wrap_exceptions_procfs(self): - return os.readlink("/proc/%s/exe" % self.pid) - else: - # OpenBSD: exe cannot be determined; references: - # https://chromium.googlesource.com/chromium/src/base/+/ - # master/base_paths_posix.cc - # We try our best guess by using which against the first - # cmdline arg (may return None). - cmdline = self.cmdline() - if cmdline: - return which(cmdline[0]) or "" - else: - return "" - - @wrap_exceptions - def cmdline(self): - if OPENBSD and self.pid == 0: - return [] # ...else it crashes - elif NETBSD: - # XXX - most of the times the underlying sysctl() call on Net - # and Open BSD returns a truncated string. - # Also /proc/pid/cmdline behaves the same so it looks - # like this is a kernel bug. - try: - return cext.proc_cmdline(self.pid) - except OSError as err: - if err.errno == errno.EINVAL: - if is_zombie(self.pid): - raise ZombieProcess(self.pid, self._name, self._ppid) - elif not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name, self._ppid) - else: - # XXX: this happens with unicode tests. It means the C - # routine is unable to decode invalid unicode chars. - return [] - else: - raise - else: - return cext.proc_cmdline(self.pid) - - @wrap_exceptions - def terminal(self): - tty_nr = self.oneshot()[kinfo_proc_map['ttynr']] - tmap = _psposix.get_terminal_map() - try: - return tmap[tty_nr] - except KeyError: - return None - - @wrap_exceptions - def ppid(self): - self._ppid = self.oneshot()[kinfo_proc_map['ppid']] - return self._ppid - - @wrap_exceptions - def uids(self): - rawtuple = self.oneshot() - return _common.puids( - rawtuple[kinfo_proc_map['real_uid']], - rawtuple[kinfo_proc_map['effective_uid']], - rawtuple[kinfo_proc_map['saved_uid']]) - - @wrap_exceptions - def gids(self): - rawtuple = self.oneshot() - return _common.pgids( - rawtuple[kinfo_proc_map['real_gid']], - rawtuple[kinfo_proc_map['effective_gid']], - rawtuple[kinfo_proc_map['saved_gid']]) - - @wrap_exceptions - def cpu_times(self): - rawtuple = self.oneshot() - return _common.pcputimes( - rawtuple[kinfo_proc_map['user_time']], - rawtuple[kinfo_proc_map['sys_time']], - rawtuple[kinfo_proc_map['ch_user_time']], - rawtuple[kinfo_proc_map['ch_sys_time']]) - - if FREEBSD: - @wrap_exceptions - def cpu_num(self): - return self.oneshot()[kinfo_proc_map['cpunum']] - - @wrap_exceptions - def memory_info(self): - rawtuple = self.oneshot() - return pmem( - rawtuple[kinfo_proc_map['rss']], - rawtuple[kinfo_proc_map['vms']], - rawtuple[kinfo_proc_map['memtext']], - rawtuple[kinfo_proc_map['memdata']], - rawtuple[kinfo_proc_map['memstack']]) - - memory_full_info = memory_info - - @wrap_exceptions - def create_time(self): - return self.oneshot()[kinfo_proc_map['create_time']] - - @wrap_exceptions - def num_threads(self): - if HAS_PROC_NUM_THREADS: - # FreeBSD - return cext.proc_num_threads(self.pid) - else: - return len(self.threads()) - - @wrap_exceptions - def num_ctx_switches(self): - rawtuple = self.oneshot() - return _common.pctxsw( - rawtuple[kinfo_proc_map['ctx_switches_vol']], - rawtuple[kinfo_proc_map['ctx_switches_unvol']]) - - @wrap_exceptions - def threads(self): - # Note: on OpenSBD this (/dev/mem) requires root access. - rawlist = cext.proc_threads(self.pid) - retlist = [] - for thread_id, utime, stime in rawlist: - ntuple = _common.pthread(thread_id, utime, stime) - retlist.append(ntuple) - if OPENBSD: - self._assert_alive() - return retlist - - @wrap_exceptions - def connections(self, kind='inet'): - if kind not in conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - - if NETBSD: - families, types = conn_tmap[kind] - ret = [] - rawlist = cext.net_connections(self.pid) - for item in rawlist: - fd, fam, type, laddr, raddr, status, pid = item - assert pid == self.pid - if fam in families and type in types: - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES) - ret.append(nt) - self._assert_alive() - return list(ret) - - families, types = conn_tmap[kind] - rawlist = cext.proc_connections(self.pid, families, types) - ret = [] - for item in rawlist: - fd, fam, type, laddr, raddr, status = item - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES) - ret.append(nt) - - if OPENBSD: - self._assert_alive() - - return ret - - @wrap_exceptions - def wait(self, timeout=None): - return _psposix.wait_pid(self.pid, timeout, self._name) - - @wrap_exceptions - def nice_get(self): - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def status(self): - code = self.oneshot()[kinfo_proc_map['status']] - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(code, '?') - - @wrap_exceptions - def io_counters(self): - rawtuple = self.oneshot() - return _common.pio( - rawtuple[kinfo_proc_map['read_io_count']], - rawtuple[kinfo_proc_map['write_io_count']], - -1, - -1) - - @wrap_exceptions - def cwd(self): - """Return process current working directory.""" - # sometimes we get an empty string, in which case we turn - # it into None - if OPENBSD and self.pid == 0: - return None # ...else it would raise EINVAL - elif NETBSD or HAS_PROC_OPEN_FILES: - # FreeBSD < 8 does not support functions based on - # kinfo_getfile() and kinfo_getvmmap() - return cext.proc_cwd(self.pid) or None - else: - raise NotImplementedError( - "supported only starting from FreeBSD 8" if - FREEBSD else "") - - nt_mmap_grouped = namedtuple( - 'mmap', 'path rss, private, ref_count, shadow_count') - nt_mmap_ext = namedtuple( - 'mmap', 'addr, perms path rss, private, ref_count, shadow_count') - - def _not_implemented(self): - raise NotImplementedError - - # FreeBSD < 8 does not support functions based on kinfo_getfile() - # and kinfo_getvmmap() - if HAS_PROC_OPEN_FILES: - @wrap_exceptions - def open_files(self): - """Return files opened by process as a list of namedtuples.""" - rawlist = cext.proc_open_files(self.pid) - return [_common.popenfile(path, fd) for path, fd in rawlist] - else: - open_files = _not_implemented - - # FreeBSD < 8 does not support functions based on kinfo_getfile() - # and kinfo_getvmmap() - if HAS_PROC_NUM_FDS: - @wrap_exceptions - def num_fds(self): - """Return the number of file descriptors opened by this process.""" - ret = cext.proc_num_fds(self.pid) - if NETBSD: - self._assert_alive() - return ret - else: - num_fds = _not_implemented - - # --- FreeBSD only APIs - - if FREEBSD: - - @wrap_exceptions - def cpu_affinity_get(self): - return cext.proc_cpu_affinity_get(self.pid) - - @wrap_exceptions - def cpu_affinity_set(self, cpus): - # Pre-emptively check if CPUs are valid because the C - # function has a weird behavior in case of invalid CPUs, - # see: https://github.com/giampaolo/psutil/issues/586 - allcpus = tuple(range(len(per_cpu_times()))) - for cpu in cpus: - if cpu not in allcpus: - raise ValueError("invalid CPU #%i (choose between %s)" - % (cpu, allcpus)) - try: - cext.proc_cpu_affinity_set(self.pid, cpus) - except OSError as err: - # 'man cpuset_setaffinity' about EDEADLK: - # <> - if err.errno in (errno.EINVAL, errno.EDEADLK): - for cpu in cpus: - if cpu not in allcpus: - raise ValueError( - "invalid CPU #%i (choose between %s)" % ( - cpu, allcpus)) - raise - - @wrap_exceptions - def memory_maps(self): - return cext.proc_memory_maps(self.pid) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/_pslinux.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/_pslinux.py deleted file mode 100644 index 9e32f25e7bf9..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/_pslinux.py +++ /dev/null @@ -1,2095 +0,0 @@ -# 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. - -"""Linux platform implementation.""" - -from __future__ import division - -import base64 -import collections -import errno -import functools -import glob -import os -import re -import socket -import struct -import sys -import traceback -import warnings -from collections import defaultdict -from collections import namedtuple - -from . import _common -from . import _psposix -from . import _psutil_linux as cext -from . import _psutil_posix as cext_posix -from ._common import AccessDenied -from ._common import debug -from ._common import decode -from ._common import get_procfs_path -from ._common import isfile_strict -from ._common import memoize -from ._common import memoize_when_activated -from ._common import NIC_DUPLEX_FULL -from ._common import NIC_DUPLEX_HALF -from ._common import NIC_DUPLEX_UNKNOWN -from ._common import NoSuchProcess -from ._common import open_binary -from ._common import open_text -from ._common import parse_environ_block -from ._common import path_exists_strict -from ._common import supports_ipv6 -from ._common import usage_percent -from ._common import ZombieProcess -from ._compat import b -from ._compat import basestring -from ._compat import FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - - -__extra__all__ = [ - # - 'PROCFS_PATH', - # io prio constants - "IOPRIO_CLASS_NONE", "IOPRIO_CLASS_RT", "IOPRIO_CLASS_BE", - "IOPRIO_CLASS_IDLE", - # connection status constants - "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", - "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", - "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", ] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -POWER_SUPPLY_PATH = "/sys/class/power_supply" -HAS_SMAPS = os.path.exists('/proc/%s/smaps' % os.getpid()) -HAS_PRLIMIT = hasattr(cext, "linux_prlimit") -HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_ioprio_get") -HAS_CPU_AFFINITY = hasattr(cext, "proc_cpu_affinity_get") -_DEFAULT = object() - -# RLIMIT_* constants, not guaranteed to be present on all kernels -if HAS_PRLIMIT: - for name in dir(cext): - if name.startswith('RLIM'): - __extra__all__.append(name) - -# Number of clock ticks per second -CLOCK_TICKS = os.sysconf("SC_CLK_TCK") -PAGESIZE = os.sysconf("SC_PAGE_SIZE") -BOOT_TIME = None # set later -# Used when reading "big" files, namely /proc/{pid}/smaps and /proc/net/*. -# On Python 2, using a buffer with open() for such files may result in a -# speedup, see: https://github.com/giampaolo/psutil/issues/708 -BIGFILE_BUFFERING = -1 if PY3 else 8192 -LITTLE_ENDIAN = sys.byteorder == 'little' - -# "man iostat" states that sectors are equivalent with blocks and have -# a size of 512 bytes. Despite this value can be queried at runtime -# via /sys/block/{DISK}/queue/hw_sector_size and results may vary -# between 1k, 2k, or 4k... 512 appears to be a magic constant used -# throughout Linux source code: -# * https://stackoverflow.com/a/38136179/376587 -# * https://lists.gt.net/linux/kernel/2241060 -# * https://github.com/giampaolo/psutil/issues/1305 -# * https://github.com/torvalds/linux/blob/ -# 4f671fe2f9523a1ea206f63fe60a7c7b3a56d5c7/include/linux/bio.h#L99 -# * https://lkml.org/lkml/2015/8/17/234 -DISK_SECTOR_SIZE = 512 - -if enum is None: - AF_LINK = socket.AF_PACKET -else: - AddressFamily = enum.IntEnum('AddressFamily', - {'AF_LINK': int(socket.AF_PACKET)}) - AF_LINK = AddressFamily.AF_LINK - -# ioprio_* constants http://linux.die.net/man/2/ioprio_get -if enum is None: - IOPRIO_CLASS_NONE = 0 - IOPRIO_CLASS_RT = 1 - IOPRIO_CLASS_BE = 2 - IOPRIO_CLASS_IDLE = 3 -else: - class IOPriority(enum.IntEnum): - IOPRIO_CLASS_NONE = 0 - IOPRIO_CLASS_RT = 1 - IOPRIO_CLASS_BE = 2 - IOPRIO_CLASS_IDLE = 3 - - globals().update(IOPriority.__members__) - -# See: -# https://github.com/torvalds/linux/blame/master/fs/proc/array.c -# ...and (TASK_* constants): -# https://github.com/torvalds/linux/blob/master/include/linux/sched.h -PROC_STATUSES = { - "R": _common.STATUS_RUNNING, - "S": _common.STATUS_SLEEPING, - "D": _common.STATUS_DISK_SLEEP, - "T": _common.STATUS_STOPPED, - "t": _common.STATUS_TRACING_STOP, - "Z": _common.STATUS_ZOMBIE, - "X": _common.STATUS_DEAD, - "x": _common.STATUS_DEAD, - "K": _common.STATUS_WAKE_KILL, - "W": _common.STATUS_WAKING, - "I": _common.STATUS_IDLE, - "P": _common.STATUS_PARKED, -} - -# https://github.com/torvalds/linux/blob/master/include/net/tcp_states.h -TCP_STATUSES = { - "01": _common.CONN_ESTABLISHED, - "02": _common.CONN_SYN_SENT, - "03": _common.CONN_SYN_RECV, - "04": _common.CONN_FIN_WAIT1, - "05": _common.CONN_FIN_WAIT2, - "06": _common.CONN_TIME_WAIT, - "07": _common.CONN_CLOSE, - "08": _common.CONN_CLOSE_WAIT, - "09": _common.CONN_LAST_ACK, - "0A": _common.CONN_LISTEN, - "0B": _common.CONN_CLOSING -} - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.virtual_memory() -svmem = namedtuple( - 'svmem', ['total', 'available', 'percent', 'used', 'free', - 'active', 'inactive', 'buffers', 'cached', 'shared', 'slab']) -# psutil.disk_io_counters() -sdiskio = namedtuple( - 'sdiskio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'read_time', 'write_time', - 'read_merged_count', 'write_merged_count', - 'busy_time']) -# psutil.Process().open_files() -popenfile = namedtuple( - 'popenfile', ['path', 'fd', 'position', 'mode', 'flags']) -# psutil.Process().memory_info() -pmem = namedtuple('pmem', 'rss vms shared text lib data dirty') -# psutil.Process().memory_full_info() -pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', 'pss', 'swap')) -# psutil.Process().memory_maps(grouped=True) -pmmap_grouped = namedtuple( - 'pmmap_grouped', - ['path', 'rss', 'size', 'pss', 'shared_clean', 'shared_dirty', - 'private_clean', 'private_dirty', 'referenced', 'anonymous', 'swap']) -# psutil.Process().memory_maps(grouped=False) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) -# psutil.Process.io_counters() -pio = namedtuple('pio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'read_chars', 'write_chars']) -# psutil.Process.cpu_times() -pcputimes = namedtuple('pcputimes', - ['user', 'system', 'children_user', 'children_system', - 'iowait']) - - -# ===================================================================== -# --- utils -# ===================================================================== - - -def readlink(path): - """Wrapper around os.readlink().""" - assert isinstance(path, basestring), path - path = os.readlink(path) - # readlink() might return paths containing null bytes ('\x00') - # resulting in "TypeError: must be encoded string without NULL - # bytes, not str" errors when the string is passed to other - # fs-related functions (os.*, open(), ...). - # Apparently everything after '\x00' is garbage (we can have - # ' (deleted)', 'new' and possibly others), see: - # https://github.com/giampaolo/psutil/issues/717 - path = path.split('\x00')[0] - # Certain paths have ' (deleted)' appended. Usually this is - # bogus as the file actually exists. Even if it doesn't we - # don't care. - if path.endswith(' (deleted)') and not path_exists_strict(path): - path = path[:-10] - return path - - -def file_flags_to_mode(flags): - """Convert file's open() flags into a readable string. - Used by Process.open_files(). - """ - modes_map = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'} - mode = modes_map[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)] - if flags & os.O_APPEND: - mode = mode.replace('w', 'a', 1) - mode = mode.replace('w+', 'r+') - # possible values: r, w, a, r+, a+ - return mode - - -def is_storage_device(name): - """Return True if the given name refers to a root device (e.g. - "sda", "nvme0n1") as opposed to a logical partition (e.g. "sda1", - "nvme0n1p1"). If name is a virtual device (e.g. "loop1", "ram") - return True. - """ - # Readapted from iostat source code, see: - # https://github.com/sysstat/sysstat/blob/ - # 97912938cd476645b267280069e83b1c8dc0e1c7/common.c#L208 - # Some devices may have a slash in their name (e.g. cciss/c0d0...). - name = name.replace('/', '!') - including_virtual = True - if including_virtual: - path = "/sys/block/%s" % name - else: - path = "/sys/block/%s/device" % name - return os.access(path, os.F_OK) - - -@memoize -def set_scputimes_ntuple(procfs_path): - """Set a namedtuple of variable fields depending on the CPU times - available on this Linux kernel version which may be: - (user, nice, system, idle, iowait, irq, softirq, [steal, [guest, - [guest_nice]]]) - Used by cpu_times() function. - """ - global scputimes - with open_binary('%s/stat' % procfs_path) as f: - values = f.readline().split()[1:] - fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq'] - vlen = len(values) - if vlen >= 8: - # Linux >= 2.6.11 - fields.append('steal') - if vlen >= 9: - # Linux >= 2.6.24 - fields.append('guest') - if vlen >= 10: - # Linux >= 3.2.0 - fields.append('guest_nice') - scputimes = namedtuple('scputimes', fields) - - -def cat(fname, fallback=_DEFAULT, binary=True): - """Return file content. - fallback: the value returned in case the file does not exist or - cannot be read - binary: whether to open the file in binary or text mode. - """ - try: - with open_binary(fname) if binary else open_text(fname) as f: - return f.read().strip() - except (IOError, OSError): - if fallback is not _DEFAULT: - return fallback - else: - raise - - -try: - set_scputimes_ntuple("/proc") -except Exception: - # Don't want to crash at import time. - traceback.print_exc() - scputimes = namedtuple('scputimes', 'user system idle')(0.0, 0.0, 0.0) - - -# ===================================================================== -# --- system memory -# ===================================================================== - - -def calculate_avail_vmem(mems): - """Fallback for kernels < 3.14 where /proc/meminfo does not provide - "MemAvailable:" column, see: - https://blog.famzah.net/2014/09/24/ - This code reimplements the algorithm outlined here: - https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ - commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 - - XXX: on recent kernels this calculation differs by ~1.5% than - "MemAvailable:" as it's calculated slightly differently, see: - https://gitlab.com/procps-ng/procps/issues/42 - https://github.com/famzah/linux-memavailable-procfs/issues/2 - It is still way more realistic than doing (free + cached) though. - """ - # Fallback for very old distros. According to - # https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ - # commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 - # ...long ago "avail" was calculated as (free + cached). - # We might fallback in such cases: - # "Active(file)" not available: 2.6.28 / Dec 2008 - # "Inactive(file)" not available: 2.6.28 / Dec 2008 - # "SReclaimable:" not available: 2.6.19 / Nov 2006 - # /proc/zoneinfo not available: 2.6.13 / Aug 2005 - free = mems[b'MemFree:'] - fallback = free + mems.get(b"Cached:", 0) - try: - lru_active_file = mems[b'Active(file):'] - lru_inactive_file = mems[b'Inactive(file):'] - slab_reclaimable = mems[b'SReclaimable:'] - except KeyError: - return fallback - try: - f = open_binary('%s/zoneinfo' % get_procfs_path()) - except IOError: - return fallback # kernel 2.6.13 - - watermark_low = 0 - with f: - for line in f: - line = line.strip() - if line.startswith(b'low'): - watermark_low += int(line.split()[1]) - watermark_low *= PAGESIZE - watermark_low = watermark_low - - avail = free - watermark_low - pagecache = lru_active_file + lru_inactive_file - pagecache -= min(pagecache / 2, watermark_low) - avail += pagecache - avail += slab_reclaimable - min(slab_reclaimable / 2.0, watermark_low) - return int(avail) - - -def virtual_memory(): - """Report virtual memory stats. - This implementation matches "free" and "vmstat -s" cmdline - utility values and procps-ng-3.3.12 source was used as a reference - (2016-09-18): - https://gitlab.com/procps-ng/procps/blob/ - 24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c - For reference, procps-ng-3.3.10 is the version available on Ubuntu - 16.04. - - Note about "available" memory: up until psutil 4.3 it was - calculated as "avail = (free + buffers + cached)". Now - "MemAvailable:" column (kernel 3.14) from /proc/meminfo is used as - it's more accurate. - That matches "available" column in newer versions of "free". - """ - missing_fields = [] - mems = {} - with open_binary('%s/meminfo' % get_procfs_path()) as f: - for line in f: - fields = line.split() - mems[fields[0]] = int(fields[1]) * 1024 - - # /proc doc states that the available fields in /proc/meminfo vary - # by architecture and compile options, but these 3 values are also - # returned by sysinfo(2); as such we assume they are always there. - total = mems[b'MemTotal:'] - free = mems[b'MemFree:'] - try: - buffers = mems[b'Buffers:'] - except KeyError: - # https://github.com/giampaolo/psutil/issues/1010 - buffers = 0 - missing_fields.append('buffers') - try: - cached = mems[b"Cached:"] - except KeyError: - cached = 0 - missing_fields.append('cached') - else: - # "free" cmdline utility sums reclaimable to cached. - # Older versions of procps used to add slab memory instead. - # This got changed in: - # https://gitlab.com/procps-ng/procps/commit/ - # 05d751c4f076a2f0118b914c5e51cfbb4762ad8e - cached += mems.get(b"SReclaimable:", 0) # since kernel 2.6.19 - - try: - shared = mems[b'Shmem:'] # since kernel 2.6.32 - except KeyError: - try: - shared = mems[b'MemShared:'] # kernels 2.4 - except KeyError: - shared = 0 - missing_fields.append('shared') - - try: - active = mems[b"Active:"] - except KeyError: - active = 0 - missing_fields.append('active') - - try: - inactive = mems[b"Inactive:"] - except KeyError: - try: - inactive = \ - mems[b"Inact_dirty:"] + \ - mems[b"Inact_clean:"] + \ - mems[b"Inact_laundry:"] - except KeyError: - inactive = 0 - missing_fields.append('inactive') - - try: - slab = mems[b"Slab:"] - except KeyError: - slab = 0 - - used = total - free - cached - buffers - if used < 0: - # May be symptomatic of running within a LCX container where such - # values will be dramatically distorted over those of the host. - used = total - free - - # - starting from 4.4.0 we match free's "available" column. - # Before 4.4.0 we calculated it as (free + buffers + cached) - # which matched htop. - # - free and htop available memory differs as per: - # http://askubuntu.com/a/369589 - # http://unix.stackexchange.com/a/65852/168884 - # - MemAvailable has been introduced in kernel 3.14 - try: - avail = mems[b'MemAvailable:'] - except KeyError: - avail = calculate_avail_vmem(mems) - - if avail < 0: - avail = 0 - missing_fields.append('available') - - # If avail is greater than total or our calculation overflows, - # that's symptomatic of running within a LCX container where such - # values will be dramatically distorted over those of the host. - # https://gitlab.com/procps-ng/procps/blob/ - # 24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c#L764 - if avail > total: - avail = free - - percent = usage_percent((total - avail), total, round_=1) - - # Warn about missing metrics which are set to 0. - if missing_fields: - msg = "%s memory stats couldn't be determined and %s set to 0" % ( - ", ".join(missing_fields), - "was" if len(missing_fields) == 1 else "were") - warnings.warn(msg, RuntimeWarning) - - return svmem(total, avail, percent, used, free, - active, inactive, buffers, cached, shared, slab) - - -def swap_memory(): - """Return swap memory metrics.""" - mems = {} - with open_binary('%s/meminfo' % get_procfs_path()) as f: - for line in f: - fields = line.split() - mems[fields[0]] = int(fields[1]) * 1024 - # We prefer /proc/meminfo over sysinfo() syscall so that - # psutil.PROCFS_PATH can be used in order to allow retrieval - # for linux containers, see: - # https://github.com/giampaolo/psutil/issues/1015 - try: - total = mems[b'SwapTotal:'] - free = mems[b'SwapFree:'] - except KeyError: - _, _, _, _, total, free, unit_multiplier = cext.linux_sysinfo() - total *= unit_multiplier - free *= unit_multiplier - - used = total - free - percent = usage_percent(used, total, round_=1) - # get pgin/pgouts - try: - f = open_binary("%s/vmstat" % get_procfs_path()) - except IOError as err: - # see https://github.com/giampaolo/psutil/issues/722 - msg = "'sin' and 'sout' swap memory stats couldn't " \ - "be determined and were set to 0 (%s)" % str(err) - warnings.warn(msg, RuntimeWarning) - sin = sout = 0 - else: - with f: - sin = sout = None - for line in f: - # values are expressed in 4 kilo bytes, we want - # bytes instead - if line.startswith(b'pswpin'): - sin = int(line.split(b' ')[1]) * 4 * 1024 - elif line.startswith(b'pswpout'): - sout = int(line.split(b' ')[1]) * 4 * 1024 - if sin is not None and sout is not None: - break - else: - # we might get here when dealing with exotic Linux - # flavors, see: - # https://github.com/giampaolo/psutil/issues/313 - msg = "'sin' and 'sout' swap memory stats couldn't " \ - "be determined and were set to 0" - warnings.warn(msg, RuntimeWarning) - sin = sout = 0 - return _common.sswap(total, used, free, percent, sin, sout) - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return a named tuple representing the following system-wide - CPU times: - (user, nice, system, idle, iowait, irq, softirq [steal, [guest, - [guest_nice]]]) - Last 3 fields may not be available on all Linux kernel versions. - """ - procfs_path = get_procfs_path() - set_scputimes_ntuple(procfs_path) - with open_binary('%s/stat' % procfs_path) as f: - values = f.readline().split() - fields = values[1:len(scputimes._fields) + 1] - fields = [float(x) / CLOCK_TICKS for x in fields] - return scputimes(*fields) - - -def per_cpu_times(): - """Return a list of namedtuple representing the CPU times - for every CPU available on the system. - """ - procfs_path = get_procfs_path() - set_scputimes_ntuple(procfs_path) - cpus = [] - with open_binary('%s/stat' % procfs_path) as f: - # get rid of the first line which refers to system wide CPU stats - f.readline() - for line in f: - if line.startswith(b'cpu'): - values = line.split() - fields = values[1:len(scputimes._fields) + 1] - fields = [float(x) / CLOCK_TICKS for x in fields] - entry = scputimes(*fields) - cpus.append(entry) - return cpus - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - try: - return os.sysconf("SC_NPROCESSORS_ONLN") - except ValueError: - # as a second fallback we try to parse /proc/cpuinfo - num = 0 - with open_binary('%s/cpuinfo' % get_procfs_path()) as f: - for line in f: - if line.lower().startswith(b'processor'): - num += 1 - - # unknown format (e.g. amrel/sparc architectures), see: - # https://github.com/giampaolo/psutil/issues/200 - # try to parse /proc/stat as a last resort - if num == 0: - search = re.compile(r'cpu\d') - with open_text('%s/stat' % get_procfs_path()) as f: - for line in f: - line = line.split(' ')[0] - if search.match(line): - num += 1 - - if num == 0: - # mimic os.cpu_count() - return None - return num - - -def cpu_count_physical(): - """Return the number of physical cores in the system.""" - # Method #1 - core_ids = set() - for path in glob.glob( - "/sys/devices/system/cpu/cpu[0-9]*/topology/core_id"): - with open_binary(path) as f: - core_ids.add(int(f.read())) - result = len(core_ids) - if result != 0: - return result - - # Method #2 - mapping = {} - current_info = {} - with open_binary('%s/cpuinfo' % get_procfs_path()) as f: - for line in f: - line = line.strip().lower() - if not line: - # new section - if (b'physical id' in current_info and - b'cpu cores' in current_info): - mapping[current_info[b'physical id']] = \ - current_info[b'cpu cores'] - current_info = {} - else: - # ongoing section - if (line.startswith(b'physical id') or - line.startswith(b'cpu cores')): - key, value = line.split(b'\t:', 1) - current_info[key] = int(value) - - result = sum(mapping.values()) - return result or None # mimic os.cpu_count() - - -def cpu_stats(): - """Return various CPU stats as a named tuple.""" - with open_binary('%s/stat' % get_procfs_path()) as f: - ctx_switches = None - interrupts = None - soft_interrupts = None - for line in f: - if line.startswith(b'ctxt'): - ctx_switches = int(line.split()[1]) - elif line.startswith(b'intr'): - interrupts = int(line.split()[1]) - elif line.startswith(b'softirq'): - soft_interrupts = int(line.split()[1]) - if ctx_switches is not None and soft_interrupts is not None \ - and interrupts is not None: - break - syscalls = 0 - return _common.scpustats( - ctx_switches, interrupts, soft_interrupts, syscalls) - - -if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or \ - os.path.exists("/sys/devices/system/cpu/cpu0/cpufreq"): - def cpu_freq(): - """Return frequency metrics for all CPUs. - Contrarily to other OSes, Linux updates these values in - real-time. - """ - def get_path(num): - for p in ("/sys/devices/system/cpu/cpufreq/policy%s" % num, - "/sys/devices/system/cpu/cpu%s/cpufreq" % num): - if os.path.exists(p): - return p - - ret = [] - for n in range(cpu_count_logical()): - path = get_path(n) - if not path: - continue - - pjoin = os.path.join - curr = cat(pjoin(path, "scaling_cur_freq"), fallback=None) - if curr is None: - # Likely an old RedHat, see: - # https://github.com/giampaolo/psutil/issues/1071 - curr = cat(pjoin(path, "cpuinfo_cur_freq"), fallback=None) - if curr is None: - raise NotImplementedError( - "can't find current frequency file") - curr = int(curr) / 1000 - max_ = int(cat(pjoin(path, "scaling_max_freq"))) / 1000 - min_ = int(cat(pjoin(path, "scaling_min_freq"))) / 1000 - ret.append(_common.scpufreq(curr, min_, max_)) - return ret - -elif os.path.exists("/proc/cpuinfo"): - def cpu_freq(): - """Alternate implementation using /proc/cpuinfo. - min and max frequencies are not available and are set to None. - """ - ret = [] - with open_binary('%s/cpuinfo' % get_procfs_path()) as f: - for line in f: - if line.lower().startswith(b'cpu mhz'): - key, value = line.split(b'\t:', 1) - ret.append(_common.scpufreq(float(value), 0., 0.)) - return ret - -else: - def cpu_freq(): - """Dummy implementation when none of the above files are present. - """ - return [] - - -# ===================================================================== -# --- network -# ===================================================================== - - -net_if_addrs = cext_posix.net_if_addrs - - -class _Ipv6UnsupportedError(Exception): - pass - - -class Connections: - """A wrapper on top of /proc/net/* files, retrieving per-process - and system-wide open connections (TCP, UDP, UNIX) similarly to - "netstat -an". - - Note: in case of UNIX sockets we're only able to determine the - local endpoint/path, not the one it's connected to. - According to [1] it would be possible but not easily. - - [1] http://serverfault.com/a/417946 - """ - - def __init__(self): - # The string represents the basename of the corresponding - # /proc/net/{proto_name} file. - tcp4 = ("tcp", socket.AF_INET, socket.SOCK_STREAM) - tcp6 = ("tcp6", socket.AF_INET6, socket.SOCK_STREAM) - udp4 = ("udp", socket.AF_INET, socket.SOCK_DGRAM) - udp6 = ("udp6", socket.AF_INET6, socket.SOCK_DGRAM) - unix = ("unix", socket.AF_UNIX, None) - self.tmap = { - "all": (tcp4, tcp6, udp4, udp6, unix), - "tcp": (tcp4, tcp6), - "tcp4": (tcp4,), - "tcp6": (tcp6,), - "udp": (udp4, udp6), - "udp4": (udp4,), - "udp6": (udp6,), - "unix": (unix,), - "inet": (tcp4, tcp6, udp4, udp6), - "inet4": (tcp4, udp4), - "inet6": (tcp6, udp6), - } - self._procfs_path = None - - def get_proc_inodes(self, pid): - inodes = defaultdict(list) - for fd in os.listdir("%s/%s/fd" % (self._procfs_path, pid)): - try: - inode = readlink("%s/%s/fd/%s" % (self._procfs_path, pid, fd)) - except (FileNotFoundError, ProcessLookupError): - # ENOENT == file which is gone in the meantime; - # os.stat('/proc/%s' % self.pid) will be done later - # to force NSP (if it's the case) - continue - except OSError as err: - if err.errno == errno.EINVAL: - # not a link - continue - raise - else: - if inode.startswith('socket:['): - # the process is using a socket - inode = inode[8:][:-1] - inodes[inode].append((pid, int(fd))) - return inodes - - def get_all_inodes(self): - inodes = {} - for pid in pids(): - try: - inodes.update(self.get_proc_inodes(pid)) - except (FileNotFoundError, ProcessLookupError, PermissionError): - # os.listdir() is gonna raise a lot of access denied - # exceptions in case of unprivileged user; that's fine - # as we'll just end up returning a connection with PID - # and fd set to None anyway. - # Both netstat -an and lsof does the same so it's - # unlikely we can do any better. - # ENOENT just means a PID disappeared on us. - continue - return inodes - - @staticmethod - def decode_address(addr, family): - """Accept an "ip:port" address as displayed in /proc/net/* - and convert it into a human readable form, like: - - "0500000A:0016" -> ("10.0.0.5", 22) - "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521) - - The IP address portion is a little or big endian four-byte - hexadecimal number; that is, the least significant byte is listed - first, so we need to reverse the order of the bytes to convert it - to an IP address. - The port is represented as a two-byte hexadecimal number. - - Reference: - http://linuxdevcenter.com/pub/a/linux/2000/11/16/LinuxAdmin.html - """ - ip, port = addr.split(':') - port = int(port, 16) - # this usually refers to a local socket in listen mode with - # no end-points connected - if not port: - return () - if PY3: - ip = ip.encode('ascii') - if family == socket.AF_INET: - # see: https://github.com/giampaolo/psutil/issues/201 - if LITTLE_ENDIAN: - ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1]) - else: - ip = socket.inet_ntop(family, base64.b16decode(ip)) - else: # IPv6 - # 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))) - ip = base64.b16decode(ip) - try: - # see: https://github.com/giampaolo/psutil/issues/201 - if LITTLE_ENDIAN: - ip = socket.inet_ntop( - socket.AF_INET6, - struct.pack('>4I', *struct.unpack('<4I', ip))) - else: - ip = socket.inet_ntop( - socket.AF_INET6, - struct.pack('<4I', *struct.unpack('<4I', ip))) - except ValueError: - # see: https://github.com/giampaolo/psutil/issues/623 - if not supports_ipv6(): - raise _Ipv6UnsupportedError - else: - raise - return _common.addr(ip, port) - - @staticmethod - def process_inet(file, family, type_, inodes, filter_pid=None): - """Parse /proc/net/tcp* and /proc/net/udp* files.""" - if file.endswith('6') and not os.path.exists(file): - # IPv6 not supported - return - with open_text(file, buffering=BIGFILE_BUFFERING) as f: - f.readline() # skip the first line - for lineno, line in enumerate(f, 1): - try: - _, laddr, raddr, status, _, _, _, _, _, inode = \ - line.split()[:10] - except ValueError: - raise RuntimeError( - "error while parsing %s; malformed line %s %r" % ( - file, lineno, line)) - if inode in inodes: - # # We assume inet sockets are unique, so we error - # # out if there are multiple references to the - # # same inode. We won't do this for UNIX sockets. - # if len(inodes[inode]) > 1 and family != socket.AF_UNIX: - # raise ValueError("ambiguos inode with multiple " - # "PIDs references") - pid, fd = inodes[inode][0] - else: - pid, fd = None, -1 - if filter_pid is not None and filter_pid != pid: - continue - else: - if type_ == socket.SOCK_STREAM: - status = TCP_STATUSES[status] - else: - status = _common.CONN_NONE - try: - laddr = Connections.decode_address(laddr, family) - raddr = Connections.decode_address(raddr, family) - except _Ipv6UnsupportedError: - continue - yield (fd, family, type_, laddr, raddr, status, pid) - - @staticmethod - def process_unix(file, family, inodes, filter_pid=None): - """Parse /proc/net/unix files.""" - with open_text(file, buffering=BIGFILE_BUFFERING) as f: - f.readline() # skip the first line - for line in f: - tokens = line.split() - try: - _, _, _, _, type_, _, inode = tokens[0:7] - except ValueError: - if ' ' not in line: - # see: https://github.com/giampaolo/psutil/issues/766 - continue - raise RuntimeError( - "error while parsing %s; malformed line %r" % ( - file, line)) - if inode in inodes: - # With UNIX sockets we can have a single inode - # referencing many file descriptors. - pairs = inodes[inode] - else: - pairs = [(None, -1)] - for pid, fd in pairs: - if filter_pid is not None and filter_pid != pid: - continue - else: - if len(tokens) == 8: - path = tokens[-1] - else: - path = "" - type_ = _common.socktype_to_enum(int(type_)) - # XXX: determining the remote endpoint of a - # UNIX socket on Linux is not possible, see: - # https://serverfault.com/questions/252723/ - raddr = "" - status = _common.CONN_NONE - yield (fd, family, type_, path, raddr, status, pid) - - def retrieve(self, kind, pid=None): - if kind not in self.tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in self.tmap]))) - self._procfs_path = get_procfs_path() - if pid is not None: - inodes = self.get_proc_inodes(pid) - if not inodes: - # no connections for this process - return [] - else: - inodes = self.get_all_inodes() - ret = set() - for proto_name, family, type_ in self.tmap[kind]: - path = "%s/net/%s" % (self._procfs_path, proto_name) - if family in (socket.AF_INET, socket.AF_INET6): - ls = self.process_inet( - path, family, type_, inodes, filter_pid=pid) - else: - ls = self.process_unix( - path, family, inodes, filter_pid=pid) - for fd, family, type_, laddr, raddr, status, bound_pid in ls: - if pid: - conn = _common.pconn(fd, family, type_, laddr, raddr, - status) - else: - conn = _common.sconn(fd, family, type_, laddr, raddr, - status, bound_pid) - ret.add(conn) - return list(ret) - - -_connections = Connections() - - -def net_connections(kind='inet'): - """Return system-wide open connections.""" - return _connections.retrieve(kind) - - -def net_io_counters(): - """Return network I/O statistics for every network interface - installed on the system as a dict of raw tuples. - """ - with open_text("%s/net/dev" % get_procfs_path()) as f: - lines = f.readlines() - retdict = {} - for line in lines[2:]: - colon = line.rfind(':') - assert colon > 0, repr(line) - name = line[:colon].strip() - fields = line[colon + 1:].strip().split() - - # in - (bytes_recv, - packets_recv, - errin, - dropin, - fifoin, # unused - framein, # unused - compressedin, # unused - multicastin, # unused - # out - bytes_sent, - packets_sent, - errout, - dropout, - fifoout, # unused - collisionsout, # unused - carrierout, # unused - compressedout) = map(int, fields) - - retdict[name] = (bytes_sent, bytes_recv, packets_sent, packets_recv, - errin, errout, dropin, dropout) - return retdict - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - duplex_map = {cext.DUPLEX_FULL: NIC_DUPLEX_FULL, - cext.DUPLEX_HALF: NIC_DUPLEX_HALF, - cext.DUPLEX_UNKNOWN: NIC_DUPLEX_UNKNOWN} - names = net_io_counters().keys() - ret = {} - for name in names: - try: - mtu = cext_posix.net_if_mtu(name) - isup = cext_posix.net_if_flags(name) - duplex, speed = cext.net_if_duplex_speed(name) - except OSError as err: - # https://github.com/giampaolo/psutil/issues/1279 - if err.errno != errno.ENODEV: - raise - else: - ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu) - return ret - - -# ===================================================================== -# --- disks -# ===================================================================== - - -disk_usage = _psposix.disk_usage - - -def disk_io_counters(perdisk=False): - """Return disk I/O statistics for every disk installed on the - system as a dict of raw tuples. - """ - def read_procfs(): - # OK, this is a bit confusing. The format of /proc/diskstats can - # have 3 variations. - # On Linux 2.4 each line has always 15 fields, e.g.: - # "3 0 8 hda 8 8 8 8 8 8 8 8 8 8 8" - # On Linux 2.6+ each line *usually* has 14 fields, and the disk - # name is in another position, like this: - # "3 0 hda 8 8 8 8 8 8 8 8 8 8 8" - # ...unless (Linux 2.6) the line refers to a partition instead - # of a disk, in which case the line has less fields (7): - # "3 1 hda1 8 8 8 8" - # 4.18+ has 4 fields added: - # "3 0 hda 8 8 8 8 8 8 8 8 8 8 8 0 0 0 0" - # 5.5 has 2 more fields. - # See: - # https://www.kernel.org/doc/Documentation/iostats.txt - # https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats - with open_text("%s/diskstats" % get_procfs_path()) as f: - lines = f.readlines() - for line in lines: - fields = line.split() - flen = len(fields) - if flen == 15: - # Linux 2.4 - name = fields[3] - reads = int(fields[2]) - (reads_merged, rbytes, rtime, writes, writes_merged, - wbytes, wtime, _, busy_time, _) = map(int, fields[4:14]) - elif flen == 14 or flen >= 18: - # Linux 2.6+, line referring to a disk - name = fields[2] - (reads, reads_merged, rbytes, rtime, writes, writes_merged, - wbytes, wtime, _, busy_time, _) = map(int, fields[3:14]) - elif flen == 7: - # Linux 2.6+, line referring to a partition - name = fields[2] - reads, rbytes, writes, wbytes = map(int, fields[3:]) - rtime = wtime = reads_merged = writes_merged = busy_time = 0 - else: - raise ValueError("not sure how to interpret line %r" % line) - yield (name, reads, writes, rbytes, wbytes, rtime, wtime, - reads_merged, writes_merged, busy_time) - - def read_sysfs(): - for block in os.listdir('/sys/block'): - for root, _, files in os.walk(os.path.join('/sys/block', block)): - if 'stat' not in files: - continue - with open_text(os.path.join(root, 'stat')) as f: - fields = f.read().strip().split() - name = os.path.basename(root) - (reads, reads_merged, rbytes, rtime, writes, writes_merged, - wbytes, wtime, _, busy_time) = map(int, fields[:10]) - yield (name, reads, writes, rbytes, wbytes, rtime, - wtime, reads_merged, writes_merged, busy_time) - - if os.path.exists('%s/diskstats' % get_procfs_path()): - gen = read_procfs() - elif os.path.exists('/sys/block'): - gen = read_sysfs() - else: - raise NotImplementedError( - "%s/diskstats nor /sys/block filesystem are available on this " - "system" % get_procfs_path()) - - retdict = {} - for entry in gen: - (name, reads, writes, rbytes, wbytes, rtime, wtime, reads_merged, - writes_merged, busy_time) = entry - if not perdisk and not is_storage_device(name): - # perdisk=False means we want to calculate totals so we skip - # partitions (e.g. 'sda1', 'nvme0n1p1') and only include - # base disk devices (e.g. 'sda', 'nvme0n1'). Base disks - # include a total of all their partitions + some extra size - # of their own: - # $ cat /proc/diskstats - # 259 0 sda 10485760 ... - # 259 1 sda1 5186039 ... - # 259 1 sda2 5082039 ... - # See: - # https://github.com/giampaolo/psutil/pull/1313 - continue - - rbytes *= DISK_SECTOR_SIZE - wbytes *= DISK_SECTOR_SIZE - retdict[name] = (reads, writes, rbytes, wbytes, rtime, wtime, - reads_merged, writes_merged, busy_time) - - return retdict - - -def disk_partitions(all=False): - """Return mounted disk partitions as a list of namedtuples.""" - fstypes = set() - procfs_path = get_procfs_path() - with open_text("%s/filesystems" % procfs_path) as f: - for line in f: - line = line.strip() - if not line.startswith("nodev"): - fstypes.add(line.strip()) - else: - # ignore all lines starting with "nodev" except "nodev zfs" - fstype = line.split("\t")[1] - if fstype == "zfs": - fstypes.add("zfs") - - # See: https://github.com/giampaolo/psutil/issues/1307 - if procfs_path == "/proc" and os.path.isfile('/etc/mtab'): - mounts_path = os.path.realpath("/etc/mtab") - else: - mounts_path = os.path.realpath("%s/self/mounts" % procfs_path) - - retlist = [] - partitions = cext.disk_partitions(mounts_path) - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - if device == '' or fstype not in fstypes: - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - - return retlist - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -def sensors_temperatures(): - """Return hardware (CPU and others) temperatures as a dict - including hardware name, label, current, max and critical - temperatures. - - Implementation notes: - - /sys/class/hwmon looks like the most recent interface to - retrieve this info, and this implementation relies on it - only (old distros will probably use something else) - - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon - - /sys/class/thermal/thermal_zone* is another one but it's more - difficult to parse - """ - ret = collections.defaultdict(list) - basenames = glob.glob('/sys/class/hwmon/hwmon*/temp*_*') - # CentOS has an intermediate /device directory: - # https://github.com/giampaolo/psutil/issues/971 - # https://github.com/nicolargo/glances/issues/1060 - basenames.extend(glob.glob('/sys/class/hwmon/hwmon*/device/temp*_*')) - basenames.extend(glob.glob( - '/sys/devices/platform/coretemp.*/hwmon/hwmon*/temp*_*')) - basenames = sorted(set([x.split('_')[0] for x in basenames])) - - for base in basenames: - try: - path = base + '_input' - current = float(cat(path)) / 1000.0 - path = os.path.join(os.path.dirname(base), 'name') - unit_name = cat(path, binary=False) - except (IOError, OSError, ValueError): - # A lot of things can go wrong here, so let's just skip the - # whole entry. Sure thing is Linux's /sys/class/hwmon really - # is a stinky broken mess. - # https://github.com/giampaolo/psutil/issues/1009 - # https://github.com/giampaolo/psutil/issues/1101 - # https://github.com/giampaolo/psutil/issues/1129 - # https://github.com/giampaolo/psutil/issues/1245 - # https://github.com/giampaolo/psutil/issues/1323 - continue - - high = cat(base + '_max', fallback=None) - critical = cat(base + '_crit', fallback=None) - label = cat(base + '_label', fallback='', binary=False) - - if high is not None: - try: - high = float(high) / 1000.0 - except ValueError: - high = None - if critical is not None: - try: - critical = float(critical) / 1000.0 - except ValueError: - critical = None - - ret[unit_name].append((label, current, high, critical)) - - # Indication that no sensors were detected in /sys/class/hwmon/ - if not basenames: - basenames = glob.glob('/sys/class/thermal/thermal_zone*') - basenames = sorted(set(basenames)) - - for base in basenames: - try: - path = os.path.join(base, 'temp') - current = float(cat(path)) / 1000.0 - path = os.path.join(base, 'type') - unit_name = cat(path, binary=False) - except (IOError, OSError, ValueError) as err: - debug("ignoring %r for file %r" % (err, path)) - continue - - trip_paths = glob.glob(base + '/trip_point*') - trip_points = set(['_'.join( - os.path.basename(p).split('_')[0:3]) for p in trip_paths]) - critical = None - high = None - for trip_point in trip_points: - path = os.path.join(base, trip_point + "_type") - trip_type = cat(path, fallback='', binary=False) - if trip_type == 'critical': - critical = cat(os.path.join(base, trip_point + "_temp"), - fallback=None) - elif trip_type == 'high': - high = cat(os.path.join(base, trip_point + "_temp"), - fallback=None) - - if high is not None: - try: - high = float(high) / 1000.0 - except ValueError: - high = None - if critical is not None: - try: - critical = float(critical) / 1000.0 - except ValueError: - critical = None - - ret[unit_name].append(('', current, high, critical)) - - return dict(ret) - - -def sensors_fans(): - """Return hardware fans info (for CPU and other peripherals) as a - dict including hardware label and current speed. - - Implementation notes: - - /sys/class/hwmon looks like the most recent interface to - retrieve this info, and this implementation relies on it - only (old distros will probably use something else) - - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon - """ - ret = collections.defaultdict(list) - basenames = glob.glob('/sys/class/hwmon/hwmon*/fan*_*') - if not basenames: - # CentOS has an intermediate /device directory: - # https://github.com/giampaolo/psutil/issues/971 - basenames = glob.glob('/sys/class/hwmon/hwmon*/device/fan*_*') - - basenames = sorted(set([x.split('_')[0] for x in basenames])) - for base in basenames: - try: - current = int(cat(base + '_input')) - except (IOError, OSError) as err: - warnings.warn("ignoring %r" % err, RuntimeWarning) - continue - unit_name = cat(os.path.join(os.path.dirname(base), 'name'), - binary=False) - label = cat(base + '_label', fallback='', binary=False) - ret[unit_name].append(_common.sfan(label, current)) - - return dict(ret) - - -def sensors_battery(): - """Return battery information. - Implementation note: it appears /sys/class/power_supply/BAT0/ - directory structure may vary and provide files with the same - meaning but under different names, see: - https://github.com/giampaolo/psutil/issues/966 - """ - null = object() - - def multi_cat(*paths): - """Attempt to read the content of multiple files which may - not exist. If none of them exist return None. - """ - for path in paths: - ret = cat(path, fallback=null) - if ret != null: - return int(ret) if ret.isdigit() else ret - return None - - bats = [x for x in os.listdir(POWER_SUPPLY_PATH) if x.startswith('BAT')] - if not bats: - return None - # Get the first available battery. Usually this is "BAT0", except - # some rare exceptions: - # https://github.com/giampaolo/psutil/issues/1238 - root = os.path.join(POWER_SUPPLY_PATH, sorted(bats)[0]) - - # Base metrics. - energy_now = multi_cat( - root + "/energy_now", - root + "/charge_now") - power_now = multi_cat( - root + "/power_now", - root + "/current_now") - energy_full = multi_cat( - root + "/energy_full", - root + "/charge_full") - if energy_now is None or power_now is None: - return None - - # Percent. If we have energy_full the percentage will be more - # accurate compared to reading /capacity file (float vs. int). - if energy_full is not None: - try: - percent = 100.0 * energy_now / energy_full - except ZeroDivisionError: - percent = 0.0 - else: - percent = int(cat(root + "/capacity", fallback=-1)) - if percent == -1: - return None - - # Is AC power cable plugged in? - # Note: AC0 is not always available and sometimes (e.g. CentOS7) - # it's called "AC". - power_plugged = None - online = multi_cat( - os.path.join(POWER_SUPPLY_PATH, "AC0/online"), - os.path.join(POWER_SUPPLY_PATH, "AC/online")) - if online is not None: - power_plugged = online == 1 - else: - status = cat(root + "/status", fallback="", binary=False).lower() - if status == "discharging": - power_plugged = False - elif status in ("charging", "full"): - power_plugged = True - - # Seconds left. - # Note to self: we may also calculate the charging ETA as per: - # https://github.com/thialfihar/dotfiles/blob/ - # 013937745fd9050c30146290e8f963d65c0179e6/bin/battery.py#L55 - if power_plugged: - secsleft = _common.POWER_TIME_UNLIMITED - else: - try: - secsleft = int(energy_now / power_now * 3600) - except ZeroDivisionError: - secsleft = _common.POWER_TIME_UNKNOWN - - return _common.sbattery(percent, secsleft, power_plugged) - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, tty, hostname, tstamp, user_process, pid = item - # note: the underlying C function includes entries about - # system boot, run level and others. We might want - # to use them in the future. - if not user_process: - continue - if hostname in (':0.0', ':0'): - hostname = 'localhost' - nt = _common.suser(user, tty or None, hostname, tstamp, pid) - retlist.append(nt) - return retlist - - -def boot_time(): - """Return the system boot time expressed in seconds since the epoch.""" - global BOOT_TIME - path = '%s/stat' % get_procfs_path() - with open_binary(path) as f: - for line in f: - if line.startswith(b'btime'): - ret = float(line.strip().split()[1]) - BOOT_TIME = ret - return ret - raise RuntimeError( - "line 'btime' not found in %s" % path) - - -# ===================================================================== -# --- processes -# ===================================================================== - - -def pids(): - """Returns a list of PIDs currently running on the system.""" - return [int(x) for x in os.listdir(b(get_procfs_path())) if x.isdigit()] - - -def pid_exists(pid): - """Check for the existence of a unix PID. Linux TIDs are not - supported (always return False). - """ - if not _psposix.pid_exists(pid): - return False - else: - # Linux's apparently does not distinguish between PIDs and TIDs - # (thread IDs). - # listdir("/proc") won't show any TID (only PIDs) but - # os.stat("/proc/{tid}") will succeed if {tid} exists. - # os.kill() can also be passed a TID. This is quite confusing. - # In here we want to enforce this distinction and support PIDs - # only, see: - # https://github.com/giampaolo/psutil/issues/687 - try: - # Note: already checked that this is faster than using a - # regular expr. Also (a lot) faster than doing - # 'return pid in pids()' - path = "%s/%s/status" % (get_procfs_path(), pid) - with open_binary(path) as f: - for line in f: - if line.startswith(b"Tgid:"): - tgid = int(line.split()[1]) - # If tgid and pid are the same then we're - # dealing with a process PID. - return tgid == pid - raise ValueError("'Tgid' line not found in %s" % path) - except (EnvironmentError, ValueError): - return pid in pids() - - -def ppid_map(): - """Obtain a {pid: ppid, ...} dict for all running processes in - one shot. Used to speed up Process.children(). - """ - ret = {} - procfs_path = get_procfs_path() - for pid in pids(): - try: - with open_binary("%s/%s/stat" % (procfs_path, pid)) as f: - data = f.read() - except (FileNotFoundError, ProcessLookupError): - # Note: we should be able to access /stat for all processes - # aka it's unlikely we'll bump into EPERM, which is good. - pass - else: - rpar = data.rfind(b')') - dset = data[rpar + 2:].split() - ppid = int(dset[1]) - ret[pid] = ppid - return ret - - -def wrap_exceptions(fun): - """Decorator which translates bare OSError and IOError exceptions - into NoSuchProcess and AccessDenied. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except ProcessLookupError: - raise NoSuchProcess(self.pid, self._name) - except FileNotFoundError: - if not os.path.exists("%s/%s" % (self._procfs_path, self.pid)): - raise NoSuchProcess(self.pid, self._name) - # Note: zombies will keep existing under /proc until they're - # gone so there's no way to distinguish them in here. - raise - return wrapper - - -class Process(object): - """Linux process implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - self._procfs_path = get_procfs_path() - - def _assert_alive(self): - """Raise NSP if the process disappeared on us.""" - # For those C function who do not raise NSP, possibly returning - # incorrect or incomplete result. - os.stat('%s/%s' % (self._procfs_path, self.pid)) - - @wrap_exceptions - @memoize_when_activated - def _parse_stat_file(self): - """Parse /proc/{pid}/stat file and return a dict with various - process info. - Using "man proc" as a reference: where "man proc" refers to - position N always substract 3 (e.g ppid position 4 in - 'man proc' == position 1 in here). - The return value is cached in case oneshot() ctx manager is - in use. - """ - with open_binary("%s/%s/stat" % (self._procfs_path, self.pid)) as f: - data = f.read() - # Process name is between parentheses. It can contain spaces and - # other parentheses. This is taken into account by looking for - # the first occurrence of "(" and the last occurence of ")". - rpar = data.rfind(b')') - name = data[data.find(b'(') + 1:rpar] - fields = data[rpar + 2:].split() - - ret = {} - ret['name'] = name - ret['status'] = fields[0] - ret['ppid'] = fields[1] - ret['ttynr'] = fields[4] - ret['utime'] = fields[11] - ret['stime'] = fields[12] - ret['children_utime'] = fields[13] - ret['children_stime'] = fields[14] - ret['create_time'] = fields[19] - ret['cpu_num'] = fields[36] - ret['blkio_ticks'] = fields[39] # aka 'delayacct_blkio_ticks' - - return ret - - @wrap_exceptions - @memoize_when_activated - def _read_status_file(self): - """Read /proc/{pid}/stat file and return its content. - The return value is cached in case oneshot() ctx manager is - in use. - """ - with open_binary("%s/%s/status" % (self._procfs_path, self.pid)) as f: - return f.read() - - @wrap_exceptions - @memoize_when_activated - def _read_smaps_file(self): - with open_binary("%s/%s/smaps" % (self._procfs_path, self.pid), - buffering=BIGFILE_BUFFERING) as f: - return f.read().strip() - - def oneshot_enter(self): - self._parse_stat_file.cache_activate(self) - self._read_status_file.cache_activate(self) - self._read_smaps_file.cache_activate(self) - - def oneshot_exit(self): - self._parse_stat_file.cache_deactivate(self) - self._read_status_file.cache_deactivate(self) - self._read_smaps_file.cache_deactivate(self) - - @wrap_exceptions - def name(self): - name = self._parse_stat_file()['name'] - if PY3: - name = decode(name) - # XXX - gets changed later and probably needs refactoring - return name - - def exe(self): - try: - return readlink("%s/%s/exe" % (self._procfs_path, self.pid)) - except (FileNotFoundError, ProcessLookupError): - # no such file error; might be raised also if the - # path actually exists for system processes with - # low pids (about 0-20) - if os.path.lexists("%s/%s" % (self._procfs_path, self.pid)): - return "" - else: - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - - @wrap_exceptions - def cmdline(self): - with open_text("%s/%s/cmdline" % (self._procfs_path, self.pid)) as f: - data = f.read() - if not data: - # may happen in case of zombie process - return [] - # 'man proc' states that args are separated by null bytes '\0' - # and last char is supposed to be a null byte. Nevertheless - # some processes may change their cmdline after being started - # (via setproctitle() or similar), they are usually not - # compliant with this rule and use spaces instead. Google - # Chrome process is an example. See: - # https://github.com/giampaolo/psutil/issues/1179 - sep = '\x00' if data.endswith('\x00') else ' ' - if data.endswith(sep): - data = data[:-1] - cmdline = data.split(sep) - # Sometimes last char is a null byte '\0' but the args are - # separated by spaces, see: https://github.com/giampaolo/psutil/ - # issues/1179#issuecomment-552984549 - if sep == '\x00' and len(cmdline) == 1 and ' ' in data: - cmdline = data.split(' ') - return cmdline - - @wrap_exceptions - def environ(self): - with open_text("%s/%s/environ" % (self._procfs_path, self.pid)) as f: - data = f.read() - return parse_environ_block(data) - - @wrap_exceptions - def terminal(self): - tty_nr = int(self._parse_stat_file()['ttynr']) - tmap = _psposix.get_terminal_map() - try: - return tmap[tty_nr] - except KeyError: - return None - - # May not be available on old kernels. - if os.path.exists('/proc/%s/io' % os.getpid()): - @wrap_exceptions - def io_counters(self): - fname = "%s/%s/io" % (self._procfs_path, self.pid) - fields = {} - with open_binary(fname) as f: - for line in f: - # https://github.com/giampaolo/psutil/issues/1004 - line = line.strip() - if line: - try: - name, value = line.split(b': ') - except ValueError: - # https://github.com/giampaolo/psutil/issues/1004 - continue - else: - fields[name] = int(value) - if not fields: - raise RuntimeError("%s file was empty" % fname) - try: - return pio( - fields[b'syscr'], # read syscalls - fields[b'syscw'], # write syscalls - fields[b'read_bytes'], # read bytes - fields[b'write_bytes'], # write bytes - fields[b'rchar'], # read chars - fields[b'wchar'], # write chars - ) - except KeyError as err: - raise ValueError("%r field was not found in %s; found fields " - "are %r" % (err[0], fname, fields)) - - @wrap_exceptions - def cpu_times(self): - values = self._parse_stat_file() - utime = float(values['utime']) / CLOCK_TICKS - stime = float(values['stime']) / CLOCK_TICKS - children_utime = float(values['children_utime']) / CLOCK_TICKS - children_stime = float(values['children_stime']) / CLOCK_TICKS - iowait = float(values['blkio_ticks']) / CLOCK_TICKS - return pcputimes(utime, stime, children_utime, children_stime, iowait) - - @wrap_exceptions - def cpu_num(self): - """What CPU the process is on.""" - return int(self._parse_stat_file()['cpu_num']) - - @wrap_exceptions - def wait(self, timeout=None): - return _psposix.wait_pid(self.pid, timeout, self._name) - - @wrap_exceptions - def create_time(self): - ctime = float(self._parse_stat_file()['create_time']) - # According to documentation, starttime is in field 21 and the - # unit is jiffies (clock ticks). - # We first divide it for clock ticks and then add uptime returning - # seconds since the epoch, in UTC. - # Also use cached value if available. - bt = BOOT_TIME or boot_time() - return (ctime / CLOCK_TICKS) + bt - - @wrap_exceptions - def memory_info(self): - # ============================================================ - # | FIELD | DESCRIPTION | AKA | TOP | - # ============================================================ - # | rss | resident set size | | RES | - # | vms | total program size | size | VIRT | - # | shared | shared pages (from shared mappings) | | SHR | - # | text | text ('code') | trs | CODE | - # | lib | library (unused in Linux 2.6) | lrs | | - # | data | data + stack | drs | DATA | - # | dirty | dirty pages (unused in Linux 2.6) | dt | | - # ============================================================ - with open_binary("%s/%s/statm" % (self._procfs_path, self.pid)) as f: - vms, rss, shared, text, lib, data, dirty = \ - [int(x) * PAGESIZE for x in f.readline().split()[:7]] - return pmem(rss, vms, shared, text, lib, data, dirty) - - # /proc/pid/smaps does not exist on kernels < 2.6.14 or if - # CONFIG_MMU kernel configuration option is not enabled. - if HAS_SMAPS: - - @wrap_exceptions - def memory_full_info( - self, - # Gets Private_Clean, Private_Dirty, Private_Hugetlb. - _private_re=re.compile(br"\nPrivate.*:\s+(\d+)"), - _pss_re=re.compile(br"\nPss\:\s+(\d+)"), - _swap_re=re.compile(br"\nSwap\:\s+(\d+)")): - basic_mem = self.memory_info() - # Note: using 3 regexes is faster than reading the file - # line by line. - # XXX: on Python 3 the 2 regexes are 30% slower than on - # Python 2 though. Figure out why. - # - # You might be tempted to calculate USS by subtracting - # the "shared" value from the "resident" value in - # /proc//statm. But at least on Linux, statm's "shared" - # value actually counts pages backed by files, which has - # little to do with whether the pages are actually shared. - # /proc/self/smaps on the other hand appears to give us the - # correct information. - smaps_data = self._read_smaps_file() - # Note: smaps file can be empty for certain processes. - # The code below will not crash though and will result to 0. - uss = sum(map(int, _private_re.findall(smaps_data))) * 1024 - pss = sum(map(int, _pss_re.findall(smaps_data))) * 1024 - swap = sum(map(int, _swap_re.findall(smaps_data))) * 1024 - return pfullmem(*basic_mem + (uss, pss, swap)) - - else: - memory_full_info = memory_info - - if HAS_SMAPS: - - @wrap_exceptions - def memory_maps(self): - """Return process's mapped memory regions as a list of named - tuples. Fields are explained in 'man proc'; here is an updated - (Apr 2012) version: http://goo.gl/fmebo - - /proc/{PID}/smaps does not exist on kernels < 2.6.14 or if - CONFIG_MMU kernel configuration option is not enabled. - """ - def get_blocks(lines, current_block): - data = {} - for line in lines: - fields = line.split(None, 5) - if not fields[0].endswith(b':'): - # new block section - yield (current_block.pop(), data) - current_block.append(line) - else: - try: - data[fields[0]] = int(fields[1]) * 1024 - except ValueError: - if fields[0].startswith(b'VmFlags:'): - # see issue #369 - continue - else: - raise ValueError("don't know how to inte" - "rpret line %r" % line) - yield (current_block.pop(), data) - - data = self._read_smaps_file() - # Note: smaps file can be empty for certain processes. - if not data: - return [] - lines = data.split(b'\n') - ls = [] - first_line = lines.pop(0) - current_block = [first_line] - for header, data in get_blocks(lines, current_block): - hfields = header.split(None, 5) - try: - addr, perms, offset, dev, inode, path = hfields - except ValueError: - addr, perms, offset, dev, inode, path = \ - hfields + [''] - if not path: - path = '[anon]' - else: - if PY3: - path = decode(path) - path = path.strip() - if (path.endswith(' (deleted)') and not - path_exists_strict(path)): - path = path[:-10] - ls.append(( - decode(addr), decode(perms), path, - data.get(b'Rss:', 0), - data.get(b'Size:', 0), - data.get(b'Pss:', 0), - data.get(b'Shared_Clean:', 0), - data.get(b'Shared_Dirty:', 0), - data.get(b'Private_Clean:', 0), - data.get(b'Private_Dirty:', 0), - data.get(b'Referenced:', 0), - data.get(b'Anonymous:', 0), - data.get(b'Swap:', 0) - )) - return ls - - @wrap_exceptions - def cwd(self): - try: - return readlink("%s/%s/cwd" % (self._procfs_path, self.pid)) - except (FileNotFoundError, ProcessLookupError): - # https://github.com/giampaolo/psutil/issues/986 - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - - @wrap_exceptions - def num_ctx_switches(self, - _ctxsw_re=re.compile(br'ctxt_switches:\t(\d+)')): - data = self._read_status_file() - ctxsw = _ctxsw_re.findall(data) - if not ctxsw: - raise NotImplementedError( - "'voluntary_ctxt_switches' and 'nonvoluntary_ctxt_switches'" - "lines were not found in %s/%s/status; the kernel is " - "probably older than 2.6.23" % ( - self._procfs_path, self.pid)) - else: - return _common.pctxsw(int(ctxsw[0]), int(ctxsw[1])) - - @wrap_exceptions - def num_threads(self, _num_threads_re=re.compile(br'Threads:\t(\d+)')): - # Note: on Python 3 using a re is faster than iterating over file - # line by line. On Python 2 is the exact opposite, and iterating - # over a file on Python 3 is slower than on Python 2. - data = self._read_status_file() - return int(_num_threads_re.findall(data)[0]) - - @wrap_exceptions - def threads(self): - thread_ids = os.listdir("%s/%s/task" % (self._procfs_path, self.pid)) - thread_ids.sort() - retlist = [] - hit_enoent = False - for thread_id in thread_ids: - fname = "%s/%s/task/%s/stat" % ( - self._procfs_path, self.pid, thread_id) - try: - with open_binary(fname) as f: - st = f.read().strip() - except FileNotFoundError: - # no such file or directory; it means thread - # disappeared on us - hit_enoent = True - continue - # ignore the first two values ("pid (exe)") - st = st[st.find(b')') + 2:] - values = st.split(b' ') - utime = float(values[11]) / CLOCK_TICKS - stime = float(values[12]) / CLOCK_TICKS - ntuple = _common.pthread(int(thread_id), utime, stime) - retlist.append(ntuple) - if hit_enoent: - self._assert_alive() - return retlist - - @wrap_exceptions - def nice_get(self): - # with open_text('%s/%s/stat' % (self._procfs_path, self.pid)) as f: - # data = f.read() - # return int(data.split()[18]) - - # Use C implementation - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - return cext_posix.setpriority(self.pid, value) - - # starting from CentOS 6. - if HAS_CPU_AFFINITY: - - @wrap_exceptions - def cpu_affinity_get(self): - return cext.proc_cpu_affinity_get(self.pid) - - def _get_eligible_cpus( - self, _re=re.compile(br"Cpus_allowed_list:\t(\d+)-(\d+)")): - # See: https://github.com/giampaolo/psutil/issues/956 - data = self._read_status_file() - match = _re.findall(data) - if match: - return list(range(int(match[0][0]), int(match[0][1]) + 1)) - else: - return list(range(len(per_cpu_times()))) - - @wrap_exceptions - def cpu_affinity_set(self, cpus): - try: - cext.proc_cpu_affinity_set(self.pid, cpus) - except (OSError, ValueError) as err: - if isinstance(err, ValueError) or err.errno == errno.EINVAL: - eligible_cpus = self._get_eligible_cpus() - all_cpus = tuple(range(len(per_cpu_times()))) - for cpu in cpus: - if cpu not in all_cpus: - raise ValueError( - "invalid CPU number %r; choose between %s" % ( - cpu, eligible_cpus)) - if cpu not in eligible_cpus: - raise ValueError( - "CPU number %r is not eligible; choose " - "between %s" % (cpu, eligible_cpus)) - raise - - # only starting from kernel 2.6.13 - if HAS_PROC_IO_PRIORITY: - - @wrap_exceptions - def ionice_get(self): - ioclass, value = cext.proc_ioprio_get(self.pid) - if enum is not None: - ioclass = IOPriority(ioclass) - return _common.pionice(ioclass, value) - - @wrap_exceptions - def ionice_set(self, ioclass, value): - if value is None: - value = 0 - if value and ioclass in (IOPRIO_CLASS_IDLE, IOPRIO_CLASS_NONE): - raise ValueError("%r ioclass accepts no value" % ioclass) - if value < 0 or value > 7: - raise ValueError("value not in 0-7 range") - return cext.proc_ioprio_set(self.pid, ioclass, value) - - if HAS_PRLIMIT: - - @wrap_exceptions - def rlimit(self, resource, limits=None): - # If pid is 0 prlimit() applies to the calling process and - # we don't want that. We should never get here though as - # PID 0 is not supported on Linux. - if self.pid == 0: - raise ValueError("can't use prlimit() against PID 0 process") - try: - if limits is None: - # get - return cext.linux_prlimit(self.pid, resource) - else: - # set - if len(limits) != 2: - raise ValueError( - "second argument must be a (soft, hard) tuple, " - "got %s" % repr(limits)) - soft, hard = limits - cext.linux_prlimit(self.pid, resource, soft, hard) - except OSError as err: - if err.errno == errno.ENOSYS and pid_exists(self.pid): - # I saw this happening on Travis: - # https://travis-ci.org/giampaolo/psutil/jobs/51368273 - raise ZombieProcess(self.pid, self._name, self._ppid) - else: - raise - - @wrap_exceptions - def status(self): - letter = self._parse_stat_file()['status'] - if PY3: - letter = letter.decode() - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(letter, '?') - - @wrap_exceptions - def open_files(self): - retlist = [] - files = os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)) - hit_enoent = False - for fd in files: - file = "%s/%s/fd/%s" % (self._procfs_path, self.pid, fd) - try: - path = readlink(file) - except (FileNotFoundError, ProcessLookupError): - # ENOENT == file which is gone in the meantime - hit_enoent = True - continue - except OSError as err: - if err.errno == errno.EINVAL: - # not a link - continue - raise - else: - # If path is not an absolute there's no way to tell - # whether it's a regular file or not, so we skip it. - # A regular file is always supposed to be have an - # absolute path though. - if path.startswith('/') and isfile_strict(path): - # Get file position and flags. - file = "%s/%s/fdinfo/%s" % ( - self._procfs_path, self.pid, fd) - try: - with open_binary(file) as f: - pos = int(f.readline().split()[1]) - flags = int(f.readline().split()[1], 8) - except FileNotFoundError: - # fd gone in the meantime; process may - # still be alive - hit_enoent = True - else: - mode = file_flags_to_mode(flags) - ntuple = popenfile( - path, int(fd), int(pos), mode, flags) - retlist.append(ntuple) - if hit_enoent: - self._assert_alive() - return retlist - - @wrap_exceptions - def connections(self, kind='inet'): - ret = _connections.retrieve(kind, self.pid) - self._assert_alive() - return ret - - @wrap_exceptions - def num_fds(self): - return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))) - - @wrap_exceptions - def ppid(self): - return int(self._parse_stat_file()['ppid']) - - @wrap_exceptions - def uids(self, _uids_re=re.compile(br'Uid:\t(\d+)\t(\d+)\t(\d+)')): - data = self._read_status_file() - real, effective, saved = _uids_re.findall(data)[0] - return _common.puids(int(real), int(effective), int(saved)) - - @wrap_exceptions - def gids(self, _gids_re=re.compile(br'Gid:\t(\d+)\t(\d+)\t(\d+)')): - data = self._read_status_file() - real, effective, saved = _gids_re.findall(data)[0] - return _common.pgids(int(real), int(effective), int(saved)) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/_psosx.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/_psosx.py deleted file mode 100644 index e4296495c45b..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/_psosx.py +++ /dev/null @@ -1,564 +0,0 @@ -# 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. - -"""macOS platform implementation.""" - -import contextlib -import errno -import functools -import os -from collections import namedtuple - -from . import _common -from . import _psposix -from . import _psutil_osx as cext -from . import _psutil_posix as cext_posix -from ._common import AccessDenied -from ._common import conn_tmap -from ._common import conn_to_ntuple -from ._common import isfile_strict -from ._common import memoize_when_activated -from ._common import NoSuchProcess -from ._common import parse_environ_block -from ._common import usage_percent -from ._common import ZombieProcess -from ._compat import PermissionError -from ._compat import ProcessLookupError - - -__extra__all__ = [] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -PAGESIZE = os.sysconf("SC_PAGE_SIZE") -AF_LINK = cext_posix.AF_LINK - -TCP_STATUSES = { - cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, - cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, - cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV, - cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, - cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, - cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.TCPS_CLOSED: _common.CONN_CLOSE, - cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, - cext.TCPS_LISTEN: _common.CONN_LISTEN, - cext.TCPS_CLOSING: _common.CONN_CLOSING, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -PROC_STATUSES = { - cext.SIDL: _common.STATUS_IDLE, - cext.SRUN: _common.STATUS_RUNNING, - cext.SSLEEP: _common.STATUS_SLEEPING, - cext.SSTOP: _common.STATUS_STOPPED, - cext.SZOMB: _common.STATUS_ZOMBIE, -} - -kinfo_proc_map = dict( - ppid=0, - ruid=1, - euid=2, - suid=3, - rgid=4, - egid=5, - sgid=6, - ttynr=7, - ctime=8, - status=9, - name=10, -) - -pidtaskinfo_map = dict( - cpuutime=0, - cpustime=1, - rss=2, - vms=3, - pfaults=4, - pageins=5, - numthreads=6, - volctxsw=7, -) - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.cpu_times() -scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle']) -# psutil.virtual_memory() -svmem = namedtuple( - 'svmem', ['total', 'available', 'percent', 'used', 'free', - 'active', 'inactive', 'wired']) -# psutil.Process.memory_info() -pmem = namedtuple('pmem', ['rss', 'vms', 'pfaults', 'pageins']) -# psutil.Process.memory_full_info() -pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', )) - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - """System virtual memory as a namedtuple.""" - total, active, inactive, wired, free, speculative = cext.virtual_mem() - # This is how Zabbix calculate avail and used mem: - # https://github.com/zabbix/zabbix/blob/trunk/src/libs/zbxsysinfo/ - # osx/memory.c - # Also see: https://github.com/giampaolo/psutil/issues/1277 - avail = inactive + free - used = active + wired - # This is NOT how Zabbix calculates free mem but it matches "free" - # cmdline utility. - free -= speculative - percent = usage_percent((total - avail), total, round_=1) - return svmem(total, avail, percent, used, free, - active, inactive, wired) - - -def swap_memory(): - """Swap system memory as a (total, used, free, sin, sout) tuple.""" - total, used, free, sin, sout = cext.swap_mem() - percent = usage_percent(used, total, round_=1) - return _common.sswap(total, used, free, percent, sin, sout) - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return system CPU times as a namedtuple.""" - user, nice, system, idle = cext.cpu_times() - return scputimes(user, nice, system, idle) - - -def per_cpu_times(): - """Return system CPU times as a named tuple""" - ret = [] - for cpu_t in cext.per_cpu_times(): - user, nice, system, idle = cpu_t - item = scputimes(user, nice, system, idle) - ret.append(item) - return ret - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - return cext.cpu_count_logical() - - -def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" - return cext.cpu_count_phys() - - -def cpu_stats(): - ctx_switches, interrupts, soft_interrupts, syscalls, traps = \ - cext.cpu_stats() - return _common.scpustats( - ctx_switches, interrupts, soft_interrupts, syscalls) - - -def cpu_freq(): - """Return CPU frequency. - On macOS per-cpu frequency is not supported. - Also, the returned frequency never changes, see: - https://arstechnica.com/civis/viewtopic.php?f=19&t=465002 - """ - curr, min_, max_ = cext.cpu_freq() - return [_common.scpufreq(curr, min_, max_)] - - -# ===================================================================== -# --- disks -# ===================================================================== - - -disk_usage = _psposix.disk_usage -disk_io_counters = cext.disk_io_counters - - -def disk_partitions(all=False): - """Return mounted disk partitions as a list of namedtuples.""" - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - if not os.path.isabs(device) or not os.path.exists(device): - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -def sensors_battery(): - """Return battery information.""" - try: - percent, minsleft, power_plugged = cext.sensors_battery() - except NotImplementedError: - # no power source - return None according to interface - return None - power_plugged = power_plugged == 1 - if power_plugged: - secsleft = _common.POWER_TIME_UNLIMITED - elif minsleft == -1: - secsleft = _common.POWER_TIME_UNKNOWN - else: - secsleft = minsleft * 60 - return _common.sbattery(percent, secsleft, power_plugged) - - -# ===================================================================== -# --- network -# ===================================================================== - - -net_io_counters = cext.net_io_counters -net_if_addrs = cext_posix.net_if_addrs - - -def net_connections(kind='inet'): - """System-wide network connections.""" - # Note: on macOS this will fail with AccessDenied unless - # the process is owned by root. - ret = [] - for pid in pids(): - try: - cons = Process(pid).connections(kind) - except NoSuchProcess: - continue - else: - if cons: - for c in cons: - c = list(c) + [pid] - ret.append(_common.sconn(*c)) - return ret - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - names = net_io_counters().keys() - ret = {} - for name in names: - try: - mtu = cext_posix.net_if_mtu(name) - isup = cext_posix.net_if_flags(name) - duplex, speed = cext_posix.net_if_duplex_speed(name) - except OSError as err: - # https://github.com/giampaolo/psutil/issues/1279 - if err.errno != errno.ENODEV: - raise - else: - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, tty, hostname, tstamp, pid = item - if tty == '~': - continue # reboot or shutdown - if not tstamp: - continue - nt = _common.suser(user, tty or None, hostname or None, tstamp, pid) - retlist.append(nt) - return retlist - - -# ===================================================================== -# --- processes -# ===================================================================== - - -def pids(): - ls = cext.pids() - if 0 not in ls: - # On certain macOS versions pids() C doesn't return PID 0 but - # "ps" does and the process is querable via sysctl(): - # https://travis-ci.org/giampaolo/psutil/jobs/309619941 - try: - Process(0).create_time() - ls.insert(0, 0) - except NoSuchProcess: - pass - except AccessDenied: - ls.insert(0, 0) - return ls - - -pid_exists = _psposix.pid_exists - - -def wrap_exceptions(fun): - """Decorator which translates bare OSError exceptions into - NoSuchProcess and AccessDenied. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except ProcessLookupError: - raise NoSuchProcess(self.pid, self._name) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except cext.ZombieProcessError: - raise ZombieProcess(self.pid, self._name, self._ppid) - return wrapper - - -@contextlib.contextmanager -def catch_zombie(proc): - """There are some poor C APIs which incorrectly raise ESRCH when - the process is still alive or it's a zombie, or even RuntimeError - (those who don't set errno). This is here in order to solve: - https://github.com/giampaolo/psutil/issues/1044 - """ - try: - yield - except (OSError, RuntimeError) as err: - if isinstance(err, RuntimeError) or err.errno == errno.ESRCH: - try: - # status() is not supposed to lie and correctly detect - # zombies so if it raises ESRCH it's true. - status = proc.status() - except NoSuchProcess: - raise err - else: - if status == _common.STATUS_ZOMBIE: - raise ZombieProcess(proc.pid, proc._name, proc._ppid) - else: - raise AccessDenied(proc.pid, proc._name) - else: - raise - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - @wrap_exceptions - @memoize_when_activated - def _get_kinfo_proc(self): - # Note: should work with all PIDs without permission issues. - ret = cext.proc_kinfo_oneshot(self.pid) - assert len(ret) == len(kinfo_proc_map) - return ret - - @wrap_exceptions - @memoize_when_activated - def _get_pidtaskinfo(self): - # Note: should work for PIDs owned by user only. - with catch_zombie(self): - ret = cext.proc_pidtaskinfo_oneshot(self.pid) - assert len(ret) == len(pidtaskinfo_map) - return ret - - def oneshot_enter(self): - self._get_kinfo_proc.cache_activate(self) - self._get_pidtaskinfo.cache_activate(self) - - def oneshot_exit(self): - self._get_kinfo_proc.cache_deactivate(self) - self._get_pidtaskinfo.cache_deactivate(self) - - @wrap_exceptions - def name(self): - name = self._get_kinfo_proc()[kinfo_proc_map['name']] - return name if name is not None else cext.proc_name(self.pid) - - @wrap_exceptions - def exe(self): - with catch_zombie(self): - return cext.proc_exe(self.pid) - - @wrap_exceptions - def cmdline(self): - with catch_zombie(self): - return cext.proc_cmdline(self.pid) - - @wrap_exceptions - def environ(self): - with catch_zombie(self): - return parse_environ_block(cext.proc_environ(self.pid)) - - @wrap_exceptions - def ppid(self): - self._ppid = self._get_kinfo_proc()[kinfo_proc_map['ppid']] - return self._ppid - - @wrap_exceptions - def cwd(self): - with catch_zombie(self): - return cext.proc_cwd(self.pid) - - @wrap_exceptions - def uids(self): - rawtuple = self._get_kinfo_proc() - return _common.puids( - rawtuple[kinfo_proc_map['ruid']], - rawtuple[kinfo_proc_map['euid']], - rawtuple[kinfo_proc_map['suid']]) - - @wrap_exceptions - def gids(self): - rawtuple = self._get_kinfo_proc() - return _common.puids( - rawtuple[kinfo_proc_map['rgid']], - rawtuple[kinfo_proc_map['egid']], - rawtuple[kinfo_proc_map['sgid']]) - - @wrap_exceptions - def terminal(self): - tty_nr = self._get_kinfo_proc()[kinfo_proc_map['ttynr']] - tmap = _psposix.get_terminal_map() - try: - return tmap[tty_nr] - except KeyError: - return None - - @wrap_exceptions - def memory_info(self): - rawtuple = self._get_pidtaskinfo() - return pmem( - rawtuple[pidtaskinfo_map['rss']], - rawtuple[pidtaskinfo_map['vms']], - rawtuple[pidtaskinfo_map['pfaults']], - rawtuple[pidtaskinfo_map['pageins']], - ) - - @wrap_exceptions - def memory_full_info(self): - basic_mem = self.memory_info() - uss = cext.proc_memory_uss(self.pid) - return pfullmem(*basic_mem + (uss, )) - - @wrap_exceptions - def cpu_times(self): - rawtuple = self._get_pidtaskinfo() - return _common.pcputimes( - rawtuple[pidtaskinfo_map['cpuutime']], - rawtuple[pidtaskinfo_map['cpustime']], - # children user / system times are not retrievable (set to 0) - 0.0, 0.0) - - @wrap_exceptions - def create_time(self): - return self._get_kinfo_proc()[kinfo_proc_map['ctime']] - - @wrap_exceptions - def num_ctx_switches(self): - # Unvoluntary value seems not to be available; - # getrusage() numbers seems to confirm this theory. - # We set it to 0. - vol = self._get_pidtaskinfo()[pidtaskinfo_map['volctxsw']] - return _common.pctxsw(vol, 0) - - @wrap_exceptions - def num_threads(self): - return self._get_pidtaskinfo()[pidtaskinfo_map['numthreads']] - - @wrap_exceptions - def open_files(self): - if self.pid == 0: - return [] - files = [] - with catch_zombie(self): - rawlist = cext.proc_open_files(self.pid) - for path, fd in rawlist: - if isfile_strict(path): - ntuple = _common.popenfile(path, fd) - files.append(ntuple) - return files - - @wrap_exceptions - def connections(self, kind='inet'): - if kind not in conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - families, types = conn_tmap[kind] - with catch_zombie(self): - rawlist = cext.proc_connections(self.pid, families, types) - ret = [] - for item in rawlist: - fd, fam, type, laddr, raddr, status = item - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES) - ret.append(nt) - return ret - - @wrap_exceptions - def num_fds(self): - if self.pid == 0: - return 0 - with catch_zombie(self): - return cext.proc_num_fds(self.pid) - - @wrap_exceptions - def wait(self, timeout=None): - return _psposix.wait_pid(self.pid, timeout, self._name) - - @wrap_exceptions - def nice_get(self): - with catch_zombie(self): - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - with catch_zombie(self): - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def status(self): - code = self._get_kinfo_proc()[kinfo_proc_map['status']] - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(code, '?') - - @wrap_exceptions - def threads(self): - rawlist = cext.proc_threads(self.pid) - retlist = [] - for thread_id, utime, stime in rawlist: - ntuple = _common.pthread(thread_id, utime, stime) - retlist.append(ntuple) - return retlist diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/_psposix.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/_psposix.py deleted file mode 100644 index 88213ef8b641..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/_psposix.py +++ /dev/null @@ -1,175 +0,0 @@ -# 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 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 - - -__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 <> 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 - - -def wait_pid(pid, timeout=None, proc_name=None): - """Wait for process with pid 'pid' to terminate and return its - exit status code as an integer. - - If pid is not a children of os.getpid() (current process) just - waits until the process disappears and return None. - - If pid does not exist at all return None immediately. - - Raise TimeoutExpired on timeout expired. - """ - def check_timeout(delay): - if timeout is not None: - if timer() >= stop_at: - raise TimeoutExpired(timeout, pid=pid, name=proc_name) - time.sleep(delay) - return min(delay * 2, 0.04) - - timer = getattr(time, 'monotonic', time.time) - if timeout is not None: - def waitcall(): - return os.waitpid(pid, os.WNOHANG) - stop_at = timer() + timeout - else: - def waitcall(): - return os.waitpid(pid, 0) - - delay = 0.0001 - while True: - try: - retpid, status = waitcall() - except InterruptedError: - delay = check_timeout(delay) - 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 True: - if pid_exists(pid): - delay = check_timeout(delay) - else: - return - else: - if retpid == 0: - # WNOHANG was used, pid is still running - delay = check_timeout(delay) - continue - # process exited due to a signal; return the integer of - # that signal - if os.WIFSIGNALED(status): - return -os.WTERMSIG(status) - # process exited using exit(2) system call; return the - # integer exit(2) system call has been called with - elif os.WIFEXITED(status): - return os.WEXITSTATUS(status) - 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 diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/_pssunos.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/_pssunos.py deleted file mode 100644 index 62362b89c631..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/_pssunos.py +++ /dev/null @@ -1,725 +0,0 @@ -# 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. - -"""Sun OS Solaris platform implementation.""" - -import errno -import functools -import os -import socket -import subprocess -import sys -from collections import namedtuple -from socket import AF_INET - -from . import _common -from . import _psposix -from . import _psutil_posix as cext_posix -from . import _psutil_sunos as cext -from ._common import AccessDenied -from ._common import AF_INET6 -from ._common import debug -from ._common import get_procfs_path -from ._common import isfile_strict -from ._common import memoize_when_activated -from ._common import NoSuchProcess -from ._common import sockfam_to_enum -from ._common import socktype_to_enum -from ._common import usage_percent -from ._common import ZombieProcess -from ._compat import b -from ._compat import FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 - - -__extra__all__ = ["CONN_IDLE", "CONN_BOUND", "PROCFS_PATH"] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -PAGE_SIZE = os.sysconf('SC_PAGE_SIZE') -AF_LINK = cext_posix.AF_LINK -IS_64_BIT = sys.maxsize > 2**32 - -CONN_IDLE = "IDLE" -CONN_BOUND = "BOUND" - -PROC_STATUSES = { - cext.SSLEEP: _common.STATUS_SLEEPING, - cext.SRUN: _common.STATUS_RUNNING, - cext.SZOMB: _common.STATUS_ZOMBIE, - cext.SSTOP: _common.STATUS_STOPPED, - cext.SIDL: _common.STATUS_IDLE, - cext.SONPROC: _common.STATUS_RUNNING, # same as run - cext.SWAIT: _common.STATUS_WAITING, -} - -TCP_STATUSES = { - cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, - cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, - cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV, - cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, - cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, - cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.TCPS_CLOSED: _common.CONN_CLOSE, - cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, - cext.TCPS_LISTEN: _common.CONN_LISTEN, - cext.TCPS_CLOSING: _common.CONN_CLOSING, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, - cext.TCPS_IDLE: CONN_IDLE, # sunos specific - cext.TCPS_BOUND: CONN_BOUND, # sunos specific -} - -proc_info_map = dict( - ppid=0, - rss=1, - vms=2, - create_time=3, - nice=4, - num_threads=5, - status=6, - ttynr=7, - uid=8, - euid=9, - gid=10, - egid=11) - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.cpu_times() -scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait']) -# psutil.cpu_times(percpu=True) -pcputimes = namedtuple('pcputimes', - ['user', 'system', 'children_user', 'children_system']) -# psutil.virtual_memory() -svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) -# psutil.Process.memory_info() -pmem = namedtuple('pmem', ['rss', 'vms']) -pfullmem = pmem -# psutil.Process.memory_maps(grouped=True) -pmmap_grouped = namedtuple('pmmap_grouped', - ['path', 'rss', 'anonymous', 'locked']) -# psutil.Process.memory_maps(grouped=False) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - """Report virtual memory metrics.""" - # we could have done this with kstat, but IMHO this is good enough - total = os.sysconf('SC_PHYS_PAGES') * PAGE_SIZE - # note: there's no difference on Solaris - free = avail = os.sysconf('SC_AVPHYS_PAGES') * PAGE_SIZE - used = total - free - percent = usage_percent(used, total, round_=1) - return svmem(total, avail, percent, used, free) - - -def swap_memory(): - """Report swap memory metrics.""" - sin, sout = cext.swap_mem() - # XXX - # we are supposed to get total/free by doing so: - # http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/ - # usr/src/cmd/swap/swap.c - # ...nevertheless I can't manage to obtain the same numbers as 'swap' - # cmdline utility, so let's parse its output (sigh!) - p = subprocess.Popen(['/usr/bin/env', 'PATH=/usr/sbin:/sbin:%s' % - os.environ['PATH'], 'swap', '-l'], - stdout=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout = stdout.decode(sys.stdout.encoding) - if p.returncode != 0: - raise RuntimeError("'swap -l' failed (retcode=%s)" % p.returncode) - - lines = stdout.strip().split('\n')[1:] - if not lines: - raise RuntimeError('no swap device(s) configured') - total = free = 0 - for line in lines: - line = line.split() - t, f = line[-2:] - total += int(int(t) * 512) - free += int(int(f) * 512) - used = total - free - percent = usage_percent(used, total, round_=1) - return _common.sswap(total, used, free, percent, - sin * PAGE_SIZE, sout * PAGE_SIZE) - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return system-wide CPU times as a named tuple""" - ret = cext.per_cpu_times() - return scputimes(*[sum(x) for x in zip(*ret)]) - - -def per_cpu_times(): - """Return system per-CPU times as a list of named tuples""" - ret = cext.per_cpu_times() - return [scputimes(*x) for x in ret] - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - try: - return os.sysconf("SC_NPROCESSORS_ONLN") - except ValueError: - # mimic os.cpu_count() behavior - return None - - -def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" - return cext.cpu_count_phys() - - -def cpu_stats(): - """Return various CPU stats as a named tuple.""" - ctx_switches, interrupts, syscalls, traps = cext.cpu_stats() - soft_interrupts = 0 - return _common.scpustats(ctx_switches, interrupts, soft_interrupts, - syscalls) - - -# ===================================================================== -# --- disks -# ===================================================================== - - -disk_io_counters = cext.disk_io_counters -disk_usage = _psposix.disk_usage - - -def disk_partitions(all=False): - """Return system disk partitions.""" - # TODO - the filtering logic should be better checked so that - # it tries to reflect 'df' as much as possible - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - # Differently from, say, Linux, we don't have a list of - # common fs types so the best we can do, AFAIK, is to - # filter by filesystem having a total size > 0. - try: - if not disk_usage(mountpoint).total: - continue - except OSError as err: - # https://github.com/giampaolo/psutil/issues/1674 - debug("skipping %r: %r" % (mountpoint, err)) - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -# ===================================================================== -# --- network -# ===================================================================== - - -net_io_counters = cext.net_io_counters -net_if_addrs = cext_posix.net_if_addrs - - -def net_connections(kind, _pid=-1): - """Return socket connections. If pid == -1 return system-wide - connections (as opposed to connections opened by one process only). - Only INET sockets are returned (UNIX are not). - """ - cmap = _common.conn_tmap.copy() - if _pid == -1: - cmap.pop('unix', 0) - if kind not in cmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in cmap]))) - families, types = _common.conn_tmap[kind] - rawlist = cext.net_connections(_pid) - ret = set() - for item in rawlist: - fd, fam, type_, laddr, raddr, status, pid = item - if fam not in families: - continue - if type_ not in types: - continue - # TODO: refactor and use _common.conn_to_ntuple. - if fam in (AF_INET, AF_INET6): - if laddr: - laddr = _common.addr(*laddr) - if raddr: - raddr = _common.addr(*raddr) - status = TCP_STATUSES[status] - fam = sockfam_to_enum(fam) - type_ = socktype_to_enum(type_) - if _pid == -1: - nt = _common.sconn(fd, fam, type_, laddr, raddr, status, pid) - else: - nt = _common.pconn(fd, fam, type_, laddr, raddr, status) - ret.add(nt) - return list(ret) - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - ret = cext.net_if_stats() - for name, items in ret.items(): - isup, duplex, speed, mtu = items - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - localhost = (':0.0', ':0') - for item in rawlist: - user, tty, hostname, tstamp, user_process, pid = item - # note: the underlying C function includes entries about - # system boot, run level and others. We might want - # to use them in the future. - if not user_process: - continue - if hostname in localhost: - hostname = 'localhost' - nt = _common.suser(user, tty, hostname, tstamp, pid) - retlist.append(nt) - return retlist - - -# ===================================================================== -# --- processes -# ===================================================================== - - -def pids(): - """Returns a list of PIDs currently running on the system.""" - return [int(x) for x in os.listdir(b(get_procfs_path())) if x.isdigit()] - - -def pid_exists(pid): - """Check for the existence of a unix pid.""" - return _psposix.pid_exists(pid) - - -def wrap_exceptions(fun): - """Call callable into a try/except clause and translate ENOENT, - EACCES and EPERM in NoSuchProcess or AccessDenied exceptions. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except (FileNotFoundError, ProcessLookupError): - # ENOENT (no such file or directory) gets raised on open(). - # ESRCH (no such process) can get raised on read() if - # process is gone in meantime. - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except OSError: - if self.pid == 0: - if 0 in pids(): - raise AccessDenied(self.pid, self._name) - else: - raise - raise - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - self._procfs_path = get_procfs_path() - - def _assert_alive(self): - """Raise NSP if the process disappeared on us.""" - # For those C function who do not raise NSP, possibly returning - # incorrect or incomplete result. - os.stat('%s/%s' % (self._procfs_path, self.pid)) - - def oneshot_enter(self): - self._proc_name_and_args.cache_activate(self) - self._proc_basic_info.cache_activate(self) - self._proc_cred.cache_activate(self) - - def oneshot_exit(self): - self._proc_name_and_args.cache_deactivate(self) - self._proc_basic_info.cache_deactivate(self) - self._proc_cred.cache_deactivate(self) - - @wrap_exceptions - @memoize_when_activated - def _proc_name_and_args(self): - return cext.proc_name_and_args(self.pid, self._procfs_path) - - @wrap_exceptions - @memoize_when_activated - def _proc_basic_info(self): - if self.pid == 0 and not \ - os.path.exists('%s/%s/psinfo' % (self._procfs_path, self.pid)): - raise AccessDenied(self.pid) - ret = cext.proc_basic_info(self.pid, self._procfs_path) - assert len(ret) == len(proc_info_map) - return ret - - @wrap_exceptions - @memoize_when_activated - def _proc_cred(self): - return cext.proc_cred(self.pid, self._procfs_path) - - @wrap_exceptions - def name(self): - # note: max len == 15 - return self._proc_name_and_args()[0] - - @wrap_exceptions - def exe(self): - try: - return os.readlink( - "%s/%s/path/a.out" % (self._procfs_path, self.pid)) - except OSError: - pass # continue and guess the exe name from the cmdline - # Will be guessed later from cmdline but we want to explicitly - # invoke cmdline here in order to get an AccessDenied - # exception if the user has not enough privileges. - self.cmdline() - return "" - - @wrap_exceptions - def cmdline(self): - return self._proc_name_and_args()[1].split(' ') - - @wrap_exceptions - def environ(self): - return cext.proc_environ(self.pid, self._procfs_path) - - @wrap_exceptions - def create_time(self): - return self._proc_basic_info()[proc_info_map['create_time']] - - @wrap_exceptions - def num_threads(self): - return self._proc_basic_info()[proc_info_map['num_threads']] - - @wrap_exceptions - def nice_get(self): - # Note #1: getpriority(3) doesn't work for realtime processes. - # Psinfo is what ps uses, see: - # https://github.com/giampaolo/psutil/issues/1194 - return self._proc_basic_info()[proc_info_map['nice']] - - @wrap_exceptions - def nice_set(self, value): - if self.pid in (2, 3): - # Special case PIDs: internally setpriority(3) return ESRCH - # (no such process), no matter what. - # The process actually exists though, as it has a name, - # creation time, etc. - raise AccessDenied(self.pid, self._name) - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def ppid(self): - self._ppid = self._proc_basic_info()[proc_info_map['ppid']] - return self._ppid - - @wrap_exceptions - def uids(self): - try: - real, effective, saved, _, _, _ = self._proc_cred() - except AccessDenied: - real = self._proc_basic_info()[proc_info_map['uid']] - effective = self._proc_basic_info()[proc_info_map['euid']] - saved = None - return _common.puids(real, effective, saved) - - @wrap_exceptions - def gids(self): - try: - _, _, _, real, effective, saved = self._proc_cred() - except AccessDenied: - real = self._proc_basic_info()[proc_info_map['gid']] - effective = self._proc_basic_info()[proc_info_map['egid']] - saved = None - return _common.puids(real, effective, saved) - - @wrap_exceptions - def cpu_times(self): - try: - times = cext.proc_cpu_times(self.pid, self._procfs_path) - except OSError as err: - if err.errno == errno.EOVERFLOW and not IS_64_BIT: - # We may get here if we attempt to query a 64bit process - # with a 32bit python. - # Error originates from read() and also tools like "cat" - # fail in the same way (!). - # Since there simply is no way to determine CPU times we - # return 0.0 as a fallback. See: - # https://github.com/giampaolo/psutil/issues/857 - times = (0.0, 0.0, 0.0, 0.0) - else: - raise - return _common.pcputimes(*times) - - @wrap_exceptions - def cpu_num(self): - return cext.proc_cpu_num(self.pid, self._procfs_path) - - @wrap_exceptions - def terminal(self): - procfs_path = self._procfs_path - hit_enoent = False - tty = wrap_exceptions( - self._proc_basic_info()[proc_info_map['ttynr']]) - if tty != cext.PRNODEV: - for x in (0, 1, 2, 255): - try: - return os.readlink( - '%s/%d/path/%d' % (procfs_path, self.pid, x)) - except FileNotFoundError: - hit_enoent = True - continue - if hit_enoent: - self._assert_alive() - - @wrap_exceptions - def cwd(self): - # /proc/PID/path/cwd may not be resolved by readlink() even if - # it exists (ls shows it). If that's the case and the process - # is still alive return None (we can return None also on BSD). - # Reference: http://goo.gl/55XgO - procfs_path = self._procfs_path - try: - return os.readlink("%s/%s/path/cwd" % (procfs_path, self.pid)) - except FileNotFoundError: - os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD - return None - - @wrap_exceptions - def memory_info(self): - ret = self._proc_basic_info() - rss = ret[proc_info_map['rss']] * 1024 - vms = ret[proc_info_map['vms']] * 1024 - return pmem(rss, vms) - - memory_full_info = memory_info - - @wrap_exceptions - def status(self): - code = self._proc_basic_info()[proc_info_map['status']] - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(code, '?') - - @wrap_exceptions - def threads(self): - procfs_path = self._procfs_path - ret = [] - tids = os.listdir('%s/%d/lwp' % (procfs_path, self.pid)) - hit_enoent = False - for tid in tids: - tid = int(tid) - try: - utime, stime = cext.query_process_thread( - self.pid, tid, procfs_path) - except EnvironmentError as err: - if err.errno == errno.EOVERFLOW and not IS_64_BIT: - # We may get here if we attempt to query a 64bit process - # with a 32bit python. - # Error originates from read() and also tools like "cat" - # fail in the same way (!). - # Since there simply is no way to determine CPU times we - # return 0.0 as a fallback. See: - # https://github.com/giampaolo/psutil/issues/857 - continue - # ENOENT == thread gone in meantime - if err.errno == errno.ENOENT: - hit_enoent = True - continue - raise - else: - nt = _common.pthread(tid, utime, stime) - ret.append(nt) - if hit_enoent: - self._assert_alive() - return ret - - @wrap_exceptions - def open_files(self): - retlist = [] - hit_enoent = False - procfs_path = self._procfs_path - pathdir = '%s/%d/path' % (procfs_path, self.pid) - for fd in os.listdir('%s/%d/fd' % (procfs_path, self.pid)): - path = os.path.join(pathdir, fd) - if os.path.islink(path): - try: - file = os.readlink(path) - except FileNotFoundError: - hit_enoent = True - continue - else: - if isfile_strict(file): - retlist.append(_common.popenfile(file, int(fd))) - if hit_enoent: - self._assert_alive() - return retlist - - def _get_unix_sockets(self, pid): - """Get UNIX sockets used by process by parsing 'pfiles' output.""" - # TODO: rewrite this in C (...but the damn netstat source code - # does not include this part! Argh!!) - cmd = "pfiles %s" % pid - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout, stderr = [x.decode(sys.stdout.encoding) - for x in (stdout, stderr)] - if p.returncode != 0: - if 'permission denied' in stderr.lower(): - raise AccessDenied(self.pid, self._name) - if 'no such process' in stderr.lower(): - raise NoSuchProcess(self.pid, self._name) - raise RuntimeError("%r command error\n%s" % (cmd, stderr)) - - lines = stdout.split('\n')[2:] - for i, line in enumerate(lines): - line = line.lstrip() - if line.startswith('sockname: AF_UNIX'): - path = line.split(' ', 2)[2] - type = lines[i - 2].strip() - if type == 'SOCK_STREAM': - type = socket.SOCK_STREAM - elif type == 'SOCK_DGRAM': - type = socket.SOCK_DGRAM - else: - type = -1 - yield (-1, socket.AF_UNIX, type, path, "", _common.CONN_NONE) - - @wrap_exceptions - def connections(self, kind='inet'): - ret = net_connections(kind, _pid=self.pid) - # The underlying C implementation retrieves all OS connections - # and filters them by PID. At this point we can't tell whether - # an empty list means there were no connections for process or - # process is no longer active so we force NSP in case the PID - # is no longer there. - if not ret: - # will raise NSP if process is gone - os.stat('%s/%s' % (self._procfs_path, self.pid)) - - # UNIX sockets - if kind in ('all', 'unix'): - ret.extend([_common.pconn(*conn) for conn in - self._get_unix_sockets(self.pid)]) - return ret - - nt_mmap_grouped = namedtuple('mmap', 'path rss anon locked') - nt_mmap_ext = namedtuple('mmap', 'addr perms path rss anon locked') - - @wrap_exceptions - def memory_maps(self): - def toaddr(start, end): - return '%s-%s' % (hex(start)[2:].strip('L'), - hex(end)[2:].strip('L')) - - procfs_path = self._procfs_path - retlist = [] - try: - rawlist = cext.proc_memory_maps(self.pid, procfs_path) - except OSError as err: - if err.errno == errno.EOVERFLOW and not IS_64_BIT: - # We may get here if we attempt to query a 64bit process - # with a 32bit python. - # Error originates from read() and also tools like "cat" - # fail in the same way (!). - # Since there simply is no way to determine CPU times we - # return 0.0 as a fallback. See: - # https://github.com/giampaolo/psutil/issues/857 - return [] - else: - raise - hit_enoent = False - for item in rawlist: - addr, addrsize, perm, name, rss, anon, locked = item - addr = toaddr(addr, addrsize) - if not name.startswith('['): - try: - name = os.readlink( - '%s/%s/path/%s' % (procfs_path, self.pid, name)) - except OSError as err: - if err.errno == errno.ENOENT: - # sometimes the link may not be resolved by - # readlink() even if it exists (ls shows it). - # If that's the case we just return the - # unresolved link path. - # This seems an incosistency with /proc similar - # to: http://goo.gl/55XgO - name = '%s/%s/path/%s' % (procfs_path, self.pid, name) - hit_enoent = True - else: - raise - retlist.append((addr, perm, name, rss, anon, locked)) - if hit_enoent: - self._assert_alive() - return retlist - - @wrap_exceptions - def num_fds(self): - return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))) - - @wrap_exceptions - def num_ctx_switches(self): - return _common.pctxsw( - *cext.proc_num_ctx_switches(self.pid, self._procfs_path)) - - @wrap_exceptions - def wait(self, timeout=None): - return _psposix.wait_pid(self.pid, timeout, self._name) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/_psutil_windows.pyd b/third_party/python/psutil-cp27-none-win_amd64/psutil/_psutil_windows.pyd deleted file mode 100644 index 9db9a66d6ed0..000000000000 Binary files a/third_party/python/psutil-cp27-none-win_amd64/psutil/_psutil_windows.pyd and /dev/null differ diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/_pswindows.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/_pswindows.py deleted file mode 100644 index 99d5d71499ba..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/_pswindows.py +++ /dev/null @@ -1,1105 +0,0 @@ -# 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. - -"""Windows platform implementation.""" - -import contextlib -import errno -import functools -import os -import signal -import sys -import time -from collections import namedtuple - -from . import _common -from ._common import AccessDenied -from ._common import conn_tmap -from ._common import conn_to_ntuple -from ._common import debug -from ._common import ENCODING -from ._common import ENCODING_ERRS -from ._common import isfile_strict -from ._common import memoize -from ._common import memoize_when_activated -from ._common import NoSuchProcess -from ._common import parse_environ_block -from ._common import TimeoutExpired -from ._common import usage_percent -from ._compat import long -from ._compat import lru_cache -from ._compat import PY3 -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 -from ._psutil_windows import IDLE_PRIORITY_CLASS -from ._psutil_windows import NORMAL_PRIORITY_CLASS -from ._psutil_windows import REALTIME_PRIORITY_CLASS - -try: - from . import _psutil_windows as cext -except ImportError as err: - if str(err).lower().startswith("dll load failed") and \ - sys.getwindowsversion()[0] < 6: - # We may get here if: - # 1) we are on an old Windows version - # 2) psutil was installed via pip + wheel - # See: https://github.com/giampaolo/psutil/issues/811 - msg = "this Windows version is too old (< Windows Vista); " - msg += "psutil 3.4.2 is the latest version which supports Windows " - msg += "2000, XP and 2003 server" - raise RuntimeError(msg) - else: - raise - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - -# process priority constants, import from __init__.py: -# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx -__extra__all__ = [ - "win_service_iter", "win_service_get", - # Process priority - "ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS", - "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS", "NORMAL_PRIORITY_CLASS", - "REALTIME_PRIORITY_CLASS", - # IO priority - "IOPRIO_VERYLOW", "IOPRIO_LOW", "IOPRIO_NORMAL", "IOPRIO_HIGH", - # others - "CONN_DELETE_TCB", "AF_LINK", -] - - -# ===================================================================== -# --- globals -# ===================================================================== - -CONN_DELETE_TCB = "DELETE_TCB" -ERROR_PARTIAL_COPY = 299 -PYPY = '__pypy__' in sys.builtin_module_names - -if enum is None: - AF_LINK = -1 -else: - AddressFamily = enum.IntEnum('AddressFamily', {'AF_LINK': -1}) - AF_LINK = AddressFamily.AF_LINK - -TCP_STATUSES = { - cext.MIB_TCP_STATE_ESTAB: _common.CONN_ESTABLISHED, - cext.MIB_TCP_STATE_SYN_SENT: _common.CONN_SYN_SENT, - cext.MIB_TCP_STATE_SYN_RCVD: _common.CONN_SYN_RECV, - cext.MIB_TCP_STATE_FIN_WAIT1: _common.CONN_FIN_WAIT1, - cext.MIB_TCP_STATE_FIN_WAIT2: _common.CONN_FIN_WAIT2, - cext.MIB_TCP_STATE_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.MIB_TCP_STATE_CLOSED: _common.CONN_CLOSE, - cext.MIB_TCP_STATE_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.MIB_TCP_STATE_LAST_ACK: _common.CONN_LAST_ACK, - cext.MIB_TCP_STATE_LISTEN: _common.CONN_LISTEN, - cext.MIB_TCP_STATE_CLOSING: _common.CONN_CLOSING, - cext.MIB_TCP_STATE_DELETE_TCB: CONN_DELETE_TCB, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -if enum is not None: - class Priority(enum.IntEnum): - ABOVE_NORMAL_PRIORITY_CLASS = ABOVE_NORMAL_PRIORITY_CLASS - BELOW_NORMAL_PRIORITY_CLASS = BELOW_NORMAL_PRIORITY_CLASS - HIGH_PRIORITY_CLASS = HIGH_PRIORITY_CLASS - IDLE_PRIORITY_CLASS = IDLE_PRIORITY_CLASS - NORMAL_PRIORITY_CLASS = NORMAL_PRIORITY_CLASS - REALTIME_PRIORITY_CLASS = REALTIME_PRIORITY_CLASS - - globals().update(Priority.__members__) - -if enum is None: - IOPRIO_VERYLOW = 0 - IOPRIO_LOW = 1 - IOPRIO_NORMAL = 2 - IOPRIO_HIGH = 3 -else: - class IOPriority(enum.IntEnum): - IOPRIO_VERYLOW = 0 - IOPRIO_LOW = 1 - IOPRIO_NORMAL = 2 - IOPRIO_HIGH = 3 - globals().update(IOPriority.__members__) - -pinfo_map = dict( - num_handles=0, - ctx_switches=1, - user_time=2, - kernel_time=3, - create_time=4, - num_threads=5, - io_rcount=6, - io_wcount=7, - io_rbytes=8, - io_wbytes=9, - io_count_others=10, - io_bytes_others=11, - num_page_faults=12, - peak_wset=13, - wset=14, - peak_paged_pool=15, - paged_pool=16, - peak_non_paged_pool=17, - non_paged_pool=18, - pagefile=19, - peak_pagefile=20, - mem_private=21, -) - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.cpu_times() -scputimes = namedtuple('scputimes', - ['user', 'system', 'idle', 'interrupt', 'dpc']) -# psutil.virtual_memory() -svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) -# psutil.Process.memory_info() -pmem = namedtuple( - 'pmem', ['rss', 'vms', - 'num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool', - 'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool', - 'pagefile', 'peak_pagefile', 'private']) -# psutil.Process.memory_full_info() -pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', )) -# psutil.Process.memory_maps(grouped=True) -pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss']) -# psutil.Process.memory_maps(grouped=False) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) -# psutil.Process.io_counters() -pio = namedtuple('pio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'other_count', 'other_bytes']) - - -# ===================================================================== -# --- utils -# ===================================================================== - - -@lru_cache(maxsize=512) -def convert_dos_path(s): - r"""Convert paths using native DOS format like: - "\Device\HarddiskVolume1\Windows\systemew\file.txt" - into: - "C:\Windows\systemew\file.txt" - """ - rawdrive = '\\'.join(s.split('\\')[:3]) - driveletter = cext.win32_QueryDosDevice(rawdrive) - remainder = s[len(rawdrive):] - return os.path.join(driveletter, remainder) - - -def py2_strencode(s): - """Encode a unicode string to a byte string by using the default fs - encoding + "replace" error handler. - """ - if PY3: - return s - else: - if isinstance(s, str): - return s - else: - return s.encode(ENCODING, ENCODING_ERRS) - - -@memoize -def getpagesize(): - return cext.getpagesize() - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - """System virtual memory as a namedtuple.""" - mem = cext.virtual_mem() - totphys, availphys, totpagef, availpagef, totvirt, freevirt = mem - # - total = totphys - avail = availphys - free = availphys - used = total - avail - percent = usage_percent((total - avail), total, round_=1) - return svmem(total, avail, percent, used, free) - - -def swap_memory(): - """Swap system memory as a (total, used, free, sin, sout) tuple.""" - mem = cext.virtual_mem() - total = mem[2] - free = mem[3] - used = total - free - percent = usage_percent(used, total, round_=1) - return _common.sswap(total, used, free, percent, 0, 0) - - -# ===================================================================== -# --- disk -# ===================================================================== - - -disk_io_counters = cext.disk_io_counters - - -def disk_usage(path): - """Return disk usage associated with path.""" - if PY3 and isinstance(path, bytes): - # XXX: do we want to use "strict"? Probably yes, in order - # to fail immediately. After all we are accepting input here... - path = path.decode(ENCODING, errors="strict") - total, free = cext.disk_usage(path) - used = total - free - percent = usage_percent(used, total, round_=1) - return _common.sdiskusage(total, used, free, percent) - - -def disk_partitions(all): - """Return disk partitions.""" - rawlist = cext.disk_partitions(all) - return [_common.sdiskpart(*x) for x in rawlist] - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return system CPU times as a named tuple.""" - user, system, idle = cext.cpu_times() - # Internally, GetSystemTimes() is used, and it doesn't return - # interrupt and dpc times. cext.per_cpu_times() does, so we - # rely on it to get those only. - percpu_summed = scputimes(*[sum(n) for n in zip(*cext.per_cpu_times())]) - return scputimes(user, system, idle, - percpu_summed.interrupt, percpu_summed.dpc) - - -def per_cpu_times(): - """Return system per-CPU times as a list of named tuples.""" - ret = [] - for user, system, idle, interrupt, dpc in cext.per_cpu_times(): - item = scputimes(user, system, idle, interrupt, dpc) - ret.append(item) - return ret - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - return cext.cpu_count_logical() - - -def cpu_count_physical(): - """Return the number of physical CPU cores in the system.""" - return cext.cpu_count_phys() - - -def cpu_stats(): - """Return CPU statistics.""" - ctx_switches, interrupts, dpcs, syscalls = cext.cpu_stats() - soft_interrupts = 0 - return _common.scpustats(ctx_switches, interrupts, soft_interrupts, - syscalls) - - -def cpu_freq(): - """Return CPU frequency. - On Windows per-cpu frequency is not supported. - """ - curr, max_ = cext.cpu_freq() - min_ = 0.0 - return [_common.scpufreq(float(curr), min_, float(max_))] - - -_loadavg_inititialized = False - - -def getloadavg(): - """Return the number of processes in the system run queue averaged - over the last 1, 5, and 15 minutes respectively as a tuple""" - global _loadavg_inititialized - - if not _loadavg_inititialized: - cext.init_loadavg_counter() - _loadavg_inititialized = True - - # Drop to 2 decimal points which is what Linux does - raw_loads = cext.getloadavg() - return tuple([round(load, 2) for load in raw_loads]) - - -# ===================================================================== -# --- network -# ===================================================================== - - -def net_connections(kind, _pid=-1): - """Return socket connections. If pid == -1 return system-wide - connections (as opposed to connections opened by one process only). - """ - if kind not in conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - families, types = conn_tmap[kind] - rawlist = cext.net_connections(_pid, families, types) - ret = set() - for item in rawlist: - fd, fam, type, laddr, raddr, status, pid = item - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, TCP_STATUSES, - pid=pid if _pid == -1 else None) - ret.add(nt) - return list(ret) - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - ret = {} - rawdict = cext.net_if_stats() - for name, items in rawdict.items(): - if not PY3: - assert isinstance(name, unicode), type(name) - name = py2_strencode(name) - isup, duplex, speed, mtu = items - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -def net_io_counters(): - """Return network I/O statistics for every network interface - installed on the system as a dict of raw tuples. - """ - ret = cext.net_io_counters() - return dict([(py2_strencode(k), v) for k, v in ret.items()]) - - -def net_if_addrs(): - """Return the addresses associated to each NIC.""" - ret = [] - for items in cext.net_if_addrs(): - items = list(items) - items[0] = py2_strencode(items[0]) - ret.append(items) - return ret - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -def sensors_battery(): - """Return battery information.""" - # For constants meaning see: - # https://msdn.microsoft.com/en-us/library/windows/desktop/ - # aa373232(v=vs.85).aspx - acline_status, flags, percent, secsleft = cext.sensors_battery() - power_plugged = acline_status == 1 - no_battery = bool(flags & 128) - charging = bool(flags & 8) - - if no_battery: - return None - if power_plugged or charging: - secsleft = _common.POWER_TIME_UNLIMITED - elif secsleft == -1: - secsleft = _common.POWER_TIME_UNKNOWN - - return _common.sbattery(percent, secsleft, power_plugged) - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -_last_btime = 0 - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - # This dirty hack is to adjust the precision of the returned - # value which may have a 1 second fluctuation, see: - # https://github.com/giampaolo/psutil/issues/1007 - global _last_btime - ret = float(cext.boot_time()) - if abs(ret - _last_btime) <= 1: - return _last_btime - else: - _last_btime = ret - return ret - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, hostname, tstamp = item - user = py2_strencode(user) - nt = _common.suser(user, None, hostname, tstamp, None) - retlist.append(nt) - return retlist - - -# ===================================================================== -# --- Windows services -# ===================================================================== - - -def win_service_iter(): - """Yields a list of WindowsService instances.""" - for name, display_name in cext.winservice_enumerate(): - yield WindowsService(py2_strencode(name), py2_strencode(display_name)) - - -def win_service_get(name): - """Open a Windows service and return it as a WindowsService instance.""" - service = WindowsService(name, None) - service._display_name = service._query_config()['display_name'] - return service - - -class WindowsService(object): - """Represents an installed Windows service.""" - - def __init__(self, name, display_name): - self._name = name - self._display_name = display_name - - def __str__(self): - details = "(name=%r, display_name=%r)" % ( - self._name, self._display_name) - return "%s%s" % (self.__class__.__name__, details) - - def __repr__(self): - return "<%s at %s>" % (self.__str__(), id(self)) - - def __eq__(self, other): - # Test for equality with another WindosService object based - # on name. - if not isinstance(other, WindowsService): - return NotImplemented - return self._name == other._name - - def __ne__(self, other): - return not self == other - - def _query_config(self): - with self._wrap_exceptions(): - display_name, binpath, username, start_type = \ - cext.winservice_query_config(self._name) - # XXX - update _self.display_name? - return dict( - display_name=py2_strencode(display_name), - binpath=py2_strencode(binpath), - username=py2_strencode(username), - start_type=py2_strencode(start_type)) - - def _query_status(self): - with self._wrap_exceptions(): - status, pid = cext.winservice_query_status(self._name) - if pid == 0: - pid = None - return dict(status=status, pid=pid) - - @contextlib.contextmanager - def _wrap_exceptions(self): - """Ctx manager which translates bare OSError and WindowsError - exceptions into NoSuchProcess and AccessDenied. - """ - try: - yield - except OSError as err: - if is_permission_err(err): - raise AccessDenied( - pid=None, name=self._name, - msg="service %r is not querable (not enough privileges)" % - self._name) - elif err.winerror in (cext.ERROR_INVALID_NAME, - cext.ERROR_SERVICE_DOES_NOT_EXIST): - raise NoSuchProcess( - pid=None, name=self._name, - msg="service %r does not exist)" % self._name) - else: - raise - - # config query - - def name(self): - """The service name. This string is how a service is referenced - and can be passed to win_service_get() to get a new - WindowsService instance. - """ - return self._name - - def display_name(self): - """The service display name. The value is cached when this class - is instantiated. - """ - return self._display_name - - def binpath(self): - """The fully qualified path to the service binary/exe file as - a string, including command line arguments. - """ - return self._query_config()['binpath'] - - def username(self): - """The name of the user that owns this service.""" - return self._query_config()['username'] - - def start_type(self): - """A string which can either be "automatic", "manual" or - "disabled". - """ - return self._query_config()['start_type'] - - # status query - - def pid(self): - """The process PID, if any, else None. This can be passed - to Process class to control the service's process. - """ - return self._query_status()['pid'] - - def status(self): - """Service status as a string.""" - return self._query_status()['status'] - - def description(self): - """Service long description.""" - return py2_strencode(cext.winservice_query_descr(self.name())) - - # utils - - def as_dict(self): - """Utility method retrieving all the information above as a - dictionary. - """ - d = self._query_config() - d.update(self._query_status()) - d['name'] = self.name() - d['display_name'] = self.display_name() - d['description'] = self.description() - return d - - # actions - # XXX: the necessary C bindings for start() and stop() are - # implemented but for now I prefer not to expose them. - # I may change my mind in the future. Reasons: - # - they require Administrator privileges - # - can't implement a timeout for stop() (unless by using a thread, - # which sucks) - # - would require adding ServiceAlreadyStarted and - # ServiceAlreadyStopped exceptions, adding two new APIs. - # - we might also want to have modify(), which would basically mean - # rewriting win32serviceutil.ChangeServiceConfig, which involves a - # lot of stuff (and API constants which would pollute the API), see: - # http://pyxr.sourceforge.net/PyXR/c/python24/lib/site-packages/ - # win32/lib/win32serviceutil.py.html#0175 - # - psutil is typically about "read only" monitoring stuff; - # win_service_* APIs should only be used to retrieve a service and - # check whether it's running - - # def start(self, timeout=None): - # with self._wrap_exceptions(): - # cext.winservice_start(self.name()) - # if timeout: - # giveup_at = time.time() + timeout - # while True: - # if self.status() == "running": - # return - # else: - # if time.time() > giveup_at: - # raise TimeoutExpired(timeout) - # else: - # time.sleep(.1) - - # def stop(self): - # # Note: timeout is not implemented because it's just not - # # possible, see: - # # http://stackoverflow.com/questions/11973228/ - # with self._wrap_exceptions(): - # return cext.winservice_stop(self.name()) - - -# ===================================================================== -# --- processes -# ===================================================================== - - -pids = cext.pids -pid_exists = cext.pid_exists -ppid_map = cext.ppid_map # used internally by Process.children() - - -def is_permission_err(exc): - """Return True if this is a permission error.""" - assert isinstance(exc, OSError), exc - # On Python 2 OSError doesn't always have 'winerror'. Sometimes - # it does, in which case the original exception was WindowsError - # (which is a subclass of OSError). - return exc.errno in (errno.EPERM, errno.EACCES) or \ - getattr(exc, "winerror", -1) in (cext.ERROR_ACCESS_DENIED, - cext.ERROR_PRIVILEGE_NOT_HELD) - - -def convert_oserror(exc, pid=None, name=None): - """Convert OSError into NoSuchProcess or AccessDenied.""" - assert isinstance(exc, OSError), exc - if is_permission_err(exc): - return AccessDenied(pid=pid, name=name) - if exc.errno == errno.ESRCH: - return NoSuchProcess(pid=pid, name=name) - raise exc - - -def wrap_exceptions(fun): - """Decorator which converts OSError into NoSuchProcess or AccessDenied.""" - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except OSError as err: - raise convert_oserror(err, pid=self.pid, name=self._name) - return wrapper - - -def retry_error_partial_copy(fun): - """Workaround for https://github.com/giampaolo/psutil/issues/875. - See: https://stackoverflow.com/questions/4457745#4457745 - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - delay = 0.0001 - times = 33 - for x in range(times): # retries for roughly 1 second - try: - return fun(self, *args, **kwargs) - except WindowsError as _: - err = _ - if err.winerror == ERROR_PARTIAL_COPY: - time.sleep(delay) - delay = min(delay * 2, 0.04) - continue - else: - raise - else: - msg = "%s retried %s times, converted to AccessDenied as it's " \ - "still returning %r" % (fun, times, err) - raise AccessDenied(pid=self.pid, name=self._name, msg=msg) - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - # --- oneshot() stuff - - def oneshot_enter(self): - self._proc_info.cache_activate(self) - self.exe.cache_activate(self) - - def oneshot_exit(self): - self._proc_info.cache_deactivate(self) - self.exe.cache_deactivate(self) - - @memoize_when_activated - def _proc_info(self): - """Return multiple information about this process as a - raw tuple. - """ - ret = cext.proc_info(self.pid) - assert len(ret) == len(pinfo_map) - return ret - - def name(self): - """Return process name, which on Windows is always the final - part of the executable. - """ - # This is how PIDs 0 and 4 are always represented in taskmgr - # and process-hacker. - if self.pid == 0: - return "System Idle Process" - if self.pid == 4: - return "System" - return os.path.basename(self.exe()) - - @wrap_exceptions - @memoize_when_activated - def exe(self): - if PYPY: - try: - exe = cext.proc_exe(self.pid) - except WindowsError as err: - # 24 = ERROR_TOO_MANY_OPEN_FILES. Not sure why this happens - # (perhaps PyPy's JIT delaying garbage collection of files?). - if err.errno == 24: - debug("%r forced into AccessDenied" % err) - raise AccessDenied(self.pid, self._name) - raise - else: - exe = cext.proc_exe(self.pid) - if not PY3: - exe = py2_strencode(exe) - if exe.startswith('\\'): - return convert_dos_path(exe) - return exe # May be "Registry", "MemCompression", ... - - @wrap_exceptions - @retry_error_partial_copy - def cmdline(self): - if cext.WINVER >= cext.WINDOWS_8_1: - # PEB method detects cmdline changes but requires more - # privileges: https://github.com/giampaolo/psutil/pull/1398 - try: - ret = cext.proc_cmdline(self.pid, use_peb=True) - except OSError as err: - if is_permission_err(err): - ret = cext.proc_cmdline(self.pid, use_peb=False) - else: - raise - else: - ret = cext.proc_cmdline(self.pid, use_peb=True) - if PY3: - return ret - else: - return [py2_strencode(s) for s in ret] - - @wrap_exceptions - @retry_error_partial_copy - def environ(self): - ustr = cext.proc_environ(self.pid) - if ustr and not PY3: - assert isinstance(ustr, unicode), type(ustr) - return parse_environ_block(py2_strencode(ustr)) - - def ppid(self): - try: - return ppid_map()[self.pid] - except KeyError: - raise NoSuchProcess(self.pid, self._name) - - def _get_raw_meminfo(self): - try: - return cext.proc_memory_info(self.pid) - except OSError as err: - if is_permission_err(err): - # TODO: the C ext can probably be refactored in order - # to get this from cext.proc_info() - info = self._proc_info() - return ( - info[pinfo_map['num_page_faults']], - info[pinfo_map['peak_wset']], - info[pinfo_map['wset']], - info[pinfo_map['peak_paged_pool']], - info[pinfo_map['paged_pool']], - info[pinfo_map['peak_non_paged_pool']], - info[pinfo_map['non_paged_pool']], - info[pinfo_map['pagefile']], - info[pinfo_map['peak_pagefile']], - info[pinfo_map['mem_private']], - ) - raise - - @wrap_exceptions - def memory_info(self): - # on Windows RSS == WorkingSetSize and VSM == PagefileUsage. - # Underlying C function returns fields of PROCESS_MEMORY_COUNTERS - # struct. - t = self._get_raw_meminfo() - rss = t[2] # wset - vms = t[7] # pagefile - return pmem(*(rss, vms, ) + t) - - @wrap_exceptions - def memory_full_info(self): - basic_mem = self.memory_info() - uss = cext.proc_memory_uss(self.pid) - uss *= getpagesize() - return pfullmem(*basic_mem + (uss, )) - - def memory_maps(self): - try: - raw = cext.proc_memory_maps(self.pid) - except OSError as err: - # XXX - can't use wrap_exceptions decorator as we're - # returning a generator; probably needs refactoring. - raise convert_oserror(err, self.pid, self._name) - else: - for addr, perm, path, rss in raw: - path = convert_dos_path(path) - if not PY3: - path = py2_strencode(path) - addr = hex(addr) - yield (addr, perm, path, rss) - - @wrap_exceptions - def kill(self): - return cext.proc_kill(self.pid) - - @wrap_exceptions - def send_signal(self, sig): - if sig == signal.SIGTERM: - cext.proc_kill(self.pid) - # py >= 2.7 - elif sig in (getattr(signal, "CTRL_C_EVENT", object()), - getattr(signal, "CTRL_BREAK_EVENT", object())): - os.kill(self.pid, sig) - else: - raise ValueError( - "only SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals " - "are supported on Windows") - - @wrap_exceptions - def wait(self, timeout=None): - if timeout is None: - cext_timeout = cext.INFINITE - else: - # WaitForSingleObject() expects time in milliseconds. - cext_timeout = int(timeout * 1000) - - timer = getattr(time, 'monotonic', time.time) - stop_at = timer() + timeout if timeout is not None else None - - try: - # Exit code is supposed to come from GetExitCodeProcess(). - # May also be None if OpenProcess() failed with - # ERROR_INVALID_PARAMETER, meaning PID is already gone. - exit_code = cext.proc_wait(self.pid, cext_timeout) - except cext.TimeoutExpired: - # WaitForSingleObject() returned WAIT_TIMEOUT. Just raise. - raise TimeoutExpired(timeout, self.pid, self._name) - except cext.TimeoutAbandoned: - # WaitForSingleObject() returned WAIT_ABANDONED, see: - # https://github.com/giampaolo/psutil/issues/1224 - # We'll just rely on the internal polling and return None - # when the PID disappears. Subprocess module does the same - # (return None): - # https://github.com/python/cpython/blob/ - # be50a7b627d0aa37e08fa8e2d5568891f19903ce/ - # Lib/subprocess.py#L1193-L1194 - exit_code = None - - # At this point WaitForSingleObject() returned WAIT_OBJECT_0, - # meaning the process is gone. Stupidly there are cases where - # its PID may still stick around so we do a further internal - # polling. - delay = 0.0001 - while True: - if not pid_exists(self.pid): - return exit_code - if stop_at and timer() >= stop_at: - raise TimeoutExpired(timeout, pid=self.pid, name=self._name) - time.sleep(delay) - delay = min(delay * 2, 0.04) # incremental delay - - @wrap_exceptions - def username(self): - if self.pid in (0, 4): - return 'NT AUTHORITY\\SYSTEM' - domain, user = cext.proc_username(self.pid) - return py2_strencode(domain) + '\\' + py2_strencode(user) - - @wrap_exceptions - def create_time(self): - # Note: proc_times() not put under oneshot() 'cause create_time() - # is already cached by the main Process class. - try: - user, system, created = cext.proc_times(self.pid) - return created - except OSError as err: - if is_permission_err(err): - return self._proc_info()[pinfo_map['create_time']] - raise - - @wrap_exceptions - def num_threads(self): - return self._proc_info()[pinfo_map['num_threads']] - - @wrap_exceptions - def threads(self): - rawlist = cext.proc_threads(self.pid) - retlist = [] - for thread_id, utime, stime in rawlist: - ntuple = _common.pthread(thread_id, utime, stime) - retlist.append(ntuple) - return retlist - - @wrap_exceptions - def cpu_times(self): - try: - user, system, created = cext.proc_times(self.pid) - except OSError as err: - if not is_permission_err(err): - raise - info = self._proc_info() - user = info[pinfo_map['user_time']] - system = info[pinfo_map['kernel_time']] - # Children user/system times are not retrievable (set to 0). - return _common.pcputimes(user, system, 0.0, 0.0) - - @wrap_exceptions - def suspend(self): - cext.proc_suspend_or_resume(self.pid, True) - - @wrap_exceptions - def resume(self): - cext.proc_suspend_or_resume(self.pid, False) - - @wrap_exceptions - @retry_error_partial_copy - def cwd(self): - if self.pid in (0, 4): - raise AccessDenied(self.pid, self._name) - # return a normalized pathname since the native C function appends - # "\\" at the and of the path - path = cext.proc_cwd(self.pid) - return py2_strencode(os.path.normpath(path)) - - @wrap_exceptions - def open_files(self): - if self.pid in (0, 4): - return [] - ret = set() - # Filenames come in in native format like: - # "\Device\HarddiskVolume1\Windows\systemew\file.txt" - # Convert the first part in the corresponding drive letter - # (e.g. "C:\") by using Windows's QueryDosDevice() - raw_file_names = cext.proc_open_files(self.pid) - for _file in raw_file_names: - _file = convert_dos_path(_file) - if isfile_strict(_file): - if not PY3: - _file = py2_strencode(_file) - ntuple = _common.popenfile(_file, -1) - ret.add(ntuple) - return list(ret) - - @wrap_exceptions - def connections(self, kind='inet'): - return net_connections(kind, _pid=self.pid) - - @wrap_exceptions - def nice_get(self): - value = cext.proc_priority_get(self.pid) - if enum is not None: - value = Priority(value) - return value - - @wrap_exceptions - def nice_set(self, value): - return cext.proc_priority_set(self.pid, value) - - @wrap_exceptions - def ionice_get(self): - ret = cext.proc_io_priority_get(self.pid) - if enum is not None: - ret = IOPriority(ret) - return ret - - @wrap_exceptions - def ionice_set(self, ioclass, value): - if value: - raise TypeError("value argument not accepted on Windows") - if ioclass not in (IOPRIO_VERYLOW, IOPRIO_LOW, IOPRIO_NORMAL, - IOPRIO_HIGH): - raise ValueError("%s is not a valid priority" % ioclass) - cext.proc_io_priority_set(self.pid, ioclass) - - @wrap_exceptions - def io_counters(self): - try: - ret = cext.proc_io_counters(self.pid) - except OSError as err: - if not is_permission_err(err): - raise - info = self._proc_info() - ret = ( - info[pinfo_map['io_rcount']], - info[pinfo_map['io_wcount']], - info[pinfo_map['io_rbytes']], - info[pinfo_map['io_wbytes']], - info[pinfo_map['io_count_others']], - info[pinfo_map['io_bytes_others']], - ) - return pio(*ret) - - @wrap_exceptions - def status(self): - suspended = cext.proc_is_suspended(self.pid) - if suspended: - return _common.STATUS_STOPPED - else: - return _common.STATUS_RUNNING - - @wrap_exceptions - def cpu_affinity_get(self): - def from_bitmask(x): - return [i for i in xrange(64) if (1 << i) & x] - bitmask = cext.proc_cpu_affinity_get(self.pid) - return from_bitmask(bitmask) - - @wrap_exceptions - def cpu_affinity_set(self, value): - def to_bitmask(l): - if not l: - raise ValueError("invalid argument %r" % l) - out = 0 - for b in l: - out |= 2 ** b - return out - - # SetProcessAffinityMask() states that ERROR_INVALID_PARAMETER - # is returned for an invalid CPU but this seems not to be true, - # therefore we check CPUs validy beforehand. - allcpus = list(range(len(per_cpu_times()))) - for cpu in value: - if cpu not in allcpus: - if not isinstance(cpu, (int, long)): - raise TypeError( - "invalid CPU %r; an integer is required" % cpu) - else: - raise ValueError("invalid CPU %r" % cpu) - - bitmask = to_bitmask(value) - cext.proc_cpu_affinity_set(self.pid, bitmask) - - @wrap_exceptions - def num_handles(self): - try: - return cext.proc_num_handles(self.pid) - except OSError as err: - if is_permission_err(err): - return self._proc_info()[pinfo_map['num_handles']] - raise - - @wrap_exceptions - def num_ctx_switches(self): - ctx_switches = self._proc_info()[pinfo_map['ctx_switches']] - # only voluntary ctx switches are supported - return _common.pctxsw(ctx_switches, 0) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/__init__.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/__init__.py deleted file mode 100644 index 3e4dc88066ca..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/__init__.py +++ /dev/null @@ -1,1137 +0,0 @@ -# -*- coding: utf-8 -*- - -# 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. - -""" -Test utilities. -""" - -from __future__ import print_function - -import atexit -import contextlib -import ctypes -import errno -import functools -import os -import random -import re -import select -import shutil -import socket -import stat -import subprocess -import sys -import tempfile -import textwrap -import threading -import time -import traceback -import warnings -from socket import AF_INET -from socket import AF_INET6 -from socket import SOCK_STREAM - -import psutil -from psutil import AIX -from psutil import MACOS -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -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 u -from psutil._compat import unicode -from psutil._compat import which - -if sys.version_info < (2, 7): - import unittest2 as unittest # requires "pip install unittest2" -else: - import unittest - -try: - from unittest import mock # py3 -except ImportError: - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - import mock # NOQA - requires "pip install mock" - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - - -__all__ = [ - # constants - 'APPVEYOR', 'DEVNULL', 'GLOBAL_TIMEOUT', 'MEMORY_TOLERANCE', 'NO_RETRIES', - 'PYPY', 'PYTHON_EXE', 'ROOT_DIR', 'SCRIPTS_DIR', 'TESTFILE_PREFIX', - 'TESTFN', 'TESTFN_UNICODE', 'TOX', 'TRAVIS', 'CIRRUS', 'CI_TESTING', - 'VALID_PROC_STATUSES', - "HAS_CPU_AFFINITY", "HAS_CPU_FREQ", "HAS_ENVIRON", "HAS_PROC_IO_COUNTERS", - "HAS_IONICE", "HAS_MEMORY_MAPS", "HAS_PROC_CPU_NUM", "HAS_RLIMIT", - "HAS_SENSORS_BATTERY", "HAS_BATTERY", "HAS_SENSORS_FANS", - "HAS_SENSORS_TEMPERATURES", "HAS_MEMORY_FULL_INFO", - # subprocesses - 'pyrun', 'reap_children', 'get_test_subprocess', 'create_zombie_proc', - 'create_proc_children_pair', - # threads - 'ThreadTask' - # test utils - 'unittest', 'skip_on_access_denied', 'skip_on_not_implemented', - 'retry_on_failure', - # install utils - 'install_pip', 'install_test_deps', - # fs utils - 'chdir', 'safe_rmpath', 'create_exe', 'decode_path', 'encode_path', - 'unique_filename', - # os - 'get_winver', 'get_kernel_version', - # sync primitives - 'call_until', 'wait_for_pid', 'wait_for_file', - # network - 'check_net_address', - 'get_free_port', 'unix_socket_path', 'bind_socket', 'bind_unix_socket', - 'tcp_socketpair', 'unix_socketpair', 'create_sockets', - # compat - 'reload_module', 'import_module_by_path', - # others - 'warn', 'copyload_shared_lib', 'is_namedtuple', -] - - -# =================================================================== -# --- constants -# =================================================================== - -# --- platforms - -TOX = os.getenv('TOX') or '' in ('1', 'true') -PYPY = '__pypy__' in sys.builtin_module_names -# whether we're running this test suite on a Continuous Integration service -TRAVIS = bool(os.environ.get('TRAVIS')) -APPVEYOR = bool(os.environ.get('APPVEYOR')) -CIRRUS = bool(os.environ.get('CIRRUS')) -CI_TESTING = TRAVIS or APPVEYOR or CIRRUS - -# --- configurable defaults - -# how many times retry_on_failure() decorator will retry -NO_RETRIES = 10 -# bytes tolerance for system-wide memory related tests -MEMORY_TOLERANCE = 500 * 1024 # 500KB -# the timeout used in functions which have to wait -GLOBAL_TIMEOUT = 5 -# be more tolerant if we're on travis / appveyor in order to avoid -# false positives -if TRAVIS or APPVEYOR: - NO_RETRIES *= 3 - GLOBAL_TIMEOUT *= 3 - -# --- files - -TESTFILE_PREFIX = '$testfn' -if os.name == 'java': - # Jython disallows @ in module names - TESTFILE_PREFIX = '$psutil-test-' -else: - TESTFILE_PREFIX = '@psutil-test-' -TESTFN = os.path.join(os.path.realpath(os.getcwd()), TESTFILE_PREFIX) -# Disambiguate TESTFN for parallel testing, while letting it remain a valid -# module name. -TESTFN = TESTFN + str(os.getpid()) - -_TESTFN = TESTFN + '-internal' -TESTFN_UNICODE = TESTFN + u("-ƒőő") -ASCII_FS = sys.getfilesystemencoding().lower() in ('ascii', 'us-ascii') - -# --- paths - -ROOT_DIR = os.path.realpath( - os.path.join(os.path.dirname(__file__), '..', '..')) -SCRIPTS_DIR = os.path.join(ROOT_DIR, 'scripts') -HERE = os.path.realpath(os.path.dirname(__file__)) - -# --- support - -HAS_CONNECTIONS_UNIX = POSIX and not SUNOS -HAS_CPU_AFFINITY = hasattr(psutil.Process, "cpu_affinity") -HAS_CPU_FREQ = hasattr(psutil, "cpu_freq") -HAS_GETLOADAVG = hasattr(psutil, "getloadavg") -HAS_ENVIRON = hasattr(psutil.Process, "environ") -HAS_IONICE = hasattr(psutil.Process, "ionice") -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_SENSORS_BATTERY = hasattr(psutil, "sensors_battery") -try: - HAS_BATTERY = HAS_SENSORS_BATTERY and bool(psutil.sensors_battery()) -except Exception: - HAS_BATTERY = True -HAS_SENSORS_FANS = hasattr(psutil, "sensors_fans") -HAS_SENSORS_TEMPERATURES = hasattr(psutil, "sensors_temperatures") -HAS_THREADS = hasattr(psutil.Process, "threads") -SKIP_SYSCONS = (MACOS or AIX) and os.getuid() != 0 - -# --- misc - - -def _get_py_exe(): - def attempt(exe): - try: - subprocess.check_call( - [exe, "-V"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - except Exception: - return None - else: - return exe - - if MACOS: - exe = \ - attempt(sys.executable) or \ - attempt(os.path.realpath(sys.executable)) or \ - attempt(which("python%s.%s" % sys.version_info[:2])) or \ - attempt(psutil.Process().exe()) - if not exe: - raise ValueError("can't find python exe real abspath") - return exe - else: - exe = os.path.realpath(sys.executable) - assert os.path.exists(exe), exe - return exe - - -PYTHON_EXE = _get_py_exe() -DEVNULL = open(os.devnull, 'r+') -VALID_PROC_STATUSES = [getattr(psutil, x) for x in dir(psutil) - if x.startswith('STATUS_')] -AF_UNIX = getattr(socket, "AF_UNIX", object()) - -_subprocesses_started = set() -_pids_started = set() -_testfiles_created = set() - - -@atexit.register -def cleanup_test_files(): - DEVNULL.close() - for name in os.listdir(u('.')): - if isinstance(name, unicode): - prefix = u(TESTFILE_PREFIX) - else: - prefix = TESTFILE_PREFIX - if name.startswith(prefix): - try: - safe_rmpath(name) - except Exception: - traceback.print_exc() - for path in _testfiles_created: - try: - safe_rmpath(path) - except Exception: - traceback.print_exc() - - -# this is executed first -@atexit.register -def cleanup_test_procs(): - reap_children(recursive=True) - - -# =================================================================== -# --- threads -# =================================================================== - - -class ThreadTask(threading.Thread): - """A thread task which does nothing expect staying alive.""" - - def __init__(self): - threading.Thread.__init__(self) - self._running = False - self._interval = 0.001 - self._flag = threading.Event() - - def __repr__(self): - name = self.__class__.__name__ - return '<%s running=%s at %#x>' % (name, self._running, id(self)) - - def __enter__(self): - self.start() - return self - - def __exit__(self, *args, **kwargs): - self.stop() - - def start(self): - """Start thread and keep it running until an explicit - stop() request. Polls for shutdown every 'timeout' seconds. - """ - if self._running: - raise ValueError("already started") - threading.Thread.start(self) - self._flag.wait() - - def run(self): - self._running = True - self._flag.set() - while self._running: - time.sleep(self._interval) - - def stop(self): - """Stop thread execution and and waits until it is stopped.""" - if not self._running: - raise ValueError("already stopped") - self._running = False - self.join() - - -# =================================================================== -# --- subprocesses -# =================================================================== - - -def _reap_children_on_err(fun): - @functools.wraps(fun) - def wrapper(*args, **kwargs): - try: - return fun(*args, **kwargs) - except Exception: - reap_children() - raise - return wrapper - - -@_reap_children_on_err -def get_test_subprocess(cmd=None, **kwds): - """Creates a python subprocess which does nothing for 60 secs and - return it as subprocess.Popen instance. - If "cmd" is specified that is used instead of python. - By default stdin and stdout are redirected to /dev/null. - It also attemps to make sure the process is in a reasonably - initialized state. - The process is registered for cleanup on reap_children(). - """ - kwds.setdefault("stdin", DEVNULL) - kwds.setdefault("stdout", DEVNULL) - kwds.setdefault("cwd", os.getcwd()) - kwds.setdefault("env", os.environ) - if WINDOWS: - # Prevents the subprocess to open error dialogs. This will also - # cause stderr to be suppressed, which is suboptimal in order - # to debug broken tests. - CREATE_NO_WINDOW = 0x8000000 - kwds.setdefault("creationflags", CREATE_NO_WINDOW) - if cmd is None: - safe_rmpath(_TESTFN) - pyline = "from time import sleep;" \ - "open(r'%s', 'w').close();" \ - "sleep(60);" % _TESTFN - cmd = [PYTHON_EXE, "-c", pyline] - sproc = subprocess.Popen(cmd, **kwds) - _subprocesses_started.add(sproc) - wait_for_file(_TESTFN, delete=True, empty=True) - else: - sproc = subprocess.Popen(cmd, **kwds) - _subprocesses_started.add(sproc) - wait_for_pid(sproc.pid) - return sproc - - -@_reap_children_on_err -def create_proc_children_pair(): - """Create a subprocess which creates another one as in: - A (us) -> B (child) -> C (grandchild). - Return a (child, grandchild) tuple. - The 2 processes are fully initialized and will live for 60 secs - and are registered for cleanup on reap_children(). - """ - _TESTFN2 = os.path.basename(_TESTFN) + '2' # need to be relative - s = textwrap.dedent("""\ - import subprocess, os, sys, time - s = "import os, time;" - s += "f = open('%s', 'w');" - s += "f.write(str(os.getpid()));" - s += "f.close();" - s += "time.sleep(60);" - p = subprocess.Popen([r'%s', '-c', s]) - p.wait() - """ % (_TESTFN2, PYTHON_EXE)) - # On Windows if we create a subprocess with CREATE_NO_WINDOW flag - # set (which is the default) a "conhost.exe" extra process will be - # spawned as a child. We don't want that. - if WINDOWS: - subp = pyrun(s, creationflags=0) - else: - subp = pyrun(s) - child1 = psutil.Process(subp.pid) - data = wait_for_file(_TESTFN2, delete=False, empty=False) - safe_rmpath(_TESTFN2) - child2_pid = int(data) - _pids_started.add(child2_pid) - child2 = psutil.Process(child2_pid) - return (child1, child2) - - -def create_zombie_proc(): - """Create a zombie process and return its PID.""" - assert psutil.POSIX - unix_file = tempfile.mktemp(prefix=TESTFILE_PREFIX) if MACOS else TESTFN - src = textwrap.dedent("""\ - import os, sys, time, socket, contextlib - child_pid = os.fork() - if child_pid > 0: - time.sleep(3000) - else: - # this is the zombie process - s = socket.socket(socket.AF_UNIX) - with contextlib.closing(s): - s.connect('%s') - if sys.version_info < (3, ): - pid = str(os.getpid()) - else: - pid = bytes(str(os.getpid()), 'ascii') - s.sendall(pid) - """ % unix_file) - with contextlib.closing(socket.socket(socket.AF_UNIX)) as sock: - sock.settimeout(GLOBAL_TIMEOUT) - sock.bind(unix_file) - sock.listen(5) - pyrun(src) - conn, _ = sock.accept() - try: - select.select([conn.fileno()], [], [], GLOBAL_TIMEOUT) - zpid = int(conn.recv(1024)) - _pids_started.add(zpid) - zproc = psutil.Process(zpid) - call_until(lambda: zproc.status(), "ret == psutil.STATUS_ZOMBIE") - return zpid - finally: - conn.close() - - -@_reap_children_on_err -def pyrun(src, **kwds): - """Run python 'src' code string in a separate interpreter. - Returns a subprocess.Popen instance. - """ - kwds.setdefault("stdout", None) - kwds.setdefault("stderr", None) - with tempfile.NamedTemporaryFile( - prefix=TESTFILE_PREFIX, mode="wt", delete=False) as f: - _testfiles_created.add(f.name) - f.write(src) - f.flush() - subp = get_test_subprocess([PYTHON_EXE, f.name], **kwds) - wait_for_pid(subp.pid) - return subp - - -@_reap_children_on_err -def sh(cmd, **kwds): - """run cmd in a subprocess and return its output. - raises RuntimeError on error. - """ - shell = True if isinstance(cmd, (str, unicode)) else False - # Prevents subprocess to open error dialogs in case of error. - flags = 0x8000000 if WINDOWS and shell else 0 - kwds.setdefault("shell", shell) - kwds.setdefault("stdout", subprocess.PIPE) - kwds.setdefault("stderr", subprocess.PIPE) - kwds.setdefault("universal_newlines", True) - kwds.setdefault("creationflags", flags) - p = subprocess.Popen(cmd, **kwds) - _subprocesses_started.add(p) - if PY3: - stdout, stderr = p.communicate(timeout=GLOBAL_TIMEOUT) - else: - stdout, stderr = p.communicate() - if p.returncode != 0: - raise RuntimeError(stderr) - if stderr: - warn(stderr) - if stdout.endswith('\n'): - stdout = stdout[:-1] - return stdout - - -def reap_children(recursive=False): - """Terminate and wait() any subprocess started by this test suite - and ensure that no zombies stick around to hog resources and - create problems when looking for refleaks. - - If resursive is True it also tries to terminate and wait() - all grandchildren started by this process. - """ - # This is here to make sure wait_procs() behaves properly and - # investigate: - # https://ci.appveyor.com/project/giampaolo/psutil/build/job/ - # jiq2cgd6stsbtn60 - def assert_gone(pid): - assert not psutil.pid_exists(pid), pid - assert pid not in psutil.pids(), pid - try: - p = psutil.Process(pid) - assert not p.is_running(), pid - except psutil.NoSuchProcess: - pass - else: - assert 0, "pid %s is not gone" % pid - - # Get the children here, before terminating the children sub - # processes as we don't want to lose the intermediate reference - # in case of grandchildren. - if recursive: - children = set(psutil.Process().children(recursive=True)) - else: - children = set() - - # Terminate subprocess.Popen instances "cleanly" by closing their - # fds and wiat()ing for them in order to avoid zombies. - while _subprocesses_started: - subp = _subprocesses_started.pop() - _pids_started.add(subp.pid) - try: - subp.terminate() - except OSError as err: - if WINDOWS and err.winerror == 6: # "invalid handle" - pass - elif err.errno != errno.ESRCH: - raise - if subp.stdout: - subp.stdout.close() - if subp.stderr: - subp.stderr.close() - try: - # Flushing a BufferedWriter may raise an error. - if subp.stdin: - subp.stdin.close() - finally: - # Wait for the process to terminate, to avoid zombies. - try: - subp.wait() - except ChildProcessError: - pass - - # Terminate started pids. - while _pids_started: - pid = _pids_started.pop() - try: - p = psutil.Process(pid) - except psutil.NoSuchProcess: - assert_gone(pid) - else: - children.add(p) - - # Terminate children. - if children: - for p in children: - try: - p.terminate() - except psutil.NoSuchProcess: - pass - gone, alive = psutil.wait_procs(children, timeout=GLOBAL_TIMEOUT) - for p in alive: - warn("couldn't terminate process %r; attempting kill()" % p) - try: - p.kill() - except psutil.NoSuchProcess: - pass - gone, alive = psutil.wait_procs(alive, timeout=GLOBAL_TIMEOUT) - if alive: - for p in alive: - warn("process %r survived kill()" % p) - - for p in children: - assert_gone(p.pid) - - -# =================================================================== -# --- OS -# =================================================================== - - -def get_kernel_version(): - """Return a tuple such as (2, 6, 36).""" - if not POSIX: - raise NotImplementedError("not POSIX") - s = "" - uname = os.uname()[2] - for c in uname: - if c.isdigit() or c == '.': - s += c - else: - break - if not s: - raise ValueError("can't parse %r" % uname) - minor = 0 - micro = 0 - nums = s.split('.') - major = int(nums[0]) - if len(nums) >= 2: - minor = int(nums[1]) - if len(nums) >= 3: - micro = int(nums[2]) - return (major, minor, micro) - - -def get_winver(): - if not WINDOWS: - raise NotImplementedError("not WINDOWS") - wv = sys.getwindowsversion() - if hasattr(wv, 'service_pack_major'): # python >= 2.7 - sp = wv.service_pack_major or 0 - else: - r = re.search(r"\s\d$", wv[4]) - if r: - sp = int(r.group(0)) - else: - sp = 0 - return (wv[0], wv[1], sp) - - -# =================================================================== -# --- sync primitives -# =================================================================== - - -class retry(object): - """A retry decorator.""" - - def __init__(self, - exception=Exception, - timeout=None, - retries=None, - interval=0.001, - logfun=None, - ): - if timeout and retries: - raise ValueError("timeout and retries args are mutually exclusive") - self.exception = exception - self.timeout = timeout - self.retries = retries - self.interval = interval - self.logfun = logfun - - def __iter__(self): - if self.timeout: - stop_at = time.time() + self.timeout - while time.time() < stop_at: - yield - elif self.retries: - for _ in range(self.retries): - yield - else: - while True: - yield - - def sleep(self): - if self.interval is not None: - time.sleep(self.interval) - - def __call__(self, fun): - @functools.wraps(fun) - def wrapper(*args, **kwargs): - exc = None - for _ in self: - try: - return fun(*args, **kwargs) - except self.exception as _: # NOQA - exc = _ - if self.logfun is not None: - self.logfun(exc) - self.sleep() - continue - if PY3: - raise exc - else: - raise - - # This way the user of the decorated function can change config - # parameters. - wrapper.decorator = self - return wrapper - - -@retry(exception=psutil.NoSuchProcess, logfun=None, timeout=GLOBAL_TIMEOUT, - interval=0.001) -def wait_for_pid(pid): - """Wait for pid to show up in the process list then return. - Used in the test suite to give time the sub process to initialize. - """ - psutil.Process(pid) - if WINDOWS: - # give it some more time to allow better initialization - time.sleep(0.01) - - -@retry(exception=(EnvironmentError, AssertionError), logfun=None, - timeout=GLOBAL_TIMEOUT, interval=0.001) -def wait_for_file(fname, delete=True, empty=False): - """Wait for a file to be written on disk with some content.""" - with open(fname, "rb") as f: - data = f.read() - if not empty: - assert data - if delete: - safe_rmpath(fname) - return data - - -@retry(exception=AssertionError, logfun=None, timeout=GLOBAL_TIMEOUT, - interval=0.001) -def call_until(fun, expr): - """Keep calling function for timeout secs and exit if eval() - expression is True. - """ - ret = fun() - assert eval(expr) - return ret - - -# =================================================================== -# --- fs -# =================================================================== - - -def safe_rmpath(path): - "Convenience function for removing temporary test files or dirs" - def retry_fun(fun): - # On Windows it could happen that the file or directory has - # open handles or references preventing the delete operation - # to succeed immediately, so we retry for a while. See: - # https://bugs.python.org/issue33240 - stop_at = time.time() + 1 - while time.time() < stop_at: - try: - return fun() - except FileNotFoundError: - pass - except WindowsError as _: - err = _ - warn("ignoring %s" % (str(err))) - time.sleep(0.01) - raise err - - try: - st = os.stat(path) - if stat.S_ISDIR(st.st_mode): - fun = functools.partial(shutil.rmtree, path) - else: - fun = functools.partial(os.remove, path) - if POSIX: - fun() - else: - retry_fun(fun) - except FileNotFoundError: - pass - - -def safe_mkdir(dir): - "Convenience function for creating a directory" - try: - os.mkdir(dir) - except FileExistsError: - pass - - -@contextlib.contextmanager -def chdir(dirname): - "Context manager which temporarily changes the current directory." - curdir = os.getcwd() - try: - os.chdir(dirname) - yield - finally: - os.chdir(curdir) - - -def create_exe(outpath, c_code=None): - """Creates an executable file in the given location.""" - assert not os.path.exists(outpath), outpath - if c_code: - if not which("gcc"): - raise ValueError("gcc is not installed") - if isinstance(c_code, bool): # c_code is True - c_code = textwrap.dedent( - """ - #include - int main() { - pause(); - return 1; - } - """) - assert isinstance(c_code, str), c_code - with tempfile.NamedTemporaryFile( - suffix='.c', delete=False, mode='wt') as f: - f.write(c_code) - try: - subprocess.check_call(["gcc", f.name, "-o", outpath]) - finally: - safe_rmpath(f.name) - else: - # copy python executable - shutil.copyfile(PYTHON_EXE, outpath) - if POSIX: - st = os.stat(outpath) - os.chmod(outpath, st.st_mode | stat.S_IEXEC) - - -def unique_filename(prefix=TESTFILE_PREFIX, suffix=""): - return tempfile.mktemp(prefix=prefix, suffix=suffix) - - -# =================================================================== -# --- testing -# =================================================================== - - -class TestCase(unittest.TestCase): - - # Print a full path representation of the single unit tests - # being run. - def __str__(self): - fqmod = self.__class__.__module__ - if not fqmod.startswith('psutil.'): - fqmod = 'psutil.tests.' + fqmod - return "%s.%s.%s" % ( - fqmod, self.__class__.__name__, self._testMethodName) - - # assertRaisesRegexp renamed to assertRaisesRegex in 3.3; - # add support for the new name. - if not hasattr(unittest.TestCase, 'assertRaisesRegex'): - assertRaisesRegex = unittest.TestCase.assertRaisesRegexp - - -# override default unittest.TestCase -unittest.TestCase = TestCase - - -def retry_on_failure(retries=NO_RETRIES): - """Decorator which runs a test function and retries N times before - actually failing. - """ - def logfun(exc): - print("%r, retrying" % exc, file=sys.stderr) - - return retry(exception=AssertionError, timeout=None, retries=retries, - logfun=logfun) - - -def skip_on_access_denied(only_if=None): - """Decorator to Ignore AccessDenied exceptions.""" - def decorator(fun): - @functools.wraps(fun) - def wrapper(*args, **kwargs): - try: - return fun(*args, **kwargs) - except psutil.AccessDenied: - if only_if is not None: - if not only_if: - raise - raise unittest.SkipTest("raises AccessDenied") - return wrapper - return decorator - - -def skip_on_not_implemented(only_if=None): - """Decorator to Ignore NotImplementedError exceptions.""" - def decorator(fun): - @functools.wraps(fun) - def wrapper(*args, **kwargs): - try: - return fun(*args, **kwargs) - except NotImplementedError: - if only_if is not None: - if not only_if: - raise - msg = "%r was skipped because it raised NotImplementedError" \ - % fun.__name__ - raise unittest.SkipTest(msg) - return wrapper - return decorator - - -# =================================================================== -# --- network -# =================================================================== - - -def get_free_port(host='127.0.0.1'): - """Return an unused TCP port.""" - with contextlib.closing(socket.socket()) as sock: - sock.bind((host, 0)) - return sock.getsockname()[1] - - -@contextlib.contextmanager -def unix_socket_path(suffix=""): - """A context manager which returns a non-existent file name - and tries to delete it on exit. - """ - assert psutil.POSIX - path = unique_filename(suffix=suffix) - try: - yield path - finally: - try: - os.unlink(path) - except OSError: - pass - - -def bind_socket(family=AF_INET, type=SOCK_STREAM, addr=None): - """Binds a generic socket.""" - if addr is None and family in (AF_INET, AF_INET6): - addr = ("", 0) - sock = socket.socket(family, type) - try: - if os.name not in ('nt', 'cygwin'): - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - sock.bind(addr) - if type == socket.SOCK_STREAM: - sock.listen(5) - return sock - except Exception: - sock.close() - raise - - -def bind_unix_socket(name, type=socket.SOCK_STREAM): - """Bind a UNIX socket.""" - assert psutil.POSIX - assert not os.path.exists(name), name - sock = socket.socket(socket.AF_UNIX, type) - try: - sock.bind(name) - if type == socket.SOCK_STREAM: - sock.listen(5) - except Exception: - sock.close() - raise - return sock - - -def tcp_socketpair(family, addr=("", 0)): - """Build a pair of TCP sockets connected to each other. - Return a (server, client) tuple. - """ - with contextlib.closing(socket.socket(family, SOCK_STREAM)) as ll: - ll.bind(addr) - ll.listen(5) - addr = ll.getsockname() - c = socket.socket(family, SOCK_STREAM) - try: - c.connect(addr) - caddr = c.getsockname() - while True: - a, addr = ll.accept() - # check that we've got the correct client - if addr == caddr: - return (a, c) - a.close() - except OSError: - c.close() - raise - - -def unix_socketpair(name): - """Build a pair of UNIX sockets connected to each other through - the same UNIX file name. - Return a (server, client) tuple. - """ - assert psutil.POSIX - server = client = None - try: - server = bind_unix_socket(name, type=socket.SOCK_STREAM) - server.setblocking(0) - client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - client.setblocking(0) - client.connect(name) - # new = server.accept() - except Exception: - if server is not None: - server.close() - if client is not None: - client.close() - raise - return (server, client) - - -@contextlib.contextmanager -def create_sockets(): - """Open as many socket families / types as possible.""" - socks = [] - fname1 = fname2 = None - try: - socks.append(bind_socket(socket.AF_INET, socket.SOCK_STREAM)) - socks.append(bind_socket(socket.AF_INET, socket.SOCK_DGRAM)) - if supports_ipv6(): - socks.append(bind_socket(socket.AF_INET6, socket.SOCK_STREAM)) - socks.append(bind_socket(socket.AF_INET6, socket.SOCK_DGRAM)) - if POSIX and HAS_CONNECTIONS_UNIX: - fname1 = unix_socket_path().__enter__() - fname2 = unix_socket_path().__enter__() - s1, s2 = unix_socketpair(fname1) - s3 = bind_unix_socket(fname2, type=socket.SOCK_DGRAM) - # self.addCleanup(safe_rmpath, fname1) - # self.addCleanup(safe_rmpath, fname2) - for s in (s1, s2, s3): - socks.append(s) - yield socks - finally: - for s in socks: - s.close() - if fname1 is not None: - safe_rmpath(fname1) - if fname2 is not None: - safe_rmpath(fname2) - - -def check_net_address(addr, family): - """Check a net address validity. Supported families are IPv4, - IPv6 and MAC addresses. - """ - import ipaddress # python >= 3.3 / requires "pip install ipaddress" - if enum and PY3: - assert isinstance(family, enum.IntEnum), family - if family == socket.AF_INET: - octs = [int(x) for x in addr.split('.')] - assert len(octs) == 4, addr - for num in octs: - assert 0 <= num <= 255, addr - if not PY3: - addr = unicode(addr) - ipaddress.IPv4Address(addr) - elif family == socket.AF_INET6: - assert isinstance(addr, str), addr - if not PY3: - addr = unicode(addr) - ipaddress.IPv6Address(addr) - elif family == psutil.AF_LINK: - assert re.match(r'([a-fA-F0-9]{2}[:|\-]?){6}', addr) is not None, addr - else: - raise ValueError("unknown family %r", family) - - -# =================================================================== -# --- compatibility -# =================================================================== - - -def reload_module(module): - """Backport of importlib.reload of Python 3.3+.""" - try: - import importlib - if not hasattr(importlib, 'reload'): # python <=3.3 - raise ImportError - except ImportError: - import imp - return imp.reload(module) - else: - return importlib.reload(module) - - -def import_module_by_path(path): - name = os.path.splitext(os.path.basename(path))[0] - if sys.version_info[0] == 2: - import imp - return imp.load_source(name, path) - elif sys.version_info[:2] <= (3, 4): - from importlib.machinery import SourceFileLoader - return SourceFileLoader(name, path).load_module() - else: - import importlib.util - spec = importlib.util.spec_from_file_location(name, path) - mod = importlib.util.module_from_spec(spec) - spec.loader.exec_module(mod) - return mod - - -# =================================================================== -# --- others -# =================================================================== - - -def warn(msg): - """Raise a warning msg.""" - warnings.warn(msg, UserWarning) - - -def is_namedtuple(x): - """Check if object is an instance of namedtuple.""" - t = type(x) - b = t.__bases__ - if len(b) != 1 or b[0] != tuple: - return False - f = getattr(t, '_fields', None) - if not isinstance(f, tuple): - return False - return all(type(n) == str for n in f) - - -if POSIX: - @contextlib.contextmanager - def copyload_shared_lib(dst_prefix=TESTFILE_PREFIX): - """Ctx manager which picks up a random shared CO lib used - by this process, copies it in another location and loads it - in memory via ctypes. Return the new absolutized path. - """ - exe = 'pypy' if PYPY else 'python' - ext = ".so" - dst = tempfile.mktemp(prefix=dst_prefix, suffix=ext) - libs = [x.path for x in psutil.Process().memory_maps() if - os.path.splitext(x.path)[1] == ext and - exe in x.path.lower()] - src = random.choice(libs) - shutil.copyfile(src, dst) - try: - ctypes.CDLL(dst) - yield dst - finally: - safe_rmpath(dst) -else: - @contextlib.contextmanager - def copyload_shared_lib(dst_prefix=TESTFILE_PREFIX): - """Ctx manager which picks up a random shared DLL lib used - by this process, copies it in another location and loads it - in memory via ctypes. - Return the new absolutized, normcased path. - """ - from ctypes import wintypes - from ctypes import WinError - ext = ".dll" - dst = tempfile.mktemp(prefix=dst_prefix, suffix=ext) - libs = [x.path for x in psutil.Process().memory_maps() if - x.path.lower().endswith(ext) and - 'python' in os.path.basename(x.path).lower() and - 'wow64' not in x.path.lower()] - if PYPY and not libs: - libs = [x.path for x in psutil.Process().memory_maps() if - 'pypy' in os.path.basename(x.path).lower()] - src = random.choice(libs) - shutil.copyfile(src, dst) - cfile = None - try: - cfile = ctypes.WinDLL(dst) - yield dst - finally: - # Work around OverflowError: - # - https://ci.appveyor.com/project/giampaolo/psutil/build/1207/ - # job/o53330pbnri9bcw7 - # - http://bugs.python.org/issue30286 - # - http://stackoverflow.com/questions/23522055 - if cfile is not None: - FreeLibrary = ctypes.windll.kernel32.FreeLibrary - FreeLibrary.argtypes = [wintypes.HMODULE] - ret = FreeLibrary(cfile._handle) - if ret == 0: - WinError() - safe_rmpath(dst) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/__main__.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/__main__.py deleted file mode 100644 index d5cd02eb1c28..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/__main__.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Run unit tests. This is invoked by: -$ python -m psutil.tests -""" - -from .runner import main -main() diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/runner.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/runner.py deleted file mode 100644 index 2e9264bd4281..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/runner.py +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Unit test runner, providing new features on top of unittest module: -- colourized output (error, skip) -- print failures/tracebacks on CTRL+C -- re-run failed tests only (make test-failed) -""" - -from __future__ import print_function -import optparse -import os -import sys -import unittest -from unittest import TestResult -from unittest import TextTestResult -from unittest import TextTestRunner -try: - import ctypes -except ImportError: - ctypes = None - -import psutil -from psutil._common import hilite -from psutil._common import print_color -from psutil._common import term_supports_colors -from psutil.tests import safe_rmpath -from psutil.tests import TOX - - -HERE = os.path.abspath(os.path.dirname(__file__)) -VERBOSITY = 1 if TOX else 2 -FAILED_TESTS_FNAME = '.failed-tests.txt' - - -# ===================================================================== -# --- unittest subclasses -# ===================================================================== - - -class ColouredResult(TextTestResult): - - def _print_color(self, s, color, bold=False): - file = sys.stderr if color == "red" else sys.stdout - print_color(s, color, bold=bold, file=file) - - def addSuccess(self, test): - TestResult.addSuccess(self, test) - self._print_color("OK", "green") - - def addError(self, test, err): - TestResult.addError(self, test, err) - self._print_color("ERROR", "red", bold=True) - - def addFailure(self, test, err): - TestResult.addFailure(self, test, err) - self._print_color("FAIL", "red") - - def addSkip(self, test, reason): - TestResult.addSkip(self, test, reason) - self._print_color("skipped: %s" % reason, "brown") - - def printErrorList(self, flavour, errors): - flavour = hilite(flavour, "red", bold=flavour == 'ERROR') - TextTestResult.printErrorList(self, flavour, errors) - - -class ColouredRunner(TextTestRunner): - resultclass = ColouredResult if term_supports_colors() else TextTestResult - - def _makeResult(self): - # Store result instance so that it can be accessed on - # KeyboardInterrupt. - self.result = TextTestRunner._makeResult(self) - return self.result - - -# ===================================================================== -# --- public API -# ===================================================================== - - -def setup_tests(): - if 'PSUTIL_TESTING' not in os.environ: - # This won't work on Windows but set_testing() below will do it. - os.environ['PSUTIL_TESTING'] = '1' - psutil._psplatform.cext.set_testing() - - -def get_suite(name=None): - suite = unittest.TestSuite() - if name is None: - testmods = [os.path.splitext(x)[0] for x in os.listdir(HERE) - if x.endswith('.py') and x.startswith('test_') and not - x.startswith('test_memory_leaks')] - if "WHEELHOUSE_UPLOADER_USERNAME" in os.environ: - testmods = [x for x in testmods if not x.endswith(( - "osx", "posix", "linux"))] - for tm in testmods: - # ...so that the full test paths are printed on screen - tm = "psutil.tests.%s" % tm - suite.addTest(unittest.defaultTestLoader.loadTestsFromName(tm)) - else: - name = os.path.splitext(os.path.basename(name))[0] - suite.addTest(unittest.defaultTestLoader.loadTestsFromName(name)) - return suite - - -def get_suite_from_failed(): - # ...from previously failed test run - suite = unittest.TestSuite() - if not os.path.isfile(FAILED_TESTS_FNAME): - return suite - with open(FAILED_TESTS_FNAME, 'rt') as f: - names = f.read().split() - for n in names: - suite.addTest(unittest.defaultTestLoader.loadTestsFromName(n)) - return suite - - -def save_failed_tests(result): - if result.wasSuccessful(): - return safe_rmpath(FAILED_TESTS_FNAME) - with open(FAILED_TESTS_FNAME, 'wt') as f: - for t in result.errors + result.failures: - tname = str(t[0]) - unittest.defaultTestLoader.loadTestsFromName(tname) - f.write(tname + '\n') - - -def run(name=None, last_failed=False): - setup_tests() - runner = ColouredRunner(verbosity=VERBOSITY) - suite = get_suite_from_failed() if last_failed else get_suite(name) - try: - result = runner.run(suite) - except (KeyboardInterrupt, SystemExit) as err: - print("received %s" % err.__class__.__name__, file=sys.stderr) - runner.result.printErrors() - sys.exit(1) - else: - save_failed_tests(result) - success = result.wasSuccessful() - sys.exit(0 if success else 1) - - -def main(): - usage = "python3 -m psutil.tests [opts]" - parser = optparse.OptionParser(usage=usage, description="run unit tests") - parser.add_option("--last-failed", - action="store_true", default=False, - help="only run last failed tests") - opts, args = parser.parse_args() - run(last_failed=opts.last_failed) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_aix.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_aix.py deleted file mode 100644 index 7171232e08f1..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_aix.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2009, Giampaolo Rodola' -# Copyright (c) 2017, Arnon Yaari -# All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""AIX specific tests.""" - -import re - -from psutil import AIX -from psutil.tests import sh -from psutil.tests import unittest -import psutil - - -@unittest.skipIf(not AIX, "AIX only") -class AIXSpecificTestCase(unittest.TestCase): - - def test_virtual_memory(self): - out = sh('/usr/bin/svmon -O unit=KB') - re_pattern = r"memory\s*" - for field in ("size inuse free pin virtual available mmode").split(): - re_pattern += r"(?P<%s>\S+)\s+" % (field,) - matchobj = re.search(re_pattern, out) - - self.assertIsNotNone( - matchobj, "svmon command returned unexpected output") - - KB = 1024 - total = int(matchobj.group("size")) * KB - available = int(matchobj.group("available")) * KB - used = int(matchobj.group("inuse")) * KB - free = int(matchobj.group("free")) * KB - - psutil_result = psutil.virtual_memory() - - # MEMORY_TOLERANCE from psutil.tests is not enough. For some reason - # we're seeing differences of ~1.2 MB. 2 MB is still a good tolerance - # when compared to GBs. - MEMORY_TOLERANCE = 2 * KB * KB # 2 MB - self.assertEqual(psutil_result.total, total) - self.assertAlmostEqual( - psutil_result.used, used, delta=MEMORY_TOLERANCE) - self.assertAlmostEqual( - psutil_result.available, available, delta=MEMORY_TOLERANCE) - self.assertAlmostEqual( - psutil_result.free, free, delta=MEMORY_TOLERANCE) - - def test_swap_memory(self): - out = sh('/usr/sbin/lsps -a') - # From the man page, "The size is given in megabytes" so we assume - # we'll always have 'MB' in the result - # TODO maybe try to use "swap -l" to check "used" too, but its units - # are not guaranteed to be "MB" so parsing may not be consistent - matchobj = re.search(r"(?P\S+)\s+" - r"(?P\S+)\s+" - r"(?P\S+)\s+" - r"(?P\d+)MB", out) - - self.assertIsNotNone( - matchobj, "lsps command returned unexpected output") - - total_mb = int(matchobj.group("size")) - MB = 1024 ** 2 - psutil_result = psutil.swap_memory() - # we divide our result by MB instead of multiplying the lsps value by - # MB because lsps may round down, so we round down too - self.assertEqual(int(psutil_result.total / MB), total_mb) - - def test_cpu_stats(self): - out = sh('/usr/bin/mpstat -a') - - re_pattern = r"ALL\s*" - for field in ("min maj mpcs mpcr dev soft dec ph cs ics bound rq " - "push S3pull S3grd S0rd S1rd S2rd S3rd S4rd S5rd " - "sysc").split(): - re_pattern += r"(?P<%s>\S+)\s+" % (field,) - matchobj = re.search(re_pattern, out) - - self.assertIsNotNone( - matchobj, "mpstat command returned unexpected output") - - # numbers are usually in the millions so 1000 is ok for tolerance - CPU_STATS_TOLERANCE = 1000 - psutil_result = psutil.cpu_stats() - self.assertAlmostEqual( - psutil_result.ctx_switches, - int(matchobj.group("cs")), - delta=CPU_STATS_TOLERANCE) - self.assertAlmostEqual( - psutil_result.syscalls, - int(matchobj.group("sysc")), - delta=CPU_STATS_TOLERANCE) - self.assertAlmostEqual( - psutil_result.interrupts, - int(matchobj.group("dev")), - delta=CPU_STATS_TOLERANCE) - self.assertAlmostEqual( - psutil_result.soft_interrupts, - int(matchobj.group("soft")), - delta=CPU_STATS_TOLERANCE) - - def test_cpu_count_logical(self): - out = sh('/usr/bin/mpstat -a') - mpstat_lcpu = int(re.search(r"lcpu=(\d+)", out).group(1)) - psutil_lcpu = psutil.cpu_count(logical=True) - self.assertEqual(mpstat_lcpu, psutil_lcpu) - - def test_net_if_addrs_names(self): - out = sh('/etc/ifconfig -l') - ifconfig_names = set(out.split()) - psutil_names = set(psutil.net_if_addrs().keys()) - self.assertSetEqual(ifconfig_names, psutil_names) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_bsd.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_bsd.py deleted file mode 100644 index 899875d076dc..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_bsd.py +++ /dev/null @@ -1,565 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -# TODO: (FreeBSD) add test for comparing connections with 'sockstat' cmd. - - -"""Tests specific to all BSD platforms.""" - - -import datetime -import os -import re -import time - -import psutil -from psutil import BSD -from psutil import FREEBSD -from psutil import NETBSD -from psutil import OPENBSD -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_BATTERY -from psutil.tests import MEMORY_TOLERANCE -from psutil.tests import reap_children -from psutil.tests import retry_on_failure -from psutil.tests import sh -from psutil.tests import unittest -from psutil.tests import which - - -if BSD: - PAGESIZE = os.sysconf("SC_PAGE_SIZE") - if os.getuid() == 0: # muse requires root privileges - MUSE_AVAILABLE = which('muse') - else: - MUSE_AVAILABLE = False -else: - MUSE_AVAILABLE = False - - -def sysctl(cmdline): - """Expects a sysctl command with an argument and parse the result - returning only the value of interest. - """ - result = sh("sysctl " + cmdline) - if FREEBSD: - result = result[result.find(": ") + 2:] - elif OPENBSD or NETBSD: - result = result[result.find("=") + 1:] - try: - return int(result) - except ValueError: - return result - - -def muse(field): - """Thin wrapper around 'muse' cmdline utility.""" - out = sh('muse') - for line in out.split('\n'): - if line.startswith(field): - break - else: - raise ValueError("line not found") - return int(line.split()[1]) - - -# ===================================================================== -# --- All BSD* -# ===================================================================== - - -@unittest.skipIf(not BSD, "BSD only") -class BSDTestCase(unittest.TestCase): - """Generic tests common to all BSD variants.""" - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - @unittest.skipIf(NETBSD, "-o lstart doesn't work on NETBSD") - def test_process_create_time(self): - output = sh("ps -o lstart -p %s" % self.pid) - start_ps = output.replace('STARTED', '').strip() - start_psutil = psutil.Process(self.pid).create_time() - start_psutil = time.strftime("%a %b %e %H:%M:%S %Y", - time.localtime(start_psutil)) - self.assertEqual(start_ps, start_psutil) - - def test_disks(self): - # test psutil.disk_usage() and psutil.disk_partitions() - # against "df -a" - def df(path): - out = sh('df -k "%s"' % path).strip() - lines = out.split('\n') - lines.pop(0) - line = lines.pop(0) - dev, total, used, free = line.split()[:4] - if dev == 'none': - dev = '' - total = int(total) * 1024 - used = int(used) * 1024 - free = int(free) * 1024 - return dev, total, used, free - - for part in psutil.disk_partitions(all=False): - usage = psutil.disk_usage(part.mountpoint) - dev, total, used, free = df(part.mountpoint) - self.assertEqual(part.device, dev) - self.assertEqual(usage.total, total) - # 10 MB tollerance - if abs(usage.free - free) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.free, free)) - if abs(usage.used - used) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.used, used)) - - @unittest.skipIf(not which('sysctl'), "sysctl cmd not available") - def test_cpu_count_logical(self): - syst = sysctl("hw.ncpu") - self.assertEqual(psutil.cpu_count(logical=True), syst) - - @unittest.skipIf(not which('sysctl'), "sysctl cmd not available") - def test_virtual_memory_total(self): - num = sysctl('hw.physmem') - self.assertEqual(num, psutil.virtual_memory().total) - - def test_net_if_stats(self): - for name, stats in psutil.net_if_stats().items(): - try: - out = sh("ifconfig %s" % name) - except RuntimeError: - pass - else: - self.assertEqual(stats.isup, 'RUNNING' in out, msg=out) - if "mtu" in out: - self.assertEqual(stats.mtu, - int(re.findall(r'mtu (\d+)', out)[0])) - - -# ===================================================================== -# --- FreeBSD -# ===================================================================== - - -@unittest.skipIf(not FREEBSD, "FREEBSD only") -class FreeBSDProcessTestCase(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - @retry_on_failure() - def test_memory_maps(self): - out = sh('procstat -v %s' % self.pid) - maps = psutil.Process(self.pid).memory_maps(grouped=False) - lines = out.split('\n')[1:] - while lines: - line = lines.pop() - fields = line.split() - _, start, stop, perms, res = fields[:5] - map = maps.pop() - self.assertEqual("%s-%s" % (start, stop), map.addr) - self.assertEqual(int(res), map.rss) - if not map.path.startswith('['): - self.assertEqual(fields[10], map.path) - - def test_exe(self): - out = sh('procstat -b %s' % self.pid) - self.assertEqual(psutil.Process(self.pid).exe(), - out.split('\n')[1].split()[-1]) - - def test_cmdline(self): - out = sh('procstat -c %s' % self.pid) - self.assertEqual(' '.join(psutil.Process(self.pid).cmdline()), - ' '.join(out.split('\n')[1].split()[2:])) - - def test_uids_gids(self): - out = sh('procstat -s %s' % self.pid) - euid, ruid, suid, egid, rgid, sgid = out.split('\n')[1].split()[2:8] - p = psutil.Process(self.pid) - uids = p.uids() - gids = p.gids() - self.assertEqual(uids.real, int(ruid)) - self.assertEqual(uids.effective, int(euid)) - self.assertEqual(uids.saved, int(suid)) - self.assertEqual(gids.real, int(rgid)) - self.assertEqual(gids.effective, int(egid)) - self.assertEqual(gids.saved, int(sgid)) - - @retry_on_failure() - def test_ctx_switches(self): - tested = [] - out = sh('procstat -r %s' % self.pid) - p = psutil.Process(self.pid) - for line in out.split('\n'): - line = line.lower().strip() - if ' voluntary context' in line: - pstat_value = int(line.split()[-1]) - psutil_value = p.num_ctx_switches().voluntary - self.assertEqual(pstat_value, psutil_value) - tested.append(None) - elif ' involuntary context' in line: - pstat_value = int(line.split()[-1]) - psutil_value = p.num_ctx_switches().involuntary - self.assertEqual(pstat_value, psutil_value) - tested.append(None) - if len(tested) != 2: - raise RuntimeError("couldn't find lines match in procstat out") - - @retry_on_failure() - def test_cpu_times(self): - tested = [] - out = sh('procstat -r %s' % self.pid) - p = psutil.Process(self.pid) - for line in out.split('\n'): - line = line.lower().strip() - if 'user time' in line: - pstat_value = float('0.' + line.split()[-1].split('.')[-1]) - psutil_value = p.cpu_times().user - self.assertEqual(pstat_value, psutil_value) - tested.append(None) - elif 'system time' in line: - pstat_value = float('0.' + line.split()[-1].split('.')[-1]) - psutil_value = p.cpu_times().system - self.assertEqual(pstat_value, psutil_value) - tested.append(None) - if len(tested) != 2: - raise RuntimeError("couldn't find lines match in procstat out") - - -@unittest.skipIf(not FREEBSD, "FREEBSD only") -class FreeBSDSystemTestCase(unittest.TestCase): - - @staticmethod - def parse_swapinfo(): - # the last line is always the total - output = sh("swapinfo -k").splitlines()[-1] - parts = re.split(r'\s+', output) - - if not parts: - raise ValueError("Can't parse swapinfo: %s" % output) - - # the size is in 1k units, so multiply by 1024 - total, used, free = (int(p) * 1024 for p in parts[1:4]) - return total, used, free - - def test_cpu_frequency_against_sysctl(self): - # Currently only cpu 0 is frequency is supported in FreeBSD - # All other cores use the same frequency. - sensor = "dev.cpu.0.freq" - try: - sysctl_result = int(sysctl(sensor)) - except RuntimeError: - self.skipTest("frequencies not supported by kernel") - self.assertEqual(psutil.cpu_freq().current, sysctl_result) - - sensor = "dev.cpu.0.freq_levels" - sysctl_result = sysctl(sensor) - # sysctl returns a string of the format: - # / /... - # Ordered highest available to lowest available. - max_freq = int(sysctl_result.split()[0].split("/")[0]) - min_freq = int(sysctl_result.split()[-1].split("/")[0]) - self.assertEqual(psutil.cpu_freq().max, max_freq) - self.assertEqual(psutil.cpu_freq().min, min_freq) - - # --- virtual_memory(); tests against sysctl - - @retry_on_failure() - def test_vmem_active(self): - syst = sysctl("vm.stats.vm.v_active_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().active, syst, - delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_inactive(self): - syst = sysctl("vm.stats.vm.v_inactive_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().inactive, syst, - delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_wired(self): - syst = sysctl("vm.stats.vm.v_wire_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().wired, syst, - delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_cached(self): - syst = sysctl("vm.stats.vm.v_cache_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().cached, syst, - delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_free(self): - syst = sysctl("vm.stats.vm.v_free_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().free, syst, - delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_buffers(self): - syst = sysctl("vfs.bufspace") - self.assertAlmostEqual(psutil.virtual_memory().buffers, syst, - delta=MEMORY_TOLERANCE) - - # --- virtual_memory(); tests against muse - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - def test_muse_vmem_total(self): - num = muse('Total') - self.assertEqual(psutil.virtual_memory().total, num) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_active(self): - num = muse('Active') - self.assertAlmostEqual(psutil.virtual_memory().active, num, - delta=MEMORY_TOLERANCE) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_inactive(self): - num = muse('Inactive') - self.assertAlmostEqual(psutil.virtual_memory().inactive, num, - delta=MEMORY_TOLERANCE) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_wired(self): - num = muse('Wired') - self.assertAlmostEqual(psutil.virtual_memory().wired, num, - delta=MEMORY_TOLERANCE) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_cached(self): - num = muse('Cache') - self.assertAlmostEqual(psutil.virtual_memory().cached, num, - delta=MEMORY_TOLERANCE) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_free(self): - num = muse('Free') - self.assertAlmostEqual(psutil.virtual_memory().free, num, - delta=MEMORY_TOLERANCE) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_buffers(self): - num = muse('Buffer') - self.assertAlmostEqual(psutil.virtual_memory().buffers, num, - delta=MEMORY_TOLERANCE) - - def test_cpu_stats_ctx_switches(self): - self.assertAlmostEqual(psutil.cpu_stats().ctx_switches, - sysctl('vm.stats.sys.v_swtch'), delta=1000) - - def test_cpu_stats_interrupts(self): - self.assertAlmostEqual(psutil.cpu_stats().interrupts, - sysctl('vm.stats.sys.v_intr'), delta=1000) - - def test_cpu_stats_soft_interrupts(self): - self.assertAlmostEqual(psutil.cpu_stats().soft_interrupts, - sysctl('vm.stats.sys.v_soft'), delta=1000) - - @retry_on_failure() - def test_cpu_stats_syscalls(self): - # pretty high tolerance but it looks like it's OK. - self.assertAlmostEqual(psutil.cpu_stats().syscalls, - sysctl('vm.stats.sys.v_syscall'), delta=200000) - - # def test_cpu_stats_traps(self): - # self.assertAlmostEqual(psutil.cpu_stats().traps, - # sysctl('vm.stats.sys.v_trap'), delta=1000) - - # --- swap memory - - def test_swapmem_free(self): - total, used, free = self.parse_swapinfo() - self.assertAlmostEqual( - psutil.swap_memory().free, free, delta=MEMORY_TOLERANCE) - - def test_swapmem_used(self): - total, used, free = self.parse_swapinfo() - self.assertAlmostEqual( - psutil.swap_memory().used, used, delta=MEMORY_TOLERANCE) - - def test_swapmem_total(self): - total, used, free = self.parse_swapinfo() - self.assertAlmostEqual( - psutil.swap_memory().total, total, delta=MEMORY_TOLERANCE) - - # --- others - - def test_boot_time(self): - s = sysctl('sysctl kern.boottime') - s = s[s.find(" sec = ") + 7:] - s = s[:s.find(',')] - btime = int(s) - self.assertEqual(btime, psutil.boot_time()) - - # --- sensors_battery - - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_sensors_battery(self): - def secs2hours(secs): - m, s = divmod(secs, 60) - h, m = divmod(m, 60) - return "%d:%02d" % (h, m) - - out = sh("acpiconf -i 0") - fields = dict([(x.split('\t')[0], x.split('\t')[-1]) - for x in out.split("\n")]) - metrics = psutil.sensors_battery() - percent = int(fields['Remaining capacity:'].replace('%', '')) - remaining_time = fields['Remaining time:'] - self.assertEqual(metrics.percent, percent) - if remaining_time == 'unknown': - self.assertEqual(metrics.secsleft, psutil.POWER_TIME_UNLIMITED) - else: - self.assertEqual(secs2hours(metrics.secsleft), remaining_time) - - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_sensors_battery_against_sysctl(self): - self.assertEqual(psutil.sensors_battery().percent, - sysctl("hw.acpi.battery.life")) - self.assertEqual(psutil.sensors_battery().power_plugged, - sysctl("hw.acpi.acline") == 1) - secsleft = psutil.sensors_battery().secsleft - if secsleft < 0: - self.assertEqual(sysctl("hw.acpi.battery.time"), -1) - else: - self.assertEqual(secsleft, sysctl("hw.acpi.battery.time") * 60) - - @unittest.skipIf(HAS_BATTERY, "has battery") - def test_sensors_battery_no_battery(self): - # If no battery is present one of these calls is supposed - # to fail, see: - # https://github.com/giampaolo/psutil/issues/1074 - with self.assertRaises(RuntimeError): - sysctl("hw.acpi.battery.life") - sysctl("hw.acpi.battery.time") - sysctl("hw.acpi.acline") - self.assertIsNone(psutil.sensors_battery()) - - # --- sensors_temperatures - - def test_sensors_temperatures_against_sysctl(self): - num_cpus = psutil.cpu_count(True) - for cpu in range(num_cpus): - sensor = "dev.cpu.%s.temperature" % cpu - # sysctl returns a string in the format 46.0C - try: - sysctl_result = int(float(sysctl(sensor)[:-1])) - except RuntimeError: - self.skipTest("temperatures not supported by kernel") - self.assertAlmostEqual( - psutil.sensors_temperatures()["coretemp"][cpu].current, - sysctl_result, delta=10) - - sensor = "dev.cpu.%s.coretemp.tjmax" % cpu - sysctl_result = int(float(sysctl(sensor)[:-1])) - self.assertEqual( - psutil.sensors_temperatures()["coretemp"][cpu].high, - sysctl_result) - -# ===================================================================== -# --- OpenBSD -# ===================================================================== - - -@unittest.skipIf(not OPENBSD, "OPENBSD only") -class OpenBSDTestCase(unittest.TestCase): - - def test_boot_time(self): - s = sysctl('kern.boottime') - sys_bt = datetime.datetime.strptime(s, "%a %b %d %H:%M:%S %Y") - psutil_bt = datetime.datetime.fromtimestamp(psutil.boot_time()) - self.assertEqual(sys_bt, psutil_bt) - - -# ===================================================================== -# --- NetBSD -# ===================================================================== - - -@unittest.skipIf(not NETBSD, "NETBSD only") -class NetBSDTestCase(unittest.TestCase): - - @staticmethod - def parse_meminfo(look_for): - with open('/proc/meminfo', 'rt') as f: - for line in f: - if line.startswith(look_for): - return int(line.split()[1]) * 1024 - raise ValueError("can't find %s" % look_for) - - def test_vmem_total(self): - self.assertEqual( - psutil.virtual_memory().total, self.parse_meminfo("MemTotal:")) - - def test_vmem_free(self): - self.assertAlmostEqual( - psutil.virtual_memory().free, self.parse_meminfo("MemFree:"), - delta=MEMORY_TOLERANCE) - - def test_vmem_buffers(self): - self.assertAlmostEqual( - psutil.virtual_memory().buffers, self.parse_meminfo("Buffers:"), - delta=MEMORY_TOLERANCE) - - def test_vmem_shared(self): - self.assertAlmostEqual( - psutil.virtual_memory().shared, self.parse_meminfo("MemShared:"), - delta=MEMORY_TOLERANCE) - - def test_swapmem_total(self): - self.assertAlmostEqual( - psutil.swap_memory().total, self.parse_meminfo("SwapTotal:"), - delta=MEMORY_TOLERANCE) - - def test_swapmem_free(self): - self.assertAlmostEqual( - psutil.swap_memory().free, self.parse_meminfo("SwapFree:"), - delta=MEMORY_TOLERANCE) - - def test_swapmem_used(self): - smem = psutil.swap_memory() - self.assertEqual(smem.used, smem.total - smem.free) - - def test_cpu_stats_interrupts(self): - with open('/proc/stat', 'rb') as f: - for line in f: - if line.startswith(b'intr'): - interrupts = int(line.split()[1]) - break - else: - raise ValueError("couldn't find line") - self.assertAlmostEqual( - psutil.cpu_stats().interrupts, interrupts, delta=1000) - - def test_cpu_stats_ctx_switches(self): - with open('/proc/stat', 'rb') as f: - for line in f: - if line.startswith(b'ctxt'): - ctx_switches = int(line.split()[1]) - break - else: - raise ValueError("couldn't find line") - self.assertAlmostEqual( - psutil.cpu_stats().ctx_switches, ctx_switches, delta=1000) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_connections.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_connections.py deleted file mode 100644 index 972ac9d58ccb..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_connections.py +++ /dev/null @@ -1,637 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Tests for net_connections() and Process.connections() APIs.""" - -import contextlib -import errno -import os -import socket -import textwrap -from contextlib import closing -from socket import AF_INET -from socket import AF_INET6 -from socket import SOCK_DGRAM -from socket import SOCK_STREAM - -import psutil -from psutil import FREEBSD -from psutil import LINUX -from psutil import MACOS -from psutil import NETBSD -from psutil import OPENBSD -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -from psutil._common import supports_ipv6 -from psutil._compat import PY3 -from psutil.tests import AF_UNIX -from psutil.tests import bind_socket -from psutil.tests import bind_unix_socket -from psutil.tests import check_net_address -from psutil.tests import CIRRUS -from psutil.tests import create_sockets -from psutil.tests import enum -from psutil.tests import get_free_port -from psutil.tests import HAS_CONNECTIONS_UNIX -from psutil.tests import pyrun -from psutil.tests import reap_children -from psutil.tests import safe_rmpath -from psutil.tests import skip_on_access_denied -from psutil.tests import SKIP_SYSCONS -from psutil.tests import tcp_socketpair -from psutil.tests import TESTFN -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import unix_socket_path -from psutil.tests import unix_socketpair -from psutil.tests import wait_for_file - - -thisproc = psutil.Process() -SOCK_SEQPACKET = getattr(socket, "SOCK_SEQPACKET", object()) - - -class Base(object): - - def setUp(self): - safe_rmpath(TESTFN) - if not (NETBSD or FREEBSD): - # process opens a UNIX socket to /var/log/run. - cons = thisproc.connections(kind='all') - assert not cons, cons - - def tearDown(self): - safe_rmpath(TESTFN) - reap_children() - if not (FREEBSD or NETBSD): - # Make sure we closed all resources. - # NetBSD opens a UNIX socket to /var/log/run. - cons = thisproc.connections(kind='all') - assert not cons, cons - - def compare_procsys_connections(self, pid, proc_cons, kind='all'): - """Given a process PID and its list of connections compare - those against system-wide connections retrieved via - psutil.net_connections. - """ - try: - sys_cons = psutil.net_connections(kind=kind) - except psutil.AccessDenied: - # On MACOS, system-wide connections are retrieved by iterating - # over all processes - if MACOS: - return - else: - raise - # Filter for this proc PID and exlucde PIDs from the tuple. - sys_cons = [c[:-1] for c in sys_cons if c.pid == pid] - sys_cons.sort() - proc_cons.sort() - self.assertEqual(proc_cons, sys_cons) - - def check_connection_ntuple(self, conn): - """Check validity of a connection namedtuple.""" - def check_ntuple(conn): - has_pid = len(conn) == 7 - self.assertIn(len(conn), (6, 7)) - self.assertEqual(conn[0], conn.fd) - self.assertEqual(conn[1], conn.family) - self.assertEqual(conn[2], conn.type) - self.assertEqual(conn[3], conn.laddr) - self.assertEqual(conn[4], conn.raddr) - self.assertEqual(conn[5], conn.status) - if has_pid: - self.assertEqual(conn[6], conn.pid) - - def check_family(conn): - self.assertIn(conn.family, (AF_INET, AF_INET6, AF_UNIX)) - if enum is not None: - assert isinstance(conn.family, enum.IntEnum), conn - else: - assert isinstance(conn.family, int), conn - if conn.family == AF_INET: - # actually try to bind the local socket; ignore IPv6 - # sockets as their address might be represented as - # an IPv4-mapped-address (e.g. "::127.0.0.1") - # and that's rejected by bind() - s = socket.socket(conn.family, conn.type) - with contextlib.closing(s): - try: - s.bind((conn.laddr[0], 0)) - except socket.error as err: - if err.errno != errno.EADDRNOTAVAIL: - raise - elif conn.family == AF_UNIX: - self.assertEqual(conn.status, psutil.CONN_NONE) - - def check_type(conn): - # SOCK_SEQPACKET may happen in case of AF_UNIX socks - self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET)) - if enum is not None: - assert isinstance(conn.type, enum.IntEnum), conn - else: - assert isinstance(conn.type, int), conn - if conn.type == SOCK_DGRAM: - self.assertEqual(conn.status, psutil.CONN_NONE) - - def check_addrs(conn): - # check IP address and port sanity - for addr in (conn.laddr, conn.raddr): - if conn.family in (AF_INET, AF_INET6): - self.assertIsInstance(addr, tuple) - if not addr: - continue - self.assertIsInstance(addr.port, int) - assert 0 <= addr.port <= 65535, addr.port - check_net_address(addr.ip, conn.family) - elif conn.family == AF_UNIX: - self.assertIsInstance(addr, str) - - def check_status(conn): - self.assertIsInstance(conn.status, str) - valids = [getattr(psutil, x) for x in dir(psutil) - if x.startswith('CONN_')] - self.assertIn(conn.status, valids) - if conn.family in (AF_INET, AF_INET6) and conn.type == SOCK_STREAM: - self.assertNotEqual(conn.status, psutil.CONN_NONE) - else: - self.assertEqual(conn.status, psutil.CONN_NONE) - - check_ntuple(conn) - check_family(conn) - check_type(conn) - check_addrs(conn) - check_status(conn) - - -class TestBase(Base, unittest.TestCase): - - @unittest.skipIf(SKIP_SYSCONS, "requires root") - def test_system(self): - with create_sockets(): - for conn in psutil.net_connections(kind='all'): - self.check_connection_ntuple(conn) - - def test_process(self): - with create_sockets(): - for conn in psutil.Process().connections(kind='all'): - self.check_connection_ntuple(conn) - - def test_invalid_kind(self): - self.assertRaises(ValueError, thisproc.connections, kind='???') - self.assertRaises(ValueError, psutil.net_connections, kind='???') - - -class TestUnconnectedSockets(Base, unittest.TestCase): - """Tests sockets which are open but not connected to anything.""" - - def get_conn_from_sock(self, sock): - cons = thisproc.connections(kind='all') - smap = dict([(c.fd, c) for c in cons]) - if NETBSD or FREEBSD: - # NetBSD opens a UNIX socket to /var/log/run - # so there may be more connections. - return smap[sock.fileno()] - else: - self.assertEqual(len(cons), 1) - if cons[0].fd != -1: - self.assertEqual(smap[sock.fileno()].fd, sock.fileno()) - return cons[0] - - def check_socket(self, sock): - """Given a socket, makes sure it matches the one obtained - via psutil. It assumes this process created one connection - only (the one supposed to be checked). - """ - conn = self.get_conn_from_sock(sock) - self.check_connection_ntuple(conn) - - # fd, family, type - if conn.fd != -1: - self.assertEqual(conn.fd, sock.fileno()) - self.assertEqual(conn.family, sock.family) - # see: http://bugs.python.org/issue30204 - self.assertEqual( - conn.type, sock.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)) - - # local address - laddr = sock.getsockname() - if not laddr and PY3 and isinstance(laddr, bytes): - # See: http://bugs.python.org/issue30205 - laddr = laddr.decode() - if sock.family == AF_INET6: - laddr = laddr[:2] - if sock.family == AF_UNIX and OPENBSD: - # No addresses are set for UNIX sockets on OpenBSD. - pass - else: - self.assertEqual(conn.laddr, laddr) - - # XXX Solaris can't retrieve system-wide UNIX sockets - if sock.family == AF_UNIX and HAS_CONNECTIONS_UNIX: - cons = thisproc.connections(kind='all') - self.compare_procsys_connections(os.getpid(), cons, kind='all') - return conn - - def test_tcp_v4(self): - addr = ("127.0.0.1", get_free_port()) - with closing(bind_socket(AF_INET, SOCK_STREAM, addr=addr)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_LISTEN) - - @unittest.skipIf(not supports_ipv6(), "IPv6 not supported") - def test_tcp_v6(self): - addr = ("::1", get_free_port()) - with closing(bind_socket(AF_INET6, SOCK_STREAM, addr=addr)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_LISTEN) - - def test_udp_v4(self): - addr = ("127.0.0.1", get_free_port()) - with closing(bind_socket(AF_INET, SOCK_DGRAM, addr=addr)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_NONE) - - @unittest.skipIf(not supports_ipv6(), "IPv6 not supported") - def test_udp_v6(self): - addr = ("::1", get_free_port()) - with closing(bind_socket(AF_INET6, SOCK_DGRAM, addr=addr)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_NONE) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_unix_tcp(self): - with unix_socket_path() as name: - with closing(bind_unix_socket(name, type=SOCK_STREAM)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_NONE) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_unix_udp(self): - with unix_socket_path() as name: - with closing(bind_unix_socket(name, type=SOCK_STREAM)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_NONE) - - -class TestConnectedSocket(Base, unittest.TestCase): - """Test socket pairs which are are actually connected to - each other. - """ - - # On SunOS, even after we close() it, the server socket stays around - # in TIME_WAIT state. - @unittest.skipIf(SUNOS, "unreliable on SUONS") - def test_tcp(self): - addr = ("127.0.0.1", get_free_port()) - assert not thisproc.connections(kind='tcp4') - server, client = tcp_socketpair(AF_INET, addr=addr) - try: - cons = thisproc.connections(kind='tcp4') - self.assertEqual(len(cons), 2) - self.assertEqual(cons[0].status, psutil.CONN_ESTABLISHED) - self.assertEqual(cons[1].status, psutil.CONN_ESTABLISHED) - # May not be fast enough to change state so it stays - # commenteed. - # client.close() - # cons = thisproc.connections(kind='all') - # self.assertEqual(len(cons), 1) - # self.assertEqual(cons[0].status, psutil.CONN_CLOSE_WAIT) - finally: - server.close() - client.close() - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_unix(self): - with unix_socket_path() as name: - server, client = unix_socketpair(name) - try: - cons = thisproc.connections(kind='unix') - assert not (cons[0].laddr and cons[0].raddr) - assert not (cons[1].laddr and cons[1].raddr) - if NETBSD or FREEBSD: - # On NetBSD creating a UNIX socket will cause - # a UNIX connection to /var/run/log. - cons = [c for c in cons if c.raddr != '/var/run/log'] - if CIRRUS: - cons = [c for c in cons if c.fd in - (server.fileno(), client.fileno())] - self.assertEqual(len(cons), 2, msg=cons) - if LINUX or FREEBSD or SUNOS: - # remote path is never set - self.assertEqual(cons[0].raddr, "") - self.assertEqual(cons[1].raddr, "") - # one local address should though - self.assertEqual(name, cons[0].laddr or cons[1].laddr) - elif OPENBSD: - # No addresses whatsoever here. - for addr in (cons[0].laddr, cons[0].raddr, - cons[1].laddr, cons[1].raddr): - self.assertEqual(addr, "") - else: - # On other systems either the laddr or raddr - # of both peers are set. - self.assertEqual(cons[0].laddr or cons[1].laddr, name) - self.assertEqual(cons[0].raddr or cons[1].raddr, name) - finally: - server.close() - client.close() - - -class TestFilters(Base, unittest.TestCase): - - def test_filters(self): - def check(kind, families, types): - for conn in thisproc.connections(kind=kind): - self.assertIn(conn.family, families) - self.assertIn(conn.type, types) - if not SKIP_SYSCONS: - for conn in psutil.net_connections(kind=kind): - self.assertIn(conn.family, families) - self.assertIn(conn.type, types) - - with create_sockets(): - check('all', - [AF_INET, AF_INET6, AF_UNIX], - [SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET]) - check('inet', - [AF_INET, AF_INET6], - [SOCK_STREAM, SOCK_DGRAM]) - check('inet4', - [AF_INET], - [SOCK_STREAM, SOCK_DGRAM]) - check('tcp', - [AF_INET, AF_INET6], - [SOCK_STREAM]) - check('tcp4', - [AF_INET], - [SOCK_STREAM]) - check('tcp6', - [AF_INET6], - [SOCK_STREAM]) - check('udp', - [AF_INET, AF_INET6], - [SOCK_DGRAM]) - check('udp4', - [AF_INET], - [SOCK_DGRAM]) - check('udp6', - [AF_INET6], - [SOCK_DGRAM]) - if HAS_CONNECTIONS_UNIX: - check('unix', - [AF_UNIX], - [SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET]) - - @skip_on_access_denied(only_if=MACOS) - def test_combos(self): - def check_conn(proc, conn, family, type, laddr, raddr, status, kinds): - all_kinds = ("all", "inet", "inet4", "inet6", "tcp", "tcp4", - "tcp6", "udp", "udp4", "udp6") - self.check_connection_ntuple(conn) - self.assertEqual(conn.family, family) - self.assertEqual(conn.type, type) - self.assertEqual(conn.laddr, laddr) - self.assertEqual(conn.raddr, raddr) - self.assertEqual(conn.status, status) - for kind in all_kinds: - cons = proc.connections(kind=kind) - if kind in kinds: - assert cons - else: - assert not cons, cons - # compare against system-wide connections - # XXX Solaris can't retrieve system-wide UNIX - # sockets. - if HAS_CONNECTIONS_UNIX: - self.compare_procsys_connections(proc.pid, [conn]) - - tcp_template = textwrap.dedent(""" - import socket, time - s = socket.socket($family, socket.SOCK_STREAM) - s.bind(('$addr', 0)) - s.listen(5) - with open('$testfn', 'w') as f: - f.write(str(s.getsockname()[:2])) - time.sleep(60) - """) - - udp_template = textwrap.dedent(""" - import socket, time - s = socket.socket($family, socket.SOCK_DGRAM) - s.bind(('$addr', 0)) - with open('$testfn', 'w') as f: - f.write(str(s.getsockname()[:2])) - time.sleep(60) - """) - - from string import Template - testfile = os.path.basename(TESTFN) - tcp4_template = Template(tcp_template).substitute( - family=int(AF_INET), addr="127.0.0.1", testfn=testfile) - udp4_template = Template(udp_template).substitute( - family=int(AF_INET), addr="127.0.0.1", testfn=testfile) - tcp6_template = Template(tcp_template).substitute( - family=int(AF_INET6), addr="::1", testfn=testfile) - udp6_template = Template(udp_template).substitute( - family=int(AF_INET6), addr="::1", testfn=testfile) - - # launch various subprocess instantiating a socket of various - # families and types to enrich psutil results - tcp4_proc = pyrun(tcp4_template) - tcp4_addr = eval(wait_for_file(testfile)) - udp4_proc = pyrun(udp4_template) - udp4_addr = eval(wait_for_file(testfile)) - if supports_ipv6(): - tcp6_proc = pyrun(tcp6_template) - tcp6_addr = eval(wait_for_file(testfile)) - udp6_proc = pyrun(udp6_template) - udp6_addr = eval(wait_for_file(testfile)) - else: - tcp6_proc = None - udp6_proc = None - tcp6_addr = None - udp6_addr = None - - for p in thisproc.children(): - cons = p.connections() - self.assertEqual(len(cons), 1) - for conn in cons: - # TCP v4 - if p.pid == tcp4_proc.pid: - check_conn(p, conn, AF_INET, SOCK_STREAM, tcp4_addr, (), - psutil.CONN_LISTEN, - ("all", "inet", "inet4", "tcp", "tcp4")) - # UDP v4 - elif p.pid == udp4_proc.pid: - check_conn(p, conn, AF_INET, SOCK_DGRAM, udp4_addr, (), - psutil.CONN_NONE, - ("all", "inet", "inet4", "udp", "udp4")) - # TCP v6 - elif p.pid == getattr(tcp6_proc, "pid", None): - check_conn(p, conn, AF_INET6, SOCK_STREAM, tcp6_addr, (), - psutil.CONN_LISTEN, - ("all", "inet", "inet6", "tcp", "tcp6")) - # UDP v6 - elif p.pid == getattr(udp6_proc, "pid", None): - check_conn(p, conn, AF_INET6, SOCK_DGRAM, udp6_addr, (), - psutil.CONN_NONE, - ("all", "inet", "inet6", "udp", "udp6")) - - def test_count(self): - with create_sockets(): - # tcp - cons = thisproc.connections(kind='tcp') - self.assertEqual(len(cons), 2 if supports_ipv6() else 1) - for conn in cons: - self.assertIn(conn.family, (AF_INET, AF_INET6)) - self.assertEqual(conn.type, SOCK_STREAM) - # tcp4 - cons = thisproc.connections(kind='tcp4') - self.assertEqual(len(cons), 1) - self.assertEqual(cons[0].family, AF_INET) - self.assertEqual(cons[0].type, SOCK_STREAM) - # tcp6 - if supports_ipv6(): - cons = thisproc.connections(kind='tcp6') - self.assertEqual(len(cons), 1) - self.assertEqual(cons[0].family, AF_INET6) - self.assertEqual(cons[0].type, SOCK_STREAM) - # udp - cons = thisproc.connections(kind='udp') - self.assertEqual(len(cons), 2 if supports_ipv6() else 1) - for conn in cons: - self.assertIn(conn.family, (AF_INET, AF_INET6)) - self.assertEqual(conn.type, SOCK_DGRAM) - # udp4 - cons = thisproc.connections(kind='udp4') - self.assertEqual(len(cons), 1) - self.assertEqual(cons[0].family, AF_INET) - self.assertEqual(cons[0].type, SOCK_DGRAM) - # udp6 - if supports_ipv6(): - cons = thisproc.connections(kind='udp6') - self.assertEqual(len(cons), 1) - self.assertEqual(cons[0].family, AF_INET6) - self.assertEqual(cons[0].type, SOCK_DGRAM) - # inet - cons = thisproc.connections(kind='inet') - self.assertEqual(len(cons), 4 if supports_ipv6() else 2) - for conn in cons: - self.assertIn(conn.family, (AF_INET, AF_INET6)) - self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM)) - # inet6 - if supports_ipv6(): - cons = thisproc.connections(kind='inet6') - self.assertEqual(len(cons), 2) - for conn in cons: - self.assertEqual(conn.family, AF_INET6) - self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM)) - # Skipped on BSD becayse by default the Python process - # creates a UNIX socket to '/var/run/log'. - if HAS_CONNECTIONS_UNIX and not (FREEBSD or NETBSD): - cons = thisproc.connections(kind='unix') - self.assertEqual(len(cons), 3) - for conn in cons: - self.assertEqual(conn.family, AF_UNIX) - self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM)) - - -@unittest.skipIf(SKIP_SYSCONS, "requires root") -class TestSystemWideConnections(Base, unittest.TestCase): - """Tests for net_connections().""" - - def test_it(self): - def check(cons, families, types_): - for conn in cons: - self.assertIn(conn.family, families, msg=conn) - if conn.family != AF_UNIX: - self.assertIn(conn.type, types_, msg=conn) - self.check_connection_ntuple(conn) - - with create_sockets(): - from psutil._common import conn_tmap - for kind, groups in conn_tmap.items(): - # XXX: SunOS does not retrieve UNIX sockets. - if kind == 'unix' and not HAS_CONNECTIONS_UNIX: - continue - families, types_ = groups - cons = psutil.net_connections(kind) - self.assertEqual(len(cons), len(set(cons))) - check(cons, families, types_) - - # See: https://travis-ci.org/giampaolo/psutil/jobs/237566297 - @unittest.skipIf(MACOS and TRAVIS, "unreliable on MACOS + TRAVIS") - def test_multi_sockets_procs(self): - # Creates multiple sub processes, each creating different - # sockets. For each process check that proc.connections() - # and net_connections() return the same results. - # This is done mainly to check whether net_connections()'s - # pid is properly set, see: - # https://github.com/giampaolo/psutil/issues/1013 - with create_sockets() as socks: - expected = len(socks) - pids = [] - times = 10 - for i in range(times): - fname = os.path.realpath(TESTFN) + str(i) - src = textwrap.dedent("""\ - import time, os - from psutil.tests import create_sockets - with create_sockets(): - with open(r'%s', 'w') as f: - f.write(str(os.getpid())) - time.sleep(60) - """ % fname) - sproc = pyrun(src) - pids.append(sproc.pid) - self.addCleanup(safe_rmpath, fname) - - # sync - for i in range(times): - fname = TESTFN + str(i) - wait_for_file(fname) - - syscons = [x for x in psutil.net_connections(kind='all') if x.pid - in pids] - for pid in pids: - self.assertEqual(len([x for x in syscons if x.pid == pid]), - expected) - p = psutil.Process(pid) - self.assertEqual(len(p.connections('all')), expected) - - -class TestMisc(unittest.TestCase): - - def test_connection_constants(self): - ints = [] - strs = [] - for name in dir(psutil): - if name.startswith('CONN_'): - num = getattr(psutil, name) - str_ = str(num) - assert str_.isupper(), str_ - self.assertNotIn(str, strs) - self.assertNotIn(num, ints) - ints.append(num) - strs.append(str_) - if SUNOS: - psutil.CONN_IDLE - psutil.CONN_BOUND - if WINDOWS: - psutil.CONN_DELETE_TCB - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_contracts.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_contracts.py deleted file mode 100644 index 312f17d9a39d..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_contracts.py +++ /dev/null @@ -1,690 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Contracts tests. These tests mainly check API sanity in terms of -returned types and APIs availability. -Some of these are duplicates of tests test_system.py and test_process.py -""" - -import errno -import os -import stat -import time -import traceback - -from psutil import AIX -from psutil import BSD -from psutil import FREEBSD -from psutil import LINUX -from psutil import MACOS -from psutil import NETBSD -from psutil import OPENBSD -from psutil import OSX -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -from psutil._compat import long -from psutil.tests import create_sockets -from psutil.tests import enum -from psutil.tests import get_kernel_version -from psutil.tests import HAS_CPU_FREQ -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 -from psutil.tests import is_namedtuple -from psutil.tests import safe_rmpath -from psutil.tests import SKIP_SYSCONS -from psutil.tests import TESTFN -from psutil.tests import unittest -from psutil.tests import VALID_PROC_STATUSES -from psutil.tests import warn -import psutil - - -# =================================================================== -# --- APIs availability -# =================================================================== - -# Make sure code reflects what doc promises in terms of APIs -# availability. - -class TestAvailConstantsAPIs(unittest.TestCase): - - def test_PROCFS_PATH(self): - self.assertEqual(hasattr(psutil, "PROCFS_PATH"), - LINUX or SUNOS or AIX) - - def test_win_priority(self): - ae = self.assertEqual - ae(hasattr(psutil, "ABOVE_NORMAL_PRIORITY_CLASS"), WINDOWS) - ae(hasattr(psutil, "BELOW_NORMAL_PRIORITY_CLASS"), WINDOWS) - ae(hasattr(psutil, "HIGH_PRIORITY_CLASS"), WINDOWS) - ae(hasattr(psutil, "IDLE_PRIORITY_CLASS"), WINDOWS) - ae(hasattr(psutil, "NORMAL_PRIORITY_CLASS"), WINDOWS) - ae(hasattr(psutil, "REALTIME_PRIORITY_CLASS"), WINDOWS) - - def test_linux_ioprio_linux(self): - ae = self.assertEqual - ae(hasattr(psutil, "IOPRIO_CLASS_NONE"), LINUX) - ae(hasattr(psutil, "IOPRIO_CLASS_RT"), LINUX) - ae(hasattr(psutil, "IOPRIO_CLASS_BE"), LINUX) - ae(hasattr(psutil, "IOPRIO_CLASS_IDLE"), LINUX) - - def test_linux_ioprio_windows(self): - ae = self.assertEqual - ae(hasattr(psutil, "IOPRIO_HIGH"), WINDOWS) - ae(hasattr(psutil, "IOPRIO_NORMAL"), WINDOWS) - ae(hasattr(psutil, "IOPRIO_LOW"), WINDOWS) - ae(hasattr(psutil, "IOPRIO_VERYLOW"), WINDOWS) - - def test_linux_rlimit(self): - ae = self.assertEqual - hasit = LINUX and get_kernel_version() >= (2, 6, 36) - ae(hasattr(psutil.Process, "rlimit"), hasit) - ae(hasattr(psutil, "RLIM_INFINITY"), hasit) - ae(hasattr(psutil, "RLIMIT_AS"), hasit) - ae(hasattr(psutil, "RLIMIT_CORE"), hasit) - ae(hasattr(psutil, "RLIMIT_CPU"), hasit) - ae(hasattr(psutil, "RLIMIT_DATA"), hasit) - ae(hasattr(psutil, "RLIMIT_FSIZE"), hasit) - ae(hasattr(psutil, "RLIMIT_LOCKS"), hasit) - ae(hasattr(psutil, "RLIMIT_MEMLOCK"), hasit) - ae(hasattr(psutil, "RLIMIT_NOFILE"), hasit) - ae(hasattr(psutil, "RLIMIT_NPROC"), hasit) - ae(hasattr(psutil, "RLIMIT_RSS"), hasit) - ae(hasattr(psutil, "RLIMIT_STACK"), hasit) - - hasit = LINUX and get_kernel_version() >= (3, 0) - ae(hasattr(psutil, "RLIMIT_MSGQUEUE"), hasit) - ae(hasattr(psutil, "RLIMIT_NICE"), hasit) - ae(hasattr(psutil, "RLIMIT_RTPRIO"), hasit) - ae(hasattr(psutil, "RLIMIT_RTTIME"), hasit) - ae(hasattr(psutil, "RLIMIT_SIGPENDING"), hasit) - - -class TestAvailSystemAPIs(unittest.TestCase): - - def test_win_service_iter(self): - self.assertEqual(hasattr(psutil, "win_service_iter"), WINDOWS) - - def test_win_service_get(self): - self.assertEqual(hasattr(psutil, "win_service_get"), WINDOWS) - - def test_cpu_freq(self): - linux = (LINUX and - (os.path.exists("/sys/devices/system/cpu/cpufreq") or - os.path.exists("/sys/devices/system/cpu/cpu0/cpufreq"))) - self.assertEqual(hasattr(psutil, "cpu_freq"), - linux or MACOS or WINDOWS or FREEBSD) - - def test_sensors_temperatures(self): - self.assertEqual( - hasattr(psutil, "sensors_temperatures"), LINUX or FREEBSD) - - def test_sensors_fans(self): - self.assertEqual(hasattr(psutil, "sensors_fans"), LINUX) - - def test_battery(self): - self.assertEqual(hasattr(psutil, "sensors_battery"), - LINUX or WINDOWS or FREEBSD or MACOS) - - -class TestAvailProcessAPIs(unittest.TestCase): - - def test_environ(self): - self.assertEqual(hasattr(psutil.Process, "environ"), - LINUX or MACOS or WINDOWS or AIX or SUNOS) - - def test_uids(self): - self.assertEqual(hasattr(psutil.Process, "uids"), POSIX) - - def test_gids(self): - self.assertEqual(hasattr(psutil.Process, "uids"), POSIX) - - def test_terminal(self): - self.assertEqual(hasattr(psutil.Process, "terminal"), POSIX) - - def test_ionice(self): - self.assertEqual(hasattr(psutil.Process, "ionice"), LINUX or WINDOWS) - - def test_rlimit(self): - self.assertEqual(hasattr(psutil.Process, "rlimit"), LINUX) - - def test_io_counters(self): - hasit = hasattr(psutil.Process, "io_counters") - self.assertEqual(hasit, False if MACOS or SUNOS else True) - - def test_num_fds(self): - self.assertEqual(hasattr(psutil.Process, "num_fds"), POSIX) - - def test_num_handles(self): - self.assertEqual(hasattr(psutil.Process, "num_handles"), WINDOWS) - - def test_cpu_affinity(self): - self.assertEqual(hasattr(psutil.Process, "cpu_affinity"), - LINUX or WINDOWS or FREEBSD) - - def test_cpu_num(self): - self.assertEqual(hasattr(psutil.Process, "cpu_num"), - LINUX or FREEBSD or SUNOS) - - def test_memory_maps(self): - hasit = hasattr(psutil.Process, "memory_maps") - self.assertEqual( - hasit, False if OPENBSD or NETBSD or AIX or MACOS else True) - - -# =================================================================== -# --- System API types -# =================================================================== - - -class TestSystemAPITypes(unittest.TestCase): - """Check the return types of system related APIs. - Mainly we want to test we never return unicode on Python 2, see: - https://github.com/giampaolo/psutil/issues/1039 - """ - - @classmethod - def setUpClass(cls): - cls.proc = psutil.Process() - - def tearDown(self): - safe_rmpath(TESTFN) - - def assert_ntuple_of_nums(self, nt, type_=float, gezero=True): - assert is_namedtuple(nt) - for n in nt: - self.assertIsInstance(n, type_) - if gezero: - self.assertGreaterEqual(n, 0) - - def test_cpu_times(self): - self.assert_ntuple_of_nums(psutil.cpu_times()) - for nt in psutil.cpu_times(percpu=True): - self.assert_ntuple_of_nums(nt) - - def test_cpu_percent(self): - self.assertIsInstance(psutil.cpu_percent(interval=None), float) - self.assertIsInstance(psutil.cpu_percent(interval=0.00001), float) - - def test_cpu_times_percent(self): - self.assert_ntuple_of_nums(psutil.cpu_times_percent(interval=None)) - self.assert_ntuple_of_nums(psutil.cpu_times_percent(interval=0.0001)) - - def test_cpu_count(self): - self.assertIsInstance(psutil.cpu_count(), int) - - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_cpu_freq(self): - if psutil.cpu_freq() is None: - raise self.skipTest("cpu_freq() returns None") - self.assert_ntuple_of_nums(psutil.cpu_freq(), type_=(float, int, long)) - - def test_disk_io_counters(self): - # Duplicate of test_system.py. Keep it anyway. - for k, v in psutil.disk_io_counters(perdisk=True).items(): - self.assertIsInstance(k, str) - self.assert_ntuple_of_nums(v, type_=(int, long)) - - def test_disk_partitions(self): - # Duplicate of test_system.py. Keep it anyway. - for disk in psutil.disk_partitions(): - self.assertIsInstance(disk.device, str) - self.assertIsInstance(disk.mountpoint, str) - self.assertIsInstance(disk.fstype, str) - self.assertIsInstance(disk.opts, str) - - @unittest.skipIf(SKIP_SYSCONS, "requires root") - def test_net_connections(self): - with create_sockets(): - ret = psutil.net_connections('all') - self.assertEqual(len(ret), len(set(ret))) - for conn in ret: - assert is_namedtuple(conn) - - def test_net_if_addrs(self): - # Duplicate of test_system.py. Keep it anyway. - for ifname, addrs in psutil.net_if_addrs().items(): - self.assertIsInstance(ifname, str) - for addr in addrs: - if enum is not None: - assert isinstance(addr.family, enum.IntEnum), addr - else: - assert isinstance(addr.family, int), addr - self.assertIsInstance(addr.address, str) - self.assertIsInstance(addr.netmask, (str, type(None))) - self.assertIsInstance(addr.broadcast, (str, type(None))) - - def test_net_if_stats(self): - # Duplicate of test_system.py. Keep it anyway. - for ifname, info in psutil.net_if_stats().items(): - self.assertIsInstance(ifname, str) - self.assertIsInstance(info.isup, bool) - if enum is not None: - self.assertIsInstance(info.duplex, enum.IntEnum) - else: - self.assertIsInstance(info.duplex, int) - self.assertIsInstance(info.speed, int) - self.assertIsInstance(info.mtu, int) - - @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(): - self.assertIsInstance(ifname, str) - - @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") - def test_sensors_fans(self): - # Duplicate of test_system.py. Keep it anyway. - for name, units in psutil.sensors_fans().items(): - self.assertIsInstance(name, str) - for unit in units: - self.assertIsInstance(unit.label, str) - self.assertIsInstance(unit.current, (float, int, type(None))) - - @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") - def test_sensors_temperatures(self): - # Duplicate of test_system.py. Keep it anyway. - for name, units in psutil.sensors_temperatures().items(): - self.assertIsInstance(name, str) - for unit in units: - self.assertIsInstance(unit.label, str) - self.assertIsInstance(unit.current, (float, int, type(None))) - self.assertIsInstance(unit.high, (float, int, type(None))) - self.assertIsInstance(unit.critical, (float, int, type(None))) - - def test_boot_time(self): - # Duplicate of test_system.py. Keep it anyway. - self.assertIsInstance(psutil.boot_time(), float) - - def test_users(self): - # Duplicate of test_system.py. Keep it anyway. - for user in psutil.users(): - self.assertIsInstance(user.name, str) - self.assertIsInstance(user.terminal, (str, type(None))) - self.assertIsInstance(user.host, (str, type(None))) - self.assertIsInstance(user.pid, (int, type(None))) - - -# =================================================================== -# --- Featch all processes test -# =================================================================== - - -class TestFetchAllProcesses(unittest.TestCase): - """Test which iterates over all running processes and performs - some sanity checks against Process API's returned values. - """ - - def get_attr_names(self): - excluded_names = set([ - 'send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait', - 'as_dict', 'parent', 'parents', 'children', 'memory_info_ex', - 'oneshot', - ]) - if LINUX and not HAS_RLIMIT: - excluded_names.add('rlimit') - attrs = [] - for name in dir(psutil.Process): - if name.startswith("_"): - continue - if name in excluded_names: - continue - attrs.append(name) - return attrs - - def iter_procs(self): - attrs = self.get_attr_names() - for p in psutil.process_iter(): - with p.oneshot(): - for name in attrs: - yield (p, name) - - def call_meth(self, p, name): - args = () - kwargs = {} - attr = getattr(p, name, None) - if attr is not None and callable(attr): - if name == 'rlimit': - args = (psutil.RLIMIT_NOFILE,) - elif name == 'memory_maps': - kwargs = {'grouped': False} - return attr(*args, **kwargs) - else: - return attr - - def test_fetch_all(self): - valid_procs = 0 - default = object() - failures = [] - for p, name in self.iter_procs(): - ret = default - try: - ret = self.call_meth(p, name) - except NotImplementedError: - msg = "%r was skipped because not implemented" % ( - self.__class__.__name__ + '.test_' + name) - warn(msg) - except (psutil.NoSuchProcess, psutil.AccessDenied) as err: - self.assertEqual(err.pid, p.pid) - if err.name: - # make sure exception's name attr is set - # with the actual process name - self.assertEqual(err.name, p.name()) - assert str(err) - assert err.msg - except Exception: - s = '\n' + '=' * 70 + '\n' - s += "FAIL: test_%s (proc=%s" % (name, p) - if ret != default: - s += ", ret=%s)" % repr(ret) - s += ')\n' - s += '-' * 70 - s += "\n%s" % traceback.format_exc() - s = "\n".join((" " * 4) + i for i in s.splitlines()) - s += '\n' - failures.append(s) - break - else: - valid_procs += 1 - if ret not in (0, 0.0, [], None, '', {}): - assert ret, ret - meth = getattr(self, name) - meth(ret, p) - - if failures: - self.fail(''.join(failures)) - - # we should always have a non-empty list, not including PID 0 etc. - # special cases. - assert valid_procs - - def cmdline(self, ret, proc): - self.assertIsInstance(ret, list) - for part in ret: - self.assertIsInstance(part, str) - - def exe(self, ret, proc): - self.assertIsInstance(ret, (str, type(None))) - if not ret: - self.assertEqual(ret, '') - else: - if WINDOWS and not ret.endswith('.exe'): - return # May be "Registry", "MemCompression", ... - assert os.path.isabs(ret), ret - # Note: os.stat() may return False even if the file is there - # hence we skip the test, see: - # http://stackoverflow.com/questions/3112546/os-path-exists-lies - if POSIX and os.path.isfile(ret): - if hasattr(os, 'access') and hasattr(os, "X_OK"): - # XXX may fail on MACOS - assert os.access(ret, os.X_OK) - - def pid(self, ret, proc): - self.assertIsInstance(ret, int) - self.assertGreaterEqual(ret, 0) - - def ppid(self, ret, proc): - self.assertIsInstance(ret, (int, long)) - self.assertGreaterEqual(ret, 0) - - def name(self, ret, proc): - self.assertIsInstance(ret, str) - # on AIX, "" processes don't have names - if not AIX: - assert ret - - def create_time(self, ret, proc): - self.assertIsInstance(ret, float) - try: - self.assertGreaterEqual(ret, 0) - except AssertionError: - # XXX - if OPENBSD and proc.status() == psutil.STATUS_ZOMBIE: - pass - else: - raise - # this can't be taken for granted on all platforms - # self.assertGreaterEqual(ret, psutil.boot_time()) - # make sure returned value can be pretty printed - # with strftime - time.strftime("%Y %m %d %H:%M:%S", time.localtime(ret)) - - def uids(self, ret, proc): - assert is_namedtuple(ret) - for uid in ret: - self.assertIsInstance(uid, int) - self.assertGreaterEqual(uid, 0) - - def gids(self, ret, proc): - assert is_namedtuple(ret) - # note: testing all gids as above seems not to be reliable for - # gid == 30 (nodoby); not sure why. - for gid in ret: - self.assertIsInstance(gid, int) - if not MACOS and not NETBSD: - self.assertGreaterEqual(gid, 0) - - def username(self, ret, proc): - self.assertIsInstance(ret, str) - assert ret - - def status(self, ret, proc): - self.assertIsInstance(ret, str) - assert ret - self.assertNotEqual(ret, '?') # XXX - self.assertIn(ret, VALID_PROC_STATUSES) - - def io_counters(self, ret, proc): - assert is_namedtuple(ret) - for field in ret: - self.assertIsInstance(field, (int, long)) - if field != -1: - self.assertGreaterEqual(field, 0) - - def ionice(self, ret, proc): - if LINUX: - self.assertIsInstance(ret.ioclass, int) - self.assertIsInstance(ret.value, int) - self.assertGreaterEqual(ret.ioclass, 0) - self.assertGreaterEqual(ret.value, 0) - else: # Windows, Cygwin - choices = [ - psutil.IOPRIO_VERYLOW, - psutil.IOPRIO_LOW, - psutil.IOPRIO_NORMAL, - psutil.IOPRIO_HIGH] - self.assertIsInstance(ret, int) - self.assertGreaterEqual(ret, 0) - self.assertIn(ret, choices) - - def num_threads(self, ret, proc): - self.assertIsInstance(ret, int) - self.assertGreaterEqual(ret, 1) - - def threads(self, ret, proc): - self.assertIsInstance(ret, list) - for t in ret: - assert is_namedtuple(t) - self.assertGreaterEqual(t.id, 0) - self.assertGreaterEqual(t.user_time, 0) - self.assertGreaterEqual(t.system_time, 0) - for field in t: - self.assertIsInstance(field, (int, float)) - - def cpu_times(self, ret, proc): - assert is_namedtuple(ret) - for n in ret: - self.assertIsInstance(n, float) - self.assertGreaterEqual(n, 0) - # TODO: check ntuple fields - - def cpu_percent(self, ret, proc): - self.assertIsInstance(ret, float) - assert 0.0 <= ret <= 100.0, ret - - def cpu_num(self, ret, proc): - self.assertIsInstance(ret, int) - if FREEBSD and ret == -1: - return - self.assertGreaterEqual(ret, 0) - if psutil.cpu_count() == 1: - self.assertEqual(ret, 0) - self.assertIn(ret, list(range(psutil.cpu_count()))) - - def memory_info(self, ret, proc): - assert is_namedtuple(ret) - for value in ret: - self.assertIsInstance(value, (int, long)) - self.assertGreaterEqual(value, 0) - if WINDOWS: - self.assertGreaterEqual(ret.peak_wset, ret.wset) - self.assertGreaterEqual(ret.peak_paged_pool, ret.paged_pool) - self.assertGreaterEqual(ret.peak_nonpaged_pool, ret.nonpaged_pool) - self.assertGreaterEqual(ret.peak_pagefile, ret.pagefile) - - def memory_full_info(self, ret, proc): - assert is_namedtuple(ret) - total = psutil.virtual_memory().total - for name in ret._fields: - value = getattr(ret, name) - self.assertIsInstance(value, (int, long)) - self.assertGreaterEqual(value, 0, msg=(name, value)) - if LINUX or OSX and name in ('vms', 'data'): - # On Linux there are processes (e.g. 'goa-daemon') whose - # VMS is incredibly high for some reason. - continue - self.assertLessEqual(value, total, msg=(name, value, total)) - - if LINUX: - self.assertGreaterEqual(ret.pss, ret.uss) - - def open_files(self, ret, proc): - self.assertIsInstance(ret, list) - for f in ret: - self.assertIsInstance(f.fd, int) - self.assertIsInstance(f.path, str) - if WINDOWS: - self.assertEqual(f.fd, -1) - elif LINUX: - self.assertIsInstance(f.position, int) - self.assertIsInstance(f.mode, str) - self.assertIsInstance(f.flags, int) - self.assertGreaterEqual(f.position, 0) - self.assertIn(f.mode, ('r', 'w', 'a', 'r+', 'a+')) - self.assertGreater(f.flags, 0) - elif BSD and not f.path: - # XXX see: https://github.com/giampaolo/psutil/issues/595 - continue - assert os.path.isabs(f.path), f - assert os.path.isfile(f.path), f - - def num_fds(self, ret, proc): - self.assertIsInstance(ret, int) - self.assertGreaterEqual(ret, 0) - - def connections(self, ret, proc): - with create_sockets(): - self.assertEqual(len(ret), len(set(ret))) - for conn in ret: - assert is_namedtuple(conn) - - def cwd(self, ret, proc): - if ret: # 'ret' can be None or empty - self.assertIsInstance(ret, str) - assert os.path.isabs(ret), ret - try: - st = os.stat(ret) - except OSError as err: - if WINDOWS and err.errno in \ - psutil._psplatform.ACCESS_DENIED_SET: - pass - # directory has been removed in mean time - elif err.errno != errno.ENOENT: - raise - else: - assert stat.S_ISDIR(st.st_mode) - - def memory_percent(self, ret, proc): - self.assertIsInstance(ret, float) - assert 0 <= ret <= 100, ret - - def is_running(self, ret, proc): - self.assertIsInstance(ret, bool) - - def cpu_affinity(self, ret, proc): - self.assertIsInstance(ret, list) - assert ret != [], ret - cpus = range(psutil.cpu_count()) - for n in ret: - self.assertIsInstance(n, int) - self.assertIn(n, cpus) - - def terminal(self, ret, proc): - self.assertIsInstance(ret, (str, type(None))) - if ret is not None: - assert os.path.isabs(ret), ret - assert os.path.exists(ret), ret - - def memory_maps(self, ret, proc): - for nt in ret: - self.assertIsInstance(nt.addr, str) - self.assertIsInstance(nt.perms, str) - self.assertIsInstance(nt.path, str) - for fname in nt._fields: - value = getattr(nt, fname) - if fname == 'path': - if not value.startswith('['): - assert os.path.isabs(nt.path), nt.path - # commented as on Linux we might get - # '/foo/bar (deleted)' - # assert os.path.exists(nt.path), nt.path - elif fname == 'addr': - assert value, repr(value) - elif fname == 'perms': - if not WINDOWS: - assert value, repr(value) - else: - self.assertIsInstance(value, (int, long)) - self.assertGreaterEqual(value, 0) - - def num_handles(self, ret, proc): - self.assertIsInstance(ret, int) - self.assertGreaterEqual(ret, 0) - - def nice(self, ret, proc): - self.assertIsInstance(ret, int) - if POSIX: - assert -20 <= ret <= 20, ret - else: - priorities = [getattr(psutil, x) for x in dir(psutil) - if x.endswith('_PRIORITY_CLASS')] - self.assertIn(ret, priorities) - - def num_ctx_switches(self, ret, proc): - assert is_namedtuple(ret) - for value in ret: - self.assertIsInstance(value, (int, long)) - self.assertGreaterEqual(value, 0) - - def rlimit(self, ret, proc): - self.assertIsInstance(ret, tuple) - self.assertEqual(len(ret), 2) - self.assertGreaterEqual(ret[0], -1) - self.assertGreaterEqual(ret[1], -1) - - def environ(self, ret, proc): - self.assertIsInstance(ret, dict) - for k, v in ret.items(): - self.assertIsInstance(k, str) - self.assertIsInstance(v, str) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_linux.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_linux.py deleted file mode 100644 index e51f8bd573ba..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_linux.py +++ /dev/null @@ -1,2118 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Linux specific tests.""" - -from __future__ import division -import collections -import contextlib -import errno -import glob -import io -import os -import re -import shutil -import socket -import struct -import tempfile -import textwrap -import time -import warnings - -import psutil -from psutil import LINUX -from psutil._compat import basestring -from psutil._compat import FileNotFoundError -from psutil._compat import PY3 -from psutil._compat import u -from psutil.tests import call_until -from psutil.tests import HAS_BATTERY -from psutil.tests import HAS_CPU_FREQ -from psutil.tests import HAS_GETLOADAVG -from psutil.tests import HAS_RLIMIT -from psutil.tests import MEMORY_TOLERANCE -from psutil.tests import mock -from psutil.tests import PYPY -from psutil.tests import pyrun -from psutil.tests import reap_children -from psutil.tests import reload_module -from psutil.tests import retry_on_failure -from psutil.tests import safe_rmpath -from psutil.tests import sh -from psutil.tests import skip_on_not_implemented -from psutil.tests import TESTFN -from psutil.tests import ThreadTask -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import which - - -HERE = os.path.abspath(os.path.dirname(__file__)) -SIOCGIFADDR = 0x8915 -SIOCGIFCONF = 0x8912 -SIOCGIFHWADDR = 0x8927 -if LINUX: - SECTOR_SIZE = 512 -EMPTY_TEMPERATURES = not glob.glob('/sys/class/hwmon/hwmon*') - -# ===================================================================== -# --- utils -# ===================================================================== - - -def get_ipv4_address(ifname): - import fcntl - ifname = ifname[:15] - if PY3: - ifname = bytes(ifname, 'ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - with contextlib.closing(s): - return socket.inet_ntoa( - fcntl.ioctl(s.fileno(), - SIOCGIFADDR, - struct.pack('256s', ifname))[20:24]) - - -def get_mac_address(ifname): - import fcntl - ifname = ifname[:15] - if PY3: - ifname = bytes(ifname, 'ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - with contextlib.closing(s): - info = fcntl.ioctl( - s.fileno(), SIOCGIFHWADDR, struct.pack('256s', ifname)) - if PY3: - def ord(x): - return x - else: - import __builtin__ - ord = __builtin__.ord - return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1] - - -def free_swap(): - """Parse 'free' cmd and return swap memory's s total, used and free - values. - """ - out = sh('free -b', env={"LANG": "C.UTF-8"}) - lines = out.split('\n') - for line in lines: - if line.startswith('Swap'): - _, total, used, free = line.split() - nt = collections.namedtuple('free', 'total used free') - return nt(int(total), int(used), int(free)) - raise ValueError( - "can't find 'Swap' in 'free' output:\n%s" % '\n'.join(lines)) - - -def free_physmem(): - """Parse 'free' cmd and return physical memory's total, used - and free values. - """ - # Note: free can have 2 different formats, invalidating 'shared' - # and 'cached' memory which may have different positions so we - # do not return them. - # https://github.com/giampaolo/psutil/issues/538#issuecomment-57059946 - out = sh('free -b', env={"LANG": "C.UTF-8"}) - lines = out.split('\n') - for line in lines: - if line.startswith('Mem'): - total, used, free, shared = \ - [int(x) for x in line.split()[1:5]] - nt = collections.namedtuple( - 'free', 'total used free shared output') - return nt(total, used, free, shared, out) - raise ValueError( - "can't find 'Mem' in 'free' output:\n%s" % '\n'.join(lines)) - - -def vmstat(stat): - out = sh("vmstat -s", env={"LANG": "C.UTF-8"}) - for line in out.split("\n"): - line = line.strip() - if stat in line: - return int(line.split(' ')[0]) - raise ValueError("can't find %r in 'vmstat' output" % stat) - - -def get_free_version_info(): - out = sh("free -V").strip() - return tuple(map(int, out.split()[-1].split('.'))) - - -@contextlib.contextmanager -def mock_open_content(for_path, content): - """Mock open() builtin and forces it to return a certain `content` - on read() if the path being opened matches `for_path`. - """ - def open_mock(name, *args, **kwargs): - if name == for_path: - if PY3: - if isinstance(content, basestring): - return io.StringIO(content) - else: - return io.BytesIO(content) - else: - return io.BytesIO(content) - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, create=True, side_effect=open_mock) as m: - yield m - - -@contextlib.contextmanager -def mock_open_exception(for_path, exc): - """Mock open() builtin and raises `exc` if the path being opened - matches `for_path`. - """ - def open_mock(name, *args, **kwargs): - if name == for_path: - raise exc - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, create=True, side_effect=open_mock) as m: - yield m - - -# ===================================================================== -# --- system virtual memory -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemVirtualMemory(unittest.TestCase): - - def test_total(self): - # free_value = free_physmem().total - # psutil_value = psutil.virtual_memory().total - # self.assertEqual(free_value, psutil_value) - vmstat_value = vmstat('total memory') * 1024 - psutil_value = psutil.virtual_memory().total - self.assertAlmostEqual(vmstat_value, psutil_value) - - # Older versions of procps used slab memory to calculate used memory. - # This got changed in: - # https://gitlab.com/procps-ng/procps/commit/ - # 05d751c4f076a2f0118b914c5e51cfbb4762ad8e - @unittest.skipIf(LINUX and get_free_version_info() < (3, 3, 12), - "old free version") - @retry_on_failure() - def test_used(self): - free = free_physmem() - free_value = free.used - psutil_value = psutil.virtual_memory().used - self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE, - msg='%s %s \n%s' % (free_value, psutil_value, free.output)) - - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - @retry_on_failure() - def test_free(self): - vmstat_value = vmstat('free memory') * 1024 - psutil_value = psutil.virtual_memory().free - self.assertAlmostEqual( - vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_buffers(self): - vmstat_value = vmstat('buffer memory') * 1024 - psutil_value = psutil.virtual_memory().buffers - self.assertAlmostEqual( - vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) - - # https://travis-ci.org/giampaolo/psutil/jobs/226719664 - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - @retry_on_failure() - def test_active(self): - vmstat_value = vmstat('active memory') * 1024 - psutil_value = psutil.virtual_memory().active - self.assertAlmostEqual( - vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) - - # https://travis-ci.org/giampaolo/psutil/jobs/227242952 - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - @retry_on_failure() - def test_inactive(self): - vmstat_value = vmstat('inactive memory') * 1024 - psutil_value = psutil.virtual_memory().inactive - self.assertAlmostEqual( - vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_shared(self): - free = free_physmem() - free_value = free.shared - if free_value == 0: - raise unittest.SkipTest("free does not support 'shared' column") - psutil_value = psutil.virtual_memory().shared - self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE, - msg='%s %s \n%s' % (free_value, psutil_value, free.output)) - - @retry_on_failure() - def test_available(self): - # "free" output format has changed at some point: - # https://github.com/giampaolo/psutil/issues/538#issuecomment-147192098 - out = sh("free -b") - lines = out.split('\n') - if 'available' not in lines[0]: - raise unittest.SkipTest("free does not support 'available' column") - else: - free_value = int(lines[1].split()[-1]) - psutil_value = psutil.virtual_memory().available - self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE, - msg='%s %s \n%s' % (free_value, psutil_value, out)) - - def test_warnings_on_misses(self): - # Emulate a case where /proc/meminfo provides few info. - # psutil is supposed to set the missing fields to 0 and - # raise a warning. - with mock_open_content( - '/proc/meminfo', - textwrap.dedent("""\ - Active(anon): 6145416 kB - Active(file): 2950064 kB - Inactive(anon): 574764 kB - Inactive(file): 1567648 kB - MemAvailable: -1 kB - MemFree: 2057400 kB - MemTotal: 16325648 kB - SReclaimable: 346648 kB - """).encode()) as m: - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter("always") - ret = psutil.virtual_memory() - assert m.called - self.assertEqual(len(ws), 1) - w = ws[0] - assert w.filename.endswith('psutil/_pslinux.py') - self.assertIn( - "memory stats couldn't be determined", str(w.message)) - self.assertIn("cached", str(w.message)) - self.assertIn("shared", str(w.message)) - self.assertIn("active", str(w.message)) - self.assertIn("inactive", str(w.message)) - self.assertIn("buffers", str(w.message)) - self.assertIn("available", str(w.message)) - self.assertEqual(ret.cached, 0) - self.assertEqual(ret.active, 0) - self.assertEqual(ret.inactive, 0) - self.assertEqual(ret.shared, 0) - self.assertEqual(ret.buffers, 0) - self.assertEqual(ret.available, 0) - self.assertEqual(ret.slab, 0) - - @retry_on_failure() - def test_avail_old_percent(self): - # Make sure that our calculation of avail mem for old kernels - # is off by max 15%. - from psutil._pslinux import calculate_avail_vmem - from psutil._pslinux import open_binary - - mems = {} - with open_binary('/proc/meminfo') as f: - for line in f: - fields = line.split() - mems[fields[0]] = int(fields[1]) * 1024 - - a = calculate_avail_vmem(mems) - if b'MemAvailable:' in mems: - b = mems[b'MemAvailable:'] - diff_percent = abs(a - b) / a * 100 - self.assertLess(diff_percent, 15) - - def test_avail_old_comes_from_kernel(self): - # Make sure "MemAvailable:" coluimn is used instead of relying - # on our internal algorithm to calculate avail mem. - with mock_open_content( - '/proc/meminfo', - textwrap.dedent("""\ - Active: 9444728 kB - Active(anon): 6145416 kB - Active(file): 2950064 kB - Buffers: 287952 kB - Cached: 4818144 kB - Inactive(file): 1578132 kB - Inactive(anon): 574764 kB - Inactive(file): 1567648 kB - MemAvailable: 6574984 kB - MemFree: 2057400 kB - MemTotal: 16325648 kB - Shmem: 577588 kB - SReclaimable: 346648 kB - """).encode()) as m: - with warnings.catch_warnings(record=True) as ws: - ret = psutil.virtual_memory() - assert m.called - self.assertEqual(ret.available, 6574984 * 1024) - w = ws[0] - self.assertIn( - "inactive memory stats couldn't be determined", str(w.message)) - - def test_avail_old_missing_fields(self): - # Remove Active(file), Inactive(file) and SReclaimable - # from /proc/meminfo and make sure the fallback is used - # (free + cached), - with mock_open_content( - "/proc/meminfo", - textwrap.dedent("""\ - Active: 9444728 kB - Active(anon): 6145416 kB - Buffers: 287952 kB - Cached: 4818144 kB - Inactive(file): 1578132 kB - Inactive(anon): 574764 kB - MemFree: 2057400 kB - MemTotal: 16325648 kB - Shmem: 577588 kB - """).encode()) as m: - with warnings.catch_warnings(record=True) as ws: - ret = psutil.virtual_memory() - assert m.called - self.assertEqual(ret.available, 2057400 * 1024 + 4818144 * 1024) - w = ws[0] - self.assertIn( - "inactive memory stats couldn't be determined", str(w.message)) - - def test_avail_old_missing_zoneinfo(self): - # Remove /proc/zoneinfo file. Make sure fallback is used - # (free + cached). - with mock_open_content( - "/proc/meminfo", - textwrap.dedent("""\ - Active: 9444728 kB - Active(anon): 6145416 kB - Active(file): 2950064 kB - Buffers: 287952 kB - Cached: 4818144 kB - Inactive(file): 1578132 kB - Inactive(anon): 574764 kB - Inactive(file): 1567648 kB - MemFree: 2057400 kB - MemTotal: 16325648 kB - Shmem: 577588 kB - SReclaimable: 346648 kB - """).encode()): - with mock_open_exception( - "/proc/zoneinfo", - IOError(errno.ENOENT, 'no such file or directory')): - with warnings.catch_warnings(record=True) as ws: - ret = psutil.virtual_memory() - self.assertEqual( - ret.available, 2057400 * 1024 + 4818144 * 1024) - w = ws[0] - self.assertIn( - "inactive memory stats couldn't be determined", - str(w.message)) - - def test_virtual_memory_mocked(self): - # Emulate /proc/meminfo because neither vmstat nor free return slab. - def open_mock(name, *args, **kwargs): - if name == '/proc/meminfo': - return io.BytesIO(textwrap.dedent("""\ - MemTotal: 100 kB - MemFree: 2 kB - MemAvailable: 3 kB - Buffers: 4 kB - Cached: 5 kB - SwapCached: 6 kB - Active: 7 kB - Inactive: 8 kB - Active(anon): 9 kB - Inactive(anon): 10 kB - Active(file): 11 kB - Inactive(file): 12 kB - Unevictable: 13 kB - Mlocked: 14 kB - SwapTotal: 15 kB - SwapFree: 16 kB - Dirty: 17 kB - Writeback: 18 kB - AnonPages: 19 kB - Mapped: 20 kB - Shmem: 21 kB - Slab: 22 kB - SReclaimable: 23 kB - SUnreclaim: 24 kB - KernelStack: 25 kB - PageTables: 26 kB - NFS_Unstable: 27 kB - Bounce: 28 kB - WritebackTmp: 29 kB - CommitLimit: 30 kB - Committed_AS: 31 kB - VmallocTotal: 32 kB - VmallocUsed: 33 kB - VmallocChunk: 34 kB - HardwareCorrupted: 35 kB - AnonHugePages: 36 kB - ShmemHugePages: 37 kB - ShmemPmdMapped: 38 kB - CmaTotal: 39 kB - CmaFree: 40 kB - HugePages_Total: 41 kB - HugePages_Free: 42 kB - HugePages_Rsvd: 43 kB - HugePages_Surp: 44 kB - Hugepagesize: 45 kB - DirectMap46k: 46 kB - DirectMap47M: 47 kB - DirectMap48G: 48 kB - """).encode()) - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, create=True, side_effect=open_mock) as m: - mem = psutil.virtual_memory() - assert m.called - self.assertEqual(mem.total, 100 * 1024) - self.assertEqual(mem.free, 2 * 1024) - self.assertEqual(mem.buffers, 4 * 1024) - # cached mem also includes reclaimable memory - self.assertEqual(mem.cached, (5 + 23) * 1024) - self.assertEqual(mem.shared, 21 * 1024) - self.assertEqual(mem.active, 7 * 1024) - self.assertEqual(mem.inactive, 8 * 1024) - self.assertEqual(mem.slab, 22 * 1024) - self.assertEqual(mem.available, 3 * 1024) - - -# ===================================================================== -# --- system swap memory -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemSwapMemory(unittest.TestCase): - - @staticmethod - def meminfo_has_swap_info(): - """Return True if /proc/meminfo provides swap metrics.""" - with open("/proc/meminfo") as f: - data = f.read() - return 'SwapTotal:' in data and 'SwapFree:' in data - - def test_total(self): - free_value = free_swap().total - psutil_value = psutil.swap_memory().total - return self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_used(self): - free_value = free_swap().used - psutil_value = psutil.swap_memory().used - return self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_free(self): - free_value = free_swap().free - psutil_value = psutil.swap_memory().free - return self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE) - - def test_missing_sin_sout(self): - with mock.patch('psutil._common.open', create=True) as m: - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter("always") - ret = psutil.swap_memory() - assert m.called - self.assertEqual(len(ws), 1) - w = ws[0] - assert w.filename.endswith('psutil/_pslinux.py') - self.assertIn( - "'sin' and 'sout' swap memory stats couldn't " - "be determined", str(w.message)) - self.assertEqual(ret.sin, 0) - self.assertEqual(ret.sout, 0) - - def test_no_vmstat_mocked(self): - # see https://github.com/giampaolo/psutil/issues/722 - with mock_open_exception( - "/proc/vmstat", - IOError(errno.ENOENT, 'no such file or directory')) as m: - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter("always") - ret = psutil.swap_memory() - assert m.called - self.assertEqual(len(ws), 1) - w = ws[0] - assert w.filename.endswith('psutil/_pslinux.py') - self.assertIn( - "'sin' and 'sout' swap memory stats couldn't " - "be determined and were set to 0", - str(w.message)) - self.assertEqual(ret.sin, 0) - self.assertEqual(ret.sout, 0) - - def test_meminfo_against_sysinfo(self): - # Make sure the content of /proc/meminfo about swap memory - # matches sysinfo() syscall, see: - # https://github.com/giampaolo/psutil/issues/1015 - if not self.meminfo_has_swap_info(): - return unittest.skip("/proc/meminfo has no swap metrics") - with mock.patch('psutil._pslinux.cext.linux_sysinfo') as m: - swap = psutil.swap_memory() - assert not m.called - import psutil._psutil_linux as cext - _, _, _, _, total, free, unit_multiplier = cext.linux_sysinfo() - total *= unit_multiplier - free *= unit_multiplier - self.assertEqual(swap.total, total) - self.assertAlmostEqual(swap.free, free, delta=MEMORY_TOLERANCE) - - def test_emulate_meminfo_has_no_metrics(self): - # Emulate a case where /proc/meminfo provides no swap metrics - # in which case sysinfo() syscall is supposed to be used - # as a fallback. - with mock_open_content("/proc/meminfo", b"") as m: - psutil.swap_memory() - assert m.called - - -# ===================================================================== -# --- system CPU -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemCPUTimes(unittest.TestCase): - - @unittest.skipIf(TRAVIS, "unknown failure on travis") - def test_fields(self): - fields = psutil.cpu_times()._fields - kernel_ver = re.findall(r'\d+\.\d+\.\d+', os.uname()[2])[0] - kernel_ver_info = tuple(map(int, kernel_ver.split('.'))) - if kernel_ver_info >= (2, 6, 11): - self.assertIn('steal', fields) - else: - self.assertNotIn('steal', fields) - if kernel_ver_info >= (2, 6, 24): - self.assertIn('guest', fields) - else: - self.assertNotIn('guest', fields) - if kernel_ver_info >= (3, 2, 0): - self.assertIn('guest_nice', fields) - else: - self.assertNotIn('guest_nice', fields) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemCPUCountLogical(unittest.TestCase): - - @unittest.skipIf(not os.path.exists("/sys/devices/system/cpu/online"), - "/sys/devices/system/cpu/online does not exist") - def test_against_sysdev_cpu_online(self): - with open("/sys/devices/system/cpu/online") as f: - value = f.read().strip() - if "-" in str(value): - value = int(value.split('-')[1]) + 1 - self.assertEqual(psutil.cpu_count(), value) - - @unittest.skipIf(not os.path.exists("/sys/devices/system/cpu"), - "/sys/devices/system/cpu does not exist") - def test_against_sysdev_cpu_num(self): - ls = os.listdir("/sys/devices/system/cpu") - count = len([x for x in ls if re.search(r"cpu\d+$", x) is not None]) - self.assertEqual(psutil.cpu_count(), count) - - @unittest.skipIf(not which("nproc"), "nproc utility not available") - def test_against_nproc(self): - num = int(sh("nproc --all")) - self.assertEqual(psutil.cpu_count(logical=True), num) - - @unittest.skipIf(not which("lscpu"), "lscpu utility not available") - def test_against_lscpu(self): - out = sh("lscpu -p") - num = len([x for x in out.split('\n') if not x.startswith('#')]) - self.assertEqual(psutil.cpu_count(logical=True), num) - - def test_emulate_fallbacks(self): - import psutil._pslinux - original = psutil._pslinux.cpu_count_logical() - # Here we want to mock os.sysconf("SC_NPROCESSORS_ONLN") in - # order to cause the parsing of /proc/cpuinfo and /proc/stat. - with mock.patch( - 'psutil._pslinux.os.sysconf', side_effect=ValueError) as m: - self.assertEqual(psutil._pslinux.cpu_count_logical(), original) - assert m.called - - # Let's have open() return emtpy data and make sure None is - # returned ('cause we mimick os.cpu_count()). - with mock.patch('psutil._common.open', create=True) as m: - self.assertIsNone(psutil._pslinux.cpu_count_logical()) - self.assertEqual(m.call_count, 2) - # /proc/stat should be the last one - self.assertEqual(m.call_args[0][0], '/proc/stat') - - # Let's push this a bit further and make sure /proc/cpuinfo - # parsing works as expected. - with open('/proc/cpuinfo', 'rb') as f: - cpuinfo_data = f.read() - fake_file = io.BytesIO(cpuinfo_data) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(psutil._pslinux.cpu_count_logical(), original) - - # Finally, let's make /proc/cpuinfo return meaningless data; - # this way we'll fall back on relying on /proc/stat - with mock_open_content('/proc/cpuinfo', b"") as m: - self.assertEqual(psutil._pslinux.cpu_count_logical(), original) - m.called - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemCPUCountPhysical(unittest.TestCase): - - @unittest.skipIf(not which("lscpu"), "lscpu utility not available") - def test_against_lscpu(self): - out = sh("lscpu -p") - core_ids = set() - for line in out.split('\n'): - if not line.startswith('#'): - fields = line.split(',') - core_ids.add(fields[1]) - self.assertEqual(psutil.cpu_count(logical=False), len(core_ids)) - - def test_emulate_none(self): - with mock.patch('glob.glob', return_value=[]) as m1: - with mock.patch('psutil._common.open', create=True) as m2: - self.assertIsNone(psutil._pslinux.cpu_count_physical()) - assert m1.called - assert m2.called - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemCPUFrequency(unittest.TestCase): - - @unittest.skipIf(TRAVIS, "fails on Travis") - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_emulate_use_second_file(self): - # https://github.com/giampaolo/psutil/issues/981 - def path_exists_mock(path): - if path.startswith("/sys/devices/system/cpu/cpufreq/policy"): - return False - else: - return orig_exists(path) - - orig_exists = os.path.exists - with mock.patch("os.path.exists", side_effect=path_exists_mock, - create=True): - assert psutil.cpu_freq() - - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_emulate_use_cpuinfo(self): - # Emulate a case where /sys/devices/system/cpu/cpufreq* does not - # exist and /proc/cpuinfo is used instead. - def path_exists_mock(path): - if path.startswith('/sys/devices/system/cpu/'): - return False - else: - if path == "/proc/cpuinfo": - flags.append(None) - return os_path_exists(path) - - flags = [] - os_path_exists = os.path.exists - try: - with mock.patch("os.path.exists", side_effect=path_exists_mock): - reload_module(psutil._pslinux) - ret = psutil.cpu_freq() - assert ret - assert flags - self.assertEqual(ret.max, 0.0) - self.assertEqual(ret.min, 0.0) - for freq in psutil.cpu_freq(percpu=True): - self.assertEqual(ret.max, 0.0) - self.assertEqual(ret.min, 0.0) - finally: - reload_module(psutil._pslinux) - reload_module(psutil) - - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_emulate_data(self): - def open_mock(name, *args, **kwargs): - if (name.endswith('/scaling_cur_freq') and - name.startswith("/sys/devices/system/cpu/cpufreq/policy")): - return io.BytesIO(b"500000") - elif (name.endswith('/scaling_min_freq') and - name.startswith("/sys/devices/system/cpu/cpufreq/policy")): - return io.BytesIO(b"600000") - elif (name.endswith('/scaling_max_freq') and - name.startswith("/sys/devices/system/cpu/cpufreq/policy")): - return io.BytesIO(b"700000") - elif name == '/proc/cpuinfo': - return io.BytesIO(b"cpu MHz : 500") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - with mock.patch( - 'os.path.exists', return_value=True): - freq = psutil.cpu_freq() - self.assertEqual(freq.current, 500.0) - # when /proc/cpuinfo is used min and max frequencies are not - # available and are set to 0. - if freq.min != 0.0: - self.assertEqual(freq.min, 600.0) - if freq.max != 0.0: - self.assertEqual(freq.max, 700.0) - - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_emulate_multi_cpu(self): - def open_mock(name, *args, **kwargs): - n = name - if (n.endswith('/scaling_cur_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy0")): - return io.BytesIO(b"100000") - elif (n.endswith('/scaling_min_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy0")): - return io.BytesIO(b"200000") - elif (n.endswith('/scaling_max_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy0")): - return io.BytesIO(b"300000") - elif (n.endswith('/scaling_cur_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy1")): - return io.BytesIO(b"400000") - elif (n.endswith('/scaling_min_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy1")): - return io.BytesIO(b"500000") - elif (n.endswith('/scaling_max_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy1")): - return io.BytesIO(b"600000") - elif name == '/proc/cpuinfo': - return io.BytesIO(b"cpu MHz : 100\n" - b"cpu MHz : 400") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - with mock.patch('os.path.exists', return_value=True): - with mock.patch('psutil._pslinux.cpu_count_logical', - return_value=2): - freq = psutil.cpu_freq(percpu=True) - self.assertEqual(freq[0].current, 100.0) - if freq[0].min != 0.0: - self.assertEqual(freq[0].min, 200.0) - if freq[0].max != 0.0: - self.assertEqual(freq[0].max, 300.0) - self.assertEqual(freq[1].current, 400.0) - if freq[1].min != 0.0: - self.assertEqual(freq[1].min, 500.0) - if freq[1].max != 0.0: - self.assertEqual(freq[1].max, 600.0) - - @unittest.skipIf(TRAVIS, "fails on Travis") - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_emulate_no_scaling_cur_freq_file(self): - # See: https://github.com/giampaolo/psutil/issues/1071 - def open_mock(name, *args, **kwargs): - if name.endswith('/scaling_cur_freq'): - raise IOError(errno.ENOENT, "") - elif name.endswith('/cpuinfo_cur_freq'): - return io.BytesIO(b"200000") - elif name == '/proc/cpuinfo': - return io.BytesIO(b"cpu MHz : 200") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - with mock.patch('os.path.exists', return_value=True): - with mock.patch('psutil._pslinux.cpu_count_logical', - return_value=1): - freq = psutil.cpu_freq() - self.assertEqual(freq.current, 200) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemCPUStats(unittest.TestCase): - - @unittest.skipIf(TRAVIS, "fails on Travis") - def test_ctx_switches(self): - vmstat_value = vmstat("context switches") - psutil_value = psutil.cpu_stats().ctx_switches - self.assertAlmostEqual(vmstat_value, psutil_value, delta=500) - - @unittest.skipIf(TRAVIS, "fails on Travis") - def test_interrupts(self): - vmstat_value = vmstat("interrupts") - psutil_value = psutil.cpu_stats().interrupts - self.assertAlmostEqual(vmstat_value, psutil_value, delta=500) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestLoadAvg(unittest.TestCase): - - @unittest.skipIf(not HAS_GETLOADAVG, "not supported") - def test_getloadavg(self): - psutil_value = psutil.getloadavg() - with open("/proc/loadavg", "r") as f: - proc_value = f.read().split() - - self.assertAlmostEqual(float(proc_value[0]), psutil_value[0], delta=1) - self.assertAlmostEqual(float(proc_value[1]), psutil_value[1], delta=1) - self.assertAlmostEqual(float(proc_value[2]), psutil_value[2], delta=1) - - -# ===================================================================== -# --- system network -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemNetIfAddrs(unittest.TestCase): - - def test_ips(self): - for name, addrs in psutil.net_if_addrs().items(): - for addr in addrs: - if addr.family == psutil.AF_LINK: - self.assertEqual(addr.address, get_mac_address(name)) - elif addr.family == socket.AF_INET: - self.assertEqual(addr.address, get_ipv4_address(name)) - # TODO: test for AF_INET6 family - - # XXX - not reliable when having virtual NICs installed by Docker. - # @unittest.skipIf(not which('ip'), "'ip' utility not available") - # @unittest.skipIf(TRAVIS, "skipped on Travis") - # def test_net_if_names(self): - # out = sh("ip addr").strip() - # nics = [x for x in psutil.net_if_addrs().keys() if ':' not in x] - # found = 0 - # for line in out.split('\n'): - # line = line.strip() - # if re.search(r"^\d+:", line): - # found += 1 - # name = line.split(':')[1].strip() - # self.assertIn(name, nics) - # self.assertEqual(len(nics), found, msg="%s\n---\n%s" % ( - # pprint.pformat(nics), out)) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemNetIfStats(unittest.TestCase): - - def test_against_ifconfig(self): - for name, stats in psutil.net_if_stats().items(): - try: - out = sh("ifconfig %s" % name) - except RuntimeError: - pass - else: - # Not always reliable. - # self.assertEqual(stats.isup, 'RUNNING' in out, msg=out) - self.assertEqual(stats.mtu, - int(re.findall(r'(?i)MTU[: ](\d+)', out)[0])) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemNetIOCounters(unittest.TestCase): - - @retry_on_failure() - def test_against_ifconfig(self): - def ifconfig(nic): - ret = {} - out = sh("ifconfig %s" % name) - ret['packets_recv'] = int( - re.findall(r'RX packets[: ](\d+)', out)[0]) - ret['packets_sent'] = int( - re.findall(r'TX packets[: ](\d+)', out)[0]) - ret['errin'] = int(re.findall(r'errors[: ](\d+)', out)[0]) - ret['errout'] = int(re.findall(r'errors[: ](\d+)', out)[1]) - ret['dropin'] = int(re.findall(r'dropped[: ](\d+)', out)[0]) - ret['dropout'] = int(re.findall(r'dropped[: ](\d+)', out)[1]) - ret['bytes_recv'] = int( - re.findall(r'RX (?:packets \d+ +)?bytes[: ](\d+)', out)[0]) - ret['bytes_sent'] = int( - re.findall(r'TX (?:packets \d+ +)?bytes[: ](\d+)', out)[0]) - return ret - - nio = psutil.net_io_counters(pernic=True, nowrap=False) - for name, stats in nio.items(): - try: - ifconfig_ret = ifconfig(name) - except RuntimeError: - continue - self.assertAlmostEqual( - stats.bytes_recv, ifconfig_ret['bytes_recv'], delta=1024 * 5) - self.assertAlmostEqual( - stats.bytes_sent, ifconfig_ret['bytes_sent'], delta=1024 * 5) - self.assertAlmostEqual( - stats.packets_recv, ifconfig_ret['packets_recv'], delta=1024) - self.assertAlmostEqual( - stats.packets_sent, ifconfig_ret['packets_sent'], delta=1024) - self.assertAlmostEqual( - stats.errin, ifconfig_ret['errin'], delta=10) - self.assertAlmostEqual( - stats.errout, ifconfig_ret['errout'], delta=10) - self.assertAlmostEqual( - stats.dropin, ifconfig_ret['dropin'], delta=10) - self.assertAlmostEqual( - stats.dropout, ifconfig_ret['dropout'], delta=10) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemNetConnections(unittest.TestCase): - - @mock.patch('psutil._pslinux.socket.inet_ntop', side_effect=ValueError) - @mock.patch('psutil._pslinux.supports_ipv6', return_value=False) - def test_emulate_ipv6_unsupported(self, supports_ipv6, inet_ntop): - # see: https://github.com/giampaolo/psutil/issues/623 - try: - s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - self.addCleanup(s.close) - s.bind(("::1", 0)) - except socket.error: - pass - psutil.net_connections(kind='inet6') - - def test_emulate_unix(self): - with mock_open_content( - '/proc/net/unix', - textwrap.dedent("""\ - 0: 00000003 000 000 0001 03 462170 @/tmp/dbus-Qw2hMPIU3n - 0: 00000003 000 000 0001 03 35010 @/tmp/dbus-tB2X8h69BQ - 0: 00000003 000 000 0001 03 34424 @/tmp/dbus-cHy80Y8O - 000000000000000000000000000000000000000000000000000000 - """)) as m: - psutil.net_connections(kind='unix') - assert m.called - - -# ===================================================================== -# --- system disks -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemDiskPartitions(unittest.TestCase): - - @unittest.skipIf(not hasattr(os, 'statvfs'), "os.statvfs() not available") - @skip_on_not_implemented() - def test_against_df(self): - # test psutil.disk_usage() and psutil.disk_partitions() - # against "df -a" - def df(path): - out = sh('df -P -B 1 "%s"' % path).strip() - lines = out.split('\n') - lines.pop(0) - line = lines.pop(0) - dev, total, used, free = line.split()[:4] - if dev == 'none': - dev = '' - total, used, free = int(total), int(used), int(free) - return dev, total, used, free - - for part in psutil.disk_partitions(all=False): - usage = psutil.disk_usage(part.mountpoint) - dev, total, used, free = df(part.mountpoint) - self.assertEqual(usage.total, total) - # 10 MB tollerance - if abs(usage.free - free) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.free, free)) - if abs(usage.used - used) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.used, used)) - - def test_zfs_fs(self): - # Test that ZFS partitions are returned. - with open("/proc/filesystems", "r") as f: - data = f.read() - if 'zfs' in data: - for part in psutil.disk_partitions(): - if part.fstype == 'zfs': - break - else: - self.fail("couldn't find any ZFS partition") - else: - # No ZFS partitions on this system. Let's fake one. - fake_file = io.StringIO(u("nodev\tzfs\n")) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m1: - with mock.patch( - 'psutil._pslinux.cext.disk_partitions', - return_value=[('/dev/sdb3', '/', 'zfs', 'rw')]) as m2: - ret = psutil.disk_partitions() - assert m1.called - assert m2.called - assert ret - self.assertEqual(ret[0].fstype, 'zfs') - - def test_emulate_realpath_fail(self): - # See: https://github.com/giampaolo/psutil/issues/1307 - try: - with mock.patch('os.path.realpath', - return_value='/non/existent') as m: - with self.assertRaises(FileNotFoundError): - psutil.disk_partitions() - assert m.called - finally: - psutil.PROCFS_PATH = "/proc" - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemDiskIoCounters(unittest.TestCase): - - def test_emulate_kernel_2_4(self): - # Tests /proc/diskstats parsing format for 2.4 kernels, see: - # https://github.com/giampaolo/psutil/issues/767 - with mock_open_content( - '/proc/diskstats', - " 3 0 1 hda 2 3 4 5 6 7 8 9 10 11 12"): - with mock.patch('psutil._pslinux.is_storage_device', - return_value=True): - ret = psutil.disk_io_counters(nowrap=False) - self.assertEqual(ret.read_count, 1) - self.assertEqual(ret.read_merged_count, 2) - self.assertEqual(ret.read_bytes, 3 * SECTOR_SIZE) - self.assertEqual(ret.read_time, 4) - self.assertEqual(ret.write_count, 5) - self.assertEqual(ret.write_merged_count, 6) - self.assertEqual(ret.write_bytes, 7 * SECTOR_SIZE) - self.assertEqual(ret.write_time, 8) - self.assertEqual(ret.busy_time, 10) - - def test_emulate_kernel_2_6_full(self): - # Tests /proc/diskstats parsing format for 2.6 kernels, - # lines reporting all metrics: - # https://github.com/giampaolo/psutil/issues/767 - with mock_open_content( - '/proc/diskstats', - " 3 0 hda 1 2 3 4 5 6 7 8 9 10 11"): - with mock.patch('psutil._pslinux.is_storage_device', - return_value=True): - ret = psutil.disk_io_counters(nowrap=False) - self.assertEqual(ret.read_count, 1) - self.assertEqual(ret.read_merged_count, 2) - self.assertEqual(ret.read_bytes, 3 * SECTOR_SIZE) - self.assertEqual(ret.read_time, 4) - self.assertEqual(ret.write_count, 5) - self.assertEqual(ret.write_merged_count, 6) - self.assertEqual(ret.write_bytes, 7 * SECTOR_SIZE) - self.assertEqual(ret.write_time, 8) - self.assertEqual(ret.busy_time, 10) - - def test_emulate_kernel_2_6_limited(self): - # Tests /proc/diskstats parsing format for 2.6 kernels, - # where one line of /proc/partitions return a limited - # amount of metrics when it bumps into a partition - # (instead of a disk). See: - # https://github.com/giampaolo/psutil/issues/767 - with mock_open_content( - '/proc/diskstats', - " 3 1 hda 1 2 3 4"): - with mock.patch('psutil._pslinux.is_storage_device', - return_value=True): - ret = psutil.disk_io_counters(nowrap=False) - self.assertEqual(ret.read_count, 1) - self.assertEqual(ret.read_bytes, 2 * SECTOR_SIZE) - self.assertEqual(ret.write_count, 3) - self.assertEqual(ret.write_bytes, 4 * SECTOR_SIZE) - - self.assertEqual(ret.read_merged_count, 0) - self.assertEqual(ret.read_time, 0) - self.assertEqual(ret.write_merged_count, 0) - self.assertEqual(ret.write_time, 0) - self.assertEqual(ret.busy_time, 0) - - def test_emulate_include_partitions(self): - # Make sure that when perdisk=True disk partitions are returned, - # see: - # https://github.com/giampaolo/psutil/pull/1313#issuecomment-408626842 - with mock_open_content( - '/proc/diskstats', - textwrap.dedent("""\ - 3 0 nvme0n1 1 2 3 4 5 6 7 8 9 10 11 - 3 0 nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11 - """)): - with mock.patch('psutil._pslinux.is_storage_device', - return_value=False): - ret = psutil.disk_io_counters(perdisk=True, nowrap=False) - self.assertEqual(len(ret), 2) - self.assertEqual(ret['nvme0n1'].read_count, 1) - self.assertEqual(ret['nvme0n1p1'].read_count, 1) - self.assertEqual(ret['nvme0n1'].write_count, 5) - self.assertEqual(ret['nvme0n1p1'].write_count, 5) - - def test_emulate_exclude_partitions(self): - # Make sure that when perdisk=False partitions (e.g. 'sda1', - # 'nvme0n1p1') are skipped and not included in the total count. - # https://github.com/giampaolo/psutil/pull/1313#issuecomment-408626842 - with mock_open_content( - '/proc/diskstats', - textwrap.dedent("""\ - 3 0 nvme0n1 1 2 3 4 5 6 7 8 9 10 11 - 3 0 nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11 - """)): - with mock.patch('psutil._pslinux.is_storage_device', - return_value=False): - ret = psutil.disk_io_counters(perdisk=False, nowrap=False) - self.assertIsNone(ret) - - # - def is_storage_device(name): - return name == 'nvme0n1' - - with mock_open_content( - '/proc/diskstats', - textwrap.dedent("""\ - 3 0 nvme0n1 1 2 3 4 5 6 7 8 9 10 11 - 3 0 nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11 - """)): - with mock.patch('psutil._pslinux.is_storage_device', - create=True, side_effect=is_storage_device): - ret = psutil.disk_io_counters(perdisk=False, nowrap=False) - self.assertEqual(ret.read_count, 1) - self.assertEqual(ret.write_count, 5) - - def test_emulate_use_sysfs(self): - def exists(path): - if path == '/proc/diskstats': - return False - return True - - wprocfs = psutil.disk_io_counters(perdisk=True) - with mock.patch('psutil._pslinux.os.path.exists', - create=True, side_effect=exists): - wsysfs = psutil.disk_io_counters(perdisk=True) - self.assertEqual(len(wprocfs), len(wsysfs)) - - def test_emulate_not_impl(self): - def exists(path): - return False - - with mock.patch('psutil._pslinux.os.path.exists', - create=True, side_effect=exists): - self.assertRaises(NotImplementedError, psutil.disk_io_counters) - - -# ===================================================================== -# --- misc -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestMisc(unittest.TestCase): - - def test_boot_time(self): - vmstat_value = vmstat('boot time') - psutil_value = psutil.boot_time() - self.assertEqual(int(vmstat_value), int(psutil_value)) - - def test_no_procfs_on_import(self): - my_procfs = tempfile.mkdtemp() - - with open(os.path.join(my_procfs, 'stat'), 'w') as f: - f.write('cpu 0 0 0 0 0 0 0 0 0 0\n') - f.write('cpu0 0 0 0 0 0 0 0 0 0 0\n') - f.write('cpu1 0 0 0 0 0 0 0 0 0 0\n') - - try: - orig_open = open - - def open_mock(name, *args, **kwargs): - if name.startswith('/proc'): - raise IOError(errno.ENOENT, 'rejecting access for test') - return orig_open(name, *args, **kwargs) - - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - reload_module(psutil) - - self.assertRaises(IOError, psutil.cpu_times) - self.assertRaises(IOError, psutil.cpu_times, percpu=True) - self.assertRaises(IOError, psutil.cpu_percent) - self.assertRaises(IOError, psutil.cpu_percent, percpu=True) - self.assertRaises(IOError, psutil.cpu_times_percent) - self.assertRaises( - IOError, psutil.cpu_times_percent, percpu=True) - - psutil.PROCFS_PATH = my_procfs - - self.assertEqual(psutil.cpu_percent(), 0) - self.assertEqual(sum(psutil.cpu_times_percent()), 0) - - # since we don't know the number of CPUs at import time, - # we awkwardly say there are none until the second call - per_cpu_percent = psutil.cpu_percent(percpu=True) - self.assertEqual(sum(per_cpu_percent), 0) - - # ditto awkward length - per_cpu_times_percent = psutil.cpu_times_percent(percpu=True) - self.assertEqual(sum(map(sum, per_cpu_times_percent)), 0) - - # much user, very busy - with open(os.path.join(my_procfs, 'stat'), 'w') as f: - f.write('cpu 1 0 0 0 0 0 0 0 0 0\n') - f.write('cpu0 1 0 0 0 0 0 0 0 0 0\n') - f.write('cpu1 1 0 0 0 0 0 0 0 0 0\n') - - self.assertNotEqual(psutil.cpu_percent(), 0) - self.assertNotEqual( - sum(psutil.cpu_percent(percpu=True)), 0) - self.assertNotEqual(sum(psutil.cpu_times_percent()), 0) - self.assertNotEqual( - sum(map(sum, psutil.cpu_times_percent(percpu=True))), 0) - finally: - shutil.rmtree(my_procfs) - reload_module(psutil) - - self.assertEqual(psutil.PROCFS_PATH, '/proc') - - def test_cpu_steal_decrease(self): - # Test cumulative cpu stats decrease. We should ignore this. - # See issue #1210. - with mock_open_content( - "/proc/stat", - textwrap.dedent("""\ - cpu 0 0 0 0 0 0 0 1 0 0 - cpu0 0 0 0 0 0 0 0 1 0 0 - cpu1 0 0 0 0 0 0 0 1 0 0 - """).encode()) as m: - # first call to "percent" functions should read the new stat file - # and compare to the "real" file read at import time - so the - # values are meaningless - psutil.cpu_percent() - assert m.called - psutil.cpu_percent(percpu=True) - psutil.cpu_times_percent() - psutil.cpu_times_percent(percpu=True) - - with mock_open_content( - "/proc/stat", - textwrap.dedent("""\ - cpu 1 0 0 0 0 0 0 0 0 0 - cpu0 1 0 0 0 0 0 0 0 0 0 - cpu1 1 0 0 0 0 0 0 0 0 0 - """).encode()) as m: - # Increase "user" while steal goes "backwards" to zero. - cpu_percent = psutil.cpu_percent() - assert m.called - cpu_percent_percpu = psutil.cpu_percent(percpu=True) - cpu_times_percent = psutil.cpu_times_percent() - cpu_times_percent_percpu = psutil.cpu_times_percent(percpu=True) - self.assertNotEqual(cpu_percent, 0) - self.assertNotEqual(sum(cpu_percent_percpu), 0) - self.assertNotEqual(sum(cpu_times_percent), 0) - self.assertNotEqual(sum(cpu_times_percent), 100.0) - self.assertNotEqual(sum(map(sum, cpu_times_percent_percpu)), 0) - self.assertNotEqual(sum(map(sum, cpu_times_percent_percpu)), 100.0) - self.assertEqual(cpu_times_percent.steal, 0) - self.assertNotEqual(cpu_times_percent.user, 0) - - def test_boot_time_mocked(self): - with mock.patch('psutil._common.open', create=True) as m: - self.assertRaises( - RuntimeError, - psutil._pslinux.boot_time) - assert m.called - - def test_users_mocked(self): - # Make sure ':0' and ':0.0' (returned by C ext) are converted - # to 'localhost'. - with mock.patch('psutil._pslinux.cext.users', - return_value=[('giampaolo', 'pts/2', ':0', - 1436573184.0, True, 2)]) as m: - self.assertEqual(psutil.users()[0].host, 'localhost') - assert m.called - with mock.patch('psutil._pslinux.cext.users', - return_value=[('giampaolo', 'pts/2', ':0.0', - 1436573184.0, True, 2)]) as m: - self.assertEqual(psutil.users()[0].host, 'localhost') - assert m.called - # ...otherwise it should be returned as-is - with mock.patch('psutil._pslinux.cext.users', - return_value=[('giampaolo', 'pts/2', 'foo', - 1436573184.0, True, 2)]) as m: - self.assertEqual(psutil.users()[0].host, 'foo') - assert m.called - - def test_procfs_path(self): - tdir = tempfile.mkdtemp() - try: - psutil.PROCFS_PATH = tdir - self.assertRaises(IOError, psutil.virtual_memory) - self.assertRaises(IOError, psutil.cpu_times) - self.assertRaises(IOError, psutil.cpu_times, percpu=True) - self.assertRaises(IOError, psutil.boot_time) - # self.assertRaises(IOError, psutil.pids) - self.assertRaises(IOError, psutil.net_connections) - self.assertRaises(IOError, psutil.net_io_counters) - self.assertRaises(IOError, psutil.net_if_stats) - # self.assertRaises(IOError, psutil.disk_io_counters) - self.assertRaises(IOError, psutil.disk_partitions) - self.assertRaises(psutil.NoSuchProcess, psutil.Process) - finally: - psutil.PROCFS_PATH = "/proc" - os.rmdir(tdir) - - def test_issue_687(self): - # In case of thread ID: - # - pid_exists() is supposed to return False - # - Process(tid) is supposed to work - # - pids() should not return the TID - # See: https://github.com/giampaolo/psutil/issues/687 - t = ThreadTask() - t.start() - try: - p = psutil.Process() - tid = p.threads()[1].id - assert not psutil.pid_exists(tid), tid - pt = psutil.Process(tid) - pt.as_dict() - self.assertNotIn(tid, psutil.pids()) - finally: - t.stop() - - def test_pid_exists_no_proc_status(self): - # Internally pid_exists relies on /proc/{pid}/status. - # Emulate a case where this file is empty in which case - # psutil is supposed to fall back on using pids(). - with mock_open_content("/proc/%s/status", "") as m: - assert psutil.pid_exists(os.getpid()) - assert m.called - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -@unittest.skipIf(not HAS_BATTERY, "no battery") -class TestSensorsBattery(unittest.TestCase): - - @unittest.skipIf(not which("acpi"), "acpi utility not available") - def test_percent(self): - out = sh("acpi -b") - acpi_value = int(out.split(",")[1].strip().replace('%', '')) - psutil_value = psutil.sensors_battery().percent - self.assertAlmostEqual(acpi_value, psutil_value, delta=1) - - @unittest.skipIf(not which("acpi"), "acpi utility not available") - def test_power_plugged(self): - out = sh("acpi -b") - if 'unknown' in out.lower(): - return unittest.skip("acpi output not reliable") - if 'discharging at zero rate' in out: - plugged = True - else: - plugged = "Charging" in out.split('\n')[0] - self.assertEqual(psutil.sensors_battery().power_plugged, plugged) - - def test_emulate_power_plugged(self): - # Pretend the AC power cable is connected. - def open_mock(name, *args, **kwargs): - if name.endswith("AC0/online") or name.endswith("AC/online"): - return io.BytesIO(b"1") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - self.assertEqual(psutil.sensors_battery().power_plugged, True) - self.assertEqual( - psutil.sensors_battery().secsleft, psutil.POWER_TIME_UNLIMITED) - assert m.called - - def test_emulate_power_plugged_2(self): - # Same as above but pretend /AC0/online does not exist in which - # case code relies on /status file. - def open_mock(name, *args, **kwargs): - if name.endswith("AC0/online") or name.endswith("AC/online"): - raise IOError(errno.ENOENT, "") - elif name.endswith("/status"): - return io.StringIO(u("charging")) - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - self.assertEqual(psutil.sensors_battery().power_plugged, True) - assert m.called - - def test_emulate_power_not_plugged(self): - # Pretend the AC power cable is not connected. - def open_mock(name, *args, **kwargs): - if name.endswith("AC0/online") or name.endswith("AC/online"): - return io.BytesIO(b"0") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - self.assertEqual(psutil.sensors_battery().power_plugged, False) - assert m.called - - def test_emulate_power_not_plugged_2(self): - # Same as above but pretend /AC0/online does not exist in which - # case code relies on /status file. - def open_mock(name, *args, **kwargs): - if name.endswith("AC0/online") or name.endswith("AC/online"): - raise IOError(errno.ENOENT, "") - elif name.endswith("/status"): - return io.StringIO(u("discharging")) - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - self.assertEqual(psutil.sensors_battery().power_plugged, False) - assert m.called - - def test_emulate_power_undetermined(self): - # Pretend we can't know whether the AC power cable not - # connected (assert fallback to False). - def open_mock(name, *args, **kwargs): - if name.startswith("/sys/class/power_supply/AC0/online") or \ - name.startswith("/sys/class/power_supply/AC/online"): - raise IOError(errno.ENOENT, "") - elif name.startswith("/sys/class/power_supply/BAT0/status"): - return io.BytesIO(b"???") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - self.assertIsNone(psutil.sensors_battery().power_plugged) - assert m.called - - def test_emulate_no_base_files(self): - # Emulate a case where base metrics files are not present, - # in which case we're supposed to get None. - with mock_open_exception( - "/sys/class/power_supply/BAT0/energy_now", - IOError(errno.ENOENT, "")): - with mock_open_exception( - "/sys/class/power_supply/BAT0/charge_now", - IOError(errno.ENOENT, "")): - self.assertIsNone(psutil.sensors_battery()) - - def test_emulate_energy_full_0(self): - # Emulate a case where energy_full files returns 0. - with mock_open_content( - "/sys/class/power_supply/BAT0/energy_full", b"0") as m: - self.assertEqual(psutil.sensors_battery().percent, 0) - assert m.called - - def test_emulate_energy_full_not_avail(self): - # Emulate a case where energy_full file does not exist. - # Expected fallback on /capacity. - with mock_open_exception( - "/sys/class/power_supply/BAT0/energy_full", - IOError(errno.ENOENT, "")): - with mock_open_exception( - "/sys/class/power_supply/BAT0/charge_full", - IOError(errno.ENOENT, "")): - with mock_open_content( - "/sys/class/power_supply/BAT0/capacity", b"88"): - self.assertEqual(psutil.sensors_battery().percent, 88) - - def test_emulate_no_power(self): - # Emulate a case where /AC0/online file nor /BAT0/status exist. - with mock_open_exception( - "/sys/class/power_supply/AC/online", - IOError(errno.ENOENT, "")): - with mock_open_exception( - "/sys/class/power_supply/AC0/online", - IOError(errno.ENOENT, "")): - with mock_open_exception( - "/sys/class/power_supply/BAT0/status", - IOError(errno.ENOENT, "")): - self.assertIsNone(psutil.sensors_battery().power_plugged) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSensorsTemperatures(unittest.TestCase): - - def test_emulate_class_hwmon(self): - def open_mock(name, *args, **kwargs): - if name.endswith('/name'): - return io.StringIO(u("name")) - elif name.endswith('/temp1_label'): - return io.StringIO(u("label")) - elif name.endswith('/temp1_input'): - return io.BytesIO(b"30000") - elif name.endswith('/temp1_max'): - return io.BytesIO(b"40000") - elif name.endswith('/temp1_crit'): - return io.BytesIO(b"50000") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - # Test case with /sys/class/hwmon - with mock.patch('glob.glob', - return_value=['/sys/class/hwmon/hwmon0/temp1']): - temp = psutil.sensors_temperatures()['name'][0] - self.assertEqual(temp.label, 'label') - self.assertEqual(temp.current, 30.0) - self.assertEqual(temp.high, 40.0) - self.assertEqual(temp.critical, 50.0) - - def test_emulate_class_thermal(self): - def open_mock(name, *args, **kwargs): - if name.endswith('0_temp'): - return io.BytesIO(b"50000") - elif name.endswith('temp'): - return io.BytesIO(b"30000") - elif name.endswith('0_type'): - return io.StringIO(u("critical")) - elif name.endswith('type'): - return io.StringIO(u("name")) - else: - return orig_open(name, *args, **kwargs) - - def glob_mock(path): - if path == '/sys/class/hwmon/hwmon*/temp*_*': - return [] - elif path == '/sys/class/hwmon/hwmon*/device/temp*_*': - return [] - elif path == '/sys/class/thermal/thermal_zone*': - return ['/sys/class/thermal/thermal_zone0'] - elif path == '/sys/class/thermal/thermal_zone0/trip_point*': - return ['/sys/class/thermal/thermal_zone1/trip_point_0_type', - '/sys/class/thermal/thermal_zone1/trip_point_0_temp'] - return [] - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - with mock.patch('glob.glob', create=True, side_effect=glob_mock): - temp = psutil.sensors_temperatures()['name'][0] - self.assertEqual(temp.label, '') - self.assertEqual(temp.current, 30.0) - self.assertEqual(temp.high, 50.0) - self.assertEqual(temp.critical, 50.0) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSensorsFans(unittest.TestCase): - - def test_emulate_data(self): - def open_mock(name, *args, **kwargs): - if name.endswith('/name'): - return io.StringIO(u("name")) - elif name.endswith('/fan1_label'): - return io.StringIO(u("label")) - elif name.endswith('/fan1_input'): - return io.StringIO(u("2000")) - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - with mock.patch('glob.glob', - return_value=['/sys/class/hwmon/hwmon2/fan1']): - fan = psutil.sensors_fans()['name'][0] - self.assertEqual(fan.label, 'label') - self.assertEqual(fan.current, 2000) - - -# ===================================================================== -# --- test process -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestProcess(unittest.TestCase): - - def setUp(self): - safe_rmpath(TESTFN) - - tearDown = setUp - - def test_memory_full_info(self): - src = textwrap.dedent(""" - import time - with open("%s", "w") as f: - time.sleep(10) - """ % TESTFN) - sproc = pyrun(src) - self.addCleanup(reap_children) - call_until(lambda: os.listdir('.'), "'%s' not in ret" % TESTFN) - p = psutil.Process(sproc.pid) - time.sleep(.1) - mem = p.memory_full_info() - maps = p.memory_maps(grouped=False) - self.assertAlmostEqual( - mem.uss, sum([x.private_dirty + x.private_clean for x in maps]), - delta=4096) - self.assertAlmostEqual( - mem.pss, sum([x.pss for x in maps]), delta=4096) - self.assertAlmostEqual( - mem.swap, sum([x.swap for x in maps]), delta=4096) - - def test_memory_full_info_mocked(self): - # See: https://github.com/giampaolo/psutil/issues/1222 - with mock_open_content( - "/proc/%s/smaps" % os.getpid(), - textwrap.dedent("""\ - fffff0 r-xp 00000000 00:00 0 [vsyscall] - Size: 1 kB - Rss: 2 kB - Pss: 3 kB - Shared_Clean: 4 kB - Shared_Dirty: 5 kB - Private_Clean: 6 kB - Private_Dirty: 7 kB - Referenced: 8 kB - Anonymous: 9 kB - LazyFree: 10 kB - AnonHugePages: 11 kB - ShmemPmdMapped: 12 kB - Shared_Hugetlb: 13 kB - Private_Hugetlb: 14 kB - Swap: 15 kB - SwapPss: 16 kB - KernelPageSize: 17 kB - MMUPageSize: 18 kB - Locked: 19 kB - VmFlags: rd ex - """).encode()) as m: - p = psutil.Process() - mem = p.memory_full_info() - assert m.called - self.assertEqual(mem.uss, (6 + 7 + 14) * 1024) - self.assertEqual(mem.pss, 3 * 1024) - self.assertEqual(mem.swap, 15 * 1024) - - # On PYPY file descriptors are not closed fast enough. - @unittest.skipIf(PYPY, "unreliable on PYPY") - def test_open_files_mode(self): - def get_test_file(): - p = psutil.Process() - giveup_at = time.time() + 2 - while True: - for file in p.open_files(): - if file.path == os.path.abspath(TESTFN): - return file - elif time.time() > giveup_at: - break - raise RuntimeError("timeout looking for test file") - - # - with open(TESTFN, "w"): - self.assertEqual(get_test_file().mode, "w") - with open(TESTFN, "r"): - self.assertEqual(get_test_file().mode, "r") - with open(TESTFN, "a"): - self.assertEqual(get_test_file().mode, "a") - # - with open(TESTFN, "r+"): - self.assertEqual(get_test_file().mode, "r+") - with open(TESTFN, "w+"): - self.assertEqual(get_test_file().mode, "r+") - with open(TESTFN, "a+"): - self.assertEqual(get_test_file().mode, "a+") - # note: "x" bit is not supported - if PY3: - safe_rmpath(TESTFN) - with open(TESTFN, "x"): - self.assertEqual(get_test_file().mode, "w") - safe_rmpath(TESTFN) - with open(TESTFN, "x+"): - self.assertEqual(get_test_file().mode, "r+") - - def test_open_files_file_gone(self): - # simulates a file which gets deleted during open_files() - # execution - p = psutil.Process() - files = p.open_files() - with tempfile.NamedTemporaryFile(): - # give the kernel some time to see the new file - call_until(p.open_files, "len(ret) != %i" % len(files)) - with mock.patch('psutil._pslinux.os.readlink', - side_effect=OSError(errno.ENOENT, "")) as m: - files = p.open_files() - assert not files - assert m.called - # also simulate the case where os.readlink() returns EINVAL - # in which case psutil is supposed to 'continue' - with mock.patch('psutil._pslinux.os.readlink', - side_effect=OSError(errno.EINVAL, "")) as m: - self.assertEqual(p.open_files(), []) - assert m.called - - def test_open_files_fd_gone(self): - # Simulate a case where /proc/{pid}/fdinfo/{fd} disappears - # while iterating through fds. - # https://travis-ci.org/giampaolo/psutil/jobs/225694530 - p = psutil.Process() - files = p.open_files() - with tempfile.NamedTemporaryFile(): - # give the kernel some time to see the new file - call_until(p.open_files, "len(ret) != %i" % len(files)) - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, - side_effect=IOError(errno.ENOENT, "")) as m: - files = p.open_files() - assert not files - assert m.called - - # --- mocked tests - - def test_terminal_mocked(self): - with mock.patch('psutil._pslinux._psposix.get_terminal_map', - return_value={}) as m: - self.assertIsNone(psutil._pslinux.Process(os.getpid()).terminal()) - assert m.called - - # TODO: re-enable this test. - # def test_num_ctx_switches_mocked(self): - # with mock.patch('psutil._common.open', create=True) as m: - # self.assertRaises( - # NotImplementedError, - # psutil._pslinux.Process(os.getpid()).num_ctx_switches) - # assert m.called - - def test_cmdline_mocked(self): - # see: https://github.com/giampaolo/psutil/issues/639 - p = psutil.Process() - fake_file = io.StringIO(u('foo\x00bar\x00')) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(p.cmdline(), ['foo', 'bar']) - assert m.called - fake_file = io.StringIO(u('foo\x00bar\x00\x00')) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(p.cmdline(), ['foo', 'bar', '']) - assert m.called - - def test_cmdline_spaces_mocked(self): - # see: https://github.com/giampaolo/psutil/issues/1179 - p = psutil.Process() - fake_file = io.StringIO(u('foo bar ')) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(p.cmdline(), ['foo', 'bar']) - assert m.called - fake_file = io.StringIO(u('foo bar ')) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(p.cmdline(), ['foo', 'bar', '']) - assert m.called - - def test_cmdline_mixed_separators(self): - # https://github.com/giampaolo/psutil/issues/ - # 1179#issuecomment-552984549 - p = psutil.Process() - fake_file = io.StringIO(u('foo\x20bar\x00')) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(p.cmdline(), ['foo', 'bar']) - assert m.called - - def test_readlink_path_deleted_mocked(self): - with mock.patch('psutil._pslinux.os.readlink', - return_value='/home/foo (deleted)'): - self.assertEqual(psutil.Process().exe(), "/home/foo") - self.assertEqual(psutil.Process().cwd(), "/home/foo") - - def test_threads_mocked(self): - # Test the case where os.listdir() returns a file (thread) - # which no longer exists by the time we open() it (race - # condition). threads() is supposed to ignore that instead - # of raising NSP. - def open_mock(name, *args, **kwargs): - if name.startswith('/proc/%s/task' % os.getpid()): - raise IOError(errno.ENOENT, "") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - ret = psutil.Process().threads() - assert m.called - self.assertEqual(ret, []) - - # ...but if it bumps into something != ENOENT we want an - # exception. - def open_mock(name, *args, **kwargs): - if name.startswith('/proc/%s/task' % os.getpid()): - raise IOError(errno.EPERM, "") - else: - return orig_open(name, *args, **kwargs) - - with mock.patch(patch_point, side_effect=open_mock): - self.assertRaises(psutil.AccessDenied, psutil.Process().threads) - - def test_exe_mocked(self): - with mock.patch('psutil._pslinux.readlink', - side_effect=OSError(errno.ENOENT, "")) as m1: - with mock.patch('psutil.Process.cmdline', - side_effect=psutil.AccessDenied(0, "")) as m2: - # No such file error; might be raised also if /proc/pid/exe - # path actually exists for system processes with low pids - # (about 0-20). In this case psutil is supposed to return - # an empty string. - ret = psutil.Process().exe() - assert m1.called - assert m2.called - self.assertEqual(ret, "") - - # ...but if /proc/pid no longer exist we're supposed to treat - # it as an alias for zombie process - with mock.patch('psutil._pslinux.os.path.lexists', - return_value=False): - self.assertRaises( - psutil.ZombieProcess, psutil.Process().exe) - - def test_issue_1014(self): - # Emulates a case where smaps file does not exist. In this case - # wrap_exception decorator should not raise NoSuchProcess. - with mock_open_exception( - '/proc/%s/smaps' % os.getpid(), - IOError(errno.ENOENT, "")) as m: - p = psutil.Process() - with self.assertRaises(FileNotFoundError): - p.memory_maps() - assert m.called - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_zombie(self): - # Emulate a case where rlimit() raises ENOSYS, which may - # happen in case of zombie process: - # https://travis-ci.org/giampaolo/psutil/jobs/51368273 - with mock.patch("psutil._pslinux.cext.linux_prlimit", - side_effect=OSError(errno.ENOSYS, "")) as m: - p = psutil.Process() - p.name() - with self.assertRaises(psutil.ZombieProcess) as exc: - p.rlimit(psutil.RLIMIT_NOFILE) - assert m.called - self.assertEqual(exc.exception.pid, p.pid) - self.assertEqual(exc.exception.name, p.name()) - - def test_cwd_zombie(self): - with mock.patch("psutil._pslinux.os.readlink", - side_effect=OSError(errno.ENOENT, "")) as m: - p = psutil.Process() - p.name() - with self.assertRaises(psutil.ZombieProcess) as exc: - p.cwd() - assert m.called - self.assertEqual(exc.exception.pid, p.pid) - self.assertEqual(exc.exception.name, p.name()) - - def test_stat_file_parsing(self): - from psutil._pslinux import CLOCK_TICKS - - args = [ - "0", # pid - "(cat)", # name - "Z", # status - "1", # ppid - "0", # pgrp - "0", # session - "0", # tty - "0", # tpgid - "0", # flags - "0", # minflt - "0", # cminflt - "0", # majflt - "0", # cmajflt - "2", # utime - "3", # stime - "4", # cutime - "5", # cstime - "0", # priority - "0", # nice - "0", # num_threads - "0", # itrealvalue - "6", # starttime - "0", # vsize - "0", # rss - "0", # rsslim - "0", # startcode - "0", # endcode - "0", # startstack - "0", # kstkesp - "0", # kstkeip - "0", # signal - "0", # blocked - "0", # sigignore - "0", # sigcatch - "0", # wchan - "0", # nswap - "0", # cnswap - "0", # exit_signal - "6", # processor - "0", # rt priority - "0", # policy - "7", # delayacct_blkio_ticks - ] - content = " ".join(args).encode() - with mock_open_content('/proc/%s/stat' % os.getpid(), content): - p = psutil.Process() - self.assertEqual(p.name(), 'cat') - self.assertEqual(p.status(), psutil.STATUS_ZOMBIE) - self.assertEqual(p.ppid(), 1) - self.assertEqual( - p.create_time(), 6 / CLOCK_TICKS + psutil.boot_time()) - cpu = p.cpu_times() - self.assertEqual(cpu.user, 2 / CLOCK_TICKS) - self.assertEqual(cpu.system, 3 / CLOCK_TICKS) - self.assertEqual(cpu.children_user, 4 / CLOCK_TICKS) - self.assertEqual(cpu.children_system, 5 / CLOCK_TICKS) - self.assertEqual(cpu.iowait, 7 / CLOCK_TICKS) - self.assertEqual(p.cpu_num(), 6) - - def test_status_file_parsing(self): - with mock_open_content( - '/proc/%s/status' % os.getpid(), - textwrap.dedent("""\ - Uid:\t1000\t1001\t1002\t1003 - Gid:\t1004\t1005\t1006\t1007 - Threads:\t66 - Cpus_allowed:\tf - Cpus_allowed_list:\t0-7 - voluntary_ctxt_switches:\t12 - nonvoluntary_ctxt_switches:\t13""").encode()): - p = psutil.Process() - self.assertEqual(p.num_ctx_switches().voluntary, 12) - self.assertEqual(p.num_ctx_switches().involuntary, 13) - self.assertEqual(p.num_threads(), 66) - uids = p.uids() - self.assertEqual(uids.real, 1000) - self.assertEqual(uids.effective, 1001) - self.assertEqual(uids.saved, 1002) - gids = p.gids() - self.assertEqual(gids.real, 1004) - self.assertEqual(gids.effective, 1005) - self.assertEqual(gids.saved, 1006) - self.assertEqual(p._proc._get_eligible_cpus(), list(range(0, 8))) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestProcessAgainstStatus(unittest.TestCase): - """/proc/pid/stat and /proc/pid/status have many values in common. - Whenever possible, psutil uses /proc/pid/stat (it's faster). - For all those cases we check that the value found in - /proc/pid/stat (by psutil) matches the one found in - /proc/pid/status. - """ - - @classmethod - def setUpClass(cls): - cls.proc = psutil.Process() - - def read_status_file(self, linestart): - with psutil._psplatform.open_text( - '/proc/%s/status' % self.proc.pid) as f: - for line in f: - line = line.strip() - if line.startswith(linestart): - value = line.partition('\t')[2] - try: - return int(value) - except ValueError: - return value - raise ValueError("can't find %r" % linestart) - - def test_name(self): - value = self.read_status_file("Name:") - self.assertEqual(self.proc.name(), value) - - def test_status(self): - value = self.read_status_file("State:") - value = value[value.find('(') + 1:value.rfind(')')] - value = value.replace(' ', '-') - self.assertEqual(self.proc.status(), value) - - def test_ppid(self): - value = self.read_status_file("PPid:") - self.assertEqual(self.proc.ppid(), value) - - def test_num_threads(self): - value = self.read_status_file("Threads:") - self.assertEqual(self.proc.num_threads(), value) - - def test_uids(self): - value = self.read_status_file("Uid:") - value = tuple(map(int, value.split()[1:4])) - self.assertEqual(self.proc.uids(), value) - - def test_gids(self): - value = self.read_status_file("Gid:") - value = tuple(map(int, value.split()[1:4])) - self.assertEqual(self.proc.gids(), value) - - @retry_on_failure() - def test_num_ctx_switches(self): - value = self.read_status_file("voluntary_ctxt_switches:") - self.assertEqual(self.proc.num_ctx_switches().voluntary, value) - value = self.read_status_file("nonvoluntary_ctxt_switches:") - self.assertEqual(self.proc.num_ctx_switches().involuntary, value) - - def test_cpu_affinity(self): - value = self.read_status_file("Cpus_allowed_list:") - if '-' in str(value): - min_, max_ = map(int, value.split('-')) - self.assertEqual( - self.proc.cpu_affinity(), list(range(min_, max_ + 1))) - - def test_cpu_affinity_eligible_cpus(self): - value = self.read_status_file("Cpus_allowed_list:") - with mock.patch("psutil._pslinux.per_cpu_times") as m: - self.proc._proc._get_eligible_cpus() - if '-' in str(value): - assert not m.called - else: - assert m.called - - -# ===================================================================== -# --- test utils -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestUtils(unittest.TestCase): - - def test_readlink(self): - with mock.patch("os.readlink", return_value="foo (deleted)") as m: - self.assertEqual(psutil._psplatform.readlink("bar"), "foo") - assert m.called - - def test_cat(self): - fname = os.path.abspath(TESTFN) - with open(fname, "wt") as f: - f.write("foo ") - self.assertEqual(psutil._psplatform.cat(TESTFN, binary=False), "foo") - self.assertEqual(psutil._psplatform.cat(TESTFN, binary=True), b"foo") - self.assertEqual( - psutil._psplatform.cat(TESTFN + '??', fallback="bar"), "bar") - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_memory_leaks.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_memory_leaks.py deleted file mode 100644 index f9cad70fd33e..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_memory_leaks.py +++ /dev/null @@ -1,600 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Tests for detecting function memory leaks (typically the ones -implemented in C). It does so by calling a function many times and -checking whether process memory usage keeps increasing between -calls or over time. -Note that this may produce false positives (especially on Windows -for some reason). -PyPy appears to be completely unstable for this framework, probably -because of how its JIT handles memory, so tests are skipped. -""" - -from __future__ import print_function -import functools -import gc -import os -import sys -import threading -import time - -import psutil -import psutil._common -from psutil import FREEBSD -from psutil import LINUX -from psutil import MACOS -from psutil import OPENBSD -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -from psutil._common import bytes2human -from psutil._compat import ProcessLookupError -from psutil._compat import xrange -from psutil.tests import CIRRUS -from psutil.tests import create_sockets -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_CPU_AFFINITY -from psutil.tests import HAS_CPU_FREQ -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 -from psutil.tests import HAS_SENSORS_BATTERY -from psutil.tests import HAS_SENSORS_FANS -from psutil.tests import HAS_SENSORS_TEMPERATURES -from psutil.tests import PYPY -from psutil.tests import reap_children -from psutil.tests import safe_rmpath -from psutil.tests import skip_on_access_denied -from psutil.tests import TESTFN -from psutil.tests import TRAVIS -from psutil.tests import unittest - - -# configurable opts -LOOPS = 1000 -MEMORY_TOLERANCE = 4096 -RETRY_FOR = 3 -SKIP_PYTHON_IMPL = True - -cext = psutil._psplatform.cext -thisproc = psutil.Process() - - -# =================================================================== -# utils -# =================================================================== - - -def skip_if_linux(): - return unittest.skipIf(LINUX and SKIP_PYTHON_IMPL, - "worthless on LINUX (pure python)") - - -@unittest.skipIf(PYPY, "unreliable on PYPY") -class TestMemLeak(unittest.TestCase): - """Base framework class which calls a function many times and - produces a failure if process memory usage keeps increasing - between calls or over time. - """ - tolerance = MEMORY_TOLERANCE - loops = LOOPS - retry_for = RETRY_FOR - - def setUp(self): - gc.collect() - - def execute(self, fun, *args, **kwargs): - """Test a callable.""" - def call_many_times(): - for x in xrange(loops): - self._call(fun, *args, **kwargs) - del x - gc.collect() - - tolerance = kwargs.pop('tolerance_', None) or self.tolerance - loops = kwargs.pop('loops_', None) or self.loops - retry_for = kwargs.pop('retry_for_', None) or self.retry_for - - # warm up - for x in range(10): - self._call(fun, *args, **kwargs) - self.assertEqual(gc.garbage, []) - self.assertEqual(threading.active_count(), 1) - self.assertEqual(thisproc.children(), []) - - # Get 2 distinct memory samples, before and after having - # called fun repeadetly. - # step 1 - call_many_times() - mem1 = self._get_mem() - # step 2 - call_many_times() - mem2 = self._get_mem() - - diff1 = mem2 - mem1 - if diff1 > tolerance: - # This doesn't necessarily mean we have a leak yet. - # At this point we assume that after having called the - # function so many times the memory usage is stabilized - # and if there are no leaks it should not increase - # anymore. - # Let's keep calling fun for 3 more seconds and fail if - # we notice any difference. - ncalls = 0 - stop_at = time.time() + retry_for - while time.time() <= stop_at: - self._call(fun, *args, **kwargs) - ncalls += 1 - - del stop_at - gc.collect() - mem3 = self._get_mem() - diff2 = mem3 - mem2 - - if mem3 > mem2: - # failure - extra_proc_mem = bytes2human(diff1 + diff2) - print("exta proc mem: %s" % extra_proc_mem, file=sys.stderr) - msg = "+%s after %s calls, +%s after another %s calls, " - msg += "+%s extra proc mem" - msg = msg % ( - bytes2human(diff1), loops, bytes2human(diff2), ncalls, - extra_proc_mem) - self.fail(msg) - - def execute_w_exc(self, exc, fun, *args, **kwargs): - """Convenience function which tests a callable raising - an exception. - """ - def call(): - self.assertRaises(exc, fun, *args, **kwargs) - - self.execute(call) - - @staticmethod - def _get_mem(): - # By using USS memory it seems it's less likely to bump - # into false positives. - if LINUX or WINDOWS or MACOS: - return thisproc.memory_full_info().uss - else: - return thisproc.memory_info().rss - - @staticmethod - def _call(fun, *args, **kwargs): - fun(*args, **kwargs) - - -# =================================================================== -# Process class -# =================================================================== - - -class TestProcessObjectLeaks(TestMemLeak): - """Test leaks of Process class methods.""" - - proc = thisproc - - def test_coverage(self): - skip = set(( - "pid", "as_dict", "children", "cpu_affinity", "cpu_percent", - "ionice", "is_running", "kill", "memory_info_ex", "memory_percent", - "nice", "oneshot", "parent", "parents", "rlimit", "send_signal", - "suspend", "terminate", "wait")) - for name in dir(psutil.Process): - if name.startswith('_'): - continue - if name in skip: - continue - self.assertTrue(hasattr(self, "test_" + name), msg=name) - - @skip_if_linux() - def test_name(self): - self.execute(self.proc.name) - - @skip_if_linux() - def test_cmdline(self): - self.execute(self.proc.cmdline) - - @skip_if_linux() - def test_exe(self): - self.execute(self.proc.exe) - - @skip_if_linux() - def test_ppid(self): - self.execute(self.proc.ppid) - - @unittest.skipIf(not POSIX, "POSIX only") - @skip_if_linux() - def test_uids(self): - self.execute(self.proc.uids) - - @unittest.skipIf(not POSIX, "POSIX only") - @skip_if_linux() - def test_gids(self): - self.execute(self.proc.gids) - - @skip_if_linux() - def test_status(self): - self.execute(self.proc.status) - - def test_nice_get(self): - self.execute(self.proc.nice) - - def test_nice_set(self): - niceness = thisproc.nice() - self.execute(self.proc.nice, niceness) - - @unittest.skipIf(not HAS_IONICE, "not supported") - def test_ionice_get(self): - self.execute(self.proc.ionice) - - @unittest.skipIf(not HAS_IONICE, "not supported") - def test_ionice_set(self): - if WINDOWS: - value = thisproc.ionice() - self.execute(self.proc.ionice, value) - else: - self.execute(self.proc.ionice, psutil.IOPRIO_CLASS_NONE) - fun = functools.partial(cext.proc_ioprio_set, os.getpid(), -1, 0) - self.execute_w_exc(OSError, fun) - - @unittest.skipIf(not HAS_PROC_IO_COUNTERS, "not supported") - @skip_if_linux() - def test_io_counters(self): - self.execute(self.proc.io_counters) - - @unittest.skipIf(POSIX, "worthless on POSIX") - def test_username(self): - self.execute(self.proc.username) - - @skip_if_linux() - def test_create_time(self): - self.execute(self.proc.create_time) - - @skip_if_linux() - @skip_on_access_denied(only_if=OPENBSD) - def test_num_threads(self): - self.execute(self.proc.num_threads) - - @unittest.skipIf(not WINDOWS, "WINDOWS only") - def test_num_handles(self): - self.execute(self.proc.num_handles) - - @unittest.skipIf(not POSIX, "POSIX only") - @skip_if_linux() - def test_num_fds(self): - self.execute(self.proc.num_fds) - - @skip_if_linux() - def test_num_ctx_switches(self): - self.execute(self.proc.num_ctx_switches) - - @skip_if_linux() - @skip_on_access_denied(only_if=OPENBSD) - def test_threads(self): - self.execute(self.proc.threads) - - @skip_if_linux() - def test_cpu_times(self): - self.execute(self.proc.cpu_times) - - @skip_if_linux() - @unittest.skipIf(not HAS_PROC_CPU_NUM, "not supported") - def test_cpu_num(self): - self.execute(self.proc.cpu_num) - - @skip_if_linux() - def test_memory_info(self): - self.execute(self.proc.memory_info) - - @skip_if_linux() - def test_memory_full_info(self): - self.execute(self.proc.memory_full_info) - - @unittest.skipIf(not POSIX, "POSIX only") - @skip_if_linux() - def test_terminal(self): - self.execute(self.proc.terminal) - - @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, - "worthless on POSIX (pure python)") - def test_resume(self): - self.execute(self.proc.resume) - - @skip_if_linux() - def test_cwd(self): - self.execute(self.proc.cwd) - - @unittest.skipIf(not HAS_CPU_AFFINITY, "not supported") - def test_cpu_affinity_get(self): - self.execute(self.proc.cpu_affinity) - - @unittest.skipIf(not HAS_CPU_AFFINITY, "not supported") - def test_cpu_affinity_set(self): - affinity = thisproc.cpu_affinity() - self.execute(self.proc.cpu_affinity, affinity) - if not TRAVIS: - self.execute_w_exc(ValueError, self.proc.cpu_affinity, [-1]) - - @skip_if_linux() - def test_open_files(self): - safe_rmpath(TESTFN) # needed after UNIX socket test has run - with open(TESTFN, 'w'): - self.execute(self.proc.open_files) - - @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") - @skip_if_linux() - def test_memory_maps(self): - self.execute(self.proc.memory_maps) - - @unittest.skipIf(not LINUX, "LINUX only") - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_get(self): - self.execute(self.proc.rlimit, psutil.RLIMIT_NOFILE) - - @unittest.skipIf(not LINUX, "LINUX only") - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_set(self): - limit = thisproc.rlimit(psutil.RLIMIT_NOFILE) - self.execute(self.proc.rlimit, psutil.RLIMIT_NOFILE, limit) - self.execute_w_exc(OSError, self.proc.rlimit, -1) - - @skip_if_linux() - # Windows implementation is based on a single system-wide - # function (tested later). - @unittest.skipIf(WINDOWS, "worthless on WINDOWS") - def test_connections(self): - # TODO: UNIX sockets are temporarily implemented by parsing - # 'pfiles' cmd output; we don't want that part of the code to - # be executed. - with create_sockets(): - kind = 'inet' if SUNOS else 'all' - self.execute(self.proc.connections, kind) - - @unittest.skipIf(not HAS_ENVIRON, "not supported") - def test_environ(self): - self.execute(self.proc.environ) - - @unittest.skipIf(not WINDOWS, "WINDOWS only") - def test_proc_info(self): - self.execute(cext.proc_info, os.getpid()) - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestProcessDualImplementation(TestMemLeak): - - def test_cmdline_peb_true(self): - self.execute(cext.proc_cmdline, os.getpid(), use_peb=True) - - def test_cmdline_peb_false(self): - self.execute(cext.proc_cmdline, os.getpid(), use_peb=False) - - -class TestTerminatedProcessLeaks(TestProcessObjectLeaks): - """Repeat the tests above looking for leaks occurring when dealing - with terminated processes raising NoSuchProcess exception. - The C functions are still invoked but will follow different code - paths. We'll check those code paths. - """ - - @classmethod - def setUpClass(cls): - super(TestTerminatedProcessLeaks, cls).setUpClass() - p = get_test_subprocess() - cls.proc = psutil.Process(p.pid) - cls.proc.kill() - cls.proc.wait() - - @classmethod - def tearDownClass(cls): - super(TestTerminatedProcessLeaks, cls).tearDownClass() - reap_children() - - def _call(self, fun, *args, **kwargs): - try: - fun(*args, **kwargs) - except psutil.NoSuchProcess: - pass - - if WINDOWS: - - def test_kill(self): - self.execute(self.proc.kill) - - def test_terminate(self): - self.execute(self.proc.terminate) - - def test_suspend(self): - self.execute(self.proc.suspend) - - def test_resume(self): - self.execute(self.proc.resume) - - def test_wait(self): - self.execute(self.proc.wait) - - def test_proc_info(self): - # test dual implementation - def call(): - try: - return cext.proc_info(self.proc.pid) - except ProcessLookupError: - pass - - self.execute(call) - - -# =================================================================== -# system APIs -# =================================================================== - - -class TestModuleFunctionsLeaks(TestMemLeak): - """Test leaks of psutil module functions.""" - - def test_coverage(self): - skip = set(( - "version_info", "__version__", "process_iter", "wait_procs", - "cpu_percent", "cpu_times_percent", "cpu_count")) - for name in psutil.__all__: - if not name.islower(): - continue - if name in skip: - continue - self.assertTrue(hasattr(self, "test_" + name), msg=name) - - # --- cpu - - @skip_if_linux() - def test_cpu_count_logical(self): - self.execute(psutil.cpu_count, logical=True) - - @skip_if_linux() - def test_cpu_count_physical(self): - self.execute(psutil.cpu_count, logical=False) - - @skip_if_linux() - def test_cpu_times(self): - self.execute(psutil.cpu_times) - - @skip_if_linux() - def test_per_cpu_times(self): - self.execute(psutil.cpu_times, percpu=True) - - @skip_if_linux() - def test_cpu_stats(self): - self.execute(psutil.cpu_stats) - - @skip_if_linux() - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_cpu_freq(self): - self.execute(psutil.cpu_freq) - - @unittest.skipIf(not WINDOWS, "WINDOWS only") - def test_getloadavg(self): - self.execute(psutil.getloadavg) - - # --- mem - - def test_virtual_memory(self): - self.execute(psutil.virtual_memory) - - # TODO: remove this skip when this gets fixed - @unittest.skipIf(SUNOS, "worthless on SUNOS (uses a subprocess)") - def test_swap_memory(self): - self.execute(psutil.swap_memory) - - @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, - "worthless on POSIX (pure python)") - def test_pid_exists(self): - self.execute(psutil.pid_exists, os.getpid()) - - # --- disk - - @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, - "worthless on POSIX (pure python)") - def test_disk_usage(self): - self.execute(psutil.disk_usage, '.') - - def test_disk_partitions(self): - self.execute(psutil.disk_partitions) - - @unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'), - '/proc/diskstats not available on this Linux version') - @skip_if_linux() - def test_disk_io_counters(self): - self.execute(psutil.disk_io_counters, nowrap=False) - - # --- proc - - @skip_if_linux() - def test_pids(self): - self.execute(psutil.pids) - - # --- net - - @unittest.skipIf(TRAVIS and MACOS, "false positive on TRAVIS + MACOS") - @unittest.skipIf(CIRRUS and FREEBSD, "false positive on CIRRUS + FREEBSD") - @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) - - @skip_if_linux() - @unittest.skipIf(MACOS and os.getuid() != 0, "need root access") - def test_net_connections(self): - with create_sockets(): - self.execute(psutil.net_connections) - - def test_net_if_addrs(self): - # Note: verified that on Windows this was a false positive. - self.execute(psutil.net_if_addrs, - tolerance_=80 * 1024 if WINDOWS else None) - - @unittest.skipIf(TRAVIS, "EPERM on travis") - def test_net_if_stats(self): - self.execute(psutil.net_if_stats) - - # --- sensors - - @skip_if_linux() - @unittest.skipIf(not HAS_SENSORS_BATTERY, "not supported") - def test_sensors_battery(self): - self.execute(psutil.sensors_battery) - - @skip_if_linux() - @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") - def test_sensors_temperatures(self): - self.execute(psutil.sensors_temperatures) - - @skip_if_linux() - @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") - def test_sensors_fans(self): - self.execute(psutil.sensors_fans) - - # --- others - - @skip_if_linux() - def test_boot_time(self): - self.execute(psutil.boot_time) - - @unittest.skipIf(WINDOWS, "XXX produces a false positive on Windows") - def test_users(self): - self.execute(psutil.users) - - if WINDOWS: - - # --- win services - - def test_win_service_iter(self): - self.execute(cext.winservice_enumerate) - - def test_win_service_get(self): - pass - - def test_win_service_get_config(self): - name = next(psutil.win_service_iter()).name() - self.execute(cext.winservice_query_config, name) - - def test_win_service_get_status(self): - name = next(psutil.win_service_iter()).name() - self.execute(cext.winservice_query_status, name) - - def test_win_service_get_description(self): - name = next(psutil.win_service_iter()).name() - self.execute(cext.winservice_query_descr, name) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_misc.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_misc.py deleted file mode 100644 index c20cd9413b6a..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_misc.py +++ /dev/null @@ -1,1065 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# 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. - -""" -Miscellaneous tests. -""" - -import ast -import collections -import contextlib -import errno -import json -import os -import pickle -import socket -import stat - -from psutil import FREEBSD -from psutil import LINUX -from psutil import NETBSD -from psutil import POSIX -from psutil import WINDOWS -from psutil._common import memoize -from psutil._common import memoize_when_activated -from psutil._common import supports_ipv6 -from psutil._common import wrap_numbers -from psutil._common import open_text -from psutil._common import open_binary -from psutil._compat import PY3 -from psutil.tests import APPVEYOR -from psutil.tests import bind_socket -from psutil.tests import bind_unix_socket -from psutil.tests import call_until -from psutil.tests import chdir -from psutil.tests import CI_TESTING -from psutil.tests import create_proc_children_pair -from psutil.tests import create_sockets -from psutil.tests import create_zombie_proc -from psutil.tests import DEVNULL -from psutil.tests import get_free_port -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_BATTERY -from psutil.tests import HAS_CONNECTIONS_UNIX -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 -from psutil.tests import import_module_by_path -from psutil.tests import is_namedtuple -from psutil.tests import mock -from psutil.tests import PYTHON_EXE -from psutil.tests import reap_children -from psutil.tests import reload_module -from psutil.tests import retry -from psutil.tests import ROOT_DIR -from psutil.tests import safe_mkdir -from psutil.tests import safe_rmpath -from psutil.tests import SCRIPTS_DIR -from psutil.tests import sh -from psutil.tests import tcp_socketpair -from psutil.tests import TESTFN -from psutil.tests import TOX -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import unix_socket_path -from psutil.tests import unix_socketpair -from psutil.tests import wait_for_file -from psutil.tests import wait_for_pid -import psutil -import psutil.tests - - -# =================================================================== -# --- Misc / generic tests. -# =================================================================== - - -class TestMisc(unittest.TestCase): - - def test_process__repr__(self, func=repr): - p = psutil.Process() - r = func(p) - self.assertIn("psutil.Process", r) - self.assertIn("pid=%s" % p.pid, r) - self.assertIn("name=", r) - self.assertIn(p.name(), r) - with mock.patch.object(psutil.Process, "name", - side_effect=psutil.ZombieProcess(os.getpid())): - p = psutil.Process() - r = func(p) - self.assertIn("pid=%s" % p.pid, r) - self.assertIn("zombie", r) - self.assertNotIn("name=", r) - with mock.patch.object(psutil.Process, "name", - side_effect=psutil.NoSuchProcess(os.getpid())): - p = psutil.Process() - r = func(p) - self.assertIn("pid=%s" % p.pid, r) - self.assertIn("terminated", r) - self.assertNotIn("name=", r) - with mock.patch.object(psutil.Process, "name", - side_effect=psutil.AccessDenied(os.getpid())): - p = psutil.Process() - r = func(p) - self.assertIn("pid=%s" % p.pid, r) - self.assertNotIn("name=", r) - - def test_process__str__(self): - self.test_process__repr__(func=str) - - def test_no_such_process__repr__(self, func=repr): - self.assertEqual( - repr(psutil.NoSuchProcess(321)), - "psutil.NoSuchProcess process no longer exists (pid=321)") - self.assertEqual( - repr(psutil.NoSuchProcess(321, name='foo')), - "psutil.NoSuchProcess process no longer exists (pid=321, " - "name='foo')") - self.assertEqual( - repr(psutil.NoSuchProcess(321, msg='foo')), - "psutil.NoSuchProcess foo") - - def test_zombie_process__repr__(self, func=repr): - self.assertEqual( - repr(psutil.ZombieProcess(321)), - "psutil.ZombieProcess process still exists but it's a zombie " - "(pid=321)") - self.assertEqual( - repr(psutil.ZombieProcess(321, name='foo')), - "psutil.ZombieProcess process still exists but it's a zombie " - "(pid=321, name='foo')") - self.assertEqual( - repr(psutil.ZombieProcess(321, name='foo', ppid=1)), - "psutil.ZombieProcess process still exists but it's a zombie " - "(pid=321, name='foo', ppid=1)") - self.assertEqual( - repr(psutil.ZombieProcess(321, msg='foo')), - "psutil.ZombieProcess foo") - - def test_access_denied__repr__(self, func=repr): - self.assertEqual( - repr(psutil.AccessDenied(321)), - "psutil.AccessDenied (pid=321)") - self.assertEqual( - repr(psutil.AccessDenied(321, name='foo')), - "psutil.AccessDenied (pid=321, name='foo')") - self.assertEqual( - repr(psutil.AccessDenied(321, msg='foo')), - "psutil.AccessDenied foo") - - def test_timeout_expired__repr__(self, func=repr): - self.assertEqual( - repr(psutil.TimeoutExpired(321)), - "psutil.TimeoutExpired timeout after 321 seconds") - self.assertEqual( - repr(psutil.TimeoutExpired(321, pid=111)), - "psutil.TimeoutExpired timeout after 321 seconds (pid=111)") - self.assertEqual( - repr(psutil.TimeoutExpired(321, pid=111, name='foo')), - "psutil.TimeoutExpired timeout after 321 seconds " - "(pid=111, name='foo')") - - def test_process__eq__(self): - p1 = psutil.Process() - p2 = psutil.Process() - self.assertEqual(p1, p2) - p2._ident = (0, 0) - self.assertNotEqual(p1, p2) - self.assertNotEqual(p1, 'foo') - - def test_process__hash__(self): - s = set([psutil.Process(), psutil.Process()]) - self.assertEqual(len(s), 1) - - def test__all__(self): - dir_psutil = dir(psutil) - for name in dir_psutil: - if name in ('callable', 'error', 'namedtuple', 'tests', - 'long', 'test', 'NUM_CPUS', 'BOOT_TIME', - 'TOTAL_PHYMEM', 'PermissionError', - 'ProcessLookupError'): - continue - if not name.startswith('_'): - try: - __import__(name) - except ImportError: - if name not in psutil.__all__: - fun = getattr(psutil, name) - if fun is None: - continue - if (fun.__doc__ is not None and - 'deprecated' not in fun.__doc__.lower()): - self.fail('%r not in psutil.__all__' % name) - - # Import 'star' will break if __all__ is inconsistent, see: - # https://github.com/giampaolo/psutil/issues/656 - # Can't do `from psutil import *` as it won't work on python 3 - # so we simply iterate over __all__. - for name in psutil.__all__: - self.assertIn(name, dir_psutil) - - def test_version(self): - self.assertEqual('.'.join([str(x) for x in psutil.version_info]), - psutil.__version__) - - def test_process_as_dict_no_new_names(self): - # See https://github.com/giampaolo/psutil/issues/813 - p = psutil.Process() - p.foo = '1' - self.assertNotIn('foo', p.as_dict()) - - def test_memoize(self): - @memoize - def foo(*args, **kwargs): - "foo docstring" - calls.append(None) - return (args, kwargs) - - calls = [] - # no args - for x in range(2): - ret = foo() - expected = ((), {}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 1) - # with args - for x in range(2): - ret = foo(1) - expected = ((1, ), {}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 2) - # with args + kwargs - for x in range(2): - ret = foo(1, bar=2) - expected = ((1, ), {'bar': 2}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 3) - # clear cache - foo.cache_clear() - ret = foo() - expected = ((), {}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 4) - # docstring - self.assertEqual(foo.__doc__, "foo docstring") - - def test_memoize_when_activated(self): - class Foo: - - @memoize_when_activated - def foo(self): - calls.append(None) - - f = Foo() - calls = [] - f.foo() - f.foo() - self.assertEqual(len(calls), 2) - - # activate - calls = [] - f.foo.cache_activate(f) - f.foo() - f.foo() - self.assertEqual(len(calls), 1) - - # deactivate - calls = [] - f.foo.cache_deactivate(f) - f.foo() - f.foo() - self.assertEqual(len(calls), 2) - - def test_parse_environ_block(self): - from psutil._common import parse_environ_block - - def k(s): - return s.upper() if WINDOWS else s - - self.assertEqual(parse_environ_block("a=1\0"), - {k("a"): "1"}) - self.assertEqual(parse_environ_block("a=1\0b=2\0\0"), - {k("a"): "1", k("b"): "2"}) - self.assertEqual(parse_environ_block("a=1\0b=\0\0"), - {k("a"): "1", k("b"): ""}) - # ignore everything after \0\0 - self.assertEqual(parse_environ_block("a=1\0b=2\0\0c=3\0"), - {k("a"): "1", k("b"): "2"}) - # ignore everything that is not an assignment - self.assertEqual(parse_environ_block("xxx\0a=1\0"), {k("a"): "1"}) - self.assertEqual(parse_environ_block("a=1\0=b=2\0"), {k("a"): "1"}) - # do not fail if the block is incomplete - self.assertEqual(parse_environ_block("a=1\0b=2"), {k("a"): "1"}) - - def test_supports_ipv6(self): - self.addCleanup(supports_ipv6.cache_clear) - if supports_ipv6(): - with mock.patch('psutil._common.socket') as s: - s.has_ipv6 = False - supports_ipv6.cache_clear() - assert not supports_ipv6() - - supports_ipv6.cache_clear() - with mock.patch('psutil._common.socket.socket', - side_effect=socket.error) as s: - assert not supports_ipv6() - assert s.called - - supports_ipv6.cache_clear() - with mock.patch('psutil._common.socket.socket', - side_effect=socket.gaierror) as s: - assert not supports_ipv6() - supports_ipv6.cache_clear() - assert s.called - - supports_ipv6.cache_clear() - with mock.patch('psutil._common.socket.socket.bind', - side_effect=socket.gaierror) as s: - assert not supports_ipv6() - supports_ipv6.cache_clear() - assert s.called - else: - with self.assertRaises(Exception): - sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - sock.bind(("::1", 0)) - - def test_isfile_strict(self): - from psutil._common import isfile_strict - this_file = os.path.abspath(__file__) - assert isfile_strict(this_file) - assert not isfile_strict(os.path.dirname(this_file)) - with mock.patch('psutil._common.os.stat', - side_effect=OSError(errno.EPERM, "foo")): - self.assertRaises(OSError, isfile_strict, this_file) - with mock.patch('psutil._common.os.stat', - side_effect=OSError(errno.EACCES, "foo")): - self.assertRaises(OSError, isfile_strict, this_file) - with mock.patch('psutil._common.os.stat', - side_effect=OSError(errno.EINVAL, "foo")): - assert not isfile_strict(this_file) - with mock.patch('psutil._common.stat.S_ISREG', return_value=False): - assert not isfile_strict(this_file) - - def test_serialization(self): - def check(ret): - if json is not None: - json.loads(json.dumps(ret)) - a = pickle.dumps(ret) - b = pickle.loads(a) - self.assertEqual(ret, b) - - check(psutil.Process().as_dict()) - check(psutil.virtual_memory()) - check(psutil.swap_memory()) - check(psutil.cpu_times()) - check(psutil.cpu_times_percent(interval=0)) - check(psutil.net_io_counters()) - if LINUX and not os.path.exists('/proc/diskstats'): - pass - else: - if not APPVEYOR: - check(psutil.disk_io_counters()) - check(psutil.disk_partitions()) - check(psutil.disk_usage(os.getcwd())) - check(psutil.users()) - - def test_setup_script(self): - setup_py = os.path.join(ROOT_DIR, 'setup.py') - if TRAVIS and not os.path.exists(setup_py): - return self.skipTest("can't find setup.py") - module = import_module_by_path(setup_py) - self.assertRaises(SystemExit, module.setup) - self.assertEqual(module.get_version(), psutil.__version__) - - def test_ad_on_process_creation(self): - # We are supposed to be able to instantiate Process also in case - # of zombie processes or access denied. - with mock.patch.object(psutil.Process, 'create_time', - side_effect=psutil.AccessDenied) as meth: - psutil.Process() - assert meth.called - with mock.patch.object(psutil.Process, 'create_time', - side_effect=psutil.ZombieProcess(1)) as meth: - psutil.Process() - assert meth.called - with mock.patch.object(psutil.Process, 'create_time', - side_effect=ValueError) as meth: - with self.assertRaises(ValueError): - psutil.Process() - assert meth.called - - def test_sanity_version_check(self): - # see: https://github.com/giampaolo/psutil/issues/564 - with mock.patch( - "psutil._psplatform.cext.version", return_value="0.0.0"): - with self.assertRaises(ImportError) as cm: - reload_module(psutil) - self.assertIn("version conflict", str(cm.exception).lower()) - - -# =================================================================== -# --- Tests for wrap_numbers() function. -# =================================================================== - - -nt = collections.namedtuple('foo', 'a b c') - - -class TestWrapNumbers(unittest.TestCase): - - def setUp(self): - wrap_numbers.cache_clear() - - tearDown = setUp - - def test_first_call(self): - input = {'disk1': nt(5, 5, 5)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - - def test_input_hasnt_changed(self): - input = {'disk1': nt(5, 5, 5)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - - def test_increase_but_no_wrap(self): - input = {'disk1': nt(5, 5, 5)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - input = {'disk1': nt(10, 15, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - input = {'disk1': nt(20, 25, 30)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - input = {'disk1': nt(20, 25, 30)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - - def test_wrap(self): - # let's say 100 is the threshold - input = {'disk1': nt(100, 100, 100)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - # first wrap restarts from 10 - input = {'disk1': nt(100, 100, 10)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(100, 100, 110)}) - # then it remains the same - input = {'disk1': nt(100, 100, 10)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(100, 100, 110)}) - # then it goes up - input = {'disk1': nt(100, 100, 90)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(100, 100, 190)}) - # then it wraps again - input = {'disk1': nt(100, 100, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(100, 100, 210)}) - # and remains the same - input = {'disk1': nt(100, 100, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(100, 100, 210)}) - # now wrap another num - input = {'disk1': nt(50, 100, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(150, 100, 210)}) - # and again - input = {'disk1': nt(40, 100, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(190, 100, 210)}) - # keep it the same - input = {'disk1': nt(40, 100, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(190, 100, 210)}) - - def test_changing_keys(self): - # Emulate a case where the second call to disk_io() - # (or whatever) provides a new disk, then the new disk - # disappears on the third call. - input = {'disk1': nt(5, 5, 5)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - input = {'disk1': nt(5, 5, 5), - 'disk2': nt(7, 7, 7)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - input = {'disk1': nt(8, 8, 8)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - - def test_changing_keys_w_wrap(self): - input = {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 100)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - # disk 2 wraps - input = {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 10)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 110)}) - # disk 2 disappears - input = {'disk1': nt(50, 50, 50)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - - # then it appears again; the old wrap is supposed to be - # gone. - input = {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 100)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - # remains the same - input = {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 100)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - # and then wraps again - input = {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 10)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 110)}) - - def test_real_data(self): - d = {'nvme0n1': (300, 508, 640, 1571, 5970, 1987, 2049, 451751, 47048), - 'nvme0n1p1': (1171, 2, 5600256, 1024, 516, 0, 0, 0, 8), - 'nvme0n1p2': (54, 54, 2396160, 5165056, 4, 24, 30, 1207, 28), - 'nvme0n1p3': (2389, 4539, 5154, 150, 4828, 1844, 2019, 398, 348)} - self.assertEqual(wrap_numbers(d, 'disk_io'), d) - self.assertEqual(wrap_numbers(d, 'disk_io'), d) - # decrease this ↓ - d = {'nvme0n1': (100, 508, 640, 1571, 5970, 1987, 2049, 451751, 47048), - 'nvme0n1p1': (1171, 2, 5600256, 1024, 516, 0, 0, 0, 8), - 'nvme0n1p2': (54, 54, 2396160, 5165056, 4, 24, 30, 1207, 28), - 'nvme0n1p3': (2389, 4539, 5154, 150, 4828, 1844, 2019, 398, 348)} - out = wrap_numbers(d, 'disk_io') - self.assertEqual(out['nvme0n1'][0], 400) - - # --- cache tests - - def test_cache_first_call(self): - input = {'disk1': nt(5, 5, 5)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - self.assertEqual(cache[1], {'disk_io': {}}) - self.assertEqual(cache[2], {'disk_io': {}}) - - def test_cache_call_twice(self): - input = {'disk1': nt(5, 5, 5)} - wrap_numbers(input, 'disk_io') - input = {'disk1': nt(10, 10, 10)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - self.assertEqual( - cache[1], - {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 0}}) - self.assertEqual(cache[2], {'disk_io': {}}) - - def test_cache_wrap(self): - # let's say 100 is the threshold - input = {'disk1': nt(100, 100, 100)} - wrap_numbers(input, 'disk_io') - - # first wrap restarts from 10 - input = {'disk1': nt(100, 100, 10)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - self.assertEqual( - cache[1], - {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 100}}) - self.assertEqual(cache[2], {'disk_io': {'disk1': set([('disk1', 2)])}}) - - def assert_(): - cache = wrap_numbers.cache_info() - self.assertEqual( - cache[1], - {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, - ('disk1', 2): 100}}) - self.assertEqual(cache[2], - {'disk_io': {'disk1': set([('disk1', 2)])}}) - - # then it remains the same - input = {'disk1': nt(100, 100, 10)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - assert_() - - # then it goes up - input = {'disk1': nt(100, 100, 90)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - assert_() - - # then it wraps again - input = {'disk1': nt(100, 100, 20)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - self.assertEqual( - cache[1], - {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 190}}) - self.assertEqual(cache[2], {'disk_io': {'disk1': set([('disk1', 2)])}}) - - def test_cache_changing_keys(self): - input = {'disk1': nt(5, 5, 5)} - wrap_numbers(input, 'disk_io') - input = {'disk1': nt(5, 5, 5), - 'disk2': nt(7, 7, 7)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - self.assertEqual( - cache[1], - {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 0}}) - self.assertEqual(cache[2], {'disk_io': {}}) - - def test_cache_clear(self): - input = {'disk1': nt(5, 5, 5)} - wrap_numbers(input, 'disk_io') - wrap_numbers(input, 'disk_io') - wrap_numbers.cache_clear('disk_io') - self.assertEqual(wrap_numbers.cache_info(), ({}, {}, {})) - wrap_numbers.cache_clear('disk_io') - wrap_numbers.cache_clear('?!?') - - @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() - for cache in caches: - self.assertIn('psutil.disk_io_counters', cache) - self.assertIn('psutil.net_io_counters', cache) - - psutil.disk_io_counters.cache_clear() - caches = wrap_numbers.cache_info() - for cache in caches: - self.assertIn('psutil.net_io_counters', cache) - self.assertNotIn('psutil.disk_io_counters', cache) - - psutil.net_io_counters.cache_clear() - caches = wrap_numbers.cache_info() - self.assertEqual(caches, ({}, {}, {})) - - -# =================================================================== -# --- Example script tests -# =================================================================== - - -@unittest.skipIf(TOX, "can't test on TOX") -# See: https://travis-ci.org/giampaolo/psutil/jobs/295224806 -@unittest.skipIf(TRAVIS and not os.path.exists(SCRIPTS_DIR), - "can't locate scripts directory") -class TestScripts(unittest.TestCase): - """Tests for scripts in the "scripts" directory.""" - - @staticmethod - def assert_stdout(exe, *args, **kwargs): - exe = '%s' % os.path.join(SCRIPTS_DIR, exe) - cmd = [PYTHON_EXE, exe] - for arg in args: - cmd.append(arg) - try: - out = sh(cmd, **kwargs).strip() - except RuntimeError as err: - if 'AccessDenied' in str(err): - return str(err) - else: - raise - assert out, out - return out - - @staticmethod - def assert_syntax(exe, args=None): - exe = os.path.join(SCRIPTS_DIR, exe) - if PY3: - f = open(exe, 'rt', encoding='utf8') - else: - f = open(exe, 'rt') - with f: - src = f.read() - ast.parse(src) - - def test_coverage(self): - # make sure all example scripts have a test method defined - meths = dir(self) - for name in os.listdir(SCRIPTS_DIR): - if name.endswith('.py'): - if 'test_' + os.path.splitext(name)[0] not in meths: - # self.assert_stdout(name) - self.fail('no test defined for %r script' - % os.path.join(SCRIPTS_DIR, name)) - - @unittest.skipIf(not POSIX, "POSIX only") - def test_executable(self): - for name in os.listdir(SCRIPTS_DIR): - if name.endswith('.py'): - path = os.path.join(SCRIPTS_DIR, name) - if not stat.S_IXUSR & os.stat(path)[stat.ST_MODE]: - self.fail('%r is not executable' % path) - - def test_disk_usage(self): - self.assert_stdout('disk_usage.py') - - def test_free(self): - self.assert_stdout('free.py') - - def test_meminfo(self): - self.assert_stdout('meminfo.py') - - def test_procinfo(self): - self.assert_stdout('procinfo.py', str(os.getpid())) - - @unittest.skipIf(CI_TESTING and not psutil.users(), "no users") - def test_who(self): - self.assert_stdout('who.py') - - def test_ps(self): - self.assert_stdout('ps.py') - - def test_pstree(self): - self.assert_stdout('pstree.py') - - def test_netstat(self): - self.assert_stdout('netstat.py') - - # permission denied on travis - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - def test_ifconfig(self): - self.assert_stdout('ifconfig.py') - - @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") - def test_pmap(self): - self.assert_stdout('pmap.py', str(os.getpid())) - - def test_procsmem(self): - if 'uss' not in psutil.Process().memory_full_info()._fields: - raise self.skipTest("not supported") - self.assert_stdout('procsmem.py', stderr=DEVNULL) - - def test_killall(self): - self.assert_syntax('killall.py') - - def test_nettop(self): - self.assert_syntax('nettop.py') - - def test_top(self): - self.assert_syntax('top.py') - - def test_iotop(self): - self.assert_syntax('iotop.py') - - def test_pidof(self): - output = self.assert_stdout('pidof.py', psutil.Process().name()) - self.assertIn(str(os.getpid()), output) - - @unittest.skipIf(not WINDOWS, "WINDOWS only") - def test_winservices(self): - self.assert_stdout('winservices.py') - - def test_cpu_distribution(self): - self.assert_syntax('cpu_distribution.py') - - @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - def test_temperatures(self): - if not psutil.sensors_temperatures(): - self.skipTest("no temperatures") - self.assert_stdout('temperatures.py') - - @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - def test_fans(self): - if not psutil.sensors_fans(): - self.skipTest("no fans") - self.assert_stdout('fans.py') - - @unittest.skipIf(not HAS_SENSORS_BATTERY, "not supported") - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_battery(self): - self.assert_stdout('battery.py') - - def test_sensors(self): - self.assert_stdout('sensors.py') - - -# =================================================================== -# --- Unit tests for test utilities. -# =================================================================== - - -class TestRetryDecorator(unittest.TestCase): - - @mock.patch('time.sleep') - def test_retry_success(self, sleep): - # Fail 3 times out of 5; make sure the decorated fun returns. - - @retry(retries=5, interval=1, logfun=None) - def foo(): - while queue: - queue.pop() - 1 / 0 - return 1 - - queue = list(range(3)) - self.assertEqual(foo(), 1) - self.assertEqual(sleep.call_count, 3) - - @mock.patch('time.sleep') - def test_retry_failure(self, sleep): - # Fail 6 times out of 5; th function is supposed to raise exc. - - @retry(retries=5, interval=1, logfun=None) - def foo(): - while queue: - queue.pop() - 1 / 0 - return 1 - - queue = list(range(6)) - self.assertRaises(ZeroDivisionError, foo) - self.assertEqual(sleep.call_count, 5) - - @mock.patch('time.sleep') - def test_exception_arg(self, sleep): - @retry(exception=ValueError, interval=1) - def foo(): - raise TypeError - - self.assertRaises(TypeError, foo) - self.assertEqual(sleep.call_count, 0) - - @mock.patch('time.sleep') - def test_no_interval_arg(self, sleep): - # if interval is not specified sleep is not supposed to be called - - @retry(retries=5, interval=None, logfun=None) - def foo(): - 1 / 0 - - self.assertRaises(ZeroDivisionError, foo) - self.assertEqual(sleep.call_count, 0) - - @mock.patch('time.sleep') - def test_retries_arg(self, sleep): - - @retry(retries=5, interval=1, logfun=None) - def foo(): - 1 / 0 - - self.assertRaises(ZeroDivisionError, foo) - self.assertEqual(sleep.call_count, 5) - - @mock.patch('time.sleep') - def test_retries_and_timeout_args(self, sleep): - self.assertRaises(ValueError, retry, retries=5, timeout=1) - - -class TestSyncTestUtils(unittest.TestCase): - - def tearDown(self): - safe_rmpath(TESTFN) - - def test_wait_for_pid(self): - wait_for_pid(os.getpid()) - nopid = max(psutil.pids()) + 99999 - with mock.patch('psutil.tests.retry.__iter__', return_value=iter([0])): - self.assertRaises(psutil.NoSuchProcess, wait_for_pid, nopid) - - def test_wait_for_file(self): - with open(TESTFN, 'w') as f: - f.write('foo') - wait_for_file(TESTFN) - assert not os.path.exists(TESTFN) - - def test_wait_for_file_empty(self): - with open(TESTFN, 'w'): - pass - wait_for_file(TESTFN, empty=True) - assert not os.path.exists(TESTFN) - - def test_wait_for_file_no_file(self): - with mock.patch('psutil.tests.retry.__iter__', return_value=iter([0])): - self.assertRaises(IOError, wait_for_file, TESTFN) - - def test_wait_for_file_no_delete(self): - with open(TESTFN, 'w') as f: - f.write('foo') - wait_for_file(TESTFN, delete=False) - assert os.path.exists(TESTFN) - - def test_call_until(self): - ret = call_until(lambda: 1, "ret == 1") - self.assertEqual(ret, 1) - - -class TestFSTestUtils(unittest.TestCase): - - def setUp(self): - safe_rmpath(TESTFN) - - tearDown = setUp - - def test_open_text(self): - with open_text(__file__) as f: - self.assertEqual(f.mode, 'rt') - - def test_open_binary(self): - with open_binary(__file__) as f: - self.assertEqual(f.mode, 'rb') - - def test_safe_mkdir(self): - safe_mkdir(TESTFN) - assert os.path.isdir(TESTFN) - safe_mkdir(TESTFN) - assert os.path.isdir(TESTFN) - - def test_safe_rmpath(self): - # test file is removed - open(TESTFN, 'w').close() - safe_rmpath(TESTFN) - assert not os.path.exists(TESTFN) - # test no exception if path does not exist - safe_rmpath(TESTFN) - # test dir is removed - os.mkdir(TESTFN) - safe_rmpath(TESTFN) - assert not os.path.exists(TESTFN) - # test other exceptions are raised - with mock.patch('psutil.tests.os.stat', - side_effect=OSError(errno.EINVAL, "")) as m: - with self.assertRaises(OSError): - safe_rmpath(TESTFN) - assert m.called - - def test_chdir(self): - base = os.getcwd() - os.mkdir(TESTFN) - with chdir(TESTFN): - self.assertEqual(os.getcwd(), os.path.join(base, TESTFN)) - self.assertEqual(os.getcwd(), base) - - -class TestProcessUtils(unittest.TestCase): - - def test_reap_children(self): - subp = get_test_subprocess() - p = psutil.Process(subp.pid) - assert p.is_running() - reap_children() - assert not p.is_running() - assert not psutil.tests._pids_started - assert not psutil.tests._subprocesses_started - - def test_create_proc_children_pair(self): - p1, p2 = create_proc_children_pair() - self.assertNotEqual(p1.pid, p2.pid) - assert p1.is_running() - assert p2.is_running() - children = psutil.Process().children(recursive=True) - self.assertEqual(len(children), 2) - self.assertIn(p1, children) - self.assertIn(p2, children) - self.assertEqual(p1.ppid(), os.getpid()) - self.assertEqual(p2.ppid(), p1.pid) - - # make sure both of them are cleaned up - reap_children() - assert not p1.is_running() - assert not p2.is_running() - assert not psutil.tests._pids_started - assert not psutil.tests._subprocesses_started - - @unittest.skipIf(not POSIX, "POSIX only") - def test_create_zombie_proc(self): - zpid = create_zombie_proc() - self.addCleanup(reap_children, recursive=True) - p = psutil.Process(zpid) - self.assertEqual(p.status(), psutil.STATUS_ZOMBIE) - - -class TestNetUtils(unittest.TestCase): - - def bind_socket(self): - port = get_free_port() - with contextlib.closing(bind_socket(addr=('', port))) as s: - self.assertEqual(s.getsockname()[1], port) - - @unittest.skipIf(not POSIX, "POSIX only") - def test_bind_unix_socket(self): - with unix_socket_path() as name: - sock = bind_unix_socket(name) - with contextlib.closing(sock): - self.assertEqual(sock.family, socket.AF_UNIX) - self.assertEqual(sock.type, socket.SOCK_STREAM) - self.assertEqual(sock.getsockname(), name) - assert os.path.exists(name) - assert stat.S_ISSOCK(os.stat(name).st_mode) - # UDP - with unix_socket_path() as name: - sock = bind_unix_socket(name, type=socket.SOCK_DGRAM) - with contextlib.closing(sock): - self.assertEqual(sock.type, socket.SOCK_DGRAM) - - def tcp_tcp_socketpair(self): - addr = ("127.0.0.1", get_free_port()) - server, client = tcp_socketpair(socket.AF_INET, addr=addr) - with contextlib.closing(server): - with contextlib.closing(client): - # Ensure they are connected and the positions are - # correct. - self.assertEqual(server.getsockname(), addr) - self.assertEqual(client.getpeername(), addr) - self.assertNotEqual(client.getsockname(), addr) - - @unittest.skipIf(not POSIX, "POSIX only") - @unittest.skipIf(NETBSD or FREEBSD, - "/var/run/log UNIX socket opened by default") - def test_unix_socketpair(self): - p = psutil.Process() - num_fds = p.num_fds() - assert not p.connections(kind='unix') - with unix_socket_path() as name: - server, client = unix_socketpair(name) - try: - assert os.path.exists(name) - assert stat.S_ISSOCK(os.stat(name).st_mode) - self.assertEqual(p.num_fds() - num_fds, 2) - self.assertEqual(len(p.connections(kind='unix')), 2) - self.assertEqual(server.getsockname(), name) - self.assertEqual(client.getpeername(), name) - finally: - client.close() - server.close() - - def test_create_sockets(self): - with create_sockets() as socks: - fams = collections.defaultdict(int) - types = collections.defaultdict(int) - for s in socks: - fams[s.family] += 1 - # work around http://bugs.python.org/issue30204 - types[s.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)] += 1 - self.assertGreaterEqual(fams[socket.AF_INET], 2) - if supports_ipv6(): - self.assertGreaterEqual(fams[socket.AF_INET6], 2) - if POSIX and HAS_CONNECTIONS_UNIX: - self.assertGreaterEqual(fams[socket.AF_UNIX], 2) - self.assertGreaterEqual(types[socket.SOCK_STREAM], 2) - self.assertGreaterEqual(types[socket.SOCK_DGRAM], 2) - - -class TestOtherUtils(unittest.TestCase): - - def test_is_namedtuple(self): - assert is_namedtuple(collections.namedtuple('foo', 'a b c')(1, 2, 3)) - assert not is_namedtuple(tuple()) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_osx.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_osx.py deleted file mode 100644 index e4e77f93537e..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_osx.py +++ /dev/null @@ -1,294 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""MACOS specific tests.""" - -import os -import re -import time - -import psutil -from psutil import MACOS -from psutil.tests import create_zombie_proc -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_BATTERY -from psutil.tests import MEMORY_TOLERANCE -from psutil.tests import reap_children -from psutil.tests import retry_on_failure -from psutil.tests import sh -from psutil.tests import unittest - - -PAGESIZE = os.sysconf("SC_PAGE_SIZE") if MACOS else None - - -def sysctl(cmdline): - """Expects a sysctl command with an argument and parse the result - returning only the value of interest. - """ - out = sh(cmdline) - result = out.split()[1] - try: - return int(result) - except ValueError: - return result - - -def vm_stat(field): - """Wrapper around 'vm_stat' cmdline utility.""" - out = sh('vm_stat') - for line in out.split('\n'): - if field in line: - break - else: - raise ValueError("line not found") - return int(re.search(r'\d+', line).group(0)) * PAGESIZE - - -# http://code.activestate.com/recipes/578019/ -def human2bytes(s): - SYMBOLS = { - 'customary': ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'), - } - init = s - num = "" - while s and s[0:1].isdigit() or s[0:1] == '.': - num += s[0] - s = s[1:] - num = float(num) - letter = s.strip() - for name, sset in SYMBOLS.items(): - if letter in sset: - break - else: - if letter == 'k': - sset = SYMBOLS['customary'] - letter = letter.upper() - else: - raise ValueError("can't interpret %r" % init) - prefix = {sset[0]: 1} - for i, s in enumerate(sset[1:]): - prefix[s] = 1 << (i + 1) * 10 - return int(num * prefix[letter]) - - -@unittest.skipIf(not MACOS, "MACOS only") -class TestProcess(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_process_create_time(self): - output = sh("ps -o lstart -p %s" % self.pid) - start_ps = output.replace('STARTED', '').strip() - hhmmss = start_ps.split(' ')[-2] - year = start_ps.split(' ')[-1] - start_psutil = psutil.Process(self.pid).create_time() - self.assertEqual( - hhmmss, - time.strftime("%H:%M:%S", time.localtime(start_psutil))) - self.assertEqual( - year, - time.strftime("%Y", time.localtime(start_psutil))) - - -@unittest.skipIf(not MACOS, "MACOS only") -class TestZombieProcessAPIs(unittest.TestCase): - - @classmethod - def setUpClass(cls): - zpid = create_zombie_proc() - cls.p = psutil.Process(zpid) - - @classmethod - def tearDownClass(cls): - reap_children(recursive=True) - - def test_pidtask_info(self): - self.assertEqual(self.p.status(), psutil.STATUS_ZOMBIE) - self.p.ppid() - self.p.uids() - self.p.gids() - self.p.terminal() - self.p.create_time() - - def test_exe(self): - self.assertRaises(psutil.ZombieProcess, self.p.exe) - - def test_cmdline(self): - self.assertRaises(psutil.ZombieProcess, self.p.cmdline) - - def test_environ(self): - self.assertRaises(psutil.ZombieProcess, self.p.environ) - - def test_cwd(self): - self.assertRaises(psutil.ZombieProcess, self.p.cwd) - - def test_memory_full_info(self): - self.assertRaises(psutil.ZombieProcess, self.p.memory_full_info) - - def test_cpu_times(self): - self.assertRaises(psutil.ZombieProcess, self.p.cpu_times) - - def test_num_ctx_switches(self): - self.assertRaises(psutil.ZombieProcess, self.p.num_ctx_switches) - - def test_num_threads(self): - self.assertRaises(psutil.ZombieProcess, self.p.num_threads) - - def test_open_files(self): - self.assertRaises(psutil.ZombieProcess, self.p.open_files) - - def test_connections(self): - self.assertRaises(psutil.ZombieProcess, self.p.connections) - - def test_num_fds(self): - self.assertRaises(psutil.ZombieProcess, self.p.num_fds) - - def test_threads(self): - self.assertRaises((psutil.ZombieProcess, psutil.AccessDenied), - self.p.threads) - - -@unittest.skipIf(not MACOS, "MACOS only") -class TestSystemAPIs(unittest.TestCase): - - # --- disk - - def test_disks(self): - # test psutil.disk_usage() and psutil.disk_partitions() - # against "df -a" - def df(path): - out = sh('df -k "%s"' % path).strip() - lines = out.split('\n') - lines.pop(0) - line = lines.pop(0) - dev, total, used, free = line.split()[:4] - if dev == 'none': - dev = '' - total = int(total) * 1024 - used = int(used) * 1024 - free = int(free) * 1024 - return dev, total, used, free - - for part in psutil.disk_partitions(all=False): - usage = psutil.disk_usage(part.mountpoint) - dev, total, used, free = df(part.mountpoint) - self.assertEqual(part.device, dev) - self.assertEqual(usage.total, total) - # 10 MB tollerance - if abs(usage.free - free) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % usage.free, free) - if abs(usage.used - used) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % usage.used, used) - - # --- cpu - - def test_cpu_count_logical(self): - num = sysctl("sysctl hw.logicalcpu") - self.assertEqual(num, psutil.cpu_count(logical=True)) - - def test_cpu_count_physical(self): - num = sysctl("sysctl hw.physicalcpu") - self.assertEqual(num, psutil.cpu_count(logical=False)) - - def test_cpu_freq(self): - freq = psutil.cpu_freq() - self.assertEqual( - freq.current * 1000 * 1000, sysctl("sysctl hw.cpufrequency")) - self.assertEqual( - freq.min * 1000 * 1000, sysctl("sysctl hw.cpufrequency_min")) - self.assertEqual( - freq.max * 1000 * 1000, sysctl("sysctl hw.cpufrequency_max")) - - # --- virtual mem - - def test_vmem_total(self): - sysctl_hwphymem = sysctl('sysctl hw.memsize') - self.assertEqual(sysctl_hwphymem, psutil.virtual_memory().total) - - @retry_on_failure() - def test_vmem_free(self): - vmstat_val = vm_stat("free") - psutil_val = psutil.virtual_memory().free - self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_active(self): - vmstat_val = vm_stat("active") - psutil_val = psutil.virtual_memory().active - self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_inactive(self): - vmstat_val = vm_stat("inactive") - psutil_val = psutil.virtual_memory().inactive - self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_wired(self): - vmstat_val = vm_stat("wired") - psutil_val = psutil.virtual_memory().wired - self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) - - # --- swap mem - - @retry_on_failure() - def test_swapmem_sin(self): - vmstat_val = vm_stat("Pageins") - psutil_val = psutil.swap_memory().sin - self.assertEqual(psutil_val, vmstat_val) - - @retry_on_failure() - def test_swapmem_sout(self): - vmstat_val = vm_stat("Pageout") - psutil_val = psutil.swap_memory().sout - self.assertEqual(psutil_val, vmstat_val) - - # Not very reliable. - # def test_swapmem_total(self): - # out = sh('sysctl vm.swapusage') - # out = out.replace('vm.swapusage: ', '') - # total, used, free = re.findall('\d+.\d+\w', out) - # psutil_smem = psutil.swap_memory() - # self.assertEqual(psutil_smem.total, human2bytes(total)) - # self.assertEqual(psutil_smem.used, human2bytes(used)) - # self.assertEqual(psutil_smem.free, human2bytes(free)) - - # --- network - - def test_net_if_stats(self): - for name, stats in psutil.net_if_stats().items(): - try: - out = sh("ifconfig %s" % name) - except RuntimeError: - pass - else: - self.assertEqual(stats.isup, 'RUNNING' in out, msg=out) - self.assertEqual(stats.mtu, - int(re.findall(r'mtu (\d+)', out)[0])) - - # --- sensors_battery - - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_sensors_battery(self): - out = sh("pmset -g batt") - percent = re.search(r"(\d+)%", out).group(1) - drawing_from = re.search("Now drawing from '([^']+)'", out).group(1) - power_plugged = drawing_from == "AC Power" - psutil_result = psutil.sensors_battery() - self.assertEqual(psutil_result.power_plugged, power_plugged) - self.assertEqual(psutil_result.percent, int(percent)) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_posix.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_posix.py deleted file mode 100644 index a96b310ffe7f..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_posix.py +++ /dev/null @@ -1,453 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# 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. - -"""POSIX specific tests.""" - -import datetime -import errno -import os -import re -import subprocess -import time - -import psutil -from psutil import AIX -from psutil import BSD -from psutil import LINUX -from psutil import MACOS -from psutil import OPENBSD -from psutil import POSIX -from psutil import SUNOS -from psutil.tests import CI_TESTING -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 -from psutil.tests import retry_on_failure -from psutil.tests import sh -from psutil.tests import skip_on_access_denied -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import wait_for_pid -from psutil.tests import which - - -def ps(fmt, pid=None): - """ - Wrapper for calling the ps command with a little bit of cross-platform - support for a narrow range of features. - """ - - cmd = ['ps'] - - if LINUX: - cmd.append('--no-headers') - - if pid is not None: - cmd.extend(['-p', str(pid)]) - else: - if SUNOS or AIX: - cmd.append('-A') - else: - cmd.append('ax') - - if SUNOS: - fmt_map = set(('command', 'comm', 'start', 'stime')) - fmt = fmt_map.get(fmt, fmt) - - cmd.extend(['-o', fmt]) - - output = sh(cmd) - - if LINUX: - output = output.splitlines() - else: - output = output.splitlines()[1:] - - all_output = [] - for line in output: - line = line.strip() - - try: - line = int(line) - except ValueError: - pass - - all_output.append(line) - - if pid is None: - return all_output - else: - return all_output[0] - -# ps "-o" field names differ wildly between platforms. -# "comm" means "only executable name" but is not available on BSD platforms. -# "args" means "command with all its arguments", and is also not available -# on BSD platforms. -# "command" is like "args" on most platforms, but like "comm" on AIX, -# and not available on SUNOS. -# so for the executable name we can use "comm" on Solaris and split "command" -# on other platforms. -# to get the cmdline (with args) we have to use "args" on AIX and -# Solaris, and can use "command" on all others. - - -def ps_name(pid): - field = "command" - if SUNOS: - field = "comm" - return ps(field, pid).split()[0] - - -def ps_args(pid): - field = "command" - if AIX or SUNOS: - field = "args" - return ps(field, pid) - - -def ps_rss(pid): - field = "rss" - if AIX: - field = "rssize" - return ps(field, pid) - - -def ps_vsz(pid): - field = "vsz" - if AIX: - field = "vsize" - return ps(field, pid) - - -@unittest.skipIf(not POSIX, "POSIX only") -class TestProcess(unittest.TestCase): - """Compare psutil results against 'ps' command line utility (mainly).""" - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess([PYTHON_EXE, "-E", "-O"], - stdin=subprocess.PIPE).pid - wait_for_pid(cls.pid) - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_ppid(self): - ppid_ps = ps('ppid', self.pid) - ppid_psutil = psutil.Process(self.pid).ppid() - self.assertEqual(ppid_ps, ppid_psutil) - - def test_uid(self): - uid_ps = ps('uid', self.pid) - uid_psutil = psutil.Process(self.pid).uids().real - self.assertEqual(uid_ps, uid_psutil) - - def test_gid(self): - gid_ps = ps('rgid', self.pid) - gid_psutil = psutil.Process(self.pid).gids().real - self.assertEqual(gid_ps, gid_psutil) - - def test_username(self): - username_ps = ps('user', self.pid) - username_psutil = psutil.Process(self.pid).username() - self.assertEqual(username_ps, username_psutil) - - def test_username_no_resolution(self): - # Emulate a case where the system can't resolve the uid to - # a username in which case psutil is supposed to return - # the stringified uid. - p = psutil.Process() - with mock.patch("psutil.pwd.getpwuid", side_effect=KeyError) as fun: - self.assertEqual(p.username(), str(p.uids().real)) - assert fun.called - - @skip_on_access_denied() - @retry_on_failure() - def test_rss_memory(self): - # give python interpreter some time to properly initialize - # so that the results are the same - time.sleep(0.1) - rss_ps = ps_rss(self.pid) - rss_psutil = psutil.Process(self.pid).memory_info()[0] / 1024 - self.assertEqual(rss_ps, rss_psutil) - - @skip_on_access_denied() - @retry_on_failure() - def test_vsz_memory(self): - # give python interpreter some time to properly initialize - # so that the results are the same - time.sleep(0.1) - vsz_ps = ps_vsz(self.pid) - vsz_psutil = psutil.Process(self.pid).memory_info()[1] / 1024 - self.assertEqual(vsz_ps, vsz_psutil) - - def test_name(self): - name_ps = ps_name(self.pid) - # remove path if there is any, from the command - name_ps = os.path.basename(name_ps).lower() - name_psutil = psutil.Process(self.pid).name().lower() - # ...because of how we calculate PYTHON_EXE; on MACOS this may - # be "pythonX.Y". - name_ps = re.sub(r"\d.\d", "", name_ps) - name_psutil = re.sub(r"\d.\d", "", name_psutil) - # ...may also be "python.X" - name_ps = re.sub(r"\d", "", name_ps) - name_psutil = re.sub(r"\d", "", name_psutil) - self.assertEqual(name_ps, name_psutil) - - def test_name_long(self): - # On UNIX the kernel truncates the name to the first 15 - # characters. In such a case psutil tries to determine the - # full name from the cmdline. - name = "long-program-name" - cmdline = ["long-program-name-extended", "foo", "bar"] - with mock.patch("psutil._psplatform.Process.name", - return_value=name): - with mock.patch("psutil._psplatform.Process.cmdline", - return_value=cmdline): - p = psutil.Process() - self.assertEqual(p.name(), "long-program-name-extended") - - def test_name_long_cmdline_ad_exc(self): - # Same as above but emulates a case where cmdline() raises - # AccessDenied in which case psutil is supposed to return - # the truncated name instead of crashing. - name = "long-program-name" - with mock.patch("psutil._psplatform.Process.name", - return_value=name): - with mock.patch("psutil._psplatform.Process.cmdline", - side_effect=psutil.AccessDenied(0, "")): - p = psutil.Process() - self.assertEqual(p.name(), "long-program-name") - - def test_name_long_cmdline_nsp_exc(self): - # Same as above but emulates a case where cmdline() raises NSP - # which is supposed to propagate. - name = "long-program-name" - with mock.patch("psutil._psplatform.Process.name", - return_value=name): - with mock.patch("psutil._psplatform.Process.cmdline", - side_effect=psutil.NoSuchProcess(0, "")): - p = psutil.Process() - self.assertRaises(psutil.NoSuchProcess, p.name) - - @unittest.skipIf(MACOS or BSD, 'ps -o start not available') - def test_create_time(self): - time_ps = ps('start', self.pid) - time_psutil = psutil.Process(self.pid).create_time() - time_psutil_tstamp = datetime.datetime.fromtimestamp( - time_psutil).strftime("%H:%M:%S") - # sometimes ps shows the time rounded up instead of down, so we check - # for both possible values - round_time_psutil = round(time_psutil) - round_time_psutil_tstamp = datetime.datetime.fromtimestamp( - round_time_psutil).strftime("%H:%M:%S") - self.assertIn(time_ps, [time_psutil_tstamp, round_time_psutil_tstamp]) - - def test_exe(self): - ps_pathname = ps_name(self.pid) - psutil_pathname = psutil.Process(self.pid).exe() - try: - self.assertEqual(ps_pathname, psutil_pathname) - except AssertionError: - # certain platforms such as BSD are more accurate returning: - # "/usr/local/bin/python2.7" - # ...instead of: - # "/usr/local/bin/python" - # We do not want to consider this difference in accuracy - # an error. - adjusted_ps_pathname = ps_pathname[:len(ps_pathname)] - self.assertEqual(ps_pathname, adjusted_ps_pathname) - - def test_cmdline(self): - ps_cmdline = ps_args(self.pid) - psutil_cmdline = " ".join(psutil.Process(self.pid).cmdline()) - self.assertEqual(ps_cmdline, psutil_cmdline) - - # On SUNOS "ps" reads niceness /proc/pid/psinfo which returns an - # incorrect value (20); the real deal is getpriority(2) which - # returns 0; psutil relies on it, see: - # https://github.com/giampaolo/psutil/issues/1082 - # AIX has the same issue - @unittest.skipIf(SUNOS, "not reliable on SUNOS") - @unittest.skipIf(AIX, "not reliable on AIX") - def test_nice(self): - ps_nice = ps('nice', self.pid) - psutil_nice = psutil.Process().nice() - self.assertEqual(ps_nice, psutil_nice) - - def test_num_fds(self): - # Note: this fails from time to time; I'm keen on thinking - # it doesn't mean something is broken - def call(p, attr): - args = () - attr = getattr(p, name, None) - if attr is not None and callable(attr): - if name == 'rlimit': - args = (psutil.RLIMIT_NOFILE,) - attr(*args) - else: - attr - - p = psutil.Process(os.getpid()) - failures = [] - ignored_names = ['terminate', 'kill', 'suspend', 'resume', 'nice', - 'send_signal', 'wait', 'children', 'as_dict', - 'memory_info_ex', 'parent', 'parents'] - if LINUX and get_kernel_version() < (2, 6, 36): - ignored_names.append('rlimit') - if LINUX and get_kernel_version() < (2, 6, 23): - ignored_names.append('num_ctx_switches') - for name in dir(psutil.Process): - if (name.startswith('_') or name in ignored_names): - continue - else: - try: - num1 = p.num_fds() - for x in range(2): - call(p, name) - num2 = p.num_fds() - except psutil.AccessDenied: - pass - else: - if abs(num2 - num1) > 1: - fail = "failure while processing Process.%s method " \ - "(before=%s, after=%s)" % (name, num1, num2) - failures.append(fail) - if failures: - self.fail('\n' + '\n'.join(failures)) - - -@unittest.skipIf(not POSIX, "POSIX only") -class TestSystemAPIs(unittest.TestCase): - """Test some system APIs.""" - - @retry_on_failure() - def test_pids(self): - # Note: this test might fail if the OS is starting/killing - # other processes in the meantime - pids_ps = sorted(ps("pid")) - pids_psutil = psutil.pids() - - # on MACOS and OPENBSD ps doesn't show pid 0 - if MACOS or OPENBSD and 0 not in pids_ps: - pids_ps.insert(0, 0) - - # There will often be one more process in pids_ps for ps itself - if len(pids_ps) - len(pids_psutil) > 1: - difference = [x for x in pids_psutil if x not in pids_ps] + \ - [x for x in pids_ps if x not in pids_psutil] - self.fail("difference: " + str(difference)) - - # for some reason ifconfig -a does not report all interfaces - # returned by psutil - @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(): - for line in output.split(): - if line.startswith(nic): - break - else: - self.fail( - "couldn't find %s nic in 'ifconfig -a' output\n%s" % ( - nic, output)) - - @unittest.skipIf(CI_TESTING and not psutil.users(), "unreliable on CI") - @retry_on_failure() - def test_users(self): - out = sh("who") - lines = out.split('\n') - if not lines: - raise self.skipTest("no users on this system") - users = [x.split()[0] for x in lines] - terminals = [x.split()[1] for x in lines] - self.assertEqual(len(users), len(psutil.users())) - for u in psutil.users(): - self.assertIn(u.name, users) - self.assertIn(u.terminal, terminals) - - def test_pid_exists_let_raise(self): - # According to "man 2 kill" possible error values for kill - # are (EINVAL, EPERM, ESRCH). Test that any other errno - # results in an exception. - with mock.patch("psutil._psposix.os.kill", - side_effect=OSError(errno.EBADF, "")) as m: - self.assertRaises(OSError, psutil._psposix.pid_exists, os.getpid()) - assert m.called - - def test_os_waitpid_let_raise(self): - # os.waitpid() is supposed to catch EINTR and ECHILD only. - # Test that any other errno results in an exception. - with mock.patch("psutil._psposix.os.waitpid", - side_effect=OSError(errno.EBADF, "")) as m: - self.assertRaises(OSError, psutil._psposix.wait_pid, os.getpid()) - assert m.called - - def test_os_waitpid_eintr(self): - # os.waitpid() is supposed to "retry" on EINTR. - with mock.patch("psutil._psposix.os.waitpid", - side_effect=OSError(errno.EINTR, "")) as m: - self.assertRaises( - psutil._psposix.TimeoutExpired, - psutil._psposix.wait_pid, os.getpid(), timeout=0.01) - assert m.called - - def test_os_waitpid_bad_ret_status(self): - # Simulate os.waitpid() returning a bad status. - with mock.patch("psutil._psposix.os.waitpid", - return_value=(1, -1)) as m: - self.assertRaises(ValueError, - psutil._psposix.wait_pid, os.getpid()) - assert m.called - - # AIX can return '-' in df output instead of numbers, e.g. for /proc - @unittest.skipIf(AIX, "unreliable on AIX") - def test_disk_usage(self): - def df(device): - out = sh("df -k %s" % device).strip() - line = out.split('\n')[1] - fields = line.split() - total = int(fields[1]) * 1024 - used = int(fields[2]) * 1024 - free = int(fields[3]) * 1024 - percent = float(fields[4].replace('%', '')) - return (total, used, free, percent) - - tolerance = 4 * 1024 * 1024 # 4MB - for part in psutil.disk_partitions(all=False): - usage = psutil.disk_usage(part.mountpoint) - try: - total, used, free, percent = df(part.device) - except RuntimeError as err: - # see: - # https://travis-ci.org/giampaolo/psutil/jobs/138338464 - # https://travis-ci.org/giampaolo/psutil/jobs/138343361 - err = str(err).lower() - if "no such file or directory" in err or \ - "raw devices not supported" in err or \ - "permission denied" in err: - continue - else: - raise - else: - self.assertAlmostEqual(usage.total, total, delta=tolerance) - self.assertAlmostEqual(usage.used, used, delta=tolerance) - self.assertAlmostEqual(usage.free, free, delta=tolerance) - self.assertAlmostEqual(usage.percent, percent, delta=1) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_process.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_process.py deleted file mode 100644 index 987bdf38bb69..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_process.py +++ /dev/null @@ -1,1643 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Tests for psutil.Process class.""" - -import collections -import errno -import getpass -import itertools -import os -import signal -import socket -import subprocess -import sys -import tempfile -import textwrap -import time -import types - -import psutil - -from psutil import AIX -from psutil import BSD -from psutil import LINUX -from psutil import MACOS -from psutil import NETBSD -from psutil import OPENBSD -from psutil import OSX -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -from psutil._common import open_text -from psutil._compat import long -from psutil._compat import PY3 -from psutil.tests import APPVEYOR -from psutil.tests import call_until -from psutil.tests import CIRRUS -from psutil.tests import copyload_shared_lib -from psutil.tests import create_exe -from psutil.tests import create_proc_children_pair -from psutil.tests import create_zombie_proc -from psutil.tests import enum -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_CPU_AFFINITY -from psutil.tests import HAS_ENVIRON -from psutil.tests import HAS_IONICE -from psutil.tests import HAS_MEMORY_MAPS -from psutil.tests import HAS_PROC_CPU_NUM -from psutil.tests import HAS_PROC_IO_COUNTERS -from psutil.tests import HAS_RLIMIT -from psutil.tests import HAS_THREADS -from psutil.tests import mock -from psutil.tests import PYPY -from psutil.tests import PYTHON_EXE -from psutil.tests import reap_children -from psutil.tests import retry_on_failure -from psutil.tests import safe_rmpath -from psutil.tests import sh -from psutil.tests import skip_on_access_denied -from psutil.tests import skip_on_not_implemented -from psutil.tests import TESTFILE_PREFIX -from psutil.tests import TESTFN -from psutil.tests import ThreadTask -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import wait_for_pid - - -# =================================================================== -# --- psutil.Process class tests -# =================================================================== - -class TestProcess(unittest.TestCase): - """Tests for psutil.Process class.""" - - def setUp(self): - safe_rmpath(TESTFN) - - def tearDown(self): - reap_children() - - def test_pid(self): - p = psutil.Process() - self.assertEqual(p.pid, os.getpid()) - sproc = get_test_subprocess() - self.assertEqual(psutil.Process(sproc.pid).pid, sproc.pid) - with self.assertRaises(AttributeError): - p.pid = 33 - - def test_kill(self): - sproc = get_test_subprocess() - test_pid = sproc.pid - p = psutil.Process(test_pid) - p.kill() - sig = p.wait() - self.assertFalse(psutil.pid_exists(test_pid)) - if POSIX: - self.assertEqual(sig, -signal.SIGKILL) - - def test_terminate(self): - sproc = get_test_subprocess() - test_pid = sproc.pid - p = psutil.Process(test_pid) - p.terminate() - sig = p.wait() - self.assertFalse(psutil.pid_exists(test_pid)) - if POSIX: - self.assertEqual(sig, -signal.SIGTERM) - - def test_send_signal(self): - sig = signal.SIGKILL if POSIX else signal.SIGTERM - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.send_signal(sig) - exit_sig = p.wait() - self.assertFalse(psutil.pid_exists(p.pid)) - if POSIX: - self.assertEqual(exit_sig, -sig) - # - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.send_signal(sig) - with mock.patch('psutil.os.kill', - side_effect=OSError(errno.ESRCH, "")): - with self.assertRaises(psutil.NoSuchProcess): - p.send_signal(sig) - # - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.send_signal(sig) - with mock.patch('psutil.os.kill', - side_effect=OSError(errno.EPERM, "")): - with self.assertRaises(psutil.AccessDenied): - psutil.Process().send_signal(sig) - # Sending a signal to process with PID 0 is not allowed as - # it would affect every process in the process group of - # the calling process (os.getpid()) instead of PID 0"). - if 0 in psutil.pids(): - p = psutil.Process(0) - self.assertRaises(ValueError, p.send_signal, signal.SIGTERM) - - def test_wait(self): - # check exit code signal - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.kill() - code = p.wait() - if POSIX: - self.assertEqual(code, -signal.SIGKILL) - else: - self.assertEqual(code, signal.SIGTERM) - self.assertFalse(p.is_running()) - - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.terminate() - code = p.wait() - if POSIX: - self.assertEqual(code, -signal.SIGTERM) - else: - self.assertEqual(code, signal.SIGTERM) - self.assertFalse(p.is_running()) - - # check sys.exit() code - code = "import time, sys; time.sleep(0.01); sys.exit(5);" - sproc = get_test_subprocess([PYTHON_EXE, "-c", code]) - p = psutil.Process(sproc.pid) - self.assertEqual(p.wait(), 5) - self.assertFalse(p.is_running()) - - # Test wait() issued twice. - # It is not supposed to raise NSP when the process is gone. - # On UNIX this should return None, on Windows it should keep - # returning the exit code. - sproc = get_test_subprocess([PYTHON_EXE, "-c", code]) - p = psutil.Process(sproc.pid) - self.assertEqual(p.wait(), 5) - self.assertIn(p.wait(), (5, None)) - - # test timeout - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.name() - self.assertRaises(psutil.TimeoutExpired, p.wait, 0.01) - - # timeout < 0 not allowed - self.assertRaises(ValueError, p.wait, -1) - - def test_wait_non_children(self): - # Test wait() against a process which is not our direct - # child. - p1, p2 = create_proc_children_pair() - self.assertRaises(psutil.TimeoutExpired, p1.wait, 0.01) - self.assertRaises(psutil.TimeoutExpired, p2.wait, 0.01) - # We also terminate the direct child otherwise the - # grandchild will hang until the parent is gone. - p1.terminate() - p2.terminate() - ret1 = p1.wait() - ret2 = p2.wait() - if POSIX: - self.assertEqual(ret1, -signal.SIGTERM) - # For processes which are not our children we're supposed - # to get None. - self.assertEqual(ret2, None) - else: - self.assertEqual(ret1, signal.SIGTERM) - self.assertEqual(ret1, signal.SIGTERM) - - def test_wait_timeout_0(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - self.assertRaises(psutil.TimeoutExpired, p.wait, 0) - p.kill() - stop_at = time.time() + 2 - while True: - try: - code = p.wait(0) - except psutil.TimeoutExpired: - if time.time() >= stop_at: - raise - else: - break - if POSIX: - self.assertEqual(code, -signal.SIGKILL) - else: - self.assertEqual(code, signal.SIGTERM) - self.assertFalse(p.is_running()) - - def test_cpu_percent(self): - p = psutil.Process() - p.cpu_percent(interval=0.001) - p.cpu_percent(interval=0.001) - for x in range(100): - percent = p.cpu_percent(interval=None) - self.assertIsInstance(percent, float) - self.assertGreaterEqual(percent, 0.0) - with self.assertRaises(ValueError): - p.cpu_percent(interval=-1) - - def test_cpu_percent_numcpus_none(self): - # See: https://github.com/giampaolo/psutil/issues/1087 - with mock.patch('psutil.cpu_count', return_value=None) as m: - psutil.Process().cpu_percent() - assert m.called - - def test_cpu_times(self): - times = psutil.Process().cpu_times() - assert (times.user > 0.0) or (times.system > 0.0), times - assert (times.children_user >= 0.0), times - assert (times.children_system >= 0.0), times - if LINUX: - assert times.iowait >= 0.0, times - # make sure returned values can be pretty printed with strftime - for name in times._fields: - time.strftime("%H:%M:%S", time.localtime(getattr(times, name))) - - def test_cpu_times_2(self): - user_time, kernel_time = psutil.Process().cpu_times()[:2] - utime, ktime = os.times()[:2] - - # Use os.times()[:2] as base values to compare our results - # using a tolerance of +/- 0.1 seconds. - # It will fail if the difference between the values is > 0.1s. - if (max([user_time, utime]) - min([user_time, utime])) > 0.1: - self.fail("expected: %s, found: %s" % (utime, user_time)) - - if (max([kernel_time, ktime]) - min([kernel_time, ktime])) > 0.1: - self.fail("expected: %s, found: %s" % (ktime, kernel_time)) - - @unittest.skipIf(not HAS_PROC_CPU_NUM, "not supported") - def test_cpu_num(self): - p = psutil.Process() - num = p.cpu_num() - self.assertGreaterEqual(num, 0) - if psutil.cpu_count() == 1: - self.assertEqual(num, 0) - self.assertIn(p.cpu_num(), range(psutil.cpu_count())) - - def test_create_time(self): - sproc = get_test_subprocess() - now = time.time() - p = psutil.Process(sproc.pid) - create_time = p.create_time() - - # Use time.time() as base value to compare our result using a - # tolerance of +/- 1 second. - # It will fail if the difference between the values is > 2s. - difference = abs(create_time - now) - if difference > 2: - self.fail("expected: %s, found: %s, difference: %s" - % (now, create_time, difference)) - - # make sure returned value can be pretty printed with strftime - time.strftime("%Y %m %d %H:%M:%S", time.localtime(p.create_time())) - - @unittest.skipIf(not POSIX, 'POSIX only') - @unittest.skipIf(TRAVIS or CIRRUS, 'not reliable on TRAVIS/CIRRUS') - def test_terminal(self): - terminal = psutil.Process().terminal() - if sys.stdin.isatty() or sys.stdout.isatty(): - tty = os.path.realpath(sh('tty')) - self.assertEqual(terminal, tty) - else: - self.assertIsNone(terminal) - - @unittest.skipIf(not HAS_PROC_IO_COUNTERS, 'not supported') - @skip_on_not_implemented(only_if=LINUX) - def test_io_counters(self): - p = psutil.Process() - # test reads - io1 = p.io_counters() - with open(PYTHON_EXE, 'rb') as f: - f.read() - io2 = p.io_counters() - if not BSD and not AIX: - self.assertGreater(io2.read_count, io1.read_count) - self.assertEqual(io2.write_count, io1.write_count) - if LINUX: - self.assertGreater(io2.read_chars, io1.read_chars) - self.assertEqual(io2.write_chars, io1.write_chars) - else: - self.assertGreaterEqual(io2.read_bytes, io1.read_bytes) - self.assertGreaterEqual(io2.write_bytes, io1.write_bytes) - - # test writes - io1 = p.io_counters() - with tempfile.TemporaryFile(prefix=TESTFILE_PREFIX) as f: - if PY3: - f.write(bytes("x" * 1000000, 'ascii')) - else: - f.write("x" * 1000000) - io2 = p.io_counters() - self.assertGreaterEqual(io2.write_count, io1.write_count) - self.assertGreaterEqual(io2.write_bytes, io1.write_bytes) - self.assertGreaterEqual(io2.read_count, io1.read_count) - self.assertGreaterEqual(io2.read_bytes, io1.read_bytes) - if LINUX: - self.assertGreater(io2.write_chars, io1.write_chars) - self.assertGreaterEqual(io2.read_chars, io1.read_chars) - - # sanity check - for i in range(len(io2)): - if BSD and i >= 2: - # On BSD read_bytes and write_bytes are always set to -1. - continue - self.assertGreaterEqual(io2[i], 0) - self.assertGreaterEqual(io2[i], 0) - - @unittest.skipIf(not HAS_IONICE, "not supported") - @unittest.skipIf(not LINUX, "linux only") - def test_ionice_linux(self): - p = psutil.Process() - self.assertEqual(p.ionice()[0], psutil.IOPRIO_CLASS_NONE) - self.assertEqual(psutil.IOPRIO_CLASS_NONE, 0) - self.assertEqual(psutil.IOPRIO_CLASS_RT, 1) # high - self.assertEqual(psutil.IOPRIO_CLASS_BE, 2) # normal - self.assertEqual(psutil.IOPRIO_CLASS_IDLE, 3) # low - try: - # low - p.ionice(psutil.IOPRIO_CLASS_IDLE) - self.assertEqual(tuple(p.ionice()), (psutil.IOPRIO_CLASS_IDLE, 0)) - with self.assertRaises(ValueError): # accepts no value - p.ionice(psutil.IOPRIO_CLASS_IDLE, value=7) - # normal - p.ionice(psutil.IOPRIO_CLASS_BE) - self.assertEqual(tuple(p.ionice()), (psutil.IOPRIO_CLASS_BE, 0)) - p.ionice(psutil.IOPRIO_CLASS_BE, value=7) - self.assertEqual(tuple(p.ionice()), (psutil.IOPRIO_CLASS_BE, 7)) - with self.assertRaises(ValueError): - p.ionice(psutil.IOPRIO_CLASS_BE, value=8) - # high - if os.getuid() == 0: # root - p.ionice(psutil.IOPRIO_CLASS_RT) - self.assertEqual(tuple(p.ionice()), - (psutil.IOPRIO_CLASS_RT, 0)) - p.ionice(psutil.IOPRIO_CLASS_RT, value=7) - self.assertEqual(tuple(p.ionice()), - (psutil.IOPRIO_CLASS_RT, 7)) - with self.assertRaises(ValueError): - p.ionice(psutil.IOPRIO_CLASS_IDLE, value=8) - # errs - self.assertRaisesRegex( - ValueError, "ioclass accepts no value", - p.ionice, psutil.IOPRIO_CLASS_NONE, 1) - self.assertRaisesRegex( - ValueError, "ioclass accepts no value", - p.ionice, psutil.IOPRIO_CLASS_IDLE, 1) - self.assertRaisesRegex( - ValueError, "'ioclass' argument must be specified", - p.ionice, value=1) - finally: - p.ionice(psutil.IOPRIO_CLASS_BE) - - @unittest.skipIf(not HAS_IONICE, "not supported") - @unittest.skipIf(not WINDOWS, 'not supported on this win version') - def test_ionice_win(self): - p = psutil.Process() - self.assertEqual(p.ionice(), psutil.IOPRIO_NORMAL) - try: - # base - p.ionice(psutil.IOPRIO_VERYLOW) - self.assertEqual(p.ionice(), psutil.IOPRIO_VERYLOW) - p.ionice(psutil.IOPRIO_LOW) - self.assertEqual(p.ionice(), psutil.IOPRIO_LOW) - try: - p.ionice(psutil.IOPRIO_HIGH) - except psutil.AccessDenied: - pass - else: - self.assertEqual(p.ionice(), psutil.IOPRIO_HIGH) - # errs - self.assertRaisesRegex( - TypeError, "value argument not accepted on Windows", - p.ionice, psutil.IOPRIO_NORMAL, value=1) - self.assertRaisesRegex( - ValueError, "is not a valid priority", - p.ionice, psutil.IOPRIO_HIGH + 1) - finally: - p.ionice(psutil.IOPRIO_NORMAL) - self.assertEqual(p.ionice(), psutil.IOPRIO_NORMAL) - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_get(self): - import resource - p = psutil.Process(os.getpid()) - names = [x for x in dir(psutil) if x.startswith('RLIMIT')] - assert names, names - for name in names: - value = getattr(psutil, name) - self.assertGreaterEqual(value, 0) - if name in dir(resource): - self.assertEqual(value, getattr(resource, name)) - # XXX - On PyPy RLIMIT_INFINITY returned by - # resource.getrlimit() is reported as a very big long - # number instead of -1. It looks like a bug with PyPy. - if PYPY: - continue - self.assertEqual(p.rlimit(value), resource.getrlimit(value)) - else: - ret = p.rlimit(value) - self.assertEqual(len(ret), 2) - self.assertGreaterEqual(ret[0], -1) - self.assertGreaterEqual(ret[1], -1) - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_set(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) - self.assertEqual(p.rlimit(psutil.RLIMIT_NOFILE), (5, 5)) - # If pid is 0 prlimit() applies to the calling process and - # we don't want that. - with self.assertRaises(ValueError): - psutil._psplatform.Process(0).rlimit(0) - with self.assertRaises(ValueError): - p.rlimit(psutil.RLIMIT_NOFILE, (5, 5, 5)) - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit(self): - p = psutil.Process() - soft, hard = p.rlimit(psutil.RLIMIT_FSIZE) - try: - p.rlimit(psutil.RLIMIT_FSIZE, (1024, hard)) - with open(TESTFN, "wb") as f: - f.write(b"X" * 1024) - # write() or flush() doesn't always cause the exception - # but close() will. - with self.assertRaises(IOError) as exc: - with open(TESTFN, "wb") as f: - f.write(b"X" * 1025) - self.assertEqual(exc.exception.errno if PY3 else exc.exception[0], - errno.EFBIG) - finally: - p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard)) - self.assertEqual(p.rlimit(psutil.RLIMIT_FSIZE), (soft, hard)) - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_infinity(self): - # First set a limit, then re-set it by specifying INFINITY - # and assume we overridden the previous limit. - p = psutil.Process() - soft, hard = p.rlimit(psutil.RLIMIT_FSIZE) - try: - p.rlimit(psutil.RLIMIT_FSIZE, (1024, hard)) - p.rlimit(psutil.RLIMIT_FSIZE, (psutil.RLIM_INFINITY, hard)) - with open(TESTFN, "wb") as f: - f.write(b"X" * 2048) - finally: - p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard)) - self.assertEqual(p.rlimit(psutil.RLIMIT_FSIZE), (soft, hard)) - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_infinity_value(self): - # RLIMIT_FSIZE should be RLIM_INFINITY, which will be a really - # big number on a platform with large file support. On these - # platforms we need to test that the get/setrlimit functions - # properly convert the number to a C long long and that the - # conversion doesn't raise an error. - p = psutil.Process() - soft, hard = p.rlimit(psutil.RLIMIT_FSIZE) - self.assertEqual(psutil.RLIM_INFINITY, hard) - p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard)) - - def test_num_threads(self): - # on certain platforms such as Linux we might test for exact - # thread number, since we always have with 1 thread per process, - # but this does not apply across all platforms (MACOS, Windows) - p = psutil.Process() - if OPENBSD: - try: - step1 = p.num_threads() - except psutil.AccessDenied: - raise unittest.SkipTest("on OpenBSD this requires root access") - else: - step1 = p.num_threads() - - with ThreadTask(): - step2 = p.num_threads() - self.assertEqual(step2, step1 + 1) - - @unittest.skipIf(not WINDOWS, 'WINDOWS only') - def test_num_handles(self): - # a better test is done later into test/_windows.py - p = psutil.Process() - self.assertGreater(p.num_handles(), 0) - - @unittest.skipIf(not HAS_THREADS, 'not supported') - def test_threads(self): - p = psutil.Process() - if OPENBSD: - try: - step1 = p.threads() - except psutil.AccessDenied: - raise unittest.SkipTest("on OpenBSD this requires root access") - else: - step1 = p.threads() - - with ThreadTask(): - step2 = p.threads() - self.assertEqual(len(step2), len(step1) + 1) - athread = step2[0] - # test named tuple - self.assertEqual(athread.id, athread[0]) - self.assertEqual(athread.user_time, athread[1]) - self.assertEqual(athread.system_time, athread[2]) - - @retry_on_failure() - @skip_on_access_denied(only_if=MACOS) - @unittest.skipIf(not HAS_THREADS, 'not supported') - def test_threads_2(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - if OPENBSD: - try: - p.threads() - except psutil.AccessDenied: - raise unittest.SkipTest( - "on OpenBSD this requires root access") - self.assertAlmostEqual( - p.cpu_times().user, - sum([x.user_time for x in p.threads()]), delta=0.1) - self.assertAlmostEqual( - p.cpu_times().system, - sum([x.system_time for x in p.threads()]), delta=0.1) - - def test_memory_info(self): - p = psutil.Process() - - # step 1 - get a base value to compare our results - rss1, vms1 = p.memory_info()[:2] - percent1 = p.memory_percent() - self.assertGreater(rss1, 0) - self.assertGreater(vms1, 0) - - # step 2 - allocate some memory - memarr = [None] * 1500000 - - rss2, vms2 = p.memory_info()[:2] - percent2 = p.memory_percent() - - # step 3 - make sure that the memory usage bumped up - self.assertGreater(rss2, rss1) - self.assertGreaterEqual(vms2, vms1) # vms might be equal - self.assertGreater(percent2, percent1) - del memarr - - if WINDOWS: - mem = p.memory_info() - self.assertEqual(mem.rss, mem.wset) - self.assertEqual(mem.vms, mem.pagefile) - - mem = p.memory_info() - for name in mem._fields: - self.assertGreaterEqual(getattr(mem, name), 0) - - def test_memory_full_info(self): - total = psutil.virtual_memory().total - mem = psutil.Process().memory_full_info() - for name in mem._fields: - value = getattr(mem, name) - self.assertGreaterEqual(value, 0, msg=(name, value)) - if name == 'vms' and OSX or LINUX: - continue - self.assertLessEqual(value, total, msg=(name, value, total)) - if LINUX or WINDOWS or MACOS: - self.assertGreaterEqual(mem.uss, 0) - if LINUX: - self.assertGreaterEqual(mem.pss, 0) - self.assertGreaterEqual(mem.swap, 0) - - @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") - def test_memory_maps(self): - p = psutil.Process() - maps = p.memory_maps() - paths = [x for x in maps] - self.assertEqual(len(paths), len(set(paths))) - ext_maps = p.memory_maps(grouped=False) - - for nt in maps: - if not nt.path.startswith('['): - assert os.path.isabs(nt.path), nt.path - if POSIX: - try: - assert os.path.exists(nt.path) or \ - os.path.islink(nt.path), nt.path - except AssertionError: - if not LINUX: - raise - else: - # https://github.com/giampaolo/psutil/issues/759 - with open_text('/proc/self/smaps') as f: - data = f.read() - if "%s (deleted)" % nt.path not in data: - raise - else: - # XXX - On Windows we have this strange behavior with - # 64 bit dlls: they are visible via explorer but cannot - # be accessed via os.stat() (wtf?). - if '64' not in os.path.basename(nt.path): - assert os.path.exists(nt.path), nt.path - for nt in ext_maps: - for fname in nt._fields: - value = getattr(nt, fname) - if fname == 'path': - continue - elif fname in ('addr', 'perms'): - assert value, value - else: - self.assertIsInstance(value, (int, long)) - assert value >= 0, value - - @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") - def test_memory_maps_lists_lib(self): - # Make sure a newly loaded shared lib is listed. - with copyload_shared_lib() as path: - def normpath(p): - return os.path.realpath(os.path.normcase(p)) - libpaths = [normpath(x.path) - for x in psutil.Process().memory_maps()] - self.assertIn(normpath(path), libpaths) - - def test_memory_percent(self): - p = psutil.Process() - p.memory_percent() - self.assertRaises(ValueError, p.memory_percent, memtype="?!?") - if LINUX or MACOS or WINDOWS: - p.memory_percent(memtype='uss') - - def test_is_running(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - assert p.is_running() - assert p.is_running() - p.kill() - p.wait() - assert not p.is_running() - assert not p.is_running() - - def test_exe(self): - sproc = get_test_subprocess() - exe = psutil.Process(sproc.pid).exe() - try: - self.assertEqual(exe, PYTHON_EXE) - except AssertionError: - if WINDOWS and len(exe) == len(PYTHON_EXE): - # on Windows we don't care about case sensitivity - normcase = os.path.normcase - self.assertEqual(normcase(exe), normcase(PYTHON_EXE)) - else: - # certain platforms such as BSD are more accurate returning: - # "/usr/local/bin/python2.7" - # ...instead of: - # "/usr/local/bin/python" - # We do not want to consider this difference in accuracy - # an error. - ver = "%s.%s" % (sys.version_info[0], sys.version_info[1]) - try: - self.assertEqual(exe.replace(ver, ''), - PYTHON_EXE.replace(ver, '')) - except AssertionError: - # Tipically MACOS. Really not sure what to do here. - pass - - out = sh([exe, "-c", "import os; print('hey')"]) - self.assertEqual(out, 'hey') - - def test_cmdline(self): - cmdline = [PYTHON_EXE, "-c", "import time; time.sleep(60)"] - sproc = get_test_subprocess(cmdline) - try: - self.assertEqual(' '.join(psutil.Process(sproc.pid).cmdline()), - ' '.join(cmdline)) - except AssertionError: - # XXX - most of the times the underlying sysctl() call on Net - # and Open BSD returns a truncated string. - # Also /proc/pid/cmdline behaves the same so it looks - # like this is a kernel bug. - # XXX - AIX truncates long arguments in /proc/pid/cmdline - if NETBSD or OPENBSD or AIX: - self.assertEqual( - psutil.Process(sproc.pid).cmdline()[0], PYTHON_EXE) - else: - raise - - @unittest.skipIf(PYPY, "broken on PYPY") - def test_long_cmdline(self): - create_exe(TESTFN) - self.addCleanup(safe_rmpath, TESTFN) - cmdline = [TESTFN] + (["0123456789"] * 20) - sproc = get_test_subprocess(cmdline) - p = psutil.Process(sproc.pid) - self.assertEqual(p.cmdline(), cmdline) - - def test_name(self): - sproc = get_test_subprocess(PYTHON_EXE) - name = psutil.Process(sproc.pid).name().lower() - pyexe = os.path.basename(os.path.realpath(sys.executable)).lower() - assert pyexe.startswith(name), (pyexe, name) - - @unittest.skipIf(PYPY, "unreliable on PYPY") - def test_long_name(self): - long_name = TESTFN + ("0123456789" * 2) - create_exe(long_name) - self.addCleanup(safe_rmpath, long_name) - sproc = get_test_subprocess(long_name) - p = psutil.Process(sproc.pid) - self.assertEqual(p.name(), os.path.basename(long_name)) - - # XXX - @unittest.skipIf(SUNOS, "broken on SUNOS") - @unittest.skipIf(AIX, "broken on AIX") - @unittest.skipIf(PYPY, "broken on PYPY") - def test_prog_w_funky_name(self): - # Test that name(), exe() and cmdline() correctly handle programs - # with funky chars such as spaces and ")", see: - # https://github.com/giampaolo/psutil/issues/628 - - def rm(): - # Try to limit occasional failures on Appveyor: - # https://ci.appveyor.com/project/giampaolo/psutil/build/1350/ - # job/lbo3bkju55le850n - try: - safe_rmpath(funky_path) - except OSError: - pass - - funky_path = TESTFN + 'foo bar )' - create_exe(funky_path) - self.addCleanup(rm) - cmdline = [funky_path, "-c", - "import time; [time.sleep(0.01) for x in range(3000)];" - "arg1", "arg2", "", "arg3", ""] - sproc = get_test_subprocess(cmdline) - p = psutil.Process(sproc.pid) - # ...in order to try to prevent occasional failures on travis - if TRAVIS: - wait_for_pid(p.pid) - self.assertEqual(p.cmdline(), cmdline) - self.assertEqual(p.name(), os.path.basename(funky_path)) - self.assertEqual(os.path.normcase(p.exe()), - os.path.normcase(funky_path)) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_uids(self): - p = psutil.Process() - real, effective, saved = p.uids() - # os.getuid() refers to "real" uid - self.assertEqual(real, os.getuid()) - # os.geteuid() refers to "effective" uid - self.assertEqual(effective, os.geteuid()) - # No such thing as os.getsuid() ("saved" uid), but starting - # from python 2.7 we have os.getresuid() which returns all - # of them. - if hasattr(os, "getresuid"): - self.assertEqual(os.getresuid(), p.uids()) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_gids(self): - p = psutil.Process() - real, effective, saved = p.gids() - # os.getuid() refers to "real" uid - self.assertEqual(real, os.getgid()) - # os.geteuid() refers to "effective" uid - self.assertEqual(effective, os.getegid()) - # No such thing as os.getsgid() ("saved" gid), but starting - # from python 2.7 we have os.getresgid() which returns all - # of them. - if hasattr(os, "getresuid"): - self.assertEqual(os.getresgid(), p.gids()) - - def test_nice(self): - p = psutil.Process() - self.assertRaises(TypeError, p.nice, "str") - if WINDOWS: - try: - init = p.nice() - if sys.version_info > (3, 4): - self.assertIsInstance(init, enum.IntEnum) - else: - self.assertIsInstance(init, int) - self.assertEqual(init, psutil.NORMAL_PRIORITY_CLASS) - p.nice(psutil.HIGH_PRIORITY_CLASS) - self.assertEqual(p.nice(), psutil.HIGH_PRIORITY_CLASS) - p.nice(psutil.NORMAL_PRIORITY_CLASS) - self.assertEqual(p.nice(), psutil.NORMAL_PRIORITY_CLASS) - finally: - p.nice(psutil.NORMAL_PRIORITY_CLASS) - else: - first_nice = p.nice() - try: - if hasattr(os, "getpriority"): - self.assertEqual( - os.getpriority(os.PRIO_PROCESS, os.getpid()), p.nice()) - p.nice(1) - self.assertEqual(p.nice(), 1) - if hasattr(os, "getpriority"): - self.assertEqual( - os.getpriority(os.PRIO_PROCESS, os.getpid()), p.nice()) - # XXX - going back to previous nice value raises - # AccessDenied on MACOS - if not MACOS: - p.nice(0) - self.assertEqual(p.nice(), 0) - except psutil.AccessDenied: - pass - finally: - try: - p.nice(first_nice) - except psutil.AccessDenied: - pass - - def test_status(self): - p = psutil.Process() - self.assertEqual(p.status(), psutil.STATUS_RUNNING) - - def test_username(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - username = p.username() - if WINDOWS: - domain, username = username.split('\\') - self.assertEqual(username, getpass.getuser()) - if 'USERDOMAIN' in os.environ: - self.assertEqual(domain, os.environ['USERDOMAIN']) - else: - self.assertEqual(username, getpass.getuser()) - - def test_cwd(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - self.assertEqual(p.cwd(), os.getcwd()) - - def test_cwd_2(self): - cmd = [PYTHON_EXE, "-c", - "import os, time; os.chdir('..'); time.sleep(60)"] - sproc = get_test_subprocess(cmd) - p = psutil.Process(sproc.pid) - call_until(p.cwd, "ret == os.path.dirname(os.getcwd())") - - @unittest.skipIf(not HAS_CPU_AFFINITY, 'not supported') - def test_cpu_affinity(self): - p = psutil.Process() - initial = p.cpu_affinity() - assert initial, initial - self.addCleanup(p.cpu_affinity, initial) - - if hasattr(os, "sched_getaffinity"): - self.assertEqual(initial, list(os.sched_getaffinity(p.pid))) - self.assertEqual(len(initial), len(set(initial))) - - all_cpus = list(range(len(psutil.cpu_percent(percpu=True)))) - # Work around travis failure: - # https://travis-ci.org/giampaolo/psutil/builds/284173194 - for n in all_cpus if not TRAVIS else initial: - p.cpu_affinity([n]) - self.assertEqual(p.cpu_affinity(), [n]) - if hasattr(os, "sched_getaffinity"): - self.assertEqual(p.cpu_affinity(), - list(os.sched_getaffinity(p.pid))) - # also test num_cpu() - if hasattr(p, "num_cpu"): - self.assertEqual(p.cpu_affinity()[0], p.num_cpu()) - - # [] is an alias for "all eligible CPUs"; on Linux this may - # not be equal to all available CPUs, see: - # https://github.com/giampaolo/psutil/issues/956 - p.cpu_affinity([]) - if LINUX: - self.assertEqual(p.cpu_affinity(), p._proc._get_eligible_cpus()) - else: - self.assertEqual(p.cpu_affinity(), all_cpus) - if hasattr(os, "sched_getaffinity"): - self.assertEqual(p.cpu_affinity(), - list(os.sched_getaffinity(p.pid))) - # - self.assertRaises(TypeError, p.cpu_affinity, 1) - p.cpu_affinity(initial) - # it should work with all iterables, not only lists - if not TRAVIS: - p.cpu_affinity(set(all_cpus)) - p.cpu_affinity(tuple(all_cpus)) - - @unittest.skipIf(not HAS_CPU_AFFINITY, 'not supported') - def test_cpu_affinity_errs(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - invalid_cpu = [len(psutil.cpu_times(percpu=True)) + 10] - self.assertRaises(ValueError, p.cpu_affinity, invalid_cpu) - self.assertRaises(ValueError, p.cpu_affinity, range(10000, 11000)) - self.assertRaises(TypeError, p.cpu_affinity, [0, "1"]) - self.assertRaises(ValueError, p.cpu_affinity, [0, -1]) - - @unittest.skipIf(not HAS_CPU_AFFINITY, 'not supported') - def test_cpu_affinity_all_combinations(self): - p = psutil.Process() - initial = p.cpu_affinity() - assert initial, initial - self.addCleanup(p.cpu_affinity, initial) - - # All possible CPU set combinations. - if len(initial) > 12: - initial = initial[:12] # ...otherwise it will take forever - combos = [] - for l in range(0, len(initial) + 1): - for subset in itertools.combinations(initial, l): - if subset: - combos.append(list(subset)) - - for combo in combos: - p.cpu_affinity(combo) - self.assertEqual(p.cpu_affinity(), combo) - - # TODO: #595 - @unittest.skipIf(BSD, "broken on BSD") - # can't find any process file on Appveyor - @unittest.skipIf(APPVEYOR, "unreliable on APPVEYOR") - def test_open_files(self): - # current process - p = psutil.Process() - files = p.open_files() - self.assertFalse(TESTFN in files) - with open(TESTFN, 'wb') as f: - f.write(b'x' * 1024) - f.flush() - # give the kernel some time to see the new file - files = call_until(p.open_files, "len(ret) != %i" % len(files)) - filenames = [os.path.normcase(x.path) for x in files] - self.assertIn(os.path.normcase(TESTFN), filenames) - if LINUX: - for file in files: - if file.path == TESTFN: - self.assertEqual(file.position, 1024) - for file in files: - assert os.path.isfile(file.path), file - - # another process - cmdline = "import time; f = open(r'%s', 'r'); time.sleep(60);" % TESTFN - sproc = get_test_subprocess([PYTHON_EXE, "-c", cmdline]) - p = psutil.Process(sproc.pid) - - for x in range(100): - filenames = [os.path.normcase(x.path) for x in p.open_files()] - if TESTFN in filenames: - break - time.sleep(.01) - else: - self.assertIn(os.path.normcase(TESTFN), filenames) - for file in filenames: - assert os.path.isfile(file), file - - # TODO: #595 - @unittest.skipIf(BSD, "broken on BSD") - # can't find any process file on Appveyor - @unittest.skipIf(APPVEYOR, "unreliable on APPVEYOR") - def test_open_files_2(self): - # test fd and path fields - normcase = os.path.normcase - with open(TESTFN, 'w') as fileobj: - p = psutil.Process() - for file in p.open_files(): - if normcase(file.path) == normcase(fileobj.name) or \ - file.fd == fileobj.fileno(): - break - else: - self.fail("no file found; files=%s" % repr(p.open_files())) - self.assertEqual(normcase(file.path), normcase(fileobj.name)) - if WINDOWS: - self.assertEqual(file.fd, -1) - else: - self.assertEqual(file.fd, fileobj.fileno()) - # test positions - ntuple = p.open_files()[0] - self.assertEqual(ntuple[0], ntuple.path) - self.assertEqual(ntuple[1], ntuple.fd) - # test file is gone - self.assertNotIn(fileobj.name, p.open_files()) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_num_fds(self): - p = psutil.Process() - start = p.num_fds() - file = open(TESTFN, 'w') - self.addCleanup(file.close) - self.assertEqual(p.num_fds(), start + 1) - sock = socket.socket() - self.addCleanup(sock.close) - self.assertEqual(p.num_fds(), start + 2) - file.close() - sock.close() - self.assertEqual(p.num_fds(), start) - - @skip_on_not_implemented(only_if=LINUX) - @unittest.skipIf(OPENBSD or NETBSD, "not reliable on OPENBSD & NETBSD") - def test_num_ctx_switches(self): - p = psutil.Process() - before = sum(p.num_ctx_switches()) - for x in range(500000): - after = sum(p.num_ctx_switches()) - if after > before: - return - self.fail("num ctx switches still the same after 50.000 iterations") - - def test_ppid(self): - if hasattr(os, 'getppid'): - self.assertEqual(psutil.Process().ppid(), os.getppid()) - this_parent = os.getpid() - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - self.assertEqual(p.ppid(), this_parent) - # no other process is supposed to have us as parent - reap_children(recursive=True) - if APPVEYOR: - # Occasional failures, see: - # https://ci.appveyor.com/project/giampaolo/psutil/build/ - # job/0hs623nenj7w4m33 - return - for p in psutil.process_iter(): - if p.pid == sproc.pid: - continue - # XXX: sometimes this fails on Windows; not sure why. - self.assertNotEqual(p.ppid(), this_parent, msg=p) - - def test_parent(self): - this_parent = os.getpid() - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - self.assertEqual(p.parent().pid, this_parent) - - lowest_pid = psutil.pids()[0] - self.assertIsNone(psutil.Process(lowest_pid).parent()) - - def test_parent_multi(self): - p1, p2 = create_proc_children_pair() - self.assertEqual(p2.parent(), p1) - self.assertEqual(p1.parent(), psutil.Process()) - - def test_parent_disappeared(self): - # Emulate a case where the parent process disappeared. - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - with mock.patch("psutil.Process", - side_effect=psutil.NoSuchProcess(0, 'foo')): - self.assertIsNone(p.parent()) - - @retry_on_failure() - def test_parents(self): - assert psutil.Process().parents() - p1, p2 = create_proc_children_pair() - self.assertEqual(p1.parents()[0], psutil.Process()) - self.assertEqual(p2.parents()[0], p1) - self.assertEqual(p2.parents()[1], psutil.Process()) - - def test_children(self): - reap_children(recursive=True) - p = psutil.Process() - self.assertEqual(p.children(), []) - self.assertEqual(p.children(recursive=True), []) - # On Windows we set the flag to 0 in order to cancel out the - # CREATE_NO_WINDOW flag (enabled by default) which creates - # an extra "conhost.exe" child. - sproc = get_test_subprocess(creationflags=0) - children1 = p.children() - children2 = p.children(recursive=True) - for children in (children1, children2): - self.assertEqual(len(children), 1) - self.assertEqual(children[0].pid, sproc.pid) - self.assertEqual(children[0].ppid(), os.getpid()) - - def test_children_recursive(self): - # Test children() against two sub processes, p1 and p2, where - # p1 (our child) spawned p2 (our grandchild). - p1, p2 = create_proc_children_pair() - p = psutil.Process() - self.assertEqual(p.children(), [p1]) - self.assertEqual(p.children(recursive=True), [p1, p2]) - # If the intermediate process is gone there's no way for - # children() to recursively find it. - p1.terminate() - p1.wait() - self.assertEqual(p.children(recursive=True), []) - - def test_children_duplicates(self): - # find the process which has the highest number of children - table = collections.defaultdict(int) - for p in psutil.process_iter(): - try: - table[p.ppid()] += 1 - except psutil.Error: - pass - # this is the one, now let's make sure there are no duplicates - pid = sorted(table.items(), key=lambda x: x[1])[-1][0] - p = psutil.Process(pid) - try: - c = p.children(recursive=True) - except psutil.AccessDenied: # windows - pass - else: - self.assertEqual(len(c), len(set(c))) - - def test_parents_and_children(self): - p1, p2 = create_proc_children_pair() - me = psutil.Process() - # forward - children = me.children(recursive=True) - self.assertEqual(len(children), 2) - self.assertEqual(children[0], p1) - self.assertEqual(children[1], p2) - # backward - parents = p2.parents() - self.assertEqual(parents[0], p1) - self.assertEqual(parents[1], me) - - def test_suspend_resume(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.suspend() - for x in range(100): - if p.status() == psutil.STATUS_STOPPED: - break - time.sleep(0.01) - p.resume() - self.assertNotEqual(p.status(), psutil.STATUS_STOPPED) - - def test_invalid_pid(self): - self.assertRaises(TypeError, psutil.Process, "1") - self.assertRaises(ValueError, psutil.Process, -1) - - def test_as_dict(self): - p = psutil.Process() - d = p.as_dict(attrs=['exe', 'name']) - self.assertEqual(sorted(d.keys()), ['exe', 'name']) - - p = psutil.Process(min(psutil.pids())) - d = p.as_dict(attrs=['connections'], ad_value='foo') - if not isinstance(d['connections'], list): - self.assertEqual(d['connections'], 'foo') - - # Test ad_value is set on AccessDenied. - with mock.patch('psutil.Process.nice', create=True, - side_effect=psutil.AccessDenied): - self.assertEqual( - p.as_dict(attrs=["nice"], ad_value=1), {"nice": 1}) - - # Test that NoSuchProcess bubbles up. - with mock.patch('psutil.Process.nice', create=True, - side_effect=psutil.NoSuchProcess(p.pid, "name")): - self.assertRaises( - psutil.NoSuchProcess, p.as_dict, attrs=["nice"]) - - # Test that ZombieProcess is swallowed. - with mock.patch('psutil.Process.nice', create=True, - side_effect=psutil.ZombieProcess(p.pid, "name")): - self.assertEqual( - p.as_dict(attrs=["nice"], ad_value="foo"), {"nice": "foo"}) - - # By default APIs raising NotImplementedError are - # supposed to be skipped. - with mock.patch('psutil.Process.nice', create=True, - side_effect=NotImplementedError): - d = p.as_dict() - self.assertNotIn('nice', list(d.keys())) - # ...unless the user explicitly asked for some attr. - with self.assertRaises(NotImplementedError): - p.as_dict(attrs=["nice"]) - - # errors - with self.assertRaises(TypeError): - p.as_dict('name') - with self.assertRaises(ValueError): - p.as_dict(['foo']) - with self.assertRaises(ValueError): - p.as_dict(['foo', 'bar']) - - def test_oneshot(self): - with mock.patch("psutil._psplatform.Process.cpu_times") as m: - p = psutil.Process() - with p.oneshot(): - p.cpu_times() - p.cpu_times() - self.assertEqual(m.call_count, 1) - - with mock.patch("psutil._psplatform.Process.cpu_times") as m: - p.cpu_times() - p.cpu_times() - self.assertEqual(m.call_count, 2) - - def test_oneshot_twice(self): - # Test the case where the ctx manager is __enter__ed twice. - # The second __enter__ is supposed to resut in a NOOP. - with mock.patch("psutil._psplatform.Process.cpu_times") as m1: - with mock.patch("psutil._psplatform.Process.oneshot_enter") as m2: - p = psutil.Process() - with p.oneshot(): - p.cpu_times() - p.cpu_times() - with p.oneshot(): - p.cpu_times() - p.cpu_times() - self.assertEqual(m1.call_count, 1) - self.assertEqual(m2.call_count, 1) - - with mock.patch("psutil._psplatform.Process.cpu_times") as m: - p.cpu_times() - p.cpu_times() - self.assertEqual(m.call_count, 2) - - def test_oneshot_cache(self): - # Make sure oneshot() cache is nonglobal. Instead it's - # supposed to be bound to the Process instance, see: - # https://github.com/giampaolo/psutil/issues/1373 - p1, p2 = create_proc_children_pair() - p1_ppid = p1.ppid() - p2_ppid = p2.ppid() - self.assertNotEqual(p1_ppid, p2_ppid) - with p1.oneshot(): - self.assertEqual(p1.ppid(), p1_ppid) - self.assertEqual(p2.ppid(), p2_ppid) - with p2.oneshot(): - self.assertEqual(p1.ppid(), p1_ppid) - self.assertEqual(p2.ppid(), p2_ppid) - - def test_halfway_terminated_process(self): - # Test that NoSuchProcess exception gets raised in case the - # process dies after we create the Process object. - # Example: - # >>> proc = Process(1234) - # >>> time.sleep(2) # time-consuming task, process dies in meantime - # >>> proc.name() - # Refers to Issue #15 - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.terminate() - p.wait() - if WINDOWS: - call_until(psutil.pids, "%s not in ret" % p.pid) - assert not p.is_running() - - if WINDOWS: - with self.assertRaises(psutil.NoSuchProcess): - p.send_signal(signal.CTRL_C_EVENT) - with self.assertRaises(psutil.NoSuchProcess): - p.send_signal(signal.CTRL_BREAK_EVENT) - - excluded_names = ['pid', 'is_running', 'wait', 'create_time', - 'oneshot', 'memory_info_ex'] - if LINUX and not HAS_RLIMIT: - excluded_names.append('rlimit') - for name in dir(p): - if (name.startswith('_') or - name in excluded_names): - continue - try: - meth = getattr(p, name) - # get/set methods - if name == 'nice': - if POSIX: - ret = meth(1) - else: - ret = meth(psutil.NORMAL_PRIORITY_CLASS) - elif name == 'ionice': - ret = meth() - ret = meth(2) - elif name == 'rlimit': - ret = meth(psutil.RLIMIT_NOFILE) - ret = meth(psutil.RLIMIT_NOFILE, (5, 5)) - elif name == 'cpu_affinity': - ret = meth() - ret = meth([0]) - elif name == 'send_signal': - ret = meth(signal.SIGTERM) - else: - ret = meth() - except psutil.ZombieProcess: - self.fail("ZombieProcess for %r was not supposed to happen" % - name) - except psutil.NoSuchProcess: - pass - except psutil.AccessDenied: - if OPENBSD and name in ('threads', 'num_threads'): - pass - else: - raise - except NotImplementedError: - pass - else: - # NtQuerySystemInformation succeeds if process is gone. - if WINDOWS and name in ('exe', 'name'): - normcase = os.path.normcase - if name == 'exe': - self.assertEqual(normcase(ret), normcase(PYTHON_EXE)) - else: - self.assertEqual( - normcase(ret), - normcase(os.path.basename(PYTHON_EXE))) - continue - self.fail( - "NoSuchProcess exception not raised for %r, retval=%s" % ( - name, ret)) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_zombie_process(self): - def succeed_or_zombie_p_exc(fun, *args, **kwargs): - try: - return fun(*args, **kwargs) - except (psutil.ZombieProcess, psutil.AccessDenied): - pass - - zpid = create_zombie_proc() - self.addCleanup(reap_children, recursive=True) - # A zombie process should always be instantiable - zproc = psutil.Process(zpid) - # ...and at least its status always be querable - self.assertEqual(zproc.status(), psutil.STATUS_ZOMBIE) - # ...and it should be considered 'running' - self.assertTrue(zproc.is_running()) - # ...and as_dict() shouldn't crash - zproc.as_dict() - # if cmdline succeeds it should be an empty list - ret = succeed_or_zombie_p_exc(zproc.suspend) - if ret is not None: - self.assertEqual(ret, []) - - if hasattr(zproc, "rlimit"): - succeed_or_zombie_p_exc(zproc.rlimit, psutil.RLIMIT_NOFILE) - succeed_or_zombie_p_exc(zproc.rlimit, psutil.RLIMIT_NOFILE, - (5, 5)) - # set methods - succeed_or_zombie_p_exc(zproc.parent) - if hasattr(zproc, 'cpu_affinity'): - try: - succeed_or_zombie_p_exc(zproc.cpu_affinity, [0]) - except ValueError as err: - if TRAVIS and LINUX and "not eligible" in str(err): - # https://travis-ci.org/giampaolo/psutil/jobs/279890461 - pass - else: - raise - - succeed_or_zombie_p_exc(zproc.nice, 0) - if hasattr(zproc, 'ionice'): - if LINUX: - succeed_or_zombie_p_exc(zproc.ionice, 2, 0) - else: - succeed_or_zombie_p_exc(zproc.ionice, 0) # Windows - if hasattr(zproc, 'rlimit'): - succeed_or_zombie_p_exc(zproc.rlimit, - psutil.RLIMIT_NOFILE, (5, 5)) - succeed_or_zombie_p_exc(zproc.suspend) - succeed_or_zombie_p_exc(zproc.resume) - succeed_or_zombie_p_exc(zproc.terminate) - succeed_or_zombie_p_exc(zproc.kill) - - # ...its parent should 'see' it - # edit: not true on BSD and MACOS - # descendants = [x.pid for x in psutil.Process().children( - # recursive=True)] - # self.assertIn(zpid, descendants) - # XXX should we also assume ppid be usable? Note: this - # would be an important use case as the only way to get - # rid of a zombie is to kill its parent. - # self.assertEqual(zpid.ppid(), os.getpid()) - # ...and all other APIs should be able to deal with it - self.assertTrue(psutil.pid_exists(zpid)) - if not TRAVIS and MACOS: - # For some reason this started failing all of the sudden. - # Maybe they upgraded MACOS version? - # https://travis-ci.org/giampaolo/psutil/jobs/310896404 - self.assertIn(zpid, psutil.pids()) - self.assertIn(zpid, [x.pid for x in psutil.process_iter()]) - psutil._pmap = {} - self.assertIn(zpid, [x.pid for x in psutil.process_iter()]) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_zombie_process_is_running_w_exc(self): - # Emulate a case where internally is_running() raises - # ZombieProcess. - p = psutil.Process() - with mock.patch("psutil.Process", - side_effect=psutil.ZombieProcess(0)) as m: - assert p.is_running() - assert m.called - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_zombie_process_status_w_exc(self): - # Emulate a case where internally status() raises - # ZombieProcess. - p = psutil.Process() - with mock.patch("psutil._psplatform.Process.status", - side_effect=psutil.ZombieProcess(0)) as m: - self.assertEqual(p.status(), psutil.STATUS_ZOMBIE) - assert m.called - - def test_pid_0(self): - # Process(0) is supposed to work on all platforms except Linux - if 0 not in psutil.pids(): - self.assertRaises(psutil.NoSuchProcess, psutil.Process, 0) - return - - # test all methods - p = psutil.Process(0) - for name in psutil._as_dict_attrnames: - if name == 'pid': - continue - meth = getattr(p, name) - try: - ret = meth() - except psutil.AccessDenied: - pass - else: - if name in ("uids", "gids"): - self.assertEqual(ret.real, 0) - elif name == "username": - if POSIX: - self.assertEqual(p.username(), 'root') - elif WINDOWS: - self.assertEqual(p.username(), 'NT AUTHORITY\\SYSTEM') - elif name == "name": - assert name, name - - if hasattr(p, 'rlimit'): - try: - p.rlimit(psutil.RLIMIT_FSIZE) - except psutil.AccessDenied: - pass - - p.as_dict() - - if not OPENBSD: - self.assertIn(0, psutil.pids()) - self.assertTrue(psutil.pid_exists(0)) - - @unittest.skipIf(not HAS_ENVIRON, "not supported") - def test_environ(self): - def clean_dict(d): - # Most of these are problematic on Travis. - d.pop("PSUTIL_TESTING", None) - d.pop("PLAT", None) - d.pop("HOME", None) - if MACOS: - d.pop("__CF_USER_TEXT_ENCODING", None) - d.pop("VERSIONER_PYTHON_PREFER_32_BIT", None) - d.pop("VERSIONER_PYTHON_VERSION", None) - return dict( - [(k.replace("\r", "").replace("\n", ""), - v.replace("\r", "").replace("\n", "")) - for k, v in d.items()]) - - self.maxDiff = None - p = psutil.Process() - d1 = clean_dict(p.environ()) - d2 = clean_dict(os.environ.copy()) - self.assertEqual(d1, d2) - - @unittest.skipIf(not HAS_ENVIRON, "not supported") - @unittest.skipIf(not POSIX, "POSIX only") - def test_weird_environ(self): - # environment variables can contain values without an equals sign - code = textwrap.dedent(""" - #include - #include - char * const argv[] = {"cat", 0}; - char * const envp[] = {"A=1", "X", "C=3", 0}; - int main(void) { - /* Close stderr on exec so parent can wait for the execve to - * finish. */ - if (fcntl(2, F_SETFD, FD_CLOEXEC) != 0) - return 0; - return execve("/bin/cat", argv, envp); - } - """) - path = TESTFN - create_exe(path, c_code=code) - self.addCleanup(safe_rmpath, path) - sproc = get_test_subprocess([path], - stdin=subprocess.PIPE, - stderr=subprocess.PIPE) - p = psutil.Process(sproc.pid) - wait_for_pid(p.pid) - self.assertTrue(p.is_running()) - # Wait for process to exec or exit. - self.assertEqual(sproc.stderr.read(), b"") - self.assertEqual(p.environ(), {"A": "1", "C": "3"}) - sproc.communicate() - self.assertEqual(sproc.returncode, 0) - - -# =================================================================== -# --- Limited user tests -# =================================================================== - - -if POSIX and os.getuid() == 0: - class LimitedUserTestCase(TestProcess): - """Repeat the previous tests by using a limited user. - Executed only on UNIX and only if the user who run the test script - is root. - """ - # the uid/gid the test suite runs under - if hasattr(os, 'getuid'): - PROCESS_UID = os.getuid() - PROCESS_GID = os.getgid() - - def __init__(self, *args, **kwargs): - TestProcess.__init__(self, *args, **kwargs) - # re-define all existent test methods in order to - # ignore AccessDenied exceptions - for attr in [x for x in dir(self) if x.startswith('test')]: - meth = getattr(self, attr) - - def test_(self): - try: - meth() - except psutil.AccessDenied: - pass - setattr(self, attr, types.MethodType(test_, self)) - - def setUp(self): - safe_rmpath(TESTFN) - TestProcess.setUp(self) - os.setegid(1000) - os.seteuid(1000) - - def tearDown(self): - os.setegid(self.PROCESS_UID) - os.seteuid(self.PROCESS_GID) - TestProcess.tearDown(self) - - def test_nice(self): - try: - psutil.Process().nice(-1) - except psutil.AccessDenied: - pass - else: - self.fail("exception not raised") - - def test_zombie_process(self): - # causes problems if test test suite is run as root - pass - - -# =================================================================== -# --- psutil.Popen tests -# =================================================================== - - -class TestPopen(unittest.TestCase): - """Tests for psutil.Popen class.""" - - def tearDown(self): - reap_children() - - def test_misc(self): - # XXX this test causes a ResourceWarning on Python 3 because - # psutil.__subproc instance doesn't get propertly freed. - # Not sure what to do though. - cmd = [PYTHON_EXE, "-c", "import time; time.sleep(60);"] - with psutil.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) as proc: - proc.name() - proc.cpu_times() - proc.stdin - self.assertTrue(dir(proc)) - self.assertRaises(AttributeError, getattr, proc, 'foo') - proc.terminate() - - def test_ctx_manager(self): - with psutil.Popen([PYTHON_EXE, "-V"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - stdin=subprocess.PIPE) as proc: - proc.communicate() - assert proc.stdout.closed - assert proc.stderr.closed - assert proc.stdin.closed - self.assertEqual(proc.returncode, 0) - - def test_kill_terminate(self): - # subprocess.Popen()'s terminate(), kill() and send_signal() do - # not raise exception after the process is gone. psutil.Popen - # diverges from that. - cmd = [PYTHON_EXE, "-c", "import time; time.sleep(60);"] - with psutil.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) as proc: - proc.terminate() - proc.wait() - self.assertRaises(psutil.NoSuchProcess, proc.terminate) - self.assertRaises(psutil.NoSuchProcess, proc.kill) - self.assertRaises(psutil.NoSuchProcess, proc.send_signal, - signal.SIGTERM) - if WINDOWS and sys.version_info >= (2, 7): - self.assertRaises(psutil.NoSuchProcess, proc.send_signal, - signal.CTRL_C_EVENT) - self.assertRaises(psutil.NoSuchProcess, proc.send_signal, - signal.CTRL_BREAK_EVENT) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_sunos.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_sunos.py deleted file mode 100644 index e3beb625bf53..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_sunos.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Sun OS specific tests.""" - -import os - -import psutil -from psutil import SUNOS -from psutil.tests import sh -from psutil.tests import unittest - - -@unittest.skipIf(not SUNOS, "SUNOS only") -class SunOSSpecificTestCase(unittest.TestCase): - - def test_swap_memory(self): - out = sh('env PATH=/usr/sbin:/sbin:%s swap -l' % os.environ['PATH']) - lines = out.strip().split('\n')[1:] - if not lines: - raise ValueError('no swap device(s) configured') - total = free = 0 - for line in lines: - line = line.split() - t, f = line[-2:] - total += int(int(t) * 512) - free += int(int(f) * 512) - used = total - free - - psutil_swap = psutil.swap_memory() - self.assertEqual(psutil_swap.total, total) - self.assertEqual(psutil_swap.used, used) - self.assertEqual(psutil_swap.free, free) - - def test_cpu_count(self): - out = sh("/usr/sbin/psrinfo") - self.assertEqual(psutil.cpu_count(), len(out.split('\n'))) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_system.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_system.py deleted file mode 100644 index 3834209fcb36..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_system.py +++ /dev/null @@ -1,904 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Tests for system APIS.""" - -import contextlib -import datetime -import errno -import os -import pprint -import shutil -import signal -import socket -import sys -import tempfile -import time - -import psutil -from psutil import AIX -from psutil import BSD -from psutil import FREEBSD -from psutil import LINUX -from psutil import MACOS -from psutil import NETBSD -from psutil import OPENBSD -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -from psutil._compat import FileNotFoundError -from psutil._compat import long -from psutil.tests import ASCII_FS -from psutil.tests import check_net_address -from psutil.tests import CI_TESTING -from psutil.tests import DEVNULL -from psutil.tests import enum -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_GETLOADAVG -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 -from psutil.tests import mock -from psutil.tests import PYPY -from psutil.tests import reap_children -from psutil.tests import retry_on_failure -from psutil.tests import safe_rmpath -from psutil.tests import TESTFN -from psutil.tests import TESTFN_UNICODE -from psutil.tests import TRAVIS -from psutil.tests import unittest - - -# =================================================================== -# --- System-related API tests -# =================================================================== - - -class TestProcessAPIs(unittest.TestCase): - - def setUp(self): - safe_rmpath(TESTFN) - - def tearDown(self): - reap_children() - - def test_process_iter(self): - self.assertIn(os.getpid(), [x.pid for x in psutil.process_iter()]) - sproc = get_test_subprocess() - self.assertIn(sproc.pid, [x.pid for x in psutil.process_iter()]) - p = psutil.Process(sproc.pid) - p.kill() - p.wait() - self.assertNotIn(sproc.pid, [x.pid for x in psutil.process_iter()]) - - with mock.patch('psutil.Process', - side_effect=psutil.NoSuchProcess(os.getpid())): - self.assertEqual(list(psutil.process_iter()), []) - with mock.patch('psutil.Process', - side_effect=psutil.AccessDenied(os.getpid())): - with self.assertRaises(psutil.AccessDenied): - list(psutil.process_iter()) - - def test_prcess_iter_w_attrs(self): - for p in psutil.process_iter(attrs=['pid']): - self.assertEqual(list(p.info.keys()), ['pid']) - with self.assertRaises(ValueError): - list(psutil.process_iter(attrs=['foo'])) - with mock.patch("psutil._psplatform.Process.cpu_times", - side_effect=psutil.AccessDenied(0, "")) as m: - for p in psutil.process_iter(attrs=["pid", "cpu_times"]): - self.assertIsNone(p.info['cpu_times']) - self.assertGreaterEqual(p.info['pid'], 0) - assert m.called - with mock.patch("psutil._psplatform.Process.cpu_times", - side_effect=psutil.AccessDenied(0, "")) as m: - flag = object() - for p in psutil.process_iter( - attrs=["pid", "cpu_times"], ad_value=flag): - self.assertIs(p.info['cpu_times'], flag) - self.assertGreaterEqual(p.info['pid'], 0) - assert m.called - - @unittest.skipIf(PYPY and WINDOWS, - "get_test_subprocess() unreliable on PYPY + WINDOWS") - def test_wait_procs(self): - def callback(p): - pids.append(p.pid) - - pids = [] - sproc1 = get_test_subprocess() - sproc2 = get_test_subprocess() - sproc3 = get_test_subprocess() - procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)] - self.assertRaises(ValueError, psutil.wait_procs, procs, timeout=-1) - self.assertRaises(TypeError, psutil.wait_procs, procs, callback=1) - t = time.time() - gone, alive = psutil.wait_procs(procs, timeout=0.01, callback=callback) - - self.assertLess(time.time() - t, 0.5) - self.assertEqual(gone, []) - self.assertEqual(len(alive), 3) - self.assertEqual(pids, []) - for p in alive: - self.assertFalse(hasattr(p, 'returncode')) - - @retry_on_failure(30) - def test(procs, callback): - gone, alive = psutil.wait_procs(procs, timeout=0.03, - callback=callback) - self.assertEqual(len(gone), 1) - self.assertEqual(len(alive), 2) - return gone, alive - - sproc3.terminate() - gone, alive = test(procs, callback) - self.assertIn(sproc3.pid, [x.pid for x in gone]) - if POSIX: - self.assertEqual(gone.pop().returncode, -signal.SIGTERM) - else: - self.assertEqual(gone.pop().returncode, 1) - self.assertEqual(pids, [sproc3.pid]) - for p in alive: - self.assertFalse(hasattr(p, 'returncode')) - - @retry_on_failure(30) - def test(procs, callback): - gone, alive = psutil.wait_procs(procs, timeout=0.03, - callback=callback) - self.assertEqual(len(gone), 3) - self.assertEqual(len(alive), 0) - return gone, alive - - sproc1.terminate() - sproc2.terminate() - gone, alive = test(procs, callback) - self.assertEqual(set(pids), set([sproc1.pid, sproc2.pid, sproc3.pid])) - for p in gone: - self.assertTrue(hasattr(p, 'returncode')) - - @unittest.skipIf(PYPY and WINDOWS, - "get_test_subprocess() unreliable on PYPY + WINDOWS") - def test_wait_procs_no_timeout(self): - sproc1 = get_test_subprocess() - sproc2 = get_test_subprocess() - sproc3 = get_test_subprocess() - procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)] - for p in procs: - p.terminate() - gone, alive = psutil.wait_procs(procs) - - def test_pid_exists(self): - sproc = get_test_subprocess() - self.assertTrue(psutil.pid_exists(sproc.pid)) - p = psutil.Process(sproc.pid) - p.kill() - p.wait() - self.assertFalse(psutil.pid_exists(sproc.pid)) - self.assertFalse(psutil.pid_exists(-1)) - self.assertEqual(psutil.pid_exists(0), 0 in psutil.pids()) - - def test_pid_exists_2(self): - reap_children() - pids = psutil.pids() - for pid in pids: - try: - assert psutil.pid_exists(pid) - except AssertionError: - # in case the process disappeared in meantime fail only - # if it is no longer in psutil.pids() - time.sleep(.1) - if pid in psutil.pids(): - self.fail(pid) - pids = range(max(pids) + 5000, max(pids) + 6000) - for pid in pids: - self.assertFalse(psutil.pid_exists(pid), msg=pid) - - def test_pids(self): - pidslist = psutil.pids() - procslist = [x.pid for x in psutil.process_iter()] - # make sure every pid is unique - self.assertEqual(sorted(set(pidslist)), pidslist) - self.assertEqual(pidslist, procslist) - - -class TestMiscAPIs(unittest.TestCase): - - def test_boot_time(self): - bt = psutil.boot_time() - self.assertIsInstance(bt, float) - self.assertGreater(bt, 0) - self.assertLess(bt, time.time()) - - @unittest.skipIf(CI_TESTING and not psutil.users(), "unreliable on CI") - def test_users(self): - users = psutil.users() - self.assertNotEqual(users, []) - for user in users: - assert user.name, user - self.assertIsInstance(user.name, str) - self.assertIsInstance(user.terminal, (str, type(None))) - if user.host is not None: - self.assertIsInstance(user.host, (str, type(None))) - user.terminal - user.host - assert user.started > 0.0, user - datetime.datetime.fromtimestamp(user.started) - if WINDOWS or OPENBSD: - self.assertIsNone(user.pid) - else: - psutil.Process(user.pid) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_PAGESIZE(self): - # pagesize is used internally to perform different calculations - # and it's determined by using SC_PAGE_SIZE; make sure - # getpagesize() returns the same value. - import resource - self.assertEqual(os.sysconf("SC_PAGE_SIZE"), resource.getpagesize()) - - def test_test(self): - # test for psutil.test() function - stdout = sys.stdout - sys.stdout = DEVNULL - try: - psutil.test() - finally: - sys.stdout = stdout - - def test_os_constants(self): - names = ["POSIX", "WINDOWS", "LINUX", "MACOS", "FREEBSD", "OPENBSD", - "NETBSD", "BSD", "SUNOS"] - for name in names: - self.assertIsInstance(getattr(psutil, name), bool, msg=name) - - if os.name == 'posix': - assert psutil.POSIX - assert not psutil.WINDOWS - names.remove("POSIX") - if "linux" in sys.platform.lower(): - assert psutil.LINUX - names.remove("LINUX") - elif "bsd" in sys.platform.lower(): - assert psutil.BSD - self.assertEqual([psutil.FREEBSD, psutil.OPENBSD, - psutil.NETBSD].count(True), 1) - names.remove("BSD") - names.remove("FREEBSD") - names.remove("OPENBSD") - names.remove("NETBSD") - elif "sunos" in sys.platform.lower() or \ - "solaris" in sys.platform.lower(): - assert psutil.SUNOS - names.remove("SUNOS") - elif "darwin" in sys.platform.lower(): - assert psutil.MACOS - names.remove("MACOS") - else: - assert psutil.WINDOWS - assert not psutil.POSIX - names.remove("WINDOWS") - - # assert all other constants are set to False - for name in names: - self.assertIs(getattr(psutil, name), False, msg=name) - - -class TestMemoryAPIs(unittest.TestCase): - - def test_virtual_memory(self): - mem = psutil.virtual_memory() - assert mem.total > 0, mem - assert mem.available > 0, mem - assert 0 <= mem.percent <= 100, mem - assert mem.used > 0, mem - assert mem.free >= 0, mem - for name in mem._fields: - value = getattr(mem, name) - if name != 'percent': - self.assertIsInstance(value, (int, long)) - if name != 'total': - if not value >= 0: - self.fail("%r < 0 (%s)" % (name, value)) - if value > mem.total: - self.fail("%r > total (total=%s, %s=%s)" - % (name, mem.total, name, value)) - - def test_swap_memory(self): - mem = psutil.swap_memory() - self.assertEqual( - mem._fields, ('total', 'used', 'free', 'percent', 'sin', 'sout')) - - assert mem.total >= 0, mem - assert mem.used >= 0, mem - if mem.total > 0: - # likely a system with no swap partition - assert mem.free > 0, mem - else: - assert mem.free == 0, mem - assert 0 <= mem.percent <= 100, mem - assert mem.sin >= 0, mem - assert mem.sout >= 0, mem - - -class TestCpuAPIs(unittest.TestCase): - - def test_cpu_count_logical(self): - logical = psutil.cpu_count() - self.assertIsNotNone(logical) - self.assertEqual(logical, len(psutil.cpu_times(percpu=True))) - self.assertGreaterEqual(logical, 1) - # - if os.path.exists("/proc/cpuinfo"): - with open("/proc/cpuinfo") as fd: - cpuinfo_data = fd.read() - if "physical id" not in cpuinfo_data: - raise unittest.SkipTest("cpuinfo doesn't include physical id") - - def test_cpu_count_physical(self): - logical = psutil.cpu_count() - physical = psutil.cpu_count(logical=False) - if physical is None: - raise self.skipTest("physical cpu_count() is None") - if WINDOWS and sys.getwindowsversion()[:2] <= (6, 1): # <= Vista - self.assertIsNone(physical) - else: - self.assertGreaterEqual(physical, 1) - self.assertGreaterEqual(logical, physical) - - def test_cpu_count_none(self): - # https://github.com/giampaolo/psutil/issues/1085 - for val in (-1, 0, None): - with mock.patch('psutil._psplatform.cpu_count_logical', - return_value=val) as m: - self.assertIsNone(psutil.cpu_count()) - assert m.called - with mock.patch('psutil._psplatform.cpu_count_physical', - return_value=val) as m: - self.assertIsNone(psutil.cpu_count(logical=False)) - assert m.called - - def test_cpu_times(self): - # Check type, value >= 0, str(). - total = 0 - times = psutil.cpu_times() - sum(times) - for cp_time in times: - self.assertIsInstance(cp_time, float) - self.assertGreaterEqual(cp_time, 0.0) - total += cp_time - self.assertEqual(total, sum(times)) - str(times) - # CPU times are always supposed to increase over time - # or at least remain the same and that's because time - # cannot go backwards. - # Surprisingly sometimes this might not be the case (at - # least on Windows and Linux), see: - # https://github.com/giampaolo/psutil/issues/392 - # https://github.com/giampaolo/psutil/issues/645 - # if not WINDOWS: - # last = psutil.cpu_times() - # for x in range(100): - # new = psutil.cpu_times() - # for field in new._fields: - # new_t = getattr(new, field) - # last_t = getattr(last, field) - # self.assertGreaterEqual(new_t, last_t, - # msg="%s %s" % (new_t, last_t)) - # last = new - - def test_cpu_times_time_increases(self): - # Make sure time increases between calls. - t1 = sum(psutil.cpu_times()) - stop_at = time.time() + 1 - while time.time() < stop_at: - t2 = sum(psutil.cpu_times()) - if t2 > t1: - return - self.fail("time remained the same") - - def test_per_cpu_times(self): - # Check type, value >= 0, str(). - for times in psutil.cpu_times(percpu=True): - total = 0 - sum(times) - for cp_time in times: - self.assertIsInstance(cp_time, float) - self.assertGreaterEqual(cp_time, 0.0) - total += cp_time - self.assertEqual(total, sum(times)) - str(times) - self.assertEqual(len(psutil.cpu_times(percpu=True)[0]), - len(psutil.cpu_times(percpu=False))) - - # Note: in theory CPU times are always supposed to increase over - # time or remain the same but never go backwards. In practice - # sometimes this is not the case. - # This issue seemd to be afflict Windows: - # https://github.com/giampaolo/psutil/issues/392 - # ...but it turns out also Linux (rarely) behaves the same. - # last = psutil.cpu_times(percpu=True) - # for x in range(100): - # new = psutil.cpu_times(percpu=True) - # for index in range(len(new)): - # newcpu = new[index] - # lastcpu = last[index] - # for field in newcpu._fields: - # new_t = getattr(newcpu, field) - # last_t = getattr(lastcpu, field) - # self.assertGreaterEqual( - # new_t, last_t, msg="%s %s" % (lastcpu, newcpu)) - # last = new - - def test_per_cpu_times_2(self): - # Simulate some work load then make sure time have increased - # between calls. - tot1 = psutil.cpu_times(percpu=True) - giveup_at = time.time() + 1 - while True: - if time.time() >= giveup_at: - return self.fail("timeout") - tot2 = psutil.cpu_times(percpu=True) - for t1, t2 in zip(tot1, tot2): - t1, t2 = psutil._cpu_busy_time(t1), psutil._cpu_busy_time(t2) - difference = t2 - t1 - if difference >= 0.05: - return - - def test_cpu_times_comparison(self): - # Make sure the sum of all per cpu times is almost equal to - # base "one cpu" times. - base = psutil.cpu_times() - per_cpu = psutil.cpu_times(percpu=True) - summed_values = base._make([sum(num) for num in zip(*per_cpu)]) - for field in base._fields: - self.assertAlmostEqual( - getattr(base, field), getattr(summed_values, field), delta=1) - - def _test_cpu_percent(self, percent, last_ret, new_ret): - try: - self.assertIsInstance(percent, float) - self.assertGreaterEqual(percent, 0.0) - self.assertIsNot(percent, -0.0) - self.assertLessEqual(percent, 100.0 * psutil.cpu_count()) - except AssertionError as err: - raise AssertionError("\n%s\nlast=%s\nnew=%s" % ( - err, pprint.pformat(last_ret), pprint.pformat(new_ret))) - - def test_cpu_percent(self): - last = psutil.cpu_percent(interval=0.001) - for x in range(100): - new = psutil.cpu_percent(interval=None) - self._test_cpu_percent(new, last, new) - last = new - with self.assertRaises(ValueError): - psutil.cpu_percent(interval=-1) - - def test_per_cpu_percent(self): - last = psutil.cpu_percent(interval=0.001, percpu=True) - self.assertEqual(len(last), psutil.cpu_count()) - for x in range(100): - new = psutil.cpu_percent(interval=None, percpu=True) - for percent in new: - self._test_cpu_percent(percent, last, new) - last = new - with self.assertRaises(ValueError): - psutil.cpu_percent(interval=-1, percpu=True) - - def test_cpu_times_percent(self): - last = psutil.cpu_times_percent(interval=0.001) - for x in range(100): - new = psutil.cpu_times_percent(interval=None) - for percent in new: - self._test_cpu_percent(percent, last, new) - self._test_cpu_percent(sum(new), last, new) - last = new - - def test_per_cpu_times_percent(self): - last = psutil.cpu_times_percent(interval=0.001, percpu=True) - self.assertEqual(len(last), psutil.cpu_count()) - for x in range(100): - new = psutil.cpu_times_percent(interval=None, percpu=True) - for cpu in new: - for percent in cpu: - self._test_cpu_percent(percent, last, new) - self._test_cpu_percent(sum(cpu), last, new) - last = new - - def test_per_cpu_times_percent_negative(self): - # see: https://github.com/giampaolo/psutil/issues/645 - psutil.cpu_times_percent(percpu=True) - zero_times = [x._make([0 for x in range(len(x._fields))]) - for x in psutil.cpu_times(percpu=True)] - with mock.patch('psutil.cpu_times', return_value=zero_times): - for cpu in psutil.cpu_times_percent(percpu=True): - for percent in cpu: - self._test_cpu_percent(percent, None, None) - - def test_cpu_stats(self): - # Tested more extensively in per-platform test modules. - infos = psutil.cpu_stats() - self.assertEqual( - infos._fields, - ('ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls')) - for name in infos._fields: - value = getattr(infos, name) - self.assertGreaterEqual(value, 0) - # on AIX, ctx_switches is always 0 - if not AIX and name in ('ctx_switches', 'interrupts'): - self.assertGreater(value, 0) - - @unittest.skipIf(not HAS_CPU_FREQ, "not suported") - def test_cpu_freq(self): - def check_ls(ls): - for nt in ls: - self.assertEqual(nt._fields, ('current', 'min', 'max')) - if nt.max != 0.0: - self.assertLessEqual(nt.current, nt.max) - for name in nt._fields: - value = getattr(nt, name) - self.assertIsInstance(value, (int, long, float)) - self.assertGreaterEqual(value, 0) - - ls = psutil.cpu_freq(percpu=True) - if TRAVIS and not ls: - raise self.skipTest("skipped on Travis") - if FREEBSD and not ls: - raise self.skipTest("returns empty list on FreeBSD") - - assert ls, ls - check_ls([psutil.cpu_freq(percpu=False)]) - - if LINUX: - self.assertEqual(len(ls), psutil.cpu_count()) - - @unittest.skipIf(not HAS_GETLOADAVG, "not supported") - def test_getloadavg(self): - loadavg = psutil.getloadavg() - assert len(loadavg) == 3 - - for load in loadavg: - self.assertIsInstance(load, float) - self.assertGreaterEqual(load, 0.0) - - -class TestDiskAPIs(unittest.TestCase): - - def test_disk_usage(self): - usage = psutil.disk_usage(os.getcwd()) - self.assertEqual(usage._fields, ('total', 'used', 'free', 'percent')) - - assert usage.total > 0, usage - assert usage.used > 0, usage - assert usage.free > 0, usage - assert usage.total > usage.used, usage - assert usage.total > usage.free, usage - assert 0 <= usage.percent <= 100, usage.percent - if hasattr(shutil, 'disk_usage'): - # py >= 3.3, see: http://bugs.python.org/issue12442 - shutil_usage = shutil.disk_usage(os.getcwd()) - tolerance = 5 * 1024 * 1024 # 5MB - self.assertEqual(usage.total, shutil_usage.total) - self.assertAlmostEqual(usage.free, shutil_usage.free, - delta=tolerance) - self.assertAlmostEqual(usage.used, shutil_usage.used, - delta=tolerance) - - # if path does not exist OSError ENOENT is expected across - # all platforms - fname = tempfile.mktemp() - with self.assertRaises(FileNotFoundError): - psutil.disk_usage(fname) - - def test_disk_usage_unicode(self): - # See: https://github.com/giampaolo/psutil/issues/416 - if ASCII_FS: - with self.assertRaises(UnicodeEncodeError): - psutil.disk_usage(TESTFN_UNICODE) - - def test_disk_usage_bytes(self): - psutil.disk_usage(b'.') - - def test_disk_partitions(self): - # all = False - ls = psutil.disk_partitions(all=False) - # on travis we get: - # self.assertEqual(p.cpu_affinity(), [n]) - # AssertionError: Lists differ: [0, 1, 2, 3, 4, 5, 6, 7,... != [0] - self.assertTrue(ls, msg=ls) - for disk in ls: - self.assertIsInstance(disk.device, str) - self.assertIsInstance(disk.mountpoint, str) - self.assertIsInstance(disk.fstype, str) - self.assertIsInstance(disk.opts, str) - if WINDOWS and 'cdrom' in disk.opts: - continue - if not POSIX: - assert os.path.exists(disk.device), disk - else: - # we cannot make any assumption about this, see: - # http://goo.gl/p9c43 - disk.device - # on modern systems mount points can also be files - assert os.path.exists(disk.mountpoint), disk - assert disk.fstype, disk - - # all = True - ls = psutil.disk_partitions(all=True) - self.assertTrue(ls, msg=ls) - for disk in psutil.disk_partitions(all=True): - if not WINDOWS and disk.mountpoint: - try: - os.stat(disk.mountpoint) - except OSError as err: - if TRAVIS and MACOS and err.errno == errno.EIO: - continue - # http://mail.python.org/pipermail/python-dev/ - # 2012-June/120787.html - if err.errno not in (errno.EPERM, errno.EACCES): - raise - else: - assert os.path.exists(disk.mountpoint), disk - self.assertIsInstance(disk.fstype, str) - self.assertIsInstance(disk.opts, str) - - def find_mount_point(path): - path = os.path.abspath(path) - while not os.path.ismount(path): - path = os.path.dirname(path) - return path.lower() - - mount = find_mount_point(__file__) - mounts = [x.mountpoint.lower() for x in - psutil.disk_partitions(all=True) if x.mountpoint] - self.assertIn(mount, mounts) - psutil.disk_usage(mount) - - @unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'), - '/proc/diskstats not available on this linux version') - @unittest.skipIf(CI_TESTING and not psutil.disk_io_counters(), - "unreliable on CI") # no visible disks - def test_disk_io_counters(self): - def check_ntuple(nt): - self.assertEqual(nt[0], nt.read_count) - self.assertEqual(nt[1], nt.write_count) - self.assertEqual(nt[2], nt.read_bytes) - self.assertEqual(nt[3], nt.write_bytes) - if not (OPENBSD or NETBSD): - self.assertEqual(nt[4], nt.read_time) - self.assertEqual(nt[5], nt.write_time) - if LINUX: - self.assertEqual(nt[6], nt.read_merged_count) - self.assertEqual(nt[7], nt.write_merged_count) - self.assertEqual(nt[8], nt.busy_time) - elif FREEBSD: - self.assertEqual(nt[6], nt.busy_time) - for name in nt._fields: - assert getattr(nt, name) >= 0, nt - - ret = psutil.disk_io_counters(perdisk=False) - assert ret is not None, "no disks on this system?" - check_ntuple(ret) - ret = psutil.disk_io_counters(perdisk=True) - # make sure there are no duplicates - self.assertEqual(len(ret), len(set(ret))) - for key in ret: - assert key, key - check_ntuple(ret[key]) - - def test_disk_io_counters_no_disks(self): - # Emulate a case where no disks are installed, see: - # https://github.com/giampaolo/psutil/issues/1062 - with mock.patch('psutil._psplatform.disk_io_counters', - return_value={}) as m: - self.assertIsNone(psutil.disk_io_counters(perdisk=False)) - self.assertEqual(psutil.disk_io_counters(perdisk=True), {}) - assert m.called - - -class TestNetAPIs(unittest.TestCase): - - @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) - self.assertEqual(nt[1], nt.bytes_recv) - self.assertEqual(nt[2], nt.packets_sent) - self.assertEqual(nt[3], nt.packets_recv) - self.assertEqual(nt[4], nt.errin) - self.assertEqual(nt[5], nt.errout) - self.assertEqual(nt[6], nt.dropin) - self.assertEqual(nt[7], nt.dropout) - assert nt.bytes_sent >= 0, nt - assert nt.bytes_recv >= 0, nt - assert nt.packets_sent >= 0, nt - assert nt.packets_recv >= 0, nt - assert nt.errin >= 0, nt - assert nt.errout >= 0, nt - assert nt.dropin >= 0, nt - assert nt.dropout >= 0, nt - - ret = psutil.net_io_counters(pernic=False) - check_ntuple(ret) - ret = psutil.net_io_counters(pernic=True) - self.assertNotEqual(ret, []) - for key in ret: - self.assertTrue(key) - 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 - with mock.patch('psutil._psplatform.net_io_counters', - return_value={}) as m: - self.assertIsNone(psutil.net_io_counters(pernic=False)) - self.assertEqual(psutil.net_io_counters(pernic=True), {}) - assert m.called - - def test_net_if_addrs(self): - nics = psutil.net_if_addrs() - assert nics, nics - - nic_stats = psutil.net_if_stats() - - # Not reliable on all platforms (net_if_addrs() reports more - # interfaces). - # self.assertEqual(sorted(nics.keys()), - # sorted(psutil.net_io_counters(pernic=True).keys())) - - families = set([socket.AF_INET, socket.AF_INET6, psutil.AF_LINK]) - for nic, addrs in nics.items(): - self.assertIsInstance(nic, str) - self.assertEqual(len(set(addrs)), len(addrs)) - for addr in addrs: - self.assertIsInstance(addr.family, int) - self.assertIsInstance(addr.address, str) - self.assertIsInstance(addr.netmask, (str, type(None))) - self.assertIsInstance(addr.broadcast, (str, type(None))) - self.assertIn(addr.family, families) - if sys.version_info >= (3, 4): - self.assertIsInstance(addr.family, enum.IntEnum) - if nic_stats[nic].isup: - # Do not test binding to addresses of interfaces - # that are down - if addr.family == socket.AF_INET: - s = socket.socket(addr.family) - with contextlib.closing(s): - s.bind((addr.address, 0)) - elif addr.family == socket.AF_INET6: - info = socket.getaddrinfo( - addr.address, 0, socket.AF_INET6, - socket.SOCK_STREAM, 0, socket.AI_PASSIVE)[0] - af, socktype, proto, canonname, sa = info - s = socket.socket(af, socktype, proto) - with contextlib.closing(s): - s.bind(sa) - for ip in (addr.address, addr.netmask, addr.broadcast, - addr.ptp): - if ip is not None: - # TODO: skip AF_INET6 for now because I get: - # AddressValueError: Only hex digits permitted in - # u'c6f3%lxcbr0' in u'fe80::c8e0:fff:fe54:c6f3%lxcbr0' - if addr.family != socket.AF_INET6: - check_net_address(ip, addr.family) - # broadcast and ptp addresses are mutually exclusive - if addr.broadcast: - self.assertIsNone(addr.ptp) - elif addr.ptp: - self.assertIsNone(addr.broadcast) - - if BSD or MACOS or SUNOS: - if hasattr(socket, "AF_LINK"): - self.assertEqual(psutil.AF_LINK, socket.AF_LINK) - elif LINUX: - self.assertEqual(psutil.AF_LINK, socket.AF_PACKET) - elif WINDOWS: - self.assertEqual(psutil.AF_LINK, -1) - - def test_net_if_addrs_mac_null_bytes(self): - # Simulate that the underlying C function returns an incomplete - # MAC address. psutil is supposed to fill it with null bytes. - # https://github.com/giampaolo/psutil/issues/786 - if POSIX: - ret = [('em1', psutil.AF_LINK, '06:3d:29', None, None, None)] - else: - ret = [('em1', -1, '06-3d-29', None, None, None)] - with mock.patch('psutil._psplatform.net_if_addrs', - return_value=ret) as m: - addr = psutil.net_if_addrs()['em1'][0] - assert m.called - if POSIX: - self.assertEqual(addr.address, '06:3d:29:00:00:00') - else: - self.assertEqual(addr.address, '06-3d-29-00-00-00') - - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") # raises EPERM - def test_net_if_stats(self): - nics = psutil.net_if_stats() - assert nics, nics - all_duplexes = (psutil.NIC_DUPLEX_FULL, - psutil.NIC_DUPLEX_HALF, - psutil.NIC_DUPLEX_UNKNOWN) - for name, stats in nics.items(): - self.assertIsInstance(name, str) - isup, duplex, speed, mtu = stats - self.assertIsInstance(isup, bool) - self.assertIn(duplex, all_duplexes) - self.assertIn(duplex, all_duplexes) - self.assertGreaterEqual(speed, 0) - self.assertGreaterEqual(mtu, 0) - - @unittest.skipIf(not (LINUX or BSD or MACOS), - "LINUX or BSD or MACOS specific") - def test_net_if_stats_enodev(self): - # See: https://github.com/giampaolo/psutil/issues/1279 - with mock.patch('psutil._psutil_posix.net_if_mtu', - side_effect=OSError(errno.ENODEV, "")) as m: - ret = psutil.net_if_stats() - self.assertEqual(ret, {}) - assert m.called - - -class TestSensorsAPIs(unittest.TestCase): - - @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") - def test_sensors_temperatures(self): - temps = psutil.sensors_temperatures() - for name, entries in temps.items(): - self.assertIsInstance(name, str) - for entry in entries: - self.assertIsInstance(entry.label, str) - if entry.current is not None: - self.assertGreaterEqual(entry.current, 0) - if entry.high is not None: - self.assertGreaterEqual(entry.high, 0) - if entry.critical is not None: - self.assertGreaterEqual(entry.critical, 0) - - @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") - def test_sensors_temperatures_fahreneit(self): - d = {'coretemp': [('label', 50.0, 60.0, 70.0)]} - with mock.patch("psutil._psplatform.sensors_temperatures", - return_value=d) as m: - temps = psutil.sensors_temperatures( - fahrenheit=True)['coretemp'][0] - assert m.called - self.assertEqual(temps.current, 122.0) - self.assertEqual(temps.high, 140.0) - self.assertEqual(temps.critical, 158.0) - - @unittest.skipIf(not HAS_SENSORS_BATTERY, "not supported") - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_sensors_battery(self): - ret = psutil.sensors_battery() - self.assertGreaterEqual(ret.percent, 0) - self.assertLessEqual(ret.percent, 100) - if ret.secsleft not in (psutil.POWER_TIME_UNKNOWN, - psutil.POWER_TIME_UNLIMITED): - self.assertGreaterEqual(ret.secsleft, 0) - else: - if ret.secsleft == psutil.POWER_TIME_UNLIMITED: - self.assertTrue(ret.power_plugged) - self.assertIsInstance(ret.power_plugged, bool) - - @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") - def test_sensors_fans(self): - fans = psutil.sensors_fans() - for name, entries in fans.items(): - self.assertIsInstance(name, str) - for entry in entries: - self.assertIsInstance(entry.label, str) - self.assertIsInstance(entry.current, (int, long)) - self.assertGreaterEqual(entry.current, 0) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_unicode.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_unicode.py deleted file mode 100644 index ac2d4f69e0aa..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_unicode.py +++ /dev/null @@ -1,372 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# 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. - -""" -Notes about unicode handling in psutil -====================================== - -Starting from version 5.3.0 psutil adds unicode support, see: -https://github.com/giampaolo/psutil/issues/1040 -The notes below apply to *any* API returning a string such as -process exe(), cwd() or username(): - -* all strings are encoded by using the OS filesystem encoding - (sys.getfilesystemencoding()) which varies depending on the platform - (e.g. "UTF-8" on macOS, "mbcs" on Win) -* no API call is supposed to crash with UnicodeDecodeError -* instead, in case of badly encoded data returned by the OS, the - following error handlers are used to replace the corrupted characters in - the string: - * Python 3: sys.getfilesystemencodeerrors() (PY 3.6+) or - "surrogatescape" on POSIX and "replace" on Windows - * Python 2: "replace" -* on Python 2 all APIs return bytes (str type), never unicode -* on Python 2, you can go back to unicode by doing: - - >>> unicode(p.exe(), sys.getdefaultencoding(), errors="replace") - -For a detailed explanation of how psutil handles unicode see #1040. - -Tests -===== - -List of APIs returning or dealing with a string: -('not tested' means they are not tested to deal with non-ASCII strings): - -* Process.cmdline() -* Process.connections('unix') -* Process.cwd() -* Process.environ() -* Process.exe() -* Process.memory_maps() -* Process.name() -* Process.open_files() -* Process.username() (not tested) - -* disk_io_counters() (not tested) -* disk_partitions() (not tested) -* disk_usage(str) -* net_connections('unix') -* net_if_addrs() (not tested) -* net_if_stats() (not tested) -* net_io_counters() (not tested) -* sensors_fans() (not tested) -* sensors_temperatures() (not tested) -* users() (not tested) - -* WindowsService.binpath() (not tested) -* WindowsService.description() (not tested) -* WindowsService.display_name() (not tested) -* WindowsService.name() (not tested) -* WindowsService.status() (not tested) -* WindowsService.username() (not tested) - -In here we create a unicode path with a funky non-ASCII name and (where -possible) make psutil return it back (e.g. on name(), exe(), open_files(), -etc.) and make sure that: - -* psutil never crashes with UnicodeDecodeError -* the returned path matches -""" - -import os -import traceback -import warnings -from contextlib import closing - -from psutil import BSD -from psutil import MACOS -from psutil import OPENBSD -from psutil import POSIX -from psutil import WINDOWS -from psutil._compat import PY3 -from psutil._compat import u -from psutil.tests import APPVEYOR -from psutil.tests import CIRRUS -from psutil.tests import ASCII_FS -from psutil.tests import bind_unix_socket -from psutil.tests import chdir -from psutil.tests import copyload_shared_lib -from psutil.tests import create_exe -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_CONNECTIONS_UNIX -from psutil.tests import HAS_ENVIRON -from psutil.tests import HAS_MEMORY_MAPS -from psutil.tests import PYPY -from psutil.tests import reap_children -from psutil.tests import safe_mkdir -from psutil.tests import safe_rmpath as _safe_rmpath -from psutil.tests import skip_on_access_denied -from psutil.tests import TESTFILE_PREFIX -from psutil.tests import TESTFN -from psutil.tests import TESTFN_UNICODE -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import unix_socket_path -import psutil - - -def safe_rmpath(path): - if APPVEYOR: - # TODO - this is quite random and I'm not sure why it happens, - # nor I can reproduce it locally: - # https://ci.appveyor.com/project/giampaolo/psutil/build/job/ - # jiq2cgd6stsbtn60 - # safe_rmpath() happens after reap_children() so this is weird - # Perhaps wait_procs() on Windows is broken? Maybe because - # of STILL_ACTIVE? - # https://github.com/giampaolo/psutil/blob/ - # 68c7a70728a31d8b8b58f4be6c4c0baa2f449eda/psutil/arch/ - # windows/process_info.c#L146 - try: - return _safe_rmpath(path) - except WindowsError: - traceback.print_exc() - else: - return _safe_rmpath(path) - - -def subprocess_supports_unicode(name): - """Return True if both the fs and the subprocess module can - deal with a unicode file name. - """ - if PY3: - return True - try: - safe_rmpath(name) - create_exe(name) - get_test_subprocess(cmd=[name]) - except UnicodeEncodeError: - return False - else: - return True - finally: - reap_children() - - -# An invalid unicode string. -if PY3: - INVALID_NAME = (TESTFN.encode('utf8') + b"f\xc0\x80").decode( - 'utf8', 'surrogateescape') -else: - INVALID_NAME = TESTFN + "f\xc0\x80" - - -# =================================================================== -# FS APIs -# =================================================================== - - -class _BaseFSAPIsTests(object): - funky_name = None - - @classmethod - def setUpClass(cls): - safe_rmpath(cls.funky_name) - create_exe(cls.funky_name) - - @classmethod - def tearDownClass(cls): - reap_children() - safe_rmpath(cls.funky_name) - - def tearDown(self): - reap_children() - - def expect_exact_path_match(self): - raise NotImplementedError("must be implemented in subclass") - - def test_proc_exe(self): - subp = get_test_subprocess(cmd=[self.funky_name]) - p = psutil.Process(subp.pid) - exe = p.exe() - self.assertIsInstance(exe, str) - if self.expect_exact_path_match(): - self.assertEqual(os.path.normcase(exe), - os.path.normcase(self.funky_name)) - - def test_proc_name(self): - subp = get_test_subprocess(cmd=[self.funky_name]) - name = psutil.Process(subp.pid).name() - self.assertIsInstance(name, str) - if self.expect_exact_path_match(): - self.assertEqual(name, os.path.basename(self.funky_name)) - - def test_proc_cmdline(self): - subp = get_test_subprocess(cmd=[self.funky_name]) - p = psutil.Process(subp.pid) - cmdline = p.cmdline() - for part in cmdline: - self.assertIsInstance(part, str) - if self.expect_exact_path_match(): - self.assertEqual(cmdline, [self.funky_name]) - - def test_proc_cwd(self): - dname = self.funky_name + "2" - self.addCleanup(safe_rmpath, dname) - safe_mkdir(dname) - with chdir(dname): - p = psutil.Process() - cwd = p.cwd() - self.assertIsInstance(p.cwd(), str) - if self.expect_exact_path_match(): - self.assertEqual(cwd, dname) - - @unittest.skipIf(PYPY and WINDOWS, "fails on PYPY + WINDOWS") - def test_proc_open_files(self): - p = psutil.Process() - start = set(p.open_files()) - with open(self.funky_name, 'rb'): - new = set(p.open_files()) - path = (new - start).pop().path - self.assertIsInstance(path, str) - if BSD and not path: - # XXX - see https://github.com/giampaolo/psutil/issues/595 - return self.skipTest("open_files on BSD is broken") - if self.expect_exact_path_match(): - self.assertEqual(os.path.normcase(path), - os.path.normcase(self.funky_name)) - - @unittest.skipIf(not POSIX, "POSIX only") - def test_proc_connections(self): - suffix = os.path.basename(self.funky_name) - with unix_socket_path(suffix=suffix) as name: - try: - sock = bind_unix_socket(name) - except UnicodeEncodeError: - if PY3: - raise - else: - raise unittest.SkipTest("not supported") - with closing(sock): - conn = psutil.Process().connections('unix')[0] - self.assertIsInstance(conn.laddr, str) - # AF_UNIX addr not set on OpenBSD - if not OPENBSD and not CIRRUS: # XXX - self.assertEqual(conn.laddr, name) - - @unittest.skipIf(not POSIX, "POSIX only") - @unittest.skipIf(not HAS_CONNECTIONS_UNIX, "can't list UNIX sockets") - @skip_on_access_denied() - def test_net_connections(self): - def find_sock(cons): - for conn in cons: - if os.path.basename(conn.laddr).startswith(TESTFILE_PREFIX): - return conn - raise ValueError("connection not found") - - suffix = os.path.basename(self.funky_name) - with unix_socket_path(suffix=suffix) as name: - try: - sock = bind_unix_socket(name) - except UnicodeEncodeError: - if PY3: - raise - else: - raise unittest.SkipTest("not supported") - with closing(sock): - cons = psutil.net_connections(kind='unix') - # AF_UNIX addr not set on OpenBSD - if not OPENBSD: - conn = find_sock(cons) - self.assertIsInstance(conn.laddr, str) - self.assertEqual(conn.laddr, name) - - def test_disk_usage(self): - dname = self.funky_name + "2" - self.addCleanup(safe_rmpath, dname) - safe_mkdir(dname) - psutil.disk_usage(dname) - - @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") - @unittest.skipIf(not PY3, "ctypes does not support unicode on PY2") - @unittest.skipIf(PYPY and WINDOWS, - "copyload_shared_lib() unsupported on PYPY + WINDOWS") - def test_memory_maps(self): - # XXX: on Python 2, using ctypes.CDLL with a unicode path - # opens a message box which blocks the test run. - with copyload_shared_lib(dst_prefix=self.funky_name) as funky_path: - def normpath(p): - return os.path.realpath(os.path.normcase(p)) - libpaths = [normpath(x.path) - for x in psutil.Process().memory_maps()] - # ...just to have a clearer msg in case of failure - libpaths = [x for x in libpaths if TESTFILE_PREFIX in x] - self.assertIn(normpath(funky_path), libpaths) - for path in libpaths: - self.assertIsInstance(path, str) - - -# https://travis-ci.org/giampaolo/psutil/jobs/440073249 -@unittest.skipIf(PYPY and TRAVIS, "unreliable on PYPY + TRAVIS") -@unittest.skipIf(MACOS and TRAVIS, "unreliable on TRAVIS") # TODO -@unittest.skipIf(ASCII_FS, "ASCII fs") -@unittest.skipIf(not subprocess_supports_unicode(TESTFN_UNICODE), - "subprocess can't deal with unicode") -class TestFSAPIs(_BaseFSAPIsTests, unittest.TestCase): - """Test FS APIs with a funky, valid, UTF8 path name.""" - funky_name = TESTFN_UNICODE - - @classmethod - def expect_exact_path_match(cls): - # Do not expect psutil to correctly handle unicode paths on - # Python 2 if os.listdir() is not able either. - here = '.' if isinstance(cls.funky_name, str) else u('.') - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - return cls.funky_name in os.listdir(here) - - -@unittest.skipIf(PYPY and TRAVIS, "unreliable on PYPY + TRAVIS") -@unittest.skipIf(MACOS and TRAVIS, "unreliable on TRAVIS") # TODO -@unittest.skipIf(PYPY, "unreliable on PYPY") -@unittest.skipIf(not subprocess_supports_unicode(INVALID_NAME), - "subprocess can't deal with invalid unicode") -class TestFSAPIsWithInvalidPath(_BaseFSAPIsTests, unittest.TestCase): - """Test FS APIs with a funky, invalid path name.""" - funky_name = INVALID_NAME - - @classmethod - def expect_exact_path_match(cls): - # Invalid unicode names are supposed to work on Python 2. - return True - - -# =================================================================== -# Non fs APIs -# =================================================================== - - -class TestNonFSAPIS(unittest.TestCase): - """Unicode tests for non fs-related APIs.""" - - def tearDown(self): - reap_children() - - @unittest.skipIf(not HAS_ENVIRON, "not supported") - @unittest.skipIf(PYPY and WINDOWS, "segfaults on PYPY + WINDOWS") - def test_proc_environ(self): - # Note: differently from others, this test does not deal - # with fs paths. On Python 2 subprocess module is broken as - # it's not able to handle with non-ASCII env vars, so - # we use "è", which is part of the extended ASCII table - # (unicode point <= 255). - env = os.environ.copy() - funky_str = TESTFN_UNICODE if PY3 else 'è' - env['FUNNY_ARG'] = funky_str - sproc = get_test_subprocess(env=env) - p = psutil.Process(sproc.pid) - env = p.environ() - for k, v in env.items(): - self.assertIsInstance(k, str) - self.assertIsInstance(v, str) - self.assertEqual(env['FUNNY_ARG'], funky_str) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_windows.py b/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_windows.py deleted file mode 100644 index f68885d0ca3d..000000000000 --- a/third_party/python/psutil-cp27-none-win_amd64/psutil/tests/test_windows.py +++ /dev/null @@ -1,870 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -* - -# 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. - -"""Windows specific tests.""" - -import datetime -import errno -import glob -import os -import platform -import re -import signal -import subprocess -import sys -import time -import warnings - -import psutil -from psutil import WINDOWS -from psutil._compat import FileNotFoundError -from psutil.tests import APPVEYOR -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_BATTERY -from psutil.tests import mock -from psutil.tests import PY3 -from psutil.tests import PYPY -from psutil.tests import reap_children -from psutil.tests import retry_on_failure -from psutil.tests import sh -from psutil.tests import unittest - - -if WINDOWS and not PYPY: - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - import win32api # requires "pip install pypiwin32" - import win32con - import win32process - import wmi # requires "pip install wmi" / "make setup-dev-env" - - -cext = psutil._psplatform.cext - -# are we a 64 bit process -IS_64_BIT = sys.maxsize > 2**32 - - -def wrap_exceptions(fun): - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except OSError as err: - from psutil._pswindows import ACCESS_DENIED_SET - if err.errno in ACCESS_DENIED_SET: - raise psutil.AccessDenied(None, None) - if err.errno == errno.ESRCH: - raise psutil.NoSuchProcess(None, None) - raise - return wrapper - - -@unittest.skipIf(PYPY, "pywin32 not available on PYPY") # skip whole module -class TestCase(unittest.TestCase): - pass - - -# =================================================================== -# System APIs -# =================================================================== - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestCpuAPIs(TestCase): - - @unittest.skipIf('NUMBER_OF_PROCESSORS' not in os.environ, - 'NUMBER_OF_PROCESSORS env var is not available') - def test_cpu_count_vs_NUMBER_OF_PROCESSORS(self): - # Will likely fail on many-cores systems: - # https://stackoverflow.com/questions/31209256 - num_cpus = int(os.environ['NUMBER_OF_PROCESSORS']) - self.assertEqual(num_cpus, psutil.cpu_count()) - - def test_cpu_count_vs_GetSystemInfo(self): - # Will likely fail on many-cores systems: - # https://stackoverflow.com/questions/31209256 - sys_value = win32api.GetSystemInfo()[5] - psutil_value = psutil.cpu_count() - self.assertEqual(sys_value, psutil_value) - - def test_cpu_count_logical_vs_wmi(self): - w = wmi.WMI() - proc = w.Win32_Processor()[0] - self.assertEqual(psutil.cpu_count(), proc.NumberOfLogicalProcessors) - - def test_cpu_count_phys_vs_wmi(self): - w = wmi.WMI() - proc = w.Win32_Processor()[0] - self.assertEqual(psutil.cpu_count(logical=False), proc.NumberOfCores) - - def test_cpu_count_vs_cpu_times(self): - self.assertEqual(psutil.cpu_count(), - len(psutil.cpu_times(percpu=True))) - - def test_cpu_freq(self): - w = wmi.WMI() - proc = w.Win32_Processor()[0] - self.assertEqual(proc.CurrentClockSpeed, psutil.cpu_freq().current) - self.assertEqual(proc.MaxClockSpeed, psutil.cpu_freq().max) - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestSystemAPIs(TestCase): - - def test_nic_names(self): - out = sh('ipconfig /all') - nics = psutil.net_io_counters(pernic=True).keys() - for nic in nics: - if "pseudo-interface" in nic.replace(' ', '-').lower(): - continue - if nic not in out: - self.fail( - "%r nic wasn't found in 'ipconfig /all' output" % nic) - - def test_total_phymem(self): - w = wmi.WMI().Win32_ComputerSystem()[0] - self.assertEqual(int(w.TotalPhysicalMemory), - psutil.virtual_memory().total) - - # @unittest.skipIf(wmi is None, "wmi module is not installed") - # def test__UPTIME(self): - # # _UPTIME constant is not public but it is used internally - # # as value to return for pid 0 creation time. - # # WMI behaves the same. - # w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - # p = psutil.Process(0) - # wmic_create = str(w.CreationDate.split('.')[0]) - # psutil_create = time.strftime("%Y%m%d%H%M%S", - # time.localtime(p.create_time())) - - # Note: this test is not very reliable - @unittest.skipIf(APPVEYOR, "test not relieable on appveyor") - @retry_on_failure() - def test_pids(self): - # Note: this test might fail if the OS is starting/killing - # other processes in the meantime - w = wmi.WMI().Win32_Process() - wmi_pids = set([x.ProcessId for x in w]) - psutil_pids = set(psutil.pids()) - self.assertEqual(wmi_pids, psutil_pids) - - @retry_on_failure() - def test_disks(self): - ps_parts = psutil.disk_partitions(all=True) - wmi_parts = wmi.WMI().Win32_LogicalDisk() - for ps_part in ps_parts: - for wmi_part in wmi_parts: - if ps_part.device.replace('\\', '') == wmi_part.DeviceID: - if not ps_part.mountpoint: - # this is usually a CD-ROM with no disk inserted - break - if 'cdrom' in ps_part.opts: - break - try: - usage = psutil.disk_usage(ps_part.mountpoint) - except FileNotFoundError: - # usually this is the floppy - break - self.assertEqual(usage.total, int(wmi_part.Size)) - wmi_free = int(wmi_part.FreeSpace) - self.assertEqual(usage.free, wmi_free) - # 10 MB tollerance - if abs(usage.free - wmi_free) > 10 * 1024 * 1024: - self.fail("psutil=%s, wmi=%s" % ( - usage.free, wmi_free)) - break - else: - self.fail("can't find partition %s" % repr(ps_part)) - - def test_disk_usage(self): - for disk in psutil.disk_partitions(): - if 'cdrom' in disk.opts: - continue - sys_value = win32api.GetDiskFreeSpaceEx(disk.mountpoint) - psutil_value = psutil.disk_usage(disk.mountpoint) - self.assertAlmostEqual(sys_value[0], psutil_value.free, - delta=1024 * 1024) - self.assertAlmostEqual(sys_value[1], psutil_value.total, - delta=1024 * 1024) - self.assertEqual(psutil_value.used, - psutil_value.total - psutil_value.free) - - def test_disk_partitions(self): - sys_value = [ - x + '\\' for x in win32api.GetLogicalDriveStrings().split("\\\x00") - if x and not x.startswith('A:')] - psutil_value = [x.mountpoint for x in psutil.disk_partitions(all=True)] - self.assertEqual(sys_value, psutil_value) - - def test_net_if_stats(self): - ps_names = set(cext.net_if_stats()) - wmi_adapters = wmi.WMI().Win32_NetworkAdapter() - wmi_names = set() - for wmi_adapter in wmi_adapters: - wmi_names.add(wmi_adapter.Name) - wmi_names.add(wmi_adapter.NetConnectionID) - self.assertTrue(ps_names & wmi_names, - "no common entries in %s, %s" % (ps_names, wmi_names)) - - def test_boot_time(self): - wmi_os = wmi.WMI().Win32_OperatingSystem() - wmi_btime_str = wmi_os[0].LastBootUpTime.split('.')[0] - wmi_btime_dt = datetime.datetime.strptime( - wmi_btime_str, "%Y%m%d%H%M%S") - psutil_dt = datetime.datetime.fromtimestamp(psutil.boot_time()) - diff = abs((wmi_btime_dt - psutil_dt).total_seconds()) - self.assertLessEqual(diff, 3) - - def test_boot_time_fluctuation(self): - # https://github.com/giampaolo/psutil/issues/1007 - with mock.patch('psutil._pswindows.cext.boot_time', return_value=5): - self.assertEqual(psutil.boot_time(), 5) - with mock.patch('psutil._pswindows.cext.boot_time', return_value=4): - self.assertEqual(psutil.boot_time(), 5) - with mock.patch('psutil._pswindows.cext.boot_time', return_value=6): - self.assertEqual(psutil.boot_time(), 5) - with mock.patch('psutil._pswindows.cext.boot_time', return_value=333): - self.assertEqual(psutil.boot_time(), 333) - - -# =================================================================== -# sensors_battery() -# =================================================================== - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestSensorsBattery(TestCase): - - def test_has_battery(self): - if win32api.GetPwrCapabilities()['SystemBatteriesPresent']: - self.assertIsNotNone(psutil.sensors_battery()) - else: - self.assertIsNone(psutil.sensors_battery()) - - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_percent(self): - w = wmi.WMI() - battery_wmi = w.query('select * from Win32_Battery')[0] - battery_psutil = psutil.sensors_battery() - self.assertAlmostEqual( - battery_psutil.percent, battery_wmi.EstimatedChargeRemaining, - delta=1) - - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_power_plugged(self): - w = wmi.WMI() - battery_wmi = w.query('select * from Win32_Battery')[0] - battery_psutil = psutil.sensors_battery() - # Status codes: - # https://msdn.microsoft.com/en-us/library/aa394074(v=vs.85).aspx - self.assertEqual(battery_psutil.power_plugged, - battery_wmi.BatteryStatus == 2) - - def test_emulate_no_battery(self): - with mock.patch("psutil._pswindows.cext.sensors_battery", - return_value=(0, 128, 0, 0)) as m: - self.assertIsNone(psutil.sensors_battery()) - assert m.called - - def test_emulate_power_connected(self): - with mock.patch("psutil._pswindows.cext.sensors_battery", - return_value=(1, 0, 0, 0)) as m: - self.assertEqual(psutil.sensors_battery().secsleft, - psutil.POWER_TIME_UNLIMITED) - assert m.called - - def test_emulate_power_charging(self): - with mock.patch("psutil._pswindows.cext.sensors_battery", - return_value=(0, 8, 0, 0)) as m: - self.assertEqual(psutil.sensors_battery().secsleft, - psutil.POWER_TIME_UNLIMITED) - assert m.called - - def test_emulate_secs_left_unknown(self): - with mock.patch("psutil._pswindows.cext.sensors_battery", - return_value=(0, 0, 0, -1)) as m: - self.assertEqual(psutil.sensors_battery().secsleft, - psutil.POWER_TIME_UNKNOWN) - assert m.called - - -# =================================================================== -# Process APIs -# =================================================================== - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestProcess(TestCase): - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_issue_24(self): - p = psutil.Process(0) - self.assertRaises(psutil.AccessDenied, p.kill) - - def test_special_pid(self): - p = psutil.Process(4) - self.assertEqual(p.name(), 'System') - # use __str__ to access all common Process properties to check - # that nothing strange happens - str(p) - p.username() - self.assertTrue(p.create_time() >= 0.0) - try: - rss, vms = p.memory_info()[:2] - except psutil.AccessDenied: - # expected on Windows Vista and Windows 7 - if not platform.uname()[1] in ('vista', 'win-7', 'win7'): - raise - else: - self.assertTrue(rss > 0) - - def test_send_signal(self): - p = psutil.Process(self.pid) - self.assertRaises(ValueError, p.send_signal, signal.SIGINT) - - def test_num_handles_increment(self): - p = psutil.Process(os.getpid()) - before = p.num_handles() - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, os.getpid()) - after = p.num_handles() - self.assertEqual(after, before + 1) - win32api.CloseHandle(handle) - self.assertEqual(p.num_handles(), before) - - def test_handles_leak(self): - # Call all Process methods and make sure no handles are left - # open. This is here mainly to make sure functions using - # OpenProcess() always call CloseHandle(). - def call(p, attr): - attr = getattr(p, name, None) - if attr is not None and callable(attr): - attr() - else: - attr - - p = psutil.Process(self.pid) - failures = [] - for name in dir(psutil.Process): - if name.startswith('_') \ - or name in ('terminate', 'kill', 'suspend', 'resume', - 'nice', 'send_signal', 'wait', 'children', - 'as_dict', 'memory_info_ex'): - continue - else: - try: - call(p, name) - num1 = p.num_handles() - call(p, name) - num2 = p.num_handles() - except (psutil.NoSuchProcess, psutil.AccessDenied): - pass - else: - if num2 > num1: - fail = \ - "failure while processing Process.%s method " \ - "(before=%s, after=%s)" % (name, num1, num2) - failures.append(fail) - if failures: - self.fail('\n' + '\n'.join(failures)) - - @unittest.skipIf(not sys.version_info >= (2, 7), - "CTRL_* signals not supported") - def test_ctrl_signals(self): - p = psutil.Process(get_test_subprocess().pid) - p.send_signal(signal.CTRL_C_EVENT) - p.send_signal(signal.CTRL_BREAK_EVENT) - p.kill() - p.wait() - self.assertRaises(psutil.NoSuchProcess, - p.send_signal, signal.CTRL_C_EVENT) - self.assertRaises(psutil.NoSuchProcess, - p.send_signal, signal.CTRL_BREAK_EVENT) - - def test_username(self): - self.assertEqual(psutil.Process().username(), - win32api.GetUserNameEx(win32con.NameSamCompatible)) - - def test_cmdline(self): - sys_value = re.sub(' +', ' ', win32api.GetCommandLine()).strip() - psutil_value = ' '.join(psutil.Process().cmdline()) - self.assertEqual(sys_value, psutil_value) - - # XXX - occasional failures - - # def test_cpu_times(self): - # handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - # win32con.FALSE, os.getpid()) - # self.addCleanup(win32api.CloseHandle, handle) - # sys_value = win32process.GetProcessTimes(handle) - # psutil_value = psutil.Process().cpu_times() - # self.assertAlmostEqual( - # psutil_value.user, sys_value['UserTime'] / 10000000.0, - # delta=0.2) - # self.assertAlmostEqual( - # psutil_value.user, sys_value['KernelTime'] / 10000000.0, - # delta=0.2) - - def test_nice(self): - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, os.getpid()) - self.addCleanup(win32api.CloseHandle, handle) - sys_value = win32process.GetPriorityClass(handle) - psutil_value = psutil.Process().nice() - self.assertEqual(psutil_value, sys_value) - - def test_memory_info(self): - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, self.pid) - self.addCleanup(win32api.CloseHandle, handle) - sys_value = win32process.GetProcessMemoryInfo(handle) - psutil_value = psutil.Process(self.pid).memory_info() - self.assertEqual( - sys_value['PeakWorkingSetSize'], psutil_value.peak_wset) - self.assertEqual( - sys_value['WorkingSetSize'], psutil_value.wset) - self.assertEqual( - sys_value['QuotaPeakPagedPoolUsage'], psutil_value.peak_paged_pool) - self.assertEqual( - sys_value['QuotaPagedPoolUsage'], psutil_value.paged_pool) - self.assertEqual( - sys_value['QuotaPeakNonPagedPoolUsage'], - psutil_value.peak_nonpaged_pool) - self.assertEqual( - sys_value['QuotaNonPagedPoolUsage'], psutil_value.nonpaged_pool) - self.assertEqual( - sys_value['PagefileUsage'], psutil_value.pagefile) - self.assertEqual( - sys_value['PeakPagefileUsage'], psutil_value.peak_pagefile) - - self.assertEqual(psutil_value.rss, psutil_value.wset) - self.assertEqual(psutil_value.vms, psutil_value.pagefile) - - def test_wait(self): - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, self.pid) - self.addCleanup(win32api.CloseHandle, handle) - p = psutil.Process(self.pid) - p.terminate() - psutil_value = p.wait() - sys_value = win32process.GetExitCodeProcess(handle) - self.assertEqual(psutil_value, sys_value) - - def test_cpu_affinity(self): - def from_bitmask(x): - return [i for i in range(64) if (1 << i) & x] - - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, self.pid) - self.addCleanup(win32api.CloseHandle, handle) - sys_value = from_bitmask( - win32process.GetProcessAffinityMask(handle)[0]) - psutil_value = psutil.Process(self.pid).cpu_affinity() - self.assertEqual(psutil_value, sys_value) - - def test_io_counters(self): - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, os.getpid()) - self.addCleanup(win32api.CloseHandle, handle) - sys_value = win32process.GetProcessIoCounters(handle) - psutil_value = psutil.Process().io_counters() - self.assertEqual( - psutil_value.read_count, sys_value['ReadOperationCount']) - self.assertEqual( - psutil_value.write_count, sys_value['WriteOperationCount']) - self.assertEqual( - psutil_value.read_bytes, sys_value['ReadTransferCount']) - self.assertEqual( - psutil_value.write_bytes, sys_value['WriteTransferCount']) - self.assertEqual( - psutil_value.other_count, sys_value['OtherOperationCount']) - self.assertEqual( - psutil_value.other_bytes, sys_value['OtherTransferCount']) - - def test_num_handles(self): - import ctypes - import ctypes.wintypes - PROCESS_QUERY_INFORMATION = 0x400 - handle = ctypes.windll.kernel32.OpenProcess( - PROCESS_QUERY_INFORMATION, 0, self.pid) - self.addCleanup(ctypes.windll.kernel32.CloseHandle, handle) - - hndcnt = ctypes.wintypes.DWORD() - ctypes.windll.kernel32.GetProcessHandleCount( - handle, ctypes.byref(hndcnt)) - sys_value = hndcnt.value - psutil_value = psutil.Process(self.pid).num_handles() - self.assertEqual(psutil_value, sys_value) - - def test_error_partial_copy(self): - # https://github.com/giampaolo/psutil/issues/875 - exc = WindowsError() - exc.winerror = 299 - with mock.patch("psutil._psplatform.cext.proc_cwd", side_effect=exc): - with mock.patch("time.sleep") as m: - p = psutil.Process() - self.assertRaises(psutil.AccessDenied, p.cwd) - self.assertGreaterEqual(m.call_count, 5) - - def test_exe(self): - # NtQuerySystemInformation succeeds if process is gone. Make sure - # it raises NSP for a non existent pid. - pid = psutil.pids()[-1] + 99999 - proc = psutil._psplatform.Process(pid) - self.assertRaises(psutil.NoSuchProcess, proc.exe) - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestProcessWMI(TestCase): - """Compare Process API results with WMI.""" - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_name(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - self.assertEqual(p.name(), w.Caption) - - def test_exe(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - # Note: wmi reports the exe as a lower case string. - # Being Windows paths case-insensitive we ignore that. - self.assertEqual(p.exe().lower(), w.ExecutablePath.lower()) - - def test_cmdline(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - self.assertEqual(' '.join(p.cmdline()), - w.CommandLine.replace('"', '')) - - def test_username(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - domain, _, username = w.GetOwner() - username = "%s\\%s" % (domain, username) - self.assertEqual(p.username(), username) - - def test_memory_rss(self): - time.sleep(0.1) - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - rss = p.memory_info().rss - self.assertEqual(rss, int(w.WorkingSetSize)) - - def test_memory_vms(self): - time.sleep(0.1) - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - vms = p.memory_info().vms - # http://msdn.microsoft.com/en-us/library/aa394372(VS.85).aspx - # ...claims that PageFileUsage is represented in Kilo - # bytes but funnily enough on certain platforms bytes are - # returned instead. - wmi_usage = int(w.PageFileUsage) - if (vms != wmi_usage) and (vms != wmi_usage * 1024): - self.fail("wmi=%s, psutil=%s" % (wmi_usage, vms)) - - def test_create_time(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - wmic_create = str(w.CreationDate.split('.')[0]) - psutil_create = time.strftime("%Y%m%d%H%M%S", - time.localtime(p.create_time())) - self.assertEqual(wmic_create, psutil_create) - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestDualProcessImplementation(TestCase): - """ - Certain APIs on Windows have 2 internal implementations, one - based on documented Windows APIs, another one based - NtQuerySystemInformation() which gets called as fallback in - case the first fails because of limited permission error. - Here we test that the two methods return the exact same value, - see: - https://github.com/giampaolo/psutil/issues/304 - """ - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_memory_info(self): - mem_1 = psutil.Process(self.pid).memory_info() - with mock.patch("psutil._psplatform.cext.proc_memory_info", - side_effect=OSError(errno.EPERM, "msg")) as fun: - mem_2 = psutil.Process(self.pid).memory_info() - self.assertEqual(len(mem_1), len(mem_2)) - for i in range(len(mem_1)): - self.assertGreaterEqual(mem_1[i], 0) - self.assertGreaterEqual(mem_2[i], 0) - self.assertAlmostEqual(mem_1[i], mem_2[i], delta=512) - assert fun.called - - def test_create_time(self): - ctime = psutil.Process(self.pid).create_time() - with mock.patch("psutil._psplatform.cext.proc_times", - side_effect=OSError(errno.EPERM, "msg")) as fun: - self.assertEqual(psutil.Process(self.pid).create_time(), ctime) - assert fun.called - - def test_cpu_times(self): - cpu_times_1 = psutil.Process(self.pid).cpu_times() - with mock.patch("psutil._psplatform.cext.proc_times", - side_effect=OSError(errno.EPERM, "msg")) as fun: - cpu_times_2 = psutil.Process(self.pid).cpu_times() - assert fun.called - self.assertAlmostEqual( - cpu_times_1.user, cpu_times_2.user, delta=0.01) - self.assertAlmostEqual( - cpu_times_1.system, cpu_times_2.system, delta=0.01) - - def test_io_counters(self): - io_counters_1 = psutil.Process(self.pid).io_counters() - with mock.patch("psutil._psplatform.cext.proc_io_counters", - side_effect=OSError(errno.EPERM, "msg")) as fun: - io_counters_2 = psutil.Process(self.pid).io_counters() - for i in range(len(io_counters_1)): - self.assertAlmostEqual( - io_counters_1[i], io_counters_2[i], delta=5) - assert fun.called - - def test_num_handles(self): - num_handles = psutil.Process(self.pid).num_handles() - with mock.patch("psutil._psplatform.cext.proc_num_handles", - side_effect=OSError(errno.EPERM, "msg")) as fun: - self.assertEqual(psutil.Process(self.pid).num_handles(), - num_handles) - assert fun.called - - def test_cmdline(self): - from psutil._pswindows import convert_oserror - for pid in psutil.pids(): - try: - a = cext.proc_cmdline(pid, use_peb=True) - b = cext.proc_cmdline(pid, use_peb=False) - except OSError as err: - err = convert_oserror(err) - if not isinstance(err, (psutil.AccessDenied, - psutil.NoSuchProcess)): - raise - else: - self.assertEqual(a, b) - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class RemoteProcessTestCase(TestCase): - """Certain functions require calling ReadProcessMemory. - This trivially works when called on the current process. - Check that this works on other processes, especially when they - have a different bitness. - """ - - @staticmethod - def find_other_interpreter(): - # find a python interpreter that is of the opposite bitness from us - code = "import sys; sys.stdout.write(str(sys.maxsize > 2**32))" - - # XXX: a different and probably more stable approach might be to access - # the registry but accessing 64 bit paths from a 32 bit process - for filename in glob.glob(r"C:\Python*\python.exe"): - proc = subprocess.Popen(args=[filename, "-c", code], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - output, _ = proc.communicate() - if output == str(not IS_64_BIT): - return filename - - @classmethod - def setUpClass(cls): - other_python = cls.find_other_interpreter() - - if other_python is None: - raise unittest.SkipTest( - "could not find interpreter with opposite bitness") - - if IS_64_BIT: - cls.python64 = sys.executable - cls.python32 = other_python - else: - cls.python64 = other_python - cls.python32 = sys.executable - - test_args = ["-c", "import sys; sys.stdin.read()"] - - def setUp(self): - env = os.environ.copy() - env["THINK_OF_A_NUMBER"] = str(os.getpid()) - self.proc32 = get_test_subprocess([self.python32] + self.test_args, - env=env, - stdin=subprocess.PIPE) - self.proc64 = get_test_subprocess([self.python64] + self.test_args, - env=env, - stdin=subprocess.PIPE) - - def tearDown(self): - self.proc32.communicate() - self.proc64.communicate() - reap_children() - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_cmdline_32(self): - p = psutil.Process(self.proc32.pid) - self.assertEqual(len(p.cmdline()), 3) - self.assertEqual(p.cmdline()[1:], self.test_args) - - def test_cmdline_64(self): - p = psutil.Process(self.proc64.pid) - self.assertEqual(len(p.cmdline()), 3) - self.assertEqual(p.cmdline()[1:], self.test_args) - - def test_cwd_32(self): - p = psutil.Process(self.proc32.pid) - self.assertEqual(p.cwd(), os.getcwd()) - - def test_cwd_64(self): - p = psutil.Process(self.proc64.pid) - self.assertEqual(p.cwd(), os.getcwd()) - - def test_environ_32(self): - p = psutil.Process(self.proc32.pid) - e = p.environ() - self.assertIn("THINK_OF_A_NUMBER", e) - self.assertEquals(e["THINK_OF_A_NUMBER"], str(os.getpid())) - - def test_environ_64(self): - p = psutil.Process(self.proc64.pid) - try: - p.environ() - except psutil.AccessDenied: - pass - - -# =================================================================== -# Windows services -# =================================================================== - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestServices(TestCase): - - def test_win_service_iter(self): - valid_statuses = set([ - "running", - "paused", - "start", - "pause", - "continue", - "stop", - "stopped", - ]) - valid_start_types = set([ - "automatic", - "manual", - "disabled", - ]) - valid_statuses = set([ - "running", - "paused", - "start_pending", - "pause_pending", - "continue_pending", - "stop_pending", - "stopped" - ]) - for serv in psutil.win_service_iter(): - data = serv.as_dict() - self.assertIsInstance(data['name'], str) - self.assertNotEqual(data['name'].strip(), "") - self.assertIsInstance(data['display_name'], str) - self.assertIsInstance(data['username'], str) - self.assertIn(data['status'], valid_statuses) - if data['pid'] is not None: - psutil.Process(data['pid']) - self.assertIsInstance(data['binpath'], str) - self.assertIsInstance(data['username'], str) - self.assertIsInstance(data['start_type'], str) - self.assertIn(data['start_type'], valid_start_types) - self.assertIn(data['status'], valid_statuses) - self.assertIsInstance(data['description'], str) - pid = serv.pid() - if pid is not None: - p = psutil.Process(pid) - self.assertTrue(p.is_running()) - # win_service_get - s = psutil.win_service_get(serv.name()) - # test __eq__ - self.assertEqual(serv, s) - - def test_win_service_get(self): - ERROR_SERVICE_DOES_NOT_EXIST = \ - psutil._psplatform.cext.ERROR_SERVICE_DOES_NOT_EXIST - ERROR_ACCESS_DENIED = psutil._psplatform.cext.ERROR_ACCESS_DENIED - - name = next(psutil.win_service_iter()).name() - with self.assertRaises(psutil.NoSuchProcess) as cm: - psutil.win_service_get(name + '???') - self.assertEqual(cm.exception.name, name + '???') - - # test NoSuchProcess - service = psutil.win_service_get(name) - if PY3: - args = (0, "msg", 0, ERROR_SERVICE_DOES_NOT_EXIST) - else: - args = (ERROR_SERVICE_DOES_NOT_EXIST, "msg") - exc = WindowsError(*args) - with mock.patch("psutil._psplatform.cext.winservice_query_status", - side_effect=exc): - self.assertRaises(psutil.NoSuchProcess, service.status) - with mock.patch("psutil._psplatform.cext.winservice_query_config", - side_effect=exc): - self.assertRaises(psutil.NoSuchProcess, service.username) - - # test AccessDenied - if PY3: - args = (0, "msg", 0, ERROR_ACCESS_DENIED) - else: - args = (ERROR_ACCESS_DENIED, "msg") - exc = WindowsError(*args) - with mock.patch("psutil._psplatform.cext.winservice_query_status", - side_effect=exc): - self.assertRaises(psutil.AccessDenied, service.status) - with mock.patch("psutil._psplatform.cext.winservice_query_config", - side_effect=exc): - self.assertRaises(psutil.AccessDenied, service.username) - - # test __str__ and __repr__ - self.assertIn(service.name(), str(service)) - self.assertIn(service.display_name(), str(service)) - self.assertIn(service.name(), repr(service)) - self.assertIn(service.display_name(), repr(service)) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/.cirrus.yml b/third_party/python/psutil/.cirrus.yml deleted file mode 100644 index 41c58a93d305..000000000000 --- a/third_party/python/psutil/.cirrus.yml +++ /dev/null @@ -1,31 +0,0 @@ -freebsd_12_1_py3_task: - freebsd_instance: - image: freebsd-12-1-release-amd64 - env: - CIRRUS: 1 - install_script: - - pkg install -y python3 gcc py37-pip - script: - - python3 -m pip install --user setuptools - - make clean - - make install - - make test - - make test-memleaks - - PSUTIL_TESTING=1 python3 -Wa scripts/internal/print_access_denied.py - - PSUTIL_TESTING=1 python3 -Wa scripts/internal/print_api_speed.py - -freebsd_12_1_py2_task: - freebsd_instance: - image: freebsd-12-1-release-amd64 - env: - CIRRUS: 1 - install_script: - - pkg install -y python gcc py27-pip - script: - - python2.7 -m pip install --user setuptools ipaddress mock - - make clean - - make install - - make test - - make test-memleaks - - PSUTIL_TESTING=1 python3 -Wa scripts/internal/print_access_denied.py - - PSUTIL_TESTING=1 python3 -Wa scripts/internal/print_api_speed.py diff --git a/third_party/python/psutil/.coveragerc b/third_party/python/psutil/.coveragerc deleted file mode 100644 index c6772e9539fa..000000000000 --- a/third_party/python/psutil/.coveragerc +++ /dev/null @@ -1,32 +0,0 @@ -[report] - -include = - *psutil* -omit = - psutil/_compat.py - psutil/tests/* - setup.py -exclude_lines = - enum.IntEnum - except ImportError: - globals().update - if __name__ == .__main__.: - if _WINDOWS: - if BSD - if enum is None: - if enum is not None: - if FREEBSD - if has_enums: - if LINUX - if LITTLE_ENDIAN: - if NETBSD - if OPENBSD - if MACOS - if ppid_map is None: - if PY3: - if SUNOS - if sys.platform.startswith - if WINDOWS - import enum - pragma: no cover - raise NotImplementedError diff --git a/third_party/python/psutil/.gitignore b/third_party/python/psutil/.gitignore deleted file mode 100644 index 3d22b0b3553c..000000000000 --- a/third_party/python/psutil/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -syntax: glob -*.al -*.bak -*.egg-info -*.la -*.lo -*.o -*.orig -*.pyc -*.pyd -*.rej -*.so -*.swp -.failed-tests.txt -.cache/ -.idea/ -.tox/ -build/ -dist/ diff --git a/third_party/python/psutil/CREDITS b/third_party/python/psutil/CREDITS deleted file mode 100644 index 716de944c23c..000000000000 --- a/third_party/python/psutil/CREDITS +++ /dev/null @@ -1,666 +0,0 @@ -Intro -===== - -I would like to recognize some of the people who have been instrumental in the -development of psutil. I'm sure I'm forgetting somebody (feel free to email me) -but here is a short list. It's modeled after the Linux CREDITS file where the -fields are: name (N), e-mail (E), website (W), country (C), description (D), -(I) issues. Issue tracker is at https://github.com/giampaolo/psutil/issues). -A big thanks to all of you. - -- Giampaolo - -Author -====== - -N: Giampaolo Rodola -C: Italy -E: g.rodola@gmail.com -W: http://grodola.blogspot.com/ - -Experts -======= - -Github usernames of people to CC on github when in need of help. - -- NetBSD: - - 0-wiz-0, Thomas Klausner - - ryoqun, Ryo Onodera -- OpenBSD: - - landryb, Landry Breuil -- FreeBSD: - - glebius, Gleb Smirnoff (#1013) - - sunpoet, Po-Chuan Hsieh (pkg maintainer, #1105) - - kostikbel, Konstantin Belousov (#1105) -- macOS: - - whitlockjc, Jeremy Whitlock -- Windows: - - mrjefftang, Jeff Tang - - wj32, Wen Jia Liu - - fbenkstein, Frank Benkstein -- SunOS: - - wiggin15, Arnon Yaari - - alxchk, Oleksii Shevchuk -- AIX: - - wiggin15, Arnon Yaari (maintainer) - -Top contributors -================ - -N: Jay Loden -C: NJ, USA -E: jloden@gmail.com -D: original co-author, initial design/bootstrap and occasional bug fixes -W: http://www.jayloden.com - -N: Arnon Yaari (wiggin15) -W: https://github.com/wiggin15 -D: AIX implementation, expert on multiple fronts -I: 517, 607, 610, 1131, 1123, 1130, 1154, 1164, 1174, 1177, 1210, 1214, 1408, - 1329, 1276, 1494, 1528. - -N: Alex Manuskin -W: https://github.com/amanusk -D: FreeBSD cpu_freq(), OSX temperatures, support for Linux temperatures. -I: 1284, 1345, 1350, 1352, 1472, 1481, 1487. - -N: Jeff Tang -W: https://github.com/mrjefftang -I: 340, 529, 616, 653, 654, 648, 641 - -N: Jeremy Whitlock -E: jcscoobyrs@gmail.com -D: great help with macOS C development. -I: 125, 150, 174, 206 - -N: Landry Breuil -W: https://github.com/landryb -D: OpenBSD implementation. -I: 615 - -N: Justin Venus -E: justin.venus@gmail.com -D: Solaris support -I: 18 - -N: Thomas Klausner -W: https://github.com/0-wiz-0 -D: NetBSD implementation (co-author). -I: 557 - -N: Ryo Onodera -W: https://github.com/ryoon -D: NetBSD implementation (co-author). -I: 557 - -Contributors -============ - -N: wj32 -E: wj32.64@gmail.com -D: process username() and get_connections() on Windows -I: 114, 115 - -N: Yan Raber -C: Bologna, Italy -E: yanraber@gmail.com -D: help on Windows development (initial version of Process.username()) - -N: Dave Daeschler -C: USA -E: david.daeschler@gmail.com -W: http://daviddaeschler.com -D: some contributions to initial design/bootstrap plus occasional bug fixing -I: 522, 536 - -N: cjgohlke -E: cjgohlke@gmail.com -D: Windows 64 bit support -I: 107 - -N: Frank Benkstein -D: process environ() -W: https://github.com/fbenkstein -I: 732, 733 - -N: Mozilla Foundation -D: sample code for process USS memory. - -N: EccoTheFlintstone -W: https://github.com/EccoTheFlintstone -I: 1368, 1348 - ----- - -N: Jeffery Kline -E: jeffery.kline@gmail.com -I: 130 - -N: Grabriel Monnerat -E: gabrielmonnerat@gmail.com -I: 146 - -N: Philip Roberts -E: philip.roberts@gmail.com -I: 168 - -N: jcscoobyrs -E: jcscoobyrs@gmail.com -I: 125 - -N: Sandro Tosi -E: sandro.tosi@gmail.com -I: 200, 201 - -N: Andrew Colin -E: andrew.colin@gmail.com -I: 248 - -N: Amoser -E: amoser@google.com -I: 266, 267, 340 - -N: Matthew Grant -E: matthewgrant5@gmail.com -I: 271 - -N: oweidner -E: oweidner@cct.lsu.edu -I: 275 - -N: Tarek Ziade -E: ziade.tarek -I: 281 - -N: Luca Cipriani -C: Turin, Italy -E: luca.opensource@gmail.com -I: 278 - -N: Maciej Lach, -E: maciej.lach@gmail.com -I: 294 - -N: James Pye -E: james.pye@gmail.com -I: 305, 306 - -N: Stanchev Emil -E: stanchev.emil -I: 314 - -N: Kim Gräsman -E: kim.grasman@gmail.com -D: ...also kindly donated some money. -I: 316 - -N: Riccardo Murri -C: Italy -I: 318 - -N: Florent Xicluna -E: florent.xicluna@gmail.com -I: 319 - -N: Michal Spondr -E: michal.spondr -I: 313 - -N: Jean Sebastien -E: dumbboules@gmail.com -I: 344 - -N: Rob Smith -W: http://www.kormoc.com/ -I: 341 - -N: Youngsik Kim -W: https://plus.google.com/101320747613749824490/ -I: 317 - -N: Gregory Szorc -W: https://plus.google.com/116873264322260110710/posts -I: 323 - -N: André Oriani -E: aoriani@gmail.com -I: 361 - -N: clackwell -E: clackwell@gmail.com -I: 356 - -N: m.malycha -E: m.malycha@gmail.com -I: 351 - -N: John Baldwin -E: jhb@FreeBSD.org -I: 370 - -N: Jan Beich -E: jbeich@tormail.org -I: 325 - -N: floppymaster -E: floppymaster@gmail.com -I: 380 - -N: Arfrever.FTA -E: Arfrever.FTA@gmail.com -I: 369, 404 - -N: danudey -E: danudey@gmail.com -I: 386 - -N: Adrien Fallou -I: 224 - -N: Gisle Vanem -E: gisle.vanem@gmail.com -I: 411 - -N: thepyr0 -E: thepyr0@gmail.com -I: 414 - -N: John Pankov -E: john.pankov@gmail.com -I: 435 - -N: Matt Good -W: http://matt-good.net/ -I: 438 - -N: Ulrich Klank -E: ulrich.klank@scitics.de -I: 448 - -N: Josiah Carlson -E: josiah.carlson@gmail.com -I: 451, 452 - -N: Raymond Hettinger -D: namedtuple and lru_cache backward compatible implementations. - -N: Jason Kirtland -D: backward compatible implementation of collections.defaultdict. - -M: Ken Seeho -D: @cached_property decorator - -N: crusaderky -E: crusaderky@gmail.com -I: 470, 477 - -E: alex@mroja.net -I: 471 - -N: Gautam Singh -E: gautam.singh@gmail.com -I: 466 - -E: lhn@hupfeldtit.dk -I: 476, 479 - -N: Francois Charron -E: francois.charron.1@gmail.com -I: 474 - -N: Naveed Roudsari -E: naveed.roudsari@gmail.com -I: 421 - -N: Alexander Grothe -E: Alexander.Grothe@gmail.com -I: 497 - -N: Szigeti Gabor Niif -E: szigeti.gabor.niif@gmail.com -I: 446 - -N: msabramo -E: msabramo@gmail.com -I: 492 - -N: Yaolong Huang -E: airekans@gmail.com -W: http://airekans.github.io/ -I: 530 - -N: Anders Chrigström -W: https://github.com/anders-chrigstrom -I: 496 - -N: spacewander -W: https://github.com/spacewander -E: spacewanderlzx@gmail.com -I: 561, 603 - -N: Sylvain Mouquet -E: sylvain.mouquet@gmail.com -I: 565 - -N: karthikrev -I: 568 - -N: Bruno Binet -E: bruno.binet@gmail.com -I: 572 - -N: Gabi Davar -C: Israel -W: https://github.com/mindw -I: 578, 581, 587 - -N: spacewanderlzx -C: Guangzhou,China -E: spacewanderlzx@gmail.com -I: 555 - -N: Fabian Groffen -I: 611, 618 - -N: desbma -W: https://github.com/desbma -C: France -I: 628 - -N: John Burnett -W: http://www.johnburnett.com/ -C: Irvine, CA, US -I: 614 - -N: Árni Már Jónsson -E: Reykjavik, Iceland -E: https://github.com/arnimarj -I: 634 - -N: Bart van Kleef -W: https://github.com/bkleef -I: 664 - -N: Steven Winfield -W: https://github.com/stevenwinfield -I: 672 - -N: sk6249 -W: https://github.com/sk6249 -I: 670 - -N: maozguttman -W: https://github.com/maozguttman -I: 659 - -N: dasumin -W: https://github.com/dasumin -I: 541 - -N: Mike Sarahan -W: https://github.com/msarahan -I: 688 - -N: Syohei YOSHIDA -W: https://github.com/syohex -I: 730 - -N: Visa Hankala -E: visa@openbsd.org -I: 741 - -N: Sebastian-Gabriel Brestin -C: Romania -E: sebastianbrestin@gmail.com -I: 704 - -N: Timmy Konick -W: https://github.com/tijko -I: 751 - -N: mpderbec -W: https://github.com/mpderbec -I: 660 - -N: wxwright -W: https://github.com/wxwright -I: 776 - -N: Farhan Khan -E: khanzf@gmail.com -I: 823 - -N: Jake Omann -E: https://github.com/jomann09 -I: 816, 775 - -N: Jeremy Humble -W: https://github.com/jhumble -I: 863 - -N: Ilya Georgievsky -W: https://github.com/xBeAsTx -I: 870 - -N: Yago Jesus -W: https://github.com/YJesus -I: 798 - -N: Andre Caron -C: Montreal, QC, Canada -E: andre.l.caron@gmail.com -W: https://github.com/AndreLouisCaron -I: 880 - -N: ewedlund -W: https://github.com/ewedlund -I: 874 - -N: Arcadiy Ivanov -W: https://github.com/arcivanov -I: 919 - -N: Max Bélanger -W: https://github.com/maxbelanger -I: 936, 1133 - -N: Pierre Fersing -C: France -E: pierre.fersing@bleemeo.com -I: 950 - -N: Thiago Borges Abdnur -W: https://github.com/bolaum -I: 959 - -N: Nicolas Hennion -W: https://github.com/nicolargo -I: 974 - -N: Baruch Siach -W: https://github.com/baruchsiach -I: 872 - -N: Danek Duvall -W: https://github.com/dhduvall -I: 1002 - -N: Alexander Hasselhuhn -C: Germany -W: https://github.com/alexanha - -N: Himanshu Shekhar -W: https://github.com/himanshub16 -I: 1036 - -N: Yannick Gingras -W: https://github.com/ygingras -I: 1057 - -N: Gleb Smirnoff -W: https://github.com/glebius -D: good help with FreeBSD -I: 1042, 1079, 1070 - -N: Oleksii Shevchuk -W: https://github.com/alxchk -I: 1077, 1093, 1091, 1220, 1346 - -N: Prodesire -W: https://github.com/Prodesire -I: 1138 - -N: Sebastian Saip -W: https://github.com/ssaip -I: 1141 - -N: Jakub Bacic -W: https://github.com/jakub-bacic -I: 1127 - -N: Akos Kiss -W: https://github.com/akosthekiss -I: 1150 - -N: Adrian Page -W: https://github.com/adpag -I: 1159, 1160, 1161 - -N: Matthew Long -W: https://github.com/matray -I: 1167 - -N: janderbrain -W: https://github.com/janderbrain -I: 1169 - -N: Dan Vinakovsky -W: https://github.com/hexaclock -I: 1216 - -N: stswandering -W: https://github.com/stswandering -I: 1243 - -N: Georg Sauthoff -W: https://github.com/gsauthof -I: 1193, 1194 - -N: Maxime Mouial -W: https://github.com/hush-hush -I: 1239 - -N: Denis Krienbühl -W: https://github.com/href -I: 1260 - -N: Jean-Luc Migot -W: https://github.com/jmigot-tehtris -I: 1258, 1289 - -N: Nikhil Marathe -W: https://github.com/nikhilm -I: 1278 - -N: Sylvain Duchesne -W: https://github.com/sylvainduchesne -I: 1294 - -N: Lawrence Ye -W: https://github.com/LEAFERx -I: 1321 - -N: Ilya Yanok -W: https://github.com/yanok -I: 1332 - -N: Jaime Fullaondo -W: https://github.com/truthbk -D: AIX support -I: 1320 - -N: Koen Kooi -W: https://github.com/koenkooi -I: 1360 - -N: Ghislain Le Meur -W: https://github.com/gigi206 -D: idea for Process.parents() -I: 1379 - -N: Benjamin Drung -D: make tests invariant to LANG setting -W: https://github.com/bdrung -I: 1462 - -N: Xiaoling Bao -I: 1223 - -N: Cedric Lamoriniere -W: https://github.com/clamoriniere -I: 1470 - -N: Daniel Beer -W: https://github.com/dbeer1 -I: 1471 - -N: Samer Masterson -W: https://github.com/samertm -I: 1480 - -N: Ammar Askar -E: ammar@ammaraskar.com -W: http://ammaraskar.com/ -I: 604, 1484 - -N: agnewee -W: https://github.com/Agnewee -C: China -I: 1491 - -N: Kamil Rytarowski -W: https://github.com/krytarowski -C: Poland -I: 1526, 1530 - -N: Athos Ribeiro -W: https://github.com/athos-ribeiro -I: 1585 - -N: Erwan Le Pape -W: https://github.com/erwan-le-pape -I: 1570 - -N: Étienne Servais -W: https://github.com/vser1 -I: 1607, 1637 - -N: Bernát Gábor -W: https://github.com/gaborbernat -I: 1565 - -N: Nathan Houghton -W: https://github.com/n1000 -I: 1619 - -N: Riccardo Schirone -W: https://github.com/ret2libc -C: Milano, Italy -I: 1616 - -N: Po-Chuan Hsieh -W: https://github.com/sunpoet -C: Taiwan -I: 1646 - -N: Javad Karabi -W: https://github.com/karabijavad -I: 1648 - -N: Mike Hommey -W: https://github.com/glandium -I: 1665 - -N: Anselm Kruis -W: https://github.com/akruis -I: 1695 diff --git a/third_party/python/psutil/HISTORY.rst b/third_party/python/psutil/HISTORY.rst deleted file mode 100644 index 9b39fa051785..000000000000 --- a/third_party/python/psutil/HISTORY.rst +++ /dev/null @@ -1,4141 +0,0 @@ -*Bug tracker at https://github.com/giampaolo/psutil/issues* - -5.7.0 -===== - -2020-12-18 - -**Enhancements** - -- 1637_: [SunOS] add partial support for old SunOS 5.10 Update 0 to 3. -- 1648_: [Linux] sensors_temperatures() looks into an additional /sys/device/ - directory for additional data. (patch by Javad Karabi) -- 1652_: [Windows] dropped support for Windows XP and Windows Server 2003. - Minimum supported Windows version now is Windows Vista. -- 1671_: [FreeBSD] add CI testing/service for FreeBSD (Cirrus CI). -- 1677_: [Windows] process exe() will succeed for all process PIDs (instead of - raising AccessDenied). -- 1679_: [Windows] net_connections() and Process.connections() are 10% faster. -- 1682_: [PyPy] added CI / test integration for PyPy via Travis. -- 1686_: [Windows] added support for PyPy on Windows. -- 1693_: [Windows] boot_time(), Process.create_time() and users()'s login time - now have 1 micro second precision (before the precision was of 1 second). - -**Bug fixes** - -- 1538_: [NetBSD] process cwd() may return ENOENT instead of NoSuchProcess. -- 1627_: [Linux] Process.memory_maps() can raise KeyError. -- 1642_: [SunOS] querying basic info for PID 0 results in FileNotFoundError. -- 1646_: [FreeBSD] many Process methods may cause a segfault on FreeBSD 12.0 - due to a backward incompatible change in a C type introduced in 12.0. -- 1656_: [Windows] Process.memory_full_info() raises AccessDenied even for the - current user and os.getpid(). -- 1660_: [Windows] Process.open_files() complete rewrite + check of errors. -- 1662_: [Windows] process exe() may raise WinError 0. -- 1665_: [Linux] disk_io_counters() does not take into account extra fields - added to recent kernels. (patch by Mike Hommey) -- 1672_: use the right C type when dealing with PIDs (int or long). Thus far - (long) was almost always assumed, which is wrong on most platforms. -- 1673_: [OpenBSD] Process connections(), num_fds() and threads() returned - improper exception if process is gone. -- 1674_: [SunOS] disk_partitions() may raise OSError. -- 1684_: [Linux] disk_io_counters() may raise ValueError on systems not - having /proc/diskstats. -- 1695_: [Linux] could not compile on kernels <= 2.6.13 due to - PSUTIL_HAVE_IOPRIO not being defined. (patch by Anselm Kruis) - -5.6.7 -===== - -2019-11-26 - -**Bug fixes** - -- 1630_: [Windows] can't compile source distribution due to C syntax error. - -5.6.6 -===== - -2019-11-25 - -**Bug fixes** - -- 1179_: [Linux] Process cmdline() now takes into account misbehaving processes - renaming the command line and using inappropriate chars to separate args. -- 1616_: use of Py_DECREF instead of Py_CLEAR will result in double free and - segfault - (`CVE-2019-18874 `__). - (patch by Riccardo Schirone) -- 1619_: [OpenBSD] compilation fails due to C syntax error. (patch by Nathan - Houghton) - -5.6.5 -===== - -2019-11-06 - -**Bug fixes** - -- 1615_: remove pyproject.toml as it was causing installation issues. - -5.6.4 -===== - -2019-11-04 - -**Enhancements** - -- 1527_: [Linux] added Process.cpu_times().iowait counter, which is the time - spent waiting for blocking I/O to complete. -- 1565_: add PEP 517/8 build backend and requirements specification for better - pip integration. (patch by Bernát Gábor) - -**Bug fixes** - -- 875_: [Windows] Process' cmdline(), environ() or cwd() may occasionally fail - with ERROR_PARTIAL_COPY which now gets translated to AccessDenied. -- 1126_: [Linux] cpu_affinity() segfaults on CentOS 5 / manylinux. - cpu_affinity() support for CentOS 5 was removed. -- 1528_: [AIX] compilation error on AIX 7.2 due to 32 vs 64 bit differences. - (patch by Arnon Yaari) -- 1535_: 'type' and 'family' fields returned by net_connections() are not - always turned into enums. -- 1536_: [NetBSD] process cmdline() erroneously raise ZombieProcess error if - cmdline has non encodable chars. -- 1546_: usage percent may be rounded to 0 on Python 2. -- 1552_: [Windows] getloadavg() math for calculating 5 and 15 mins values is - incorrect. -- 1568_: [Linux] use CC compiler env var if defined. -- 1570_: [Windows] `NtWow64*` syscalls fail to raise the proper error code -- 1585_: [OSX] calling close() (in C) on possible negative integers. (patch - by Athos Ribeiro) -- 1606_: [SunOS] compilation fails on SunOS 5.10. (patch by vser1) - -5.6.3 -===== - -2019-06-11 - -**Enhancements** - -- 1494_: [AIX] added support for Process.environ(). (patch by Arnon Yaari) - -**Bug fixes** - -- 1276_: [AIX] can't get whole cmdline(). (patch by Arnon Yaari) -- 1501_: [Windows] Process cmdline() and exe() raise unhandled "WinError 1168 - element not found" exceptions for "Registry" and "Memory Compression" psuedo - processes on Windows 10. -- 1526_: [NetBSD] process cmdline() could raise MemoryError. (patch by - Kamil Rytarowski) - -5.6.2 -===== - -2019-04-26 - -**Enhancements** - -- 604_: [Windows, Windows] add new psutil.getloadavg(), returning system load - average calculation, including on Windows (emulated). (patch by Ammar Askar) -- 1404_: [Linux] cpu_count(logical=False) uses a second method (read from - `/sys/devices/system/cpu/cpu[0-9]/topology/core_id`) in order to determine - the number of physical CPUs in case /proc/cpuinfo does not provide this info. -- 1458_: provide coloured test output. Also show failures on KeyboardInterrupt. -- 1464_: various docfixes (always point to python3 doc, fix links, etc.). -- 1476_: [Windows] it is now possible to set process high I/O priority - (ionice()).Also, I/O priority values are now exposed as 4 new constants: - IOPRIO_VERYLOW, IOPRIO_LOW, IOPRIO_NORMAL, IOPRIO_HIGH. -- 1478_: add make command to re-run tests failed on last run. - -**Bug fixes** - -- 1223_: [Windows] boot_time() may return value on Windows XP. -- 1456_: [Linux] cpu_freq() returns None instead of 0.0 when min/max not - available (patch by Alex Manuskin) -- 1462_: [Linux] (tests) make tests invariant to LANG setting (patch by - Benjamin Drung) -- 1463_: cpu_distribution.py script was broken. -- 1470_: [Linux] disk_partitions(): fix corner case when /etc/mtab doesn't - exist. (patch by Cedric Lamoriniere) -- 1471_: [SunOS] Process name() and cmdline() can return SystemError. (patch - by Daniel Beer) -- 1472_: [Linux] cpu_freq() does not return all CPUs on Rasbperry-pi 3. -- 1474_: fix formatting of psutil.tests() which mimicks 'ps aux' output. -- 1475_: [Windows] OSError.winerror attribute wasn't properly checked resuling - in WindowsError being raised instead of AccessDenied. -- 1477_: [Windows] wrong or absent error handling for private NTSTATUS Windows - APIs. Different process methods were affected by this. -- 1480_: [Windows] psutil.cpu_count(logical=False) could cause a crash due to - fixed read violation. (patch by Samer Masterson) -- 1486_: [AIX, SunOS] AttributeError when interacting with Process methods - involved into oneshot() context. -- 1491_: [SunOS] net_if_addrs(): free() ifap struct on error. (patch by - Agnewee) -- 1493_: [Linux] cpu_freq(): handle the case where - /sys/devices/system/cpu/cpufreq/ exists but is empty. - -5.6.1 -===== - -2019-03-11 - -**Bug fixes** - -- 1329_: [AIX] psutil doesn't compile on AIX 6.1. (patch by Arnon Yaari) -- 1448_: [Windows] crash on import due to rtlIpv6AddressToStringA not available - on Wine. -- 1451_: [Windows] Process.memory_full_info() segfaults. NtQueryVirtualMemory - is now used instead of QueryWorkingSet to calculate USS memory. - -5.6.0 -===== - -2019-03-05 - -**Enhancements** - -- 1379_: [Windows] Process suspend() and resume() now use NtSuspendProcess - and NtResumeProcess instead of stopping/resuming all threads of a process. - This is faster and more reliable (aka this is what ProcessHacker does). -- 1420_: [Windows] in case of exception disk_usage() now also shows the path - name. -- 1422_: [Windows] Windows APIs requiring to be dynamically loaded from DLL - libraries are now loaded only once on startup (instead of on per function - call) significantly speeding up different functions and methods. -- 1426_: [Windows] PAGESIZE and number of processors is now calculated on - startup. -- 1428_: in case of error, the traceback message now shows the underlying C - function called which failed. -- 1433_: new Process.parents() method. (idea by Ghislain Le Meur) -- 1437_: pids() are returned in sorted order. -- 1442_: python3 is now the default interpreter used by Makefile. - -**Bug fixes** - -- 1353_: process_iter() is now thread safe (it rarely raised TypeError). -- 1394_: [Windows] Process name() and exe() may erroneously return "Registry". - QueryFullProcessImageNameW is now used instead of GetProcessImageFileNameW - in order to prevent that. -- 1411_: [BSD] lack of Py_DECREF could cause segmentation fault on process - instantiation. -- 1419_: [Windows] Process.environ() raises NotImplementedError when querying - a 64-bit process in 32-bit-WoW mode. Now it raises AccessDenied. -- 1427_: [OSX] Process cmdline() and environ() may erroneously raise OSError - on failed malloc(). -- 1429_: [Windows] SE DEBUG was not properly set for current process. It is - now, and it should result in less AccessDenied exceptions for low-pid - processes. -- 1432_: [Windows] Process.memory_info_ex()'s USS memory is miscalculated - because we're not using the actual system PAGESIZE. -- 1439_: [NetBSD] Process.connections() may return incomplete results if using - oneshot(). -- 1447_: original exception wasn't turned into NSP/AD exceptions when using - Process.oneshot() ctx manager. - -**Incompatible API changes** - -- 1291_: [OSX] Process.memory_maps() was removed because inherently broken - (segfault) for years. - -5.5.1 -===== - -2019-02-15 - -**Enhancements** - -- 1348_: [Windows] on Windows >= 8.1 if Process.cmdline() fails due to - ERROR_ACCESS_DENIED attempt using NtQueryInformationProcess + - ProcessCommandLineInformation. (patch by EccoTheFlintstone) - -**Bug fixes** - -- 1394_: [Windows] Process.exe() returns "[Error 0] The operation completed - successfully" when Python process runs in "Virtual Secure Mode". -- 1402_: psutil exceptions' repr() show the internal private module path. -- 1408_: [AIX] psutil won't compile on AIX 7.1 due to missing header. (patch - by Arnon Yaari) - -5.5.0 -===== - -2019-01-23 - -**Enhancements** - -- 1350_: [FreeBSD] added support for sensors_temperatures(). (patch by Alex - Manuskin) -- 1352_: [FreeBSD] added support for CPU frequency. (patch by Alex Manuskin) - -**Bug fixes** - -- 1111_: Process.oneshot() is now thread safe. -- 1354_: [Linux] disk_io_counters() fails on Linux kernel 4.18+. -- 1357_: [Linux] Process' memory_maps() and io_counters() method are no longer - exposed if not supported by the kernel. -- 1368_: [Windows] fix psutil.Process().ionice(...) mismatch. (patch by - EccoTheFlintstone) -- 1370_: [Windows] improper usage of CloseHandle() may lead to override the - original error code when raising an exception. -- 1373_: incorrect handling of cache in Process.oneshot() context causes - Process instances to return incorrect results. -- 1376_: [Windows] OpenProcess() now uses PROCESS_QUERY_LIMITED_INFORMATION - access rights wherever possible, resulting in less AccessDenied exceptions - being thrown for system processes. -- 1376_: [Windows] check if variable is NULL before free()ing it. (patch by - EccoTheFlintstone) - -5.4.8 -===== - -2018-10-30 - -**Enhancements** - -- 1197_: [Linux] cpu_freq() is now implemented by parsing /proc/cpuinfo in case - /sys/devices/system/cpu/* filesystem is not available. -- 1310_: [Linux] psutil.sensors_temperatures() now parses /sys/class/thermal - in case /sys/class/hwmon fs is not available (e.g. Raspberry Pi). (patch - by Alex Manuskin) -- 1320_: [Posix] better compilation support when using g++ instead of gcc. - (patch by Jaime Fullaondo) - -**Bug fixes** - -- 715_: do not print exception on import time in case cpu_times() fails. -- 1004_: [Linux] Process.io_counters() may raise ValueError. -- 1277_: [OSX] available and used memory (psutil.virtual_memory()) metrics are - not accurate. -- 1294_: [Windows] psutil.Process().connections() may sometimes fail with - intermittent 0xC0000001. (patch by Sylvain Duchesne) -- 1307_: [Linux] disk_partitions() does not honour PROCFS_PATH. -- 1320_: [AIX] system CPU times (psutil.cpu_times()) were being reported with - ticks unit as opposed to seconds. (patch by Jaime Fullaondo) -- 1332_: [OSX] psutil debug messages are erroneously printed all the time. - (patch by Ilya Yanok) -- 1346_: [SunOS] net_connections() returns an empty list. (patch by Oleksii - Shevchuk) - -5.4.7 -===== - -2018-08-14 - -**Enhancements** - -- 1286_: [macOS] psutil.OSX constant is now deprecated in favor of new - psutil.MACOS. -- 1309_: [Linux] added psutil.STATUS_PARKED constant for Process.status(). -- 1321_: [Linux] add disk_io_counters() dual implementation relying on - /sys/block filesystem in case /proc/diskstats is not available. (patch by - Lawrence Ye) - -**Bug fixes** - -- 1209_: [macOS] Process.memory_maps() may fail with EINVAL due to poor - task_for_pid() syscall. AccessDenied is now raised instead. -- 1278_: [macOS] Process.threads() incorrectly return microseconds instead of - seconds. (patch by Nikhil Marathe) -- 1279_: [Linux, macOS, BSD] net_if_stats() may return ENODEV. -- 1294_: [Windows] psutil.Process().connections() may sometime fail with - MemoryError. (patch by sylvainduchesne) -- 1305_: [Linux] disk_io_stats() may report inflated r/w bytes values. -- 1309_: [Linux] Process.status() is unable to recognize "idle" and "parked" - statuses (returns '?'). -- 1313_: [Linux] disk_io_counters() can report inflated IO counters due to - erroneously counting base disk device and its partition(s) twice. -- 1323_: [Linux] sensors_temperatures() may fail with ValueError. - -5.4.6 -===== - -2018-06-07 - -**Bug fixes** - -- 1258_: [Windows] Process.username() may cause a segfault (Python interpreter - crash). (patch by Jean-Luc Migot) -- 1273_: net_if_addr() namedtuple's name has been renamed from "snic" to - "snicaddr". -- 1274_: [Linux] there was a small chance Process.children() may swallow - AccessDenied exceptions. - -5.4.5 -===== - -2018-04-14 - -**Bug fixes** - -- 1268_: setup.py's extra_require parameter requires latest setuptools version, - breaking quite a lot of installations. - -5.4.4 -===== - -2018-04-13 - -**Enhancements** - -- 1239_: [Linux] expose kernel "slab" memory for psutil.virtual_memory(). - (patch by Maxime Mouial) - -**Bug fixes** - -- 694_: [SunOS] cmdline() could be truncated at the 15th character when - reading it from /proc. An extra effort is made by reading it from process - address space first. (patch by Georg Sauthoff) -- 771_: [Windows] cpu_count() (both logical and physical) return a wrong - (smaller) number on systems using process groups (> 64 cores). -- 771_: [Windows] cpu_times(percpu=True) return fewer CPUs on systems using - process groups (> 64 cores). -- 771_: [Windows] cpu_stats() and cpu_freq() may return incorrect results on - systems using process groups (> 64 cores). -- 1193_: [SunOS] Return uid/gid from /proc/pid/psinfo if there aren't - enough permissions for /proc/pid/cred. (patch by Georg Sauthoff) -- 1194_: [SunOS] Return nice value from psinfo as getpriority() doesn't - support real-time processes. (patch by Georg Sauthoff) -- 1194_: [SunOS] Fix double free in psutil_proc_cpu_num(). (patch by Georg - Sauthoff) -- 1194_: [SunOS] Fix undefined behavior related to strict-aliasing rules - and warnings. (patch by Georg Sauthoff) -- 1210_: [Linux] cpu_percent() steal time may remain stuck at 100% due to Linux - erroneously reporting a decreased steal time between calls. (patch by Arnon - Yaari) -- 1216_: fix compatibility with python 2.6 on Windows (patch by Dan Vinakovsky) -- 1222_: [Linux] Process.memory_full_info() was erroneously summing "Swap:" and - "SwapPss:". Same for "Pss:" and "SwapPss". Not anymore. -- 1224_: [Windows] Process.wait() may erroneously raise TimeoutExpired. -- 1238_: [Linux] sensors_battery() may return None in case battery is not - listed as "BAT0" under /sys/class/power_supply. -- 1240_: [Windows] cpu_times() float loses accuracy in a long running system. - (patch by stswandering) -- 1245_: [Linux] sensors_temperatures() may fail with IOError "no such file". -- 1255_: [FreeBSD] swap_memory() stats were erroneously represented in KB. - (patch by Denis Krienbühl) - -**Backward compatibility** - -- 771_: [Windows] cpu_count(logical=False) on Windows XP and Vista is no - longer supported and returns None. - -5.4.3 -===== - -*2018-01-01* - -**Enhancements** - -- 775_: disk_partitions() on Windows return mount points. - -**Bug fixes** - -- 1193_: pids() may return False on macOS. - -5.4.2 -===== - -*2017-12-07* - -**Enhancements** - -- 1173_: introduced PSUTIL_DEBUG environment variable which can be set in order - to print useful debug messages on stderr (useful in case of nasty errors). -- 1177_: added support for sensors_battery() on macOS. (patch by Arnon Yaari) -- 1183_: Process.children() is 2x faster on UNIX and 2.4x faster on Linux. -- 1188_: deprecated method Process.memory_info_ex() now warns by using - FutureWarning instead of DeprecationWarning. - -**Bug fixes** - -- 1152_: [Windows] disk_io_counters() may return an empty dict. -- 1169_: [Linux] users() "hostname" returns username instead. (patch by - janderbrain) -- 1172_: [Windows] `make test` does not work. -- 1179_: [Linux] Process.cmdline() is now able to splits cmdline args for - misbehaving processes which overwrite /proc/pid/cmdline and use spaces - instead of null bytes as args separator. -- 1181_: [macOS] Process.memory_maps() may raise ENOENT. -- 1187_: [macOS] pids() does not return PID 0 on recent macOS versions. - -5.4.1 -===== - -*2017-11-08* - -**Enhancements** - -- 1164_: [AIX] add support for Process.num_ctx_switches(). (patch by Arnon - Yaari) -- 1053_: abandon Python 3.3 support (psutil still works but it's no longer - tested). - -**Bug fixes** - -- 1150_: [Windows] when a process is terminate()d now the exit code is set to - SIGTERM instead of 0. (patch by Akos Kiss) -- 1151_: python -m psutil.tests fail -- 1154_: [AIX] psutil won't compile on AIX 6.1.0. (patch by Arnon Yaari) -- 1167_: [Windows] net_io_counter() packets count now include also non-unicast - packets. (patch by Matthew Long) - -5.4.0 -===== - -*2017-10-12* - -**Enhancements** - -- 1123_: [AIX] added support for AIX platform. (patch by Arnon Yaari) - -**Bug fixes** - -- 1009_: [Linux] sensors_temperatures() may crash with IOError. -- 1012_: [Windows] disk_io_counters()'s read_time and write_time were expressed - in tens of micro seconds instead of milliseconds. -- 1127_: [macOS] invalid reference counting in Process.open_files() may lead to - segfault. (patch by Jakub Bacic) -- 1129_: [Linux] sensors_fans() may crash with IOError. (patch by Sebastian - Saip) -- 1131_: [SunOS] fix compilation warnings. (patch by Arnon Yaari) -- 1133_: [Windows] can't compile on newer versions of Visual Studio 2017 15.4. - (patch by Max Bélanger) -- 1138_: [Linux] can't compile on CentOS 5.0 and RedHat 5.0. - (patch by Prodesire) - -5.3.1 -===== - -*2017-09-10* - -**Enhancements** - -- 1124_: documentation moved to http://psutil.readthedocs.io - -**Bug fixes** - -- 1105_: [FreeBSD] psutil does not compile on FreeBSD 12. -- 1125_: [BSD] net_connections() raises TypeError. - -**Compatibility notes** - -- 1120_: .exe files for Windows are no longer uploaded on PyPI as per PEP-527; - only wheels are provided. - -5.3.0 -===== - -*2017-09-01* - -**Enhancements** - -- 802_: disk_io_counters() and net_io_counters() numbers no longer wrap - (restart from 0). Introduced a new "nowrap" argument. -- 928_: psutil.net_connections() and psutil.Process.connections() "laddr" and - "raddr" are now named tuples. -- 1015_: swap_memory() now relies on /proc/meminfo instead of sysinfo() syscall - so that it can be used in conjunction with PROCFS_PATH in order to retrieve - memory info about Linux containers such as Docker and Heroku. -- 1022_: psutil.users() provides a new "pid" field. -- 1025_: process_iter() accepts two new parameters in order to invoke - Process.as_dict(): "attrs" and "ad_value". With this you can iterate over all - processes in one shot without needing to catch NoSuchProcess and do list/dict - comprehensions. -- 1040_: implemented full unicode support. -- 1051_: disk_usage() on Python 3 is now able to accept bytes. -- 1058_: test suite now enables all warnings by default. -- 1060_: source distribution is dynamically generated so that it only includes - relevant files. -- 1079_: [FreeBSD] net_connections()'s fd number is now being set for real - (instead of -1). (patch by Gleb Smirnoff) -- 1091_: [SunOS] implemented Process.environ(). (patch by Oleksii Shevchuk) - -**Bug fixes** - -- 989_: [Windows] boot_time() may return a negative value. -- 1007_: [Windows] boot_time() can have a 1 sec fluctuation between calls; the - value of the first call is now cached so that boot_time() always returns the - same value if fluctuation is <= 1 second. -- 1013_: [FreeBSD] psutil.net_connections() may return incorrect PID. (patch - by Gleb Smirnoff) -- 1014_: [Linux] Process class can mask legitimate ENOENT exceptions as - NoSuchProcess. -- 1016_: disk_io_counters() raises RuntimeError on a system with no disks. -- 1017_: net_io_counters() raises RuntimeError on a system with no network - cards installed. -- 1021_: [Linux] open_files() may erroneously raise NoSuchProcess instead of - skipping a file which gets deleted while open files are retrieved. -- 1029_: [macOS, FreeBSD] Process.connections('unix') on Python 3 doesn't - properly handle unicode paths and may raise UnicodeDecodeError. -- 1033_: [macOS, FreeBSD] memory leak for net_connections() and - Process.connections() when retrieving UNIX sockets (kind='unix'). -- 1040_: fixed many unicode related issues such as UnicodeDecodeError on - Python 3 + UNIX and invalid encoded data on Windows. -- 1042_: [FreeBSD] psutil won't compile on FreeBSD 12. -- 1044_: [macOS] different Process methods incorrectly raise AccessDenied for - zombie processes. -- 1046_: [Windows] disk_partitions() on Windows overrides user's SetErrorMode. -- 1047_: [Windows] Process username(): memory leak in case exception is thrown. -- 1048_: [Windows] users()'s host field report an invalid IP address. -- 1050_: [Windows] Process.memory_maps memory() leaks memory. -- 1055_: cpu_count() is no longer cached; this is useful on systems such as - Linux where CPUs can be disabled at runtime. This also reflects on - Process.cpu_percent() which no longer uses the cache. -- 1058_: fixed Python warnings. -- 1062_: disk_io_counters() and net_io_counters() raise TypeError if no disks - or NICs are installed on the system. -- 1063_: [NetBSD] net_connections() may list incorrect sockets. -- 1064_: [NetBSD] swap_memory() may segfault in case of error. -- 1065_: [OpenBSD] Process.cmdline() may raise SystemError. -- 1067_: [NetBSD] Process.cmdline() leaks memory if process has terminated. -- 1069_: [FreeBSD] Process.cpu_num() may return 255 for certain kernel - processes. -- 1071_: [Linux] cpu_freq() may raise IOError on old RedHat distros. -- 1074_: [FreeBSD] sensors_battery() raises OSError in case of no battery. -- 1075_: [Windows] net_if_addrs(): inet_ntop() return value is not checked. -- 1077_: [SunOS] net_if_addrs() shows garbage addresses on SunOS 5.10. - (patch by Oleksii Shevchuk) -- 1077_: [SunOS] net_connections() does not work on SunOS 5.10. (patch by - Oleksii Shevchuk) -- 1079_: [FreeBSD] net_connections() didn't list locally connected sockets. - (patch by Gleb Smirnoff) -- 1085_: cpu_count() return value is now checked and forced to None if <= 1. -- 1087_: Process.cpu_percent() guard against cpu_count() returning None and - assumes 1 instead. -- 1093_: [SunOS] memory_maps() shows wrong 64 bit addresses. -- 1094_: [Windows] psutil.pid_exists() may lie. Also, all process APIs relying - on OpenProcess Windows API now check whether the PID is actually running. -- 1098_: [Windows] Process.wait() may erroneously return sooner, when the PID - is still alive. -- 1099_: [Windows] Process.terminate() may raise AccessDenied even if the - process already died. -- 1101_: [Linux] sensors_temperatures() may raise ENODEV. - -**Porting notes** - -- 1039_: returned types consolidation: - - Windows / Process.cpu_times(): fields #3 and #4 were int instead of float - - Linux / FreeBSD: connections('unix'): raddr is now set to "" instead of - None - - OpenBSD: connections('unix'): laddr and raddr are now set to "" instead of - None -- 1040_: all strings are encoded by using OS fs encoding. -- 1040_: the following Windows APIs on Python 2 now return a string instead of - unicode: - - Process.memory_maps().path - - WindowsService.bin_path() - - WindowsService.description() - - WindowsService.display_name() - - WindowsService.username() - -5.2.2 -===== - -*2017-04-10* - -**Bug fixes** - -- 1000_: fixed some setup.py warnings. -- 1002_: [SunOS] remove C macro which will not be available on new Solaris - versions. (patch by Danek Duvall) -- 1004_: [Linux] Process.io_counters() may raise ValueError. -- 1006_: [Linux] cpu_freq() may return None on some Linux versions does not - support the function; now the function is not declared instead. -- 1009_: [Linux] sensors_temperatures() may raise OSError. -- 1010_: [Linux] virtual_memory() may raise ValueError on Ubuntu 14.04. - -5.2.1 -===== - -*2017-03-24* - -**Bug fixes** - -- 981_: [Linux] cpu_freq() may return an empty list. -- 993_: [Windows] Process.memory_maps() on Python 3 may raise - UnicodeDecodeError. -- 996_: [Linux] sensors_temperatures() may not show all temperatures. -- 997_: [FreeBSD] virtual_memory() may fail due to missing sysctl parameter on - FreeBSD 12. - -5.2.0 -===== - -*2017-03-05* - -**Enhancements** - -- 971_: [Linux] Add psutil.sensors_fans() function. (patch by Nicolas Hennion) -- 976_: [Windows] Process.io_counters() has 2 new fields: *other_count* and - *other_bytes*. -- 976_: [Linux] Process.io_counters() has 2 new fields: *read_chars* and - *write_chars*. - -**Bug fixes** - -- 872_: [Linux] can now compile on Linux by using MUSL C library. -- 985_: [Windows] Fix a crash in `Process.open_files` when the worker thread - for `NtQueryObject` times out. -- 986_: [Linux] Process.cwd() may raise NoSuchProcess instead of ZombieProcess. - -5.1.3 -===== - -**Bug fixes** - -- 971_: [Linux] sensors_temperatures() didn't work on CentOS 7. -- 973_: cpu_percent() may raise ZeroDivisionError. - -5.1.2 -===== - -*2017-02-03* - -**Bug fixes** - -- 966_: [Linux] sensors_battery().power_plugged may erroneously return None on - Python 3. -- 968_: [Linux] disk_io_counters() raises TypeError on python 3. -- 970_: [Linux] sensors_battery()'s name and label fields on Python 3 are bytes - instead of str. - -5.1.1 -===== - -*2017-02-03* - -**Enhancements** - -- 966_: [Linux] sensors_battery().percent is a float and is more precise. - -**Bug fixes** - -- 964_: [Windows] Process.username() and psutil.users() may return badly - decoding character on Python 3. -- 965_: [Linux] disk_io_counters() may miscalculate sector size and report the - wrong number of bytes read and written. -- 966_: [Linux] sensors_battery() may fail with "no such file error". -- 966_: [Linux] sensors_battery().power_plugged may lie. - -5.1.0 -===== - -*2017-02-01* - -**Enhancements** - -- 357_: added psutil.Process.cpu_num() (what CPU a process is on). -- 371_: added psutil.sensors_temperatures() (Linux only). -- 941_: added psutil.cpu_freq() (CPU frequency). -- 955_: added psutil.sensors_battery() (Linux, Windows, only). -- 956_: cpu_affinity([]) can now be used as an alias to set affinity against - all eligible CPUs. - -**Bug fixes** - -- 687_: [Linux] pid_exists() no longer returns True if passed a process thread - ID. -- 948_: cannot install psutil with PYTHONOPTIMIZE=2. -- 950_: [Windows] Process.cpu_percent() was calculated incorrectly and showed - higher number than real usage. -- 951_: [Windows] the uploaded wheels for Python 3.6 64 bit didn't work. -- 959_: psutil exception objects could not be pickled. -- 960_: Popen.wait() did not return the correct negative exit status if process - is ``kill()``ed by a signal. -- 961_: [Windows] WindowsService.description() may fail with - ERROR_MUI_FILE_NOT_FOUND. - -5.0.1 -===== - -*2016-12-21* - -**Enhancements** - -- 939_: tar.gz distribution went from 1.8M to 258K. -- 811_: [Windows] provide a more meaningful error message if trying to use - psutil on unsupported Windows XP. - -**Bug fixes** - -- 609_: [SunOS] psutil does not compile on Solaris 10. -- 936_: [Windows] fix compilation error on VS 2013 (patch by Max Bélanger). -- 940_: [Linux] cpu_percent() and cpu_times_percent() was calculated - incorrectly as "iowait", "guest" and "guest_nice" times were not properly - taken into account. -- 944_: [OpenBSD] psutil.pids() was omitting PID 0. - -5.0.0 -===== - -*2016-11-06* - -**Enhncements** - -- 799_: new Process.oneshot() context manager making Process methods around - +2x faster in general and from +2x to +6x faster on Windows. -- 943_: better error message in case of version conflict on import. - -**Bug fixes** - -- 932_: [NetBSD] net_connections() and Process.connections() may fail without - raising an exception. -- 933_: [Windows] memory leak in cpu_stats() and WindowsService.description(). - -4.4.2 -===== - -*2016-10-26* - -**Bug fixes** - -- 931_: psutil no longer compiles on Solaris. - -4.4.1 -===== - -*2016-10-25* - -**Bug fixes** - -- 927_: ``Popen.__del__`` may cause maximum recursion depth error. - -4.4.0 -===== - -*2016-10-23* - -**Enhancements** - -- 874_: [Windows] net_if_addrs() returns also the netmask. -- 887_: [Linux] virtual_memory()'s 'available' and 'used' values are more - precise and match "free" cmdline utility. "available" also takes into - account LCX containers preventing "available" to overflow "total". -- 891_: procinfo.py script has been updated and provides a lot more info. - -**Bug fixes** - -- 514_: [macOS] possibly fix Process.memory_maps() segfault (critical!). -- 783_: [macOS] Process.status() may erroneously return "running" for zombie - processes. -- 798_: [Windows] Process.open_files() returns and empty list on Windows 10. -- 825_: [Linux] cpu_affinity; fix possible double close and use of unopened - socket. -- 880_: [Windows] Handle race condition inside psutil_net_connections. -- 885_: ValueError is raised if a negative integer is passed to cpu_percent() - functions. -- 892_: [Linux] Process.cpu_affinity([-1]) raise SystemError with no error - set; now ValueError is raised. -- 906_: [BSD] disk_partitions(all=False) returned an empty list. Now the - argument is ignored and all partitions are always returned. -- 907_: [FreeBSD] Process.exe() may fail with OSError(ENOENT). -- 908_: [macOS, BSD] different process methods could errounesuly mask the real - error for high-privileged PIDs and raise NoSuchProcess and AccessDenied - instead of OSError and RuntimeError. -- 909_: [macOS] Process open_files() and connections() methods may raise - OSError with no exception set if process is gone. -- 916_: [macOS] fix many compilation warnings. - -4.3.1 -===== - -*2016-09-01* - -**Enhancements** - -- 881_: "make install" now works also when using a virtual env. - -**Bug fixes** - -- 854_: Process.as_dict() raises ValueError if passed an erroneous attrs name. -- 857_: [SunOS] Process cpu_times(), cpu_percent(), threads() amd memory_maps() - may raise RuntimeError if attempting to query a 64bit process with a 32bit - python. "Null" values are returned as a fallback. -- 858_: Process.as_dict() should not return memory_info_ex() because it's - deprecated. -- 863_: [Windows] memory_map truncates addresses above 32 bits -- 866_: [Windows] win_service_iter() and services in general are not able to - handle unicode service names / descriptions. -- 869_: [Windows] Process.wait() may raise TimeoutExpired with wrong timeout - unit (ms instead of sec). -- 870_: [Windows] Handle leak inside psutil_get_process_data. - -4.3.0 -===== - -*2016-06-18* - -**Enhancements** - -- 819_: [Linux] different speedup improvements: - Process.ppid() is 20% faster - Process.status() is 28% faster - Process.name() is 25% faster - Process.num_threads is 20% faster on Python 3 - -**Bug fixes** - -- 810_: [Windows] Windows wheels are incompatible with pip 7.1.2. -- 812_: [NetBSD] fix compilation on NetBSD-5.x. -- 823_: [NetBSD] virtual_memory() raises TypeError on Python 3. -- 829_: [UNIX] psutil.disk_usage() percent field takes root reserved space - into account. -- 816_: [Windows] fixed net_io_counter() values wrapping after 4.3GB in - Windows Vista (NT 6.0) and above using 64bit values from newer win APIs. - -4.2.0 -===== - -*2016-05-14* - -**Enhancements** - -- 795_: [Windows] new APIs to deal with Windows services: win_service_iter() - and win_service_get(). -- 800_: [Linux] psutil.virtual_memory() returns a new "shared" memory field. -- 819_: [Linux] speedup /proc parsing: - - Process.ppid() is 20% faster - - Process.status() is 28% faster - - Process.name() is 25% faster - - Process.num_threads is 20% faster on Python 3 - -**Bug fixes** - -- 797_: [Linux] net_if_stats() may raise OSError for certain NIC cards. -- 813_: Process.as_dict() should ignore extraneous attribute names which gets - attached to the Process instance. - -4.1.0 -===== - -*2016-03-12* - -**Enhancements** - -- 777_: [Linux] Process.open_files() on Linux return 3 new fields: position, - mode and flags. -- 779_: Process.cpu_times() returns two new fields, 'children_user' and - 'children_system' (always set to 0 on macOS and Windows). -- 789_: [Windows] psutil.cpu_times() return two new fields: "interrupt" and - "dpc". Same for psutil.cpu_times_percent(). -- 792_: new psutil.cpu_stats() function returning number of CPU ctx switches - interrupts, soft interrupts and syscalls. - -**Bug fixes** - -- 774_: [FreeBSD] net_io_counters() dropout is no longer set to 0 if the kernel - provides it. -- 776_: [Linux] Process.cpu_affinity() may erroneously raise NoSuchProcess. - (patch by wxwright) -- 780_: [macOS] psutil does not compile with some gcc versions. -- 786_: net_if_addrs() may report incomplete MAC addresses. -- 788_: [NetBSD] virtual_memory()'s buffers and shared values were set to 0. -- 790_: [macOS] psutil won't compile on macOS 10.4. - -4.0.0 -===== - -*2016-02-17* - -**Enhancements** - -- 523_: [Linux, FreeBSD] disk_io_counters() return a new "busy_time" field. -- 660_: [Windows] make.bat is smarter in finding alternative VS install - locations. (patch by mpderbec) -- 732_: Process.environ(). (patch by Frank Benkstein) -- 753_: [Linux, macOS, Windows] Process USS and PSS (Linux) "real" memory stats. - (patch by Eric Rahm) -- 755_: Process.memory_percent() "memtype" parameter. -- 758_: tests now live in psutil namespace. -- 760_: expose OS constants (psutil.LINUX, psutil.macOS, etc.) -- 756_: [Linux] disk_io_counters() return 2 new fields: read_merged_count and - write_merged_count. -- 762_: new scripts/procsmem.py script. - -**Bug fixes** - -- 685_: [Linux] virtual_memory() provides wrong results on systems with a lot - of physical memory. -- 704_: [Solaris] psutil does not compile on Solaris sparc. -- 734_: on Python 3 invalid UTF-8 data is not correctly handled for process - name(), cwd(), exe(), cmdline() and open_files() methods resulting in - UnicodeDecodeError exceptions. 'surrogateescape' error handler is now - used as a workaround for replacing the corrupted data. -- 737_: [Windows] when the bitness of psutil and the target process was - different cmdline() and cwd() could return a wrong result or incorrectly - report an AccessDenied error. -- 741_: [OpenBSD] psutil does not compile on mips64. -- 751_: [Linux] fixed call to Py_DECREF on possible Null object. -- 754_: [Linux] cmdline() can be wrong in case of zombie process. -- 759_: [Linux] Process.memory_maps() may return paths ending with " (deleted)" -- 761_: [Windows] psutil.boot_time() wraps to 0 after 49 days. -- 764_: [NetBSD] fix compilation on NetBSD-6.x. -- 766_: [Linux] net_connections() can't handle malformed /proc/net/unix file. -- 767_: [Linux] disk_io_counters() may raise ValueError on 2.6 kernels and it's - broken on 2.4 kernels. -- 770_: [NetBSD] disk_io_counters() metrics didn't update. - -3.4.2 -===== - -*2016-01-20* - -**Enhancements** - -- 728_: [Solaris] exposed psutil.PROCFS_PATH constant to change the default - location of /proc filesystem. - -**Bug fixes** - -- 724_: [FreeBSD] psutil.virtual_memory().total is incorrect. -- 730_: [FreeBSD] psutil.virtual_memory() crashes. - -3.4.1 -===== - -*2016-01-15* - -**Enhancements** - -- 557_: [NetBSD] added NetBSD support. (contributed by Ryo Onodera and - Thomas Klausner) -- 708_: [Linux] psutil.net_connections() and Process.connections() on Python 2 - can be up to 3x faster in case of many connections. - Also psutil.Process.memory_maps() is slightly faster. -- 718_: process_iter() is now thread safe. - -**Bug fixes** - -- 714_: [OpenBSD] virtual_memory().cached value was always set to 0. -- 715_: don't crash at import time if cpu_times() fail for some reason. -- 717_: [Linux] Process.open_files fails if deleted files still visible. -- 722_: [Linux] swap_memory() no longer crashes if sin/sout can't be determined - due to missing /proc/vmstat. -- 724_: [FreeBSD] virtual_memory().total is slightly incorrect. - -3.3.0 -===== - -*2015-11-25* - -**Enhancements** - -- 558_: [Linux] exposed psutil.PROCFS_PATH constant to change the default - location of /proc filesystem. -- 615_: [OpenBSD] added OpenBSD support. (contributed by Landry Breuil) - -**Bug fixes** - -- 692_: [UNIX] Process.name() is no longer cached as it may change. - -3.2.2 -===== - -*2015-10-04* - -**Bug fixes** - -- 517_: [SunOS] net_io_counters failed to detect network interfaces - correctly on Solaris 10 -- 541_: [FreeBSD] disk_io_counters r/w times were expressed in seconds instead - of milliseconds. (patch by dasumin) -- 610_: [SunOS] fix build and tests on Solaris 10 -- 623_: [Linux] process or system connections raises ValueError if IPv6 is not - supported by the system. -- 678_: [Linux] can't install psutil due to bug in setup.py. -- 688_: [Windows] compilation fails with MSVC 2015, Python 3.5. (patch by - Mike Sarahan) - -3.2.1 -===== - -*2015-09-03* - -**Bug fixes** - -- 677_: [Linux] can't install psutil due to bug in setup.py. - -3.2.0 -===== - -*2015-09-02* - -**Enhancements** - -- 644_: [Windows] added support for CTRL_C_EVENT and CTRL_BREAK_EVENT signals - to use with Process.send_signal(). -- 648_: CI test integration for macOS. (patch by Jeff Tang) -- 663_: [UNIX] net_if_addrs() now returns point-to-point (VPNs) addresses. -- 655_: [Windows] different issues regarding unicode handling were fixed. On - Python 2 all APIs returning a string will now return an encoded version of it - by using sys.getfilesystemencoding() codec. The APIs involved are: - - psutil.net_if_addrs() - - psutil.net_if_stats() - - psutil.net_io_counters() - - psutil.Process.cmdline() - - psutil.Process.name() - - psutil.Process.username() - - psutil.users() - -**Bug fixes** - -- 513_: [Linux] fixed integer overflow for RLIM_INFINITY. -- 641_: [Windows] fixed many compilation warnings. (patch by Jeff Tang) -- 652_: [Windows] net_if_addrs() UnicodeDecodeError in case of non-ASCII NIC - names. -- 655_: [Windows] net_if_stats() UnicodeDecodeError in case of non-ASCII NIC - names. -- 659_: [Linux] compilation error on Suse 10. (patch by maozguttman) -- 664_: [Linux] compilation error on Alpine Linux. (patch by Bart van Kleef) -- 670_: [Windows] segfgault of net_if_addrs() in case of non-ASCII NIC names. - (patch by sk6249) -- 672_: [Windows] compilation fails if using Windows SDK v8.0. (patch by - Steven Winfield) -- 675_: [Linux] net_connections(); UnicodeDecodeError may occur when listing - UNIX sockets. - -3.1.1 -===== - -*2015-07-15* - -**Bug fixes** - -- 603_: [Linux] ionice_set value range is incorrect. (patch by spacewander) -- 645_: [Linux] psutil.cpu_times_percent() may produce negative results. -- 656_: 'from psutil import *' does not work. - -3.1.0 -===== - -*2015-07-15* - -**Enhancements** - -- 534_: [Linux] disk_partitions() added support for ZFS filesystems. -- 646_: continuous tests integration for Windows with - https://ci.appveyor.com/project/giampaolo/psutil. -- 647_: new dev guide: - https://github.com/giampaolo/psutil/blob/master/docs/DEVGUIDE.rst -- 651_: continuous code quality test integration with scrutinizer-ci.com - -**Bug fixes** - -- 340_: [Windows] Process.open_files() no longer hangs. Instead it uses a - thred which times out and skips the file handle in case it's taking too long - to be retrieved. (patch by Jeff Tang, PR #597) -- 627_: [Windows] Process.name() no longer raises AccessDenied for pids owned - by another user. -- 636_: [Windows] Process.memory_info() raise AccessDenied. -- 637_: [UNIX] raise exception if trying to send signal to Process PID 0 as it - will affect os.getpid()'s process group instead of PID 0. -- 639_: [Linux] Process.cmdline() can be truncated. -- 640_: [Linux] *connections functions may swallow errors and return an - incomplete list of connnections. -- 642_: repr() of exceptions is incorrect. -- 653_: [Windows] Add inet_ntop function for Windows XP to support IPv6. -- 641_: [Windows] Replace deprecated string functions with safe equivalents. - -3.0.1 -===== - -*2015-06-18* - -**Bug fixes** - -- 632_: [Linux] better error message if cannot parse process UNIX connections. -- 634_: [Linux] Proces.cmdline() does not include empty string arguments. -- 635_: [UNIX] crash on module import if 'enum' package is installed on python - < 3.4. - -3.0.0 -===== - -*2015-06-13* - -**Enhancements** - -- 250_: new psutil.net_if_stats() returning NIC statistics (isup, duplex, - speed, MTU). -- 376_: new psutil.net_if_addrs() returning all NIC addresses a-la ifconfig. -- 469_: on Python >= 3.4 ``IOPRIO_CLASS_*`` and ``*_PRIORITY_CLASS`` constants - returned by psutil.Process' ionice() and nice() methods are enums instead of - plain integers. -- 581_: add .gitignore. (patch by Gabi Davar) -- 582_: connection constants returned by psutil.net_connections() and - psutil.Process.connections() were turned from int to enums on Python > 3.4. -- 587_: Move native extension into the package. -- 589_: Process.cpu_affinity() accepts any kind of iterable (set, tuple, ...), - not only lists. -- 594_: all deprecated APIs were removed. -- 599_: [Windows] process name() can now be determined for all processes even - when running as a limited user. -- 602_: pre-commit GIT hook. -- 629_: enhanced support for py.test and nose test discovery and tests run. -- 616_: [Windows] Add inet_ntop function for Windows XP. - -**Bug fixes** - -- 428_: [all UNIXes except Linux] correct handling of zombie processes; - introduced new ZombieProcess exception class. -- 512_: [BSD] fix segfault in net_connections(). -- 555_: [Linux] psutil.users() correctly handles ":0" as an alias for - "localhost" -- 579_: [Windows] Fixed open_files() for PID>64K. -- 579_: [Windows] fixed many compiler warnings. -- 585_: [FreeBSD] net_connections() may raise KeyError. -- 586_: [FreeBSD] cpu_affinity() segfaults on set in case an invalid CPU - number is provided. -- 593_: [FreeBSD] Process().memory_maps() segfaults. -- 606_: Process.parent() may swallow NoSuchProcess exceptions. -- 611_: [SunOS] net_io_counters has send and received swapped -- 614_: [Linux]: cpu_count(logical=False) return the number of physical CPUs - instead of physical cores. -- 618_: [SunOS] swap tests fail on Solaris when run as normal user -- 628_: [Linux] Process.name() truncates process name in case it contains - spaces or parentheses. - -2.2.1 -===== - -*2015-02-02* - -**Bug fixes** - -- 496_: [Linux] fix "ValueError: ambiguos inode with multiple PIDs references" - (patch by Bruno Binet) - -2.2.0 -===== - -*2015-01-06* - -**Enhancements** - -- 521_: drop support for Python 2.4 and 2.5. -- 553_: new examples/pstree.py script. -- 564_: C extension version mismatch in case the user messed up with psutil - installation or with sys.path is now detected at import time. -- 568_: New examples/pidof.py script. -- 569_: [FreeBSD] add support for process CPU affinity. - -**Bug fixes** - -- 496_: [Solaris] can't import psutil. -- 547_: [UNIX] Process.username() may raise KeyError if UID can't be resolved. -- 551_: [Windows] get rid of the unicode hack for net_io_counters() NIC names. -- 556_: [Linux] lots of file handles were left open. -- 561_: [Linux] net_connections() might skip some legitimate UNIX sockets. - (patch by spacewander) -- 565_: [Windows] use proper encoding for psutil.Process.username() and - psutil.users(). (patch by Sylvain Mouquet) -- 567_: [Linux] in the alternative implementation of CPU affinity PyList_Append - and Py_BuildValue return values are not checked. -- 569_: [FreeBSD] fix memory leak in psutil.cpu_count(logical=False). -- 571_: [Linux] Process.open_files() might swallow AccessDenied exceptions and - return an incomplete list of open files. - -2.1.3 -===== - -*2014-09-26* - -- 536_: [Linux]: fix "undefined symbol: CPU_ALLOC" compilation error. - -2.1.2 -===== - -*2014-09-21* - -**Enhancements** - -- 407_: project moved from Google Code to Github; code moved from Mercurial - to Git. -- 492_: use tox to run tests on multiple python versions. (patch by msabramo) -- 505_: [Windows] distribution as wheel packages. -- 511_: new examples/ps.py sample code. - -**Bug fixes** - -- 340_: [Windows] Process.get_open_files() no longer hangs. (patch by - Jeff Tang) -- 501_: [Windows] disk_io_counters() may return negative values. -- 503_: [Linux] in rare conditions Process exe(), open_files() and - connections() methods can raise OSError(ESRCH) instead of NoSuchProcess. -- 504_: [Linux] can't build RPM packages via setup.py -- 506_: [Linux] python 2.4 support was broken. -- 522_: [Linux] Process.cpu_affinity() might return EINVAL. (patch by David - Daeschler) -- 529_: [Windows] Process.exe() may raise unhandled WindowsError exception - for PIDs 0 and 4. (patch by Jeff Tang) -- 530_: [Linux] psutil.disk_io_counters() may crash on old Linux distros - (< 2.6.5) (patch by Yaolong Huang) -- 533_: [Linux] Process.memory_maps() may raise TypeError on old Linux distros. - -2.1.1 -===== - -*2014-04-30* - -**Bug fixes** - -- 446_: [Windows] fix encoding error when using net_io_counters() on Python 3. - (patch by Szigeti Gabor Niif) -- 460_: [Windows] net_io_counters() wraps after 4G. -- 491_: [Linux] psutil.net_connections() exceptions. (patch by Alexander Grothe) - -2.1.0 -===== - -*2014-04-08* - -**Enhancements** - -- 387_: system-wide open connections a-la netstat. - -**Bug fixes** - -- 421_: [Solaris] psutil does not compile on SunOS 5.10 (patch by Naveed - Roudsari) -- 489_: [Linux] psutil.disk_partitions() return an empty list. - -2.0.0 -===== - -*2014-03-10* - -**Enhancements** - -- 424_: [Windows] installer for Python 3.X 64 bit. -- 427_: number of logical and physical CPUs (psutil.cpu_count()). -- 447_: psutil.wait_procs() timeout parameter is now optional. -- 452_: make Process instances hashable and usable with set()s. -- 453_: tests on Python < 2.7 require unittest2 module. -- 459_: add a make file for running tests and other repetitive tasks (also - on Windows). -- 463_: make timeout parameter of cpu_percent* functions default to 0.0 'cause - it's a common trap to introduce slowdowns. -- 468_: move documentation to readthedocs.com. -- 477_: process cpu_percent() is about 30% faster. (suggested by crusaderky) -- 478_: [Linux] almost all APIs are about 30% faster on Python 3.X. -- 479_: long deprecated psutil.error module is gone; exception classes now - live in "psutil" namespace only. - -**Bug fixes** - -- 193_: psutil.Popen constructor can throw an exception if the spawned process - terminates quickly. -- 340_: [Windows] process get_open_files() no longer hangs. (patch by - jtang@vahna.net) -- 443_: [Linux] fix a potential overflow issue for Process.set_cpu_affinity() - on systems with more than 64 CPUs. -- 448_: [Windows] get_children() and ppid() memory leak (patch by Ulrich - Klank). -- 457_: [POSIX] pid_exists() always returns True for PID 0. -- 461_: namedtuples are not pickle-able. -- 466_: [Linux] process exe improper null bytes handling. (patch by - Gautam Singh) -- 470_: wait_procs() might not wait. (patch by crusaderky) -- 471_: [Windows] process exe improper unicode handling. (patch by - alex@mroja.net) -- 473_: psutil.Popen.wait() does not set returncode attribute. -- 474_: [Windows] Process.cpu_percent() is no longer capped at 100%. -- 476_: [Linux] encoding error for process name and cmdline. - -**API changes** - -For the sake of consistency a lot of psutil APIs have been renamed. -In most cases accessing the old names will work but it will cause a -DeprecationWarning. - -- psutil.* module level constants have being replaced by functions: - - +-----------------------+-------------------------------+ - | Old name | Replacement | - +=======================+===============================+ - | psutil.NUM_CPUS | psutil.cpu_cpunt() | - +-----------------------+-------------------------------+ - | psutil.BOOT_TIME | psutil.boot_time() | - +-----------------------+-------------------------------+ - | psutil.TOTAL_PHYMEM | psutil.virtual_memory().total | - +-----------------------+-------------------------------+ - -- Renamed psutil.* functions: - - +--------------------------+-------------------------------+ - | Old name | Replacement | - +==========================+===============================+ - | - psutil.get_pid_list() | psutil.pids() | - +--------------------------+-------------------------------+ - | - psutil.get_users() | psutil.users() | - +--------------------------+-------------------------------+ - | - psutil.get_boot_time() | psutil.boot_time() | - +--------------------------+-------------------------------+ - -- All psutil.Process ``get_*`` methods lost the ``get_`` prefix. - get_ext_memory_info() renamed to memory_info_ex(). - Assuming "p = psutil.Process()": - - +--------------------------+----------------------+ - | Old name | Replacement | - +==========================+======================+ - | p.get_children() | p.children() | - +--------------------------+----------------------+ - | p.get_connections() | p.connections() | - +--------------------------+----------------------+ - | p.get_cpu_affinity() | p.cpu_affinity() | - +--------------------------+----------------------+ - | p.get_cpu_percent() | p.cpu_percent() | - +--------------------------+----------------------+ - | p.get_cpu_times() | p.cpu_times() | - +--------------------------+----------------------+ - | p.get_ext_memory_info() | p.memory_info_ex() | - +--------------------------+----------------------+ - | p.get_io_counters() | p.io_counters() | - +--------------------------+----------------------+ - | p.get_ionice() | p.ionice() | - +--------------------------+----------------------+ - | p.get_memory_info() | p.memory_info() | - +--------------------------+----------------------+ - | p.get_memory_maps() | p.memory_maps() | - +--------------------------+----------------------+ - | p.get_memory_percent() | p.memory_percent() | - +--------------------------+----------------------+ - | p.get_nice() | p.nice() | - +--------------------------+----------------------+ - | p.get_num_ctx_switches() | p.num_ctx_switches() | - +--------------------------+----------------------+ - | p.get_num_fds() | p.num_fds() | - +--------------------------+----------------------+ - | p.get_num_threads() | p.num_threads() | - +--------------------------+----------------------+ - | p.get_open_files() | p.open_files() | - +--------------------------+----------------------+ - | p.get_rlimit() | p.rlimit() | - +--------------------------+----------------------+ - | p.get_threads() | p.threads() | - +--------------------------+----------------------+ - | p.getcwd() | p.cwd() | - +--------------------------+----------------------+ - -- All psutil.Process ``set_*`` methods lost the ``set_`` prefix. - Assuming "p = psutil.Process()": - - +----------------------+---------------------------------+ - | Old name | Replacement | - +======================+=================================+ - | p.set_nice() | p.nice(value) | - +----------------------+---------------------------------+ - | p.set_ionice() | p.ionice(ioclass, value=None) | - +----------------------+---------------------------------+ - | p.set_cpu_affinity() | p.cpu_affinity(cpus) | - +----------------------+---------------------------------+ - | p.set_rlimit() | p.rlimit(resource, limits=None) | - +----------------------+---------------------------------+ - -- Except for 'pid' all psutil.Process class properties have been turned into - methods. This is the only case which there are no aliases. - Assuming "p = psutil.Process()": - - +---------------+-----------------+ - | Old name | Replacement | - +===============+=================+ - | p.name | p.name() | - +---------------+-----------------+ - | p.parent | p.parent() | - +---------------+-----------------+ - | p.ppid | p.ppid() | - +---------------+-----------------+ - | p.exe | p.exe() | - +---------------+-----------------+ - | p.cmdline | p.cmdline() | - +---------------+-----------------+ - | p.status | p.status() | - +---------------+-----------------+ - | p.uids | p.uids() | - +---------------+-----------------+ - | p.gids | p.gids() | - +---------------+-----------------+ - | p.username | p.username() | - +---------------+-----------------+ - | p.create_time | p.create_time() | - +---------------+-----------------+ - -- timeout parameter of cpu_percent* functions defaults to 0.0 instead of 0.1. -- long deprecated psutil.error module is gone; exception classes now live in - "psutil" namespace only. -- Process instances' "retcode" attribute returned by psutil.wait_procs() has - been renamed to "returncode" for consistency with subprocess.Popen. - -1.2.1 -===== - -*2013-11-25* - -**Bug fixes** - -- 348_: [Windows XP] fixed "ImportError: DLL load failed" occurring on module - import. -- 425_: [Solaris] crash on import due to failure at determining BOOT_TIME. -- 443_: [Linux] can't set CPU affinity on systems with more than 64 cores. - -1.2.0 -===== - -*2013-11-20* - -**Enhancements** - -- 439_: assume os.getpid() if no argument is passed to psutil.Process - constructor. -- 440_: new psutil.wait_procs() utility function which waits for multiple - processes to terminate. - -**Bug fixes** - -- 348_: [Windows XP/Vista] fix "ImportError: DLL load failed" occurring on - module import. - -1.1.3 -===== - -*2013-11-07* - -**Bug fixes** - -- 442_: [Linux] psutil won't compile on certain version of Linux because of - missing prlimit(2) syscall. - -1.1.2 -===== - -*2013-10-22* - -**Bug fixes** - -- 442_: [Linux] psutil won't compile on Debian 6.0 because of missing - prlimit(2) syscall. - -1.1.1 -===== - -*2013-10-08* - -**Bug fixes** - -- 442_: [Linux] psutil won't compile on kernels < 2.6.36 due to missing - prlimit(2) syscall. - -1.1.0 -===== - -*2013-09-28* - -**Enhancements** - -- 410_: host tar.gz and windows binary files are on PyPI. -- 412_: [Linux] get/set process resource limits. -- 415_: [Windows] Process.get_children() is an order of magnitude faster. -- 426_: [Windows] Process.name is an order of magnitude faster. -- 431_: [UNIX] Process.name is slightly faster because it unnecessarily - retrieved also process cmdline. - -**Bug fixes** - -- 391_: [Windows] psutil.cpu_times_percent() returns negative percentages. -- 408_: STATUS_* and CONN_* constants don't properly serialize on JSON. -- 411_: [Windows] examples/disk_usage.py may pop-up a GUI error. -- 413_: [Windows] Process.get_memory_info() leaks memory. -- 414_: [Windows] Process.exe on Windows XP may raise ERROR_INVALID_PARAMETER. -- 416_: psutil.disk_usage() doesn't work well with unicode path names. -- 430_: [Linux] process IO counters report wrong number of r/w syscalls. -- 435_: [Linux] psutil.net_io_counters() might report erreneous NIC names. -- 436_: [Linux] psutil.net_io_counters() reports a wrong 'dropin' value. - -**API changes** - -- 408_: turn STATUS_* and CONN_* constants into plain Python strings. - -1.0.1 -===== - -*2013-07-12* - -**Bug fixes** - -- 405_: network_io_counters(pernic=True) no longer works as intended in 1.0.0. - -1.0.0 -===== - -*2013-07-10* - -**Enhancements** - -- 18_: Solaris support (yay!) (thanks Justin Venus) -- 367_: Process.get_connections() 'status' strings are now constants. -- 380_: test suite exits with non-zero on failure. (patch by floppymaster) -- 391_: introduce unittest2 facilities and provide workarounds if unittest2 - is not installed (python < 2.7). - -**Bug fixes** - -- 374_: [Windows] negative memory usage reported if process uses a lot of - memory. -- 379_: [Linux] Process.get_memory_maps() may raise ValueError. -- 394_: [macOS] Mapped memory regions report incorrect file name. -- 404_: [Linux] sched_*affinity() are implicitly declared. (patch by Arfrever) - -**API changes** - -- Process.get_connections() 'status' field is no longer a string but a - constant object (psutil.CONN_*). -- Process.get_connections() 'local_address' and 'remote_address' fields - renamed to 'laddr' and 'raddr'. -- psutil.network_io_counters() renamed to psutil.net_io_counters(). - -0.7.1 -===== - -*2013-05-03* - -**Bug fixes** - -- 325_: [BSD] psutil.virtual_memory() can raise SystemError. - (patch by Jan Beich) -- 370_: [BSD] Process.get_connections() requires root. (patch by John Baldwin) -- 372_: [BSD] different process methods raise NoSuchProcess instead of - AccessDenied. - -0.7.0 -===== - -*2013-04-12* - -**Enhancements** - -- 233_: code migrated to Mercurial (yay!) -- 246_: psutil.error module is deprecated and scheduled for removal. -- 328_: [Windows] process IO nice/priority support. -- 359_: psutil.get_boot_time() -- 361_: [Linux] psutil.cpu_times() now includes new 'steal', 'guest' and - 'guest_nice' fields available on recent Linux kernels. - Also, psutil.cpu_percent() is more accurate. -- 362_: cpu_times_percent() (per-CPU-time utilization as a percentage) - -**Bug fixes** - -- 234_: [Windows] disk_io_counters() fails to list certain disks. -- 264_: [Windows] use of psutil.disk_partitions() may cause a message box to - appear. -- 313_: [Linux] psutil.virtual_memory() and psutil.swap_memory() can crash on - certain exotic Linux flavors having an incomplete /proc interface. - If that's the case we now set the unretrievable stats to 0 and raise a - RuntimeWarning. -- 315_: [macOS] fix some compilation warnings. -- 317_: [Windows] cannot set process CPU affinity above 31 cores. -- 319_: [Linux] process get_memory_maps() raises KeyError 'Anonymous' on Debian - squeeze. -- 321_: [UNIX] Process.ppid property is no longer cached as the kernel may set - the ppid to 1 in case of a zombie process. -- 323_: [macOS] disk_io_counters()'s read_time and write_time parameters were - reporting microseconds not milliseconds. (patch by Gregory Szorc) -- 331_: Process cmdline is no longer cached after first acces as it may change. -- 333_: [macOS] Leak of Mach ports on macOS (patch by rsesek@google.com) -- 337_: [Linux] process methods not working because of a poor /proc - implementation will raise NotImplementedError rather than RuntimeError - and Process.as_dict() will not blow up. (patch by Curtin1060) -- 338_: [Linux] disk_io_counters() fails to find some disks. -- 339_: [FreeBSD] get_pid_list() can allocate all the memory on system. -- 341_: [Linux] psutil might crash on import due to error in retrieving system - terminals map. -- 344_: [FreeBSD] swap_memory() might return incorrect results due to - kvm_open(3) not being called. (patch by Jean Sebastien) -- 338_: [Linux] disk_io_counters() fails to find some disks. -- 351_: [Windows] if psutil is compiled with mingw32 (provided installers for - py2.4 and py2.5 are) disk_io_counters() will fail. (Patch by m.malycha) -- 353_: [macOS] get_users() returns an empty list on macOS 10.8. -- 356_: Process.parent now checks whether parent PID has been reused in which - case returns None. -- 365_: Process.set_nice() should check PID has not been reused by another - process. -- 366_: [FreeBSD] get_memory_maps(), get_num_fds(), get_open_files() and - getcwd() Process methods raise RuntimeError instead of AccessDenied. - -**API changes** - -- Process.cmdline property is no longer cached after first access. -- Process.ppid property is no longer cached after first access. -- [Linux] Process methods not working because of a poor /proc implementation - will raise NotImplementedError instead of RuntimeError. -- psutil.error module is deprecated and scheduled for removal. - -0.6.1 -===== - -*2012-08-16* - -**Enhancements** - -- 316_: process cmdline property now makes a better job at guessing the process - executable from the cmdline. - -**Bug fixes** - -- 316_: process exe was resolved in case it was a symlink. -- 318_: python 2.4 compatibility was broken. - -**API changes** - -- process exe can now return an empty string instead of raising AccessDenied. -- process exe is no longer resolved in case it's a symlink. - -0.6.0 -===== - -*2012-08-13* - -**Enhancements** - -- 216_: [POSIX] get_connections() UNIX sockets support. -- 220_: [FreeBSD] get_connections() has been rewritten in C and no longer - requires lsof. -- 222_: [macOS] add support for process cwd. -- 261_: process extended memory info. -- 295_: [macOS] process executable path is now determined by asking the OS - instead of being guessed from process cmdline. -- 297_: [macOS] the Process methods below were always raising AccessDenied for - any process except the current one. Now this is no longer true. Also - they are 2.5x faster. - - name - - get_memory_info() - - get_memory_percent() - - get_cpu_times() - - get_cpu_percent() - - get_num_threads() -- 300_: examples/pmap.py script. -- 301_: process_iter() now yields processes sorted by their PIDs. -- 302_: process number of voluntary and involuntary context switches. -- 303_: [Windows] the Process methods below were always raising AccessDenied - for any process not owned by current user. Now this is no longer true: - - create_time - - get_cpu_times() - - get_cpu_percent() - - get_memory_info() - - get_memory_percent() - - get_num_handles() - - get_io_counters() -- 305_: add examples/netstat.py script. -- 311_: system memory functions has been refactorized and rewritten and now - provide a more detailed and consistent representation of the system - memory. New psutil.virtual_memory() function provides the following - memory amounts: - - total - - available - - percent - - used - - active [POSIX] - - inactive [POSIX] - - buffers (BSD, Linux) - - cached (BSD, macOS) - - wired (macOS, BSD) - - shared [FreeBSD] - New psutil.swap_memory() provides: - - total - - used - - free - - percent - - sin (no. of bytes the system has swapped in from disk (cumulative)) - - sout (no. of bytes the system has swapped out from disk (cumulative)) - All old memory-related functions are deprecated. - Also two new example scripts were added: free.py and meminfo.py. -- 312_: psutil.network_io_counters() namedtuple includes 4 new fields: - errin, errout dropin and dropout, reflecting the number of packets - dropped and with errors. - -**Bug fixes** - -- 298_: [macOS and BSD] memory leak in get_num_fds(). -- 299_: potential memory leak every time PyList_New(0) is used. -- 303_: [Windows] potential heap corruption in get_num_threads() and - get_status() Process methods. -- 305_: [FreeBSD] psutil can't compile on FreeBSD 9 due to removal of utmp.h. -- 306_: at C level, errors are not checked when invoking Py* functions which - create or manipulate Python objects leading to potential memory related - errors and/or segmentation faults. -- 307_: [FreeBSD] values returned by psutil.network_io_counters() are wrong. -- 308_: [BSD / Windows] psutil.virtmem_usage() wasn't actually returning - information about swap memory usage as it was supposed to do. It does - now. -- 309_: get_open_files() might not return files which can not be accessed - due to limited permissions. AccessDenied is now raised instead. - -**API changes** - -- psutil.phymem_usage() is deprecated (use psutil.virtual_memory()) -- psutil.virtmem_usage() is deprecated (use psutil.swap_memory()) -- psutil.phymem_buffers() on Linux is deprecated (use psutil.virtual_memory()) -- psutil.cached_phymem() on Linux is deprecated (use psutil.virtual_memory()) -- [Windows and BSD] psutil.virtmem_usage() now returns information about swap - memory instead of virtual memory. - -0.5.1 -===== - -*2012-06-29* - -**Enhancements** - -- 293_: [Windows] process executable path is now determined by asking the OS - instead of being guessed from process cmdline. - -**Bug fixes** - -- 292_: [Linux] race condition in process files/threads/connections. -- 294_: [Windows] Process CPU affinity is only able to set CPU #0. - -0.5.0 -===== - -*2012-06-27* - -**Enhancements** - -- 195_: [Windows] number of handles opened by process. -- 209_: psutil.disk_partitions() now provides also mount options. -- 229_: list users currently connected on the system (psutil.get_users()). -- 238_: [Linux, Windows] process CPU affinity (get and set). -- 242_: Process.get_children(recursive=True): return all process - descendants. -- 245_: [POSIX] Process.wait() incrementally consumes less CPU cycles. -- 257_: [Windows] removed Windows 2000 support. -- 258_: [Linux] Process.get_memory_info() is now 0.5x faster. -- 260_: process's mapped memory regions. (Windows patch by wj32.64, macOS patch - by Jeremy Whitlock) -- 262_: [Windows] psutil.disk_partitions() was slow due to inspecting the - floppy disk drive also when "all" argument was False. -- 273_: psutil.get_process_list() is deprecated. -- 274_: psutil no longer requires 2to3 at installation time in order to work - with Python 3. -- 278_: new Process.as_dict() method. -- 281_: ppid, name, exe, cmdline and create_time properties of Process class - are now cached after being accessed. -- 282_: psutil.STATUS_* constants can now be compared by using their string - representation. -- 283_: speedup Process.is_running() by caching its return value in case the - process is terminated. -- 284_: [POSIX] per-process number of opened file descriptors. -- 287_: psutil.process_iter() now caches Process instances between calls. -- 290_: Process.nice property is deprecated in favor of new get_nice() and - set_nice() methods. - -**Bug fixes** - -- 193_: psutil.Popen constructor can throw an exception if the spawned process - terminates quickly. -- 240_: [macOS] incorrect use of free() for Process.get_connections(). -- 244_: [POSIX] Process.wait() can hog CPU resources if called against a - process which is not our children. -- 248_: [Linux] psutil.network_io_counters() might return erroneous NIC names. -- 252_: [Windows] process getcwd() erroneously raise NoSuchProcess for - processes owned by another user. It now raises AccessDenied instead. -- 266_: [Windows] psutil.get_pid_list() only shows 1024 processes. - (patch by Amoser) -- 267_: [macOS] Process.get_connections() - an erroneous remote address was - returned. (Patch by Amoser) -- 272_: [Linux] Porcess.get_open_files() - potential race condition can lead to - unexpected NoSuchProcess exception. Also, we can get incorrect reports - of not absolutized path names. -- 275_: [Linux] Process.get_io_counters() erroneously raise NoSuchProcess on - old Linux versions. Where not available it now raises - NotImplementedError. -- 286_: Process.is_running() doesn't actually check whether PID has been - reused. -- 314_: Process.get_children() can sometimes return non-children. - -**API changes** - -- Process.nice property is deprecated in favor of new get_nice() and set_nice() - methods. -- psutil.get_process_list() is deprecated. -- ppid, name, exe, cmdline and create_time properties of Process class are now - cached after being accessed, meaning NoSuchProcess will no longer be raised - in case the process is gone in the meantime. -- psutil.STATUS_* constants can now be compared by using their string - representation. - -0.4.1 -===== - -*2011-12-14* - -**Bug fixes** - -- 228_: some example scripts were not working with python 3. -- 230_: [Windows / macOS] memory leak in Process.get_connections(). -- 232_: [Linux] psutil.phymem_usage() can report erroneous values which are - different than "free" command. -- 236_: [Windows] memory/handle leak in Process's get_memory_info(), - suspend() and resume() methods. - -0.4.0 -===== - -*2011-10-29* - -**Enhancements** - -- 150_: network I/O counters. (macOS and Windows patch by Jeremy Whitlock) -- 154_: [FreeBSD] add support for process getcwd() -- 157_: [Windows] provide installer for Python 3.2 64-bit. -- 198_: Process.wait(timeout=0) can now be used to make wait() return - immediately. -- 206_: disk I/O counters. (macOS and Windows patch by Jeremy Whitlock) -- 213_: examples/iotop.py script. -- 217_: Process.get_connections() now has a "kind" argument to filter - for connections with different criteria. -- 221_: [FreeBSD] Process.get_open_files has been rewritten in C and no longer - relies on lsof. -- 223_: examples/top.py script. -- 227_: examples/nettop.py script. - -**Bug fixes** - -- 135_: [macOS] psutil cannot create Process object. -- 144_: [Linux] no longer support 0 special PID. -- 188_: [Linux] psutil import error on Linux ARM architectures. -- 194_: [POSIX] psutil.Process.get_cpu_percent() now reports a percentage over - 100 on multicore processors. -- 197_: [Linux] Process.get_connections() is broken on platforms not - supporting IPv6. -- 200_: [Linux] psutil.NUM_CPUS not working on armel and sparc architectures - and causing crash on module import. -- 201_: [Linux] Process.get_connections() is broken on big-endian - architectures. -- 211_: Process instance can unexpectedly raise NoSuchProcess if tested for - equality with another object. -- 218_: [Linux] crash at import time on Debian 64-bit because of a missing - line in /proc/meminfo. -- 226_: [FreeBSD] crash at import time on FreeBSD 7 and minor. - -0.3.0 -===== - -*2011-07-08* - -**Enhancements** - -- 125_: system per-cpu percentage utilization and times. -- 163_: per-process associated terminal (TTY). -- 171_: added get_phymem() and get_virtmem() functions returning system - memory information (total, used, free) and memory percent usage. - total_* avail_* and used_* memory functions are deprecated. -- 172_: disk usage statistics. -- 174_: mounted disk partitions. -- 179_: setuptools is now used in setup.py - -**Bug fixes** - -- 159_: SetSeDebug() does not close handles or unset impersonation on return. -- 164_: [Windows] wait function raises a TimeoutException when a process - returns -1 . -- 165_: process.status raises an unhandled exception. -- 166_: get_memory_info() leaks handles hogging system resources. -- 168_: psutil.cpu_percent() returns erroneous results when used in - non-blocking mode. (patch by Philip Roberts) -- 178_: macOS - Process.get_threads() leaks memory -- 180_: [Windows] Process's get_num_threads() and get_threads() methods can - raise NoSuchProcess exception while process still exists. - -0.2.1 -===== - -*2011-03-20* - -**Enhancements** - -- 64_: per-process I/O counters. -- 116_: per-process wait() (wait for process to terminate and return its exit - code). -- 134_: per-process get_threads() returning information (id, user and kernel - times) about threads opened by process. -- 136_: process executable path on FreeBSD is now determined by asking the - kernel instead of guessing it from cmdline[0]. -- 137_: per-process real, effective and saved user and group ids. -- 140_: system boot time. -- 142_: per-process get and set niceness (priority). -- 143_: per-process status. -- 147_: per-process I/O nice (priority) - Linux only. -- 148_: psutil.Popen class which tidies up subprocess.Popen and psutil.Process - in a unique interface. -- 152_: [macOS] get_process_open_files() implementation has been rewritten - in C and no longer relies on lsof resulting in a 3x speedup. -- 153_: [macOS] get_process_connection() implementation has been rewritten - in C and no longer relies on lsof resulting in a 3x speedup. - -**Bug fixes** - -- 83_: process cmdline is empty on macOS 64-bit. -- 130_: a race condition can cause IOError exception be raised on - Linux if process disappears between open() and subsequent read() calls. -- 145_: WindowsError was raised instead of psutil.AccessDenied when using - process resume() or suspend() on Windows. -- 146_: 'exe' property on Linux can raise TypeError if path contains NULL - bytes. -- 151_: exe and getcwd() for PID 0 on Linux return inconsistent data. - -**API changes** - -- Process "uid" and "gid" properties are deprecated in favor of "uids" and - "gids" properties. - -0.2.0 -===== - -*2010-11-13* - -**Enhancements** - -- 79_: per-process open files. -- 88_: total system physical cached memory. -- 88_: total system physical memory buffers used by the kernel. -- 91_: per-process send_signal() and terminate() methods. -- 95_: NoSuchProcess and AccessDenied exception classes now provide "pid", - "name" and "msg" attributes. -- 97_: per-process children. -- 98_: Process.get_cpu_times() and Process.get_memory_info now return - a namedtuple instead of a tuple. -- 103_: per-process opened TCP and UDP connections. -- 107_: add support for Windows 64 bit. (patch by cjgohlke) -- 111_: per-process executable name. -- 113_: exception messages now include process name and pid. -- 114_: process username Windows implementation has been rewritten in pure - C and no longer uses WMI resulting in a big speedup. Also, pywin32 is no - longer required as a third-party dependancy. (patch by wj32) -- 117_: added support for Windows 2000. -- 123_: psutil.cpu_percent() and psutil.Process.cpu_percent() accept a - new 'interval' parameter. -- 129_: per-process number of threads. - -**Bug fixes** - -- 80_: fixed warnings when installing psutil with easy_install. -- 81_: psutil fails to compile with Visual Studio. -- 94_: suspend() raises OSError instead of AccessDenied. -- 86_: psutil didn't compile against FreeBSD 6.x. -- 102_: orphaned process handles obtained by using OpenProcess in C were - left behind every time Process class was instantiated. -- 111_: path and name Process properties report truncated or erroneous - values on UNIX. -- 120_: cpu_percent() always returning 100% on macOS. -- 112_: uid and gid properties don't change if process changes effective - user/group id at some point. -- 126_: ppid, uid, gid, name, exe, cmdline and create_time properties are - no longer cached and correctly raise NoSuchProcess exception if the process - disappears. - -**API changes** - -- psutil.Process.path property is deprecated and works as an alias for "exe" - property. -- psutil.Process.kill(): signal argument was removed - to send a signal to the - process use send_signal(signal) method instead. -- psutil.Process.get_memory_info() returns a nametuple instead of a tuple. -- psutil.cpu_times() returns a nametuple instead of a tuple. -- New psutil.Process methods: get_open_files(), get_connections(), - send_signal() and terminate(). -- ppid, uid, gid, name, exe, cmdline and create_time properties are no longer - cached and raise NoSuchProcess exception if process disappears. -- psutil.cpu_percent() no longer returns immediately (see issue 123). -- psutil.Process.get_cpu_percent() and psutil.cpu_percent() no longer returns - immediately by default (see issue 123). - -0.1.3 -===== - -*2010-03-02* - -**Enhancements** - -- 14_: per-process username -- 51_: per-process current working directory (Windows and Linux only) -- 59_: Process.is_running() is now 10 times faster -- 61_: added supoprt for FreeBSD 64 bit -- 71_: implemented suspend/resume process -- 75_: python 3 support - -**Bug fixes** - -- 36_: process cpu_times() and memory_info() functions succeeded also for dead - processes while a NoSuchProcess exception is supposed to be raised. -- 48_: incorrect size for mib array defined in getcmdargs for BSD -- 49_: possible memory leak due to missing free() on error condition on -- 50_: fixed getcmdargs() memory fragmentation on BSD -- 55_: test_pid_4 was failing on Windows Vista -- 57_: some unit tests were failing on systems where no swap memory is - available -- 58_: is_running() is now called before kill() to make sure we are going - to kill the correct process. -- 73_: virtual memory size reported on macOS includes shared library size -- 77_: NoSuchProcess wasn't raised on Process.create_time if kill() was - used first. - -0.1.2 -===== - -*2009-05-06* - -**Enhancements** - -- 32_: Per-process CPU user/kernel times -- 33_: Process create time -- 34_: Per-process CPU utilization percentage -- 38_: Per-process memory usage (bytes) -- 41_: Per-process memory utilization (percent) -- 39_: System uptime -- 43_: Total system virtual memory -- 46_: Total system physical memory -- 44_: Total system used/free virtual and physical memory - -**Bug fixes** - -- 36_: [Windows] NoSuchProcess not raised when accessing timing methods. -- 40_: test_get_cpu_times() failing on FreeBSD and macOS. -- 42_: [Windows] get_memory_percent() raises AccessDenied. - -0.1.1 -===== - -*2009-03-06* - -**Enhancements** - -- 4_: FreeBSD support for all functions of psutil -- 9_: Process.uid and Process.gid now retrieve process UID and GID. -- 11_: Support for parent/ppid - Process.parent property returns a - Process object representing the parent process, and Process.ppid returns - the parent PID. -- 12_ & 15: - NoSuchProcess exception now raised when creating an object - for a nonexistent process, or when retrieving information about a process - that has gone away. -- 21_: AccessDenied exception created for raising access denied errors - from OSError or WindowsError on individual platforms. -- 26_: psutil.process_iter() function to iterate over processes as - Process objects with a generator. -- Process objects can now also be compared with == operator for equality - (PID, name, command line are compared). - -**Bug fixes** - -- 16_: [Windows] Special case for "System Idle Process" (PID 0) which - otherwise would return an "invalid parameter" exception. -- 17_: get_process_list() ignores NoSuchProcess and AccessDenied - exceptions during building of the list. -- 22_: [Windows] Process(0).kill() was failing with an unset exception. -- 23_: Special case for pid_exists(0) -- 24_: [Windows] Process(0).kill() now raises AccessDenied exception instead - of WindowsError. -- 30_: psutil.get_pid_list() was returning two ins - -.. _1: https://github.com/giampaolo/psutil/issues/1 -.. _2: https://github.com/giampaolo/psutil/issues/2 -.. _3: https://github.com/giampaolo/psutil/issues/3 -.. _4: https://github.com/giampaolo/psutil/issues/4 -.. _5: https://github.com/giampaolo/psutil/issues/5 -.. _6: https://github.com/giampaolo/psutil/issues/6 -.. _7: https://github.com/giampaolo/psutil/issues/7 -.. _8: https://github.com/giampaolo/psutil/issues/8 -.. _9: https://github.com/giampaolo/psutil/issues/9 -.. _10: https://github.com/giampaolo/psutil/issues/10 -.. _11: https://github.com/giampaolo/psutil/issues/11 -.. _12: https://github.com/giampaolo/psutil/issues/12 -.. _13: https://github.com/giampaolo/psutil/issues/13 -.. _14: https://github.com/giampaolo/psutil/issues/14 -.. _15: https://github.com/giampaolo/psutil/issues/15 -.. _16: https://github.com/giampaolo/psutil/issues/16 -.. _17: https://github.com/giampaolo/psutil/issues/17 -.. _18: https://github.com/giampaolo/psutil/issues/18 -.. _19: https://github.com/giampaolo/psutil/issues/19 -.. _20: https://github.com/giampaolo/psutil/issues/20 -.. _21: https://github.com/giampaolo/psutil/issues/21 -.. _22: https://github.com/giampaolo/psutil/issues/22 -.. _23: https://github.com/giampaolo/psutil/issues/23 -.. _24: https://github.com/giampaolo/psutil/issues/24 -.. _25: https://github.com/giampaolo/psutil/issues/25 -.. _26: https://github.com/giampaolo/psutil/issues/26 -.. _27: https://github.com/giampaolo/psutil/issues/27 -.. _28: https://github.com/giampaolo/psutil/issues/28 -.. _29: https://github.com/giampaolo/psutil/issues/29 -.. _30: https://github.com/giampaolo/psutil/issues/30 -.. _31: https://github.com/giampaolo/psutil/issues/31 -.. _32: https://github.com/giampaolo/psutil/issues/32 -.. _33: https://github.com/giampaolo/psutil/issues/33 -.. _34: https://github.com/giampaolo/psutil/issues/34 -.. _35: https://github.com/giampaolo/psutil/issues/35 -.. _36: https://github.com/giampaolo/psutil/issues/36 -.. _37: https://github.com/giampaolo/psutil/issues/37 -.. _38: https://github.com/giampaolo/psutil/issues/38 -.. _39: https://github.com/giampaolo/psutil/issues/39 -.. _40: https://github.com/giampaolo/psutil/issues/40 -.. _41: https://github.com/giampaolo/psutil/issues/41 -.. _42: https://github.com/giampaolo/psutil/issues/42 -.. _43: https://github.com/giampaolo/psutil/issues/43 -.. _44: https://github.com/giampaolo/psutil/issues/44 -.. _45: https://github.com/giampaolo/psutil/issues/45 -.. _46: https://github.com/giampaolo/psutil/issues/46 -.. _47: https://github.com/giampaolo/psutil/issues/47 -.. _48: https://github.com/giampaolo/psutil/issues/48 -.. _49: https://github.com/giampaolo/psutil/issues/49 -.. _50: https://github.com/giampaolo/psutil/issues/50 -.. _51: https://github.com/giampaolo/psutil/issues/51 -.. _52: https://github.com/giampaolo/psutil/issues/52 -.. _53: https://github.com/giampaolo/psutil/issues/53 -.. _54: https://github.com/giampaolo/psutil/issues/54 -.. _55: https://github.com/giampaolo/psutil/issues/55 -.. _56: https://github.com/giampaolo/psutil/issues/56 -.. _57: https://github.com/giampaolo/psutil/issues/57 -.. _58: https://github.com/giampaolo/psutil/issues/58 -.. _59: https://github.com/giampaolo/psutil/issues/59 -.. _60: https://github.com/giampaolo/psutil/issues/60 -.. _61: https://github.com/giampaolo/psutil/issues/61 -.. _62: https://github.com/giampaolo/psutil/issues/62 -.. _63: https://github.com/giampaolo/psutil/issues/63 -.. _64: https://github.com/giampaolo/psutil/issues/64 -.. _65: https://github.com/giampaolo/psutil/issues/65 -.. _66: https://github.com/giampaolo/psutil/issues/66 -.. _67: https://github.com/giampaolo/psutil/issues/67 -.. _68: https://github.com/giampaolo/psutil/issues/68 -.. _69: https://github.com/giampaolo/psutil/issues/69 -.. _70: https://github.com/giampaolo/psutil/issues/70 -.. _71: https://github.com/giampaolo/psutil/issues/71 -.. _72: https://github.com/giampaolo/psutil/issues/72 -.. _73: https://github.com/giampaolo/psutil/issues/73 -.. _74: https://github.com/giampaolo/psutil/issues/74 -.. _75: https://github.com/giampaolo/psutil/issues/75 -.. _76: https://github.com/giampaolo/psutil/issues/76 -.. _77: https://github.com/giampaolo/psutil/issues/77 -.. _78: https://github.com/giampaolo/psutil/issues/78 -.. _79: https://github.com/giampaolo/psutil/issues/79 -.. _80: https://github.com/giampaolo/psutil/issues/80 -.. _81: https://github.com/giampaolo/psutil/issues/81 -.. _82: https://github.com/giampaolo/psutil/issues/82 -.. _83: https://github.com/giampaolo/psutil/issues/83 -.. _84: https://github.com/giampaolo/psutil/issues/84 -.. _85: https://github.com/giampaolo/psutil/issues/85 -.. _86: https://github.com/giampaolo/psutil/issues/86 -.. _87: https://github.com/giampaolo/psutil/issues/87 -.. _88: https://github.com/giampaolo/psutil/issues/88 -.. _89: https://github.com/giampaolo/psutil/issues/89 -.. _90: https://github.com/giampaolo/psutil/issues/90 -.. _91: https://github.com/giampaolo/psutil/issues/91 -.. _92: https://github.com/giampaolo/psutil/issues/92 -.. _93: https://github.com/giampaolo/psutil/issues/93 -.. _94: https://github.com/giampaolo/psutil/issues/94 -.. _95: https://github.com/giampaolo/psutil/issues/95 -.. _96: https://github.com/giampaolo/psutil/issues/96 -.. _97: https://github.com/giampaolo/psutil/issues/97 -.. _98: https://github.com/giampaolo/psutil/issues/98 -.. _99: https://github.com/giampaolo/psutil/issues/99 -.. _100: https://github.com/giampaolo/psutil/issues/100 -.. _101: https://github.com/giampaolo/psutil/issues/101 -.. _102: https://github.com/giampaolo/psutil/issues/102 -.. _103: https://github.com/giampaolo/psutil/issues/103 -.. _104: https://github.com/giampaolo/psutil/issues/104 -.. _105: https://github.com/giampaolo/psutil/issues/105 -.. _106: https://github.com/giampaolo/psutil/issues/106 -.. _107: https://github.com/giampaolo/psutil/issues/107 -.. _108: https://github.com/giampaolo/psutil/issues/108 -.. _109: https://github.com/giampaolo/psutil/issues/109 -.. _110: https://github.com/giampaolo/psutil/issues/110 -.. _111: https://github.com/giampaolo/psutil/issues/111 -.. _112: https://github.com/giampaolo/psutil/issues/112 -.. _113: https://github.com/giampaolo/psutil/issues/113 -.. _114: https://github.com/giampaolo/psutil/issues/114 -.. _115: https://github.com/giampaolo/psutil/issues/115 -.. _116: https://github.com/giampaolo/psutil/issues/116 -.. _117: https://github.com/giampaolo/psutil/issues/117 -.. _118: https://github.com/giampaolo/psutil/issues/118 -.. _119: https://github.com/giampaolo/psutil/issues/119 -.. _120: https://github.com/giampaolo/psutil/issues/120 -.. _121: https://github.com/giampaolo/psutil/issues/121 -.. _122: https://github.com/giampaolo/psutil/issues/122 -.. _123: https://github.com/giampaolo/psutil/issues/123 -.. _124: https://github.com/giampaolo/psutil/issues/124 -.. _125: https://github.com/giampaolo/psutil/issues/125 -.. _126: https://github.com/giampaolo/psutil/issues/126 -.. _127: https://github.com/giampaolo/psutil/issues/127 -.. _128: https://github.com/giampaolo/psutil/issues/128 -.. _129: https://github.com/giampaolo/psutil/issues/129 -.. _130: https://github.com/giampaolo/psutil/issues/130 -.. _131: https://github.com/giampaolo/psutil/issues/131 -.. _132: https://github.com/giampaolo/psutil/issues/132 -.. _133: https://github.com/giampaolo/psutil/issues/133 -.. _134: https://github.com/giampaolo/psutil/issues/134 -.. _135: https://github.com/giampaolo/psutil/issues/135 -.. _136: https://github.com/giampaolo/psutil/issues/136 -.. _137: https://github.com/giampaolo/psutil/issues/137 -.. _138: https://github.com/giampaolo/psutil/issues/138 -.. _139: https://github.com/giampaolo/psutil/issues/139 -.. _140: https://github.com/giampaolo/psutil/issues/140 -.. _141: https://github.com/giampaolo/psutil/issues/141 -.. _142: https://github.com/giampaolo/psutil/issues/142 -.. _143: https://github.com/giampaolo/psutil/issues/143 -.. _144: https://github.com/giampaolo/psutil/issues/144 -.. _145: https://github.com/giampaolo/psutil/issues/145 -.. _146: https://github.com/giampaolo/psutil/issues/146 -.. _147: https://github.com/giampaolo/psutil/issues/147 -.. _148: https://github.com/giampaolo/psutil/issues/148 -.. _149: https://github.com/giampaolo/psutil/issues/149 -.. _150: https://github.com/giampaolo/psutil/issues/150 -.. _151: https://github.com/giampaolo/psutil/issues/151 -.. _152: https://github.com/giampaolo/psutil/issues/152 -.. _153: https://github.com/giampaolo/psutil/issues/153 -.. _154: https://github.com/giampaolo/psutil/issues/154 -.. _155: https://github.com/giampaolo/psutil/issues/155 -.. _156: https://github.com/giampaolo/psutil/issues/156 -.. _157: https://github.com/giampaolo/psutil/issues/157 -.. _158: https://github.com/giampaolo/psutil/issues/158 -.. _159: https://github.com/giampaolo/psutil/issues/159 -.. _160: https://github.com/giampaolo/psutil/issues/160 -.. _161: https://github.com/giampaolo/psutil/issues/161 -.. _162: https://github.com/giampaolo/psutil/issues/162 -.. _163: https://github.com/giampaolo/psutil/issues/163 -.. _164: https://github.com/giampaolo/psutil/issues/164 -.. _165: https://github.com/giampaolo/psutil/issues/165 -.. _166: https://github.com/giampaolo/psutil/issues/166 -.. _167: https://github.com/giampaolo/psutil/issues/167 -.. _168: https://github.com/giampaolo/psutil/issues/168 -.. _169: https://github.com/giampaolo/psutil/issues/169 -.. _170: https://github.com/giampaolo/psutil/issues/170 -.. _171: https://github.com/giampaolo/psutil/issues/171 -.. _172: https://github.com/giampaolo/psutil/issues/172 -.. _173: https://github.com/giampaolo/psutil/issues/173 -.. _174: https://github.com/giampaolo/psutil/issues/174 -.. _175: https://github.com/giampaolo/psutil/issues/175 -.. _176: https://github.com/giampaolo/psutil/issues/176 -.. _177: https://github.com/giampaolo/psutil/issues/177 -.. _178: https://github.com/giampaolo/psutil/issues/178 -.. _179: https://github.com/giampaolo/psutil/issues/179 -.. _180: https://github.com/giampaolo/psutil/issues/180 -.. _181: https://github.com/giampaolo/psutil/issues/181 -.. _182: https://github.com/giampaolo/psutil/issues/182 -.. _183: https://github.com/giampaolo/psutil/issues/183 -.. _184: https://github.com/giampaolo/psutil/issues/184 -.. _185: https://github.com/giampaolo/psutil/issues/185 -.. _186: https://github.com/giampaolo/psutil/issues/186 -.. _187: https://github.com/giampaolo/psutil/issues/187 -.. _188: https://github.com/giampaolo/psutil/issues/188 -.. _189: https://github.com/giampaolo/psutil/issues/189 -.. _190: https://github.com/giampaolo/psutil/issues/190 -.. _191: https://github.com/giampaolo/psutil/issues/191 -.. _192: https://github.com/giampaolo/psutil/issues/192 -.. _193: https://github.com/giampaolo/psutil/issues/193 -.. _194: https://github.com/giampaolo/psutil/issues/194 -.. _195: https://github.com/giampaolo/psutil/issues/195 -.. _196: https://github.com/giampaolo/psutil/issues/196 -.. _197: https://github.com/giampaolo/psutil/issues/197 -.. _198: https://github.com/giampaolo/psutil/issues/198 -.. _199: https://github.com/giampaolo/psutil/issues/199 -.. _200: https://github.com/giampaolo/psutil/issues/200 -.. _201: https://github.com/giampaolo/psutil/issues/201 -.. _202: https://github.com/giampaolo/psutil/issues/202 -.. _203: https://github.com/giampaolo/psutil/issues/203 -.. _204: https://github.com/giampaolo/psutil/issues/204 -.. _205: https://github.com/giampaolo/psutil/issues/205 -.. _206: https://github.com/giampaolo/psutil/issues/206 -.. _207: https://github.com/giampaolo/psutil/issues/207 -.. _208: https://github.com/giampaolo/psutil/issues/208 -.. _209: https://github.com/giampaolo/psutil/issues/209 -.. _210: https://github.com/giampaolo/psutil/issues/210 -.. _211: https://github.com/giampaolo/psutil/issues/211 -.. _212: https://github.com/giampaolo/psutil/issues/212 -.. _213: https://github.com/giampaolo/psutil/issues/213 -.. _214: https://github.com/giampaolo/psutil/issues/214 -.. _215: https://github.com/giampaolo/psutil/issues/215 -.. _216: https://github.com/giampaolo/psutil/issues/216 -.. _217: https://github.com/giampaolo/psutil/issues/217 -.. _218: https://github.com/giampaolo/psutil/issues/218 -.. _219: https://github.com/giampaolo/psutil/issues/219 -.. _220: https://github.com/giampaolo/psutil/issues/220 -.. _221: https://github.com/giampaolo/psutil/issues/221 -.. _222: https://github.com/giampaolo/psutil/issues/222 -.. _223: https://github.com/giampaolo/psutil/issues/223 -.. _224: https://github.com/giampaolo/psutil/issues/224 -.. _225: https://github.com/giampaolo/psutil/issues/225 -.. _226: https://github.com/giampaolo/psutil/issues/226 -.. _227: https://github.com/giampaolo/psutil/issues/227 -.. _228: https://github.com/giampaolo/psutil/issues/228 -.. _229: https://github.com/giampaolo/psutil/issues/229 -.. _230: https://github.com/giampaolo/psutil/issues/230 -.. _231: https://github.com/giampaolo/psutil/issues/231 -.. _232: https://github.com/giampaolo/psutil/issues/232 -.. _233: https://github.com/giampaolo/psutil/issues/233 -.. _234: https://github.com/giampaolo/psutil/issues/234 -.. _235: https://github.com/giampaolo/psutil/issues/235 -.. _236: https://github.com/giampaolo/psutil/issues/236 -.. _237: https://github.com/giampaolo/psutil/issues/237 -.. _238: https://github.com/giampaolo/psutil/issues/238 -.. _239: https://github.com/giampaolo/psutil/issues/239 -.. _240: https://github.com/giampaolo/psutil/issues/240 -.. _241: https://github.com/giampaolo/psutil/issues/241 -.. _242: https://github.com/giampaolo/psutil/issues/242 -.. _243: https://github.com/giampaolo/psutil/issues/243 -.. _244: https://github.com/giampaolo/psutil/issues/244 -.. _245: https://github.com/giampaolo/psutil/issues/245 -.. _246: https://github.com/giampaolo/psutil/issues/246 -.. _247: https://github.com/giampaolo/psutil/issues/247 -.. _248: https://github.com/giampaolo/psutil/issues/248 -.. _249: https://github.com/giampaolo/psutil/issues/249 -.. _250: https://github.com/giampaolo/psutil/issues/250 -.. _251: https://github.com/giampaolo/psutil/issues/251 -.. _252: https://github.com/giampaolo/psutil/issues/252 -.. _253: https://github.com/giampaolo/psutil/issues/253 -.. _254: https://github.com/giampaolo/psutil/issues/254 -.. _255: https://github.com/giampaolo/psutil/issues/255 -.. _256: https://github.com/giampaolo/psutil/issues/256 -.. _257: https://github.com/giampaolo/psutil/issues/257 -.. _258: https://github.com/giampaolo/psutil/issues/258 -.. _259: https://github.com/giampaolo/psutil/issues/259 -.. _260: https://github.com/giampaolo/psutil/issues/260 -.. _261: https://github.com/giampaolo/psutil/issues/261 -.. _262: https://github.com/giampaolo/psutil/issues/262 -.. _263: https://github.com/giampaolo/psutil/issues/263 -.. _264: https://github.com/giampaolo/psutil/issues/264 -.. _265: https://github.com/giampaolo/psutil/issues/265 -.. _266: https://github.com/giampaolo/psutil/issues/266 -.. _267: https://github.com/giampaolo/psutil/issues/267 -.. _268: https://github.com/giampaolo/psutil/issues/268 -.. _269: https://github.com/giampaolo/psutil/issues/269 -.. _270: https://github.com/giampaolo/psutil/issues/270 -.. _271: https://github.com/giampaolo/psutil/issues/271 -.. _272: https://github.com/giampaolo/psutil/issues/272 -.. _273: https://github.com/giampaolo/psutil/issues/273 -.. _274: https://github.com/giampaolo/psutil/issues/274 -.. _275: https://github.com/giampaolo/psutil/issues/275 -.. _276: https://github.com/giampaolo/psutil/issues/276 -.. _277: https://github.com/giampaolo/psutil/issues/277 -.. _278: https://github.com/giampaolo/psutil/issues/278 -.. _279: https://github.com/giampaolo/psutil/issues/279 -.. _280: https://github.com/giampaolo/psutil/issues/280 -.. _281: https://github.com/giampaolo/psutil/issues/281 -.. _282: https://github.com/giampaolo/psutil/issues/282 -.. _283: https://github.com/giampaolo/psutil/issues/283 -.. _284: https://github.com/giampaolo/psutil/issues/284 -.. _285: https://github.com/giampaolo/psutil/issues/285 -.. _286: https://github.com/giampaolo/psutil/issues/286 -.. _287: https://github.com/giampaolo/psutil/issues/287 -.. _288: https://github.com/giampaolo/psutil/issues/288 -.. _289: https://github.com/giampaolo/psutil/issues/289 -.. _290: https://github.com/giampaolo/psutil/issues/290 -.. _291: https://github.com/giampaolo/psutil/issues/291 -.. _292: https://github.com/giampaolo/psutil/issues/292 -.. _293: https://github.com/giampaolo/psutil/issues/293 -.. _294: https://github.com/giampaolo/psutil/issues/294 -.. _295: https://github.com/giampaolo/psutil/issues/295 -.. _296: https://github.com/giampaolo/psutil/issues/296 -.. _297: https://github.com/giampaolo/psutil/issues/297 -.. _298: https://github.com/giampaolo/psutil/issues/298 -.. _299: https://github.com/giampaolo/psutil/issues/299 -.. _300: https://github.com/giampaolo/psutil/issues/300 -.. _301: https://github.com/giampaolo/psutil/issues/301 -.. _302: https://github.com/giampaolo/psutil/issues/302 -.. _303: https://github.com/giampaolo/psutil/issues/303 -.. _304: https://github.com/giampaolo/psutil/issues/304 -.. _305: https://github.com/giampaolo/psutil/issues/305 -.. _306: https://github.com/giampaolo/psutil/issues/306 -.. _307: https://github.com/giampaolo/psutil/issues/307 -.. _308: https://github.com/giampaolo/psutil/issues/308 -.. _309: https://github.com/giampaolo/psutil/issues/309 -.. _310: https://github.com/giampaolo/psutil/issues/310 -.. _311: https://github.com/giampaolo/psutil/issues/311 -.. _312: https://github.com/giampaolo/psutil/issues/312 -.. _313: https://github.com/giampaolo/psutil/issues/313 -.. _314: https://github.com/giampaolo/psutil/issues/314 -.. _315: https://github.com/giampaolo/psutil/issues/315 -.. _316: https://github.com/giampaolo/psutil/issues/316 -.. _317: https://github.com/giampaolo/psutil/issues/317 -.. _318: https://github.com/giampaolo/psutil/issues/318 -.. _319: https://github.com/giampaolo/psutil/issues/319 -.. _320: https://github.com/giampaolo/psutil/issues/320 -.. _321: https://github.com/giampaolo/psutil/issues/321 -.. _322: https://github.com/giampaolo/psutil/issues/322 -.. _323: https://github.com/giampaolo/psutil/issues/323 -.. _324: https://github.com/giampaolo/psutil/issues/324 -.. _325: https://github.com/giampaolo/psutil/issues/325 -.. _326: https://github.com/giampaolo/psutil/issues/326 -.. _327: https://github.com/giampaolo/psutil/issues/327 -.. _328: https://github.com/giampaolo/psutil/issues/328 -.. _329: https://github.com/giampaolo/psutil/issues/329 -.. _330: https://github.com/giampaolo/psutil/issues/330 -.. _331: https://github.com/giampaolo/psutil/issues/331 -.. _332: https://github.com/giampaolo/psutil/issues/332 -.. _333: https://github.com/giampaolo/psutil/issues/333 -.. _334: https://github.com/giampaolo/psutil/issues/334 -.. _335: https://github.com/giampaolo/psutil/issues/335 -.. _336: https://github.com/giampaolo/psutil/issues/336 -.. _337: https://github.com/giampaolo/psutil/issues/337 -.. _338: https://github.com/giampaolo/psutil/issues/338 -.. _339: https://github.com/giampaolo/psutil/issues/339 -.. _340: https://github.com/giampaolo/psutil/issues/340 -.. _341: https://github.com/giampaolo/psutil/issues/341 -.. _342: https://github.com/giampaolo/psutil/issues/342 -.. _343: https://github.com/giampaolo/psutil/issues/343 -.. _344: https://github.com/giampaolo/psutil/issues/344 -.. _345: https://github.com/giampaolo/psutil/issues/345 -.. _346: https://github.com/giampaolo/psutil/issues/346 -.. _347: https://github.com/giampaolo/psutil/issues/347 -.. _348: https://github.com/giampaolo/psutil/issues/348 -.. _349: https://github.com/giampaolo/psutil/issues/349 -.. _350: https://github.com/giampaolo/psutil/issues/350 -.. _351: https://github.com/giampaolo/psutil/issues/351 -.. _352: https://github.com/giampaolo/psutil/issues/352 -.. _353: https://github.com/giampaolo/psutil/issues/353 -.. _354: https://github.com/giampaolo/psutil/issues/354 -.. _355: https://github.com/giampaolo/psutil/issues/355 -.. _356: https://github.com/giampaolo/psutil/issues/356 -.. _357: https://github.com/giampaolo/psutil/issues/357 -.. _358: https://github.com/giampaolo/psutil/issues/358 -.. _359: https://github.com/giampaolo/psutil/issues/359 -.. _360: https://github.com/giampaolo/psutil/issues/360 -.. _361: https://github.com/giampaolo/psutil/issues/361 -.. _362: https://github.com/giampaolo/psutil/issues/362 -.. _363: https://github.com/giampaolo/psutil/issues/363 -.. _364: https://github.com/giampaolo/psutil/issues/364 -.. _365: https://github.com/giampaolo/psutil/issues/365 -.. _366: https://github.com/giampaolo/psutil/issues/366 -.. _367: https://github.com/giampaolo/psutil/issues/367 -.. _368: https://github.com/giampaolo/psutil/issues/368 -.. _369: https://github.com/giampaolo/psutil/issues/369 -.. _370: https://github.com/giampaolo/psutil/issues/370 -.. _371: https://github.com/giampaolo/psutil/issues/371 -.. _372: https://github.com/giampaolo/psutil/issues/372 -.. _373: https://github.com/giampaolo/psutil/issues/373 -.. _374: https://github.com/giampaolo/psutil/issues/374 -.. _375: https://github.com/giampaolo/psutil/issues/375 -.. _376: https://github.com/giampaolo/psutil/issues/376 -.. _377: https://github.com/giampaolo/psutil/issues/377 -.. _378: https://github.com/giampaolo/psutil/issues/378 -.. _379: https://github.com/giampaolo/psutil/issues/379 -.. _380: https://github.com/giampaolo/psutil/issues/380 -.. _381: https://github.com/giampaolo/psutil/issues/381 -.. _382: https://github.com/giampaolo/psutil/issues/382 -.. _383: https://github.com/giampaolo/psutil/issues/383 -.. _384: https://github.com/giampaolo/psutil/issues/384 -.. _385: https://github.com/giampaolo/psutil/issues/385 -.. _386: https://github.com/giampaolo/psutil/issues/386 -.. _387: https://github.com/giampaolo/psutil/issues/387 -.. _388: https://github.com/giampaolo/psutil/issues/388 -.. _389: https://github.com/giampaolo/psutil/issues/389 -.. _390: https://github.com/giampaolo/psutil/issues/390 -.. _391: https://github.com/giampaolo/psutil/issues/391 -.. _392: https://github.com/giampaolo/psutil/issues/392 -.. _393: https://github.com/giampaolo/psutil/issues/393 -.. _394: https://github.com/giampaolo/psutil/issues/394 -.. _395: https://github.com/giampaolo/psutil/issues/395 -.. _396: https://github.com/giampaolo/psutil/issues/396 -.. _397: https://github.com/giampaolo/psutil/issues/397 -.. _398: https://github.com/giampaolo/psutil/issues/398 -.. _399: https://github.com/giampaolo/psutil/issues/399 -.. _400: https://github.com/giampaolo/psutil/issues/400 -.. _401: https://github.com/giampaolo/psutil/issues/401 -.. _402: https://github.com/giampaolo/psutil/issues/402 -.. _403: https://github.com/giampaolo/psutil/issues/403 -.. _404: https://github.com/giampaolo/psutil/issues/404 -.. _405: https://github.com/giampaolo/psutil/issues/405 -.. _406: https://github.com/giampaolo/psutil/issues/406 -.. _407: https://github.com/giampaolo/psutil/issues/407 -.. _408: https://github.com/giampaolo/psutil/issues/408 -.. _409: https://github.com/giampaolo/psutil/issues/409 -.. _410: https://github.com/giampaolo/psutil/issues/410 -.. _411: https://github.com/giampaolo/psutil/issues/411 -.. _412: https://github.com/giampaolo/psutil/issues/412 -.. _413: https://github.com/giampaolo/psutil/issues/413 -.. _414: https://github.com/giampaolo/psutil/issues/414 -.. _415: https://github.com/giampaolo/psutil/issues/415 -.. _416: https://github.com/giampaolo/psutil/issues/416 -.. _417: https://github.com/giampaolo/psutil/issues/417 -.. _418: https://github.com/giampaolo/psutil/issues/418 -.. _419: https://github.com/giampaolo/psutil/issues/419 -.. _420: https://github.com/giampaolo/psutil/issues/420 -.. _421: https://github.com/giampaolo/psutil/issues/421 -.. _422: https://github.com/giampaolo/psutil/issues/422 -.. _423: https://github.com/giampaolo/psutil/issues/423 -.. _424: https://github.com/giampaolo/psutil/issues/424 -.. _425: https://github.com/giampaolo/psutil/issues/425 -.. _426: https://github.com/giampaolo/psutil/issues/426 -.. _427: https://github.com/giampaolo/psutil/issues/427 -.. _428: https://github.com/giampaolo/psutil/issues/428 -.. _429: https://github.com/giampaolo/psutil/issues/429 -.. _430: https://github.com/giampaolo/psutil/issues/430 -.. _431: https://github.com/giampaolo/psutil/issues/431 -.. _432: https://github.com/giampaolo/psutil/issues/432 -.. _433: https://github.com/giampaolo/psutil/issues/433 -.. _434: https://github.com/giampaolo/psutil/issues/434 -.. _435: https://github.com/giampaolo/psutil/issues/435 -.. _436: https://github.com/giampaolo/psutil/issues/436 -.. _437: https://github.com/giampaolo/psutil/issues/437 -.. _438: https://github.com/giampaolo/psutil/issues/438 -.. _439: https://github.com/giampaolo/psutil/issues/439 -.. _440: https://github.com/giampaolo/psutil/issues/440 -.. _441: https://github.com/giampaolo/psutil/issues/441 -.. _442: https://github.com/giampaolo/psutil/issues/442 -.. _443: https://github.com/giampaolo/psutil/issues/443 -.. _444: https://github.com/giampaolo/psutil/issues/444 -.. _445: https://github.com/giampaolo/psutil/issues/445 -.. _446: https://github.com/giampaolo/psutil/issues/446 -.. _447: https://github.com/giampaolo/psutil/issues/447 -.. _448: https://github.com/giampaolo/psutil/issues/448 -.. _449: https://github.com/giampaolo/psutil/issues/449 -.. _450: https://github.com/giampaolo/psutil/issues/450 -.. _451: https://github.com/giampaolo/psutil/issues/451 -.. _452: https://github.com/giampaolo/psutil/issues/452 -.. _453: https://github.com/giampaolo/psutil/issues/453 -.. _454: https://github.com/giampaolo/psutil/issues/454 -.. _455: https://github.com/giampaolo/psutil/issues/455 -.. _456: https://github.com/giampaolo/psutil/issues/456 -.. _457: https://github.com/giampaolo/psutil/issues/457 -.. _458: https://github.com/giampaolo/psutil/issues/458 -.. _459: https://github.com/giampaolo/psutil/issues/459 -.. _460: https://github.com/giampaolo/psutil/issues/460 -.. _461: https://github.com/giampaolo/psutil/issues/461 -.. _462: https://github.com/giampaolo/psutil/issues/462 -.. _463: https://github.com/giampaolo/psutil/issues/463 -.. _464: https://github.com/giampaolo/psutil/issues/464 -.. _465: https://github.com/giampaolo/psutil/issues/465 -.. _466: https://github.com/giampaolo/psutil/issues/466 -.. _467: https://github.com/giampaolo/psutil/issues/467 -.. _468: https://github.com/giampaolo/psutil/issues/468 -.. _469: https://github.com/giampaolo/psutil/issues/469 -.. _470: https://github.com/giampaolo/psutil/issues/470 -.. _471: https://github.com/giampaolo/psutil/issues/471 -.. _472: https://github.com/giampaolo/psutil/issues/472 -.. _473: https://github.com/giampaolo/psutil/issues/473 -.. _474: https://github.com/giampaolo/psutil/issues/474 -.. _475: https://github.com/giampaolo/psutil/issues/475 -.. _476: https://github.com/giampaolo/psutil/issues/476 -.. _477: https://github.com/giampaolo/psutil/issues/477 -.. _478: https://github.com/giampaolo/psutil/issues/478 -.. _479: https://github.com/giampaolo/psutil/issues/479 -.. _480: https://github.com/giampaolo/psutil/issues/480 -.. _481: https://github.com/giampaolo/psutil/issues/481 -.. _482: https://github.com/giampaolo/psutil/issues/482 -.. _483: https://github.com/giampaolo/psutil/issues/483 -.. _484: https://github.com/giampaolo/psutil/issues/484 -.. _485: https://github.com/giampaolo/psutil/issues/485 -.. _486: https://github.com/giampaolo/psutil/issues/486 -.. _487: https://github.com/giampaolo/psutil/issues/487 -.. _488: https://github.com/giampaolo/psutil/issues/488 -.. _489: https://github.com/giampaolo/psutil/issues/489 -.. _490: https://github.com/giampaolo/psutil/issues/490 -.. _491: https://github.com/giampaolo/psutil/issues/491 -.. _492: https://github.com/giampaolo/psutil/issues/492 -.. _493: https://github.com/giampaolo/psutil/issues/493 -.. _494: https://github.com/giampaolo/psutil/issues/494 -.. _495: https://github.com/giampaolo/psutil/issues/495 -.. _496: https://github.com/giampaolo/psutil/issues/496 -.. _497: https://github.com/giampaolo/psutil/issues/497 -.. _498: https://github.com/giampaolo/psutil/issues/498 -.. _499: https://github.com/giampaolo/psutil/issues/499 -.. _500: https://github.com/giampaolo/psutil/issues/500 -.. _501: https://github.com/giampaolo/psutil/issues/501 -.. _502: https://github.com/giampaolo/psutil/issues/502 -.. _503: https://github.com/giampaolo/psutil/issues/503 -.. _504: https://github.com/giampaolo/psutil/issues/504 -.. _505: https://github.com/giampaolo/psutil/issues/505 -.. _506: https://github.com/giampaolo/psutil/issues/506 -.. _507: https://github.com/giampaolo/psutil/issues/507 -.. _508: https://github.com/giampaolo/psutil/issues/508 -.. _509: https://github.com/giampaolo/psutil/issues/509 -.. _510: https://github.com/giampaolo/psutil/issues/510 -.. _511: https://github.com/giampaolo/psutil/issues/511 -.. _512: https://github.com/giampaolo/psutil/issues/512 -.. _513: https://github.com/giampaolo/psutil/issues/513 -.. _514: https://github.com/giampaolo/psutil/issues/514 -.. _515: https://github.com/giampaolo/psutil/issues/515 -.. _516: https://github.com/giampaolo/psutil/issues/516 -.. _517: https://github.com/giampaolo/psutil/issues/517 -.. _518: https://github.com/giampaolo/psutil/issues/518 -.. _519: https://github.com/giampaolo/psutil/issues/519 -.. _520: https://github.com/giampaolo/psutil/issues/520 -.. _521: https://github.com/giampaolo/psutil/issues/521 -.. _522: https://github.com/giampaolo/psutil/issues/522 -.. _523: https://github.com/giampaolo/psutil/issues/523 -.. _524: https://github.com/giampaolo/psutil/issues/524 -.. _525: https://github.com/giampaolo/psutil/issues/525 -.. _526: https://github.com/giampaolo/psutil/issues/526 -.. _527: https://github.com/giampaolo/psutil/issues/527 -.. _528: https://github.com/giampaolo/psutil/issues/528 -.. _529: https://github.com/giampaolo/psutil/issues/529 -.. _530: https://github.com/giampaolo/psutil/issues/530 -.. _531: https://github.com/giampaolo/psutil/issues/531 -.. _532: https://github.com/giampaolo/psutil/issues/532 -.. _533: https://github.com/giampaolo/psutil/issues/533 -.. _534: https://github.com/giampaolo/psutil/issues/534 -.. _535: https://github.com/giampaolo/psutil/issues/535 -.. _536: https://github.com/giampaolo/psutil/issues/536 -.. _537: https://github.com/giampaolo/psutil/issues/537 -.. _538: https://github.com/giampaolo/psutil/issues/538 -.. _539: https://github.com/giampaolo/psutil/issues/539 -.. _540: https://github.com/giampaolo/psutil/issues/540 -.. _541: https://github.com/giampaolo/psutil/issues/541 -.. _542: https://github.com/giampaolo/psutil/issues/542 -.. _543: https://github.com/giampaolo/psutil/issues/543 -.. _544: https://github.com/giampaolo/psutil/issues/544 -.. _545: https://github.com/giampaolo/psutil/issues/545 -.. _546: https://github.com/giampaolo/psutil/issues/546 -.. _547: https://github.com/giampaolo/psutil/issues/547 -.. _548: https://github.com/giampaolo/psutil/issues/548 -.. _549: https://github.com/giampaolo/psutil/issues/549 -.. _550: https://github.com/giampaolo/psutil/issues/550 -.. _551: https://github.com/giampaolo/psutil/issues/551 -.. _552: https://github.com/giampaolo/psutil/issues/552 -.. _553: https://github.com/giampaolo/psutil/issues/553 -.. _554: https://github.com/giampaolo/psutil/issues/554 -.. _555: https://github.com/giampaolo/psutil/issues/555 -.. _556: https://github.com/giampaolo/psutil/issues/556 -.. _557: https://github.com/giampaolo/psutil/issues/557 -.. _558: https://github.com/giampaolo/psutil/issues/558 -.. _559: https://github.com/giampaolo/psutil/issues/559 -.. _560: https://github.com/giampaolo/psutil/issues/560 -.. _561: https://github.com/giampaolo/psutil/issues/561 -.. _562: https://github.com/giampaolo/psutil/issues/562 -.. _563: https://github.com/giampaolo/psutil/issues/563 -.. _564: https://github.com/giampaolo/psutil/issues/564 -.. _565: https://github.com/giampaolo/psutil/issues/565 -.. _566: https://github.com/giampaolo/psutil/issues/566 -.. _567: https://github.com/giampaolo/psutil/issues/567 -.. _568: https://github.com/giampaolo/psutil/issues/568 -.. _569: https://github.com/giampaolo/psutil/issues/569 -.. _570: https://github.com/giampaolo/psutil/issues/570 -.. _571: https://github.com/giampaolo/psutil/issues/571 -.. _572: https://github.com/giampaolo/psutil/issues/572 -.. _573: https://github.com/giampaolo/psutil/issues/573 -.. _574: https://github.com/giampaolo/psutil/issues/574 -.. _575: https://github.com/giampaolo/psutil/issues/575 -.. _576: https://github.com/giampaolo/psutil/issues/576 -.. _577: https://github.com/giampaolo/psutil/issues/577 -.. _578: https://github.com/giampaolo/psutil/issues/578 -.. _579: https://github.com/giampaolo/psutil/issues/579 -.. _580: https://github.com/giampaolo/psutil/issues/580 -.. _581: https://github.com/giampaolo/psutil/issues/581 -.. _582: https://github.com/giampaolo/psutil/issues/582 -.. _583: https://github.com/giampaolo/psutil/issues/583 -.. _584: https://github.com/giampaolo/psutil/issues/584 -.. _585: https://github.com/giampaolo/psutil/issues/585 -.. _586: https://github.com/giampaolo/psutil/issues/586 -.. _587: https://github.com/giampaolo/psutil/issues/587 -.. _588: https://github.com/giampaolo/psutil/issues/588 -.. _589: https://github.com/giampaolo/psutil/issues/589 -.. _590: https://github.com/giampaolo/psutil/issues/590 -.. _591: https://github.com/giampaolo/psutil/issues/591 -.. _592: https://github.com/giampaolo/psutil/issues/592 -.. _593: https://github.com/giampaolo/psutil/issues/593 -.. _594: https://github.com/giampaolo/psutil/issues/594 -.. _595: https://github.com/giampaolo/psutil/issues/595 -.. _596: https://github.com/giampaolo/psutil/issues/596 -.. _597: https://github.com/giampaolo/psutil/issues/597 -.. _598: https://github.com/giampaolo/psutil/issues/598 -.. _599: https://github.com/giampaolo/psutil/issues/599 -.. _600: https://github.com/giampaolo/psutil/issues/600 -.. _601: https://github.com/giampaolo/psutil/issues/601 -.. _602: https://github.com/giampaolo/psutil/issues/602 -.. _603: https://github.com/giampaolo/psutil/issues/603 -.. _604: https://github.com/giampaolo/psutil/issues/604 -.. _605: https://github.com/giampaolo/psutil/issues/605 -.. _606: https://github.com/giampaolo/psutil/issues/606 -.. _607: https://github.com/giampaolo/psutil/issues/607 -.. _608: https://github.com/giampaolo/psutil/issues/608 -.. _609: https://github.com/giampaolo/psutil/issues/609 -.. _610: https://github.com/giampaolo/psutil/issues/610 -.. _611: https://github.com/giampaolo/psutil/issues/611 -.. _612: https://github.com/giampaolo/psutil/issues/612 -.. _613: https://github.com/giampaolo/psutil/issues/613 -.. _614: https://github.com/giampaolo/psutil/issues/614 -.. _615: https://github.com/giampaolo/psutil/issues/615 -.. _616: https://github.com/giampaolo/psutil/issues/616 -.. _617: https://github.com/giampaolo/psutil/issues/617 -.. _618: https://github.com/giampaolo/psutil/issues/618 -.. _619: https://github.com/giampaolo/psutil/issues/619 -.. _620: https://github.com/giampaolo/psutil/issues/620 -.. _621: https://github.com/giampaolo/psutil/issues/621 -.. _622: https://github.com/giampaolo/psutil/issues/622 -.. _623: https://github.com/giampaolo/psutil/issues/623 -.. _624: https://github.com/giampaolo/psutil/issues/624 -.. _625: https://github.com/giampaolo/psutil/issues/625 -.. _626: https://github.com/giampaolo/psutil/issues/626 -.. _627: https://github.com/giampaolo/psutil/issues/627 -.. _628: https://github.com/giampaolo/psutil/issues/628 -.. _629: https://github.com/giampaolo/psutil/issues/629 -.. _630: https://github.com/giampaolo/psutil/issues/630 -.. _631: https://github.com/giampaolo/psutil/issues/631 -.. _632: https://github.com/giampaolo/psutil/issues/632 -.. _633: https://github.com/giampaolo/psutil/issues/633 -.. _634: https://github.com/giampaolo/psutil/issues/634 -.. _635: https://github.com/giampaolo/psutil/issues/635 -.. _636: https://github.com/giampaolo/psutil/issues/636 -.. _637: https://github.com/giampaolo/psutil/issues/637 -.. _638: https://github.com/giampaolo/psutil/issues/638 -.. _639: https://github.com/giampaolo/psutil/issues/639 -.. _640: https://github.com/giampaolo/psutil/issues/640 -.. _641: https://github.com/giampaolo/psutil/issues/641 -.. _642: https://github.com/giampaolo/psutil/issues/642 -.. _643: https://github.com/giampaolo/psutil/issues/643 -.. _644: https://github.com/giampaolo/psutil/issues/644 -.. _645: https://github.com/giampaolo/psutil/issues/645 -.. _646: https://github.com/giampaolo/psutil/issues/646 -.. _647: https://github.com/giampaolo/psutil/issues/647 -.. _648: https://github.com/giampaolo/psutil/issues/648 -.. _649: https://github.com/giampaolo/psutil/issues/649 -.. _650: https://github.com/giampaolo/psutil/issues/650 -.. _651: https://github.com/giampaolo/psutil/issues/651 -.. _652: https://github.com/giampaolo/psutil/issues/652 -.. _653: https://github.com/giampaolo/psutil/issues/653 -.. _654: https://github.com/giampaolo/psutil/issues/654 -.. _655: https://github.com/giampaolo/psutil/issues/655 -.. _656: https://github.com/giampaolo/psutil/issues/656 -.. _657: https://github.com/giampaolo/psutil/issues/657 -.. _658: https://github.com/giampaolo/psutil/issues/658 -.. _659: https://github.com/giampaolo/psutil/issues/659 -.. _660: https://github.com/giampaolo/psutil/issues/660 -.. _661: https://github.com/giampaolo/psutil/issues/661 -.. _662: https://github.com/giampaolo/psutil/issues/662 -.. _663: https://github.com/giampaolo/psutil/issues/663 -.. _664: https://github.com/giampaolo/psutil/issues/664 -.. _665: https://github.com/giampaolo/psutil/issues/665 -.. _666: https://github.com/giampaolo/psutil/issues/666 -.. _667: https://github.com/giampaolo/psutil/issues/667 -.. _668: https://github.com/giampaolo/psutil/issues/668 -.. _669: https://github.com/giampaolo/psutil/issues/669 -.. _670: https://github.com/giampaolo/psutil/issues/670 -.. _671: https://github.com/giampaolo/psutil/issues/671 -.. _672: https://github.com/giampaolo/psutil/issues/672 -.. _673: https://github.com/giampaolo/psutil/issues/673 -.. _674: https://github.com/giampaolo/psutil/issues/674 -.. _675: https://github.com/giampaolo/psutil/issues/675 -.. _676: https://github.com/giampaolo/psutil/issues/676 -.. _677: https://github.com/giampaolo/psutil/issues/677 -.. _678: https://github.com/giampaolo/psutil/issues/678 -.. _679: https://github.com/giampaolo/psutil/issues/679 -.. _680: https://github.com/giampaolo/psutil/issues/680 -.. _681: https://github.com/giampaolo/psutil/issues/681 -.. _682: https://github.com/giampaolo/psutil/issues/682 -.. _683: https://github.com/giampaolo/psutil/issues/683 -.. _684: https://github.com/giampaolo/psutil/issues/684 -.. _685: https://github.com/giampaolo/psutil/issues/685 -.. _686: https://github.com/giampaolo/psutil/issues/686 -.. _687: https://github.com/giampaolo/psutil/issues/687 -.. _688: https://github.com/giampaolo/psutil/issues/688 -.. _689: https://github.com/giampaolo/psutil/issues/689 -.. _690: https://github.com/giampaolo/psutil/issues/690 -.. _691: https://github.com/giampaolo/psutil/issues/691 -.. _692: https://github.com/giampaolo/psutil/issues/692 -.. _693: https://github.com/giampaolo/psutil/issues/693 -.. _694: https://github.com/giampaolo/psutil/issues/694 -.. _695: https://github.com/giampaolo/psutil/issues/695 -.. _696: https://github.com/giampaolo/psutil/issues/696 -.. _697: https://github.com/giampaolo/psutil/issues/697 -.. _698: https://github.com/giampaolo/psutil/issues/698 -.. _699: https://github.com/giampaolo/psutil/issues/699 -.. _700: https://github.com/giampaolo/psutil/issues/700 -.. _701: https://github.com/giampaolo/psutil/issues/701 -.. _702: https://github.com/giampaolo/psutil/issues/702 -.. _703: https://github.com/giampaolo/psutil/issues/703 -.. _704: https://github.com/giampaolo/psutil/issues/704 -.. _705: https://github.com/giampaolo/psutil/issues/705 -.. _706: https://github.com/giampaolo/psutil/issues/706 -.. _707: https://github.com/giampaolo/psutil/issues/707 -.. _708: https://github.com/giampaolo/psutil/issues/708 -.. _709: https://github.com/giampaolo/psutil/issues/709 -.. _710: https://github.com/giampaolo/psutil/issues/710 -.. _711: https://github.com/giampaolo/psutil/issues/711 -.. _712: https://github.com/giampaolo/psutil/issues/712 -.. _713: https://github.com/giampaolo/psutil/issues/713 -.. _714: https://github.com/giampaolo/psutil/issues/714 -.. _715: https://github.com/giampaolo/psutil/issues/715 -.. _716: https://github.com/giampaolo/psutil/issues/716 -.. _717: https://github.com/giampaolo/psutil/issues/717 -.. _718: https://github.com/giampaolo/psutil/issues/718 -.. _719: https://github.com/giampaolo/psutil/issues/719 -.. _720: https://github.com/giampaolo/psutil/issues/720 -.. _721: https://github.com/giampaolo/psutil/issues/721 -.. _722: https://github.com/giampaolo/psutil/issues/722 -.. _723: https://github.com/giampaolo/psutil/issues/723 -.. _724: https://github.com/giampaolo/psutil/issues/724 -.. _725: https://github.com/giampaolo/psutil/issues/725 -.. _726: https://github.com/giampaolo/psutil/issues/726 -.. _727: https://github.com/giampaolo/psutil/issues/727 -.. _728: https://github.com/giampaolo/psutil/issues/728 -.. _729: https://github.com/giampaolo/psutil/issues/729 -.. _730: https://github.com/giampaolo/psutil/issues/730 -.. _731: https://github.com/giampaolo/psutil/issues/731 -.. _732: https://github.com/giampaolo/psutil/issues/732 -.. _733: https://github.com/giampaolo/psutil/issues/733 -.. _734: https://github.com/giampaolo/psutil/issues/734 -.. _735: https://github.com/giampaolo/psutil/issues/735 -.. _736: https://github.com/giampaolo/psutil/issues/736 -.. _737: https://github.com/giampaolo/psutil/issues/737 -.. _738: https://github.com/giampaolo/psutil/issues/738 -.. _739: https://github.com/giampaolo/psutil/issues/739 -.. _740: https://github.com/giampaolo/psutil/issues/740 -.. _741: https://github.com/giampaolo/psutil/issues/741 -.. _742: https://github.com/giampaolo/psutil/issues/742 -.. _743: https://github.com/giampaolo/psutil/issues/743 -.. _744: https://github.com/giampaolo/psutil/issues/744 -.. _745: https://github.com/giampaolo/psutil/issues/745 -.. _746: https://github.com/giampaolo/psutil/issues/746 -.. _747: https://github.com/giampaolo/psutil/issues/747 -.. _748: https://github.com/giampaolo/psutil/issues/748 -.. _749: https://github.com/giampaolo/psutil/issues/749 -.. _750: https://github.com/giampaolo/psutil/issues/750 -.. _751: https://github.com/giampaolo/psutil/issues/751 -.. _752: https://github.com/giampaolo/psutil/issues/752 -.. _753: https://github.com/giampaolo/psutil/issues/753 -.. _754: https://github.com/giampaolo/psutil/issues/754 -.. _755: https://github.com/giampaolo/psutil/issues/755 -.. _756: https://github.com/giampaolo/psutil/issues/756 -.. _757: https://github.com/giampaolo/psutil/issues/757 -.. _758: https://github.com/giampaolo/psutil/issues/758 -.. _759: https://github.com/giampaolo/psutil/issues/759 -.. _760: https://github.com/giampaolo/psutil/issues/760 -.. _761: https://github.com/giampaolo/psutil/issues/761 -.. _762: https://github.com/giampaolo/psutil/issues/762 -.. _763: https://github.com/giampaolo/psutil/issues/763 -.. _764: https://github.com/giampaolo/psutil/issues/764 -.. _765: https://github.com/giampaolo/psutil/issues/765 -.. _766: https://github.com/giampaolo/psutil/issues/766 -.. _767: https://github.com/giampaolo/psutil/issues/767 -.. _768: https://github.com/giampaolo/psutil/issues/768 -.. _769: https://github.com/giampaolo/psutil/issues/769 -.. _770: https://github.com/giampaolo/psutil/issues/770 -.. _771: https://github.com/giampaolo/psutil/issues/771 -.. _772: https://github.com/giampaolo/psutil/issues/772 -.. _773: https://github.com/giampaolo/psutil/issues/773 -.. _774: https://github.com/giampaolo/psutil/issues/774 -.. _775: https://github.com/giampaolo/psutil/issues/775 -.. _776: https://github.com/giampaolo/psutil/issues/776 -.. _777: https://github.com/giampaolo/psutil/issues/777 -.. _778: https://github.com/giampaolo/psutil/issues/778 -.. _779: https://github.com/giampaolo/psutil/issues/779 -.. _780: https://github.com/giampaolo/psutil/issues/780 -.. _781: https://github.com/giampaolo/psutil/issues/781 -.. _782: https://github.com/giampaolo/psutil/issues/782 -.. _783: https://github.com/giampaolo/psutil/issues/783 -.. _784: https://github.com/giampaolo/psutil/issues/784 -.. _785: https://github.com/giampaolo/psutil/issues/785 -.. _786: https://github.com/giampaolo/psutil/issues/786 -.. _787: https://github.com/giampaolo/psutil/issues/787 -.. _788: https://github.com/giampaolo/psutil/issues/788 -.. _789: https://github.com/giampaolo/psutil/issues/789 -.. _790: https://github.com/giampaolo/psutil/issues/790 -.. _791: https://github.com/giampaolo/psutil/issues/791 -.. _792: https://github.com/giampaolo/psutil/issues/792 -.. _793: https://github.com/giampaolo/psutil/issues/793 -.. _794: https://github.com/giampaolo/psutil/issues/794 -.. _795: https://github.com/giampaolo/psutil/issues/795 -.. _796: https://github.com/giampaolo/psutil/issues/796 -.. _797: https://github.com/giampaolo/psutil/issues/797 -.. _798: https://github.com/giampaolo/psutil/issues/798 -.. _799: https://github.com/giampaolo/psutil/issues/799 -.. _800: https://github.com/giampaolo/psutil/issues/800 -.. _801: https://github.com/giampaolo/psutil/issues/801 -.. _802: https://github.com/giampaolo/psutil/issues/802 -.. _803: https://github.com/giampaolo/psutil/issues/803 -.. _804: https://github.com/giampaolo/psutil/issues/804 -.. _805: https://github.com/giampaolo/psutil/issues/805 -.. _806: https://github.com/giampaolo/psutil/issues/806 -.. _807: https://github.com/giampaolo/psutil/issues/807 -.. _808: https://github.com/giampaolo/psutil/issues/808 -.. _809: https://github.com/giampaolo/psutil/issues/809 -.. _810: https://github.com/giampaolo/psutil/issues/810 -.. _811: https://github.com/giampaolo/psutil/issues/811 -.. _812: https://github.com/giampaolo/psutil/issues/812 -.. _813: https://github.com/giampaolo/psutil/issues/813 -.. _814: https://github.com/giampaolo/psutil/issues/814 -.. _815: https://github.com/giampaolo/psutil/issues/815 -.. _816: https://github.com/giampaolo/psutil/issues/816 -.. _817: https://github.com/giampaolo/psutil/issues/817 -.. _818: https://github.com/giampaolo/psutil/issues/818 -.. _819: https://github.com/giampaolo/psutil/issues/819 -.. _820: https://github.com/giampaolo/psutil/issues/820 -.. _821: https://github.com/giampaolo/psutil/issues/821 -.. _822: https://github.com/giampaolo/psutil/issues/822 -.. _823: https://github.com/giampaolo/psutil/issues/823 -.. _824: https://github.com/giampaolo/psutil/issues/824 -.. _825: https://github.com/giampaolo/psutil/issues/825 -.. _826: https://github.com/giampaolo/psutil/issues/826 -.. _827: https://github.com/giampaolo/psutil/issues/827 -.. _828: https://github.com/giampaolo/psutil/issues/828 -.. _829: https://github.com/giampaolo/psutil/issues/829 -.. _830: https://github.com/giampaolo/psutil/issues/830 -.. _831: https://github.com/giampaolo/psutil/issues/831 -.. _832: https://github.com/giampaolo/psutil/issues/832 -.. _833: https://github.com/giampaolo/psutil/issues/833 -.. _834: https://github.com/giampaolo/psutil/issues/834 -.. _835: https://github.com/giampaolo/psutil/issues/835 -.. _836: https://github.com/giampaolo/psutil/issues/836 -.. _837: https://github.com/giampaolo/psutil/issues/837 -.. _838: https://github.com/giampaolo/psutil/issues/838 -.. _839: https://github.com/giampaolo/psutil/issues/839 -.. _840: https://github.com/giampaolo/psutil/issues/840 -.. _841: https://github.com/giampaolo/psutil/issues/841 -.. _842: https://github.com/giampaolo/psutil/issues/842 -.. _843: https://github.com/giampaolo/psutil/issues/843 -.. _844: https://github.com/giampaolo/psutil/issues/844 -.. _845: https://github.com/giampaolo/psutil/issues/845 -.. _846: https://github.com/giampaolo/psutil/issues/846 -.. _847: https://github.com/giampaolo/psutil/issues/847 -.. _848: https://github.com/giampaolo/psutil/issues/848 -.. _849: https://github.com/giampaolo/psutil/issues/849 -.. _850: https://github.com/giampaolo/psutil/issues/850 -.. _851: https://github.com/giampaolo/psutil/issues/851 -.. _852: https://github.com/giampaolo/psutil/issues/852 -.. _853: https://github.com/giampaolo/psutil/issues/853 -.. _854: https://github.com/giampaolo/psutil/issues/854 -.. _855: https://github.com/giampaolo/psutil/issues/855 -.. _856: https://github.com/giampaolo/psutil/issues/856 -.. _857: https://github.com/giampaolo/psutil/issues/857 -.. _858: https://github.com/giampaolo/psutil/issues/858 -.. _859: https://github.com/giampaolo/psutil/issues/859 -.. _860: https://github.com/giampaolo/psutil/issues/860 -.. _861: https://github.com/giampaolo/psutil/issues/861 -.. _862: https://github.com/giampaolo/psutil/issues/862 -.. _863: https://github.com/giampaolo/psutil/issues/863 -.. _864: https://github.com/giampaolo/psutil/issues/864 -.. _865: https://github.com/giampaolo/psutil/issues/865 -.. _866: https://github.com/giampaolo/psutil/issues/866 -.. _867: https://github.com/giampaolo/psutil/issues/867 -.. _868: https://github.com/giampaolo/psutil/issues/868 -.. _869: https://github.com/giampaolo/psutil/issues/869 -.. _870: https://github.com/giampaolo/psutil/issues/870 -.. _871: https://github.com/giampaolo/psutil/issues/871 -.. _872: https://github.com/giampaolo/psutil/issues/872 -.. _873: https://github.com/giampaolo/psutil/issues/873 -.. _874: https://github.com/giampaolo/psutil/issues/874 -.. _875: https://github.com/giampaolo/psutil/issues/875 -.. _876: https://github.com/giampaolo/psutil/issues/876 -.. _877: https://github.com/giampaolo/psutil/issues/877 -.. _878: https://github.com/giampaolo/psutil/issues/878 -.. _879: https://github.com/giampaolo/psutil/issues/879 -.. _880: https://github.com/giampaolo/psutil/issues/880 -.. _881: https://github.com/giampaolo/psutil/issues/881 -.. _882: https://github.com/giampaolo/psutil/issues/882 -.. _883: https://github.com/giampaolo/psutil/issues/883 -.. _884: https://github.com/giampaolo/psutil/issues/884 -.. _885: https://github.com/giampaolo/psutil/issues/885 -.. _886: https://github.com/giampaolo/psutil/issues/886 -.. _887: https://github.com/giampaolo/psutil/issues/887 -.. _888: https://github.com/giampaolo/psutil/issues/888 -.. _889: https://github.com/giampaolo/psutil/issues/889 -.. _890: https://github.com/giampaolo/psutil/issues/890 -.. _891: https://github.com/giampaolo/psutil/issues/891 -.. _892: https://github.com/giampaolo/psutil/issues/892 -.. _893: https://github.com/giampaolo/psutil/issues/893 -.. _894: https://github.com/giampaolo/psutil/issues/894 -.. _895: https://github.com/giampaolo/psutil/issues/895 -.. _896: https://github.com/giampaolo/psutil/issues/896 -.. _897: https://github.com/giampaolo/psutil/issues/897 -.. _898: https://github.com/giampaolo/psutil/issues/898 -.. _899: https://github.com/giampaolo/psutil/issues/899 -.. _900: https://github.com/giampaolo/psutil/issues/900 -.. _901: https://github.com/giampaolo/psutil/issues/901 -.. _902: https://github.com/giampaolo/psutil/issues/902 -.. _903: https://github.com/giampaolo/psutil/issues/903 -.. _904: https://github.com/giampaolo/psutil/issues/904 -.. _905: https://github.com/giampaolo/psutil/issues/905 -.. _906: https://github.com/giampaolo/psutil/issues/906 -.. _907: https://github.com/giampaolo/psutil/issues/907 -.. _908: https://github.com/giampaolo/psutil/issues/908 -.. _909: https://github.com/giampaolo/psutil/issues/909 -.. _910: https://github.com/giampaolo/psutil/issues/910 -.. _911: https://github.com/giampaolo/psutil/issues/911 -.. _912: https://github.com/giampaolo/psutil/issues/912 -.. _913: https://github.com/giampaolo/psutil/issues/913 -.. _914: https://github.com/giampaolo/psutil/issues/914 -.. _915: https://github.com/giampaolo/psutil/issues/915 -.. _916: https://github.com/giampaolo/psutil/issues/916 -.. _917: https://github.com/giampaolo/psutil/issues/917 -.. _918: https://github.com/giampaolo/psutil/issues/918 -.. _919: https://github.com/giampaolo/psutil/issues/919 -.. _920: https://github.com/giampaolo/psutil/issues/920 -.. _921: https://github.com/giampaolo/psutil/issues/921 -.. _922: https://github.com/giampaolo/psutil/issues/922 -.. _923: https://github.com/giampaolo/psutil/issues/923 -.. _924: https://github.com/giampaolo/psutil/issues/924 -.. _925: https://github.com/giampaolo/psutil/issues/925 -.. _926: https://github.com/giampaolo/psutil/issues/926 -.. _927: https://github.com/giampaolo/psutil/issues/927 -.. _928: https://github.com/giampaolo/psutil/issues/928 -.. _929: https://github.com/giampaolo/psutil/issues/929 -.. _930: https://github.com/giampaolo/psutil/issues/930 -.. _931: https://github.com/giampaolo/psutil/issues/931 -.. _932: https://github.com/giampaolo/psutil/issues/932 -.. _933: https://github.com/giampaolo/psutil/issues/933 -.. _934: https://github.com/giampaolo/psutil/issues/934 -.. _935: https://github.com/giampaolo/psutil/issues/935 -.. _936: https://github.com/giampaolo/psutil/issues/936 -.. _937: https://github.com/giampaolo/psutil/issues/937 -.. _938: https://github.com/giampaolo/psutil/issues/938 -.. _939: https://github.com/giampaolo/psutil/issues/939 -.. _940: https://github.com/giampaolo/psutil/issues/940 -.. _941: https://github.com/giampaolo/psutil/issues/941 -.. _942: https://github.com/giampaolo/psutil/issues/942 -.. _943: https://github.com/giampaolo/psutil/issues/943 -.. _944: https://github.com/giampaolo/psutil/issues/944 -.. _945: https://github.com/giampaolo/psutil/issues/945 -.. _946: https://github.com/giampaolo/psutil/issues/946 -.. _947: https://github.com/giampaolo/psutil/issues/947 -.. _948: https://github.com/giampaolo/psutil/issues/948 -.. _949: https://github.com/giampaolo/psutil/issues/949 -.. _950: https://github.com/giampaolo/psutil/issues/950 -.. _951: https://github.com/giampaolo/psutil/issues/951 -.. _952: https://github.com/giampaolo/psutil/issues/952 -.. _953: https://github.com/giampaolo/psutil/issues/953 -.. _954: https://github.com/giampaolo/psutil/issues/954 -.. _955: https://github.com/giampaolo/psutil/issues/955 -.. _956: https://github.com/giampaolo/psutil/issues/956 -.. _957: https://github.com/giampaolo/psutil/issues/957 -.. _958: https://github.com/giampaolo/psutil/issues/958 -.. _959: https://github.com/giampaolo/psutil/issues/959 -.. _960: https://github.com/giampaolo/psutil/issues/960 -.. _961: https://github.com/giampaolo/psutil/issues/961 -.. _962: https://github.com/giampaolo/psutil/issues/962 -.. _963: https://github.com/giampaolo/psutil/issues/963 -.. _964: https://github.com/giampaolo/psutil/issues/964 -.. _965: https://github.com/giampaolo/psutil/issues/965 -.. _966: https://github.com/giampaolo/psutil/issues/966 -.. _967: https://github.com/giampaolo/psutil/issues/967 -.. _968: https://github.com/giampaolo/psutil/issues/968 -.. _969: https://github.com/giampaolo/psutil/issues/969 -.. _970: https://github.com/giampaolo/psutil/issues/970 -.. _971: https://github.com/giampaolo/psutil/issues/971 -.. _972: https://github.com/giampaolo/psutil/issues/972 -.. _973: https://github.com/giampaolo/psutil/issues/973 -.. _974: https://github.com/giampaolo/psutil/issues/974 -.. _975: https://github.com/giampaolo/psutil/issues/975 -.. _976: https://github.com/giampaolo/psutil/issues/976 -.. _977: https://github.com/giampaolo/psutil/issues/977 -.. _978: https://github.com/giampaolo/psutil/issues/978 -.. _979: https://github.com/giampaolo/psutil/issues/979 -.. _980: https://github.com/giampaolo/psutil/issues/980 -.. _981: https://github.com/giampaolo/psutil/issues/981 -.. _982: https://github.com/giampaolo/psutil/issues/982 -.. _983: https://github.com/giampaolo/psutil/issues/983 -.. _984: https://github.com/giampaolo/psutil/issues/984 -.. _985: https://github.com/giampaolo/psutil/issues/985 -.. _986: https://github.com/giampaolo/psutil/issues/986 -.. _987: https://github.com/giampaolo/psutil/issues/987 -.. _988: https://github.com/giampaolo/psutil/issues/988 -.. _989: https://github.com/giampaolo/psutil/issues/989 -.. _990: https://github.com/giampaolo/psutil/issues/990 -.. _991: https://github.com/giampaolo/psutil/issues/991 -.. _992: https://github.com/giampaolo/psutil/issues/992 -.. _993: https://github.com/giampaolo/psutil/issues/993 -.. _994: https://github.com/giampaolo/psutil/issues/994 -.. _995: https://github.com/giampaolo/psutil/issues/995 -.. _996: https://github.com/giampaolo/psutil/issues/996 -.. _997: https://github.com/giampaolo/psutil/issues/997 -.. _998: https://github.com/giampaolo/psutil/issues/998 -.. _999: https://github.com/giampaolo/psutil/issues/999 -.. _1000: https://github.com/giampaolo/psutil/issues/1000 -.. _1001: https://github.com/giampaolo/psutil/issues/1001 -.. _1002: https://github.com/giampaolo/psutil/issues/1002 -.. _1003: https://github.com/giampaolo/psutil/issues/1003 -.. _1004: https://github.com/giampaolo/psutil/issues/1004 -.. _1005: https://github.com/giampaolo/psutil/issues/1005 -.. _1006: https://github.com/giampaolo/psutil/issues/1006 -.. _1007: https://github.com/giampaolo/psutil/issues/1007 -.. _1008: https://github.com/giampaolo/psutil/issues/1008 -.. _1009: https://github.com/giampaolo/psutil/issues/1009 -.. _1010: https://github.com/giampaolo/psutil/issues/1010 -.. _1011: https://github.com/giampaolo/psutil/issues/1011 -.. _1012: https://github.com/giampaolo/psutil/issues/1012 -.. _1013: https://github.com/giampaolo/psutil/issues/1013 -.. _1014: https://github.com/giampaolo/psutil/issues/1014 -.. _1015: https://github.com/giampaolo/psutil/issues/1015 -.. _1016: https://github.com/giampaolo/psutil/issues/1016 -.. _1017: https://github.com/giampaolo/psutil/issues/1017 -.. _1018: https://github.com/giampaolo/psutil/issues/1018 -.. _1019: https://github.com/giampaolo/psutil/issues/1019 -.. _1020: https://github.com/giampaolo/psutil/issues/1020 -.. _1021: https://github.com/giampaolo/psutil/issues/1021 -.. _1022: https://github.com/giampaolo/psutil/issues/1022 -.. _1023: https://github.com/giampaolo/psutil/issues/1023 -.. _1024: https://github.com/giampaolo/psutil/issues/1024 -.. _1025: https://github.com/giampaolo/psutil/issues/1025 -.. _1026: https://github.com/giampaolo/psutil/issues/1026 -.. _1027: https://github.com/giampaolo/psutil/issues/1027 -.. _1028: https://github.com/giampaolo/psutil/issues/1028 -.. _1029: https://github.com/giampaolo/psutil/issues/1029 -.. _1030: https://github.com/giampaolo/psutil/issues/1030 -.. _1031: https://github.com/giampaolo/psutil/issues/1031 -.. _1032: https://github.com/giampaolo/psutil/issues/1032 -.. _1033: https://github.com/giampaolo/psutil/issues/1033 -.. _1034: https://github.com/giampaolo/psutil/issues/1034 -.. _1035: https://github.com/giampaolo/psutil/issues/1035 -.. _1036: https://github.com/giampaolo/psutil/issues/1036 -.. _1037: https://github.com/giampaolo/psutil/issues/1037 -.. _1038: https://github.com/giampaolo/psutil/issues/1038 -.. _1039: https://github.com/giampaolo/psutil/issues/1039 -.. _1040: https://github.com/giampaolo/psutil/issues/1040 -.. _1041: https://github.com/giampaolo/psutil/issues/1041 -.. _1042: https://github.com/giampaolo/psutil/issues/1042 -.. _1043: https://github.com/giampaolo/psutil/issues/1043 -.. _1044: https://github.com/giampaolo/psutil/issues/1044 -.. _1045: https://github.com/giampaolo/psutil/issues/1045 -.. _1046: https://github.com/giampaolo/psutil/issues/1046 -.. _1047: https://github.com/giampaolo/psutil/issues/1047 -.. _1048: https://github.com/giampaolo/psutil/issues/1048 -.. _1049: https://github.com/giampaolo/psutil/issues/1049 -.. _1050: https://github.com/giampaolo/psutil/issues/1050 -.. _1051: https://github.com/giampaolo/psutil/issues/1051 -.. _1052: https://github.com/giampaolo/psutil/issues/1052 -.. _1053: https://github.com/giampaolo/psutil/issues/1053 -.. _1054: https://github.com/giampaolo/psutil/issues/1054 -.. _1055: https://github.com/giampaolo/psutil/issues/1055 -.. _1056: https://github.com/giampaolo/psutil/issues/1056 -.. _1057: https://github.com/giampaolo/psutil/issues/1057 -.. _1058: https://github.com/giampaolo/psutil/issues/1058 -.. _1059: https://github.com/giampaolo/psutil/issues/1059 -.. _1060: https://github.com/giampaolo/psutil/issues/1060 -.. _1061: https://github.com/giampaolo/psutil/issues/1061 -.. _1062: https://github.com/giampaolo/psutil/issues/1062 -.. _1063: https://github.com/giampaolo/psutil/issues/1063 -.. _1064: https://github.com/giampaolo/psutil/issues/1064 -.. _1065: https://github.com/giampaolo/psutil/issues/1065 -.. _1066: https://github.com/giampaolo/psutil/issues/1066 -.. _1067: https://github.com/giampaolo/psutil/issues/1067 -.. _1068: https://github.com/giampaolo/psutil/issues/1068 -.. _1069: https://github.com/giampaolo/psutil/issues/1069 -.. _1070: https://github.com/giampaolo/psutil/issues/1070 -.. _1071: https://github.com/giampaolo/psutil/issues/1071 -.. _1072: https://github.com/giampaolo/psutil/issues/1072 -.. _1073: https://github.com/giampaolo/psutil/issues/1073 -.. _1074: https://github.com/giampaolo/psutil/issues/1074 -.. _1075: https://github.com/giampaolo/psutil/issues/1075 -.. _1076: https://github.com/giampaolo/psutil/issues/1076 -.. _1077: https://github.com/giampaolo/psutil/issues/1077 -.. _1078: https://github.com/giampaolo/psutil/issues/1078 -.. _1079: https://github.com/giampaolo/psutil/issues/1079 -.. _1080: https://github.com/giampaolo/psutil/issues/1080 -.. _1081: https://github.com/giampaolo/psutil/issues/1081 -.. _1082: https://github.com/giampaolo/psutil/issues/1082 -.. _1083: https://github.com/giampaolo/psutil/issues/1083 -.. _1084: https://github.com/giampaolo/psutil/issues/1084 -.. _1085: https://github.com/giampaolo/psutil/issues/1085 -.. _1086: https://github.com/giampaolo/psutil/issues/1086 -.. _1087: https://github.com/giampaolo/psutil/issues/1087 -.. _1088: https://github.com/giampaolo/psutil/issues/1088 -.. _1089: https://github.com/giampaolo/psutil/issues/1089 -.. _1090: https://github.com/giampaolo/psutil/issues/1090 -.. _1091: https://github.com/giampaolo/psutil/issues/1091 -.. _1092: https://github.com/giampaolo/psutil/issues/1092 -.. _1093: https://github.com/giampaolo/psutil/issues/1093 -.. _1094: https://github.com/giampaolo/psutil/issues/1094 -.. _1095: https://github.com/giampaolo/psutil/issues/1095 -.. _1096: https://github.com/giampaolo/psutil/issues/1096 -.. _1097: https://github.com/giampaolo/psutil/issues/1097 -.. _1098: https://github.com/giampaolo/psutil/issues/1098 -.. _1099: https://github.com/giampaolo/psutil/issues/1099 -.. _1100: https://github.com/giampaolo/psutil/issues/1100 -.. _1101: https://github.com/giampaolo/psutil/issues/1101 -.. _1102: https://github.com/giampaolo/psutil/issues/1102 -.. _1103: https://github.com/giampaolo/psutil/issues/1103 -.. _1104: https://github.com/giampaolo/psutil/issues/1104 -.. _1105: https://github.com/giampaolo/psutil/issues/1105 -.. _1106: https://github.com/giampaolo/psutil/issues/1106 -.. _1107: https://github.com/giampaolo/psutil/issues/1107 -.. _1108: https://github.com/giampaolo/psutil/issues/1108 -.. _1109: https://github.com/giampaolo/psutil/issues/1109 -.. _1110: https://github.com/giampaolo/psutil/issues/1110 -.. _1111: https://github.com/giampaolo/psutil/issues/1111 -.. _1112: https://github.com/giampaolo/psutil/issues/1112 -.. _1113: https://github.com/giampaolo/psutil/issues/1113 -.. _1114: https://github.com/giampaolo/psutil/issues/1114 -.. _1115: https://github.com/giampaolo/psutil/issues/1115 -.. _1116: https://github.com/giampaolo/psutil/issues/1116 -.. _1117: https://github.com/giampaolo/psutil/issues/1117 -.. _1118: https://github.com/giampaolo/psutil/issues/1118 -.. _1119: https://github.com/giampaolo/psutil/issues/1119 -.. _1120: https://github.com/giampaolo/psutil/issues/1120 -.. _1121: https://github.com/giampaolo/psutil/issues/1121 -.. _1122: https://github.com/giampaolo/psutil/issues/1122 -.. _1123: https://github.com/giampaolo/psutil/issues/1123 -.. _1124: https://github.com/giampaolo/psutil/issues/1124 -.. _1125: https://github.com/giampaolo/psutil/issues/1125 -.. _1126: https://github.com/giampaolo/psutil/issues/1126 -.. _1127: https://github.com/giampaolo/psutil/issues/1127 -.. _1128: https://github.com/giampaolo/psutil/issues/1128 -.. _1129: https://github.com/giampaolo/psutil/issues/1129 -.. _1130: https://github.com/giampaolo/psutil/issues/1130 -.. _1131: https://github.com/giampaolo/psutil/issues/1131 -.. _1132: https://github.com/giampaolo/psutil/issues/1132 -.. _1133: https://github.com/giampaolo/psutil/issues/1133 -.. _1134: https://github.com/giampaolo/psutil/issues/1134 -.. _1135: https://github.com/giampaolo/psutil/issues/1135 -.. _1136: https://github.com/giampaolo/psutil/issues/1136 -.. _1137: https://github.com/giampaolo/psutil/issues/1137 -.. _1138: https://github.com/giampaolo/psutil/issues/1138 -.. _1139: https://github.com/giampaolo/psutil/issues/1139 -.. _1140: https://github.com/giampaolo/psutil/issues/1140 -.. _1141: https://github.com/giampaolo/psutil/issues/1141 -.. _1142: https://github.com/giampaolo/psutil/issues/1142 -.. _1143: https://github.com/giampaolo/psutil/issues/1143 -.. _1144: https://github.com/giampaolo/psutil/issues/1144 -.. _1145: https://github.com/giampaolo/psutil/issues/1145 -.. _1146: https://github.com/giampaolo/psutil/issues/1146 -.. _1147: https://github.com/giampaolo/psutil/issues/1147 -.. _1148: https://github.com/giampaolo/psutil/issues/1148 -.. _1149: https://github.com/giampaolo/psutil/issues/1149 -.. _1150: https://github.com/giampaolo/psutil/issues/1150 -.. _1151: https://github.com/giampaolo/psutil/issues/1151 -.. _1152: https://github.com/giampaolo/psutil/issues/1152 -.. _1153: https://github.com/giampaolo/psutil/issues/1153 -.. _1154: https://github.com/giampaolo/psutil/issues/1154 -.. _1155: https://github.com/giampaolo/psutil/issues/1155 -.. _1156: https://github.com/giampaolo/psutil/issues/1156 -.. _1157: https://github.com/giampaolo/psutil/issues/1157 -.. _1158: https://github.com/giampaolo/psutil/issues/1158 -.. _1159: https://github.com/giampaolo/psutil/issues/1159 -.. _1160: https://github.com/giampaolo/psutil/issues/1160 -.. _1161: https://github.com/giampaolo/psutil/issues/1161 -.. _1162: https://github.com/giampaolo/psutil/issues/1162 -.. _1163: https://github.com/giampaolo/psutil/issues/1163 -.. _1164: https://github.com/giampaolo/psutil/issues/1164 -.. _1165: https://github.com/giampaolo/psutil/issues/1165 -.. _1166: https://github.com/giampaolo/psutil/issues/1166 -.. _1167: https://github.com/giampaolo/psutil/issues/1167 -.. _1168: https://github.com/giampaolo/psutil/issues/1168 -.. _1169: https://github.com/giampaolo/psutil/issues/1169 -.. _1170: https://github.com/giampaolo/psutil/issues/1170 -.. _1171: https://github.com/giampaolo/psutil/issues/1171 -.. _1172: https://github.com/giampaolo/psutil/issues/1172 -.. _1173: https://github.com/giampaolo/psutil/issues/1173 -.. _1174: https://github.com/giampaolo/psutil/issues/1174 -.. _1175: https://github.com/giampaolo/psutil/issues/1175 -.. _1176: https://github.com/giampaolo/psutil/issues/1176 -.. _1177: https://github.com/giampaolo/psutil/issues/1177 -.. _1178: https://github.com/giampaolo/psutil/issues/1178 -.. _1179: https://github.com/giampaolo/psutil/issues/1179 -.. _1180: https://github.com/giampaolo/psutil/issues/1180 -.. _1181: https://github.com/giampaolo/psutil/issues/1181 -.. _1182: https://github.com/giampaolo/psutil/issues/1182 -.. _1183: https://github.com/giampaolo/psutil/issues/1183 -.. _1184: https://github.com/giampaolo/psutil/issues/1184 -.. _1185: https://github.com/giampaolo/psutil/issues/1185 -.. _1186: https://github.com/giampaolo/psutil/issues/1186 -.. _1187: https://github.com/giampaolo/psutil/issues/1187 -.. _1188: https://github.com/giampaolo/psutil/issues/1188 -.. _1189: https://github.com/giampaolo/psutil/issues/1189 -.. _1190: https://github.com/giampaolo/psutil/issues/1190 -.. _1191: https://github.com/giampaolo/psutil/issues/1191 -.. _1192: https://github.com/giampaolo/psutil/issues/1192 -.. _1193: https://github.com/giampaolo/psutil/issues/1193 -.. _1194: https://github.com/giampaolo/psutil/issues/1194 -.. _1195: https://github.com/giampaolo/psutil/issues/1195 -.. _1196: https://github.com/giampaolo/psutil/issues/1196 -.. _1197: https://github.com/giampaolo/psutil/issues/1197 -.. _1198: https://github.com/giampaolo/psutil/issues/1198 -.. _1199: https://github.com/giampaolo/psutil/issues/1199 -.. _1200: https://github.com/giampaolo/psutil/issues/1200 -.. _1201: https://github.com/giampaolo/psutil/issues/1201 -.. _1202: https://github.com/giampaolo/psutil/issues/1202 -.. _1203: https://github.com/giampaolo/psutil/issues/1203 -.. _1204: https://github.com/giampaolo/psutil/issues/1204 -.. _1205: https://github.com/giampaolo/psutil/issues/1205 -.. _1206: https://github.com/giampaolo/psutil/issues/1206 -.. _1207: https://github.com/giampaolo/psutil/issues/1207 -.. _1208: https://github.com/giampaolo/psutil/issues/1208 -.. _1209: https://github.com/giampaolo/psutil/issues/1209 -.. _1210: https://github.com/giampaolo/psutil/issues/1210 -.. _1211: https://github.com/giampaolo/psutil/issues/1211 -.. _1212: https://github.com/giampaolo/psutil/issues/1212 -.. _1213: https://github.com/giampaolo/psutil/issues/1213 -.. _1214: https://github.com/giampaolo/psutil/issues/1214 -.. _1215: https://github.com/giampaolo/psutil/issues/1215 -.. _1216: https://github.com/giampaolo/psutil/issues/1216 -.. _1217: https://github.com/giampaolo/psutil/issues/1217 -.. _1218: https://github.com/giampaolo/psutil/issues/1218 -.. _1219: https://github.com/giampaolo/psutil/issues/1219 -.. _1220: https://github.com/giampaolo/psutil/issues/1220 -.. _1221: https://github.com/giampaolo/psutil/issues/1221 -.. _1222: https://github.com/giampaolo/psutil/issues/1222 -.. _1223: https://github.com/giampaolo/psutil/issues/1223 -.. _1224: https://github.com/giampaolo/psutil/issues/1224 -.. _1225: https://github.com/giampaolo/psutil/issues/1225 -.. _1226: https://github.com/giampaolo/psutil/issues/1226 -.. _1227: https://github.com/giampaolo/psutil/issues/1227 -.. _1228: https://github.com/giampaolo/psutil/issues/1228 -.. _1229: https://github.com/giampaolo/psutil/issues/1229 -.. _1230: https://github.com/giampaolo/psutil/issues/1230 -.. _1231: https://github.com/giampaolo/psutil/issues/1231 -.. _1232: https://github.com/giampaolo/psutil/issues/1232 -.. _1233: https://github.com/giampaolo/psutil/issues/1233 -.. _1234: https://github.com/giampaolo/psutil/issues/1234 -.. _1235: https://github.com/giampaolo/psutil/issues/1235 -.. _1236: https://github.com/giampaolo/psutil/issues/1236 -.. _1237: https://github.com/giampaolo/psutil/issues/1237 -.. _1238: https://github.com/giampaolo/psutil/issues/1238 -.. _1239: https://github.com/giampaolo/psutil/issues/1239 -.. _1240: https://github.com/giampaolo/psutil/issues/1240 -.. _1241: https://github.com/giampaolo/psutil/issues/1241 -.. _1242: https://github.com/giampaolo/psutil/issues/1242 -.. _1243: https://github.com/giampaolo/psutil/issues/1243 -.. _1244: https://github.com/giampaolo/psutil/issues/1244 -.. _1245: https://github.com/giampaolo/psutil/issues/1245 -.. _1246: https://github.com/giampaolo/psutil/issues/1246 -.. _1247: https://github.com/giampaolo/psutil/issues/1247 -.. _1248: https://github.com/giampaolo/psutil/issues/1248 -.. _1249: https://github.com/giampaolo/psutil/issues/1249 -.. _1250: https://github.com/giampaolo/psutil/issues/1250 -.. _1251: https://github.com/giampaolo/psutil/issues/1251 -.. _1252: https://github.com/giampaolo/psutil/issues/1252 -.. _1253: https://github.com/giampaolo/psutil/issues/1253 -.. _1254: https://github.com/giampaolo/psutil/issues/1254 -.. _1255: https://github.com/giampaolo/psutil/issues/1255 -.. _1256: https://github.com/giampaolo/psutil/issues/1256 -.. _1257: https://github.com/giampaolo/psutil/issues/1257 -.. _1258: https://github.com/giampaolo/psutil/issues/1258 -.. _1259: https://github.com/giampaolo/psutil/issues/1259 -.. _1260: https://github.com/giampaolo/psutil/issues/1260 -.. _1261: https://github.com/giampaolo/psutil/issues/1261 -.. _1262: https://github.com/giampaolo/psutil/issues/1262 -.. _1263: https://github.com/giampaolo/psutil/issues/1263 -.. _1264: https://github.com/giampaolo/psutil/issues/1264 -.. _1265: https://github.com/giampaolo/psutil/issues/1265 -.. _1266: https://github.com/giampaolo/psutil/issues/1266 -.. _1267: https://github.com/giampaolo/psutil/issues/1267 -.. _1268: https://github.com/giampaolo/psutil/issues/1268 -.. _1269: https://github.com/giampaolo/psutil/issues/1269 -.. _1270: https://github.com/giampaolo/psutil/issues/1270 -.. _1271: https://github.com/giampaolo/psutil/issues/1271 -.. _1272: https://github.com/giampaolo/psutil/issues/1272 -.. _1273: https://github.com/giampaolo/psutil/issues/1273 -.. _1274: https://github.com/giampaolo/psutil/issues/1274 -.. _1275: https://github.com/giampaolo/psutil/issues/1275 -.. _1276: https://github.com/giampaolo/psutil/issues/1276 -.. _1277: https://github.com/giampaolo/psutil/issues/1277 -.. _1278: https://github.com/giampaolo/psutil/issues/1278 -.. _1279: https://github.com/giampaolo/psutil/issues/1279 -.. _1280: https://github.com/giampaolo/psutil/issues/1280 -.. _1281: https://github.com/giampaolo/psutil/issues/1281 -.. _1282: https://github.com/giampaolo/psutil/issues/1282 -.. _1283: https://github.com/giampaolo/psutil/issues/1283 -.. _1284: https://github.com/giampaolo/psutil/issues/1284 -.. _1285: https://github.com/giampaolo/psutil/issues/1285 -.. _1286: https://github.com/giampaolo/psutil/issues/1286 -.. _1287: https://github.com/giampaolo/psutil/issues/1287 -.. _1288: https://github.com/giampaolo/psutil/issues/1288 -.. _1289: https://github.com/giampaolo/psutil/issues/1289 -.. _1290: https://github.com/giampaolo/psutil/issues/1290 -.. _1291: https://github.com/giampaolo/psutil/issues/1291 -.. _1292: https://github.com/giampaolo/psutil/issues/1292 -.. _1293: https://github.com/giampaolo/psutil/issues/1293 -.. _1294: https://github.com/giampaolo/psutil/issues/1294 -.. _1295: https://github.com/giampaolo/psutil/issues/1295 -.. _1296: https://github.com/giampaolo/psutil/issues/1296 -.. _1297: https://github.com/giampaolo/psutil/issues/1297 -.. _1298: https://github.com/giampaolo/psutil/issues/1298 -.. _1299: https://github.com/giampaolo/psutil/issues/1299 -.. _1300: https://github.com/giampaolo/psutil/issues/1300 -.. _1301: https://github.com/giampaolo/psutil/issues/1301 -.. _1302: https://github.com/giampaolo/psutil/issues/1302 -.. _1303: https://github.com/giampaolo/psutil/issues/1303 -.. _1304: https://github.com/giampaolo/psutil/issues/1304 -.. _1305: https://github.com/giampaolo/psutil/issues/1305 -.. _1306: https://github.com/giampaolo/psutil/issues/1306 -.. _1307: https://github.com/giampaolo/psutil/issues/1307 -.. _1308: https://github.com/giampaolo/psutil/issues/1308 -.. _1309: https://github.com/giampaolo/psutil/issues/1309 -.. _1310: https://github.com/giampaolo/psutil/issues/1310 -.. _1311: https://github.com/giampaolo/psutil/issues/1311 -.. _1312: https://github.com/giampaolo/psutil/issues/1312 -.. _1313: https://github.com/giampaolo/psutil/issues/1313 -.. _1314: https://github.com/giampaolo/psutil/issues/1314 -.. _1315: https://github.com/giampaolo/psutil/issues/1315 -.. _1316: https://github.com/giampaolo/psutil/issues/1316 -.. _1317: https://github.com/giampaolo/psutil/issues/1317 -.. _1318: https://github.com/giampaolo/psutil/issues/1318 -.. _1319: https://github.com/giampaolo/psutil/issues/1319 -.. _1320: https://github.com/giampaolo/psutil/issues/1320 -.. _1321: https://github.com/giampaolo/psutil/issues/1321 -.. _1322: https://github.com/giampaolo/psutil/issues/1322 -.. _1323: https://github.com/giampaolo/psutil/issues/1323 -.. _1324: https://github.com/giampaolo/psutil/issues/1324 -.. _1325: https://github.com/giampaolo/psutil/issues/1325 -.. _1326: https://github.com/giampaolo/psutil/issues/1326 -.. _1327: https://github.com/giampaolo/psutil/issues/1327 -.. _1328: https://github.com/giampaolo/psutil/issues/1328 -.. _1329: https://github.com/giampaolo/psutil/issues/1329 -.. _1330: https://github.com/giampaolo/psutil/issues/1330 -.. _1331: https://github.com/giampaolo/psutil/issues/1331 -.. _1332: https://github.com/giampaolo/psutil/issues/1332 -.. _1333: https://github.com/giampaolo/psutil/issues/1333 -.. _1334: https://github.com/giampaolo/psutil/issues/1334 -.. _1335: https://github.com/giampaolo/psutil/issues/1335 -.. _1336: https://github.com/giampaolo/psutil/issues/1336 -.. _1337: https://github.com/giampaolo/psutil/issues/1337 -.. _1338: https://github.com/giampaolo/psutil/issues/1338 -.. _1339: https://github.com/giampaolo/psutil/issues/1339 -.. _1340: https://github.com/giampaolo/psutil/issues/1340 -.. _1341: https://github.com/giampaolo/psutil/issues/1341 -.. _1342: https://github.com/giampaolo/psutil/issues/1342 -.. _1343: https://github.com/giampaolo/psutil/issues/1343 -.. _1344: https://github.com/giampaolo/psutil/issues/1344 -.. _1345: https://github.com/giampaolo/psutil/issues/1345 -.. _1346: https://github.com/giampaolo/psutil/issues/1346 -.. _1347: https://github.com/giampaolo/psutil/issues/1347 -.. _1348: https://github.com/giampaolo/psutil/issues/1348 -.. _1349: https://github.com/giampaolo/psutil/issues/1349 -.. _1350: https://github.com/giampaolo/psutil/issues/1350 -.. _1351: https://github.com/giampaolo/psutil/issues/1351 -.. _1352: https://github.com/giampaolo/psutil/issues/1352 -.. _1353: https://github.com/giampaolo/psutil/issues/1353 -.. _1354: https://github.com/giampaolo/psutil/issues/1354 -.. _1355: https://github.com/giampaolo/psutil/issues/1355 -.. _1356: https://github.com/giampaolo/psutil/issues/1356 -.. _1357: https://github.com/giampaolo/psutil/issues/1357 -.. _1358: https://github.com/giampaolo/psutil/issues/1358 -.. _1359: https://github.com/giampaolo/psutil/issues/1359 -.. _1360: https://github.com/giampaolo/psutil/issues/1360 -.. _1361: https://github.com/giampaolo/psutil/issues/1361 -.. _1362: https://github.com/giampaolo/psutil/issues/1362 -.. _1363: https://github.com/giampaolo/psutil/issues/1363 -.. _1364: https://github.com/giampaolo/psutil/issues/1364 -.. _1365: https://github.com/giampaolo/psutil/issues/1365 -.. _1366: https://github.com/giampaolo/psutil/issues/1366 -.. _1367: https://github.com/giampaolo/psutil/issues/1367 -.. _1368: https://github.com/giampaolo/psutil/issues/1368 -.. _1369: https://github.com/giampaolo/psutil/issues/1369 -.. _1370: https://github.com/giampaolo/psutil/issues/1370 -.. _1371: https://github.com/giampaolo/psutil/issues/1371 -.. _1372: https://github.com/giampaolo/psutil/issues/1372 -.. _1373: https://github.com/giampaolo/psutil/issues/1373 -.. _1374: https://github.com/giampaolo/psutil/issues/1374 -.. _1375: https://github.com/giampaolo/psutil/issues/1375 -.. _1376: https://github.com/giampaolo/psutil/issues/1376 -.. _1377: https://github.com/giampaolo/psutil/issues/1377 -.. _1378: https://github.com/giampaolo/psutil/issues/1378 -.. _1379: https://github.com/giampaolo/psutil/issues/1379 -.. _1380: https://github.com/giampaolo/psutil/issues/1380 -.. _1381: https://github.com/giampaolo/psutil/issues/1381 -.. _1382: https://github.com/giampaolo/psutil/issues/1382 -.. _1383: https://github.com/giampaolo/psutil/issues/1383 -.. _1384: https://github.com/giampaolo/psutil/issues/1384 -.. _1385: https://github.com/giampaolo/psutil/issues/1385 -.. _1386: https://github.com/giampaolo/psutil/issues/1386 -.. _1387: https://github.com/giampaolo/psutil/issues/1387 -.. _1388: https://github.com/giampaolo/psutil/issues/1388 -.. _1389: https://github.com/giampaolo/psutil/issues/1389 -.. _1390: https://github.com/giampaolo/psutil/issues/1390 -.. _1391: https://github.com/giampaolo/psutil/issues/1391 -.. _1392: https://github.com/giampaolo/psutil/issues/1392 -.. _1393: https://github.com/giampaolo/psutil/issues/1393 -.. _1394: https://github.com/giampaolo/psutil/issues/1394 -.. _1395: https://github.com/giampaolo/psutil/issues/1395 -.. _1396: https://github.com/giampaolo/psutil/issues/1396 -.. _1397: https://github.com/giampaolo/psutil/issues/1397 -.. _1398: https://github.com/giampaolo/psutil/issues/1398 -.. _1399: https://github.com/giampaolo/psutil/issues/1399 -.. _1400: https://github.com/giampaolo/psutil/issues/1400 -.. _1401: https://github.com/giampaolo/psutil/issues/1401 -.. _1402: https://github.com/giampaolo/psutil/issues/1402 -.. _1403: https://github.com/giampaolo/psutil/issues/1403 -.. _1404: https://github.com/giampaolo/psutil/issues/1404 -.. _1405: https://github.com/giampaolo/psutil/issues/1405 -.. _1406: https://github.com/giampaolo/psutil/issues/1406 -.. _1407: https://github.com/giampaolo/psutil/issues/1407 -.. _1408: https://github.com/giampaolo/psutil/issues/1408 -.. _1409: https://github.com/giampaolo/psutil/issues/1409 -.. _1410: https://github.com/giampaolo/psutil/issues/1410 -.. _1411: https://github.com/giampaolo/psutil/issues/1411 -.. _1412: https://github.com/giampaolo/psutil/issues/1412 -.. _1413: https://github.com/giampaolo/psutil/issues/1413 -.. _1414: https://github.com/giampaolo/psutil/issues/1414 -.. _1415: https://github.com/giampaolo/psutil/issues/1415 -.. _1416: https://github.com/giampaolo/psutil/issues/1416 -.. _1417: https://github.com/giampaolo/psutil/issues/1417 -.. _1418: https://github.com/giampaolo/psutil/issues/1418 -.. _1419: https://github.com/giampaolo/psutil/issues/1419 -.. _1420: https://github.com/giampaolo/psutil/issues/1420 -.. _1421: https://github.com/giampaolo/psutil/issues/1421 -.. _1422: https://github.com/giampaolo/psutil/issues/1422 -.. _1423: https://github.com/giampaolo/psutil/issues/1423 -.. _1424: https://github.com/giampaolo/psutil/issues/1424 -.. _1425: https://github.com/giampaolo/psutil/issues/1425 -.. _1426: https://github.com/giampaolo/psutil/issues/1426 -.. _1427: https://github.com/giampaolo/psutil/issues/1427 -.. _1428: https://github.com/giampaolo/psutil/issues/1428 -.. _1429: https://github.com/giampaolo/psutil/issues/1429 -.. _1430: https://github.com/giampaolo/psutil/issues/1430 -.. _1431: https://github.com/giampaolo/psutil/issues/1431 -.. _1432: https://github.com/giampaolo/psutil/issues/1432 -.. _1433: https://github.com/giampaolo/psutil/issues/1433 -.. _1434: https://github.com/giampaolo/psutil/issues/1434 -.. _1435: https://github.com/giampaolo/psutil/issues/1435 -.. _1436: https://github.com/giampaolo/psutil/issues/1436 -.. _1437: https://github.com/giampaolo/psutil/issues/1437 -.. _1438: https://github.com/giampaolo/psutil/issues/1438 -.. _1439: https://github.com/giampaolo/psutil/issues/1439 -.. _1440: https://github.com/giampaolo/psutil/issues/1440 -.. _1441: https://github.com/giampaolo/psutil/issues/1441 -.. _1442: https://github.com/giampaolo/psutil/issues/1442 -.. _1443: https://github.com/giampaolo/psutil/issues/1443 -.. _1444: https://github.com/giampaolo/psutil/issues/1444 -.. _1445: https://github.com/giampaolo/psutil/issues/1445 -.. _1446: https://github.com/giampaolo/psutil/issues/1446 -.. _1447: https://github.com/giampaolo/psutil/issues/1447 -.. _1448: https://github.com/giampaolo/psutil/issues/1448 -.. _1449: https://github.com/giampaolo/psutil/issues/1449 -.. _1450: https://github.com/giampaolo/psutil/issues/1450 -.. _1451: https://github.com/giampaolo/psutil/issues/1451 -.. _1452: https://github.com/giampaolo/psutil/issues/1452 -.. _1453: https://github.com/giampaolo/psutil/issues/1453 -.. _1454: https://github.com/giampaolo/psutil/issues/1454 -.. _1455: https://github.com/giampaolo/psutil/issues/1455 -.. _1456: https://github.com/giampaolo/psutil/issues/1456 -.. _1457: https://github.com/giampaolo/psutil/issues/1457 -.. _1458: https://github.com/giampaolo/psutil/issues/1458 -.. _1459: https://github.com/giampaolo/psutil/issues/1459 -.. _1460: https://github.com/giampaolo/psutil/issues/1460 -.. _1461: https://github.com/giampaolo/psutil/issues/1461 -.. _1462: https://github.com/giampaolo/psutil/issues/1462 -.. _1463: https://github.com/giampaolo/psutil/issues/1463 -.. _1464: https://github.com/giampaolo/psutil/issues/1464 -.. _1465: https://github.com/giampaolo/psutil/issues/1465 -.. _1466: https://github.com/giampaolo/psutil/issues/1466 -.. _1467: https://github.com/giampaolo/psutil/issues/1467 -.. _1468: https://github.com/giampaolo/psutil/issues/1468 -.. _1469: https://github.com/giampaolo/psutil/issues/1469 -.. _1470: https://github.com/giampaolo/psutil/issues/1470 -.. _1471: https://github.com/giampaolo/psutil/issues/1471 -.. _1472: https://github.com/giampaolo/psutil/issues/1472 -.. _1473: https://github.com/giampaolo/psutil/issues/1473 -.. _1474: https://github.com/giampaolo/psutil/issues/1474 -.. _1475: https://github.com/giampaolo/psutil/issues/1475 -.. _1476: https://github.com/giampaolo/psutil/issues/1476 -.. _1477: https://github.com/giampaolo/psutil/issues/1477 -.. _1478: https://github.com/giampaolo/psutil/issues/1478 -.. _1479: https://github.com/giampaolo/psutil/issues/1479 -.. _1480: https://github.com/giampaolo/psutil/issues/1480 -.. _1481: https://github.com/giampaolo/psutil/issues/1481 -.. _1482: https://github.com/giampaolo/psutil/issues/1482 -.. _1483: https://github.com/giampaolo/psutil/issues/1483 -.. _1484: https://github.com/giampaolo/psutil/issues/1484 -.. _1485: https://github.com/giampaolo/psutil/issues/1485 -.. _1486: https://github.com/giampaolo/psutil/issues/1486 -.. _1487: https://github.com/giampaolo/psutil/issues/1487 -.. _1488: https://github.com/giampaolo/psutil/issues/1488 -.. _1489: https://github.com/giampaolo/psutil/issues/1489 -.. _1490: https://github.com/giampaolo/psutil/issues/1490 -.. _1491: https://github.com/giampaolo/psutil/issues/1491 -.. _1492: https://github.com/giampaolo/psutil/issues/1492 -.. _1493: https://github.com/giampaolo/psutil/issues/1493 -.. _1494: https://github.com/giampaolo/psutil/issues/1494 -.. _1495: https://github.com/giampaolo/psutil/issues/1495 -.. _1496: https://github.com/giampaolo/psutil/issues/1496 -.. _1497: https://github.com/giampaolo/psutil/issues/1497 -.. _1498: https://github.com/giampaolo/psutil/issues/1498 -.. _1499: https://github.com/giampaolo/psutil/issues/1499 -.. _1500: https://github.com/giampaolo/psutil/issues/1500 -.. _1501: https://github.com/giampaolo/psutil/issues/1501 -.. _1502: https://github.com/giampaolo/psutil/issues/1502 -.. _1503: https://github.com/giampaolo/psutil/issues/1503 -.. _1504: https://github.com/giampaolo/psutil/issues/1504 -.. _1505: https://github.com/giampaolo/psutil/issues/1505 -.. _1506: https://github.com/giampaolo/psutil/issues/1506 -.. _1507: https://github.com/giampaolo/psutil/issues/1507 -.. _1508: https://github.com/giampaolo/psutil/issues/1508 -.. _1509: https://github.com/giampaolo/psutil/issues/1509 -.. _1510: https://github.com/giampaolo/psutil/issues/1510 -.. _1511: https://github.com/giampaolo/psutil/issues/1511 -.. _1512: https://github.com/giampaolo/psutil/issues/1512 -.. _1513: https://github.com/giampaolo/psutil/issues/1513 -.. _1514: https://github.com/giampaolo/psutil/issues/1514 -.. _1515: https://github.com/giampaolo/psutil/issues/1515 -.. _1516: https://github.com/giampaolo/psutil/issues/1516 -.. _1517: https://github.com/giampaolo/psutil/issues/1517 -.. _1518: https://github.com/giampaolo/psutil/issues/1518 -.. _1519: https://github.com/giampaolo/psutil/issues/1519 -.. _1520: https://github.com/giampaolo/psutil/issues/1520 -.. _1521: https://github.com/giampaolo/psutil/issues/1521 -.. _1522: https://github.com/giampaolo/psutil/issues/1522 -.. _1523: https://github.com/giampaolo/psutil/issues/1523 -.. _1524: https://github.com/giampaolo/psutil/issues/1524 -.. _1525: https://github.com/giampaolo/psutil/issues/1525 -.. _1526: https://github.com/giampaolo/psutil/issues/1526 -.. _1527: https://github.com/giampaolo/psutil/issues/1527 -.. _1528: https://github.com/giampaolo/psutil/issues/1528 -.. _1529: https://github.com/giampaolo/psutil/issues/1529 -.. _1530: https://github.com/giampaolo/psutil/issues/1530 -.. _1531: https://github.com/giampaolo/psutil/issues/1531 -.. _1532: https://github.com/giampaolo/psutil/issues/1532 -.. _1533: https://github.com/giampaolo/psutil/issues/1533 -.. _1534: https://github.com/giampaolo/psutil/issues/1534 -.. _1535: https://github.com/giampaolo/psutil/issues/1535 -.. _1536: https://github.com/giampaolo/psutil/issues/1536 -.. _1537: https://github.com/giampaolo/psutil/issues/1537 -.. _1538: https://github.com/giampaolo/psutil/issues/1538 -.. _1539: https://github.com/giampaolo/psutil/issues/1539 -.. _1540: https://github.com/giampaolo/psutil/issues/1540 -.. _1541: https://github.com/giampaolo/psutil/issues/1541 -.. _1542: https://github.com/giampaolo/psutil/issues/1542 -.. _1543: https://github.com/giampaolo/psutil/issues/1543 -.. _1544: https://github.com/giampaolo/psutil/issues/1544 -.. _1545: https://github.com/giampaolo/psutil/issues/1545 -.. _1546: https://github.com/giampaolo/psutil/issues/1546 -.. _1547: https://github.com/giampaolo/psutil/issues/1547 -.. _1548: https://github.com/giampaolo/psutil/issues/1548 -.. _1549: https://github.com/giampaolo/psutil/issues/1549 -.. _1550: https://github.com/giampaolo/psutil/issues/1550 -.. _1551: https://github.com/giampaolo/psutil/issues/1551 -.. _1552: https://github.com/giampaolo/psutil/issues/1552 -.. _1553: https://github.com/giampaolo/psutil/issues/1553 -.. _1554: https://github.com/giampaolo/psutil/issues/1554 -.. _1555: https://github.com/giampaolo/psutil/issues/1555 -.. _1556: https://github.com/giampaolo/psutil/issues/1556 -.. _1557: https://github.com/giampaolo/psutil/issues/1557 -.. _1558: https://github.com/giampaolo/psutil/issues/1558 -.. _1559: https://github.com/giampaolo/psutil/issues/1559 -.. _1560: https://github.com/giampaolo/psutil/issues/1560 -.. _1561: https://github.com/giampaolo/psutil/issues/1561 -.. _1562: https://github.com/giampaolo/psutil/issues/1562 -.. _1563: https://github.com/giampaolo/psutil/issues/1563 -.. _1564: https://github.com/giampaolo/psutil/issues/1564 -.. _1565: https://github.com/giampaolo/psutil/issues/1565 -.. _1566: https://github.com/giampaolo/psutil/issues/1566 -.. _1567: https://github.com/giampaolo/psutil/issues/1567 -.. _1568: https://github.com/giampaolo/psutil/issues/1568 -.. _1569: https://github.com/giampaolo/psutil/issues/1569 -.. _1570: https://github.com/giampaolo/psutil/issues/1570 -.. _1571: https://github.com/giampaolo/psutil/issues/1571 -.. _1572: https://github.com/giampaolo/psutil/issues/1572 -.. _1573: https://github.com/giampaolo/psutil/issues/1573 -.. _1574: https://github.com/giampaolo/psutil/issues/1574 -.. _1575: https://github.com/giampaolo/psutil/issues/1575 -.. _1576: https://github.com/giampaolo/psutil/issues/1576 -.. _1577: https://github.com/giampaolo/psutil/issues/1577 -.. _1578: https://github.com/giampaolo/psutil/issues/1578 -.. _1579: https://github.com/giampaolo/psutil/issues/1579 -.. _1580: https://github.com/giampaolo/psutil/issues/1580 -.. _1581: https://github.com/giampaolo/psutil/issues/1581 -.. _1582: https://github.com/giampaolo/psutil/issues/1582 -.. _1583: https://github.com/giampaolo/psutil/issues/1583 -.. _1584: https://github.com/giampaolo/psutil/issues/1584 -.. _1585: https://github.com/giampaolo/psutil/issues/1585 -.. _1586: https://github.com/giampaolo/psutil/issues/1586 -.. _1587: https://github.com/giampaolo/psutil/issues/1587 -.. _1588: https://github.com/giampaolo/psutil/issues/1588 -.. _1589: https://github.com/giampaolo/psutil/issues/1589 -.. _1590: https://github.com/giampaolo/psutil/issues/1590 -.. _1591: https://github.com/giampaolo/psutil/issues/1591 -.. _1592: https://github.com/giampaolo/psutil/issues/1592 -.. _1593: https://github.com/giampaolo/psutil/issues/1593 -.. _1594: https://github.com/giampaolo/psutil/issues/1594 -.. _1595: https://github.com/giampaolo/psutil/issues/1595 -.. _1596: https://github.com/giampaolo/psutil/issues/1596 -.. _1597: https://github.com/giampaolo/psutil/issues/1597 -.. _1598: https://github.com/giampaolo/psutil/issues/1598 -.. _1599: https://github.com/giampaolo/psutil/issues/1599 -.. _1600: https://github.com/giampaolo/psutil/issues/1600 -.. _1601: https://github.com/giampaolo/psutil/issues/1601 -.. _1602: https://github.com/giampaolo/psutil/issues/1602 -.. _1603: https://github.com/giampaolo/psutil/issues/1603 -.. _1604: https://github.com/giampaolo/psutil/issues/1604 -.. _1605: https://github.com/giampaolo/psutil/issues/1605 -.. _1606: https://github.com/giampaolo/psutil/issues/1606 -.. _1607: https://github.com/giampaolo/psutil/issues/1607 -.. _1608: https://github.com/giampaolo/psutil/issues/1608 -.. _1609: https://github.com/giampaolo/psutil/issues/1609 -.. _1610: https://github.com/giampaolo/psutil/issues/1610 -.. _1611: https://github.com/giampaolo/psutil/issues/1611 -.. _1612: https://github.com/giampaolo/psutil/issues/1612 -.. _1613: https://github.com/giampaolo/psutil/issues/1613 -.. _1614: https://github.com/giampaolo/psutil/issues/1614 -.. _1615: https://github.com/giampaolo/psutil/issues/1615 -.. _1616: https://github.com/giampaolo/psutil/issues/1616 -.. _1617: https://github.com/giampaolo/psutil/issues/1617 -.. _1618: https://github.com/giampaolo/psutil/issues/1618 -.. _1619: https://github.com/giampaolo/psutil/issues/1619 -.. _1620: https://github.com/giampaolo/psutil/issues/1620 -.. _1621: https://github.com/giampaolo/psutil/issues/1621 -.. _1622: https://github.com/giampaolo/psutil/issues/1622 -.. _1623: https://github.com/giampaolo/psutil/issues/1623 -.. _1624: https://github.com/giampaolo/psutil/issues/1624 -.. _1625: https://github.com/giampaolo/psutil/issues/1625 -.. _1626: https://github.com/giampaolo/psutil/issues/1626 -.. _1627: https://github.com/giampaolo/psutil/issues/1627 -.. _1628: https://github.com/giampaolo/psutil/issues/1628 -.. _1629: https://github.com/giampaolo/psutil/issues/1629 -.. _1630: https://github.com/giampaolo/psutil/issues/1630 -.. _1631: https://github.com/giampaolo/psutil/issues/1631 -.. _1632: https://github.com/giampaolo/psutil/issues/1632 -.. _1633: https://github.com/giampaolo/psutil/issues/1633 -.. _1634: https://github.com/giampaolo/psutil/issues/1634 -.. _1635: https://github.com/giampaolo/psutil/issues/1635 -.. _1636: https://github.com/giampaolo/psutil/issues/1636 -.. _1637: https://github.com/giampaolo/psutil/issues/1637 -.. _1638: https://github.com/giampaolo/psutil/issues/1638 -.. _1639: https://github.com/giampaolo/psutil/issues/1639 -.. _1640: https://github.com/giampaolo/psutil/issues/1640 -.. _1641: https://github.com/giampaolo/psutil/issues/1641 -.. _1642: https://github.com/giampaolo/psutil/issues/1642 -.. _1643: https://github.com/giampaolo/psutil/issues/1643 -.. _1644: https://github.com/giampaolo/psutil/issues/1644 -.. _1645: https://github.com/giampaolo/psutil/issues/1645 -.. _1646: https://github.com/giampaolo/psutil/issues/1646 -.. _1647: https://github.com/giampaolo/psutil/issues/1647 -.. _1648: https://github.com/giampaolo/psutil/issues/1648 -.. _1649: https://github.com/giampaolo/psutil/issues/1649 -.. _1650: https://github.com/giampaolo/psutil/issues/1650 -.. _1651: https://github.com/giampaolo/psutil/issues/1651 -.. _1652: https://github.com/giampaolo/psutil/issues/1652 -.. _1653: https://github.com/giampaolo/psutil/issues/1653 -.. _1654: https://github.com/giampaolo/psutil/issues/1654 -.. _1655: https://github.com/giampaolo/psutil/issues/1655 -.. _1656: https://github.com/giampaolo/psutil/issues/1656 -.. _1657: https://github.com/giampaolo/psutil/issues/1657 -.. _1658: https://github.com/giampaolo/psutil/issues/1658 -.. _1659: https://github.com/giampaolo/psutil/issues/1659 -.. _1660: https://github.com/giampaolo/psutil/issues/1660 -.. _1661: https://github.com/giampaolo/psutil/issues/1661 -.. _1662: https://github.com/giampaolo/psutil/issues/1662 -.. _1663: https://github.com/giampaolo/psutil/issues/1663 -.. _1664: https://github.com/giampaolo/psutil/issues/1664 -.. _1665: https://github.com/giampaolo/psutil/issues/1665 -.. _1666: https://github.com/giampaolo/psutil/issues/1666 -.. _1667: https://github.com/giampaolo/psutil/issues/1667 -.. _1668: https://github.com/giampaolo/psutil/issues/1668 -.. _1669: https://github.com/giampaolo/psutil/issues/1669 -.. _1670: https://github.com/giampaolo/psutil/issues/1670 -.. _1671: https://github.com/giampaolo/psutil/issues/1671 -.. _1672: https://github.com/giampaolo/psutil/issues/1672 -.. _1673: https://github.com/giampaolo/psutil/issues/1673 -.. _1674: https://github.com/giampaolo/psutil/issues/1674 -.. _1675: https://github.com/giampaolo/psutil/issues/1675 -.. _1676: https://github.com/giampaolo/psutil/issues/1676 -.. _1677: https://github.com/giampaolo/psutil/issues/1677 -.. _1678: https://github.com/giampaolo/psutil/issues/1678 -.. _1679: https://github.com/giampaolo/psutil/issues/1679 -.. _1680: https://github.com/giampaolo/psutil/issues/1680 -.. _1681: https://github.com/giampaolo/psutil/issues/1681 -.. _1682: https://github.com/giampaolo/psutil/issues/1682 -.. _1683: https://github.com/giampaolo/psutil/issues/1683 -.. _1684: https://github.com/giampaolo/psutil/issues/1684 -.. _1685: https://github.com/giampaolo/psutil/issues/1685 -.. _1686: https://github.com/giampaolo/psutil/issues/1686 -.. _1687: https://github.com/giampaolo/psutil/issues/1687 -.. _1688: https://github.com/giampaolo/psutil/issues/1688 -.. _1689: https://github.com/giampaolo/psutil/issues/1689 -.. _1690: https://github.com/giampaolo/psutil/issues/1690 -.. _1691: https://github.com/giampaolo/psutil/issues/1691 -.. _1692: https://github.com/giampaolo/psutil/issues/1692 -.. _1693: https://github.com/giampaolo/psutil/issues/1693 -.. _1694: https://github.com/giampaolo/psutil/issues/1694 -.. _1695: https://github.com/giampaolo/psutil/issues/1695 -.. _1696: https://github.com/giampaolo/psutil/issues/1696 -.. _1697: https://github.com/giampaolo/psutil/issues/1697 -.. _1698: https://github.com/giampaolo/psutil/issues/1698 -.. _1699: https://github.com/giampaolo/psutil/issues/1699 -.. _1700: https://github.com/giampaolo/psutil/issues/1700 -.. _1701: https://github.com/giampaolo/psutil/issues/1701 -.. _1702: https://github.com/giampaolo/psutil/issues/1702 -.. _1703: https://github.com/giampaolo/psutil/issues/1703 -.. _1704: https://github.com/giampaolo/psutil/issues/1704 -.. _1705: https://github.com/giampaolo/psutil/issues/1705 -.. _1706: https://github.com/giampaolo/psutil/issues/1706 -.. _1707: https://github.com/giampaolo/psutil/issues/1707 -.. _1708: https://github.com/giampaolo/psutil/issues/1708 -.. _1709: https://github.com/giampaolo/psutil/issues/1709 -.. _1710: https://github.com/giampaolo/psutil/issues/1710 -.. _1711: https://github.com/giampaolo/psutil/issues/1711 -.. _1712: https://github.com/giampaolo/psutil/issues/1712 -.. _1713: https://github.com/giampaolo/psutil/issues/1713 -.. _1714: https://github.com/giampaolo/psutil/issues/1714 -.. _1715: https://github.com/giampaolo/psutil/issues/1715 -.. _1716: https://github.com/giampaolo/psutil/issues/1716 -.. _1717: https://github.com/giampaolo/psutil/issues/1717 -.. _1718: https://github.com/giampaolo/psutil/issues/1718 -.. _1719: https://github.com/giampaolo/psutil/issues/1719 -.. _1720: https://github.com/giampaolo/psutil/issues/1720 -.. _1721: https://github.com/giampaolo/psutil/issues/1721 -.. _1722: https://github.com/giampaolo/psutil/issues/1722 -.. _1723: https://github.com/giampaolo/psutil/issues/1723 -.. _1724: https://github.com/giampaolo/psutil/issues/1724 -.. _1725: https://github.com/giampaolo/psutil/issues/1725 -.. _1726: https://github.com/giampaolo/psutil/issues/1726 -.. _1727: https://github.com/giampaolo/psutil/issues/1727 -.. _1728: https://github.com/giampaolo/psutil/issues/1728 -.. _1729: https://github.com/giampaolo/psutil/issues/1729 -.. _1730: https://github.com/giampaolo/psutil/issues/1730 -.. _1731: https://github.com/giampaolo/psutil/issues/1731 -.. _1732: https://github.com/giampaolo/psutil/issues/1732 -.. _1733: https://github.com/giampaolo/psutil/issues/1733 -.. _1734: https://github.com/giampaolo/psutil/issues/1734 -.. _1735: https://github.com/giampaolo/psutil/issues/1735 -.. _1736: https://github.com/giampaolo/psutil/issues/1736 -.. _1737: https://github.com/giampaolo/psutil/issues/1737 -.. _1738: https://github.com/giampaolo/psutil/issues/1738 -.. _1739: https://github.com/giampaolo/psutil/issues/1739 -.. _1740: https://github.com/giampaolo/psutil/issues/1740 -.. _1741: https://github.com/giampaolo/psutil/issues/1741 -.. _1742: https://github.com/giampaolo/psutil/issues/1742 -.. _1743: https://github.com/giampaolo/psutil/issues/1743 -.. _1744: https://github.com/giampaolo/psutil/issues/1744 -.. _1745: https://github.com/giampaolo/psutil/issues/1745 -.. _1746: https://github.com/giampaolo/psutil/issues/1746 -.. _1747: https://github.com/giampaolo/psutil/issues/1747 -.. _1748: https://github.com/giampaolo/psutil/issues/1748 -.. _1749: https://github.com/giampaolo/psutil/issues/1749 -.. _1750: https://github.com/giampaolo/psutil/issues/1750 -.. _1751: https://github.com/giampaolo/psutil/issues/1751 -.. _1752: https://github.com/giampaolo/psutil/issues/1752 -.. _1753: https://github.com/giampaolo/psutil/issues/1753 -.. _1754: https://github.com/giampaolo/psutil/issues/1754 -.. _1755: https://github.com/giampaolo/psutil/issues/1755 -.. _1756: https://github.com/giampaolo/psutil/issues/1756 -.. _1757: https://github.com/giampaolo/psutil/issues/1757 -.. _1758: https://github.com/giampaolo/psutil/issues/1758 -.. _1759: https://github.com/giampaolo/psutil/issues/1759 -.. _1760: https://github.com/giampaolo/psutil/issues/1760 -.. _1761: https://github.com/giampaolo/psutil/issues/1761 -.. _1762: https://github.com/giampaolo/psutil/issues/1762 -.. _1763: https://github.com/giampaolo/psutil/issues/1763 -.. _1764: https://github.com/giampaolo/psutil/issues/1764 -.. _1765: https://github.com/giampaolo/psutil/issues/1765 -.. _1766: https://github.com/giampaolo/psutil/issues/1766 -.. _1767: https://github.com/giampaolo/psutil/issues/1767 -.. _1768: https://github.com/giampaolo/psutil/issues/1768 -.. _1769: https://github.com/giampaolo/psutil/issues/1769 -.. _1770: https://github.com/giampaolo/psutil/issues/1770 -.. _1771: https://github.com/giampaolo/psutil/issues/1771 -.. _1772: https://github.com/giampaolo/psutil/issues/1772 -.. _1773: https://github.com/giampaolo/psutil/issues/1773 -.. _1774: https://github.com/giampaolo/psutil/issues/1774 -.. _1775: https://github.com/giampaolo/psutil/issues/1775 -.. _1776: https://github.com/giampaolo/psutil/issues/1776 -.. _1777: https://github.com/giampaolo/psutil/issues/1777 -.. _1778: https://github.com/giampaolo/psutil/issues/1778 -.. _1779: https://github.com/giampaolo/psutil/issues/1779 -.. _1780: https://github.com/giampaolo/psutil/issues/1780 -.. _1781: https://github.com/giampaolo/psutil/issues/1781 -.. _1782: https://github.com/giampaolo/psutil/issues/1782 -.. _1783: https://github.com/giampaolo/psutil/issues/1783 -.. _1784: https://github.com/giampaolo/psutil/issues/1784 -.. _1785: https://github.com/giampaolo/psutil/issues/1785 -.. _1786: https://github.com/giampaolo/psutil/issues/1786 -.. _1787: https://github.com/giampaolo/psutil/issues/1787 -.. _1788: https://github.com/giampaolo/psutil/issues/1788 -.. _1789: https://github.com/giampaolo/psutil/issues/1789 -.. _1790: https://github.com/giampaolo/psutil/issues/1790 -.. _1791: https://github.com/giampaolo/psutil/issues/1791 -.. _1792: https://github.com/giampaolo/psutil/issues/1792 -.. _1793: https://github.com/giampaolo/psutil/issues/1793 -.. _1794: https://github.com/giampaolo/psutil/issues/1794 -.. _1795: https://github.com/giampaolo/psutil/issues/1795 -.. _1796: https://github.com/giampaolo/psutil/issues/1796 -.. _1797: https://github.com/giampaolo/psutil/issues/1797 -.. _1798: https://github.com/giampaolo/psutil/issues/1798 -.. _1799: https://github.com/giampaolo/psutil/issues/1799 -.. _1800: https://github.com/giampaolo/psutil/issues/1800 -.. _1801: https://github.com/giampaolo/psutil/issues/1801 -.. _1802: https://github.com/giampaolo/psutil/issues/1802 -.. _1803: https://github.com/giampaolo/psutil/issues/1803 -.. _1804: https://github.com/giampaolo/psutil/issues/1804 -.. _1805: https://github.com/giampaolo/psutil/issues/1805 -.. _1806: https://github.com/giampaolo/psutil/issues/1806 -.. _1807: https://github.com/giampaolo/psutil/issues/1807 -.. _1808: https://github.com/giampaolo/psutil/issues/1808 -.. _1809: https://github.com/giampaolo/psutil/issues/1809 -.. _1810: https://github.com/giampaolo/psutil/issues/1810 -.. _1811: https://github.com/giampaolo/psutil/issues/1811 -.. _1812: https://github.com/giampaolo/psutil/issues/1812 -.. _1813: https://github.com/giampaolo/psutil/issues/1813 -.. _1814: https://github.com/giampaolo/psutil/issues/1814 -.. _1815: https://github.com/giampaolo/psutil/issues/1815 -.. _1816: https://github.com/giampaolo/psutil/issues/1816 -.. _1817: https://github.com/giampaolo/psutil/issues/1817 -.. _1818: https://github.com/giampaolo/psutil/issues/1818 -.. _1819: https://github.com/giampaolo/psutil/issues/1819 -.. _1820: https://github.com/giampaolo/psutil/issues/1820 -.. _1821: https://github.com/giampaolo/psutil/issues/1821 -.. _1822: https://github.com/giampaolo/psutil/issues/1822 -.. _1823: https://github.com/giampaolo/psutil/issues/1823 -.. _1824: https://github.com/giampaolo/psutil/issues/1824 -.. _1825: https://github.com/giampaolo/psutil/issues/1825 -.. _1826: https://github.com/giampaolo/psutil/issues/1826 -.. _1827: https://github.com/giampaolo/psutil/issues/1827 -.. _1828: https://github.com/giampaolo/psutil/issues/1828 -.. _1829: https://github.com/giampaolo/psutil/issues/1829 -.. _1830: https://github.com/giampaolo/psutil/issues/1830 -.. _1831: https://github.com/giampaolo/psutil/issues/1831 -.. _1832: https://github.com/giampaolo/psutil/issues/1832 -.. _1833: https://github.com/giampaolo/psutil/issues/1833 -.. _1834: https://github.com/giampaolo/psutil/issues/1834 -.. _1835: https://github.com/giampaolo/psutil/issues/1835 -.. _1836: https://github.com/giampaolo/psutil/issues/1836 -.. _1837: https://github.com/giampaolo/psutil/issues/1837 -.. _1838: https://github.com/giampaolo/psutil/issues/1838 -.. _1839: https://github.com/giampaolo/psutil/issues/1839 -.. _1840: https://github.com/giampaolo/psutil/issues/1840 -.. _1841: https://github.com/giampaolo/psutil/issues/1841 -.. _1842: https://github.com/giampaolo/psutil/issues/1842 -.. _1843: https://github.com/giampaolo/psutil/issues/1843 -.. _1844: https://github.com/giampaolo/psutil/issues/1844 -.. _1845: https://github.com/giampaolo/psutil/issues/1845 -.. _1846: https://github.com/giampaolo/psutil/issues/1846 -.. _1847: https://github.com/giampaolo/psutil/issues/1847 -.. _1848: https://github.com/giampaolo/psutil/issues/1848 -.. _1849: https://github.com/giampaolo/psutil/issues/1849 -.. _1850: https://github.com/giampaolo/psutil/issues/1850 -.. _1851: https://github.com/giampaolo/psutil/issues/1851 -.. _1852: https://github.com/giampaolo/psutil/issues/1852 -.. _1853: https://github.com/giampaolo/psutil/issues/1853 -.. _1854: https://github.com/giampaolo/psutil/issues/1854 -.. _1855: https://github.com/giampaolo/psutil/issues/1855 -.. _1856: https://github.com/giampaolo/psutil/issues/1856 -.. _1857: https://github.com/giampaolo/psutil/issues/1857 -.. _1858: https://github.com/giampaolo/psutil/issues/1858 -.. _1859: https://github.com/giampaolo/psutil/issues/1859 -.. _1860: https://github.com/giampaolo/psutil/issues/1860 -.. _1861: https://github.com/giampaolo/psutil/issues/1861 -.. _1862: https://github.com/giampaolo/psutil/issues/1862 -.. _1863: https://github.com/giampaolo/psutil/issues/1863 -.. _1864: https://github.com/giampaolo/psutil/issues/1864 -.. _1865: https://github.com/giampaolo/psutil/issues/1865 -.. _1866: https://github.com/giampaolo/psutil/issues/1866 -.. _1867: https://github.com/giampaolo/psutil/issues/1867 -.. _1868: https://github.com/giampaolo/psutil/issues/1868 -.. _1869: https://github.com/giampaolo/psutil/issues/1869 -.. _1870: https://github.com/giampaolo/psutil/issues/1870 -.. _1871: https://github.com/giampaolo/psutil/issues/1871 -.. _1872: https://github.com/giampaolo/psutil/issues/1872 -.. _1873: https://github.com/giampaolo/psutil/issues/1873 -.. _1874: https://github.com/giampaolo/psutil/issues/1874 -.. _1875: https://github.com/giampaolo/psutil/issues/1875 -.. _1876: https://github.com/giampaolo/psutil/issues/1876 -.. _1877: https://github.com/giampaolo/psutil/issues/1877 -.. _1878: https://github.com/giampaolo/psutil/issues/1878 -.. _1879: https://github.com/giampaolo/psutil/issues/1879 -.. _1880: https://github.com/giampaolo/psutil/issues/1880 -.. _1881: https://github.com/giampaolo/psutil/issues/1881 -.. _1882: https://github.com/giampaolo/psutil/issues/1882 -.. _1883: https://github.com/giampaolo/psutil/issues/1883 -.. _1884: https://github.com/giampaolo/psutil/issues/1884 -.. _1885: https://github.com/giampaolo/psutil/issues/1885 -.. _1886: https://github.com/giampaolo/psutil/issues/1886 -.. _1887: https://github.com/giampaolo/psutil/issues/1887 -.. _1888: https://github.com/giampaolo/psutil/issues/1888 -.. _1889: https://github.com/giampaolo/psutil/issues/1889 -.. _1890: https://github.com/giampaolo/psutil/issues/1890 -.. _1891: https://github.com/giampaolo/psutil/issues/1891 -.. _1892: https://github.com/giampaolo/psutil/issues/1892 -.. _1893: https://github.com/giampaolo/psutil/issues/1893 -.. _1894: https://github.com/giampaolo/psutil/issues/1894 -.. _1895: https://github.com/giampaolo/psutil/issues/1895 -.. _1896: https://github.com/giampaolo/psutil/issues/1896 -.. _1897: https://github.com/giampaolo/psutil/issues/1897 -.. _1898: https://github.com/giampaolo/psutil/issues/1898 -.. _1899: https://github.com/giampaolo/psutil/issues/1899 -.. _1900: https://github.com/giampaolo/psutil/issues/1900 -.. _1901: https://github.com/giampaolo/psutil/issues/1901 -.. _1902: https://github.com/giampaolo/psutil/issues/1902 -.. _1903: https://github.com/giampaolo/psutil/issues/1903 -.. _1904: https://github.com/giampaolo/psutil/issues/1904 -.. _1905: https://github.com/giampaolo/psutil/issues/1905 -.. _1906: https://github.com/giampaolo/psutil/issues/1906 -.. _1907: https://github.com/giampaolo/psutil/issues/1907 -.. _1908: https://github.com/giampaolo/psutil/issues/1908 -.. _1909: https://github.com/giampaolo/psutil/issues/1909 -.. _1910: https://github.com/giampaolo/psutil/issues/1910 -.. _1911: https://github.com/giampaolo/psutil/issues/1911 -.. _1912: https://github.com/giampaolo/psutil/issues/1912 -.. _1913: https://github.com/giampaolo/psutil/issues/1913 -.. _1914: https://github.com/giampaolo/psutil/issues/1914 -.. _1915: https://github.com/giampaolo/psutil/issues/1915 -.. _1916: https://github.com/giampaolo/psutil/issues/1916 -.. _1917: https://github.com/giampaolo/psutil/issues/1917 -.. _1918: https://github.com/giampaolo/psutil/issues/1918 -.. _1919: https://github.com/giampaolo/psutil/issues/1919 -.. _1920: https://github.com/giampaolo/psutil/issues/1920 -.. _1921: https://github.com/giampaolo/psutil/issues/1921 -.. _1922: https://github.com/giampaolo/psutil/issues/1922 -.. _1923: https://github.com/giampaolo/psutil/issues/1923 -.. _1924: https://github.com/giampaolo/psutil/issues/1924 -.. _1925: https://github.com/giampaolo/psutil/issues/1925 -.. _1926: https://github.com/giampaolo/psutil/issues/1926 -.. _1927: https://github.com/giampaolo/psutil/issues/1927 -.. _1928: https://github.com/giampaolo/psutil/issues/1928 -.. _1929: https://github.com/giampaolo/psutil/issues/1929 -.. _1930: https://github.com/giampaolo/psutil/issues/1930 -.. _1931: https://github.com/giampaolo/psutil/issues/1931 -.. _1932: https://github.com/giampaolo/psutil/issues/1932 -.. _1933: https://github.com/giampaolo/psutil/issues/1933 -.. _1934: https://github.com/giampaolo/psutil/issues/1934 -.. _1935: https://github.com/giampaolo/psutil/issues/1935 -.. _1936: https://github.com/giampaolo/psutil/issues/1936 -.. _1937: https://github.com/giampaolo/psutil/issues/1937 -.. _1938: https://github.com/giampaolo/psutil/issues/1938 -.. _1939: https://github.com/giampaolo/psutil/issues/1939 -.. _1940: https://github.com/giampaolo/psutil/issues/1940 -.. _1941: https://github.com/giampaolo/psutil/issues/1941 -.. _1942: https://github.com/giampaolo/psutil/issues/1942 -.. _1943: https://github.com/giampaolo/psutil/issues/1943 -.. _1944: https://github.com/giampaolo/psutil/issues/1944 -.. _1945: https://github.com/giampaolo/psutil/issues/1945 -.. _1946: https://github.com/giampaolo/psutil/issues/1946 -.. _1947: https://github.com/giampaolo/psutil/issues/1947 -.. _1948: https://github.com/giampaolo/psutil/issues/1948 -.. _1949: https://github.com/giampaolo/psutil/issues/1949 -.. _1950: https://github.com/giampaolo/psutil/issues/1950 -.. _1951: https://github.com/giampaolo/psutil/issues/1951 -.. _1952: https://github.com/giampaolo/psutil/issues/1952 -.. _1953: https://github.com/giampaolo/psutil/issues/1953 -.. _1954: https://github.com/giampaolo/psutil/issues/1954 -.. _1955: https://github.com/giampaolo/psutil/issues/1955 -.. _1956: https://github.com/giampaolo/psutil/issues/1956 -.. _1957: https://github.com/giampaolo/psutil/issues/1957 -.. _1958: https://github.com/giampaolo/psutil/issues/1958 -.. _1959: https://github.com/giampaolo/psutil/issues/1959 -.. _1960: https://github.com/giampaolo/psutil/issues/1960 -.. _1961: https://github.com/giampaolo/psutil/issues/1961 -.. _1962: https://github.com/giampaolo/psutil/issues/1962 -.. _1963: https://github.com/giampaolo/psutil/issues/1963 -.. _1964: https://github.com/giampaolo/psutil/issues/1964 -.. _1965: https://github.com/giampaolo/psutil/issues/1965 -.. _1966: https://github.com/giampaolo/psutil/issues/1966 -.. _1967: https://github.com/giampaolo/psutil/issues/1967 -.. _1968: https://github.com/giampaolo/psutil/issues/1968 -.. _1969: https://github.com/giampaolo/psutil/issues/1969 -.. _1970: https://github.com/giampaolo/psutil/issues/1970 -.. _1971: https://github.com/giampaolo/psutil/issues/1971 -.. _1972: https://github.com/giampaolo/psutil/issues/1972 -.. _1973: https://github.com/giampaolo/psutil/issues/1973 -.. _1974: https://github.com/giampaolo/psutil/issues/1974 -.. _1975: https://github.com/giampaolo/psutil/issues/1975 -.. _1976: https://github.com/giampaolo/psutil/issues/1976 -.. _1977: https://github.com/giampaolo/psutil/issues/1977 -.. _1978: https://github.com/giampaolo/psutil/issues/1978 -.. _1979: https://github.com/giampaolo/psutil/issues/1979 -.. _1980: https://github.com/giampaolo/psutil/issues/1980 -.. _1981: https://github.com/giampaolo/psutil/issues/1981 -.. _1982: https://github.com/giampaolo/psutil/issues/1982 -.. _1983: https://github.com/giampaolo/psutil/issues/1983 -.. _1984: https://github.com/giampaolo/psutil/issues/1984 -.. _1985: https://github.com/giampaolo/psutil/issues/1985 -.. _1986: https://github.com/giampaolo/psutil/issues/1986 -.. _1987: https://github.com/giampaolo/psutil/issues/1987 -.. _1988: https://github.com/giampaolo/psutil/issues/1988 -.. _1989: https://github.com/giampaolo/psutil/issues/1989 -.. _1990: https://github.com/giampaolo/psutil/issues/1990 -.. _1991: https://github.com/giampaolo/psutil/issues/1991 -.. _1992: https://github.com/giampaolo/psutil/issues/1992 -.. _1993: https://github.com/giampaolo/psutil/issues/1993 -.. _1994: https://github.com/giampaolo/psutil/issues/1994 -.. _1995: https://github.com/giampaolo/psutil/issues/1995 -.. _1996: https://github.com/giampaolo/psutil/issues/1996 -.. _1997: https://github.com/giampaolo/psutil/issues/1997 -.. _1998: https://github.com/giampaolo/psutil/issues/1998 -.. _1999: https://github.com/giampaolo/psutil/issues/1999 -.. _2000: https://github.com/giampaolo/psutil/issues/2000 diff --git a/third_party/python/psutil/INSTALL.rst b/third_party/python/psutil/INSTALL.rst deleted file mode 100644 index c3b9e91c0c9a..000000000000 --- a/third_party/python/psutil/INSTALL.rst +++ /dev/null @@ -1,140 +0,0 @@ -Install pip -=========== - -pip is the easiest way to install psutil. It is shipped by default with Python -2.7.9+ and 3.4+. For other Python versions you can install it manually. -On Linux or via wget:: - - wget https://bootstrap.pypa.io/get-pip.py -O - | python - -On macOS or via curl:: - - python < <(curl -s https://bootstrap.pypa.io/get-pip.py) - -On Windows, `download pip `__, open -cmd.exe and install it:: - - C:\Python27\python.exe get-pip.py - -Permission issues (UNIX) -======================== - -The commands below assume you're running as root. -If you aren't or you bump into permission errors you can either install psutil -for your user only:: - - pip3 install --user psutil - -...or prepend ``sudo`` and install it globally, e.g.:: - - sudo pip3 install psutil - -Linux -===== - -Ubuntu / Debian:: - - sudo apt-get install gcc python3-dev - pip3 install psutil - -RedHat / CentOS:: - - sudo yum install gcc python3-devel - pip3 install psutil - -If you're on Python 2 use ``python-dev`` instead. - -macOS -===== - -Install `Xcode `__ then run:: - - pip3 install psutil - -Windows -======= - -Open a cmd.exe shell and run:: - - python3 -m pip install psutil - -This assumes "python" is in your PATH. If not, specify the full python.exe -path. - -In order to compile psutil from sources you'll need **Visual Studio** (Mingw32 -is not supported). -This `blog post `__ -provides numerous info on how to properly set up VS. The needed VS versions are: - -* Python 2.6, 2.7: `VS-2008 `__ -* Python 3.4: `VS-2010 `__ -* Python 3.5+: `VS-2015 `__ - -Compiling 64 bit versions of Python 2.6 and 2.7 with VS 2008 requires -`Windows SDK and .NET Framework 3.5 SP1 `__. -Once installed run `vcvars64.bat` -(see `here `__). -Once VS is setup open a cmd.exe shell, cd into psutil directory and run:: - - python3 setup.py build - python3 setup.py install - -FreeBSD -======= - -:: - - pkg install python3 gcc - python -m pip3 install psutil - -OpenBSD -======= - -:: - - export PKG_PATH=http://ftp.eu.openbsd.org/pub/OpenBSD/`uname -r`/packages/`uname -m`/ - pkg_add -v python gcc - python3 -m pip install psutil - -NetBSD -====== - -:: - - export PKG_PATH="ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/`uname -m`/`uname -r`/All" - pkg_add -v pkgin - pkgin install python3 gcc - python3 -m pip install psutil - -Solaris -======= - -If ``cc`` compiler is not installed create a symlink to ``gcc``:: - - sudo ln -s /usr/bin/gcc /usr/local/bin/cc - -Install:: - - pkg install gcc - python3 -m pip install psutil - -Install from sources -==================== - -:: - - git clone https://github.com/giampaolo/psutil.git - cd psutil - python3 setup.py install - -Testing installation -==================== - -:: - - python3 -m psutil.tests - -Dev Guide -========= - -See: `dev guide `__. diff --git a/third_party/python/psutil/LICENSE b/third_party/python/psutil/LICENSE deleted file mode 100644 index 0bf4a7fc04a1..000000000000 --- a/third_party/python/psutil/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola' -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name of the psutil authors nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/python/psutil/MANIFEST.in b/third_party/python/psutil/MANIFEST.in deleted file mode 100644 index 801139b2c131..000000000000 --- a/third_party/python/psutil/MANIFEST.in +++ /dev/null @@ -1,145 +0,0 @@ -include .cirrus.yml -include .coveragerc -include .gitignore -include CREDITS -include HISTORY.rst -include INSTALL.rst -include LICENSE -include MANIFEST.in -include Makefile -include README.rst -include docs/DEVGUIDE.rst -include docs/DEVNOTES -include docs/Makefile -include docs/README -include docs/_static/copybutton.js -include docs/_static/css/custom.css -include docs/_static/favicon.ico -include docs/_static/sidebar.js -include docs/conf.py -include docs/index.rst -include docs/make.bat -include make.bat -include psutil/__init__.py -include psutil/_common.py -include psutil/_compat.py -include psutil/_psaix.py -include psutil/_psbsd.py -include psutil/_pslinux.py -include psutil/_psosx.py -include psutil/_psposix.py -include psutil/_pssunos.py -include psutil/_psutil_aix.c -include psutil/_psutil_bsd.c -include psutil/_psutil_common.c -include psutil/_psutil_common.h -include psutil/_psutil_linux.c -include psutil/_psutil_osx.c -include psutil/_psutil_posix.c -include psutil/_psutil_posix.h -include psutil/_psutil_sunos.c -include psutil/_psutil_windows.c -include psutil/_pswindows.py -include psutil/arch/aix/common.c -include psutil/arch/aix/common.h -include psutil/arch/aix/ifaddrs.c -include psutil/arch/aix/ifaddrs.h -include psutil/arch/aix/net_connections.c -include psutil/arch/aix/net_connections.h -include psutil/arch/aix/net_kernel_structs.h -include psutil/arch/freebsd/proc_socks.c -include psutil/arch/freebsd/proc_socks.h -include psutil/arch/freebsd/specific.c -include psutil/arch/freebsd/specific.h -include psutil/arch/freebsd/sys_socks.c -include psutil/arch/freebsd/sys_socks.h -include psutil/arch/netbsd/socks.c -include psutil/arch/netbsd/socks.h -include psutil/arch/netbsd/specific.c -include psutil/arch/netbsd/specific.h -include psutil/arch/openbsd/specific.c -include psutil/arch/openbsd/specific.h -include psutil/arch/osx/process_info.c -include psutil/arch/osx/process_info.h -include psutil/arch/solaris/environ.c -include psutil/arch/solaris/environ.h -include psutil/arch/solaris/v10/ifaddrs.c -include psutil/arch/solaris/v10/ifaddrs.h -include psutil/arch/windows/cpu.c -include psutil/arch/windows/cpu.h -include psutil/arch/windows/disk.c -include psutil/arch/windows/disk.h -include psutil/arch/windows/net.c -include psutil/arch/windows/net.h -include psutil/arch/windows/ntextapi.h -include psutil/arch/windows/process_handles.c -include psutil/arch/windows/process_handles.h -include psutil/arch/windows/process_info.c -include psutil/arch/windows/process_info.h -include psutil/arch/windows/process_utils.c -include psutil/arch/windows/process_utils.h -include psutil/arch/windows/security.c -include psutil/arch/windows/security.h -include psutil/arch/windows/services.c -include psutil/arch/windows/services.h -include psutil/arch/windows/socks.c -include psutil/arch/windows/socks.h -include psutil/arch/windows/wmi.c -include psutil/arch/windows/wmi.h -include psutil/tests/README.rst -include psutil/tests/__init__.py -include psutil/tests/__main__.py -include psutil/tests/runner.py -include psutil/tests/test_aix.py -include psutil/tests/test_bsd.py -include psutil/tests/test_connections.py -include psutil/tests/test_contracts.py -include psutil/tests/test_linux.py -include psutil/tests/test_memory_leaks.py -include psutil/tests/test_misc.py -include psutil/tests/test_osx.py -include psutil/tests/test_posix.py -include psutil/tests/test_process.py -include psutil/tests/test_sunos.py -include psutil/tests/test_system.py -include psutil/tests/test_unicode.py -include psutil/tests/test_windows.py -include scripts/battery.py -include scripts/cpu_distribution.py -include scripts/disk_usage.py -include scripts/fans.py -include scripts/free.py -include scripts/ifconfig.py -include scripts/internal/.git-pre-commit -include scripts/internal/README -include scripts/internal/bench_oneshot.py -include scripts/internal/bench_oneshot_2.py -include scripts/internal/check_broken_links.py -include scripts/internal/clinter.py -include scripts/internal/fix_flake8.py -include scripts/internal/generate_manifest.py -include scripts/internal/print_access_denied.py -include scripts/internal/print_announce.py -include scripts/internal/print_api_speed.py -include scripts/internal/print_timeline.py -include scripts/internal/purge_installation.py -include scripts/internal/win_download_wheels.py -include scripts/internal/winmake.py -include scripts/iotop.py -include scripts/killall.py -include scripts/meminfo.py -include scripts/netstat.py -include scripts/nettop.py -include scripts/pidof.py -include scripts/pmap.py -include scripts/procinfo.py -include scripts/procsmem.py -include scripts/ps.py -include scripts/pstree.py -include scripts/sensors.py -include scripts/temperatures.py -include scripts/top.py -include scripts/who.py -include scripts/winservices.py -include setup.py -include tox.ini diff --git a/third_party/python/psutil/Makefile b/third_party/python/psutil/Makefile deleted file mode 100644 index b15aa5d95723..000000000000 --- a/third_party/python/psutil/Makefile +++ /dev/null @@ -1,292 +0,0 @@ -# Shortcuts for various tasks (UNIX only). -# To use a specific Python version run: "make install PYTHON=python3.3" -# You can set the variables below from the command line. - -PYTHON = python3 -TSCRIPT = psutil/tests/runner.py -ARGS = -# List of nice-to-have dev libs. -DEPS = \ - argparse \ - check-manifest \ - coverage \ - flake8 \ - pyperf \ - requests \ - setuptools \ - twine \ - virtualenv \ - wheel -PY2_DEPS = \ - futures \ - ipaddress \ - mock==1.0.1 \ - unittest2 -DEPS += `$(PYTHON) -c \ - "import sys; print('$(PY2_DEPS)' if sys.version_info[0] == 2 else '')"` -# In not in a virtualenv, add --user options for install commands. -INSTALL_OPTS = `$(PYTHON) -c \ - "import sys; print('' if hasattr(sys, 'real_prefix') else '--user')"` -TEST_PREFIX = PYTHONWARNINGS=all PSUTIL_TESTING=1 PSUTIL_DEBUG=1 - -all: test - -# =================================================================== -# Install -# =================================================================== - -clean: ## Remove all build files. - rm -rf `find . -type d -name __pycache__ \ - -o -type f -name \*.bak \ - -o -type f -name \*.orig \ - -o -type f -name \*.pyc \ - -o -type f -name \*.pyd \ - -o -type f -name \*.pyo \ - -o -type f -name \*.rej \ - -o -type f -name \*.so \ - -o -type f -name \*.~ \ - -o -type f -name \*\$testfn` - rm -rf \ - *.core \ - *.egg-info \ - *\$testfn* \ - .coverage \ - .failed-tests.txt \ - .tox \ - build/ \ - dist/ \ - docs/_build/ \ - htmlcov/ - -_: - -build: _ ## Compile without installing. - # make sure setuptools is installed (needed for 'develop' / edit mode) - $(PYTHON) -c "import setuptools" - PYTHONWARNINGS=all $(PYTHON) setup.py build - @# copies compiled *.so files in ./psutil directory in order to allow - @# "import psutil" when using the interactive interpreter from within - @# this directory. - PYTHONWARNINGS=all $(PYTHON) setup.py build_ext -i - $(PYTHON) -c "import psutil" # make sure it actually worked - -install: ## Install this package as current user in "edit" mode. - ${MAKE} build - PYTHONWARNINGS=all $(PYTHON) setup.py develop $(INSTALL_OPTS) - -uninstall: ## Uninstall this package via pip. - cd ..; $(PYTHON) -m pip uninstall -y -v psutil || true - $(PYTHON) scripts/internal/purge_installation.py - -install-pip: ## Install pip (no-op if already installed). - $(PYTHON) -c \ - "import sys, ssl, os, pkgutil, tempfile, atexit; \ - sys.exit(0) if pkgutil.find_loader('pip') else None; \ - pyexc = 'from urllib.request import urlopen' if sys.version_info[0] == 3 else 'from urllib2 import urlopen'; \ - exec(pyexc); \ - ctx = ssl._create_unverified_context() if hasattr(ssl, '_create_unverified_context') else None; \ - kw = dict(context=ctx) if ctx else {}; \ - req = urlopen('https://bootstrap.pypa.io/get-pip.py', **kw); \ - data = req.read(); \ - f = tempfile.NamedTemporaryFile(suffix='.py'); \ - atexit.register(f.close); \ - f.write(data); \ - f.flush(); \ - print('downloaded %s' % f.name); \ - code = os.system('%s %s --user' % (sys.executable, f.name)); \ - f.close(); \ - sys.exit(code);" - -setup-dev-env: ## Install GIT hooks, pip, test deps (also upgrades them). - ${MAKE} install-git-hooks - ${MAKE} install-pip - $(PYTHON) -m pip install $(INSTALL_OPTS) --upgrade --trusted-host files.pythonhosted.org pip - $(PYTHON) -m pip install $(INSTALL_OPTS) --upgrade --trusted-host files.pythonhosted.org $(DEPS) - -# =================================================================== -# Tests -# =================================================================== - -test: ## Run all tests. - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) $(TSCRIPT) - -test-process: ## Run process-related API tests. - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) psutil/tests/test_process.py - -test-system: ## Run system-related API tests. - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) psutil/tests/test_system.py - -test-misc: ## Run miscellaneous tests. - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) psutil/tests/test_misc.py - -test-unicode: ## Test APIs dealing with strings. - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) psutil/tests/test_unicode.py - -test-contracts: ## APIs sanity tests. - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) psutil/tests/test_contracts.py - -test-connections: ## Test net_connections() and Process.connections(). - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) psutil/tests/test_connections.py - -test-posix: ## POSIX specific tests. - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) psutil/tests/test_posix.py - -test-platform: ## Run specific platform tests only. - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) psutil/tests/test_`$(PYTHON) -c 'import psutil; print([x.lower() for x in ("LINUX", "BSD", "OSX", "SUNOS", "WINDOWS", "AIX") if getattr(psutil, x)][0])'`.py - -test-memleaks: ## Memory leak tests. - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) psutil/tests/test_memory_leaks.py - -test-by-name: ## e.g. make test-by-name ARGS=psutil.tests.test_system.TestSystemAPIs - ${MAKE} install - @$(TEST_PREFIX) $(PYTHON) -m unittest -v $(ARGS) - -test-failed: ## Re-run tests which failed on last run - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) $(TSCRIPT) --last-failed - -test-coverage: ## Run test coverage. - ${MAKE} install - # Note: coverage options are controlled by .coveragerc file - rm -rf .coverage htmlcov - $(TEST_PREFIX) $(PYTHON) -m coverage run $(TSCRIPT) - $(PYTHON) -m coverage report - @echo "writing results to htmlcov/index.html" - $(PYTHON) -m coverage html - $(PYTHON) -m webbrowser -t htmlcov/index.html - -# =================================================================== -# Linters -# =================================================================== - -lint-py: ## Run Python (flake8) linter. - @git ls-files '*.py' | xargs $(PYTHON) -m flake8 - -lint-c: ## Run C linter. - @git ls-files '*.c' '*.h' | xargs $(PYTHON) scripts/internal/clinter.py - -lint: ## Run Python (flake8) and C linters. - ${MAKE} lint-py - ${MAKE} lint-c - -fix-lint: ## Attempt to automatically fix some Python lint issues. - @git ls-files | grep \\.py$ | xargs $(PYTHON) -m flake8 --exit-zero | $(PYTHON) scripts/internal/fix_flake8.py - -# =================================================================== -# GIT -# =================================================================== - -git-tag-release: ## Git-tag a new release. - git tag -a release-`python -c "import setup; print(setup.get_version())"` -m `git rev-list HEAD --count`:`git rev-parse --short HEAD` - git push --follow-tags - -install-git-hooks: ## Install GIT pre-commit hook. - ln -sf ../../scripts/internal/.git-pre-commit .git/hooks/pre-commit - chmod +x .git/hooks/pre-commit - -# =================================================================== -# Distribution -# =================================================================== - -sdist: ## Create tar.gz source distribution. - ${MAKE} generate-manifest - $(PYTHON) setup.py sdist - -wheel: ## Generate wheel. - $(PYTHON) setup.py bdist_wheel - -win-download-wheels: ## Download wheels hosted on appveyor. - $(TEST_PREFIX) $(PYTHON) scripts/internal/win_download_wheels.py --user giampaolo --project psutil - -upload-src: ## Upload source tarball on https://pypi.org/project/psutil/ - ${MAKE} sdist - $(PYTHON) setup.py sdist upload - -upload-win-wheels: ## Upload wheels in dist/* directory on PyPI. - $(PYTHON) -m twine upload dist/*.whl - -# --- others - -check-sdist: ## Create source distribution and checks its sanity (MANIFEST) - rm -rf dist - ${MAKE} clean - $(PYTHON) -m virtualenv --clear --no-wheel --quiet build/venv - PYTHONWARNINGS=all $(PYTHON) setup.py sdist - build/venv/bin/python -m pip install -v --isolated --quiet dist/*.tar.gz - build/venv/bin/python -c "import os; os.chdir('build/venv'); import psutil" - -pre-release: ## Check if we're ready to produce a new release. - ${MAKE} check-sdist - ${MAKE} install - ${MAKE} generate-manifest - git diff MANIFEST.in > /dev/null # ...otherwise 'git diff-index HEAD' will complain - ${MAKE} win-download-wheels - ${MAKE} sdist - $(PYTHON) -c \ - "from psutil import __version__ as ver; \ - doc = open('docs/index.rst').read(); \ - history = open('HISTORY.rst').read(); \ - assert ver in doc, '%r not in docs/index.rst' % ver; \ - assert ver in history, '%r not in HISTORY.rst' % ver; \ - assert 'XXXX' not in history, 'XXXX in HISTORY.rst';" - $(PYTHON) -c "import subprocess, sys; out = subprocess.check_output('git diff --quiet && git diff --cached --quiet', shell=True).strip(); sys.exit('there are uncommitted changes:\n%s' % out) if out else 0 ;" - -release: ## Create a release (down/uploads tar.gz, wheels, git tag release). - ${MAKE} pre-release - $(PYTHON) -m twine upload dist/* # upload tar.gz and Windows wheels on PyPI - ${MAKE} git-tag-release - -check-manifest: ## Inspect MANIFEST.in file. - $(PYTHON) -m check_manifest -v $(ARGS) - -generate-manifest: ## Generates MANIFEST.in file. - $(PYTHON) scripts/internal/generate_manifest.py > MANIFEST.in - -# =================================================================== -# Printers -# =================================================================== - -print-announce: ## Print announce of new release. - @$(PYTHON) scripts/internal/print_announce.py - -print-timeline: ## Print releases' timeline. - @$(PYTHON) scripts/internal/print_timeline.py - -print-access-denied: ## Print AD exceptions - ${MAKE} install - @$(TEST_PREFIX) $(PYTHON) scripts/internal/print_access_denied.py - -print-api-speed: ## Benchmark all API calls - ${MAKE} install - @$(TEST_PREFIX) $(PYTHON) scripts/internal/print_api_speed.py $(ARGS) - -# =================================================================== -# Misc -# =================================================================== - -grep-todos: ## Look for TODOs in the source files. - git grep -EIn "TODO|FIXME|XXX" - -bench-oneshot: ## Benchmarks for oneshot() ctx manager (see #799). - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) scripts/internal/bench_oneshot.py - -bench-oneshot-2: ## Same as above but using perf module (supposed to be more precise) - ${MAKE} install - $(TEST_PREFIX) $(PYTHON) scripts/internal/bench_oneshot_2.py - -check-broken-links: ## Look for broken links in source files. - git ls-files | xargs $(PYTHON) -Wa scripts/internal/check_broken_links.py - -help: ## Display callable targets. - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' diff --git a/third_party/python/psutil/PKG-INFO b/third_party/python/psutil/PKG-INFO deleted file mode 100644 index bc21bff7fb25..000000000000 --- a/third_party/python/psutil/PKG-INFO +++ /dev/null @@ -1,578 +0,0 @@ -Metadata-Version: 1.2 -Name: psutil -Version: 5.7.0 -Summary: Cross-platform lib for process and system monitoring in Python. -Home-page: https://github.com/giampaolo/psutil -Author: Giampaolo Rodola -Author-email: g.rodola@gmail.com -License: BSD -Description: | |downloads| |stars| |forks| |contributors| |coverage| |quality| - | |version| |py-versions| |packages| |license| - | |travis| |appveyor| |cirrus| |doc| |twitter| |tidelift| - - .. |downloads| image:: https://img.shields.io/pypi/dm/psutil.svg - :target: https://pepy.tech/project/psutil - :alt: Downloads - - .. |stars| image:: https://img.shields.io/github/stars/giampaolo/psutil.svg - :target: https://github.com/giampaolo/psutil/stargazers - :alt: Github stars - - .. |forks| image:: https://img.shields.io/github/forks/giampaolo/psutil.svg - :target: https://github.com/giampaolo/psutil/network/members - :alt: Github forks - - .. |contributors| image:: https://img.shields.io/github/contributors/giampaolo/psutil.svg - :target: https://github.com/giampaolo/psutil/graphs/contributors - :alt: Contributors - - .. |quality| image:: https://img.shields.io/codacy/grade/ce63e7f7f69d44b5b59682196e6fbfca.svg - :target: https://www.codacy.com/app/g-rodola/psutil?utm_source=github.com&utm_medium=referral&utm_content=giampaolo/psutil&utm_campaign=Badge_Grade - :alt: Code quality - - .. |travis| image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux,%20OSX,%20PyPy - :target: https://travis-ci.org/giampaolo/psutil - :alt: Linux tests (Travis) - - .. |appveyor| image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows - :target: https://ci.appveyor.com/project/giampaolo/psutil - :alt: Windows tests (Appveyor) - - .. |cirrus| image:: https://img.shields.io/cirrus/github/giampaolo/psutil?label=FreeBSD - :target: https://cirrus-ci.com/github/giampaolo/psutil-cirrus-ci - :alt: FreeBSD tests (Cirrus-Ci) - - .. |coverage| image:: https://img.shields.io/coveralls/github/giampaolo/psutil.svg?label=test%20coverage - :target: https://coveralls.io/github/giampaolo/psutil?branch=master - :alt: Test coverage (coverall.io) - - .. |doc| image:: https://readthedocs.org/projects/psutil/badge/?version=latest - :target: http://psutil.readthedocs.io/en/latest/?badge=latest - :alt: Documentation Status - - .. |version| image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi - :target: https://pypi.org/project/psutil - :alt: Latest version - - .. |py-versions| image:: https://img.shields.io/pypi/pyversions/psutil.svg - :target: https://pypi.org/project/psutil - :alt: Supported Python versions - - .. |packages| image:: https://repology.org/badge/tiny-repos/python:psutil.svg - :target: https://repology.org/metapackage/python:psutil/versions - :alt: Binary packages - - .. |license| image:: https://img.shields.io/pypi/l/psutil.svg - :target: https://github.com/giampaolo/psutil/blob/master/LICENSE - :alt: License - - .. |twitter| image:: https://img.shields.io/twitter/follow/grodola.svg?label=follow&style=flat&logo=twitter&logoColor=4FADFF - :target: https://twitter.com/grodola - :alt: Twitter Follow - - .. |tidelift| image:: https://tidelift.com/badges/github/giampaolo/psutil?style=flat - :target: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme - :alt: Tidelift - - ----- - - Quick links - =========== - - - `Home page `_ - - `Install `_ - - `Documentation `_ - - `Download `_ - - `Forum `_ - - `StackOverflow `_ - - `Blog `_ - - `Development guide `_ - - `What's new `_ - - Summary - ======= - - psutil (process and system utilities) is a cross-platform library for - retrieving information on **running processes** and **system utilization** - (CPU, memory, disks, network, sensors) in Python. - It is useful mainly for **system monitoring**, **profiling and limiting process - resources** and **management of running processes**. - It implements many functionalities offered by classic UNIX command line tools - such as *ps, top, iotop, lsof, netstat, ifconfig, free* and others. - psutil currently supports the following platforms: - - - **Linux** - - **Windows** - - **macOS** - - **FreeBSD, OpenBSD**, **NetBSD** - - **Sun Solaris** - - **AIX** - - ...both **32-bit** and **64-bit** architectures. Supported Python versions are **2.6**, **2.7** and **3.4+**. `PyPy3 `__ is also known to work. - - psutil for enterprise - ===================== - - .. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png - :width: 150 - :alt: Tidelift - :target: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme - - .. list-table:: - :widths: 10 150 - - * - |tideliftlogo| - - The maintainer of psutil and thousands of other packages are working - with Tidelift to deliver commercial support and maintenance for the open - source dependencies you use to build your applications. Save time, - reduce risk, and improve code health, while paying the maintainers of - the exact dependencies you use. - `Learn more `__. - - By subscribing to Tidelift you will help me (`Giampaolo Rodola`_) support - psutil future development. Alternatively consider making a small - `donation`_. - - Security - ======== - - To report a security vulnerability, please use the `Tidelift security - contact`_. Tidelift will coordinate the fix and disclosure. - - Example applications - ==================== - - +------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ - | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/top-small.png | - | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/top.png | - +------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ - | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap-small.png | - | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap.png | - +------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ - - Also see `scripts directory `__ - and `doc recipes `__. - - Projects using psutil - ===================== - - psutil has roughly the following monthly downloads: - - .. image:: https://img.shields.io/pypi/dm/psutil.svg - :target: https://pepy.tech/project/psutil - :alt: Downloads - - There are over - `10.000 open source projects `__ - on github which depend from psutil. - Here's some I find particularly interesting: - - - https://github.com/google/grr - - https://github.com/facebook/osquery/ - - https://github.com/nicolargo/glances - - https://github.com/Jahaja/psdash - - https://github.com/ajenti/ajenti - - https://github.com/home-assistant/home-assistant/ - - - Portings - ======== - - - Go: https://github.com/shirou/gopsutil - - C: https://github.com/hamon-in/cpslib - - Rust: https://github.com/borntyping/rust-psutil - - Nim: https://github.com/johnscillieri/psutil-nim - - - Example usages - ============== - - This represents pretty much the whole psutil API. - - CPU - --- - - .. code-block:: python - - >>> import psutil - >>> - >>> psutil.cpu_times() - scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0) - >>> - >>> for x in range(3): - ... psutil.cpu_percent(interval=1) - ... - 4.0 - 5.9 - 3.8 - >>> - >>> for x in range(3): - ... psutil.cpu_percent(interval=1, percpu=True) - ... - [4.0, 6.9, 3.7, 9.2] - [7.0, 8.5, 2.4, 2.1] - [1.2, 9.0, 9.9, 7.2] - >>> - >>> for x in range(3): - ... psutil.cpu_times_percent(interval=1, percpu=False) - ... - scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - >>> - >>> psutil.cpu_count() - 4 - >>> psutil.cpu_count(logical=False) - 2 - >>> - >>> psutil.cpu_stats() - scpustats(ctx_switches=20455687, interrupts=6598984, soft_interrupts=2134212, syscalls=0) - >>> - >>> psutil.cpu_freq() - scpufreq(current=931.42925, min=800.0, max=3500.0) - >>> - >>> psutil.getloadavg() # also on Windows (emulated) - (3.14, 3.89, 4.67) - - Memory - ------ - - .. code-block:: python - - >>> psutil.virtual_memory() - svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304) - >>> psutil.swap_memory() - sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944) - >>> - - Disks - ----- - - .. code-block:: python - - >>> psutil.disk_partitions() - [sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'), - sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')] - >>> - >>> psutil.disk_usage('/') - sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5) - >>> - >>> psutil.disk_io_counters(perdisk=False) - sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568, read_merged_count=619166, write_merged_count=812396, busy_time=4523412) - >>> - - Network - ------- - - .. code-block:: python - - >>> psutil.net_io_counters(pernic=True) - {'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0), - 'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)} - >>> - >>> psutil.net_connections() - [sconn(fd=115, family=, type=, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254), - sconn(fd=117, family=, type=, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING', pid=2987), - ...] - >>> - >>> psutil.net_if_addrs() - {'lo': [snicaddr(family=, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None), - snicaddr(family=, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None), - snicaddr(family=, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)], - 'wlan0': [snicaddr(family=, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None), - snicaddr(family=, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None), - snicaddr(family=, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]} - >>> - >>> psutil.net_if_stats() - {'lo': snicstats(isup=True, duplex=, speed=0, mtu=65536), - 'wlan0': snicstats(isup=True, duplex=, speed=100, mtu=1500)} - >>> - - Sensors - ------- - - .. code-block:: python - - >>> import psutil - >>> psutil.sensors_temperatures() - {'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)], - 'asus': [shwtemp(label='', current=47.0, high=None, critical=None)], - 'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0), - shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0)]} - >>> - >>> psutil.sensors_fans() - {'asus': [sfan(label='cpu_fan', current=3200)]} - >>> - >>> psutil.sensors_battery() - sbattery(percent=93, secsleft=16628, power_plugged=False) - >>> - - Other system info - ----------------- - - .. code-block:: python - - >>> import psutil - >>> psutil.users() - [suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0, pid=1352), - suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0, pid=1788)] - >>> - >>> psutil.boot_time() - 1365519115.0 - >>> - - Process management - ------------------ - - .. code-block:: python - - >>> import psutil - >>> psutil.pids() - [1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224, 268, 1215, 1216, 1220, 1221, 1243, 1244, - 1301, 1601, 2237, 2355, 2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, 4263, 4282, - 4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358, 4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446, - 5167, 5234, 5235, 5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071] - >>> - >>> p = psutil.Process(7055) - >>> p - psutil.Process(pid=7055, name='python', started='09:04:44') - >>> p.name() - 'python' - >>> p.exe() - '/usr/bin/python' - >>> p.cwd() - '/home/giampaolo' - >>> p.cmdline() - ['/usr/bin/python', 'main.py'] - >>> - >>> p.pid - 7055 - >>> p.ppid() - 7054 - >>> p.children(recursive=True) - [psutil.Process(pid=29835, name='python2.7', started='11:45:38'), - psutil.Process(pid=29836, name='python2.7', started='11:43:39')] - >>> - >>> p.parent() - psutil.Process(pid=4699, name='bash', started='09:06:44') - >>> p.parents() - [psutil.Process(pid=4699, name='bash', started='09:06:44'), - psutil.Process(pid=4689, name='gnome-terminal-server', started='0:06:44'), - psutil.Process(pid=1, name='systemd', started='05:56:55')] - >>> - >>> p.status() - 'running' - >>> p.username() - 'giampaolo' - >>> p.create_time() - 1267551141.5019531 - >>> p.terminal() - '/dev/pts/0' - >>> - >>> p.uids() - puids(real=1000, effective=1000, saved=1000) - >>> p.gids() - pgids(real=1000, effective=1000, saved=1000) - >>> - >>> p.cpu_times() - pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1, iowait=0.0) - >>> p.cpu_percent(interval=1.0) - 12.1 - >>> p.cpu_affinity() - [0, 1, 2, 3] - >>> p.cpu_affinity([0, 1]) # set - >>> p.cpu_num() - 1 - >>> - >>> p.memory_info() - pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0) - >>> p.memory_full_info() # "real" USS memory usage (Linux, macOS, Win only) - pfullmem(rss=10199040, vms=52133888, shared=3887104, text=2867200, lib=0, data=5967872, dirty=0, uss=6545408, pss=6872064, swap=0) - >>> p.memory_percent() - 0.7823 - >>> p.memory_maps() - [pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0), - pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0), - pmmap_grouped(path='[heap]', rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0), - pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0), - ...] - >>> - >>> p.io_counters() - pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632, read_chars=456232, write_chars=517543) - >>> - >>> p.open_files() - [popenfile(path='/home/giampaolo/monit.py', fd=3, position=0, mode='r', flags=32768), - popenfile(path='/var/log/monit.log', fd=4, position=235542, mode='a', flags=33793)] - >>> - >>> p.connections() - [pconn(fd=115, family=, type=, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'), - pconn(fd=117, family=, type=, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING')] - >>> - >>> p.num_threads() - 4 - >>> p.num_fds() - 8 - >>> p.threads() - [pthread(id=5234, user_time=22.5, system_time=9.2891), - pthread(id=5237, user_time=0.0707, system_time=1.1)] - >>> - >>> p.num_ctx_switches() - pctxsw(voluntary=78, involuntary=19) - >>> - >>> p.nice() - 0 - >>> p.nice(10) # set - >>> - >>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only) - >>> p.ionice() - pionice(ioclass=, value=0) - >>> - >>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only) - >>> p.rlimit(psutil.RLIMIT_NOFILE) - (5, 5) - >>> - >>> p.environ() - {'LC_PAPER': 'it_IT.UTF-8', 'SHELL': '/bin/bash', 'GREP_OPTIONS': '--color=auto', - 'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg', - ...} - >>> - >>> p.as_dict() - {'status': 'running', 'num_ctx_switches': pctxsw(voluntary=63, involuntary=1), 'pid': 5457, ...} - >>> p.is_running() - True - >>> p.suspend() - >>> p.resume() - >>> - >>> p.terminate() - >>> p.kill() - >>> p.wait(timeout=3) - 0 - >>> - >>> psutil.test() - USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND - root 1 0.0 0.0 24584 2240 Jun17 00:00 init - root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd - ... - giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4 - giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome - root 31763 0.0 0.0 0 0 00:05 00:00 kworker/0:1 - >>> - - Further process APIs - -------------------- - - .. code-block:: python - - >>> import psutil - >>> for proc in psutil.process_iter(['pid', 'name']): - ... print(proc.info) - ... - {'pid': 1, 'name': 'systemd'} - {'pid': 2, 'name': 'kthreadd'} - {'pid': 3, 'name': 'ksoftirqd/0'} - ... - >>> - >>> psutil.pid_exists(3) - True - >>> - >>> def on_terminate(proc): - ... print("process {} terminated".format(proc)) - ... - >>> # waits for multiple processes to terminate - >>> gone, alive = psutil.wait_procs(procs_list, timeout=3, callback=on_terminate) - >>> - - Popen wrapper: - - .. code-block:: python - - >>> import psutil - >>> from subprocess import PIPE - >>> p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE) - >>> p.name() - 'python' - >>> p.username() - 'giampaolo' - >>> p.communicate() - ('hello\n', None) - >>> p.wait(timeout=2) - 0 - >>> - - Windows services - ---------------- - - .. code-block:: python - - >>> list(psutil.win_service_iter()) - [, - , - , - , - ...] - >>> s = psutil.win_service_get('alg') - >>> s.as_dict() - {'binpath': 'C:\\Windows\\System32\\alg.exe', - 'description': 'Provides support for 3rd party protocol plug-ins for Internet Connection Sharing', - 'display_name': 'Application Layer Gateway Service', - 'name': 'alg', - 'pid': None, - 'start_type': 'manual', - 'status': 'stopped', - 'username': 'NT AUTHORITY\\LocalService'} - - - .. _`Giampaolo Rodola`: http://grodola.blogspot.com/p/about.html - .. _`donation`: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8 - .. _Tidelift security contact: https://tidelift.com/security - .. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme - - -Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,pstree,monitoring,ulimit,prlimit,smem,performance,metrics,agent,observability -Platform: Platform Independent -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Console -Classifier: Environment :: Win32 (MS Windows) -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Information Technology -Classifier: Intended Audience :: System Administrators -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: Microsoft :: Windows :: Windows 10 -Classifier: Operating System :: Microsoft :: Windows :: Windows 7 -Classifier: Operating System :: Microsoft :: Windows :: Windows 8 -Classifier: Operating System :: Microsoft :: Windows :: Windows 8.1 -Classifier: Operating System :: Microsoft :: Windows :: Windows Server 2003 -Classifier: Operating System :: Microsoft :: Windows :: Windows Server 2008 -Classifier: Operating System :: Microsoft :: Windows :: Windows Vista -Classifier: Operating System :: Microsoft -Classifier: Operating System :: OS Independent -Classifier: Operating System :: POSIX :: AIX -Classifier: Operating System :: POSIX :: BSD :: FreeBSD -Classifier: Operating System :: POSIX :: BSD :: NetBSD -Classifier: Operating System :: POSIX :: BSD :: OpenBSD -Classifier: Operating System :: POSIX :: BSD -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: POSIX :: SunOS/Solaris -Classifier: Operating System :: POSIX -Classifier: Programming Language :: C -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Programming Language :: Python -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Software Development :: Libraries -Classifier: Topic :: System :: Benchmark -Classifier: Topic :: System :: Hardware :: Hardware Drivers -Classifier: Topic :: System :: Hardware -Classifier: Topic :: System :: Monitoring -Classifier: Topic :: System :: Networking :: Monitoring :: Hardware Watchdog -Classifier: Topic :: System :: Networking :: Monitoring -Classifier: Topic :: System :: Networking -Classifier: Topic :: System :: Operating System -Classifier: Topic :: System :: Systems Administration -Classifier: Topic :: Utilities -Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* diff --git a/third_party/python/psutil/README.rst b/third_party/python/psutil/README.rst deleted file mode 100644 index 56b4017e7d95..000000000000 --- a/third_party/python/psutil/README.rst +++ /dev/null @@ -1,521 +0,0 @@ -| |downloads| |stars| |forks| |contributors| |coverage| |quality| -| |version| |py-versions| |packages| |license| -| |travis| |appveyor| |cirrus| |doc| |twitter| |tidelift| - -.. |downloads| image:: https://img.shields.io/pypi/dm/psutil.svg - :target: https://pepy.tech/project/psutil - :alt: Downloads - -.. |stars| image:: https://img.shields.io/github/stars/giampaolo/psutil.svg - :target: https://github.com/giampaolo/psutil/stargazers - :alt: Github stars - -.. |forks| image:: https://img.shields.io/github/forks/giampaolo/psutil.svg - :target: https://github.com/giampaolo/psutil/network/members - :alt: Github forks - -.. |contributors| image:: https://img.shields.io/github/contributors/giampaolo/psutil.svg - :target: https://github.com/giampaolo/psutil/graphs/contributors - :alt: Contributors - -.. |quality| image:: https://img.shields.io/codacy/grade/ce63e7f7f69d44b5b59682196e6fbfca.svg - :target: https://www.codacy.com/app/g-rodola/psutil?utm_source=github.com&utm_medium=referral&utm_content=giampaolo/psutil&utm_campaign=Badge_Grade - :alt: Code quality - -.. |travis| image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux,%20OSX,%20PyPy - :target: https://travis-ci.org/giampaolo/psutil - :alt: Linux tests (Travis) - -.. |appveyor| image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows - :target: https://ci.appveyor.com/project/giampaolo/psutil - :alt: Windows tests (Appveyor) - -.. |cirrus| image:: https://img.shields.io/cirrus/github/giampaolo/psutil?label=FreeBSD - :target: https://cirrus-ci.com/github/giampaolo/psutil-cirrus-ci - :alt: FreeBSD tests (Cirrus-Ci) - -.. |coverage| image:: https://img.shields.io/coveralls/github/giampaolo/psutil.svg?label=test%20coverage - :target: https://coveralls.io/github/giampaolo/psutil?branch=master - :alt: Test coverage (coverall.io) - -.. |doc| image:: https://readthedocs.org/projects/psutil/badge/?version=latest - :target: http://psutil.readthedocs.io/en/latest/?badge=latest - :alt: Documentation Status - -.. |version| image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi - :target: https://pypi.org/project/psutil - :alt: Latest version - -.. |py-versions| image:: https://img.shields.io/pypi/pyversions/psutil.svg - :target: https://pypi.org/project/psutil - :alt: Supported Python versions - -.. |packages| image:: https://repology.org/badge/tiny-repos/python:psutil.svg - :target: https://repology.org/metapackage/python:psutil/versions - :alt: Binary packages - -.. |license| image:: https://img.shields.io/pypi/l/psutil.svg - :target: https://github.com/giampaolo/psutil/blob/master/LICENSE - :alt: License - -.. |twitter| image:: https://img.shields.io/twitter/follow/grodola.svg?label=follow&style=flat&logo=twitter&logoColor=4FADFF - :target: https://twitter.com/grodola - :alt: Twitter Follow - -.. |tidelift| image:: https://tidelift.com/badges/github/giampaolo/psutil?style=flat - :target: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme - :alt: Tidelift - ------ - -Quick links -=========== - -- `Home page `_ -- `Install `_ -- `Documentation `_ -- `Download `_ -- `Forum `_ -- `StackOverflow `_ -- `Blog `_ -- `Development guide `_ -- `What's new `_ - -Summary -======= - -psutil (process and system utilities) is a cross-platform library for -retrieving information on **running processes** and **system utilization** -(CPU, memory, disks, network, sensors) in Python. -It is useful mainly for **system monitoring**, **profiling and limiting process -resources** and **management of running processes**. -It implements many functionalities offered by classic UNIX command line tools -such as *ps, top, iotop, lsof, netstat, ifconfig, free* and others. -psutil currently supports the following platforms: - -- **Linux** -- **Windows** -- **macOS** -- **FreeBSD, OpenBSD**, **NetBSD** -- **Sun Solaris** -- **AIX** - -...both **32-bit** and **64-bit** architectures. Supported Python versions are **2.6**, **2.7** and **3.4+**. `PyPy3 `__ is also known to work. - -psutil for enterprise -===================== - -.. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png - :width: 150 - :alt: Tidelift - :target: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme - -.. list-table:: - :widths: 10 150 - - * - |tideliftlogo| - - The maintainer of psutil and thousands of other packages are working - with Tidelift to deliver commercial support and maintenance for the open - source dependencies you use to build your applications. Save time, - reduce risk, and improve code health, while paying the maintainers of - the exact dependencies you use. - `Learn more `__. - - By subscribing to Tidelift you will help me (`Giampaolo Rodola`_) support - psutil future development. Alternatively consider making a small - `donation`_. - -Security -======== - -To report a security vulnerability, please use the `Tidelift security -contact`_. Tidelift will coordinate the fix and disclosure. - -Example applications -==================== - -+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/top-small.png | -| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/top.png | -+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ -| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap-small.png | -| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap.png | -+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ - -Also see `scripts directory `__ -and `doc recipes `__. - -Projects using psutil -===================== - -psutil has roughly the following monthly downloads: - -.. image:: https://img.shields.io/pypi/dm/psutil.svg - :target: https://pepy.tech/project/psutil - :alt: Downloads - -There are over -`10.000 open source projects `__ -on github which depend from psutil. -Here's some I find particularly interesting: - -- https://github.com/google/grr -- https://github.com/facebook/osquery/ -- https://github.com/nicolargo/glances -- https://github.com/Jahaja/psdash -- https://github.com/ajenti/ajenti -- https://github.com/home-assistant/home-assistant/ - - -Portings -======== - -- Go: https://github.com/shirou/gopsutil -- C: https://github.com/hamon-in/cpslib -- Rust: https://github.com/borntyping/rust-psutil -- Nim: https://github.com/johnscillieri/psutil-nim - - -Example usages -============== - -This represents pretty much the whole psutil API. - -CPU ---- - -.. code-block:: python - - >>> import psutil - >>> - >>> psutil.cpu_times() - scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0) - >>> - >>> for x in range(3): - ... psutil.cpu_percent(interval=1) - ... - 4.0 - 5.9 - 3.8 - >>> - >>> for x in range(3): - ... psutil.cpu_percent(interval=1, percpu=True) - ... - [4.0, 6.9, 3.7, 9.2] - [7.0, 8.5, 2.4, 2.1] - [1.2, 9.0, 9.9, 7.2] - >>> - >>> for x in range(3): - ... psutil.cpu_times_percent(interval=1, percpu=False) - ... - scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - >>> - >>> psutil.cpu_count() - 4 - >>> psutil.cpu_count(logical=False) - 2 - >>> - >>> psutil.cpu_stats() - scpustats(ctx_switches=20455687, interrupts=6598984, soft_interrupts=2134212, syscalls=0) - >>> - >>> psutil.cpu_freq() - scpufreq(current=931.42925, min=800.0, max=3500.0) - >>> - >>> psutil.getloadavg() # also on Windows (emulated) - (3.14, 3.89, 4.67) - -Memory ------- - -.. code-block:: python - - >>> psutil.virtual_memory() - svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304) - >>> psutil.swap_memory() - sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944) - >>> - -Disks ------ - -.. code-block:: python - - >>> psutil.disk_partitions() - [sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'), - sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')] - >>> - >>> psutil.disk_usage('/') - sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5) - >>> - >>> psutil.disk_io_counters(perdisk=False) - sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568, read_merged_count=619166, write_merged_count=812396, busy_time=4523412) - >>> - -Network -------- - -.. code-block:: python - - >>> psutil.net_io_counters(pernic=True) - {'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0), - 'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)} - >>> - >>> psutil.net_connections() - [sconn(fd=115, family=, type=, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254), - sconn(fd=117, family=, type=, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING', pid=2987), - ...] - >>> - >>> psutil.net_if_addrs() - {'lo': [snicaddr(family=, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None), - snicaddr(family=, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None), - snicaddr(family=, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)], - 'wlan0': [snicaddr(family=, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None), - snicaddr(family=, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None), - snicaddr(family=, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]} - >>> - >>> psutil.net_if_stats() - {'lo': snicstats(isup=True, duplex=, speed=0, mtu=65536), - 'wlan0': snicstats(isup=True, duplex=, speed=100, mtu=1500)} - >>> - -Sensors -------- - -.. code-block:: python - - >>> import psutil - >>> psutil.sensors_temperatures() - {'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)], - 'asus': [shwtemp(label='', current=47.0, high=None, critical=None)], - 'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0), - shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0)]} - >>> - >>> psutil.sensors_fans() - {'asus': [sfan(label='cpu_fan', current=3200)]} - >>> - >>> psutil.sensors_battery() - sbattery(percent=93, secsleft=16628, power_plugged=False) - >>> - -Other system info ------------------ - -.. code-block:: python - - >>> import psutil - >>> psutil.users() - [suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0, pid=1352), - suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0, pid=1788)] - >>> - >>> psutil.boot_time() - 1365519115.0 - >>> - -Process management ------------------- - -.. code-block:: python - - >>> import psutil - >>> psutil.pids() - [1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224, 268, 1215, 1216, 1220, 1221, 1243, 1244, - 1301, 1601, 2237, 2355, 2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, 4263, 4282, - 4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358, 4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446, - 5167, 5234, 5235, 5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071] - >>> - >>> p = psutil.Process(7055) - >>> p - psutil.Process(pid=7055, name='python', started='09:04:44') - >>> p.name() - 'python' - >>> p.exe() - '/usr/bin/python' - >>> p.cwd() - '/home/giampaolo' - >>> p.cmdline() - ['/usr/bin/python', 'main.py'] - >>> - >>> p.pid - 7055 - >>> p.ppid() - 7054 - >>> p.children(recursive=True) - [psutil.Process(pid=29835, name='python2.7', started='11:45:38'), - psutil.Process(pid=29836, name='python2.7', started='11:43:39')] - >>> - >>> p.parent() - psutil.Process(pid=4699, name='bash', started='09:06:44') - >>> p.parents() - [psutil.Process(pid=4699, name='bash', started='09:06:44'), - psutil.Process(pid=4689, name='gnome-terminal-server', started='0:06:44'), - psutil.Process(pid=1, name='systemd', started='05:56:55')] - >>> - >>> p.status() - 'running' - >>> p.username() - 'giampaolo' - >>> p.create_time() - 1267551141.5019531 - >>> p.terminal() - '/dev/pts/0' - >>> - >>> p.uids() - puids(real=1000, effective=1000, saved=1000) - >>> p.gids() - pgids(real=1000, effective=1000, saved=1000) - >>> - >>> p.cpu_times() - pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1, iowait=0.0) - >>> p.cpu_percent(interval=1.0) - 12.1 - >>> p.cpu_affinity() - [0, 1, 2, 3] - >>> p.cpu_affinity([0, 1]) # set - >>> p.cpu_num() - 1 - >>> - >>> p.memory_info() - pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0) - >>> p.memory_full_info() # "real" USS memory usage (Linux, macOS, Win only) - pfullmem(rss=10199040, vms=52133888, shared=3887104, text=2867200, lib=0, data=5967872, dirty=0, uss=6545408, pss=6872064, swap=0) - >>> p.memory_percent() - 0.7823 - >>> p.memory_maps() - [pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0), - pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0), - pmmap_grouped(path='[heap]', rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0), - pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0), - ...] - >>> - >>> p.io_counters() - pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632, read_chars=456232, write_chars=517543) - >>> - >>> p.open_files() - [popenfile(path='/home/giampaolo/monit.py', fd=3, position=0, mode='r', flags=32768), - popenfile(path='/var/log/monit.log', fd=4, position=235542, mode='a', flags=33793)] - >>> - >>> p.connections() - [pconn(fd=115, family=, type=, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'), - pconn(fd=117, family=, type=, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING')] - >>> - >>> p.num_threads() - 4 - >>> p.num_fds() - 8 - >>> p.threads() - [pthread(id=5234, user_time=22.5, system_time=9.2891), - pthread(id=5237, user_time=0.0707, system_time=1.1)] - >>> - >>> p.num_ctx_switches() - pctxsw(voluntary=78, involuntary=19) - >>> - >>> p.nice() - 0 - >>> p.nice(10) # set - >>> - >>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only) - >>> p.ionice() - pionice(ioclass=, value=0) - >>> - >>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only) - >>> p.rlimit(psutil.RLIMIT_NOFILE) - (5, 5) - >>> - >>> p.environ() - {'LC_PAPER': 'it_IT.UTF-8', 'SHELL': '/bin/bash', 'GREP_OPTIONS': '--color=auto', - 'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg', - ...} - >>> - >>> p.as_dict() - {'status': 'running', 'num_ctx_switches': pctxsw(voluntary=63, involuntary=1), 'pid': 5457, ...} - >>> p.is_running() - True - >>> p.suspend() - >>> p.resume() - >>> - >>> p.terminate() - >>> p.kill() - >>> p.wait(timeout=3) - 0 - >>> - >>> psutil.test() - USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND - root 1 0.0 0.0 24584 2240 Jun17 00:00 init - root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd - ... - giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4 - giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome - root 31763 0.0 0.0 0 0 00:05 00:00 kworker/0:1 - >>> - -Further process APIs --------------------- - -.. code-block:: python - - >>> import psutil - >>> for proc in psutil.process_iter(['pid', 'name']): - ... print(proc.info) - ... - {'pid': 1, 'name': 'systemd'} - {'pid': 2, 'name': 'kthreadd'} - {'pid': 3, 'name': 'ksoftirqd/0'} - ... - >>> - >>> psutil.pid_exists(3) - True - >>> - >>> def on_terminate(proc): - ... print("process {} terminated".format(proc)) - ... - >>> # waits for multiple processes to terminate - >>> gone, alive = psutil.wait_procs(procs_list, timeout=3, callback=on_terminate) - >>> - -Popen wrapper: - -.. code-block:: python - - >>> import psutil - >>> from subprocess import PIPE - >>> p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE) - >>> p.name() - 'python' - >>> p.username() - 'giampaolo' - >>> p.communicate() - ('hello\n', None) - >>> p.wait(timeout=2) - 0 - >>> - -Windows services ----------------- - -.. code-block:: python - - >>> list(psutil.win_service_iter()) - [, - , - , - , - ...] - >>> s = psutil.win_service_get('alg') - >>> s.as_dict() - {'binpath': 'C:\\Windows\\System32\\alg.exe', - 'description': 'Provides support for 3rd party protocol plug-ins for Internet Connection Sharing', - 'display_name': 'Application Layer Gateway Service', - 'name': 'alg', - 'pid': None, - 'start_type': 'manual', - 'status': 'stopped', - 'username': 'NT AUTHORITY\\LocalService'} - - -.. _`Giampaolo Rodola`: http://grodola.blogspot.com/p/about.html -.. _`donation`: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8 -.. _Tidelift security contact: https://tidelift.com/security -.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme - diff --git a/third_party/python/psutil/make.bat b/third_party/python/psutil/make.bat deleted file mode 100644 index 8e60811ccfac..000000000000 --- a/third_party/python/psutil/make.bat +++ /dev/null @@ -1,37 +0,0 @@ -@echo off - -rem ========================================================================== -rem Shortcuts for various tasks, emulating UNIX "make" on Windows. -rem It is primarly intended as a shortcut for compiling / installing -rem psutil ("make.bat build", "make.bat install") and running tests -rem ("make.bat test"). -rem -rem This script is modeled after my Windows installation which uses: -rem - Visual studio 2008 for Python 2.6, 2.7 -rem - Visual studio 2010 for Python 3.4+ -rem ...therefore it might not work on your Windows installation. -rem -rem By default C:\Python27\python.exe is used. -rem To compile for a specific Python version run: -rem set PYTHON=C:\Python34\python.exe & make.bat build -rem -rem To use a different test script: -rem set PYTHON=C:\Python34\python.exe & set TSCRIPT=foo.py & make.bat test -rem ========================================================================== - -if "%PYTHON%" == "" ( - if exist "C:\Python38-64\python.exe" ( - set PYTHON=C:\Python38-64\python.exe - ) else ( - set PYTHON=C:\Python27\python.exe - ) -) - -if "%TSCRIPT%" == "" ( - set TSCRIPT=psutil\tests\runner.py -) - -rem Needed to locate the .pypirc file and upload exes on PyPI. -set HOME=%USERPROFILE% - -%PYTHON% scripts\internal\winmake.py %1 %2 %3 %4 %5 %6 diff --git a/third_party/python/psutil/psutil/__init__.py b/third_party/python/psutil/psutil/__init__.py deleted file mode 100644 index 22bb46f3f9bd..000000000000 --- a/third_party/python/psutil/psutil/__init__.py +++ /dev/null @@ -1,2409 +0,0 @@ -# -*- coding: utf-8 -*- - -# 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. - -"""psutil is a cross-platform library for retrieving information on -running processes and system utilization (CPU, memory, disks, network, -sensors) in Python. Supported platforms: - - - Linux - - Windows - - macOS - - FreeBSD - - OpenBSD - - NetBSD - - Sun Solaris - - AIX - -Works with Python versions from 2.6 to 3.4+. -""" - -from __future__ import division - -import collections -import contextlib -import datetime -import functools -import os -import signal -import subprocess -import sys -import threading -import time -try: - import pwd -except ImportError: - pwd = None - -from . import _common -from ._common import AccessDenied -from ._common import deprecated_method -from ._common import Error -from ._common import memoize -from ._common import memoize_when_activated -from ._common import NoSuchProcess -from ._common import TimeoutExpired -from ._common import wrap_numbers as _wrap_numbers -from ._common import ZombieProcess -from ._compat import long -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 as _PY3 - -from ._common import STATUS_DEAD -from ._common import STATUS_DISK_SLEEP -from ._common import STATUS_IDLE -from ._common import STATUS_LOCKED -from ._common import STATUS_PARKED -from ._common import STATUS_RUNNING -from ._common import STATUS_SLEEPING -from ._common import STATUS_STOPPED -from ._common import STATUS_TRACING_STOP -from ._common import STATUS_WAITING -from ._common import STATUS_WAKING -from ._common import STATUS_ZOMBIE - -from ._common import CONN_CLOSE -from ._common import CONN_CLOSE_WAIT -from ._common import CONN_CLOSING -from ._common import CONN_ESTABLISHED -from ._common import CONN_FIN_WAIT1 -from ._common import CONN_FIN_WAIT2 -from ._common import CONN_LAST_ACK -from ._common import CONN_LISTEN -from ._common import CONN_NONE -from ._common import CONN_SYN_RECV -from ._common import CONN_SYN_SENT -from ._common import CONN_TIME_WAIT -from ._common import NIC_DUPLEX_FULL -from ._common import NIC_DUPLEX_HALF -from ._common import NIC_DUPLEX_UNKNOWN - -from ._common import AIX -from ._common import BSD -from ._common import FREEBSD # NOQA -from ._common import LINUX -from ._common import MACOS -from ._common import NETBSD # NOQA -from ._common import OPENBSD # NOQA -from ._common import OSX # deprecated alias -from ._common import POSIX # NOQA -from ._common import SUNOS -from ._common import WINDOWS - -if LINUX: - # This is public API and it will be retrieved from _pslinux.py - # via sys.modules. - PROCFS_PATH = "/proc" - - from . import _pslinux as _psplatform - - from ._pslinux import IOPRIO_CLASS_BE # NOQA - from ._pslinux import IOPRIO_CLASS_IDLE # NOQA - from ._pslinux import IOPRIO_CLASS_NONE # NOQA - from ._pslinux import IOPRIO_CLASS_RT # NOQA - # Linux >= 2.6.36 - if _psplatform.HAS_PRLIMIT: - from ._psutil_linux import RLIM_INFINITY # NOQA - from ._psutil_linux import RLIMIT_AS # NOQA - from ._psutil_linux import RLIMIT_CORE # NOQA - from ._psutil_linux import RLIMIT_CPU # NOQA - from ._psutil_linux import RLIMIT_DATA # NOQA - from ._psutil_linux import RLIMIT_FSIZE # NOQA - from ._psutil_linux import RLIMIT_LOCKS # NOQA - from ._psutil_linux import RLIMIT_MEMLOCK # NOQA - from ._psutil_linux import RLIMIT_NOFILE # NOQA - from ._psutil_linux import RLIMIT_NPROC # NOQA - from ._psutil_linux import RLIMIT_RSS # NOQA - from ._psutil_linux import RLIMIT_STACK # NOQA - # Kinda ugly but considerably faster than using hasattr() and - # setattr() against the module object (we are at import time: - # speed matters). - from . import _psutil_linux - try: - RLIMIT_MSGQUEUE = _psutil_linux.RLIMIT_MSGQUEUE - except AttributeError: - pass - try: - RLIMIT_NICE = _psutil_linux.RLIMIT_NICE - except AttributeError: - pass - try: - RLIMIT_RTPRIO = _psutil_linux.RLIMIT_RTPRIO - except AttributeError: - pass - try: - RLIMIT_RTTIME = _psutil_linux.RLIMIT_RTTIME - except AttributeError: - pass - try: - RLIMIT_SIGPENDING = _psutil_linux.RLIMIT_SIGPENDING - except AttributeError: - pass - -elif WINDOWS: - from . import _pswindows as _psplatform - from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS # NOQA - from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS # NOQA - from ._psutil_windows import HIGH_PRIORITY_CLASS # NOQA - from ._psutil_windows import IDLE_PRIORITY_CLASS # NOQA - from ._psutil_windows import NORMAL_PRIORITY_CLASS # NOQA - from ._psutil_windows import REALTIME_PRIORITY_CLASS # NOQA - from ._pswindows import CONN_DELETE_TCB # NOQA - from ._pswindows import IOPRIO_VERYLOW # NOQA - from ._pswindows import IOPRIO_LOW # NOQA - from ._pswindows import IOPRIO_NORMAL # NOQA - from ._pswindows import IOPRIO_HIGH # NOQA - -elif MACOS: - from . import _psosx as _psplatform - -elif BSD: - from . import _psbsd as _psplatform - -elif SUNOS: - from . import _pssunos as _psplatform - from ._pssunos import CONN_BOUND # NOQA - from ._pssunos import CONN_IDLE # NOQA - - # This is public writable API which is read from _pslinux.py and - # _pssunos.py via sys.modules. - PROCFS_PATH = "/proc" - -elif AIX: - from . import _psaix as _psplatform - - # This is public API and it will be retrieved from _pslinux.py - # via sys.modules. - PROCFS_PATH = "/proc" - -else: # pragma: no cover - raise NotImplementedError('platform %s is not supported' % sys.platform) - - -__all__ = [ - # exceptions - "Error", "NoSuchProcess", "ZombieProcess", "AccessDenied", - "TimeoutExpired", - - # constants - "version_info", "__version__", - - "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP", - "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD", - "STATUS_WAKING", "STATUS_LOCKED", "STATUS_WAITING", "STATUS_LOCKED", - "STATUS_PARKED", - - "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", - "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", - "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", "CONN_NONE", - - "AF_LINK", - - "NIC_DUPLEX_FULL", "NIC_DUPLEX_HALF", "NIC_DUPLEX_UNKNOWN", - - "POWER_TIME_UNKNOWN", "POWER_TIME_UNLIMITED", - - "BSD", "FREEBSD", "LINUX", "NETBSD", "OPENBSD", "MACOS", "OSX", "POSIX", - "SUNOS", "WINDOWS", "AIX", - - # classes - "Process", "Popen", - - # functions - "pid_exists", "pids", "process_iter", "wait_procs", # proc - "virtual_memory", "swap_memory", # memory - "cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count", # cpu - "cpu_stats", # "cpu_freq", "getloadavg" - "net_io_counters", "net_connections", "net_if_addrs", # network - "net_if_stats", - "disk_io_counters", "disk_partitions", "disk_usage", # disk - # "sensors_temperatures", "sensors_battery", "sensors_fans" # sensors - "users", "boot_time", # others -] - - -__all__.extend(_psplatform.__extra__all__) -__author__ = "Giampaolo Rodola'" -__version__ = "5.7.0" -version_info = tuple([int(num) for num in __version__.split('.')]) - -_timer = getattr(time, 'monotonic', time.time) -AF_LINK = _psplatform.AF_LINK -POWER_TIME_UNLIMITED = _common.POWER_TIME_UNLIMITED -POWER_TIME_UNKNOWN = _common.POWER_TIME_UNKNOWN -_TOTAL_PHYMEM = None -_LOWEST_PID = None - -# Sanity check in case the user messed up with psutil installation -# or did something weird with sys.path. In this case we might end -# up importing a python module using a C extension module which -# was compiled for a different version of psutil. -# We want to prevent that by failing sooner rather than later. -# See: https://github.com/giampaolo/psutil/issues/564 -if (int(__version__.replace('.', '')) != - getattr(_psplatform.cext, 'version', None)): - msg = "version conflict: %r C extension module was built for another " \ - "version of psutil" % getattr(_psplatform.cext, "__file__") - if hasattr(_psplatform.cext, 'version'): - msg += " (%s instead of %s)" % ( - '.'.join([x for x in str(_psplatform.cext.version)]), __version__) - else: - msg += " (different than %s)" % __version__ - msg += "; you may try to 'pip uninstall psutil', manually remove %s" % ( - getattr(_psplatform.cext, "__file__", - "the existing psutil install directory")) - msg += " or clean the virtual env somehow, then reinstall" - raise ImportError(msg) - - -# ===================================================================== -# --- Utils -# ===================================================================== - - -if hasattr(_psplatform, 'ppid_map'): - # Faster version (Windows and Linux). - _ppid_map = _psplatform.ppid_map -else: - def _ppid_map(): - """Return a {pid: ppid, ...} dict for all running processes in - one shot. Used to speed up Process.children(). - """ - ret = {} - for pid in pids(): - try: - ret[pid] = _psplatform.Process(pid).ppid() - except (NoSuchProcess, ZombieProcess): - pass - return ret - - -def _assert_pid_not_reused(fun): - """Decorator which raises NoSuchProcess in case a process is no - longer running or its PID has been reused. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - if not self.is_running(): - raise NoSuchProcess(self.pid, self._name) - return fun(self, *args, **kwargs) - return wrapper - - -def _pprint_secs(secs): - """Format seconds in a human readable form.""" - now = time.time() - secs_ago = int(now - secs) - if secs_ago < 60 * 60 * 24: - fmt = "%H:%M:%S" - else: - fmt = "%Y-%m-%d %H:%M:%S" - return datetime.datetime.fromtimestamp(secs).strftime(fmt) - - -# ===================================================================== -# --- Process class -# ===================================================================== - - -class Process(object): - """Represents an OS process with the given PID. - If PID is omitted current process PID (os.getpid()) is used. - Raise NoSuchProcess if PID does not exist. - - Note that most of the methods of this class do not make sure - the PID of the process being queried has been reused over time. - That means you might end up retrieving an information referring - to another process in case the original one this instance - refers to is gone in the meantime. - - The only exceptions for which process identity is pre-emptively - checked and guaranteed are: - - - parent() - - children() - - nice() (set) - - ionice() (set) - - rlimit() (set) - - cpu_affinity (set) - - suspend() - - resume() - - send_signal() - - terminate() - - kill() - - To prevent this problem for all other methods you can: - - use is_running() before querying the process - - if you're continuously iterating over a set of Process - instances use process_iter() which pre-emptively checks - process identity for every yielded instance - """ - - def __init__(self, pid=None): - self._init(pid) - - def _init(self, pid, _ignore_nsp=False): - if pid is None: - pid = os.getpid() - else: - if not _PY3 and not isinstance(pid, (int, long)): - raise TypeError('pid must be an integer (got %r)' % pid) - if pid < 0: - raise ValueError('pid must be a positive integer (got %s)' - % pid) - self._pid = pid - self._name = None - self._exe = None - self._create_time = None - self._gone = False - self._hash = None - self._lock = threading.RLock() - # used for caching on Windows only (on POSIX ppid may change) - self._ppid = None - # platform-specific modules define an _psplatform.Process - # implementation class - self._proc = _psplatform.Process(pid) - self._last_sys_cpu_times = None - self._last_proc_cpu_times = None - # cache creation time for later use in is_running() method - try: - self.create_time() - except AccessDenied: - # We should never get here as AFAIK we're able to get - # process creation time on all platforms even as a - # limited user. - pass - except ZombieProcess: - # Zombies can still be queried by this class (although - # not always) and pids() return them so just go on. - pass - except NoSuchProcess: - if not _ignore_nsp: - msg = 'no process found with pid %s' % pid - raise NoSuchProcess(pid, None, msg) - else: - self._gone = True - # This pair is supposed to indentify a Process instance - # univocally over time (the PID alone is not enough as - # it might refer to a process whose PID has been reused). - # This will be used later in __eq__() and is_running(). - self._ident = (self.pid, self._create_time) - - def __str__(self): - try: - info = collections.OrderedDict() - except AttributeError: - info = {} # Python 2.6 - info["pid"] = self.pid - try: - info["name"] = self.name() - if self._create_time: - info['started'] = _pprint_secs(self._create_time) - except ZombieProcess: - info["status"] = "zombie" - except NoSuchProcess: - info["status"] = "terminated" - except AccessDenied: - pass - return "%s.%s(%s)" % ( - self.__class__.__module__, - self.__class__.__name__, - ", ".join(["%s=%r" % (k, v) for k, v in info.items()])) - - __repr__ = __str__ - - def __eq__(self, other): - # Test for equality with another Process object based - # on PID and creation time. - if not isinstance(other, Process): - return NotImplemented - return self._ident == other._ident - - def __ne__(self, other): - return not self == other - - def __hash__(self): - if self._hash is None: - self._hash = hash(self._ident) - return self._hash - - @property - def pid(self): - """The process PID.""" - return self._pid - - # --- utility methods - - @contextlib.contextmanager - def oneshot(self): - """Utility context manager which considerably speeds up the - retrieval of multiple process information at the same time. - - Internally different process info (e.g. name, ppid, uids, - gids, ...) may be fetched by using the same routine, but - only one information is returned and the others are discarded. - When using this context manager the internal routine is - executed once (in the example below on name()) and the - other info are cached. - - The cache is cleared when exiting the context manager block. - The advice is to use this every time you retrieve more than - one information about the process. If you're lucky, you'll - get a hell of a speedup. - - >>> import psutil - >>> p = psutil.Process() - >>> with p.oneshot(): - ... p.name() # collect multiple info - ... p.cpu_times() # return cached value - ... p.cpu_percent() # return cached value - ... p.create_time() # return cached value - ... - >>> - """ - with self._lock: - if hasattr(self, "_cache"): - # NOOP: this covers the use case where the user enters the - # context twice: - # - # >>> with p.oneshot(): - # ... with p.oneshot(): - # ... - # - # Also, since as_dict() internally uses oneshot() - # I expect that the code below will be a pretty common - # "mistake" that the user will make, so let's guard - # against that: - # - # >>> with p.oneshot(): - # ... p.as_dict() - # ... - yield - else: - try: - # cached in case cpu_percent() is used - self.cpu_times.cache_activate(self) - # cached in case memory_percent() is used - self.memory_info.cache_activate(self) - # cached in case parent() is used - self.ppid.cache_activate(self) - # cached in case username() is used - if POSIX: - self.uids.cache_activate(self) - # specific implementation cache - self._proc.oneshot_enter() - yield - finally: - self.cpu_times.cache_deactivate(self) - self.memory_info.cache_deactivate(self) - self.ppid.cache_deactivate(self) - if POSIX: - self.uids.cache_deactivate(self) - self._proc.oneshot_exit() - - def as_dict(self, attrs=None, ad_value=None): - """Utility method returning process information as a - hashable dictionary. - If *attrs* is specified it must be a list of strings - reflecting available Process class' attribute names - (e.g. ['cpu_times', 'name']) else all public (read - only) attributes are assumed. - *ad_value* is the value which gets assigned in case - AccessDenied or ZombieProcess exception is raised when - retrieving that particular process information. - """ - valid_names = _as_dict_attrnames - if attrs is not None: - if not isinstance(attrs, (list, tuple, set, frozenset)): - raise TypeError("invalid attrs type %s" % type(attrs)) - attrs = set(attrs) - invalid_names = attrs - valid_names - if invalid_names: - raise ValueError("invalid attr name%s %s" % ( - "s" if len(invalid_names) > 1 else "", - ", ".join(map(repr, invalid_names)))) - - retdict = dict() - ls = attrs or valid_names - with self.oneshot(): - for name in ls: - try: - if name == 'pid': - ret = self.pid - else: - meth = getattr(self, name) - ret = meth() - except (AccessDenied, ZombieProcess): - ret = ad_value - except NotImplementedError: - # in case of not implemented functionality (may happen - # on old or exotic systems) we want to crash only if - # the user explicitly asked for that particular attr - if attrs: - raise - continue - retdict[name] = ret - return retdict - - def parent(self): - """Return the parent process as a Process object pre-emptively - checking whether PID has been reused. - If no parent is known return None. - """ - lowest_pid = _LOWEST_PID if _LOWEST_PID is not None else pids()[0] - if self.pid == lowest_pid: - return None - ppid = self.ppid() - if ppid is not None: - ctime = self.create_time() - try: - parent = Process(ppid) - if parent.create_time() <= ctime: - return parent - # ...else ppid has been reused by another process - except NoSuchProcess: - pass - - def parents(self): - """Return the parents of this process as a list of Process - instances. If no parents are known return an empty list. - """ - parents = [] - proc = self.parent() - while proc is not None: - parents.append(proc) - proc = proc.parent() - return parents - - def is_running(self): - """Return whether this process is running. - It also checks if PID has been reused by another process in - which case return False. - """ - if self._gone: - return False - try: - # Checking if PID is alive is not enough as the PID might - # have been reused by another process: we also want to - # verify process identity. - # Process identity / uniqueness over time is guaranteed by - # (PID + creation time) and that is verified in __eq__. - return self == Process(self.pid) - except ZombieProcess: - # We should never get here as it's already handled in - # Process.__init__; here just for extra safety. - return True - except NoSuchProcess: - self._gone = True - return False - - # --- actual API - - @memoize_when_activated - def ppid(self): - """The process parent PID. - On Windows the return value is cached after first call. - """ - # On POSIX we don't want to cache the ppid as it may unexpectedly - # change to 1 (init) in case this process turns into a zombie: - # https://github.com/giampaolo/psutil/issues/321 - # http://stackoverflow.com/questions/356722/ - - # XXX should we check creation time here rather than in - # Process.parent()? - if POSIX: - return self._proc.ppid() - else: # pragma: no cover - self._ppid = self._ppid or self._proc.ppid() - return self._ppid - - def name(self): - """The process name. The return value is cached after first call.""" - # Process name is only cached on Windows as on POSIX it may - # change, see: - # https://github.com/giampaolo/psutil/issues/692 - if WINDOWS and self._name is not None: - return self._name - name = self._proc.name() - if POSIX and len(name) >= 15: - # On UNIX the name gets truncated to the first 15 characters. - # If it matches the first part of the cmdline we return that - # one instead because it's usually more explicative. - # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon". - try: - cmdline = self.cmdline() - except AccessDenied: - pass - else: - if cmdline: - extended_name = os.path.basename(cmdline[0]) - if extended_name.startswith(name): - name = extended_name - self._name = name - self._proc._name = name - return name - - def exe(self): - """The process executable as an absolute path. - May also be an empty string. - The return value is cached after first call. - """ - def guess_it(fallback): - # try to guess exe from cmdline[0] in absence of a native - # exe representation - cmdline = self.cmdline() - if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'): - exe = cmdline[0] # the possible exe - # Attempt to guess only in case of an absolute path. - # It is not safe otherwise as the process might have - # changed cwd. - if (os.path.isabs(exe) and - os.path.isfile(exe) and - os.access(exe, os.X_OK)): - return exe - if isinstance(fallback, AccessDenied): - raise fallback - return fallback - - if self._exe is None: - try: - exe = self._proc.exe() - except AccessDenied as err: - return guess_it(fallback=err) - else: - if not exe: - # underlying implementation can legitimately return an - # empty string; if that's the case we don't want to - # raise AD while guessing from the cmdline - try: - exe = guess_it(fallback=exe) - except AccessDenied: - pass - self._exe = exe - return self._exe - - def cmdline(self): - """The command line this process has been called with.""" - return self._proc.cmdline() - - def status(self): - """The process current status as a STATUS_* constant.""" - try: - return self._proc.status() - except ZombieProcess: - return STATUS_ZOMBIE - - def username(self): - """The name of the user that owns the process. - On UNIX this is calculated by using *real* process uid. - """ - if POSIX: - if pwd is None: - # might happen if python was installed from sources - raise ImportError( - "requires pwd module shipped with standard python") - real_uid = self.uids().real - try: - return pwd.getpwuid(real_uid).pw_name - except KeyError: - # the uid can't be resolved by the system - return str(real_uid) - else: - return self._proc.username() - - def create_time(self): - """The process creation time as a floating point number - expressed in seconds since the epoch, in UTC. - The return value is cached after first call. - """ - if self._create_time is None: - self._create_time = self._proc.create_time() - return self._create_time - - def cwd(self): - """Process current working directory as an absolute path.""" - return self._proc.cwd() - - def nice(self, value=None): - """Get or set process niceness (priority).""" - if value is None: - return self._proc.nice_get() - else: - if not self.is_running(): - raise NoSuchProcess(self.pid, self._name) - self._proc.nice_set(value) - - if POSIX: - - @memoize_when_activated - def uids(self): - """Return process UIDs as a (real, effective, saved) - namedtuple. - """ - return self._proc.uids() - - def gids(self): - """Return process GIDs as a (real, effective, saved) - namedtuple. - """ - return self._proc.gids() - - def terminal(self): - """The terminal associated with this process, if any, - else None. - """ - return self._proc.terminal() - - def num_fds(self): - """Return the number of file descriptors opened by this - process (POSIX only). - """ - return self._proc.num_fds() - - # Linux, BSD, AIX and Windows only - if hasattr(_psplatform.Process, "io_counters"): - - def io_counters(self): - """Return process I/O statistics as a - (read_count, write_count, read_bytes, write_bytes) - namedtuple. - Those are the number of read/write calls performed and the - amount of bytes read and written by the process. - """ - return self._proc.io_counters() - - # Linux and Windows - if hasattr(_psplatform.Process, "ionice_get"): - - def ionice(self, ioclass=None, value=None): - """Get or set process I/O niceness (priority). - - On Linux *ioclass* is one of the IOPRIO_CLASS_* constants. - *value* is a number which goes from 0 to 7. The higher the - value, the lower the I/O priority of the process. - - On Windows only *ioclass* is used and it can be set to 2 - (normal), 1 (low) or 0 (very low). - - Available on Linux and Windows > Vista only. - """ - if ioclass is None: - if value is not None: - raise ValueError("'ioclass' argument must be specified") - return self._proc.ionice_get() - else: - return self._proc.ionice_set(ioclass, value) - - # Linux only - if hasattr(_psplatform.Process, "rlimit"): - - def rlimit(self, resource, limits=None): - """Get or set process resource limits as a (soft, hard) - tuple. - - *resource* is one of the RLIMIT_* constants. - *limits* is supposed to be a (soft, hard) tuple. - - See "man prlimit" for further info. - Available on Linux only. - """ - if limits is None: - return self._proc.rlimit(resource) - else: - return self._proc.rlimit(resource, limits) - - # Windows, Linux and FreeBSD only - if hasattr(_psplatform.Process, "cpu_affinity_get"): - - def cpu_affinity(self, cpus=None): - """Get or set process CPU affinity. - If specified, *cpus* must be a list of CPUs for which you - want to set the affinity (e.g. [0, 1]). - If an empty list is passed, all egible CPUs are assumed - (and set). - (Windows, Linux and BSD only). - """ - if cpus is None: - return list(set(self._proc.cpu_affinity_get())) - else: - if not cpus: - if hasattr(self._proc, "_get_eligible_cpus"): - cpus = self._proc._get_eligible_cpus() - else: - cpus = tuple(range(len(cpu_times(percpu=True)))) - self._proc.cpu_affinity_set(list(set(cpus))) - - # Linux, FreeBSD, SunOS - if hasattr(_psplatform.Process, "cpu_num"): - - def cpu_num(self): - """Return what CPU this process is currently running on. - The returned number should be <= psutil.cpu_count() - and <= len(psutil.cpu_percent(percpu=True)). - It may be used in conjunction with - psutil.cpu_percent(percpu=True) to observe the system - workload distributed across CPUs. - """ - return self._proc.cpu_num() - - # Linux, macOS, Windows, Solaris, AIX - if hasattr(_psplatform.Process, "environ"): - - def environ(self): - """The environment variables of the process as a dict. Note: this - might not reflect changes made after the process started. """ - return self._proc.environ() - - if WINDOWS: - - def num_handles(self): - """Return the number of handles opened by this process - (Windows only). - """ - return self._proc.num_handles() - - def num_ctx_switches(self): - """Return the number of voluntary and involuntary context - switches performed by this process. - """ - return self._proc.num_ctx_switches() - - def num_threads(self): - """Return the number of threads used by this process.""" - return self._proc.num_threads() - - if hasattr(_psplatform.Process, "threads"): - - def threads(self): - """Return threads opened by process as a list of - (id, user_time, system_time) namedtuples representing - thread id and thread CPU times (user/system). - On OpenBSD this method requires root access. - """ - return self._proc.threads() - - @_assert_pid_not_reused - def children(self, recursive=False): - """Return the children of this process as a list of Process - instances, pre-emptively checking whether PID has been reused. - If *recursive* is True return all the parent descendants. - - Example (A == this process): - - A ─┐ - │ - ├─ B (child) ─┐ - │ └─ X (grandchild) ─┐ - │ └─ Y (great grandchild) - ├─ C (child) - └─ D (child) - - >>> import psutil - >>> p = psutil.Process() - >>> p.children() - B, C, D - >>> p.children(recursive=True) - B, X, Y, C, D - - Note that in the example above if process X disappears - process Y won't be listed as the reference to process A - is lost. - """ - ppid_map = _ppid_map() - ret = [] - if not recursive: - for pid, ppid in ppid_map.items(): - if ppid == self.pid: - try: - child = Process(pid) - # if child happens to be older than its parent - # (self) it means child's PID has been reused - if self.create_time() <= child.create_time(): - ret.append(child) - except (NoSuchProcess, ZombieProcess): - pass - else: - # Construct a {pid: [child pids]} dict - reverse_ppid_map = collections.defaultdict(list) - for pid, ppid in ppid_map.items(): - reverse_ppid_map[ppid].append(pid) - # Recursively traverse that dict, starting from self.pid, - # such that we only call Process() on actual children - seen = set() - stack = [self.pid] - while stack: - pid = stack.pop() - if pid in seen: - # Since pids can be reused while the ppid_map is - # constructed, there may be rare instances where - # there's a cycle in the recorded process "tree". - continue - seen.add(pid) - for child_pid in reverse_ppid_map[pid]: - try: - child = Process(child_pid) - # if child happens to be older than its parent - # (self) it means child's PID has been reused - intime = self.create_time() <= child.create_time() - if intime: - ret.append(child) - stack.append(child_pid) - except (NoSuchProcess, ZombieProcess): - pass - return ret - - def cpu_percent(self, interval=None): - """Return a float representing the current process CPU - utilization as a percentage. - - When *interval* is 0.0 or None (default) compares process times - to system CPU times elapsed since last call, returning - immediately (non-blocking). That means that the first time - this is called it will return a meaningful 0.0 value. - - When *interval* is > 0.0 compares process times to system CPU - times elapsed before and after the interval (blocking). - - In this case is recommended for accuracy that this function - be called with at least 0.1 seconds between calls. - - A value > 100.0 can be returned in case of processes running - multiple threads on different CPU cores. - - The returned value is explicitly NOT split evenly between - all available logical CPUs. This means that a busy loop process - running on a system with 2 logical CPUs will be reported as - having 100% CPU utilization instead of 50%. - - Examples: - - >>> import psutil - >>> p = psutil.Process(os.getpid()) - >>> # blocking - >>> p.cpu_percent(interval=1) - 2.0 - >>> # non-blocking (percentage since last call) - >>> p.cpu_percent(interval=None) - 2.9 - >>> - """ - blocking = interval is not None and interval > 0.0 - if interval is not None and interval < 0: - raise ValueError("interval is not positive (got %r)" % interval) - num_cpus = cpu_count() or 1 - - def timer(): - return _timer() * num_cpus - - if blocking: - st1 = timer() - pt1 = self._proc.cpu_times() - time.sleep(interval) - st2 = timer() - pt2 = self._proc.cpu_times() - else: - st1 = self._last_sys_cpu_times - pt1 = self._last_proc_cpu_times - st2 = timer() - pt2 = self._proc.cpu_times() - if st1 is None or pt1 is None: - self._last_sys_cpu_times = st2 - self._last_proc_cpu_times = pt2 - return 0.0 - - delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system) - delta_time = st2 - st1 - # reset values for next call in case of interval == None - self._last_sys_cpu_times = st2 - self._last_proc_cpu_times = pt2 - - try: - # This is the utilization split evenly between all CPUs. - # E.g. a busy loop process on a 2-CPU-cores system at this - # point is reported as 50% instead of 100%. - overall_cpus_percent = ((delta_proc / delta_time) * 100) - except ZeroDivisionError: - # interval was too low - return 0.0 - else: - # Note 1: - # in order to emulate "top" we multiply the value for the num - # of CPU cores. This way the busy process will be reported as - # having 100% (or more) usage. - # - # Note 2: - # taskmgr.exe on Windows differs in that it will show 50% - # instead. - # - # Note 3: - # a percentage > 100 is legitimate as it can result from a - # process with multiple threads running on different CPU - # cores (top does the same), see: - # http://stackoverflow.com/questions/1032357 - # https://github.com/giampaolo/psutil/issues/474 - single_cpu_percent = overall_cpus_percent * num_cpus - return round(single_cpu_percent, 1) - - @memoize_when_activated - def cpu_times(self): - """Return a (user, system, children_user, children_system) - namedtuple representing the accumulated process time, in - seconds. - This is similar to os.times() but per-process. - On macOS and Windows children_user and children_system are - always set to 0. - """ - return self._proc.cpu_times() - - @memoize_when_activated - def memory_info(self): - """Return a namedtuple with variable fields depending on the - platform, representing memory information about the process. - - The "portable" fields available on all plaforms are `rss` and `vms`. - - All numbers are expressed in bytes. - """ - return self._proc.memory_info() - - @deprecated_method(replacement="memory_info") - def memory_info_ex(self): - return self.memory_info() - - def memory_full_info(self): - """This method returns the same information as memory_info(), - plus, on some platform (Linux, macOS, Windows), also provides - additional metrics (USS, PSS and swap). - The additional metrics provide a better representation of actual - process memory usage. - - Namely USS is the memory which is unique to a process and which - would be freed if the process was terminated right now. - - It does so by passing through the whole process address. - As such it usually requires higher user privileges than - memory_info() and is considerably slower. - """ - return self._proc.memory_full_info() - - def memory_percent(self, memtype="rss"): - """Compare process memory to total physical system memory and - calculate process memory utilization as a percentage. - *memtype* argument is a string that dictates what type of - process memory you want to compare against (defaults to "rss"). - The list of available strings can be obtained like this: - - >>> psutil.Process().memory_info()._fields - ('rss', 'vms', 'shared', 'text', 'lib', 'data', 'dirty', 'uss', 'pss') - """ - valid_types = list(_psplatform.pfullmem._fields) - if memtype not in valid_types: - raise ValueError("invalid memtype %r; valid types are %r" % ( - memtype, tuple(valid_types))) - fun = self.memory_info if memtype in _psplatform.pmem._fields else \ - self.memory_full_info - metrics = fun() - value = getattr(metrics, memtype) - - # use cached value if available - total_phymem = _TOTAL_PHYMEM or virtual_memory().total - if not total_phymem > 0: - # we should never get here - raise ValueError( - "can't calculate process memory percent because " - "total physical system memory is not positive (%r)" - % total_phymem) - return (value / float(total_phymem)) * 100 - - if hasattr(_psplatform.Process, "memory_maps"): - def memory_maps(self, grouped=True): - """Return process' mapped memory regions as a list of namedtuples - whose fields are variable depending on the platform. - - If *grouped* is True the mapped regions with the same 'path' - are grouped together and the different memory fields are summed. - - If *grouped* is False every mapped region is shown as a single - entity and the namedtuple will also include the mapped region's - address space ('addr') and permission set ('perms'). - """ - it = self._proc.memory_maps() - if grouped: - d = {} - for tupl in it: - path = tupl[2] - nums = tupl[3:] - try: - d[path] = map(lambda x, y: x + y, d[path], nums) - except KeyError: - d[path] = nums - nt = _psplatform.pmmap_grouped - return [nt(path, *d[path]) for path in d] # NOQA - else: - nt = _psplatform.pmmap_ext - return [nt(*x) for x in it] - - def open_files(self): - """Return files opened by process as a list of - (path, fd) namedtuples including the absolute file name - and file descriptor number. - """ - return self._proc.open_files() - - def connections(self, kind='inet'): - """Return socket connections opened by process as a list of - (fd, family, type, laddr, raddr, status) namedtuples. - The *kind* parameter filters for connections that match the - following criteria: - - +------------+----------------------------------------------------+ - | Kind Value | Connections using | - +------------+----------------------------------------------------+ - | inet | IPv4 and IPv6 | - | inet4 | IPv4 | - | inet6 | IPv6 | - | tcp | TCP | - | tcp4 | TCP over IPv4 | - | tcp6 | TCP over IPv6 | - | udp | UDP | - | udp4 | UDP over IPv4 | - | udp6 | UDP over IPv6 | - | unix | UNIX socket (both UDP and TCP protocols) | - | all | the sum of all the possible families and protocols | - +------------+----------------------------------------------------+ - """ - return self._proc.connections(kind) - - # --- signals - - if POSIX: - def _send_signal(self, sig): - assert not self.pid < 0, self.pid - if self.pid == 0: - # see "man 2 kill" - raise ValueError( - "preventing sending signal to process with PID 0 as it " - "would affect every process in the process group of the " - "calling process (os.getpid()) instead of PID 0") - try: - os.kill(self.pid, sig) - except ProcessLookupError: - if OPENBSD and pid_exists(self.pid): - # We do this because os.kill() lies in case of - # zombie processes. - raise ZombieProcess(self.pid, self._name, self._ppid) - else: - self._gone = True - raise NoSuchProcess(self.pid, self._name) - except PermissionError: - raise AccessDenied(self.pid, self._name) - - @_assert_pid_not_reused - def send_signal(self, sig): - """Send a signal *sig* to process pre-emptively checking - whether PID has been reused (see signal module constants) . - On Windows only SIGTERM is valid and is treated as an alias - for kill(). - """ - if POSIX: - self._send_signal(sig) - else: # pragma: no cover - self._proc.send_signal(sig) - - @_assert_pid_not_reused - def suspend(self): - """Suspend process execution with SIGSTOP pre-emptively checking - whether PID has been reused. - On Windows this has the effect ot suspending all process threads. - """ - if POSIX: - self._send_signal(signal.SIGSTOP) - else: # pragma: no cover - self._proc.suspend() - - @_assert_pid_not_reused - def resume(self): - """Resume process execution with SIGCONT pre-emptively checking - whether PID has been reused. - On Windows this has the effect of resuming all process threads. - """ - if POSIX: - self._send_signal(signal.SIGCONT) - else: # pragma: no cover - self._proc.resume() - - @_assert_pid_not_reused - def terminate(self): - """Terminate the process with SIGTERM pre-emptively checking - whether PID has been reused. - On Windows this is an alias for kill(). - """ - if POSIX: - self._send_signal(signal.SIGTERM) - else: # pragma: no cover - self._proc.kill() - - @_assert_pid_not_reused - def kill(self): - """Kill the current process with SIGKILL pre-emptively checking - whether PID has been reused. - """ - if POSIX: - self._send_signal(signal.SIGKILL) - else: # pragma: no cover - self._proc.kill() - - def wait(self, timeout=None): - """Wait for process to terminate and, if process is a children - of os.getpid(), also return its exit code, else None. - On Windows there's no such limitation (exit code is always - returned). - - If the process is already terminated immediately return None - instead of raising NoSuchProcess. - - If *timeout* (in seconds) is specified and process is still - alive raise TimeoutExpired. - - To wait for multiple Process(es) use psutil.wait_procs(). - """ - if timeout is not None and not timeout >= 0: - raise ValueError("timeout must be a positive integer") - return self._proc.wait(timeout) - - -# ===================================================================== -# --- Popen class -# ===================================================================== - - -class Popen(Process): - """A more convenient interface to stdlib subprocess.Popen class. - It starts a sub process and deals with it exactly as when using - subprocess.Popen class but in addition also provides all the - properties and methods of psutil.Process class as a unified - interface: - - >>> import psutil - >>> from subprocess import PIPE - >>> p = psutil.Popen(["python", "-c", "print 'hi'"], stdout=PIPE) - >>> p.name() - 'python' - >>> p.uids() - user(real=1000, effective=1000, saved=1000) - >>> p.username() - 'giampaolo' - >>> p.communicate() - ('hi\n', None) - >>> p.terminate() - >>> p.wait(timeout=2) - 0 - >>> - - For method names common to both classes such as kill(), terminate() - and wait(), psutil.Process implementation takes precedence. - - Unlike subprocess.Popen this class pre-emptively checks whether PID - has been reused on send_signal(), terminate() and kill() so that - you don't accidentally terminate another process, fixing - http://bugs.python.org/issue6973. - - For a complete documentation refer to: - http://docs.python.org/3/library/subprocess.html - """ - - def __init__(self, *args, **kwargs): - # Explicitly avoid to raise NoSuchProcess in case the process - # spawned by subprocess.Popen terminates too quickly, see: - # https://github.com/giampaolo/psutil/issues/193 - self.__subproc = subprocess.Popen(*args, **kwargs) - self._init(self.__subproc.pid, _ignore_nsp=True) - - def __dir__(self): - return sorted(set(dir(Popen) + dir(subprocess.Popen))) - - def __enter__(self): - if hasattr(self.__subproc, '__enter__'): - self.__subproc.__enter__() - return self - - def __exit__(self, *args, **kwargs): - if hasattr(self.__subproc, '__exit__'): - return self.__subproc.__exit__(*args, **kwargs) - else: - if self.stdout: - self.stdout.close() - if self.stderr: - self.stderr.close() - try: - # Flushing a BufferedWriter may raise an error. - if self.stdin: - self.stdin.close() - finally: - # Wait for the process to terminate, to avoid zombies. - self.wait() - - def __getattribute__(self, name): - try: - return object.__getattribute__(self, name) - except AttributeError: - try: - return object.__getattribute__(self.__subproc, name) - except AttributeError: - raise AttributeError("%s instance has no attribute '%s'" - % (self.__class__.__name__, name)) - - def wait(self, timeout=None): - if self.__subproc.returncode is not None: - return self.__subproc.returncode - ret = super(Popen, self).wait(timeout) - self.__subproc.returncode = ret - return ret - - -# The valid attr names which can be processed by Process.as_dict(). -_as_dict_attrnames = set( - [x for x in dir(Process) if not x.startswith('_') and x not in - ['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait', - 'is_running', 'as_dict', 'parent', 'parents', 'children', 'rlimit', - 'memory_info_ex', 'oneshot']]) - - -# ===================================================================== -# --- system processes related functions -# ===================================================================== - - -def pids(): - """Return a list of current running PIDs.""" - global _LOWEST_PID - ret = sorted(_psplatform.pids()) - _LOWEST_PID = ret[0] - return ret - - -def pid_exists(pid): - """Return True if given PID exists in the current process list. - This is faster than doing "pid in psutil.pids()" and - should be preferred. - """ - if pid < 0: - return False - elif pid == 0 and POSIX: - # On POSIX we use os.kill() to determine PID existence. - # According to "man 2 kill" PID 0 has a special meaning - # though: it refers to <> and that is not we want - # to do here. - return pid in pids() - else: - return _psplatform.pid_exists(pid) - - -_pmap = {} -_lock = threading.Lock() - - -def process_iter(attrs=None, ad_value=None): - """Return a generator yielding a Process instance for all - running processes. - - Every new Process instance is only created once and then cached - into an internal table which is updated every time this is used. - - Cached Process instances are checked for identity so that you're - safe in case a PID has been reused by another process, in which - case the cached instance is updated. - - The sorting order in which processes are yielded is based on - their PIDs. - - *attrs* and *ad_value* have the same meaning as in - Process.as_dict(). If *attrs* is specified as_dict() is called - and the resulting dict is stored as a 'info' attribute attached - to returned Process instance. - If *attrs* is an empty list it will retrieve all process info - (slow). - """ - def add(pid): - proc = Process(pid) - if attrs is not None: - proc.info = proc.as_dict(attrs=attrs, ad_value=ad_value) - with _lock: - _pmap[proc.pid] = proc - return proc - - def remove(pid): - with _lock: - _pmap.pop(pid, None) - - a = set(pids()) - b = set(_pmap.keys()) - new_pids = a - b - gone_pids = b - a - for pid in gone_pids: - remove(pid) - - with _lock: - ls = sorted(list(_pmap.items()) + - list(dict.fromkeys(new_pids).items())) - - for pid, proc in ls: - try: - if proc is None: # new process - yield add(pid) - else: - # use is_running() to check whether PID has been reused by - # another process in which case yield a new Process instance - if proc.is_running(): - if attrs is not None: - proc.info = proc.as_dict( - attrs=attrs, ad_value=ad_value) - yield proc - else: - yield add(pid) - except NoSuchProcess: - remove(pid) - except AccessDenied: - # Process creation time can't be determined hence there's - # no way to tell whether the pid of the cached process - # has been reused. Just return the cached version. - if proc is None and pid in _pmap: - try: - yield _pmap[pid] - except KeyError: - # If we get here it is likely that 2 threads were - # using process_iter(). - pass - else: - raise - - -def wait_procs(procs, timeout=None, callback=None): - """Convenience function which waits for a list of processes to - terminate. - - Return a (gone, alive) tuple indicating which processes - are gone and which ones are still alive. - - The gone ones will have a new *returncode* attribute indicating - process exit status (may be None). - - *callback* is a function which gets called every time a process - terminates (a Process instance is passed as callback argument). - - Function will return as soon as all processes terminate or when - *timeout* occurs. - Differently from Process.wait() it will not raise TimeoutExpired if - *timeout* occurs. - - Typical use case is: - - - send SIGTERM to a list of processes - - give them some time to terminate - - send SIGKILL to those ones which are still alive - - Example: - - >>> def on_terminate(proc): - ... print("process {} terminated".format(proc)) - ... - >>> for p in procs: - ... p.terminate() - ... - >>> gone, alive = wait_procs(procs, timeout=3, callback=on_terminate) - >>> for p in alive: - ... p.kill() - """ - def check_gone(proc, timeout): - try: - returncode = proc.wait(timeout=timeout) - except TimeoutExpired: - pass - else: - if returncode is not None or not proc.is_running(): - # Set new Process instance attribute. - proc.returncode = returncode - gone.add(proc) - if callback is not None: - callback(proc) - - if timeout is not None and not timeout >= 0: - msg = "timeout must be a positive integer, got %s" % timeout - raise ValueError(msg) - gone = set() - alive = set(procs) - if callback is not None and not callable(callback): - raise TypeError("callback %r is not a callable" % callable) - if timeout is not None: - deadline = _timer() + timeout - - while alive: - if timeout is not None and timeout <= 0: - break - for proc in alive: - # Make sure that every complete iteration (all processes) - # will last max 1 sec. - # We do this because we don't want to wait too long on a - # single process: in case it terminates too late other - # processes may disappear in the meantime and their PID - # reused. - max_timeout = 1.0 / len(alive) - if timeout is not None: - timeout = min((deadline - _timer()), max_timeout) - if timeout <= 0: - break - check_gone(proc, timeout) - else: - check_gone(proc, max_timeout) - alive = alive - gone - - if alive: - # Last attempt over processes survived so far. - # timeout == 0 won't make this function wait any further. - for proc in alive: - check_gone(proc, 0) - alive = alive - gone - - return (list(gone), list(alive)) - - -# ===================================================================== -# --- CPU related functions -# ===================================================================== - - -def cpu_count(logical=True): - """Return the number of logical CPUs in the system (same as - os.cpu_count() in Python 3.4). - - If *logical* is False return the number of physical cores only - (e.g. hyper thread CPUs are excluded). - - Return None if undetermined. - - The return value is cached after first call. - If desired cache can be cleared like this: - - >>> psutil.cpu_count.cache_clear() - """ - if logical: - ret = _psplatform.cpu_count_logical() - else: - ret = _psplatform.cpu_count_physical() - if ret is not None and ret < 1: - ret = None - return ret - - -def cpu_times(percpu=False): - """Return system-wide CPU times as a namedtuple. - Every CPU time represents the seconds the CPU has spent in the - given mode. The namedtuple's fields availability varies depending on the - platform: - - - user - - system - - idle - - nice (UNIX) - - iowait (Linux) - - irq (Linux, FreeBSD) - - softirq (Linux) - - steal (Linux >= 2.6.11) - - guest (Linux >= 2.6.24) - - guest_nice (Linux >= 3.2.0) - - When *percpu* is True return a list of namedtuples for each CPU. - First element of the list refers to first CPU, second element - to second CPU and so on. - The order of the list is consistent across calls. - """ - if not percpu: - return _psplatform.cpu_times() - else: - return _psplatform.per_cpu_times() - - -try: - _last_cpu_times = cpu_times() -except Exception: - # Don't want to crash at import time. - _last_cpu_times = None - -try: - _last_per_cpu_times = cpu_times(percpu=True) -except Exception: - # Don't want to crash at import time. - _last_per_cpu_times = None - - -def _cpu_tot_time(times): - """Given a cpu_time() ntuple calculates the total CPU time - (including idle time). - """ - tot = sum(times) - if LINUX: - # On Linux guest times are already accounted in "user" or - # "nice" times, so we subtract them from total. - # Htop does the same. References: - # https://github.com/giampaolo/psutil/pull/940 - # http://unix.stackexchange.com/questions/178045 - # https://github.com/torvalds/linux/blob/ - # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/ - # cputime.c#L158 - tot -= getattr(times, "guest", 0) # Linux 2.6.24+ - tot -= getattr(times, "guest_nice", 0) # Linux 3.2.0+ - return tot - - -def _cpu_busy_time(times): - """Given a cpu_time() ntuple calculates the busy CPU time. - We do so by subtracting all idle CPU times. - """ - busy = _cpu_tot_time(times) - busy -= times.idle - # Linux: "iowait" is time during which the CPU does not do anything - # (waits for IO to complete). On Linux IO wait is *not* accounted - # in "idle" time so we subtract it. Htop does the same. - # References: - # https://github.com/torvalds/linux/blob/ - # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/cputime.c#L244 - busy -= getattr(times, "iowait", 0) - return busy - - -def _cpu_times_deltas(t1, t2): - assert t1._fields == t2._fields, (t1, t2) - field_deltas = [] - for field in _psplatform.scputimes._fields: - field_delta = getattr(t2, field) - getattr(t1, field) - # CPU times are always supposed to increase over time - # or at least remain the same and that's because time - # cannot go backwards. - # Surprisingly sometimes this might not be the case (at - # least on Windows and Linux), see: - # https://github.com/giampaolo/psutil/issues/392 - # https://github.com/giampaolo/psutil/issues/645 - # https://github.com/giampaolo/psutil/issues/1210 - # Trim negative deltas to zero to ignore decreasing fields. - # top does the same. Reference: - # https://gitlab.com/procps-ng/procps/blob/v3.3.12/top/top.c#L5063 - field_delta = max(0, field_delta) - field_deltas.append(field_delta) - return _psplatform.scputimes(*field_deltas) - - -def cpu_percent(interval=None, percpu=False): - """Return a float representing the current system-wide CPU - utilization as a percentage. - - When *interval* is > 0.0 compares system CPU times elapsed before - and after the interval (blocking). - - When *interval* is 0.0 or None compares system CPU times elapsed - since last call or module import, returning immediately (non - blocking). That means the first time this is called it will - return a meaningless 0.0 value which you should ignore. - In this case is recommended for accuracy that this function be - called with at least 0.1 seconds between calls. - - When *percpu* is True returns a list of floats representing the - utilization as a percentage for each CPU. - First element of the list refers to first CPU, second element - to second CPU and so on. - The order of the list is consistent across calls. - - Examples: - - >>> # blocking, system-wide - >>> psutil.cpu_percent(interval=1) - 2.0 - >>> - >>> # blocking, per-cpu - >>> psutil.cpu_percent(interval=1, percpu=True) - [2.0, 1.0] - >>> - >>> # non-blocking (percentage since last call) - >>> psutil.cpu_percent(interval=None) - 2.9 - >>> - """ - global _last_cpu_times - global _last_per_cpu_times - blocking = interval is not None and interval > 0.0 - if interval is not None and interval < 0: - raise ValueError("interval is not positive (got %r)" % interval) - - def calculate(t1, t2): - times_delta = _cpu_times_deltas(t1, t2) - - all_delta = _cpu_tot_time(times_delta) - busy_delta = _cpu_busy_time(times_delta) - - try: - busy_perc = (busy_delta / all_delta) * 100 - except ZeroDivisionError: - return 0.0 - else: - return round(busy_perc, 1) - - # system-wide usage - if not percpu: - if blocking: - t1 = cpu_times() - time.sleep(interval) - else: - t1 = _last_cpu_times - if t1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - t1 = cpu_times() - _last_cpu_times = cpu_times() - return calculate(t1, _last_cpu_times) - # per-cpu usage - else: - ret = [] - if blocking: - tot1 = cpu_times(percpu=True) - time.sleep(interval) - else: - tot1 = _last_per_cpu_times - if tot1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - tot1 = cpu_times(percpu=True) - _last_per_cpu_times = cpu_times(percpu=True) - for t1, t2 in zip(tot1, _last_per_cpu_times): - ret.append(calculate(t1, t2)) - return ret - - -# Use separate global vars for cpu_times_percent() so that it's -# independent from cpu_percent() and they can both be used within -# the same program. -_last_cpu_times_2 = _last_cpu_times -_last_per_cpu_times_2 = _last_per_cpu_times - - -def cpu_times_percent(interval=None, percpu=False): - """Same as cpu_percent() but provides utilization percentages - for each specific CPU time as is returned by cpu_times(). - For instance, on Linux we'll get: - - >>> cpu_times_percent() - cpupercent(user=4.8, nice=0.0, system=4.8, idle=90.5, iowait=0.0, - irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - >>> - - *interval* and *percpu* arguments have the same meaning as in - cpu_percent(). - """ - global _last_cpu_times_2 - global _last_per_cpu_times_2 - blocking = interval is not None and interval > 0.0 - if interval is not None and interval < 0: - raise ValueError("interval is not positive (got %r)" % interval) - - def calculate(t1, t2): - nums = [] - times_delta = _cpu_times_deltas(t1, t2) - all_delta = _cpu_tot_time(times_delta) - # "scale" is the value to multiply each delta with to get percentages. - # We use "max" to avoid division by zero (if all_delta is 0, then all - # fields are 0 so percentages will be 0 too. all_delta cannot be a - # fraction because cpu times are integers) - scale = 100.0 / max(1, all_delta) - for field_delta in times_delta: - field_perc = field_delta * scale - field_perc = round(field_perc, 1) - # make sure we don't return negative values or values over 100% - field_perc = min(max(0.0, field_perc), 100.0) - nums.append(field_perc) - return _psplatform.scputimes(*nums) - - # system-wide usage - if not percpu: - if blocking: - t1 = cpu_times() - time.sleep(interval) - else: - t1 = _last_cpu_times_2 - if t1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - t1 = cpu_times() - _last_cpu_times_2 = cpu_times() - return calculate(t1, _last_cpu_times_2) - # per-cpu usage - else: - ret = [] - if blocking: - tot1 = cpu_times(percpu=True) - time.sleep(interval) - else: - tot1 = _last_per_cpu_times_2 - if tot1 is None: - # Something bad happened at import time. We'll - # get a meaningful result on the next call. See: - # https://github.com/giampaolo/psutil/pull/715 - tot1 = cpu_times(percpu=True) - _last_per_cpu_times_2 = cpu_times(percpu=True) - for t1, t2 in zip(tot1, _last_per_cpu_times_2): - ret.append(calculate(t1, t2)) - return ret - - -def cpu_stats(): - """Return CPU statistics.""" - return _psplatform.cpu_stats() - - -if hasattr(_psplatform, "cpu_freq"): - - def cpu_freq(percpu=False): - """Return CPU frequency as a nameduple including current, - min and max frequency expressed in Mhz. - - If *percpu* is True and the system supports per-cpu frequency - retrieval (Linux only) a list of frequencies is returned for - each CPU. If not a list with one element is returned. - """ - ret = _psplatform.cpu_freq() - if percpu: - return ret - else: - num_cpus = float(len(ret)) - if num_cpus == 0: - return None - elif num_cpus == 1: - return ret[0] - else: - currs, mins, maxs = 0.0, 0.0, 0.0 - set_none = False - for cpu in ret: - currs += cpu.current - # On Linux if /proc/cpuinfo is used min/max are set - # to None. - if LINUX and cpu.min is None: - set_none = True - continue - mins += cpu.min - maxs += cpu.max - - current = currs / num_cpus - - if set_none: - min_ = max_ = None - else: - min_ = mins / num_cpus - max_ = maxs / num_cpus - - return _common.scpufreq(current, min_, max_) - - __all__.append("cpu_freq") - - -if hasattr(os, "getloadavg") or hasattr(_psplatform, "getloadavg"): - # Perform this hasattr check once on import time to either use the - # platform based code or proxy straight from the os module. - if hasattr(os, "getloadavg"): - getloadavg = os.getloadavg - else: - getloadavg = _psplatform.getloadavg - - __all__.append("getloadavg") - - -# ===================================================================== -# --- system memory related functions -# ===================================================================== - - -def virtual_memory(): - """Return statistics about system memory usage as a namedtuple - including the following fields, expressed in bytes: - - - total: - total physical memory available. - - - available: - the memory that can be given instantly to processes without the - system going into swap. - This is calculated by summing different memory values depending - on the platform and it is supposed to be used to monitor actual - memory usage in a cross platform fashion. - - - percent: - the percentage usage calculated as (total - available) / total * 100 - - - used: - memory used, calculated differently depending on the platform and - designed for informational purposes only: - macOS: active + wired - BSD: active + wired + cached - Linux: total - free - - - free: - memory not being used at all (zeroed) that is readily available; - note that this doesn't reflect the actual memory available - (use 'available' instead) - - Platform-specific fields: - - - active (UNIX): - memory currently in use or very recently used, and so it is in RAM. - - - inactive (UNIX): - memory that is marked as not used. - - - buffers (BSD, Linux): - cache for things like file system metadata. - - - cached (BSD, macOS): - cache for various things. - - - wired (macOS, BSD): - memory that is marked to always stay in RAM. It is never moved to disk. - - - shared (BSD): - memory that may be simultaneously accessed by multiple processes. - - The sum of 'used' and 'available' does not necessarily equal total. - On Windows 'available' and 'free' are the same. - """ - global _TOTAL_PHYMEM - ret = _psplatform.virtual_memory() - # cached for later use in Process.memory_percent() - _TOTAL_PHYMEM = ret.total - return ret - - -def swap_memory(): - """Return system swap memory statistics as a namedtuple including - the following fields: - - - total: total swap memory in bytes - - used: used swap memory in bytes - - free: free swap memory in bytes - - percent: the percentage usage - - sin: no. of bytes the system has swapped in from disk (cumulative) - - sout: no. of bytes the system has swapped out from disk (cumulative) - - 'sin' and 'sout' on Windows are meaningless and always set to 0. - """ - return _psplatform.swap_memory() - - -# ===================================================================== -# --- disks/paritions related functions -# ===================================================================== - - -def disk_usage(path): - """Return disk usage statistics about the given *path* as a - namedtuple including total, used and free space expressed in bytes - plus the percentage usage. - """ - return _psplatform.disk_usage(path) - - -def disk_partitions(all=False): - """Return mounted partitions as a list of - (device, mountpoint, fstype, opts) namedtuple. - 'opts' field is a raw string separated by commas indicating mount - options which may vary depending on the platform. - - If *all* parameter is False return physical devices only and ignore - all others. - """ - return _psplatform.disk_partitions(all) - - -def disk_io_counters(perdisk=False, nowrap=True): - """Return system disk I/O statistics as a namedtuple including - the following fields: - - - read_count: number of reads - - write_count: number of writes - - read_bytes: number of bytes read - - write_bytes: number of bytes written - - read_time: time spent reading from disk (in ms) - - write_time: time spent writing to disk (in ms) - - Platform specific: - - - busy_time: (Linux, FreeBSD) time spent doing actual I/Os (in ms) - - read_merged_count (Linux): number of merged reads - - write_merged_count (Linux): number of merged writes - - If *perdisk* is True return the same information for every - physical disk installed on the system as a dictionary - with partition names as the keys and the namedtuple - described above as the values. - - If *nowrap* is True it detects and adjust the numbers which overflow - and wrap (restart from 0) and add "old value" to "new value" so that - the returned numbers will always be increasing or remain the same, - but never decrease. - "disk_io_counters.cache_clear()" can be used to invalidate the - cache. - - On recent Windows versions 'diskperf -y' command may need to be - executed first otherwise this function won't find any disk. - """ - kwargs = dict(perdisk=perdisk) if LINUX else {} - rawdict = _psplatform.disk_io_counters(**kwargs) - if not rawdict: - return {} if perdisk else None - if nowrap: - rawdict = _wrap_numbers(rawdict, 'psutil.disk_io_counters') - nt = getattr(_psplatform, "sdiskio", _common.sdiskio) - if perdisk: - for disk, fields in rawdict.items(): - rawdict[disk] = nt(*fields) - return rawdict - else: - return nt(*[sum(x) for x in zip(*rawdict.values())]) - - -disk_io_counters.cache_clear = functools.partial( - _wrap_numbers.cache_clear, 'psutil.disk_io_counters') -disk_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache" - - -# ===================================================================== -# --- network related functions -# ===================================================================== - - -def net_io_counters(pernic=False, nowrap=True): - """Return network I/O statistics as a namedtuple including - the following fields: - - - bytes_sent: number of bytes sent - - bytes_recv: number of bytes received - - packets_sent: number of packets sent - - packets_recv: number of packets received - - errin: total number of errors while receiving - - errout: total number of errors while sending - - dropin: total number of incoming packets which were dropped - - dropout: total number of outgoing packets which were dropped - (always 0 on macOS and BSD) - - If *pernic* is True return the same information for every - network interface installed on the system as a dictionary - with network interface names as the keys and the namedtuple - described above as the values. - - If *nowrap* is True it detects and adjust the numbers which overflow - and wrap (restart from 0) and add "old value" to "new value" so that - the returned numbers will always be increasing or remain the same, - but never decrease. - "disk_io_counters.cache_clear()" can be used to invalidate the - cache. - """ - rawdict = _psplatform.net_io_counters() - if not rawdict: - return {} if pernic else None - if nowrap: - rawdict = _wrap_numbers(rawdict, 'psutil.net_io_counters') - if pernic: - for nic, fields in rawdict.items(): - rawdict[nic] = _common.snetio(*fields) - return rawdict - else: - return _common.snetio(*[sum(x) for x in zip(*rawdict.values())]) - - -net_io_counters.cache_clear = functools.partial( - _wrap_numbers.cache_clear, 'psutil.net_io_counters') -net_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache" - - -def net_connections(kind='inet'): - """Return system-wide socket connections as a list of - (fd, family, type, laddr, raddr, status, pid) namedtuples. - In case of limited privileges 'fd' and 'pid' may be set to -1 - and None respectively. - The *kind* parameter filters for connections that fit the - following criteria: - - +------------+----------------------------------------------------+ - | Kind Value | Connections using | - +------------+----------------------------------------------------+ - | inet | IPv4 and IPv6 | - | inet4 | IPv4 | - | inet6 | IPv6 | - | tcp | TCP | - | tcp4 | TCP over IPv4 | - | tcp6 | TCP over IPv6 | - | udp | UDP | - | udp4 | UDP over IPv4 | - | udp6 | UDP over IPv6 | - | unix | UNIX socket (both UDP and TCP protocols) | - | all | the sum of all the possible families and protocols | - +------------+----------------------------------------------------+ - - On macOS this function requires root privileges. - """ - return _psplatform.net_connections(kind) - - -def net_if_addrs(): - """Return the addresses associated to each NIC (network interface - card) installed on the system as a dictionary whose keys are the - NIC names and value is a list of namedtuples for each address - assigned to the NIC. Each namedtuple includes 5 fields: - - - family: can be either socket.AF_INET, socket.AF_INET6 or - psutil.AF_LINK, which refers to a MAC address. - - address: is the primary address and it is always set. - - netmask: and 'broadcast' and 'ptp' may be None. - - ptp: stands for "point to point" and references the - destination address on a point to point interface - (typically a VPN). - - broadcast: and *ptp* are mutually exclusive. - - Note: you can have more than one address of the same family - associated with each interface. - """ - has_enums = sys.version_info >= (3, 4) - if has_enums: - import socket - rawlist = _psplatform.net_if_addrs() - rawlist.sort(key=lambda x: x[1]) # sort by family - ret = collections.defaultdict(list) - for name, fam, addr, mask, broadcast, ptp in rawlist: - if has_enums: - try: - fam = socket.AddressFamily(fam) - except ValueError: - if WINDOWS and fam == -1: - fam = _psplatform.AF_LINK - elif (hasattr(_psplatform, "AF_LINK") and - _psplatform.AF_LINK == fam): - # Linux defines AF_LINK as an alias for AF_PACKET. - # We re-set the family here so that repr(family) - # will show AF_LINK rather than AF_PACKET - fam = _psplatform.AF_LINK - if fam == _psplatform.AF_LINK: - # The underlying C function may return an incomplete MAC - # address in which case we fill it with null bytes, see: - # https://github.com/giampaolo/psutil/issues/786 - separator = ":" if POSIX else "-" - while addr.count(separator) < 5: - addr += "%s00" % separator - ret[name].append(_common.snicaddr(fam, addr, mask, broadcast, ptp)) - return dict(ret) - - -def net_if_stats(): - """Return information about each NIC (network interface card) - installed on the system as a dictionary whose keys are the - NIC names and value is a namedtuple with the following fields: - - - isup: whether the interface is up (bool) - - duplex: can be either NIC_DUPLEX_FULL, NIC_DUPLEX_HALF or - NIC_DUPLEX_UNKNOWN - - speed: the NIC speed expressed in mega bits (MB); if it can't - be determined (e.g. 'localhost') it will be set to 0. - - mtu: the maximum transmission unit expressed in bytes. - """ - return _psplatform.net_if_stats() - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -# Linux, macOS -if hasattr(_psplatform, "sensors_temperatures"): - - def sensors_temperatures(fahrenheit=False): - """Return hardware temperatures. Each entry is a namedtuple - representing a certain hardware sensor (it may be a CPU, an - hard disk or something else, depending on the OS and its - configuration). - All temperatures are expressed in celsius unless *fahrenheit* - is set to True. - """ - def convert(n): - if n is not None: - return (float(n) * 9 / 5) + 32 if fahrenheit else n - - ret = collections.defaultdict(list) - rawdict = _psplatform.sensors_temperatures() - - for name, values in rawdict.items(): - while values: - label, current, high, critical = values.pop(0) - current = convert(current) - high = convert(high) - critical = convert(critical) - - if high and not critical: - critical = high - elif critical and not high: - high = critical - - ret[name].append( - _common.shwtemp(label, current, high, critical)) - - return dict(ret) - - __all__.append("sensors_temperatures") - - -# Linux, macOS -if hasattr(_psplatform, "sensors_fans"): - - def sensors_fans(): - """Return fans speed. Each entry is a namedtuple - representing a certain hardware sensor. - All speed are expressed in RPM (rounds per minute). - """ - return _psplatform.sensors_fans() - - __all__.append("sensors_fans") - - -# Linux, Windows, FreeBSD, macOS -if hasattr(_psplatform, "sensors_battery"): - - def sensors_battery(): - """Return battery information. If no battery is installed - returns None. - - - percent: battery power left as a percentage. - - secsleft: a rough approximation of how many seconds are left - before the battery runs out of power. May be - POWER_TIME_UNLIMITED or POWER_TIME_UNLIMITED. - - power_plugged: True if the AC power cable is connected. - """ - return _psplatform.sensors_battery() - - __all__.append("sensors_battery") - - -# ===================================================================== -# --- other system related functions -# ===================================================================== - - -def boot_time(): - """Return the system boot time expressed in seconds since the epoch.""" - # Note: we are not caching this because it is subject to - # system clock updates. - return _psplatform.boot_time() - - -def users(): - """Return users currently connected on the system as a list of - namedtuples including the following fields. - - - user: the name of the user - - terminal: the tty or pseudo-tty associated with the user, if any. - - host: the host name associated with the entry, if any. - - started: the creation time as a floating point number expressed in - seconds since the epoch. - """ - return _psplatform.users() - - -# ===================================================================== -# --- Windows services -# ===================================================================== - - -if WINDOWS: - - def win_service_iter(): - """Return a generator yielding a WindowsService instance for all - Windows services installed. - """ - return _psplatform.win_service_iter() - - def win_service_get(name): - """Get a Windows service by *name*. - Raise NoSuchProcess if no service with such name exists. - """ - return _psplatform.win_service_get(name) - - -# ===================================================================== - - -def test(): # pragma: no cover - from ._common import bytes2human - from ._compat import get_terminal_size - - today_day = datetime.date.today() - templ = "%-10s %5s %5s %7s %7s %5s %6s %6s %6s %s" - attrs = ['pid', 'memory_percent', 'name', 'cmdline', 'cpu_times', - 'create_time', 'memory_info', 'status', 'nice', 'username'] - print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "NICE", - "STATUS", "START", "TIME", "CMDLINE")) - for p in process_iter(attrs, ad_value=None): - if p.info['create_time']: - ctime = datetime.datetime.fromtimestamp(p.info['create_time']) - if ctime.date() == today_day: - ctime = ctime.strftime("%H:%M") - else: - ctime = ctime.strftime("%b%d") - else: - ctime = '' - if p.info['cpu_times']: - cputime = time.strftime("%M:%S", - time.localtime(sum(p.info['cpu_times']))) - else: - cputime = '' - - user = p.info['username'] or '' - if not user and POSIX: - try: - user = p.uids()[0] - except Error: - pass - if user and WINDOWS and '\\' in user: - user = user.split('\\')[1] - user = user[:9] - vms = bytes2human(p.info['memory_info'].vms) if \ - p.info['memory_info'] is not None else '' - rss = bytes2human(p.info['memory_info'].rss) if \ - p.info['memory_info'] is not None else '' - memp = round(p.info['memory_percent'], 1) if \ - p.info['memory_percent'] is not None else '' - nice = int(p.info['nice']) if p.info['nice'] else '' - if p.info['cmdline']: - cmdline = ' '.join(p.info['cmdline']) - else: - cmdline = p.info['name'] - status = p.info['status'][:5] if p.info['status'] else '' - - line = templ % ( - user[:10], - p.info['pid'], - memp, - vms, - rss, - nice, - status, - ctime, - cputime, - cmdline) - print(line[:get_terminal_size()[0]]) - - -del memoize, memoize_when_activated, division, deprecated_method -if sys.version_info[0] < 3: - del num, x - -if __name__ == "__main__": - test() diff --git a/third_party/python/psutil/psutil/_common.py b/third_party/python/psutil/psutil/_common.py deleted file mode 100644 index 17b6eeb3bf85..000000000000 --- a/third_party/python/psutil/psutil/_common.py +++ /dev/null @@ -1,846 +0,0 @@ -# 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. - -"""Common objects shared by __init__.py and _ps*.py modules.""" - -# Note: this module is imported by setup.py so it should not import -# psutil or third-party modules. - -from __future__ import division, print_function - -import contextlib -import errno -import functools -import os -import socket -import stat -import sys -import threading -import warnings -from collections import defaultdict -from collections import namedtuple -from socket import AF_INET -from socket import SOCK_DGRAM -from socket import SOCK_STREAM - -try: - from socket import AF_INET6 -except ImportError: - AF_INET6 = None -try: - from socket import AF_UNIX -except ImportError: - AF_UNIX = None - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - - -# can't take it from _common.py as this script is imported by setup.py -PY3 = sys.version_info[0] == 3 - -__all__ = [ - # OS constants - 'FREEBSD', 'BSD', 'LINUX', 'NETBSD', 'OPENBSD', 'MACOS', 'OSX', 'POSIX', - 'SUNOS', 'WINDOWS', - # connection constants - 'CONN_CLOSE', 'CONN_CLOSE_WAIT', 'CONN_CLOSING', 'CONN_ESTABLISHED', - 'CONN_FIN_WAIT1', 'CONN_FIN_WAIT2', 'CONN_LAST_ACK', 'CONN_LISTEN', - 'CONN_NONE', 'CONN_SYN_RECV', 'CONN_SYN_SENT', 'CONN_TIME_WAIT', - # net constants - 'NIC_DUPLEX_FULL', 'NIC_DUPLEX_HALF', 'NIC_DUPLEX_UNKNOWN', - # process status constants - 'STATUS_DEAD', 'STATUS_DISK_SLEEP', 'STATUS_IDLE', 'STATUS_LOCKED', - 'STATUS_RUNNING', 'STATUS_SLEEPING', 'STATUS_STOPPED', 'STATUS_SUSPENDED', - 'STATUS_TRACING_STOP', 'STATUS_WAITING', 'STATUS_WAKE_KILL', - 'STATUS_WAKING', 'STATUS_ZOMBIE', 'STATUS_PARKED', - # other constants - 'ENCODING', 'ENCODING_ERRS', 'AF_INET6', - # named tuples - 'pconn', 'pcputimes', 'pctxsw', 'pgids', 'pio', 'pionice', 'popenfile', - 'pthread', 'puids', 'sconn', 'scpustats', 'sdiskio', 'sdiskpart', - 'sdiskusage', 'snetio', 'snicaddr', 'snicstats', 'sswap', 'suser', - # utility functions - 'conn_tmap', 'deprecated_method', 'isfile_strict', 'memoize', - 'parse_environ_block', 'path_exists_strict', 'usage_percent', - 'supports_ipv6', 'sockfam_to_enum', 'socktype_to_enum', "wrap_numbers", - 'bytes2human', 'conn_to_ntuple', 'debug', - # shell utils - 'hilite', 'term_supports_colors', 'print_color', -] - - -# =================================================================== -# --- OS constants -# =================================================================== - - -POSIX = os.name == "posix" -WINDOWS = os.name == "nt" -LINUX = sys.platform.startswith("linux") -MACOS = sys.platform.startswith("darwin") -OSX = MACOS # deprecated alias -FREEBSD = sys.platform.startswith("freebsd") -OPENBSD = sys.platform.startswith("openbsd") -NETBSD = sys.platform.startswith("netbsd") -BSD = FREEBSD or OPENBSD or NETBSD -SUNOS = sys.platform.startswith(("sunos", "solaris")) -AIX = sys.platform.startswith("aix") - - -# =================================================================== -# --- API constants -# =================================================================== - - -# Process.status() -STATUS_RUNNING = "running" -STATUS_SLEEPING = "sleeping" -STATUS_DISK_SLEEP = "disk-sleep" -STATUS_STOPPED = "stopped" -STATUS_TRACING_STOP = "tracing-stop" -STATUS_ZOMBIE = "zombie" -STATUS_DEAD = "dead" -STATUS_WAKE_KILL = "wake-kill" -STATUS_WAKING = "waking" -STATUS_IDLE = "idle" # Linux, macOS, FreeBSD -STATUS_LOCKED = "locked" # FreeBSD -STATUS_WAITING = "waiting" # FreeBSD -STATUS_SUSPENDED = "suspended" # NetBSD -STATUS_PARKED = "parked" # Linux - -# Process.connections() and psutil.net_connections() -CONN_ESTABLISHED = "ESTABLISHED" -CONN_SYN_SENT = "SYN_SENT" -CONN_SYN_RECV = "SYN_RECV" -CONN_FIN_WAIT1 = "FIN_WAIT1" -CONN_FIN_WAIT2 = "FIN_WAIT2" -CONN_TIME_WAIT = "TIME_WAIT" -CONN_CLOSE = "CLOSE" -CONN_CLOSE_WAIT = "CLOSE_WAIT" -CONN_LAST_ACK = "LAST_ACK" -CONN_LISTEN = "LISTEN" -CONN_CLOSING = "CLOSING" -CONN_NONE = "NONE" - -# net_if_stats() -if enum is None: - NIC_DUPLEX_FULL = 2 - NIC_DUPLEX_HALF = 1 - NIC_DUPLEX_UNKNOWN = 0 -else: - class NicDuplex(enum.IntEnum): - NIC_DUPLEX_FULL = 2 - NIC_DUPLEX_HALF = 1 - NIC_DUPLEX_UNKNOWN = 0 - - globals().update(NicDuplex.__members__) - -# sensors_battery() -if enum is None: - POWER_TIME_UNKNOWN = -1 - POWER_TIME_UNLIMITED = -2 -else: - class BatteryTime(enum.IntEnum): - POWER_TIME_UNKNOWN = -1 - POWER_TIME_UNLIMITED = -2 - - globals().update(BatteryTime.__members__) - -# --- others - -ENCODING = sys.getfilesystemencoding() -if not PY3: - ENCODING_ERRS = "replace" -else: - try: - ENCODING_ERRS = sys.getfilesystemencodeerrors() # py 3.6 - except AttributeError: - ENCODING_ERRS = "surrogateescape" if POSIX else "replace" - - -# =================================================================== -# --- namedtuples -# =================================================================== - -# --- for system functions - -# psutil.swap_memory() -sswap = namedtuple('sswap', ['total', 'used', 'free', 'percent', 'sin', - 'sout']) -# psutil.disk_usage() -sdiskusage = namedtuple('sdiskusage', ['total', 'used', 'free', 'percent']) -# psutil.disk_io_counters() -sdiskio = namedtuple('sdiskio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'read_time', 'write_time']) -# psutil.disk_partitions() -sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts']) -# psutil.net_io_counters() -snetio = namedtuple('snetio', ['bytes_sent', 'bytes_recv', - 'packets_sent', 'packets_recv', - 'errin', 'errout', - 'dropin', 'dropout']) -# psutil.users() -suser = namedtuple('suser', ['name', 'terminal', 'host', 'started', 'pid']) -# psutil.net_connections() -sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr', - 'status', 'pid']) -# psutil.net_if_addrs() -snicaddr = namedtuple('snicaddr', - ['family', 'address', 'netmask', 'broadcast', 'ptp']) -# psutil.net_if_stats() -snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu']) -# psutil.cpu_stats() -scpustats = namedtuple( - 'scpustats', ['ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls']) -# psutil.cpu_freq() -scpufreq = namedtuple('scpufreq', ['current', 'min', 'max']) -# psutil.sensors_temperatures() -shwtemp = namedtuple( - 'shwtemp', ['label', 'current', 'high', 'critical']) -# psutil.sensors_battery() -sbattery = namedtuple('sbattery', ['percent', 'secsleft', 'power_plugged']) -# psutil.sensors_fans() -sfan = namedtuple('sfan', ['label', 'current']) - -# --- for Process methods - -# psutil.Process.cpu_times() -pcputimes = namedtuple('pcputimes', - ['user', 'system', 'children_user', 'children_system']) -# psutil.Process.open_files() -popenfile = namedtuple('popenfile', ['path', 'fd']) -# psutil.Process.threads() -pthread = namedtuple('pthread', ['id', 'user_time', 'system_time']) -# psutil.Process.uids() -puids = namedtuple('puids', ['real', 'effective', 'saved']) -# psutil.Process.gids() -pgids = namedtuple('pgids', ['real', 'effective', 'saved']) -# psutil.Process.io_counters() -pio = namedtuple('pio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes']) -# psutil.Process.ionice() -pionice = namedtuple('pionice', ['ioclass', 'value']) -# psutil.Process.ctx_switches() -pctxsw = namedtuple('pctxsw', ['voluntary', 'involuntary']) -# psutil.Process.connections() -pconn = namedtuple('pconn', ['fd', 'family', 'type', 'laddr', 'raddr', - 'status']) - -# psutil.connections() and psutil.Process.connections() -addr = namedtuple('addr', ['ip', 'port']) - - -# =================================================================== -# --- Process.connections() 'kind' parameter mapping -# =================================================================== - - -conn_tmap = { - "all": ([AF_INET, AF_INET6, AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), - "tcp": ([AF_INET, AF_INET6], [SOCK_STREAM]), - "tcp4": ([AF_INET], [SOCK_STREAM]), - "udp": ([AF_INET, AF_INET6], [SOCK_DGRAM]), - "udp4": ([AF_INET], [SOCK_DGRAM]), - "inet": ([AF_INET, AF_INET6], [SOCK_STREAM, SOCK_DGRAM]), - "inet4": ([AF_INET], [SOCK_STREAM, SOCK_DGRAM]), - "inet6": ([AF_INET6], [SOCK_STREAM, SOCK_DGRAM]), -} - -if AF_INET6 is not None: - conn_tmap.update({ - "tcp6": ([AF_INET6], [SOCK_STREAM]), - "udp6": ([AF_INET6], [SOCK_DGRAM]), - }) - -if AF_UNIX is not None: - conn_tmap.update({ - "unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), - }) - - -# ===================================================================== -# --- Exceptions -# ===================================================================== - - -class Error(Exception): - """Base exception class. All other psutil exceptions inherit - from this one. - """ - __module__ = 'psutil' - - def __init__(self, msg=""): - Exception.__init__(self, msg) - self.msg = msg - - def __repr__(self): - ret = "psutil.%s %s" % (self.__class__.__name__, self.msg) - return ret.strip() - - __str__ = __repr__ - - -class NoSuchProcess(Error): - """Exception raised when a process with a certain PID doesn't - or no longer exists. - """ - __module__ = 'psutil' - - def __init__(self, pid, name=None, msg=None): - Error.__init__(self, msg) - self.pid = pid - self.name = name - self.msg = msg - if msg is None: - if name: - details = "(pid=%s, name=%s)" % (self.pid, repr(self.name)) - else: - details = "(pid=%s)" % self.pid - self.msg = "process no longer exists " + details - - def __path__(self): - return 'xxx' - - -class ZombieProcess(NoSuchProcess): - """Exception raised when querying a zombie process. This is - raised on macOS, BSD and Solaris only, and not always: depending - on the query the OS may be able to succeed anyway. - On Linux all zombie processes are querable (hence this is never - raised). Windows doesn't have zombie processes. - """ - __module__ = 'psutil' - - def __init__(self, pid, name=None, ppid=None, msg=None): - NoSuchProcess.__init__(self, msg) - self.pid = pid - self.ppid = ppid - self.name = name - self.msg = msg - if msg is None: - args = ["pid=%s" % pid] - if name: - args.append("name=%s" % repr(self.name)) - if ppid: - args.append("ppid=%s" % self.ppid) - details = "(%s)" % ", ".join(args) - self.msg = "process still exists but it's a zombie " + details - - -class AccessDenied(Error): - """Exception raised when permission to perform an action is denied.""" - __module__ = 'psutil' - - def __init__(self, pid=None, name=None, msg=None): - Error.__init__(self, msg) - self.pid = pid - self.name = name - self.msg = msg - if msg is None: - if (pid is not None) and (name is not None): - self.msg = "(pid=%s, name=%s)" % (pid, repr(name)) - elif (pid is not None): - self.msg = "(pid=%s)" % self.pid - else: - self.msg = "" - - -class TimeoutExpired(Error): - """Raised on Process.wait(timeout) if timeout expires and process - is still alive. - """ - __module__ = 'psutil' - - def __init__(self, seconds, pid=None, name=None): - Error.__init__(self, "timeout after %s seconds" % seconds) - self.seconds = seconds - self.pid = pid - self.name = name - if (pid is not None) and (name is not None): - self.msg += " (pid=%s, name=%s)" % (pid, repr(name)) - elif (pid is not None): - self.msg += " (pid=%s)" % self.pid - - -# =================================================================== -# --- utils -# =================================================================== - - -def usage_percent(used, total, round_=None): - """Calculate percentage usage of 'used' against 'total'.""" - try: - ret = (float(used) / total) * 100 - except ZeroDivisionError: - return 0.0 - else: - if round_ is not None: - ret = round(ret, round_) - return ret - - -def memoize(fun): - """A simple memoize decorator for functions supporting (hashable) - positional arguments. - It also provides a cache_clear() function for clearing the cache: - - >>> @memoize - ... def foo() - ... return 1 - ... - >>> foo() - 1 - >>> foo.cache_clear() - >>> - """ - @functools.wraps(fun) - def wrapper(*args, **kwargs): - key = (args, frozenset(sorted(kwargs.items()))) - try: - return cache[key] - except KeyError: - ret = cache[key] = fun(*args, **kwargs) - return ret - - def cache_clear(): - """Clear cache.""" - cache.clear() - - cache = {} - wrapper.cache_clear = cache_clear - return wrapper - - -def memoize_when_activated(fun): - """A memoize decorator which is disabled by default. It can be - activated and deactivated on request. - For efficiency reasons it can be used only against class methods - accepting no arguments. - - >>> class Foo: - ... @memoize - ... def foo() - ... print(1) - ... - >>> f = Foo() - >>> # deactivated (default) - >>> foo() - 1 - >>> foo() - 1 - >>> - >>> # activated - >>> foo.cache_activate(self) - >>> foo() - 1 - >>> foo() - >>> foo() - >>> - """ - @functools.wraps(fun) - def wrapper(self): - try: - # case 1: we previously entered oneshot() ctx - ret = self._cache[fun] - except AttributeError: - # case 2: we never entered oneshot() ctx - return fun(self) - except KeyError: - # case 3: we entered oneshot() ctx but there's no cache - # for this entry yet - ret = self._cache[fun] = fun(self) - return ret - - def cache_activate(proc): - """Activate cache. Expects a Process instance. Cache will be - stored as a "_cache" instance attribute.""" - proc._cache = {} - - def cache_deactivate(proc): - """Deactivate and clear cache.""" - try: - del proc._cache - except AttributeError: - pass - - wrapper.cache_activate = cache_activate - wrapper.cache_deactivate = cache_deactivate - return wrapper - - -def isfile_strict(path): - """Same as os.path.isfile() but does not swallow EACCES / EPERM - exceptions, see: - http://mail.python.org/pipermail/python-dev/2012-June/120787.html - """ - try: - st = os.stat(path) - except OSError as err: - if err.errno in (errno.EPERM, errno.EACCES): - raise - return False - else: - return stat.S_ISREG(st.st_mode) - - -def path_exists_strict(path): - """Same as os.path.exists() but does not swallow EACCES / EPERM - exceptions, see: - http://mail.python.org/pipermail/python-dev/2012-June/120787.html - """ - try: - os.stat(path) - except OSError as err: - if err.errno in (errno.EPERM, errno.EACCES): - raise - return False - else: - return True - - -@memoize -def supports_ipv6(): - """Return True if IPv6 is supported on this platform.""" - if not socket.has_ipv6 or AF_INET6 is None: - return False - try: - sock = socket.socket(AF_INET6, socket.SOCK_STREAM) - with contextlib.closing(sock): - sock.bind(("::1", 0)) - return True - except socket.error: - return False - - -def parse_environ_block(data): - """Parse a C environ block of environment variables into a dictionary.""" - # The block is usually raw data from the target process. It might contain - # trailing garbage and lines that do not look like assignments. - ret = {} - pos = 0 - - # localize global variable to speed up access. - WINDOWS_ = WINDOWS - while True: - next_pos = data.find("\0", pos) - # nul byte at the beginning or double nul byte means finish - if next_pos <= pos: - break - # there might not be an equals sign - equal_pos = data.find("=", pos, next_pos) - if equal_pos > pos: - key = data[pos:equal_pos] - value = data[equal_pos + 1:next_pos] - # Windows expects environment variables to be uppercase only - if WINDOWS_: - key = key.upper() - ret[key] = value - pos = next_pos + 1 - - return ret - - -def sockfam_to_enum(num): - """Convert a numeric socket family value to an IntEnum member. - If it's not a known member, return the numeric value itself. - """ - if enum is None: - return num - else: # pragma: no cover - try: - return socket.AddressFamily(num) - except ValueError: - return num - - -def socktype_to_enum(num): - """Convert a numeric socket type value to an IntEnum member. - If it's not a known member, return the numeric value itself. - """ - if enum is None: - return num - else: # pragma: no cover - try: - return socket.SocketKind(num) - except ValueError: - return num - - -def conn_to_ntuple(fd, fam, type_, laddr, raddr, status, status_map, pid=None): - """Convert a raw connection tuple to a proper ntuple.""" - if fam in (socket.AF_INET, AF_INET6): - if laddr: - laddr = addr(*laddr) - if raddr: - raddr = addr(*raddr) - if type_ == socket.SOCK_STREAM and fam in (AF_INET, AF_INET6): - status = status_map.get(status, CONN_NONE) - else: - status = CONN_NONE # ignore whatever C returned to us - fam = sockfam_to_enum(fam) - type_ = socktype_to_enum(type_) - if pid is None: - return pconn(fd, fam, type_, laddr, raddr, status) - else: - return sconn(fd, fam, type_, laddr, raddr, status, pid) - - -def deprecated_method(replacement): - """A decorator which can be used to mark a method as deprecated - 'replcement' is the method name which will be called instead. - """ - def outer(fun): - msg = "%s() is deprecated and will be removed; use %s() instead" % ( - fun.__name__, replacement) - if fun.__doc__ is None: - fun.__doc__ = msg - - @functools.wraps(fun) - def inner(self, *args, **kwargs): - warnings.warn(msg, category=DeprecationWarning, stacklevel=2) - return getattr(self, replacement)(*args, **kwargs) - return inner - return outer - - -class _WrapNumbers: - """Watches numbers so that they don't overflow and wrap - (reset to zero). - """ - - def __init__(self): - self.lock = threading.Lock() - self.cache = {} - self.reminders = {} - self.reminder_keys = {} - - def _add_dict(self, input_dict, name): - assert name not in self.cache - assert name not in self.reminders - assert name not in self.reminder_keys - self.cache[name] = input_dict - self.reminders[name] = defaultdict(int) - self.reminder_keys[name] = defaultdict(set) - - def _remove_dead_reminders(self, input_dict, name): - """In case the number of keys changed between calls (e.g. a - disk disappears) this removes the entry from self.reminders. - """ - old_dict = self.cache[name] - gone_keys = set(old_dict.keys()) - set(input_dict.keys()) - for gone_key in gone_keys: - for remkey in self.reminder_keys[name][gone_key]: - del self.reminders[name][remkey] - del self.reminder_keys[name][gone_key] - - def run(self, input_dict, name): - """Cache dict and sum numbers which overflow and wrap. - Return an updated copy of `input_dict` - """ - if name not in self.cache: - # This was the first call. - self._add_dict(input_dict, name) - return input_dict - - self._remove_dead_reminders(input_dict, name) - - old_dict = self.cache[name] - new_dict = {} - for key in input_dict.keys(): - input_tuple = input_dict[key] - try: - old_tuple = old_dict[key] - except KeyError: - # The input dict has a new key (e.g. a new disk or NIC) - # which didn't exist in the previous call. - new_dict[key] = input_tuple - continue - - bits = [] - for i in range(len(input_tuple)): - input_value = input_tuple[i] - old_value = old_tuple[i] - remkey = (key, i) - if input_value < old_value: - # it wrapped! - self.reminders[name][remkey] += old_value - self.reminder_keys[name][key].add(remkey) - bits.append(input_value + self.reminders[name][remkey]) - - new_dict[key] = tuple(bits) - - self.cache[name] = input_dict - return new_dict - - def cache_clear(self, name=None): - """Clear the internal cache, optionally only for function 'name'.""" - with self.lock: - if name is None: - self.cache.clear() - self.reminders.clear() - self.reminder_keys.clear() - else: - self.cache.pop(name, None) - self.reminders.pop(name, None) - self.reminder_keys.pop(name, None) - - def cache_info(self): - """Return internal cache dicts as a tuple of 3 elements.""" - with self.lock: - return (self.cache, self.reminders, self.reminder_keys) - - -def wrap_numbers(input_dict, name): - """Given an `input_dict` and a function `name`, adjust the numbers - which "wrap" (restart from zero) across different calls by adding - "old value" to "new value" and return an updated dict. - """ - with _wn.lock: - return _wn.run(input_dict, name) - - -_wn = _WrapNumbers() -wrap_numbers.cache_clear = _wn.cache_clear -wrap_numbers.cache_info = _wn.cache_info - - -def open_binary(fname, **kwargs): - return open(fname, "rb", **kwargs) - - -def open_text(fname, **kwargs): - """On Python 3 opens a file in text mode by using fs encoding and - a proper en/decoding errors handler. - On Python 2 this is just an alias for open(name, 'rt'). - """ - if PY3: - # See: - # https://github.com/giampaolo/psutil/issues/675 - # https://github.com/giampaolo/psutil/pull/733 - kwargs.setdefault('encoding', ENCODING) - kwargs.setdefault('errors', ENCODING_ERRS) - return open(fname, "rt", **kwargs) - - -def bytes2human(n, format="%(value).1f%(symbol)s"): - """Used by various scripts. See: - http://goo.gl/zeJZl - - >>> bytes2human(10000) - '9.8K' - >>> bytes2human(100001221) - '95.4M' - """ - symbols = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') - prefix = {} - for i, s in enumerate(symbols[1:]): - prefix[s] = 1 << (i + 1) * 10 - for symbol in reversed(symbols[1:]): - if n >= prefix[symbol]: - value = float(n) / prefix[symbol] - return format % locals() - return format % dict(symbol=symbols[0], value=n) - - -def get_procfs_path(): - """Return updated psutil.PROCFS_PATH constant.""" - return sys.modules['psutil'].PROCFS_PATH - - -if PY3: - def decode(s): - return s.decode(encoding=ENCODING, errors=ENCODING_ERRS) -else: - def decode(s): - return s - - -# ===================================================================== -# --- shell utils -# ===================================================================== - - -@memoize -def term_supports_colors(file=sys.stdout): - if os.name == 'nt': - return True - try: - import curses - assert file.isatty() - curses.setupterm() - assert curses.tigetnum("colors") > 0 - except Exception: - return False - else: - return True - - -def hilite(s, color="green", bold=False): - """Return an highlighted version of 'string'.""" - if not term_supports_colors(): - return s - attr = [] - colors = dict(green='32', red='91', brown='33') - colors[None] = '29' - try: - color = colors[color] - except KeyError: - raise ValueError("invalid color %r; choose between %s" % ( - list(colors.keys()))) - attr.append(color) - if bold: - attr.append('1') - return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), s) - - -def print_color(s, color="green", bold=False, file=sys.stdout): - """Print a colorized version of string.""" - if not term_supports_colors(): - print(s, file=file) - elif POSIX: - print(hilite(s, color, bold), file=file) - else: - import ctypes - - DEFAULT_COLOR = 7 - GetStdHandle = ctypes.windll.Kernel32.GetStdHandle - SetConsoleTextAttribute = \ - ctypes.windll.Kernel32.SetConsoleTextAttribute - - colors = dict(green=2, red=4, brown=6) - colors[None] = DEFAULT_COLOR - try: - color = colors[color] - except KeyError: - raise ValueError("invalid color %r; choose between %r" % ( - color, list(colors.keys()))) - if bold and color <= 7: - color += 8 - - handle_id = -12 if file is sys.stderr else -11 - GetStdHandle.restype = ctypes.c_ulong - handle = GetStdHandle(handle_id) - SetConsoleTextAttribute(handle, color) - try: - print(s, file=file) - finally: - SetConsoleTextAttribute(handle, DEFAULT_COLOR) - - -if bool(os.getenv('PSUTIL_DEBUG', 0)): - import inspect - - def debug(msg): - """If PSUTIL_DEBUG env var is set, print a debug message to stderr.""" - fname, lineno, func_name, lines, index = inspect.getframeinfo( - inspect.currentframe().f_back) - print("psutil-debug [%s:%s]> %s" % (fname, lineno, msg), - file=sys.stderr) -else: - def debug(msg): - pass diff --git a/third_party/python/psutil/psutil/_compat.py b/third_party/python/psutil/psutil/_compat.py deleted file mode 100644 index a9371382bd6e..000000000000 --- a/third_party/python/psutil/psutil/_compat.py +++ /dev/null @@ -1,345 +0,0 @@ -# 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. - -"""Module which provides compatibility with older Python versions.""" - -import collections -import errno -import functools -import os -import sys - -__all__ = ["PY3", "long", "xrange", "unicode", "basestring", "u", "b", - "lru_cache", "which", "get_terminal_size", - "FileNotFoundError", "PermissionError", "ProcessLookupError", - "InterruptedError", "ChildProcessError", "FileExistsError"] - -PY3 = sys.version_info[0] == 3 - -if PY3: - long = int - xrange = range - unicode = str - basestring = str - - def u(s): - return s - - def b(s): - return s.encode("latin-1") -else: - long = long - xrange = xrange - unicode = unicode - basestring = basestring - - def u(s): - return unicode(s, "unicode_escape") - - def b(s): - return s - - -# --- exceptions - - -if PY3: - FileNotFoundError = FileNotFoundError # NOQA - PermissionError = PermissionError # NOQA - ProcessLookupError = ProcessLookupError # NOQA - InterruptedError = InterruptedError # NOQA - ChildProcessError = ChildProcessError # NOQA - FileExistsError = FileExistsError # NOQA -else: - # https://github.com/PythonCharmers/python-future/blob/exceptions/ - # src/future/types/exceptions/pep3151.py - import platform - - _singleton = object() - - def instance_checking_exception(base_exception=Exception): - def wrapped(instance_checker): - class TemporaryClass(base_exception): - - def __init__(self, *args, **kwargs): - if len(args) == 1 and isinstance(args[0], TemporaryClass): - unwrap_me = args[0] - for attr in dir(unwrap_me): - if not attr.startswith('__'): - setattr(self, attr, getattr(unwrap_me, attr)) - else: - super(TemporaryClass, self).__init__(*args, **kwargs) - - class __metaclass__(type): - def __instancecheck__(cls, inst): - return instance_checker(inst) - - def __subclasscheck__(cls, classinfo): - value = sys.exc_info()[1] - return isinstance(value, cls) - - TemporaryClass.__name__ = instance_checker.__name__ - TemporaryClass.__doc__ = instance_checker.__doc__ - return TemporaryClass - - return wrapped - - @instance_checking_exception(EnvironmentError) - def FileNotFoundError(inst): - return getattr(inst, 'errno', _singleton) == errno.ENOENT - - @instance_checking_exception(EnvironmentError) - def ProcessLookupError(inst): - return getattr(inst, 'errno', _singleton) == errno.ESRCH - - @instance_checking_exception(EnvironmentError) - def PermissionError(inst): - return getattr(inst, 'errno', _singleton) in ( - errno.EACCES, errno.EPERM) - - @instance_checking_exception(EnvironmentError) - def InterruptedError(inst): - return getattr(inst, 'errno', _singleton) == errno.EINTR - - @instance_checking_exception(EnvironmentError) - def ChildProcessError(inst): - return getattr(inst, 'errno', _singleton) == errno.ECHILD - - @instance_checking_exception(EnvironmentError) - def FileExistsError(inst): - return getattr(inst, 'errno', _singleton) == errno.EEXIST - - if platform.python_implementation() != "CPython": - try: - raise OSError(errno.EEXIST, "perm") - except FileExistsError: - pass - except OSError: - raise RuntimeError( - "broken / incompatible Python implementation, see: " - "https://github.com/giampaolo/psutil/issues/1659") - - -# --- stdlib additions - - -# py 3.2 functools.lru_cache -# Taken from: http://code.activestate.com/recipes/578078 -# Credit: Raymond Hettinger -try: - from functools import lru_cache -except ImportError: - try: - from threading import RLock - except ImportError: - from dummy_threading import RLock - - _CacheInfo = collections.namedtuple( - "CacheInfo", ["hits", "misses", "maxsize", "currsize"]) - - class _HashedSeq(list): - __slots__ = 'hashvalue' - - def __init__(self, tup, hash=hash): - self[:] = tup - self.hashvalue = hash(tup) - - def __hash__(self): - return self.hashvalue - - def _make_key(args, kwds, typed, - kwd_mark=(object(), ), - fasttypes=set((int, str, frozenset, type(None))), - sorted=sorted, tuple=tuple, type=type, len=len): - key = args - if kwds: - sorted_items = sorted(kwds.items()) - key += kwd_mark - for item in sorted_items: - key += item - if typed: - key += tuple(type(v) for v in args) - if kwds: - key += tuple(type(v) for k, v in sorted_items) - elif len(key) == 1 and type(key[0]) in fasttypes: - return key[0] - return _HashedSeq(key) - - def lru_cache(maxsize=100, typed=False): - """Least-recently-used cache decorator, see: - http://docs.python.org/3/library/functools.html#functools.lru_cache - """ - def decorating_function(user_function): - cache = dict() - stats = [0, 0] - HITS, MISSES = 0, 1 - make_key = _make_key - cache_get = cache.get - _len = len - lock = RLock() - root = [] - root[:] = [root, root, None, None] - nonlocal_root = [root] - PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 - if maxsize == 0: - def wrapper(*args, **kwds): - result = user_function(*args, **kwds) - stats[MISSES] += 1 - return result - elif maxsize is None: - def wrapper(*args, **kwds): - key = make_key(args, kwds, typed) - result = cache_get(key, root) - if result is not root: - stats[HITS] += 1 - return result - result = user_function(*args, **kwds) - cache[key] = result - stats[MISSES] += 1 - return result - else: - def wrapper(*args, **kwds): - if kwds or typed: - key = make_key(args, kwds, typed) - else: - key = args - lock.acquire() - try: - link = cache_get(key) - if link is not None: - root, = nonlocal_root - link_prev, link_next, key, result = link - link_prev[NEXT] = link_next - link_next[PREV] = link_prev - last = root[PREV] - last[NEXT] = root[PREV] = link - link[PREV] = last - link[NEXT] = root - stats[HITS] += 1 - return result - finally: - lock.release() - result = user_function(*args, **kwds) - lock.acquire() - try: - root, = nonlocal_root - if key in cache: - pass - elif _len(cache) >= maxsize: - oldroot = root - oldroot[KEY] = key - oldroot[RESULT] = result - root = nonlocal_root[0] = oldroot[NEXT] - oldkey = root[KEY] - root[KEY] = root[RESULT] = None - del cache[oldkey] - cache[key] = oldroot - else: - last = root[PREV] - link = [last, root, key, result] - last[NEXT] = root[PREV] = cache[key] = link - stats[MISSES] += 1 - finally: - lock.release() - return result - - def cache_info(): - """Report cache statistics""" - lock.acquire() - try: - return _CacheInfo(stats[HITS], stats[MISSES], maxsize, - len(cache)) - finally: - lock.release() - - def cache_clear(): - """Clear the cache and cache statistics""" - lock.acquire() - try: - cache.clear() - root = nonlocal_root[0] - root[:] = [root, root, None, None] - stats[:] = [0, 0] - finally: - lock.release() - - wrapper.__wrapped__ = user_function - wrapper.cache_info = cache_info - wrapper.cache_clear = cache_clear - return functools.update_wrapper(wrapper, user_function) - - return decorating_function - - -# python 3.3 -try: - from shutil import which -except ImportError: - def which(cmd, mode=os.F_OK | os.X_OK, path=None): - """Given a command, mode, and a PATH string, return the path which - conforms to the given mode on the PATH, or None if there is no such - file. - - `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result - of os.environ.get("PATH"), or can be overridden with a custom search - path. - """ - def _access_check(fn, mode): - return (os.path.exists(fn) and os.access(fn, mode) and - not os.path.isdir(fn)) - - if os.path.dirname(cmd): - if _access_check(cmd, mode): - return cmd - return None - - if path is None: - path = os.environ.get("PATH", os.defpath) - if not path: - return None - path = path.split(os.pathsep) - - if sys.platform == "win32": - if os.curdir not in path: - path.insert(0, os.curdir) - - pathext = os.environ.get("PATHEXT", "").split(os.pathsep) - if any(cmd.lower().endswith(ext.lower()) for ext in pathext): - files = [cmd] - else: - files = [cmd + ext for ext in pathext] - else: - files = [cmd] - - seen = set() - for dir in path: - normdir = os.path.normcase(dir) - if normdir not in seen: - seen.add(normdir) - for thefile in files: - name = os.path.join(dir, thefile) - if _access_check(name, mode): - return name - return None - - -# python 3.3 -try: - from shutil import get_terminal_size -except ImportError: - def get_terminal_size(fallback=(80, 24)): - try: - import fcntl - import termios - import struct - except ImportError: - return fallback - else: - try: - # This should work on Linux. - res = struct.unpack( - 'hh', fcntl.ioctl(1, termios.TIOCGWINSZ, '1234')) - return (res[1], res[0]) - except Exception: - return fallback diff --git a/third_party/python/psutil/psutil/_psaix.py b/third_party/python/psutil/psutil/_psaix.py deleted file mode 100644 index 994366aaa1b9..000000000000 --- a/third_party/python/psutil/psutil/_psaix.py +++ /dev/null @@ -1,550 +0,0 @@ -# Copyright (c) 2009, Giampaolo Rodola' -# Copyright (c) 2017, Arnon Yaari -# All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""AIX platform implementation.""" - -import functools -import glob -import os -import re -import subprocess -import sys -from collections import namedtuple - -from . import _common -from . import _psposix -from . import _psutil_aix as cext -from . import _psutil_posix as cext_posix -from ._common import AccessDenied -from ._common import conn_to_ntuple -from ._common import get_procfs_path -from ._common import memoize_when_activated -from ._common import NIC_DUPLEX_FULL -from ._common import NIC_DUPLEX_HALF -from ._common import NIC_DUPLEX_UNKNOWN -from ._common import NoSuchProcess -from ._common import usage_percent -from ._common import ZombieProcess -from ._compat import FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 - - -__extra__all__ = ["PROCFS_PATH"] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -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 - -PROC_STATUSES = { - cext.SIDL: _common.STATUS_IDLE, - cext.SZOMB: _common.STATUS_ZOMBIE, - cext.SACTIVE: _common.STATUS_RUNNING, - cext.SSWAP: _common.STATUS_RUNNING, # TODO what status is this? - cext.SSTOP: _common.STATUS_STOPPED, -} - -TCP_STATUSES = { - cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, - cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, - cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV, - cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, - cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, - cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.TCPS_CLOSED: _common.CONN_CLOSE, - cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, - cext.TCPS_LISTEN: _common.CONN_LISTEN, - cext.TCPS_CLOSING: _common.CONN_CLOSING, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -proc_info_map = dict( - ppid=0, - rss=1, - vms=2, - create_time=3, - nice=4, - num_threads=5, - status=6, - ttynr=7) - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.Process.memory_info() -pmem = namedtuple('pmem', ['rss', 'vms']) -# psutil.Process.memory_full_info() -pfullmem = pmem -# psutil.Process.cpu_times() -scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait']) -# psutil.virtual_memory() -svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - total, avail, free, pinned, inuse = cext.virtual_mem() - percent = usage_percent((total - avail), total, round_=1) - return svmem(total, avail, percent, inuse, free) - - -def swap_memory(): - """Swap system memory as a (total, used, free, sin, sout) tuple.""" - total, free, sin, sout = cext.swap_mem() - used = total - free - percent = usage_percent(used, total, round_=1) - return _common.sswap(total, used, free, percent, sin, sout) - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return system-wide CPU times as a named tuple""" - ret = cext.per_cpu_times() - return scputimes(*[sum(x) for x in zip(*ret)]) - - -def per_cpu_times(): - """Return system per-CPU times as a list of named tuples""" - ret = cext.per_cpu_times() - return [scputimes(*x) for x in ret] - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - try: - return os.sysconf("SC_NPROCESSORS_ONLN") - except ValueError: - # mimic os.cpu_count() behavior - return None - - -def cpu_count_physical(): - cmd = "lsdev -Cc processor" - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout, stderr = [x.decode(sys.stdout.encoding) - for x in (stdout, stderr)] - if p.returncode != 0: - raise RuntimeError("%r command error\n%s" % (cmd, stderr)) - processors = stdout.strip().splitlines() - return len(processors) or None - - -def cpu_stats(): - """Return various CPU stats as a named tuple.""" - ctx_switches, interrupts, soft_interrupts, syscalls = cext.cpu_stats() - return _common.scpustats( - ctx_switches, interrupts, soft_interrupts, syscalls) - - -# ===================================================================== -# --- disks -# ===================================================================== - - -disk_io_counters = cext.disk_io_counters -disk_usage = _psposix.disk_usage - - -def disk_partitions(all=False): - """Return system disk partitions.""" - # TODO - the filtering logic should be better checked so that - # it tries to reflect 'df' as much as possible - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - # Differently from, say, Linux, we don't have a list of - # common fs types so the best we can do, AFAIK, is to - # filter by filesystem having a total size > 0. - if not disk_usage(mountpoint).total: - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -# ===================================================================== -# --- network -# ===================================================================== - - -net_if_addrs = cext_posix.net_if_addrs - -if HAS_NET_IO_COUNTERS: - net_io_counters = cext.net_io_counters - - -def net_connections(kind, _pid=-1): - """Return socket connections. If pid == -1 return system-wide - connections (as opposed to connections opened by one process only). - """ - cmap = _common.conn_tmap - if kind not in cmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in cmap]))) - families, types = _common.conn_tmap[kind] - rawlist = cext.net_connections(_pid) - ret = [] - for item in rawlist: - fd, fam, type_, laddr, raddr, status, pid = item - if fam not in families: - continue - if type_ not in types: - continue - nt = conn_to_ntuple(fd, fam, type_, laddr, raddr, status, - TCP_STATUSES, pid=pid if _pid == -1 else None) - ret.append(nt) - return ret - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - duplex_map = {"Full": NIC_DUPLEX_FULL, - "Half": NIC_DUPLEX_HALF} - names = set([x[0] for x in net_if_addrs()]) - ret = {} - for name in names: - isup, mtu = cext.net_if_stats(name) - - # try to get speed and duplex - # TODO: rewrite this in C (entstat forks, so use truss -f to follow. - # looks like it is using an undocumented ioctl?) - duplex = "" - speed = 0 - p = subprocess.Popen(["/usr/bin/entstat", "-d", name], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout, stderr = [x.decode(sys.stdout.encoding) - for x in (stdout, stderr)] - if p.returncode == 0: - re_result = re.search( - r"Running: (\d+) Mbps.*?(\w+) Duplex", stdout) - if re_result is not None: - speed = int(re_result.group(1)) - duplex = re_result.group(2) - - duplex = duplex_map.get(duplex, NIC_DUPLEX_UNKNOWN) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - localhost = (':0.0', ':0') - for item in rawlist: - user, tty, hostname, tstamp, user_process, pid = item - # note: the underlying C function includes entries about - # system boot, run level and others. We might want - # to use them in the future. - if not user_process: - continue - if hostname in localhost: - hostname = 'localhost' - nt = _common.suser(user, tty, hostname, tstamp, pid) - retlist.append(nt) - return retlist - - -# ===================================================================== -# --- processes -# ===================================================================== - - -def pids(): - """Returns a list of PIDs currently running on the system.""" - return [int(x) for x in os.listdir(get_procfs_path()) if x.isdigit()] - - -def pid_exists(pid): - """Check for the existence of a unix pid.""" - return os.path.exists(os.path.join(get_procfs_path(), str(pid), "psinfo")) - - -def wrap_exceptions(fun): - """Call callable into a try/except clause and translate ENOENT, - EACCES and EPERM in NoSuchProcess or AccessDenied exceptions. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except (FileNotFoundError, ProcessLookupError): - # ENOENT (no such file or directory) gets raised on open(). - # ESRCH (no such process) can get raised on read() if - # process is gone in meantime. - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - self._procfs_path = get_procfs_path() - - def oneshot_enter(self): - self._proc_basic_info.cache_activate(self) - self._proc_cred.cache_activate(self) - - def oneshot_exit(self): - self._proc_basic_info.cache_deactivate(self) - self._proc_cred.cache_deactivate(self) - - @wrap_exceptions - @memoize_when_activated - def _proc_basic_info(self): - return cext.proc_basic_info(self.pid, self._procfs_path) - - @wrap_exceptions - @memoize_when_activated - def _proc_cred(self): - return cext.proc_cred(self.pid, self._procfs_path) - - @wrap_exceptions - def name(self): - if self.pid == 0: - return "swapper" - # note: max 16 characters - return cext.proc_name(self.pid, self._procfs_path).rstrip("\x00") - - @wrap_exceptions - def exe(self): - # there is no way to get executable path in AIX other than to guess, - # and guessing is more complex than what's in the wrapping class - cmdline = self.cmdline() - if not cmdline: - return '' - exe = cmdline[0] - if os.path.sep in exe: - # relative or absolute path - if not os.path.isabs(exe): - # if cwd has changed, we're out of luck - this may be wrong! - exe = os.path.abspath(os.path.join(self.cwd(), exe)) - if (os.path.isabs(exe) and - os.path.isfile(exe) and - os.access(exe, os.X_OK)): - return exe - # not found, move to search in PATH using basename only - exe = os.path.basename(exe) - # search for exe name PATH - for path in os.environ["PATH"].split(":"): - possible_exe = os.path.abspath(os.path.join(path, exe)) - if (os.path.isfile(possible_exe) and - os.access(possible_exe, os.X_OK)): - return possible_exe - return '' - - @wrap_exceptions - def cmdline(self): - return cext.proc_args(self.pid) - - @wrap_exceptions - def environ(self): - return cext.proc_environ(self.pid) - - @wrap_exceptions - def create_time(self): - return self._proc_basic_info()[proc_info_map['create_time']] - - @wrap_exceptions - def num_threads(self): - return self._proc_basic_info()[proc_info_map['num_threads']] - - if HAS_THREADS: - @wrap_exceptions - def threads(self): - rawlist = cext.proc_threads(self.pid) - retlist = [] - for thread_id, utime, stime in rawlist: - ntuple = _common.pthread(thread_id, utime, stime) - retlist.append(ntuple) - # The underlying C implementation retrieves all OS threads - # and filters them by PID. At this point we can't tell whether - # an empty list means there were no connections for process or - # process is no longer active so we force NSP in case the PID - # is no longer there. - if not retlist: - # will raise NSP if process is gone - os.stat('%s/%s' % (self._procfs_path, self.pid)) - return retlist - - @wrap_exceptions - def connections(self, kind='inet'): - ret = net_connections(kind, _pid=self.pid) - # The underlying C implementation retrieves all OS connections - # and filters them by PID. At this point we can't tell whether - # an empty list means there were no connections for process or - # process is no longer active so we force NSP in case the PID - # is no longer there. - if not ret: - # will raise NSP if process is gone - os.stat('%s/%s' % (self._procfs_path, self.pid)) - return ret - - @wrap_exceptions - def nice_get(self): - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def ppid(self): - self._ppid = self._proc_basic_info()[proc_info_map['ppid']] - return self._ppid - - @wrap_exceptions - def uids(self): - real, effective, saved, _, _, _ = self._proc_cred() - return _common.puids(real, effective, saved) - - @wrap_exceptions - def gids(self): - _, _, _, real, effective, saved = self._proc_cred() - return _common.puids(real, effective, saved) - - @wrap_exceptions - def cpu_times(self): - cpu_times = cext.proc_cpu_times(self.pid, self._procfs_path) - return _common.pcputimes(*cpu_times) - - @wrap_exceptions - def terminal(self): - ttydev = self._proc_basic_info()[proc_info_map['ttynr']] - # convert from 64-bit dev_t to 32-bit dev_t and then map the device - ttydev = (((ttydev & 0x0000FFFF00000000) >> 16) | (ttydev & 0xFFFF)) - # try to match rdev of /dev/pts/* files ttydev - for dev in glob.glob("/dev/**/*"): - if os.stat(dev).st_rdev == ttydev: - return dev - return None - - @wrap_exceptions - def cwd(self): - procfs_path = self._procfs_path - try: - result = os.readlink("%s/%s/cwd" % (procfs_path, self.pid)) - return result.rstrip('/') - except FileNotFoundError: - os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD - return None - - @wrap_exceptions - def memory_info(self): - ret = self._proc_basic_info() - rss = ret[proc_info_map['rss']] * 1024 - vms = ret[proc_info_map['vms']] * 1024 - return pmem(rss, vms) - - memory_full_info = memory_info - - @wrap_exceptions - def status(self): - code = self._proc_basic_info()[proc_info_map['status']] - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(code, '?') - - def open_files(self): - # TODO rewrite without using procfiles (stat /proc/pid/fd/* and then - # find matching name of the inode) - p = subprocess.Popen(["/usr/bin/procfiles", "-n", str(self.pid)], - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout, stderr = [x.decode(sys.stdout.encoding) - for x in (stdout, stderr)] - if "no such process" in stderr.lower(): - raise NoSuchProcess(self.pid, self._name) - procfiles = re.findall(r"(\d+): S_IFREG.*\s*.*name:(.*)\n", stdout) - retlist = [] - for fd, path in procfiles: - path = path.strip() - if path.startswith("//"): - path = path[1:] - if path.lower() == "cannot be retrieved": - continue - retlist.append(_common.popenfile(path, int(fd))) - return retlist - - @wrap_exceptions - def num_fds(self): - if self.pid == 0: # no /proc/0/fd - return 0 - return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))) - - @wrap_exceptions - def num_ctx_switches(self): - return _common.pctxsw( - *cext.proc_num_ctx_switches(self.pid)) - - @wrap_exceptions - def wait(self, timeout=None): - return _psposix.wait_pid(self.pid, timeout, self._name) - - 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/third_party/python/psutil/psutil/_psbsd.py b/third_party/python/psutil/psutil/_psbsd.py deleted file mode 100644 index 49ad1e995cc1..000000000000 --- a/third_party/python/psutil/psutil/_psbsd.py +++ /dev/null @@ -1,903 +0,0 @@ -# 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. - -"""FreeBSD, OpenBSD and NetBSD platforms implementation.""" - -import contextlib -import errno -import functools -import os -import xml.etree.ElementTree as ET -from collections import namedtuple -from collections import defaultdict - -from . import _common -from . import _psposix -from . import _psutil_bsd as cext -from . import _psutil_posix as cext_posix -from ._common import AccessDenied -from ._common import conn_tmap -from ._common import conn_to_ntuple -from ._common import FREEBSD -from ._common import memoize -from ._common import memoize_when_activated -from ._common import NETBSD -from ._common import NoSuchProcess -from ._common import OPENBSD -from ._common import usage_percent -from ._common import ZombieProcess -from ._compat import FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import which - - -__extra__all__ = [] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -if FREEBSD: - PROC_STATUSES = { - cext.SIDL: _common.STATUS_IDLE, - cext.SRUN: _common.STATUS_RUNNING, - cext.SSLEEP: _common.STATUS_SLEEPING, - cext.SSTOP: _common.STATUS_STOPPED, - cext.SZOMB: _common.STATUS_ZOMBIE, - cext.SWAIT: _common.STATUS_WAITING, - cext.SLOCK: _common.STATUS_LOCKED, - } -elif OPENBSD or NETBSD: - PROC_STATUSES = { - cext.SIDL: _common.STATUS_IDLE, - cext.SSLEEP: _common.STATUS_SLEEPING, - cext.SSTOP: _common.STATUS_STOPPED, - # According to /usr/include/sys/proc.h SZOMB is unused. - # test_zombie_process() shows that SDEAD is the right - # equivalent. Also it appears there's no equivalent of - # psutil.STATUS_DEAD. SDEAD really means STATUS_ZOMBIE. - # cext.SZOMB: _common.STATUS_ZOMBIE, - cext.SDEAD: _common.STATUS_ZOMBIE, - cext.SZOMB: _common.STATUS_ZOMBIE, - # From http://www.eecs.harvard.edu/~margo/cs161/videos/proc.h.txt - # OpenBSD has SRUN and SONPROC: SRUN indicates that a process - # is runnable but *not* yet running, i.e. is on a run queue. - # SONPROC indicates that the process is actually executing on - # a CPU, i.e. it is no longer on a run queue. - # As such we'll map SRUN to STATUS_WAKING and SONPROC to - # STATUS_RUNNING - cext.SRUN: _common.STATUS_WAKING, - cext.SONPROC: _common.STATUS_RUNNING, - } -elif NETBSD: - PROC_STATUSES = { - cext.SIDL: _common.STATUS_IDLE, - cext.SACTIVE: _common.STATUS_RUNNING, - cext.SDYING: _common.STATUS_ZOMBIE, - cext.SSTOP: _common.STATUS_STOPPED, - cext.SZOMB: _common.STATUS_ZOMBIE, - cext.SDEAD: _common.STATUS_DEAD, - cext.SSUSPENDED: _common.STATUS_SUSPENDED, # unique to NetBSD - } - -TCP_STATUSES = { - cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, - cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, - cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV, - cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, - cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, - cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.TCPS_CLOSED: _common.CONN_CLOSE, - cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, - cext.TCPS_LISTEN: _common.CONN_LISTEN, - cext.TCPS_CLOSING: _common.CONN_CLOSING, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -if NETBSD: - PAGESIZE = os.sysconf("SC_PAGESIZE") -else: - PAGESIZE = os.sysconf("SC_PAGE_SIZE") -AF_LINK = cext_posix.AF_LINK - -HAS_PER_CPU_TIMES = hasattr(cext, "per_cpu_times") -HAS_PROC_NUM_THREADS = hasattr(cext, "proc_num_threads") -HAS_PROC_OPEN_FILES = hasattr(cext, 'proc_open_files') -HAS_PROC_NUM_FDS = hasattr(cext, 'proc_num_fds') - -kinfo_proc_map = dict( - ppid=0, - status=1, - real_uid=2, - effective_uid=3, - saved_uid=4, - real_gid=5, - effective_gid=6, - saved_gid=7, - ttynr=8, - create_time=9, - ctx_switches_vol=10, - ctx_switches_unvol=11, - read_io_count=12, - write_io_count=13, - user_time=14, - sys_time=15, - ch_user_time=16, - ch_sys_time=17, - rss=18, - vms=19, - memtext=20, - memdata=21, - memstack=22, - cpunum=23, - name=24, -) - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.virtual_memory() -svmem = namedtuple( - 'svmem', ['total', 'available', 'percent', 'used', 'free', - 'active', 'inactive', 'buffers', 'cached', 'shared', 'wired']) -# psutil.cpu_times() -scputimes = namedtuple( - 'scputimes', ['user', 'nice', 'system', 'idle', 'irq']) -# psutil.Process.memory_info() -pmem = namedtuple('pmem', ['rss', 'vms', 'text', 'data', 'stack']) -# psutil.Process.memory_full_info() -pfullmem = pmem -# psutil.Process.cpu_times() -pcputimes = namedtuple('pcputimes', - ['user', 'system', 'children_user', 'children_system']) -# psutil.Process.memory_maps(grouped=True) -pmmap_grouped = namedtuple( - 'pmmap_grouped', 'path rss, private, ref_count, shadow_count') -# psutil.Process.memory_maps(grouped=False) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr, perms path rss, private, ref_count, shadow_count') -# psutil.disk_io_counters() -if FREEBSD: - sdiskio = namedtuple('sdiskio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'read_time', 'write_time', - 'busy_time']) -else: - sdiskio = namedtuple('sdiskio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes']) - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - """System virtual memory as a namedtuple.""" - mem = cext.virtual_mem() - total, free, active, inactive, wired, cached, buffers, shared = mem - if NETBSD: - # On NetBSD buffers and shared mem is determined via /proc. - # The C ext set them to 0. - with open('/proc/meminfo', 'rb') as f: - for line in f: - if line.startswith(b'Buffers:'): - buffers = int(line.split()[1]) * 1024 - elif line.startswith(b'MemShared:'): - shared = int(line.split()[1]) * 1024 - avail = inactive + cached + free - used = active + wired + cached - percent = usage_percent((total - avail), total, round_=1) - return svmem(total, avail, percent, used, free, - active, inactive, buffers, cached, shared, wired) - - -def swap_memory(): - """System swap memory as (total, used, free, sin, sout) namedtuple.""" - total, used, free, sin, sout = cext.swap_mem() - percent = usage_percent(used, total, round_=1) - return _common.sswap(total, used, free, percent, sin, sout) - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return system per-CPU times as a namedtuple""" - user, nice, system, idle, irq = cext.cpu_times() - return scputimes(user, nice, system, idle, irq) - - -if HAS_PER_CPU_TIMES: - def per_cpu_times(): - """Return system CPU times as a namedtuple""" - ret = [] - for cpu_t in cext.per_cpu_times(): - user, nice, system, idle, irq = cpu_t - item = scputimes(user, nice, system, idle, irq) - ret.append(item) - return ret -else: - # XXX - # Ok, this is very dirty. - # On FreeBSD < 8 we cannot gather per-cpu information, see: - # https://github.com/giampaolo/psutil/issues/226 - # If num cpus > 1, on first call we return single cpu times to avoid a - # crash at psutil import time. - # Next calls will fail with NotImplementedError - def per_cpu_times(): - """Return system CPU times as a namedtuple""" - if cpu_count_logical() == 1: - return [cpu_times()] - if per_cpu_times.__called__: - raise NotImplementedError("supported only starting from FreeBSD 8") - per_cpu_times.__called__ = True - return [cpu_times()] - - per_cpu_times.__called__ = False - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - return cext.cpu_count_logical() - - -if OPENBSD or NETBSD: - def cpu_count_physical(): - # OpenBSD and NetBSD do not implement this. - return 1 if cpu_count_logical() == 1 else None -else: - def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" - # From the C module we'll get an XML string similar to this: - # http://manpages.ubuntu.com/manpages/precise/man4/smp.4freebsd.html - # We may get None in case "sysctl kern.sched.topology_spec" - # is not supported on this BSD version, in which case we'll mimic - # os.cpu_count() and return None. - ret = None - s = cext.cpu_count_phys() - if s is not None: - # get rid of padding chars appended at the end of the string - index = s.rfind("") - if index != -1: - s = s[:index + 9] - root = ET.fromstring(s) - try: - ret = len(root.findall('group/children/group/cpu')) or None - finally: - # needed otherwise it will memleak - root.clear() - if not ret: - # If logical CPUs are 1 it's obvious we'll have only 1 - # physical CPU. - if cpu_count_logical() == 1: - return 1 - return ret - - -def cpu_stats(): - """Return various CPU stats as a named tuple.""" - if FREEBSD: - # Note: the C ext is returning some metrics we are not exposing: - # traps. - ctxsw, intrs, soft_intrs, syscalls, traps = cext.cpu_stats() - elif NETBSD: - # XXX - # Note about intrs: the C extension returns 0. intrs - # can be determined via /proc/stat; it has the same value as - # soft_intrs thought so the kernel is faking it (?). - # - # Note about syscalls: the C extension always sets it to 0 (?). - # - # Note: the C ext is returning some metrics we are not exposing: - # traps, faults and forks. - ctxsw, intrs, soft_intrs, syscalls, traps, faults, forks = \ - cext.cpu_stats() - with open('/proc/stat', 'rb') as f: - for line in f: - if line.startswith(b'intr'): - intrs = int(line.split()[1]) - elif OPENBSD: - # Note: the C ext is returning some metrics we are not exposing: - # traps, faults and forks. - ctxsw, intrs, soft_intrs, syscalls, traps, faults, forks = \ - cext.cpu_stats() - return _common.scpustats(ctxsw, intrs, soft_intrs, syscalls) - - -# ===================================================================== -# --- disks -# ===================================================================== - - -def disk_partitions(all=False): - """Return mounted disk partitions as a list of namedtuples. - 'all' argument is ignored, see: - https://github.com/giampaolo/psutil/issues/906 - """ - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -disk_usage = _psposix.disk_usage -disk_io_counters = cext.disk_io_counters - - -# ===================================================================== -# --- network -# ===================================================================== - - -net_io_counters = cext.net_io_counters -net_if_addrs = cext_posix.net_if_addrs - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - names = net_io_counters().keys() - ret = {} - for name in names: - try: - mtu = cext_posix.net_if_mtu(name) - isup = cext_posix.net_if_flags(name) - duplex, speed = cext_posix.net_if_duplex_speed(name) - except OSError as err: - # https://github.com/giampaolo/psutil/issues/1279 - if err.errno != errno.ENODEV: - raise - else: - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -def net_connections(kind): - """System-wide network connections.""" - if OPENBSD: - ret = [] - for pid in pids(): - try: - cons = Process(pid).connections(kind) - except (NoSuchProcess, ZombieProcess): - continue - else: - for conn in cons: - conn = list(conn) - conn.append(pid) - ret.append(_common.sconn(*conn)) - return ret - - if kind not in _common.conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - families, types = conn_tmap[kind] - ret = set() - if NETBSD: - rawlist = cext.net_connections(-1) - else: - rawlist = cext.net_connections() - for item in rawlist: - fd, fam, type, laddr, raddr, status, pid = item - # TODO: apply filter at C level - if fam in families and type in types: - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES, pid) - ret.add(nt) - return list(ret) - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -if FREEBSD: - - def sensors_battery(): - """Return battery info.""" - try: - percent, minsleft, power_plugged = cext.sensors_battery() - except NotImplementedError: - # See: https://github.com/giampaolo/psutil/issues/1074 - return None - power_plugged = power_plugged == 1 - if power_plugged: - secsleft = _common.POWER_TIME_UNLIMITED - elif minsleft == -1: - secsleft = _common.POWER_TIME_UNKNOWN - else: - secsleft = minsleft * 60 - return _common.sbattery(percent, secsleft, power_plugged) - - def sensors_temperatures(): - "Return CPU cores temperatures if available, else an empty dict." - ret = defaultdict(list) - num_cpus = cpu_count_logical() - for cpu in range(num_cpus): - try: - current, high = cext.sensors_cpu_temperature(cpu) - if high <= 0: - high = None - name = "Core %s" % cpu - ret["coretemp"].append( - _common.shwtemp(name, current, high, high)) - except NotImplementedError: - pass - - return ret - - def cpu_freq(): - """Return frequency metrics for CPUs. As of Dec 2018 only - CPU 0 appears to be supported by FreeBSD and all other cores - match the frequency of CPU 0. - """ - ret = [] - num_cpus = cpu_count_logical() - for cpu in range(num_cpus): - try: - current, available_freq = cext.cpu_frequency(cpu) - except NotImplementedError: - continue - if available_freq: - try: - min_freq = int(available_freq.split(" ")[-1].split("/")[0]) - except(IndexError, ValueError): - min_freq = None - try: - max_freq = int(available_freq.split(" ")[0].split("/")[0]) - except(IndexError, ValueError): - max_freq = None - ret.append(_common.scpufreq(current, min_freq, max_freq)) - return ret - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, tty, hostname, tstamp, pid = item - if pid == -1: - assert OPENBSD - pid = None - if tty == '~': - continue # reboot or shutdown - nt = _common.suser(user, tty or None, hostname, tstamp, pid) - retlist.append(nt) - return retlist - - -# ===================================================================== -# --- processes -# ===================================================================== - - -@memoize -def _pid_0_exists(): - try: - Process(0).name() - except NoSuchProcess: - return False - except AccessDenied: - return True - else: - return True - - -def pids(): - """Returns a list of PIDs currently running on the system.""" - ret = cext.pids() - if OPENBSD and (0 not in ret) and _pid_0_exists(): - # On OpenBSD the kernel does not return PID 0 (neither does - # ps) but it's actually querable (Process(0) will succeed). - ret.insert(0, 0) - return ret - - -if OPENBSD or NETBSD: - def pid_exists(pid): - """Return True if pid exists.""" - exists = _psposix.pid_exists(pid) - if not exists: - # We do this because _psposix.pid_exists() lies in case of - # zombie processes. - return pid in pids() - else: - return True -else: - pid_exists = _psposix.pid_exists - - -def is_zombie(pid): - try: - st = cext.proc_oneshot_info(pid)[kinfo_proc_map['status']] - return st == cext.SZOMB - except Exception: - return False - - -def wrap_exceptions(fun): - """Decorator which translates bare OSError exceptions into - NoSuchProcess and AccessDenied. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except ProcessLookupError: - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except OSError: - if self.pid == 0: - if 0 in pids(): - raise AccessDenied(self.pid, self._name) - else: - raise - raise - return wrapper - - -@contextlib.contextmanager -def wrap_exceptions_procfs(inst): - """Same as above, for routines relying on reading /proc fs.""" - try: - yield - except (ProcessLookupError, FileNotFoundError): - # ENOENT (no such file or directory) gets raised on open(). - # ESRCH (no such process) can get raised on read() if - # process is gone in meantime. - if not pid_exists(inst.pid): - raise NoSuchProcess(inst.pid, inst._name) - else: - raise ZombieProcess(inst.pid, inst._name, inst._ppid) - except PermissionError: - raise AccessDenied(inst.pid, inst._name) - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - def _assert_alive(self): - """Raise NSP if the process disappeared on us.""" - # For those C function who do not raise NSP, possibly returning - # incorrect or incomplete result. - cext.proc_name(self.pid) - - @wrap_exceptions - @memoize_when_activated - def oneshot(self): - """Retrieves multiple process info in one shot as a raw tuple.""" - ret = cext.proc_oneshot_info(self.pid) - assert len(ret) == len(kinfo_proc_map) - return ret - - def oneshot_enter(self): - self.oneshot.cache_activate(self) - - def oneshot_exit(self): - self.oneshot.cache_deactivate(self) - - @wrap_exceptions - def name(self): - name = self.oneshot()[kinfo_proc_map['name']] - return name if name is not None else cext.proc_name(self.pid) - - @wrap_exceptions - def exe(self): - if FREEBSD: - if self.pid == 0: - return '' # else NSP - return cext.proc_exe(self.pid) - elif NETBSD: - if self.pid == 0: - # /proc/0 dir exists but /proc/0/exe doesn't - return "" - with wrap_exceptions_procfs(self): - return os.readlink("/proc/%s/exe" % self.pid) - else: - # OpenBSD: exe cannot be determined; references: - # https://chromium.googlesource.com/chromium/src/base/+/ - # master/base_paths_posix.cc - # We try our best guess by using which against the first - # cmdline arg (may return None). - cmdline = self.cmdline() - if cmdline: - return which(cmdline[0]) or "" - else: - return "" - - @wrap_exceptions - def cmdline(self): - if OPENBSD and self.pid == 0: - return [] # ...else it crashes - elif NETBSD: - # XXX - most of the times the underlying sysctl() call on Net - # and Open BSD returns a truncated string. - # Also /proc/pid/cmdline behaves the same so it looks - # like this is a kernel bug. - try: - return cext.proc_cmdline(self.pid) - except OSError as err: - if err.errno == errno.EINVAL: - if is_zombie(self.pid): - raise ZombieProcess(self.pid, self._name, self._ppid) - elif not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name, self._ppid) - else: - # XXX: this happens with unicode tests. It means the C - # routine is unable to decode invalid unicode chars. - return [] - else: - raise - else: - return cext.proc_cmdline(self.pid) - - @wrap_exceptions - def terminal(self): - tty_nr = self.oneshot()[kinfo_proc_map['ttynr']] - tmap = _psposix.get_terminal_map() - try: - return tmap[tty_nr] - except KeyError: - return None - - @wrap_exceptions - def ppid(self): - self._ppid = self.oneshot()[kinfo_proc_map['ppid']] - return self._ppid - - @wrap_exceptions - def uids(self): - rawtuple = self.oneshot() - return _common.puids( - rawtuple[kinfo_proc_map['real_uid']], - rawtuple[kinfo_proc_map['effective_uid']], - rawtuple[kinfo_proc_map['saved_uid']]) - - @wrap_exceptions - def gids(self): - rawtuple = self.oneshot() - return _common.pgids( - rawtuple[kinfo_proc_map['real_gid']], - rawtuple[kinfo_proc_map['effective_gid']], - rawtuple[kinfo_proc_map['saved_gid']]) - - @wrap_exceptions - def cpu_times(self): - rawtuple = self.oneshot() - return _common.pcputimes( - rawtuple[kinfo_proc_map['user_time']], - rawtuple[kinfo_proc_map['sys_time']], - rawtuple[kinfo_proc_map['ch_user_time']], - rawtuple[kinfo_proc_map['ch_sys_time']]) - - if FREEBSD: - @wrap_exceptions - def cpu_num(self): - return self.oneshot()[kinfo_proc_map['cpunum']] - - @wrap_exceptions - def memory_info(self): - rawtuple = self.oneshot() - return pmem( - rawtuple[kinfo_proc_map['rss']], - rawtuple[kinfo_proc_map['vms']], - rawtuple[kinfo_proc_map['memtext']], - rawtuple[kinfo_proc_map['memdata']], - rawtuple[kinfo_proc_map['memstack']]) - - memory_full_info = memory_info - - @wrap_exceptions - def create_time(self): - return self.oneshot()[kinfo_proc_map['create_time']] - - @wrap_exceptions - def num_threads(self): - if HAS_PROC_NUM_THREADS: - # FreeBSD - return cext.proc_num_threads(self.pid) - else: - return len(self.threads()) - - @wrap_exceptions - def num_ctx_switches(self): - rawtuple = self.oneshot() - return _common.pctxsw( - rawtuple[kinfo_proc_map['ctx_switches_vol']], - rawtuple[kinfo_proc_map['ctx_switches_unvol']]) - - @wrap_exceptions - def threads(self): - # Note: on OpenSBD this (/dev/mem) requires root access. - rawlist = cext.proc_threads(self.pid) - retlist = [] - for thread_id, utime, stime in rawlist: - ntuple = _common.pthread(thread_id, utime, stime) - retlist.append(ntuple) - if OPENBSD: - self._assert_alive() - return retlist - - @wrap_exceptions - def connections(self, kind='inet'): - if kind not in conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - - if NETBSD: - families, types = conn_tmap[kind] - ret = [] - rawlist = cext.net_connections(self.pid) - for item in rawlist: - fd, fam, type, laddr, raddr, status, pid = item - assert pid == self.pid - if fam in families and type in types: - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES) - ret.append(nt) - self._assert_alive() - return list(ret) - - families, types = conn_tmap[kind] - rawlist = cext.proc_connections(self.pid, families, types) - ret = [] - for item in rawlist: - fd, fam, type, laddr, raddr, status = item - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES) - ret.append(nt) - - if OPENBSD: - self._assert_alive() - - return ret - - @wrap_exceptions - def wait(self, timeout=None): - return _psposix.wait_pid(self.pid, timeout, self._name) - - @wrap_exceptions - def nice_get(self): - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def status(self): - code = self.oneshot()[kinfo_proc_map['status']] - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(code, '?') - - @wrap_exceptions - def io_counters(self): - rawtuple = self.oneshot() - return _common.pio( - rawtuple[kinfo_proc_map['read_io_count']], - rawtuple[kinfo_proc_map['write_io_count']], - -1, - -1) - - @wrap_exceptions - def cwd(self): - """Return process current working directory.""" - # sometimes we get an empty string, in which case we turn - # it into None - if OPENBSD and self.pid == 0: - return None # ...else it would raise EINVAL - elif NETBSD or HAS_PROC_OPEN_FILES: - # FreeBSD < 8 does not support functions based on - # kinfo_getfile() and kinfo_getvmmap() - return cext.proc_cwd(self.pid) or None - else: - raise NotImplementedError( - "supported only starting from FreeBSD 8" if - FREEBSD else "") - - nt_mmap_grouped = namedtuple( - 'mmap', 'path rss, private, ref_count, shadow_count') - nt_mmap_ext = namedtuple( - 'mmap', 'addr, perms path rss, private, ref_count, shadow_count') - - def _not_implemented(self): - raise NotImplementedError - - # FreeBSD < 8 does not support functions based on kinfo_getfile() - # and kinfo_getvmmap() - if HAS_PROC_OPEN_FILES: - @wrap_exceptions - def open_files(self): - """Return files opened by process as a list of namedtuples.""" - rawlist = cext.proc_open_files(self.pid) - return [_common.popenfile(path, fd) for path, fd in rawlist] - else: - open_files = _not_implemented - - # FreeBSD < 8 does not support functions based on kinfo_getfile() - # and kinfo_getvmmap() - if HAS_PROC_NUM_FDS: - @wrap_exceptions - def num_fds(self): - """Return the number of file descriptors opened by this process.""" - ret = cext.proc_num_fds(self.pid) - if NETBSD: - self._assert_alive() - return ret - else: - num_fds = _not_implemented - - # --- FreeBSD only APIs - - if FREEBSD: - - @wrap_exceptions - def cpu_affinity_get(self): - return cext.proc_cpu_affinity_get(self.pid) - - @wrap_exceptions - def cpu_affinity_set(self, cpus): - # Pre-emptively check if CPUs are valid because the C - # function has a weird behavior in case of invalid CPUs, - # see: https://github.com/giampaolo/psutil/issues/586 - allcpus = tuple(range(len(per_cpu_times()))) - for cpu in cpus: - if cpu not in allcpus: - raise ValueError("invalid CPU #%i (choose between %s)" - % (cpu, allcpus)) - try: - cext.proc_cpu_affinity_set(self.pid, cpus) - except OSError as err: - # 'man cpuset_setaffinity' about EDEADLK: - # <> - if err.errno in (errno.EINVAL, errno.EDEADLK): - for cpu in cpus: - if cpu not in allcpus: - raise ValueError( - "invalid CPU #%i (choose between %s)" % ( - cpu, allcpus)) - raise - - @wrap_exceptions - def memory_maps(self): - return cext.proc_memory_maps(self.pid) diff --git a/third_party/python/psutil/psutil/_pslinux.py b/third_party/python/psutil/psutil/_pslinux.py deleted file mode 100644 index 9e32f25e7bf9..000000000000 --- a/third_party/python/psutil/psutil/_pslinux.py +++ /dev/null @@ -1,2095 +0,0 @@ -# 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. - -"""Linux platform implementation.""" - -from __future__ import division - -import base64 -import collections -import errno -import functools -import glob -import os -import re -import socket -import struct -import sys -import traceback -import warnings -from collections import defaultdict -from collections import namedtuple - -from . import _common -from . import _psposix -from . import _psutil_linux as cext -from . import _psutil_posix as cext_posix -from ._common import AccessDenied -from ._common import debug -from ._common import decode -from ._common import get_procfs_path -from ._common import isfile_strict -from ._common import memoize -from ._common import memoize_when_activated -from ._common import NIC_DUPLEX_FULL -from ._common import NIC_DUPLEX_HALF -from ._common import NIC_DUPLEX_UNKNOWN -from ._common import NoSuchProcess -from ._common import open_binary -from ._common import open_text -from ._common import parse_environ_block -from ._common import path_exists_strict -from ._common import supports_ipv6 -from ._common import usage_percent -from ._common import ZombieProcess -from ._compat import b -from ._compat import basestring -from ._compat import FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - - -__extra__all__ = [ - # - 'PROCFS_PATH', - # io prio constants - "IOPRIO_CLASS_NONE", "IOPRIO_CLASS_RT", "IOPRIO_CLASS_BE", - "IOPRIO_CLASS_IDLE", - # connection status constants - "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", - "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", - "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", ] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -POWER_SUPPLY_PATH = "/sys/class/power_supply" -HAS_SMAPS = os.path.exists('/proc/%s/smaps' % os.getpid()) -HAS_PRLIMIT = hasattr(cext, "linux_prlimit") -HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_ioprio_get") -HAS_CPU_AFFINITY = hasattr(cext, "proc_cpu_affinity_get") -_DEFAULT = object() - -# RLIMIT_* constants, not guaranteed to be present on all kernels -if HAS_PRLIMIT: - for name in dir(cext): - if name.startswith('RLIM'): - __extra__all__.append(name) - -# Number of clock ticks per second -CLOCK_TICKS = os.sysconf("SC_CLK_TCK") -PAGESIZE = os.sysconf("SC_PAGE_SIZE") -BOOT_TIME = None # set later -# Used when reading "big" files, namely /proc/{pid}/smaps and /proc/net/*. -# On Python 2, using a buffer with open() for such files may result in a -# speedup, see: https://github.com/giampaolo/psutil/issues/708 -BIGFILE_BUFFERING = -1 if PY3 else 8192 -LITTLE_ENDIAN = sys.byteorder == 'little' - -# "man iostat" states that sectors are equivalent with blocks and have -# a size of 512 bytes. Despite this value can be queried at runtime -# via /sys/block/{DISK}/queue/hw_sector_size and results may vary -# between 1k, 2k, or 4k... 512 appears to be a magic constant used -# throughout Linux source code: -# * https://stackoverflow.com/a/38136179/376587 -# * https://lists.gt.net/linux/kernel/2241060 -# * https://github.com/giampaolo/psutil/issues/1305 -# * https://github.com/torvalds/linux/blob/ -# 4f671fe2f9523a1ea206f63fe60a7c7b3a56d5c7/include/linux/bio.h#L99 -# * https://lkml.org/lkml/2015/8/17/234 -DISK_SECTOR_SIZE = 512 - -if enum is None: - AF_LINK = socket.AF_PACKET -else: - AddressFamily = enum.IntEnum('AddressFamily', - {'AF_LINK': int(socket.AF_PACKET)}) - AF_LINK = AddressFamily.AF_LINK - -# ioprio_* constants http://linux.die.net/man/2/ioprio_get -if enum is None: - IOPRIO_CLASS_NONE = 0 - IOPRIO_CLASS_RT = 1 - IOPRIO_CLASS_BE = 2 - IOPRIO_CLASS_IDLE = 3 -else: - class IOPriority(enum.IntEnum): - IOPRIO_CLASS_NONE = 0 - IOPRIO_CLASS_RT = 1 - IOPRIO_CLASS_BE = 2 - IOPRIO_CLASS_IDLE = 3 - - globals().update(IOPriority.__members__) - -# See: -# https://github.com/torvalds/linux/blame/master/fs/proc/array.c -# ...and (TASK_* constants): -# https://github.com/torvalds/linux/blob/master/include/linux/sched.h -PROC_STATUSES = { - "R": _common.STATUS_RUNNING, - "S": _common.STATUS_SLEEPING, - "D": _common.STATUS_DISK_SLEEP, - "T": _common.STATUS_STOPPED, - "t": _common.STATUS_TRACING_STOP, - "Z": _common.STATUS_ZOMBIE, - "X": _common.STATUS_DEAD, - "x": _common.STATUS_DEAD, - "K": _common.STATUS_WAKE_KILL, - "W": _common.STATUS_WAKING, - "I": _common.STATUS_IDLE, - "P": _common.STATUS_PARKED, -} - -# https://github.com/torvalds/linux/blob/master/include/net/tcp_states.h -TCP_STATUSES = { - "01": _common.CONN_ESTABLISHED, - "02": _common.CONN_SYN_SENT, - "03": _common.CONN_SYN_RECV, - "04": _common.CONN_FIN_WAIT1, - "05": _common.CONN_FIN_WAIT2, - "06": _common.CONN_TIME_WAIT, - "07": _common.CONN_CLOSE, - "08": _common.CONN_CLOSE_WAIT, - "09": _common.CONN_LAST_ACK, - "0A": _common.CONN_LISTEN, - "0B": _common.CONN_CLOSING -} - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.virtual_memory() -svmem = namedtuple( - 'svmem', ['total', 'available', 'percent', 'used', 'free', - 'active', 'inactive', 'buffers', 'cached', 'shared', 'slab']) -# psutil.disk_io_counters() -sdiskio = namedtuple( - 'sdiskio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'read_time', 'write_time', - 'read_merged_count', 'write_merged_count', - 'busy_time']) -# psutil.Process().open_files() -popenfile = namedtuple( - 'popenfile', ['path', 'fd', 'position', 'mode', 'flags']) -# psutil.Process().memory_info() -pmem = namedtuple('pmem', 'rss vms shared text lib data dirty') -# psutil.Process().memory_full_info() -pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', 'pss', 'swap')) -# psutil.Process().memory_maps(grouped=True) -pmmap_grouped = namedtuple( - 'pmmap_grouped', - ['path', 'rss', 'size', 'pss', 'shared_clean', 'shared_dirty', - 'private_clean', 'private_dirty', 'referenced', 'anonymous', 'swap']) -# psutil.Process().memory_maps(grouped=False) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) -# psutil.Process.io_counters() -pio = namedtuple('pio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'read_chars', 'write_chars']) -# psutil.Process.cpu_times() -pcputimes = namedtuple('pcputimes', - ['user', 'system', 'children_user', 'children_system', - 'iowait']) - - -# ===================================================================== -# --- utils -# ===================================================================== - - -def readlink(path): - """Wrapper around os.readlink().""" - assert isinstance(path, basestring), path - path = os.readlink(path) - # readlink() might return paths containing null bytes ('\x00') - # resulting in "TypeError: must be encoded string without NULL - # bytes, not str" errors when the string is passed to other - # fs-related functions (os.*, open(), ...). - # Apparently everything after '\x00' is garbage (we can have - # ' (deleted)', 'new' and possibly others), see: - # https://github.com/giampaolo/psutil/issues/717 - path = path.split('\x00')[0] - # Certain paths have ' (deleted)' appended. Usually this is - # bogus as the file actually exists. Even if it doesn't we - # don't care. - if path.endswith(' (deleted)') and not path_exists_strict(path): - path = path[:-10] - return path - - -def file_flags_to_mode(flags): - """Convert file's open() flags into a readable string. - Used by Process.open_files(). - """ - modes_map = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'} - mode = modes_map[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)] - if flags & os.O_APPEND: - mode = mode.replace('w', 'a', 1) - mode = mode.replace('w+', 'r+') - # possible values: r, w, a, r+, a+ - return mode - - -def is_storage_device(name): - """Return True if the given name refers to a root device (e.g. - "sda", "nvme0n1") as opposed to a logical partition (e.g. "sda1", - "nvme0n1p1"). If name is a virtual device (e.g. "loop1", "ram") - return True. - """ - # Readapted from iostat source code, see: - # https://github.com/sysstat/sysstat/blob/ - # 97912938cd476645b267280069e83b1c8dc0e1c7/common.c#L208 - # Some devices may have a slash in their name (e.g. cciss/c0d0...). - name = name.replace('/', '!') - including_virtual = True - if including_virtual: - path = "/sys/block/%s" % name - else: - path = "/sys/block/%s/device" % name - return os.access(path, os.F_OK) - - -@memoize -def set_scputimes_ntuple(procfs_path): - """Set a namedtuple of variable fields depending on the CPU times - available on this Linux kernel version which may be: - (user, nice, system, idle, iowait, irq, softirq, [steal, [guest, - [guest_nice]]]) - Used by cpu_times() function. - """ - global scputimes - with open_binary('%s/stat' % procfs_path) as f: - values = f.readline().split()[1:] - fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq'] - vlen = len(values) - if vlen >= 8: - # Linux >= 2.6.11 - fields.append('steal') - if vlen >= 9: - # Linux >= 2.6.24 - fields.append('guest') - if vlen >= 10: - # Linux >= 3.2.0 - fields.append('guest_nice') - scputimes = namedtuple('scputimes', fields) - - -def cat(fname, fallback=_DEFAULT, binary=True): - """Return file content. - fallback: the value returned in case the file does not exist or - cannot be read - binary: whether to open the file in binary or text mode. - """ - try: - with open_binary(fname) if binary else open_text(fname) as f: - return f.read().strip() - except (IOError, OSError): - if fallback is not _DEFAULT: - return fallback - else: - raise - - -try: - set_scputimes_ntuple("/proc") -except Exception: - # Don't want to crash at import time. - traceback.print_exc() - scputimes = namedtuple('scputimes', 'user system idle')(0.0, 0.0, 0.0) - - -# ===================================================================== -# --- system memory -# ===================================================================== - - -def calculate_avail_vmem(mems): - """Fallback for kernels < 3.14 where /proc/meminfo does not provide - "MemAvailable:" column, see: - https://blog.famzah.net/2014/09/24/ - This code reimplements the algorithm outlined here: - https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ - commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 - - XXX: on recent kernels this calculation differs by ~1.5% than - "MemAvailable:" as it's calculated slightly differently, see: - https://gitlab.com/procps-ng/procps/issues/42 - https://github.com/famzah/linux-memavailable-procfs/issues/2 - It is still way more realistic than doing (free + cached) though. - """ - # Fallback for very old distros. According to - # https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ - # commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 - # ...long ago "avail" was calculated as (free + cached). - # We might fallback in such cases: - # "Active(file)" not available: 2.6.28 / Dec 2008 - # "Inactive(file)" not available: 2.6.28 / Dec 2008 - # "SReclaimable:" not available: 2.6.19 / Nov 2006 - # /proc/zoneinfo not available: 2.6.13 / Aug 2005 - free = mems[b'MemFree:'] - fallback = free + mems.get(b"Cached:", 0) - try: - lru_active_file = mems[b'Active(file):'] - lru_inactive_file = mems[b'Inactive(file):'] - slab_reclaimable = mems[b'SReclaimable:'] - except KeyError: - return fallback - try: - f = open_binary('%s/zoneinfo' % get_procfs_path()) - except IOError: - return fallback # kernel 2.6.13 - - watermark_low = 0 - with f: - for line in f: - line = line.strip() - if line.startswith(b'low'): - watermark_low += int(line.split()[1]) - watermark_low *= PAGESIZE - watermark_low = watermark_low - - avail = free - watermark_low - pagecache = lru_active_file + lru_inactive_file - pagecache -= min(pagecache / 2, watermark_low) - avail += pagecache - avail += slab_reclaimable - min(slab_reclaimable / 2.0, watermark_low) - return int(avail) - - -def virtual_memory(): - """Report virtual memory stats. - This implementation matches "free" and "vmstat -s" cmdline - utility values and procps-ng-3.3.12 source was used as a reference - (2016-09-18): - https://gitlab.com/procps-ng/procps/blob/ - 24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c - For reference, procps-ng-3.3.10 is the version available on Ubuntu - 16.04. - - Note about "available" memory: up until psutil 4.3 it was - calculated as "avail = (free + buffers + cached)". Now - "MemAvailable:" column (kernel 3.14) from /proc/meminfo is used as - it's more accurate. - That matches "available" column in newer versions of "free". - """ - missing_fields = [] - mems = {} - with open_binary('%s/meminfo' % get_procfs_path()) as f: - for line in f: - fields = line.split() - mems[fields[0]] = int(fields[1]) * 1024 - - # /proc doc states that the available fields in /proc/meminfo vary - # by architecture and compile options, but these 3 values are also - # returned by sysinfo(2); as such we assume they are always there. - total = mems[b'MemTotal:'] - free = mems[b'MemFree:'] - try: - buffers = mems[b'Buffers:'] - except KeyError: - # https://github.com/giampaolo/psutil/issues/1010 - buffers = 0 - missing_fields.append('buffers') - try: - cached = mems[b"Cached:"] - except KeyError: - cached = 0 - missing_fields.append('cached') - else: - # "free" cmdline utility sums reclaimable to cached. - # Older versions of procps used to add slab memory instead. - # This got changed in: - # https://gitlab.com/procps-ng/procps/commit/ - # 05d751c4f076a2f0118b914c5e51cfbb4762ad8e - cached += mems.get(b"SReclaimable:", 0) # since kernel 2.6.19 - - try: - shared = mems[b'Shmem:'] # since kernel 2.6.32 - except KeyError: - try: - shared = mems[b'MemShared:'] # kernels 2.4 - except KeyError: - shared = 0 - missing_fields.append('shared') - - try: - active = mems[b"Active:"] - except KeyError: - active = 0 - missing_fields.append('active') - - try: - inactive = mems[b"Inactive:"] - except KeyError: - try: - inactive = \ - mems[b"Inact_dirty:"] + \ - mems[b"Inact_clean:"] + \ - mems[b"Inact_laundry:"] - except KeyError: - inactive = 0 - missing_fields.append('inactive') - - try: - slab = mems[b"Slab:"] - except KeyError: - slab = 0 - - used = total - free - cached - buffers - if used < 0: - # May be symptomatic of running within a LCX container where such - # values will be dramatically distorted over those of the host. - used = total - free - - # - starting from 4.4.0 we match free's "available" column. - # Before 4.4.0 we calculated it as (free + buffers + cached) - # which matched htop. - # - free and htop available memory differs as per: - # http://askubuntu.com/a/369589 - # http://unix.stackexchange.com/a/65852/168884 - # - MemAvailable has been introduced in kernel 3.14 - try: - avail = mems[b'MemAvailable:'] - except KeyError: - avail = calculate_avail_vmem(mems) - - if avail < 0: - avail = 0 - missing_fields.append('available') - - # If avail is greater than total or our calculation overflows, - # that's symptomatic of running within a LCX container where such - # values will be dramatically distorted over those of the host. - # https://gitlab.com/procps-ng/procps/blob/ - # 24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c#L764 - if avail > total: - avail = free - - percent = usage_percent((total - avail), total, round_=1) - - # Warn about missing metrics which are set to 0. - if missing_fields: - msg = "%s memory stats couldn't be determined and %s set to 0" % ( - ", ".join(missing_fields), - "was" if len(missing_fields) == 1 else "were") - warnings.warn(msg, RuntimeWarning) - - return svmem(total, avail, percent, used, free, - active, inactive, buffers, cached, shared, slab) - - -def swap_memory(): - """Return swap memory metrics.""" - mems = {} - with open_binary('%s/meminfo' % get_procfs_path()) as f: - for line in f: - fields = line.split() - mems[fields[0]] = int(fields[1]) * 1024 - # We prefer /proc/meminfo over sysinfo() syscall so that - # psutil.PROCFS_PATH can be used in order to allow retrieval - # for linux containers, see: - # https://github.com/giampaolo/psutil/issues/1015 - try: - total = mems[b'SwapTotal:'] - free = mems[b'SwapFree:'] - except KeyError: - _, _, _, _, total, free, unit_multiplier = cext.linux_sysinfo() - total *= unit_multiplier - free *= unit_multiplier - - used = total - free - percent = usage_percent(used, total, round_=1) - # get pgin/pgouts - try: - f = open_binary("%s/vmstat" % get_procfs_path()) - except IOError as err: - # see https://github.com/giampaolo/psutil/issues/722 - msg = "'sin' and 'sout' swap memory stats couldn't " \ - "be determined and were set to 0 (%s)" % str(err) - warnings.warn(msg, RuntimeWarning) - sin = sout = 0 - else: - with f: - sin = sout = None - for line in f: - # values are expressed in 4 kilo bytes, we want - # bytes instead - if line.startswith(b'pswpin'): - sin = int(line.split(b' ')[1]) * 4 * 1024 - elif line.startswith(b'pswpout'): - sout = int(line.split(b' ')[1]) * 4 * 1024 - if sin is not None and sout is not None: - break - else: - # we might get here when dealing with exotic Linux - # flavors, see: - # https://github.com/giampaolo/psutil/issues/313 - msg = "'sin' and 'sout' swap memory stats couldn't " \ - "be determined and were set to 0" - warnings.warn(msg, RuntimeWarning) - sin = sout = 0 - return _common.sswap(total, used, free, percent, sin, sout) - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return a named tuple representing the following system-wide - CPU times: - (user, nice, system, idle, iowait, irq, softirq [steal, [guest, - [guest_nice]]]) - Last 3 fields may not be available on all Linux kernel versions. - """ - procfs_path = get_procfs_path() - set_scputimes_ntuple(procfs_path) - with open_binary('%s/stat' % procfs_path) as f: - values = f.readline().split() - fields = values[1:len(scputimes._fields) + 1] - fields = [float(x) / CLOCK_TICKS for x in fields] - return scputimes(*fields) - - -def per_cpu_times(): - """Return a list of namedtuple representing the CPU times - for every CPU available on the system. - """ - procfs_path = get_procfs_path() - set_scputimes_ntuple(procfs_path) - cpus = [] - with open_binary('%s/stat' % procfs_path) as f: - # get rid of the first line which refers to system wide CPU stats - f.readline() - for line in f: - if line.startswith(b'cpu'): - values = line.split() - fields = values[1:len(scputimes._fields) + 1] - fields = [float(x) / CLOCK_TICKS for x in fields] - entry = scputimes(*fields) - cpus.append(entry) - return cpus - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - try: - return os.sysconf("SC_NPROCESSORS_ONLN") - except ValueError: - # as a second fallback we try to parse /proc/cpuinfo - num = 0 - with open_binary('%s/cpuinfo' % get_procfs_path()) as f: - for line in f: - if line.lower().startswith(b'processor'): - num += 1 - - # unknown format (e.g. amrel/sparc architectures), see: - # https://github.com/giampaolo/psutil/issues/200 - # try to parse /proc/stat as a last resort - if num == 0: - search = re.compile(r'cpu\d') - with open_text('%s/stat' % get_procfs_path()) as f: - for line in f: - line = line.split(' ')[0] - if search.match(line): - num += 1 - - if num == 0: - # mimic os.cpu_count() - return None - return num - - -def cpu_count_physical(): - """Return the number of physical cores in the system.""" - # Method #1 - core_ids = set() - for path in glob.glob( - "/sys/devices/system/cpu/cpu[0-9]*/topology/core_id"): - with open_binary(path) as f: - core_ids.add(int(f.read())) - result = len(core_ids) - if result != 0: - return result - - # Method #2 - mapping = {} - current_info = {} - with open_binary('%s/cpuinfo' % get_procfs_path()) as f: - for line in f: - line = line.strip().lower() - if not line: - # new section - if (b'physical id' in current_info and - b'cpu cores' in current_info): - mapping[current_info[b'physical id']] = \ - current_info[b'cpu cores'] - current_info = {} - else: - # ongoing section - if (line.startswith(b'physical id') or - line.startswith(b'cpu cores')): - key, value = line.split(b'\t:', 1) - current_info[key] = int(value) - - result = sum(mapping.values()) - return result or None # mimic os.cpu_count() - - -def cpu_stats(): - """Return various CPU stats as a named tuple.""" - with open_binary('%s/stat' % get_procfs_path()) as f: - ctx_switches = None - interrupts = None - soft_interrupts = None - for line in f: - if line.startswith(b'ctxt'): - ctx_switches = int(line.split()[1]) - elif line.startswith(b'intr'): - interrupts = int(line.split()[1]) - elif line.startswith(b'softirq'): - soft_interrupts = int(line.split()[1]) - if ctx_switches is not None and soft_interrupts is not None \ - and interrupts is not None: - break - syscalls = 0 - return _common.scpustats( - ctx_switches, interrupts, soft_interrupts, syscalls) - - -if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or \ - os.path.exists("/sys/devices/system/cpu/cpu0/cpufreq"): - def cpu_freq(): - """Return frequency metrics for all CPUs. - Contrarily to other OSes, Linux updates these values in - real-time. - """ - def get_path(num): - for p in ("/sys/devices/system/cpu/cpufreq/policy%s" % num, - "/sys/devices/system/cpu/cpu%s/cpufreq" % num): - if os.path.exists(p): - return p - - ret = [] - for n in range(cpu_count_logical()): - path = get_path(n) - if not path: - continue - - pjoin = os.path.join - curr = cat(pjoin(path, "scaling_cur_freq"), fallback=None) - if curr is None: - # Likely an old RedHat, see: - # https://github.com/giampaolo/psutil/issues/1071 - curr = cat(pjoin(path, "cpuinfo_cur_freq"), fallback=None) - if curr is None: - raise NotImplementedError( - "can't find current frequency file") - curr = int(curr) / 1000 - max_ = int(cat(pjoin(path, "scaling_max_freq"))) / 1000 - min_ = int(cat(pjoin(path, "scaling_min_freq"))) / 1000 - ret.append(_common.scpufreq(curr, min_, max_)) - return ret - -elif os.path.exists("/proc/cpuinfo"): - def cpu_freq(): - """Alternate implementation using /proc/cpuinfo. - min and max frequencies are not available and are set to None. - """ - ret = [] - with open_binary('%s/cpuinfo' % get_procfs_path()) as f: - for line in f: - if line.lower().startswith(b'cpu mhz'): - key, value = line.split(b'\t:', 1) - ret.append(_common.scpufreq(float(value), 0., 0.)) - return ret - -else: - def cpu_freq(): - """Dummy implementation when none of the above files are present. - """ - return [] - - -# ===================================================================== -# --- network -# ===================================================================== - - -net_if_addrs = cext_posix.net_if_addrs - - -class _Ipv6UnsupportedError(Exception): - pass - - -class Connections: - """A wrapper on top of /proc/net/* files, retrieving per-process - and system-wide open connections (TCP, UDP, UNIX) similarly to - "netstat -an". - - Note: in case of UNIX sockets we're only able to determine the - local endpoint/path, not the one it's connected to. - According to [1] it would be possible but not easily. - - [1] http://serverfault.com/a/417946 - """ - - def __init__(self): - # The string represents the basename of the corresponding - # /proc/net/{proto_name} file. - tcp4 = ("tcp", socket.AF_INET, socket.SOCK_STREAM) - tcp6 = ("tcp6", socket.AF_INET6, socket.SOCK_STREAM) - udp4 = ("udp", socket.AF_INET, socket.SOCK_DGRAM) - udp6 = ("udp6", socket.AF_INET6, socket.SOCK_DGRAM) - unix = ("unix", socket.AF_UNIX, None) - self.tmap = { - "all": (tcp4, tcp6, udp4, udp6, unix), - "tcp": (tcp4, tcp6), - "tcp4": (tcp4,), - "tcp6": (tcp6,), - "udp": (udp4, udp6), - "udp4": (udp4,), - "udp6": (udp6,), - "unix": (unix,), - "inet": (tcp4, tcp6, udp4, udp6), - "inet4": (tcp4, udp4), - "inet6": (tcp6, udp6), - } - self._procfs_path = None - - def get_proc_inodes(self, pid): - inodes = defaultdict(list) - for fd in os.listdir("%s/%s/fd" % (self._procfs_path, pid)): - try: - inode = readlink("%s/%s/fd/%s" % (self._procfs_path, pid, fd)) - except (FileNotFoundError, ProcessLookupError): - # ENOENT == file which is gone in the meantime; - # os.stat('/proc/%s' % self.pid) will be done later - # to force NSP (if it's the case) - continue - except OSError as err: - if err.errno == errno.EINVAL: - # not a link - continue - raise - else: - if inode.startswith('socket:['): - # the process is using a socket - inode = inode[8:][:-1] - inodes[inode].append((pid, int(fd))) - return inodes - - def get_all_inodes(self): - inodes = {} - for pid in pids(): - try: - inodes.update(self.get_proc_inodes(pid)) - except (FileNotFoundError, ProcessLookupError, PermissionError): - # os.listdir() is gonna raise a lot of access denied - # exceptions in case of unprivileged user; that's fine - # as we'll just end up returning a connection with PID - # and fd set to None anyway. - # Both netstat -an and lsof does the same so it's - # unlikely we can do any better. - # ENOENT just means a PID disappeared on us. - continue - return inodes - - @staticmethod - def decode_address(addr, family): - """Accept an "ip:port" address as displayed in /proc/net/* - and convert it into a human readable form, like: - - "0500000A:0016" -> ("10.0.0.5", 22) - "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521) - - The IP address portion is a little or big endian four-byte - hexadecimal number; that is, the least significant byte is listed - first, so we need to reverse the order of the bytes to convert it - to an IP address. - The port is represented as a two-byte hexadecimal number. - - Reference: - http://linuxdevcenter.com/pub/a/linux/2000/11/16/LinuxAdmin.html - """ - ip, port = addr.split(':') - port = int(port, 16) - # this usually refers to a local socket in listen mode with - # no end-points connected - if not port: - return () - if PY3: - ip = ip.encode('ascii') - if family == socket.AF_INET: - # see: https://github.com/giampaolo/psutil/issues/201 - if LITTLE_ENDIAN: - ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1]) - else: - ip = socket.inet_ntop(family, base64.b16decode(ip)) - else: # IPv6 - # 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))) - ip = base64.b16decode(ip) - try: - # see: https://github.com/giampaolo/psutil/issues/201 - if LITTLE_ENDIAN: - ip = socket.inet_ntop( - socket.AF_INET6, - struct.pack('>4I', *struct.unpack('<4I', ip))) - else: - ip = socket.inet_ntop( - socket.AF_INET6, - struct.pack('<4I', *struct.unpack('<4I', ip))) - except ValueError: - # see: https://github.com/giampaolo/psutil/issues/623 - if not supports_ipv6(): - raise _Ipv6UnsupportedError - else: - raise - return _common.addr(ip, port) - - @staticmethod - def process_inet(file, family, type_, inodes, filter_pid=None): - """Parse /proc/net/tcp* and /proc/net/udp* files.""" - if file.endswith('6') and not os.path.exists(file): - # IPv6 not supported - return - with open_text(file, buffering=BIGFILE_BUFFERING) as f: - f.readline() # skip the first line - for lineno, line in enumerate(f, 1): - try: - _, laddr, raddr, status, _, _, _, _, _, inode = \ - line.split()[:10] - except ValueError: - raise RuntimeError( - "error while parsing %s; malformed line %s %r" % ( - file, lineno, line)) - if inode in inodes: - # # We assume inet sockets are unique, so we error - # # out if there are multiple references to the - # # same inode. We won't do this for UNIX sockets. - # if len(inodes[inode]) > 1 and family != socket.AF_UNIX: - # raise ValueError("ambiguos inode with multiple " - # "PIDs references") - pid, fd = inodes[inode][0] - else: - pid, fd = None, -1 - if filter_pid is not None and filter_pid != pid: - continue - else: - if type_ == socket.SOCK_STREAM: - status = TCP_STATUSES[status] - else: - status = _common.CONN_NONE - try: - laddr = Connections.decode_address(laddr, family) - raddr = Connections.decode_address(raddr, family) - except _Ipv6UnsupportedError: - continue - yield (fd, family, type_, laddr, raddr, status, pid) - - @staticmethod - def process_unix(file, family, inodes, filter_pid=None): - """Parse /proc/net/unix files.""" - with open_text(file, buffering=BIGFILE_BUFFERING) as f: - f.readline() # skip the first line - for line in f: - tokens = line.split() - try: - _, _, _, _, type_, _, inode = tokens[0:7] - except ValueError: - if ' ' not in line: - # see: https://github.com/giampaolo/psutil/issues/766 - continue - raise RuntimeError( - "error while parsing %s; malformed line %r" % ( - file, line)) - if inode in inodes: - # With UNIX sockets we can have a single inode - # referencing many file descriptors. - pairs = inodes[inode] - else: - pairs = [(None, -1)] - for pid, fd in pairs: - if filter_pid is not None and filter_pid != pid: - continue - else: - if len(tokens) == 8: - path = tokens[-1] - else: - path = "" - type_ = _common.socktype_to_enum(int(type_)) - # XXX: determining the remote endpoint of a - # UNIX socket on Linux is not possible, see: - # https://serverfault.com/questions/252723/ - raddr = "" - status = _common.CONN_NONE - yield (fd, family, type_, path, raddr, status, pid) - - def retrieve(self, kind, pid=None): - if kind not in self.tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in self.tmap]))) - self._procfs_path = get_procfs_path() - if pid is not None: - inodes = self.get_proc_inodes(pid) - if not inodes: - # no connections for this process - return [] - else: - inodes = self.get_all_inodes() - ret = set() - for proto_name, family, type_ in self.tmap[kind]: - path = "%s/net/%s" % (self._procfs_path, proto_name) - if family in (socket.AF_INET, socket.AF_INET6): - ls = self.process_inet( - path, family, type_, inodes, filter_pid=pid) - else: - ls = self.process_unix( - path, family, inodes, filter_pid=pid) - for fd, family, type_, laddr, raddr, status, bound_pid in ls: - if pid: - conn = _common.pconn(fd, family, type_, laddr, raddr, - status) - else: - conn = _common.sconn(fd, family, type_, laddr, raddr, - status, bound_pid) - ret.add(conn) - return list(ret) - - -_connections = Connections() - - -def net_connections(kind='inet'): - """Return system-wide open connections.""" - return _connections.retrieve(kind) - - -def net_io_counters(): - """Return network I/O statistics for every network interface - installed on the system as a dict of raw tuples. - """ - with open_text("%s/net/dev" % get_procfs_path()) as f: - lines = f.readlines() - retdict = {} - for line in lines[2:]: - colon = line.rfind(':') - assert colon > 0, repr(line) - name = line[:colon].strip() - fields = line[colon + 1:].strip().split() - - # in - (bytes_recv, - packets_recv, - errin, - dropin, - fifoin, # unused - framein, # unused - compressedin, # unused - multicastin, # unused - # out - bytes_sent, - packets_sent, - errout, - dropout, - fifoout, # unused - collisionsout, # unused - carrierout, # unused - compressedout) = map(int, fields) - - retdict[name] = (bytes_sent, bytes_recv, packets_sent, packets_recv, - errin, errout, dropin, dropout) - return retdict - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - duplex_map = {cext.DUPLEX_FULL: NIC_DUPLEX_FULL, - cext.DUPLEX_HALF: NIC_DUPLEX_HALF, - cext.DUPLEX_UNKNOWN: NIC_DUPLEX_UNKNOWN} - names = net_io_counters().keys() - ret = {} - for name in names: - try: - mtu = cext_posix.net_if_mtu(name) - isup = cext_posix.net_if_flags(name) - duplex, speed = cext.net_if_duplex_speed(name) - except OSError as err: - # https://github.com/giampaolo/psutil/issues/1279 - if err.errno != errno.ENODEV: - raise - else: - ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu) - return ret - - -# ===================================================================== -# --- disks -# ===================================================================== - - -disk_usage = _psposix.disk_usage - - -def disk_io_counters(perdisk=False): - """Return disk I/O statistics for every disk installed on the - system as a dict of raw tuples. - """ - def read_procfs(): - # OK, this is a bit confusing. The format of /proc/diskstats can - # have 3 variations. - # On Linux 2.4 each line has always 15 fields, e.g.: - # "3 0 8 hda 8 8 8 8 8 8 8 8 8 8 8" - # On Linux 2.6+ each line *usually* has 14 fields, and the disk - # name is in another position, like this: - # "3 0 hda 8 8 8 8 8 8 8 8 8 8 8" - # ...unless (Linux 2.6) the line refers to a partition instead - # of a disk, in which case the line has less fields (7): - # "3 1 hda1 8 8 8 8" - # 4.18+ has 4 fields added: - # "3 0 hda 8 8 8 8 8 8 8 8 8 8 8 0 0 0 0" - # 5.5 has 2 more fields. - # See: - # https://www.kernel.org/doc/Documentation/iostats.txt - # https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats - with open_text("%s/diskstats" % get_procfs_path()) as f: - lines = f.readlines() - for line in lines: - fields = line.split() - flen = len(fields) - if flen == 15: - # Linux 2.4 - name = fields[3] - reads = int(fields[2]) - (reads_merged, rbytes, rtime, writes, writes_merged, - wbytes, wtime, _, busy_time, _) = map(int, fields[4:14]) - elif flen == 14 or flen >= 18: - # Linux 2.6+, line referring to a disk - name = fields[2] - (reads, reads_merged, rbytes, rtime, writes, writes_merged, - wbytes, wtime, _, busy_time, _) = map(int, fields[3:14]) - elif flen == 7: - # Linux 2.6+, line referring to a partition - name = fields[2] - reads, rbytes, writes, wbytes = map(int, fields[3:]) - rtime = wtime = reads_merged = writes_merged = busy_time = 0 - else: - raise ValueError("not sure how to interpret line %r" % line) - yield (name, reads, writes, rbytes, wbytes, rtime, wtime, - reads_merged, writes_merged, busy_time) - - def read_sysfs(): - for block in os.listdir('/sys/block'): - for root, _, files in os.walk(os.path.join('/sys/block', block)): - if 'stat' not in files: - continue - with open_text(os.path.join(root, 'stat')) as f: - fields = f.read().strip().split() - name = os.path.basename(root) - (reads, reads_merged, rbytes, rtime, writes, writes_merged, - wbytes, wtime, _, busy_time) = map(int, fields[:10]) - yield (name, reads, writes, rbytes, wbytes, rtime, - wtime, reads_merged, writes_merged, busy_time) - - if os.path.exists('%s/diskstats' % get_procfs_path()): - gen = read_procfs() - elif os.path.exists('/sys/block'): - gen = read_sysfs() - else: - raise NotImplementedError( - "%s/diskstats nor /sys/block filesystem are available on this " - "system" % get_procfs_path()) - - retdict = {} - for entry in gen: - (name, reads, writes, rbytes, wbytes, rtime, wtime, reads_merged, - writes_merged, busy_time) = entry - if not perdisk and not is_storage_device(name): - # perdisk=False means we want to calculate totals so we skip - # partitions (e.g. 'sda1', 'nvme0n1p1') and only include - # base disk devices (e.g. 'sda', 'nvme0n1'). Base disks - # include a total of all their partitions + some extra size - # of their own: - # $ cat /proc/diskstats - # 259 0 sda 10485760 ... - # 259 1 sda1 5186039 ... - # 259 1 sda2 5082039 ... - # See: - # https://github.com/giampaolo/psutil/pull/1313 - continue - - rbytes *= DISK_SECTOR_SIZE - wbytes *= DISK_SECTOR_SIZE - retdict[name] = (reads, writes, rbytes, wbytes, rtime, wtime, - reads_merged, writes_merged, busy_time) - - return retdict - - -def disk_partitions(all=False): - """Return mounted disk partitions as a list of namedtuples.""" - fstypes = set() - procfs_path = get_procfs_path() - with open_text("%s/filesystems" % procfs_path) as f: - for line in f: - line = line.strip() - if not line.startswith("nodev"): - fstypes.add(line.strip()) - else: - # ignore all lines starting with "nodev" except "nodev zfs" - fstype = line.split("\t")[1] - if fstype == "zfs": - fstypes.add("zfs") - - # See: https://github.com/giampaolo/psutil/issues/1307 - if procfs_path == "/proc" and os.path.isfile('/etc/mtab'): - mounts_path = os.path.realpath("/etc/mtab") - else: - mounts_path = os.path.realpath("%s/self/mounts" % procfs_path) - - retlist = [] - partitions = cext.disk_partitions(mounts_path) - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - if device == '' or fstype not in fstypes: - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - - return retlist - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -def sensors_temperatures(): - """Return hardware (CPU and others) temperatures as a dict - including hardware name, label, current, max and critical - temperatures. - - Implementation notes: - - /sys/class/hwmon looks like the most recent interface to - retrieve this info, and this implementation relies on it - only (old distros will probably use something else) - - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon - - /sys/class/thermal/thermal_zone* is another one but it's more - difficult to parse - """ - ret = collections.defaultdict(list) - basenames = glob.glob('/sys/class/hwmon/hwmon*/temp*_*') - # CentOS has an intermediate /device directory: - # https://github.com/giampaolo/psutil/issues/971 - # https://github.com/nicolargo/glances/issues/1060 - basenames.extend(glob.glob('/sys/class/hwmon/hwmon*/device/temp*_*')) - basenames.extend(glob.glob( - '/sys/devices/platform/coretemp.*/hwmon/hwmon*/temp*_*')) - basenames = sorted(set([x.split('_')[0] for x in basenames])) - - for base in basenames: - try: - path = base + '_input' - current = float(cat(path)) / 1000.0 - path = os.path.join(os.path.dirname(base), 'name') - unit_name = cat(path, binary=False) - except (IOError, OSError, ValueError): - # A lot of things can go wrong here, so let's just skip the - # whole entry. Sure thing is Linux's /sys/class/hwmon really - # is a stinky broken mess. - # https://github.com/giampaolo/psutil/issues/1009 - # https://github.com/giampaolo/psutil/issues/1101 - # https://github.com/giampaolo/psutil/issues/1129 - # https://github.com/giampaolo/psutil/issues/1245 - # https://github.com/giampaolo/psutil/issues/1323 - continue - - high = cat(base + '_max', fallback=None) - critical = cat(base + '_crit', fallback=None) - label = cat(base + '_label', fallback='', binary=False) - - if high is not None: - try: - high = float(high) / 1000.0 - except ValueError: - high = None - if critical is not None: - try: - critical = float(critical) / 1000.0 - except ValueError: - critical = None - - ret[unit_name].append((label, current, high, critical)) - - # Indication that no sensors were detected in /sys/class/hwmon/ - if not basenames: - basenames = glob.glob('/sys/class/thermal/thermal_zone*') - basenames = sorted(set(basenames)) - - for base in basenames: - try: - path = os.path.join(base, 'temp') - current = float(cat(path)) / 1000.0 - path = os.path.join(base, 'type') - unit_name = cat(path, binary=False) - except (IOError, OSError, ValueError) as err: - debug("ignoring %r for file %r" % (err, path)) - continue - - trip_paths = glob.glob(base + '/trip_point*') - trip_points = set(['_'.join( - os.path.basename(p).split('_')[0:3]) for p in trip_paths]) - critical = None - high = None - for trip_point in trip_points: - path = os.path.join(base, trip_point + "_type") - trip_type = cat(path, fallback='', binary=False) - if trip_type == 'critical': - critical = cat(os.path.join(base, trip_point + "_temp"), - fallback=None) - elif trip_type == 'high': - high = cat(os.path.join(base, trip_point + "_temp"), - fallback=None) - - if high is not None: - try: - high = float(high) / 1000.0 - except ValueError: - high = None - if critical is not None: - try: - critical = float(critical) / 1000.0 - except ValueError: - critical = None - - ret[unit_name].append(('', current, high, critical)) - - return dict(ret) - - -def sensors_fans(): - """Return hardware fans info (for CPU and other peripherals) as a - dict including hardware label and current speed. - - Implementation notes: - - /sys/class/hwmon looks like the most recent interface to - retrieve this info, and this implementation relies on it - only (old distros will probably use something else) - - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon - """ - ret = collections.defaultdict(list) - basenames = glob.glob('/sys/class/hwmon/hwmon*/fan*_*') - if not basenames: - # CentOS has an intermediate /device directory: - # https://github.com/giampaolo/psutil/issues/971 - basenames = glob.glob('/sys/class/hwmon/hwmon*/device/fan*_*') - - basenames = sorted(set([x.split('_')[0] for x in basenames])) - for base in basenames: - try: - current = int(cat(base + '_input')) - except (IOError, OSError) as err: - warnings.warn("ignoring %r" % err, RuntimeWarning) - continue - unit_name = cat(os.path.join(os.path.dirname(base), 'name'), - binary=False) - label = cat(base + '_label', fallback='', binary=False) - ret[unit_name].append(_common.sfan(label, current)) - - return dict(ret) - - -def sensors_battery(): - """Return battery information. - Implementation note: it appears /sys/class/power_supply/BAT0/ - directory structure may vary and provide files with the same - meaning but under different names, see: - https://github.com/giampaolo/psutil/issues/966 - """ - null = object() - - def multi_cat(*paths): - """Attempt to read the content of multiple files which may - not exist. If none of them exist return None. - """ - for path in paths: - ret = cat(path, fallback=null) - if ret != null: - return int(ret) if ret.isdigit() else ret - return None - - bats = [x for x in os.listdir(POWER_SUPPLY_PATH) if x.startswith('BAT')] - if not bats: - return None - # Get the first available battery. Usually this is "BAT0", except - # some rare exceptions: - # https://github.com/giampaolo/psutil/issues/1238 - root = os.path.join(POWER_SUPPLY_PATH, sorted(bats)[0]) - - # Base metrics. - energy_now = multi_cat( - root + "/energy_now", - root + "/charge_now") - power_now = multi_cat( - root + "/power_now", - root + "/current_now") - energy_full = multi_cat( - root + "/energy_full", - root + "/charge_full") - if energy_now is None or power_now is None: - return None - - # Percent. If we have energy_full the percentage will be more - # accurate compared to reading /capacity file (float vs. int). - if energy_full is not None: - try: - percent = 100.0 * energy_now / energy_full - except ZeroDivisionError: - percent = 0.0 - else: - percent = int(cat(root + "/capacity", fallback=-1)) - if percent == -1: - return None - - # Is AC power cable plugged in? - # Note: AC0 is not always available and sometimes (e.g. CentOS7) - # it's called "AC". - power_plugged = None - online = multi_cat( - os.path.join(POWER_SUPPLY_PATH, "AC0/online"), - os.path.join(POWER_SUPPLY_PATH, "AC/online")) - if online is not None: - power_plugged = online == 1 - else: - status = cat(root + "/status", fallback="", binary=False).lower() - if status == "discharging": - power_plugged = False - elif status in ("charging", "full"): - power_plugged = True - - # Seconds left. - # Note to self: we may also calculate the charging ETA as per: - # https://github.com/thialfihar/dotfiles/blob/ - # 013937745fd9050c30146290e8f963d65c0179e6/bin/battery.py#L55 - if power_plugged: - secsleft = _common.POWER_TIME_UNLIMITED - else: - try: - secsleft = int(energy_now / power_now * 3600) - except ZeroDivisionError: - secsleft = _common.POWER_TIME_UNKNOWN - - return _common.sbattery(percent, secsleft, power_plugged) - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, tty, hostname, tstamp, user_process, pid = item - # note: the underlying C function includes entries about - # system boot, run level and others. We might want - # to use them in the future. - if not user_process: - continue - if hostname in (':0.0', ':0'): - hostname = 'localhost' - nt = _common.suser(user, tty or None, hostname, tstamp, pid) - retlist.append(nt) - return retlist - - -def boot_time(): - """Return the system boot time expressed in seconds since the epoch.""" - global BOOT_TIME - path = '%s/stat' % get_procfs_path() - with open_binary(path) as f: - for line in f: - if line.startswith(b'btime'): - ret = float(line.strip().split()[1]) - BOOT_TIME = ret - return ret - raise RuntimeError( - "line 'btime' not found in %s" % path) - - -# ===================================================================== -# --- processes -# ===================================================================== - - -def pids(): - """Returns a list of PIDs currently running on the system.""" - return [int(x) for x in os.listdir(b(get_procfs_path())) if x.isdigit()] - - -def pid_exists(pid): - """Check for the existence of a unix PID. Linux TIDs are not - supported (always return False). - """ - if not _psposix.pid_exists(pid): - return False - else: - # Linux's apparently does not distinguish between PIDs and TIDs - # (thread IDs). - # listdir("/proc") won't show any TID (only PIDs) but - # os.stat("/proc/{tid}") will succeed if {tid} exists. - # os.kill() can also be passed a TID. This is quite confusing. - # In here we want to enforce this distinction and support PIDs - # only, see: - # https://github.com/giampaolo/psutil/issues/687 - try: - # Note: already checked that this is faster than using a - # regular expr. Also (a lot) faster than doing - # 'return pid in pids()' - path = "%s/%s/status" % (get_procfs_path(), pid) - with open_binary(path) as f: - for line in f: - if line.startswith(b"Tgid:"): - tgid = int(line.split()[1]) - # If tgid and pid are the same then we're - # dealing with a process PID. - return tgid == pid - raise ValueError("'Tgid' line not found in %s" % path) - except (EnvironmentError, ValueError): - return pid in pids() - - -def ppid_map(): - """Obtain a {pid: ppid, ...} dict for all running processes in - one shot. Used to speed up Process.children(). - """ - ret = {} - procfs_path = get_procfs_path() - for pid in pids(): - try: - with open_binary("%s/%s/stat" % (procfs_path, pid)) as f: - data = f.read() - except (FileNotFoundError, ProcessLookupError): - # Note: we should be able to access /stat for all processes - # aka it's unlikely we'll bump into EPERM, which is good. - pass - else: - rpar = data.rfind(b')') - dset = data[rpar + 2:].split() - ppid = int(dset[1]) - ret[pid] = ppid - return ret - - -def wrap_exceptions(fun): - """Decorator which translates bare OSError and IOError exceptions - into NoSuchProcess and AccessDenied. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except ProcessLookupError: - raise NoSuchProcess(self.pid, self._name) - except FileNotFoundError: - if not os.path.exists("%s/%s" % (self._procfs_path, self.pid)): - raise NoSuchProcess(self.pid, self._name) - # Note: zombies will keep existing under /proc until they're - # gone so there's no way to distinguish them in here. - raise - return wrapper - - -class Process(object): - """Linux process implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - self._procfs_path = get_procfs_path() - - def _assert_alive(self): - """Raise NSP if the process disappeared on us.""" - # For those C function who do not raise NSP, possibly returning - # incorrect or incomplete result. - os.stat('%s/%s' % (self._procfs_path, self.pid)) - - @wrap_exceptions - @memoize_when_activated - def _parse_stat_file(self): - """Parse /proc/{pid}/stat file and return a dict with various - process info. - Using "man proc" as a reference: where "man proc" refers to - position N always substract 3 (e.g ppid position 4 in - 'man proc' == position 1 in here). - The return value is cached in case oneshot() ctx manager is - in use. - """ - with open_binary("%s/%s/stat" % (self._procfs_path, self.pid)) as f: - data = f.read() - # Process name is between parentheses. It can contain spaces and - # other parentheses. This is taken into account by looking for - # the first occurrence of "(" and the last occurence of ")". - rpar = data.rfind(b')') - name = data[data.find(b'(') + 1:rpar] - fields = data[rpar + 2:].split() - - ret = {} - ret['name'] = name - ret['status'] = fields[0] - ret['ppid'] = fields[1] - ret['ttynr'] = fields[4] - ret['utime'] = fields[11] - ret['stime'] = fields[12] - ret['children_utime'] = fields[13] - ret['children_stime'] = fields[14] - ret['create_time'] = fields[19] - ret['cpu_num'] = fields[36] - ret['blkio_ticks'] = fields[39] # aka 'delayacct_blkio_ticks' - - return ret - - @wrap_exceptions - @memoize_when_activated - def _read_status_file(self): - """Read /proc/{pid}/stat file and return its content. - The return value is cached in case oneshot() ctx manager is - in use. - """ - with open_binary("%s/%s/status" % (self._procfs_path, self.pid)) as f: - return f.read() - - @wrap_exceptions - @memoize_when_activated - def _read_smaps_file(self): - with open_binary("%s/%s/smaps" % (self._procfs_path, self.pid), - buffering=BIGFILE_BUFFERING) as f: - return f.read().strip() - - def oneshot_enter(self): - self._parse_stat_file.cache_activate(self) - self._read_status_file.cache_activate(self) - self._read_smaps_file.cache_activate(self) - - def oneshot_exit(self): - self._parse_stat_file.cache_deactivate(self) - self._read_status_file.cache_deactivate(self) - self._read_smaps_file.cache_deactivate(self) - - @wrap_exceptions - def name(self): - name = self._parse_stat_file()['name'] - if PY3: - name = decode(name) - # XXX - gets changed later and probably needs refactoring - return name - - def exe(self): - try: - return readlink("%s/%s/exe" % (self._procfs_path, self.pid)) - except (FileNotFoundError, ProcessLookupError): - # no such file error; might be raised also if the - # path actually exists for system processes with - # low pids (about 0-20) - if os.path.lexists("%s/%s" % (self._procfs_path, self.pid)): - return "" - else: - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - - @wrap_exceptions - def cmdline(self): - with open_text("%s/%s/cmdline" % (self._procfs_path, self.pid)) as f: - data = f.read() - if not data: - # may happen in case of zombie process - return [] - # 'man proc' states that args are separated by null bytes '\0' - # and last char is supposed to be a null byte. Nevertheless - # some processes may change their cmdline after being started - # (via setproctitle() or similar), they are usually not - # compliant with this rule and use spaces instead. Google - # Chrome process is an example. See: - # https://github.com/giampaolo/psutil/issues/1179 - sep = '\x00' if data.endswith('\x00') else ' ' - if data.endswith(sep): - data = data[:-1] - cmdline = data.split(sep) - # Sometimes last char is a null byte '\0' but the args are - # separated by spaces, see: https://github.com/giampaolo/psutil/ - # issues/1179#issuecomment-552984549 - if sep == '\x00' and len(cmdline) == 1 and ' ' in data: - cmdline = data.split(' ') - return cmdline - - @wrap_exceptions - def environ(self): - with open_text("%s/%s/environ" % (self._procfs_path, self.pid)) as f: - data = f.read() - return parse_environ_block(data) - - @wrap_exceptions - def terminal(self): - tty_nr = int(self._parse_stat_file()['ttynr']) - tmap = _psposix.get_terminal_map() - try: - return tmap[tty_nr] - except KeyError: - return None - - # May not be available on old kernels. - if os.path.exists('/proc/%s/io' % os.getpid()): - @wrap_exceptions - def io_counters(self): - fname = "%s/%s/io" % (self._procfs_path, self.pid) - fields = {} - with open_binary(fname) as f: - for line in f: - # https://github.com/giampaolo/psutil/issues/1004 - line = line.strip() - if line: - try: - name, value = line.split(b': ') - except ValueError: - # https://github.com/giampaolo/psutil/issues/1004 - continue - else: - fields[name] = int(value) - if not fields: - raise RuntimeError("%s file was empty" % fname) - try: - return pio( - fields[b'syscr'], # read syscalls - fields[b'syscw'], # write syscalls - fields[b'read_bytes'], # read bytes - fields[b'write_bytes'], # write bytes - fields[b'rchar'], # read chars - fields[b'wchar'], # write chars - ) - except KeyError as err: - raise ValueError("%r field was not found in %s; found fields " - "are %r" % (err[0], fname, fields)) - - @wrap_exceptions - def cpu_times(self): - values = self._parse_stat_file() - utime = float(values['utime']) / CLOCK_TICKS - stime = float(values['stime']) / CLOCK_TICKS - children_utime = float(values['children_utime']) / CLOCK_TICKS - children_stime = float(values['children_stime']) / CLOCK_TICKS - iowait = float(values['blkio_ticks']) / CLOCK_TICKS - return pcputimes(utime, stime, children_utime, children_stime, iowait) - - @wrap_exceptions - def cpu_num(self): - """What CPU the process is on.""" - return int(self._parse_stat_file()['cpu_num']) - - @wrap_exceptions - def wait(self, timeout=None): - return _psposix.wait_pid(self.pid, timeout, self._name) - - @wrap_exceptions - def create_time(self): - ctime = float(self._parse_stat_file()['create_time']) - # According to documentation, starttime is in field 21 and the - # unit is jiffies (clock ticks). - # We first divide it for clock ticks and then add uptime returning - # seconds since the epoch, in UTC. - # Also use cached value if available. - bt = BOOT_TIME or boot_time() - return (ctime / CLOCK_TICKS) + bt - - @wrap_exceptions - def memory_info(self): - # ============================================================ - # | FIELD | DESCRIPTION | AKA | TOP | - # ============================================================ - # | rss | resident set size | | RES | - # | vms | total program size | size | VIRT | - # | shared | shared pages (from shared mappings) | | SHR | - # | text | text ('code') | trs | CODE | - # | lib | library (unused in Linux 2.6) | lrs | | - # | data | data + stack | drs | DATA | - # | dirty | dirty pages (unused in Linux 2.6) | dt | | - # ============================================================ - with open_binary("%s/%s/statm" % (self._procfs_path, self.pid)) as f: - vms, rss, shared, text, lib, data, dirty = \ - [int(x) * PAGESIZE for x in f.readline().split()[:7]] - return pmem(rss, vms, shared, text, lib, data, dirty) - - # /proc/pid/smaps does not exist on kernels < 2.6.14 or if - # CONFIG_MMU kernel configuration option is not enabled. - if HAS_SMAPS: - - @wrap_exceptions - def memory_full_info( - self, - # Gets Private_Clean, Private_Dirty, Private_Hugetlb. - _private_re=re.compile(br"\nPrivate.*:\s+(\d+)"), - _pss_re=re.compile(br"\nPss\:\s+(\d+)"), - _swap_re=re.compile(br"\nSwap\:\s+(\d+)")): - basic_mem = self.memory_info() - # Note: using 3 regexes is faster than reading the file - # line by line. - # XXX: on Python 3 the 2 regexes are 30% slower than on - # Python 2 though. Figure out why. - # - # You might be tempted to calculate USS by subtracting - # the "shared" value from the "resident" value in - # /proc//statm. But at least on Linux, statm's "shared" - # value actually counts pages backed by files, which has - # little to do with whether the pages are actually shared. - # /proc/self/smaps on the other hand appears to give us the - # correct information. - smaps_data = self._read_smaps_file() - # Note: smaps file can be empty for certain processes. - # The code below will not crash though and will result to 0. - uss = sum(map(int, _private_re.findall(smaps_data))) * 1024 - pss = sum(map(int, _pss_re.findall(smaps_data))) * 1024 - swap = sum(map(int, _swap_re.findall(smaps_data))) * 1024 - return pfullmem(*basic_mem + (uss, pss, swap)) - - else: - memory_full_info = memory_info - - if HAS_SMAPS: - - @wrap_exceptions - def memory_maps(self): - """Return process's mapped memory regions as a list of named - tuples. Fields are explained in 'man proc'; here is an updated - (Apr 2012) version: http://goo.gl/fmebo - - /proc/{PID}/smaps does not exist on kernels < 2.6.14 or if - CONFIG_MMU kernel configuration option is not enabled. - """ - def get_blocks(lines, current_block): - data = {} - for line in lines: - fields = line.split(None, 5) - if not fields[0].endswith(b':'): - # new block section - yield (current_block.pop(), data) - current_block.append(line) - else: - try: - data[fields[0]] = int(fields[1]) * 1024 - except ValueError: - if fields[0].startswith(b'VmFlags:'): - # see issue #369 - continue - else: - raise ValueError("don't know how to inte" - "rpret line %r" % line) - yield (current_block.pop(), data) - - data = self._read_smaps_file() - # Note: smaps file can be empty for certain processes. - if not data: - return [] - lines = data.split(b'\n') - ls = [] - first_line = lines.pop(0) - current_block = [first_line] - for header, data in get_blocks(lines, current_block): - hfields = header.split(None, 5) - try: - addr, perms, offset, dev, inode, path = hfields - except ValueError: - addr, perms, offset, dev, inode, path = \ - hfields + [''] - if not path: - path = '[anon]' - else: - if PY3: - path = decode(path) - path = path.strip() - if (path.endswith(' (deleted)') and not - path_exists_strict(path)): - path = path[:-10] - ls.append(( - decode(addr), decode(perms), path, - data.get(b'Rss:', 0), - data.get(b'Size:', 0), - data.get(b'Pss:', 0), - data.get(b'Shared_Clean:', 0), - data.get(b'Shared_Dirty:', 0), - data.get(b'Private_Clean:', 0), - data.get(b'Private_Dirty:', 0), - data.get(b'Referenced:', 0), - data.get(b'Anonymous:', 0), - data.get(b'Swap:', 0) - )) - return ls - - @wrap_exceptions - def cwd(self): - try: - return readlink("%s/%s/cwd" % (self._procfs_path, self.pid)) - except (FileNotFoundError, ProcessLookupError): - # https://github.com/giampaolo/psutil/issues/986 - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - - @wrap_exceptions - def num_ctx_switches(self, - _ctxsw_re=re.compile(br'ctxt_switches:\t(\d+)')): - data = self._read_status_file() - ctxsw = _ctxsw_re.findall(data) - if not ctxsw: - raise NotImplementedError( - "'voluntary_ctxt_switches' and 'nonvoluntary_ctxt_switches'" - "lines were not found in %s/%s/status; the kernel is " - "probably older than 2.6.23" % ( - self._procfs_path, self.pid)) - else: - return _common.pctxsw(int(ctxsw[0]), int(ctxsw[1])) - - @wrap_exceptions - def num_threads(self, _num_threads_re=re.compile(br'Threads:\t(\d+)')): - # Note: on Python 3 using a re is faster than iterating over file - # line by line. On Python 2 is the exact opposite, and iterating - # over a file on Python 3 is slower than on Python 2. - data = self._read_status_file() - return int(_num_threads_re.findall(data)[0]) - - @wrap_exceptions - def threads(self): - thread_ids = os.listdir("%s/%s/task" % (self._procfs_path, self.pid)) - thread_ids.sort() - retlist = [] - hit_enoent = False - for thread_id in thread_ids: - fname = "%s/%s/task/%s/stat" % ( - self._procfs_path, self.pid, thread_id) - try: - with open_binary(fname) as f: - st = f.read().strip() - except FileNotFoundError: - # no such file or directory; it means thread - # disappeared on us - hit_enoent = True - continue - # ignore the first two values ("pid (exe)") - st = st[st.find(b')') + 2:] - values = st.split(b' ') - utime = float(values[11]) / CLOCK_TICKS - stime = float(values[12]) / CLOCK_TICKS - ntuple = _common.pthread(int(thread_id), utime, stime) - retlist.append(ntuple) - if hit_enoent: - self._assert_alive() - return retlist - - @wrap_exceptions - def nice_get(self): - # with open_text('%s/%s/stat' % (self._procfs_path, self.pid)) as f: - # data = f.read() - # return int(data.split()[18]) - - # Use C implementation - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - return cext_posix.setpriority(self.pid, value) - - # starting from CentOS 6. - if HAS_CPU_AFFINITY: - - @wrap_exceptions - def cpu_affinity_get(self): - return cext.proc_cpu_affinity_get(self.pid) - - def _get_eligible_cpus( - self, _re=re.compile(br"Cpus_allowed_list:\t(\d+)-(\d+)")): - # See: https://github.com/giampaolo/psutil/issues/956 - data = self._read_status_file() - match = _re.findall(data) - if match: - return list(range(int(match[0][0]), int(match[0][1]) + 1)) - else: - return list(range(len(per_cpu_times()))) - - @wrap_exceptions - def cpu_affinity_set(self, cpus): - try: - cext.proc_cpu_affinity_set(self.pid, cpus) - except (OSError, ValueError) as err: - if isinstance(err, ValueError) or err.errno == errno.EINVAL: - eligible_cpus = self._get_eligible_cpus() - all_cpus = tuple(range(len(per_cpu_times()))) - for cpu in cpus: - if cpu not in all_cpus: - raise ValueError( - "invalid CPU number %r; choose between %s" % ( - cpu, eligible_cpus)) - if cpu not in eligible_cpus: - raise ValueError( - "CPU number %r is not eligible; choose " - "between %s" % (cpu, eligible_cpus)) - raise - - # only starting from kernel 2.6.13 - if HAS_PROC_IO_PRIORITY: - - @wrap_exceptions - def ionice_get(self): - ioclass, value = cext.proc_ioprio_get(self.pid) - if enum is not None: - ioclass = IOPriority(ioclass) - return _common.pionice(ioclass, value) - - @wrap_exceptions - def ionice_set(self, ioclass, value): - if value is None: - value = 0 - if value and ioclass in (IOPRIO_CLASS_IDLE, IOPRIO_CLASS_NONE): - raise ValueError("%r ioclass accepts no value" % ioclass) - if value < 0 or value > 7: - raise ValueError("value not in 0-7 range") - return cext.proc_ioprio_set(self.pid, ioclass, value) - - if HAS_PRLIMIT: - - @wrap_exceptions - def rlimit(self, resource, limits=None): - # If pid is 0 prlimit() applies to the calling process and - # we don't want that. We should never get here though as - # PID 0 is not supported on Linux. - if self.pid == 0: - raise ValueError("can't use prlimit() against PID 0 process") - try: - if limits is None: - # get - return cext.linux_prlimit(self.pid, resource) - else: - # set - if len(limits) != 2: - raise ValueError( - "second argument must be a (soft, hard) tuple, " - "got %s" % repr(limits)) - soft, hard = limits - cext.linux_prlimit(self.pid, resource, soft, hard) - except OSError as err: - if err.errno == errno.ENOSYS and pid_exists(self.pid): - # I saw this happening on Travis: - # https://travis-ci.org/giampaolo/psutil/jobs/51368273 - raise ZombieProcess(self.pid, self._name, self._ppid) - else: - raise - - @wrap_exceptions - def status(self): - letter = self._parse_stat_file()['status'] - if PY3: - letter = letter.decode() - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(letter, '?') - - @wrap_exceptions - def open_files(self): - retlist = [] - files = os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)) - hit_enoent = False - for fd in files: - file = "%s/%s/fd/%s" % (self._procfs_path, self.pid, fd) - try: - path = readlink(file) - except (FileNotFoundError, ProcessLookupError): - # ENOENT == file which is gone in the meantime - hit_enoent = True - continue - except OSError as err: - if err.errno == errno.EINVAL: - # not a link - continue - raise - else: - # If path is not an absolute there's no way to tell - # whether it's a regular file or not, so we skip it. - # A regular file is always supposed to be have an - # absolute path though. - if path.startswith('/') and isfile_strict(path): - # Get file position and flags. - file = "%s/%s/fdinfo/%s" % ( - self._procfs_path, self.pid, fd) - try: - with open_binary(file) as f: - pos = int(f.readline().split()[1]) - flags = int(f.readline().split()[1], 8) - except FileNotFoundError: - # fd gone in the meantime; process may - # still be alive - hit_enoent = True - else: - mode = file_flags_to_mode(flags) - ntuple = popenfile( - path, int(fd), int(pos), mode, flags) - retlist.append(ntuple) - if hit_enoent: - self._assert_alive() - return retlist - - @wrap_exceptions - def connections(self, kind='inet'): - ret = _connections.retrieve(kind, self.pid) - self._assert_alive() - return ret - - @wrap_exceptions - def num_fds(self): - return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))) - - @wrap_exceptions - def ppid(self): - return int(self._parse_stat_file()['ppid']) - - @wrap_exceptions - def uids(self, _uids_re=re.compile(br'Uid:\t(\d+)\t(\d+)\t(\d+)')): - data = self._read_status_file() - real, effective, saved = _uids_re.findall(data)[0] - return _common.puids(int(real), int(effective), int(saved)) - - @wrap_exceptions - def gids(self, _gids_re=re.compile(br'Gid:\t(\d+)\t(\d+)\t(\d+)')): - data = self._read_status_file() - real, effective, saved = _gids_re.findall(data)[0] - return _common.pgids(int(real), int(effective), int(saved)) diff --git a/third_party/python/psutil/psutil/_psosx.py b/third_party/python/psutil/psutil/_psosx.py deleted file mode 100644 index e4296495c45b..000000000000 --- a/third_party/python/psutil/psutil/_psosx.py +++ /dev/null @@ -1,564 +0,0 @@ -# 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. - -"""macOS platform implementation.""" - -import contextlib -import errno -import functools -import os -from collections import namedtuple - -from . import _common -from . import _psposix -from . import _psutil_osx as cext -from . import _psutil_posix as cext_posix -from ._common import AccessDenied -from ._common import conn_tmap -from ._common import conn_to_ntuple -from ._common import isfile_strict -from ._common import memoize_when_activated -from ._common import NoSuchProcess -from ._common import parse_environ_block -from ._common import usage_percent -from ._common import ZombieProcess -from ._compat import PermissionError -from ._compat import ProcessLookupError - - -__extra__all__ = [] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -PAGESIZE = os.sysconf("SC_PAGE_SIZE") -AF_LINK = cext_posix.AF_LINK - -TCP_STATUSES = { - cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, - cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, - cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV, - cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, - cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, - cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.TCPS_CLOSED: _common.CONN_CLOSE, - cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, - cext.TCPS_LISTEN: _common.CONN_LISTEN, - cext.TCPS_CLOSING: _common.CONN_CLOSING, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -PROC_STATUSES = { - cext.SIDL: _common.STATUS_IDLE, - cext.SRUN: _common.STATUS_RUNNING, - cext.SSLEEP: _common.STATUS_SLEEPING, - cext.SSTOP: _common.STATUS_STOPPED, - cext.SZOMB: _common.STATUS_ZOMBIE, -} - -kinfo_proc_map = dict( - ppid=0, - ruid=1, - euid=2, - suid=3, - rgid=4, - egid=5, - sgid=6, - ttynr=7, - ctime=8, - status=9, - name=10, -) - -pidtaskinfo_map = dict( - cpuutime=0, - cpustime=1, - rss=2, - vms=3, - pfaults=4, - pageins=5, - numthreads=6, - volctxsw=7, -) - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.cpu_times() -scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle']) -# psutil.virtual_memory() -svmem = namedtuple( - 'svmem', ['total', 'available', 'percent', 'used', 'free', - 'active', 'inactive', 'wired']) -# psutil.Process.memory_info() -pmem = namedtuple('pmem', ['rss', 'vms', 'pfaults', 'pageins']) -# psutil.Process.memory_full_info() -pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', )) - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - """System virtual memory as a namedtuple.""" - total, active, inactive, wired, free, speculative = cext.virtual_mem() - # This is how Zabbix calculate avail and used mem: - # https://github.com/zabbix/zabbix/blob/trunk/src/libs/zbxsysinfo/ - # osx/memory.c - # Also see: https://github.com/giampaolo/psutil/issues/1277 - avail = inactive + free - used = active + wired - # This is NOT how Zabbix calculates free mem but it matches "free" - # cmdline utility. - free -= speculative - percent = usage_percent((total - avail), total, round_=1) - return svmem(total, avail, percent, used, free, - active, inactive, wired) - - -def swap_memory(): - """Swap system memory as a (total, used, free, sin, sout) tuple.""" - total, used, free, sin, sout = cext.swap_mem() - percent = usage_percent(used, total, round_=1) - return _common.sswap(total, used, free, percent, sin, sout) - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return system CPU times as a namedtuple.""" - user, nice, system, idle = cext.cpu_times() - return scputimes(user, nice, system, idle) - - -def per_cpu_times(): - """Return system CPU times as a named tuple""" - ret = [] - for cpu_t in cext.per_cpu_times(): - user, nice, system, idle = cpu_t - item = scputimes(user, nice, system, idle) - ret.append(item) - return ret - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - return cext.cpu_count_logical() - - -def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" - return cext.cpu_count_phys() - - -def cpu_stats(): - ctx_switches, interrupts, soft_interrupts, syscalls, traps = \ - cext.cpu_stats() - return _common.scpustats( - ctx_switches, interrupts, soft_interrupts, syscalls) - - -def cpu_freq(): - """Return CPU frequency. - On macOS per-cpu frequency is not supported. - Also, the returned frequency never changes, see: - https://arstechnica.com/civis/viewtopic.php?f=19&t=465002 - """ - curr, min_, max_ = cext.cpu_freq() - return [_common.scpufreq(curr, min_, max_)] - - -# ===================================================================== -# --- disks -# ===================================================================== - - -disk_usage = _psposix.disk_usage -disk_io_counters = cext.disk_io_counters - - -def disk_partitions(all=False): - """Return mounted disk partitions as a list of namedtuples.""" - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - if not os.path.isabs(device) or not os.path.exists(device): - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -def sensors_battery(): - """Return battery information.""" - try: - percent, minsleft, power_plugged = cext.sensors_battery() - except NotImplementedError: - # no power source - return None according to interface - return None - power_plugged = power_plugged == 1 - if power_plugged: - secsleft = _common.POWER_TIME_UNLIMITED - elif minsleft == -1: - secsleft = _common.POWER_TIME_UNKNOWN - else: - secsleft = minsleft * 60 - return _common.sbattery(percent, secsleft, power_plugged) - - -# ===================================================================== -# --- network -# ===================================================================== - - -net_io_counters = cext.net_io_counters -net_if_addrs = cext_posix.net_if_addrs - - -def net_connections(kind='inet'): - """System-wide network connections.""" - # Note: on macOS this will fail with AccessDenied unless - # the process is owned by root. - ret = [] - for pid in pids(): - try: - cons = Process(pid).connections(kind) - except NoSuchProcess: - continue - else: - if cons: - for c in cons: - c = list(c) + [pid] - ret.append(_common.sconn(*c)) - return ret - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - names = net_io_counters().keys() - ret = {} - for name in names: - try: - mtu = cext_posix.net_if_mtu(name) - isup = cext_posix.net_if_flags(name) - duplex, speed = cext_posix.net_if_duplex_speed(name) - except OSError as err: - # https://github.com/giampaolo/psutil/issues/1279 - if err.errno != errno.ENODEV: - raise - else: - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, tty, hostname, tstamp, pid = item - if tty == '~': - continue # reboot or shutdown - if not tstamp: - continue - nt = _common.suser(user, tty or None, hostname or None, tstamp, pid) - retlist.append(nt) - return retlist - - -# ===================================================================== -# --- processes -# ===================================================================== - - -def pids(): - ls = cext.pids() - if 0 not in ls: - # On certain macOS versions pids() C doesn't return PID 0 but - # "ps" does and the process is querable via sysctl(): - # https://travis-ci.org/giampaolo/psutil/jobs/309619941 - try: - Process(0).create_time() - ls.insert(0, 0) - except NoSuchProcess: - pass - except AccessDenied: - ls.insert(0, 0) - return ls - - -pid_exists = _psposix.pid_exists - - -def wrap_exceptions(fun): - """Decorator which translates bare OSError exceptions into - NoSuchProcess and AccessDenied. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except ProcessLookupError: - raise NoSuchProcess(self.pid, self._name) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except cext.ZombieProcessError: - raise ZombieProcess(self.pid, self._name, self._ppid) - return wrapper - - -@contextlib.contextmanager -def catch_zombie(proc): - """There are some poor C APIs which incorrectly raise ESRCH when - the process is still alive or it's a zombie, or even RuntimeError - (those who don't set errno). This is here in order to solve: - https://github.com/giampaolo/psutil/issues/1044 - """ - try: - yield - except (OSError, RuntimeError) as err: - if isinstance(err, RuntimeError) or err.errno == errno.ESRCH: - try: - # status() is not supposed to lie and correctly detect - # zombies so if it raises ESRCH it's true. - status = proc.status() - except NoSuchProcess: - raise err - else: - if status == _common.STATUS_ZOMBIE: - raise ZombieProcess(proc.pid, proc._name, proc._ppid) - else: - raise AccessDenied(proc.pid, proc._name) - else: - raise - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - @wrap_exceptions - @memoize_when_activated - def _get_kinfo_proc(self): - # Note: should work with all PIDs without permission issues. - ret = cext.proc_kinfo_oneshot(self.pid) - assert len(ret) == len(kinfo_proc_map) - return ret - - @wrap_exceptions - @memoize_when_activated - def _get_pidtaskinfo(self): - # Note: should work for PIDs owned by user only. - with catch_zombie(self): - ret = cext.proc_pidtaskinfo_oneshot(self.pid) - assert len(ret) == len(pidtaskinfo_map) - return ret - - def oneshot_enter(self): - self._get_kinfo_proc.cache_activate(self) - self._get_pidtaskinfo.cache_activate(self) - - def oneshot_exit(self): - self._get_kinfo_proc.cache_deactivate(self) - self._get_pidtaskinfo.cache_deactivate(self) - - @wrap_exceptions - def name(self): - name = self._get_kinfo_proc()[kinfo_proc_map['name']] - return name if name is not None else cext.proc_name(self.pid) - - @wrap_exceptions - def exe(self): - with catch_zombie(self): - return cext.proc_exe(self.pid) - - @wrap_exceptions - def cmdline(self): - with catch_zombie(self): - return cext.proc_cmdline(self.pid) - - @wrap_exceptions - def environ(self): - with catch_zombie(self): - return parse_environ_block(cext.proc_environ(self.pid)) - - @wrap_exceptions - def ppid(self): - self._ppid = self._get_kinfo_proc()[kinfo_proc_map['ppid']] - return self._ppid - - @wrap_exceptions - def cwd(self): - with catch_zombie(self): - return cext.proc_cwd(self.pid) - - @wrap_exceptions - def uids(self): - rawtuple = self._get_kinfo_proc() - return _common.puids( - rawtuple[kinfo_proc_map['ruid']], - rawtuple[kinfo_proc_map['euid']], - rawtuple[kinfo_proc_map['suid']]) - - @wrap_exceptions - def gids(self): - rawtuple = self._get_kinfo_proc() - return _common.puids( - rawtuple[kinfo_proc_map['rgid']], - rawtuple[kinfo_proc_map['egid']], - rawtuple[kinfo_proc_map['sgid']]) - - @wrap_exceptions - def terminal(self): - tty_nr = self._get_kinfo_proc()[kinfo_proc_map['ttynr']] - tmap = _psposix.get_terminal_map() - try: - return tmap[tty_nr] - except KeyError: - return None - - @wrap_exceptions - def memory_info(self): - rawtuple = self._get_pidtaskinfo() - return pmem( - rawtuple[pidtaskinfo_map['rss']], - rawtuple[pidtaskinfo_map['vms']], - rawtuple[pidtaskinfo_map['pfaults']], - rawtuple[pidtaskinfo_map['pageins']], - ) - - @wrap_exceptions - def memory_full_info(self): - basic_mem = self.memory_info() - uss = cext.proc_memory_uss(self.pid) - return pfullmem(*basic_mem + (uss, )) - - @wrap_exceptions - def cpu_times(self): - rawtuple = self._get_pidtaskinfo() - return _common.pcputimes( - rawtuple[pidtaskinfo_map['cpuutime']], - rawtuple[pidtaskinfo_map['cpustime']], - # children user / system times are not retrievable (set to 0) - 0.0, 0.0) - - @wrap_exceptions - def create_time(self): - return self._get_kinfo_proc()[kinfo_proc_map['ctime']] - - @wrap_exceptions - def num_ctx_switches(self): - # Unvoluntary value seems not to be available; - # getrusage() numbers seems to confirm this theory. - # We set it to 0. - vol = self._get_pidtaskinfo()[pidtaskinfo_map['volctxsw']] - return _common.pctxsw(vol, 0) - - @wrap_exceptions - def num_threads(self): - return self._get_pidtaskinfo()[pidtaskinfo_map['numthreads']] - - @wrap_exceptions - def open_files(self): - if self.pid == 0: - return [] - files = [] - with catch_zombie(self): - rawlist = cext.proc_open_files(self.pid) - for path, fd in rawlist: - if isfile_strict(path): - ntuple = _common.popenfile(path, fd) - files.append(ntuple) - return files - - @wrap_exceptions - def connections(self, kind='inet'): - if kind not in conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - families, types = conn_tmap[kind] - with catch_zombie(self): - rawlist = cext.proc_connections(self.pid, families, types) - ret = [] - for item in rawlist: - fd, fam, type, laddr, raddr, status = item - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, - TCP_STATUSES) - ret.append(nt) - return ret - - @wrap_exceptions - def num_fds(self): - if self.pid == 0: - return 0 - with catch_zombie(self): - return cext.proc_num_fds(self.pid) - - @wrap_exceptions - def wait(self, timeout=None): - return _psposix.wait_pid(self.pid, timeout, self._name) - - @wrap_exceptions - def nice_get(self): - with catch_zombie(self): - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - with catch_zombie(self): - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def status(self): - code = self._get_kinfo_proc()[kinfo_proc_map['status']] - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(code, '?') - - @wrap_exceptions - def threads(self): - rawlist = cext.proc_threads(self.pid) - retlist = [] - for thread_id, utime, stime in rawlist: - ntuple = _common.pthread(thread_id, utime, stime) - retlist.append(ntuple) - return retlist diff --git a/third_party/python/psutil/psutil/_psposix.py b/third_party/python/psutil/psutil/_psposix.py deleted file mode 100644 index 88213ef8b641..000000000000 --- a/third_party/python/psutil/psutil/_psposix.py +++ /dev/null @@ -1,175 +0,0 @@ -# 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 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 - - -__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 <> 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 - - -def wait_pid(pid, timeout=None, proc_name=None): - """Wait for process with pid 'pid' to terminate and return its - exit status code as an integer. - - If pid is not a children of os.getpid() (current process) just - waits until the process disappears and return None. - - If pid does not exist at all return None immediately. - - Raise TimeoutExpired on timeout expired. - """ - def check_timeout(delay): - if timeout is not None: - if timer() >= stop_at: - raise TimeoutExpired(timeout, pid=pid, name=proc_name) - time.sleep(delay) - return min(delay * 2, 0.04) - - timer = getattr(time, 'monotonic', time.time) - if timeout is not None: - def waitcall(): - return os.waitpid(pid, os.WNOHANG) - stop_at = timer() + timeout - else: - def waitcall(): - return os.waitpid(pid, 0) - - delay = 0.0001 - while True: - try: - retpid, status = waitcall() - except InterruptedError: - delay = check_timeout(delay) - 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 True: - if pid_exists(pid): - delay = check_timeout(delay) - else: - return - else: - if retpid == 0: - # WNOHANG was used, pid is still running - delay = check_timeout(delay) - continue - # process exited due to a signal; return the integer of - # that signal - if os.WIFSIGNALED(status): - return -os.WTERMSIG(status) - # process exited using exit(2) system call; return the - # integer exit(2) system call has been called with - elif os.WIFEXITED(status): - return os.WEXITSTATUS(status) - 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 diff --git a/third_party/python/psutil/psutil/_pssunos.py b/third_party/python/psutil/psutil/_pssunos.py deleted file mode 100644 index 62362b89c631..000000000000 --- a/third_party/python/psutil/psutil/_pssunos.py +++ /dev/null @@ -1,725 +0,0 @@ -# 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. - -"""Sun OS Solaris platform implementation.""" - -import errno -import functools -import os -import socket -import subprocess -import sys -from collections import namedtuple -from socket import AF_INET - -from . import _common -from . import _psposix -from . import _psutil_posix as cext_posix -from . import _psutil_sunos as cext -from ._common import AccessDenied -from ._common import AF_INET6 -from ._common import debug -from ._common import get_procfs_path -from ._common import isfile_strict -from ._common import memoize_when_activated -from ._common import NoSuchProcess -from ._common import sockfam_to_enum -from ._common import socktype_to_enum -from ._common import usage_percent -from ._common import ZombieProcess -from ._compat import b -from ._compat import FileNotFoundError -from ._compat import PermissionError -from ._compat import ProcessLookupError -from ._compat import PY3 - - -__extra__all__ = ["CONN_IDLE", "CONN_BOUND", "PROCFS_PATH"] - - -# ===================================================================== -# --- globals -# ===================================================================== - - -PAGE_SIZE = os.sysconf('SC_PAGE_SIZE') -AF_LINK = cext_posix.AF_LINK -IS_64_BIT = sys.maxsize > 2**32 - -CONN_IDLE = "IDLE" -CONN_BOUND = "BOUND" - -PROC_STATUSES = { - cext.SSLEEP: _common.STATUS_SLEEPING, - cext.SRUN: _common.STATUS_RUNNING, - cext.SZOMB: _common.STATUS_ZOMBIE, - cext.SSTOP: _common.STATUS_STOPPED, - cext.SIDL: _common.STATUS_IDLE, - cext.SONPROC: _common.STATUS_RUNNING, # same as run - cext.SWAIT: _common.STATUS_WAITING, -} - -TCP_STATUSES = { - cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, - cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, - cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV, - cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, - cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, - cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.TCPS_CLOSED: _common.CONN_CLOSE, - cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, - cext.TCPS_LISTEN: _common.CONN_LISTEN, - cext.TCPS_CLOSING: _common.CONN_CLOSING, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, - cext.TCPS_IDLE: CONN_IDLE, # sunos specific - cext.TCPS_BOUND: CONN_BOUND, # sunos specific -} - -proc_info_map = dict( - ppid=0, - rss=1, - vms=2, - create_time=3, - nice=4, - num_threads=5, - status=6, - ttynr=7, - uid=8, - euid=9, - gid=10, - egid=11) - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.cpu_times() -scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait']) -# psutil.cpu_times(percpu=True) -pcputimes = namedtuple('pcputimes', - ['user', 'system', 'children_user', 'children_system']) -# psutil.virtual_memory() -svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) -# psutil.Process.memory_info() -pmem = namedtuple('pmem', ['rss', 'vms']) -pfullmem = pmem -# psutil.Process.memory_maps(grouped=True) -pmmap_grouped = namedtuple('pmmap_grouped', - ['path', 'rss', 'anonymous', 'locked']) -# psutil.Process.memory_maps(grouped=False) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - """Report virtual memory metrics.""" - # we could have done this with kstat, but IMHO this is good enough - total = os.sysconf('SC_PHYS_PAGES') * PAGE_SIZE - # note: there's no difference on Solaris - free = avail = os.sysconf('SC_AVPHYS_PAGES') * PAGE_SIZE - used = total - free - percent = usage_percent(used, total, round_=1) - return svmem(total, avail, percent, used, free) - - -def swap_memory(): - """Report swap memory metrics.""" - sin, sout = cext.swap_mem() - # XXX - # we are supposed to get total/free by doing so: - # http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/ - # usr/src/cmd/swap/swap.c - # ...nevertheless I can't manage to obtain the same numbers as 'swap' - # cmdline utility, so let's parse its output (sigh!) - p = subprocess.Popen(['/usr/bin/env', 'PATH=/usr/sbin:/sbin:%s' % - os.environ['PATH'], 'swap', '-l'], - stdout=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout = stdout.decode(sys.stdout.encoding) - if p.returncode != 0: - raise RuntimeError("'swap -l' failed (retcode=%s)" % p.returncode) - - lines = stdout.strip().split('\n')[1:] - if not lines: - raise RuntimeError('no swap device(s) configured') - total = free = 0 - for line in lines: - line = line.split() - t, f = line[-2:] - total += int(int(t) * 512) - free += int(int(f) * 512) - used = total - free - percent = usage_percent(used, total, round_=1) - return _common.sswap(total, used, free, percent, - sin * PAGE_SIZE, sout * PAGE_SIZE) - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return system-wide CPU times as a named tuple""" - ret = cext.per_cpu_times() - return scputimes(*[sum(x) for x in zip(*ret)]) - - -def per_cpu_times(): - """Return system per-CPU times as a list of named tuples""" - ret = cext.per_cpu_times() - return [scputimes(*x) for x in ret] - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - try: - return os.sysconf("SC_NPROCESSORS_ONLN") - except ValueError: - # mimic os.cpu_count() behavior - return None - - -def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" - return cext.cpu_count_phys() - - -def cpu_stats(): - """Return various CPU stats as a named tuple.""" - ctx_switches, interrupts, syscalls, traps = cext.cpu_stats() - soft_interrupts = 0 - return _common.scpustats(ctx_switches, interrupts, soft_interrupts, - syscalls) - - -# ===================================================================== -# --- disks -# ===================================================================== - - -disk_io_counters = cext.disk_io_counters -disk_usage = _psposix.disk_usage - - -def disk_partitions(all=False): - """Return system disk partitions.""" - # TODO - the filtering logic should be better checked so that - # it tries to reflect 'df' as much as possible - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - # Differently from, say, Linux, we don't have a list of - # common fs types so the best we can do, AFAIK, is to - # filter by filesystem having a total size > 0. - try: - if not disk_usage(mountpoint).total: - continue - except OSError as err: - # https://github.com/giampaolo/psutil/issues/1674 - debug("skipping %r: %r" % (mountpoint, err)) - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -# ===================================================================== -# --- network -# ===================================================================== - - -net_io_counters = cext.net_io_counters -net_if_addrs = cext_posix.net_if_addrs - - -def net_connections(kind, _pid=-1): - """Return socket connections. If pid == -1 return system-wide - connections (as opposed to connections opened by one process only). - Only INET sockets are returned (UNIX are not). - """ - cmap = _common.conn_tmap.copy() - if _pid == -1: - cmap.pop('unix', 0) - if kind not in cmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in cmap]))) - families, types = _common.conn_tmap[kind] - rawlist = cext.net_connections(_pid) - ret = set() - for item in rawlist: - fd, fam, type_, laddr, raddr, status, pid = item - if fam not in families: - continue - if type_ not in types: - continue - # TODO: refactor and use _common.conn_to_ntuple. - if fam in (AF_INET, AF_INET6): - if laddr: - laddr = _common.addr(*laddr) - if raddr: - raddr = _common.addr(*raddr) - status = TCP_STATUSES[status] - fam = sockfam_to_enum(fam) - type_ = socktype_to_enum(type_) - if _pid == -1: - nt = _common.sconn(fd, fam, type_, laddr, raddr, status, pid) - else: - nt = _common.pconn(fd, fam, type_, laddr, raddr, status) - ret.add(nt) - return list(ret) - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - ret = cext.net_if_stats() - for name, items in ret.items(): - isup, duplex, speed, mtu = items - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - localhost = (':0.0', ':0') - for item in rawlist: - user, tty, hostname, tstamp, user_process, pid = item - # note: the underlying C function includes entries about - # system boot, run level and others. We might want - # to use them in the future. - if not user_process: - continue - if hostname in localhost: - hostname = 'localhost' - nt = _common.suser(user, tty, hostname, tstamp, pid) - retlist.append(nt) - return retlist - - -# ===================================================================== -# --- processes -# ===================================================================== - - -def pids(): - """Returns a list of PIDs currently running on the system.""" - return [int(x) for x in os.listdir(b(get_procfs_path())) if x.isdigit()] - - -def pid_exists(pid): - """Check for the existence of a unix pid.""" - return _psposix.pid_exists(pid) - - -def wrap_exceptions(fun): - """Call callable into a try/except clause and translate ENOENT, - EACCES and EPERM in NoSuchProcess or AccessDenied exceptions. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except (FileNotFoundError, ProcessLookupError): - # ENOENT (no such file or directory) gets raised on open(). - # ESRCH (no such process) can get raised on read() if - # process is gone in meantime. - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - except PermissionError: - raise AccessDenied(self.pid, self._name) - except OSError: - if self.pid == 0: - if 0 in pids(): - raise AccessDenied(self.pid, self._name) - else: - raise - raise - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - self._procfs_path = get_procfs_path() - - def _assert_alive(self): - """Raise NSP if the process disappeared on us.""" - # For those C function who do not raise NSP, possibly returning - # incorrect or incomplete result. - os.stat('%s/%s' % (self._procfs_path, self.pid)) - - def oneshot_enter(self): - self._proc_name_and_args.cache_activate(self) - self._proc_basic_info.cache_activate(self) - self._proc_cred.cache_activate(self) - - def oneshot_exit(self): - self._proc_name_and_args.cache_deactivate(self) - self._proc_basic_info.cache_deactivate(self) - self._proc_cred.cache_deactivate(self) - - @wrap_exceptions - @memoize_when_activated - def _proc_name_and_args(self): - return cext.proc_name_and_args(self.pid, self._procfs_path) - - @wrap_exceptions - @memoize_when_activated - def _proc_basic_info(self): - if self.pid == 0 and not \ - os.path.exists('%s/%s/psinfo' % (self._procfs_path, self.pid)): - raise AccessDenied(self.pid) - ret = cext.proc_basic_info(self.pid, self._procfs_path) - assert len(ret) == len(proc_info_map) - return ret - - @wrap_exceptions - @memoize_when_activated - def _proc_cred(self): - return cext.proc_cred(self.pid, self._procfs_path) - - @wrap_exceptions - def name(self): - # note: max len == 15 - return self._proc_name_and_args()[0] - - @wrap_exceptions - def exe(self): - try: - return os.readlink( - "%s/%s/path/a.out" % (self._procfs_path, self.pid)) - except OSError: - pass # continue and guess the exe name from the cmdline - # Will be guessed later from cmdline but we want to explicitly - # invoke cmdline here in order to get an AccessDenied - # exception if the user has not enough privileges. - self.cmdline() - return "" - - @wrap_exceptions - def cmdline(self): - return self._proc_name_and_args()[1].split(' ') - - @wrap_exceptions - def environ(self): - return cext.proc_environ(self.pid, self._procfs_path) - - @wrap_exceptions - def create_time(self): - return self._proc_basic_info()[proc_info_map['create_time']] - - @wrap_exceptions - def num_threads(self): - return self._proc_basic_info()[proc_info_map['num_threads']] - - @wrap_exceptions - def nice_get(self): - # Note #1: getpriority(3) doesn't work for realtime processes. - # Psinfo is what ps uses, see: - # https://github.com/giampaolo/psutil/issues/1194 - return self._proc_basic_info()[proc_info_map['nice']] - - @wrap_exceptions - def nice_set(self, value): - if self.pid in (2, 3): - # Special case PIDs: internally setpriority(3) return ESRCH - # (no such process), no matter what. - # The process actually exists though, as it has a name, - # creation time, etc. - raise AccessDenied(self.pid, self._name) - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def ppid(self): - self._ppid = self._proc_basic_info()[proc_info_map['ppid']] - return self._ppid - - @wrap_exceptions - def uids(self): - try: - real, effective, saved, _, _, _ = self._proc_cred() - except AccessDenied: - real = self._proc_basic_info()[proc_info_map['uid']] - effective = self._proc_basic_info()[proc_info_map['euid']] - saved = None - return _common.puids(real, effective, saved) - - @wrap_exceptions - def gids(self): - try: - _, _, _, real, effective, saved = self._proc_cred() - except AccessDenied: - real = self._proc_basic_info()[proc_info_map['gid']] - effective = self._proc_basic_info()[proc_info_map['egid']] - saved = None - return _common.puids(real, effective, saved) - - @wrap_exceptions - def cpu_times(self): - try: - times = cext.proc_cpu_times(self.pid, self._procfs_path) - except OSError as err: - if err.errno == errno.EOVERFLOW and not IS_64_BIT: - # We may get here if we attempt to query a 64bit process - # with a 32bit python. - # Error originates from read() and also tools like "cat" - # fail in the same way (!). - # Since there simply is no way to determine CPU times we - # return 0.0 as a fallback. See: - # https://github.com/giampaolo/psutil/issues/857 - times = (0.0, 0.0, 0.0, 0.0) - else: - raise - return _common.pcputimes(*times) - - @wrap_exceptions - def cpu_num(self): - return cext.proc_cpu_num(self.pid, self._procfs_path) - - @wrap_exceptions - def terminal(self): - procfs_path = self._procfs_path - hit_enoent = False - tty = wrap_exceptions( - self._proc_basic_info()[proc_info_map['ttynr']]) - if tty != cext.PRNODEV: - for x in (0, 1, 2, 255): - try: - return os.readlink( - '%s/%d/path/%d' % (procfs_path, self.pid, x)) - except FileNotFoundError: - hit_enoent = True - continue - if hit_enoent: - self._assert_alive() - - @wrap_exceptions - def cwd(self): - # /proc/PID/path/cwd may not be resolved by readlink() even if - # it exists (ls shows it). If that's the case and the process - # is still alive return None (we can return None also on BSD). - # Reference: http://goo.gl/55XgO - procfs_path = self._procfs_path - try: - return os.readlink("%s/%s/path/cwd" % (procfs_path, self.pid)) - except FileNotFoundError: - os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD - return None - - @wrap_exceptions - def memory_info(self): - ret = self._proc_basic_info() - rss = ret[proc_info_map['rss']] * 1024 - vms = ret[proc_info_map['vms']] * 1024 - return pmem(rss, vms) - - memory_full_info = memory_info - - @wrap_exceptions - def status(self): - code = self._proc_basic_info()[proc_info_map['status']] - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(code, '?') - - @wrap_exceptions - def threads(self): - procfs_path = self._procfs_path - ret = [] - tids = os.listdir('%s/%d/lwp' % (procfs_path, self.pid)) - hit_enoent = False - for tid in tids: - tid = int(tid) - try: - utime, stime = cext.query_process_thread( - self.pid, tid, procfs_path) - except EnvironmentError as err: - if err.errno == errno.EOVERFLOW and not IS_64_BIT: - # We may get here if we attempt to query a 64bit process - # with a 32bit python. - # Error originates from read() and also tools like "cat" - # fail in the same way (!). - # Since there simply is no way to determine CPU times we - # return 0.0 as a fallback. See: - # https://github.com/giampaolo/psutil/issues/857 - continue - # ENOENT == thread gone in meantime - if err.errno == errno.ENOENT: - hit_enoent = True - continue - raise - else: - nt = _common.pthread(tid, utime, stime) - ret.append(nt) - if hit_enoent: - self._assert_alive() - return ret - - @wrap_exceptions - def open_files(self): - retlist = [] - hit_enoent = False - procfs_path = self._procfs_path - pathdir = '%s/%d/path' % (procfs_path, self.pid) - for fd in os.listdir('%s/%d/fd' % (procfs_path, self.pid)): - path = os.path.join(pathdir, fd) - if os.path.islink(path): - try: - file = os.readlink(path) - except FileNotFoundError: - hit_enoent = True - continue - else: - if isfile_strict(file): - retlist.append(_common.popenfile(file, int(fd))) - if hit_enoent: - self._assert_alive() - return retlist - - def _get_unix_sockets(self, pid): - """Get UNIX sockets used by process by parsing 'pfiles' output.""" - # TODO: rewrite this in C (...but the damn netstat source code - # does not include this part! Argh!!) - cmd = "pfiles %s" % pid - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout, stderr = [x.decode(sys.stdout.encoding) - for x in (stdout, stderr)] - if p.returncode != 0: - if 'permission denied' in stderr.lower(): - raise AccessDenied(self.pid, self._name) - if 'no such process' in stderr.lower(): - raise NoSuchProcess(self.pid, self._name) - raise RuntimeError("%r command error\n%s" % (cmd, stderr)) - - lines = stdout.split('\n')[2:] - for i, line in enumerate(lines): - line = line.lstrip() - if line.startswith('sockname: AF_UNIX'): - path = line.split(' ', 2)[2] - type = lines[i - 2].strip() - if type == 'SOCK_STREAM': - type = socket.SOCK_STREAM - elif type == 'SOCK_DGRAM': - type = socket.SOCK_DGRAM - else: - type = -1 - yield (-1, socket.AF_UNIX, type, path, "", _common.CONN_NONE) - - @wrap_exceptions - def connections(self, kind='inet'): - ret = net_connections(kind, _pid=self.pid) - # The underlying C implementation retrieves all OS connections - # and filters them by PID. At this point we can't tell whether - # an empty list means there were no connections for process or - # process is no longer active so we force NSP in case the PID - # is no longer there. - if not ret: - # will raise NSP if process is gone - os.stat('%s/%s' % (self._procfs_path, self.pid)) - - # UNIX sockets - if kind in ('all', 'unix'): - ret.extend([_common.pconn(*conn) for conn in - self._get_unix_sockets(self.pid)]) - return ret - - nt_mmap_grouped = namedtuple('mmap', 'path rss anon locked') - nt_mmap_ext = namedtuple('mmap', 'addr perms path rss anon locked') - - @wrap_exceptions - def memory_maps(self): - def toaddr(start, end): - return '%s-%s' % (hex(start)[2:].strip('L'), - hex(end)[2:].strip('L')) - - procfs_path = self._procfs_path - retlist = [] - try: - rawlist = cext.proc_memory_maps(self.pid, procfs_path) - except OSError as err: - if err.errno == errno.EOVERFLOW and not IS_64_BIT: - # We may get here if we attempt to query a 64bit process - # with a 32bit python. - # Error originates from read() and also tools like "cat" - # fail in the same way (!). - # Since there simply is no way to determine CPU times we - # return 0.0 as a fallback. See: - # https://github.com/giampaolo/psutil/issues/857 - return [] - else: - raise - hit_enoent = False - for item in rawlist: - addr, addrsize, perm, name, rss, anon, locked = item - addr = toaddr(addr, addrsize) - if not name.startswith('['): - try: - name = os.readlink( - '%s/%s/path/%s' % (procfs_path, self.pid, name)) - except OSError as err: - if err.errno == errno.ENOENT: - # sometimes the link may not be resolved by - # readlink() even if it exists (ls shows it). - # If that's the case we just return the - # unresolved link path. - # This seems an incosistency with /proc similar - # to: http://goo.gl/55XgO - name = '%s/%s/path/%s' % (procfs_path, self.pid, name) - hit_enoent = True - else: - raise - retlist.append((addr, perm, name, rss, anon, locked)) - if hit_enoent: - self._assert_alive() - return retlist - - @wrap_exceptions - def num_fds(self): - return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))) - - @wrap_exceptions - def num_ctx_switches(self): - return _common.pctxsw( - *cext.proc_num_ctx_switches(self.pid, self._procfs_path)) - - @wrap_exceptions - def wait(self, timeout=None): - return _psposix.wait_pid(self.pid, timeout, self._name) diff --git a/third_party/python/psutil/psutil/_psutil_aix.c b/third_party/python/psutil/psutil/_psutil_aix.c deleted file mode 100644 index cf79d307d907..000000000000 --- a/third_party/python/psutil/psutil/_psutil_aix.c +++ /dev/null @@ -1,1136 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola' - * Copyright (c) 2017, Arnon Yaari - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* - * AIX support is experimental at this time. - * The following functions and methods are unsupported on the AIX platform: - * - psutil.Process.memory_maps - * - * 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 - * versions) - * - * Useful resources: - * - proc filesystem: http://www-01.ibm.com/support/knowledgecenter/ - * ssw_aix_72/com.ibm.aix.files/proc.htm - * - libperfstat: http://www-01.ibm.com/support/knowledgecenter/ - * ssw_aix_72/com.ibm.aix.files/libperfstat.h.htm - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "_psutil_common.h" -#include "_psutil_posix.h" -#include "arch/aix/ifaddrs.h" -#include "arch/aix/net_connections.h" -#include "arch/aix/common.h" - - -#define TV2DOUBLE(t) (((t).tv_nsec * 0.000000001) + (t).tv_sec) - -/* - * Read a file content and fills a C structure with it. - */ -int -psutil_file_to_struct(char *path, void *fstruct, size_t size) { - int fd; - size_t nbytes; - fd = open(path, O_RDONLY); - if (fd == -1) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); - return 0; - } - nbytes = read(fd, fstruct, size); - if (nbytes <= 0) { - close(fd); - PyErr_SetFromErrno(PyExc_OSError); - return 0; - } - if (nbytes != size) { - close(fd); - PyErr_SetString(PyExc_RuntimeError, "structure size mismatch"); - return 0; - } - close(fd); - return nbytes; -} - - -/* - * Return process ppid, rss, vms, ctime, nice, nthreads, status and tty - * as a Python tuple. - */ -static PyObject * -psutil_proc_basic_info(PyObject *self, PyObject *args) { - int pid; - char path[100]; - psinfo_t info; - pstatus_t status; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - - sprintf(path, "%s/%i/psinfo", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - - if (info.pr_nlwp == 0 && info.pr_lwp.pr_lwpid == 0) { - // From the /proc docs: "If the process is a zombie, the pr_nlwp - // and pr_lwp.pr_lwpid flags are zero." - status.pr_stat = SZOMB; - } else if (info.pr_flag & SEXIT) { - // "exiting" processes don't have /proc//status - // There are other "exiting" processes that 'ps' shows as "active" - status.pr_stat = SACTIVE; - } else { - sprintf(path, "%s/%i/status", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&status, sizeof(status))) - return NULL; - } - - return Py_BuildValue("KKKdiiiK", - (unsigned long long) info.pr_ppid, // parent pid - (unsigned long long) info.pr_rssize, // rss - (unsigned long long) info.pr_size, // vms - TV2DOUBLE(info.pr_start), // create time - (int) info.pr_lwp.pr_nice, // nice - (int) info.pr_nlwp, // no. of threads - (int) status.pr_stat, // status code - (unsigned long long)info.pr_ttydev // tty nr - ); -} - - -/* - * Return process name as a Python string. - */ -static PyObject * -psutil_proc_name(PyObject *self, PyObject *args) { - int pid; - char path[100]; - psinfo_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/psinfo", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - - return PyUnicode_DecodeFSDefaultAndSize(info.pr_fname, PRFNSZ); -} - - -/* - * Return process command line arguments as a Python list - */ -static PyObject * -psutil_proc_args(PyObject *self, PyObject *args) { - int pid; - PyObject *py_retlist = PyList_New(0); - PyObject *py_arg = NULL; - struct procsinfo procbuf; - long arg_max; - char *argbuf = NULL; - char *curarg = NULL; - int ret; - - if (py_retlist == NULL) - return NULL; - if (!PyArg_ParseTuple(args, "i", &pid)) - goto error; - arg_max = sysconf(_SC_ARG_MAX); - argbuf = malloc(arg_max); - if (argbuf == NULL) { - PyErr_NoMemory(); - goto error; - } - - procbuf.pi_pid = pid; - ret = getargs(&procbuf, sizeof(procbuf), argbuf, ARG_MAX); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - curarg = argbuf; - /* getargs will always append an extra NULL to end the arg list, - * even if the buffer is not big enough (even though it is supposed - * to be) so the following 'while' is safe */ - while (*curarg != '\0') { - py_arg = PyUnicode_DecodeFSDefault(curarg); - if (!py_arg) - goto error; - if (PyList_Append(py_retlist, py_arg)) - goto error; - Py_DECREF(py_arg); - curarg = strchr(curarg, '\0') + 1; - } - - free(argbuf); - - return py_retlist; - -error: - if (argbuf != NULL) - free(argbuf); - Py_XDECREF(py_retlist); - Py_XDECREF(py_arg); - return NULL; -} - - -/* - * Return process environment variables as a Python dict - */ -static PyObject * -psutil_proc_environ(PyObject *self, PyObject *args) { - int pid; - PyObject *py_retdict = PyDict_New(); - PyObject *py_key = NULL; - PyObject *py_val = NULL; - struct procsinfo procbuf; - long env_max; - char *envbuf = NULL; - char *curvar = NULL; - char *separator = NULL; - int ret; - - if (py_retdict == NULL) - return NULL; - if (!PyArg_ParseTuple(args, "i", &pid)) - goto error; - env_max = sysconf(_SC_ARG_MAX); - envbuf = malloc(env_max); - if (envbuf == NULL) { - PyErr_NoMemory(); - goto error; - } - - procbuf.pi_pid = pid; - ret = getevars(&procbuf, sizeof(procbuf), envbuf, ARG_MAX); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - curvar = envbuf; - /* getevars will always append an extra NULL to end the arg list, - * even if the buffer is not big enough (even though it is supposed - * to be) so the following 'while' is safe */ - while (*curvar != '\0') { - separator = strchr(curvar, '='); - if (separator != NULL) { - py_key = PyUnicode_DecodeFSDefaultAndSize( - curvar, - (Py_ssize_t)(separator - curvar) - ); - if (!py_key) - goto error; - py_val = PyUnicode_DecodeFSDefault(separator + 1); - if (!py_val) - goto error; - if (PyDict_SetItem(py_retdict, py_key, py_val)) - goto error; - Py_CLEAR(py_key); - Py_CLEAR(py_val); - } - curvar = strchr(curvar, '\0') + 1; - } - - free(envbuf); - - return py_retdict; - -error: - if (envbuf != NULL) - free(envbuf); - Py_XDECREF(py_retdict); - Py_XDECREF(py_key); - Py_XDECREF(py_val); - return NULL; -} - - -#ifdef CURR_VERSION_THREAD - -/* - * Retrieves all threads used by process returning a list of tuples - * including thread id, user time and system time. - */ -static PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - long pid; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - perfstat_thread_t *threadt = NULL; - perfstat_id_t id; - int i, rc, thread_count; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - /* Get the count of threads */ - thread_count = perfstat_thread(NULL, NULL, sizeof(perfstat_thread_t), 0); - if (thread_count <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - /* Allocate enough memory */ - threadt = (perfstat_thread_t *)calloc(thread_count, - sizeof(perfstat_thread_t)); - if (threadt == NULL) { - PyErr_NoMemory(); - goto error; - } - - strcpy(id.name, ""); - rc = perfstat_thread(&id, threadt, sizeof(perfstat_thread_t), - thread_count); - if (rc <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < thread_count; i++) { - if (threadt[i].pid != pid) - continue; - - py_tuple = Py_BuildValue("Idd", - threadt[i].tid, - threadt[i].ucpu_time, - threadt[i].scpu_time); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - free(threadt); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (threadt != NULL) - free(threadt); - return NULL; -} - -#endif - - -#ifdef CURR_VERSION_PROCESS - -static PyObject * -psutil_proc_io_counters(PyObject *self, PyObject *args) { - long pid; - int rc; - perfstat_process_t procinfo; - perfstat_id_t id; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - snprintf(id.name, sizeof(id.name), "%ld", pid); - rc = perfstat_process(&id, &procinfo, sizeof(perfstat_process_t), 1); - if (rc <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("(KKKK)", - procinfo.inOps, // XXX always 0 - procinfo.outOps, - procinfo.inBytes, // XXX always 0 - procinfo.outBytes); -} - -#endif - - -/* - * Return process user and system CPU times as a Python tuple. - */ -static PyObject * -psutil_proc_cpu_times(PyObject *self, PyObject *args) { - int pid; - char path[100]; - pstatus_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/status", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - // results are more precise than os.times() - return Py_BuildValue("dddd", - TV2DOUBLE(info.pr_utime), - TV2DOUBLE(info.pr_stime), - TV2DOUBLE(info.pr_cutime), - TV2DOUBLE(info.pr_cstime)); -} - - -/* - * Return process uids/gids as a Python tuple. - */ -static PyObject * -psutil_proc_cred(PyObject *self, PyObject *args) { - int pid; - char path[100]; - prcred_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/cred", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("iiiiii", - info.pr_ruid, info.pr_euid, info.pr_suid, - info.pr_rgid, info.pr_egid, info.pr_sgid); -} - - -/* - * Return process voluntary and involuntary context switches as a Python tuple. - */ -static PyObject * -psutil_proc_num_ctx_switches(PyObject *self, PyObject *args) { - PyObject *py_tuple = NULL; - pid32_t requested_pid; - pid32_t pid = 0; - int np = 0; - struct procentry64 *processes = (struct procentry64 *)NULL; - struct procentry64 *p; - - if (! PyArg_ParseTuple(args, "i", &requested_pid)) - return NULL; - - processes = psutil_read_process_table(&np); - if (!processes) - return NULL; - - /* Loop through processes */ - for (p = processes; np > 0; np--, p++) { - pid = p->pi_pid; - if (requested_pid != pid) - continue; - py_tuple = Py_BuildValue("LL", - (long long) p->pi_ru.ru_nvcsw, /* voluntary context switches */ - (long long) p->pi_ru.ru_nivcsw); /* involuntary */ - free(processes); - return py_tuple; - } - - /* finished iteration without finding requested pid */ - free(processes); - return NoSuchProcess("psutil_read_process_table (no PID found)"); -} - - -/* - * Return users currently connected on the system. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - struct utmpx *ut; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_username = NULL; - PyObject *py_tty = NULL; - PyObject *py_hostname = NULL; - PyObject *py_user_proc = NULL; - - if (py_retlist == NULL) - return NULL; - - setutxent(); - while (NULL != (ut = getutxent())) { - if (ut->ut_type == USER_PROCESS) - py_user_proc = Py_True; - else - py_user_proc = Py_False; - py_username = PyUnicode_DecodeFSDefault(ut->ut_user); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(ut->ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(ut->ut_host); - if (! py_hostname) - goto error; - py_tuple = Py_BuildValue( - "(OOOfOi)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)ut->ut_tv.tv_sec, // tstamp - py_user_proc, // (bool) user process - ut->ut_pid // process id - ); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - } - endutxent(); - - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tty); - Py_XDECREF(py_hostname); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (ut != NULL) - endutxent(); - return NULL; -} - - -/* - * Return disk mounted partitions as a list of tuples including device, - * mount point and filesystem type. - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - FILE *file = NULL; - struct mntent * mt = NULL; - PyObject *py_dev = NULL; - PyObject *py_mountp = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - file = setmntent(MNTTAB, "rb"); - if (file == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - mt = getmntent(file); - while (mt != NULL) { - py_dev = PyUnicode_DecodeFSDefault(mt->mnt_fsname); - if (! py_dev) - goto error; - py_mountp = PyUnicode_DecodeFSDefault(mt->mnt_dir); - if (! py_mountp) - goto error; - py_tuple = Py_BuildValue( - "(OOss)", - py_dev, // device - py_mountp, // mount point - mt->mnt_type, // fs type - mt->mnt_opts); // options - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_dev); - Py_CLEAR(py_mountp); - Py_CLEAR(py_tuple); - mt = getmntent(file); - } - endmntent(file); - return py_retlist; - -error: - Py_XDECREF(py_dev); - Py_XDECREF(py_mountp); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (file != NULL) - endmntent(file); - return NULL; -} - - -#if defined(CURR_VERSION_NETINTERFACE) && CURR_VERSION_NETINTERFACE >= 3 - -/* - * Return a list of tuples for network I/O statistics. - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) { - perfstat_netinterface_t *statp = NULL; - int tot, i; - perfstat_id_t first; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - - if (py_retdict == NULL) - return NULL; - - /* check how many perfstat_netinterface_t structures are available */ - tot = perfstat_netinterface( - NULL, NULL, sizeof(perfstat_netinterface_t), 0); - if (tot == 0) { - // no network interfaces - return empty dict - return py_retdict; - } - if (tot < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - statp = (perfstat_netinterface_t *) - malloc(tot * sizeof(perfstat_netinterface_t)); - if (statp == NULL) { - PyErr_NoMemory(); - goto error; - } - strcpy(first.name, FIRST_NETINTERFACE); - tot = perfstat_netinterface(&first, statp, - sizeof(perfstat_netinterface_t), tot); - if (tot < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < tot; i++) { - py_ifc_info = Py_BuildValue("(KKKKKKKK)", - statp[i].obytes, /* number of bytes sent on interface */ - statp[i].ibytes, /* number of bytes received on interface */ - statp[i].opackets, /* number of packets sent on interface */ - statp[i].ipackets, /* number of packets received on interface */ - statp[i].ierrors, /* number of input errors on interface */ - statp[i].oerrors, /* number of output errors on interface */ - statp[i].if_iqdrops, /* Dropped on input, this interface */ - statp[i].xmitdrops /* number of packets not transmitted */ - ); - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, statp[i].name, py_ifc_info)) - goto error; - Py_DECREF(py_ifc_info); - } - - free(statp); - return py_retdict; - -error: - if (statp != NULL) - free(statp); - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - return NULL; -} - -#endif - - -static PyObject* -psutil_net_if_stats(PyObject* self, PyObject* args) { - char *nic_name; - int sock = 0; - int ret; - int mtu; - struct ifreq ifr; - PyObject *py_is_up = NULL; - PyObject *py_retlist = NULL; - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - goto error; - - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - - // is up? - ret = ioctl(sock, SIOCGIFFLAGS, &ifr); - if (ret == -1) - goto error; - if ((ifr.ifr_flags & IFF_UP) != 0) - py_is_up = Py_True; - else - py_is_up = Py_False; - Py_INCREF(py_is_up); - - // MTU - ret = ioctl(sock, SIOCGIFMTU, &ifr); - if (ret == -1) - goto error; - mtu = ifr.ifr_mtu; - - close(sock); - py_retlist = Py_BuildValue("[Oi]", py_is_up, mtu); - if (!py_retlist) - goto error; - Py_DECREF(py_is_up); - return py_retlist; - -error: - Py_XDECREF(py_is_up); - if (sock != 0) - close(sock); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) { - float boot_time = 0.0; - struct utmpx *ut; - - setutxent(); - while (NULL != (ut = getutxent())) { - if (ut->ut_type == BOOT_TIME) { - boot_time = (float)ut->ut_tv.tv_sec; - break; - } - } - endutxent(); - if (boot_time == 0.0) { - /* could not find BOOT_TIME in getutxent loop */ - PyErr_SetString(PyExc_RuntimeError, "can't determine boot time"); - return NULL; - } - return Py_BuildValue("f", boot_time); -} - - -/* - * Return a Python list of tuple representing per-cpu times - */ -static PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - int ncpu, rc, i; - long ticks; - perfstat_cpu_t *cpu = NULL; - perfstat_id_t id; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - /* get the number of ticks per second */ - ticks = sysconf(_SC_CLK_TCK); - if (ticks < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - /* get the number of cpus in ncpu */ - ncpu = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); - if (ncpu <= 0){ - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - /* allocate enough memory to hold the ncpu structures */ - cpu = (perfstat_cpu_t *) malloc(ncpu * sizeof(perfstat_cpu_t)); - if (cpu == NULL) { - PyErr_NoMemory(); - goto error; - } - - strcpy(id.name, ""); - rc = perfstat_cpu(&id, cpu, sizeof(perfstat_cpu_t), ncpu); - - if (rc <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < ncpu; i++) { - py_cputime = Py_BuildValue( - "(dddd)", - (double)cpu[i].user / ticks, - (double)cpu[i].sys / ticks, - (double)cpu[i].idle / ticks, - (double)cpu[i].wait / ticks); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_DECREF(py_cputime); - } - free(cpu); - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - if (cpu != NULL) - free(cpu); - return NULL; -} - - -/* - * Return disk IO statistics. - */ -static PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - perfstat_disk_t *diskt = NULL; - perfstat_id_t id; - int i, rc, disk_count; - - if (py_retdict == NULL) - return NULL; - - /* Get the count of disks */ - disk_count = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0); - if (disk_count <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - /* Allocate enough memory */ - diskt = (perfstat_disk_t *)calloc(disk_count, - sizeof(perfstat_disk_t)); - if (diskt == NULL) { - PyErr_NoMemory(); - goto error; - } - - strcpy(id.name, FIRST_DISK); - rc = perfstat_disk(&id, diskt, sizeof(perfstat_disk_t), - disk_count); - if (rc <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < disk_count; i++) { - py_disk_info = Py_BuildValue( - "KKKKKK", - diskt[i].__rxfers, - diskt[i].xfers - diskt[i].__rxfers, - diskt[i].rblks * diskt[i].bsize, - diskt[i].wblks * diskt[i].bsize, - diskt[i].rserv / 1000 / 1000, // from nano to milli secs - diskt[i].wserv / 1000 / 1000 // from nano to milli secs - ); - if (py_disk_info == NULL) - goto error; - if (PyDict_SetItemString(py_retdict, diskt[i].name, - py_disk_info)) - goto error; - Py_DECREF(py_disk_info); - } - free(diskt); - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (diskt != NULL) - free(diskt); - return NULL; -} - - -/* - * Return virtual memory usage statistics. - */ -static PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - int rc; - int pagesize = getpagesize(); - perfstat_memory_total_t memory; - - rc = perfstat_memory_total( - NULL, &memory, sizeof(perfstat_memory_total_t), 1); - if (rc <= 0){ - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("KKKKK", - (unsigned long long) memory.real_total * pagesize, - (unsigned long long) memory.real_avail * pagesize, - (unsigned long long) memory.real_free * pagesize, - (unsigned long long) memory.real_pinned * pagesize, - (unsigned long long) memory.real_inuse * pagesize - ); -} - - -/* - * Return stats about swap memory. - */ -static PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { - int rc; - int pagesize = getpagesize(); - perfstat_memory_total_t memory; - - rc = perfstat_memory_total( - NULL, &memory, sizeof(perfstat_memory_total_t), 1); - if (rc <= 0){ - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("KKKK", - (unsigned long long) memory.pgsp_total * pagesize, - (unsigned long long) memory.pgsp_free * pagesize, - (unsigned long long) memory.pgins * pagesize, - (unsigned long long) memory.pgouts * pagesize - ); -} - - -/* - * Return CPU statistics. - */ -static PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - int ncpu, rc, i; - // perfstat_cpu_total_t doesn't have invol/vol cswitch, only pswitch - // which is apparently something else. We have to sum over all cpus - perfstat_cpu_t *cpu = NULL; - perfstat_id_t id; - u_longlong_t cswitches = 0; - u_longlong_t devintrs = 0; - u_longlong_t softintrs = 0; - u_longlong_t syscall = 0; - - /* get the number of cpus in ncpu */ - ncpu = perfstat_cpu(NULL, NULL, sizeof(perfstat_cpu_t), 0); - if (ncpu <= 0){ - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - /* allocate enough memory to hold the ncpu structures */ - cpu = (perfstat_cpu_t *) malloc(ncpu * sizeof(perfstat_cpu_t)); - if (cpu == NULL) { - PyErr_NoMemory(); - goto error; - } - - strcpy(id.name, ""); - rc = perfstat_cpu(&id, cpu, sizeof(perfstat_cpu_t), ncpu); - - if (rc <= 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < ncpu; i++) { - cswitches += cpu[i].invol_cswitch + cpu[i].vol_cswitch; - devintrs += cpu[i].devintrs; - softintrs += cpu[i].softintrs; - syscall += cpu[i].syscall; - } - - free(cpu); - - return Py_BuildValue( - "KKKK", - cswitches, - devintrs, - softintrs, - syscall - ); - -error: - if (cpu != NULL) - free(cpu); - return NULL; -} - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef -PsutilMethods[] = -{ - // --- process-related functions - {"proc_basic_info", psutil_proc_basic_info, METH_VARARGS, - "Return process ppid, rss, vms, ctime, nice, nthreads, status and tty"}, - {"proc_name", psutil_proc_name, METH_VARARGS, - "Return process name."}, - {"proc_args", psutil_proc_args, METH_VARARGS, - "Return process command line arguments."}, - {"proc_environ", psutil_proc_environ, METH_VARARGS, - "Return process environment variables."}, - {"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS, - "Return process user and system CPU times."}, - {"proc_cred", psutil_proc_cred, METH_VARARGS, - "Return process uids/gids."}, -#ifdef CURR_VERSION_THREAD - {"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."}, - - // --- system-related functions - {"users", psutil_users, METH_VARARGS, - "Return currently connected users."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return disk partitions."}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return system boot time in seconds since the EPOCH."}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-cpu times as a list of tuples"}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return a Python dict of tuples for disk I/O statistics."}, - {"virtual_mem", psutil_virtual_mem, METH_VARARGS, - "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, - "Return NIC stats (isup, mtu)"}, - {"cpu_stats", psutil_cpu_stats, METH_VARARGS, - "Return CPU statistics"}, - - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int -psutil_aix_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int -psutil_aix_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_aix", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_aix_traverse, - psutil_aix_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_aix(void) - -#else -#define INITERROR return - -void init_psutil_aix(void) -#endif -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_aix", PsutilMethods); -#endif - PyModule_AddIntConstant(module, "version", PSUTIL_VERSION); - - PyModule_AddIntConstant(module, "SIDL", SIDL); - PyModule_AddIntConstant(module, "SZOMB", SZOMB); - PyModule_AddIntConstant(module, "SACTIVE", SACTIVE); - PyModule_AddIntConstant(module, "SSWAP", SSWAP); - PyModule_AddIntConstant(module, "SSTOP", SSTOP); - - PyModule_AddIntConstant(module, "TCPS_CLOSED", TCPS_CLOSED); - PyModule_AddIntConstant(module, "TCPS_CLOSING", TCPS_CLOSING); - PyModule_AddIntConstant(module, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT); - PyModule_AddIntConstant(module, "TCPS_LISTEN", TCPS_LISTEN); - PyModule_AddIntConstant(module, "TCPS_ESTABLISHED", TCPS_ESTABLISHED); - PyModule_AddIntConstant(module, "TCPS_SYN_SENT", TCPS_SYN_SENT); - PyModule_AddIntConstant(module, "TCPS_SYN_RCVD", TCPS_SYN_RECEIVED); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2); - PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK); - PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT); - PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE); - - psutil_setup(); - - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} - -#ifdef __cplusplus -} -#endif diff --git a/third_party/python/psutil/psutil/_psutil_bsd.c b/third_party/python/psutil/psutil/_psutil_bsd.c deleted file mode 100644 index 953fcd083c28..000000000000 --- a/third_party/python/psutil/psutil/_psutil_bsd.c +++ /dev/null @@ -1,1102 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil (OpenBSD). - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Platform-specific module methods for FreeBSD and OpenBSD. - - * OpenBSD references: - * - OpenBSD source code: https://github.com/openbsd/src - * - * OpenBSD / NetBSD: missing APIs compared to FreeBSD implementation: - * - psutil.net_connections() - * - psutil.Process.get/set_cpu_affinity() (not supported natively) - * - psutil.Process.memory_maps() - */ - -#if defined(PSUTIL_NETBSD) - #define _KMEMUSER -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if !defined(__NetBSD__) - #include -#endif -#include -#include -#include -#include -#include // for struct xsocket -#include -#include -// for xinpcb struct -#include -#include -#include -#include -#include -#include -#include -#include // for struct xtcpcb -#include // for TCP connection states -#include // for inet_ntop() -#include -#include // net io counters -#include -#include -#include // process open files/connections -#include - -#include "_psutil_common.h" -#include "_psutil_posix.h" - -#ifdef PSUTIL_FREEBSD - #include "arch/freebsd/specific.h" - #include "arch/freebsd/sys_socks.h" - #include "arch/freebsd/proc_socks.h" - - #include - #include // get io counters - #include // process open files, shared libs (kinfo_getvmmap) - #if __FreeBSD_version < 900000 - #include // system users - #else - #include - #endif -#elif PSUTIL_OPENBSD - #include "arch/openbsd/specific.h" - - #include - #include // for VREG - #define _KERNEL // for DTYPE_VNODE - #include - #undef _KERNEL - #include // for CPUSTATES & CP_* -#elif PSUTIL_NETBSD - #include "arch/netbsd/specific.h" - #include "arch/netbsd/socks.h" - - #include - #include // for VREG - #include // for CPUSTATES & CP_* - #ifndef DTYPE_VNODE - #define DTYPE_VNODE 1 - #endif -#endif - - -// convert a timeval struct to a double -#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) - -#ifdef PSUTIL_FREEBSD - // convert a bintime struct to milliseconds - #define PSUTIL_BT2MSEC(bt) (bt.sec * 1000 + (((uint64_t) 1000000000 * \ - (uint32_t) (bt.frac >> 32) ) >> 32 ) / 1000000) -#endif - -#if defined(PSUTIL_OPENBSD) || defined (PSUTIL_NETBSD) - #define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0) -#endif - - -/* - * Return a Python list of all the PIDs running on the system. - */ -static PyObject * -psutil_pids(PyObject *self, PyObject *args) { - kinfo_proc *proclist = NULL; - kinfo_proc *orig_address = NULL; - size_t num_processes; - size_t idx; - PyObject *py_retlist = PyList_New(0); - PyObject *py_pid = NULL; - - if (py_retlist == NULL) - return NULL; - - if (psutil_get_proc_list(&proclist, &num_processes) != 0) - goto error; - - if (num_processes > 0) { - orig_address = proclist; // save so we can free it after we're done - for (idx = 0; idx < num_processes; idx++) { -#ifdef PSUTIL_FREEBSD - py_pid = PyLong_FromPid(proclist->ki_pid); -#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD) - py_pid = PyLong_FromPid(proclist->p_pid); -#endif - if (!py_pid) - goto error; - if (PyList_Append(py_retlist, py_pid)) - goto error; - Py_CLEAR(py_pid); - proclist++; - } - free(orig_address); - } - - return py_retlist; - -error: - Py_XDECREF(py_pid); - Py_DECREF(py_retlist); - if (orig_address != NULL) - free(orig_address); - return NULL; -} - - -/* - * Return a Python float indicating the system boot time expressed in - * seconds since the epoch. - */ -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) { - // fetch sysctl "kern.boottime" - static int request[2] = { CTL_KERN, KERN_BOOTTIME }; - struct timeval boottime; - size_t len = sizeof(boottime); - - if (sysctl(request, 2, &boottime, &len, NULL, 0) == -1) - return PyErr_SetFromErrno(PyExc_OSError); - return Py_BuildValue("d", (double)boottime.tv_sec); -} - - -/* - * Collect different info about a process in one shot and return - * them as a big Python tuple. - */ -static PyObject * -psutil_proc_oneshot_info(PyObject *self, PyObject *args) { - pid_t pid; - long rss; - long vms; - long memtext; - long memdata; - long memstack; - int oncpu; - kinfo_proc kp; - long pagesize = sysconf(_SC_PAGESIZE); - char str[1000]; - PyObject *py_name; - PyObject *py_ppid; - PyObject *py_retlist; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - - // Process -#ifdef PSUTIL_FREEBSD - sprintf(str, "%s", kp.ki_comm); -#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD) - sprintf(str, "%s", kp.p_comm); -#endif - py_name = PyUnicode_DecodeFSDefault(str); - if (! py_name) { - // Likely a decoding error. We don't want to fail the whole - // operation. The python module may retry with proc_name(). - PyErr_Clear(); - py_name = Py_None; - } - // Py_INCREF(py_name); - - // Calculate memory. -#ifdef PSUTIL_FREEBSD - rss = (long)kp.ki_rssize * pagesize; - vms = (long)kp.ki_size; - memtext = (long)kp.ki_tsize * pagesize; - memdata = (long)kp.ki_dsize * pagesize; - memstack = (long)kp.ki_ssize * pagesize; -#else - rss = (long)kp.p_vm_rssize * pagesize; - #ifdef PSUTIL_OPENBSD - // VMS, this is how ps determines it on OpenBSD: - // https://github.com/openbsd/src/blob/ - // 588f7f8c69786211f2d16865c552afb91b1c7cba/bin/ps/print.c#L505 - vms = (long)(kp.p_vm_dsize + kp.p_vm_ssize + kp.p_vm_tsize) * pagesize; - #elif PSUTIL_NETBSD - // VMS, this is how top determines it on NetBSD: - // https://github.com/IIJ-NetBSD/netbsd-src/blob/master/external/ - // bsd/top/dist/machine/m_netbsd.c - vms = (long)kp.p_vm_msize * pagesize; - #endif - memtext = (long)kp.p_vm_tsize * pagesize; - memdata = (long)kp.p_vm_dsize * pagesize; - memstack = (long)kp.p_vm_ssize * pagesize; -#endif - -#ifdef PSUTIL_FREEBSD - // what CPU we're on; top was used as an example: - // https://svnweb.freebsd.org/base/head/usr.bin/top/machine.c? - // view=markup&pathrev=273835 - // XXX - note: for "intr" PID this is -1. - if (kp.ki_stat == SRUN && kp.ki_oncpu != NOCPU) - oncpu = kp.ki_oncpu; - else - oncpu = kp.ki_lastcpu; -#else - // On Net/OpenBSD we have kp.p_cpuid but it appears it's always - // set to KI_NOCPU. Even if it's not, ki_lastcpu does not exist - // so there's no way to determine where "sleeping" processes - // were. Not supported. - oncpu = -1; -#endif - -#ifdef PSUTIL_FREEBSD - py_ppid = PyLong_FromPid(kp.ki_ppid); -#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD) - py_ppid = PyLong_FromPid(kp.p_ppid); -#else - py_ppid = Py_BuildfValue(-1); -#endif - if (! py_ppid) - return NULL; - - // Return a single big tuple with all process info. - py_retlist = Py_BuildValue( -#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031 - "(OillllllLdllllddddlllllbO)", -#else - "(OillllllidllllddddlllllbO)", -#endif -#ifdef PSUTIL_FREEBSD - py_ppid, // (pid_t) ppid - (int)kp.ki_stat, // (int) status - // UIDs - (long)kp.ki_ruid, // (long) real uid - (long)kp.ki_uid, // (long) effective uid - (long)kp.ki_svuid, // (long) saved uid - // GIDs - (long)kp.ki_rgid, // (long) real gid - (long)kp.ki_groups[0], // (long) effective gid - (long)kp.ki_svuid, // (long) saved gid - // - kp.ki_tdev, // (int or long long) tty nr - PSUTIL_TV2DOUBLE(kp.ki_start), // (double) create time - // ctx switches - kp.ki_rusage.ru_nvcsw, // (long) ctx switches (voluntary) - kp.ki_rusage.ru_nivcsw, // (long) ctx switches (unvoluntary) - // IO count - kp.ki_rusage.ru_inblock, // (long) read io count - kp.ki_rusage.ru_oublock, // (long) write io count - // CPU times: convert from micro seconds to seconds. - PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_utime), // (double) user time - PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_stime), // (double) sys time - PSUTIL_TV2DOUBLE(kp.ki_rusage_ch.ru_utime), // (double) children utime - PSUTIL_TV2DOUBLE(kp.ki_rusage_ch.ru_stime), // (double) children stime - // memory - rss, // (long) rss - vms, // (long) vms - memtext, // (long) mem text - memdata, // (long) mem data - memstack, // (long) mem stack - // others - oncpu, // (int) the CPU we are on -#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD) - py_ppid, // (pid_t) ppid - (int)kp.p_stat, // (int) status - // UIDs - (long)kp.p_ruid, // (long) real uid - (long)kp.p_uid, // (long) effective uid - (long)kp.p_svuid, // (long) saved uid - // GIDs - (long)kp.p_rgid, // (long) real gid - (long)kp.p_groups[0], // (long) effective gid - (long)kp.p_svuid, // (long) saved gid - // - kp.p_tdev, // (int) tty nr - PSUTIL_KPT2DOUBLE(kp.p_ustart), // (double) create time - // ctx switches - kp.p_uru_nvcsw, // (long) ctx switches (voluntary) - kp.p_uru_nivcsw, // (long) ctx switches (unvoluntary) - // IO count - kp.p_uru_inblock, // (long) read io count - kp.p_uru_oublock, // (long) write io count - // CPU times: convert from micro seconds to seconds. - PSUTIL_KPT2DOUBLE(kp.p_uutime), // (double) user time - PSUTIL_KPT2DOUBLE(kp.p_ustime), // (double) sys time - // OpenBSD and NetBSD provide children user + system times summed - // together (no distinction). - kp.p_uctime_sec + kp.p_uctime_usec / 1000000.0, // (double) ch utime - kp.p_uctime_sec + kp.p_uctime_usec / 1000000.0, // (double) ch stime - // memory - rss, // (long) rss - vms, // (long) vms - memtext, // (long) mem text - memdata, // (long) mem data - memstack, // (long) mem stack - // others - oncpu, // (int) the CPU we are on -#endif - py_name // (pystr) name - ); - - Py_DECREF(py_name); - Py_DECREF(py_ppid); - return py_retlist; -} - - -/* - * Return process name from kinfo_proc as a Python string. - */ -static PyObject * -psutil_proc_name(PyObject *self, PyObject *args) { - pid_t pid; - kinfo_proc kp; - char str[1000]; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - -#ifdef PSUTIL_FREEBSD - sprintf(str, "%s", kp.ki_comm); -#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD) - sprintf(str, "%s", kp.p_comm); -#endif - return PyUnicode_DecodeFSDefault(str); -} - - -/* - * Return process cmdline as a Python list of cmdline arguments. - */ -static PyObject * -psutil_proc_cmdline(PyObject *self, PyObject *args) { - pid_t pid; - PyObject *py_retlist = NULL; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - py_retlist = psutil_get_cmdline(pid); - if (py_retlist == NULL) - return NULL; - return Py_BuildValue("N", py_retlist); -} - - -/* - * Return the number of logical CPUs in the system. - * XXX this could be shared with macOS - */ -static PyObject * -psutil_cpu_count_logical(PyObject *self, PyObject *args) { - int mib[2]; - int ncpu; - size_t len; - - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("i", ncpu); -} - - -/* - * Return a Python tuple representing user, kernel and idle CPU times - */ -static PyObject * -psutil_cpu_times(PyObject *self, PyObject *args) { -#ifdef PSUTIL_NETBSD - u_int64_t cpu_time[CPUSTATES]; -#else - long cpu_time[CPUSTATES]; -#endif - size_t size = sizeof(cpu_time); - int ret; - -#if defined(PSUTIL_FREEBSD) || defined(PSUTIL_NETBSD) - ret = sysctlbyname("kern.cp_time", &cpu_time, &size, NULL, 0); -#elif PSUTIL_OPENBSD - int mib[] = {CTL_KERN, KERN_CPTIME}; - ret = sysctl(mib, 2, &cpu_time, &size, NULL, 0); -#endif - if (ret == -1) - return PyErr_SetFromErrno(PyExc_OSError); - return Py_BuildValue("(ddddd)", - (double)cpu_time[CP_USER] / CLOCKS_PER_SEC, - (double)cpu_time[CP_NICE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_SYS] / CLOCKS_PER_SEC, - (double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_INTR] / CLOCKS_PER_SEC - ); -} - - - /* - * Return files opened by process as a list of (path, fd) tuples. - * TODO: this is broken as it may report empty paths. 'procstat' - * utility has the same problem see: - * https://github.com/giampaolo/psutil/issues/595 - */ -#if (defined(__FreeBSD_version) && __FreeBSD_version >= 800000) || PSUTIL_OPENBSD || defined(PSUTIL_NETBSD) -static PyObject * -psutil_proc_open_files(PyObject *self, PyObject *args) { - pid_t pid; - int i; - int cnt; - int regular; - int fd; - char *path; - struct kinfo_file *freep = NULL; - struct kinfo_file *kif; - kinfo_proc kipp; - PyObject *py_tuple = NULL; - PyObject *py_path = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - goto error; - if (psutil_kinfo_proc(pid, &kipp) == -1) - goto error; - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { -#if !defined(PSUTIL_OPENBSD) - psutil_raise_for_pid(pid, "kinfo_getfile()"); -#endif - goto error; - } - - for (i = 0; i < cnt; i++) { - kif = &freep[i]; - -#ifdef PSUTIL_FREEBSD - regular = (kif->kf_type == KF_TYPE_VNODE) && \ - (kif->kf_vnode_type == KF_VTYPE_VREG); - fd = kif->kf_fd; - path = kif->kf_path; -#elif PSUTIL_OPENBSD - regular = (kif->f_type == DTYPE_VNODE) && (kif->v_type == VREG); - fd = kif->fd_fd; - // XXX - it appears path is not exposed in the kinfo_file struct. - path = ""; -#elif PSUTIL_NETBSD - regular = (kif->ki_ftype == DTYPE_VNODE) && (kif->ki_vtype == VREG); - fd = kif->ki_fd; - // XXX - it appears path is not exposed in the kinfo_file struct. - path = ""; -#endif - if (regular == 1) { - py_path = PyUnicode_DecodeFSDefault(path); - if (! py_path) - goto error; - py_tuple = Py_BuildValue("(Oi)", py_path, fd); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_path); - Py_CLEAR(py_tuple); - } - } - free(freep); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (freep != NULL) - free(freep); - return NULL; -} -#endif - - -/* - * Return a list of tuples including device, mount point and fs type - * for all partitions mounted on the system. - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - int num; - int i; - long len; - uint64_t flags; - char opts[200]; -#ifdef PSUTIL_NETBSD - struct statvfs *fs = NULL; -#else - struct statfs *fs = NULL; -#endif - PyObject *py_retlist = PyList_New(0); - PyObject *py_dev = NULL; - PyObject *py_mountp = NULL; - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - - // get the number of mount points - Py_BEGIN_ALLOW_THREADS -#ifdef PSUTIL_NETBSD - num = getvfsstat(NULL, 0, MNT_NOWAIT); -#else - num = getfsstat(NULL, 0, MNT_NOWAIT); -#endif - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - len = sizeof(*fs) * num; - fs = malloc(len); - if (fs == NULL) { - PyErr_NoMemory(); - goto error; - } - - Py_BEGIN_ALLOW_THREADS -#ifdef PSUTIL_NETBSD - num = getvfsstat(fs, len, MNT_NOWAIT); -#else - num = getfsstat(fs, len, MNT_NOWAIT); -#endif - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < num; i++) { - py_tuple = NULL; - opts[0] = 0; -#ifdef PSUTIL_NETBSD - flags = fs[i].f_flag; -#else - flags = fs[i].f_flags; -#endif - - // see sys/mount.h - if (flags & MNT_RDONLY) - strlcat(opts, "ro", sizeof(opts)); - else - strlcat(opts, "rw", sizeof(opts)); - if (flags & MNT_SYNCHRONOUS) - strlcat(opts, ",sync", sizeof(opts)); - if (flags & MNT_NOEXEC) - strlcat(opts, ",noexec", sizeof(opts)); - if (flags & MNT_NOSUID) - strlcat(opts, ",nosuid", sizeof(opts)); - if (flags & MNT_ASYNC) - strlcat(opts, ",async", sizeof(opts)); - if (flags & MNT_NOATIME) - strlcat(opts, ",noatime", sizeof(opts)); - if (flags & MNT_SOFTDEP) - strlcat(opts, ",softdep", sizeof(opts)); -#ifdef PSUTIL_FREEBSD - if (flags & MNT_UNION) - strlcat(opts, ",union", sizeof(opts)); - if (flags & MNT_SUIDDIR) - strlcat(opts, ",suiddir", sizeof(opts)); - if (flags & MNT_SOFTDEP) - strlcat(opts, ",softdep", sizeof(opts)); - if (flags & MNT_NOSYMFOLLOW) - strlcat(opts, ",nosymfollow", sizeof(opts)); - if (flags & MNT_GJOURNAL) - strlcat(opts, ",gjournal", sizeof(opts)); - if (flags & MNT_MULTILABEL) - strlcat(opts, ",multilabel", sizeof(opts)); - if (flags & MNT_ACLS) - strlcat(opts, ",acls", sizeof(opts)); - if (flags & MNT_NOCLUSTERR) - strlcat(opts, ",noclusterr", sizeof(opts)); - if (flags & MNT_NOCLUSTERW) - strlcat(opts, ",noclusterw", sizeof(opts)); - if (flags & MNT_NFS4ACLS) - strlcat(opts, ",nfs4acls", sizeof(opts)); -#elif PSUTIL_NETBSD - if (flags & MNT_NODEV) - strlcat(opts, ",nodev", sizeof(opts)); - if (flags & MNT_UNION) - strlcat(opts, ",union", sizeof(opts)); - if (flags & MNT_NOCOREDUMP) - strlcat(opts, ",nocoredump", sizeof(opts)); -#ifdef MNT_RELATIME - if (flags & MNT_RELATIME) - strlcat(opts, ",relatime", sizeof(opts)); -#endif - if (flags & MNT_IGNORE) - strlcat(opts, ",ignore", sizeof(opts)); -#ifdef MNT_DISCARD - if (flags & MNT_DISCARD) - strlcat(opts, ",discard", sizeof(opts)); -#endif -#ifdef MNT_EXTATTR - if (flags & MNT_EXTATTR) - strlcat(opts, ",extattr", sizeof(opts)); -#endif - if (flags & MNT_LOG) - strlcat(opts, ",log", sizeof(opts)); - if (flags & MNT_SYMPERM) - strlcat(opts, ",symperm", sizeof(opts)); - if (flags & MNT_NODEVMTIME) - strlcat(opts, ",nodevmtime", sizeof(opts)); -#endif - py_dev = PyUnicode_DecodeFSDefault(fs[i].f_mntfromname); - if (! py_dev) - goto error; - py_mountp = PyUnicode_DecodeFSDefault(fs[i].f_mntonname); - if (! py_mountp) - goto error; - py_tuple = Py_BuildValue("(OOss)", - py_dev, // device - py_mountp, // mount point - fs[i].f_fstypename, // fs type - opts); // options - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_dev); - Py_CLEAR(py_mountp); - Py_CLEAR(py_tuple); - } - - free(fs); - return py_retlist; - -error: - Py_XDECREF(py_dev); - Py_XDECREF(py_mountp); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (fs != NULL) - free(fs); - return NULL; -} - - -/* - * Return a Python list of named tuples with overall network I/O information - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) { - char *buf = NULL, *lim, *next; - struct if_msghdr *ifm; - int mib[6]; - size_t len; - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - if (py_retdict == NULL) - return NULL; - - mib[0] = CTL_NET; // networking subsystem - mib[1] = PF_ROUTE; // type of information - mib[2] = 0; // protocol (IPPROTO_xxx) - mib[3] = 0; // address family - mib[4] = NET_RT_IFLIST; // operation - mib[5] = 0; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - buf = malloc(len); - if (buf == NULL) { - PyErr_NoMemory(); - goto error; - } - - if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - lim = buf + len; - - for (next = buf; next < lim; ) { - py_ifc_info = NULL; - ifm = (struct if_msghdr *)next; - next += ifm->ifm_msglen; - - if (ifm->ifm_type == RTM_IFINFO) { - struct if_msghdr *if2m = (struct if_msghdr *)ifm; - struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1); - char ifc_name[32]; - - strncpy(ifc_name, sdl->sdl_data, sdl->sdl_nlen); - ifc_name[sdl->sdl_nlen] = 0; - // XXX: ignore usbus interfaces: - // http://lists.freebsd.org/pipermail/freebsd-current/ - // 2011-October/028752.html - // 'ifconfig -a' doesn't show them, nor do we. - if (strncmp(ifc_name, "usbus", 5) == 0) - continue; - - py_ifc_info = Py_BuildValue("(kkkkkkki)", - if2m->ifm_data.ifi_obytes, - if2m->ifm_data.ifi_ibytes, - if2m->ifm_data.ifi_opackets, - if2m->ifm_data.ifi_ipackets, - if2m->ifm_data.ifi_ierrors, - if2m->ifm_data.ifi_oerrors, - if2m->ifm_data.ifi_iqdrops, -#ifdef _IFI_OQDROPS - if2m->ifm_data.ifi_oqdrops -#else - 0 -#endif - ); - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info)) - goto error; - Py_CLEAR(py_ifc_info); - } - else { - continue; - } - } - - free(buf); - return py_retdict; - -error: - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (buf != NULL) - free(buf); - return NULL; -} - - -/* - * Return currently connected users as a list of tuples. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - PyObject *py_retlist = PyList_New(0); - PyObject *py_username = NULL; - PyObject *py_tty = NULL; - PyObject *py_hostname = NULL; - PyObject *py_tuple = NULL; - PyObject *py_pid = NULL; - - if (py_retlist == NULL) - return NULL; - -#if (defined(__FreeBSD_version) && (__FreeBSD_version < 900000)) || PSUTIL_OPENBSD - struct utmp ut; - FILE *fp; - - Py_BEGIN_ALLOW_THREADS - fp = fopen(_PATH_UTMP, "r"); - Py_END_ALLOW_THREADS - if (fp == NULL) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, _PATH_UTMP); - goto error; - } - - while (fread(&ut, sizeof(ut), 1, fp) == 1) { - if (*ut.ut_name == '\0') - continue; - py_username = PyUnicode_DecodeFSDefault(ut.ut_name); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(ut.ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(ut.ut_host); - if (! py_hostname) - goto error; - py_tuple = Py_BuildValue( - "(OOOfi)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)ut.ut_time, // start time -#ifdef PSUTIL_OPENBSD - -1 // process id (set to None later) -#else - ut.ut_pid // TODO: use PyLong_FromPid -#endif - ); - if (!py_tuple) { - fclose(fp); - goto error; - } - if (PyList_Append(py_retlist, py_tuple)) { - fclose(fp); - goto error; - } - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - } - - fclose(fp); -#else - struct utmpx *utx; - setutxent(); - while ((utx = getutxent()) != NULL) { - if (utx->ut_type != USER_PROCESS) - continue; - py_username = PyUnicode_DecodeFSDefault(utx->ut_user); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(utx->ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(utx->ut_host); - if (! py_hostname) - goto error; -#ifdef PSUTIL_OPENBSD - py_pid = Py_BuildValue("i", -1); // set to None later -#else - py_pid = PyLong_FromPid(utx->ut_pid); -#endif - if (! py_pid) - goto error; - - py_tuple = Py_BuildValue( - "(OOOfO)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)utx->ut_tv.tv_sec, // start time - py_pid // process id - ); - - if (!py_tuple) { - endutxent(); - goto error; - } - if (PyList_Append(py_retlist, py_tuple)) { - endutxent(); - goto error; - } - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - Py_CLEAR(py_pid); - } - - endutxent(); -#endif - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tty); - Py_XDECREF(py_hostname); - Py_XDECREF(py_tuple); - Py_XDECREF(py_pid); - Py_DECREF(py_retlist); - return NULL; -} - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef mod_methods[] = { - // --- per-process functions - - {"proc_oneshot_info", psutil_proc_oneshot_info, METH_VARARGS, - "Return multiple info about a process"}, - {"proc_name", psutil_proc_name, METH_VARARGS, - "Return process name"}, - {"proc_cmdline", psutil_proc_cmdline, METH_VARARGS, - "Return process cmdline as a list of cmdline arguments"}, - {"proc_threads", psutil_proc_threads, METH_VARARGS, - "Return process threads"}, -#if defined(PSUTIL_FREEBSD) || defined(PSUTIL_OPENBSD) - {"proc_connections", psutil_proc_connections, METH_VARARGS, - "Return connections opened by process"}, -#endif - {"proc_cwd", psutil_proc_cwd, METH_VARARGS, - "Return process current working directory."}, -#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 || PSUTIL_OPENBSD || defined(PSUTIL_NETBSD) - {"proc_num_fds", psutil_proc_num_fds, METH_VARARGS, - "Return the number of file descriptors opened by this process"}, - {"proc_open_files", psutil_proc_open_files, METH_VARARGS, - "Return files opened by process as a list of (path, fd) tuples"}, -#endif -#if defined(PSUTIL_FREEBSD) || defined(PSUTIL_NETBSD) - {"proc_num_threads", psutil_proc_num_threads, METH_VARARGS, - "Return number of threads used by process"}, -#endif -#if defined(PSUTIL_FREEBSD) - {"proc_exe", psutil_proc_exe, METH_VARARGS, - "Return process pathname executable"}, - {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS, - "Return a list of tuples for every process's memory map"}, - {"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS, - "Return process CPU affinity."}, - {"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS, - "Set process CPU affinity."}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Return an XML string to determine the number physical CPUs."}, -#endif - - // --- system-related functions - - {"pids", psutil_pids, METH_VARARGS, - "Returns a list of PIDs currently running on the system"}, - {"cpu_count_logical", psutil_cpu_count_logical, METH_VARARGS, - "Return number of logical CPUs on the system"}, - {"virtual_mem", psutil_virtual_mem, METH_VARARGS, - "Return system virtual memory usage statistics"}, - {"swap_mem", psutil_swap_mem, METH_VARARGS, - "Return swap mem stats"}, - {"cpu_times", psutil_cpu_times, METH_VARARGS, - "Return system cpu times as a tuple (user, system, nice, idle, irc)"}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-cpu times as a list of tuples"}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return the system boot time expressed in seconds since the epoch."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return a list of tuples including device, mount point and " - "fs type for all partitions mounted on the system."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return dict of tuples of networks I/O information."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return a Python dict of tuples for disk I/O information"}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users as a list of tuples"}, - {"cpu_stats", psutil_cpu_stats, METH_VARARGS, - "Return CPU statistics"}, -#if defined(PSUTIL_FREEBSD) || defined(PSUTIL_NETBSD) - {"net_connections", psutil_net_connections, METH_VARARGS, - "Return system-wide open connections."}, -#endif -#if defined(PSUTIL_FREEBSD) - {"sensors_battery", psutil_sensors_battery, METH_VARARGS, - "Return battery information."}, - {"sensors_cpu_temperature", psutil_sensors_cpu_temperature, METH_VARARGS, - "Return temperature information for a given CPU core number."}, - {"cpu_frequency", psutil_cpu_freq, METH_VARARGS, - "Return frequency of a given CPU"}, -#endif - - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - -#if PY_MAJOR_VERSION >= 3 - #define INITERR return NULL - - static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_psutil_bsd", - NULL, - -1, - mod_methods, - NULL, - NULL, - NULL, - NULL - }; - - PyObject *PyInit__psutil_bsd(void) -#else /* PY_MAJOR_VERSION */ - #define INITERR return - - void init_psutil_bsd(void) -#endif /* PY_MAJOR_VERSION */ -{ - PyObject *v; -#if PY_MAJOR_VERSION >= 3 - PyObject *mod = PyModule_Create(&moduledef); -#else - PyObject *mod = Py_InitModule("_psutil_bsd", mod_methods); -#endif - if (mod == NULL) - INITERR; - - if (PyModule_AddIntConstant(mod, "version", PSUTIL_VERSION)) INITERR; - // process status constants - -#ifdef PSUTIL_FREEBSD - if (PyModule_AddIntConstant(mod, "SIDL", SIDL)) INITERR; - if (PyModule_AddIntConstant(mod, "SRUN", SRUN)) INITERR; - if (PyModule_AddIntConstant(mod, "SSLEEP", SSLEEP)) INITERR; - if (PyModule_AddIntConstant(mod, "SSTOP", SSTOP)) INITERR; - if (PyModule_AddIntConstant(mod, "SZOMB", SZOMB)) INITERR; - if (PyModule_AddIntConstant(mod, "SWAIT", SWAIT)) INITERR; - if (PyModule_AddIntConstant(mod, "SLOCK", SLOCK)) INITERR; -#elif PSUTIL_OPENBSD - if (PyModule_AddIntConstant(mod, "SIDL", SIDL)) INITERR; - if (PyModule_AddIntConstant(mod, "SRUN", SRUN)) INITERR; - if (PyModule_AddIntConstant(mod, "SSLEEP", SSLEEP)) INITERR; - if (PyModule_AddIntConstant(mod, "SSTOP", SSTOP)) INITERR; - if (PyModule_AddIntConstant(mod, "SZOMB", SZOMB)) INITERR; // unused - if (PyModule_AddIntConstant(mod, "SDEAD", SDEAD)) INITERR; - if (PyModule_AddIntConstant(mod, "SONPROC", SONPROC)) INITERR; -#elif defined(PSUTIL_NETBSD) - if (PyModule_AddIntConstant(mod, "SIDL", LSIDL)) INITERR; - if (PyModule_AddIntConstant(mod, "SRUN", LSRUN)) INITERR; - if (PyModule_AddIntConstant(mod, "SSLEEP", LSSLEEP)) INITERR; - if (PyModule_AddIntConstant(mod, "SSTOP", LSSTOP)) INITERR; - if (PyModule_AddIntConstant(mod, "SZOMB", LSZOMB)) INITERR; - if (PyModule_AddIntConstant(mod, "SDEAD", LSDEAD)) INITERR; - if (PyModule_AddIntConstant(mod, "SONPROC", LSONPROC)) INITERR; - // unique to NetBSD - if (PyModule_AddIntConstant(mod, "SSUSPENDED", LSSUSPENDED)) INITERR; -#endif - - // connection status constants - if (PyModule_AddIntConstant(mod, "TCPS_CLOSED", TCPS_CLOSED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_CLOSING", TCPS_CLOSING)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_LISTEN", TCPS_LISTEN)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_ESTABLISHED", TCPS_ESTABLISHED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_SYN_SENT", TCPS_SYN_SENT)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_LAST_ACK", TCPS_LAST_ACK)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_TIME_WAIT", TCPS_TIME_WAIT)) - INITERR; - // PSUTIL_CONN_NONE - if (PyModule_AddIntConstant(mod, "PSUTIL_CONN_NONE", 128)) INITERR; - - psutil_setup(); - - if (mod == NULL) - INITERR; -#if PY_MAJOR_VERSION >= 3 - return mod; -#endif -} diff --git a/third_party/python/psutil/psutil/_psutil_common.c b/third_party/python/psutil/psutil/_psutil_common.c deleted file mode 100644 index 07578edaa277..000000000000 --- a/third_party/python/psutil/psutil/_psutil_common.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * 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 platforms. - */ - -#include -#include "_psutil_common.h" - -// ==================================================================== -// --- Global vars -// ==================================================================== - -int PSUTIL_DEBUG = 0; -int PSUTIL_TESTING = 0; -// PSUTIL_CONN_NONE - - -// ==================================================================== -// --- Backward compatibility with missing Python.h APIs -// ==================================================================== - -// PyPy on Windows -#if defined(PSUTIL_WINDOWS) && \ - defined(PYPY_VERSION) && \ - !defined(PyErr_SetFromWindowsErrWithFilename) -PyObject * -PyErr_SetFromWindowsErrWithFilename(int winerr, const char *filename) { - PyObject *py_exc = NULL; - PyObject *py_winerr = NULL; - - if (winerr == 0) - winerr = GetLastError(); - if (filename == NULL) { - py_exc = PyObject_CallFunction(PyExc_OSError, "(is)", winerr, - strerror(winerr)); - } - else { - py_exc = PyObject_CallFunction(PyExc_OSError, "(iss)", winerr, - strerror(winerr), filename); - } - if (py_exc == NULL) - return NULL; - - py_winerr = Py_BuildValue("i", winerr); - if (py_winerr == NULL) - goto error; - if (PyObject_SetAttrString(py_exc, "winerror", py_winerr) != 0) - goto error; - PyErr_SetObject(PyExc_OSError, py_exc); - Py_XDECREF(py_exc); - return NULL; - -error: - Py_XDECREF(py_exc); - Py_XDECREF(py_winerr); - return NULL; -} -#endif // PYPY on Windows - - -// ==================================================================== -// --- Custom exceptions -// ==================================================================== - -/* - * Same as PyErr_SetFromErrno(0) but adds the syscall to the exception - * message. - */ -PyObject * -PyErr_SetFromOSErrnoWithSyscall(const char *syscall) { - char fullmsg[1024]; - -#ifdef PSUTIL_WINDOWS - sprintf(fullmsg, "(originated from %s)", syscall); - PyErr_SetFromWindowsErrWithFilename(GetLastError(), fullmsg); -#else - PyObject *exc; - sprintf(fullmsg, "%s (originated from %s)", strerror(errno), syscall); - exc = PyObject_CallFunction(PyExc_OSError, "(is)", errno, fullmsg); - PyErr_SetObject(PyExc_OSError, exc); - Py_XDECREF(exc); -#endif - return NULL; -} - - -/* - * Set OSError(errno=ESRCH, strerror="No such process (originated from") - * Python exception. - */ -PyObject * -NoSuchProcess(const char *syscall) { - PyObject *exc; - char msg[1024]; - - sprintf(msg, "No such process (originated from %s)", syscall); - exc = PyObject_CallFunction(PyExc_OSError, "(is)", ESRCH, msg); - PyErr_SetObject(PyExc_OSError, exc); - Py_XDECREF(exc); - return NULL; -} - - -/* - * Set OSError(errno=EACCES, strerror="Permission denied" (originated from ...) - * Python exception. - */ -PyObject * -AccessDenied(const char *syscall) { - PyObject *exc; - char msg[1024]; - - sprintf(msg, "Access denied (originated from %s)", syscall); - exc = PyObject_CallFunction(PyExc_OSError, "(is)", EACCES, msg); - PyErr_SetObject(PyExc_OSError, exc); - Py_XDECREF(exc); - return NULL; -} - - -// ==================================================================== -// --- Global utils -// ==================================================================== - -/* - * Enable testing mode. This has the same effect as setting PSUTIL_TESTING - * env var. This dual method exists because updating os.environ on - * Windows has no effect. Called on unit tests setup. - */ -PyObject * -psutil_set_testing(PyObject *self, PyObject *args) { - PSUTIL_TESTING = 1; - Py_INCREF(Py_None); - return Py_None; -} - - -/* - * Print a debug message on stderr. No-op if PSUTIL_DEBUG env var is not set. - */ -void -psutil_debug(const char* format, ...) { - va_list argptr; - if (PSUTIL_DEBUG) { - va_start(argptr, format); - fprintf(stderr, "psutil-debug> "); - vfprintf(stderr, format, argptr); - fprintf(stderr, "\n"); - va_end(argptr); - } -} - - -/* - * Called on module import on all platforms. - */ -int -psutil_setup(void) { - if (getenv("PSUTIL_DEBUG") != NULL) - PSUTIL_DEBUG = 1; - if (getenv("PSUTIL_TESTING") != NULL) - PSUTIL_TESTING = 1; - return 0; -} - - -// ==================================================================== -// --- Windows -// ==================================================================== - -#ifdef PSUTIL_WINDOWS -#include - -// Needed to make these globally visible. -int PSUTIL_WINVER; -SYSTEM_INFO PSUTIL_SYSTEM_INFO; -CRITICAL_SECTION PSUTIL_CRITICAL_SECTION; - -#define NT_FACILITY_MASK 0xfff -#define NT_FACILITY_SHIFT 16 -#define NT_FACILITY(Status) \ - ((((ULONG)(Status)) >> NT_FACILITY_SHIFT) & NT_FACILITY_MASK) -#define NT_NTWIN32(status) (NT_FACILITY(Status) == FACILITY_WIN32) -#define WIN32_FROM_NTSTATUS(Status) (((ULONG)(Status)) & 0xffff) - - -// A wrapper around GetModuleHandle and GetProcAddress. -PVOID -psutil_GetProcAddress(LPCSTR libname, LPCSTR procname) { - HMODULE mod; - FARPROC addr; - - if ((mod = GetModuleHandleA(libname)) == NULL) { - PyErr_SetFromWindowsErrWithFilename(0, libname); - return NULL; - } - if ((addr = GetProcAddress(mod, procname)) == NULL) { - PyErr_SetFromWindowsErrWithFilename(0, procname); - return NULL; - } - return addr; -} - - -// A wrapper around LoadLibrary and GetProcAddress. -PVOID -psutil_GetProcAddressFromLib(LPCSTR libname, LPCSTR procname) { - HMODULE mod; - FARPROC addr; - - Py_BEGIN_ALLOW_THREADS - mod = LoadLibraryA(libname); - Py_END_ALLOW_THREADS - if (mod == NULL) { - PyErr_SetFromWindowsErrWithFilename(0, libname); - return NULL; - } - if ((addr = GetProcAddress(mod, procname)) == NULL) { - PyErr_SetFromWindowsErrWithFilename(0, procname); - FreeLibrary(mod); - return NULL; - } - // Causes crash. - // FreeLibrary(mod); - return addr; -} - - -/* - * Convert a NTSTATUS value to a Win32 error code and set the proper - * Python exception. - */ -PVOID -psutil_SetFromNTStatusErr(NTSTATUS Status, const char *syscall) { - ULONG err; - char fullmsg[1024]; - - if (NT_NTWIN32(Status)) - err = WIN32_FROM_NTSTATUS(Status); - else - err = RtlNtStatusToDosErrorNoTeb(Status); - // if (GetLastError() != 0) - // err = GetLastError(); - sprintf(fullmsg, "(originated from %s)", syscall); - return PyErr_SetFromWindowsErrWithFilename(err, fullmsg); -} - - -static int -psutil_loadlibs() { - // --- Mandatory - NtQuerySystemInformation = psutil_GetProcAddressFromLib( - "ntdll.dll", "NtQuerySystemInformation"); - if (! NtQuerySystemInformation) - return 1; - NtQueryInformationProcess = psutil_GetProcAddress( - "ntdll.dll", "NtQueryInformationProcess"); - if (! NtQueryInformationProcess) - return 1; - NtSetInformationProcess = psutil_GetProcAddress( - "ntdll.dll", "NtSetInformationProcess"); - if (! NtSetInformationProcess) - return 1; - WinStationQueryInformationW = psutil_GetProcAddressFromLib( - "winsta.dll", "WinStationQueryInformationW"); - if (! WinStationQueryInformationW) - return 1; - NtQueryObject = psutil_GetProcAddressFromLib( - "ntdll.dll", "NtQueryObject"); - if (! NtQueryObject) - return 1; - RtlIpv4AddressToStringA = psutil_GetProcAddressFromLib( - "ntdll.dll", "RtlIpv4AddressToStringA"); - if (! RtlIpv4AddressToStringA) - return 1; - GetExtendedTcpTable = psutil_GetProcAddressFromLib( - "iphlpapi.dll", "GetExtendedTcpTable"); - if (! GetExtendedTcpTable) - return 1; - GetExtendedUdpTable = psutil_GetProcAddressFromLib( - "iphlpapi.dll", "GetExtendedUdpTable"); - if (! GetExtendedUdpTable) - return 1; - RtlGetVersion = psutil_GetProcAddressFromLib( - "ntdll.dll", "RtlGetVersion"); - if (! RtlGetVersion) - return 1; - NtSuspendProcess = psutil_GetProcAddressFromLib( - "ntdll", "NtSuspendProcess"); - if (! NtSuspendProcess) - return 1; - NtResumeProcess = psutil_GetProcAddressFromLib( - "ntdll", "NtResumeProcess"); - if (! NtResumeProcess) - return 1; - NtQueryVirtualMemory = psutil_GetProcAddressFromLib( - "ntdll", "NtQueryVirtualMemory"); - if (! NtQueryVirtualMemory) - return 1; - RtlNtStatusToDosErrorNoTeb = psutil_GetProcAddressFromLib( - "ntdll", "RtlNtStatusToDosErrorNoTeb"); - if (! RtlNtStatusToDosErrorNoTeb) - return 1; - GetTickCount64 = psutil_GetProcAddress( - "kernel32", "GetTickCount64"); - if (! GetTickCount64) - return 1; - RtlIpv6AddressToStringA = psutil_GetProcAddressFromLib( - "ntdll.dll", "RtlIpv6AddressToStringA"); - if (! RtlIpv6AddressToStringA) - return 1; - - // --- Optional - // minimum requirement: Win 7 - GetActiveProcessorCount = psutil_GetProcAddress( - "kernel32", "GetActiveProcessorCount"); - // minumum requirement: Win 7 - GetLogicalProcessorInformationEx = psutil_GetProcAddressFromLib( - "kernel32", "GetLogicalProcessorInformationEx"); - - PyErr_Clear(); - return 0; -} - - -static int -psutil_set_winver() { - RTL_OSVERSIONINFOEXW versionInfo; - ULONG maj; - ULONG min; - - versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); - memset(&versionInfo, 0, sizeof(RTL_OSVERSIONINFOEXW)); - RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo); - maj = versionInfo.dwMajorVersion; - min = versionInfo.dwMinorVersion; - if (maj == 6 && min == 0) - PSUTIL_WINVER = PSUTIL_WINDOWS_VISTA; // or Server 2008 - else if (maj == 6 && min == 1) - PSUTIL_WINVER = PSUTIL_WINDOWS_7; - else if (maj == 6 && min == 2) - PSUTIL_WINVER = PSUTIL_WINDOWS_8; - else if (maj == 6 && min == 3) - PSUTIL_WINVER = PSUTIL_WINDOWS_8_1; - else if (maj == 10 && min == 0) - PSUTIL_WINVER = PSUTIL_WINDOWS_10; - else - PSUTIL_WINVER = PSUTIL_WINDOWS_NEW; - return 0; -} - - -int -psutil_load_globals() { - if (psutil_loadlibs() != 0) - return 1; - if (psutil_set_winver() != 0) - return 1; - GetSystemInfo(&PSUTIL_SYSTEM_INFO); - InitializeCriticalSection(&PSUTIL_CRITICAL_SECTION); - return 0; -} - - -/* - * Convert the hi and lo parts of a FILETIME structure or a LARGE_INTEGER - * to a UNIX time. - * A FILETIME contains a 64-bit value representing the number of - * 100-nanosecond intervals since January 1, 1601 (UTC). - * A UNIX time is the number of seconds that have elapsed since the - * UNIX epoch, that is the time 00:00:00 UTC on 1 January 1970. - */ -static double -_to_unix_time(ULONGLONG hiPart, ULONGLONG loPart) { - ULONGLONG ret; - - // 100 nanosecond intervals since January 1, 1601. - ret = hiPart << 32; - ret += loPart; - // Change starting time to the Epoch (00:00:00 UTC, January 1, 1970). - ret -= 116444736000000000ull; - // Convert nano secs to secs. - return (double) ret / 10000000ull; -} - - -double -psutil_FiletimeToUnixTime(FILETIME ft) { - return _to_unix_time((ULONGLONG)ft.dwHighDateTime, - (ULONGLONG)ft.dwLowDateTime); - -} - - -double -psutil_LargeIntegerToUnixTime(LARGE_INTEGER li) { - return _to_unix_time((ULONGLONG)li.HighPart, - (ULONGLONG)li.LowPart); -} -#endif // PSUTIL_WINDOWS diff --git a/third_party/python/psutil/psutil/_psutil_common.h b/third_party/python/psutil/psutil/_psutil_common.h deleted file mode 100644 index 34c428c0581a..000000000000 --- a/third_party/python/psutil/psutil/_psutil_common.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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. - */ - -#include - -// ==================================================================== -// --- Global vars / constants -// ==================================================================== - -extern int PSUTIL_TESTING; -extern int PSUTIL_DEBUG; -// a signaler for connections without an actual status -static const int PSUTIL_CONN_NONE = 128; - -// ==================================================================== -// --- Backward compatibility with missing Python.h APIs -// ==================================================================== - -#if PY_MAJOR_VERSION < 3 - // On Python 2 we just return a plain byte string, which is never - // supposed to raise decoding errors, see: - // https://github.com/giampaolo/psutil/issues/1040 - #define PyUnicode_DecodeFSDefault PyString_FromString - #define PyUnicode_DecodeFSDefaultAndSize PyString_FromStringAndSize -#endif - -#if defined(PSUTIL_WINDOWS) && \ - defined(PYPY_VERSION) && \ - !defined(PyErr_SetFromWindowsErrWithFilename) - PyObject *PyErr_SetFromWindowsErrWithFilename(int ierr, - const char *filename); -#endif - -// --- _Py_PARSE_PID - -// SIZEOF_INT|LONG is missing on Linux + PyPy (only?). -// SIZEOF_PID_T is missing on Windows + Python2. -// In this case we guess it from setup.py. It's not 100% bullet proof, -// If wrong we'll probably get compiler warnings. -// FWIW on all UNIX platforms I've seen pid_t is defined as an int. -// _getpid() on Windows also returns an int. -#if !defined(SIZEOF_INT) - #define SIZEOF_INT 4 -#endif -#if !defined(SIZEOF_LONG) - #define SIZEOF_LONG 8 -#endif -#if !defined(SIZEOF_PID_T) - #define SIZEOF_PID_T PSUTIL_SIZEOF_PID_T // set as a macro in setup.py -#endif - -// _Py_PARSE_PID is Python 3 only, but since it's private make sure it's -// always present. -#ifndef _Py_PARSE_PID - #if SIZEOF_PID_T == SIZEOF_INT - #define _Py_PARSE_PID "i" - #elif SIZEOF_PID_T == SIZEOF_LONG - #define _Py_PARSE_PID "l" - #elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG - #define _Py_PARSE_PID "L" - #else - #error "_Py_PARSE_PID: sizeof(pid_t) is neither sizeof(int), " - "sizeof(long) or sizeof(long long)" - #endif -#endif - -// Python 2 or PyPy on Windows -#ifndef PyLong_FromPid - #if ((SIZEOF_PID_T == SIZEOF_INT) || (SIZEOF_PID_T == SIZEOF_LONG)) - #if PY_MAJOR_VERSION >= 3 - #define PyLong_FromPid PyLong_FromLong - #else - #define PyLong_FromPid PyInt_FromLong - #endif - #elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG - #define PyLong_FromPid PyLong_FromLongLong - #else - #error "PyLong_FromPid: sizeof(pid_t) is neither sizeof(int), " - "sizeof(long) or sizeof(long long)" - #endif -#endif - -// ==================================================================== -// --- Custom exceptions -// ==================================================================== - -PyObject* AccessDenied(const char *msg); -PyObject* NoSuchProcess(const char *msg); -PyObject* PyErr_SetFromOSErrnoWithSyscall(const char *syscall); - -// ==================================================================== -// --- Global utils -// ==================================================================== - -PyObject* psutil_set_testing(PyObject *self, PyObject *args); -void psutil_debug(const char* format, ...); -int psutil_setup(void); - -// ==================================================================== -// --- Windows -// ==================================================================== - -#ifdef PSUTIL_WINDOWS - #include - // make it available to any file which includes this module - #include "arch/windows/ntextapi.h" - - extern int PSUTIL_WINVER; - extern SYSTEM_INFO PSUTIL_SYSTEM_INFO; - extern CRITICAL_SECTION PSUTIL_CRITICAL_SECTION; - - #define PSUTIL_WINDOWS_VISTA 60 - #define PSUTIL_WINDOWS_7 61 - #define PSUTIL_WINDOWS_8 62 - #define PSUTIL_WINDOWS_8_1 63 - #define PSUTIL_WINDOWS_10 100 - #define PSUTIL_WINDOWS_NEW MAXLONG - - #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) - #define MALLOC_ZERO(x) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (x)) - #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) - - #define LO_T 1e-7 - #define HI_T 429.4967296 - - #ifndef AF_INET6 - #define AF_INET6 23 - #endif - - int psutil_load_globals(); - PVOID psutil_GetProcAddress(LPCSTR libname, LPCSTR procname); - PVOID psutil_GetProcAddressFromLib(LPCSTR libname, LPCSTR procname); - PVOID psutil_SetFromNTStatusErr(NTSTATUS Status, const char *syscall); - double psutil_FiletimeToUnixTime(FILETIME ft); - double psutil_LargeIntegerToUnixTime(LARGE_INTEGER li); -#endif diff --git a/third_party/python/psutil/psutil/_psutil_linux.c b/third_party/python/psutil/psutil/_psutil_linux.c deleted file mode 100644 index 915ab9b4868c..000000000000 --- a/third_party/python/psutil/psutil/_psutil_linux.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - * 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. - * - * Linux-specific functions. - */ - -#ifndef _GNU_SOURCE - #define _GNU_SOURCE 1 -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// see: https://github.com/giampaolo/psutil/issues/659 -#ifdef PSUTIL_ETHTOOL_MISSING_TYPES - #include - typedef __u64 u64; - typedef __u32 u32; - typedef __u16 u16; - typedef __u8 u8; -#endif -/* Avoid redefinition of struct sysinfo with musl libc */ -#define _LINUX_SYSINFO_H -#include - -/* The minimum number of CPUs allocated in a cpu_set_t */ -static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; - -// Linux >= 2.6.13 -#define PSUTIL_HAVE_IOPRIO defined(__NR_ioprio_get) && defined(__NR_ioprio_set) - -// Linux >= 2.6.36 (supposedly) and glibc >= 13 -#define PSUTIL_HAVE_PRLIMIT \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) && \ - (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 13) && \ - defined(__NR_prlimit64) - -#if PSUTIL_HAVE_PRLIMIT - #define _FILE_OFFSET_BITS 64 - #include - #include -#endif - -// Should exist starting from CentOS 6 (year 2011). -#ifdef CPU_ALLOC - #define PSUTIL_HAVE_CPU_AFFINITY -#endif - -#include "_psutil_common.h" -#include "_psutil_posix.h" - -// May happen on old RedHat versions, see: -// https://github.com/giampaolo/psutil/issues/607 -#ifndef DUPLEX_UNKNOWN - #define DUPLEX_UNKNOWN 0xff -#endif - - -#if PSUTIL_HAVE_IOPRIO -enum { - IOPRIO_WHO_PROCESS = 1, -}; - -static inline int -ioprio_get(int which, int who) { - return syscall(__NR_ioprio_get, which, who); -} - -static inline int -ioprio_set(int which, int who, int ioprio) { - return syscall(__NR_ioprio_set, which, who, ioprio); -} - -#define IOPRIO_CLASS_SHIFT 13 -#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1) - -#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT) -#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK) -#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) - - -/* - * Return a (ioclass, iodata) Python tuple representing process I/O priority. - */ -static PyObject * -psutil_proc_ioprio_get(PyObject *self, PyObject *args) { - pid_t pid; - int ioprio, ioclass, iodata; - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid); - if (ioprio == -1) - return PyErr_SetFromErrno(PyExc_OSError); - ioclass = IOPRIO_PRIO_CLASS(ioprio); - iodata = IOPRIO_PRIO_DATA(ioprio); - return Py_BuildValue("ii", ioclass, iodata); -} - - -/* - * A wrapper around ioprio_set(); sets process I/O priority. - * ioclass can be either IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE - * or 0. iodata goes from 0 to 7 depending on ioclass specified. - */ -static PyObject * -psutil_proc_ioprio_set(PyObject *self, PyObject *args) { - pid_t pid; - int ioprio, ioclass, iodata; - int retval; - - if (! PyArg_ParseTuple( - args, _Py_PARSE_PID "ii", &pid, &ioclass, &iodata)) { - return NULL; - } - ioprio = IOPRIO_PRIO_VALUE(ioclass, iodata); - retval = ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio); - if (retval == -1) - return PyErr_SetFromErrno(PyExc_OSError); - Py_RETURN_NONE; -} -#endif - - -#if PSUTIL_HAVE_PRLIMIT -/* - * A wrapper around prlimit(2); sets process resource limits. - * This can be used for both get and set, in which case extra - * 'soft' and 'hard' args must be provided. - */ -static PyObject * -psutil_linux_prlimit(PyObject *self, PyObject *args) { - pid_t pid; - int ret, resource; - struct rlimit old, new; - struct rlimit *newp = NULL; - PyObject *py_soft = NULL; - PyObject *py_hard = NULL; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "i|OO", &pid, &resource, - &py_soft, &py_hard)) { - return NULL; - } - - // get - if (py_soft == NULL && py_hard == NULL) { - ret = prlimit(pid, resource, NULL, &old); - if (ret == -1) - return PyErr_SetFromErrno(PyExc_OSError); -#if defined(PSUTIL_HAVE_LONG_LONG) - if (sizeof(old.rlim_cur) > sizeof(long)) { - return Py_BuildValue("LL", - (PY_LONG_LONG)old.rlim_cur, - (PY_LONG_LONG)old.rlim_max); - } -#endif - return Py_BuildValue("ll", (long)old.rlim_cur, (long)old.rlim_max); - } - - // set - else { -#if defined(PSUTIL_HAVE_LARGEFILE_SUPPORT) - new.rlim_cur = PyLong_AsLongLong(py_soft); - if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; - new.rlim_max = PyLong_AsLongLong(py_hard); - if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; -#else - new.rlim_cur = PyLong_AsLong(py_soft); - if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; - new.rlim_max = PyLong_AsLong(py_hard); - if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; -#endif - newp = &new; - ret = prlimit(pid, resource, newp, &old); - if (ret == -1) - return PyErr_SetFromErrno(PyExc_OSError); - Py_RETURN_NONE; - } -} -#endif - - -/* - * Return disk mounted partitions as a list of tuples including device, - * mount point and filesystem type - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - FILE *file = NULL; - struct mntent *entry; - char *mtab_path; - PyObject *py_dev = NULL; - PyObject *py_mountp = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - if (!PyArg_ParseTuple(args, "s", &mtab_path)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - file = setmntent(mtab_path, "r"); - Py_END_ALLOW_THREADS - if ((file == 0) || (file == NULL)) { - psutil_debug("setmntent() failed"); - PyErr_SetFromErrnoWithFilename(PyExc_OSError, mtab_path); - goto error; - } - - while ((entry = getmntent(file))) { - if (entry == NULL) { - PyErr_Format(PyExc_RuntimeError, "getmntent() syscall failed"); - goto error; - } - py_dev = PyUnicode_DecodeFSDefault(entry->mnt_fsname); - if (! py_dev) - goto error; - py_mountp = PyUnicode_DecodeFSDefault(entry->mnt_dir); - if (! py_mountp) - goto error; - py_tuple = Py_BuildValue("(OOss)", - py_dev, // device - py_mountp, // mount point - entry->mnt_type, // fs type - entry->mnt_opts); // options - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_dev); - Py_CLEAR(py_mountp); - Py_CLEAR(py_tuple); - } - endmntent(file); - return py_retlist; - -error: - if (file != NULL) - endmntent(file); - Py_XDECREF(py_dev); - Py_XDECREF(py_mountp); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - return NULL; -} - - -/* - * A wrapper around sysinfo(), return system memory usage statistics. - */ -static PyObject * -psutil_linux_sysinfo(PyObject *self, PyObject *args) { - struct sysinfo info; - - if (sysinfo(&info) != 0) - return PyErr_SetFromErrno(PyExc_OSError); - // note: boot time might also be determined from here - return Py_BuildValue( - "(kkkkkkI)", - info.totalram, // total - info.freeram, // free - info.bufferram, // buffer - info.sharedram, // shared - info.totalswap, // swap tot - info.freeswap, // swap free - info.mem_unit // multiplier - ); -} - - -/* - * Return process CPU affinity as a Python list - */ -#ifdef PSUTIL_HAVE_CPU_AFFINITY - -static PyObject * -psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) { - int cpu, ncpus, count, cpucount_s; - pid_t pid; - size_t setsize; - cpu_set_t *mask = NULL; - PyObject *py_list = NULL; - - if (!PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - ncpus = NCPUS_START; - while (1) { - setsize = CPU_ALLOC_SIZE(ncpus); - mask = CPU_ALLOC(ncpus); - if (mask == NULL) { - psutil_debug("CPU_ALLOC() failed"); - return PyErr_NoMemory(); - } - if (sched_getaffinity(pid, setsize, mask) == 0) - break; - CPU_FREE(mask); - if (errno != EINVAL) - return PyErr_SetFromErrno(PyExc_OSError); - if (ncpus > INT_MAX / 2) { - PyErr_SetString(PyExc_OverflowError, "could not allocate " - "a large enough CPU set"); - return NULL; - } - ncpus = ncpus * 2; - } - - py_list = PyList_New(0); - if (py_list == NULL) - goto error; - - cpucount_s = CPU_COUNT_S(setsize, mask); - for (cpu = 0, count = cpucount_s; count; cpu++) { - if (CPU_ISSET_S(cpu, setsize, mask)) { -#if PY_MAJOR_VERSION >= 3 - PyObject *cpu_num = PyLong_FromLong(cpu); -#else - PyObject *cpu_num = PyInt_FromLong(cpu); -#endif - if (cpu_num == NULL) - goto error; - if (PyList_Append(py_list, cpu_num)) { - Py_DECREF(cpu_num); - goto error; - } - Py_DECREF(cpu_num); - --count; - } - } - CPU_FREE(mask); - return py_list; - -error: - if (mask) - CPU_FREE(mask); - Py_XDECREF(py_list); - return NULL; -} - - -/* - * Set process CPU affinity; expects a bitmask - */ -static PyObject * -psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) { - cpu_set_t cpu_set; - size_t len; - pid_t pid; - int i, seq_len; - PyObject *py_cpu_set; - PyObject *py_cpu_seq = NULL; - - if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O", &pid, &py_cpu_set)) - return NULL; - - if (!PySequence_Check(py_cpu_set)) { - PyErr_Format(PyExc_TypeError, "sequence argument expected, got %s", - Py_TYPE(py_cpu_set)->tp_name); - goto error; - } - - py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer"); - if (!py_cpu_seq) - goto error; - seq_len = PySequence_Fast_GET_SIZE(py_cpu_seq); - CPU_ZERO(&cpu_set); - for (i = 0; i < seq_len; i++) { - PyObject *item = PySequence_Fast_GET_ITEM(py_cpu_seq, i); -#if PY_MAJOR_VERSION >= 3 - long value = PyLong_AsLong(item); -#else - long value = PyInt_AsLong(item); -#endif - if ((value == -1) || PyErr_Occurred()) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_ValueError, "invalid CPU value"); - goto error; - } - CPU_SET(value, &cpu_set); - } - - len = sizeof(cpu_set); - if (sched_setaffinity(pid, len, &cpu_set)) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - Py_DECREF(py_cpu_seq); - Py_RETURN_NONE; - -error: - if (py_cpu_seq != NULL) - Py_DECREF(py_cpu_seq); - return NULL; -} -#endif /* PSUTIL_HAVE_CPU_AFFINITY */ - - -/* - * Return currently connected users as a list of tuples. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - struct utmp *ut; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_username = NULL; - PyObject *py_tty = NULL; - PyObject *py_hostname = NULL; - PyObject *py_user_proc = NULL; - - if (py_retlist == NULL) - return NULL; - setutent(); - while (NULL != (ut = getutent())) { - py_tuple = NULL; - py_user_proc = NULL; - if (ut->ut_type == USER_PROCESS) - py_user_proc = Py_True; - else - py_user_proc = Py_False; - py_username = PyUnicode_DecodeFSDefault(ut->ut_user); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(ut->ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(ut->ut_host); - if (! py_hostname) - goto error; - - py_tuple = Py_BuildValue( - "OOOfO" _Py_PARSE_PID, - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)ut->ut_tv.tv_sec, // tstamp - py_user_proc, // (bool) user process - ut->ut_pid // process id - ); - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - } - endutent(); - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tty); - Py_XDECREF(py_hostname); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - endutent(); - return NULL; -} - - -/* - * Return stats about a particular network - * interface. References: - * https://github.com/dpaleino/wicd/blob/master/wicd/backends/be-ioctl.py - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject* -psutil_net_if_duplex_speed(PyObject* self, PyObject* args) { - char *nic_name; - int sock = 0; - int ret; - int duplex; - int speed; - struct ifreq ifr; - struct ethtool_cmd ethcmd; - PyObject *py_retlist = NULL; - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - return PyErr_SetFromOSErrnoWithSyscall("socket()"); - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - - // duplex and speed - memset(ðcmd, 0, sizeof ethcmd); - ethcmd.cmd = ETHTOOL_GSET; - ifr.ifr_data = (void *)ðcmd; - ret = ioctl(sock, SIOCETHTOOL, &ifr); - - if (ret != -1) { - duplex = ethcmd.duplex; - speed = ethcmd.speed; - } - else { - if ((errno == EOPNOTSUPP) || (errno == EINVAL)) { - // EOPNOTSUPP may occur in case of wi-fi cards. - // For EINVAL see: - // https://github.com/giampaolo/psutil/issues/797 - // #issuecomment-202999532 - duplex = DUPLEX_UNKNOWN; - speed = 0; - } - else { - PyErr_SetFromOSErrnoWithSyscall("ioctl(SIOCETHTOOL)"); - goto error; - } - } - - py_retlist = Py_BuildValue("[ii]", duplex, speed); - if (!py_retlist) - goto error; - close(sock); - return py_retlist; - -error: - if (sock != -1) - close(sock); - return NULL; -} - - -/* - * Module init. - */ - -static PyMethodDef mod_methods[] = { - // --- per-process functions - -#if PSUTIL_HAVE_IOPRIO - {"proc_ioprio_get", psutil_proc_ioprio_get, METH_VARARGS, - "Get process I/O priority"}, - {"proc_ioprio_set", psutil_proc_ioprio_set, METH_VARARGS, - "Set process I/O priority"}, -#endif -#ifdef PSUTIL_HAVE_CPU_AFFINITY - {"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS, - "Return process CPU affinity as a Python long (the bitmask)."}, - {"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS, - "Set process CPU affinity; expects a bitmask."}, -#endif - - // --- system related functions - - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return disk mounted partitions as a list of tuples including " - "device, mount point and filesystem type"}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users as a list of tuples"}, - {"net_if_duplex_speed", psutil_net_if_duplex_speed, METH_VARARGS, - "Return duplex and speed info about a NIC"}, - - // --- linux specific - - {"linux_sysinfo", psutil_linux_sysinfo, METH_VARARGS, - "A wrapper around sysinfo(), return system memory usage statistics"}, -#if PSUTIL_HAVE_PRLIMIT - {"linux_prlimit", psutil_linux_prlimit, METH_VARARGS, - "Get or set process resource limits."}, -#endif - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - - -#if PY_MAJOR_VERSION >= 3 - #define INITERR return NULL - - static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_psutil_linux", - NULL, - -1, - mod_methods, - NULL, - NULL, - NULL, - NULL - }; - - PyObject *PyInit__psutil_linux(void) -#else /* PY_MAJOR_VERSION */ - #define INITERR return - - void init_psutil_linux(void) -#endif /* PY_MAJOR_VERSION */ -{ - PyObject *v; -#if PY_MAJOR_VERSION >= 3 - PyObject *mod = PyModule_Create(&moduledef); -#else - PyObject *mod = Py_InitModule("_psutil_linux", mod_methods); -#endif - if (mod == NULL) - INITERR; - - if (PyModule_AddIntConstant(mod, "version", PSUTIL_VERSION)) INITERR; -#if PSUTIL_HAVE_PRLIMIT - if (PyModule_AddIntConstant(mod, "RLIMIT_AS", RLIMIT_AS)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_CORE", RLIMIT_CORE)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_CPU", RLIMIT_CPU)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_DATA", RLIMIT_DATA)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_FSIZE", RLIMIT_FSIZE)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_LOCKS", RLIMIT_LOCKS)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_NOFILE", RLIMIT_NOFILE)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_NPROC", RLIMIT_NPROC)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_RSS", RLIMIT_RSS)) INITERR; - if (PyModule_AddIntConstant(mod, "RLIMIT_STACK", RLIMIT_STACK)) INITERR; - -#if defined(HAVE_LONG_LONG) - if (sizeof(RLIM_INFINITY) > sizeof(long)) { - v = PyLong_FromLongLong((PY_LONG_LONG) RLIM_INFINITY); - } else -#endif - { - v = PyLong_FromLong((long) RLIM_INFINITY); - } - if (v) { - PyModule_AddObject(mod, "RLIM_INFINITY", v); - } - -#ifdef RLIMIT_MSGQUEUE - if (PyModule_AddIntConstant(mod, "RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE)) INITERR; -#endif -#ifdef RLIMIT_NICE - if (PyModule_AddIntConstant(mod, "RLIMIT_NICE", RLIMIT_NICE)) INITERR; -#endif -#ifdef RLIMIT_RTPRIO - if (PyModule_AddIntConstant(mod, "RLIMIT_RTPRIO", RLIMIT_RTPRIO)) INITERR; -#endif -#ifdef RLIMIT_RTTIME - if (PyModule_AddIntConstant(mod, "RLIMIT_RTTIME", RLIMIT_RTTIME)) INITERR; -#endif -#ifdef RLIMIT_SIGPENDING - if (PyModule_AddIntConstant(mod, "RLIMIT_SIGPENDING", RLIMIT_SIGPENDING)) - INITERR; -#endif -#endif - if (PyModule_AddIntConstant(mod, "DUPLEX_HALF", DUPLEX_HALF)) INITERR; - if (PyModule_AddIntConstant(mod, "DUPLEX_FULL", DUPLEX_FULL)) INITERR; - if (PyModule_AddIntConstant(mod, "DUPLEX_UNKNOWN", DUPLEX_UNKNOWN)) INITERR; - - if (mod == NULL) - INITERR; -#if PY_MAJOR_VERSION >= 3 - return mod; -#endif -} diff --git a/third_party/python/psutil/psutil/_psutil_osx.c b/third_party/python/psutil/psutil/_psutil_osx.c deleted file mode 100644 index c51c1c788b11..000000000000 --- a/third_party/python/psutil/psutil/_psutil_osx.c +++ /dev/null @@ -1,1906 +0,0 @@ -/* - * 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. - * - * macOS platform-specific module methods. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "_psutil_common.h" -#include "_psutil_posix.h" -#include "arch/osx/process_info.h" - - -#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) - -static PyObject *ZombieProcessError; - - -/* - * A wrapper around host_statistics() invoked with HOST_VM_INFO. - */ -int -psutil_sys_vminfo(vm_statistics_data_t *vmstat) { - kern_return_t ret; - mach_msg_type_number_t count = sizeof(*vmstat) / sizeof(integer_t); - mach_port_t mport = mach_host_self(); - - ret = host_statistics(mport, HOST_VM_INFO, (host_info_t)vmstat, &count); - if (ret != KERN_SUCCESS) { - PyErr_Format( - PyExc_RuntimeError, - "host_statistics(HOST_VM_INFO) syscall failed: %s", - mach_error_string(ret)); - return 0; - } - mach_port_deallocate(mach_task_self(), mport); - return 1; -} - - -/* - * A wrapper around task_for_pid() which sucks big time: - * - it's not documented - * - errno is set only sometimes - * - sometimes errno is ENOENT (?!?) - * - for PIDs != getpid() or PIDs which are not members of the procmod - * it requires root - * As such we can only guess what the heck went wrong and fail either - * with NoSuchProcess, ZombieProcessError or giveup with AccessDenied. - * Here's some history: - * https://github.com/giampaolo/psutil/issues/1181 - * https://github.com/giampaolo/psutil/issues/1209 - * https://github.com/giampaolo/psutil/issues/1291#issuecomment-396062519 - */ -int -psutil_task_for_pid(pid_t pid, mach_port_t *task) -{ - // See: https://github.com/giampaolo/psutil/issues/1181 - kern_return_t err = KERN_SUCCESS; - - err = task_for_pid(mach_task_self(), pid, task); - if (err != KERN_SUCCESS) { - if (psutil_pid_exists(pid) == 0) - NoSuchProcess("task_for_pid"); - else if (psutil_is_zombie(pid) == 1) - PyErr_SetString(ZombieProcessError, "task_for_pid() failed"); - else { - psutil_debug( - "task_for_pid() failed (pid=%ld, err=%i, errno=%i, msg='%s'); " - "setting AccessDenied()", - pid, err, errno, mach_error_string(err)); - AccessDenied("task_for_pid"); - } - return 1; - } - return 0; -} - - -/* - * Return a Python list of all the PIDs running on the system. - */ -static PyObject * -psutil_pids(PyObject *self, PyObject *args) { - kinfo_proc *proclist = NULL; - kinfo_proc *orig_address = NULL; - size_t num_processes; - size_t idx; - PyObject *py_pid = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - if (psutil_get_proc_list(&proclist, &num_processes) != 0) - goto error; - - // save the address of proclist so we can free it later - orig_address = proclist; - for (idx = 0; idx < num_processes; idx++) { - py_pid = PyLong_FromPid(proclist->kp_proc.p_pid); - if (! py_pid) - goto error; - if (PyList_Append(py_retlist, py_pid)) - goto error; - Py_CLEAR(py_pid); - proclist++; - } - free(orig_address); - - return py_retlist; - -error: - Py_XDECREF(py_pid); - Py_DECREF(py_retlist); - if (orig_address != NULL) - free(orig_address); - return NULL; -} - - -/* - * Return multiple process info as a Python tuple in one shot by - * using sysctl() and filling up a kinfo_proc struct. - * It should be possible to do this for all processes without - * incurring into permission (EPERM) errors. - * This will also succeed for zombie processes returning correct - * information. - */ -static PyObject * -psutil_proc_kinfo_oneshot(PyObject *self, PyObject *args) { - pid_t pid; - struct kinfo_proc kp; - PyObject *py_name; - PyObject *py_retlist; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return NULL; - - py_name = PyUnicode_DecodeFSDefault(kp.kp_proc.p_comm); - if (! py_name) { - // Likely a decoding error. We don't want to fail the whole - // operation. The python module may retry with proc_name(). - PyErr_Clear(); - py_name = Py_None; - } - - py_retlist = Py_BuildValue( - _Py_PARSE_PID "llllllidiO", - kp.kp_eproc.e_ppid, // (pid_t) ppid - (long)kp.kp_eproc.e_pcred.p_ruid, // (long) real uid - (long)kp.kp_eproc.e_ucred.cr_uid, // (long) effective uid - (long)kp.kp_eproc.e_pcred.p_svuid, // (long) saved uid - (long)kp.kp_eproc.e_pcred.p_rgid, // (long) real gid - (long)kp.kp_eproc.e_ucred.cr_groups[0], // (long) effective gid - (long)kp.kp_eproc.e_pcred.p_svgid, // (long) saved gid - kp.kp_eproc.e_tdev, // (int) tty nr - PSUTIL_TV2DOUBLE(kp.kp_proc.p_starttime), // (double) create time - (int)kp.kp_proc.p_stat, // (int) status - py_name // (pystr) name - ); - - if (py_retlist != NULL) { - // XXX shall we decref() also in case of Py_BuildValue() error? - Py_DECREF(py_name); - } - return py_retlist; -} - - -/* - * Return multiple process info as a Python tuple in one shot by - * using proc_pidinfo(PROC_PIDTASKINFO) and filling a proc_taskinfo - * struct. - * Contrarily from proc_kinfo above this function will fail with - * EACCES for PIDs owned by another user and with ESRCH for zombie - * processes. - */ -static PyObject * -psutil_proc_pidtaskinfo_oneshot(PyObject *self, PyObject *args) { - pid_t pid; - struct proc_taskinfo pti; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if (psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti)) <= 0) - return NULL; - - return Py_BuildValue( - "(ddKKkkkk)", - (float)pti.pti_total_user / 1000000000.0, // (float) cpu user time - (float)pti.pti_total_system / 1000000000.0, // (float) cpu sys time - // Note about memory: determining other mem stats on macOS is a mess: - // http://www.opensource.apple.com/source/top/top-67/libtop.c?txt - // I just give up. - // struct proc_regioninfo pri; - // psutil_proc_pidinfo(pid, PROC_PIDREGIONINFO, 0, &pri, sizeof(pri)) - pti.pti_resident_size, // (uns long long) rss - pti.pti_virtual_size, // (uns long long) vms - pti.pti_faults, // (uns long) number of page faults (pages) - pti.pti_pageins, // (uns long) number of actual pageins (pages) - pti.pti_threadnum, // (uns long) num threads - // Unvoluntary value seems not to be available; - // pti.pti_csw probably refers to the sum of the two; - // getrusage() numbers seems to confirm this theory. - pti.pti_csw // (uns long) voluntary ctx switches - ); -} - - -/* - * Return process name from kinfo_proc as a Python string. - */ -static PyObject * -psutil_proc_name(PyObject *self, PyObject *args) { - pid_t pid; - struct kinfo_proc kp; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return NULL; - return PyUnicode_DecodeFSDefault(kp.kp_proc.p_comm); -} - - -/* - * Return process current working directory. - * Raises NSP in case of zombie process. - */ -static PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) { - pid_t pid; - struct proc_vnodepathinfo pathinfo; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - if (psutil_proc_pidinfo( - pid, PROC_PIDVNODEPATHINFO, 0, &pathinfo, sizeof(pathinfo)) <= 0) - { - return NULL; - } - - return PyUnicode_DecodeFSDefault(pathinfo.pvi_cdir.vip_path); -} - - -/* - * Return path of the process executable. - */ -static PyObject * -psutil_proc_exe(PyObject *self, PyObject *args) { - pid_t pid; - char buf[PATH_MAX]; - int ret; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - errno = 0; - ret = proc_pidpath(pid, &buf, sizeof(buf)); - if (ret == 0) { - if (pid == 0) - AccessDenied("automatically set for PID 0"); - else - psutil_raise_for_pid(pid, "proc_pidpath()"); - return NULL; - } - return PyUnicode_DecodeFSDefault(buf); -} - - -/* - * Return process cmdline as a Python list of cmdline arguments. - */ -static PyObject * -psutil_proc_cmdline(PyObject *self, PyObject *args) { - pid_t pid; - PyObject *py_retlist = NULL; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - // get the commandline, defined in arch/osx/process_info.c - py_retlist = psutil_get_cmdline(pid); - return py_retlist; -} - - -/* - * Return process environment as a Python string. - */ -static PyObject * -psutil_proc_environ(PyObject *self, PyObject *args) { - pid_t pid; - PyObject *py_retdict = NULL; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - // get the environment block, defined in arch/osx/process_info.c - py_retdict = psutil_get_environ(pid); - return py_retdict; -} - - -/* - * Return the number of logical CPUs in the system. - * XXX this could be shared with BSD. - */ -static PyObject * -psutil_cpu_count_logical(PyObject *self, PyObject *args) { - /* - int mib[2]; - int ncpu; - size_t len; - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("i", ncpu); - */ - int num; - size_t size = sizeof(int); - - if (sysctlbyname("hw.logicalcpu", &num, &size, NULL, 2)) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("i", num); -} - - -/* - * Return the number of physical CPUs in the system. - */ -static PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) { - int num; - size_t size = sizeof(int); - - if (sysctlbyname("hw.physicalcpu", &num, &size, NULL, 0)) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("i", num); -} - - -/* - * Indicates if the given virtual address on the given architecture is in the - * shared VM region. - */ -static bool -psutil_in_shared_region(mach_vm_address_t addr, cpu_type_t type) { - mach_vm_address_t base; - mach_vm_address_t size; - - switch (type) { - case CPU_TYPE_ARM: - base = SHARED_REGION_BASE_ARM; - size = SHARED_REGION_SIZE_ARM; - break; - case CPU_TYPE_I386: - base = SHARED_REGION_BASE_I386; - size = SHARED_REGION_SIZE_I386; - break; - case CPU_TYPE_X86_64: - base = SHARED_REGION_BASE_X86_64; - size = SHARED_REGION_SIZE_X86_64; - break; - default: - return false; - } - - return base <= addr && addr < (base + size); -} - - -/* - * Returns the USS (unique set size) of the process. Reference: - * https://dxr.mozilla.org/mozilla-central/source/xpcom/base/ - * nsMemoryReporterManager.cpp - */ -static PyObject * -psutil_proc_memory_uss(PyObject *self, PyObject *args) { - pid_t pid; - size_t len; - cpu_type_t cpu_type; - size_t private_pages = 0; - mach_vm_size_t size = 0; - mach_msg_type_number_t info_count = VM_REGION_TOP_INFO_COUNT; - kern_return_t kr; - vm_size_t page_size; - mach_vm_address_t addr = MACH_VM_MIN_ADDRESS; - mach_port_t task = MACH_PORT_NULL; - vm_region_top_info_data_t info; - mach_port_t object_name; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - if (psutil_task_for_pid(pid, &task) != 0) - return NULL; - - len = sizeof(cpu_type); - if (sysctlbyname("sysctl.proc_cputype", &cpu_type, &len, NULL, 0) != 0) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('sysctl.proc_cputype')"); - } - - // Roughly based on libtop_update_vm_regions in - // http://www.opensource.apple.com/source/top/top-100.1.2/libtop.c - for (addr = 0; ; addr += size) { - kr = mach_vm_region( - task, &addr, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info, - &info_count, &object_name); - if (kr == KERN_INVALID_ADDRESS) { - // Done iterating VM regions. - break; - } - else if (kr != KERN_SUCCESS) { - PyErr_Format( - PyExc_RuntimeError, - "mach_vm_region(VM_REGION_TOP_INFO) syscall failed"); - return NULL; - } - - if (psutil_in_shared_region(addr, cpu_type) && - info.share_mode != SM_PRIVATE) { - continue; - } - - switch (info.share_mode) { -#ifdef SM_LARGE_PAGE - case SM_LARGE_PAGE: - // NB: Large pages are not shareable and always resident. -#endif - case SM_PRIVATE: - private_pages += info.private_pages_resident; - private_pages += info.shared_pages_resident; - break; - case SM_COW: - private_pages += info.private_pages_resident; - if (info.ref_count == 1) { - // Treat copy-on-write pages as private if they only - // have one reference. - private_pages += info.shared_pages_resident; - } - break; - case SM_SHARED: - default: - break; - } - } - - mach_port_deallocate(mach_task_self(), task); - - if (host_page_size(mach_host_self(), &page_size) != KERN_SUCCESS) - page_size = PAGE_SIZE; - - return Py_BuildValue("K", private_pages * page_size); -} - - -/* - * Return system virtual memory stats. - * See: - * https://opensource.apple.com/source/system_cmds/system_cmds-790/ - * vm_stat.tproj/vm_stat.c.auto.html - */ -static PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - int mib[2]; - uint64_t total; - size_t len = sizeof(total); - vm_statistics_data_t vm; - int pagesize = getpagesize(); - // physical mem - mib[0] = CTL_HW; - mib[1] = HW_MEMSIZE; - - // This is also available as sysctlbyname("hw.memsize"). - if (sysctl(mib, 2, &total, &len, NULL, 0)) { - if (errno != 0) - PyErr_SetFromErrno(PyExc_OSError); - else - PyErr_Format( - PyExc_RuntimeError, "sysctl(HW_MEMSIZE) syscall failed"); - return NULL; - } - - // vm - if (!psutil_sys_vminfo(&vm)) - return NULL; - - return Py_BuildValue( - "KKKKKK", - total, - (unsigned long long) vm.active_count * pagesize, // active - (unsigned long long) vm.inactive_count * pagesize, // inactive - (unsigned long long) vm.wire_count * pagesize, // wired - (unsigned long long) vm.free_count * pagesize, // free - (unsigned long long) vm.speculative_count * pagesize // speculative - ); -} - - -/* - * Return stats about swap memory. - */ -static PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { - int mib[2]; - size_t size; - struct xsw_usage totals; - vm_statistics_data_t vmstat; - int pagesize = getpagesize(); - - mib[0] = CTL_VM; - mib[1] = VM_SWAPUSAGE; - size = sizeof(totals); - if (sysctl(mib, 2, &totals, &size, NULL, 0) == -1) { - if (errno != 0) - PyErr_SetFromErrno(PyExc_OSError); - else - PyErr_Format( - PyExc_RuntimeError, "sysctl(VM_SWAPUSAGE) syscall failed"); - return NULL; - } - if (!psutil_sys_vminfo(&vmstat)) - return NULL; - - return Py_BuildValue( - "LLLKK", - totals.xsu_total, - totals.xsu_used, - totals.xsu_avail, - (unsigned long long)vmstat.pageins * pagesize, - (unsigned long long)vmstat.pageouts * pagesize); -} - - -/* - * Return a Python tuple representing user, kernel and idle CPU times - */ -static PyObject * -psutil_cpu_times(PyObject *self, PyObject *args) { - mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; - kern_return_t error; - host_cpu_load_info_data_t r_load; - - mach_port_t host_port = mach_host_self(); - error = host_statistics(host_port, HOST_CPU_LOAD_INFO, - (host_info_t)&r_load, &count); - if (error != KERN_SUCCESS) { - return PyErr_Format( - PyExc_RuntimeError, - "host_statistics(HOST_CPU_LOAD_INFO) syscall failed: %s", - mach_error_string(error)); - } - mach_port_deallocate(mach_task_self(), host_port); - - return Py_BuildValue( - "(dddd)", - (double)r_load.cpu_ticks[CPU_STATE_USER] / CLK_TCK, - (double)r_load.cpu_ticks[CPU_STATE_NICE] / CLK_TCK, - (double)r_load.cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK, - (double)r_load.cpu_ticks[CPU_STATE_IDLE] / CLK_TCK - ); -} - - -/* - * Return a Python list of tuple representing per-cpu times - */ -static PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - natural_t cpu_count; - natural_t i; - processor_info_array_t info_array; - mach_msg_type_number_t info_count; - kern_return_t error; - processor_cpu_load_info_data_t *cpu_load_info = NULL; - int ret; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - mach_port_t host_port = mach_host_self(); - error = host_processor_info(host_port, PROCESSOR_CPU_LOAD_INFO, - &cpu_count, &info_array, &info_count); - if (error != KERN_SUCCESS) { - PyErr_Format( - PyExc_RuntimeError, - "host_processor_info(PROCESSOR_CPU_LOAD_INFO) syscall failed: %s", - mach_error_string(error)); - goto error; - } - mach_port_deallocate(mach_task_self(), host_port); - - cpu_load_info = (processor_cpu_load_info_data_t *) info_array; - - for (i = 0; i < cpu_count; i++) { - py_cputime = Py_BuildValue( - "(dddd)", - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_USER] / CLK_TCK, - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_NICE] / CLK_TCK, - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK, - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_IDLE] / CLK_TCK - ); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_CLEAR(py_cputime); - } - - ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array, - info_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - if (cpu_load_info != NULL) { - ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array, - info_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - } - return NULL; -} - - -/* - * Retrieve CPU frequency. - */ -static PyObject * -psutil_cpu_freq(PyObject *self, PyObject *args) { - int64_t curr; - int64_t min; - int64_t max; - size_t size = sizeof(int64_t); - - if (sysctlbyname("hw.cpufrequency", &curr, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('hw.cpufrequency')"); - } - if (sysctlbyname("hw.cpufrequency_min", &min, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('hw.cpufrequency_min')"); - } - if (sysctlbyname("hw.cpufrequency_max", &max, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('hw.cpufrequency_max')"); - } - - return Py_BuildValue( - "KKK", - curr / 1000 / 1000, - min / 1000 / 1000, - max / 1000 / 1000); -} - - -/* - * Return a Python float indicating the system boot time expressed in - * seconds since the epoch. - */ -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) { - // fetch sysctl "kern.boottime" - static int request[2] = { CTL_KERN, KERN_BOOTTIME }; - struct timeval result; - size_t result_len = sizeof result; - time_t boot_time = 0; - - if (sysctl(request, 2, &result, &result_len, NULL, 0) == -1) - return PyErr_SetFromErrno(PyExc_OSError); - boot_time = result.tv_sec; - return Py_BuildValue("f", (float)boot_time); -} - - -/* - * Return a list of tuples including device, mount point and fs type - * for all partitions mounted on the system. - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - int num; - int i; - int len; - uint64_t flags; - char opts[400]; - struct statfs *fs = NULL; - PyObject *py_dev = NULL; - PyObject *py_mountp = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - // get the number of mount points - Py_BEGIN_ALLOW_THREADS - num = getfsstat(NULL, 0, MNT_NOWAIT); - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - len = sizeof(*fs) * num; - fs = malloc(len); - if (fs == NULL) { - PyErr_NoMemory(); - goto error; - } - - Py_BEGIN_ALLOW_THREADS - num = getfsstat(fs, len, MNT_NOWAIT); - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < num; i++) { - opts[0] = 0; - flags = fs[i].f_flags; - - // see sys/mount.h - if (flags & MNT_RDONLY) - strlcat(opts, "ro", sizeof(opts)); - else - strlcat(opts, "rw", sizeof(opts)); - if (flags & MNT_SYNCHRONOUS) - strlcat(opts, ",sync", sizeof(opts)); - if (flags & MNT_NOEXEC) - strlcat(opts, ",noexec", sizeof(opts)); - if (flags & MNT_NOSUID) - strlcat(opts, ",nosuid", sizeof(opts)); - if (flags & MNT_UNION) - strlcat(opts, ",union", sizeof(opts)); - if (flags & MNT_ASYNC) - strlcat(opts, ",async", sizeof(opts)); - if (flags & MNT_EXPORTED) - strlcat(opts, ",exported", sizeof(opts)); - if (flags & MNT_QUARANTINE) - strlcat(opts, ",quarantine", sizeof(opts)); - if (flags & MNT_LOCAL) - strlcat(opts, ",local", sizeof(opts)); - if (flags & MNT_QUOTA) - strlcat(opts, ",quota", sizeof(opts)); - if (flags & MNT_ROOTFS) - strlcat(opts, ",rootfs", sizeof(opts)); - if (flags & MNT_DOVOLFS) - strlcat(opts, ",dovolfs", sizeof(opts)); - if (flags & MNT_DONTBROWSE) - strlcat(opts, ",dontbrowse", sizeof(opts)); - if (flags & MNT_IGNORE_OWNERSHIP) - strlcat(opts, ",ignore-ownership", sizeof(opts)); - if (flags & MNT_AUTOMOUNTED) - strlcat(opts, ",automounted", sizeof(opts)); - if (flags & MNT_JOURNALED) - strlcat(opts, ",journaled", sizeof(opts)); - if (flags & MNT_NOUSERXATTR) - strlcat(opts, ",nouserxattr", sizeof(opts)); - if (flags & MNT_DEFWRITE) - strlcat(opts, ",defwrite", sizeof(opts)); - if (flags & MNT_MULTILABEL) - strlcat(opts, ",multilabel", sizeof(opts)); - if (flags & MNT_NOATIME) - strlcat(opts, ",noatime", sizeof(opts)); - if (flags & MNT_UPDATE) - strlcat(opts, ",update", sizeof(opts)); - if (flags & MNT_RELOAD) - strlcat(opts, ",reload", sizeof(opts)); - if (flags & MNT_FORCE) - strlcat(opts, ",force", sizeof(opts)); - if (flags & MNT_CMDFLAGS) - strlcat(opts, ",cmdflags", sizeof(opts)); - - py_dev = PyUnicode_DecodeFSDefault(fs[i].f_mntfromname); - if (! py_dev) - goto error; - py_mountp = PyUnicode_DecodeFSDefault(fs[i].f_mntonname); - if (! py_mountp) - goto error; - py_tuple = Py_BuildValue( - "(OOss)", - py_dev, // device - py_mountp, // mount point - fs[i].f_fstypename, // fs type - opts); // options - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_dev); - Py_CLEAR(py_mountp); - Py_CLEAR(py_tuple); - } - - free(fs); - return py_retlist; - -error: - Py_XDECREF(py_dev); - Py_XDECREF(py_mountp); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (fs != NULL) - free(fs); - return NULL; -} - - -/* - * Return process threads - */ -static PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - pid_t pid; - int err, ret; - kern_return_t kr; - unsigned int info_count = TASK_BASIC_INFO_COUNT; - mach_port_t task = MACH_PORT_NULL; - struct task_basic_info tasks_info; - thread_act_port_array_t thread_list = NULL; - thread_info_data_t thinfo_basic; - thread_basic_info_t basic_info_th; - mach_msg_type_number_t thread_count, thread_info_count, j; - - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - goto error; - - if (psutil_task_for_pid(pid, &task) != 0) - goto error; - - info_count = TASK_BASIC_INFO_COUNT; - err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, - &info_count); - if (err != KERN_SUCCESS) { - // errcode 4 is "invalid argument" (access denied) - if (err == 4) { - AccessDenied("task_info"); - } - else { - // otherwise throw a runtime error with appropriate error code - PyErr_Format(PyExc_RuntimeError, - "task_info(TASK_BASIC_INFO) syscall failed"); - } - goto error; - } - - err = task_threads(task, &thread_list, &thread_count); - if (err != KERN_SUCCESS) { - PyErr_Format(PyExc_RuntimeError, "task_threads() syscall failed"); - goto error; - } - - for (j = 0; j < thread_count; j++) { - thread_info_count = THREAD_INFO_MAX; - kr = thread_info(thread_list[j], THREAD_BASIC_INFO, - (thread_info_t)thinfo_basic, &thread_info_count); - if (kr != KERN_SUCCESS) { - PyErr_Format(PyExc_RuntimeError, - "thread_info(THREAD_BASIC_INFO) syscall failed"); - goto error; - } - - basic_info_th = (thread_basic_info_t)thinfo_basic; - py_tuple = Py_BuildValue( - "Iff", - j + 1, - basic_info_th->user_time.seconds + \ - (float)basic_info_th->user_time.microseconds / 1000000.0, - basic_info_th->system_time.seconds + \ - (float)basic_info_th->system_time.microseconds / 1000000.0 - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - - ret = vm_deallocate(task, (vm_address_t)thread_list, - thread_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - - mach_port_deallocate(mach_task_self(), task); - - return py_retlist; - -error: - if (task != MACH_PORT_NULL) - mach_port_deallocate(mach_task_self(), task); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (thread_list != NULL) { - ret = vm_deallocate(task, (vm_address_t)thread_list, - thread_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - } - return NULL; -} - - -/* - * Return process open files as a Python tuple. - * References: - * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/m78fd - * - /usr/include/sys/proc_info.h - */ -static PyObject * -psutil_proc_open_files(PyObject *self, PyObject *args) { - pid_t pid; - int pidinfo_result; - int iterations; - int i; - unsigned long nb; - - struct proc_fdinfo *fds_pointer = NULL; - struct proc_fdinfo *fdp_pointer; - struct vnode_fdinfowithpath vi; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_path = NULL; - - if (py_retlist == NULL) - return NULL; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - goto error; - - pidinfo_result = psutil_proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); - if (pidinfo_result <= 0) - goto error; - - fds_pointer = malloc(pidinfo_result); - if (fds_pointer == NULL) { - PyErr_NoMemory(); - goto error; - } - pidinfo_result = psutil_proc_pidinfo( - pid, PROC_PIDLISTFDS, 0, fds_pointer, pidinfo_result); - if (pidinfo_result <= 0) - goto error; - - iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE); - - for (i = 0; i < iterations; i++) { - fdp_pointer = &fds_pointer[i]; - - if (fdp_pointer->proc_fdtype == PROX_FDTYPE_VNODE) { - errno = 0; - nb = proc_pidfdinfo((pid_t)pid, - fdp_pointer->proc_fd, - PROC_PIDFDVNODEPATHINFO, - &vi, - sizeof(vi)); - - // --- errors checking - if ((nb <= 0) || nb < sizeof(vi)) { - if ((errno == ENOENT) || (errno == EBADF)) { - // no such file or directory or bad file descriptor; - // let's assume the file has been closed or removed - continue; - } - else { - psutil_raise_for_pid( - pid, "proc_pidinfo(PROC_PIDFDVNODEPATHINFO)"); - goto error; - } - } - // --- /errors checking - - // --- construct python list - py_path = PyUnicode_DecodeFSDefault(vi.pvip.vip_path); - if (! py_path) - goto error; - py_tuple = Py_BuildValue( - "(Oi)", - py_path, - (int)fdp_pointer->proc_fd); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_path); - // --- /construct python list - } - } - - free(fds_pointer); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_path); - Py_DECREF(py_retlist); - if (fds_pointer != NULL) - free(fds_pointer); - return NULL; // exception has already been set earlier -} - - -/* - * Return process TCP and UDP connections as a list of tuples. - * Raises NSP in case of zombie process. - * References: - * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/wNrC0 - * - /usr/include/sys/proc_info.h - */ -static PyObject * -psutil_proc_connections(PyObject *self, PyObject *args) { - pid_t pid; - int pidinfo_result; - int iterations; - int i; - unsigned long nb; - - struct proc_fdinfo *fds_pointer = NULL; - struct proc_fdinfo *fdp_pointer; - struct socket_fdinfo si; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - PyObject *py_af_filter = NULL; - PyObject *py_type_filter = NULL; - - if (py_retlist == NULL) - return NULL; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "OO", &pid, &py_af_filter, - &py_type_filter)) { - goto error; - } - - if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) { - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - goto error; - } - - if (pid == 0) - return py_retlist; - pidinfo_result = psutil_proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); - if (pidinfo_result <= 0) - goto error; - - fds_pointer = malloc(pidinfo_result); - if (fds_pointer == NULL) { - PyErr_NoMemory(); - goto error; - } - - pidinfo_result = psutil_proc_pidinfo( - pid, PROC_PIDLISTFDS, 0, fds_pointer, pidinfo_result); - if (pidinfo_result <= 0) - goto error; - - iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE); - for (i = 0; i < iterations; i++) { - py_tuple = NULL; - py_laddr = NULL; - py_raddr = NULL; - fdp_pointer = &fds_pointer[i]; - - if (fdp_pointer->proc_fdtype == PROX_FDTYPE_SOCKET) { - errno = 0; - nb = proc_pidfdinfo(pid, fdp_pointer->proc_fd, - PROC_PIDFDSOCKETINFO, &si, sizeof(si)); - - // --- errors checking - if ((nb <= 0) || (nb < sizeof(si))) { - if (errno == EBADF) { - // let's assume socket has been closed - continue; - } - else { - psutil_raise_for_pid( - pid, "proc_pidinfo(PROC_PIDFDSOCKETINFO)"); - goto error; - } - } - // --- /errors checking - - // - int fd, family, type, lport, rport, state; - char lip[200], rip[200]; - int inseq; - PyObject *py_family; - PyObject *py_type; - - fd = (int)fdp_pointer->proc_fd; - family = si.psi.soi_family; - type = si.psi.soi_type; - - // apply filters - py_family = PyLong_FromLong((long)family); - inseq = PySequence_Contains(py_af_filter, py_family); - Py_DECREF(py_family); - if (inseq == 0) - continue; - py_type = PyLong_FromLong((long)type); - inseq = PySequence_Contains(py_type_filter, py_type); - Py_DECREF(py_type); - if (inseq == 0) - continue; - - if (errno != 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - if ((family == AF_INET) || (family == AF_INET6)) { - if (family == AF_INET) { - inet_ntop(AF_INET, - &si.psi.soi_proto.pri_tcp.tcpsi_ini. \ - insi_laddr.ina_46.i46a_addr4, - lip, - sizeof(lip)); - inet_ntop(AF_INET, - &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr. \ - ina_46.i46a_addr4, - rip, - sizeof(rip)); - } - else { - inet_ntop(AF_INET6, - &si.psi.soi_proto.pri_tcp.tcpsi_ini. \ - insi_laddr.ina_6, - lip, sizeof(lip)); - inet_ntop(AF_INET6, - &si.psi.soi_proto.pri_tcp.tcpsi_ini. \ - insi_faddr.ina_6, - rip, sizeof(rip)); - } - - // check for inet_ntop failures - if (errno != 0) { - PyErr_SetFromOSErrnoWithSyscall("inet_ntop()"); - goto error; - } - - lport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport); - rport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport); - if (type == SOCK_STREAM) - state = (int)si.psi.soi_proto.pri_tcp.tcpsi_state; - else - state = PSUTIL_CONN_NONE; - - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - - // construct the python list - py_tuple = Py_BuildValue( - "(iiiNNi)", fd, family, type, py_laddr, py_raddr, state); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - else if (family == AF_UNIX) { - py_laddr = PyUnicode_DecodeFSDefault( - si.psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path); - if (!py_laddr) - goto error; - py_raddr = PyUnicode_DecodeFSDefault( - si.psi.soi_proto.pri_un.unsi_caddr.ua_sun.sun_path); - if (!py_raddr) - goto error; - // construct the python list - py_tuple = Py_BuildValue( - "(iiiOOi)", - fd, family, type, - py_laddr, - py_raddr, - PSUTIL_CONN_NONE); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_laddr); - Py_CLEAR(py_raddr); - } - } - } - - free(fds_pointer); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - Py_DECREF(py_retlist); - if (fds_pointer != NULL) - free(fds_pointer); - return NULL; -} - - -/* - * Return number of file descriptors opened by process. - * Raises NSP in case of zombie process. - */ -static PyObject * -psutil_proc_num_fds(PyObject *self, PyObject *args) { - pid_t pid; - int pidinfo_result; - int num; - struct proc_fdinfo *fds_pointer; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); - if (pidinfo_result <= 0) - return PyErr_SetFromErrno(PyExc_OSError); - - fds_pointer = malloc(pidinfo_result); - if (fds_pointer == NULL) - return PyErr_NoMemory(); - pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer, - pidinfo_result); - if (pidinfo_result <= 0) { - free(fds_pointer); - return PyErr_SetFromErrno(PyExc_OSError); - } - - num = (pidinfo_result / PROC_PIDLISTFD_SIZE); - free(fds_pointer); - return Py_BuildValue("i", num); -} - - -/* - * Return a Python list of named tuples with overall network I/O information - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) { - char *buf = NULL, *lim, *next; - struct if_msghdr *ifm; - int mib[6]; - mib[0] = CTL_NET; // networking subsystem - mib[1] = PF_ROUTE; // type of information - mib[2] = 0; // protocol (IPPROTO_xxx) - mib[3] = 0; // address family - mib[4] = NET_RT_IFLIST2; // operation - mib[5] = 0; - size_t len; - PyObject *py_ifc_info = NULL; - PyObject *py_retdict = PyDict_New(); - - if (py_retdict == NULL) - return NULL; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - buf = malloc(len); - if (buf == NULL) { - PyErr_NoMemory(); - goto error; - } - - if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - lim = buf + len; - - for (next = buf; next < lim; ) { - ifm = (struct if_msghdr *)next; - next += ifm->ifm_msglen; - - if (ifm->ifm_type == RTM_IFINFO2) { - py_ifc_info = NULL; - struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm; - struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1); - char ifc_name[32]; - - strncpy(ifc_name, sdl->sdl_data, sdl->sdl_nlen); - ifc_name[sdl->sdl_nlen] = 0; - - py_ifc_info = Py_BuildValue( - "(KKKKKKKi)", - if2m->ifm_data.ifi_obytes, - if2m->ifm_data.ifi_ibytes, - if2m->ifm_data.ifi_opackets, - if2m->ifm_data.ifi_ipackets, - if2m->ifm_data.ifi_ierrors, - if2m->ifm_data.ifi_oerrors, - if2m->ifm_data.ifi_iqdrops, - 0); // dropout not supported - - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info)) - goto error; - Py_CLEAR(py_ifc_info); - } - else { - continue; - } - } - - free(buf); - return py_retdict; - -error: - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (buf != NULL) - free(buf); - return NULL; -} - - -/* - * Return a Python dict of tuples for disk I/O information - */ -static PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - CFDictionaryRef parent_dict; - CFDictionaryRef props_dict; - CFDictionaryRef stats_dict; - io_registry_entry_t parent; - io_registry_entry_t disk; - io_iterator_t disk_list; - PyObject *py_disk_info = NULL; - PyObject *py_retdict = PyDict_New(); - - if (py_retdict == NULL) - return NULL; - - // Get list of disks - if (IOServiceGetMatchingServices(kIOMasterPortDefault, - IOServiceMatching(kIOMediaClass), - &disk_list) != kIOReturnSuccess) { - PyErr_SetString( - PyExc_RuntimeError, "unable to get the list of disks."); - goto error; - } - - // Iterate over disks - while ((disk = IOIteratorNext(disk_list)) != 0) { - py_disk_info = NULL; - parent_dict = NULL; - props_dict = NULL; - stats_dict = NULL; - - if (IORegistryEntryGetParentEntry(disk, kIOServicePlane, &parent) - != kIOReturnSuccess) { - PyErr_SetString(PyExc_RuntimeError, - "unable to get the disk's parent."); - IOObjectRelease(disk); - goto error; - } - - if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) { - if (IORegistryEntryCreateCFProperties( - disk, - (CFMutableDictionaryRef *) &parent_dict, - kCFAllocatorDefault, - kNilOptions - ) != kIOReturnSuccess) - { - PyErr_SetString(PyExc_RuntimeError, - "unable to get the parent's properties."); - IOObjectRelease(disk); - IOObjectRelease(parent); - goto error; - } - - if (IORegistryEntryCreateCFProperties( - parent, - (CFMutableDictionaryRef *) &props_dict, - kCFAllocatorDefault, - kNilOptions - ) != kIOReturnSuccess) - { - PyErr_SetString(PyExc_RuntimeError, - "unable to get the disk properties."); - CFRelease(props_dict); - IOObjectRelease(disk); - IOObjectRelease(parent); - goto error; - } - - const int kMaxDiskNameSize = 64; - CFStringRef disk_name_ref = (CFStringRef)CFDictionaryGetValue( - parent_dict, CFSTR(kIOBSDNameKey)); - char disk_name[kMaxDiskNameSize]; - - CFStringGetCString(disk_name_ref, - disk_name, - kMaxDiskNameSize, - CFStringGetSystemEncoding()); - - stats_dict = (CFDictionaryRef)CFDictionaryGetValue( - props_dict, CFSTR(kIOBlockStorageDriverStatisticsKey)); - - if (stats_dict == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "Unable to get disk stats."); - goto error; - } - - CFNumberRef number; - int64_t reads = 0; - int64_t writes = 0; - int64_t read_bytes = 0; - int64_t write_bytes = 0; - int64_t read_time = 0; - int64_t write_time = 0; - - // Get disk reads/writes - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &reads); - } - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &writes); - } - - // Get disk bytes read/written - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &read_bytes); - } - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &write_bytes); - } - - // Get disk time spent reading/writing (nanoseconds) - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &read_time); - } - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &write_time); - } - - // Read/Write time on macOS comes back in nanoseconds and in psutil - // we've standardized on milliseconds so do the conversion. - py_disk_info = Py_BuildValue( - "(KKKKKK)", - reads, - writes, - read_bytes, - write_bytes, - read_time / 1000 / 1000, - write_time / 1000 / 1000); - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, disk_name, py_disk_info)) - goto error; - Py_CLEAR(py_disk_info); - - CFRelease(parent_dict); - IOObjectRelease(parent); - CFRelease(props_dict); - IOObjectRelease(disk); - } - } - - IOObjectRelease (disk_list); - - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - return NULL; -} - - -/* - * Return currently connected users as a list of tuples. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - struct utmpx *utx; - PyObject *py_username = NULL; - PyObject *py_tty = NULL; - PyObject *py_hostname = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - while ((utx = getutxent()) != NULL) { - if (utx->ut_type != USER_PROCESS) - continue; - py_username = PyUnicode_DecodeFSDefault(utx->ut_user); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(utx->ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(utx->ut_host); - if (! py_hostname) - goto error; - py_tuple = Py_BuildValue( - "(OOOfi)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)utx->ut_tv.tv_sec, // start time - utx->ut_pid // process id - ); - if (!py_tuple) { - endutxent(); - goto error; - } - if (PyList_Append(py_retlist, py_tuple)) { - endutxent(); - goto error; - } - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - } - - endutxent(); - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tty); - Py_XDECREF(py_hostname); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - return NULL; -} - - -/* - * Return CPU statistics. - */ -static PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - struct vmmeter vmstat; - kern_return_t ret; - mach_msg_type_number_t count = sizeof(vmstat) / sizeof(integer_t); - mach_port_t mport = mach_host_self(); - - ret = host_statistics(mport, HOST_VM_INFO, (host_info_t)&vmstat, &count); - if (ret != KERN_SUCCESS) { - PyErr_Format( - PyExc_RuntimeError, - "host_statistics(HOST_VM_INFO) failed: %s", - mach_error_string(ret)); - return NULL; - } - mach_port_deallocate(mach_task_self(), mport); - - return Py_BuildValue( - "IIIII", - vmstat.v_swtch, // ctx switches - vmstat.v_intr, // interrupts - vmstat.v_soft, // software interrupts - vmstat.v_syscall, // syscalls - vmstat.v_trap // traps - ); -} - - -/* - * Return battery information. - */ -static PyObject * -psutil_sensors_battery(PyObject *self, PyObject *args) { - PyObject *py_tuple = NULL; - CFTypeRef power_info = NULL; - CFArrayRef power_sources_list = NULL; - CFDictionaryRef power_sources_information = NULL; - CFNumberRef capacity_ref = NULL; - CFNumberRef time_to_empty_ref = NULL; - CFStringRef ps_state_ref = NULL; - uint32_t capacity; /* units are percent */ - int time_to_empty; /* units are minutes */ - int is_power_plugged; - - power_info = IOPSCopyPowerSourcesInfo(); - - if (!power_info) { - PyErr_SetString(PyExc_RuntimeError, - "IOPSCopyPowerSourcesInfo() syscall failed"); - goto error; - } - - power_sources_list = IOPSCopyPowerSourcesList(power_info); - if (!power_sources_list) { - PyErr_SetString(PyExc_RuntimeError, - "IOPSCopyPowerSourcesList() syscall failed"); - goto error; - } - - /* Should only get one source. But in practice, check for > 0 sources */ - if (!CFArrayGetCount(power_sources_list)) { - PyErr_SetString(PyExc_NotImplementedError, "no battery"); - goto error; - } - - power_sources_information = IOPSGetPowerSourceDescription( - power_info, CFArrayGetValueAtIndex(power_sources_list, 0)); - - capacity_ref = (CFNumberRef) CFDictionaryGetValue( - power_sources_information, CFSTR(kIOPSCurrentCapacityKey)); - if (!CFNumberGetValue(capacity_ref, kCFNumberSInt32Type, &capacity)) { - PyErr_SetString(PyExc_RuntimeError, - "No battery capacity infomration in power sources info"); - goto error; - } - - ps_state_ref = (CFStringRef) CFDictionaryGetValue( - power_sources_information, CFSTR(kIOPSPowerSourceStateKey)); - is_power_plugged = CFStringCompare( - ps_state_ref, CFSTR(kIOPSACPowerValue), 0) - == kCFCompareEqualTo; - - time_to_empty_ref = (CFNumberRef) CFDictionaryGetValue( - power_sources_information, CFSTR(kIOPSTimeToEmptyKey)); - if (!CFNumberGetValue(time_to_empty_ref, - kCFNumberIntType, &time_to_empty)) { - /* This value is recommended for non-Apple power sources, so it's not - * an error if it doesn't exist. We'll return -1 for "unknown" */ - /* A value of -1 indicates "Still Calculating the Time" also for - * apple power source */ - time_to_empty = -1; - } - - py_tuple = Py_BuildValue("Iii", - capacity, time_to_empty, is_power_plugged); - if (!py_tuple) { - goto error; - } - - CFRelease(power_info); - CFRelease(power_sources_list); - /* Caller should NOT release power_sources_information */ - - return py_tuple; - -error: - if (power_info) - CFRelease(power_info); - if (power_sources_list) - CFRelease(power_sources_list); - Py_XDECREF(py_tuple); - return NULL; -} - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef mod_methods[] = { - // --- per-process functions - - {"proc_kinfo_oneshot", psutil_proc_kinfo_oneshot, METH_VARARGS, - "Return multiple process info."}, - {"proc_pidtaskinfo_oneshot", psutil_proc_pidtaskinfo_oneshot, METH_VARARGS, - "Return multiple process info."}, - {"proc_name", psutil_proc_name, METH_VARARGS, - "Return process name"}, - {"proc_cmdline", psutil_proc_cmdline, METH_VARARGS, - "Return process cmdline as a list of cmdline arguments"}, - {"proc_environ", psutil_proc_environ, METH_VARARGS, - "Return process environment data"}, - {"proc_exe", psutil_proc_exe, METH_VARARGS, - "Return path of the process executable"}, - {"proc_cwd", psutil_proc_cwd, METH_VARARGS, - "Return process current working directory."}, - {"proc_memory_uss", psutil_proc_memory_uss, METH_VARARGS, - "Return process USS memory"}, - {"proc_threads", psutil_proc_threads, METH_VARARGS, - "Return process threads as a list of tuples"}, - {"proc_open_files", psutil_proc_open_files, METH_VARARGS, - "Return files opened by process as a list of tuples"}, - {"proc_num_fds", psutil_proc_num_fds, METH_VARARGS, - "Return the number of fds opened by process."}, - {"proc_connections", psutil_proc_connections, METH_VARARGS, - "Get process TCP and UDP connections as a list of tuples"}, - - // --- system-related functions - - {"pids", psutil_pids, METH_VARARGS, - "Returns a list of PIDs currently running on the system"}, - {"cpu_count_logical", psutil_cpu_count_logical, METH_VARARGS, - "Return number of logical CPUs on the system"}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Return number of physical CPUs on the system"}, - {"virtual_mem", psutil_virtual_mem, METH_VARARGS, - "Return system virtual memory stats"}, - {"swap_mem", psutil_swap_mem, METH_VARARGS, - "Return stats about swap memory, in bytes"}, - {"cpu_times", psutil_cpu_times, METH_VARARGS, - "Return system cpu times as a tuple (user, system, nice, idle, irc)"}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-cpu times as a list of tuples"}, - {"cpu_freq", psutil_cpu_freq, METH_VARARGS, - "Return cpu current frequency"}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return the system boot time expressed in seconds since the epoch."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return a list of tuples including device, mount point and " - "fs type for all partitions mounted on the system."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return dict of tuples of networks I/O information."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return dict of tuples of disks I/O information."}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users as a list of tuples"}, - {"cpu_stats", psutil_cpu_stats, METH_VARARGS, - "Return CPU statistics"}, - {"sensors_battery", psutil_sensors_battery, METH_VARARGS, - "Return battery information."}, - - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - - -#if PY_MAJOR_VERSION >= 3 - #define INITERR return NULL - - static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_psutil_osx", - NULL, - -1, - mod_methods, - NULL, - NULL, - NULL, - NULL - }; - - PyObject *PyInit__psutil_osx(void) -#else /* PY_MAJOR_VERSION */ - #define INITERR return - - void init_psutil_osx(void) -#endif /* PY_MAJOR_VERSION */ -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *mod = PyModule_Create(&moduledef); -#else - PyObject *mod = Py_InitModule("_psutil_osx", mod_methods); -#endif - if (mod == NULL) - INITERR; - - if (psutil_setup() != 0) - INITERR; - - if (PyModule_AddIntConstant(mod, "version", PSUTIL_VERSION)) - INITERR; - // process status constants, defined in: - // http://fxr.watson.org/fxr/source/bsd/sys/proc.h?v=xnu-792.6.70#L149 - if (PyModule_AddIntConstant(mod, "SIDL", SIDL)) - INITERR; - if (PyModule_AddIntConstant(mod, "SRUN", SRUN)) - INITERR; - if (PyModule_AddIntConstant(mod, "SSLEEP", SSLEEP)) - INITERR; - if (PyModule_AddIntConstant(mod, "SSTOP", SSTOP)) - INITERR; - if (PyModule_AddIntConstant(mod, "SZOMB", SZOMB)) - INITERR; - // connection status constants - if (PyModule_AddIntConstant(mod, "TCPS_CLOSED", TCPS_CLOSED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_CLOSING", TCPS_CLOSING)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_LISTEN", TCPS_LISTEN)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_ESTABLISHED", TCPS_ESTABLISHED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_SYN_SENT", TCPS_SYN_SENT)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_LAST_ACK", TCPS_LAST_ACK)) - INITERR; - if (PyModule_AddIntConstant(mod, "TCPS_TIME_WAIT", TCPS_TIME_WAIT)) - INITERR; - if (PyModule_AddIntConstant(mod, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE)) - INITERR; - - // Exception. - ZombieProcessError = PyErr_NewException( - "_psutil_osx.ZombieProcessError", NULL, NULL); - if (ZombieProcessError == NULL) - INITERR; - Py_INCREF(ZombieProcessError); - if (PyModule_AddObject(mod, "ZombieProcessError", ZombieProcessError)) { - Py_DECREF(ZombieProcessError); - INITERR; - } - - if (mod == NULL) - INITERR; -#if PY_MAJOR_VERSION >= 3 - return mod; -#endif -} diff --git a/third_party/python/psutil/psutil/_psutil_posix.c b/third_party/python/psutil/psutil/_psutil_posix.c deleted file mode 100644 index 38483b3b024a..000000000000 --- a/third_party/python/psutil/psutil/_psutil_posix.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - * 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. - * - * Functions specific to all POSIX compliant platforms. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef PSUTIL_SUNOS10 - #include "arch/solaris/v10/ifaddrs.h" -#elif PSUTIL_AIX - #include "arch/aix/ifaddrs.h" -#else - #include -#endif - -#if defined(PSUTIL_LINUX) - #include - #include - #include -#elif defined(PSUTIL_BSD) || defined(PSUTIL_OSX) - #include - #include - #include - #include - #include - #include -#elif defined(PSUTIL_SUNOS) - #include - #include -#elif defined(PSUTIL_AIX) - #include -#endif - -#include "_psutil_common.h" - -/* - * Check if PID exists. Return values: - * 1: exists - * 0: does not exist - * -1: error (Python exception is set) - */ -int -psutil_pid_exists(pid_t pid) { - int ret; - - // No negative PID exists, plus -1 is an alias for sending signal - // too all processes except system ones. Not what we want. - if (pid < 0) - return 0; - - // As per "man 2 kill" PID 0 is an alias for sending the signal to - // every process in the process group of the calling process. - // Not what we want. Some platforms have PID 0, some do not. - // We decide that at runtime. - if (pid == 0) { -#if defined(PSUTIL_LINUX) || defined(PSUTIL_FREEBSD) - return 0; -#else - return 1; -#endif - } - - ret = kill(pid , 0); - if (ret == 0) - return 1; - else { - if (errno == ESRCH) { - // ESRCH == No such process - return 0; - } - else if (errno == EPERM) { - // EPERM clearly indicates there's a process to deny - // access to. - return 1; - } - else { - // According to "man 2 kill" possible error values are - // (EINVAL, EPERM, ESRCH) therefore we should never get - // here. If we do let's be explicit in considering this - // an error. - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - } -} - - -/* - * Utility used for those syscalls which do not return a meaningful - * error that we can translate into an exception which makes sense. - * As such, we'll have to guess. - * On UNIX, if errno is set, we return that one (OSError). - * Else, if PID does not exist we assume the syscall failed because - * of that so we raise NoSuchProcess. - * If none of this is true we giveup and raise RuntimeError(msg). - * This will always set a Python exception and return NULL. - */ -void -psutil_raise_for_pid(long pid, char *syscall) { - if (errno != 0) // unlikely - PyErr_SetFromOSErrnoWithSyscall(syscall); - else if (psutil_pid_exists(pid) == 0) - NoSuchProcess(syscall); - else - PyErr_Format(PyExc_RuntimeError, "%s syscall failed", syscall); -} - - -/* - * Given a PID return process priority as a Python integer. - */ -static PyObject * -psutil_posix_getpriority(PyObject *self, PyObject *args) { - pid_t pid; - int priority; - errno = 0; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - -#ifdef PSUTIL_OSX - priority = getpriority(PRIO_PROCESS, (id_t)pid); -#else - priority = getpriority(PRIO_PROCESS, pid); -#endif - if (errno != 0) - return PyErr_SetFromErrno(PyExc_OSError); - return Py_BuildValue("i", priority); -} - - -/* - * Given a PID and a value change process priority. - */ -static PyObject * -psutil_posix_setpriority(PyObject *self, PyObject *args) { - pid_t pid; - int priority; - int retval; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "i", &pid, &priority)) - return NULL; - -#ifdef PSUTIL_OSX - retval = setpriority(PRIO_PROCESS, (id_t)pid, priority); -#else - retval = setpriority(PRIO_PROCESS, pid, priority); -#endif - if (retval == -1) - return PyErr_SetFromErrno(PyExc_OSError); - Py_RETURN_NONE; -} - - -/* - * Translate a sockaddr struct into a Python string. - * Return None if address family is not AF_INET* or AF_PACKET. - */ -static PyObject * -psutil_convert_ipaddr(struct sockaddr *addr, int family) { - char buf[NI_MAXHOST]; - int err; - int addrlen; - size_t n; - size_t len; - const char *data; - char *ptr; - - if (addr == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - else if (family == AF_INET || family == AF_INET6) { - if (family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else - addrlen = sizeof(struct sockaddr_in6); - err = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, - NI_NUMERICHOST); - if (err != 0) { - // XXX we get here on FreeBSD when processing 'lo' / AF_INET6 - // broadcast. Not sure what to do other than returning None. - // ifconfig does not show anything BTW. - // PyErr_Format(PyExc_RuntimeError, gai_strerror(err)); - // return NULL; - Py_INCREF(Py_None); - return Py_None; - } - else { - return Py_BuildValue("s", buf); - } - } -#ifdef PSUTIL_LINUX - else if (family == AF_PACKET) { - struct sockaddr_ll *lladdr = (struct sockaddr_ll *)addr; - len = lladdr->sll_halen; - data = (const char *)lladdr->sll_addr; - } -#elif defined(PSUTIL_BSD) || defined(PSUTIL_OSX) - else if (addr->sa_family == AF_LINK) { - // Note: prior to Python 3.4 socket module does not expose - // AF_LINK so we'll do. - struct sockaddr_dl *dladdr = (struct sockaddr_dl *)addr; - len = dladdr->sdl_alen; - data = LLADDR(dladdr); - } -#endif - else { - // unknown family - Py_INCREF(Py_None); - return Py_None; - } - - // AF_PACKET or AF_LINK - if (len > 0) { - ptr = buf; - for (n = 0; n < len; ++n) { - sprintf(ptr, "%02x:", data[n] & 0xff); - ptr += 3; - } - *--ptr = '\0'; - return Py_BuildValue("s", buf); - } - else { - Py_INCREF(Py_None); - return Py_None; - } -} - - -/* - * Return NICs information a-la ifconfig as a list of tuples. - * TODO: on Solaris we won't get any MAC address. - */ -static PyObject* -psutil_net_if_addrs(PyObject* self, PyObject* args) { - struct ifaddrs *ifaddr, *ifa; - int family; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_address = NULL; - PyObject *py_netmask = NULL; - PyObject *py_broadcast = NULL; - PyObject *py_ptp = NULL; - - if (py_retlist == NULL) - return NULL; - if (getifaddrs(&ifaddr) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (!ifa->ifa_addr) - continue; - family = ifa->ifa_addr->sa_family; - py_address = psutil_convert_ipaddr(ifa->ifa_addr, family); - // If the primary address can't be determined just skip it. - // I've never seen this happen on Linux but I did on FreeBSD. - if (py_address == Py_None) - continue; - if (py_address == NULL) - goto error; - py_netmask = psutil_convert_ipaddr(ifa->ifa_netmask, family); - if (py_netmask == NULL) - goto error; - - if (ifa->ifa_flags & IFF_BROADCAST) { - py_broadcast = psutil_convert_ipaddr(ifa->ifa_broadaddr, family); - Py_INCREF(Py_None); - py_ptp = Py_None; - } - else if (ifa->ifa_flags & IFF_POINTOPOINT) { - py_ptp = psutil_convert_ipaddr(ifa->ifa_dstaddr, family); - Py_INCREF(Py_None); - py_broadcast = Py_None; - } - else { - Py_INCREF(Py_None); - Py_INCREF(Py_None); - py_broadcast = Py_None; - py_ptp = Py_None; - } - - if ((py_broadcast == NULL) || (py_ptp == NULL)) - goto error; - py_tuple = Py_BuildValue( - "(siOOOO)", - ifa->ifa_name, - family, - py_address, - py_netmask, - py_broadcast, - py_ptp - ); - - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_address); - Py_CLEAR(py_netmask); - Py_CLEAR(py_broadcast); - Py_CLEAR(py_ptp); - } - - freeifaddrs(ifaddr); - return py_retlist; - -error: - if (ifaddr != NULL) - freeifaddrs(ifaddr); - Py_DECREF(py_retlist); - Py_XDECREF(py_tuple); - Py_XDECREF(py_address); - Py_XDECREF(py_netmask); - Py_XDECREF(py_broadcast); - Py_XDECREF(py_ptp); - return NULL; -} - - -/* - * Return NIC MTU. References: - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject * -psutil_net_if_mtu(PyObject *self, PyObject *args) { - char *nic_name; - int sock = -1; - int ret; -#ifdef PSUTIL_SUNOS10 - struct lifreq lifr; -#else - struct ifreq ifr; -#endif - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - goto error; - -#ifdef PSUTIL_SUNOS10 - strncpy(lifr.lifr_name, nic_name, sizeof(lifr.lifr_name)); - ret = ioctl(sock, SIOCGIFMTU, &lifr); -#else - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - ret = ioctl(sock, SIOCGIFMTU, &ifr); -#endif - if (ret == -1) - goto error; - close(sock); - -#ifdef PSUTIL_SUNOS10 - return Py_BuildValue("i", lifr.lifr_mtu); -#else - return Py_BuildValue("i", ifr.ifr_mtu); -#endif - -error: - if (sock != -1) - close(sock); - return PyErr_SetFromErrno(PyExc_OSError); -} - - -/* - * Inspect NIC flags, returns a bool indicating whether the NIC is - * running. References: - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject * -psutil_net_if_flags(PyObject *self, PyObject *args) { - char *nic_name; - int sock = -1; - int ret; - struct ifreq ifr; - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - goto error; - - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - ret = ioctl(sock, SIOCGIFFLAGS, &ifr); - if (ret == -1) - goto error; - - close(sock); - if ((ifr.ifr_flags & IFF_UP) != 0) - return Py_BuildValue("O", Py_True); - else - return Py_BuildValue("O", Py_False); - -error: - if (sock != -1) - close(sock); - return PyErr_SetFromErrno(PyExc_OSError); -} - - -/* - * net_if_stats() macOS/BSD implementation. - */ -#if defined(PSUTIL_BSD) || defined(PSUTIL_OSX) - -int psutil_get_nic_speed(int ifm_active) { - // Determine NIC speed. Taken from: - // http://www.i-scream.org/libstatgrab/ - // Assuming only ETHER devices - switch(IFM_TYPE(ifm_active)) { - case IFM_ETHER: - switch(IFM_SUBTYPE(ifm_active)) { -#if defined(IFM_HPNA_1) && ((!defined(IFM_10G_LR)) \ - || (IFM_10G_LR != IFM_HPNA_1)) - // HomePNA 1.0 (1Mb/s) - case(IFM_HPNA_1): - return 1; -#endif - // 10 Mbit - case(IFM_10_T): // 10BaseT - RJ45 - case(IFM_10_2): // 10Base2 - Thinnet - case(IFM_10_5): // 10Base5 - AUI - case(IFM_10_STP): // 10BaseT over shielded TP - case(IFM_10_FL): // 10baseFL - Fiber - return 10; - // 100 Mbit - case(IFM_100_TX): // 100BaseTX - RJ45 - case(IFM_100_FX): // 100BaseFX - Fiber - case(IFM_100_T4): // 100BaseT4 - 4 pair cat 3 - case(IFM_100_VG): // 100VG-AnyLAN - case(IFM_100_T2): // 100BaseT2 - return 100; - // 1000 Mbit - case(IFM_1000_SX): // 1000BaseSX - multi-mode fiber - case(IFM_1000_LX): // 1000baseLX - single-mode fiber - case(IFM_1000_CX): // 1000baseCX - 150ohm STP -#if defined(IFM_1000_TX) && !defined(PSUTIL_OPENBSD) - // FreeBSD 4 and others (but NOT OpenBSD) -> #define IFM_1000_T in net/if_media.h - case(IFM_1000_TX): -#endif -#ifdef IFM_1000_FX - case(IFM_1000_FX): -#endif -#ifdef IFM_1000_T - case(IFM_1000_T): -#endif - return 1000; -#if defined(IFM_10G_SR) || defined(IFM_10G_LR) || defined(IFM_10G_CX4) \ - || defined(IFM_10G_T) -#ifdef IFM_10G_SR - case(IFM_10G_SR): -#endif -#ifdef IFM_10G_LR - case(IFM_10G_LR): -#endif -#ifdef IFM_10G_CX4 - case(IFM_10G_CX4): -#endif -#ifdef IFM_10G_TWINAX - case(IFM_10G_TWINAX): -#endif -#ifdef IFM_10G_TWINAX_LONG - case(IFM_10G_TWINAX_LONG): -#endif -#ifdef IFM_10G_T - case(IFM_10G_T): -#endif - return 10000; -#endif -#if defined(IFM_2500_SX) -#ifdef IFM_2500_SX - case(IFM_2500_SX): -#endif - return 2500; -#endif // any 2.5GBit stuff... - // We don't know what it is - default: - return 0; - } - break; - -#ifdef IFM_TOKEN - case IFM_TOKEN: - switch(IFM_SUBTYPE(ifm_active)) { - case IFM_TOK_STP4: // Shielded twisted pair 4m - DB9 - case IFM_TOK_UTP4: // Unshielded twisted pair 4m - RJ45 - return 4; - case IFM_TOK_STP16: // Shielded twisted pair 16m - DB9 - case IFM_TOK_UTP16: // Unshielded twisted pair 16m - RJ45 - return 16; -#if defined(IFM_TOK_STP100) || defined(IFM_TOK_UTP100) -#ifdef IFM_TOK_STP100 - case IFM_TOK_STP100: // Shielded twisted pair 100m - DB9 -#endif -#ifdef IFM_TOK_UTP100 - case IFM_TOK_UTP100: // Unshielded twisted pair 100m - RJ45 -#endif - return 100; -#endif - // We don't know what it is - default: - return 0; - } - break; -#endif - -#ifdef IFM_FDDI - case IFM_FDDI: - switch(IFM_SUBTYPE(ifm_active)) { - // We don't know what it is - default: - return 0; - } - break; -#endif - case IFM_IEEE80211: - switch(IFM_SUBTYPE(ifm_active)) { - case IFM_IEEE80211_FH1: // Frequency Hopping 1Mbps - case IFM_IEEE80211_DS1: // Direct Sequence 1Mbps - return 1; - case IFM_IEEE80211_FH2: // Frequency Hopping 2Mbps - case IFM_IEEE80211_DS2: // Direct Sequence 2Mbps - return 2; - case IFM_IEEE80211_DS5: // Direct Sequence 5Mbps - return 5; - case IFM_IEEE80211_DS11: // Direct Sequence 11Mbps - return 11; - case IFM_IEEE80211_DS22: // Direct Sequence 22Mbps - return 22; - // We don't know what it is - default: - return 0; - } - break; - - default: - return 0; - } -} - - -/* - * Return stats about a particular network interface. - * References: - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject * -psutil_net_if_duplex_speed(PyObject *self, PyObject *args) { - char *nic_name; - int sock = -1; - int ret; - int duplex; - int speed; - struct ifreq ifr; - struct ifmediareq ifmed; - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - return PyErr_SetFromErrno(PyExc_OSError); - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - - // speed / duplex - memset(&ifmed, 0, sizeof(struct ifmediareq)); - strlcpy(ifmed.ifm_name, nic_name, sizeof(ifmed.ifm_name)); - ret = ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmed); - if (ret == -1) { - speed = 0; - duplex = 0; - } - else { - speed = psutil_get_nic_speed(ifmed.ifm_active); - if ((ifmed.ifm_active | IFM_FDX) == ifmed.ifm_active) - duplex = 2; - else if ((ifmed.ifm_active | IFM_HDX) == ifmed.ifm_active) - duplex = 1; - else - duplex = 0; - } - - close(sock); - return Py_BuildValue("[ii]", duplex, speed); -} -#endif // net_if_stats() macOS/BSD implementation - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef mod_methods[] = { - {"getpriority", psutil_posix_getpriority, METH_VARARGS, - "Return process priority"}, - {"setpriority", psutil_posix_setpriority, METH_VARARGS, - "Set process priority"}, - {"net_if_addrs", psutil_net_if_addrs, METH_VARARGS, - "Retrieve NICs information"}, - {"net_if_mtu", psutil_net_if_mtu, METH_VARARGS, - "Retrieve NIC MTU"}, - {"net_if_flags", psutil_net_if_flags, METH_VARARGS, - "Retrieve NIC flags"}, -#if defined(PSUTIL_BSD) || defined(PSUTIL_OSX) - {"net_if_duplex_speed", psutil_net_if_duplex_speed, METH_VARARGS, - "Return NIC stats."}, -#endif - {NULL, NULL, 0, NULL} -}; - - -#if PY_MAJOR_VERSION >= 3 - #define INITERR return NULL - - static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_psutil_posix", - NULL, - -1, - mod_methods, - NULL, - NULL, - NULL, - NULL - }; - - PyObject *PyInit__psutil_posix(void) -#else /* PY_MAJOR_VERSION */ - #define INITERR return - - void init_psutil_posix(void) -#endif /* PY_MAJOR_VERSION */ -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *mod = PyModule_Create(&moduledef); -#else - PyObject *mod = Py_InitModule("_psutil_posix", mod_methods); -#endif - if (mod == NULL) - INITERR; - -#if defined(PSUTIL_BSD) || \ - defined(PSUTIL_OSX) || \ - defined(PSUTIL_SUNOS) || \ - defined(PSUTIL_AIX) - if (PyModule_AddIntConstant(mod, "AF_LINK", AF_LINK)) INITERR; -#endif - - if (mod == NULL) - INITERR; -#if PY_MAJOR_VERSION >= 3 - return mod; -#endif -} - -#ifdef __cplusplus -} -#endif diff --git a/third_party/python/psutil/psutil/_psutil_posix.h b/third_party/python/psutil/psutil/_psutil_posix.h deleted file mode 100644 index 59b9e53238af..000000000000 --- a/third_party/python/psutil/psutil/_psutil_posix.h +++ /dev/null @@ -1,8 +0,0 @@ -/* - * 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. - */ - -int psutil_pid_exists(pid_t pid); -void psutil_raise_for_pid(pid_t pid, char *msg); diff --git a/third_party/python/psutil/psutil/_psutil_sunos.c b/third_party/python/psutil/psutil/_psutil_sunos.c deleted file mode 100644 index 6548640b70cf..000000000000 --- a/third_party/python/psutil/psutil/_psutil_sunos.c +++ /dev/null @@ -1,1787 +0,0 @@ -/* - * 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. - * - * Functions specific to Sun OS Solaris platforms. - * - * Thanks to Justin Venus who originally wrote a consistent part of - * this in Cython which I later on translated in C. - */ - -/* fix compilation issue on SunOS 5.10, see: - * https://github.com/giampaolo/psutil/issues/421 - * https://github.com/giampaolo/psutil/issues/1077 -*/ - -#define _STRUCTURED_PROC 1 - -#include - -#if !defined(_LP64) && _FILE_OFFSET_BITS == 64 -# undef _FILE_OFFSET_BITS -# undef _LARGEFILE64_SOURCE -#endif - -#include -#include -#include -#include -#include -#include // for MNTTAB -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef NEW_MIB_COMPLIANT -/* - * Solaris introduced NEW_MIB_COMPLIANT macro with Update 4. - * See https://github.com/giampaolo/psutil/issues/421 - * Prior to Update 4, one has to include mib2 by hand. - */ -#include -#endif -#include -#include -#include // fabs() - -#include "_psutil_common.h" -#include "_psutil_posix.h" - -#include "arch/solaris/environ.h" - -#define PSUTIL_TV2DOUBLE(t) (((t).tv_nsec * 0.000000001) + (t).tv_sec) - - -/* - * Read a file content and fills a C structure with it. - */ -static int -psutil_file_to_struct(char *path, void *fstruct, size_t size) { - int fd; - ssize_t nbytes; - fd = open(path, O_RDONLY); - if (fd == -1) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); - return 0; - } - nbytes = read(fd, fstruct, size); - if (nbytes == -1) { - close(fd); - PyErr_SetFromErrno(PyExc_OSError); - return 0; - } - if (nbytes != (ssize_t) size) { - close(fd); - PyErr_SetString( - PyExc_RuntimeError, "read() file structure size mismatch"); - return 0; - } - close(fd); - return nbytes; -} - - -/* - * Return process ppid, rss, vms, ctime, nice, nthreads, status and tty - * as a Python tuple. - */ -static PyObject * -psutil_proc_basic_info(PyObject *self, PyObject *args) { - int pid; - char path[1000]; - psinfo_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - - sprintf(path, "%s/%i/psinfo", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue( - "ikkdiiikiiii", - info.pr_ppid, // parent pid - info.pr_rssize, // rss - info.pr_size, // vms - PSUTIL_TV2DOUBLE(info.pr_start), // create time - info.pr_lwp.pr_nice, // nice - info.pr_nlwp, // no. of threads - info.pr_lwp.pr_state, // status code - info.pr_ttydev, // tty nr - (int)info.pr_uid, // real user id - (int)info.pr_euid, // effective user id - (int)info.pr_gid, // real group id - (int)info.pr_egid // effective group id - ); -} - -/* - * Join array of C strings to C string with delemiter dm. - * Omit empty records. - */ -static int -cstrings_array_to_string(char **joined, char ** array, size_t count, char dm) { - int i; - size_t total_length = 0; - size_t item_length = 0; - char *result = NULL; - char *last = NULL; - - if (!array || !joined) - return 0; - - for (i=0; i 0) { - py_args = PyUnicode_DecodeFSDefault(argv_plain); - free(argv_plain); - } else if (joined < 0) { - goto error; - } - - psutil_free_cstrings_array(argv, argc); - } - } - - /* If we can't read process memory or can't decode the result - * then return args from /proc. */ - if (!py_args) { - PyErr_Clear(); - py_args = PyUnicode_DecodeFSDefault(info.pr_psargs); - } - - /* Both methods has been failed. */ - if (!py_args) - goto error; - - py_retlist = Py_BuildValue("OO", py_name, py_args); - if (!py_retlist) - goto error; - - Py_DECREF(py_name); - Py_DECREF(py_args); - return py_retlist; - -error: - Py_XDECREF(py_name); - Py_XDECREF(py_args); - Py_XDECREF(py_retlist); - return NULL; -} - - -/* - * Return process environ block. - */ -static PyObject * -psutil_proc_environ(PyObject *self, PyObject *args) { - int pid; - char path[1000]; - psinfo_t info; - const char *procfs_path; - char **env = NULL; - ssize_t env_count = -1; - char *dm; - int i = 0; - PyObject *py_envname = NULL; - PyObject *py_envval = NULL; - PyObject *py_retdict = PyDict_New(); - - if (! py_retdict) - return PyErr_NoMemory(); - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - - sprintf(path, "%s/%i/psinfo", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - goto error; - - if (! info.pr_envp) { - AccessDenied("/proc/pid/psinfo struct not set"); - goto error; - } - - env = psutil_read_raw_env(info, procfs_path, &env_count); - if (! env && env_count != 0) - goto error; - - for (i=0; i= 0) - psutil_free_cstrings_array(env, env_count); - - Py_XDECREF(py_envname); - Py_XDECREF(py_envval); - Py_XDECREF(py_retdict); - return NULL; -} - - -/* - * Return process user and system CPU times as a Python tuple. - */ -static PyObject * -psutil_proc_cpu_times(PyObject *self, PyObject *args) { - int pid; - char path[1000]; - pstatus_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/status", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - // results are more precise than os.times() - return Py_BuildValue( - "(dddd)", - PSUTIL_TV2DOUBLE(info.pr_utime), - PSUTIL_TV2DOUBLE(info.pr_stime), - PSUTIL_TV2DOUBLE(info.pr_cutime), - PSUTIL_TV2DOUBLE(info.pr_cstime) - ); -} - - -/* - * Return what CPU the process is running on. - */ -static PyObject * -psutil_proc_cpu_num(PyObject *self, PyObject *args) { - int fd = NULL; - int pid; - char path[1000]; - struct prheader header; - struct lwpsinfo *lwp = NULL; - int nent; - int size; - int proc_num; - ssize_t nbytes; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - - sprintf(path, "%s/%i/lpsinfo", procfs_path, pid); - fd = open(path, O_RDONLY); - if (fd == -1) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); - return NULL; - } - - // read header - nbytes = pread(fd, &header, sizeof(header), 0); - if (nbytes == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - if (nbytes != sizeof(header)) { - PyErr_SetString( - PyExc_RuntimeError, "read() file structure size mismatch"); - goto error; - } - - // malloc - nent = header.pr_nent; - size = header.pr_entsize * nent; - lwp = malloc(size); - if (lwp == NULL) { - PyErr_NoMemory(); - goto error; - } - - // read the rest - nbytes = pread(fd, lwp, size, sizeof(header)); - if (nbytes == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - if (nbytes != size) { - PyErr_SetString( - PyExc_RuntimeError, "read() file structure size mismatch"); - goto error; - } - - // done - proc_num = lwp->pr_onpro; - close(fd); - free(lwp); - return Py_BuildValue("i", proc_num); - -error: - if (fd != -1) - close(fd); - free(lwp); - return NULL; -} - - -/* - * Return process uids/gids as a Python tuple. - */ -static PyObject * -psutil_proc_cred(PyObject *self, PyObject *args) { - int pid; - char path[1000]; - prcred_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/cred", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("iiiiii", - info.pr_ruid, info.pr_euid, info.pr_suid, - info.pr_rgid, info.pr_egid, info.pr_sgid); -} - - -/* - * Return process voluntary and involuntary context switches as a Python tuple. - */ -static PyObject * -psutil_proc_num_ctx_switches(PyObject *self, PyObject *args) { - int pid; - char path[1000]; - prusage_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/usage", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("kk", info.pr_vctx, info.pr_ictx); -} - - -/* - * Process IO counters. - * - * Commented out and left here as a reminder. Apparently we cannot - * retrieve process IO stats because: - * - 'pr_ioch' is a sum of chars read and written, with no distinction - * - 'pr_inblk' and 'pr_oublk', which should be the number of bytes - * read and written, hardly increase and according to: - * http://www.brendangregg.com/Solaris/paper_diskubyp1.pdf - * ...they should be meaningless anyway. - * -static PyObject* -proc_io_counters(PyObject* self, PyObject* args) { - int pid; - char path[1000]; - prusage_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/usage", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - - // On Solaris we only have 'pr_ioch' which accounts for bytes read - // *and* written. - // 'pr_inblk' and 'pr_oublk' should be expressed in blocks of - // 8KB according to: - // http://www.brendangregg.com/Solaris/paper_diskubyp1.pdf (pag. 8) - return Py_BuildValue("kkkk", - info.pr_ioch, - info.pr_ioch, - info.pr_inblk, - info.pr_oublk); -} -*/ - - -/* - * Return information about a given process thread. - */ -static PyObject * -psutil_proc_query_thread(PyObject *self, PyObject *args) { - int pid, tid; - char path[1000]; - lwpstatus_t info; - const char *procfs_path; - - if (! PyArg_ParseTuple(args, "iis", &pid, &tid, &procfs_path)) - return NULL; - sprintf(path, "%s/%i/lwp/%i/lwpstatus", procfs_path, pid, tid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("dd", - PSUTIL_TV2DOUBLE(info.pr_utime), - PSUTIL_TV2DOUBLE(info.pr_stime)); -} - - -/* - * Return information about system virtual memory. - */ -static PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { -// XXX (arghhh!) -// total/free swap mem: commented out as for some reason I can't -// manage to get the same results shown by "swap -l", despite the -// code below is exactly the same as: -// http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/ -// cmd/swap/swap.c -// We're going to parse "swap -l" output from Python (sigh!) - -/* - struct swaptable *st; - struct swapent *swapent; - int i; - struct stat64 statbuf; - char *path; - char fullpath[MAXPATHLEN+1]; - int num; - - if ((num = swapctl(SC_GETNSWP, NULL)) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if (num == 0) { - PyErr_SetString(PyExc_RuntimeError, "no swap devices configured"); - return NULL; - } - if ((st = malloc(num * sizeof(swapent_t) + sizeof (int))) == NULL) { - PyErr_SetString(PyExc_RuntimeError, "malloc failed"); - return NULL; - } - if ((path = malloc(num * MAXPATHLEN)) == NULL) { - PyErr_SetString(PyExc_RuntimeError, "malloc failed"); - return NULL; - } - swapent = st->swt_ent; - for (i = 0; i < num; i++, swapent++) { - swapent->ste_path = path; - path += MAXPATHLEN; - } - st->swt_n = num; - if ((num = swapctl(SC_LIST, st)) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - swapent = st->swt_ent; - long t = 0, f = 0; - for (i = 0; i < num; i++, swapent++) { - int diskblks_per_page =(int)(sysconf(_SC_PAGESIZE) >> DEV_BSHIFT); - t += (long)swapent->ste_pages; - f += (long)swapent->ste_free; - } - - free(st); - return Py_BuildValue("(kk)", t, f); -*/ - - kstat_ctl_t *kc; - kstat_t *k; - cpu_stat_t *cpu; - int cpu_count = 0; - int flag = 0; - uint_t sin = 0; - uint_t sout = 0; - - kc = kstat_open(); - if (kc == NULL) - return PyErr_SetFromErrno(PyExc_OSError);; - - k = kc->kc_chain; - while (k != NULL) { - if ((strncmp(k->ks_name, "cpu_stat", 8) == 0) && \ - (kstat_read(kc, k, NULL) != -1) ) - { - flag = 1; - cpu = (cpu_stat_t *) k->ks_data; - sin += cpu->cpu_vminfo.pgswapin; // num pages swapped in - sout += cpu->cpu_vminfo.pgswapout; // num pages swapped out - } - cpu_count += 1; - k = k->ks_next; - } - kstat_close(kc); - if (!flag) { - PyErr_SetString(PyExc_RuntimeError, "no swap device was found"); - return NULL; - } - return Py_BuildValue("(II)", sin, sout); -} - - -/* - * Return users currently connected on the system. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - struct utmpx *ut; - PyObject *py_tuple = NULL; - PyObject *py_username = NULL; - PyObject *py_tty = NULL; - PyObject *py_hostname = NULL; - PyObject *py_user_proc = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - setutxent(); - while (NULL != (ut = getutxent())) { - if (ut->ut_type == USER_PROCESS) - py_user_proc = Py_True; - else - py_user_proc = Py_False; - py_username = PyUnicode_DecodeFSDefault(ut->ut_user); - if (! py_username) - goto error; - py_tty = PyUnicode_DecodeFSDefault(ut->ut_line); - if (! py_tty) - goto error; - py_hostname = PyUnicode_DecodeFSDefault(ut->ut_host); - if (! py_hostname) - goto error; - py_tuple = Py_BuildValue( - "(OOOfOi)", - py_username, // username - py_tty, // tty - py_hostname, // hostname - (float)ut->ut_tv.tv_sec, // tstamp - py_user_proc, // (bool) user process - ut->ut_pid // process id - ); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_username); - Py_CLEAR(py_tty); - Py_CLEAR(py_hostname); - Py_CLEAR(py_tuple); - } - endutxent(); - - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tty); - Py_XDECREF(py_hostname); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - endutxent(); - return NULL; -} - - -/* - * Return disk mounted partitions as a list of tuples including device, - * mount point and filesystem type. - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - FILE *file; - struct mnttab mt; - PyObject *py_dev = NULL; - PyObject *py_mountp = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - file = fopen(MNTTAB, "rb"); - if (file == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - while (getmntent(file, &mt) == 0) { - py_dev = PyUnicode_DecodeFSDefault(mt.mnt_special); - if (! py_dev) - goto error; - py_mountp = PyUnicode_DecodeFSDefault(mt.mnt_mountp); - if (! py_mountp) - goto error; - py_tuple = Py_BuildValue( - "(OOss)", - py_dev, // device - py_mountp, // mount point - mt.mnt_fstype, // fs type - mt.mnt_mntopts); // options - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_dev); - Py_CLEAR(py_mountp); - Py_CLEAR(py_tuple); - } - fclose(file); - return py_retlist; - -error: - Py_XDECREF(py_dev); - Py_XDECREF(py_mountp); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (file != NULL) - fclose(file); - return NULL; -} - - -/* - * Return system-wide CPU times. - */ -static PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - kstat_ctl_t *kc; - kstat_t *ksp; - cpu_stat_t cs; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - kc = kstat_open(); - if (kc == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_module, "cpu_stat") == 0) { - if (kstat_read(kc, ksp, &cs) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - py_cputime = Py_BuildValue("ffff", - (float)cs.cpu_sysinfo.cpu[CPU_USER], - (float)cs.cpu_sysinfo.cpu[CPU_KERNEL], - (float)cs.cpu_sysinfo.cpu[CPU_IDLE], - (float)cs.cpu_sysinfo.cpu[CPU_WAIT]); - if (py_cputime == NULL) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_CLEAR(py_cputime); - } - } - - kstat_close(kc); - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - if (kc != NULL) - kstat_close(kc); - return NULL; -} - - -/* - * Return disk IO statistics. - */ -static PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - kstat_ctl_t *kc; - kstat_t *ksp; - kstat_io_t kio; - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - - if (py_retdict == NULL) - return NULL; - kc = kstat_open(); - if (kc == NULL) { - PyErr_SetFromErrno(PyExc_OSError);; - goto error; - } - ksp = kc->kc_chain; - while (ksp != NULL) { - if (ksp->ks_type == KSTAT_TYPE_IO) { - if (strcmp(ksp->ks_class, "disk") == 0) { - if (kstat_read(kc, ksp, &kio) == -1) { - kstat_close(kc); - return PyErr_SetFromErrno(PyExc_OSError);; - } - py_disk_info = Py_BuildValue( - "(IIKKLL)", - kio.reads, - kio.writes, - kio.nread, - kio.nwritten, - kio.rtime / 1000 / 1000, // from nano to milli secs - kio.wtime / 1000 / 1000 // from nano to milli secs - ); - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, ksp->ks_name, - py_disk_info)) - goto error; - Py_CLEAR(py_disk_info); - } - } - ksp = ksp->ks_next; - } - kstat_close(kc); - - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (kc != NULL) - kstat_close(kc); - return NULL; -} - - -/* - * Return process memory mappings. - */ -static PyObject * -psutil_proc_memory_maps(PyObject *self, PyObject *args) { - int pid; - int fd = -1; - char path[1000]; - char perms[10]; - const char *name; - struct stat st; - pstatus_t status; - - prxmap_t *xmap = NULL, *p; - off_t size; - size_t nread; - int nmap; - uintptr_t pr_addr_sz; - uintptr_t stk_base_sz, brk_base_sz; - const char *procfs_path; - - PyObject *py_tuple = NULL; - PyObject *py_path = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "is", &pid, &procfs_path)) - goto error; - - sprintf(path, "%s/%i/status", procfs_path, pid); - if (! psutil_file_to_struct(path, (void *)&status, sizeof(status))) - goto error; - - sprintf(path, "%s/%i/xmap", procfs_path, pid); - if (stat(path, &st) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - size = st.st_size; - - fd = open(path, O_RDONLY); - if (fd == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - xmap = (prxmap_t *)malloc(size); - if (xmap == NULL) { - PyErr_NoMemory(); - goto error; - } - - nread = pread(fd, xmap, size, 0); - nmap = nread / sizeof(prxmap_t); - p = xmap; - - while (nmap) { - nmap -= 1; - if (p == NULL) { - p += 1; - continue; - } - - perms[0] = '\0'; - pr_addr_sz = p->pr_vaddr + p->pr_size; - - // perms - sprintf(perms, "%c%c%c%c", p->pr_mflags & MA_READ ? 'r' : '-', - p->pr_mflags & MA_WRITE ? 'w' : '-', - p->pr_mflags & MA_EXEC ? 'x' : '-', - p->pr_mflags & MA_SHARED ? 's' : '-'); - - // name - if (strlen(p->pr_mapname) > 0) { - name = p->pr_mapname; - } - else { - if ((p->pr_mflags & MA_ISM) || (p->pr_mflags & MA_SHM)) { - name = "[shmid]"; - } - else { - stk_base_sz = status.pr_stkbase + status.pr_stksize; - brk_base_sz = status.pr_brkbase + status.pr_brksize; - - if ((pr_addr_sz > status.pr_stkbase) && - (p->pr_vaddr < stk_base_sz)) { - name = "[stack]"; - } - else if ((p->pr_mflags & MA_ANON) && \ - (pr_addr_sz > status.pr_brkbase) && \ - (p->pr_vaddr < brk_base_sz)) { - name = "[heap]"; - } - else { - name = "[anon]"; - } - } - } - - py_path = PyUnicode_DecodeFSDefault(name); - if (! py_path) - goto error; - py_tuple = Py_BuildValue( - "kksOkkk", - (unsigned long)p->pr_vaddr, - (unsigned long)pr_addr_sz, - perms, - py_path, - (unsigned long)p->pr_rss * p->pr_pagesize, - (unsigned long)p->pr_anon * p->pr_pagesize, - (unsigned long)p->pr_locked * p->pr_pagesize); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_path); - Py_CLEAR(py_tuple); - - // increment pointer - p += 1; - } - - close(fd); - free(xmap); - return py_retlist; - -error: - if (fd != -1) - close(fd); - Py_XDECREF(py_tuple); - Py_XDECREF(py_path); - Py_DECREF(py_retlist); - if (xmap != NULL) - free(xmap); - return NULL; -} - - -/* - * Return a list of tuples for network I/O statistics. - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) { - kstat_ctl_t *kc = NULL; - kstat_t *ksp; - kstat_named_t *rbytes, *wbytes, *rpkts, *wpkts, *ierrs, *oerrs; - int ret; - int sock = -1; - struct lifreq ifr; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - - if (py_retdict == NULL) - return NULL; - kc = kstat_open(); - if (kc == NULL) - goto error; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - ksp = kc->kc_chain; - while (ksp != NULL) { - if (ksp->ks_type != KSTAT_TYPE_NAMED) - goto next; - if (strcmp(ksp->ks_class, "net") != 0) - goto next; - // skip 'lo' (localhost) because it doesn't have the statistics we need - // and it makes kstat_data_lookup() fail - if (strcmp(ksp->ks_module, "lo") == 0) - goto next; - - // check if this is a network interface by sending a ioctl - strncpy(ifr.lifr_name, ksp->ks_name, sizeof(ifr.lifr_name)); - ret = ioctl(sock, SIOCGLIFFLAGS, &ifr); - if (ret == -1) - goto next; - - if (kstat_read(kc, ksp, NULL) == -1) { - errno = 0; - goto next; - } - - rbytes = (kstat_named_t *)kstat_data_lookup(ksp, "rbytes"); - wbytes = (kstat_named_t *)kstat_data_lookup(ksp, "obytes"); - rpkts = (kstat_named_t *)kstat_data_lookup(ksp, "ipackets"); - wpkts = (kstat_named_t *)kstat_data_lookup(ksp, "opackets"); - ierrs = (kstat_named_t *)kstat_data_lookup(ksp, "ierrors"); - oerrs = (kstat_named_t *)kstat_data_lookup(ksp, "oerrors"); - - if ((rbytes == NULL) || (wbytes == NULL) || (rpkts == NULL) || - (wpkts == NULL) || (ierrs == NULL) || (oerrs == NULL)) - { - PyErr_SetString(PyExc_RuntimeError, "kstat_data_lookup() failed"); - goto error; - } - - if (rbytes->data_type == KSTAT_DATA_UINT64) - { - py_ifc_info = Py_BuildValue("(KKKKIIii)", - wbytes->value.ui64, - rbytes->value.ui64, - wpkts->value.ui64, - rpkts->value.ui64, - ierrs->value.ui32, - oerrs->value.ui32, - 0, // dropin not supported - 0 // dropout not supported - ); - } - else - { - py_ifc_info = Py_BuildValue("(IIIIIIii)", - wbytes->value.ui32, - rbytes->value.ui32, - wpkts->value.ui32, - rpkts->value.ui32, - ierrs->value.ui32, - oerrs->value.ui32, - 0, // dropin not supported - 0 // dropout not supported - ); - } - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_ifc_info)) - goto error; - Py_CLEAR(py_ifc_info); - goto next; - -next: - ksp = ksp->ks_next; - } - - kstat_close(kc); - close(sock); - return py_retdict; - -error: - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (kc != NULL) - kstat_close(kc); - if (sock != -1) { - close(sock); - } - return NULL; -} - - -/* - * Return TCP and UDP connections opened by process. - * UNIX sockets are excluded. - * - * Thanks to: - * https://github.com/DavidGriffith/finx/blob/master/ - * nxsensor-3.5.0-1/src/sysdeps/solaris.c - * ...and: - * https://hg.java.net/hg/solaris~on-src/file/tip/usr/src/cmd/ - * cmd-inet/usr.bin/netstat/netstat.c - */ -static PyObject * -psutil_net_connections(PyObject *self, PyObject *args) { - long pid; - int sd = 0; - mib2_tcpConnEntry_t tp; - mib2_udpEntry_t ude; -#if defined(AF_INET6) - mib2_tcp6ConnEntry_t tp6; - mib2_udp6Entry_t ude6; -#endif - char buf[512]; - int i, flags, getcode, num_ent, state, ret; - char lip[INET6_ADDRSTRLEN], rip[INET6_ADDRSTRLEN]; - int lport, rport; - int processed_pid; - int databuf_init = 0; - struct strbuf ctlbuf, databuf; - struct T_optmgmt_req tor = {0}; - struct T_optmgmt_ack toa = {0}; - struct T_error_ack tea = {0}; - struct opthdr mibhdr = {0}; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - sd = open("/dev/arp", O_RDWR); - if (sd == -1) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, "/dev/arp"); - goto error; - } - - ret = ioctl(sd, I_PUSH, "tcp"); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - ret = ioctl(sd, I_PUSH, "udp"); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - // - // OK, this mess is basically copied and pasted from nxsensor project - // which copied and pasted it from netstat source code, mibget() - // function. Also see: - // http://stackoverflow.com/questions/8723598/ - tor.PRIM_type = T_SVR4_OPTMGMT_REQ; - tor.OPT_offset = sizeof (struct T_optmgmt_req); - tor.OPT_length = sizeof (struct opthdr); - tor.MGMT_flags = T_CURRENT; - mibhdr.level = MIB2_IP; - mibhdr.name = 0; - -#ifdef NEW_MIB_COMPLIANT - mibhdr.len = 1; -#else - mibhdr.len = 0; -#endif - memcpy(buf, &tor, sizeof tor); - memcpy(buf + tor.OPT_offset, &mibhdr, sizeof mibhdr); - - ctlbuf.buf = buf; - ctlbuf.len = tor.OPT_offset + tor.OPT_length; - flags = 0; // request to be sent in non-priority - - if (putmsg(sd, &ctlbuf, (struct strbuf *)0, flags) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - ctlbuf.maxlen = sizeof (buf); - for (;;) { - flags = 0; - getcode = getmsg(sd, &ctlbuf, (struct strbuf *)0, &flags); - memcpy(&toa, buf, sizeof toa); - memcpy(&tea, buf, sizeof tea); - - if (getcode != MOREDATA || - ctlbuf.len < (int)sizeof (struct T_optmgmt_ack) || - toa.PRIM_type != T_OPTMGMT_ACK || - toa.MGMT_flags != T_SUCCESS) - { - break; - } - if (ctlbuf.len >= (int)sizeof (struct T_error_ack) && - tea.PRIM_type == T_ERROR_ACK) - { - PyErr_SetString(PyExc_RuntimeError, "ERROR_ACK"); - goto error; - } - if (getcode == 0 && - ctlbuf.len >= (int)sizeof (struct T_optmgmt_ack) && - toa.PRIM_type == T_OPTMGMT_ACK && - toa.MGMT_flags == T_SUCCESS) - { - PyErr_SetString(PyExc_RuntimeError, "ERROR_T_OPTMGMT_ACK"); - goto error; - } - - memset(&mibhdr, 0x0, sizeof(mibhdr)); - memcpy(&mibhdr, buf + toa.OPT_offset, toa.OPT_length); - - databuf.maxlen = mibhdr.len; - databuf.len = 0; - databuf.buf = (char *)malloc((int)mibhdr.len); - if (!databuf.buf) { - PyErr_NoMemory(); - goto error; - } - databuf_init = 1; - - flags = 0; - getcode = getmsg(sd, (struct strbuf *)0, &databuf, &flags); - if (getcode < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - // TCPv4 - if (mibhdr.level == MIB2_TCP && mibhdr.name == MIB2_TCP_13) { - num_ent = mibhdr.len / sizeof(mib2_tcpConnEntry_t); - for (i = 0; i < num_ent; i++) { - memcpy(&tp, databuf.buf + i * sizeof tp, sizeof tp); -#ifdef NEW_MIB_COMPLIANT - processed_pid = tp.tcpConnCreationProcess; -#else - processed_pid = 0; -#endif - if (pid != -1 && processed_pid != pid) - continue; - // construct local/remote addresses - inet_ntop(AF_INET, &tp.tcpConnLocalAddress, lip, sizeof(lip)); - inet_ntop(AF_INET, &tp.tcpConnRemAddress, rip, sizeof(rip)); - lport = tp.tcpConnLocalPort; - rport = tp.tcpConnRemPort; - - // contruct python tuple/list - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else { - py_raddr = Py_BuildValue("()"); - } - if (!py_raddr) - goto error; - state = tp.tcpConnEntryInfo.ce_state; - - // add item - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_STREAM, - py_laddr, py_raddr, state, - processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - } -#if defined(AF_INET6) - // TCPv6 - else if (mibhdr.level == MIB2_TCP6 && mibhdr.name == MIB2_TCP6_CONN) - { - num_ent = mibhdr.len / sizeof(mib2_tcp6ConnEntry_t); - - for (i = 0; i < num_ent; i++) { - memcpy(&tp6, databuf.buf + i * sizeof tp6, sizeof tp6); -#ifdef NEW_MIB_COMPLIANT - processed_pid = tp6.tcp6ConnCreationProcess; -#else - processed_pid = 0; -#endif - if (pid != -1 && processed_pid != pid) - continue; - // construct local/remote addresses - inet_ntop(AF_INET6, &tp6.tcp6ConnLocalAddress, lip, sizeof(lip)); - inet_ntop(AF_INET6, &tp6.tcp6ConnRemAddress, rip, sizeof(rip)); - lport = tp6.tcp6ConnLocalPort; - rport = tp6.tcp6ConnRemPort; - - // contruct python tuple/list - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - state = tp6.tcp6ConnEntryInfo.ce_state; - - // add item - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_STREAM, - py_laddr, py_raddr, state, processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - } -#endif - // UDPv4 - else if (mibhdr.level == MIB2_UDP || mibhdr.level == MIB2_UDP_ENTRY) { - num_ent = mibhdr.len / sizeof(mib2_udpEntry_t); - assert(num_ent * sizeof(mib2_udpEntry_t) == mibhdr.len); - for (i = 0; i < num_ent; i++) { - memcpy(&ude, databuf.buf + i * sizeof ude, sizeof ude); -#ifdef NEW_MIB_COMPLIANT - processed_pid = ude.udpCreationProcess; -#else - processed_pid = 0; -#endif - if (pid != -1 && processed_pid != pid) - continue; - // XXX Very ugly hack! It seems we get here only the first - // time we bump into a UDPv4 socket. PID is a very high - // number (clearly impossible) and the address does not - // belong to any valid interface. Not sure what else - // to do other than skipping. - if (processed_pid > 131072) - continue; - inet_ntop(AF_INET, &ude.udpLocalAddress, lip, sizeof(lip)); - lport = ude.udpLocalPort; - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_DGRAM, - py_laddr, py_raddr, PSUTIL_CONN_NONE, - processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - } -#if defined(AF_INET6) - // UDPv6 - else if (mibhdr.level == MIB2_UDP6 || - mibhdr.level == MIB2_UDP6_ENTRY) - { - num_ent = mibhdr.len / sizeof(mib2_udp6Entry_t); - for (i = 0; i < num_ent; i++) { - memcpy(&ude6, databuf.buf + i * sizeof ude6, sizeof ude6); -#ifdef NEW_MIB_COMPLIANT - processed_pid = ude6.udp6CreationProcess; -#else - processed_pid = 0; -#endif - if (pid != -1 && processed_pid != pid) - continue; - inet_ntop(AF_INET6, &ude6.udp6LocalAddress, lip, sizeof(lip)); - lport = ude6.udp6LocalPort; - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_DGRAM, - py_laddr, py_raddr, PSUTIL_CONN_NONE, - processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - } -#endif - free(databuf.buf); - } - - close(sd); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - Py_DECREF(py_retlist); - if (databuf_init == 1) - free(databuf.buf); - if (sd != 0) - close(sd); - return NULL; -} - - -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) { - float boot_time = 0.0; - struct utmpx *ut; - - setutxent(); - while (NULL != (ut = getutxent())) { - if (ut->ut_type == BOOT_TIME) { - boot_time = (float)ut->ut_tv.tv_sec; - break; - } - } - endutxent(); - if (fabs(boot_time) < 0.000001) { - /* could not find BOOT_TIME in getutxent loop */ - PyErr_SetString(PyExc_RuntimeError, "can't determine boot time"); - return NULL; - } - return Py_BuildValue("f", boot_time); -} - - -/* - * Return the number of physical CPU cores on the system. - */ -static PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) { - kstat_ctl_t *kc; - kstat_t *ksp; - int ncpus = 0; - - kc = kstat_open(); - if (kc == NULL) - goto error; - ksp = kstat_lookup(kc, "cpu_info", -1, NULL); - if (ksp == NULL) - goto error; - - for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_module, "cpu_info") != 0) - continue; - if (kstat_read(kc, ksp, NULL) == -1) - goto error; - ncpus += 1; - } - - kstat_close(kc); - if (ncpus > 0) - return Py_BuildValue("i", ncpus); - else - goto error; - -error: - // mimic os.cpu_count() - if (kc != NULL) - kstat_close(kc); - Py_RETURN_NONE; -} - - -/* - * Return stats about a particular network - * interface. References: - * https://github.com/dpaleino/wicd/blob/master/wicd/backends/be-ioctl.py - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject* -psutil_net_if_stats(PyObject* self, PyObject* args) { - kstat_ctl_t *kc = NULL; - kstat_t *ksp; - kstat_named_t *knp; - int ret; - int sock = -1; - int duplex; - int speed; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - PyObject *py_is_up = NULL; - - if (py_retdict == NULL) - return NULL; - kc = kstat_open(); - if (kc == NULL) - goto error; - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_class, "net") == 0) { - struct lifreq ifr; - - kstat_read(kc, ksp, NULL); - if (ksp->ks_type != KSTAT_TYPE_NAMED) - continue; - if (strcmp(ksp->ks_class, "net") != 0) - continue; - - strncpy(ifr.lifr_name, ksp->ks_name, sizeof(ifr.lifr_name)); - ret = ioctl(sock, SIOCGLIFFLAGS, &ifr); - if (ret == -1) - continue; // not a network interface - - // is up? - if ((ifr.lifr_flags & IFF_UP) != 0) { - if ((knp = kstat_data_lookup(ksp, "link_up")) != NULL) { - if (knp->value.ui32 != 0u) - py_is_up = Py_True; - else - py_is_up = Py_False; - } - else { - py_is_up = Py_True; - } - } - else { - py_is_up = Py_False; - } - Py_INCREF(py_is_up); - - // duplex - duplex = 0; // unknown - if ((knp = kstat_data_lookup(ksp, "link_duplex")) != NULL) { - if (knp->value.ui32 == 1) - duplex = 1; // half - else if (knp->value.ui32 == 2) - duplex = 2; // full - } - - // speed - if ((knp = kstat_data_lookup(ksp, "ifspeed")) != NULL) - // expressed in bits per sec, we want mega bits per sec - speed = (int)knp->value.ui64 / 1000000; - else - speed = 0; - - // mtu - ret = ioctl(sock, SIOCGLIFMTU, &ifr); - if (ret == -1) - goto error; - - py_ifc_info = Py_BuildValue("(Oiii)", py_is_up, duplex, speed, - ifr.lifr_mtu); - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_ifc_info)) - goto error; - Py_CLEAR(py_ifc_info); - } - } - - close(sock); - kstat_close(kc); - return py_retdict; - -error: - Py_XDECREF(py_is_up); - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (sock != -1) - close(sock); - if (kc != NULL) - kstat_close(kc); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -/* - * Return CPU statistics. - */ -static PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - kstat_ctl_t *kc; - kstat_t *ksp; - cpu_stat_t cs; - unsigned int ctx_switches = 0; - unsigned int interrupts = 0; - unsigned int traps = 0; - unsigned int syscalls = 0; - - kc = kstat_open(); - if (kc == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_module, "cpu_stat") == 0) { - if (kstat_read(kc, ksp, &cs) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - // voluntary + involuntary - ctx_switches += cs.cpu_sysinfo.pswitch + cs.cpu_sysinfo.inv_swtch; - interrupts += cs.cpu_sysinfo.intr; - traps += cs.cpu_sysinfo.trap; - syscalls += cs.cpu_sysinfo.syscall; - } - } - - kstat_close(kc); - return Py_BuildValue( - "IIII", ctx_switches, interrupts, syscalls, traps); - -error: - if (kc != NULL) - kstat_close(kc); - return NULL; -} - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef -PsutilMethods[] = { - // --- process-related functions - {"proc_basic_info", psutil_proc_basic_info, METH_VARARGS, - "Return process ppid, rss, vms, ctime, nice, nthreads, status and tty"}, - {"proc_name_and_args", psutil_proc_name_and_args, METH_VARARGS, - "Return process name and args."}, - {"proc_environ", psutil_proc_environ, METH_VARARGS, - "Return process environment."}, - {"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS, - "Return process user and system CPU times."}, - {"proc_cred", psutil_proc_cred, METH_VARARGS, - "Return process uids/gids."}, - {"query_process_thread", psutil_proc_query_thread, METH_VARARGS, - "Return info about a process thread"}, - {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS, - "Return process memory mappings"}, - {"proc_num_ctx_switches", psutil_proc_num_ctx_switches, METH_VARARGS, - "Return the number of context switches performed by process"}, - {"proc_cpu_num", psutil_proc_cpu_num, METH_VARARGS, - "Return what CPU the process is on"}, - - // --- system-related functions - {"swap_mem", psutil_swap_mem, METH_VARARGS, - "Return information about system swap memory."}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return disk partitions."}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-CPU times."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return a Python dict of tuples for disk I/O statistics."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return a Python dict of tuples for network I/O statistics."}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return system boot time in seconds since the EPOCH."}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Return the number of physical CPUs on the system."}, - {"net_connections", psutil_net_connections, METH_VARARGS, - "Return TCP and UDP syste-wide open connections."}, - {"net_if_stats", psutil_net_if_stats, METH_VARARGS, - "Return NIC stats (isup, duplex, speed, mtu)"}, - {"cpu_stats", psutil_cpu_stats, METH_VARARGS, - "Return CPU statistics"}, - - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int -psutil_sunos_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int -psutil_sunos_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_sunos", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_sunos_traverse, - psutil_sunos_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_sunos(void) - -#else -#define INITERROR return - -void init_psutil_sunos(void) -#endif -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_sunos", PsutilMethods); -#endif - if (module == NULL) - INITERROR; - - if (psutil_setup() != 0) - INITERROR; - - PyModule_AddIntConstant(module, "version", PSUTIL_VERSION); - - PyModule_AddIntConstant(module, "SSLEEP", SSLEEP); - PyModule_AddIntConstant(module, "SRUN", SRUN); - PyModule_AddIntConstant(module, "SZOMB", SZOMB); - PyModule_AddIntConstant(module, "SSTOP", SSTOP); - PyModule_AddIntConstant(module, "SIDL", SIDL); - PyModule_AddIntConstant(module, "SONPROC", SONPROC); -#ifdef SWAIT - PyModule_AddIntConstant(module, "SWAIT", SWAIT); -#else - /* sys/proc.h started defining SWAIT somewhere - * after Update 3 and prior to Update 5 included. - */ - PyModule_AddIntConstant(module, "SWAIT", 0); -#endif - - PyModule_AddIntConstant(module, "PRNODEV", PRNODEV); // for process tty - - PyModule_AddIntConstant(module, "TCPS_CLOSED", TCPS_CLOSED); - PyModule_AddIntConstant(module, "TCPS_CLOSING", TCPS_CLOSING); - PyModule_AddIntConstant(module, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT); - PyModule_AddIntConstant(module, "TCPS_LISTEN", TCPS_LISTEN); - PyModule_AddIntConstant(module, "TCPS_ESTABLISHED", TCPS_ESTABLISHED); - PyModule_AddIntConstant(module, "TCPS_SYN_SENT", TCPS_SYN_SENT); - PyModule_AddIntConstant(module, "TCPS_SYN_RCVD", TCPS_SYN_RCVD); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2); - PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK); - PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT); - // sunos specific - PyModule_AddIntConstant(module, "TCPS_IDLE", TCPS_IDLE); - // sunos specific - PyModule_AddIntConstant(module, "TCPS_BOUND", TCPS_BOUND); - PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE); - - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/third_party/python/psutil/psutil/_psutil_windows.c b/third_party/python/psutil/psutil/_psutil_windows.c deleted file mode 100644 index 82fa518eeb7d..000000000000 --- a/third_party/python/psutil/psutil/_psutil_windows.c +++ /dev/null @@ -1,1825 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Windows platform-specific module methods for _psutil_windows. - * - * List of undocumented Windows NT APIs which are used in here and in - * other modules: - * - NtQuerySystemInformation - * - NtQueryInformationProcess - * - NtQueryObject - * - NtSuspendProcess - * - NtResumeProcess - */ - -// Fixes clash between winsock2.h and windows.h -#define WIN32_LEAN_AND_MEAN - -#include -#include -#include // memory_info(), memory_maps() -#include -#include // threads(), PROCESSENTRY32 -#include // users() - -// Link with Iphlpapi.lib -#pragma comment(lib, "IPHLPAPI.lib") - -#include "_psutil_common.h" -#include "arch/windows/security.h" -#include "arch/windows/process_utils.h" -#include "arch/windows/process_info.h" -#include "arch/windows/process_handles.h" -#include "arch/windows/disk.h" -#include "arch/windows/cpu.h" -#include "arch/windows/net.h" -#include "arch/windows/services.h" -#include "arch/windows/socks.h" -#include "arch/windows/wmi.h" - -// Raised by Process.wait(). -static PyObject *TimeoutExpired; -static PyObject *TimeoutAbandoned; - - -/* - * Return the number of logical, active CPUs. Return 0 if undetermined. - * See discussion at: https://bugs.python.org/issue33166#msg314631 - */ -unsigned int -psutil_get_num_cpus(int fail_on_err) { - unsigned int ncpus = 0; - - // Minimum requirement: Windows 7 - if (GetActiveProcessorCount != NULL) { - ncpus = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); - if ((ncpus == 0) && (fail_on_err == 1)) { - PyErr_SetFromWindowsErr(0); - } - } - else { - psutil_debug("GetActiveProcessorCount() not available; " - "using GetSystemInfo()"); - ncpus = (unsigned int)PSUTIL_SYSTEM_INFO.dwNumberOfProcessors; - if ((ncpus <= 0) && (fail_on_err == 1)) { - PyErr_SetString( - PyExc_RuntimeError, - "GetSystemInfo() failed to retrieve CPU count"); - } - } - return ncpus; -} - - -/* - * Return a Python float representing the system uptime expressed in seconds - * since the epoch. - */ -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) { - ULONGLONG upTime; - FILETIME fileTime; - - GetSystemTimeAsFileTime(&fileTime); - // Number of milliseconds that have elapsed since the system was started. - upTime = GetTickCount64() / 1000ull; - return Py_BuildValue("d", psutil_FiletimeToUnixTime(fileTime) - upTime); -} - - -/* - * Return 1 if PID exists in the current process list, else 0. - */ -static PyObject * -psutil_pid_exists(PyObject *self, PyObject *args) { - DWORD pid; - int status; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - status = psutil_pid_is_running(pid); - if (-1 == status) - return NULL; // exception raised in psutil_pid_is_running() - return PyBool_FromLong(status); -} - - -/* - * Return a Python list of all the PIDs running on the system. - */ -static PyObject * -psutil_pids(PyObject *self, PyObject *args) { - DWORD *proclist = NULL; - DWORD numberOfReturnedPIDs; - DWORD i; - PyObject *py_pid = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - proclist = psutil_get_pids(&numberOfReturnedPIDs); - if (proclist == NULL) - goto error; - - for (i = 0; i < numberOfReturnedPIDs; i++) { - py_pid = PyLong_FromPid(proclist[i]); - if (!py_pid) - goto error; - if (PyList_Append(py_retlist, py_pid)) - goto error; - Py_CLEAR(py_pid); - } - - // free C array allocated for PIDs - free(proclist); - return py_retlist; - -error: - Py_XDECREF(py_pid); - Py_DECREF(py_retlist); - if (proclist != NULL) - free(proclist); - return NULL; -} - - -/* - * Kill a process given its PID. - */ -static PyObject * -psutil_proc_kill(PyObject *self, PyObject *args) { - HANDLE hProcess; - DWORD pid; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if (pid == 0) - return AccessDenied("automatically set for PID 0"); - - hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); - if (hProcess == NULL) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - // see https://github.com/giampaolo/psutil/issues/24 - psutil_debug("OpenProcess -> ERROR_INVALID_PARAMETER turned " - "into NoSuchProcess"); - NoSuchProcess("OpenProcess"); - } - else { - PyErr_SetFromWindowsErr(0); - } - return NULL; - } - - if (! TerminateProcess(hProcess, SIGTERM)) { - // ERROR_ACCESS_DENIED may happen if the process already died. See: - // https://github.com/giampaolo/psutil/issues/1099 - if (GetLastError() != ERROR_ACCESS_DENIED) { - PyErr_SetFromOSErrnoWithSyscall("TerminateProcess"); - return NULL; - } - } - - CloseHandle(hProcess); - Py_RETURN_NONE; -} - - -/* - * Wait for process to terminate and return its exit code. - */ -static PyObject * -psutil_proc_wait(PyObject *self, PyObject *args) { - HANDLE hProcess; - DWORD ExitCode; - DWORD retVal; - DWORD pid; - long timeout; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "l", &pid, &timeout)) - return NULL; - if (pid == 0) - return AccessDenied("automatically set for PID 0"); - - hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, - FALSE, pid); - if (hProcess == NULL) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - // no such process; we do not want to raise NSP but - // return None instead. - Py_RETURN_NONE; - } - else { - PyErr_SetFromWindowsErr(0); - return NULL; - } - } - - // wait until the process has terminated - Py_BEGIN_ALLOW_THREADS - retVal = WaitForSingleObject(hProcess, timeout); - Py_END_ALLOW_THREADS - - // handle return code - if (retVal == WAIT_FAILED) { - PyErr_SetFromOSErrnoWithSyscall("WaitForSingleObject"); - CloseHandle(hProcess); - return NULL; - } - if (retVal == WAIT_TIMEOUT) { - PyErr_SetString(TimeoutExpired, - "WaitForSingleObject() returned WAIT_TIMEOUT"); - CloseHandle(hProcess); - return NULL; - } - if (retVal == WAIT_ABANDONED) { - psutil_debug("WaitForSingleObject() -> WAIT_ABANDONED"); - PyErr_SetString(TimeoutAbandoned, - "WaitForSingleObject() returned WAIT_ABANDONED"); - CloseHandle(hProcess); - return NULL; - } - - // WaitForSingleObject() returned WAIT_OBJECT_0. It means the - // process is gone so we can get its process exit code. The PID - // may still stick around though but we'll handle that from Python. - if (GetExitCodeProcess(hProcess, &ExitCode) == 0) { - PyErr_SetFromOSErrnoWithSyscall("GetExitCodeProcess"); - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong((long) ExitCode); -#else - return PyInt_FromLong((long) ExitCode); -#endif -} - - -/* - * Return a Python tuple (user_time, kernel_time) - */ -static PyObject * -psutil_proc_times(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - FILETIME ftCreate, ftExit, ftKernel, ftUser; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - - if (hProcess == NULL) - return NULL; - if (! GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) { - if (GetLastError() == ERROR_ACCESS_DENIED) { - // usually means the process has died so we throw a NoSuchProcess - // here - NoSuchProcess("GetProcessTimes"); - } - else { - PyErr_SetFromWindowsErr(0); - } - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - - /* - * User and kernel times are represented as a FILETIME structure - * which contains a 64-bit value representing the number of - * 100-nanosecond intervals since January 1, 1601 (UTC): - * http://msdn.microsoft.com/en-us/library/ms724284(VS.85).aspx - * To convert it into a float representing the seconds that the - * process has executed in user/kernel mode I borrowed the code - * below from Python's Modules/posixmodule.c - */ - return Py_BuildValue( - "(ddd)", - (double)(ftUser.dwHighDateTime * HI_T + \ - ftUser.dwLowDateTime * LO_T), - (double)(ftKernel.dwHighDateTime * HI_T + \ - ftKernel.dwLowDateTime * LO_T), - psutil_FiletimeToUnixTime(ftCreate) - ); -} - - -/* - * Return process cmdline as a Python list of cmdline arguments. - */ -static PyObject * -psutil_proc_cmdline(PyObject *self, PyObject *args, PyObject *kwdict) { - DWORD pid; - int pid_return; - int use_peb; - PyObject *py_usepeb = Py_True; - static char *keywords[] = {"pid", "use_peb", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwdict, _Py_PARSE_PID "|O", - keywords, &pid, &py_usepeb)) - { - return NULL; - } - if ((pid == 0) || (pid == 4)) - return Py_BuildValue("[]"); - - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) - return NoSuchProcess("psutil_pid_is_running"); - if (pid_return == -1) - return NULL; - - use_peb = (py_usepeb == Py_True) ? 1 : 0; - return psutil_get_cmdline(pid, use_peb); -} - - -/* - * Return process cmdline as a Python list of cmdline arguments. - */ -static PyObject * -psutil_proc_environ(PyObject *self, PyObject *args) { - DWORD pid; - int pid_return; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if ((pid == 0) || (pid == 4)) - return Py_BuildValue("s", ""); - - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) - return NoSuchProcess("psutil_pid_is_running"); - if (pid_return == -1) - return NULL; - - return psutil_get_environ(pid); -} - - -/* - * Return process executable path. Works for all processes regardless of - * privilege. NtQuerySystemInformation has some sort of internal cache, - * since it succeeds even when a process is gone (but not if a PID never - * existed). - */ -static PyObject * -psutil_proc_exe(PyObject *self, PyObject *args) { - DWORD pid; - NTSTATUS status; - PVOID buffer; - ULONG bufferSize = 0x100; - SYSTEM_PROCESS_ID_INFORMATION processIdInfo; - PyObject *py_exe; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - if (pid == 0) - return AccessDenied("forced for PID 0"); - - buffer = MALLOC_ZERO(bufferSize); - if (! buffer) - return PyErr_NoMemory(); - processIdInfo.ProcessId = (HANDLE)(ULONG_PTR)pid; - processIdInfo.ImageName.Length = 0; - processIdInfo.ImageName.MaximumLength = (USHORT)bufferSize; - processIdInfo.ImageName.Buffer = buffer; - - status = NtQuerySystemInformation( - SystemProcessIdInformation, - &processIdInfo, - sizeof(SYSTEM_PROCESS_ID_INFORMATION), - NULL); - - if (status == STATUS_INFO_LENGTH_MISMATCH) { - // Required length is stored in MaximumLength. - FREE(buffer); - buffer = MALLOC_ZERO(processIdInfo.ImageName.MaximumLength); - if (! buffer) - return PyErr_NoMemory(); - processIdInfo.ImageName.Buffer = buffer; - - status = NtQuerySystemInformation( - SystemProcessIdInformation, - &processIdInfo, - sizeof(SYSTEM_PROCESS_ID_INFORMATION), - NULL); - } - - if (! NT_SUCCESS(status)) { - FREE(buffer); - if (psutil_pid_is_running(pid) == 0) - NoSuchProcess("NtQuerySystemInformation"); - else - psutil_SetFromNTStatusErr(status, "NtQuerySystemInformation"); - return NULL; - } - - if (processIdInfo.ImageName.Buffer == NULL) { - // Happens for PID 4. - py_exe = Py_BuildValue("s", ""); - } - else { - py_exe = PyUnicode_FromWideChar(processIdInfo.ImageName.Buffer, - processIdInfo.ImageName.Length / 2); - } - FREE(buffer); - return py_exe; -} - - -/* - * Return process memory information as a Python tuple. - */ -static PyObject * -psutil_proc_memory_info(PyObject *self, PyObject *args) { - HANDLE hProcess; - DWORD pid; - PROCESS_MEMORY_COUNTERS_EX cnt; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (NULL == hProcess) - return NULL; - - if (! GetProcessMemoryInfo(hProcess, (PPROCESS_MEMORY_COUNTERS)&cnt, - sizeof(cnt))) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - CloseHandle(hProcess); - - // PROCESS_MEMORY_COUNTERS values are defined as SIZE_T which on 64bits - // is an (unsigned long long) and on 32bits is an (unsigned int). - // "_WIN64" is defined if we're running a 64bit Python interpreter not - // exclusively if the *system* is 64bit. -#if defined(_WIN64) - return Py_BuildValue( - "(kKKKKKKKKK)", - cnt.PageFaultCount, // unsigned long - (unsigned long long)cnt.PeakWorkingSetSize, - (unsigned long long)cnt.WorkingSetSize, - (unsigned long long)cnt.QuotaPeakPagedPoolUsage, - (unsigned long long)cnt.QuotaPagedPoolUsage, - (unsigned long long)cnt.QuotaPeakNonPagedPoolUsage, - (unsigned long long)cnt.QuotaNonPagedPoolUsage, - (unsigned long long)cnt.PagefileUsage, - (unsigned long long)cnt.PeakPagefileUsage, - (unsigned long long)cnt.PrivateUsage); -#else - return Py_BuildValue( - "(kIIIIIIIII)", - cnt.PageFaultCount, // unsigned long - (unsigned int)cnt.PeakWorkingSetSize, - (unsigned int)cnt.WorkingSetSize, - (unsigned int)cnt.QuotaPeakPagedPoolUsage, - (unsigned int)cnt.QuotaPagedPoolUsage, - (unsigned int)cnt.QuotaPeakNonPagedPoolUsage, - (unsigned int)cnt.QuotaNonPagedPoolUsage, - (unsigned int)cnt.PagefileUsage, - (unsigned int)cnt.PeakPagefileUsage, - (unsigned int)cnt.PrivateUsage); -#endif -} - - -static int -psutil_GetProcWsetInformation( - DWORD pid, - HANDLE hProcess, - PMEMORY_WORKING_SET_INFORMATION *wSetInfo) -{ - NTSTATUS status; - PVOID buffer; - SIZE_T bufferSize; - - bufferSize = 0x8000; - buffer = MALLOC_ZERO(bufferSize); - if (! buffer) { - PyErr_NoMemory(); - return 1; - } - - while ((status = NtQueryVirtualMemory( - hProcess, - NULL, - MemoryWorkingSetInformation, - buffer, - bufferSize, - NULL)) == STATUS_INFO_LENGTH_MISMATCH) - { - FREE(buffer); - bufferSize *= 2; - // Fail if we're resizing the buffer to something very large. - if (bufferSize > 256 * 1024 * 1024) { - PyErr_SetString(PyExc_RuntimeError, - "NtQueryVirtualMemory bufsize is too large"); - return 1; - } - buffer = MALLOC_ZERO(bufferSize); - if (! buffer) { - PyErr_NoMemory(); - return 1; - } - } - - if (!NT_SUCCESS(status)) { - if (status == STATUS_ACCESS_DENIED) { - AccessDenied("NtQueryVirtualMemory"); - } - else if (psutil_pid_is_running(pid) == 0) { - NoSuchProcess("psutil_pid_is_running"); - } - else { - PyErr_Clear(); - psutil_SetFromNTStatusErr( - status, "NtQueryVirtualMemory(MemoryWorkingSetInformation)"); - } - HeapFree(GetProcessHeap(), 0, buffer); - return 1; - } - - *wSetInfo = (PMEMORY_WORKING_SET_INFORMATION)buffer; - return 0; -} - - -/* - * Returns the USS of the process. - * Reference: - * https://dxr.mozilla.org/mozilla-central/source/xpcom/base/ - * nsMemoryReporterManager.cpp - */ -static PyObject * -psutil_proc_memory_uss(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - PSUTIL_PROCESS_WS_COUNTERS wsCounters; - PMEMORY_WORKING_SET_INFORMATION wsInfo; - ULONG_PTR i; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_INFORMATION); - if (hProcess == NULL) - return NULL; - - if (psutil_GetProcWsetInformation(pid, hProcess, &wsInfo) != 0) { - CloseHandle(hProcess); - return NULL; - } - memset(&wsCounters, 0, sizeof(PSUTIL_PROCESS_WS_COUNTERS)); - - for (i = 0; i < wsInfo->NumberOfEntries; i++) { - // This is what ProcessHacker does. - /* - wsCounters.NumberOfPages++; - if (wsInfo->WorkingSetInfo[i].ShareCount > 1) - wsCounters.NumberOfSharedPages++; - if (wsInfo->WorkingSetInfo[i].ShareCount == 0) - wsCounters.NumberOfPrivatePages++; - if (wsInfo->WorkingSetInfo[i].Shared) - wsCounters.NumberOfShareablePages++; - */ - - // This is what we do: count shared pages that only one process - // is using as private (USS). - if (!wsInfo->WorkingSetInfo[i].Shared || - wsInfo->WorkingSetInfo[i].ShareCount <= 1) { - wsCounters.NumberOfPrivatePages++; - } - } - - HeapFree(GetProcessHeap(), 0, wsInfo); - CloseHandle(hProcess); - - return Py_BuildValue("I", wsCounters.NumberOfPrivatePages); -} - - -/* - * Return a Python integer indicating the total amount of physical memory - * in bytes. - */ -static PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - MEMORYSTATUSEX memInfo; - memInfo.dwLength = sizeof(MEMORYSTATUSEX); - - if (! GlobalMemoryStatusEx(&memInfo)) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - return Py_BuildValue("(LLLLLL)", - memInfo.ullTotalPhys, // total - memInfo.ullAvailPhys, // avail - memInfo.ullTotalPageFile, // total page file - memInfo.ullAvailPageFile, // avail page file - memInfo.ullTotalVirtual, // total virtual - memInfo.ullAvailVirtual); // avail virtual -} - - -/* - * Return process current working directory as a Python string. - */ -static PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) { - DWORD pid; - int pid_return; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) - return NoSuchProcess("psutil_pid_is_running"); - if (pid_return == -1) - return NULL; - - return psutil_get_cwd(pid); -} - - -/* - * Resume or suspends a process - */ -static PyObject * -psutil_proc_suspend_or_resume(PyObject *self, PyObject *args) { - DWORD pid; - NTSTATUS status; - HANDLE hProcess; - PyObject* suspend; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "O", &pid, &suspend)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, PROCESS_SUSPEND_RESUME); - if (hProcess == NULL) - return NULL; - - if (PyObject_IsTrue(suspend)) - status = NtSuspendProcess(hProcess); - else - status = NtResumeProcess(hProcess); - - if (! NT_SUCCESS(status)) { - CloseHandle(hProcess); - return psutil_SetFromNTStatusErr(status, "NtSuspend|ResumeProcess"); - } - - CloseHandle(hProcess); - Py_RETURN_NONE; -} - - -static PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - HANDLE hThread = NULL; - THREADENTRY32 te32 = {0}; - DWORD pid; - int pid_return; - int rc; - FILETIME ftDummy, ftKernel, ftUser; - HANDLE hThreadSnap = NULL; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - goto error; - if (pid == 0) { - // raise AD instead of returning 0 as procexp is able to - // retrieve useful information somehow - AccessDenied("automatically set for PID 0"); - goto error; - } - - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) { - NoSuchProcess("psutil_pid_is_running"); - goto error; - } - if (pid_return == -1) - goto error; - - hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hThreadSnap == INVALID_HANDLE_VALUE) { - PyErr_SetFromOSErrnoWithSyscall("CreateToolhelp32Snapshot"); - goto error; - } - - // Fill in the size of the structure before using it - te32.dwSize = sizeof(THREADENTRY32); - - if (! Thread32First(hThreadSnap, &te32)) { - PyErr_SetFromOSErrnoWithSyscall("Thread32First"); - goto error; - } - - // Walk the thread snapshot to find all threads of the process. - // If the thread belongs to the process, increase the counter. - do { - if (te32.th32OwnerProcessID == pid) { - py_tuple = NULL; - hThread = NULL; - hThread = OpenThread(THREAD_QUERY_INFORMATION, - FALSE, te32.th32ThreadID); - if (hThread == NULL) { - // thread has disappeared on us - continue; - } - - rc = GetThreadTimes(hThread, &ftDummy, &ftDummy, &ftKernel, - &ftUser); - if (rc == 0) { - PyErr_SetFromOSErrnoWithSyscall("GetThreadTimes"); - goto error; - } - - /* - * User and kernel times are represented as a FILETIME structure - * which contains a 64-bit value representing the number of - * 100-nanosecond intervals since January 1, 1601 (UTC): - * http://msdn.microsoft.com/en-us/library/ms724284(VS.85).aspx - * To convert it into a float representing the seconds that the - * process has executed in user/kernel mode I borrowed the code - * below from Python's Modules/posixmodule.c - */ - py_tuple = Py_BuildValue( - "kdd", - te32.th32ThreadID, - (double)(ftUser.dwHighDateTime * HI_T + \ - ftUser.dwLowDateTime * LO_T), - (double)(ftKernel.dwHighDateTime * HI_T + \ - ftKernel.dwLowDateTime * LO_T)); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - - CloseHandle(hThread); - } - } while (Thread32Next(hThreadSnap, &te32)); - - CloseHandle(hThreadSnap); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (hThread != NULL) - CloseHandle(hThread); - if (hThreadSnap != NULL) - CloseHandle(hThreadSnap); - return NULL; -} - - -static PyObject * -psutil_proc_open_files(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE processHandle; - DWORD access = PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; - PyObject *py_retlist; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - processHandle = psutil_handle_from_pid(pid, access); - if (processHandle == NULL) - return NULL; - - py_retlist = psutil_get_open_files(pid, processHandle); - CloseHandle(processHandle); - return py_retlist; -} - - -/* - * Return process username as a "DOMAIN//USERNAME" string. - */ -static PyObject * -psutil_proc_username(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE processHandle = NULL; - HANDLE tokenHandle = NULL; - PTOKEN_USER user = NULL; - ULONG bufferSize; - WCHAR *name = NULL; - WCHAR *domainName = NULL; - ULONG nameSize; - ULONG domainNameSize; - SID_NAME_USE nameUse; - PyObject *py_username = NULL; - PyObject *py_domain = NULL; - PyObject *py_tuple = NULL; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - processHandle = psutil_handle_from_pid( - pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (processHandle == NULL) - return NULL; - - if (!OpenProcessToken(processHandle, TOKEN_QUERY, &tokenHandle)) { - PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken"); - goto error; - } - - CloseHandle(processHandle); - processHandle = NULL; - - // Get the user SID. - bufferSize = 0x100; - while (1) { - user = malloc(bufferSize); - if (user == NULL) { - PyErr_NoMemory(); - goto error; - } - if (!GetTokenInformation(tokenHandle, TokenUser, user, bufferSize, - &bufferSize)) - { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - free(user); - continue; - } - else { - PyErr_SetFromOSErrnoWithSyscall("GetTokenInformation"); - goto error; - } - } - break; - } - - CloseHandle(tokenHandle); - tokenHandle = NULL; - - // resolve the SID to a name - nameSize = 0x100; - domainNameSize = 0x100; - while (1) { - name = malloc(nameSize * sizeof(WCHAR)); - if (name == NULL) { - PyErr_NoMemory(); - goto error; - } - domainName = malloc(domainNameSize * sizeof(WCHAR)); - if (domainName == NULL) { - PyErr_NoMemory(); - goto error; - } - if (!LookupAccountSidW(NULL, user->User.Sid, name, &nameSize, - domainName, &domainNameSize, &nameUse)) - { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - free(name); - free(domainName); - continue; - } - else { - PyErr_SetFromOSErrnoWithSyscall("LookupAccountSidW"); - goto error; - } - } - break; - } - - py_domain = PyUnicode_FromWideChar(domainName, wcslen(domainName)); - if (! py_domain) - goto error; - py_username = PyUnicode_FromWideChar(name, wcslen(name)); - if (! py_username) - goto error; - py_tuple = Py_BuildValue("OO", py_domain, py_username); - if (! py_tuple) - goto error; - Py_DECREF(py_domain); - Py_DECREF(py_username); - - free(name); - free(domainName); - free(user); - - return py_tuple; - -error: - if (processHandle != NULL) - CloseHandle(processHandle); - if (tokenHandle != NULL) - CloseHandle(tokenHandle); - if (name != NULL) - free(name); - if (domainName != NULL) - free(domainName); - if (user != NULL) - free(user); - Py_XDECREF(py_domain); - Py_XDECREF(py_username); - Py_XDECREF(py_tuple); - return NULL; -} - - -/* - * Get process priority as a Python integer. - */ -static PyObject * -psutil_proc_priority_get(PyObject *self, PyObject *args) { - DWORD pid; - DWORD priority; - HANDLE hProcess; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (hProcess == NULL) - return NULL; - - priority = GetPriorityClass(hProcess); - if (priority == 0) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - CloseHandle(hProcess); - return Py_BuildValue("i", priority); -} - - -/* - * Set process priority. - */ -static PyObject * -psutil_proc_priority_set(PyObject *self, PyObject *args) { - DWORD pid; - int priority; - int retval; - HANDLE hProcess; - DWORD access = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "i", &pid, &priority)) - return NULL; - hProcess = psutil_handle_from_pid(pid, access); - if (hProcess == NULL) - return NULL; - - retval = SetPriorityClass(hProcess, priority); - if (retval == 0) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - Py_RETURN_NONE; -} - - -/* - * Get process IO priority as a Python integer. - */ -static PyObject * -psutil_proc_io_priority_get(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - DWORD IoPriority; - NTSTATUS status; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (hProcess == NULL) - return NULL; - - status = NtQueryInformationProcess( - hProcess, - ProcessIoPriority, - &IoPriority, - sizeof(DWORD), - NULL - ); - - CloseHandle(hProcess); - if (! NT_SUCCESS(status)) - return psutil_SetFromNTStatusErr(status, "NtQueryInformationProcess"); - return Py_BuildValue("i", IoPriority); -} - - -/* - * Set process IO priority. - */ -static PyObject * -psutil_proc_io_priority_set(PyObject *self, PyObject *args) { - DWORD pid; - DWORD prio; - HANDLE hProcess; - NTSTATUS status; - DWORD access = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "i", &pid, &prio)) - return NULL; - - hProcess = psutil_handle_from_pid(pid, access); - if (hProcess == NULL) - return NULL; - - status = NtSetInformationProcess( - hProcess, - ProcessIoPriority, - (PVOID)&prio, - sizeof(DWORD) - ); - - CloseHandle(hProcess); - if (! NT_SUCCESS(status)) - return psutil_SetFromNTStatusErr(status, "NtSetInformationProcess"); - Py_RETURN_NONE; -} - - -/* - * Return a Python tuple referencing process I/O counters. - */ -static PyObject * -psutil_proc_io_counters(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - IO_COUNTERS IoCounters; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (NULL == hProcess) - return NULL; - - if (! GetProcessIoCounters(hProcess, &IoCounters)) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - return Py_BuildValue("(KKKKKK)", - IoCounters.ReadOperationCount, - IoCounters.WriteOperationCount, - IoCounters.ReadTransferCount, - IoCounters.WriteTransferCount, - IoCounters.OtherOperationCount, - IoCounters.OtherTransferCount); -} - - -/* - * Return process CPU affinity as a bitmask - */ -static PyObject * -psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - DWORD_PTR proc_mask; - DWORD_PTR system_mask; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (hProcess == NULL) { - return NULL; - } - if (GetProcessAffinityMask(hProcess, &proc_mask, &system_mask) == 0) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); -#ifdef _WIN64 - return Py_BuildValue("K", (unsigned long long)proc_mask); -#else - return Py_BuildValue("k", (unsigned long)proc_mask); -#endif -} - - -/* - * Set process CPU affinity - */ -static PyObject * -psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - DWORD access = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION; - DWORD_PTR mask; - -#ifdef _WIN64 - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "K", &pid, &mask)) -#else - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "k", &pid, &mask)) -#endif - { - return NULL; - } - hProcess = psutil_handle_from_pid(pid, access); - if (hProcess == NULL) - return NULL; - - if (SetProcessAffinityMask(hProcess, mask) == 0) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - Py_RETURN_NONE; -} - - -/* - * Return True if all process threads are in waiting/suspended state. - */ -static PyObject * -psutil_proc_is_suspended(PyObject *self, PyObject *args) { - DWORD pid; - ULONG i; - PSYSTEM_PROCESS_INFORMATION process; - PVOID buffer; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if (! psutil_get_proc_info(pid, &process, &buffer)) - return NULL; - for (i = 0; i < process->NumberOfThreads; i++) { - if (process->Threads[i].ThreadState != Waiting || - process->Threads[i].WaitReason != Suspended) - { - free(buffer); - Py_RETURN_FALSE; - } - } - free(buffer); - Py_RETURN_TRUE; -} - - -/* - * Return a Python dict of tuples for disk I/O information - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) { - HANDLE hServer = WTS_CURRENT_SERVER_HANDLE; - WCHAR *buffer_user = NULL; - LPTSTR buffer_addr = NULL; - PWTS_SESSION_INFO sessions = NULL; - DWORD count; - DWORD i; - DWORD sessionId; - DWORD bytes; - PWTS_CLIENT_ADDRESS address; - char address_str[50]; - WINSTATION_INFO station_info; - ULONG returnLen; - PyObject *py_tuple = NULL; - PyObject *py_address = NULL; - PyObject *py_username = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - if (WTSEnumerateSessions(hServer, 0, 1, &sessions, &count) == 0) { - PyErr_SetFromOSErrnoWithSyscall("WTSEnumerateSessions"); - goto error; - } - - for (i = 0; i < count; i++) { - py_address = NULL; - py_tuple = NULL; - sessionId = sessions[i].SessionId; - if (buffer_user != NULL) - WTSFreeMemory(buffer_user); - if (buffer_addr != NULL) - WTSFreeMemory(buffer_addr); - - buffer_user = NULL; - buffer_addr = NULL; - - // username - bytes = 0; - if (WTSQuerySessionInformationW(hServer, sessionId, WTSUserName, - &buffer_user, &bytes) == 0) { - PyErr_SetFromOSErrnoWithSyscall("WTSQuerySessionInformationW"); - goto error; - } - if (bytes <= 2) - continue; - - // address - bytes = 0; - if (WTSQuerySessionInformation(hServer, sessionId, WTSClientAddress, - &buffer_addr, &bytes) == 0) { - PyErr_SetFromOSErrnoWithSyscall("WTSQuerySessionInformation"); - goto error; - } - - address = (PWTS_CLIENT_ADDRESS)buffer_addr; - if (address->AddressFamily == 0) { // AF_INET - sprintf_s(address_str, - _countof(address_str), - "%u.%u.%u.%u", - address->Address[0], - address->Address[1], - address->Address[2], - address->Address[3]); - py_address = Py_BuildValue("s", address_str); - if (!py_address) - goto error; - } - else { - py_address = Py_None; - } - - // login time - if (! WinStationQueryInformationW( - hServer, - sessionId, - WinStationInformation, - &station_info, - sizeof(station_info), - &returnLen)) - { - PyErr_SetFromOSErrnoWithSyscall("WinStationQueryInformationW"); - goto error; - } - - py_username = PyUnicode_FromWideChar(buffer_user, wcslen(buffer_user)); - if (py_username == NULL) - goto error; - py_tuple = Py_BuildValue( - "OOd", - py_username, - py_address, - psutil_FiletimeToUnixTime(station_info.ConnectTime) - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_username); - Py_CLEAR(py_address); - Py_CLEAR(py_tuple); - } - - WTSFreeMemory(sessions); - WTSFreeMemory(buffer_user); - WTSFreeMemory(buffer_addr); - return py_retlist; - -error: - Py_XDECREF(py_username); - Py_XDECREF(py_tuple); - Py_XDECREF(py_address); - Py_DECREF(py_retlist); - - if (sessions != NULL) - WTSFreeMemory(sessions); - if (buffer_user != NULL) - WTSFreeMemory(buffer_user); - if (buffer_addr != NULL) - WTSFreeMemory(buffer_addr); - return NULL; -} - - -/* - * Return the number of handles opened by process. - */ -static PyObject * -psutil_proc_num_handles(PyObject *self, PyObject *args) { - DWORD pid; - HANDLE hProcess; - DWORD handleCount; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (NULL == hProcess) - return NULL; - if (! GetProcessHandleCount(hProcess, &handleCount)) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - CloseHandle(hProcess); - return Py_BuildValue("k", handleCount); -} - - -static char *get_region_protection_string(ULONG protection) { - switch (protection & 0xff) { - case PAGE_NOACCESS: - return ""; - case PAGE_READONLY: - return "r"; - case PAGE_READWRITE: - return "rw"; - case PAGE_WRITECOPY: - return "wc"; - case PAGE_EXECUTE: - return "x"; - case PAGE_EXECUTE_READ: - return "xr"; - case PAGE_EXECUTE_READWRITE: - return "xrw"; - case PAGE_EXECUTE_WRITECOPY: - return "xwc"; - default: - return "?"; - } -} - - -/* - * Return a list of process's memory mappings. - */ -static PyObject * -psutil_proc_memory_maps(PyObject *self, PyObject *args) { - MEMORY_BASIC_INFORMATION basicInfo; - DWORD pid; - HANDLE hProcess = NULL; - PVOID baseAddress; - WCHAR mappedFileName[MAX_PATH]; - LPVOID maxAddr; - // required by GetMappedFileNameW - DWORD access = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_str = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - goto error; - hProcess = psutil_handle_from_pid(pid, access); - if (NULL == hProcess) - goto error; - - maxAddr = PSUTIL_SYSTEM_INFO.lpMaximumApplicationAddress; - baseAddress = NULL; - - while (VirtualQueryEx(hProcess, baseAddress, &basicInfo, - sizeof(MEMORY_BASIC_INFORMATION))) - { - py_tuple = NULL; - if (baseAddress > maxAddr) - break; - if (GetMappedFileNameW(hProcess, baseAddress, mappedFileName, - sizeof(mappedFileName))) - { - py_str = PyUnicode_FromWideChar(mappedFileName, - wcslen(mappedFileName)); - if (py_str == NULL) - goto error; -#ifdef _WIN64 - py_tuple = Py_BuildValue( - "(KsOI)", - (unsigned long long)baseAddress, -#else - py_tuple = Py_BuildValue( - "(ksOI)", - (unsigned long)baseAddress, -#endif - get_region_protection_string(basicInfo.Protect), - py_str, - basicInfo.RegionSize); - - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_str); - } - baseAddress = (PCHAR)baseAddress + basicInfo.RegionSize; - } - - CloseHandle(hProcess); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_str); - Py_DECREF(py_retlist); - if (hProcess != NULL) - CloseHandle(hProcess); - return NULL; -} - - -/* - * Return a {pid:ppid, ...} dict for all running processes. - */ -static PyObject * -psutil_ppid_map(PyObject *self, PyObject *args) { - PyObject *py_pid = NULL; - PyObject *py_ppid = NULL; - PyObject *py_retdict = PyDict_New(); - HANDLE handle = NULL; - PROCESSENTRY32 pe = {0}; - pe.dwSize = sizeof(PROCESSENTRY32); - - if (py_retdict == NULL) - return NULL; - handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (handle == INVALID_HANDLE_VALUE) { - PyErr_SetFromWindowsErr(0); - Py_DECREF(py_retdict); - return NULL; - } - - if (Process32First(handle, &pe)) { - do { - py_pid = PyLong_FromPid(pe.th32ProcessID); - if (py_pid == NULL) - goto error; - py_ppid = PyLong_FromPid(pe.th32ParentProcessID); - if (py_ppid == NULL) - goto error; - if (PyDict_SetItem(py_retdict, py_pid, py_ppid)) - goto error; - Py_CLEAR(py_pid); - Py_CLEAR(py_ppid); - } while (Process32Next(handle, &pe)); - } - - CloseHandle(handle); - return py_retdict; - -error: - Py_XDECREF(py_pid); - Py_XDECREF(py_ppid); - Py_DECREF(py_retdict); - CloseHandle(handle); - return NULL; -} - - -/* - * Return battery usage stats. - */ -static PyObject * -psutil_sensors_battery(PyObject *self, PyObject *args) { - SYSTEM_POWER_STATUS sps; - - if (GetSystemPowerStatus(&sps) == 0) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - return Py_BuildValue( - "iiiI", - sps.ACLineStatus, // whether AC is connected: 0=no, 1=yes, 255=unknown - // status flag: - // 1, 2, 4 = high, low, critical - // 8 = charging - // 128 = no battery - sps.BatteryFlag, - sps.BatteryLifePercent, // percent - sps.BatteryLifeTime // remaining secs - ); -} - - -/* - * System memory page size as an int. - */ -static PyObject * -psutil_getpagesize(PyObject *self, PyObject *args) { - // XXX: we may want to use GetNativeSystemInfo to differentiate - // page size for WoW64 processes (but am not sure). - return Py_BuildValue("I", PSUTIL_SYSTEM_INFO.dwPageSize); -} - - -// ------------------------ Python init --------------------------- - -static PyMethodDef -PsutilMethods[] = { - // --- per-process functions - {"proc_cmdline", (PyCFunction)(void(*)(void))psutil_proc_cmdline, - METH_VARARGS | METH_KEYWORDS, - "Return process cmdline as a list of cmdline arguments"}, - {"proc_environ", psutil_proc_environ, METH_VARARGS, - "Return process environment data"}, - {"proc_exe", psutil_proc_exe, METH_VARARGS, - "Return path of the process executable"}, - {"proc_kill", psutil_proc_kill, METH_VARARGS, - "Kill the process identified by the given PID"}, - {"proc_times", psutil_proc_times, METH_VARARGS, - "Return tuple of user/kern time for the given PID"}, - {"proc_memory_info", psutil_proc_memory_info, METH_VARARGS, - "Return a tuple of process memory information"}, - {"proc_memory_uss", psutil_proc_memory_uss, METH_VARARGS, - "Return the USS of the process"}, - {"proc_cwd", psutil_proc_cwd, METH_VARARGS, - "Return process current working directory"}, - {"proc_suspend_or_resume", psutil_proc_suspend_or_resume, METH_VARARGS, - "Suspend or resume a process"}, - {"proc_open_files", psutil_proc_open_files, METH_VARARGS, - "Return files opened by process"}, - {"proc_username", psutil_proc_username, METH_VARARGS, - "Return the username of a process"}, - {"proc_threads", psutil_proc_threads, METH_VARARGS, - "Return process threads information as a list of tuple"}, - {"proc_wait", psutil_proc_wait, METH_VARARGS, - "Wait for process to terminate and return its exit code."}, - {"proc_priority_get", psutil_proc_priority_get, METH_VARARGS, - "Return process priority."}, - {"proc_priority_set", psutil_proc_priority_set, METH_VARARGS, - "Set process priority."}, - {"proc_io_priority_get", psutil_proc_io_priority_get, METH_VARARGS, - "Return process IO priority."}, - {"proc_io_priority_set", psutil_proc_io_priority_set, METH_VARARGS, - "Set process IO priority."}, - {"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS, - "Return process CPU affinity as a bitmask."}, - {"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS, - "Set process CPU affinity."}, - {"proc_io_counters", psutil_proc_io_counters, METH_VARARGS, - "Get process I/O counters."}, - {"proc_is_suspended", psutil_proc_is_suspended, METH_VARARGS, - "Return True if one of the process threads is in a suspended state"}, - {"proc_num_handles", psutil_proc_num_handles, METH_VARARGS, - "Return the number of handles opened by process."}, - {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS, - "Return a list of process's memory mappings"}, - - // --- alternative pinfo interface - {"proc_info", psutil_proc_info, METH_VARARGS, - "Various process information"}, - - // --- system-related functions - {"pids", psutil_pids, METH_VARARGS, - "Returns a list of PIDs currently running on the system"}, - {"ppid_map", psutil_ppid_map, METH_VARARGS, - "Return a {pid:ppid, ...} dict for all running processes"}, - {"pid_exists", psutil_pid_exists, METH_VARARGS, - "Determine if the process exists in the current process list."}, - {"cpu_count_logical", psutil_cpu_count_logical, METH_VARARGS, - "Returns the number of logical CPUs on the system"}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Returns the number of physical CPUs on the system"}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return the system boot time expressed in seconds since the epoch."}, - {"virtual_mem", psutil_virtual_mem, METH_VARARGS, - "Return the total amount of physical memory, in bytes"}, - {"cpu_times", psutil_cpu_times, METH_VARARGS, - "Return system cpu times as a list"}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-cpu times as a list of tuples"}, - {"disk_usage", psutil_disk_usage, METH_VARARGS, - "Return path's disk total and free as a Python tuple."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return dict of tuples of networks I/O information."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return dict of tuples of disks I/O information."}, - {"users", psutil_users, METH_VARARGS, - "Return a list of currently connected users."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return disk partitions."}, - {"net_connections", psutil_net_connections, METH_VARARGS, - "Return system-wide connections"}, - {"net_if_addrs", psutil_net_if_addrs, METH_VARARGS, - "Return NICs addresses."}, - {"net_if_stats", psutil_net_if_stats, METH_VARARGS, - "Return NICs stats."}, - {"cpu_stats", psutil_cpu_stats, METH_VARARGS, - "Return NICs stats."}, - {"cpu_freq", psutil_cpu_freq, METH_VARARGS, - "Return CPU frequency."}, - {"init_loadavg_counter", (PyCFunction)psutil_init_loadavg_counter, - METH_VARARGS, - "Initializes the emulated load average calculator."}, - {"getloadavg", (PyCFunction)psutil_get_loadavg, METH_VARARGS, - "Returns the emulated POSIX-like load average."}, - {"sensors_battery", psutil_sensors_battery, METH_VARARGS, - "Return battery metrics usage."}, - {"getpagesize", psutil_getpagesize, METH_VARARGS, - "Return system memory page size."}, - - // --- windows services - {"winservice_enumerate", psutil_winservice_enumerate, METH_VARARGS, - "List all services"}, - {"winservice_query_config", psutil_winservice_query_config, METH_VARARGS, - "Return service config"}, - {"winservice_query_status", psutil_winservice_query_status, METH_VARARGS, - "Return service config"}, - {"winservice_query_descr", psutil_winservice_query_descr, METH_VARARGS, - "Return the description of a service"}, - {"winservice_start", psutil_winservice_start, METH_VARARGS, - "Start a service"}, - {"winservice_stop", psutil_winservice_stop, METH_VARARGS, - "Stop a service"}, - - // --- windows API bindings - {"win32_QueryDosDevice", psutil_win32_QueryDosDevice, METH_VARARGS, - "QueryDosDevice binding"}, - - // --- others - {"set_testing", psutil_set_testing, METH_NOARGS, - "Set psutil in testing mode"}, - - {NULL, NULL, 0, NULL} -}; - - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -static struct module_state _state; -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int psutil_windows_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int psutil_windows_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_windows", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_windows_traverse, - psutil_windows_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_windows(void) - -#else -#define INITERROR return -void init_psutil_windows(void) -#endif -{ - struct module_state *st = NULL; -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_windows", PsutilMethods); -#endif - if (module == NULL) - INITERROR; - - if (psutil_setup() != 0) - INITERROR; - if (psutil_load_globals() != 0) - INITERROR; - if (psutil_set_se_debug() != 0) - INITERROR; - - st = GETSTATE(module); - st->error = PyErr_NewException("_psutil_windows.Error", NULL, NULL); - if (st->error == NULL) { - Py_DECREF(module); - INITERROR; - } - - // Exceptions. - TimeoutExpired = PyErr_NewException( - "_psutil_windows.TimeoutExpired", NULL, NULL); - Py_INCREF(TimeoutExpired); - PyModule_AddObject(module, "TimeoutExpired", TimeoutExpired); - - TimeoutAbandoned = PyErr_NewException( - "_psutil_windows.TimeoutAbandoned", NULL, NULL); - Py_INCREF(TimeoutAbandoned); - PyModule_AddObject(module, "TimeoutAbandoned", TimeoutAbandoned); - - // version constant - PyModule_AddIntConstant(module, "version", PSUTIL_VERSION); - - // process status constants - // http://msdn.microsoft.com/en-us/library/ms683211(v=vs.85).aspx - PyModule_AddIntConstant( - module, "ABOVE_NORMAL_PRIORITY_CLASS", ABOVE_NORMAL_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "BELOW_NORMAL_PRIORITY_CLASS", BELOW_NORMAL_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "HIGH_PRIORITY_CLASS", HIGH_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "IDLE_PRIORITY_CLASS", IDLE_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "NORMAL_PRIORITY_CLASS", NORMAL_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "REALTIME_PRIORITY_CLASS", REALTIME_PRIORITY_CLASS); - - // connection status constants - // http://msdn.microsoft.com/en-us/library/cc669305.aspx - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_CLOSED", MIB_TCP_STATE_CLOSED); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_CLOSING", MIB_TCP_STATE_CLOSING); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_CLOSE_WAIT", MIB_TCP_STATE_CLOSE_WAIT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_LISTEN", MIB_TCP_STATE_LISTEN); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_ESTAB", MIB_TCP_STATE_ESTAB); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_SYN_SENT", MIB_TCP_STATE_SYN_SENT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_SYN_RCVD", MIB_TCP_STATE_SYN_RCVD); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_FIN_WAIT1", MIB_TCP_STATE_FIN_WAIT1); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_FIN_WAIT2", MIB_TCP_STATE_FIN_WAIT2); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_LAST_ACK", MIB_TCP_STATE_LAST_ACK); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_TIME_WAIT", MIB_TCP_STATE_TIME_WAIT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_TIME_WAIT", MIB_TCP_STATE_TIME_WAIT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_DELETE_TCB", MIB_TCP_STATE_DELETE_TCB); - PyModule_AddIntConstant( - module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE); - - // service status constants - /* - PyModule_AddIntConstant( - module, "SERVICE_CONTINUE_PENDING", SERVICE_CONTINUE_PENDING); - PyModule_AddIntConstant( - module, "SERVICE_PAUSE_PENDING", SERVICE_PAUSE_PENDING); - PyModule_AddIntConstant( - module, "SERVICE_PAUSED", SERVICE_PAUSED); - PyModule_AddIntConstant( - module, "SERVICE_RUNNING", SERVICE_RUNNING); - PyModule_AddIntConstant( - module, "SERVICE_START_PENDING", SERVICE_START_PENDING); - PyModule_AddIntConstant( - module, "SERVICE_STOP_PENDING", SERVICE_STOP_PENDING); - PyModule_AddIntConstant( - module, "SERVICE_STOPPED", SERVICE_STOPPED); - */ - - // ...for internal use in _psutil_windows.py - PyModule_AddIntConstant( - module, "INFINITE", INFINITE); - PyModule_AddIntConstant( - module, "ERROR_ACCESS_DENIED", ERROR_ACCESS_DENIED); - PyModule_AddIntConstant( - module, "ERROR_INVALID_NAME", ERROR_INVALID_NAME); - PyModule_AddIntConstant( - module, "ERROR_SERVICE_DOES_NOT_EXIST", ERROR_SERVICE_DOES_NOT_EXIST); - PyModule_AddIntConstant( - module, "ERROR_PRIVILEGE_NOT_HELD", ERROR_PRIVILEGE_NOT_HELD); - PyModule_AddIntConstant( - module, "WINVER", PSUTIL_WINVER); - PyModule_AddIntConstant( - module, "WINDOWS_VISTA", PSUTIL_WINDOWS_VISTA); - PyModule_AddIntConstant( - module, "WINDOWS_7", PSUTIL_WINDOWS_7); - PyModule_AddIntConstant( - module, "WINDOWS_8", PSUTIL_WINDOWS_8); - PyModule_AddIntConstant( - module, "WINDOWS_8_1", PSUTIL_WINDOWS_8_1); - PyModule_AddIntConstant( - module, "WINDOWS_10", PSUTIL_WINDOWS_10); - -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/third_party/python/psutil/psutil/_pswindows.py b/third_party/python/psutil/psutil/_pswindows.py deleted file mode 100644 index 99d5d71499ba..000000000000 --- a/third_party/python/psutil/psutil/_pswindows.py +++ /dev/null @@ -1,1105 +0,0 @@ -# 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. - -"""Windows platform implementation.""" - -import contextlib -import errno -import functools -import os -import signal -import sys -import time -from collections import namedtuple - -from . import _common -from ._common import AccessDenied -from ._common import conn_tmap -from ._common import conn_to_ntuple -from ._common import debug -from ._common import ENCODING -from ._common import ENCODING_ERRS -from ._common import isfile_strict -from ._common import memoize -from ._common import memoize_when_activated -from ._common import NoSuchProcess -from ._common import parse_environ_block -from ._common import TimeoutExpired -from ._common import usage_percent -from ._compat import long -from ._compat import lru_cache -from ._compat import PY3 -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 -from ._psutil_windows import IDLE_PRIORITY_CLASS -from ._psutil_windows import NORMAL_PRIORITY_CLASS -from ._psutil_windows import REALTIME_PRIORITY_CLASS - -try: - from . import _psutil_windows as cext -except ImportError as err: - if str(err).lower().startswith("dll load failed") and \ - sys.getwindowsversion()[0] < 6: - # We may get here if: - # 1) we are on an old Windows version - # 2) psutil was installed via pip + wheel - # See: https://github.com/giampaolo/psutil/issues/811 - msg = "this Windows version is too old (< Windows Vista); " - msg += "psutil 3.4.2 is the latest version which supports Windows " - msg += "2000, XP and 2003 server" - raise RuntimeError(msg) - else: - raise - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - -# process priority constants, import from __init__.py: -# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx -__extra__all__ = [ - "win_service_iter", "win_service_get", - # Process priority - "ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS", - "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS", "NORMAL_PRIORITY_CLASS", - "REALTIME_PRIORITY_CLASS", - # IO priority - "IOPRIO_VERYLOW", "IOPRIO_LOW", "IOPRIO_NORMAL", "IOPRIO_HIGH", - # others - "CONN_DELETE_TCB", "AF_LINK", -] - - -# ===================================================================== -# --- globals -# ===================================================================== - -CONN_DELETE_TCB = "DELETE_TCB" -ERROR_PARTIAL_COPY = 299 -PYPY = '__pypy__' in sys.builtin_module_names - -if enum is None: - AF_LINK = -1 -else: - AddressFamily = enum.IntEnum('AddressFamily', {'AF_LINK': -1}) - AF_LINK = AddressFamily.AF_LINK - -TCP_STATUSES = { - cext.MIB_TCP_STATE_ESTAB: _common.CONN_ESTABLISHED, - cext.MIB_TCP_STATE_SYN_SENT: _common.CONN_SYN_SENT, - cext.MIB_TCP_STATE_SYN_RCVD: _common.CONN_SYN_RECV, - cext.MIB_TCP_STATE_FIN_WAIT1: _common.CONN_FIN_WAIT1, - cext.MIB_TCP_STATE_FIN_WAIT2: _common.CONN_FIN_WAIT2, - cext.MIB_TCP_STATE_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.MIB_TCP_STATE_CLOSED: _common.CONN_CLOSE, - cext.MIB_TCP_STATE_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.MIB_TCP_STATE_LAST_ACK: _common.CONN_LAST_ACK, - cext.MIB_TCP_STATE_LISTEN: _common.CONN_LISTEN, - cext.MIB_TCP_STATE_CLOSING: _common.CONN_CLOSING, - cext.MIB_TCP_STATE_DELETE_TCB: CONN_DELETE_TCB, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -if enum is not None: - class Priority(enum.IntEnum): - ABOVE_NORMAL_PRIORITY_CLASS = ABOVE_NORMAL_PRIORITY_CLASS - BELOW_NORMAL_PRIORITY_CLASS = BELOW_NORMAL_PRIORITY_CLASS - HIGH_PRIORITY_CLASS = HIGH_PRIORITY_CLASS - IDLE_PRIORITY_CLASS = IDLE_PRIORITY_CLASS - NORMAL_PRIORITY_CLASS = NORMAL_PRIORITY_CLASS - REALTIME_PRIORITY_CLASS = REALTIME_PRIORITY_CLASS - - globals().update(Priority.__members__) - -if enum is None: - IOPRIO_VERYLOW = 0 - IOPRIO_LOW = 1 - IOPRIO_NORMAL = 2 - IOPRIO_HIGH = 3 -else: - class IOPriority(enum.IntEnum): - IOPRIO_VERYLOW = 0 - IOPRIO_LOW = 1 - IOPRIO_NORMAL = 2 - IOPRIO_HIGH = 3 - globals().update(IOPriority.__members__) - -pinfo_map = dict( - num_handles=0, - ctx_switches=1, - user_time=2, - kernel_time=3, - create_time=4, - num_threads=5, - io_rcount=6, - io_wcount=7, - io_rbytes=8, - io_wbytes=9, - io_count_others=10, - io_bytes_others=11, - num_page_faults=12, - peak_wset=13, - wset=14, - peak_paged_pool=15, - paged_pool=16, - peak_non_paged_pool=17, - non_paged_pool=18, - pagefile=19, - peak_pagefile=20, - mem_private=21, -) - - -# ===================================================================== -# --- named tuples -# ===================================================================== - - -# psutil.cpu_times() -scputimes = namedtuple('scputimes', - ['user', 'system', 'idle', 'interrupt', 'dpc']) -# psutil.virtual_memory() -svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) -# psutil.Process.memory_info() -pmem = namedtuple( - 'pmem', ['rss', 'vms', - 'num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool', - 'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool', - 'pagefile', 'peak_pagefile', 'private']) -# psutil.Process.memory_full_info() -pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', )) -# psutil.Process.memory_maps(grouped=True) -pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss']) -# psutil.Process.memory_maps(grouped=False) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) -# psutil.Process.io_counters() -pio = namedtuple('pio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'other_count', 'other_bytes']) - - -# ===================================================================== -# --- utils -# ===================================================================== - - -@lru_cache(maxsize=512) -def convert_dos_path(s): - r"""Convert paths using native DOS format like: - "\Device\HarddiskVolume1\Windows\systemew\file.txt" - into: - "C:\Windows\systemew\file.txt" - """ - rawdrive = '\\'.join(s.split('\\')[:3]) - driveletter = cext.win32_QueryDosDevice(rawdrive) - remainder = s[len(rawdrive):] - return os.path.join(driveletter, remainder) - - -def py2_strencode(s): - """Encode a unicode string to a byte string by using the default fs - encoding + "replace" error handler. - """ - if PY3: - return s - else: - if isinstance(s, str): - return s - else: - return s.encode(ENCODING, ENCODING_ERRS) - - -@memoize -def getpagesize(): - return cext.getpagesize() - - -# ===================================================================== -# --- memory -# ===================================================================== - - -def virtual_memory(): - """System virtual memory as a namedtuple.""" - mem = cext.virtual_mem() - totphys, availphys, totpagef, availpagef, totvirt, freevirt = mem - # - total = totphys - avail = availphys - free = availphys - used = total - avail - percent = usage_percent((total - avail), total, round_=1) - return svmem(total, avail, percent, used, free) - - -def swap_memory(): - """Swap system memory as a (total, used, free, sin, sout) tuple.""" - mem = cext.virtual_mem() - total = mem[2] - free = mem[3] - used = total - free - percent = usage_percent(used, total, round_=1) - return _common.sswap(total, used, free, percent, 0, 0) - - -# ===================================================================== -# --- disk -# ===================================================================== - - -disk_io_counters = cext.disk_io_counters - - -def disk_usage(path): - """Return disk usage associated with path.""" - if PY3 and isinstance(path, bytes): - # XXX: do we want to use "strict"? Probably yes, in order - # to fail immediately. After all we are accepting input here... - path = path.decode(ENCODING, errors="strict") - total, free = cext.disk_usage(path) - used = total - free - percent = usage_percent(used, total, round_=1) - return _common.sdiskusage(total, used, free, percent) - - -def disk_partitions(all): - """Return disk partitions.""" - rawlist = cext.disk_partitions(all) - return [_common.sdiskpart(*x) for x in rawlist] - - -# ===================================================================== -# --- CPU -# ===================================================================== - - -def cpu_times(): - """Return system CPU times as a named tuple.""" - user, system, idle = cext.cpu_times() - # Internally, GetSystemTimes() is used, and it doesn't return - # interrupt and dpc times. cext.per_cpu_times() does, so we - # rely on it to get those only. - percpu_summed = scputimes(*[sum(n) for n in zip(*cext.per_cpu_times())]) - return scputimes(user, system, idle, - percpu_summed.interrupt, percpu_summed.dpc) - - -def per_cpu_times(): - """Return system per-CPU times as a list of named tuples.""" - ret = [] - for user, system, idle, interrupt, dpc in cext.per_cpu_times(): - item = scputimes(user, system, idle, interrupt, dpc) - ret.append(item) - return ret - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - return cext.cpu_count_logical() - - -def cpu_count_physical(): - """Return the number of physical CPU cores in the system.""" - return cext.cpu_count_phys() - - -def cpu_stats(): - """Return CPU statistics.""" - ctx_switches, interrupts, dpcs, syscalls = cext.cpu_stats() - soft_interrupts = 0 - return _common.scpustats(ctx_switches, interrupts, soft_interrupts, - syscalls) - - -def cpu_freq(): - """Return CPU frequency. - On Windows per-cpu frequency is not supported. - """ - curr, max_ = cext.cpu_freq() - min_ = 0.0 - return [_common.scpufreq(float(curr), min_, float(max_))] - - -_loadavg_inititialized = False - - -def getloadavg(): - """Return the number of processes in the system run queue averaged - over the last 1, 5, and 15 minutes respectively as a tuple""" - global _loadavg_inititialized - - if not _loadavg_inititialized: - cext.init_loadavg_counter() - _loadavg_inititialized = True - - # Drop to 2 decimal points which is what Linux does - raw_loads = cext.getloadavg() - return tuple([round(load, 2) for load in raw_loads]) - - -# ===================================================================== -# --- network -# ===================================================================== - - -def net_connections(kind, _pid=-1): - """Return socket connections. If pid == -1 return system-wide - connections (as opposed to connections opened by one process only). - """ - if kind not in conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - families, types = conn_tmap[kind] - rawlist = cext.net_connections(_pid, families, types) - ret = set() - for item in rawlist: - fd, fam, type, laddr, raddr, status, pid = item - nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, TCP_STATUSES, - pid=pid if _pid == -1 else None) - ret.add(nt) - return list(ret) - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - ret = {} - rawdict = cext.net_if_stats() - for name, items in rawdict.items(): - if not PY3: - assert isinstance(name, unicode), type(name) - name = py2_strencode(name) - isup, duplex, speed, mtu = items - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -def net_io_counters(): - """Return network I/O statistics for every network interface - installed on the system as a dict of raw tuples. - """ - ret = cext.net_io_counters() - return dict([(py2_strencode(k), v) for k, v in ret.items()]) - - -def net_if_addrs(): - """Return the addresses associated to each NIC.""" - ret = [] - for items in cext.net_if_addrs(): - items = list(items) - items[0] = py2_strencode(items[0]) - ret.append(items) - return ret - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -def sensors_battery(): - """Return battery information.""" - # For constants meaning see: - # https://msdn.microsoft.com/en-us/library/windows/desktop/ - # aa373232(v=vs.85).aspx - acline_status, flags, percent, secsleft = cext.sensors_battery() - power_plugged = acline_status == 1 - no_battery = bool(flags & 128) - charging = bool(flags & 8) - - if no_battery: - return None - if power_plugged or charging: - secsleft = _common.POWER_TIME_UNLIMITED - elif secsleft == -1: - secsleft = _common.POWER_TIME_UNKNOWN - - return _common.sbattery(percent, secsleft, power_plugged) - - -# ===================================================================== -# --- other system functions -# ===================================================================== - - -_last_btime = 0 - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - # This dirty hack is to adjust the precision of the returned - # value which may have a 1 second fluctuation, see: - # https://github.com/giampaolo/psutil/issues/1007 - global _last_btime - ret = float(cext.boot_time()) - if abs(ret - _last_btime) <= 1: - return _last_btime - else: - _last_btime = ret - return ret - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, hostname, tstamp = item - user = py2_strencode(user) - nt = _common.suser(user, None, hostname, tstamp, None) - retlist.append(nt) - return retlist - - -# ===================================================================== -# --- Windows services -# ===================================================================== - - -def win_service_iter(): - """Yields a list of WindowsService instances.""" - for name, display_name in cext.winservice_enumerate(): - yield WindowsService(py2_strencode(name), py2_strencode(display_name)) - - -def win_service_get(name): - """Open a Windows service and return it as a WindowsService instance.""" - service = WindowsService(name, None) - service._display_name = service._query_config()['display_name'] - return service - - -class WindowsService(object): - """Represents an installed Windows service.""" - - def __init__(self, name, display_name): - self._name = name - self._display_name = display_name - - def __str__(self): - details = "(name=%r, display_name=%r)" % ( - self._name, self._display_name) - return "%s%s" % (self.__class__.__name__, details) - - def __repr__(self): - return "<%s at %s>" % (self.__str__(), id(self)) - - def __eq__(self, other): - # Test for equality with another WindosService object based - # on name. - if not isinstance(other, WindowsService): - return NotImplemented - return self._name == other._name - - def __ne__(self, other): - return not self == other - - def _query_config(self): - with self._wrap_exceptions(): - display_name, binpath, username, start_type = \ - cext.winservice_query_config(self._name) - # XXX - update _self.display_name? - return dict( - display_name=py2_strencode(display_name), - binpath=py2_strencode(binpath), - username=py2_strencode(username), - start_type=py2_strencode(start_type)) - - def _query_status(self): - with self._wrap_exceptions(): - status, pid = cext.winservice_query_status(self._name) - if pid == 0: - pid = None - return dict(status=status, pid=pid) - - @contextlib.contextmanager - def _wrap_exceptions(self): - """Ctx manager which translates bare OSError and WindowsError - exceptions into NoSuchProcess and AccessDenied. - """ - try: - yield - except OSError as err: - if is_permission_err(err): - raise AccessDenied( - pid=None, name=self._name, - msg="service %r is not querable (not enough privileges)" % - self._name) - elif err.winerror in (cext.ERROR_INVALID_NAME, - cext.ERROR_SERVICE_DOES_NOT_EXIST): - raise NoSuchProcess( - pid=None, name=self._name, - msg="service %r does not exist)" % self._name) - else: - raise - - # config query - - def name(self): - """The service name. This string is how a service is referenced - and can be passed to win_service_get() to get a new - WindowsService instance. - """ - return self._name - - def display_name(self): - """The service display name. The value is cached when this class - is instantiated. - """ - return self._display_name - - def binpath(self): - """The fully qualified path to the service binary/exe file as - a string, including command line arguments. - """ - return self._query_config()['binpath'] - - def username(self): - """The name of the user that owns this service.""" - return self._query_config()['username'] - - def start_type(self): - """A string which can either be "automatic", "manual" or - "disabled". - """ - return self._query_config()['start_type'] - - # status query - - def pid(self): - """The process PID, if any, else None. This can be passed - to Process class to control the service's process. - """ - return self._query_status()['pid'] - - def status(self): - """Service status as a string.""" - return self._query_status()['status'] - - def description(self): - """Service long description.""" - return py2_strencode(cext.winservice_query_descr(self.name())) - - # utils - - def as_dict(self): - """Utility method retrieving all the information above as a - dictionary. - """ - d = self._query_config() - d.update(self._query_status()) - d['name'] = self.name() - d['display_name'] = self.display_name() - d['description'] = self.description() - return d - - # actions - # XXX: the necessary C bindings for start() and stop() are - # implemented but for now I prefer not to expose them. - # I may change my mind in the future. Reasons: - # - they require Administrator privileges - # - can't implement a timeout for stop() (unless by using a thread, - # which sucks) - # - would require adding ServiceAlreadyStarted and - # ServiceAlreadyStopped exceptions, adding two new APIs. - # - we might also want to have modify(), which would basically mean - # rewriting win32serviceutil.ChangeServiceConfig, which involves a - # lot of stuff (and API constants which would pollute the API), see: - # http://pyxr.sourceforge.net/PyXR/c/python24/lib/site-packages/ - # win32/lib/win32serviceutil.py.html#0175 - # - psutil is typically about "read only" monitoring stuff; - # win_service_* APIs should only be used to retrieve a service and - # check whether it's running - - # def start(self, timeout=None): - # with self._wrap_exceptions(): - # cext.winservice_start(self.name()) - # if timeout: - # giveup_at = time.time() + timeout - # while True: - # if self.status() == "running": - # return - # else: - # if time.time() > giveup_at: - # raise TimeoutExpired(timeout) - # else: - # time.sleep(.1) - - # def stop(self): - # # Note: timeout is not implemented because it's just not - # # possible, see: - # # http://stackoverflow.com/questions/11973228/ - # with self._wrap_exceptions(): - # return cext.winservice_stop(self.name()) - - -# ===================================================================== -# --- processes -# ===================================================================== - - -pids = cext.pids -pid_exists = cext.pid_exists -ppid_map = cext.ppid_map # used internally by Process.children() - - -def is_permission_err(exc): - """Return True if this is a permission error.""" - assert isinstance(exc, OSError), exc - # On Python 2 OSError doesn't always have 'winerror'. Sometimes - # it does, in which case the original exception was WindowsError - # (which is a subclass of OSError). - return exc.errno in (errno.EPERM, errno.EACCES) or \ - getattr(exc, "winerror", -1) in (cext.ERROR_ACCESS_DENIED, - cext.ERROR_PRIVILEGE_NOT_HELD) - - -def convert_oserror(exc, pid=None, name=None): - """Convert OSError into NoSuchProcess or AccessDenied.""" - assert isinstance(exc, OSError), exc - if is_permission_err(exc): - return AccessDenied(pid=pid, name=name) - if exc.errno == errno.ESRCH: - return NoSuchProcess(pid=pid, name=name) - raise exc - - -def wrap_exceptions(fun): - """Decorator which converts OSError into NoSuchProcess or AccessDenied.""" - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except OSError as err: - raise convert_oserror(err, pid=self.pid, name=self._name) - return wrapper - - -def retry_error_partial_copy(fun): - """Workaround for https://github.com/giampaolo/psutil/issues/875. - See: https://stackoverflow.com/questions/4457745#4457745 - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - delay = 0.0001 - times = 33 - for x in range(times): # retries for roughly 1 second - try: - return fun(self, *args, **kwargs) - except WindowsError as _: - err = _ - if err.winerror == ERROR_PARTIAL_COPY: - time.sleep(delay) - delay = min(delay * 2, 0.04) - continue - else: - raise - else: - msg = "%s retried %s times, converted to AccessDenied as it's " \ - "still returning %r" % (fun, times, err) - raise AccessDenied(pid=self.pid, name=self._name, msg=msg) - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid", "_cache"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - # --- oneshot() stuff - - def oneshot_enter(self): - self._proc_info.cache_activate(self) - self.exe.cache_activate(self) - - def oneshot_exit(self): - self._proc_info.cache_deactivate(self) - self.exe.cache_deactivate(self) - - @memoize_when_activated - def _proc_info(self): - """Return multiple information about this process as a - raw tuple. - """ - ret = cext.proc_info(self.pid) - assert len(ret) == len(pinfo_map) - return ret - - def name(self): - """Return process name, which on Windows is always the final - part of the executable. - """ - # This is how PIDs 0 and 4 are always represented in taskmgr - # and process-hacker. - if self.pid == 0: - return "System Idle Process" - if self.pid == 4: - return "System" - return os.path.basename(self.exe()) - - @wrap_exceptions - @memoize_when_activated - def exe(self): - if PYPY: - try: - exe = cext.proc_exe(self.pid) - except WindowsError as err: - # 24 = ERROR_TOO_MANY_OPEN_FILES. Not sure why this happens - # (perhaps PyPy's JIT delaying garbage collection of files?). - if err.errno == 24: - debug("%r forced into AccessDenied" % err) - raise AccessDenied(self.pid, self._name) - raise - else: - exe = cext.proc_exe(self.pid) - if not PY3: - exe = py2_strencode(exe) - if exe.startswith('\\'): - return convert_dos_path(exe) - return exe # May be "Registry", "MemCompression", ... - - @wrap_exceptions - @retry_error_partial_copy - def cmdline(self): - if cext.WINVER >= cext.WINDOWS_8_1: - # PEB method detects cmdline changes but requires more - # privileges: https://github.com/giampaolo/psutil/pull/1398 - try: - ret = cext.proc_cmdline(self.pid, use_peb=True) - except OSError as err: - if is_permission_err(err): - ret = cext.proc_cmdline(self.pid, use_peb=False) - else: - raise - else: - ret = cext.proc_cmdline(self.pid, use_peb=True) - if PY3: - return ret - else: - return [py2_strencode(s) for s in ret] - - @wrap_exceptions - @retry_error_partial_copy - def environ(self): - ustr = cext.proc_environ(self.pid) - if ustr and not PY3: - assert isinstance(ustr, unicode), type(ustr) - return parse_environ_block(py2_strencode(ustr)) - - def ppid(self): - try: - return ppid_map()[self.pid] - except KeyError: - raise NoSuchProcess(self.pid, self._name) - - def _get_raw_meminfo(self): - try: - return cext.proc_memory_info(self.pid) - except OSError as err: - if is_permission_err(err): - # TODO: the C ext can probably be refactored in order - # to get this from cext.proc_info() - info = self._proc_info() - return ( - info[pinfo_map['num_page_faults']], - info[pinfo_map['peak_wset']], - info[pinfo_map['wset']], - info[pinfo_map['peak_paged_pool']], - info[pinfo_map['paged_pool']], - info[pinfo_map['peak_non_paged_pool']], - info[pinfo_map['non_paged_pool']], - info[pinfo_map['pagefile']], - info[pinfo_map['peak_pagefile']], - info[pinfo_map['mem_private']], - ) - raise - - @wrap_exceptions - def memory_info(self): - # on Windows RSS == WorkingSetSize and VSM == PagefileUsage. - # Underlying C function returns fields of PROCESS_MEMORY_COUNTERS - # struct. - t = self._get_raw_meminfo() - rss = t[2] # wset - vms = t[7] # pagefile - return pmem(*(rss, vms, ) + t) - - @wrap_exceptions - def memory_full_info(self): - basic_mem = self.memory_info() - uss = cext.proc_memory_uss(self.pid) - uss *= getpagesize() - return pfullmem(*basic_mem + (uss, )) - - def memory_maps(self): - try: - raw = cext.proc_memory_maps(self.pid) - except OSError as err: - # XXX - can't use wrap_exceptions decorator as we're - # returning a generator; probably needs refactoring. - raise convert_oserror(err, self.pid, self._name) - else: - for addr, perm, path, rss in raw: - path = convert_dos_path(path) - if not PY3: - path = py2_strencode(path) - addr = hex(addr) - yield (addr, perm, path, rss) - - @wrap_exceptions - def kill(self): - return cext.proc_kill(self.pid) - - @wrap_exceptions - def send_signal(self, sig): - if sig == signal.SIGTERM: - cext.proc_kill(self.pid) - # py >= 2.7 - elif sig in (getattr(signal, "CTRL_C_EVENT", object()), - getattr(signal, "CTRL_BREAK_EVENT", object())): - os.kill(self.pid, sig) - else: - raise ValueError( - "only SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals " - "are supported on Windows") - - @wrap_exceptions - def wait(self, timeout=None): - if timeout is None: - cext_timeout = cext.INFINITE - else: - # WaitForSingleObject() expects time in milliseconds. - cext_timeout = int(timeout * 1000) - - timer = getattr(time, 'monotonic', time.time) - stop_at = timer() + timeout if timeout is not None else None - - try: - # Exit code is supposed to come from GetExitCodeProcess(). - # May also be None if OpenProcess() failed with - # ERROR_INVALID_PARAMETER, meaning PID is already gone. - exit_code = cext.proc_wait(self.pid, cext_timeout) - except cext.TimeoutExpired: - # WaitForSingleObject() returned WAIT_TIMEOUT. Just raise. - raise TimeoutExpired(timeout, self.pid, self._name) - except cext.TimeoutAbandoned: - # WaitForSingleObject() returned WAIT_ABANDONED, see: - # https://github.com/giampaolo/psutil/issues/1224 - # We'll just rely on the internal polling and return None - # when the PID disappears. Subprocess module does the same - # (return None): - # https://github.com/python/cpython/blob/ - # be50a7b627d0aa37e08fa8e2d5568891f19903ce/ - # Lib/subprocess.py#L1193-L1194 - exit_code = None - - # At this point WaitForSingleObject() returned WAIT_OBJECT_0, - # meaning the process is gone. Stupidly there are cases where - # its PID may still stick around so we do a further internal - # polling. - delay = 0.0001 - while True: - if not pid_exists(self.pid): - return exit_code - if stop_at and timer() >= stop_at: - raise TimeoutExpired(timeout, pid=self.pid, name=self._name) - time.sleep(delay) - delay = min(delay * 2, 0.04) # incremental delay - - @wrap_exceptions - def username(self): - if self.pid in (0, 4): - return 'NT AUTHORITY\\SYSTEM' - domain, user = cext.proc_username(self.pid) - return py2_strencode(domain) + '\\' + py2_strencode(user) - - @wrap_exceptions - def create_time(self): - # Note: proc_times() not put under oneshot() 'cause create_time() - # is already cached by the main Process class. - try: - user, system, created = cext.proc_times(self.pid) - return created - except OSError as err: - if is_permission_err(err): - return self._proc_info()[pinfo_map['create_time']] - raise - - @wrap_exceptions - def num_threads(self): - return self._proc_info()[pinfo_map['num_threads']] - - @wrap_exceptions - def threads(self): - rawlist = cext.proc_threads(self.pid) - retlist = [] - for thread_id, utime, stime in rawlist: - ntuple = _common.pthread(thread_id, utime, stime) - retlist.append(ntuple) - return retlist - - @wrap_exceptions - def cpu_times(self): - try: - user, system, created = cext.proc_times(self.pid) - except OSError as err: - if not is_permission_err(err): - raise - info = self._proc_info() - user = info[pinfo_map['user_time']] - system = info[pinfo_map['kernel_time']] - # Children user/system times are not retrievable (set to 0). - return _common.pcputimes(user, system, 0.0, 0.0) - - @wrap_exceptions - def suspend(self): - cext.proc_suspend_or_resume(self.pid, True) - - @wrap_exceptions - def resume(self): - cext.proc_suspend_or_resume(self.pid, False) - - @wrap_exceptions - @retry_error_partial_copy - def cwd(self): - if self.pid in (0, 4): - raise AccessDenied(self.pid, self._name) - # return a normalized pathname since the native C function appends - # "\\" at the and of the path - path = cext.proc_cwd(self.pid) - return py2_strencode(os.path.normpath(path)) - - @wrap_exceptions - def open_files(self): - if self.pid in (0, 4): - return [] - ret = set() - # Filenames come in in native format like: - # "\Device\HarddiskVolume1\Windows\systemew\file.txt" - # Convert the first part in the corresponding drive letter - # (e.g. "C:\") by using Windows's QueryDosDevice() - raw_file_names = cext.proc_open_files(self.pid) - for _file in raw_file_names: - _file = convert_dos_path(_file) - if isfile_strict(_file): - if not PY3: - _file = py2_strencode(_file) - ntuple = _common.popenfile(_file, -1) - ret.add(ntuple) - return list(ret) - - @wrap_exceptions - def connections(self, kind='inet'): - return net_connections(kind, _pid=self.pid) - - @wrap_exceptions - def nice_get(self): - value = cext.proc_priority_get(self.pid) - if enum is not None: - value = Priority(value) - return value - - @wrap_exceptions - def nice_set(self, value): - return cext.proc_priority_set(self.pid, value) - - @wrap_exceptions - def ionice_get(self): - ret = cext.proc_io_priority_get(self.pid) - if enum is not None: - ret = IOPriority(ret) - return ret - - @wrap_exceptions - def ionice_set(self, ioclass, value): - if value: - raise TypeError("value argument not accepted on Windows") - if ioclass not in (IOPRIO_VERYLOW, IOPRIO_LOW, IOPRIO_NORMAL, - IOPRIO_HIGH): - raise ValueError("%s is not a valid priority" % ioclass) - cext.proc_io_priority_set(self.pid, ioclass) - - @wrap_exceptions - def io_counters(self): - try: - ret = cext.proc_io_counters(self.pid) - except OSError as err: - if not is_permission_err(err): - raise - info = self._proc_info() - ret = ( - info[pinfo_map['io_rcount']], - info[pinfo_map['io_wcount']], - info[pinfo_map['io_rbytes']], - info[pinfo_map['io_wbytes']], - info[pinfo_map['io_count_others']], - info[pinfo_map['io_bytes_others']], - ) - return pio(*ret) - - @wrap_exceptions - def status(self): - suspended = cext.proc_is_suspended(self.pid) - if suspended: - return _common.STATUS_STOPPED - else: - return _common.STATUS_RUNNING - - @wrap_exceptions - def cpu_affinity_get(self): - def from_bitmask(x): - return [i for i in xrange(64) if (1 << i) & x] - bitmask = cext.proc_cpu_affinity_get(self.pid) - return from_bitmask(bitmask) - - @wrap_exceptions - def cpu_affinity_set(self, value): - def to_bitmask(l): - if not l: - raise ValueError("invalid argument %r" % l) - out = 0 - for b in l: - out |= 2 ** b - return out - - # SetProcessAffinityMask() states that ERROR_INVALID_PARAMETER - # is returned for an invalid CPU but this seems not to be true, - # therefore we check CPUs validy beforehand. - allcpus = list(range(len(per_cpu_times()))) - for cpu in value: - if cpu not in allcpus: - if not isinstance(cpu, (int, long)): - raise TypeError( - "invalid CPU %r; an integer is required" % cpu) - else: - raise ValueError("invalid CPU %r" % cpu) - - bitmask = to_bitmask(value) - cext.proc_cpu_affinity_set(self.pid, bitmask) - - @wrap_exceptions - def num_handles(self): - try: - return cext.proc_num_handles(self.pid) - except OSError as err: - if is_permission_err(err): - return self._proc_info()[pinfo_map['num_handles']] - raise - - @wrap_exceptions - def num_ctx_switches(self): - ctx_switches = self._proc_info()[pinfo_map['ctx_switches']] - # only voluntary ctx switches are supported - return _common.pctxsw(ctx_switches, 0) diff --git a/third_party/python/psutil/psutil/arch/aix/common.c b/third_party/python/psutil/psutil/arch/aix/common.c deleted file mode 100644 index 945cbd978b30..000000000000 --- a/third_party/python/psutil/psutil/arch/aix/common.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2017, Arnon Yaari - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include -#include -#include -#include "common.h" - -/* psutil_kread() - read from kernel memory */ -int -psutil_kread( - int Kd, /* kernel memory file descriptor */ - KA_T addr, /* kernel memory address */ - char *buf, /* buffer to receive data */ - size_t len) { /* length to read */ - int br; - - if (lseek64(Kd, (off64_t)addr, L_SET) == (off64_t)-1) { - PyErr_SetFromErrno(PyExc_OSError); - return 1; - } - br = read(Kd, buf, len); - if (br == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return 1; - } - if (br != len) { - PyErr_SetString(PyExc_RuntimeError, - "size mismatch when reading kernel memory fd"); - return 1; - } - return 0; -} - -struct procentry64 * -psutil_read_process_table(int * num) { - size_t msz; - pid32_t pid = 0; - struct procentry64 *processes = (struct procentry64 *)NULL; - struct procentry64 *p; - int Np = 0; /* number of processes allocated in 'processes' */ - int np = 0; /* number of processes read into 'processes' */ - int i; /* number of processes read in current iteration */ - - msz = (size_t)(PROCSIZE * PROCINFO_INCR); - processes = (struct procentry64 *)malloc(msz); - if (!processes) { - PyErr_NoMemory(); - return NULL; - } - Np = PROCINFO_INCR; - p = processes; - while ((i = getprocs64(p, PROCSIZE, (struct fdsinfo64 *)NULL, 0, &pid, - PROCINFO_INCR)) - == PROCINFO_INCR) { - np += PROCINFO_INCR; - if (np >= Np) { - msz = (size_t)(PROCSIZE * (Np + PROCINFO_INCR)); - processes = (struct procentry64 *)realloc((char *)processes, msz); - if (!processes) { - PyErr_NoMemory(); - return NULL; - } - Np += PROCINFO_INCR; - } - p = (struct procentry64 *)((char *)processes + (np * PROCSIZE)); - } - - /* add the number of processes read in the last iteration */ - if (i > 0) - np += i; - - *num = np; - return processes; -} diff --git a/third_party/python/psutil/psutil/arch/aix/common.h b/third_party/python/psutil/psutil/arch/aix/common.h deleted file mode 100644 index b677d8c29eed..000000000000 --- a/third_party/python/psutil/psutil/arch/aix/common.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2017, Arnon Yaari - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __PSUTIL_AIX_COMMON_H__ -#define __PSUTIL_AIX_COMMON_H__ - -#include - -#define PROCINFO_INCR (256) -#define PROCSIZE (sizeof(struct procentry64)) -#define FDSINFOSIZE (sizeof(struct fdsinfo64)) -#define KMEM "/dev/kmem" - -typedef u_longlong_t KA_T; - -/* psutil_kread() - read from kernel memory */ -int psutil_kread(int Kd, /* kernel memory file descriptor */ - KA_T addr, /* kernel memory address */ - char *buf, /* buffer to receive data */ - size_t len); /* length to read */ - -struct procentry64 * -psutil_read_process_table( - int * num /* out - number of processes read */ -); - -#endif /* __PSUTIL_AIX_COMMON_H__ */ diff --git a/third_party/python/psutil/psutil/arch/aix/ifaddrs.c b/third_party/python/psutil/psutil/arch/aix/ifaddrs.c deleted file mode 100644 index 1480b60fab2a..000000000000 --- a/third_party/python/psutil/psutil/arch/aix/ifaddrs.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2017, Arnon Yaari - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/*! Based on code from - https://lists.samba.org/archive/samba-technical/2009-February/063079.html -!*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ifaddrs.h" - -#define MAX(x,y) ((x)>(y)?(x):(y)) -#define SIZE(p) MAX((p).sa_len,sizeof(p)) - - -static struct sockaddr * -sa_dup(struct sockaddr *sa1) -{ - struct sockaddr *sa2; - size_t sz = sa1->sa_len; - sa2 = (struct sockaddr *) calloc(1, sz); - if (sa2 == NULL) - return NULL; - memcpy(sa2, sa1, sz); - return sa2; -} - - -void freeifaddrs(struct ifaddrs *ifp) -{ - if (NULL == ifp) return; - free(ifp->ifa_name); - free(ifp->ifa_addr); - free(ifp->ifa_netmask); - free(ifp->ifa_dstaddr); - freeifaddrs(ifp->ifa_next); - free(ifp); -} - - -int getifaddrs(struct ifaddrs **ifap) -{ - int sd, ifsize; - char *ccp, *ecp; - struct ifconf ifc; - struct ifreq *ifr; - struct ifaddrs *cifa = NULL; /* current */ - struct ifaddrs *pifa = NULL; /* previous */ - const size_t IFREQSZ = sizeof(struct ifreq); - int fam; - - *ifap = NULL; - - sd = socket(AF_INET, SOCK_DGRAM, 0); - if (sd == -1) - goto error; - - /* find how much memory to allocate for the SIOCGIFCONF call */ - if (ioctl(sd, SIOCGSIZIFCONF, (caddr_t)&ifsize) < 0) - goto error; - - ifc.ifc_req = (struct ifreq *) calloc(1, ifsize); - if (ifc.ifc_req == NULL) - goto error; - ifc.ifc_len = ifsize; - - if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) - goto error; - - ccp = (char *)ifc.ifc_req; - ecp = ccp + ifsize; - - while (ccp < ecp) { - - ifr = (struct ifreq *) ccp; - ifsize = sizeof(ifr->ifr_name) + SIZE(ifr->ifr_addr); - fam = ifr->ifr_addr.sa_family; - - if (fam == AF_INET || fam == AF_INET6) { - cifa = (struct ifaddrs *) calloc(1, sizeof(struct ifaddrs)); - if (cifa == NULL) - goto error; - cifa->ifa_next = NULL; - - if (pifa == NULL) *ifap = cifa; /* first one */ - else pifa->ifa_next = cifa; - - cifa->ifa_name = strdup(ifr->ifr_name); - if (cifa->ifa_name == NULL) - goto error; - cifa->ifa_flags = 0; - cifa->ifa_dstaddr = NULL; - - cifa->ifa_addr = sa_dup(&ifr->ifr_addr); - if (cifa->ifa_addr == NULL) - goto error; - - if (fam == AF_INET) { - if (ioctl(sd, SIOCGIFNETMASK, ifr, IFREQSZ) < 0) - goto error; - cifa->ifa_netmask = sa_dup(&ifr->ifr_addr); - if (cifa->ifa_netmask == NULL) - goto error; - } - - if (0 == ioctl(sd, SIOCGIFFLAGS, ifr)) /* optional */ - cifa->ifa_flags = ifr->ifr_flags; - - if (fam == AF_INET) { - if (ioctl(sd, SIOCGIFDSTADDR, ifr, IFREQSZ) < 0) { - if (0 == ioctl(sd, SIOCGIFBRDADDR, ifr, IFREQSZ)) { - cifa->ifa_dstaddr = sa_dup(&ifr->ifr_addr); - if (cifa->ifa_dstaddr == NULL) - goto error; - } - } - else { - cifa->ifa_dstaddr = sa_dup(&ifr->ifr_addr); - if (cifa->ifa_dstaddr == NULL) - goto error; - } - } - pifa = cifa; - } - - ccp += ifsize; - } - free(ifc.ifc_req); - close(sd); - return 0; -error: - if (ifc.ifc_req != NULL) - free(ifc.ifc_req); - if (sd != -1) - close(sd); - freeifaddrs(*ifap); - return (-1); -} diff --git a/third_party/python/psutil/psutil/arch/aix/ifaddrs.h b/third_party/python/psutil/psutil/arch/aix/ifaddrs.h deleted file mode 100644 index e15802bf7b21..000000000000 --- a/third_party/python/psutil/psutil/arch/aix/ifaddrs.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017, Arnon Yaari - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/*! Based on code from - https://lists.samba.org/archive/samba-technical/2009-February/063079.html -!*/ - - -#ifndef GENERIC_AIX_IFADDRS_H -#define GENERIC_AIX_IFADDRS_H - -#include -#include - -#undef ifa_dstaddr -#undef ifa_broadaddr -#define ifa_broadaddr ifa_dstaddr - -struct ifaddrs { - struct ifaddrs *ifa_next; - char *ifa_name; - unsigned int ifa_flags; - struct sockaddr *ifa_addr; - struct sockaddr *ifa_netmask; - struct sockaddr *ifa_dstaddr; -}; - -extern int getifaddrs(struct ifaddrs **); -extern void freeifaddrs(struct ifaddrs *); -#endif diff --git a/third_party/python/psutil/psutil/arch/aix/net_connections.c b/third_party/python/psutil/psutil/arch/aix/net_connections.c deleted file mode 100644 index 69b43892012e..000000000000 --- a/third_party/python/psutil/psutil/arch/aix/net_connections.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) 2017, Arnon Yaari - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Baded on code from lsof: - * http://www.ibm.com/developerworks/aix/library/au-lsof.html - * - dialects/aix/dproc.c:gather_proc_info - * - lib/prfp.c:process_file - * - dialects/aix/dsock.c:process_socket - * - dialects/aix/dproc.c:get_kernel_access -*/ - -#include -#include -#include -#define _KERNEL -#include -#undef _KERNEL -#include -#include -#include -#include -#include -#include - -#include "../../_psutil_common.h" -#include "net_kernel_structs.h" -#include "net_connections.h" -#include "common.h" - -#define NO_SOCKET (PyObject *)(-1) - -static int -read_unp_addr( - int Kd, - KA_T unp_addr, - char *buf, - size_t buflen -) { - struct sockaddr_un *ua = (struct sockaddr_un *)NULL; - struct sockaddr_un un; - struct mbuf64 mb; - int uo; - - if (psutil_kread(Kd, unp_addr, (char *)&mb, sizeof(mb))) { - return 1; - } - - uo = (int)(mb.m_hdr.mh_data - unp_addr); - if ((uo + sizeof(struct sockaddr)) <= sizeof(mb)) - ua = (struct sockaddr_un *)((char *)&mb + uo); - else { - if (psutil_kread(Kd, (KA_T)mb.m_hdr.mh_data, - (char *)&un, sizeof(un))) { - return 1; - } - ua = &un; - } - if (ua && ua->sun_path[0]) { - if (mb.m_len > sizeof(struct sockaddr_un)) - mb.m_len = sizeof(struct sockaddr_un); - *((char *)ua + mb.m_len - 1) = '\0'; - snprintf(buf, buflen, "%s", ua->sun_path); - } - return 0; -} - -static PyObject * -process_file(int Kd, pid32_t pid, int fd, KA_T fp) { - struct file64 f; - struct socket64 s; - struct protosw64 p; - struct domain d; - struct inpcb64 inp; - int fam; - struct tcpcb64 t; - int state = PSUTIL_CONN_NONE; - unsigned char *laddr = (unsigned char *)NULL; - unsigned char *raddr = (unsigned char *)NULL; - int rport, lport; - char laddr_str[INET6_ADDRSTRLEN]; - char raddr_str[INET6_ADDRSTRLEN]; - struct unpcb64 unp; - char unix_laddr_str[PATH_MAX] = { 0 }; - char unix_raddr_str[PATH_MAX] = { 0 }; - - /* Read file structure */ - if (psutil_kread(Kd, fp, (char *)&f, sizeof(f))) { - return NULL; - } - if (!f.f_count || f.f_type != DTYPE_SOCKET) { - return NO_SOCKET; - } - - if (psutil_kread(Kd, (KA_T) f.f_data, (char *) &s, sizeof(s))) { - return NULL; - } - - if (!s.so_type) { - return NO_SOCKET; - } - - if (!s.so_proto) { - PyErr_SetString(PyExc_RuntimeError, "invalid socket protocol handle"); - return NULL; - } - if (psutil_kread(Kd, (KA_T)s.so_proto, (char *)&p, sizeof(p))) { - return NULL; - } - - if (!p.pr_domain) { - PyErr_SetString(PyExc_RuntimeError, "invalid socket protocol domain"); - return NULL; - } - if (psutil_kread(Kd, (KA_T)p.pr_domain, (char *)&d, sizeof(d))) { - return NULL; - } - - fam = d.dom_family; - if (fam == AF_INET || fam == AF_INET6) { - /* Read protocol control block */ - if (!s.so_pcb) { - PyErr_SetString(PyExc_RuntimeError, "invalid socket PCB"); - return NULL; - } - if (psutil_kread(Kd, (KA_T) s.so_pcb, (char *) &inp, sizeof(inp))) { - return NULL; - } - - if (p.pr_protocol == IPPROTO_TCP) { - /* If this is a TCP socket, read its control block */ - if (inp.inp_ppcb - && !psutil_kread(Kd, (KA_T)inp.inp_ppcb, - (char *)&t, sizeof(t))) - state = t.t_state; - } - - if (fam == AF_INET6) { - laddr = (unsigned char *)&inp.inp_laddr6; - if (!IN6_IS_ADDR_UNSPECIFIED(&inp.inp_faddr6)) { - raddr = (unsigned char *)&inp.inp_faddr6; - rport = (int)ntohs(inp.inp_fport); - } - } - if (fam == AF_INET) { - laddr = (unsigned char *)&inp.inp_laddr; - if (inp.inp_faddr.s_addr != INADDR_ANY || inp.inp_fport != 0) { - raddr = (unsigned char *)&inp.inp_faddr; - rport = (int)ntohs(inp.inp_fport); - } - } - lport = (int)ntohs(inp.inp_lport); - - inet_ntop(fam, laddr, laddr_str, sizeof(laddr_str)); - - if (raddr != NULL) { - inet_ntop(fam, raddr, raddr_str, sizeof(raddr_str)); - return Py_BuildValue("(iii(si)(si)ii)", fd, fam, - s.so_type, laddr_str, lport, raddr_str, - rport, state, pid); - } - else { - return Py_BuildValue("(iii(si)()ii)", fd, fam, - s.so_type, laddr_str, lport, state, - pid); - } - } - - - if (fam == AF_UNIX) { - if (psutil_kread(Kd, (KA_T) s.so_pcb, (char *)&unp, sizeof(unp))) { - return NULL; - } - if ((KA_T) f.f_data != (KA_T) unp.unp_socket) { - PyErr_SetString(PyExc_RuntimeError, "unp_socket mismatch"); - return NULL; - } - - if (unp.unp_addr) { - if (read_unp_addr(Kd, unp.unp_addr, unix_laddr_str, - sizeof(unix_laddr_str))) { - return NULL; - } - } - - if (unp.unp_conn) { - if (psutil_kread(Kd, (KA_T) unp.unp_conn, (char *)&unp, - sizeof(unp))) { - return NULL; - } - if (read_unp_addr(Kd, unp.unp_addr, unix_raddr_str, - sizeof(unix_raddr_str))) { - return NULL; - } - } - - return Py_BuildValue("(iiissii)", fd, d.dom_family, - s.so_type, unix_laddr_str, unix_raddr_str, PSUTIL_CONN_NONE, - pid); - } - return NO_SOCKET; -} - -PyObject * -psutil_net_connections(PyObject *self, PyObject *args) { - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - KA_T fp; - int Kd = -1; - int i, np; - struct procentry64 *p; - struct fdsinfo64 *fds = (struct fdsinfo64 *)NULL; - pid32_t requested_pid; - pid32_t pid; - struct procentry64 *processes = (struct procentry64 *)NULL; - /* the process table */ - - if (py_retlist == NULL) - goto error; - if (! PyArg_ParseTuple(args, "i", &requested_pid)) - goto error; - - Kd = open(KMEM, O_RDONLY, 0); - if (Kd < 0) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, KMEM); - goto error; - } - - processes = psutil_read_process_table(&np); - if (!processes) - goto error; - - /* Loop through processes */ - for (p = processes; np > 0; np--, p++) { - pid = p->pi_pid; - if (requested_pid != -1 && requested_pid != pid) - continue; - if (p->pi_state == 0 || p->pi_state == SZOMB) - continue; - - if (!fds) { - fds = (struct fdsinfo64 *)malloc((size_t)FDSINFOSIZE); - if (!fds) { - PyErr_NoMemory(); - goto error; - } - } - if (getprocs64((struct procentry64 *)NULL, PROCSIZE, fds, FDSINFOSIZE, - &pid, 1) - != 1) - continue; - - /* loop over file descriptors */ - for (i = 0; i < p->pi_maxofile; i++) { - fp = (KA_T)fds->pi_ufd[i].fp; - if (fp) { - py_tuple = process_file(Kd, p->pi_pid, i, fp); - if (py_tuple == NULL) - goto error; - if (py_tuple != NO_SOCKET) { - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - } - } - } - close(Kd); - free(processes); - if (fds != NULL) - free(fds); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (Kd > 0) - close(Kd); - if (processes != NULL) - free(processes); - if (fds != NULL) - free(fds); - return NULL; -} diff --git a/third_party/python/psutil/psutil/arch/aix/net_connections.h b/third_party/python/psutil/psutil/arch/aix/net_connections.h deleted file mode 100644 index d57ee4284711..000000000000 --- a/third_party/python/psutil/psutil/arch/aix/net_connections.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2017, Arnon Yaari - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __NET_CONNECTIONS_H__ -#define __NET_CONNECTIONS_H__ - -#include - -PyObject* psutil_net_connections(PyObject *self, PyObject *args); - -#endif /* __NET_CONNECTIONS_H__ */ diff --git a/third_party/python/psutil/psutil/arch/aix/net_kernel_structs.h b/third_party/python/psutil/psutil/arch/aix/net_kernel_structs.h deleted file mode 100644 index 7e22a1639a02..000000000000 --- a/third_party/python/psutil/psutil/arch/aix/net_kernel_structs.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2017, Arnon Yaari - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* The kernel is always 64 bit but Python is usually compiled as a 32 bit - * process. We're reading the kernel memory to get the network connections, - * so we need the structs we read to be defined with 64 bit "pointers". - * Here are the partial definitions of the structs we use, taken from the - * header files, with data type sizes converted to their 64 bit counterparts, - * and unused data truncated. */ - -#ifdef __64BIT__ -/* In case we're in a 64 bit process after all */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define file64 file -#define socket64 socket -#define protosw64 protosw -#define inpcb64 inpcb -#define tcpcb64 tcpcb -#define unpcb64 unpcb -#define mbuf64 mbuf -#else /* __64BIT__ */ - struct file64 { - int f_flag; - int f_count; - int f_options; - int f_type; - u_longlong_t f_data; - }; - - struct socket64 { - short so_type; /* generic type, see socket.h */ - short so_options; /* from socket call, see socket.h */ - ushort so_linger; /* time to linger while closing */ - short so_state; /* internal state flags SS_*, below */ - u_longlong_t so_pcb; /* protocol control block */ - u_longlong_t so_proto; /* protocol handle */ - }; - - struct protosw64 { - short pr_type; /* socket type used for */ - u_longlong_t pr_domain; /* domain protocol a member of */ - short pr_protocol; /* protocol number */ - short pr_flags; /* see below */ - }; - - struct inpcb64 { - u_longlong_t inp_next,inp_prev; - /* pointers to other pcb's */ - u_longlong_t inp_head; /* pointer back to chain of inpcb's - for this protocol */ - u_int32_t inp_iflowinfo; /* input flow label */ - u_short inp_fport; /* foreign port */ - u_int16_t inp_fatype; /* foreign address type */ - union in_addr_6 inp_faddr_6; /* foreign host table entry */ - u_int32_t inp_oflowinfo; /* output flow label */ - u_short inp_lport; /* local port */ - u_int16_t inp_latype; /* local address type */ - union in_addr_6 inp_laddr_6; /* local host table entry */ - u_longlong_t inp_socket; /* back pointer to socket */ - u_longlong_t inp_ppcb; /* pointer to per-protocol pcb */ - u_longlong_t space_rt; - struct sockaddr_in6 spare_dst; - u_longlong_t inp_ifa; /* interface address to use */ - int inp_flags; /* generic IP/datagram flags */ -}; - -struct tcpcb64 { - u_longlong_t seg__next; - u_longlong_t seg__prev; - short t_state; /* state of this connection */ -}; - -struct unpcb64 { - u_longlong_t unp_socket; /* pointer back to socket */ - u_longlong_t unp_vnode; /* if associated with file */ - ino_t unp_vno; /* fake vnode number */ - u_longlong_t unp_conn; /* control block of connected socket */ - u_longlong_t unp_refs; /* referencing socket linked list */ - u_longlong_t unp_nextref; /* link in unp_refs list */ - u_longlong_t unp_addr; /* bound address of socket */ -}; - -struct m_hdr64 -{ - u_longlong_t mh_next; /* next buffer in chain */ - u_longlong_t mh_nextpkt; /* next chain in queue/record */ - long mh_len; /* amount of data in this mbuf */ - u_longlong_t mh_data; /* location of data */ -}; - -struct mbuf64 -{ - struct m_hdr64 m_hdr; -}; - -#define m_len m_hdr.mh_len - -#endif /* __64BIT__ */ diff --git a/third_party/python/psutil/psutil/arch/freebsd/proc_socks.c b/third_party/python/psutil/psutil/arch/freebsd/proc_socks.c deleted file mode 100644 index cdf5770b6f8f..000000000000 --- a/third_party/python/psutil/psutil/arch/freebsd/proc_socks.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * 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. - * - * Retrieves per-process open socket connections. - */ - -#include -#include -#include // for struct xsocket -#include -#include -#include // for xinpcb struct -#include -#include // for struct xtcpcb -#include // for inet_ntop() -#include - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - - -// The tcplist fetching and walking is borrowed from netstat/inet.c. -static char * -psutil_fetch_tcplist(void) { - char *buf; - size_t len; - - for (;;) { - if (sysctlbyname("net.inet.tcp.pcblist", NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - buf = malloc(len); - if (buf == NULL) { - PyErr_NoMemory(); - return NULL; - } - if (sysctlbyname("net.inet.tcp.pcblist", buf, &len, NULL, 0) < 0) { - free(buf); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - return buf; - } -} - - -static int -psutil_sockaddr_port(int family, struct sockaddr_storage *ss) { - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin; - - if (family == AF_INET) { - sin = (struct sockaddr_in *)ss; - return (sin->sin_port); - } - else { - sin6 = (struct sockaddr_in6 *)ss; - return (sin6->sin6_port); - } -} - - -static void * -psutil_sockaddr_addr(int family, struct sockaddr_storage *ss) { - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin; - - if (family == AF_INET) { - sin = (struct sockaddr_in *)ss; - return (&sin->sin_addr); - } - else { - sin6 = (struct sockaddr_in6 *)ss; - return (&sin6->sin6_addr); - } -} - - -static socklen_t -psutil_sockaddr_addrlen(int family) { - if (family == AF_INET) - return (sizeof(struct in_addr)); - else - return (sizeof(struct in6_addr)); -} - - -static int -psutil_sockaddr_matches(int family, int port, void *pcb_addr, - struct sockaddr_storage *ss) { - if (psutil_sockaddr_port(family, ss) != port) - return (0); - return (memcmp(psutil_sockaddr_addr(family, ss), pcb_addr, - psutil_sockaddr_addrlen(family)) == 0); -} - - -#if __FreeBSD_version >= 1200026 -static struct xtcpcb * -psutil_search_tcplist(char *buf, struct kinfo_file *kif) { - struct xtcpcb *tp; - struct xinpcb *inp; -#else -static struct tcpcb * -psutil_search_tcplist(char *buf, struct kinfo_file *kif) { - struct tcpcb *tp; - struct inpcb *inp; -#endif - struct xinpgen *xig, *oxig; - struct xsocket *so; - - oxig = xig = (struct xinpgen *)buf; - for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); - xig->xig_len > sizeof(struct xinpgen); - xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { - -#if __FreeBSD_version >= 1200026 - tp = (struct xtcpcb *)xig; - inp = &tp->xt_inp; - so = &inp->xi_socket; -#else - tp = &((struct xtcpcb *)xig)->xt_tp; - inp = &((struct xtcpcb *)xig)->xt_inp; - so = &((struct xtcpcb *)xig)->xt_socket; -#endif - - if (so->so_type != kif->kf_sock_type || - so->xso_family != kif->kf_sock_domain || - so->xso_protocol != kif->kf_sock_protocol) - continue; - - if (kif->kf_sock_domain == AF_INET) { - if (!psutil_sockaddr_matches( - AF_INET, inp->inp_lport, &inp->inp_laddr, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_local)) -#else - &kif->kf_un.kf_sock.kf_sa_local)) -#endif - continue; - if (!psutil_sockaddr_matches( - AF_INET, inp->inp_fport, &inp->inp_faddr, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_peer)) -#else - &kif->kf_un.kf_sock.kf_sa_peer)) -#endif - continue; - } else { - if (!psutil_sockaddr_matches( - AF_INET6, inp->inp_lport, &inp->in6p_laddr, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_local)) -#else - &kif->kf_un.kf_sock.kf_sa_local)) -#endif - continue; - if (!psutil_sockaddr_matches( - AF_INET6, inp->inp_fport, &inp->in6p_faddr, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_peer)) -#else - &kif->kf_un.kf_sock.kf_sa_peer)) -#endif - continue; - } - - return (tp); - } - return NULL; -} - - - -PyObject * -psutil_proc_connections(PyObject *self, PyObject *args) { - // Return connections opened by process. - pid_t pid; - int i; - int cnt; - struct kinfo_file *freep = NULL; - struct kinfo_file *kif; - char *tcplist = NULL; -#if __FreeBSD_version >= 1200026 - struct xtcpcb *tcp; -#else - struct tcpcb *tcp; -#endif - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - PyObject *py_af_filter = NULL; - PyObject *py_type_filter = NULL; - PyObject *py_family = NULL; - PyObject *py_type = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "OO", &pid, - &py_af_filter, &py_type_filter)) - { - goto error; - } - if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) { - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - goto error; - } - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getfile()"); - goto error; - } - - tcplist = psutil_fetch_tcplist(); - if (tcplist == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < cnt; i++) { - int lport, rport, state; - char lip[200], rip[200]; - char path[PATH_MAX]; - int inseq; - py_tuple = NULL; - py_laddr = NULL; - py_raddr = NULL; - - kif = &freep[i]; - if (kif->kf_type == KF_TYPE_SOCKET) { - // apply filters - py_family = PyLong_FromLong((long)kif->kf_sock_domain); - inseq = PySequence_Contains(py_af_filter, py_family); - Py_DECREF(py_family); - if (inseq == 0) - continue; - py_type = PyLong_FromLong((long)kif->kf_sock_type); - inseq = PySequence_Contains(py_type_filter, py_type); - Py_DECREF(py_type); - if (inseq == 0) - continue; - // IPv4 / IPv6 socket - if ((kif->kf_sock_domain == AF_INET) || - (kif->kf_sock_domain == AF_INET6)) { - // fill status - state = PSUTIL_CONN_NONE; - if (kif->kf_sock_type == SOCK_STREAM) { - tcp = psutil_search_tcplist(tcplist, kif); - if (tcp != NULL) - state = (int)tcp->t_state; - } - - // build addr and port - inet_ntop( - kif->kf_sock_domain, - psutil_sockaddr_addr(kif->kf_sock_domain, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_local), -#else - &kif->kf_un.kf_sock.kf_sa_local), -#endif - lip, - sizeof(lip)); - inet_ntop( - kif->kf_sock_domain, - psutil_sockaddr_addr(kif->kf_sock_domain, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_peer), -#else - &kif->kf_un.kf_sock.kf_sa_peer), -#endif - rip, - sizeof(rip)); - lport = htons(psutil_sockaddr_port(kif->kf_sock_domain, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_local)); -#else - &kif->kf_un.kf_sock.kf_sa_local)); -#endif - rport = htons(psutil_sockaddr_port(kif->kf_sock_domain, -#if __FreeBSD_version < 1200031 - &kif->kf_sa_peer)); -#else - &kif->kf_un.kf_sock.kf_sa_peer)); -#endif - - // construct python tuple/list - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue( - "(iiiNNi)", - kif->kf_fd, - kif->kf_sock_domain, - kif->kf_sock_type, - py_laddr, - py_raddr, - state - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - // UNIX socket. - // Note: remote path cannot be determined. - else if (kif->kf_sock_domain == AF_UNIX) { - struct sockaddr_un *sun; - -#if __FreeBSD_version < 1200031 - sun = (struct sockaddr_un *)&kif->kf_sa_local; -#else - sun = (struct sockaddr_un *)&kif->kf_un.kf_sock.kf_sa_local; -#endif - snprintf( - path, sizeof(path), "%.*s", - (int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))), - sun->sun_path); - - py_laddr = PyUnicode_DecodeFSDefault(path); - if (! py_laddr) - goto error; - - py_tuple = Py_BuildValue( - "(iiiOsi)", - kif->kf_fd, - kif->kf_sock_domain, - kif->kf_sock_type, - py_laddr, - "", // raddr can't be determined - PSUTIL_CONN_NONE - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - Py_DECREF(py_laddr); - } - } - } - free(freep); - free(tcplist); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - Py_DECREF(py_retlist); - if (freep != NULL) - free(freep); - if (tcplist != NULL) - free(tcplist); - return NULL; -} diff --git a/third_party/python/psutil/psutil/arch/freebsd/proc_socks.h b/third_party/python/psutil/psutil/arch/freebsd/proc_socks.h deleted file mode 100644 index a7996b107496..000000000000 --- a/third_party/python/psutil/psutil/arch/freebsd/proc_socks.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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. - */ - -#include - -PyObject* psutil_proc_connections(PyObject* self, PyObject* args); diff --git a/third_party/python/psutil/psutil/arch/freebsd/specific.c b/third_party/python/psutil/psutil/arch/freebsd/specific.c deleted file mode 100644 index 3f37a08e2d2a..000000000000 --- a/third_party/python/psutil/psutil/arch/freebsd/specific.c +++ /dev/null @@ -1,1077 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Helper functions specific to FreeBSD. - * Used by _psutil_bsd module methods. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // needed for vmtotal struct -#include // for swap mem -#include // process open files, shared libs (kinfo_getvmmap), cwd -#include - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - - -#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) -#define PSUTIL_BT2MSEC(bt) (bt.sec * 1000 + (((uint64_t) 1000000000 * (uint32_t) \ - (bt.frac >> 32) ) >> 32 ) / 1000000) -#define DECIKELVIN_2_CELCIUS(t) (t - 2731) / 10 -#ifndef _PATH_DEVNULL -#define _PATH_DEVNULL "/dev/null" -#endif - - -// ============================================================================ -// Utility functions -// ============================================================================ - - -int -psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc) { - // Fills a kinfo_proc struct based on process pid. - int mib[4]; - size_t size; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = pid; - - size = sizeof(struct kinfo_proc); - if (sysctl((int *)mib, 4, proc, &size, NULL, 0) == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_PID)"); - return -1; - } - - // sysctl stores 0 in the size if we can't find the process information. - if (size == 0) { - NoSuchProcess("sysctl (size = 0)"); - return -1; - } - return 0; -} - - -// remove spaces from string -static void psutil_remove_spaces(char *str) { - char *p1 = str; - char *p2 = str; - do - while (*p2 == ' ') - p2++; - while ((*p1++ = *p2++)); -} - - -// ============================================================================ -// APIS -// ============================================================================ - -int -psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) { - // Returns a list of all BSD processes on the system. This routine - // allocates the list and puts it in *procList and a count of the - // number of entries in *procCount. You are responsible for freeing - // this list. On success returns 0, else 1 with exception set. - int err; - struct kinfo_proc *buf = NULL; - int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0 }; - size_t length = 0; - - assert(procList != NULL); - assert(*procList == NULL); - assert(procCount != NULL); - - // Call sysctl with a NULL buffer in order to get buffer length. - err = sysctl(name, 3, NULL, &length, NULL, 0); - if (err == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl (null buffer)"); - return 1; - } - - // Allocate an appropriately sized buffer based on the results - // from the previous call. - buf = malloc(length); - if (buf == NULL) { - PyErr_NoMemory(); - return 1; - } - - // Call sysctl again with the new buffer. - err = sysctl(name, 3, buf, &length, NULL, 0); - if (err == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl"); - free(buf); - return 1; - } - - *procList = buf; - *procCount = length / sizeof(struct kinfo_proc); - return 0; -} - - -/* - * XXX no longer used; it probably makese sense to remove it. - * Borrowed from psi Python System Information project - * - * Get command arguments and environment variables. - * - * Based on code from ps. - * - * Returns: - * 0 for success; - * -1 for failure (Exception raised); - * 1 for insufficient privileges. - */ -static char -*psutil_get_cmd_args(pid_t pid, size_t *argsize) { - int mib[4]; - int argmax; - size_t size = sizeof(argmax); - char *procargs = NULL; - - // Get the maximum process arguments size. - mib[0] = CTL_KERN; - mib[1] = KERN_ARGMAX; - - size = sizeof(argmax); - if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) - return NULL; - - // Allocate space for the arguments. - procargs = (char *)malloc(argmax); - if (procargs == NULL) { - PyErr_NoMemory(); - return NULL; - } - - // Make a sysctl() call to get the raw argument space of the process. - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_ARGS; - mib[3] = pid; - - size = argmax; - if (sysctl(mib, 4, procargs, &size, NULL, 0) == -1) { - free(procargs); - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_ARGS)"); - return NULL; - } - - // return string and set the length of arguments - *argsize = size; - return procargs; -} - - -// returns the command line as a python list object -PyObject * -psutil_get_cmdline(pid_t pid) { - char *argstr = NULL; - size_t pos = 0; - size_t argsize = 0; - PyObject *py_retlist = Py_BuildValue("[]"); - PyObject *py_arg = NULL; - - if (pid < 0) - return py_retlist; - argstr = psutil_get_cmd_args(pid, &argsize); - if (argstr == NULL) - goto error; - - // args are returned as a flattened string with \0 separators between - // arguments add each string to the list then step forward to the next - // separator - if (argsize > 0) { - while (pos < argsize) { - py_arg = PyUnicode_DecodeFSDefault(&argstr[pos]); - if (!py_arg) - goto error; - if (PyList_Append(py_retlist, py_arg)) - goto error; - Py_DECREF(py_arg); - pos = pos + strlen(&argstr[pos]) + 1; - } - } - - free(argstr); - return py_retlist; - -error: - Py_XDECREF(py_arg); - Py_DECREF(py_retlist); - if (argstr != NULL) - free(argstr); - return NULL; -} - - -/* - * Return process pathname executable. - * Thanks to Robert N. M. Watson: - * http://fxr.googlebit.com/source/usr.bin/procstat/procstat_bin.c?v=8-CURRENT - */ -PyObject * -psutil_proc_exe(PyObject *self, PyObject *args) { - pid_t pid; - char pathname[PATH_MAX]; - int error; - int mib[4]; - int ret; - size_t size; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PATHNAME; - mib[3] = pid; - - size = sizeof(pathname); - error = sysctl(mib, 4, pathname, &size, NULL, 0); - if (error == -1) { - // see: https://github.com/giampaolo/psutil/issues/907 - if (errno == ENOENT) { - return PyUnicode_DecodeFSDefault(""); - } - else { - return \ - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_PATHNAME)"); - } - } - if (size == 0 || strlen(pathname) == 0) { - ret = psutil_pid_exists(pid); - if (ret == -1) - return NULL; - else if (ret == 0) - return NoSuchProcess("psutil_pid_exists"); - else - strcpy(pathname, ""); - } - - return PyUnicode_DecodeFSDefault(pathname); -} - - -PyObject * -psutil_proc_num_threads(PyObject *self, PyObject *args) { - // Return number of threads used by process as a Python integer. - pid_t pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("l", (long)kp.ki_numthreads); -} - - -PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - // Retrieves all threads used by process returning a list of tuples - // including thread id, user time and system time. - // Thanks to Robert N. M. Watson: - // http://code.metager.de/source/xref/freebsd/usr.bin/procstat/ - // procstat_threads.c - pid_t pid; - int mib[4]; - struct kinfo_proc *kip = NULL; - struct kinfo_proc *kipp = NULL; - int error; - unsigned int i; - size_t size; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - goto error; - - // we need to re-query for thread information, so don't use *kipp - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD; - mib[3] = pid; - - size = 0; - error = sysctl(mib, 4, NULL, &size, NULL, 0); - if (error == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_INC_THREAD)"); - goto error; - } - if (size == 0) { - NoSuchProcess("sysctl (size = 0)"); - goto error; - } - - kip = malloc(size); - if (kip == NULL) { - PyErr_NoMemory(); - goto error; - } - - error = sysctl(mib, 4, kip, &size, NULL, 0); - if (error == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_INC_THREAD)"); - goto error; - } - if (size == 0) { - NoSuchProcess("sysctl (size = 0)"); - goto error; - } - - for (i = 0; i < size / sizeof(*kipp); i++) { - kipp = &kip[i]; - py_tuple = Py_BuildValue("Idd", - kipp->ki_tid, - PSUTIL_TV2DOUBLE(kipp->ki_rusage.ru_utime), - PSUTIL_TV2DOUBLE(kipp->ki_rusage.ru_stime)); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - free(kip); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (kip != NULL) - free(kip); - return NULL; -} - - -PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) { - // Return an XML string from which we'll determine the number of - // physical CPU cores in the system. - void *topology = NULL; - size_t size = 0; - PyObject *py_str; - - if (sysctlbyname("kern.sched.topology_spec", NULL, &size, NULL, 0)) - goto error; - - topology = malloc(size); - if (!topology) { - PyErr_NoMemory(); - return NULL; - } - - if (sysctlbyname("kern.sched.topology_spec", topology, &size, NULL, 0)) - goto error; - - py_str = Py_BuildValue("s", topology); - free(topology); - return py_str; - -error: - if (topology != NULL) - free(topology); - Py_RETURN_NONE; -} - - -/* - * Return virtual memory usage statistics. - */ -PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - unsigned long total; - unsigned int active, inactive, wired, cached, free; - size_t size = sizeof(total); - struct vmtotal vm; - int mib[] = {CTL_VM, VM_METER}; - long pagesize = getpagesize(); -#if __FreeBSD_version > 702101 - long buffers; -#else - int buffers; -#endif - size_t buffers_size = sizeof(buffers); - - if (sysctlbyname("hw.physmem", &total, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall("sysctlbyname('hw.physmem')"); - } - if (sysctlbyname("vm.stats.vm.v_active_count", &active, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_active_count')"); - } - if (sysctlbyname("vm.stats.vm.v_inactive_count", &inactive, &size, NULL, 0)) - { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_inactive_count')"); - } - if (sysctlbyname("vm.stats.vm.v_wire_count", &wired, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_wire_count')"); - } - // https://github.com/giampaolo/psutil/issues/997 - if (sysctlbyname("vm.stats.vm.v_cache_count", &cached, &size, NULL, 0)) { - cached = 0; - } - if (sysctlbyname("vm.stats.vm.v_free_count", &free, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_free_count')"); - } - if (sysctlbyname("vfs.bufspace", &buffers, &buffers_size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall("sysctlbyname('vfs.bufspace')"); - } - - size = sizeof(vm); - if (sysctl(mib, 2, &vm, &size, NULL, 0) != 0) { - return PyErr_SetFromOSErrnoWithSyscall("sysctl(CTL_VM | VM_METER)"); - } - - return Py_BuildValue("KKKKKKKK", - (unsigned long long) total, - (unsigned long long) free * pagesize, - (unsigned long long) active * pagesize, - (unsigned long long) inactive * pagesize, - (unsigned long long) wired * pagesize, - (unsigned long long) cached * pagesize, - (unsigned long long) buffers, - (unsigned long long) (vm.t_vmshr + vm.t_rmshr) * pagesize // shared - ); -} - - -PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { - // Return swap memory stats (see 'swapinfo' cmdline tool) - kvm_t *kd; - struct kvm_swap kvmsw[1]; - unsigned int swapin, swapout, nodein, nodeout; - size_t size = sizeof(unsigned int); - int pagesize; - - kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open failed"); - if (kd == NULL) { - PyErr_SetString(PyExc_RuntimeError, "kvm_open() syscall failed"); - return NULL; - } - - if (kvm_getswapinfo(kd, kvmsw, 1, 0) < 0) { - kvm_close(kd); - PyErr_SetString(PyExc_RuntimeError, - "kvm_getswapinfo() syscall failed"); - return NULL; - } - - kvm_close(kd); - - if (sysctlbyname("vm.stats.vm.v_swapin", &swapin, &size, NULL, 0) == -1) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_swapin)'"); - } - if (sysctlbyname("vm.stats.vm.v_swapout", &swapout, &size, NULL, 0) == -1){ - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_swapout)'"); - } - if (sysctlbyname("vm.stats.vm.v_vnodein", &nodein, &size, NULL, 0) == -1) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_vnodein)'"); - } - if (sysctlbyname("vm.stats.vm.v_vnodeout", &nodeout, &size, NULL, 0) == -1) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.vm.v_vnodeout)'"); - } - - pagesize = getpagesize(); - if (pagesize <= 0) { - PyErr_SetString(PyExc_ValueError, "invalid getpagesize()"); - return NULL; - } - - return Py_BuildValue( - "(KKKII)", - (unsigned long long)kvmsw[0].ksw_total * pagesize, // total - (unsigned long long)kvmsw[0].ksw_used * pagesize, // used - (unsigned long long)kvmsw[0].ksw_total * pagesize - // free - kvmsw[0].ksw_used * pagesize, - swapin + swapout, // swap in - nodein + nodeout // swap out - ); -} - - -#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 -PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) { - pid_t pid; - struct kinfo_file *freep = NULL; - struct kinfo_file *kif; - struct kinfo_proc kipp; - PyObject *py_path = NULL; - - int i, cnt; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - goto error; - if (psutil_kinfo_proc(pid, &kipp) == -1) - goto error; - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getfile()"); - goto error; - } - - for (i = 0; i < cnt; i++) { - kif = &freep[i]; - if (kif->kf_fd == KF_FD_TYPE_CWD) { - py_path = PyUnicode_DecodeFSDefault(kif->kf_path); - if (!py_path) - goto error; - break; - } - } - /* - * For lower pids it seems we can't retrieve any information - * (lsof can't do that it either). Since this happens even - * as root we return an empty string instead of AccessDenied. - */ - if (py_path == NULL) - py_path = PyUnicode_DecodeFSDefault(""); - free(freep); - return py_path; - -error: - Py_XDECREF(py_path); - if (freep != NULL) - free(freep); - return NULL; -} -#endif - - -#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 -PyObject * -psutil_proc_num_fds(PyObject *self, PyObject *args) { - pid_t pid; - int cnt; - - struct kinfo_file *freep; - struct kinfo_proc kipp; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kipp) == -1) - return NULL; - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getfile()"); - return NULL; - } - free(freep); - - return Py_BuildValue("i", cnt); -} -#endif - - -PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - static int maxcpus; - int mib[2]; - int ncpu; - size_t len; - size_t size; - int i; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - // retrieve maxcpus value - size = sizeof(maxcpus); - if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) { - Py_DECREF(py_retlist); - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('kern.smp.maxcpus')"); - } - long cpu_time[maxcpus][CPUSTATES]; - - // retrieve the number of cpus - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(HW_NCPU)"); - goto error; - } - - // per-cpu info - size = sizeof(cpu_time); - if (sysctlbyname("kern.cp_times", &cpu_time, &size, NULL, 0) == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctlbyname('kern.smp.maxcpus')"); - goto error; - } - - for (i = 0; i < ncpu; i++) { - py_cputime = Py_BuildValue( - "(ddddd)", - (double)cpu_time[i][CP_USER] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_NICE] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_SYS] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_IDLE] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_INTR] / CLOCKS_PER_SEC); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_DECREF(py_cputime); - } - - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - return NULL; -} - - -PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - int i; - struct statinfo stats; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - - if (py_retdict == NULL) - return NULL; - if (devstat_checkversion(NULL) < 0) { - PyErr_Format(PyExc_RuntimeError, - "devstat_checkversion() syscall failed"); - goto error; - } - - stats.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); - if (stats.dinfo == NULL) { - PyErr_NoMemory(); - goto error; - } - bzero(stats.dinfo, sizeof(struct devinfo)); - - if (devstat_getdevs(NULL, &stats) == -1) { - PyErr_Format(PyExc_RuntimeError, "devstat_getdevs() syscall failed"); - goto error; - } - - for (i = 0; i < stats.dinfo->numdevs; i++) { - py_disk_info = NULL; - struct devstat current; - char disk_name[128]; - current = stats.dinfo->devices[i]; - snprintf(disk_name, sizeof(disk_name), "%s%d", - current.device_name, - current.unit_number); - - py_disk_info = Py_BuildValue( - "(KKKKLLL)", - current.operations[DEVSTAT_READ], // no reads - current.operations[DEVSTAT_WRITE], // no writes - current.bytes[DEVSTAT_READ], // bytes read - current.bytes[DEVSTAT_WRITE], // bytes written - (long long) PSUTIL_BT2MSEC(current.duration[DEVSTAT_READ]), // r time - (long long) PSUTIL_BT2MSEC(current.duration[DEVSTAT_WRITE]), // w time - (long long) PSUTIL_BT2MSEC(current.busy_time) // busy time - ); // finished transactions - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, disk_name, py_disk_info)) - goto error; - Py_DECREF(py_disk_info); - } - - if (stats.dinfo->mem_ptr) - free(stats.dinfo->mem_ptr); - free(stats.dinfo); - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (stats.dinfo != NULL) - free(stats.dinfo); - return NULL; -} - - -PyObject * -psutil_proc_memory_maps(PyObject *self, PyObject *args) { - // Return a list of tuples for every process memory maps. - // 'procstat' cmdline utility has been used as an example. - pid_t pid; - int ptrwidth; - int i, cnt; - char addr[1000]; - char perms[4]; - char *path; - struct kinfo_proc kp; - struct kinfo_vmentry *freep = NULL; - struct kinfo_vmentry *kve; - ptrwidth = 2 * sizeof(void *); - PyObject *py_tuple = NULL; - PyObject *py_path = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - goto error; - if (psutil_kinfo_proc(pid, &kp) == -1) - goto error; - - errno = 0; - freep = kinfo_getvmmap(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getvmmap()"); - goto error; - } - for (i = 0; i < cnt; i++) { - py_tuple = NULL; - kve = &freep[i]; - addr[0] = '\0'; - perms[0] = '\0'; - sprintf(addr, "%#*jx-%#*jx", ptrwidth, (uintmax_t)kve->kve_start, - ptrwidth, (uintmax_t)kve->kve_end); - psutil_remove_spaces(addr); - strlcat(perms, kve->kve_protection & KVME_PROT_READ ? "r" : "-", - sizeof(perms)); - strlcat(perms, kve->kve_protection & KVME_PROT_WRITE ? "w" : "-", - sizeof(perms)); - strlcat(perms, kve->kve_protection & KVME_PROT_EXEC ? "x" : "-", - sizeof(perms)); - - if (strlen(kve->kve_path) == 0) { - switch (kve->kve_type) { - case KVME_TYPE_NONE: - path = "[none]"; - break; - case KVME_TYPE_DEFAULT: - path = "[default]"; - break; - case KVME_TYPE_VNODE: - path = "[vnode]"; - break; - case KVME_TYPE_SWAP: - path = "[swap]"; - break; - case KVME_TYPE_DEVICE: - path = "[device]"; - break; - case KVME_TYPE_PHYS: - path = "[phys]"; - break; - case KVME_TYPE_DEAD: - path = "[dead]"; - break; - case KVME_TYPE_SG: - path = "[sg]"; - break; - case KVME_TYPE_UNKNOWN: - path = "[unknown]"; - break; - default: - path = "[?]"; - break; - } - } - else { - path = kve->kve_path; - } - - py_path = PyUnicode_DecodeFSDefault(path); - if (! py_path) - goto error; - py_tuple = Py_BuildValue("ssOiiii", - addr, // "start-end" address - perms, // "rwx" permissions - py_path, // path - kve->kve_resident, // rss - kve->kve_private_resident, // private - kve->kve_ref_count, // ref count - kve->kve_shadow_count); // shadow count - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_path); - Py_DECREF(py_tuple); - } - free(freep); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_path); - Py_DECREF(py_retlist); - if (freep != NULL) - free(freep); - return NULL; -} - - -PyObject* -psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args) { - // Get process CPU affinity. - // Reference: - // http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c - pid_t pid; - int ret; - int i; - cpuset_t mask; - PyObject* py_retlist; - PyObject* py_cpu_num; - - if (!PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, - sizeof(mask), &mask); - if (ret != 0) - return PyErr_SetFromErrno(PyExc_OSError); - - py_retlist = PyList_New(0); - if (py_retlist == NULL) - return NULL; - - for (i = 0; i < CPU_SETSIZE; i++) { - if (CPU_ISSET(i, &mask)) { - py_cpu_num = Py_BuildValue("i", i); - if (py_cpu_num == NULL) - goto error; - if (PyList_Append(py_retlist, py_cpu_num)) - goto error; - } - } - - return py_retlist; - -error: - Py_XDECREF(py_cpu_num); - Py_DECREF(py_retlist); - return NULL; -} - - -PyObject * -psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) { - // Set process CPU affinity. - // Reference: - // http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c - pid_t pid; - int i; - int seq_len; - int ret; - cpuset_t cpu_set; - PyObject *py_cpu_set; - PyObject *py_cpu_seq = NULL; - - if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O", &pid, &py_cpu_set)) - return NULL; - - py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer"); - if (!py_cpu_seq) - return NULL; - seq_len = PySequence_Fast_GET_SIZE(py_cpu_seq); - - // calculate the mask - CPU_ZERO(&cpu_set); - for (i = 0; i < seq_len; i++) { - PyObject *item = PySequence_Fast_GET_ITEM(py_cpu_seq, i); -#if PY_MAJOR_VERSION >= 3 - long value = PyLong_AsLong(item); -#else - long value = PyInt_AsLong(item); -#endif - if (value == -1 || PyErr_Occurred()) - goto error; - CPU_SET(value, &cpu_set); - } - - // set affinity - ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, - sizeof(cpu_set), &cpu_set); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - Py_DECREF(py_cpu_seq); - Py_RETURN_NONE; - -error: - if (py_cpu_seq != NULL) - Py_DECREF(py_cpu_seq); - return NULL; -} - - -PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - unsigned int v_soft; - unsigned int v_intr; - unsigned int v_syscall; - unsigned int v_trap; - unsigned int v_swtch; - size_t size = sizeof(v_soft); - - if (sysctlbyname("vm.stats.sys.v_soft", &v_soft, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.sys.v_soft')"); - } - if (sysctlbyname("vm.stats.sys.v_intr", &v_intr, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.sys.v_intr')"); - } - if (sysctlbyname("vm.stats.sys.v_syscall", &v_syscall, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.sys.v_syscall')"); - } - if (sysctlbyname("vm.stats.sys.v_trap", &v_trap, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.sys.v_trap')"); - } - if (sysctlbyname("vm.stats.sys.v_swtch", &v_swtch, &size, NULL, 0)) { - return PyErr_SetFromOSErrnoWithSyscall( - "sysctlbyname('vm.stats.sys.v_swtch')"); - } - - return Py_BuildValue( - "IIIII", - v_swtch, // ctx switches - v_intr, // interrupts - v_soft, // software interrupts - v_syscall, // syscalls - v_trap // traps - ); -} - - -/* - * Return battery information. - */ -PyObject * -psutil_sensors_battery(PyObject *self, PyObject *args) { - int percent; - int minsleft; - int power_plugged; - size_t size = sizeof(percent); - - if (sysctlbyname("hw.acpi.battery.life", &percent, &size, NULL, 0)) - goto error; - if (sysctlbyname("hw.acpi.battery.time", &minsleft, &size, NULL, 0)) - goto error; - if (sysctlbyname("hw.acpi.acline", &power_plugged, &size, NULL, 0)) - goto error; - return Py_BuildValue("iii", percent, minsleft, power_plugged); - -error: - // see: https://github.com/giampaolo/psutil/issues/1074 - if (errno == ENOENT) - PyErr_SetString(PyExc_NotImplementedError, "no battery"); - else - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -/* - * Return temperature information for a given CPU core number. - */ -PyObject * -psutil_sensors_cpu_temperature(PyObject *self, PyObject *args) { - int current; - int tjmax; - int core; - char sensor[26]; - size_t size = sizeof(current); - - if (! PyArg_ParseTuple(args, "i", &core)) - return NULL; - sprintf(sensor, "dev.cpu.%d.temperature", core); - if (sysctlbyname(sensor, ¤t, &size, NULL, 0)) - goto error; - current = DECIKELVIN_2_CELCIUS(current); - - // Return -273 in case of faliure. - sprintf(sensor, "dev.cpu.%d.coretemp.tjmax", core); - if (sysctlbyname(sensor, &tjmax, &size, NULL, 0)) - tjmax = 0; - tjmax = DECIKELVIN_2_CELCIUS(tjmax); - - return Py_BuildValue("ii", current, tjmax); - -error: - if (errno == ENOENT) - PyErr_SetString(PyExc_NotImplementedError, "no temperature sensors"); - else - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -/* - * Return frequency information of a given CPU. - * As of Dec 2018 only CPU 0 appears to be supported and all other - * cores match the frequency of CPU 0. - */ -PyObject * -psutil_cpu_freq(PyObject *self, PyObject *args) { - int current; - int core; - char sensor[26]; - char available_freq_levels[1000]; - size_t size = sizeof(current); - - if (! PyArg_ParseTuple(args, "i", &core)) - return NULL; - // https://www.unix.com/man-page/FreeBSD/4/cpufreq/ - sprintf(sensor, "dev.cpu.%d.freq", core); - if (sysctlbyname(sensor, ¤t, &size, NULL, 0)) - goto error; - - size = sizeof(available_freq_levels); - // https://www.unix.com/man-page/FreeBSD/4/cpufreq/ - // In case of failure, an empty string is returned. - sprintf(sensor, "dev.cpu.%d.freq_levels", core); - sysctlbyname(sensor, &available_freq_levels, &size, NULL, 0); - - return Py_BuildValue("is", current, available_freq_levels); - -error: - if (errno == ENOENT) - PyErr_SetString(PyExc_NotImplementedError, "unable to read frequency"); - else - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} diff --git a/third_party/python/psutil/psutil/arch/freebsd/specific.h b/third_party/python/psutil/psutil/arch/freebsd/specific.h deleted file mode 100644 index 875c8166465f..000000000000 --- a/third_party/python/psutil/psutil/arch/freebsd/specific.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ - -#include - -typedef struct kinfo_proc kinfo_proc; - -int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount); -int psutil_kinfo_proc(const pid_t pid, struct kinfo_proc *proc); - -// -PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args); -PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args); -PyObject* psutil_get_cmdline(long pid); -PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args); -PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args); -PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args); -PyObject* psutil_proc_cwd(PyObject* self, PyObject* args); -PyObject* psutil_proc_exe(PyObject* self, PyObject* args); -PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args); -PyObject* psutil_proc_num_fds(PyObject* self, PyObject* args); -PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args); -PyObject* psutil_proc_threads(PyObject* self, PyObject* args); -PyObject* psutil_swap_mem(PyObject* self, PyObject* args); -PyObject* psutil_virtual_mem(PyObject* self, PyObject* args); -PyObject* psutil_cpu_stats(PyObject* self, PyObject* args); -#if defined(PSUTIL_FREEBSD) -PyObject* psutil_sensors_battery(PyObject* self, PyObject* args); -PyObject* psutil_sensors_cpu_temperature(PyObject* self, PyObject* args); -PyObject* psutil_cpu_freq(PyObject* self, PyObject* args); -#endif diff --git a/third_party/python/psutil/psutil/arch/freebsd/sys_socks.c b/third_party/python/psutil/psutil/arch/freebsd/sys_socks.c deleted file mode 100644 index ab61f393b99c..000000000000 --- a/third_party/python/psutil/psutil/arch/freebsd/sys_socks.c +++ /dev/null @@ -1,363 +0,0 @@ -/* - * 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. - * - * Retrieves system-wide open socket connections. This is based off of - * sockstat utility source code: - * https://github.com/freebsd/freebsd/blob/master/usr.bin/sockstat/sockstat.c - */ - -#include -#include -#include -#include // for struct xsocket -#include -#include -#include -#include // for xinpcb struct -#include -#include -#include // for struct xtcpcb -#include // for inet_ntop() - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - -static struct xfile *psutil_xfiles; -static int psutil_nxfiles; - - -int -psutil_populate_xfiles() { - size_t len; - - if ((psutil_xfiles = malloc(len = sizeof *psutil_xfiles)) == NULL) { - PyErr_NoMemory(); - return 0; - } - while (sysctlbyname("kern.file", psutil_xfiles, &len, 0, 0) == -1) { - if (errno != ENOMEM) { - PyErr_SetFromErrno(0); - return 0; - } - len *= 2; - if ((psutil_xfiles = realloc(psutil_xfiles, len)) == NULL) { - PyErr_NoMemory(); - return 0; - } - } - if (len > 0 && psutil_xfiles->xf_size != sizeof *psutil_xfiles) { - PyErr_Format(PyExc_RuntimeError, "struct xfile size mismatch"); - return 0; - } - psutil_nxfiles = len / sizeof *psutil_xfiles; - return 1; -} - - -struct xfile * -psutil_get_file_from_sock(void *sock) { - struct xfile *xf; - int n; - - for (xf = psutil_xfiles, n = 0; n < psutil_nxfiles; ++n, ++xf) { - if (xf->xf_data == sock) - return xf; - } - return NULL; -} - - -// Reference: -// https://github.com/freebsd/freebsd/blob/master/usr.bin/sockstat/sockstat.c -int psutil_gather_inet(int proto, PyObject *py_retlist) { - struct xinpgen *xig, *exig; - struct xinpcb *xip; - struct xtcpcb *xtp; -#if __FreeBSD_version >= 1200026 - struct xinpcb *inp; -#else - struct inpcb *inp; -#endif - struct xsocket *so; - const char *varname = NULL; - size_t len, bufsize; - void *buf; - int retry; - int type; - - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - - switch (proto) { - case IPPROTO_TCP: - varname = "net.inet.tcp.pcblist"; - type = SOCK_STREAM; - break; - case IPPROTO_UDP: - varname = "net.inet.udp.pcblist"; - type = SOCK_DGRAM; - break; - } - - buf = NULL; - bufsize = 8192; - retry = 5; - do { - for (;;) { - buf = realloc(buf, bufsize); - if (buf == NULL) - continue; // XXX - len = bufsize; - if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) - break; - if (errno != ENOMEM) { - PyErr_SetFromErrno(0); - goto error; - } - bufsize *= 2; - } - xig = (struct xinpgen *)buf; - exig = (struct xinpgen *)(void *)((char *)buf + len - sizeof *exig); - if (xig->xig_len != sizeof *xig || exig->xig_len != sizeof *exig) { - PyErr_Format(PyExc_RuntimeError, "struct xinpgen size mismatch"); - goto error; - } - } while (xig->xig_gen != exig->xig_gen && retry--); - - for (;;) { - struct xfile *xf; - int lport, rport, status, family; - - xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); - if (xig >= exig) - break; - - switch (proto) { - case IPPROTO_TCP: - xtp = (struct xtcpcb *)xig; - if (xtp->xt_len != sizeof *xtp) { - PyErr_Format(PyExc_RuntimeError, - "struct xtcpcb size mismatch"); - goto error; - } - inp = &xtp->xt_inp; -#if __FreeBSD_version >= 1200026 - so = &inp->xi_socket; - status = xtp->t_state; -#else - so = &xtp->xt_socket; - status = xtp->xt_tp.t_state; -#endif - break; - case IPPROTO_UDP: - xip = (struct xinpcb *)xig; - if (xip->xi_len != sizeof *xip) { - PyErr_Format(PyExc_RuntimeError, - "struct xinpcb size mismatch"); - goto error; - } -#if __FreeBSD_version >= 1200026 - inp = xip; -#else - inp = &xip->xi_inp; -#endif - so = &xip->xi_socket; - status = PSUTIL_CONN_NONE; - break; - default: - PyErr_Format(PyExc_RuntimeError, "invalid proto"); - goto error; - } - - char lip[200], rip[200]; - - xf = psutil_get_file_from_sock(so->xso_so); - if (xf == NULL) - continue; - lport = ntohs(inp->inp_lport); - rport = ntohs(inp->inp_fport); - - if (inp->inp_vflag & INP_IPV4) { - family = AF_INET; - inet_ntop(AF_INET, &inp->inp_laddr.s_addr, lip, sizeof(lip)); - inet_ntop(AF_INET, &inp->inp_faddr.s_addr, rip, sizeof(rip)); - } - else if (inp->inp_vflag & INP_IPV6) { - family = AF_INET6; - inet_ntop(AF_INET6, &inp->in6p_laddr.s6_addr, lip, sizeof(lip)); - inet_ntop(AF_INET6, &inp->in6p_faddr.s6_addr, rip, sizeof(rip)); - } - - // construct python tuple/list - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue( - "iiiNNi" _Py_PARSE_PID, - xf->xf_fd, // fd - family, // family - type, // type - py_laddr, // laddr - py_raddr, // raddr - status, // status - xf->xf_pid // pid - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - - free(buf); - return 1; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - free(buf); - return 0; -} - - -int psutil_gather_unix(int proto, PyObject *py_retlist) { - struct xunpgen *xug, *exug; - struct xunpcb *xup; - const char *varname = NULL; - const char *protoname = NULL; - size_t len; - size_t bufsize; - void *buf; - int retry; - struct sockaddr_un *sun; - char path[PATH_MAX]; - - PyObject *py_tuple = NULL; - PyObject *py_lpath = NULL; - - switch (proto) { - case SOCK_STREAM: - varname = "net.local.stream.pcblist"; - protoname = "stream"; - break; - case SOCK_DGRAM: - varname = "net.local.dgram.pcblist"; - protoname = "dgram"; - break; - } - - buf = NULL; - bufsize = 8192; - retry = 5; - - do { - for (;;) { - buf = realloc(buf, bufsize); - if (buf == NULL) { - PyErr_NoMemory(); - goto error; - } - len = bufsize; - if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) - break; - if (errno != ENOMEM) { - PyErr_SetFromErrno(0); - goto error; - } - bufsize *= 2; - } - xug = (struct xunpgen *)buf; - exug = (struct xunpgen *)(void *) - ((char *)buf + len - sizeof *exug); - if (xug->xug_len != sizeof *xug || exug->xug_len != sizeof *exug) { - PyErr_Format(PyExc_RuntimeError, "struct xinpgen size mismatch"); - goto error; - } - } while (xug->xug_gen != exug->xug_gen && retry--); - - for (;;) { - struct xfile *xf; - - xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); - if (xug >= exug) - break; - xup = (struct xunpcb *)xug; - if (xup->xu_len != sizeof *xup) - goto error; - - xf = psutil_get_file_from_sock(xup->xu_socket.xso_so); - if (xf == NULL) - continue; - - sun = (struct sockaddr_un *)&xup->xu_addr; - snprintf(path, sizeof(path), "%.*s", - (int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))), - sun->sun_path); - py_lpath = PyUnicode_DecodeFSDefault(path); - if (! py_lpath) - goto error; - - py_tuple = Py_BuildValue("(iiiOsii)", - xf->xf_fd, // fd - AF_UNIX, // family - proto, // type - py_lpath, // lpath - "", // rath - PSUTIL_CONN_NONE, // status - xf->xf_pid); // pid - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_lpath); - Py_DECREF(py_tuple); - } - - free(buf); - return 1; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_lpath); - free(buf); - return 0; -} - - -PyObject* -psutil_net_connections(PyObject* self, PyObject* args) { - // Return system-wide open connections. - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (psutil_populate_xfiles() != 1) - goto error; - if (psutil_gather_inet(IPPROTO_TCP, py_retlist) == 0) - goto error; - if (psutil_gather_inet(IPPROTO_UDP, py_retlist) == 0) - goto error; - if (psutil_gather_unix(SOCK_STREAM, py_retlist) == 0) - goto error; - if (psutil_gather_unix(SOCK_DGRAM, py_retlist) == 0) - goto error; - - free(psutil_xfiles); - return py_retlist; - -error: - Py_DECREF(py_retlist); - free(psutil_xfiles); - return NULL; -} diff --git a/third_party/python/psutil/psutil/arch/freebsd/sys_socks.h b/third_party/python/psutil/psutil/arch/freebsd/sys_socks.h deleted file mode 100644 index 752479265569..000000000000 --- a/third_party/python/psutil/psutil/arch/freebsd/sys_socks.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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. - */ - -#include - -PyObject* psutil_net_connections(PyObject* self, PyObject* args); diff --git a/third_party/python/psutil/psutil/arch/netbsd/socks.c b/third_party/python/psutil/psutil/arch/netbsd/socks.c deleted file mode 100644 index f370f0946671..000000000000 --- a/third_party/python/psutil/psutil/arch/netbsd/socks.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. - * Copyright (c) 2015, Ryo ONODERA. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - - -// address family filter -enum af_filter { - INET, - INET4, - INET6, - TCP, - TCP4, - TCP6, - UDP, - UDP4, - UDP6, - UNIX, - ALL, -}; - -// kinfo_file results -struct kif { - SLIST_ENTRY(kif) kifs; - struct kinfo_file *kif; -}; - -// kinfo_file results list -SLIST_HEAD(kifhead, kif) kihead = SLIST_HEAD_INITIALIZER(kihead); - - -// kinfo_pcb results -struct kpcb { - SLIST_ENTRY(kpcb) kpcbs; - struct kinfo_pcb *kpcb; -}; - -// kinfo_pcb results list -SLIST_HEAD(kpcbhead, kpcb) kpcbhead = SLIST_HEAD_INITIALIZER(kpcbhead); - -static void psutil_kiflist_init(void); -static void psutil_kiflist_clear(void); -static void psutil_kpcblist_init(void); -static void psutil_kpcblist_clear(void); -static int psutil_get_files(void); -static int psutil_get_sockets(const char *name); -static int psutil_get_info(int aff); - - -// Initialize kinfo_file results list. -static void -psutil_kiflist_init(void) { - SLIST_INIT(&kihead); - return; -} - - -// Clear kinfo_file results list. -static void -psutil_kiflist_clear(void) { - while (!SLIST_EMPTY(&kihead)) { - SLIST_REMOVE_HEAD(&kihead, kifs); - } - - return; -} - - -// Initialize kinof_pcb result list. -static void -psutil_kpcblist_init(void) { - SLIST_INIT(&kpcbhead); - return; -} - - -// Clear kinof_pcb result list. -static void -psutil_kpcblist_clear(void) { - while (!SLIST_EMPTY(&kpcbhead)) { - SLIST_REMOVE_HEAD(&kpcbhead, kpcbs); - } - - return; -} - - -// Get all open files including socket. -static int -psutil_get_files(void) { - size_t len; - size_t j; - int mib[6]; - char *buf; - off_t offset; - - mib[0] = CTL_KERN; - mib[1] = KERN_FILE2; - mib[2] = KERN_FILE_BYFILE; - mib[3] = 0; - mib[4] = sizeof(struct kinfo_file); - mib[5] = 0; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - offset = len % sizeof(off_t); - mib[5] = len / sizeof(struct kinfo_file); - - if ((buf = malloc(len + offset)) == NULL) { - PyErr_NoMemory(); - return -1; - } - - if (sysctl(mib, 6, buf + offset, &len, NULL, 0) == -1) { - free(buf); - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - len /= sizeof(struct kinfo_file); - struct kinfo_file *ki = (struct kinfo_file *)(buf + offset); - - for (j = 0; j < len; j++) { - struct kif *kif = malloc(sizeof(struct kif)); - kif->kif = &ki[j]; - SLIST_INSERT_HEAD(&kihead, kif, kifs); - } - - /* - // debug - struct kif *k; - SLIST_FOREACH(k, &kihead, kifs) { - printf("%d\n", k->kif->ki_pid); - } - */ - - return 0; -} - - -// Get open sockets. -static int -psutil_get_sockets(const char *name) { - size_t namelen; - int mib[8]; - struct kinfo_pcb *pcb; - size_t len; - size_t j; - - memset(mib, 0, sizeof(mib)); - - if (sysctlnametomib(name, mib, &namelen) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - if (sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - if ((pcb = malloc(len)) == NULL) { - PyErr_NoMemory(); - return -1; - } - memset(pcb, 0, len); - - mib[6] = sizeof(*pcb); - mib[7] = len / sizeof(*pcb); - - if (sysctl(mib, __arraycount(mib), pcb, &len, NULL, 0) == -1) { - free(pcb); - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - len /= sizeof(struct kinfo_pcb); - struct kinfo_pcb *kp = (struct kinfo_pcb *)pcb; - - for (j = 0; j < len; j++) { - struct kpcb *kpcb = malloc(sizeof(struct kpcb)); - kpcb->kpcb = &kp[j]; - SLIST_INSERT_HEAD(&kpcbhead, kpcb, kpcbs); - } - - /* - // debug - struct kif *k; - struct kpcb *k; - SLIST_FOREACH(k, &kpcbhead, kpcbs) { - printf("ki_type: %d\n", k->kpcb->ki_type); - printf("ki_family: %d\n", k->kpcb->ki_family); - } - */ - - return 0; -} - - -// Collect open file and connections. -static int -psutil_get_info(int aff) { - switch (aff) { - case INET: - if (psutil_get_sockets("net.inet.tcp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet.udp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0) - return -1; - break; - case INET4: - if (psutil_get_sockets("net.inet.tcp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet.udp.pcblist") != 0) - return -1; - break; - case INET6: - if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0) - return -1; - break; - case TCP: - if (psutil_get_sockets("net.inet.tcp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0) - return -1; - break; - case TCP4: - if (psutil_get_sockets("net.inet.tcp.pcblist") != 0) - return -1; - break; - case TCP6: - if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0) - return -1; - break; - case UDP: - if (psutil_get_sockets("net.inet.udp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0) - return -1; - break; - case UDP4: - if (psutil_get_sockets("net.inet.udp.pcblist") != 0) - return -1; - break; - case UDP6: - if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0) - return -1; - break; - case UNIX: - if (psutil_get_sockets("net.local.stream.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.local.seqpacket.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.local.dgram.pcblist") != 0) - return -1; - break; - case ALL: - if (psutil_get_sockets("net.inet.tcp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet.udp.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.tcp6.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.inet6.udp6.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.local.stream.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.local.seqpacket.pcblist") != 0) - return -1; - if (psutil_get_sockets("net.local.dgram.pcblist") != 0) - return -1; - break; - } - - return 0; -} - - -/* - * Return system-wide connections (unless a pid != -1 is passed). - */ -PyObject * -psutil_net_connections(PyObject *self, PyObject *args) { - char laddr[PATH_MAX]; - char raddr[PATH_MAX]; - int32_t lport; - int32_t rport; - int32_t status; - pid_t pid; - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - psutil_kiflist_init(); - psutil_kpcblist_init(); - if (psutil_get_files() != 0) - goto error; - if (psutil_get_info(ALL) != 0) - goto error; - - struct kif *k; - SLIST_FOREACH(k, &kihead, kifs) { - struct kpcb *kp; - if ((pid != -1) && (k->kif->ki_pid != (unsigned int)pid)) - continue; - SLIST_FOREACH(kp, &kpcbhead, kpcbs) { - if (k->kif->ki_fdata != kp->kpcb->ki_sockaddr) - continue; - - // IPv4 or IPv6 - if ((kp->kpcb->ki_family == AF_INET) || - (kp->kpcb->ki_family == AF_INET6)) { - - if (kp->kpcb->ki_family == AF_INET) { - // IPv4 - struct sockaddr_in *sin_src = - (struct sockaddr_in *)&kp->kpcb->ki_src; - struct sockaddr_in *sin_dst = - (struct sockaddr_in *)&kp->kpcb->ki_dst; - // source addr and port - inet_ntop(AF_INET, &sin_src->sin_addr, laddr, - sizeof(laddr)); - lport = ntohs(sin_src->sin_port); - // remote addr and port - inet_ntop(AF_INET, &sin_dst->sin_addr, raddr, - sizeof(raddr)); - rport = ntohs(sin_dst->sin_port); - } - else { - // IPv6 - struct sockaddr_in6 *sin6_src = - (struct sockaddr_in6 *)&kp->kpcb->ki_src; - struct sockaddr_in6 *sin6_dst = - (struct sockaddr_in6 *)&kp->kpcb->ki_dst; - // local addr and port - inet_ntop(AF_INET6, &sin6_src->sin6_addr, laddr, - sizeof(laddr)); - lport = ntohs(sin6_src->sin6_port); - // remote addr and port - inet_ntop(AF_INET6, &sin6_dst->sin6_addr, raddr, - sizeof(raddr)); - rport = ntohs(sin6_dst->sin6_port); - } - - // status - if (kp->kpcb->ki_type == SOCK_STREAM) - status = kp->kpcb->ki_tstate; - else - status = PSUTIL_CONN_NONE; - - // build addr tuple - py_laddr = Py_BuildValue("(si)", laddr, lport); - if (! py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", raddr, rport); - else - py_raddr = Py_BuildValue("()"); - if (! py_raddr) - goto error; - } - else if (kp->kpcb->ki_family == AF_UNIX) { - // UNIX sockets - struct sockaddr_un *sun_src = - (struct sockaddr_un *)&kp->kpcb->ki_src; - struct sockaddr_un *sun_dst = - (struct sockaddr_un *)&kp->kpcb->ki_dst; - strcpy(laddr, sun_src->sun_path); - strcpy(raddr, sun_dst->sun_path); - status = PSUTIL_CONN_NONE; - py_laddr = PyUnicode_DecodeFSDefault(laddr); - if (! py_laddr) - goto error; - py_raddr = PyUnicode_DecodeFSDefault(raddr); - if (! py_raddr) - goto error; - } - else { - continue; - } - - // append tuple to list - py_tuple = Py_BuildValue( - "(iiiOOii)", - k->kif->ki_fd, - kp->kpcb->ki_family, - kp->kpcb->ki_type, - py_laddr, - py_raddr, - status, - k->kif->ki_pid); - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_laddr); - Py_DECREF(py_raddr); - Py_DECREF(py_tuple); - } - } - - psutil_kiflist_clear(); - psutil_kpcblist_clear(); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - return 0; -} diff --git a/third_party/python/psutil/psutil/arch/netbsd/socks.h b/third_party/python/psutil/psutil/arch/netbsd/socks.h deleted file mode 100644 index 9e6a97c0a8c8..000000000000 --- a/third_party/python/psutil/psutil/arch/netbsd/socks.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. - * Copyright (c) 2015, Ryo ONODERA. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -PyObject *psutil_proc_connections(PyObject *, PyObject *); -PyObject *psutil_net_connections(PyObject *, PyObject *); diff --git a/third_party/python/psutil/psutil/arch/netbsd/specific.c b/third_party/python/psutil/psutil/arch/netbsd/specific.c deleted file mode 100644 index 9dab36183994..000000000000 --- a/third_party/python/psutil/psutil/arch/netbsd/specific.c +++ /dev/null @@ -1,688 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Platform-specific module methods for NetBSD. - */ - -#if defined(PSUTIL_NETBSD) - #define _KMEMUSER -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // for swap_mem -#include -#include -// connection stuff -#include // for NI_MAXHOST -#include -#include // for CPUSTATES & CP_* -#define _KERNEL // for DTYPE_* - #include -#undef _KERNEL -#include // struct diskstats -#include -#include - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" -#include "specific.h" - - -#define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0) -#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) - - -// ============================================================================ -// Utility functions -// ============================================================================ - - -int -psutil_kinfo_proc(pid_t pid, kinfo_proc *proc) { - // Fills a kinfo_proc struct based on process pid. - int ret; - int mib[6]; - size_t size = sizeof(kinfo_proc); - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC2; - mib[2] = KERN_PROC_PID; - mib[3] = pid; - mib[4] = size; - mib[5] = 1; - - ret = sysctl((int*)mib, 6, proc, &size, NULL, 0); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - // sysctl stores 0 in the size if we can't find the process information. - if (size == 0) { - NoSuchProcess("sysctl (size = 0)"); - return -1; - } - return 0; -} - - -struct kinfo_file * -kinfo_getfile(pid_t pid, int* cnt) { - // Mimic's FreeBSD kinfo_file call, taking a pid and a ptr to an - // int as arg and returns an array with cnt struct kinfo_file. - int mib[6]; - size_t len; - struct kinfo_file* kf; - mib[0] = CTL_KERN; - mib[1] = KERN_FILE2; - mib[2] = KERN_FILE_BYPID; - mib[3] = (int) pid; - mib[4] = sizeof(struct kinfo_file); - mib[5] = 0; - - // get the size of what would be returned - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if ((kf = malloc(len)) == NULL) { - PyErr_NoMemory(); - return NULL; - } - mib[5] = (int)(len / sizeof(struct kinfo_file)); - if (sysctl(mib, 6, kf, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - *cnt = (int)(len / sizeof(struct kinfo_file)); - return kf; -} - -PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) { - long pid; - - char path[MAXPATHLEN]; - size_t pathlen = sizeof path; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - -#ifdef KERN_PROC_CWD - int name[] = { CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD}; - if (sysctl(name, 4, path, &pathlen, NULL, 0) != 0) { - if (errno == ENOENT) - NoSuchProcess(""); - else - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } -#else - char *buf; - if (asprintf(&buf, "/proc/%d/cwd", (int)pid) < 0) { - PyErr_NoMemory(); - return NULL; - } - - ssize_t len = readlink(buf, path, sizeof(path) - 1); - free(buf); - if (len == -1) { - if (errno == ENOENT) - NoSuchProcess("readlink (ENOENT)"); - else - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - path[len] = '\0'; -#endif - - return PyUnicode_DecodeFSDefault(path); -} - - -// XXX: This is no longer used as per -// https://github.com/giampaolo/psutil/pull/557#issuecomment-171912820 -// Current implementation uses /proc instead. -// Left here just in case. -/* -PyObject * -psutil_proc_exe(PyObject *self, PyObject *args) { -#if __NetBSD_Version__ >= 799000000 - pid_t pid; - char pathname[MAXPATHLEN]; - int error; - int mib[4]; - int ret; - size_t size; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (pid == 0) { - // else returns ENOENT - return Py_BuildValue("s", ""); - } - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC_ARGS; - mib[2] = pid; - mib[3] = KERN_PROC_PATHNAME; - - size = sizeof(pathname); - error = sysctl(mib, 4, NULL, &size, NULL, 0); - if (error == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - error = sysctl(mib, 4, pathname, &size, NULL, 0); - if (error == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if (size == 0 || strlen(pathname) == 0) { - ret = psutil_pid_exists(pid); - if (ret == -1) - return NULL; - else if (ret == 0) - return NoSuchProcess("psutil_pid_exists"); - else - strcpy(pathname, ""); - } - - return PyUnicode_DecodeFSDefault(pathname); -#else - return Py_BuildValue("s", ""); -#endif -} -*/ - -PyObject * -psutil_proc_num_threads(PyObject *self, PyObject *args) { - // Return number of threads used by process as a Python integer. - long pid; - kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("l", (long)kp.p_nlwps); -} - -PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - pid_t pid; - int mib[5]; - int i, nlwps; - ssize_t st; - size_t size; - struct kinfo_lwp *kl = NULL; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - mib[0] = CTL_KERN; - mib[1] = KERN_LWP; - mib[2] = pid; - mib[3] = sizeof(struct kinfo_lwp); - mib[4] = 0; - - st = sysctl(mib, 5, NULL, &size, NULL, 0); - if (st == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - if (size == 0) { - NoSuchProcess("sysctl (size = 0)"); - goto error; - } - - mib[4] = size / sizeof(size_t); - kl = malloc(size); - if (kl == NULL) { - PyErr_NoMemory(); - goto error; - } - - st = sysctl(mib, 5, kl, &size, NULL, 0); - if (st == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - if (size == 0) { - NoSuchProcess("sysctl (size = 0)"); - goto error; - } - - nlwps = (int)(size / sizeof(struct kinfo_lwp)); - for (i = 0; i < nlwps; i++) { - py_tuple = Py_BuildValue("idd", - (&kl[i])->l_lid, - PSUTIL_KPT2DOUBLE((&kl[i])->l_rtime), - PSUTIL_KPT2DOUBLE((&kl[i])->l_rtime)); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - free(kl); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (kl != NULL) - free(kl); - return NULL; -} - - -// ============================================================================ -// APIS -// ============================================================================ - -int -psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) { - // Returns a list of all BSD processes on the system. This routine - // allocates the list and puts it in *procList and a count of the - // number of entries in *procCount. You are responsible for freeing - // this list (use "free" from System framework). - // On success, the function returns 0. - // On error, the function returns a BSD errno value. - kinfo_proc *result; - // Declaring name as const requires us to cast it when passing it to - // sysctl because the prototype doesn't include the const modifier. - char errbuf[_POSIX2_LINE_MAX]; - int cnt; - kvm_t *kd; - - assert( procList != NULL); - assert(*procList == NULL); - assert(procCount != NULL); - - kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); - - if (kd == NULL) { - PyErr_Format( - PyExc_RuntimeError, "kvm_openfiles() syscall failed: %s", errbuf); - return 1; - } - - result = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(kinfo_proc), &cnt); - if (result == NULL) { - PyErr_Format(PyExc_RuntimeError, "kvm_getproc2() syscall failed"); - kvm_close(kd); - return 1; - } - - *procCount = (size_t)cnt; - - size_t mlen = cnt * sizeof(kinfo_proc); - - if ((*procList = malloc(mlen)) == NULL) { - PyErr_NoMemory(); - kvm_close(kd); - return 1; - } - - memcpy(*procList, result, mlen); - assert(*procList != NULL); - kvm_close(kd); - - return 0; -} - - -char * -psutil_get_cmd_args(pid_t pid, size_t *argsize) { - int mib[4]; - int st; - size_t len; - char *procargs; - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC_ARGS; - mib[2] = pid; - mib[3] = KERN_PROC_ARGV; - len = 0; - - st = sysctl(mib, __arraycount(mib), NULL, &len, NULL, 0); - if (st == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - procargs = (char *)malloc(len); - if (procargs == NULL) { - PyErr_NoMemory(); - return NULL; - } - st = sysctl(mib, __arraycount(mib), procargs, &len, NULL, 0); - if (st == -1) { - free(procargs); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - *argsize = len; - return procargs; -} - - -// Return the command line as a python list object. -// XXX - most of the times sysctl() returns a truncated string. -// Also /proc/pid/cmdline behaves the same so it looks like this -// is a kernel bug. -PyObject * -psutil_get_cmdline(pid_t pid) { - char *argstr = NULL; - size_t pos = 0; - size_t argsize = 0; - PyObject *py_arg = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (pid == 0) - return py_retlist; - - argstr = psutil_get_cmd_args(pid, &argsize); - if (argstr == NULL) - goto error; - - // args are returned as a flattened string with \0 separators between - // arguments add each string to the list then step forward to the next - // separator - if (argsize > 0) { - while (pos < argsize) { - py_arg = PyUnicode_DecodeFSDefault(&argstr[pos]); - if (!py_arg) - goto error; - if (PyList_Append(py_retlist, py_arg)) - goto error; - Py_DECREF(py_arg); - pos = pos + strlen(&argstr[pos]) + 1; - } - } - - free(argstr); - return py_retlist; - -error: - Py_XDECREF(py_arg); - Py_DECREF(py_retlist); - if (argstr != NULL) - free(argstr); - return NULL; -} - - -/* - * Virtual memory stats, taken from: - * https://github.com/satterly/zabbix-stats/blob/master/src/libs/zbxsysinfo/ - * netbsd/memory.c - */ -PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - size_t size; - struct uvmexp_sysctl uv; - int mib[] = {CTL_VM, VM_UVMEXP2}; - long pagesize = getpagesize(); - - size = sizeof(uv); - if (sysctl(mib, 2, &uv, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("KKKKKKKK", - (unsigned long long) uv.npages << uv.pageshift, // total - (unsigned long long) uv.free << uv.pageshift, // free - (unsigned long long) uv.active << uv.pageshift, // active - (unsigned long long) uv.inactive << uv.pageshift, // inactive - (unsigned long long) uv.wired << uv.pageshift, // wired - (unsigned long long) uv.filepages + uv.execpages * pagesize, // cached - // These are determined from /proc/meminfo in Python. - (unsigned long long) 0, // buffers - (unsigned long long) 0 // shared - ); -} - - -PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { - uint64_t swap_total, swap_free; - struct swapent *swdev; - int nswap, i; - - nswap = swapctl(SWAP_NSWAP, 0, 0); - if (nswap == 0) { - // This means there's no swap partition. - return Py_BuildValue("(iiiii)", 0, 0, 0, 0, 0); - } - - swdev = calloc(nswap, sizeof(*swdev)); - if (swdev == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - if (swapctl(SWAP_STATS, swdev, nswap) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - // Total things up. - swap_total = swap_free = 0; - for (i = 0; i < nswap; i++) { - if (swdev[i].se_flags & SWF_ENABLE) { - swap_total += swdev[i].se_nblks * DEV_BSIZE; - swap_free += (swdev[i].se_nblks - swdev[i].se_inuse) * DEV_BSIZE; - } - } - free(swdev); - - // Get swap in/out - unsigned int total; - size_t size = sizeof(total); - struct uvmexp_sysctl uv; - int mib[] = {CTL_VM, VM_UVMEXP2}; - long pagesize = getpagesize(); - size = sizeof(uv); - if (sysctl(mib, 2, &uv, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - return Py_BuildValue("(LLLll)", - swap_total, - (swap_total - swap_free), - swap_free, - (long) uv.pgswapin * pagesize, // swap in - (long) uv.pgswapout * pagesize); // swap out - -error: - free(swdev); - return NULL; -} - - -PyObject * -psutil_proc_num_fds(PyObject *self, PyObject *args) { - long pid; - int cnt; - - struct kinfo_file *freep; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - errno = 0; - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_for_pid(pid, "kinfo_getfile()"); - return NULL; - } - free(freep); - - return Py_BuildValue("i", cnt); -} - - -PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - // XXX: why static? - int mib[3]; - int ncpu; - size_t len; - size_t size; - int i; - PyObject *py_cputime = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - // retrieve the number of cpus - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - uint64_t cpu_time[CPUSTATES]; - - for (i = 0; i < ncpu; i++) { - // per-cpu info - mib[0] = CTL_KERN; - mib[1] = KERN_CP_TIME; - mib[2] = i; - size = sizeof(cpu_time); - if (sysctl(mib, 3, &cpu_time, &size, NULL, 0) == -1) { - warn("failed to get kern.cptime2"); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - py_cputime = Py_BuildValue( - "(ddddd)", - (double)cpu_time[CP_USER] / CLOCKS_PER_SEC, - (double)cpu_time[CP_NICE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_SYS] / CLOCKS_PER_SEC, - (double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_INTR] / CLOCKS_PER_SEC); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_DECREF(py_cputime); - } - - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - return NULL; -} - - -PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - int i, dk_ndrive, mib[3]; - size_t len; - struct io_sysctl *stats = NULL; - PyObject *py_disk_info = NULL; - PyObject *py_retdict = PyDict_New(); - - if (py_retdict == NULL) - return NULL; - mib[0] = CTL_HW; - mib[1] = HW_IOSTATS; - mib[2] = sizeof(struct io_sysctl); - len = 0; - if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0) { - warn("can't get HW_IOSTATS"); - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - dk_ndrive = (int)(len / sizeof(struct io_sysctl)); - - stats = malloc(len); - if (stats == NULL) { - PyErr_NoMemory(); - goto error; - } - if (sysctl(mib, 3, stats, &len, NULL, 0) < 0 ) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < dk_ndrive; i++) { - py_disk_info = Py_BuildValue( - "(KKKK)", - stats[i].rxfer, - stats[i].wxfer, - stats[i].rbytes, - stats[i].wbytes - ); - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, stats[i].name, py_disk_info)) - goto error; - Py_DECREF(py_disk_info); - } - - free(stats); - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (stats != NULL) - free(stats); - return NULL; -} - - -PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - size_t size; - struct uvmexp_sysctl uv; - int uvmexp_mib[] = {CTL_VM, VM_UVMEXP2}; - - size = sizeof(uv); - if (sysctl(uvmexp_mib, 2, &uv, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue( - "IIIIIII", - uv.swtch, // ctx switches - uv.intrs, // interrupts - XXX always 0, will be determined via /proc - uv.softs, // soft interrupts - uv.syscalls, // syscalls - XXX always 0 - uv.traps, // traps - uv.faults, // faults - uv.forks // forks - ); -} diff --git a/third_party/python/psutil/psutil/arch/netbsd/specific.h b/third_party/python/psutil/psutil/arch/netbsd/specific.h deleted file mode 100644 index 391ed164a4c7..000000000000 --- a/third_party/python/psutil/psutil/arch/netbsd/specific.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include - -typedef struct kinfo_proc2 kinfo_proc; - -int psutil_kinfo_proc(pid_t pid, kinfo_proc *proc); -struct kinfo_file * kinfo_getfile(pid_t pid, int* cnt); -int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount); -char *psutil_get_cmd_args(pid_t pid, size_t *argsize); - -// -PyObject *psutil_get_cmdline(pid_t pid); -PyObject *psutil_proc_threads(PyObject *self, PyObject *args); -PyObject *psutil_virtual_mem(PyObject *self, PyObject *args); -PyObject *psutil_swap_mem(PyObject *self, PyObject *args); -PyObject *psutil_proc_num_fds(PyObject *self, PyObject *args); -PyObject *psutil_proc_connections(PyObject *self, PyObject *args); -PyObject *psutil_per_cpu_times(PyObject *self, PyObject *args); -PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args); -PyObject* psutil_proc_exe(PyObject* self, PyObject* args); -PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args); -PyObject* psutil_cpu_stats(PyObject* self, PyObject* args); -PyObject *psutil_proc_cwd(PyObject *self, PyObject *args); diff --git a/third_party/python/psutil/psutil/arch/openbsd/specific.c b/third_party/python/psutil/psutil/arch/openbsd/specific.c deleted file mode 100644 index d97a8f9b93fa..000000000000 --- a/third_party/python/psutil/psutil/arch/openbsd/specific.c +++ /dev/null @@ -1,800 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Platform-specific module methods for OpenBSD. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // for VFS_* -#include // for swap_mem -#include // for vmtotal struct -#include -#include -// connection stuff -#include // for NI_MAXHOST -#include -#include // for CPUSTATES & CP_* -#define _KERNEL // for DTYPE_* -#include -#undef _KERNEL -#include // struct diskstats -#include // for inet_ntoa() -#include // for warn() & err() - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" - -#define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0) -// #define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) - - -// ============================================================================ -// Utility functions -// ============================================================================ - - -static void -convert_kvm_err(const char *syscall, char *errbuf) { - char fullmsg[8192]; - - sprintf(fullmsg, "(originated from %s: %s)", syscall, errbuf); - if (strstr(errbuf, "Permission denied") != NULL) - AccessDenied(fullmsg); - else if (strstr(errbuf, "Operation not permitted") != NULL) - AccessDenied(fullmsg); - else - PyErr_Format(PyExc_RuntimeError, fullmsg); -} - - -int -psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc) { - // Fills a kinfo_proc struct based on process pid. - int ret; - int mib[6]; - size_t size = sizeof(struct kinfo_proc); - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = pid; - mib[4] = size; - mib[5] = 1; - - ret = sysctl((int*)mib, 6, proc, &size, NULL, 0); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - // sysctl stores 0 in the size if we can't find the process information. - if (size == 0) { - NoSuchProcess("sysctl (size = 0)"); - return -1; - } - return 0; -} - - -struct kinfo_file * -kinfo_getfile(pid_t pid, int* cnt) { - // Mimic's FreeBSD kinfo_file call, taking a pid and a ptr to an - // int as arg and returns an array with cnt struct kinfo_file. - int mib[6]; - size_t len; - struct kinfo_file* kf; - mib[0] = CTL_KERN; - mib[1] = KERN_FILE; - mib[2] = KERN_FILE_BYPID; - mib[3] = pid; - mib[4] = sizeof(struct kinfo_file); - mib[5] = 0; - - /* get the size of what would be returned */ - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if ((kf = malloc(len)) == NULL) { - PyErr_NoMemory(); - return NULL; - } - mib[5] = (int)(len / sizeof(struct kinfo_file)); - if (sysctl(mib, 6, kf, &len, NULL, 0) < 0) { - free(kf); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - *cnt = (int)(len / sizeof(struct kinfo_file)); - return kf; -} - - -// ============================================================================ -// APIS -// ============================================================================ - -int -psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) { - // Returns a list of all BSD processes on the system. This routine - // allocates the list and puts it in *procList and a count of the - // number of entries in *procCount. You are responsible for freeing - // this list (use "free" from System framework). - // On success, the function returns 0. - // On error, the function returns a BSD errno value. - struct kinfo_proc *result; - // Declaring name as const requires us to cast it when passing it to - // sysctl because the prototype doesn't include the const modifier. - char errbuf[_POSIX2_LINE_MAX]; - int cnt; - kvm_t *kd; - - assert(procList != NULL); - assert(*procList == NULL); - assert(procCount != NULL); - - kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); - if (! kd) { - convert_kvm_err("kvm_openfiles", errbuf); - return 1; - } - - result = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cnt); - if (result == NULL) { - PyErr_Format(PyExc_RuntimeError, "kvm_getprocs syscall failed"); - kvm_close(kd); - return 1; - } - - *procCount = (size_t)cnt; - - size_t mlen = cnt * sizeof(struct kinfo_proc); - - if ((*procList = malloc(mlen)) == NULL) { - PyErr_NoMemory(); - kvm_close(kd); - return 1; - } - - memcpy(*procList, result, mlen); - assert(*procList != NULL); - kvm_close(kd); - - return 0; -} - - -static char ** -_psutil_get_argv(pid_t pid) { - static char **argv; - int argv_mib[] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV}; - size_t argv_size = 128; - // Loop and reallocate until we have enough space to fit argv. - for (;; argv_size *= 2) { - if (argv_size >= 8192) { - PyErr_SetString(PyExc_RuntimeError, - "can't allocate enough space for KERN_PROC_ARGV"); - return NULL; - } - if ((argv = realloc(argv, argv_size)) == NULL) - continue; - if (sysctl(argv_mib, 4, argv, &argv_size, NULL, 0) == 0) - return argv; - if (errno == ENOMEM) - continue; - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } -} - - -// returns the command line as a python list object -PyObject * -psutil_get_cmdline(pid_t pid) { - static char **argv; - char **p; - PyObject *py_arg = NULL; - PyObject *py_retlist = Py_BuildValue("[]"); - - if (!py_retlist) - return NULL; - if (pid < 0) - return py_retlist; - - if ((argv = _psutil_get_argv(pid)) == NULL) - goto error; - - for (p = argv; *p != NULL; p++) { - py_arg = PyUnicode_DecodeFSDefault(*p); - if (!py_arg) - goto error; - if (PyList_Append(py_retlist, py_arg)) - goto error; - Py_DECREF(py_arg); - } - return py_retlist; - -error: - Py_XDECREF(py_arg); - Py_DECREF(py_retlist); - return NULL; -} - - -PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) { - // OpenBSD reference: - // https://github.com/janmojzis/pstree/blob/master/proc_kvm.c - // Note: this requires root access, else it will fail trying - // to access /dev/kmem. - pid_t pid; - kvm_t *kd = NULL; - int nentries, i; - char errbuf[4096]; - struct kinfo_proc *kp; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - goto error; - - kd = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf); - if (! kd) { - convert_kvm_err("kvm_openfiles()", errbuf); - goto error; - } - - kp = kvm_getprocs( - kd, KERN_PROC_PID | KERN_PROC_SHOW_THREADS | KERN_PROC_KTHREAD, pid, - sizeof(*kp), &nentries); - if (! kp) { - if (strstr(errbuf, "Permission denied") != NULL) - AccessDenied("kvm_getprocs"); - else - PyErr_Format(PyExc_RuntimeError, "kvm_getprocs() syscall failed"); - goto error; - } - - for (i = 0; i < nentries; i++) { - if (kp[i].p_tid < 0) - continue; - if (kp[i].p_pid == pid) { - py_tuple = Py_BuildValue( - _Py_PARSE_PID "dd", - kp[i].p_tid, - PSUTIL_KPT2DOUBLE(kp[i].p_uutime), - PSUTIL_KPT2DOUBLE(kp[i].p_ustime)); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - } - - kvm_close(kd); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (kd != NULL) - kvm_close(kd); - return NULL; -} - - -PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - int64_t total_physmem; - int uvmexp_mib[] = {CTL_VM, VM_UVMEXP}; - int bcstats_mib[] = {CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT}; - int physmem_mib[] = {CTL_HW, HW_PHYSMEM64}; - int vmmeter_mib[] = {CTL_VM, VM_METER}; - size_t size; - struct uvmexp uvmexp; - struct bcachestats bcstats; - struct vmtotal vmdata; - long pagesize = getpagesize(); - - size = sizeof(total_physmem); - if (sysctl(physmem_mib, 2, &total_physmem, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - size = sizeof(uvmexp); - if (sysctl(uvmexp_mib, 2, &uvmexp, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - size = sizeof(bcstats); - if (sysctl(bcstats_mib, 3, &bcstats, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - size = sizeof(vmdata); - if (sysctl(vmmeter_mib, 2, &vmdata, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("KKKKKKKK", - // Note: many programs calculate total memory as - // "uvmexp.npages * pagesize" but this is incorrect and does not - // match "sysctl | grep hw.physmem". - (unsigned long long) total_physmem, - (unsigned long long) uvmexp.free * pagesize, - (unsigned long long) uvmexp.active * pagesize, - (unsigned long long) uvmexp.inactive * pagesize, - (unsigned long long) uvmexp.wired * pagesize, - // this is how "top" determines it - (unsigned long long) bcstats.numbufpages * pagesize, // cached - (unsigned long long) 0, // buffers - (unsigned long long) vmdata.t_vmshr + vmdata.t_rmshr // shared - ); -} - - -PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) { - uint64_t swap_total, swap_free; - struct swapent *swdev; - int nswap, i; - - if ((nswap = swapctl(SWAP_NSWAP, 0, 0)) == 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - if ((swdev = calloc(nswap, sizeof(*swdev))) == NULL) { - PyErr_NoMemory(); - return NULL; - } - - if (swapctl(SWAP_STATS, swdev, nswap) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - // Total things up. - swap_total = swap_free = 0; - for (i = 0; i < nswap; i++) { - if (swdev[i].se_flags & SWF_ENABLE) { - swap_free += (swdev[i].se_nblks - swdev[i].se_inuse); - swap_total += swdev[i].se_nblks; - } - } - - free(swdev); - return Py_BuildValue("(LLLII)", - swap_total * DEV_BSIZE, - (swap_total - swap_free) * DEV_BSIZE, - swap_free * DEV_BSIZE, - // swap in / swap out is not supported as the - // swapent struct does not provide any info - // about it. - 0, 0); - -error: - free(swdev); - return NULL; -} - - -PyObject * -psutil_proc_num_fds(PyObject *self, PyObject *args) { - pid_t pid; - int cnt; - - struct kinfo_file *freep; - struct kinfo_proc kipp; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - - if (psutil_kinfo_proc(pid, &kipp) == -1) - return NULL; - - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) - return NULL; - - free(freep); - return Py_BuildValue("i", cnt); -} - - -PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) { - // Reference: - // https://github.com/openbsd/src/blob/ - // 588f7f8c69786211f2d16865c552afb91b1c7cba/bin/ps/print.c#L191 - pid_t pid; - struct kinfo_proc kp; - char path[MAXPATHLEN]; - size_t pathlen = sizeof path; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - - int name[] = { CTL_KERN, KERN_PROC_CWD, pid }; - if (sysctl(name, 3, path, &pathlen, NULL, 0) != 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - return PyUnicode_DecodeFSDefault(path); -} - - -// see sys/kern/kern_sysctl.c lines 1100 and -// usr.bin/fstat/fstat.c print_inet_details() -static char * -psutil_convert_ipv4(int family, uint32_t addr[4]) { - struct in_addr a; - memcpy(&a, addr, sizeof(a)); - return inet_ntoa(a); -} - - -static char * -psutil_inet6_addrstr(struct in6_addr *p) -{ - struct sockaddr_in6 sin6; - static char hbuf[NI_MAXHOST]; - const int niflags = NI_NUMERICHOST; - - memset(&sin6, 0, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_len = sizeof(struct sockaddr_in6); - sin6.sin6_addr = *p; - if (IN6_IS_ADDR_LINKLOCAL(p) && - *(u_int16_t *)&sin6.sin6_addr.s6_addr[2] != 0) { - sin6.sin6_scope_id = - ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); - sin6.sin6_addr.s6_addr[2] = sin6.sin6_addr.s6_addr[3] = 0; - } - - if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, - hbuf, sizeof(hbuf), NULL, 0, niflags)) - return "invalid"; - - return hbuf; -} - - -/* - * List process connections. - * Note: there is no net_connections() on OpenBSD. The Python - * implementation will iterate over all processes and use this - * function. - * Note: local and remote paths cannot be determined for UNIX sockets. - */ -PyObject * -psutil_proc_connections(PyObject *self, PyObject *args) { - pid_t pid; - int i; - int cnt; - struct kinfo_file *freep = NULL; - struct kinfo_file *kif; - char *tcplist = NULL; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - PyObject *py_af_filter = NULL; - PyObject *py_type_filter = NULL; - PyObject *py_family = NULL; - PyObject *_type = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "OO", &pid, &py_af_filter, - &py_type_filter)) - goto error; - if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) { - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - goto error; - } - - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - goto error; - } - - for (i = 0; i < cnt; i++) { - int state; - int lport; - int rport; - char addrbuf[NI_MAXHOST + 2]; - int inseq; - struct in6_addr laddr6; - py_tuple = NULL; - py_laddr = NULL; - py_raddr = NULL; - - kif = &freep[i]; - if (kif->f_type == DTYPE_SOCKET) { - // apply filters - py_family = PyLong_FromLong((long)kif->so_family); - inseq = PySequence_Contains(py_af_filter, py_family); - Py_DECREF(py_family); - if (inseq == 0) - continue; - _type = PyLong_FromLong((long)kif->so_type); - inseq = PySequence_Contains(py_type_filter, _type); - Py_DECREF(_type); - if (inseq == 0) - continue; - - // IPv4 / IPv6 socket - if ((kif->so_family == AF_INET) || (kif->so_family == AF_INET6)) { - // fill status - if (kif->so_type == SOCK_STREAM) - state = kif->t_state; - else - state = PSUTIL_CONN_NONE; - - // ports - lport = ntohs(kif->inp_lport); - rport = ntohs(kif->inp_fport); - - // local address, IPv4 - if (kif->so_family == AF_INET) { - py_laddr = Py_BuildValue( - "(si)", - psutil_convert_ipv4(kif->so_family, kif->inp_laddru), - lport); - if (!py_laddr) - goto error; - } - else { - // local address, IPv6 - memcpy(&laddr6, kif->inp_laddru, sizeof(laddr6)); - snprintf(addrbuf, sizeof(addrbuf), "%s", - psutil_inet6_addrstr(&laddr6)); - py_laddr = Py_BuildValue("(si)", addrbuf, lport); - if (!py_laddr) - goto error; - } - - if (rport != 0) { - // remote address, IPv4 - if (kif->so_family == AF_INET) { - py_raddr = Py_BuildValue( - "(si)", - psutil_convert_ipv4( - kif->so_family, kif->inp_faddru), - rport); - } - else { - // remote address, IPv6 - memcpy(&laddr6, kif->inp_faddru, sizeof(laddr6)); - snprintf(addrbuf, sizeof(addrbuf), "%s", - psutil_inet6_addrstr(&laddr6)); - py_raddr = Py_BuildValue("(si)", addrbuf, rport); - if (!py_raddr) - goto error; - } - } - else { - py_raddr = Py_BuildValue("()"); - } - - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue( - "(iiiNNi)", - kif->fd_fd, - kif->so_family, - kif->so_type, - py_laddr, - py_raddr, - state); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - // UNIX socket. - // XXX: local addr is supposed to be in "unp_path" but it - // always empty; also "fstat" command is not able to show - // UNIX socket paths. - else if (kif->so_family == AF_UNIX) { - py_tuple = Py_BuildValue( - "(iiissi)", - kif->fd_fd, - kif->so_family, - kif->so_type, - "", // laddr (kif->unp_path is empty) - "", // raddr - PSUTIL_CONN_NONE); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - Py_INCREF(Py_None); - } - } - } - free(freep); - free(tcplist); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - Py_DECREF(py_retlist); - if (freep != NULL) - free(freep); - if (tcplist != NULL) - free(tcplist); - return NULL; -} - - -PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - int mib[3]; - int ncpu; - size_t len; - size_t size; - int i; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - - // retrieve the number of cpus - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - uint64_t cpu_time[CPUSTATES]; - - for (i = 0; i < ncpu; i++) { - // per-cpu info - mib[0] = CTL_KERN; - mib[1] = KERN_CPTIME2; - mib[2] = i; - size = sizeof(cpu_time); - if (sysctl(mib, 3, &cpu_time, &size, NULL, 0) == -1) { - warn("failed to get kern.cptime2"); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - py_cputime = Py_BuildValue( - "(ddddd)", - (double)cpu_time[CP_USER] / CLOCKS_PER_SEC, - (double)cpu_time[CP_NICE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_SYS] / CLOCKS_PER_SEC, - (double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_INTR] / CLOCKS_PER_SEC); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_DECREF(py_cputime); - } - - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - return NULL; -} - - -PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - int i, dk_ndrive, mib[3]; - size_t len; - struct diskstats *stats = NULL; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - if (py_retdict == NULL) - return NULL; - - mib[0] = CTL_HW; - mib[1] = HW_DISKSTATS; - len = 0; - if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0) { - warn("can't get hw.diskstats size"); - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - dk_ndrive = (int)(len / sizeof(struct diskstats)); - - stats = malloc(len); - if (stats == NULL) { - warn("can't malloc"); - PyErr_NoMemory(); - goto error; - } - if (sysctl(mib, 2, stats, &len, NULL, 0) < 0 ) { - warn("could not read hw.diskstats"); - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < dk_ndrive; i++) { - py_disk_info = Py_BuildValue( - "(KKKK)", - stats[i].ds_rxfer, // num reads - stats[i].ds_wxfer, // num writes - stats[i].ds_rbytes, // read bytes - stats[i].ds_wbytes // write bytes - ); - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, stats[i].ds_name, py_disk_info)) - goto error; - Py_DECREF(py_disk_info); - } - - free(stats); - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (stats != NULL) - free(stats); - return NULL; -} - - -PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - size_t size; - struct uvmexp uv; - int uvmexp_mib[] = {CTL_VM, VM_UVMEXP}; - - size = sizeof(uv); - if (sysctl(uvmexp_mib, 2, &uv, &size, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue( - "IIIIIII", - uv.swtch, // ctx switches - uv.intrs, // interrupts - XXX always 0, will be determined via /proc - uv.softs, // soft interrupts - uv.syscalls, // syscalls - XXX always 0 - uv.traps, // traps - uv.faults, // faults - uv.forks // forks - ); -} diff --git a/third_party/python/psutil/psutil/arch/openbsd/specific.h b/third_party/python/psutil/psutil/arch/openbsd/specific.h deleted file mode 100644 index b8170a02239b..000000000000 --- a/third_party/python/psutil/psutil/arch/openbsd/specific.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Landry Breuil. - * All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include - -typedef struct kinfo_proc kinfo_proc; - -int psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc); -struct kinfo_file * kinfo_getfile(pid_t pid, int* cnt); -int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount); -char **_psutil_get_argv(pid_t pid); -PyObject * psutil_get_cmdline(pid_t pid); - -// -PyObject *psutil_proc_threads(PyObject *self, PyObject *args); -PyObject *psutil_virtual_mem(PyObject *self, PyObject *args); -PyObject *psutil_swap_mem(PyObject *self, PyObject *args); -PyObject *psutil_proc_num_fds(PyObject *self, PyObject *args); -PyObject *psutil_proc_cwd(PyObject *self, PyObject *args); -PyObject *psutil_proc_connections(PyObject *self, PyObject *args); -PyObject *psutil_per_cpu_times(PyObject *self, PyObject *args); -PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args); -PyObject* psutil_cpu_stats(PyObject* self, PyObject* args); diff --git a/third_party/python/psutil/psutil/arch/osx/process_info.c b/third_party/python/psutil/psutil/arch/osx/process_info.c deleted file mode 100644 index 4b84a723a0f9..000000000000 --- a/third_party/python/psutil/psutil/arch/osx/process_info.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Helper functions related to fetching process information. - * Used by _psutil_osx module methods. - */ - - -#include -#include -#include -#include // for INT_MAX -#include -#include -#include -#include -#include -#include - -#include "../../_psutil_common.h" -#include "../../_psutil_posix.h" -#include "process_info.h" - -/* - * Returns a list of all BSD processes on the system. This routine - * allocates the list and puts it in *procList and a count of the - * number of entries in *procCount. You are responsible for freeing - * this list (use "free" from System framework). - * On success, the function returns 0. - * On error, the function returns a BSD errno value. - */ -int -psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) { - int mib3[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; - size_t size, size2; - void *ptr; - int err; - int lim = 8; // some limit - - assert( procList != NULL); - assert(*procList == NULL); - assert(procCount != NULL); - - *procCount = 0; - - /* - * We start by calling sysctl with ptr == NULL and size == 0. - * That will succeed, and set size to the appropriate length. - * We then allocate a buffer of at least that size and call - * sysctl with that buffer. If that succeeds, we're done. - * If that call fails with ENOMEM, we throw the buffer away - * and try again. - * Note that the loop calls sysctl with NULL again. This is - * is necessary because the ENOMEM failure case sets size to - * the amount of data returned, not the amount of data that - * could have been returned. - */ - while (lim-- > 0) { - size = 0; - if (sysctl((int *)mib3, 3, NULL, &size, NULL, 0) == -1) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_ALL)"); - return 1; - } - size2 = size + (size >> 3); // add some - if (size2 > size) { - ptr = malloc(size2); - if (ptr == NULL) - ptr = malloc(size); - else - size = size2; - } - else { - ptr = malloc(size); - } - if (ptr == NULL) { - PyErr_NoMemory(); - return 1; - } - - if (sysctl((int *)mib3, 3, ptr, &size, NULL, 0) == -1) { - err = errno; - free(ptr); - if (err != ENOMEM) { - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_PROC_ALL)"); - return 1; - } - } - else { - *procList = (kinfo_proc *)ptr; - *procCount = size / sizeof(kinfo_proc); - if (procCount <= 0) { - PyErr_Format(PyExc_RuntimeError, "no PIDs found"); - return 1; - } - return 0; // success - } - } - - PyErr_Format(PyExc_RuntimeError, "couldn't collect PIDs list"); - return 1; -} - - -// Read the maximum argument size for processes -int -psutil_get_argmax() { - int argmax; - int mib[] = { CTL_KERN, KERN_ARGMAX }; - size_t size = sizeof(argmax); - - if (sysctl(mib, 2, &argmax, &size, NULL, 0) == 0) - return argmax; - PyErr_SetFromOSErrnoWithSyscall("sysctl(KERN_ARGMAX)"); - return 0; -} - - -// Return 1 if pid refers to a zombie process else 0. -int -psutil_is_zombie(pid_t pid) { - struct kinfo_proc kp; - - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return 0; - return (kp.kp_proc.p_stat == SZOMB) ? 1 : 0; -} - - - -// return process args as a python list -PyObject * -psutil_get_cmdline(pid_t pid) { - int mib[3]; - int nargs; - size_t len; - char *procargs = NULL; - char *arg_ptr; - char *arg_end; - char *curr_arg; - size_t argmax; - - PyObject *py_arg = NULL; - PyObject *py_retlist = NULL; - - // special case for PID 0 (kernel_task) where cmdline cannot be fetched - if (pid == 0) - return Py_BuildValue("[]"); - - // read argmax and allocate memory for argument space. - argmax = psutil_get_argmax(); - if (! argmax) - goto error; - - procargs = (char *)malloc(argmax); - if (NULL == procargs) { - PyErr_NoMemory(); - goto error; - } - - // read argument space - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = pid; - if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) { - // In case of zombie process we'll get EINVAL. We translate it - // to NSP and _psosx.py will translate it to ZP. - if ((errno == EINVAL) && (psutil_pid_exists(pid))) - NoSuchProcess("sysctl"); - else - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - arg_end = &procargs[argmax]; - // copy the number of arguments to nargs - memcpy(&nargs, procargs, sizeof(nargs)); - - arg_ptr = procargs + sizeof(nargs); - len = strlen(arg_ptr); - arg_ptr += len + 1; - - if (arg_ptr == arg_end) { - free(procargs); - return Py_BuildValue("[]"); - } - - // skip ahead to the first argument - for (; arg_ptr < arg_end; arg_ptr++) { - if (*arg_ptr != '\0') - break; - } - - // iterate through arguments - curr_arg = arg_ptr; - py_retlist = Py_BuildValue("[]"); - if (!py_retlist) - goto error; - while (arg_ptr < arg_end && nargs > 0) { - if (*arg_ptr++ == '\0') { - py_arg = PyUnicode_DecodeFSDefault(curr_arg); - if (! py_arg) - goto error; - if (PyList_Append(py_retlist, py_arg)) - goto error; - Py_DECREF(py_arg); - // iterate to next arg and decrement # of args - curr_arg = arg_ptr; - nargs--; - } - } - - free(procargs); - return py_retlist; - -error: - Py_XDECREF(py_arg); - Py_XDECREF(py_retlist); - if (procargs != NULL) - free(procargs); - return NULL; -} - - -// return process environment as a python string -PyObject * -psutil_get_environ(pid_t pid) { - int mib[3]; - int nargs; - char *procargs = NULL; - char *procenv = NULL; - char *arg_ptr; - char *arg_end; - char *env_start; - size_t argmax; - PyObject *py_ret = NULL; - - // special case for PID 0 (kernel_task) where cmdline cannot be fetched - if (pid == 0) - goto empty; - - // read argmax and allocate memory for argument space. - argmax = psutil_get_argmax(); - if (! argmax) - goto error; - - procargs = (char *)malloc(argmax); - if (NULL == procargs) { - PyErr_NoMemory(); - goto error; - } - - // read argument space - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = pid; - if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) { - // In case of zombie process we'll get EINVAL. We translate it - // to NSP and _psosx.py will translate it to ZP. - if ((errno == EINVAL) && (psutil_pid_exists(pid))) - NoSuchProcess("sysctl"); - else - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - arg_end = &procargs[argmax]; - // copy the number of arguments to nargs - memcpy(&nargs, procargs, sizeof(nargs)); - - // skip executable path - arg_ptr = procargs + sizeof(nargs); - arg_ptr = memchr(arg_ptr, '\0', arg_end - arg_ptr); - - if (arg_ptr == NULL || arg_ptr == arg_end) - goto empty; - - // skip ahead to the first argument - for (; arg_ptr < arg_end; arg_ptr++) { - if (*arg_ptr != '\0') - break; - } - - // iterate through arguments - while (arg_ptr < arg_end && nargs > 0) { - if (*arg_ptr++ == '\0') - nargs--; - } - - // build an environment variable block - env_start = arg_ptr; - - procenv = calloc(1, arg_end - arg_ptr); - if (procenv == NULL) { - PyErr_NoMemory(); - goto error; - } - - while (*arg_ptr != '\0' && arg_ptr < arg_end) { - char *s = memchr(arg_ptr + 1, '\0', arg_end - arg_ptr); - - if (s == NULL) - break; - - memcpy(procenv + (arg_ptr - env_start), arg_ptr, s - arg_ptr); - - arg_ptr = s + 1; - } - - py_ret = PyUnicode_DecodeFSDefaultAndSize( - procenv, arg_ptr - env_start + 1); - if (!py_ret) { - // XXX: don't want to free() this as per: - // https://github.com/giampaolo/psutil/issues/926 - // It sucks but not sure what else to do. - procargs = NULL; - goto error; - } - - free(procargs); - free(procenv); - - return py_ret; - -empty: - if (procargs != NULL) - free(procargs); - return Py_BuildValue("s", ""); - -error: - Py_XDECREF(py_ret); - if (procargs != NULL) - free(procargs); - if (procenv != NULL) - free(procargs); - return NULL; -} - - -int -psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp) { - int mib[4]; - size_t len; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = pid; - - // fetch the info with sysctl() - len = sizeof(struct kinfo_proc); - - // now read the data from sysctl - if (sysctl(mib, 4, kp, &len, NULL, 0) == -1) { - // raise an exception and throw errno as the error - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - // sysctl succeeds but len is zero, happens when process has gone away - if (len == 0) { - NoSuchProcess("sysctl (len == 0)"); - return -1; - } - return 0; -} - - -/* - * A wrapper around proc_pidinfo(). - * Returns 0 on failure (and Python exception gets already set). - */ -int -psutil_proc_pidinfo(pid_t pid, int flavor, uint64_t arg, void *pti, int size) { - errno = 0; - int ret = proc_pidinfo(pid, flavor, arg, pti, size); - if ((ret <= 0) || ((unsigned long)ret < sizeof(pti))) { - psutil_raise_for_pid(pid, "proc_pidinfo()"); - return 0; - } - return ret; -} diff --git a/third_party/python/psutil/psutil/arch/osx/process_info.h b/third_party/python/psutil/psutil/arch/osx/process_info.h deleted file mode 100644 index 35755247aa41..000000000000 --- a/third_party/python/psutil/psutil/arch/osx/process_info.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ - -#include - -typedef struct kinfo_proc kinfo_proc; - -int psutil_get_argmax(void); -int psutil_is_zombie(pid_t pid); -int psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp); -int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount); -int psutil_proc_pidinfo( - pid_t pid, int flavor, uint64_t arg, void *pti, int size); -PyObject* psutil_get_cmdline(pid_t pid); -PyObject* psutil_get_environ(pid_t pid); diff --git a/third_party/python/psutil/psutil/arch/solaris/environ.c b/third_party/python/psutil/psutil/arch/solaris/environ.c deleted file mode 100644 index 482fe1fc1658..000000000000 --- a/third_party/python/psutil/psutil/arch/solaris/environ.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Oleksii Shevchuk. - * All rights reserved. Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - * - * Functions specific for Process.environ(). - */ - -#define _STRUCTURED_PROC 1 - -#include - -#if !defined(_LP64) && _FILE_OFFSET_BITS == 64 - #undef _FILE_OFFSET_BITS - #undef _LARGEFILE64_SOURCE -#endif - -#include -#include -#include -#include - -#include "environ.h" - - -#define STRING_SEARCH_BUF_SIZE 512 - - -/* - * Open address space of specified process and return file descriptor. - * @param pid a pid of process. - * @param procfs_path a path to mounted procfs filesystem. - * @return file descriptor or -1 in case of error. - */ -static int -open_address_space(pid_t pid, const char *procfs_path) { - int fd; - char proc_path[PATH_MAX]; - - snprintf(proc_path, PATH_MAX, "%s/%i/as", procfs_path, pid); - fd = open(proc_path, O_RDONLY); - if (fd < 0) - PyErr_SetFromErrno(PyExc_OSError); - - return fd; -} - - -/* - * Read chunk of data by offset to specified buffer of the same size. - * @param fd a file descriptor. - * @param offset an required offset in file. - * @param buf a buffer where to store result. - * @param buf_size a size of buffer where data will be stored. - * @return amount of bytes stored to the buffer or -1 in case of - * error. - */ -static int -read_offt(int fd, off_t offset, char *buf, size_t buf_size) { - size_t to_read = buf_size; - size_t stored = 0; - int r; - - while (to_read) { - r = pread(fd, buf + stored, to_read, offset + stored); - if (r < 0) - goto error; - else if (r == 0) - break; - - to_read -= r; - stored += r; - } - - return stored; - - error: - PyErr_SetFromErrno(PyExc_OSError); - return -1; -} - - -/* - * Read null-terminated string from file descriptor starting from - * specified offset. - * @param fd a file descriptor of opened address space. - * @param offset an offset in specified file descriptor. - * @return allocated null-terminated string or NULL in case of error. -*/ -static char * -read_cstring_offt(int fd, off_t offset) { - int r; - int i = 0; - off_t end = offset; - size_t len; - char buf[STRING_SEARCH_BUF_SIZE]; - char *result = NULL; - - if (lseek(fd, offset, SEEK_SET) == (off_t)-1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - // Search end of string - for (;;) { - r = read(fd, buf, sizeof(buf)); - if (r == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - else if (r == 0) { - break; - } - else { - for (i=0; i= 0 && count) - *count = env_count; - - if (env_count > 0) - result = read_cstrings_block( - as, info.pr_envp, ptr_size, env_count); - - close(as); - return result; -} - - -/* - * Free array of cstrings. - * @param array an array of cstrings returned by psutil_read_raw_env, - * psutil_read_raw_args or any other function. - * @param count a count of strings in the passed array - */ -void -psutil_free_cstrings_array(char **array, size_t count) { - int i; - - if (!array) - return; - for (i=0; i -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ifaddrs.h" - -#define MAX(x,y) ((x)>(y)?(x):(y)) -#define SIZE(p) MAX((p).ss_len,sizeof(p)) - - -static struct sockaddr * -sa_dup (struct sockaddr_storage *sa1) -{ - struct sockaddr *sa2; - size_t sz = sizeof(struct sockaddr_storage); - sa2 = (struct sockaddr *) calloc(1,sz); - memcpy(sa2,sa1,sz); - return(sa2); -} - - -void freeifaddrs (struct ifaddrs *ifp) -{ - if (NULL == ifp) return; - free(ifp->ifa_name); - free(ifp->ifa_addr); - free(ifp->ifa_netmask); - free(ifp->ifa_dstaddr); - freeifaddrs(ifp->ifa_next); - free(ifp); -} - - -int getifaddrs (struct ifaddrs **ifap) -{ - int sd = -1; - char *ccp, *ecp; - struct lifconf ifc; - struct lifreq *ifr; - struct lifnum lifn; - struct ifaddrs *cifa = NULL; /* current */ - struct ifaddrs *pifa = NULL; /* previous */ - const size_t IFREQSZ = sizeof(struct lifreq); - - sd = socket(AF_INET, SOCK_STREAM, 0); - if (sd < 0) - goto error; - - ifc.lifc_buf = NULL; - *ifap = NULL; - /* find how much memory to allocate for the SIOCGLIFCONF call */ - lifn.lifn_family = AF_UNSPEC; - lifn.lifn_flags = 0; - if (ioctl(sd, SIOCGLIFNUM, &lifn) < 0) - goto error; - - /* Sun and Apple code likes to pad the interface count here in case interfaces - * are coming up between calls */ - lifn.lifn_count += 4; - - ifc.lifc_family = AF_UNSPEC; - ifc.lifc_len = lifn.lifn_count * sizeof(struct lifreq); - ifc.lifc_buf = calloc(1, ifc.lifc_len); - if (ioctl(sd, SIOCGLIFCONF, &ifc) < 0) - goto error; - - ccp = (char *)ifc.lifc_req; - ecp = ccp + ifc.lifc_len; - - while (ccp < ecp) { - - ifr = (struct lifreq *) ccp; - cifa = (struct ifaddrs *) calloc(1, sizeof(struct ifaddrs)); - cifa->ifa_next = NULL; - cifa->ifa_name = strdup(ifr->lifr_name); - - if (pifa == NULL) *ifap = cifa; /* first one */ - else pifa->ifa_next = cifa; - - if (ioctl(sd, SIOCGLIFADDR, ifr, IFREQSZ) < 0) - goto error; - cifa->ifa_addr = sa_dup(&ifr->lifr_addr); - - if (ioctl(sd, SIOCGLIFNETMASK, ifr, IFREQSZ) < 0) - goto error; - cifa->ifa_netmask = sa_dup(&ifr->lifr_addr); - - cifa->ifa_flags = 0; - cifa->ifa_dstaddr = NULL; - - if (0 == ioctl(sd, SIOCGLIFFLAGS, ifr)) /* optional */ - cifa->ifa_flags = ifr->lifr_flags; - - if (ioctl(sd, SIOCGLIFDSTADDR, ifr, IFREQSZ) < 0) { - if (0 == ioctl(sd, SIOCGLIFBRDADDR, ifr, IFREQSZ)) - cifa->ifa_dstaddr = sa_dup(&ifr->lifr_addr); - } - else cifa->ifa_dstaddr = sa_dup(&ifr->lifr_addr); - - pifa = cifa; - ccp += IFREQSZ; - } - free(ifc.lifc_buf); - close(sd); - return 0; -error: - if (ifc.lifc_buf != NULL) - free(ifc.lifc_buf); - if (sd != -1) - close(sd); - freeifaddrs(*ifap); - return (-1); -} diff --git a/third_party/python/psutil/psutil/arch/solaris/v10/ifaddrs.h b/third_party/python/psutil/psutil/arch/solaris/v10/ifaddrs.h deleted file mode 100644 index 0953a9b99a06..000000000000 --- a/third_party/python/psutil/psutil/arch/solaris/v10/ifaddrs.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Reference: https://lists.samba.org/archive/samba-technical/2009-February/063079.html */ - - -#ifndef __IFADDRS_H__ -#define __IFADDRS_H__ - -#include -#include - -#undef ifa_dstaddr -#undef ifa_broadaddr -#define ifa_broadaddr ifa_dstaddr - -struct ifaddrs { - struct ifaddrs *ifa_next; - char *ifa_name; - unsigned int ifa_flags; - struct sockaddr *ifa_addr; - struct sockaddr *ifa_netmask; - struct sockaddr *ifa_dstaddr; -}; - -extern int getifaddrs(struct ifaddrs **); -extern void freeifaddrs(struct ifaddrs *); - -#endif diff --git a/third_party/python/psutil/psutil/arch/windows/cpu.c b/third_party/python/psutil/psutil/arch/windows/cpu.c deleted file mode 100644 index 18f32e598326..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/cpu.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * 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. - */ - -#include -#include -#include - -#include "../../_psutil_common.h" - - -/* - * Return the number of logical, active CPUs. Return 0 if undetermined. - * See discussion at: https://bugs.python.org/issue33166#msg314631 - */ -static unsigned int -psutil_get_num_cpus(int fail_on_err) { - unsigned int ncpus = 0; - - // Minimum requirement: Windows 7 - if (GetActiveProcessorCount != NULL) { - ncpus = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); - if ((ncpus == 0) && (fail_on_err == 1)) { - PyErr_SetFromWindowsErr(0); - } - } - else { - psutil_debug("GetActiveProcessorCount() not available; " - "using GetSystemInfo()"); - ncpus = (unsigned int)PSUTIL_SYSTEM_INFO.dwNumberOfProcessors; - if ((ncpus <= 0) && (fail_on_err == 1)) { - PyErr_SetString( - PyExc_RuntimeError, - "GetSystemInfo() failed to retrieve CPU count"); - } - } - return ncpus; -} - - -/* - * Retrieves system CPU timing information as a (user, system, idle) - * tuple. On a multiprocessor system, the values returned are the - * sum of the designated times across all processors. - */ -PyObject * -psutil_cpu_times(PyObject *self, PyObject *args) { - double idle, kernel, user, system; - FILETIME idle_time, kernel_time, user_time; - - if (!GetSystemTimes(&idle_time, &kernel_time, &user_time)) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - - idle = (double)((HI_T * idle_time.dwHighDateTime) + \ - (LO_T * idle_time.dwLowDateTime)); - user = (double)((HI_T * user_time.dwHighDateTime) + \ - (LO_T * user_time.dwLowDateTime)); - kernel = (double)((HI_T * kernel_time.dwHighDateTime) + \ - (LO_T * kernel_time.dwLowDateTime)); - - // Kernel time includes idle time. - // We return only busy kernel time subtracting idle time from - // kernel time. - system = (kernel - idle); - return Py_BuildValue("(ddd)", user, system, idle); -} - - -/* - * Same as above but for all system CPUs. - */ -PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) { - double idle, kernel, systemt, user, interrupt, dpc; - NTSTATUS status; - _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL; - UINT i; - unsigned int ncpus; - PyObject *py_tuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - - // retrieves number of processors - ncpus = psutil_get_num_cpus(1); - if (ncpus == 0) - goto error; - - // allocates an array of _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION - // structures, one per processor - sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \ - malloc(ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); - if (sppi == NULL) { - PyErr_NoMemory(); - goto error; - } - - // gets cpu time informations - status = NtQuerySystemInformation( - SystemProcessorPerformanceInformation, - sppi, - ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), - NULL); - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, - "NtQuerySystemInformation(SystemProcessorPerformanceInformation)" - ); - goto error; - } - - // computes system global times summing each - // processor value - idle = user = kernel = interrupt = dpc = 0; - for (i = 0; i < ncpus; i++) { - py_tuple = NULL; - user = (double)((HI_T * sppi[i].UserTime.HighPart) + - (LO_T * sppi[i].UserTime.LowPart)); - idle = (double)((HI_T * sppi[i].IdleTime.HighPart) + - (LO_T * sppi[i].IdleTime.LowPart)); - kernel = (double)((HI_T * sppi[i].KernelTime.HighPart) + - (LO_T * sppi[i].KernelTime.LowPart)); - interrupt = (double)((HI_T * sppi[i].InterruptTime.HighPart) + - (LO_T * sppi[i].InterruptTime.LowPart)); - dpc = (double)((HI_T * sppi[i].DpcTime.HighPart) + - (LO_T * sppi[i].DpcTime.LowPart)); - - // kernel time includes idle time on windows - // we return only busy kernel time subtracting - // idle time from kernel time - systemt = kernel - idle; - py_tuple = Py_BuildValue( - "(ddddd)", - user, - systemt, - idle, - interrupt, - dpc - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - } - - free(sppi); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (sppi) - free(sppi); - return NULL; -} - - -/* - * Return the number of active, logical CPUs. - */ -PyObject * -psutil_cpu_count_logical(PyObject *self, PyObject *args) { - unsigned int ncpus; - - ncpus = psutil_get_num_cpus(0); - if (ncpus != 0) - return Py_BuildValue("I", ncpus); - else - Py_RETURN_NONE; // mimick os.cpu_count() -} - - -/* - * Return the number of physical CPU cores (hyper-thread CPUs count - * is excluded). - */ -PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) { - DWORD rc; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX buffer = NULL; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX ptr = NULL; - DWORD length = 0; - DWORD offset = 0; - DWORD ncpus = 0; - DWORD prev_processor_info_size = 0; - - // GetLogicalProcessorInformationEx() is available from Windows 7 - // onward. Differently from GetLogicalProcessorInformation() - // it supports process groups, meaning this is able to report more - // than 64 CPUs. See: - // https://bugs.python.org/issue33166 - if (GetLogicalProcessorInformationEx == NULL) { - psutil_debug("Win < 7; cpu_count_phys() forced to None"); - Py_RETURN_NONE; - } - - while (1) { - rc = GetLogicalProcessorInformationEx( - RelationAll, buffer, &length); - if (rc == FALSE) { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - if (buffer) { - free(buffer); - } - buffer = \ - (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)malloc(length); - if (NULL == buffer) { - PyErr_NoMemory(); - return NULL; - } - } - else { - psutil_debug("GetLogicalProcessorInformationEx() returned ", - GetLastError()); - goto return_none; - } - } - else { - break; - } - } - - ptr = buffer; - while (offset < length) { - // Advance ptr by the size of the previous - // SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX struct. - ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) \ - (((char*)ptr) + prev_processor_info_size); - - if (ptr->Relationship == RelationProcessorCore) { - ncpus += 1; - } - - // When offset == length, we've reached the last processor - // info struct in the buffer. - offset += ptr->Size; - prev_processor_info_size = ptr->Size; - } - - free(buffer); - if (ncpus != 0) { - return Py_BuildValue("I", ncpus); - } - else { - psutil_debug("GetLogicalProcessorInformationEx() count was 0"); - Py_RETURN_NONE; // mimick os.cpu_count() - } - -return_none: - if (buffer != NULL) - free(buffer); - Py_RETURN_NONE; -} - - -/* - * Return CPU statistics. - */ -PyObject * -psutil_cpu_stats(PyObject *self, PyObject *args) { - NTSTATUS status; - _SYSTEM_PERFORMANCE_INFORMATION *spi = NULL; - _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL; - _SYSTEM_INTERRUPT_INFORMATION *InterruptInformation = NULL; - unsigned int ncpus; - UINT i; - ULONG64 dpcs = 0; - ULONG interrupts = 0; - - // retrieves number of processors - ncpus = psutil_get_num_cpus(1); - if (ncpus == 0) - goto error; - - // get syscalls / ctx switches - spi = (_SYSTEM_PERFORMANCE_INFORMATION *) \ - malloc(ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION)); - if (spi == NULL) { - PyErr_NoMemory(); - goto error; - } - status = NtQuerySystemInformation( - SystemPerformanceInformation, - spi, - ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION), - NULL); - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQuerySystemInformation(SystemPerformanceInformation)"); - goto error; - } - - // get DPCs - InterruptInformation = \ - malloc(sizeof(_SYSTEM_INTERRUPT_INFORMATION) * ncpus); - if (InterruptInformation == NULL) { - PyErr_NoMemory(); - goto error; - } - - status = NtQuerySystemInformation( - SystemInterruptInformation, - InterruptInformation, - ncpus * sizeof(SYSTEM_INTERRUPT_INFORMATION), - NULL); - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQuerySystemInformation(SystemInterruptInformation)"); - goto error; - } - for (i = 0; i < ncpus; i++) { - dpcs += InterruptInformation[i].DpcCount; - } - - // get interrupts - sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \ - malloc(ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); - if (sppi == NULL) { - PyErr_NoMemory(); - goto error; - } - - status = NtQuerySystemInformation( - SystemProcessorPerformanceInformation, - sppi, - ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), - NULL); - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, - "NtQuerySystemInformation(SystemProcessorPerformanceInformation)"); - goto error; - } - - for (i = 0; i < ncpus; i++) { - interrupts += sppi[i].InterruptCount; - } - - // done - free(spi); - free(InterruptInformation); - free(sppi); - return Py_BuildValue( - "kkkk", - spi->ContextSwitches, - interrupts, - (unsigned long)dpcs, - spi->SystemCalls - ); - -error: - if (spi) - free(spi); - if (InterruptInformation) - free(InterruptInformation); - if (sppi) - free(sppi); - return NULL; -} - - -/* - * Return CPU frequency. - */ -PyObject * -psutil_cpu_freq(PyObject *self, PyObject *args) { - PROCESSOR_POWER_INFORMATION *ppi; - NTSTATUS ret; - ULONG size; - LPBYTE pBuffer = NULL; - ULONG current; - ULONG max; - unsigned int ncpus; - - // Get the number of CPUs. - ncpus = psutil_get_num_cpus(1); - if (ncpus == 0) - return NULL; - - // Allocate size. - size = ncpus * sizeof(PROCESSOR_POWER_INFORMATION); - pBuffer = (BYTE*)LocalAlloc(LPTR, size); - if (! pBuffer) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - - // Syscall. - ret = CallNtPowerInformation( - ProcessorInformation, NULL, 0, pBuffer, size); - if (ret != 0) { - PyErr_SetString(PyExc_RuntimeError, - "CallNtPowerInformation syscall failed"); - goto error; - } - - // Results. - ppi = (PROCESSOR_POWER_INFORMATION *)pBuffer; - max = ppi->MaxMhz; - current = ppi->CurrentMhz; - LocalFree(pBuffer); - - return Py_BuildValue("kk", current, max); - -error: - if (pBuffer != NULL) - LocalFree(pBuffer); - return NULL; -} diff --git a/third_party/python/psutil/psutil/arch/windows/cpu.h b/third_party/python/psutil/psutil/arch/windows/cpu.h deleted file mode 100644 index d88c22121082..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/cpu.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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. - */ - -#include - -PyObject *psutil_cpu_count_logical(PyObject *self, PyObject *args); -PyObject *psutil_cpu_count_phys(PyObject *self, PyObject *args); -PyObject *psutil_cpu_freq(PyObject *self, PyObject *args); -PyObject *psutil_cpu_stats(PyObject *self, PyObject *args); -PyObject *psutil_cpu_times(PyObject *self, PyObject *args); -PyObject *psutil_per_cpu_times(PyObject *self, PyObject *args); diff --git a/third_party/python/psutil/psutil/arch/windows/disk.c b/third_party/python/psutil/psutil/arch/windows/disk.c deleted file mode 100644 index 45e0ee1e6290..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/disk.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * 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. - */ - -#include -#include -#include - -#include "../../_psutil_common.h" - - -#ifndef _ARRAYSIZE -#define _ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) -#endif - -static char *psutil_get_drive_type(int type) { - switch (type) { - case DRIVE_FIXED: - return "fixed"; - case DRIVE_CDROM: - return "cdrom"; - case DRIVE_REMOVABLE: - return "removable"; - case DRIVE_UNKNOWN: - return "unknown"; - case DRIVE_NO_ROOT_DIR: - return "unmounted"; - case DRIVE_REMOTE: - return "remote"; - case DRIVE_RAMDISK: - return "ramdisk"; - default: - return "?"; - } -} - - -/* - * Return path's disk total and free as a Python tuple. - */ -PyObject * -psutil_disk_usage(PyObject *self, PyObject *args) { - BOOL retval; - ULARGE_INTEGER _, total, free; - char *path; - - if (PyArg_ParseTuple(args, "u", &path)) { - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceExW((LPCWSTR)path, &_, &total, &free); - Py_END_ALLOW_THREADS - goto return_; - } - - // on Python 2 we also want to accept plain strings other - // than Unicode -#if PY_MAJOR_VERSION <= 2 - PyErr_Clear(); // drop the argument parsing error - if (PyArg_ParseTuple(args, "s", &path)) { - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceEx(path, &_, &total, &free); - Py_END_ALLOW_THREADS - goto return_; - } -#endif - - return NULL; - -return_: - if (retval == 0) - return PyErr_SetFromWindowsErrWithFilename(0, path); - else - return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); -} - - -/* - * Return a Python dict of tuples for disk I/O information. This may - * require running "diskperf -y" command first. - */ -PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) { - DISK_PERFORMANCE diskPerformance; - DWORD dwSize; - HANDLE hDevice = NULL; - char szDevice[MAX_PATH]; - char szDeviceDisplay[MAX_PATH]; - int devNum; - int i; - DWORD ioctrlSize; - BOOL ret; - PyObject *py_retdict = PyDict_New(); - PyObject *py_tuple = NULL; - - if (py_retdict == NULL) - return NULL; - // Apparently there's no way to figure out how many times we have - // to iterate in order to find valid drives. - // Let's assume 32, which is higher than 26, the number of letters - // in the alphabet (from A:\ to Z:\). - for (devNum = 0; devNum <= 32; ++devNum) { - py_tuple = NULL; - sprintf_s(szDevice, MAX_PATH, "\\\\.\\PhysicalDrive%d", devNum); - hDevice = CreateFile(szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - if (hDevice == INVALID_HANDLE_VALUE) - continue; - - // DeviceIoControl() sucks! - i = 0; - ioctrlSize = sizeof(diskPerformance); - while (1) { - i += 1; - ret = DeviceIoControl( - hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &diskPerformance, - ioctrlSize, &dwSize, NULL); - if (ret != 0) - break; // OK! - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - // Retry with a bigger buffer (+ limit for retries). - if (i <= 1024) { - ioctrlSize *= 2; - continue; - } - } - else if (GetLastError() == ERROR_INVALID_FUNCTION) { - // This happens on AppVeyor: - // https://ci.appveyor.com/project/giampaolo/psutil/build/ - // 1364/job/ascpdi271b06jle3 - // Assume it means we're dealing with some exotic disk - // and go on. - psutil_debug("DeviceIoControl -> ERROR_INVALID_FUNCTION; " - "ignore PhysicalDrive%i", devNum); - goto next; - } - else if (GetLastError() == ERROR_NOT_SUPPORTED) { - // Again, let's assume we're dealing with some exotic disk. - psutil_debug("DeviceIoControl -> ERROR_NOT_SUPPORTED; " - "ignore PhysicalDrive%i", devNum); - goto next; - } - // XXX: it seems we should also catch ERROR_INVALID_PARAMETER: - // https://sites.ualberta.ca/dept/aict/uts/software/openbsd/ - // ports/4.1/i386/openafs/w-openafs-1.4.14-transarc/ - // openafs-1.4.14/src/usd/usd_nt.c - - // XXX: we can also bump into ERROR_MORE_DATA in which case - // (quoting doc) we're supposed to retry with a bigger buffer - // and specify a new "starting point", whatever it means. - PyErr_SetFromWindowsErr(0); - goto error; - } - - sprintf_s(szDeviceDisplay, MAX_PATH, "PhysicalDrive%i", devNum); - py_tuple = Py_BuildValue( - "(IILLKK)", - diskPerformance.ReadCount, - diskPerformance.WriteCount, - diskPerformance.BytesRead, - diskPerformance.BytesWritten, - // convert to ms: - // https://github.com/giampaolo/psutil/issues/1012 - (unsigned long long) - (diskPerformance.ReadTime.QuadPart) / 10000000, - (unsigned long long) - (diskPerformance.WriteTime.QuadPart) / 10000000); - if (!py_tuple) - goto error; - if (PyDict_SetItemString(py_retdict, szDeviceDisplay, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - -next: - CloseHandle(hDevice); - } - - return py_retdict; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retdict); - if (hDevice != NULL) - CloseHandle(hDevice); - return NULL; -} - - -/* - * Return disk partitions as a list of tuples such as - * (drive_letter, drive_letter, type, "") - */ -PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) { - DWORD num_bytes; - char drive_strings[255]; - char *drive_letter = drive_strings; - char mp_buf[MAX_PATH]; - char mp_path[MAX_PATH]; - int all; - int type; - int ret; - unsigned int old_mode = 0; - char opts[20]; - HANDLE mp_h; - BOOL mp_flag= TRUE; - LPTSTR fs_type[MAX_PATH + 1] = { 0 }; - DWORD pflags = 0; - PyObject *py_all; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) { - return NULL; - } - - // avoid to visualize a message box in case something goes wrong - // see https://github.com/giampaolo/psutil/issues/264 - old_mode = SetErrorMode(SEM_FAILCRITICALERRORS); - - if (! PyArg_ParseTuple(args, "O", &py_all)) - goto error; - all = PyObject_IsTrue(py_all); - - Py_BEGIN_ALLOW_THREADS - num_bytes = GetLogicalDriveStrings(254, drive_letter); - Py_END_ALLOW_THREADS - - if (num_bytes == 0) { - PyErr_SetFromWindowsErr(0); - goto error; - } - - while (*drive_letter != 0) { - py_tuple = NULL; - opts[0] = 0; - fs_type[0] = 0; - - Py_BEGIN_ALLOW_THREADS - type = GetDriveType(drive_letter); - Py_END_ALLOW_THREADS - - // by default we only show hard drives and cd-roms - if (all == 0) { - if ((type == DRIVE_UNKNOWN) || - (type == DRIVE_NO_ROOT_DIR) || - (type == DRIVE_REMOTE) || - (type == DRIVE_RAMDISK)) { - goto next; - } - // floppy disk: skip it by default as it introduces a - // considerable slowdown. - if ((type == DRIVE_REMOVABLE) && - (strcmp(drive_letter, "A:\\") == 0)) { - goto next; - } - } - - ret = GetVolumeInformation( - (LPCTSTR)drive_letter, NULL, _ARRAYSIZE(drive_letter), - NULL, NULL, &pflags, (LPTSTR)fs_type, _ARRAYSIZE(fs_type)); - if (ret == 0) { - // We might get here in case of a floppy hard drive, in - // which case the error is (21, "device not ready"). - // Let's pretend it didn't happen as we already have - // the drive name and type ('removable'). - strcat_s(opts, _countof(opts), ""); - SetLastError(0); - } - else { - if (pflags & FILE_READ_ONLY_VOLUME) - strcat_s(opts, _countof(opts), "ro"); - else - strcat_s(opts, _countof(opts), "rw"); - if (pflags & FILE_VOLUME_IS_COMPRESSED) - strcat_s(opts, _countof(opts), ",compressed"); - - // Check for mount points on this volume and add/get info - // (checks first to know if we can even have mount points) - if (pflags & FILE_SUPPORTS_REPARSE_POINTS) { - mp_h = FindFirstVolumeMountPoint( - drive_letter, mp_buf, MAX_PATH); - if (mp_h != INVALID_HANDLE_VALUE) { - while (mp_flag) { - - // Append full mount path with drive letter - strcpy_s(mp_path, _countof(mp_path), drive_letter); - strcat_s(mp_path, _countof(mp_path), mp_buf); - - py_tuple = Py_BuildValue( - "(ssss)", - drive_letter, - mp_path, - fs_type, // Typically NTFS - opts); - - if (!py_tuple || - PyList_Append(py_retlist, py_tuple) == -1) { - FindVolumeMountPointClose(mp_h); - goto error; - } - - Py_CLEAR(py_tuple); - - // Continue looking for more mount points - mp_flag = FindNextVolumeMountPoint( - mp_h, mp_buf, MAX_PATH); - } - FindVolumeMountPointClose(mp_h); - } - - } - } - - if (strlen(opts) > 0) - strcat_s(opts, _countof(opts), ","); - strcat_s(opts, _countof(opts), psutil_get_drive_type(type)); - - py_tuple = Py_BuildValue( - "(ssss)", - drive_letter, - drive_letter, - fs_type, // either FAT, FAT32, NTFS, HPFS, CDFS, UDF or NWFS - opts); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - goto next; - -next: - drive_letter = strchr(drive_letter, 0) + 1; - } - - SetErrorMode(old_mode); - return py_retlist; - -error: - SetErrorMode(old_mode); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - return NULL; -} - - -/* - Accept a filename's drive in native format like "\Device\HarddiskVolume1\" - and return the corresponding drive letter (e.g. "C:\\"). - If no match is found return an empty string. -*/ -PyObject * -psutil_win32_QueryDosDevice(PyObject *self, PyObject *args) { - LPCTSTR lpDevicePath; - TCHAR d = TEXT('A'); - TCHAR szBuff[5]; - - if (!PyArg_ParseTuple(args, "s", &lpDevicePath)) - return NULL; - - while (d <= TEXT('Z')) { - TCHAR szDeviceName[3] = {d, TEXT(':'), TEXT('\0')}; - TCHAR szTarget[512] = {0}; - if (QueryDosDevice(szDeviceName, szTarget, 511) != 0) { - if (_tcscmp(lpDevicePath, szTarget) == 0) { - _stprintf_s(szBuff, _countof(szBuff), TEXT("%c:"), d); - return Py_BuildValue("s", szBuff); - } - } - d++; - } - return Py_BuildValue("s", ""); -} diff --git a/third_party/python/psutil/psutil/arch/windows/disk.h b/third_party/python/psutil/psutil/arch/windows/disk.h deleted file mode 100644 index 298fb6ba0e07..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/disk.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ - -#include - -PyObject *psutil_disk_io_counters(PyObject *self, PyObject *args); -PyObject *psutil_disk_partitions(PyObject *self, PyObject *args); -PyObject *psutil_disk_usage(PyObject *self, PyObject *args); -PyObject *psutil_win32_QueryDosDevice(PyObject *self, PyObject *args); diff --git a/third_party/python/psutil/psutil/arch/windows/net.c b/third_party/python/psutil/psutil/arch/windows/net.c deleted file mode 100644 index 56c6b6f1f7e3..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/net.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * 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. - */ - -// Fixes clash between winsock2.h and windows.h -#define WIN32_LEAN_AND_MEAN - -#include -#include -#include -#include - -#include "../../_psutil_common.h" - - -static PIP_ADAPTER_ADDRESSES -psutil_get_nic_addresses() { - // allocate a 15 KB buffer to start with - int outBufLen = 15000; - DWORD dwRetVal = 0; - ULONG attempts = 0; - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - - do { - pAddresses = (IP_ADAPTER_ADDRESSES *) malloc(outBufLen); - if (pAddresses == NULL) { - PyErr_NoMemory(); - return NULL; - } - - dwRetVal = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, - &outBufLen); - if (dwRetVal == ERROR_BUFFER_OVERFLOW) { - free(pAddresses); - pAddresses = NULL; - } - else { - break; - } - - attempts++; - } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (attempts < 3)); - - if (dwRetVal != NO_ERROR) { - PyErr_SetString( - PyExc_RuntimeError, "GetAdaptersAddresses() syscall failed."); - return NULL; - } - - return pAddresses; -} - - -/* - * Return a Python list of named tuples with overall network I/O information - */ -PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) { - DWORD dwRetVal = 0; - MIB_IF_ROW2 *pIfRow = NULL; - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; - PyObject *py_retdict = PyDict_New(); - PyObject *py_nic_info = NULL; - PyObject *py_nic_name = NULL; - - if (py_retdict == NULL) - return NULL; - pAddresses = psutil_get_nic_addresses(); - if (pAddresses == NULL) - goto error; - pCurrAddresses = pAddresses; - - while (pCurrAddresses) { - py_nic_name = NULL; - py_nic_info = NULL; - - pIfRow = (MIB_IF_ROW2 *) malloc(sizeof(MIB_IF_ROW2)); - if (pIfRow == NULL) { - PyErr_NoMemory(); - goto error; - } - - SecureZeroMemory((PVOID)pIfRow, sizeof(MIB_IF_ROW2)); - pIfRow->InterfaceIndex = pCurrAddresses->IfIndex; - dwRetVal = GetIfEntry2(pIfRow); - if (dwRetVal != NO_ERROR) { - PyErr_SetString(PyExc_RuntimeError, - "GetIfEntry() or GetIfEntry2() syscalls failed."); - goto error; - } - - py_nic_info = Py_BuildValue( - "(KKKKKKKK)", - pIfRow->OutOctets, - pIfRow->InOctets, - (pIfRow->OutUcastPkts + pIfRow->OutNUcastPkts), - (pIfRow->InUcastPkts + pIfRow->InNUcastPkts), - pIfRow->InErrors, - pIfRow->OutErrors, - pIfRow->InDiscards, - pIfRow->OutDiscards); - if (!py_nic_info) - goto error; - - py_nic_name = PyUnicode_FromWideChar( - pCurrAddresses->FriendlyName, - wcslen(pCurrAddresses->FriendlyName)); - - if (py_nic_name == NULL) - goto error; - if (PyDict_SetItem(py_retdict, py_nic_name, py_nic_info)) - goto error; - Py_CLEAR(py_nic_name); - Py_CLEAR(py_nic_info); - - free(pIfRow); - pCurrAddresses = pCurrAddresses->Next; - } - - free(pAddresses); - return py_retdict; - -error: - Py_XDECREF(py_nic_name); - Py_XDECREF(py_nic_info); - Py_DECREF(py_retdict); - if (pAddresses != NULL) - free(pAddresses); - if (pIfRow != NULL) - free(pIfRow); - return NULL; -} - - -/* - * Return NICs addresses. - */ -PyObject * -psutil_net_if_addrs(PyObject *self, PyObject *args) { - unsigned int i = 0; - ULONG family; - PCTSTR intRet; - PCTSTR netmaskIntRet; - char *ptr; - char buff_addr[1024]; - char buff_macaddr[1024]; - char buff_netmask[1024]; - DWORD dwRetVal = 0; - ULONG converted_netmask; - UINT netmask_bits; - struct in_addr in_netmask; - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; - PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_address = NULL; - PyObject *py_mac_address = NULL; - PyObject *py_nic_name = NULL; - PyObject *py_netmask = NULL; - - if (py_retlist == NULL) - return NULL; - - pAddresses = psutil_get_nic_addresses(); - if (pAddresses == NULL) - goto error; - pCurrAddresses = pAddresses; - - while (pCurrAddresses) { - pUnicast = pCurrAddresses->FirstUnicastAddress; - - netmaskIntRet = NULL; - py_nic_name = NULL; - py_nic_name = PyUnicode_FromWideChar( - pCurrAddresses->FriendlyName, - wcslen(pCurrAddresses->FriendlyName)); - if (py_nic_name == NULL) - goto error; - - // MAC address - if (pCurrAddresses->PhysicalAddressLength != 0) { - ptr = buff_macaddr; - *ptr = '\0'; - for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength; i++) { - if (i == (pCurrAddresses->PhysicalAddressLength - 1)) { - sprintf_s(ptr, _countof(buff_macaddr), "%.2X\n", - (int)pCurrAddresses->PhysicalAddress[i]); - } - else { - sprintf_s(ptr, _countof(buff_macaddr), "%.2X-", - (int)pCurrAddresses->PhysicalAddress[i]); - } - ptr += 3; - } - *--ptr = '\0'; - - py_mac_address = Py_BuildValue("s", buff_macaddr); - if (py_mac_address == NULL) - goto error; - - Py_INCREF(Py_None); - Py_INCREF(Py_None); - Py_INCREF(Py_None); - py_tuple = Py_BuildValue( - "(OiOOOO)", - py_nic_name, - -1, // this will be converted later to AF_LINK - py_mac_address, - Py_None, // netmask (not supported) - Py_None, // broadcast (not supported) - Py_None // ptp (not supported on Windows) - ); - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_mac_address); - } - - // find out the IP address associated with the NIC - if (pUnicast != NULL) { - for (i = 0; pUnicast != NULL; i++) { - family = pUnicast->Address.lpSockaddr->sa_family; - if (family == AF_INET) { - struct sockaddr_in *sa_in = (struct sockaddr_in *) - pUnicast->Address.lpSockaddr; - intRet = inet_ntop(AF_INET, &(sa_in->sin_addr), buff_addr, - sizeof(buff_addr)); - if (!intRet) - goto error; - netmask_bits = pUnicast->OnLinkPrefixLength; - dwRetVal = ConvertLengthToIpv4Mask( - netmask_bits, &converted_netmask); - if (dwRetVal == NO_ERROR) { - in_netmask.s_addr = converted_netmask; - netmaskIntRet = inet_ntop( - AF_INET, &in_netmask, buff_netmask, - sizeof(buff_netmask)); - if (!netmaskIntRet) - goto error; - } - } - else if (family == AF_INET6) { - struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *) - pUnicast->Address.lpSockaddr; - intRet = inet_ntop(AF_INET6, &(sa_in6->sin6_addr), - buff_addr, sizeof(buff_addr)); - if (!intRet) - goto error; - } - else { - // we should never get here - pUnicast = pUnicast->Next; - continue; - } - -#if PY_MAJOR_VERSION >= 3 - py_address = PyUnicode_FromString(buff_addr); -#else - py_address = PyString_FromString(buff_addr); -#endif - if (py_address == NULL) - goto error; - - if (netmaskIntRet != NULL) { -#if PY_MAJOR_VERSION >= 3 - py_netmask = PyUnicode_FromString(buff_netmask); -#else - py_netmask = PyString_FromString(buff_netmask); -#endif - } else { - Py_INCREF(Py_None); - py_netmask = Py_None; - } - - Py_INCREF(Py_None); - Py_INCREF(Py_None); - py_tuple = Py_BuildValue( - "(OiOOOO)", - py_nic_name, - family, - py_address, - py_netmask, - Py_None, // broadcast (not supported) - Py_None // ptp (not supported on Windows) - ); - - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_CLEAR(py_tuple); - Py_CLEAR(py_address); - Py_CLEAR(py_netmask); - - pUnicast = pUnicast->Next; - } - } - Py_CLEAR(py_nic_name); - pCurrAddresses = pCurrAddresses->Next; - } - - free(pAddresses); - return py_retlist; - -error: - if (pAddresses) - free(pAddresses); - Py_DECREF(py_retlist); - Py_XDECREF(py_tuple); - Py_XDECREF(py_address); - Py_XDECREF(py_nic_name); - Py_XDECREF(py_netmask); - return NULL; -} - - -/* - * Provides stats about NIC interfaces installed on the system. - * TODO: get 'duplex' (currently it's hard coded to '2', aka - 'full duplex') - */ -PyObject * -psutil_net_if_stats(PyObject *self, PyObject *args) { - int i; - DWORD dwSize = 0; - DWORD dwRetVal = 0; - MIB_IFTABLE *pIfTable; - MIB_IFROW *pIfRow; - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; - char descr[MAX_PATH]; - int ifname_found; - - PyObject *py_nic_name = NULL; - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - PyObject *py_is_up = NULL; - - if (py_retdict == NULL) - return NULL; - - pAddresses = psutil_get_nic_addresses(); - if (pAddresses == NULL) - goto error; - - pIfTable = (MIB_IFTABLE *) malloc(sizeof (MIB_IFTABLE)); - if (pIfTable == NULL) { - PyErr_NoMemory(); - goto error; - } - dwSize = sizeof(MIB_IFTABLE); - if (GetIfTable(pIfTable, &dwSize, FALSE) == ERROR_INSUFFICIENT_BUFFER) { - free(pIfTable); - pIfTable = (MIB_IFTABLE *) malloc(dwSize); - if (pIfTable == NULL) { - PyErr_NoMemory(); - goto error; - } - } - // Make a second call to GetIfTable to get the actual - // data we want. - if ((dwRetVal = GetIfTable(pIfTable, &dwSize, FALSE)) != NO_ERROR) { - PyErr_SetString(PyExc_RuntimeError, "GetIfTable() syscall failed"); - goto error; - } - - for (i = 0; i < (int) pIfTable->dwNumEntries; i++) { - pIfRow = (MIB_IFROW *) & pIfTable->table[i]; - - // GetIfTable is not able to give us NIC with "friendly names" - // so we determine them via GetAdapterAddresses() which - // provides friendly names *and* descriptions and find the - // ones that match. - ifname_found = 0; - pCurrAddresses = pAddresses; - while (pCurrAddresses) { - sprintf_s(descr, MAX_PATH, "%wS", pCurrAddresses->Description); - if (lstrcmp(descr, pIfRow->bDescr) == 0) { - py_nic_name = PyUnicode_FromWideChar( - pCurrAddresses->FriendlyName, - wcslen(pCurrAddresses->FriendlyName)); - if (py_nic_name == NULL) - goto error; - ifname_found = 1; - break; - } - pCurrAddresses = pCurrAddresses->Next; - } - if (ifname_found == 0) { - // Name not found means GetAdapterAddresses() doesn't list - // this NIC, only GetIfTable, meaning it's not really a NIC - // interface so we skip it. - continue; - } - - // is up? - if ((pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || - pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL) && - pIfRow->dwAdminStatus == 1 ) { - py_is_up = Py_True; - } - else { - py_is_up = Py_False; - } - Py_INCREF(py_is_up); - - py_ifc_info = Py_BuildValue( - "(Oikk)", - py_is_up, - 2, // there's no way to know duplex so let's assume 'full' - pIfRow->dwSpeed / 1000000, // expressed in bytes, we want Mb - pIfRow->dwMtu - ); - if (!py_ifc_info) - goto error; - if (PyDict_SetItem(py_retdict, py_nic_name, py_ifc_info)) - goto error; - Py_CLEAR(py_nic_name); - Py_CLEAR(py_ifc_info); - } - - free(pIfTable); - free(pAddresses); - return py_retdict; - -error: - Py_XDECREF(py_is_up); - Py_XDECREF(py_ifc_info); - Py_XDECREF(py_nic_name); - Py_DECREF(py_retdict); - if (pIfTable != NULL) - free(pIfTable); - if (pAddresses != NULL) - free(pAddresses); - return NULL; -} diff --git a/third_party/python/psutil/psutil/arch/windows/net.h b/third_party/python/psutil/psutil/arch/windows/net.h deleted file mode 100644 index 7a6158d13b16..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/net.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ - -#include - -PyObject *psutil_net_if_addrs(PyObject *self, PyObject *args); -PyObject *psutil_net_if_stats(PyObject *self, PyObject *args); -PyObject *psutil_net_io_counters(PyObject *self, PyObject *args); diff --git a/third_party/python/psutil/psutil/arch/windows/ntextapi.h b/third_party/python/psutil/psutil/arch/windows/ntextapi.h deleted file mode 100644 index 8cb00430e29c..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/ntextapi.h +++ /dev/null @@ -1,603 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * Define Windows structs and constants which are considered private. - */ - -#if !defined(__NTEXTAPI_H__) -#define __NTEXTAPI_H__ -#include -#include - -typedef LONG NTSTATUS; - -// https://github.com/ajkhoury/TestDll/blob/master/nt_ddk.h -#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) -#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L) -#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) -#define STATUS_NOT_FOUND ((NTSTATUS)0xC0000225L) -#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L) - -// ================================================================ -// Enums -// ================================================================ - -#undef SystemExtendedHandleInformation -#define SystemExtendedHandleInformation 64 -#undef MemoryWorkingSetInformation -#define MemoryWorkingSetInformation 0x1 -#undef ObjectNameInformation -#define ObjectNameInformation 1 -#undef ProcessIoPriority -#define ProcessIoPriority 33 -#undef ProcessWow64Information -#define ProcessWow64Information 26 -#undef SystemProcessIdInformation -#define SystemProcessIdInformation 88 - -// process suspend() / resume() -typedef enum _KTHREAD_STATE { - Initialized, - Ready, - Running, - Standby, - Terminated, - Waiting, - Transition, - DeferredReady, - GateWait, - MaximumThreadState -} KTHREAD_STATE, *PKTHREAD_STATE; - -typedef enum _KWAIT_REASON { - Executive, - FreePage, - PageIn, - PoolAllocation, - DelayExecution, - Suspended, - UserRequest, - WrExecutive, - WrFreePage, - WrPageIn, - WrPoolAllocation, - WrDelayExecution, - WrSuspended, - WrUserRequest, - WrEventPair, - WrQueue, - WrLpcReceive, - WrLpcReply, - WrVirtualMemory, - WrPageOut, - WrRendezvous, - WrKeyedEvent, - WrTerminated, - WrProcessInSwap, - WrCpuRateControl, - WrCalloutStack, - WrKernel, - WrResource, - WrPushLock, - WrMutex, - WrQuantumEnd, - WrDispatchInt, - WrPreempted, - WrYieldExecution, - WrFastMutex, - WrGuardedMutex, - WrRundown, - WrAlertByThreadId, - WrDeferredPreempt, - MaximumWaitReason -} KWAIT_REASON, *PKWAIT_REASON; - -// ================================================================ -// Structs. -// ================================================================ - -// cpu_stats(), per_cpu_times() -typedef struct { - LARGE_INTEGER IdleTime; - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER DpcTime; - LARGE_INTEGER InterruptTime; - ULONG InterruptCount; -} _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; - -// cpu_stats() -typedef struct { - LARGE_INTEGER IdleProcessTime; - LARGE_INTEGER IoReadTransferCount; - LARGE_INTEGER IoWriteTransferCount; - LARGE_INTEGER IoOtherTransferCount; - ULONG IoReadOperationCount; - ULONG IoWriteOperationCount; - ULONG IoOtherOperationCount; - ULONG AvailablePages; - ULONG CommittedPages; - ULONG CommitLimit; - ULONG PeakCommitment; - ULONG PageFaultCount; - ULONG CopyOnWriteCount; - ULONG TransitionCount; - ULONG CacheTransitionCount; - ULONG DemandZeroCount; - ULONG PageReadCount; - ULONG PageReadIoCount; - ULONG CacheReadCount; - ULONG CacheIoCount; - ULONG DirtyPagesWriteCount; - ULONG DirtyWriteIoCount; - ULONG MappedPagesWriteCount; - ULONG MappedWriteIoCount; - ULONG PagedPoolPages; - ULONG NonPagedPoolPages; - ULONG PagedPoolAllocs; - ULONG PagedPoolFrees; - ULONG NonPagedPoolAllocs; - ULONG NonPagedPoolFrees; - ULONG FreeSystemPtes; - ULONG ResidentSystemCodePage; - ULONG TotalSystemDriverPages; - ULONG TotalSystemCodePages; - ULONG NonPagedPoolLookasideHits; - ULONG PagedPoolLookasideHits; - ULONG AvailablePagedPoolPages; - ULONG ResidentSystemCachePage; - ULONG ResidentPagedPoolPage; - ULONG ResidentSystemDriverPage; - ULONG CcFastReadNoWait; - ULONG CcFastReadWait; - ULONG CcFastReadResourceMiss; - ULONG CcFastReadNotPossible; - ULONG CcFastMdlReadNoWait; - ULONG CcFastMdlReadWait; - ULONG CcFastMdlReadResourceMiss; - ULONG CcFastMdlReadNotPossible; - ULONG CcMapDataNoWait; - ULONG CcMapDataWait; - ULONG CcMapDataNoWaitMiss; - ULONG CcMapDataWaitMiss; - ULONG CcPinMappedDataCount; - ULONG CcPinReadNoWait; - ULONG CcPinReadWait; - ULONG CcPinReadNoWaitMiss; - ULONG CcPinReadWaitMiss; - ULONG CcCopyReadNoWait; - ULONG CcCopyReadWait; - ULONG CcCopyReadNoWaitMiss; - ULONG CcCopyReadWaitMiss; - ULONG CcMdlReadNoWait; - ULONG CcMdlReadWait; - ULONG CcMdlReadNoWaitMiss; - ULONG CcMdlReadWaitMiss; - ULONG CcReadAheadIos; - ULONG CcLazyWriteIos; - ULONG CcLazyWritePages; - ULONG CcDataFlushes; - ULONG CcDataPages; - ULONG ContextSwitches; - ULONG FirstLevelTbFills; - ULONG SecondLevelTbFills; - ULONG SystemCalls; -} _SYSTEM_PERFORMANCE_INFORMATION; - -// cpu_stats() -typedef struct { - ULONG ContextSwitches; - ULONG DpcCount; - ULONG DpcRate; - ULONG TimeIncrement; - ULONG DpcBypassCount; - ULONG ApcBypassCount; -} _SYSTEM_INTERRUPT_INFORMATION; - -typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX { - PVOID Object; - HANDLE UniqueProcessId; - HANDLE HandleValue; - ULONG GrantedAccess; - USHORT CreatorBackTraceIndex; - USHORT ObjectTypeIndex; - ULONG HandleAttributes; - ULONG Reserved; -} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; - -typedef struct _SYSTEM_HANDLE_INFORMATION_EX { - ULONG_PTR NumberOfHandles; - ULONG_PTR Reserved; - SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1]; -} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; - -typedef struct _CLIENT_ID2 { - HANDLE UniqueProcess; - HANDLE UniqueThread; -} CLIENT_ID2, *PCLIENT_ID2; - -#define CLIENT_ID CLIENT_ID2 -#define PCLIENT_ID PCLIENT_ID2 - -typedef struct _SYSTEM_THREAD_INFORMATION2 { - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER CreateTime; - ULONG WaitTime; - PVOID StartAddress; - CLIENT_ID ClientId; - LONG Priority; - LONG BasePriority; - ULONG ContextSwitches; - ULONG ThreadState; - KWAIT_REASON WaitReason; -} SYSTEM_THREAD_INFORMATION2, *PSYSTEM_THREAD_INFORMATION2; - -#define SYSTEM_THREAD_INFORMATION SYSTEM_THREAD_INFORMATION2 -#define PSYSTEM_THREAD_INFORMATION PSYSTEM_THREAD_INFORMATION2 - -typedef struct _SYSTEM_PROCESS_INFORMATION2 { - ULONG NextEntryOffset; - ULONG NumberOfThreads; - LARGE_INTEGER SpareLi1; - LARGE_INTEGER SpareLi2; - LARGE_INTEGER SpareLi3; - LARGE_INTEGER CreateTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER KernelTime; - UNICODE_STRING ImageName; - LONG BasePriority; - HANDLE UniqueProcessId; - HANDLE InheritedFromUniqueProcessId; - ULONG HandleCount; - ULONG SessionId; - ULONG_PTR PageDirectoryBase; - SIZE_T PeakVirtualSize; - SIZE_T VirtualSize; - DWORD PageFaultCount; - SIZE_T PeakWorkingSetSize; - SIZE_T WorkingSetSize; - SIZE_T QuotaPeakPagedPoolUsage; - SIZE_T QuotaPagedPoolUsage; - SIZE_T QuotaPeakNonPagedPoolUsage; - SIZE_T QuotaNonPagedPoolUsage; - SIZE_T PagefileUsage; - SIZE_T PeakPagefileUsage; - SIZE_T PrivatePageCount; - LARGE_INTEGER ReadOperationCount; - LARGE_INTEGER WriteOperationCount; - LARGE_INTEGER OtherOperationCount; - LARGE_INTEGER ReadTransferCount; - LARGE_INTEGER WriteTransferCount; - LARGE_INTEGER OtherTransferCount; - SYSTEM_THREAD_INFORMATION Threads[1]; -} SYSTEM_PROCESS_INFORMATION2, *PSYSTEM_PROCESS_INFORMATION2; - -#define SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION2 -#define PSYSTEM_PROCESS_INFORMATION PSYSTEM_PROCESS_INFORMATION2 - -// cpu_freq() -typedef struct _PROCESSOR_POWER_INFORMATION { - ULONG Number; - ULONG MaxMhz; - ULONG CurrentMhz; - ULONG MhzLimit; - ULONG MaxIdleState; - ULONG CurrentIdleState; -} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION; - -#ifndef __IPHLPAPI_H__ -typedef struct in6_addr { - union { - UCHAR Byte[16]; - USHORT Word[8]; - } u; -} IN6_ADDR, *PIN6_ADDR, FAR *LPIN6_ADDR; -#endif - -// PEB / cmdline(), cwd(), environ() -typedef struct { - BYTE Reserved1[16]; - PVOID Reserved2[5]; - UNICODE_STRING CurrentDirectoryPath; - PVOID CurrentDirectoryHandle; - UNICODE_STRING DllPath; - UNICODE_STRING ImagePathName; - UNICODE_STRING CommandLine; - LPCWSTR env; -} RTL_USER_PROCESS_PARAMETERS_, *PRTL_USER_PROCESS_PARAMETERS_; - -// users() -typedef struct _WINSTATION_INFO { - BYTE Reserved1[72]; - ULONG SessionId; - BYTE Reserved2[4]; - FILETIME ConnectTime; - FILETIME DisconnectTime; - FILETIME LastInputTime; - FILETIME LoginTime; - BYTE Reserved3[1096]; - FILETIME CurrentTime; -} WINSTATION_INFO, *PWINSTATION_INFO; - -// cpu_count_phys() -#if (_WIN32_WINNT < 0x0601) // Windows < 7 (Vista and XP) -typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX { - LOGICAL_PROCESSOR_RELATIONSHIP Relationship; - DWORD Size; - _ANONYMOUS_UNION - union { - PROCESSOR_RELATIONSHIP Processor; - NUMA_NODE_RELATIONSHIP NumaNode; - CACHE_RELATIONSHIP Cache; - GROUP_RELATIONSHIP Group; - } DUMMYUNIONNAME; -} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, \ - *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX; -#endif - -// memory_uss() -typedef struct _MEMORY_WORKING_SET_BLOCK { - ULONG_PTR Protection : 5; - ULONG_PTR ShareCount : 3; - ULONG_PTR Shared : 1; - ULONG_PTR Node : 3; -#ifdef _WIN64 - ULONG_PTR VirtualPage : 52; -#else - ULONG VirtualPage : 20; -#endif -} MEMORY_WORKING_SET_BLOCK, *PMEMORY_WORKING_SET_BLOCK; - -// memory_uss() -typedef struct _MEMORY_WORKING_SET_INFORMATION { - ULONG_PTR NumberOfEntries; - MEMORY_WORKING_SET_BLOCK WorkingSetInfo[1]; -} MEMORY_WORKING_SET_INFORMATION, *PMEMORY_WORKING_SET_INFORMATION; - -// memory_uss() -typedef struct _PSUTIL_PROCESS_WS_COUNTERS { - SIZE_T NumberOfPages; - SIZE_T NumberOfPrivatePages; - SIZE_T NumberOfSharedPages; - SIZE_T NumberOfShareablePages; -} PSUTIL_PROCESS_WS_COUNTERS, *PPSUTIL_PROCESS_WS_COUNTERS; - -// exe() -typedef struct _SYSTEM_PROCESS_ID_INFORMATION { - HANDLE ProcessId; - UNICODE_STRING ImageName; -} SYSTEM_PROCESS_ID_INFORMATION, *PSYSTEM_PROCESS_ID_INFORMATION; - -// ==================================================================== -// PEB structs for cmdline(), cwd(), environ() -// ==================================================================== - -#ifdef _WIN64 -typedef struct { - BYTE Reserved1[2]; - BYTE BeingDebugged; - BYTE Reserved2[21]; - PVOID LoaderData; - PRTL_USER_PROCESS_PARAMETERS_ ProcessParameters; - // more fields... -} PEB_; - -// When we are a 64 bit process accessing a 32 bit (WoW64) -// process we need to use the 32 bit structure layout. -typedef struct { - USHORT Length; - USHORT MaxLength; - DWORD Buffer; -} UNICODE_STRING32; - -typedef struct { - BYTE Reserved1[16]; - DWORD Reserved2[5]; - UNICODE_STRING32 CurrentDirectoryPath; - DWORD CurrentDirectoryHandle; - UNICODE_STRING32 DllPath; - UNICODE_STRING32 ImagePathName; - UNICODE_STRING32 CommandLine; - DWORD env; -} RTL_USER_PROCESS_PARAMETERS32; - -typedef struct { - BYTE Reserved1[2]; - BYTE BeingDebugged; - BYTE Reserved2[1]; - DWORD Reserved3[2]; - DWORD Ldr; - DWORD ProcessParameters; - // more fields... -} PEB32; -#else // ! _WIN64 -typedef struct { - BYTE Reserved1[2]; - BYTE BeingDebugged; - BYTE Reserved2[1]; - PVOID Reserved3[2]; - PVOID Ldr; - PRTL_USER_PROCESS_PARAMETERS_ ProcessParameters; - // more fields... -} PEB_; - -// When we are a 32 bit (WoW64) process accessing a 64 bit process -// we need to use the 64 bit structure layout and a special function -// to read its memory. -typedef NTSTATUS (NTAPI *_NtWow64ReadVirtualMemory64)( - HANDLE ProcessHandle, - PVOID64 BaseAddress, - PVOID Buffer, - ULONG64 Size, - PULONG64 NumberOfBytesRead); - -typedef struct { - PVOID Reserved1[2]; - PVOID64 PebBaseAddress; - PVOID Reserved2[4]; - PVOID UniqueProcessId[2]; - PVOID Reserved3[2]; -} PROCESS_BASIC_INFORMATION64; - -typedef struct { - USHORT Length; - USHORT MaxLength; - PVOID64 Buffer; -} UNICODE_STRING64; - -typedef struct { - BYTE Reserved1[16]; - PVOID64 Reserved2[5]; - UNICODE_STRING64 CurrentDirectoryPath; - PVOID64 CurrentDirectoryHandle; - UNICODE_STRING64 DllPath; - UNICODE_STRING64 ImagePathName; - UNICODE_STRING64 CommandLine; - PVOID64 env; -} RTL_USER_PROCESS_PARAMETERS64; - -typedef struct { - BYTE Reserved1[2]; - BYTE BeingDebugged; - BYTE Reserved2[21]; - PVOID64 LoaderData; - PVOID64 ProcessParameters; - // more fields... -} PEB64; -#endif // _WIN64 - -// ================================================================ -// Type defs for modules loaded at runtime. -// ================================================================ - -BOOL (WINAPI *_GetLogicalProcessorInformationEx) ( - LOGICAL_PROCESSOR_RELATIONSHIP relationship, - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, - PDWORD ReturnLength); - -#define GetLogicalProcessorInformationEx _GetLogicalProcessorInformationEx - -BOOLEAN (WINAPI * _WinStationQueryInformationW) ( - HANDLE ServerHandle, - ULONG SessionId, - WINSTATIONINFOCLASS WinStationInformationClass, - PVOID pWinStationInformation, - ULONG WinStationInformationLength, - PULONG pReturnLength); - -#define WinStationQueryInformationW _WinStationQueryInformationW - -NTSTATUS (NTAPI *_NtQueryInformationProcess) ( - HANDLE ProcessHandle, - DWORD ProcessInformationClass, - PVOID ProcessInformation, - DWORD ProcessInformationLength, - PDWORD ReturnLength); - -#define NtQueryInformationProcess _NtQueryInformationProcess - -NTSTATUS (NTAPI *_NtQuerySystemInformation) ( - ULONG SystemInformationClass, - PVOID SystemInformation, - ULONG SystemInformationLength, - PULONG ReturnLength); - -#define NtQuerySystemInformation _NtQuerySystemInformation - -NTSTATUS (NTAPI *_NtSetInformationProcess) ( - HANDLE ProcessHandle, - DWORD ProcessInformationClass, - PVOID ProcessInformation, - DWORD ProcessInformationLength); - -#define NtSetInformationProcess _NtSetInformationProcess - -PSTR (NTAPI * _RtlIpv4AddressToStringA) ( - struct in_addr *Addr, - PSTR S); - -#define RtlIpv4AddressToStringA _RtlIpv4AddressToStringA - -PSTR (NTAPI * _RtlIpv6AddressToStringA) ( - struct in6_addr *Addr, - PSTR P); - -#define RtlIpv6AddressToStringA _RtlIpv6AddressToStringA - -DWORD (WINAPI * _GetExtendedTcpTable) ( - PVOID pTcpTable, - PDWORD pdwSize, - BOOL bOrder, - ULONG ulAf, - TCP_TABLE_CLASS TableClass, - ULONG Reserved); - -#define GetExtendedTcpTable _GetExtendedTcpTable - -DWORD (WINAPI * _GetExtendedUdpTable) ( - PVOID pUdpTable, - PDWORD pdwSize, - BOOL bOrder, - ULONG ulAf, - UDP_TABLE_CLASS TableClass, - ULONG Reserved); - -#define GetExtendedUdpTable _GetExtendedUdpTable - -DWORD (CALLBACK *_GetActiveProcessorCount) ( - WORD GroupNumber); - -#define GetActiveProcessorCount _GetActiveProcessorCount - -ULONGLONG (CALLBACK *_GetTickCount64) ( - void); - -#define GetTickCount64 _GetTickCount64 - -NTSTATUS (NTAPI *_NtQueryObject) ( - HANDLE Handle, - OBJECT_INFORMATION_CLASS ObjectInformationClass, - PVOID ObjectInformation, - ULONG ObjectInformationLength, - PULONG ReturnLength); - -#define NtQueryObject _NtQueryObject - -NTSTATUS (WINAPI *_RtlGetVersion) ( - PRTL_OSVERSIONINFOW lpVersionInformation -); - -#define RtlGetVersion _RtlGetVersion - -NTSTATUS (WINAPI *_NtResumeProcess) ( - HANDLE hProcess -); - -#define NtResumeProcess _NtResumeProcess - -NTSTATUS (WINAPI *_NtSuspendProcess) ( - HANDLE hProcess -); - -#define NtSuspendProcess _NtSuspendProcess - -NTSTATUS (NTAPI *_NtQueryVirtualMemory) ( - HANDLE ProcessHandle, - PVOID BaseAddress, - int MemoryInformationClass, - PVOID MemoryInformation, - SIZE_T MemoryInformationLength, - PSIZE_T ReturnLength -); - -#define NtQueryVirtualMemory _NtQueryVirtualMemory - -ULONG (WINAPI *_RtlNtStatusToDosErrorNoTeb) ( - NTSTATUS status -); - -#define RtlNtStatusToDosErrorNoTeb _RtlNtStatusToDosErrorNoTeb - -#endif // __NTEXTAPI_H__ diff --git a/third_party/python/psutil/psutil/arch/windows/process_handles.c b/third_party/python/psutil/psutil/arch/windows/process_handles.c deleted file mode 100644 index f63d4af36cef..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/process_handles.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * 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. - */ - -/* - * This module retrieves handles opened by a process. - * We use NtQuerySystemInformation to enumerate them and NtQueryObject - * to obtain the corresponding file name. - * Since NtQueryObject hangs for certain handle types we call it in a - * separate thread which gets killed if it doesn't complete within 100ms. - * This is a limitation of the Windows API and ProcessHacker uses the - * same trick: https://github.com/giampaolo/psutil/pull/597 - * - * CREDITS: original implementation was written by Jeff Tang. - * It was then rewritten by Giampaolo Rodola many years later. - * Utility functions for getting the file handles and names were re-adapted - * from the excellent ProcessHacker. - */ - -#include -#include - -#include "../../_psutil_common.h" -#include "process_utils.h" - - -#define THREAD_TIMEOUT 100 // ms -// Global object shared between the 2 threads. -PUNICODE_STRING globalFileName = NULL; - - -static int -psutil_enum_handles(PSYSTEM_HANDLE_INFORMATION_EX *handles) { - static ULONG initialBufferSize = 0x10000; - NTSTATUS status; - PVOID buffer; - ULONG bufferSize; - - bufferSize = initialBufferSize; - buffer = MALLOC_ZERO(bufferSize); - if (buffer == NULL) { - PyErr_NoMemory(); - return 1; - } - - while ((status = NtQuerySystemInformation( - SystemExtendedHandleInformation, - buffer, - bufferSize, - NULL - )) == STATUS_INFO_LENGTH_MISMATCH) - { - FREE(buffer); - bufferSize *= 2; - - // Fail if we're resizing the buffer to something very large. - if (bufferSize > 256 * 1024 * 1024) { - PyErr_SetString( - PyExc_RuntimeError, - "SystemExtendedHandleInformation buffer too big"); - return 1; - } - - buffer = MALLOC_ZERO(bufferSize); - if (buffer == NULL) { - PyErr_NoMemory(); - return 1; - } - } - - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr(status, "NtQuerySystemInformation"); - FREE(buffer); - return 1; - } - - *handles = (PSYSTEM_HANDLE_INFORMATION_EX)buffer; - return 0; -} - - -static int -psutil_get_filename(LPVOID lpvParam) { - HANDLE hFile = *((HANDLE*)lpvParam); - NTSTATUS status; - ULONG bufferSize; - ULONG attempts = 8; - - bufferSize = 0x200; - globalFileName = MALLOC_ZERO(bufferSize); - if (globalFileName == NULL) { - PyErr_NoMemory(); - goto error; - } - - - // Note: also this is supposed to hang, hence why we do it in here. - if (GetFileType(hFile) != FILE_TYPE_DISK) { - SetLastError(0); - globalFileName->Length = 0; - return 0; - } - - // A loop is needed because the I/O subsystem likes to give us the - // wrong return lengths... - do { - status = NtQueryObject( - hFile, - ObjectNameInformation, - globalFileName, - bufferSize, - &bufferSize - ); - if (status == STATUS_BUFFER_OVERFLOW || - status == STATUS_INFO_LENGTH_MISMATCH || - status == STATUS_BUFFER_TOO_SMALL) - { - FREE(globalFileName); - globalFileName = MALLOC_ZERO(bufferSize); - if (globalFileName == NULL) { - PyErr_NoMemory(); - goto error; - } - } - else { - break; - } - } while (--attempts); - - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr(status, "NtQuerySystemInformation"); - FREE(globalFileName); - globalFileName = NULL; - return 1; - } - - return 0; - -error: - if (globalFileName != NULL) { - FREE(globalFileName); - globalFileName = NULL; - } - return 1; -} - - -static DWORD -psutil_threaded_get_filename(HANDLE hFile) { - DWORD dwWait; - HANDLE hThread; - DWORD threadRetValue; - - hThread = CreateThread( - NULL, 0, (LPTHREAD_START_ROUTINE)psutil_get_filename, &hFile, 0, NULL); - if (hThread == NULL) { - PyErr_SetFromOSErrnoWithSyscall("CreateThread"); - return 1; - } - - // Wait for the worker thread to finish. - dwWait = WaitForSingleObject(hThread, THREAD_TIMEOUT); - - // If the thread hangs, kill it and cleanup. - if (dwWait == WAIT_TIMEOUT) { - psutil_debug( - "get handle name thread timed out after %i ms", THREAD_TIMEOUT); - if (TerminateThread(hThread, 0) == 0) { - PyErr_SetFromOSErrnoWithSyscall("TerminateThread"); - CloseHandle(hThread); - return 1; - } - CloseHandle(hThread); - return 0; - } - - if (dwWait == WAIT_FAILED) { - psutil_debug("WaitForSingleObject -> WAIT_FAILED"); - if (TerminateThread(hThread, 0) == 0) { - PyErr_SetFromOSErrnoWithSyscall( - "WaitForSingleObject -> WAIT_FAILED -> TerminateThread"); - CloseHandle(hThread); - return 1; - } - PyErr_SetFromOSErrnoWithSyscall("WaitForSingleObject"); - CloseHandle(hThread); - return 1; - } - - if (GetExitCodeThread(hThread, &threadRetValue) == 0) { - if (TerminateThread(hThread, 0) == 0) { - PyErr_SetFromOSErrnoWithSyscall( - "GetExitCodeThread (failed) -> TerminateThread"); - CloseHandle(hThread); - return 1; - } - - CloseHandle(hThread); - PyErr_SetFromOSErrnoWithSyscall("GetExitCodeThread"); - return 1; - } - CloseHandle(hThread); - return threadRetValue; -} - - -PyObject * -psutil_get_open_files(DWORD dwPid, HANDLE hProcess) { - PSYSTEM_HANDLE_INFORMATION_EX handlesList = NULL; - PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX hHandle = NULL; - HANDLE hFile = NULL; - ULONG i = 0; - BOOLEAN errorOccurred = FALSE; - PyObject* py_path = NULL; - PyObject* py_retlist = PyList_New(0);; - - if (!py_retlist) - return NULL; - - // Due to the use of global variables, ensure only 1 call - // to psutil_get_open_files() is running. - EnterCriticalSection(&PSUTIL_CRITICAL_SECTION); - - if (psutil_enum_handles(&handlesList) != 0) - goto error; - - for (i = 0; i < handlesList->NumberOfHandles; i++) { - hHandle = &handlesList->Handles[i]; - if ((ULONG_PTR)hHandle->UniqueProcessId != dwPid) - continue; - if (! DuplicateHandle( - hProcess, - hHandle->HandleValue, - GetCurrentProcess(), - &hFile, - 0, - TRUE, - DUPLICATE_SAME_ACCESS)) - { - // Will fail if not a regular file; just skip it. - continue; - } - - // This will set *globalFileName* global variable. - if (psutil_threaded_get_filename(hFile) != 0) - goto error; - - if (globalFileName->Length > 0) { - py_path = PyUnicode_FromWideChar(globalFileName->Buffer, - wcslen(globalFileName->Buffer)); - if (! py_path) - goto error; - if (PyList_Append(py_retlist, py_path)) - goto error; - Py_CLEAR(py_path); // also sets to NULL - } - - // Loop cleanup section. - if (globalFileName != NULL) { - FREE(globalFileName); - globalFileName = NULL; - } - CloseHandle(hFile); - hFile = NULL; - } - - goto exit; - -error: - Py_XDECREF(py_retlist); - errorOccurred = TRUE; - goto exit; - -exit: - if (hFile != NULL) - CloseHandle(hFile); - if (globalFileName != NULL) { - FREE(globalFileName); - globalFileName = NULL; - } - if (py_path != NULL) - Py_DECREF(py_path); - if (handlesList != NULL) - FREE(handlesList); - - LeaveCriticalSection(&PSUTIL_CRITICAL_SECTION); - if (errorOccurred == TRUE) - return NULL; - return py_retlist; -} diff --git a/third_party/python/psutil/psutil/arch/windows/process_handles.h b/third_party/python/psutil/psutil/arch/windows/process_handles.h deleted file mode 100644 index d1be3152d5f9..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/process_handles.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ - -#include -#include - -PyObject* psutil_get_open_files(DWORD pid, HANDLE hProcess); diff --git a/third_party/python/psutil/psutil/arch/windows/process_info.c b/third_party/python/psutil/psutil/arch/windows/process_info.c deleted file mode 100644 index 73a6991279fa..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/process_info.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Helper functions related to fetching process information. Used by - * _psutil_windows module methods. - */ - -#include -#include - -#include "../../_psutil_common.h" -#include "process_info.h" -#include "process_utils.h" - - -#ifndef _WIN64 -typedef NTSTATUS (NTAPI *__NtQueryInformationProcess)( - HANDLE ProcessHandle, - DWORD ProcessInformationClass, - PVOID ProcessInformation, - DWORD ProcessInformationLength, - PDWORD ReturnLength); -#endif - - -/* - * Given a pointer into a process's memory, figure out how much - * data can be read from it. - */ -static int -psutil_get_process_region_size(HANDLE hProcess, LPCVOID src, SIZE_T *psize) { - MEMORY_BASIC_INFORMATION info; - - if (!VirtualQueryEx(hProcess, src, &info, sizeof(info))) { - PyErr_SetFromOSErrnoWithSyscall("VirtualQueryEx"); - return -1; - } - - *psize = info.RegionSize - ((char*)src - (char*)info.BaseAddress); - return 0; -} - - -enum psutil_process_data_kind { - KIND_CMDLINE, - KIND_CWD, - KIND_ENVIRON, -}; - - -/* - * Get data from the process with the given pid. The data is returned - * in the pdata output member as a nul terminated string which must be - * freed on success. - * On success 0 is returned. On error the output parameter is not touched, - * -1 is returned, and an appropriate Python exception is set. - */ -static int -psutil_get_process_data(DWORD pid, - enum psutil_process_data_kind kind, - WCHAR **pdata, - SIZE_T *psize) { - /* This function is quite complex because there are several cases to be - considered: - - Two cases are really simple: we (i.e. the python interpreter) and the - target process are both 32 bit or both 64 bit. In that case the memory - layout of the structures matches up and all is well. - - When we are 64 bit and the target process is 32 bit we need to use - custom 32 bit versions of the structures. - - When we are 32 bit and the target process is 64 bit we need to use - custom 64 bit version of the structures. Also we need to use separate - Wow64 functions to get the information. - - A few helper structs are defined above so that the compiler can handle - calculating the correct offsets. - - Additional help also came from the following sources: - - https://github.com/kohsuke/winp and - http://wj32.org/wp/2009/01/24/howto-get-the-command-line-of-processes/ - http://stackoverflow.com/a/14012919 - http://www.drdobbs.com/embracing-64-bit-windows/184401966 - */ - SIZE_T size = 0; -#ifndef _WIN64 - static __NtQueryInformationProcess NtWow64QueryInformationProcess64 = NULL; - static _NtWow64ReadVirtualMemory64 NtWow64ReadVirtualMemory64 = NULL; -#endif - HANDLE hProcess = NULL; - LPCVOID src; - WCHAR *buffer = NULL; -#ifdef _WIN64 - LPVOID ppeb32 = NULL; -#else - PVOID64 src64; - BOOL weAreWow64; - BOOL theyAreWow64; -#endif - DWORD access = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ; - NTSTATUS status; - - hProcess = psutil_handle_from_pid(pid, access); - if (hProcess == NULL) - return -1; - -#ifdef _WIN64 - /* 64 bit case. Check if the target is a 32 bit process running in WoW64 - * mode. */ - status = NtQueryInformationProcess( - hProcess, - ProcessWow64Information, - &ppeb32, - sizeof(LPVOID), - NULL); - - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQueryInformationProcess(ProcessWow64Information)"); - goto error; - } - - if (ppeb32 != NULL) { - /* We are 64 bit. Target process is 32 bit running in WoW64 mode. */ - PEB32 peb32; - RTL_USER_PROCESS_PARAMETERS32 procParameters32; - - // read PEB - if (!ReadProcessMemory(hProcess, ppeb32, &peb32, sizeof(peb32), NULL)) { - // May fail with ERROR_PARTIAL_COPY, see: - // https://github.com/giampaolo/psutil/issues/875 - PyErr_SetFromWindowsErr(0); - goto error; - } - - // read process parameters - if (!ReadProcessMemory(hProcess, - UlongToPtr(peb32.ProcessParameters), - &procParameters32, - sizeof(procParameters32), - NULL)) - { - // May fail with ERROR_PARTIAL_COPY, see: - // https://github.com/giampaolo/psutil/issues/875 - PyErr_SetFromWindowsErr(0); - goto error; - } - - switch (kind) { - case KIND_CMDLINE: - src = UlongToPtr(procParameters32.CommandLine.Buffer), - size = procParameters32.CommandLine.Length; - break; - case KIND_CWD: - src = UlongToPtr(procParameters32.CurrentDirectoryPath.Buffer); - size = procParameters32.CurrentDirectoryPath.Length; - break; - case KIND_ENVIRON: - src = UlongToPtr(procParameters32.env); - break; - } - } else -#else - /* 32 bit case. Check if the target is also 32 bit. */ - if (!IsWow64Process(GetCurrentProcess(), &weAreWow64) || - !IsWow64Process(hProcess, &theyAreWow64)) { - PyErr_SetFromOSErrnoWithSyscall("IsWow64Process"); - goto error; - } - - if (weAreWow64 && !theyAreWow64) { - /* We are 32 bit running in WoW64 mode. Target process is 64 bit. */ - PROCESS_BASIC_INFORMATION64 pbi64; - PEB64 peb64; - RTL_USER_PROCESS_PARAMETERS64 procParameters64; - - if (NtWow64QueryInformationProcess64 == NULL) { - NtWow64QueryInformationProcess64 = \ - psutil_GetProcAddressFromLib( - "ntdll.dll", "NtWow64QueryInformationProcess64"); - if (NtWow64QueryInformationProcess64 == NULL) { - PyErr_Clear(); - AccessDenied("can't query 64-bit process in 32-bit-WoW mode"); - goto error; - } - } - if (NtWow64ReadVirtualMemory64 == NULL) { - NtWow64ReadVirtualMemory64 = \ - psutil_GetProcAddressFromLib( - "ntdll.dll", "NtWow64ReadVirtualMemory64"); - if (NtWow64ReadVirtualMemory64 == NULL) { - PyErr_Clear(); - AccessDenied("can't query 64-bit process in 32-bit-WoW mode"); - goto error; - } - } - - status = NtWow64QueryInformationProcess64( - hProcess, - ProcessBasicInformation, - &pbi64, - sizeof(pbi64), - NULL); - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, - "NtWow64QueryInformationProcess64(ProcessBasicInformation)" - ); - goto error; - } - - // read peb - status = NtWow64ReadVirtualMemory64( - hProcess, - pbi64.PebBaseAddress, - &peb64, - sizeof(peb64), - NULL); - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr(status, "NtWow64ReadVirtualMemory64"); - goto error; - } - - // read process parameters - status = NtWow64ReadVirtualMemory64( - hProcess, - peb64.ProcessParameters, - &procParameters64, - sizeof(procParameters64), - NULL); - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, - "NtWow64ReadVirtualMemory64(ProcessParameters)" - ); - goto error; - } - - switch (kind) { - case KIND_CMDLINE: - src64 = procParameters64.CommandLine.Buffer; - size = procParameters64.CommandLine.Length; - break; - case KIND_CWD: - src64 = procParameters64.CurrentDirectoryPath.Buffer, - size = procParameters64.CurrentDirectoryPath.Length; - break; - case KIND_ENVIRON: - src64 = procParameters64.env; - break; - } - } else -#endif - /* Target process is of the same bitness as us. */ - { - PROCESS_BASIC_INFORMATION pbi; - PEB_ peb; - RTL_USER_PROCESS_PARAMETERS_ procParameters; - - status = NtQueryInformationProcess( - hProcess, - ProcessBasicInformation, - &pbi, - sizeof(pbi), - NULL); - - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQueryInformationProcess(ProcessBasicInformation)"); - goto error; - } - - - // read peb - if (!ReadProcessMemory(hProcess, - pbi.PebBaseAddress, - &peb, - sizeof(peb), - NULL)) - { - // May fail with ERROR_PARTIAL_COPY, see: - // https://github.com/giampaolo/psutil/issues/875 - PyErr_SetFromWindowsErr(0); - goto error; - } - - // read process parameters - if (!ReadProcessMemory(hProcess, - peb.ProcessParameters, - &procParameters, - sizeof(procParameters), - NULL)) - { - // May fail with ERROR_PARTIAL_COPY, see: - // https://github.com/giampaolo/psutil/issues/875 - PyErr_SetFromWindowsErr(0); - goto error; - } - - switch (kind) { - case KIND_CMDLINE: - src = procParameters.CommandLine.Buffer; - size = procParameters.CommandLine.Length; - break; - case KIND_CWD: - src = procParameters.CurrentDirectoryPath.Buffer; - size = procParameters.CurrentDirectoryPath.Length; - break; - case KIND_ENVIRON: - src = procParameters.env; - break; - } - } - - if (kind == KIND_ENVIRON) { -#ifndef _WIN64 - if (weAreWow64 && !theyAreWow64) { - AccessDenied("can't query 64-bit process in 32-bit-WoW mode"); - goto error; - } - else -#endif - if (psutil_get_process_region_size(hProcess, src, &size) != 0) - goto error; - } - - buffer = calloc(size + 2, 1); - if (buffer == NULL) { - PyErr_NoMemory(); - goto error; - } - -#ifndef _WIN64 - if (weAreWow64 && !theyAreWow64) { - status = NtWow64ReadVirtualMemory64( - hProcess, - src64, - buffer, - size, - NULL); - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr(status, "NtWow64ReadVirtualMemory64"); - goto error; - } - } else -#endif - if (!ReadProcessMemory(hProcess, src, buffer, size, NULL)) { - // May fail with ERROR_PARTIAL_COPY, see: - // https://github.com/giampaolo/psutil/issues/875 - PyErr_SetFromWindowsErr(0); - goto error; - } - - CloseHandle(hProcess); - - *pdata = buffer; - *psize = size; - - return 0; - -error: - if (hProcess != NULL) - CloseHandle(hProcess); - if (buffer != NULL) - free(buffer); - return -1; -} - - -/* - * Get process cmdline by using NtQueryInformationProcess. This is a - * method alternative to PEB which is less likely to result in - * AccessDenied. Requires Windows 8.1+. - */ -static int -psutil_cmdline_query_proc(DWORD pid, WCHAR **pdata, SIZE_T *psize) { - HANDLE hProcess = NULL; - ULONG bufLen = 0; - NTSTATUS status; - char * buffer = NULL; - WCHAR * bufWchar = NULL; - PUNICODE_STRING tmp = NULL; - size_t size; - int ProcessCommandLineInformation = 60; - - if (PSUTIL_WINVER < PSUTIL_WINDOWS_8_1) { - PyErr_SetString( - PyExc_RuntimeError, "requires Windows 8.1+"); - goto error; - } - - hProcess = psutil_handle_from_pid(pid, PROCESS_QUERY_LIMITED_INFORMATION); - if (hProcess == NULL) - goto error; - - // get the right buf size - status = NtQueryInformationProcess( - hProcess, - ProcessCommandLineInformation, - NULL, - 0, - &bufLen); - - // https://github.com/giampaolo/psutil/issues/1501 - if (status == STATUS_NOT_FOUND) { - AccessDenied("NtQueryInformationProcess(ProcessBasicInformation) -> " - "STATUS_NOT_FOUND translated into PermissionError"); - goto error; - } - - if (status != STATUS_BUFFER_OVERFLOW && \ - status != STATUS_BUFFER_TOO_SMALL && \ - status != STATUS_INFO_LENGTH_MISMATCH) { - psutil_SetFromNTStatusErr( - status, "NtQueryInformationProcess(ProcessBasicInformation)"); - goto error; - } - - // allocate memory - buffer = calloc(bufLen, 1); - if (buffer == NULL) { - PyErr_NoMemory(); - goto error; - } - - // get the cmdline - status = NtQueryInformationProcess( - hProcess, - ProcessCommandLineInformation, - buffer, - bufLen, - &bufLen - ); - if (!NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQueryInformationProcess(ProcessCommandLineInformation)"); - goto error; - } - - // build the string - tmp = (PUNICODE_STRING)buffer; - size = wcslen(tmp->Buffer) + 1; - bufWchar = (WCHAR *)calloc(size, sizeof(WCHAR)); - if (bufWchar == NULL) { - PyErr_NoMemory(); - goto error; - } - wcscpy_s(bufWchar, size, tmp->Buffer); - *pdata = bufWchar; - *psize = size * sizeof(WCHAR); - free(buffer); - CloseHandle(hProcess); - return 0; - -error: - if (buffer != NULL) - free(buffer); - if (hProcess != NULL) - CloseHandle(hProcess); - return -1; -} - - -/* - * Return a Python list representing the arguments for the process - * with given pid or NULL on error. - */ -PyObject * -psutil_get_cmdline(DWORD pid, int use_peb) { - PyObject *ret = NULL; - WCHAR *data = NULL; - SIZE_T size; - PyObject *py_retlist = NULL; - PyObject *py_unicode = NULL; - LPWSTR *szArglist = NULL; - int nArgs, i; - int func_ret; - - /* - Reading the PEB to get the cmdline seem to be the best method if - somebody has tampered with the parameters after creating the process. - For instance, create a process as suspended, patch the command line - in its PEB and unfreeze it. It requires more privileges than - NtQueryInformationProcess though (the fallback): - - https://github.com/giampaolo/psutil/pull/1398 - - https://blog.xpnsec.com/how-to-argue-like-cobalt-strike/ - */ - if (use_peb == 1) - func_ret = psutil_get_process_data(pid, KIND_CMDLINE, &data, &size); - else - func_ret = psutil_cmdline_query_proc(pid, &data, &size); - if (func_ret != 0) - goto out; - - // attempt to parse the command line using Win32 API - szArglist = CommandLineToArgvW(data, &nArgs); - if (szArglist == NULL) { - PyErr_SetFromOSErrnoWithSyscall("CommandLineToArgvW"); - goto out; - } - - // arglist parsed as array of UNICODE_STRING, so convert each to - // Python string object and add to arg list - py_retlist = PyList_New(nArgs); - if (py_retlist == NULL) - goto out; - for (i = 0; i < nArgs; i++) { - py_unicode = PyUnicode_FromWideChar(szArglist[i], - wcslen(szArglist[i])); - if (py_unicode == NULL) - goto out; - PyList_SET_ITEM(py_retlist, i, py_unicode); - py_unicode = NULL; - } - ret = py_retlist; - py_retlist = NULL; - -out: - if (szArglist != NULL) - LocalFree(szArglist); - if (data != NULL) - free(data); - Py_XDECREF(py_unicode); - Py_XDECREF(py_retlist); - return ret; -} - - -PyObject * -psutil_get_cwd(DWORD pid) { - PyObject *ret = NULL; - WCHAR *data = NULL; - SIZE_T size; - - if (psutil_get_process_data(pid, KIND_CWD, &data, &size) != 0) - goto out; - - // convert wchar array to a Python unicode string - ret = PyUnicode_FromWideChar(data, wcslen(data)); - -out: - if (data != NULL) - free(data); - - return ret; -} - - -/* - * returns a Python string containing the environment variable data for the - * process with given pid or NULL on error. - */ -PyObject * -psutil_get_environ(DWORD pid) { - PyObject *ret = NULL; - WCHAR *data = NULL; - SIZE_T size; - - if (psutil_get_process_data(pid, KIND_ENVIRON, &data, &size) != 0) - goto out; - - // convert wchar array to a Python unicode string - ret = PyUnicode_FromWideChar(data, size / 2); - -out: - if (data != NULL) - free(data); - return ret; -} - - -/* - * Given a process PID and a PSYSTEM_PROCESS_INFORMATION structure - * fills the structure with various process information in one shot - * by using NtQuerySystemInformation. - * We use this as a fallback when faster functions fail with access - * denied. This is slower because it iterates over all processes - * but it doesn't require any privilege (also work for PID 0). - * On success return 1, else 0 with Python exception already set. - */ -int -psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, - PVOID *retBuffer) { - static ULONG initialBufferSize = 0x4000; - NTSTATUS status; - PVOID buffer; - ULONG bufferSize; - PSYSTEM_PROCESS_INFORMATION process; - - bufferSize = initialBufferSize; - buffer = malloc(bufferSize); - if (buffer == NULL) { - PyErr_NoMemory(); - goto error; - } - - while (TRUE) { - status = NtQuerySystemInformation( - SystemProcessInformation, - buffer, - bufferSize, - &bufferSize); - if (status == STATUS_BUFFER_TOO_SMALL || - status == STATUS_INFO_LENGTH_MISMATCH) - { - free(buffer); - buffer = malloc(bufferSize); - if (buffer == NULL) { - PyErr_NoMemory(); - goto error; - } - } - else { - break; - } - } - - if (! NT_SUCCESS(status)) { - psutil_SetFromNTStatusErr( - status, "NtQuerySystemInformation(SystemProcessInformation)"); - goto error; - } - - if (bufferSize <= 0x20000) - initialBufferSize = bufferSize; - - process = PSUTIL_FIRST_PROCESS(buffer); - do { - if ((ULONG_PTR)process->UniqueProcessId == pid) { - *retProcess = process; - *retBuffer = buffer; - return 1; - } - } while ((process = PSUTIL_NEXT_PROCESS(process))); - - NoSuchProcess("NtQuerySystemInformation (no PID found)"); - goto error; - -error: - if (buffer != NULL) - free(buffer); - return 0; -} - - -/* - * Get various process information by using NtQuerySystemInformation. - * We use this as a fallback when faster functions fail with access - * denied. This is slower because it iterates over all processes. - * Returned tuple includes the following process info: - * - * - num_threads() - * - ctx_switches() - * - num_handles() (fallback) - * - cpu_times() (fallback) - * - create_time() (fallback) - * - io_counters() (fallback) - * - memory_info() (fallback) - */ -PyObject * -psutil_proc_info(PyObject *self, PyObject *args) { - DWORD pid; - PSYSTEM_PROCESS_INFORMATION process; - PVOID buffer; - ULONG i; - ULONG ctx_switches = 0; - double user_time; - double kernel_time; - double create_time; - PyObject *py_retlist; - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid)) - return NULL; - if (! psutil_get_proc_info(pid, &process, &buffer)) - return NULL; - - for (i = 0; i < process->NumberOfThreads; i++) - ctx_switches += process->Threads[i].ContextSwitches; - user_time = (double)process->UserTime.HighPart * HI_T + \ - (double)process->UserTime.LowPart * LO_T; - kernel_time = (double)process->KernelTime.HighPart * HI_T + \ - (double)process->KernelTime.LowPart * LO_T; - - // Convert the LARGE_INTEGER union to a Unix time. - // It's the best I could find by googling and borrowing code here - // and there. The time returned has a precision of 1 second. - if (0 == pid || 4 == pid) { - // the python module will translate this into BOOT_TIME later - create_time = 0; - } - else { - create_time = psutil_LargeIntegerToUnixTime(process->CreateTime); - } - - py_retlist = Py_BuildValue( -#if defined(_WIN64) - "kkdddiKKKKKK" "kKKKKKKKKK", -#else - "kkdddiKKKKKK" "kIIIIIIIII", -#endif - process->HandleCount, // num handles - ctx_switches, // num ctx switches - user_time, // cpu user time - kernel_time, // cpu kernel time - create_time, // create time - (int)process->NumberOfThreads, // num threads - // IO counters - process->ReadOperationCount.QuadPart, // io rcount - process->WriteOperationCount.QuadPart, // io wcount - process->ReadTransferCount.QuadPart, // io rbytes - process->WriteTransferCount.QuadPart, // io wbytes - process->OtherOperationCount.QuadPart, // io others count - process->OtherTransferCount.QuadPart, // io others bytes - // memory - process->PageFaultCount, // num page faults - process->PeakWorkingSetSize, // peak wset - process->WorkingSetSize, // wset - process->QuotaPeakPagedPoolUsage, // peak paged pool - process->QuotaPagedPoolUsage, // paged pool - process->QuotaPeakNonPagedPoolUsage, // peak non paged pool - process->QuotaNonPagedPoolUsage, // non paged pool - process->PagefileUsage, // pagefile - process->PeakPagefileUsage, // peak pagefile - process->PrivatePageCount // private - ); - - free(buffer); - return py_retlist; -} diff --git a/third_party/python/psutil/psutil/arch/windows/process_info.h b/third_party/python/psutil/psutil/arch/windows/process_info.h deleted file mode 100644 index 5e89ddebdf1b..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/process_info.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - */ - -#include - -#define PSUTIL_FIRST_PROCESS(Processes) ( \ - (PSYSTEM_PROCESS_INFORMATION)(Processes)) -#define PSUTIL_NEXT_PROCESS(Process) ( \ - ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset ? \ - (PSYSTEM_PROCESS_INFORMATION)((PCHAR)(Process) + \ - ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset) : NULL) - -int psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, - PVOID *retBuffer); -PyObject* psutil_get_cmdline(DWORD pid, int use_peb); -PyObject* psutil_get_cwd(DWORD pid); -PyObject* psutil_get_environ(DWORD pid); -PyObject* psutil_proc_info(PyObject *self, PyObject *args); diff --git a/third_party/python/psutil/psutil/arch/windows/process_utils.c b/third_party/python/psutil/psutil/arch/windows/process_utils.c deleted file mode 100644 index f9d2f2f93dc5..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/process_utils.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Helper process functions. - */ - -#include -#include -#include // EnumProcesses - -#include "../../_psutil_common.h" -#include "process_utils.h" - - -DWORD * -psutil_get_pids(DWORD *numberOfReturnedPIDs) { - // Win32 SDK says the only way to know if our process array - // wasn't large enough is to check the returned size and make - // sure that it doesn't match the size of the array. - // If it does we allocate a larger array and try again - - // Stores the actual array - DWORD *procArray = NULL; - DWORD procArrayByteSz; - int procArraySz = 0; - - // Stores the byte size of the returned array from enumprocesses - DWORD enumReturnSz = 0; - - do { - procArraySz += 1024; - if (procArray != NULL) - free(procArray); - procArrayByteSz = procArraySz * sizeof(DWORD); - procArray = malloc(procArrayByteSz); - if (procArray == NULL) { - PyErr_NoMemory(); - return NULL; - } - if (! EnumProcesses(procArray, procArrayByteSz, &enumReturnSz)) { - free(procArray); - PyErr_SetFromWindowsErr(0); - return NULL; - } - } while (enumReturnSz == procArraySz * sizeof(DWORD)); - - // The number of elements is the returned size / size of each element - *numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD); - - return procArray; -} - - -// Return 1 if PID exists, 0 if not, -1 on error. -int -psutil_pid_in_pids(DWORD pid) { - DWORD *proclist = NULL; - DWORD numberOfReturnedPIDs; - DWORD i; - - proclist = psutil_get_pids(&numberOfReturnedPIDs); - if (proclist == NULL) - return -1; - for (i = 0; i < numberOfReturnedPIDs; i++) { - if (proclist[i] == pid) { - free(proclist); - return 1; - } - } - free(proclist); - return 0; -} - - -// Given a process handle checks whether it's actually running. If it -// does return the handle, else return NULL with Python exception set. -// This is needed because OpenProcess API sucks. -HANDLE -psutil_check_phandle(HANDLE hProcess, DWORD pid) { - DWORD exitCode; - - if (hProcess == NULL) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - // Yeah, this is the actual error code in case of - // "no such process". - NoSuchProcess("OpenProcess"); - return NULL; - } - PyErr_SetFromOSErrnoWithSyscall("OpenProcess"); - return NULL; - } - - if (GetExitCodeProcess(hProcess, &exitCode)) { - // XXX - maybe STILL_ACTIVE is not fully reliable as per: - // http://stackoverflow.com/questions/1591342/#comment47830782_1591379 - if (exitCode == STILL_ACTIVE) { - return hProcess; - } - if (psutil_pid_in_pids(pid) == 1) { - return hProcess; - } - CloseHandle(hProcess); - NoSuchProcess("GetExitCodeProcess != STILL_ACTIVE"); - return NULL; - } - - if (GetLastError() == ERROR_ACCESS_DENIED) { - psutil_debug("GetExitCodeProcess -> ERROR_ACCESS_DENIED (ignored)"); - SetLastError(0); - return hProcess; - } - PyErr_SetFromOSErrnoWithSyscall("GetExitCodeProcess"); - CloseHandle(hProcess); - return NULL; -} - - -// A wrapper around OpenProcess setting NSP exception if process no -// longer exists. *pid* is the process PID, *access* is the first -// argument to OpenProcess. -// Return a process handle or NULL with exception set. -HANDLE -psutil_handle_from_pid(DWORD pid, DWORD access) { - HANDLE hProcess; - - if (pid == 0) { - // otherwise we'd get NoSuchProcess - return AccessDenied("automatically set for PID 0"); - } - - hProcess = OpenProcess(access, FALSE, pid); - - if ((hProcess == NULL) && (GetLastError() == ERROR_ACCESS_DENIED)) { - PyErr_SetFromOSErrnoWithSyscall("OpenProcess"); - return NULL; - } - - hProcess = psutil_check_phandle(hProcess, pid); - return hProcess; -} - - -// Check for PID existance. Return 1 if pid exists, 0 if not, -1 on error. -int -psutil_pid_is_running(DWORD pid) { - HANDLE hProcess; - - // Special case for PID 0 System Idle Process - if (pid == 0) - return 1; - if (pid < 0) - return 0; - - hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); - - // Access denied means there's a process to deny access to. - if ((hProcess == NULL) && (GetLastError() == ERROR_ACCESS_DENIED)) - return 1; - - hProcess = psutil_check_phandle(hProcess, pid); - if (hProcess != NULL) { - CloseHandle(hProcess); - return 1; - } - - CloseHandle(hProcess); - PyErr_Clear(); - return psutil_pid_in_pids(pid); -} diff --git a/third_party/python/psutil/psutil/arch/windows/process_utils.h b/third_party/python/psutil/psutil/arch/windows/process_utils.h deleted file mode 100644 index a7171c5ca4c8..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/process_utils.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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. - */ - -DWORD* psutil_get_pids(DWORD *numberOfReturnedPIDs); -HANDLE psutil_handle_from_pid(DWORD pid, DWORD dwDesiredAccess); -int psutil_pid_is_running(DWORD pid); -int psutil_assert_pid_exists(DWORD pid, char *err); -int psutil_assert_pid_not_exists(DWORD pid, char *err); diff --git a/third_party/python/psutil/psutil/arch/windows/security.c b/third_party/python/psutil/psutil/arch/windows/security.c deleted file mode 100644 index 7e400a254137..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/security.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Security related functions for Windows platform (Set privileges such as - * SE DEBUG). - */ - -#include -#include - -#include "../../_psutil_common.h" - - -static BOOL -psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege) { - TOKEN_PRIVILEGES tp; - LUID luid; - TOKEN_PRIVILEGES tpPrevious; - DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); - - if (! LookupPrivilegeValue(NULL, Privilege, &luid)) { - PyErr_SetFromOSErrnoWithSyscall("LookupPrivilegeValue"); - return 1; - } - - // first pass. get current privilege setting - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = 0; - - if (! AdjustTokenPrivileges( - hToken, - FALSE, - &tp, - sizeof(TOKEN_PRIVILEGES), - &tpPrevious, - &cbPrevious)) - { - PyErr_SetFromOSErrnoWithSyscall("AdjustTokenPrivileges"); - return 1; - } - - // Second pass. Set privilege based on previous setting. - tpPrevious.PrivilegeCount = 1; - tpPrevious.Privileges[0].Luid = luid; - - if (bEnablePrivilege) - tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED); - else - tpPrevious.Privileges[0].Attributes ^= - (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes); - - if (! AdjustTokenPrivileges( - hToken, - FALSE, - &tpPrevious, - cbPrevious, - NULL, - NULL)) - { - PyErr_SetFromOSErrnoWithSyscall("AdjustTokenPrivileges"); - return 1; - } - - return 0; -} - - -static HANDLE -psutil_get_thisproc_token() { - HANDLE hToken = NULL; - HANDLE me = GetCurrentProcess(); - - if (! OpenProcessToken( - me, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) - { - if (GetLastError() == ERROR_NO_TOKEN) - { - if (! ImpersonateSelf(SecurityImpersonation)) { - PyErr_SetFromOSErrnoWithSyscall("ImpersonateSelf"); - return NULL; - } - if (! OpenProcessToken( - me, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) - { - PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken"); - return NULL; - } - } - else { - PyErr_SetFromOSErrnoWithSyscall("OpenProcessToken"); - return NULL; - } - } - - return hToken; -} - - -static void -psutil_print_err() { - char *msg = "psutil module couldn't set SE DEBUG mode for this process; " \ - "please file an issue against psutil bug tracker"; - psutil_debug(msg); - if (GetLastError() != ERROR_ACCESS_DENIED) - PyErr_WarnEx(PyExc_RuntimeWarning, msg, 1); - PyErr_Clear(); -} - - -/* - * Set this process in SE DEBUG mode so that we have more chances of - * querying processes owned by other users, including many owned by - * Administrator and Local System. - * https://docs.microsoft.com/windows-hardware/drivers/debugger/debug-privilege - * This is executed on module import and we don't crash on error. - */ -int -psutil_set_se_debug() { - HANDLE hToken; - - if ((hToken = psutil_get_thisproc_token()) == NULL) { - // "return 1;" to get an exception - psutil_print_err(); - return 0; - } - - if (psutil_set_privilege(hToken, SE_DEBUG_NAME, TRUE) != 0) { - // "return 1;" to get an exception - psutil_print_err(); - } - - RevertToSelf(); - CloseHandle(hToken); - return 0; -} diff --git a/third_party/python/psutil/psutil/arch/windows/security.h b/third_party/python/psutil/psutil/arch/windows/security.h deleted file mode 100644 index 8d4ddb00d412..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/security.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, 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. - * - * Security related functions for Windows platform (Set privileges such as - * SeDebug), as well as security helper functions. - */ - -#include - -int psutil_set_se_debug(); - diff --git a/third_party/python/psutil/psutil/arch/windows/services.c b/third_party/python/psutil/psutil/arch/windows/services.c deleted file mode 100644 index a91cb8f79701..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/services.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * 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. - */ - -#include -#include -#include - -#include "../../_psutil_common.h" -#include "services.h" - - -// ================================================================== -// utils -// ================================================================== - -SC_HANDLE -psutil_get_service_handler(char *service_name, DWORD scm_access, DWORD access) -{ - SC_HANDLE sc = NULL; - SC_HANDLE hService = NULL; - - sc = OpenSCManager(NULL, NULL, scm_access); - if (sc == NULL) { - PyErr_SetFromOSErrnoWithSyscall("OpenSCManager"); - return NULL; - } - hService = OpenService(sc, service_name, access); - if (hService == NULL) { - PyErr_SetFromOSErrnoWithSyscall("OpenService"); - CloseServiceHandle(sc); - return NULL; - } - CloseServiceHandle(sc); - return hService; -} - - -// XXX - expose these as constants? -static const char * -get_startup_string(DWORD startup) { - switch (startup) { - case SERVICE_AUTO_START: - return "automatic"; - case SERVICE_DEMAND_START: - return "manual"; - case SERVICE_DISABLED: - return "disabled"; -/* - // drivers only (since we use EnumServicesStatusEx() with - // SERVICE_WIN32) - case SERVICE_BOOT_START: - return "boot-start"; - case SERVICE_SYSTEM_START: - return "system-start"; -*/ - default: - return "unknown"; - } -} - - -// XXX - expose these as constants? -static const char * -get_state_string(DWORD state) { - switch (state) { - case SERVICE_RUNNING: - return "running"; - case SERVICE_PAUSED: - return "paused"; - case SERVICE_START_PENDING: - return "start_pending"; - case SERVICE_PAUSE_PENDING: - return "pause_pending"; - case SERVICE_CONTINUE_PENDING: - return "continue_pending"; - case SERVICE_STOP_PENDING: - return "stop_pending"; - case SERVICE_STOPPED: - return "stopped"; - default: - return "unknown"; - } -} - - -// ================================================================== -// APIs -// ================================================================== - -/* - * Enumerate all services. - */ -PyObject * -psutil_winservice_enumerate(PyObject *self, PyObject *args) { - ENUM_SERVICE_STATUS_PROCESSW *lpService = NULL; - BOOL ok; - SC_HANDLE sc = NULL; - DWORD bytesNeeded = 0; - DWORD srvCount; - DWORD resumeHandle = 0; - DWORD dwBytes = 0; - DWORD i; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_name = NULL; - PyObject *py_display_name = NULL; - - if (py_retlist == NULL) - return NULL; - - sc = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); - if (sc == NULL) { - PyErr_SetFromOSErrnoWithSyscall("OpenSCManager"); - return NULL; - } - - for (;;) { - ok = EnumServicesStatusExW( - sc, - SC_ENUM_PROCESS_INFO, - SERVICE_WIN32, // XXX - extend this to include drivers etc.? - SERVICE_STATE_ALL, - (LPBYTE)lpService, - dwBytes, - &bytesNeeded, - &srvCount, - &resumeHandle, - NULL); - if (ok || (GetLastError() != ERROR_MORE_DATA)) - break; - if (lpService) - free(lpService); - dwBytes = bytesNeeded; - lpService = (ENUM_SERVICE_STATUS_PROCESSW*)malloc(dwBytes); - } - - for (i = 0; i < srvCount; i++) { - // Get unicode name / display name. - py_name = NULL; - py_name = PyUnicode_FromWideChar( - lpService[i].lpServiceName, wcslen(lpService[i].lpServiceName)); - if (py_name == NULL) - goto error; - - py_display_name = NULL; - py_display_name = PyUnicode_FromWideChar( - lpService[i].lpDisplayName, wcslen(lpService[i].lpDisplayName)); - if (py_display_name == NULL) - goto error; - - // Construct the result. - py_tuple = Py_BuildValue("(OO)", py_name, py_display_name); - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_display_name); - Py_DECREF(py_name); - Py_DECREF(py_tuple); - } - - // Free resources. - CloseServiceHandle(sc); - free(lpService); - return py_retlist; - -error: - Py_DECREF(py_name); - Py_XDECREF(py_display_name); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (sc != NULL) - CloseServiceHandle(sc); - if (lpService != NULL) - free(lpService); - return NULL; -} - - -/* - * Get service config information. Returns: - * - display_name - * - binpath - * - username - * - startup_type - */ -PyObject * -psutil_winservice_query_config(PyObject *self, PyObject *args) { - char *service_name; - SC_HANDLE hService = NULL; - BOOL ok; - DWORD bytesNeeded = 0; - QUERY_SERVICE_CONFIGW *qsc = NULL; - PyObject *py_tuple = NULL; - PyObject *py_unicode_display_name = NULL; - PyObject *py_unicode_binpath = NULL; - PyObject *py_unicode_username = NULL; - - if (!PyArg_ParseTuple(args, "s", &service_name)) - return NULL; - hService = psutil_get_service_handler( - service_name, SC_MANAGER_ENUMERATE_SERVICE, SERVICE_QUERY_CONFIG); - if (hService == NULL) - goto error; - - // First call to QueryServiceConfigW() is necessary to get the - // right size. - bytesNeeded = 0; - QueryServiceConfigW(hService, NULL, 0, &bytesNeeded); - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceConfigW"); - goto error; - } - qsc = (QUERY_SERVICE_CONFIGW *)malloc(bytesNeeded); - ok = QueryServiceConfigW(hService, qsc, bytesNeeded, &bytesNeeded); - if (ok == 0) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceConfigW"); - goto error; - } - - // Get unicode display name. - py_unicode_display_name = PyUnicode_FromWideChar( - qsc->lpDisplayName, wcslen(qsc->lpDisplayName)); - if (py_unicode_display_name == NULL) - goto error; - - // Get unicode bin path. - py_unicode_binpath = PyUnicode_FromWideChar( - qsc->lpBinaryPathName, wcslen(qsc->lpBinaryPathName)); - if (py_unicode_binpath == NULL) - goto error; - - // Get unicode username. - py_unicode_username = PyUnicode_FromWideChar( - qsc->lpServiceStartName, wcslen(qsc->lpServiceStartName)); - if (py_unicode_username == NULL) - goto error; - - // Construct result tuple. - py_tuple = Py_BuildValue( - "(OOOs)", - py_unicode_display_name, - py_unicode_binpath, - py_unicode_username, - get_startup_string(qsc->dwStartType) // startup - ); - if (py_tuple == NULL) - goto error; - - // Free resources. - Py_DECREF(py_unicode_display_name); - Py_DECREF(py_unicode_binpath); - Py_DECREF(py_unicode_username); - free(qsc); - CloseServiceHandle(hService); - return py_tuple; - -error: - Py_XDECREF(py_unicode_display_name); - Py_XDECREF(py_unicode_binpath); - Py_XDECREF(py_unicode_username); - Py_XDECREF(py_tuple); - if (hService != NULL) - CloseServiceHandle(hService); - if (qsc != NULL) - free(qsc); - return NULL; -} - - -/* - * Get service status information. Returns: - * - status - * - pid - */ -PyObject * -psutil_winservice_query_status(PyObject *self, PyObject *args) { - char *service_name; - SC_HANDLE hService = NULL; - BOOL ok; - DWORD bytesNeeded = 0; - SERVICE_STATUS_PROCESS *ssp = NULL; - PyObject *py_tuple = NULL; - - if (!PyArg_ParseTuple(args, "s", &service_name)) - return NULL; - hService = psutil_get_service_handler( - service_name, SC_MANAGER_ENUMERATE_SERVICE, SERVICE_QUERY_STATUS); - if (hService == NULL) - goto error; - - // First call to QueryServiceStatusEx() is necessary to get the - // right size. - QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, NULL, 0, - &bytesNeeded); - if (GetLastError() == ERROR_MUI_FILE_NOT_FOUND) { - // Also services.msc fails in the same manner, so we return an - // empty string. - CloseServiceHandle(hService); - return Py_BuildValue("s", ""); - } - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceStatusEx"); - goto error; - } - ssp = (SERVICE_STATUS_PROCESS *)HeapAlloc( - GetProcessHeap(), 0, bytesNeeded); - if (ssp == NULL) { - PyErr_NoMemory(); - goto error; - } - - // Actual call. - ok = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)ssp, - bytesNeeded, &bytesNeeded); - if (ok == 0) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceStatusEx"); - goto error; - } - - py_tuple = Py_BuildValue( - "(sk)", - get_state_string(ssp->dwCurrentState), - ssp->dwProcessId - ); - if (py_tuple == NULL) - goto error; - - CloseServiceHandle(hService); - HeapFree(GetProcessHeap(), 0, ssp); - return py_tuple; - -error: - Py_XDECREF(py_tuple); - if (hService != NULL) - CloseServiceHandle(hService); - if (ssp != NULL) - HeapFree(GetProcessHeap(), 0, ssp); - return NULL; -} - - -/* - * Get service description. - */ -PyObject * -psutil_winservice_query_descr(PyObject *self, PyObject *args) { - ENUM_SERVICE_STATUS_PROCESSW *lpService = NULL; - BOOL ok; - DWORD bytesNeeded = 0; - SC_HANDLE hService = NULL; - SERVICE_DESCRIPTIONW *scd = NULL; - char *service_name; - PyObject *py_retstr = NULL; - - if (!PyArg_ParseTuple(args, "s", &service_name)) - return NULL; - hService = psutil_get_service_handler( - service_name, SC_MANAGER_ENUMERATE_SERVICE, SERVICE_QUERY_CONFIG); - if (hService == NULL) - goto error; - - // This first call to QueryServiceConfig2W() is necessary in order - // to get the right size. - bytesNeeded = 0; - QueryServiceConfig2W(hService, SERVICE_CONFIG_DESCRIPTION, NULL, 0, - &bytesNeeded); - if (GetLastError() == ERROR_MUI_FILE_NOT_FOUND) { - // Also services.msc fails in the same manner, so we return an - // empty string. - CloseServiceHandle(hService); - return Py_BuildValue("s", ""); - } - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceConfig2W"); - goto error; - } - - scd = (SERVICE_DESCRIPTIONW *)malloc(bytesNeeded); - ok = QueryServiceConfig2W(hService, SERVICE_CONFIG_DESCRIPTION, - (LPBYTE)scd, bytesNeeded, &bytesNeeded); - if (ok == 0) { - PyErr_SetFromOSErrnoWithSyscall("QueryServiceConfig2W"); - goto error; - } - - if (scd->lpDescription == NULL) { - py_retstr = Py_BuildValue("s", ""); - } - else { - py_retstr = PyUnicode_FromWideChar( - scd->lpDescription, wcslen(scd->lpDescription)); - } - if (!py_retstr) - goto error; - - free(scd); - CloseServiceHandle(hService); - return py_retstr; - -error: - if (hService != NULL) - CloseServiceHandle(hService); - if (lpService != NULL) - free(lpService); - return NULL; -} - - -/* - * Start service. - * XXX - note: this is exposed but not used. - */ -PyObject * -psutil_winservice_start(PyObject *self, PyObject *args) { - char *service_name; - BOOL ok; - SC_HANDLE hService = NULL; - - if (!PyArg_ParseTuple(args, "s", &service_name)) - return NULL; - hService = psutil_get_service_handler( - service_name, SC_MANAGER_ALL_ACCESS, SERVICE_START); - if (hService == NULL) { - goto error; - } - ok = StartService(hService, 0, NULL); - if (ok == 0) { - PyErr_SetFromOSErrnoWithSyscall("StartService"); - goto error; - } - - Py_RETURN_NONE; - -error: - if (hService != NULL) - CloseServiceHandle(hService); - return NULL; -} - - -/* - * Stop service. - * XXX - note: this is exposed but not used. - */ -PyObject * -psutil_winservice_stop(PyObject *self, PyObject *args) { - char *service_name; - BOOL ok; - SC_HANDLE hService = NULL; - SERVICE_STATUS ssp; - - if (!PyArg_ParseTuple(args, "s", &service_name)) - return NULL; - hService = psutil_get_service_handler( - service_name, SC_MANAGER_ALL_ACCESS, SERVICE_STOP); - if (hService == NULL) - goto error; - - // Note: this can hang for 30 secs. - Py_BEGIN_ALLOW_THREADS - ok = ControlService(hService, SERVICE_CONTROL_STOP, &ssp); - Py_END_ALLOW_THREADS - if (ok == 0) { - PyErr_SetFromOSErrnoWithSyscall("ControlService"); - goto error; - } - - CloseServiceHandle(hService); - Py_RETURN_NONE; - -error: - if (hService != NULL) - CloseServiceHandle(hService); - return NULL; -} diff --git a/third_party/python/psutil/psutil/arch/windows/services.h b/third_party/python/psutil/psutil/arch/windows/services.h deleted file mode 100644 index ebcfa5ef590a..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/services.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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. - */ - -#include -#include - -SC_HANDLE psutil_get_service_handle( - char service_name, DWORD scm_access, DWORD access); -PyObject *psutil_winservice_enumerate(PyObject *self, PyObject *args); -PyObject *psutil_winservice_query_config(PyObject *self, PyObject *args); -PyObject *psutil_winservice_query_status(PyObject *self, PyObject *args); -PyObject *psutil_winservice_query_descr(PyObject *self, PyObject *args); -PyObject *psutil_winservice_start(PyObject *self, PyObject *args); -PyObject *psutil_winservice_stop(PyObject *self, PyObject *args); diff --git a/third_party/python/psutil/psutil/arch/windows/socks.c b/third_party/python/psutil/psutil/arch/windows/socks.c deleted file mode 100644 index 5e4c2df802a7..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/socks.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * 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. - */ - -// Fixes clash between winsock2.h and windows.h -#define WIN32_LEAN_AND_MEAN - -#include -#include -#include - -#include "../../_psutil_common.h" -#include "process_utils.h" - - -#define BYTESWAP_USHORT(x) ((((USHORT)(x) << 8) | ((USHORT)(x) >> 8)) & 0xffff) -#define STATUS_UNSUCCESSFUL 0xC0000001 - -ULONG g_TcpTableSize = 0; -ULONG g_UdpTableSize = 0; - - -// Note about GetExtended[Tcp|Udp]Table syscalls: due to other processes -// being active on the machine, it's possible that the size of the table -// increases between the moment we query the size and the moment we query -// the data. Therefore we retry if that happens. See: -// https://github.com/giampaolo/psutil/pull/1335 -// https://github.com/giampaolo/psutil/issues/1294 -// A global and ever increasing size is used in order to avoid calling -// GetExtended[Tcp|Udp]Table twice per call (faster). - - -static PVOID __GetExtendedTcpTable(ULONG family) { - DWORD err; - PVOID table; - ULONG size; - TCP_TABLE_CLASS class = TCP_TABLE_OWNER_PID_ALL; - - size = g_TcpTableSize; - if (size == 0) { - GetExtendedTcpTable(NULL, &size, FALSE, family, class, 0); - // reserve 25% more space - size = size + (size / 2 / 2); - g_TcpTableSize = size; - } - - table = malloc(size); - if (table == NULL) { - PyErr_NoMemory(); - return NULL; - } - - err = GetExtendedTcpTable(table, &size, FALSE, family, class, 0); - if (err == NO_ERROR) - return table; - - free(table); - if (err == ERROR_INSUFFICIENT_BUFFER || err == STATUS_UNSUCCESSFUL) { - psutil_debug("GetExtendedTcpTable: retry with different bufsize"); - g_TcpTableSize = 0; - return __GetExtendedTcpTable(family); - } - - PyErr_SetString(PyExc_RuntimeError, "GetExtendedTcpTable failed"); - return NULL; -} - - -static PVOID __GetExtendedUdpTable(ULONG family) { - DWORD err; - PVOID table; - ULONG size; - UDP_TABLE_CLASS class = UDP_TABLE_OWNER_PID; - - size = g_UdpTableSize; - if (size == 0) { - GetExtendedUdpTable(NULL, &size, FALSE, family, class, 0); - // reserve 25% more space - size = size + (size / 2 / 2); - g_UdpTableSize = size; - } - - table = malloc(size); - if (table == NULL) { - PyErr_NoMemory(); - return NULL; - } - - err = GetExtendedUdpTable(table, &size, FALSE, family, class, 0); - if (err == NO_ERROR) - return table; - - free(table); - if (err == ERROR_INSUFFICIENT_BUFFER || err == STATUS_UNSUCCESSFUL) { - psutil_debug("GetExtendedUdpTable: retry with different bufsize"); - g_UdpTableSize = 0; - return __GetExtendedUdpTable(family); - } - - PyErr_SetString(PyExc_RuntimeError, "GetExtendedUdpTable failed"); - return NULL; -} - - -#define psutil_conn_decref_objs() \ - Py_DECREF(_AF_INET); \ - Py_DECREF(_AF_INET6);\ - Py_DECREF(_SOCK_STREAM);\ - Py_DECREF(_SOCK_DGRAM); - - -/* - * Return a list of network connections opened by a process - */ -PyObject * -psutil_net_connections(PyObject *self, PyObject *args) { - static long null_address[4] = { 0, 0, 0, 0 }; - DWORD pid; - int pid_return; - PVOID table = NULL; - PMIB_TCPTABLE_OWNER_PID tcp4Table; - PMIB_UDPTABLE_OWNER_PID udp4Table; - PMIB_TCP6TABLE_OWNER_PID tcp6Table; - PMIB_UDP6TABLE_OWNER_PID udp6Table; - ULONG i; - CHAR addressBufferLocal[65]; - CHAR addressBufferRemote[65]; - - PyObject *py_retlist = NULL; - PyObject *py_conn_tuple = NULL; - PyObject *py_af_filter = NULL; - PyObject *py_type_filter = NULL; - PyObject *py_addr_tuple_local = NULL; - PyObject *py_addr_tuple_remote = NULL; - PyObject *_AF_INET = PyLong_FromLong((long)AF_INET); - PyObject *_AF_INET6 = PyLong_FromLong((long)AF_INET6); - PyObject *_SOCK_STREAM = PyLong_FromLong((long)SOCK_STREAM); - PyObject *_SOCK_DGRAM = PyLong_FromLong((long)SOCK_DGRAM); - - if (! PyArg_ParseTuple(args, _Py_PARSE_PID "OO", &pid, &py_af_filter, - &py_type_filter)) - { - goto error; - } - - if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) { - psutil_conn_decref_objs(); - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - return NULL; - } - - if (pid != -1) { - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) { - psutil_conn_decref_objs(); - return NoSuchProcess("psutil_pid_is_running"); - } - else if (pid_return == -1) { - psutil_conn_decref_objs(); - return NULL; - } - } - - py_retlist = PyList_New(0); - if (py_retlist == NULL) { - psutil_conn_decref_objs(); - return NULL; - } - - // TCP IPv4 - - if ((PySequence_Contains(py_af_filter, _AF_INET) == 1) && - (PySequence_Contains(py_type_filter, _SOCK_STREAM) == 1)) - { - table = NULL; - py_conn_tuple = NULL; - py_addr_tuple_local = NULL; - py_addr_tuple_remote = NULL; - - table = __GetExtendedTcpTable(AF_INET); - if (table == NULL) - goto error; - tcp4Table = table; - for (i = 0; i < tcp4Table->dwNumEntries; i++) { - if (pid != -1) { - if (tcp4Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (tcp4Table->table[i].dwLocalAddr != 0 || - tcp4Table->table[i].dwLocalPort != 0) - { - struct in_addr addr; - - addr.S_un.S_addr = tcp4Table->table[i].dwLocalAddr; - RtlIpv4AddressToStringA(&addr, addressBufferLocal); - py_addr_tuple_local = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(tcp4Table->table[i].dwLocalPort)); - } - else { - py_addr_tuple_local = PyTuple_New(0); - } - - if (py_addr_tuple_local == NULL) - goto error; - - // On Windows <= XP, remote addr is filled even if socket - // is in LISTEN mode in which case we just ignore it. - if ((tcp4Table->table[i].dwRemoteAddr != 0 || - tcp4Table->table[i].dwRemotePort != 0) && - (tcp4Table->table[i].dwState != MIB_TCP_STATE_LISTEN)) - { - struct in_addr addr; - - addr.S_un.S_addr = tcp4Table->table[i].dwRemoteAddr; - RtlIpv4AddressToStringA(&addr, addressBufferRemote); - py_addr_tuple_remote = Py_BuildValue( - "(si)", - addressBufferRemote, - BYTESWAP_USHORT(tcp4Table->table[i].dwRemotePort)); - } - else - { - py_addr_tuple_remote = PyTuple_New(0); - } - - if (py_addr_tuple_remote == NULL) - goto error; - - py_conn_tuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET, - SOCK_STREAM, - py_addr_tuple_local, - py_addr_tuple_remote, - tcp4Table->table[i].dwState, - tcp4Table->table[i].dwOwningPid); - if (!py_conn_tuple) - goto error; - if (PyList_Append(py_retlist, py_conn_tuple)) - goto error; - Py_CLEAR(py_conn_tuple); - } - - free(table); - table = NULL; - } - - // TCP IPv6 - if ((PySequence_Contains(py_af_filter, _AF_INET6) == 1) && - (PySequence_Contains(py_type_filter, _SOCK_STREAM) == 1) && - (RtlIpv6AddressToStringA != NULL)) - { - table = NULL; - py_conn_tuple = NULL; - py_addr_tuple_local = NULL; - py_addr_tuple_remote = NULL; - - table = __GetExtendedTcpTable(AF_INET6); - if (table == NULL) - goto error; - tcp6Table = table; - for (i = 0; i < tcp6Table->dwNumEntries; i++) - { - if (pid != -1) { - if (tcp6Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (memcmp(tcp6Table->table[i].ucLocalAddr, null_address, 16) - != 0 || tcp6Table->table[i].dwLocalPort != 0) - { - struct in6_addr addr; - - memcpy(&addr, tcp6Table->table[i].ucLocalAddr, 16); - RtlIpv6AddressToStringA(&addr, addressBufferLocal); - py_addr_tuple_local = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(tcp6Table->table[i].dwLocalPort)); - } - else { - py_addr_tuple_local = PyTuple_New(0); - } - - if (py_addr_tuple_local == NULL) - goto error; - - // On Windows <= XP, remote addr is filled even if socket - // is in LISTEN mode in which case we just ignore it. - if ((memcmp(tcp6Table->table[i].ucRemoteAddr, null_address, 16) - != 0 || - tcp6Table->table[i].dwRemotePort != 0) && - (tcp6Table->table[i].dwState != MIB_TCP_STATE_LISTEN)) - { - struct in6_addr addr; - - memcpy(&addr, tcp6Table->table[i].ucRemoteAddr, 16); - RtlIpv6AddressToStringA(&addr, addressBufferRemote); - py_addr_tuple_remote = Py_BuildValue( - "(si)", - addressBufferRemote, - BYTESWAP_USHORT(tcp6Table->table[i].dwRemotePort)); - } - else { - py_addr_tuple_remote = PyTuple_New(0); - } - - if (py_addr_tuple_remote == NULL) - goto error; - - py_conn_tuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET6, - SOCK_STREAM, - py_addr_tuple_local, - py_addr_tuple_remote, - tcp6Table->table[i].dwState, - tcp6Table->table[i].dwOwningPid); - if (!py_conn_tuple) - goto error; - if (PyList_Append(py_retlist, py_conn_tuple)) - goto error; - Py_CLEAR(py_conn_tuple); - } - - free(table); - table = NULL; - } - - // UDP IPv4 - - if ((PySequence_Contains(py_af_filter, _AF_INET) == 1) && - (PySequence_Contains(py_type_filter, _SOCK_DGRAM) == 1)) - { - table = NULL; - py_conn_tuple = NULL; - py_addr_tuple_local = NULL; - py_addr_tuple_remote = NULL; - table = __GetExtendedUdpTable(AF_INET); - if (table == NULL) - goto error; - udp4Table = table; - for (i = 0; i < udp4Table->dwNumEntries; i++) - { - if (pid != -1) { - if (udp4Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (udp4Table->table[i].dwLocalAddr != 0 || - udp4Table->table[i].dwLocalPort != 0) - { - struct in_addr addr; - - addr.S_un.S_addr = udp4Table->table[i].dwLocalAddr; - RtlIpv4AddressToStringA(&addr, addressBufferLocal); - py_addr_tuple_local = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(udp4Table->table[i].dwLocalPort)); - } - else { - py_addr_tuple_local = PyTuple_New(0); - } - - if (py_addr_tuple_local == NULL) - goto error; - - py_conn_tuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET, - SOCK_DGRAM, - py_addr_tuple_local, - PyTuple_New(0), - PSUTIL_CONN_NONE, - udp4Table->table[i].dwOwningPid); - if (!py_conn_tuple) - goto error; - if (PyList_Append(py_retlist, py_conn_tuple)) - goto error; - Py_CLEAR(py_conn_tuple); - } - - free(table); - table = NULL; - } - - // UDP IPv6 - - if ((PySequence_Contains(py_af_filter, _AF_INET6) == 1) && - (PySequence_Contains(py_type_filter, _SOCK_DGRAM) == 1) && - (RtlIpv6AddressToStringA != NULL)) - { - table = NULL; - py_conn_tuple = NULL; - py_addr_tuple_local = NULL; - py_addr_tuple_remote = NULL; - table = __GetExtendedUdpTable(AF_INET6); - if (table == NULL) - goto error; - udp6Table = table; - for (i = 0; i < udp6Table->dwNumEntries; i++) { - if (pid != -1) { - if (udp6Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (memcmp(udp6Table->table[i].ucLocalAddr, null_address, 16) - != 0 || udp6Table->table[i].dwLocalPort != 0) - { - struct in6_addr addr; - - memcpy(&addr, udp6Table->table[i].ucLocalAddr, 16); - RtlIpv6AddressToStringA(&addr, addressBufferLocal); - py_addr_tuple_local = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(udp6Table->table[i].dwLocalPort)); - } - else { - py_addr_tuple_local = PyTuple_New(0); - } - - if (py_addr_tuple_local == NULL) - goto error; - - py_conn_tuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET6, - SOCK_DGRAM, - py_addr_tuple_local, - PyTuple_New(0), - PSUTIL_CONN_NONE, - udp6Table->table[i].dwOwningPid); - if (!py_conn_tuple) - goto error; - if (PyList_Append(py_retlist, py_conn_tuple)) - goto error; - Py_CLEAR(py_conn_tuple); - } - - free(table); - table = NULL; - } - - psutil_conn_decref_objs(); - return py_retlist; - -error: - psutil_conn_decref_objs(); - Py_XDECREF(py_conn_tuple); - Py_XDECREF(py_addr_tuple_local); - Py_XDECREF(py_addr_tuple_remote); - Py_DECREF(py_retlist); - if (table != NULL) - free(table); - return NULL; -} diff --git a/third_party/python/psutil/psutil/arch/windows/socks.h b/third_party/python/psutil/psutil/arch/windows/socks.h deleted file mode 100644 index cd9ba58dcbc8..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/socks.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola', Jeff Tang. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include - -PyObject *psutil_net_connections(PyObject *self, PyObject *args); diff --git a/third_party/python/psutil/psutil/arch/windows/wmi.c b/third_party/python/psutil/psutil/arch/windows/wmi.c deleted file mode 100644 index 42a70df76673..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/wmi.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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. - * - * Functions related to the Windows Management Instrumentation API. - */ - -#include -#include -#include - - -// We use an exponentially weighted moving average, just like Unix systems do -// https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation -// -// These constants serve as the damping factor and are calculated with -// 1 / exp(sampling interval in seconds / window size in seconds) -// -// This formula comes from linux's include/linux/sched/loadavg.h -// https://github.com/torvalds/linux/blob/345671ea0f9258f410eb057b9ced9cefbbe5dc78/include/linux/sched/loadavg.h#L20-L23 -#define LOADAVG_FACTOR_1F 0.9200444146293232478931553241 -#define LOADAVG_FACTOR_5F 0.9834714538216174894737477501 -#define LOADAVG_FACTOR_15F 0.9944598480048967508795473394 -// The time interval in seconds between taking load counts, same as Linux -#define SAMPLING_INTERVAL 5 - -double load_avg_1m = 0; -double load_avg_5m = 0; -double load_avg_15m = 0; - - -VOID CALLBACK LoadAvgCallback(PVOID hCounter) { - PDH_FMT_COUNTERVALUE displayValue; - double currentLoad; - PDH_STATUS err; - - err = PdhGetFormattedCounterValue( - (PDH_HCOUNTER)hCounter, PDH_FMT_DOUBLE, 0, &displayValue); - // Skip updating the load if we can't get the value successfully - if (err != ERROR_SUCCESS) { - return; - } - currentLoad = displayValue.doubleValue; - - load_avg_1m = load_avg_1m * LOADAVG_FACTOR_1F + currentLoad * \ - (1.0 - LOADAVG_FACTOR_1F); - load_avg_5m = load_avg_5m * LOADAVG_FACTOR_5F + currentLoad * \ - (1.0 - LOADAVG_FACTOR_5F); - load_avg_15m = load_avg_15m * LOADAVG_FACTOR_15F + currentLoad * \ - (1.0 - LOADAVG_FACTOR_15F); -} - - -PyObject * -psutil_init_loadavg_counter(PyObject *self, PyObject *args) { - WCHAR *szCounterPath = L"\\System\\Processor Queue Length"; - PDH_STATUS s; - BOOL ret; - HQUERY hQuery; - HCOUNTER hCounter; - HANDLE event; - HANDLE waitHandle; - - if ((PdhOpenQueryW(NULL, 0, &hQuery)) != ERROR_SUCCESS) - goto error; - - s = PdhAddEnglishCounterW(hQuery, szCounterPath, 0, &hCounter); - if (s != ERROR_SUCCESS) - goto error; - - event = CreateEventW(NULL, FALSE, FALSE, L"LoadUpdateEvent"); - if (event == NULL) { - PyErr_SetFromWindowsErr(GetLastError()); - return NULL; - } - - s = PdhCollectQueryDataEx(hQuery, SAMPLING_INTERVAL, event); - if (s != ERROR_SUCCESS) - goto error; - - ret = RegisterWaitForSingleObject( - &waitHandle, - event, - (WAITORTIMERCALLBACK)LoadAvgCallback, - (PVOID) - hCounter, - INFINITE, - WT_EXECUTEDEFAULT); - - if (ret == 0) { - PyErr_SetFromWindowsErr(GetLastError()); - return NULL; - } - - Py_RETURN_NONE; - -error: - PyErr_SetFromWindowsErr(0); - return NULL; -} - - -/* - * Gets the emulated 1 minute, 5 minute and 15 minute load averages - * (processor queue length) for the system. - * `init_loadavg_counter` must be called before this function to engage the - * mechanism that records load values. - */ -PyObject * -psutil_get_loadavg(PyObject *self, PyObject *args) { - return Py_BuildValue("(ddd)", load_avg_1m, load_avg_5m, load_avg_15m); -} diff --git a/third_party/python/psutil/psutil/arch/windows/wmi.h b/third_party/python/psutil/psutil/arch/windows/wmi.h deleted file mode 100644 index 311242a393d8..000000000000 --- a/third_party/python/psutil/psutil/arch/windows/wmi.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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. - */ - -#include - -PyObject* psutil_init_loadavg_counter(); -PyObject* psutil_get_loadavg(); diff --git a/third_party/python/psutil/psutil/tests/README.rst b/third_party/python/psutil/psutil/tests/README.rst deleted file mode 100644 index 9b870d5b1b8f..000000000000 --- a/third_party/python/psutil/psutil/tests/README.rst +++ /dev/null @@ -1,22 +0,0 @@ -Instructions for running tests -============================== - -* There are two ways of running tests. As a "user", if psutil is already - installed and you just want to test it works:: - - python -m psutil.tests - - As a "developer", if you have a copy of the source code and you wish to hack - on psutil:: - - make setup-dev-env # install missing third-party deps - make test - -* To run tests on all supported Python versions install tox - (``pip install tox``) then run ``tox`` from within psutil root directory. - -* Every time a commit is pushed tests are automatically run on Travis - (Linux, MACOS) and appveyor (Windows): - - * Travis builds: https://travis-ci.org/giampaolo/psutil - * AppVeyor builds: https://ci.appveyor.com/project/giampaolo/psutil diff --git a/third_party/python/psutil/psutil/tests/__init__.py b/third_party/python/psutil/psutil/tests/__init__.py deleted file mode 100644 index 3e4dc88066ca..000000000000 --- a/third_party/python/psutil/psutil/tests/__init__.py +++ /dev/null @@ -1,1137 +0,0 @@ -# -*- coding: utf-8 -*- - -# 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. - -""" -Test utilities. -""" - -from __future__ import print_function - -import atexit -import contextlib -import ctypes -import errno -import functools -import os -import random -import re -import select -import shutil -import socket -import stat -import subprocess -import sys -import tempfile -import textwrap -import threading -import time -import traceback -import warnings -from socket import AF_INET -from socket import AF_INET6 -from socket import SOCK_STREAM - -import psutil -from psutil import AIX -from psutil import MACOS -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -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 u -from psutil._compat import unicode -from psutil._compat import which - -if sys.version_info < (2, 7): - import unittest2 as unittest # requires "pip install unittest2" -else: - import unittest - -try: - from unittest import mock # py3 -except ImportError: - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - import mock # NOQA - requires "pip install mock" - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - - -__all__ = [ - # constants - 'APPVEYOR', 'DEVNULL', 'GLOBAL_TIMEOUT', 'MEMORY_TOLERANCE', 'NO_RETRIES', - 'PYPY', 'PYTHON_EXE', 'ROOT_DIR', 'SCRIPTS_DIR', 'TESTFILE_PREFIX', - 'TESTFN', 'TESTFN_UNICODE', 'TOX', 'TRAVIS', 'CIRRUS', 'CI_TESTING', - 'VALID_PROC_STATUSES', - "HAS_CPU_AFFINITY", "HAS_CPU_FREQ", "HAS_ENVIRON", "HAS_PROC_IO_COUNTERS", - "HAS_IONICE", "HAS_MEMORY_MAPS", "HAS_PROC_CPU_NUM", "HAS_RLIMIT", - "HAS_SENSORS_BATTERY", "HAS_BATTERY", "HAS_SENSORS_FANS", - "HAS_SENSORS_TEMPERATURES", "HAS_MEMORY_FULL_INFO", - # subprocesses - 'pyrun', 'reap_children', 'get_test_subprocess', 'create_zombie_proc', - 'create_proc_children_pair', - # threads - 'ThreadTask' - # test utils - 'unittest', 'skip_on_access_denied', 'skip_on_not_implemented', - 'retry_on_failure', - # install utils - 'install_pip', 'install_test_deps', - # fs utils - 'chdir', 'safe_rmpath', 'create_exe', 'decode_path', 'encode_path', - 'unique_filename', - # os - 'get_winver', 'get_kernel_version', - # sync primitives - 'call_until', 'wait_for_pid', 'wait_for_file', - # network - 'check_net_address', - 'get_free_port', 'unix_socket_path', 'bind_socket', 'bind_unix_socket', - 'tcp_socketpair', 'unix_socketpair', 'create_sockets', - # compat - 'reload_module', 'import_module_by_path', - # others - 'warn', 'copyload_shared_lib', 'is_namedtuple', -] - - -# =================================================================== -# --- constants -# =================================================================== - -# --- platforms - -TOX = os.getenv('TOX') or '' in ('1', 'true') -PYPY = '__pypy__' in sys.builtin_module_names -# whether we're running this test suite on a Continuous Integration service -TRAVIS = bool(os.environ.get('TRAVIS')) -APPVEYOR = bool(os.environ.get('APPVEYOR')) -CIRRUS = bool(os.environ.get('CIRRUS')) -CI_TESTING = TRAVIS or APPVEYOR or CIRRUS - -# --- configurable defaults - -# how many times retry_on_failure() decorator will retry -NO_RETRIES = 10 -# bytes tolerance for system-wide memory related tests -MEMORY_TOLERANCE = 500 * 1024 # 500KB -# the timeout used in functions which have to wait -GLOBAL_TIMEOUT = 5 -# be more tolerant if we're on travis / appveyor in order to avoid -# false positives -if TRAVIS or APPVEYOR: - NO_RETRIES *= 3 - GLOBAL_TIMEOUT *= 3 - -# --- files - -TESTFILE_PREFIX = '$testfn' -if os.name == 'java': - # Jython disallows @ in module names - TESTFILE_PREFIX = '$psutil-test-' -else: - TESTFILE_PREFIX = '@psutil-test-' -TESTFN = os.path.join(os.path.realpath(os.getcwd()), TESTFILE_PREFIX) -# Disambiguate TESTFN for parallel testing, while letting it remain a valid -# module name. -TESTFN = TESTFN + str(os.getpid()) - -_TESTFN = TESTFN + '-internal' -TESTFN_UNICODE = TESTFN + u("-ƒőő") -ASCII_FS = sys.getfilesystemencoding().lower() in ('ascii', 'us-ascii') - -# --- paths - -ROOT_DIR = os.path.realpath( - os.path.join(os.path.dirname(__file__), '..', '..')) -SCRIPTS_DIR = os.path.join(ROOT_DIR, 'scripts') -HERE = os.path.realpath(os.path.dirname(__file__)) - -# --- support - -HAS_CONNECTIONS_UNIX = POSIX and not SUNOS -HAS_CPU_AFFINITY = hasattr(psutil.Process, "cpu_affinity") -HAS_CPU_FREQ = hasattr(psutil, "cpu_freq") -HAS_GETLOADAVG = hasattr(psutil, "getloadavg") -HAS_ENVIRON = hasattr(psutil.Process, "environ") -HAS_IONICE = hasattr(psutil.Process, "ionice") -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_SENSORS_BATTERY = hasattr(psutil, "sensors_battery") -try: - HAS_BATTERY = HAS_SENSORS_BATTERY and bool(psutil.sensors_battery()) -except Exception: - HAS_BATTERY = True -HAS_SENSORS_FANS = hasattr(psutil, "sensors_fans") -HAS_SENSORS_TEMPERATURES = hasattr(psutil, "sensors_temperatures") -HAS_THREADS = hasattr(psutil.Process, "threads") -SKIP_SYSCONS = (MACOS or AIX) and os.getuid() != 0 - -# --- misc - - -def _get_py_exe(): - def attempt(exe): - try: - subprocess.check_call( - [exe, "-V"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - except Exception: - return None - else: - return exe - - if MACOS: - exe = \ - attempt(sys.executable) or \ - attempt(os.path.realpath(sys.executable)) or \ - attempt(which("python%s.%s" % sys.version_info[:2])) or \ - attempt(psutil.Process().exe()) - if not exe: - raise ValueError("can't find python exe real abspath") - return exe - else: - exe = os.path.realpath(sys.executable) - assert os.path.exists(exe), exe - return exe - - -PYTHON_EXE = _get_py_exe() -DEVNULL = open(os.devnull, 'r+') -VALID_PROC_STATUSES = [getattr(psutil, x) for x in dir(psutil) - if x.startswith('STATUS_')] -AF_UNIX = getattr(socket, "AF_UNIX", object()) - -_subprocesses_started = set() -_pids_started = set() -_testfiles_created = set() - - -@atexit.register -def cleanup_test_files(): - DEVNULL.close() - for name in os.listdir(u('.')): - if isinstance(name, unicode): - prefix = u(TESTFILE_PREFIX) - else: - prefix = TESTFILE_PREFIX - if name.startswith(prefix): - try: - safe_rmpath(name) - except Exception: - traceback.print_exc() - for path in _testfiles_created: - try: - safe_rmpath(path) - except Exception: - traceback.print_exc() - - -# this is executed first -@atexit.register -def cleanup_test_procs(): - reap_children(recursive=True) - - -# =================================================================== -# --- threads -# =================================================================== - - -class ThreadTask(threading.Thread): - """A thread task which does nothing expect staying alive.""" - - def __init__(self): - threading.Thread.__init__(self) - self._running = False - self._interval = 0.001 - self._flag = threading.Event() - - def __repr__(self): - name = self.__class__.__name__ - return '<%s running=%s at %#x>' % (name, self._running, id(self)) - - def __enter__(self): - self.start() - return self - - def __exit__(self, *args, **kwargs): - self.stop() - - def start(self): - """Start thread and keep it running until an explicit - stop() request. Polls for shutdown every 'timeout' seconds. - """ - if self._running: - raise ValueError("already started") - threading.Thread.start(self) - self._flag.wait() - - def run(self): - self._running = True - self._flag.set() - while self._running: - time.sleep(self._interval) - - def stop(self): - """Stop thread execution and and waits until it is stopped.""" - if not self._running: - raise ValueError("already stopped") - self._running = False - self.join() - - -# =================================================================== -# --- subprocesses -# =================================================================== - - -def _reap_children_on_err(fun): - @functools.wraps(fun) - def wrapper(*args, **kwargs): - try: - return fun(*args, **kwargs) - except Exception: - reap_children() - raise - return wrapper - - -@_reap_children_on_err -def get_test_subprocess(cmd=None, **kwds): - """Creates a python subprocess which does nothing for 60 secs and - return it as subprocess.Popen instance. - If "cmd" is specified that is used instead of python. - By default stdin and stdout are redirected to /dev/null. - It also attemps to make sure the process is in a reasonably - initialized state. - The process is registered for cleanup on reap_children(). - """ - kwds.setdefault("stdin", DEVNULL) - kwds.setdefault("stdout", DEVNULL) - kwds.setdefault("cwd", os.getcwd()) - kwds.setdefault("env", os.environ) - if WINDOWS: - # Prevents the subprocess to open error dialogs. This will also - # cause stderr to be suppressed, which is suboptimal in order - # to debug broken tests. - CREATE_NO_WINDOW = 0x8000000 - kwds.setdefault("creationflags", CREATE_NO_WINDOW) - if cmd is None: - safe_rmpath(_TESTFN) - pyline = "from time import sleep;" \ - "open(r'%s', 'w').close();" \ - "sleep(60);" % _TESTFN - cmd = [PYTHON_EXE, "-c", pyline] - sproc = subprocess.Popen(cmd, **kwds) - _subprocesses_started.add(sproc) - wait_for_file(_TESTFN, delete=True, empty=True) - else: - sproc = subprocess.Popen(cmd, **kwds) - _subprocesses_started.add(sproc) - wait_for_pid(sproc.pid) - return sproc - - -@_reap_children_on_err -def create_proc_children_pair(): - """Create a subprocess which creates another one as in: - A (us) -> B (child) -> C (grandchild). - Return a (child, grandchild) tuple. - The 2 processes are fully initialized and will live for 60 secs - and are registered for cleanup on reap_children(). - """ - _TESTFN2 = os.path.basename(_TESTFN) + '2' # need to be relative - s = textwrap.dedent("""\ - import subprocess, os, sys, time - s = "import os, time;" - s += "f = open('%s', 'w');" - s += "f.write(str(os.getpid()));" - s += "f.close();" - s += "time.sleep(60);" - p = subprocess.Popen([r'%s', '-c', s]) - p.wait() - """ % (_TESTFN2, PYTHON_EXE)) - # On Windows if we create a subprocess with CREATE_NO_WINDOW flag - # set (which is the default) a "conhost.exe" extra process will be - # spawned as a child. We don't want that. - if WINDOWS: - subp = pyrun(s, creationflags=0) - else: - subp = pyrun(s) - child1 = psutil.Process(subp.pid) - data = wait_for_file(_TESTFN2, delete=False, empty=False) - safe_rmpath(_TESTFN2) - child2_pid = int(data) - _pids_started.add(child2_pid) - child2 = psutil.Process(child2_pid) - return (child1, child2) - - -def create_zombie_proc(): - """Create a zombie process and return its PID.""" - assert psutil.POSIX - unix_file = tempfile.mktemp(prefix=TESTFILE_PREFIX) if MACOS else TESTFN - src = textwrap.dedent("""\ - import os, sys, time, socket, contextlib - child_pid = os.fork() - if child_pid > 0: - time.sleep(3000) - else: - # this is the zombie process - s = socket.socket(socket.AF_UNIX) - with contextlib.closing(s): - s.connect('%s') - if sys.version_info < (3, ): - pid = str(os.getpid()) - else: - pid = bytes(str(os.getpid()), 'ascii') - s.sendall(pid) - """ % unix_file) - with contextlib.closing(socket.socket(socket.AF_UNIX)) as sock: - sock.settimeout(GLOBAL_TIMEOUT) - sock.bind(unix_file) - sock.listen(5) - pyrun(src) - conn, _ = sock.accept() - try: - select.select([conn.fileno()], [], [], GLOBAL_TIMEOUT) - zpid = int(conn.recv(1024)) - _pids_started.add(zpid) - zproc = psutil.Process(zpid) - call_until(lambda: zproc.status(), "ret == psutil.STATUS_ZOMBIE") - return zpid - finally: - conn.close() - - -@_reap_children_on_err -def pyrun(src, **kwds): - """Run python 'src' code string in a separate interpreter. - Returns a subprocess.Popen instance. - """ - kwds.setdefault("stdout", None) - kwds.setdefault("stderr", None) - with tempfile.NamedTemporaryFile( - prefix=TESTFILE_PREFIX, mode="wt", delete=False) as f: - _testfiles_created.add(f.name) - f.write(src) - f.flush() - subp = get_test_subprocess([PYTHON_EXE, f.name], **kwds) - wait_for_pid(subp.pid) - return subp - - -@_reap_children_on_err -def sh(cmd, **kwds): - """run cmd in a subprocess and return its output. - raises RuntimeError on error. - """ - shell = True if isinstance(cmd, (str, unicode)) else False - # Prevents subprocess to open error dialogs in case of error. - flags = 0x8000000 if WINDOWS and shell else 0 - kwds.setdefault("shell", shell) - kwds.setdefault("stdout", subprocess.PIPE) - kwds.setdefault("stderr", subprocess.PIPE) - kwds.setdefault("universal_newlines", True) - kwds.setdefault("creationflags", flags) - p = subprocess.Popen(cmd, **kwds) - _subprocesses_started.add(p) - if PY3: - stdout, stderr = p.communicate(timeout=GLOBAL_TIMEOUT) - else: - stdout, stderr = p.communicate() - if p.returncode != 0: - raise RuntimeError(stderr) - if stderr: - warn(stderr) - if stdout.endswith('\n'): - stdout = stdout[:-1] - return stdout - - -def reap_children(recursive=False): - """Terminate and wait() any subprocess started by this test suite - and ensure that no zombies stick around to hog resources and - create problems when looking for refleaks. - - If resursive is True it also tries to terminate and wait() - all grandchildren started by this process. - """ - # This is here to make sure wait_procs() behaves properly and - # investigate: - # https://ci.appveyor.com/project/giampaolo/psutil/build/job/ - # jiq2cgd6stsbtn60 - def assert_gone(pid): - assert not psutil.pid_exists(pid), pid - assert pid not in psutil.pids(), pid - try: - p = psutil.Process(pid) - assert not p.is_running(), pid - except psutil.NoSuchProcess: - pass - else: - assert 0, "pid %s is not gone" % pid - - # Get the children here, before terminating the children sub - # processes as we don't want to lose the intermediate reference - # in case of grandchildren. - if recursive: - children = set(psutil.Process().children(recursive=True)) - else: - children = set() - - # Terminate subprocess.Popen instances "cleanly" by closing their - # fds and wiat()ing for them in order to avoid zombies. - while _subprocesses_started: - subp = _subprocesses_started.pop() - _pids_started.add(subp.pid) - try: - subp.terminate() - except OSError as err: - if WINDOWS and err.winerror == 6: # "invalid handle" - pass - elif err.errno != errno.ESRCH: - raise - if subp.stdout: - subp.stdout.close() - if subp.stderr: - subp.stderr.close() - try: - # Flushing a BufferedWriter may raise an error. - if subp.stdin: - subp.stdin.close() - finally: - # Wait for the process to terminate, to avoid zombies. - try: - subp.wait() - except ChildProcessError: - pass - - # Terminate started pids. - while _pids_started: - pid = _pids_started.pop() - try: - p = psutil.Process(pid) - except psutil.NoSuchProcess: - assert_gone(pid) - else: - children.add(p) - - # Terminate children. - if children: - for p in children: - try: - p.terminate() - except psutil.NoSuchProcess: - pass - gone, alive = psutil.wait_procs(children, timeout=GLOBAL_TIMEOUT) - for p in alive: - warn("couldn't terminate process %r; attempting kill()" % p) - try: - p.kill() - except psutil.NoSuchProcess: - pass - gone, alive = psutil.wait_procs(alive, timeout=GLOBAL_TIMEOUT) - if alive: - for p in alive: - warn("process %r survived kill()" % p) - - for p in children: - assert_gone(p.pid) - - -# =================================================================== -# --- OS -# =================================================================== - - -def get_kernel_version(): - """Return a tuple such as (2, 6, 36).""" - if not POSIX: - raise NotImplementedError("not POSIX") - s = "" - uname = os.uname()[2] - for c in uname: - if c.isdigit() or c == '.': - s += c - else: - break - if not s: - raise ValueError("can't parse %r" % uname) - minor = 0 - micro = 0 - nums = s.split('.') - major = int(nums[0]) - if len(nums) >= 2: - minor = int(nums[1]) - if len(nums) >= 3: - micro = int(nums[2]) - return (major, minor, micro) - - -def get_winver(): - if not WINDOWS: - raise NotImplementedError("not WINDOWS") - wv = sys.getwindowsversion() - if hasattr(wv, 'service_pack_major'): # python >= 2.7 - sp = wv.service_pack_major or 0 - else: - r = re.search(r"\s\d$", wv[4]) - if r: - sp = int(r.group(0)) - else: - sp = 0 - return (wv[0], wv[1], sp) - - -# =================================================================== -# --- sync primitives -# =================================================================== - - -class retry(object): - """A retry decorator.""" - - def __init__(self, - exception=Exception, - timeout=None, - retries=None, - interval=0.001, - logfun=None, - ): - if timeout and retries: - raise ValueError("timeout and retries args are mutually exclusive") - self.exception = exception - self.timeout = timeout - self.retries = retries - self.interval = interval - self.logfun = logfun - - def __iter__(self): - if self.timeout: - stop_at = time.time() + self.timeout - while time.time() < stop_at: - yield - elif self.retries: - for _ in range(self.retries): - yield - else: - while True: - yield - - def sleep(self): - if self.interval is not None: - time.sleep(self.interval) - - def __call__(self, fun): - @functools.wraps(fun) - def wrapper(*args, **kwargs): - exc = None - for _ in self: - try: - return fun(*args, **kwargs) - except self.exception as _: # NOQA - exc = _ - if self.logfun is not None: - self.logfun(exc) - self.sleep() - continue - if PY3: - raise exc - else: - raise - - # This way the user of the decorated function can change config - # parameters. - wrapper.decorator = self - return wrapper - - -@retry(exception=psutil.NoSuchProcess, logfun=None, timeout=GLOBAL_TIMEOUT, - interval=0.001) -def wait_for_pid(pid): - """Wait for pid to show up in the process list then return. - Used in the test suite to give time the sub process to initialize. - """ - psutil.Process(pid) - if WINDOWS: - # give it some more time to allow better initialization - time.sleep(0.01) - - -@retry(exception=(EnvironmentError, AssertionError), logfun=None, - timeout=GLOBAL_TIMEOUT, interval=0.001) -def wait_for_file(fname, delete=True, empty=False): - """Wait for a file to be written on disk with some content.""" - with open(fname, "rb") as f: - data = f.read() - if not empty: - assert data - if delete: - safe_rmpath(fname) - return data - - -@retry(exception=AssertionError, logfun=None, timeout=GLOBAL_TIMEOUT, - interval=0.001) -def call_until(fun, expr): - """Keep calling function for timeout secs and exit if eval() - expression is True. - """ - ret = fun() - assert eval(expr) - return ret - - -# =================================================================== -# --- fs -# =================================================================== - - -def safe_rmpath(path): - "Convenience function for removing temporary test files or dirs" - def retry_fun(fun): - # On Windows it could happen that the file or directory has - # open handles or references preventing the delete operation - # to succeed immediately, so we retry for a while. See: - # https://bugs.python.org/issue33240 - stop_at = time.time() + 1 - while time.time() < stop_at: - try: - return fun() - except FileNotFoundError: - pass - except WindowsError as _: - err = _ - warn("ignoring %s" % (str(err))) - time.sleep(0.01) - raise err - - try: - st = os.stat(path) - if stat.S_ISDIR(st.st_mode): - fun = functools.partial(shutil.rmtree, path) - else: - fun = functools.partial(os.remove, path) - if POSIX: - fun() - else: - retry_fun(fun) - except FileNotFoundError: - pass - - -def safe_mkdir(dir): - "Convenience function for creating a directory" - try: - os.mkdir(dir) - except FileExistsError: - pass - - -@contextlib.contextmanager -def chdir(dirname): - "Context manager which temporarily changes the current directory." - curdir = os.getcwd() - try: - os.chdir(dirname) - yield - finally: - os.chdir(curdir) - - -def create_exe(outpath, c_code=None): - """Creates an executable file in the given location.""" - assert not os.path.exists(outpath), outpath - if c_code: - if not which("gcc"): - raise ValueError("gcc is not installed") - if isinstance(c_code, bool): # c_code is True - c_code = textwrap.dedent( - """ - #include - int main() { - pause(); - return 1; - } - """) - assert isinstance(c_code, str), c_code - with tempfile.NamedTemporaryFile( - suffix='.c', delete=False, mode='wt') as f: - f.write(c_code) - try: - subprocess.check_call(["gcc", f.name, "-o", outpath]) - finally: - safe_rmpath(f.name) - else: - # copy python executable - shutil.copyfile(PYTHON_EXE, outpath) - if POSIX: - st = os.stat(outpath) - os.chmod(outpath, st.st_mode | stat.S_IEXEC) - - -def unique_filename(prefix=TESTFILE_PREFIX, suffix=""): - return tempfile.mktemp(prefix=prefix, suffix=suffix) - - -# =================================================================== -# --- testing -# =================================================================== - - -class TestCase(unittest.TestCase): - - # Print a full path representation of the single unit tests - # being run. - def __str__(self): - fqmod = self.__class__.__module__ - if not fqmod.startswith('psutil.'): - fqmod = 'psutil.tests.' + fqmod - return "%s.%s.%s" % ( - fqmod, self.__class__.__name__, self._testMethodName) - - # assertRaisesRegexp renamed to assertRaisesRegex in 3.3; - # add support for the new name. - if not hasattr(unittest.TestCase, 'assertRaisesRegex'): - assertRaisesRegex = unittest.TestCase.assertRaisesRegexp - - -# override default unittest.TestCase -unittest.TestCase = TestCase - - -def retry_on_failure(retries=NO_RETRIES): - """Decorator which runs a test function and retries N times before - actually failing. - """ - def logfun(exc): - print("%r, retrying" % exc, file=sys.stderr) - - return retry(exception=AssertionError, timeout=None, retries=retries, - logfun=logfun) - - -def skip_on_access_denied(only_if=None): - """Decorator to Ignore AccessDenied exceptions.""" - def decorator(fun): - @functools.wraps(fun) - def wrapper(*args, **kwargs): - try: - return fun(*args, **kwargs) - except psutil.AccessDenied: - if only_if is not None: - if not only_if: - raise - raise unittest.SkipTest("raises AccessDenied") - return wrapper - return decorator - - -def skip_on_not_implemented(only_if=None): - """Decorator to Ignore NotImplementedError exceptions.""" - def decorator(fun): - @functools.wraps(fun) - def wrapper(*args, **kwargs): - try: - return fun(*args, **kwargs) - except NotImplementedError: - if only_if is not None: - if not only_if: - raise - msg = "%r was skipped because it raised NotImplementedError" \ - % fun.__name__ - raise unittest.SkipTest(msg) - return wrapper - return decorator - - -# =================================================================== -# --- network -# =================================================================== - - -def get_free_port(host='127.0.0.1'): - """Return an unused TCP port.""" - with contextlib.closing(socket.socket()) as sock: - sock.bind((host, 0)) - return sock.getsockname()[1] - - -@contextlib.contextmanager -def unix_socket_path(suffix=""): - """A context manager which returns a non-existent file name - and tries to delete it on exit. - """ - assert psutil.POSIX - path = unique_filename(suffix=suffix) - try: - yield path - finally: - try: - os.unlink(path) - except OSError: - pass - - -def bind_socket(family=AF_INET, type=SOCK_STREAM, addr=None): - """Binds a generic socket.""" - if addr is None and family in (AF_INET, AF_INET6): - addr = ("", 0) - sock = socket.socket(family, type) - try: - if os.name not in ('nt', 'cygwin'): - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - sock.bind(addr) - if type == socket.SOCK_STREAM: - sock.listen(5) - return sock - except Exception: - sock.close() - raise - - -def bind_unix_socket(name, type=socket.SOCK_STREAM): - """Bind a UNIX socket.""" - assert psutil.POSIX - assert not os.path.exists(name), name - sock = socket.socket(socket.AF_UNIX, type) - try: - sock.bind(name) - if type == socket.SOCK_STREAM: - sock.listen(5) - except Exception: - sock.close() - raise - return sock - - -def tcp_socketpair(family, addr=("", 0)): - """Build a pair of TCP sockets connected to each other. - Return a (server, client) tuple. - """ - with contextlib.closing(socket.socket(family, SOCK_STREAM)) as ll: - ll.bind(addr) - ll.listen(5) - addr = ll.getsockname() - c = socket.socket(family, SOCK_STREAM) - try: - c.connect(addr) - caddr = c.getsockname() - while True: - a, addr = ll.accept() - # check that we've got the correct client - if addr == caddr: - return (a, c) - a.close() - except OSError: - c.close() - raise - - -def unix_socketpair(name): - """Build a pair of UNIX sockets connected to each other through - the same UNIX file name. - Return a (server, client) tuple. - """ - assert psutil.POSIX - server = client = None - try: - server = bind_unix_socket(name, type=socket.SOCK_STREAM) - server.setblocking(0) - client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - client.setblocking(0) - client.connect(name) - # new = server.accept() - except Exception: - if server is not None: - server.close() - if client is not None: - client.close() - raise - return (server, client) - - -@contextlib.contextmanager -def create_sockets(): - """Open as many socket families / types as possible.""" - socks = [] - fname1 = fname2 = None - try: - socks.append(bind_socket(socket.AF_INET, socket.SOCK_STREAM)) - socks.append(bind_socket(socket.AF_INET, socket.SOCK_DGRAM)) - if supports_ipv6(): - socks.append(bind_socket(socket.AF_INET6, socket.SOCK_STREAM)) - socks.append(bind_socket(socket.AF_INET6, socket.SOCK_DGRAM)) - if POSIX and HAS_CONNECTIONS_UNIX: - fname1 = unix_socket_path().__enter__() - fname2 = unix_socket_path().__enter__() - s1, s2 = unix_socketpair(fname1) - s3 = bind_unix_socket(fname2, type=socket.SOCK_DGRAM) - # self.addCleanup(safe_rmpath, fname1) - # self.addCleanup(safe_rmpath, fname2) - for s in (s1, s2, s3): - socks.append(s) - yield socks - finally: - for s in socks: - s.close() - if fname1 is not None: - safe_rmpath(fname1) - if fname2 is not None: - safe_rmpath(fname2) - - -def check_net_address(addr, family): - """Check a net address validity. Supported families are IPv4, - IPv6 and MAC addresses. - """ - import ipaddress # python >= 3.3 / requires "pip install ipaddress" - if enum and PY3: - assert isinstance(family, enum.IntEnum), family - if family == socket.AF_INET: - octs = [int(x) for x in addr.split('.')] - assert len(octs) == 4, addr - for num in octs: - assert 0 <= num <= 255, addr - if not PY3: - addr = unicode(addr) - ipaddress.IPv4Address(addr) - elif family == socket.AF_INET6: - assert isinstance(addr, str), addr - if not PY3: - addr = unicode(addr) - ipaddress.IPv6Address(addr) - elif family == psutil.AF_LINK: - assert re.match(r'([a-fA-F0-9]{2}[:|\-]?){6}', addr) is not None, addr - else: - raise ValueError("unknown family %r", family) - - -# =================================================================== -# --- compatibility -# =================================================================== - - -def reload_module(module): - """Backport of importlib.reload of Python 3.3+.""" - try: - import importlib - if not hasattr(importlib, 'reload'): # python <=3.3 - raise ImportError - except ImportError: - import imp - return imp.reload(module) - else: - return importlib.reload(module) - - -def import_module_by_path(path): - name = os.path.splitext(os.path.basename(path))[0] - if sys.version_info[0] == 2: - import imp - return imp.load_source(name, path) - elif sys.version_info[:2] <= (3, 4): - from importlib.machinery import SourceFileLoader - return SourceFileLoader(name, path).load_module() - else: - import importlib.util - spec = importlib.util.spec_from_file_location(name, path) - mod = importlib.util.module_from_spec(spec) - spec.loader.exec_module(mod) - return mod - - -# =================================================================== -# --- others -# =================================================================== - - -def warn(msg): - """Raise a warning msg.""" - warnings.warn(msg, UserWarning) - - -def is_namedtuple(x): - """Check if object is an instance of namedtuple.""" - t = type(x) - b = t.__bases__ - if len(b) != 1 or b[0] != tuple: - return False - f = getattr(t, '_fields', None) - if not isinstance(f, tuple): - return False - return all(type(n) == str for n in f) - - -if POSIX: - @contextlib.contextmanager - def copyload_shared_lib(dst_prefix=TESTFILE_PREFIX): - """Ctx manager which picks up a random shared CO lib used - by this process, copies it in another location and loads it - in memory via ctypes. Return the new absolutized path. - """ - exe = 'pypy' if PYPY else 'python' - ext = ".so" - dst = tempfile.mktemp(prefix=dst_prefix, suffix=ext) - libs = [x.path for x in psutil.Process().memory_maps() if - os.path.splitext(x.path)[1] == ext and - exe in x.path.lower()] - src = random.choice(libs) - shutil.copyfile(src, dst) - try: - ctypes.CDLL(dst) - yield dst - finally: - safe_rmpath(dst) -else: - @contextlib.contextmanager - def copyload_shared_lib(dst_prefix=TESTFILE_PREFIX): - """Ctx manager which picks up a random shared DLL lib used - by this process, copies it in another location and loads it - in memory via ctypes. - Return the new absolutized, normcased path. - """ - from ctypes import wintypes - from ctypes import WinError - ext = ".dll" - dst = tempfile.mktemp(prefix=dst_prefix, suffix=ext) - libs = [x.path for x in psutil.Process().memory_maps() if - x.path.lower().endswith(ext) and - 'python' in os.path.basename(x.path).lower() and - 'wow64' not in x.path.lower()] - if PYPY and not libs: - libs = [x.path for x in psutil.Process().memory_maps() if - 'pypy' in os.path.basename(x.path).lower()] - src = random.choice(libs) - shutil.copyfile(src, dst) - cfile = None - try: - cfile = ctypes.WinDLL(dst) - yield dst - finally: - # Work around OverflowError: - # - https://ci.appveyor.com/project/giampaolo/psutil/build/1207/ - # job/o53330pbnri9bcw7 - # - http://bugs.python.org/issue30286 - # - http://stackoverflow.com/questions/23522055 - if cfile is not None: - FreeLibrary = ctypes.windll.kernel32.FreeLibrary - FreeLibrary.argtypes = [wintypes.HMODULE] - ret = FreeLibrary(cfile._handle) - if ret == 0: - WinError() - safe_rmpath(dst) diff --git a/third_party/python/psutil/psutil/tests/__main__.py b/third_party/python/psutil/psutil/tests/__main__.py deleted file mode 100755 index d5cd02eb1c28..000000000000 --- a/third_party/python/psutil/psutil/tests/__main__.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Run unit tests. This is invoked by: -$ python -m psutil.tests -""" - -from .runner import main -main() diff --git a/third_party/python/psutil/psutil/tests/runner.py b/third_party/python/psutil/psutil/tests/runner.py deleted file mode 100755 index 2e9264bd4281..000000000000 --- a/third_party/python/psutil/psutil/tests/runner.py +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Unit test runner, providing new features on top of unittest module: -- colourized output (error, skip) -- print failures/tracebacks on CTRL+C -- re-run failed tests only (make test-failed) -""" - -from __future__ import print_function -import optparse -import os -import sys -import unittest -from unittest import TestResult -from unittest import TextTestResult -from unittest import TextTestRunner -try: - import ctypes -except ImportError: - ctypes = None - -import psutil -from psutil._common import hilite -from psutil._common import print_color -from psutil._common import term_supports_colors -from psutil.tests import safe_rmpath -from psutil.tests import TOX - - -HERE = os.path.abspath(os.path.dirname(__file__)) -VERBOSITY = 1 if TOX else 2 -FAILED_TESTS_FNAME = '.failed-tests.txt' - - -# ===================================================================== -# --- unittest subclasses -# ===================================================================== - - -class ColouredResult(TextTestResult): - - def _print_color(self, s, color, bold=False): - file = sys.stderr if color == "red" else sys.stdout - print_color(s, color, bold=bold, file=file) - - def addSuccess(self, test): - TestResult.addSuccess(self, test) - self._print_color("OK", "green") - - def addError(self, test, err): - TestResult.addError(self, test, err) - self._print_color("ERROR", "red", bold=True) - - def addFailure(self, test, err): - TestResult.addFailure(self, test, err) - self._print_color("FAIL", "red") - - def addSkip(self, test, reason): - TestResult.addSkip(self, test, reason) - self._print_color("skipped: %s" % reason, "brown") - - def printErrorList(self, flavour, errors): - flavour = hilite(flavour, "red", bold=flavour == 'ERROR') - TextTestResult.printErrorList(self, flavour, errors) - - -class ColouredRunner(TextTestRunner): - resultclass = ColouredResult if term_supports_colors() else TextTestResult - - def _makeResult(self): - # Store result instance so that it can be accessed on - # KeyboardInterrupt. - self.result = TextTestRunner._makeResult(self) - return self.result - - -# ===================================================================== -# --- public API -# ===================================================================== - - -def setup_tests(): - if 'PSUTIL_TESTING' not in os.environ: - # This won't work on Windows but set_testing() below will do it. - os.environ['PSUTIL_TESTING'] = '1' - psutil._psplatform.cext.set_testing() - - -def get_suite(name=None): - suite = unittest.TestSuite() - if name is None: - testmods = [os.path.splitext(x)[0] for x in os.listdir(HERE) - if x.endswith('.py') and x.startswith('test_') and not - x.startswith('test_memory_leaks')] - if "WHEELHOUSE_UPLOADER_USERNAME" in os.environ: - testmods = [x for x in testmods if not x.endswith(( - "osx", "posix", "linux"))] - for tm in testmods: - # ...so that the full test paths are printed on screen - tm = "psutil.tests.%s" % tm - suite.addTest(unittest.defaultTestLoader.loadTestsFromName(tm)) - else: - name = os.path.splitext(os.path.basename(name))[0] - suite.addTest(unittest.defaultTestLoader.loadTestsFromName(name)) - return suite - - -def get_suite_from_failed(): - # ...from previously failed test run - suite = unittest.TestSuite() - if not os.path.isfile(FAILED_TESTS_FNAME): - return suite - with open(FAILED_TESTS_FNAME, 'rt') as f: - names = f.read().split() - for n in names: - suite.addTest(unittest.defaultTestLoader.loadTestsFromName(n)) - return suite - - -def save_failed_tests(result): - if result.wasSuccessful(): - return safe_rmpath(FAILED_TESTS_FNAME) - with open(FAILED_TESTS_FNAME, 'wt') as f: - for t in result.errors + result.failures: - tname = str(t[0]) - unittest.defaultTestLoader.loadTestsFromName(tname) - f.write(tname + '\n') - - -def run(name=None, last_failed=False): - setup_tests() - runner = ColouredRunner(verbosity=VERBOSITY) - suite = get_suite_from_failed() if last_failed else get_suite(name) - try: - result = runner.run(suite) - except (KeyboardInterrupt, SystemExit) as err: - print("received %s" % err.__class__.__name__, file=sys.stderr) - runner.result.printErrors() - sys.exit(1) - else: - save_failed_tests(result) - success = result.wasSuccessful() - sys.exit(0 if success else 1) - - -def main(): - usage = "python3 -m psutil.tests [opts]" - parser = optparse.OptionParser(usage=usage, description="run unit tests") - parser.add_option("--last-failed", - action="store_true", default=False, - help="only run last failed tests") - opts, args = parser.parse_args() - run(last_failed=opts.last_failed) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/psutil/tests/test_aix.py b/third_party/python/psutil/psutil/tests/test_aix.py deleted file mode 100755 index 7171232e08f1..000000000000 --- a/third_party/python/psutil/psutil/tests/test_aix.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2009, Giampaolo Rodola' -# Copyright (c) 2017, Arnon Yaari -# All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""AIX specific tests.""" - -import re - -from psutil import AIX -from psutil.tests import sh -from psutil.tests import unittest -import psutil - - -@unittest.skipIf(not AIX, "AIX only") -class AIXSpecificTestCase(unittest.TestCase): - - def test_virtual_memory(self): - out = sh('/usr/bin/svmon -O unit=KB') - re_pattern = r"memory\s*" - for field in ("size inuse free pin virtual available mmode").split(): - re_pattern += r"(?P<%s>\S+)\s+" % (field,) - matchobj = re.search(re_pattern, out) - - self.assertIsNotNone( - matchobj, "svmon command returned unexpected output") - - KB = 1024 - total = int(matchobj.group("size")) * KB - available = int(matchobj.group("available")) * KB - used = int(matchobj.group("inuse")) * KB - free = int(matchobj.group("free")) * KB - - psutil_result = psutil.virtual_memory() - - # MEMORY_TOLERANCE from psutil.tests is not enough. For some reason - # we're seeing differences of ~1.2 MB. 2 MB is still a good tolerance - # when compared to GBs. - MEMORY_TOLERANCE = 2 * KB * KB # 2 MB - self.assertEqual(psutil_result.total, total) - self.assertAlmostEqual( - psutil_result.used, used, delta=MEMORY_TOLERANCE) - self.assertAlmostEqual( - psutil_result.available, available, delta=MEMORY_TOLERANCE) - self.assertAlmostEqual( - psutil_result.free, free, delta=MEMORY_TOLERANCE) - - def test_swap_memory(self): - out = sh('/usr/sbin/lsps -a') - # From the man page, "The size is given in megabytes" so we assume - # we'll always have 'MB' in the result - # TODO maybe try to use "swap -l" to check "used" too, but its units - # are not guaranteed to be "MB" so parsing may not be consistent - matchobj = re.search(r"(?P\S+)\s+" - r"(?P\S+)\s+" - r"(?P\S+)\s+" - r"(?P\d+)MB", out) - - self.assertIsNotNone( - matchobj, "lsps command returned unexpected output") - - total_mb = int(matchobj.group("size")) - MB = 1024 ** 2 - psutil_result = psutil.swap_memory() - # we divide our result by MB instead of multiplying the lsps value by - # MB because lsps may round down, so we round down too - self.assertEqual(int(psutil_result.total / MB), total_mb) - - def test_cpu_stats(self): - out = sh('/usr/bin/mpstat -a') - - re_pattern = r"ALL\s*" - for field in ("min maj mpcs mpcr dev soft dec ph cs ics bound rq " - "push S3pull S3grd S0rd S1rd S2rd S3rd S4rd S5rd " - "sysc").split(): - re_pattern += r"(?P<%s>\S+)\s+" % (field,) - matchobj = re.search(re_pattern, out) - - self.assertIsNotNone( - matchobj, "mpstat command returned unexpected output") - - # numbers are usually in the millions so 1000 is ok for tolerance - CPU_STATS_TOLERANCE = 1000 - psutil_result = psutil.cpu_stats() - self.assertAlmostEqual( - psutil_result.ctx_switches, - int(matchobj.group("cs")), - delta=CPU_STATS_TOLERANCE) - self.assertAlmostEqual( - psutil_result.syscalls, - int(matchobj.group("sysc")), - delta=CPU_STATS_TOLERANCE) - self.assertAlmostEqual( - psutil_result.interrupts, - int(matchobj.group("dev")), - delta=CPU_STATS_TOLERANCE) - self.assertAlmostEqual( - psutil_result.soft_interrupts, - int(matchobj.group("soft")), - delta=CPU_STATS_TOLERANCE) - - def test_cpu_count_logical(self): - out = sh('/usr/bin/mpstat -a') - mpstat_lcpu = int(re.search(r"lcpu=(\d+)", out).group(1)) - psutil_lcpu = psutil.cpu_count(logical=True) - self.assertEqual(mpstat_lcpu, psutil_lcpu) - - def test_net_if_addrs_names(self): - out = sh('/etc/ifconfig -l') - ifconfig_names = set(out.split()) - psutil_names = set(psutil.net_if_addrs().keys()) - self.assertSetEqual(ifconfig_names, psutil_names) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_bsd.py b/third_party/python/psutil/psutil/tests/test_bsd.py deleted file mode 100755 index 899875d076dc..000000000000 --- a/third_party/python/psutil/psutil/tests/test_bsd.py +++ /dev/null @@ -1,565 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -# TODO: (FreeBSD) add test for comparing connections with 'sockstat' cmd. - - -"""Tests specific to all BSD platforms.""" - - -import datetime -import os -import re -import time - -import psutil -from psutil import BSD -from psutil import FREEBSD -from psutil import NETBSD -from psutil import OPENBSD -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_BATTERY -from psutil.tests import MEMORY_TOLERANCE -from psutil.tests import reap_children -from psutil.tests import retry_on_failure -from psutil.tests import sh -from psutil.tests import unittest -from psutil.tests import which - - -if BSD: - PAGESIZE = os.sysconf("SC_PAGE_SIZE") - if os.getuid() == 0: # muse requires root privileges - MUSE_AVAILABLE = which('muse') - else: - MUSE_AVAILABLE = False -else: - MUSE_AVAILABLE = False - - -def sysctl(cmdline): - """Expects a sysctl command with an argument and parse the result - returning only the value of interest. - """ - result = sh("sysctl " + cmdline) - if FREEBSD: - result = result[result.find(": ") + 2:] - elif OPENBSD or NETBSD: - result = result[result.find("=") + 1:] - try: - return int(result) - except ValueError: - return result - - -def muse(field): - """Thin wrapper around 'muse' cmdline utility.""" - out = sh('muse') - for line in out.split('\n'): - if line.startswith(field): - break - else: - raise ValueError("line not found") - return int(line.split()[1]) - - -# ===================================================================== -# --- All BSD* -# ===================================================================== - - -@unittest.skipIf(not BSD, "BSD only") -class BSDTestCase(unittest.TestCase): - """Generic tests common to all BSD variants.""" - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - @unittest.skipIf(NETBSD, "-o lstart doesn't work on NETBSD") - def test_process_create_time(self): - output = sh("ps -o lstart -p %s" % self.pid) - start_ps = output.replace('STARTED', '').strip() - start_psutil = psutil.Process(self.pid).create_time() - start_psutil = time.strftime("%a %b %e %H:%M:%S %Y", - time.localtime(start_psutil)) - self.assertEqual(start_ps, start_psutil) - - def test_disks(self): - # test psutil.disk_usage() and psutil.disk_partitions() - # against "df -a" - def df(path): - out = sh('df -k "%s"' % path).strip() - lines = out.split('\n') - lines.pop(0) - line = lines.pop(0) - dev, total, used, free = line.split()[:4] - if dev == 'none': - dev = '' - total = int(total) * 1024 - used = int(used) * 1024 - free = int(free) * 1024 - return dev, total, used, free - - for part in psutil.disk_partitions(all=False): - usage = psutil.disk_usage(part.mountpoint) - dev, total, used, free = df(part.mountpoint) - self.assertEqual(part.device, dev) - self.assertEqual(usage.total, total) - # 10 MB tollerance - if abs(usage.free - free) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.free, free)) - if abs(usage.used - used) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.used, used)) - - @unittest.skipIf(not which('sysctl'), "sysctl cmd not available") - def test_cpu_count_logical(self): - syst = sysctl("hw.ncpu") - self.assertEqual(psutil.cpu_count(logical=True), syst) - - @unittest.skipIf(not which('sysctl'), "sysctl cmd not available") - def test_virtual_memory_total(self): - num = sysctl('hw.physmem') - self.assertEqual(num, psutil.virtual_memory().total) - - def test_net_if_stats(self): - for name, stats in psutil.net_if_stats().items(): - try: - out = sh("ifconfig %s" % name) - except RuntimeError: - pass - else: - self.assertEqual(stats.isup, 'RUNNING' in out, msg=out) - if "mtu" in out: - self.assertEqual(stats.mtu, - int(re.findall(r'mtu (\d+)', out)[0])) - - -# ===================================================================== -# --- FreeBSD -# ===================================================================== - - -@unittest.skipIf(not FREEBSD, "FREEBSD only") -class FreeBSDProcessTestCase(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - @retry_on_failure() - def test_memory_maps(self): - out = sh('procstat -v %s' % self.pid) - maps = psutil.Process(self.pid).memory_maps(grouped=False) - lines = out.split('\n')[1:] - while lines: - line = lines.pop() - fields = line.split() - _, start, stop, perms, res = fields[:5] - map = maps.pop() - self.assertEqual("%s-%s" % (start, stop), map.addr) - self.assertEqual(int(res), map.rss) - if not map.path.startswith('['): - self.assertEqual(fields[10], map.path) - - def test_exe(self): - out = sh('procstat -b %s' % self.pid) - self.assertEqual(psutil.Process(self.pid).exe(), - out.split('\n')[1].split()[-1]) - - def test_cmdline(self): - out = sh('procstat -c %s' % self.pid) - self.assertEqual(' '.join(psutil.Process(self.pid).cmdline()), - ' '.join(out.split('\n')[1].split()[2:])) - - def test_uids_gids(self): - out = sh('procstat -s %s' % self.pid) - euid, ruid, suid, egid, rgid, sgid = out.split('\n')[1].split()[2:8] - p = psutil.Process(self.pid) - uids = p.uids() - gids = p.gids() - self.assertEqual(uids.real, int(ruid)) - self.assertEqual(uids.effective, int(euid)) - self.assertEqual(uids.saved, int(suid)) - self.assertEqual(gids.real, int(rgid)) - self.assertEqual(gids.effective, int(egid)) - self.assertEqual(gids.saved, int(sgid)) - - @retry_on_failure() - def test_ctx_switches(self): - tested = [] - out = sh('procstat -r %s' % self.pid) - p = psutil.Process(self.pid) - for line in out.split('\n'): - line = line.lower().strip() - if ' voluntary context' in line: - pstat_value = int(line.split()[-1]) - psutil_value = p.num_ctx_switches().voluntary - self.assertEqual(pstat_value, psutil_value) - tested.append(None) - elif ' involuntary context' in line: - pstat_value = int(line.split()[-1]) - psutil_value = p.num_ctx_switches().involuntary - self.assertEqual(pstat_value, psutil_value) - tested.append(None) - if len(tested) != 2: - raise RuntimeError("couldn't find lines match in procstat out") - - @retry_on_failure() - def test_cpu_times(self): - tested = [] - out = sh('procstat -r %s' % self.pid) - p = psutil.Process(self.pid) - for line in out.split('\n'): - line = line.lower().strip() - if 'user time' in line: - pstat_value = float('0.' + line.split()[-1].split('.')[-1]) - psutil_value = p.cpu_times().user - self.assertEqual(pstat_value, psutil_value) - tested.append(None) - elif 'system time' in line: - pstat_value = float('0.' + line.split()[-1].split('.')[-1]) - psutil_value = p.cpu_times().system - self.assertEqual(pstat_value, psutil_value) - tested.append(None) - if len(tested) != 2: - raise RuntimeError("couldn't find lines match in procstat out") - - -@unittest.skipIf(not FREEBSD, "FREEBSD only") -class FreeBSDSystemTestCase(unittest.TestCase): - - @staticmethod - def parse_swapinfo(): - # the last line is always the total - output = sh("swapinfo -k").splitlines()[-1] - parts = re.split(r'\s+', output) - - if not parts: - raise ValueError("Can't parse swapinfo: %s" % output) - - # the size is in 1k units, so multiply by 1024 - total, used, free = (int(p) * 1024 for p in parts[1:4]) - return total, used, free - - def test_cpu_frequency_against_sysctl(self): - # Currently only cpu 0 is frequency is supported in FreeBSD - # All other cores use the same frequency. - sensor = "dev.cpu.0.freq" - try: - sysctl_result = int(sysctl(sensor)) - except RuntimeError: - self.skipTest("frequencies not supported by kernel") - self.assertEqual(psutil.cpu_freq().current, sysctl_result) - - sensor = "dev.cpu.0.freq_levels" - sysctl_result = sysctl(sensor) - # sysctl returns a string of the format: - # / /... - # Ordered highest available to lowest available. - max_freq = int(sysctl_result.split()[0].split("/")[0]) - min_freq = int(sysctl_result.split()[-1].split("/")[0]) - self.assertEqual(psutil.cpu_freq().max, max_freq) - self.assertEqual(psutil.cpu_freq().min, min_freq) - - # --- virtual_memory(); tests against sysctl - - @retry_on_failure() - def test_vmem_active(self): - syst = sysctl("vm.stats.vm.v_active_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().active, syst, - delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_inactive(self): - syst = sysctl("vm.stats.vm.v_inactive_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().inactive, syst, - delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_wired(self): - syst = sysctl("vm.stats.vm.v_wire_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().wired, syst, - delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_cached(self): - syst = sysctl("vm.stats.vm.v_cache_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().cached, syst, - delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_free(self): - syst = sysctl("vm.stats.vm.v_free_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().free, syst, - delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_buffers(self): - syst = sysctl("vfs.bufspace") - self.assertAlmostEqual(psutil.virtual_memory().buffers, syst, - delta=MEMORY_TOLERANCE) - - # --- virtual_memory(); tests against muse - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - def test_muse_vmem_total(self): - num = muse('Total') - self.assertEqual(psutil.virtual_memory().total, num) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_active(self): - num = muse('Active') - self.assertAlmostEqual(psutil.virtual_memory().active, num, - delta=MEMORY_TOLERANCE) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_inactive(self): - num = muse('Inactive') - self.assertAlmostEqual(psutil.virtual_memory().inactive, num, - delta=MEMORY_TOLERANCE) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_wired(self): - num = muse('Wired') - self.assertAlmostEqual(psutil.virtual_memory().wired, num, - delta=MEMORY_TOLERANCE) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_cached(self): - num = muse('Cache') - self.assertAlmostEqual(psutil.virtual_memory().cached, num, - delta=MEMORY_TOLERANCE) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_free(self): - num = muse('Free') - self.assertAlmostEqual(psutil.virtual_memory().free, num, - delta=MEMORY_TOLERANCE) - - @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") - @retry_on_failure() - def test_muse_vmem_buffers(self): - num = muse('Buffer') - self.assertAlmostEqual(psutil.virtual_memory().buffers, num, - delta=MEMORY_TOLERANCE) - - def test_cpu_stats_ctx_switches(self): - self.assertAlmostEqual(psutil.cpu_stats().ctx_switches, - sysctl('vm.stats.sys.v_swtch'), delta=1000) - - def test_cpu_stats_interrupts(self): - self.assertAlmostEqual(psutil.cpu_stats().interrupts, - sysctl('vm.stats.sys.v_intr'), delta=1000) - - def test_cpu_stats_soft_interrupts(self): - self.assertAlmostEqual(psutil.cpu_stats().soft_interrupts, - sysctl('vm.stats.sys.v_soft'), delta=1000) - - @retry_on_failure() - def test_cpu_stats_syscalls(self): - # pretty high tolerance but it looks like it's OK. - self.assertAlmostEqual(psutil.cpu_stats().syscalls, - sysctl('vm.stats.sys.v_syscall'), delta=200000) - - # def test_cpu_stats_traps(self): - # self.assertAlmostEqual(psutil.cpu_stats().traps, - # sysctl('vm.stats.sys.v_trap'), delta=1000) - - # --- swap memory - - def test_swapmem_free(self): - total, used, free = self.parse_swapinfo() - self.assertAlmostEqual( - psutil.swap_memory().free, free, delta=MEMORY_TOLERANCE) - - def test_swapmem_used(self): - total, used, free = self.parse_swapinfo() - self.assertAlmostEqual( - psutil.swap_memory().used, used, delta=MEMORY_TOLERANCE) - - def test_swapmem_total(self): - total, used, free = self.parse_swapinfo() - self.assertAlmostEqual( - psutil.swap_memory().total, total, delta=MEMORY_TOLERANCE) - - # --- others - - def test_boot_time(self): - s = sysctl('sysctl kern.boottime') - s = s[s.find(" sec = ") + 7:] - s = s[:s.find(',')] - btime = int(s) - self.assertEqual(btime, psutil.boot_time()) - - # --- sensors_battery - - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_sensors_battery(self): - def secs2hours(secs): - m, s = divmod(secs, 60) - h, m = divmod(m, 60) - return "%d:%02d" % (h, m) - - out = sh("acpiconf -i 0") - fields = dict([(x.split('\t')[0], x.split('\t')[-1]) - for x in out.split("\n")]) - metrics = psutil.sensors_battery() - percent = int(fields['Remaining capacity:'].replace('%', '')) - remaining_time = fields['Remaining time:'] - self.assertEqual(metrics.percent, percent) - if remaining_time == 'unknown': - self.assertEqual(metrics.secsleft, psutil.POWER_TIME_UNLIMITED) - else: - self.assertEqual(secs2hours(metrics.secsleft), remaining_time) - - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_sensors_battery_against_sysctl(self): - self.assertEqual(psutil.sensors_battery().percent, - sysctl("hw.acpi.battery.life")) - self.assertEqual(psutil.sensors_battery().power_plugged, - sysctl("hw.acpi.acline") == 1) - secsleft = psutil.sensors_battery().secsleft - if secsleft < 0: - self.assertEqual(sysctl("hw.acpi.battery.time"), -1) - else: - self.assertEqual(secsleft, sysctl("hw.acpi.battery.time") * 60) - - @unittest.skipIf(HAS_BATTERY, "has battery") - def test_sensors_battery_no_battery(self): - # If no battery is present one of these calls is supposed - # to fail, see: - # https://github.com/giampaolo/psutil/issues/1074 - with self.assertRaises(RuntimeError): - sysctl("hw.acpi.battery.life") - sysctl("hw.acpi.battery.time") - sysctl("hw.acpi.acline") - self.assertIsNone(psutil.sensors_battery()) - - # --- sensors_temperatures - - def test_sensors_temperatures_against_sysctl(self): - num_cpus = psutil.cpu_count(True) - for cpu in range(num_cpus): - sensor = "dev.cpu.%s.temperature" % cpu - # sysctl returns a string in the format 46.0C - try: - sysctl_result = int(float(sysctl(sensor)[:-1])) - except RuntimeError: - self.skipTest("temperatures not supported by kernel") - self.assertAlmostEqual( - psutil.sensors_temperatures()["coretemp"][cpu].current, - sysctl_result, delta=10) - - sensor = "dev.cpu.%s.coretemp.tjmax" % cpu - sysctl_result = int(float(sysctl(sensor)[:-1])) - self.assertEqual( - psutil.sensors_temperatures()["coretemp"][cpu].high, - sysctl_result) - -# ===================================================================== -# --- OpenBSD -# ===================================================================== - - -@unittest.skipIf(not OPENBSD, "OPENBSD only") -class OpenBSDTestCase(unittest.TestCase): - - def test_boot_time(self): - s = sysctl('kern.boottime') - sys_bt = datetime.datetime.strptime(s, "%a %b %d %H:%M:%S %Y") - psutil_bt = datetime.datetime.fromtimestamp(psutil.boot_time()) - self.assertEqual(sys_bt, psutil_bt) - - -# ===================================================================== -# --- NetBSD -# ===================================================================== - - -@unittest.skipIf(not NETBSD, "NETBSD only") -class NetBSDTestCase(unittest.TestCase): - - @staticmethod - def parse_meminfo(look_for): - with open('/proc/meminfo', 'rt') as f: - for line in f: - if line.startswith(look_for): - return int(line.split()[1]) * 1024 - raise ValueError("can't find %s" % look_for) - - def test_vmem_total(self): - self.assertEqual( - psutil.virtual_memory().total, self.parse_meminfo("MemTotal:")) - - def test_vmem_free(self): - self.assertAlmostEqual( - psutil.virtual_memory().free, self.parse_meminfo("MemFree:"), - delta=MEMORY_TOLERANCE) - - def test_vmem_buffers(self): - self.assertAlmostEqual( - psutil.virtual_memory().buffers, self.parse_meminfo("Buffers:"), - delta=MEMORY_TOLERANCE) - - def test_vmem_shared(self): - self.assertAlmostEqual( - psutil.virtual_memory().shared, self.parse_meminfo("MemShared:"), - delta=MEMORY_TOLERANCE) - - def test_swapmem_total(self): - self.assertAlmostEqual( - psutil.swap_memory().total, self.parse_meminfo("SwapTotal:"), - delta=MEMORY_TOLERANCE) - - def test_swapmem_free(self): - self.assertAlmostEqual( - psutil.swap_memory().free, self.parse_meminfo("SwapFree:"), - delta=MEMORY_TOLERANCE) - - def test_swapmem_used(self): - smem = psutil.swap_memory() - self.assertEqual(smem.used, smem.total - smem.free) - - def test_cpu_stats_interrupts(self): - with open('/proc/stat', 'rb') as f: - for line in f: - if line.startswith(b'intr'): - interrupts = int(line.split()[1]) - break - else: - raise ValueError("couldn't find line") - self.assertAlmostEqual( - psutil.cpu_stats().interrupts, interrupts, delta=1000) - - def test_cpu_stats_ctx_switches(self): - with open('/proc/stat', 'rb') as f: - for line in f: - if line.startswith(b'ctxt'): - ctx_switches = int(line.split()[1]) - break - else: - raise ValueError("couldn't find line") - self.assertAlmostEqual( - psutil.cpu_stats().ctx_switches, ctx_switches, delta=1000) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_connections.py b/third_party/python/psutil/psutil/tests/test_connections.py deleted file mode 100755 index 972ac9d58ccb..000000000000 --- a/third_party/python/psutil/psutil/tests/test_connections.py +++ /dev/null @@ -1,637 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Tests for net_connections() and Process.connections() APIs.""" - -import contextlib -import errno -import os -import socket -import textwrap -from contextlib import closing -from socket import AF_INET -from socket import AF_INET6 -from socket import SOCK_DGRAM -from socket import SOCK_STREAM - -import psutil -from psutil import FREEBSD -from psutil import LINUX -from psutil import MACOS -from psutil import NETBSD -from psutil import OPENBSD -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -from psutil._common import supports_ipv6 -from psutil._compat import PY3 -from psutil.tests import AF_UNIX -from psutil.tests import bind_socket -from psutil.tests import bind_unix_socket -from psutil.tests import check_net_address -from psutil.tests import CIRRUS -from psutil.tests import create_sockets -from psutil.tests import enum -from psutil.tests import get_free_port -from psutil.tests import HAS_CONNECTIONS_UNIX -from psutil.tests import pyrun -from psutil.tests import reap_children -from psutil.tests import safe_rmpath -from psutil.tests import skip_on_access_denied -from psutil.tests import SKIP_SYSCONS -from psutil.tests import tcp_socketpair -from psutil.tests import TESTFN -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import unix_socket_path -from psutil.tests import unix_socketpair -from psutil.tests import wait_for_file - - -thisproc = psutil.Process() -SOCK_SEQPACKET = getattr(socket, "SOCK_SEQPACKET", object()) - - -class Base(object): - - def setUp(self): - safe_rmpath(TESTFN) - if not (NETBSD or FREEBSD): - # process opens a UNIX socket to /var/log/run. - cons = thisproc.connections(kind='all') - assert not cons, cons - - def tearDown(self): - safe_rmpath(TESTFN) - reap_children() - if not (FREEBSD or NETBSD): - # Make sure we closed all resources. - # NetBSD opens a UNIX socket to /var/log/run. - cons = thisproc.connections(kind='all') - assert not cons, cons - - def compare_procsys_connections(self, pid, proc_cons, kind='all'): - """Given a process PID and its list of connections compare - those against system-wide connections retrieved via - psutil.net_connections. - """ - try: - sys_cons = psutil.net_connections(kind=kind) - except psutil.AccessDenied: - # On MACOS, system-wide connections are retrieved by iterating - # over all processes - if MACOS: - return - else: - raise - # Filter for this proc PID and exlucde PIDs from the tuple. - sys_cons = [c[:-1] for c in sys_cons if c.pid == pid] - sys_cons.sort() - proc_cons.sort() - self.assertEqual(proc_cons, sys_cons) - - def check_connection_ntuple(self, conn): - """Check validity of a connection namedtuple.""" - def check_ntuple(conn): - has_pid = len(conn) == 7 - self.assertIn(len(conn), (6, 7)) - self.assertEqual(conn[0], conn.fd) - self.assertEqual(conn[1], conn.family) - self.assertEqual(conn[2], conn.type) - self.assertEqual(conn[3], conn.laddr) - self.assertEqual(conn[4], conn.raddr) - self.assertEqual(conn[5], conn.status) - if has_pid: - self.assertEqual(conn[6], conn.pid) - - def check_family(conn): - self.assertIn(conn.family, (AF_INET, AF_INET6, AF_UNIX)) - if enum is not None: - assert isinstance(conn.family, enum.IntEnum), conn - else: - assert isinstance(conn.family, int), conn - if conn.family == AF_INET: - # actually try to bind the local socket; ignore IPv6 - # sockets as their address might be represented as - # an IPv4-mapped-address (e.g. "::127.0.0.1") - # and that's rejected by bind() - s = socket.socket(conn.family, conn.type) - with contextlib.closing(s): - try: - s.bind((conn.laddr[0], 0)) - except socket.error as err: - if err.errno != errno.EADDRNOTAVAIL: - raise - elif conn.family == AF_UNIX: - self.assertEqual(conn.status, psutil.CONN_NONE) - - def check_type(conn): - # SOCK_SEQPACKET may happen in case of AF_UNIX socks - self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET)) - if enum is not None: - assert isinstance(conn.type, enum.IntEnum), conn - else: - assert isinstance(conn.type, int), conn - if conn.type == SOCK_DGRAM: - self.assertEqual(conn.status, psutil.CONN_NONE) - - def check_addrs(conn): - # check IP address and port sanity - for addr in (conn.laddr, conn.raddr): - if conn.family in (AF_INET, AF_INET6): - self.assertIsInstance(addr, tuple) - if not addr: - continue - self.assertIsInstance(addr.port, int) - assert 0 <= addr.port <= 65535, addr.port - check_net_address(addr.ip, conn.family) - elif conn.family == AF_UNIX: - self.assertIsInstance(addr, str) - - def check_status(conn): - self.assertIsInstance(conn.status, str) - valids = [getattr(psutil, x) for x in dir(psutil) - if x.startswith('CONN_')] - self.assertIn(conn.status, valids) - if conn.family in (AF_INET, AF_INET6) and conn.type == SOCK_STREAM: - self.assertNotEqual(conn.status, psutil.CONN_NONE) - else: - self.assertEqual(conn.status, psutil.CONN_NONE) - - check_ntuple(conn) - check_family(conn) - check_type(conn) - check_addrs(conn) - check_status(conn) - - -class TestBase(Base, unittest.TestCase): - - @unittest.skipIf(SKIP_SYSCONS, "requires root") - def test_system(self): - with create_sockets(): - for conn in psutil.net_connections(kind='all'): - self.check_connection_ntuple(conn) - - def test_process(self): - with create_sockets(): - for conn in psutil.Process().connections(kind='all'): - self.check_connection_ntuple(conn) - - def test_invalid_kind(self): - self.assertRaises(ValueError, thisproc.connections, kind='???') - self.assertRaises(ValueError, psutil.net_connections, kind='???') - - -class TestUnconnectedSockets(Base, unittest.TestCase): - """Tests sockets which are open but not connected to anything.""" - - def get_conn_from_sock(self, sock): - cons = thisproc.connections(kind='all') - smap = dict([(c.fd, c) for c in cons]) - if NETBSD or FREEBSD: - # NetBSD opens a UNIX socket to /var/log/run - # so there may be more connections. - return smap[sock.fileno()] - else: - self.assertEqual(len(cons), 1) - if cons[0].fd != -1: - self.assertEqual(smap[sock.fileno()].fd, sock.fileno()) - return cons[0] - - def check_socket(self, sock): - """Given a socket, makes sure it matches the one obtained - via psutil. It assumes this process created one connection - only (the one supposed to be checked). - """ - conn = self.get_conn_from_sock(sock) - self.check_connection_ntuple(conn) - - # fd, family, type - if conn.fd != -1: - self.assertEqual(conn.fd, sock.fileno()) - self.assertEqual(conn.family, sock.family) - # see: http://bugs.python.org/issue30204 - self.assertEqual( - conn.type, sock.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)) - - # local address - laddr = sock.getsockname() - if not laddr and PY3 and isinstance(laddr, bytes): - # See: http://bugs.python.org/issue30205 - laddr = laddr.decode() - if sock.family == AF_INET6: - laddr = laddr[:2] - if sock.family == AF_UNIX and OPENBSD: - # No addresses are set for UNIX sockets on OpenBSD. - pass - else: - self.assertEqual(conn.laddr, laddr) - - # XXX Solaris can't retrieve system-wide UNIX sockets - if sock.family == AF_UNIX and HAS_CONNECTIONS_UNIX: - cons = thisproc.connections(kind='all') - self.compare_procsys_connections(os.getpid(), cons, kind='all') - return conn - - def test_tcp_v4(self): - addr = ("127.0.0.1", get_free_port()) - with closing(bind_socket(AF_INET, SOCK_STREAM, addr=addr)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_LISTEN) - - @unittest.skipIf(not supports_ipv6(), "IPv6 not supported") - def test_tcp_v6(self): - addr = ("::1", get_free_port()) - with closing(bind_socket(AF_INET6, SOCK_STREAM, addr=addr)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_LISTEN) - - def test_udp_v4(self): - addr = ("127.0.0.1", get_free_port()) - with closing(bind_socket(AF_INET, SOCK_DGRAM, addr=addr)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_NONE) - - @unittest.skipIf(not supports_ipv6(), "IPv6 not supported") - def test_udp_v6(self): - addr = ("::1", get_free_port()) - with closing(bind_socket(AF_INET6, SOCK_DGRAM, addr=addr)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_NONE) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_unix_tcp(self): - with unix_socket_path() as name: - with closing(bind_unix_socket(name, type=SOCK_STREAM)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_NONE) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_unix_udp(self): - with unix_socket_path() as name: - with closing(bind_unix_socket(name, type=SOCK_STREAM)) as sock: - conn = self.check_socket(sock) - assert not conn.raddr - self.assertEqual(conn.status, psutil.CONN_NONE) - - -class TestConnectedSocket(Base, unittest.TestCase): - """Test socket pairs which are are actually connected to - each other. - """ - - # On SunOS, even after we close() it, the server socket stays around - # in TIME_WAIT state. - @unittest.skipIf(SUNOS, "unreliable on SUONS") - def test_tcp(self): - addr = ("127.0.0.1", get_free_port()) - assert not thisproc.connections(kind='tcp4') - server, client = tcp_socketpair(AF_INET, addr=addr) - try: - cons = thisproc.connections(kind='tcp4') - self.assertEqual(len(cons), 2) - self.assertEqual(cons[0].status, psutil.CONN_ESTABLISHED) - self.assertEqual(cons[1].status, psutil.CONN_ESTABLISHED) - # May not be fast enough to change state so it stays - # commenteed. - # client.close() - # cons = thisproc.connections(kind='all') - # self.assertEqual(len(cons), 1) - # self.assertEqual(cons[0].status, psutil.CONN_CLOSE_WAIT) - finally: - server.close() - client.close() - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_unix(self): - with unix_socket_path() as name: - server, client = unix_socketpair(name) - try: - cons = thisproc.connections(kind='unix') - assert not (cons[0].laddr and cons[0].raddr) - assert not (cons[1].laddr and cons[1].raddr) - if NETBSD or FREEBSD: - # On NetBSD creating a UNIX socket will cause - # a UNIX connection to /var/run/log. - cons = [c for c in cons if c.raddr != '/var/run/log'] - if CIRRUS: - cons = [c for c in cons if c.fd in - (server.fileno(), client.fileno())] - self.assertEqual(len(cons), 2, msg=cons) - if LINUX or FREEBSD or SUNOS: - # remote path is never set - self.assertEqual(cons[0].raddr, "") - self.assertEqual(cons[1].raddr, "") - # one local address should though - self.assertEqual(name, cons[0].laddr or cons[1].laddr) - elif OPENBSD: - # No addresses whatsoever here. - for addr in (cons[0].laddr, cons[0].raddr, - cons[1].laddr, cons[1].raddr): - self.assertEqual(addr, "") - else: - # On other systems either the laddr or raddr - # of both peers are set. - self.assertEqual(cons[0].laddr or cons[1].laddr, name) - self.assertEqual(cons[0].raddr or cons[1].raddr, name) - finally: - server.close() - client.close() - - -class TestFilters(Base, unittest.TestCase): - - def test_filters(self): - def check(kind, families, types): - for conn in thisproc.connections(kind=kind): - self.assertIn(conn.family, families) - self.assertIn(conn.type, types) - if not SKIP_SYSCONS: - for conn in psutil.net_connections(kind=kind): - self.assertIn(conn.family, families) - self.assertIn(conn.type, types) - - with create_sockets(): - check('all', - [AF_INET, AF_INET6, AF_UNIX], - [SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET]) - check('inet', - [AF_INET, AF_INET6], - [SOCK_STREAM, SOCK_DGRAM]) - check('inet4', - [AF_INET], - [SOCK_STREAM, SOCK_DGRAM]) - check('tcp', - [AF_INET, AF_INET6], - [SOCK_STREAM]) - check('tcp4', - [AF_INET], - [SOCK_STREAM]) - check('tcp6', - [AF_INET6], - [SOCK_STREAM]) - check('udp', - [AF_INET, AF_INET6], - [SOCK_DGRAM]) - check('udp4', - [AF_INET], - [SOCK_DGRAM]) - check('udp6', - [AF_INET6], - [SOCK_DGRAM]) - if HAS_CONNECTIONS_UNIX: - check('unix', - [AF_UNIX], - [SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET]) - - @skip_on_access_denied(only_if=MACOS) - def test_combos(self): - def check_conn(proc, conn, family, type, laddr, raddr, status, kinds): - all_kinds = ("all", "inet", "inet4", "inet6", "tcp", "tcp4", - "tcp6", "udp", "udp4", "udp6") - self.check_connection_ntuple(conn) - self.assertEqual(conn.family, family) - self.assertEqual(conn.type, type) - self.assertEqual(conn.laddr, laddr) - self.assertEqual(conn.raddr, raddr) - self.assertEqual(conn.status, status) - for kind in all_kinds: - cons = proc.connections(kind=kind) - if kind in kinds: - assert cons - else: - assert not cons, cons - # compare against system-wide connections - # XXX Solaris can't retrieve system-wide UNIX - # sockets. - if HAS_CONNECTIONS_UNIX: - self.compare_procsys_connections(proc.pid, [conn]) - - tcp_template = textwrap.dedent(""" - import socket, time - s = socket.socket($family, socket.SOCK_STREAM) - s.bind(('$addr', 0)) - s.listen(5) - with open('$testfn', 'w') as f: - f.write(str(s.getsockname()[:2])) - time.sleep(60) - """) - - udp_template = textwrap.dedent(""" - import socket, time - s = socket.socket($family, socket.SOCK_DGRAM) - s.bind(('$addr', 0)) - with open('$testfn', 'w') as f: - f.write(str(s.getsockname()[:2])) - time.sleep(60) - """) - - from string import Template - testfile = os.path.basename(TESTFN) - tcp4_template = Template(tcp_template).substitute( - family=int(AF_INET), addr="127.0.0.1", testfn=testfile) - udp4_template = Template(udp_template).substitute( - family=int(AF_INET), addr="127.0.0.1", testfn=testfile) - tcp6_template = Template(tcp_template).substitute( - family=int(AF_INET6), addr="::1", testfn=testfile) - udp6_template = Template(udp_template).substitute( - family=int(AF_INET6), addr="::1", testfn=testfile) - - # launch various subprocess instantiating a socket of various - # families and types to enrich psutil results - tcp4_proc = pyrun(tcp4_template) - tcp4_addr = eval(wait_for_file(testfile)) - udp4_proc = pyrun(udp4_template) - udp4_addr = eval(wait_for_file(testfile)) - if supports_ipv6(): - tcp6_proc = pyrun(tcp6_template) - tcp6_addr = eval(wait_for_file(testfile)) - udp6_proc = pyrun(udp6_template) - udp6_addr = eval(wait_for_file(testfile)) - else: - tcp6_proc = None - udp6_proc = None - tcp6_addr = None - udp6_addr = None - - for p in thisproc.children(): - cons = p.connections() - self.assertEqual(len(cons), 1) - for conn in cons: - # TCP v4 - if p.pid == tcp4_proc.pid: - check_conn(p, conn, AF_INET, SOCK_STREAM, tcp4_addr, (), - psutil.CONN_LISTEN, - ("all", "inet", "inet4", "tcp", "tcp4")) - # UDP v4 - elif p.pid == udp4_proc.pid: - check_conn(p, conn, AF_INET, SOCK_DGRAM, udp4_addr, (), - psutil.CONN_NONE, - ("all", "inet", "inet4", "udp", "udp4")) - # TCP v6 - elif p.pid == getattr(tcp6_proc, "pid", None): - check_conn(p, conn, AF_INET6, SOCK_STREAM, tcp6_addr, (), - psutil.CONN_LISTEN, - ("all", "inet", "inet6", "tcp", "tcp6")) - # UDP v6 - elif p.pid == getattr(udp6_proc, "pid", None): - check_conn(p, conn, AF_INET6, SOCK_DGRAM, udp6_addr, (), - psutil.CONN_NONE, - ("all", "inet", "inet6", "udp", "udp6")) - - def test_count(self): - with create_sockets(): - # tcp - cons = thisproc.connections(kind='tcp') - self.assertEqual(len(cons), 2 if supports_ipv6() else 1) - for conn in cons: - self.assertIn(conn.family, (AF_INET, AF_INET6)) - self.assertEqual(conn.type, SOCK_STREAM) - # tcp4 - cons = thisproc.connections(kind='tcp4') - self.assertEqual(len(cons), 1) - self.assertEqual(cons[0].family, AF_INET) - self.assertEqual(cons[0].type, SOCK_STREAM) - # tcp6 - if supports_ipv6(): - cons = thisproc.connections(kind='tcp6') - self.assertEqual(len(cons), 1) - self.assertEqual(cons[0].family, AF_INET6) - self.assertEqual(cons[0].type, SOCK_STREAM) - # udp - cons = thisproc.connections(kind='udp') - self.assertEqual(len(cons), 2 if supports_ipv6() else 1) - for conn in cons: - self.assertIn(conn.family, (AF_INET, AF_INET6)) - self.assertEqual(conn.type, SOCK_DGRAM) - # udp4 - cons = thisproc.connections(kind='udp4') - self.assertEqual(len(cons), 1) - self.assertEqual(cons[0].family, AF_INET) - self.assertEqual(cons[0].type, SOCK_DGRAM) - # udp6 - if supports_ipv6(): - cons = thisproc.connections(kind='udp6') - self.assertEqual(len(cons), 1) - self.assertEqual(cons[0].family, AF_INET6) - self.assertEqual(cons[0].type, SOCK_DGRAM) - # inet - cons = thisproc.connections(kind='inet') - self.assertEqual(len(cons), 4 if supports_ipv6() else 2) - for conn in cons: - self.assertIn(conn.family, (AF_INET, AF_INET6)) - self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM)) - # inet6 - if supports_ipv6(): - cons = thisproc.connections(kind='inet6') - self.assertEqual(len(cons), 2) - for conn in cons: - self.assertEqual(conn.family, AF_INET6) - self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM)) - # Skipped on BSD becayse by default the Python process - # creates a UNIX socket to '/var/run/log'. - if HAS_CONNECTIONS_UNIX and not (FREEBSD or NETBSD): - cons = thisproc.connections(kind='unix') - self.assertEqual(len(cons), 3) - for conn in cons: - self.assertEqual(conn.family, AF_UNIX) - self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM)) - - -@unittest.skipIf(SKIP_SYSCONS, "requires root") -class TestSystemWideConnections(Base, unittest.TestCase): - """Tests for net_connections().""" - - def test_it(self): - def check(cons, families, types_): - for conn in cons: - self.assertIn(conn.family, families, msg=conn) - if conn.family != AF_UNIX: - self.assertIn(conn.type, types_, msg=conn) - self.check_connection_ntuple(conn) - - with create_sockets(): - from psutil._common import conn_tmap - for kind, groups in conn_tmap.items(): - # XXX: SunOS does not retrieve UNIX sockets. - if kind == 'unix' and not HAS_CONNECTIONS_UNIX: - continue - families, types_ = groups - cons = psutil.net_connections(kind) - self.assertEqual(len(cons), len(set(cons))) - check(cons, families, types_) - - # See: https://travis-ci.org/giampaolo/psutil/jobs/237566297 - @unittest.skipIf(MACOS and TRAVIS, "unreliable on MACOS + TRAVIS") - def test_multi_sockets_procs(self): - # Creates multiple sub processes, each creating different - # sockets. For each process check that proc.connections() - # and net_connections() return the same results. - # This is done mainly to check whether net_connections()'s - # pid is properly set, see: - # https://github.com/giampaolo/psutil/issues/1013 - with create_sockets() as socks: - expected = len(socks) - pids = [] - times = 10 - for i in range(times): - fname = os.path.realpath(TESTFN) + str(i) - src = textwrap.dedent("""\ - import time, os - from psutil.tests import create_sockets - with create_sockets(): - with open(r'%s', 'w') as f: - f.write(str(os.getpid())) - time.sleep(60) - """ % fname) - sproc = pyrun(src) - pids.append(sproc.pid) - self.addCleanup(safe_rmpath, fname) - - # sync - for i in range(times): - fname = TESTFN + str(i) - wait_for_file(fname) - - syscons = [x for x in psutil.net_connections(kind='all') if x.pid - in pids] - for pid in pids: - self.assertEqual(len([x for x in syscons if x.pid == pid]), - expected) - p = psutil.Process(pid) - self.assertEqual(len(p.connections('all')), expected) - - -class TestMisc(unittest.TestCase): - - def test_connection_constants(self): - ints = [] - strs = [] - for name in dir(psutil): - if name.startswith('CONN_'): - num = getattr(psutil, name) - str_ = str(num) - assert str_.isupper(), str_ - self.assertNotIn(str, strs) - self.assertNotIn(num, ints) - ints.append(num) - strs.append(str_) - if SUNOS: - psutil.CONN_IDLE - psutil.CONN_BOUND - if WINDOWS: - psutil.CONN_DELETE_TCB - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_contracts.py b/third_party/python/psutil/psutil/tests/test_contracts.py deleted file mode 100755 index 312f17d9a39d..000000000000 --- a/third_party/python/psutil/psutil/tests/test_contracts.py +++ /dev/null @@ -1,690 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Contracts tests. These tests mainly check API sanity in terms of -returned types and APIs availability. -Some of these are duplicates of tests test_system.py and test_process.py -""" - -import errno -import os -import stat -import time -import traceback - -from psutil import AIX -from psutil import BSD -from psutil import FREEBSD -from psutil import LINUX -from psutil import MACOS -from psutil import NETBSD -from psutil import OPENBSD -from psutil import OSX -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -from psutil._compat import long -from psutil.tests import create_sockets -from psutil.tests import enum -from psutil.tests import get_kernel_version -from psutil.tests import HAS_CPU_FREQ -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 -from psutil.tests import is_namedtuple -from psutil.tests import safe_rmpath -from psutil.tests import SKIP_SYSCONS -from psutil.tests import TESTFN -from psutil.tests import unittest -from psutil.tests import VALID_PROC_STATUSES -from psutil.tests import warn -import psutil - - -# =================================================================== -# --- APIs availability -# =================================================================== - -# Make sure code reflects what doc promises in terms of APIs -# availability. - -class TestAvailConstantsAPIs(unittest.TestCase): - - def test_PROCFS_PATH(self): - self.assertEqual(hasattr(psutil, "PROCFS_PATH"), - LINUX or SUNOS or AIX) - - def test_win_priority(self): - ae = self.assertEqual - ae(hasattr(psutil, "ABOVE_NORMAL_PRIORITY_CLASS"), WINDOWS) - ae(hasattr(psutil, "BELOW_NORMAL_PRIORITY_CLASS"), WINDOWS) - ae(hasattr(psutil, "HIGH_PRIORITY_CLASS"), WINDOWS) - ae(hasattr(psutil, "IDLE_PRIORITY_CLASS"), WINDOWS) - ae(hasattr(psutil, "NORMAL_PRIORITY_CLASS"), WINDOWS) - ae(hasattr(psutil, "REALTIME_PRIORITY_CLASS"), WINDOWS) - - def test_linux_ioprio_linux(self): - ae = self.assertEqual - ae(hasattr(psutil, "IOPRIO_CLASS_NONE"), LINUX) - ae(hasattr(psutil, "IOPRIO_CLASS_RT"), LINUX) - ae(hasattr(psutil, "IOPRIO_CLASS_BE"), LINUX) - ae(hasattr(psutil, "IOPRIO_CLASS_IDLE"), LINUX) - - def test_linux_ioprio_windows(self): - ae = self.assertEqual - ae(hasattr(psutil, "IOPRIO_HIGH"), WINDOWS) - ae(hasattr(psutil, "IOPRIO_NORMAL"), WINDOWS) - ae(hasattr(psutil, "IOPRIO_LOW"), WINDOWS) - ae(hasattr(psutil, "IOPRIO_VERYLOW"), WINDOWS) - - def test_linux_rlimit(self): - ae = self.assertEqual - hasit = LINUX and get_kernel_version() >= (2, 6, 36) - ae(hasattr(psutil.Process, "rlimit"), hasit) - ae(hasattr(psutil, "RLIM_INFINITY"), hasit) - ae(hasattr(psutil, "RLIMIT_AS"), hasit) - ae(hasattr(psutil, "RLIMIT_CORE"), hasit) - ae(hasattr(psutil, "RLIMIT_CPU"), hasit) - ae(hasattr(psutil, "RLIMIT_DATA"), hasit) - ae(hasattr(psutil, "RLIMIT_FSIZE"), hasit) - ae(hasattr(psutil, "RLIMIT_LOCKS"), hasit) - ae(hasattr(psutil, "RLIMIT_MEMLOCK"), hasit) - ae(hasattr(psutil, "RLIMIT_NOFILE"), hasit) - ae(hasattr(psutil, "RLIMIT_NPROC"), hasit) - ae(hasattr(psutil, "RLIMIT_RSS"), hasit) - ae(hasattr(psutil, "RLIMIT_STACK"), hasit) - - hasit = LINUX and get_kernel_version() >= (3, 0) - ae(hasattr(psutil, "RLIMIT_MSGQUEUE"), hasit) - ae(hasattr(psutil, "RLIMIT_NICE"), hasit) - ae(hasattr(psutil, "RLIMIT_RTPRIO"), hasit) - ae(hasattr(psutil, "RLIMIT_RTTIME"), hasit) - ae(hasattr(psutil, "RLIMIT_SIGPENDING"), hasit) - - -class TestAvailSystemAPIs(unittest.TestCase): - - def test_win_service_iter(self): - self.assertEqual(hasattr(psutil, "win_service_iter"), WINDOWS) - - def test_win_service_get(self): - self.assertEqual(hasattr(psutil, "win_service_get"), WINDOWS) - - def test_cpu_freq(self): - linux = (LINUX and - (os.path.exists("/sys/devices/system/cpu/cpufreq") or - os.path.exists("/sys/devices/system/cpu/cpu0/cpufreq"))) - self.assertEqual(hasattr(psutil, "cpu_freq"), - linux or MACOS or WINDOWS or FREEBSD) - - def test_sensors_temperatures(self): - self.assertEqual( - hasattr(psutil, "sensors_temperatures"), LINUX or FREEBSD) - - def test_sensors_fans(self): - self.assertEqual(hasattr(psutil, "sensors_fans"), LINUX) - - def test_battery(self): - self.assertEqual(hasattr(psutil, "sensors_battery"), - LINUX or WINDOWS or FREEBSD or MACOS) - - -class TestAvailProcessAPIs(unittest.TestCase): - - def test_environ(self): - self.assertEqual(hasattr(psutil.Process, "environ"), - LINUX or MACOS or WINDOWS or AIX or SUNOS) - - def test_uids(self): - self.assertEqual(hasattr(psutil.Process, "uids"), POSIX) - - def test_gids(self): - self.assertEqual(hasattr(psutil.Process, "uids"), POSIX) - - def test_terminal(self): - self.assertEqual(hasattr(psutil.Process, "terminal"), POSIX) - - def test_ionice(self): - self.assertEqual(hasattr(psutil.Process, "ionice"), LINUX or WINDOWS) - - def test_rlimit(self): - self.assertEqual(hasattr(psutil.Process, "rlimit"), LINUX) - - def test_io_counters(self): - hasit = hasattr(psutil.Process, "io_counters") - self.assertEqual(hasit, False if MACOS or SUNOS else True) - - def test_num_fds(self): - self.assertEqual(hasattr(psutil.Process, "num_fds"), POSIX) - - def test_num_handles(self): - self.assertEqual(hasattr(psutil.Process, "num_handles"), WINDOWS) - - def test_cpu_affinity(self): - self.assertEqual(hasattr(psutil.Process, "cpu_affinity"), - LINUX or WINDOWS or FREEBSD) - - def test_cpu_num(self): - self.assertEqual(hasattr(psutil.Process, "cpu_num"), - LINUX or FREEBSD or SUNOS) - - def test_memory_maps(self): - hasit = hasattr(psutil.Process, "memory_maps") - self.assertEqual( - hasit, False if OPENBSD or NETBSD or AIX or MACOS else True) - - -# =================================================================== -# --- System API types -# =================================================================== - - -class TestSystemAPITypes(unittest.TestCase): - """Check the return types of system related APIs. - Mainly we want to test we never return unicode on Python 2, see: - https://github.com/giampaolo/psutil/issues/1039 - """ - - @classmethod - def setUpClass(cls): - cls.proc = psutil.Process() - - def tearDown(self): - safe_rmpath(TESTFN) - - def assert_ntuple_of_nums(self, nt, type_=float, gezero=True): - assert is_namedtuple(nt) - for n in nt: - self.assertIsInstance(n, type_) - if gezero: - self.assertGreaterEqual(n, 0) - - def test_cpu_times(self): - self.assert_ntuple_of_nums(psutil.cpu_times()) - for nt in psutil.cpu_times(percpu=True): - self.assert_ntuple_of_nums(nt) - - def test_cpu_percent(self): - self.assertIsInstance(psutil.cpu_percent(interval=None), float) - self.assertIsInstance(psutil.cpu_percent(interval=0.00001), float) - - def test_cpu_times_percent(self): - self.assert_ntuple_of_nums(psutil.cpu_times_percent(interval=None)) - self.assert_ntuple_of_nums(psutil.cpu_times_percent(interval=0.0001)) - - def test_cpu_count(self): - self.assertIsInstance(psutil.cpu_count(), int) - - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_cpu_freq(self): - if psutil.cpu_freq() is None: - raise self.skipTest("cpu_freq() returns None") - self.assert_ntuple_of_nums(psutil.cpu_freq(), type_=(float, int, long)) - - def test_disk_io_counters(self): - # Duplicate of test_system.py. Keep it anyway. - for k, v in psutil.disk_io_counters(perdisk=True).items(): - self.assertIsInstance(k, str) - self.assert_ntuple_of_nums(v, type_=(int, long)) - - def test_disk_partitions(self): - # Duplicate of test_system.py. Keep it anyway. - for disk in psutil.disk_partitions(): - self.assertIsInstance(disk.device, str) - self.assertIsInstance(disk.mountpoint, str) - self.assertIsInstance(disk.fstype, str) - self.assertIsInstance(disk.opts, str) - - @unittest.skipIf(SKIP_SYSCONS, "requires root") - def test_net_connections(self): - with create_sockets(): - ret = psutil.net_connections('all') - self.assertEqual(len(ret), len(set(ret))) - for conn in ret: - assert is_namedtuple(conn) - - def test_net_if_addrs(self): - # Duplicate of test_system.py. Keep it anyway. - for ifname, addrs in psutil.net_if_addrs().items(): - self.assertIsInstance(ifname, str) - for addr in addrs: - if enum is not None: - assert isinstance(addr.family, enum.IntEnum), addr - else: - assert isinstance(addr.family, int), addr - self.assertIsInstance(addr.address, str) - self.assertIsInstance(addr.netmask, (str, type(None))) - self.assertIsInstance(addr.broadcast, (str, type(None))) - - def test_net_if_stats(self): - # Duplicate of test_system.py. Keep it anyway. - for ifname, info in psutil.net_if_stats().items(): - self.assertIsInstance(ifname, str) - self.assertIsInstance(info.isup, bool) - if enum is not None: - self.assertIsInstance(info.duplex, enum.IntEnum) - else: - self.assertIsInstance(info.duplex, int) - self.assertIsInstance(info.speed, int) - self.assertIsInstance(info.mtu, int) - - @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(): - self.assertIsInstance(ifname, str) - - @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") - def test_sensors_fans(self): - # Duplicate of test_system.py. Keep it anyway. - for name, units in psutil.sensors_fans().items(): - self.assertIsInstance(name, str) - for unit in units: - self.assertIsInstance(unit.label, str) - self.assertIsInstance(unit.current, (float, int, type(None))) - - @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") - def test_sensors_temperatures(self): - # Duplicate of test_system.py. Keep it anyway. - for name, units in psutil.sensors_temperatures().items(): - self.assertIsInstance(name, str) - for unit in units: - self.assertIsInstance(unit.label, str) - self.assertIsInstance(unit.current, (float, int, type(None))) - self.assertIsInstance(unit.high, (float, int, type(None))) - self.assertIsInstance(unit.critical, (float, int, type(None))) - - def test_boot_time(self): - # Duplicate of test_system.py. Keep it anyway. - self.assertIsInstance(psutil.boot_time(), float) - - def test_users(self): - # Duplicate of test_system.py. Keep it anyway. - for user in psutil.users(): - self.assertIsInstance(user.name, str) - self.assertIsInstance(user.terminal, (str, type(None))) - self.assertIsInstance(user.host, (str, type(None))) - self.assertIsInstance(user.pid, (int, type(None))) - - -# =================================================================== -# --- Featch all processes test -# =================================================================== - - -class TestFetchAllProcesses(unittest.TestCase): - """Test which iterates over all running processes and performs - some sanity checks against Process API's returned values. - """ - - def get_attr_names(self): - excluded_names = set([ - 'send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait', - 'as_dict', 'parent', 'parents', 'children', 'memory_info_ex', - 'oneshot', - ]) - if LINUX and not HAS_RLIMIT: - excluded_names.add('rlimit') - attrs = [] - for name in dir(psutil.Process): - if name.startswith("_"): - continue - if name in excluded_names: - continue - attrs.append(name) - return attrs - - def iter_procs(self): - attrs = self.get_attr_names() - for p in psutil.process_iter(): - with p.oneshot(): - for name in attrs: - yield (p, name) - - def call_meth(self, p, name): - args = () - kwargs = {} - attr = getattr(p, name, None) - if attr is not None and callable(attr): - if name == 'rlimit': - args = (psutil.RLIMIT_NOFILE,) - elif name == 'memory_maps': - kwargs = {'grouped': False} - return attr(*args, **kwargs) - else: - return attr - - def test_fetch_all(self): - valid_procs = 0 - default = object() - failures = [] - for p, name in self.iter_procs(): - ret = default - try: - ret = self.call_meth(p, name) - except NotImplementedError: - msg = "%r was skipped because not implemented" % ( - self.__class__.__name__ + '.test_' + name) - warn(msg) - except (psutil.NoSuchProcess, psutil.AccessDenied) as err: - self.assertEqual(err.pid, p.pid) - if err.name: - # make sure exception's name attr is set - # with the actual process name - self.assertEqual(err.name, p.name()) - assert str(err) - assert err.msg - except Exception: - s = '\n' + '=' * 70 + '\n' - s += "FAIL: test_%s (proc=%s" % (name, p) - if ret != default: - s += ", ret=%s)" % repr(ret) - s += ')\n' - s += '-' * 70 - s += "\n%s" % traceback.format_exc() - s = "\n".join((" " * 4) + i for i in s.splitlines()) - s += '\n' - failures.append(s) - break - else: - valid_procs += 1 - if ret not in (0, 0.0, [], None, '', {}): - assert ret, ret - meth = getattr(self, name) - meth(ret, p) - - if failures: - self.fail(''.join(failures)) - - # we should always have a non-empty list, not including PID 0 etc. - # special cases. - assert valid_procs - - def cmdline(self, ret, proc): - self.assertIsInstance(ret, list) - for part in ret: - self.assertIsInstance(part, str) - - def exe(self, ret, proc): - self.assertIsInstance(ret, (str, type(None))) - if not ret: - self.assertEqual(ret, '') - else: - if WINDOWS and not ret.endswith('.exe'): - return # May be "Registry", "MemCompression", ... - assert os.path.isabs(ret), ret - # Note: os.stat() may return False even if the file is there - # hence we skip the test, see: - # http://stackoverflow.com/questions/3112546/os-path-exists-lies - if POSIX and os.path.isfile(ret): - if hasattr(os, 'access') and hasattr(os, "X_OK"): - # XXX may fail on MACOS - assert os.access(ret, os.X_OK) - - def pid(self, ret, proc): - self.assertIsInstance(ret, int) - self.assertGreaterEqual(ret, 0) - - def ppid(self, ret, proc): - self.assertIsInstance(ret, (int, long)) - self.assertGreaterEqual(ret, 0) - - def name(self, ret, proc): - self.assertIsInstance(ret, str) - # on AIX, "" processes don't have names - if not AIX: - assert ret - - def create_time(self, ret, proc): - self.assertIsInstance(ret, float) - try: - self.assertGreaterEqual(ret, 0) - except AssertionError: - # XXX - if OPENBSD and proc.status() == psutil.STATUS_ZOMBIE: - pass - else: - raise - # this can't be taken for granted on all platforms - # self.assertGreaterEqual(ret, psutil.boot_time()) - # make sure returned value can be pretty printed - # with strftime - time.strftime("%Y %m %d %H:%M:%S", time.localtime(ret)) - - def uids(self, ret, proc): - assert is_namedtuple(ret) - for uid in ret: - self.assertIsInstance(uid, int) - self.assertGreaterEqual(uid, 0) - - def gids(self, ret, proc): - assert is_namedtuple(ret) - # note: testing all gids as above seems not to be reliable for - # gid == 30 (nodoby); not sure why. - for gid in ret: - self.assertIsInstance(gid, int) - if not MACOS and not NETBSD: - self.assertGreaterEqual(gid, 0) - - def username(self, ret, proc): - self.assertIsInstance(ret, str) - assert ret - - def status(self, ret, proc): - self.assertIsInstance(ret, str) - assert ret - self.assertNotEqual(ret, '?') # XXX - self.assertIn(ret, VALID_PROC_STATUSES) - - def io_counters(self, ret, proc): - assert is_namedtuple(ret) - for field in ret: - self.assertIsInstance(field, (int, long)) - if field != -1: - self.assertGreaterEqual(field, 0) - - def ionice(self, ret, proc): - if LINUX: - self.assertIsInstance(ret.ioclass, int) - self.assertIsInstance(ret.value, int) - self.assertGreaterEqual(ret.ioclass, 0) - self.assertGreaterEqual(ret.value, 0) - else: # Windows, Cygwin - choices = [ - psutil.IOPRIO_VERYLOW, - psutil.IOPRIO_LOW, - psutil.IOPRIO_NORMAL, - psutil.IOPRIO_HIGH] - self.assertIsInstance(ret, int) - self.assertGreaterEqual(ret, 0) - self.assertIn(ret, choices) - - def num_threads(self, ret, proc): - self.assertIsInstance(ret, int) - self.assertGreaterEqual(ret, 1) - - def threads(self, ret, proc): - self.assertIsInstance(ret, list) - for t in ret: - assert is_namedtuple(t) - self.assertGreaterEqual(t.id, 0) - self.assertGreaterEqual(t.user_time, 0) - self.assertGreaterEqual(t.system_time, 0) - for field in t: - self.assertIsInstance(field, (int, float)) - - def cpu_times(self, ret, proc): - assert is_namedtuple(ret) - for n in ret: - self.assertIsInstance(n, float) - self.assertGreaterEqual(n, 0) - # TODO: check ntuple fields - - def cpu_percent(self, ret, proc): - self.assertIsInstance(ret, float) - assert 0.0 <= ret <= 100.0, ret - - def cpu_num(self, ret, proc): - self.assertIsInstance(ret, int) - if FREEBSD and ret == -1: - return - self.assertGreaterEqual(ret, 0) - if psutil.cpu_count() == 1: - self.assertEqual(ret, 0) - self.assertIn(ret, list(range(psutil.cpu_count()))) - - def memory_info(self, ret, proc): - assert is_namedtuple(ret) - for value in ret: - self.assertIsInstance(value, (int, long)) - self.assertGreaterEqual(value, 0) - if WINDOWS: - self.assertGreaterEqual(ret.peak_wset, ret.wset) - self.assertGreaterEqual(ret.peak_paged_pool, ret.paged_pool) - self.assertGreaterEqual(ret.peak_nonpaged_pool, ret.nonpaged_pool) - self.assertGreaterEqual(ret.peak_pagefile, ret.pagefile) - - def memory_full_info(self, ret, proc): - assert is_namedtuple(ret) - total = psutil.virtual_memory().total - for name in ret._fields: - value = getattr(ret, name) - self.assertIsInstance(value, (int, long)) - self.assertGreaterEqual(value, 0, msg=(name, value)) - if LINUX or OSX and name in ('vms', 'data'): - # On Linux there are processes (e.g. 'goa-daemon') whose - # VMS is incredibly high for some reason. - continue - self.assertLessEqual(value, total, msg=(name, value, total)) - - if LINUX: - self.assertGreaterEqual(ret.pss, ret.uss) - - def open_files(self, ret, proc): - self.assertIsInstance(ret, list) - for f in ret: - self.assertIsInstance(f.fd, int) - self.assertIsInstance(f.path, str) - if WINDOWS: - self.assertEqual(f.fd, -1) - elif LINUX: - self.assertIsInstance(f.position, int) - self.assertIsInstance(f.mode, str) - self.assertIsInstance(f.flags, int) - self.assertGreaterEqual(f.position, 0) - self.assertIn(f.mode, ('r', 'w', 'a', 'r+', 'a+')) - self.assertGreater(f.flags, 0) - elif BSD and not f.path: - # XXX see: https://github.com/giampaolo/psutil/issues/595 - continue - assert os.path.isabs(f.path), f - assert os.path.isfile(f.path), f - - def num_fds(self, ret, proc): - self.assertIsInstance(ret, int) - self.assertGreaterEqual(ret, 0) - - def connections(self, ret, proc): - with create_sockets(): - self.assertEqual(len(ret), len(set(ret))) - for conn in ret: - assert is_namedtuple(conn) - - def cwd(self, ret, proc): - if ret: # 'ret' can be None or empty - self.assertIsInstance(ret, str) - assert os.path.isabs(ret), ret - try: - st = os.stat(ret) - except OSError as err: - if WINDOWS and err.errno in \ - psutil._psplatform.ACCESS_DENIED_SET: - pass - # directory has been removed in mean time - elif err.errno != errno.ENOENT: - raise - else: - assert stat.S_ISDIR(st.st_mode) - - def memory_percent(self, ret, proc): - self.assertIsInstance(ret, float) - assert 0 <= ret <= 100, ret - - def is_running(self, ret, proc): - self.assertIsInstance(ret, bool) - - def cpu_affinity(self, ret, proc): - self.assertIsInstance(ret, list) - assert ret != [], ret - cpus = range(psutil.cpu_count()) - for n in ret: - self.assertIsInstance(n, int) - self.assertIn(n, cpus) - - def terminal(self, ret, proc): - self.assertIsInstance(ret, (str, type(None))) - if ret is not None: - assert os.path.isabs(ret), ret - assert os.path.exists(ret), ret - - def memory_maps(self, ret, proc): - for nt in ret: - self.assertIsInstance(nt.addr, str) - self.assertIsInstance(nt.perms, str) - self.assertIsInstance(nt.path, str) - for fname in nt._fields: - value = getattr(nt, fname) - if fname == 'path': - if not value.startswith('['): - assert os.path.isabs(nt.path), nt.path - # commented as on Linux we might get - # '/foo/bar (deleted)' - # assert os.path.exists(nt.path), nt.path - elif fname == 'addr': - assert value, repr(value) - elif fname == 'perms': - if not WINDOWS: - assert value, repr(value) - else: - self.assertIsInstance(value, (int, long)) - self.assertGreaterEqual(value, 0) - - def num_handles(self, ret, proc): - self.assertIsInstance(ret, int) - self.assertGreaterEqual(ret, 0) - - def nice(self, ret, proc): - self.assertIsInstance(ret, int) - if POSIX: - assert -20 <= ret <= 20, ret - else: - priorities = [getattr(psutil, x) for x in dir(psutil) - if x.endswith('_PRIORITY_CLASS')] - self.assertIn(ret, priorities) - - def num_ctx_switches(self, ret, proc): - assert is_namedtuple(ret) - for value in ret: - self.assertIsInstance(value, (int, long)) - self.assertGreaterEqual(value, 0) - - def rlimit(self, ret, proc): - self.assertIsInstance(ret, tuple) - self.assertEqual(len(ret), 2) - self.assertGreaterEqual(ret[0], -1) - self.assertGreaterEqual(ret[1], -1) - - def environ(self, ret, proc): - self.assertIsInstance(ret, dict) - for k, v in ret.items(): - self.assertIsInstance(k, str) - self.assertIsInstance(v, str) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_linux.py b/third_party/python/psutil/psutil/tests/test_linux.py deleted file mode 100755 index e51f8bd573ba..000000000000 --- a/third_party/python/psutil/psutil/tests/test_linux.py +++ /dev/null @@ -1,2118 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Linux specific tests.""" - -from __future__ import division -import collections -import contextlib -import errno -import glob -import io -import os -import re -import shutil -import socket -import struct -import tempfile -import textwrap -import time -import warnings - -import psutil -from psutil import LINUX -from psutil._compat import basestring -from psutil._compat import FileNotFoundError -from psutil._compat import PY3 -from psutil._compat import u -from psutil.tests import call_until -from psutil.tests import HAS_BATTERY -from psutil.tests import HAS_CPU_FREQ -from psutil.tests import HAS_GETLOADAVG -from psutil.tests import HAS_RLIMIT -from psutil.tests import MEMORY_TOLERANCE -from psutil.tests import mock -from psutil.tests import PYPY -from psutil.tests import pyrun -from psutil.tests import reap_children -from psutil.tests import reload_module -from psutil.tests import retry_on_failure -from psutil.tests import safe_rmpath -from psutil.tests import sh -from psutil.tests import skip_on_not_implemented -from psutil.tests import TESTFN -from psutil.tests import ThreadTask -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import which - - -HERE = os.path.abspath(os.path.dirname(__file__)) -SIOCGIFADDR = 0x8915 -SIOCGIFCONF = 0x8912 -SIOCGIFHWADDR = 0x8927 -if LINUX: - SECTOR_SIZE = 512 -EMPTY_TEMPERATURES = not glob.glob('/sys/class/hwmon/hwmon*') - -# ===================================================================== -# --- utils -# ===================================================================== - - -def get_ipv4_address(ifname): - import fcntl - ifname = ifname[:15] - if PY3: - ifname = bytes(ifname, 'ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - with contextlib.closing(s): - return socket.inet_ntoa( - fcntl.ioctl(s.fileno(), - SIOCGIFADDR, - struct.pack('256s', ifname))[20:24]) - - -def get_mac_address(ifname): - import fcntl - ifname = ifname[:15] - if PY3: - ifname = bytes(ifname, 'ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - with contextlib.closing(s): - info = fcntl.ioctl( - s.fileno(), SIOCGIFHWADDR, struct.pack('256s', ifname)) - if PY3: - def ord(x): - return x - else: - import __builtin__ - ord = __builtin__.ord - return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1] - - -def free_swap(): - """Parse 'free' cmd and return swap memory's s total, used and free - values. - """ - out = sh('free -b', env={"LANG": "C.UTF-8"}) - lines = out.split('\n') - for line in lines: - if line.startswith('Swap'): - _, total, used, free = line.split() - nt = collections.namedtuple('free', 'total used free') - return nt(int(total), int(used), int(free)) - raise ValueError( - "can't find 'Swap' in 'free' output:\n%s" % '\n'.join(lines)) - - -def free_physmem(): - """Parse 'free' cmd and return physical memory's total, used - and free values. - """ - # Note: free can have 2 different formats, invalidating 'shared' - # and 'cached' memory which may have different positions so we - # do not return them. - # https://github.com/giampaolo/psutil/issues/538#issuecomment-57059946 - out = sh('free -b', env={"LANG": "C.UTF-8"}) - lines = out.split('\n') - for line in lines: - if line.startswith('Mem'): - total, used, free, shared = \ - [int(x) for x in line.split()[1:5]] - nt = collections.namedtuple( - 'free', 'total used free shared output') - return nt(total, used, free, shared, out) - raise ValueError( - "can't find 'Mem' in 'free' output:\n%s" % '\n'.join(lines)) - - -def vmstat(stat): - out = sh("vmstat -s", env={"LANG": "C.UTF-8"}) - for line in out.split("\n"): - line = line.strip() - if stat in line: - return int(line.split(' ')[0]) - raise ValueError("can't find %r in 'vmstat' output" % stat) - - -def get_free_version_info(): - out = sh("free -V").strip() - return tuple(map(int, out.split()[-1].split('.'))) - - -@contextlib.contextmanager -def mock_open_content(for_path, content): - """Mock open() builtin and forces it to return a certain `content` - on read() if the path being opened matches `for_path`. - """ - def open_mock(name, *args, **kwargs): - if name == for_path: - if PY3: - if isinstance(content, basestring): - return io.StringIO(content) - else: - return io.BytesIO(content) - else: - return io.BytesIO(content) - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, create=True, side_effect=open_mock) as m: - yield m - - -@contextlib.contextmanager -def mock_open_exception(for_path, exc): - """Mock open() builtin and raises `exc` if the path being opened - matches `for_path`. - """ - def open_mock(name, *args, **kwargs): - if name == for_path: - raise exc - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, create=True, side_effect=open_mock) as m: - yield m - - -# ===================================================================== -# --- system virtual memory -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemVirtualMemory(unittest.TestCase): - - def test_total(self): - # free_value = free_physmem().total - # psutil_value = psutil.virtual_memory().total - # self.assertEqual(free_value, psutil_value) - vmstat_value = vmstat('total memory') * 1024 - psutil_value = psutil.virtual_memory().total - self.assertAlmostEqual(vmstat_value, psutil_value) - - # Older versions of procps used slab memory to calculate used memory. - # This got changed in: - # https://gitlab.com/procps-ng/procps/commit/ - # 05d751c4f076a2f0118b914c5e51cfbb4762ad8e - @unittest.skipIf(LINUX and get_free_version_info() < (3, 3, 12), - "old free version") - @retry_on_failure() - def test_used(self): - free = free_physmem() - free_value = free.used - psutil_value = psutil.virtual_memory().used - self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE, - msg='%s %s \n%s' % (free_value, psutil_value, free.output)) - - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - @retry_on_failure() - def test_free(self): - vmstat_value = vmstat('free memory') * 1024 - psutil_value = psutil.virtual_memory().free - self.assertAlmostEqual( - vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_buffers(self): - vmstat_value = vmstat('buffer memory') * 1024 - psutil_value = psutil.virtual_memory().buffers - self.assertAlmostEqual( - vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) - - # https://travis-ci.org/giampaolo/psutil/jobs/226719664 - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - @retry_on_failure() - def test_active(self): - vmstat_value = vmstat('active memory') * 1024 - psutil_value = psutil.virtual_memory().active - self.assertAlmostEqual( - vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) - - # https://travis-ci.org/giampaolo/psutil/jobs/227242952 - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - @retry_on_failure() - def test_inactive(self): - vmstat_value = vmstat('inactive memory') * 1024 - psutil_value = psutil.virtual_memory().inactive - self.assertAlmostEqual( - vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_shared(self): - free = free_physmem() - free_value = free.shared - if free_value == 0: - raise unittest.SkipTest("free does not support 'shared' column") - psutil_value = psutil.virtual_memory().shared - self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE, - msg='%s %s \n%s' % (free_value, psutil_value, free.output)) - - @retry_on_failure() - def test_available(self): - # "free" output format has changed at some point: - # https://github.com/giampaolo/psutil/issues/538#issuecomment-147192098 - out = sh("free -b") - lines = out.split('\n') - if 'available' not in lines[0]: - raise unittest.SkipTest("free does not support 'available' column") - else: - free_value = int(lines[1].split()[-1]) - psutil_value = psutil.virtual_memory().available - self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE, - msg='%s %s \n%s' % (free_value, psutil_value, out)) - - def test_warnings_on_misses(self): - # Emulate a case where /proc/meminfo provides few info. - # psutil is supposed to set the missing fields to 0 and - # raise a warning. - with mock_open_content( - '/proc/meminfo', - textwrap.dedent("""\ - Active(anon): 6145416 kB - Active(file): 2950064 kB - Inactive(anon): 574764 kB - Inactive(file): 1567648 kB - MemAvailable: -1 kB - MemFree: 2057400 kB - MemTotal: 16325648 kB - SReclaimable: 346648 kB - """).encode()) as m: - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter("always") - ret = psutil.virtual_memory() - assert m.called - self.assertEqual(len(ws), 1) - w = ws[0] - assert w.filename.endswith('psutil/_pslinux.py') - self.assertIn( - "memory stats couldn't be determined", str(w.message)) - self.assertIn("cached", str(w.message)) - self.assertIn("shared", str(w.message)) - self.assertIn("active", str(w.message)) - self.assertIn("inactive", str(w.message)) - self.assertIn("buffers", str(w.message)) - self.assertIn("available", str(w.message)) - self.assertEqual(ret.cached, 0) - self.assertEqual(ret.active, 0) - self.assertEqual(ret.inactive, 0) - self.assertEqual(ret.shared, 0) - self.assertEqual(ret.buffers, 0) - self.assertEqual(ret.available, 0) - self.assertEqual(ret.slab, 0) - - @retry_on_failure() - def test_avail_old_percent(self): - # Make sure that our calculation of avail mem for old kernels - # is off by max 15%. - from psutil._pslinux import calculate_avail_vmem - from psutil._pslinux import open_binary - - mems = {} - with open_binary('/proc/meminfo') as f: - for line in f: - fields = line.split() - mems[fields[0]] = int(fields[1]) * 1024 - - a = calculate_avail_vmem(mems) - if b'MemAvailable:' in mems: - b = mems[b'MemAvailable:'] - diff_percent = abs(a - b) / a * 100 - self.assertLess(diff_percent, 15) - - def test_avail_old_comes_from_kernel(self): - # Make sure "MemAvailable:" coluimn is used instead of relying - # on our internal algorithm to calculate avail mem. - with mock_open_content( - '/proc/meminfo', - textwrap.dedent("""\ - Active: 9444728 kB - Active(anon): 6145416 kB - Active(file): 2950064 kB - Buffers: 287952 kB - Cached: 4818144 kB - Inactive(file): 1578132 kB - Inactive(anon): 574764 kB - Inactive(file): 1567648 kB - MemAvailable: 6574984 kB - MemFree: 2057400 kB - MemTotal: 16325648 kB - Shmem: 577588 kB - SReclaimable: 346648 kB - """).encode()) as m: - with warnings.catch_warnings(record=True) as ws: - ret = psutil.virtual_memory() - assert m.called - self.assertEqual(ret.available, 6574984 * 1024) - w = ws[0] - self.assertIn( - "inactive memory stats couldn't be determined", str(w.message)) - - def test_avail_old_missing_fields(self): - # Remove Active(file), Inactive(file) and SReclaimable - # from /proc/meminfo and make sure the fallback is used - # (free + cached), - with mock_open_content( - "/proc/meminfo", - textwrap.dedent("""\ - Active: 9444728 kB - Active(anon): 6145416 kB - Buffers: 287952 kB - Cached: 4818144 kB - Inactive(file): 1578132 kB - Inactive(anon): 574764 kB - MemFree: 2057400 kB - MemTotal: 16325648 kB - Shmem: 577588 kB - """).encode()) as m: - with warnings.catch_warnings(record=True) as ws: - ret = psutil.virtual_memory() - assert m.called - self.assertEqual(ret.available, 2057400 * 1024 + 4818144 * 1024) - w = ws[0] - self.assertIn( - "inactive memory stats couldn't be determined", str(w.message)) - - def test_avail_old_missing_zoneinfo(self): - # Remove /proc/zoneinfo file. Make sure fallback is used - # (free + cached). - with mock_open_content( - "/proc/meminfo", - textwrap.dedent("""\ - Active: 9444728 kB - Active(anon): 6145416 kB - Active(file): 2950064 kB - Buffers: 287952 kB - Cached: 4818144 kB - Inactive(file): 1578132 kB - Inactive(anon): 574764 kB - Inactive(file): 1567648 kB - MemFree: 2057400 kB - MemTotal: 16325648 kB - Shmem: 577588 kB - SReclaimable: 346648 kB - """).encode()): - with mock_open_exception( - "/proc/zoneinfo", - IOError(errno.ENOENT, 'no such file or directory')): - with warnings.catch_warnings(record=True) as ws: - ret = psutil.virtual_memory() - self.assertEqual( - ret.available, 2057400 * 1024 + 4818144 * 1024) - w = ws[0] - self.assertIn( - "inactive memory stats couldn't be determined", - str(w.message)) - - def test_virtual_memory_mocked(self): - # Emulate /proc/meminfo because neither vmstat nor free return slab. - def open_mock(name, *args, **kwargs): - if name == '/proc/meminfo': - return io.BytesIO(textwrap.dedent("""\ - MemTotal: 100 kB - MemFree: 2 kB - MemAvailable: 3 kB - Buffers: 4 kB - Cached: 5 kB - SwapCached: 6 kB - Active: 7 kB - Inactive: 8 kB - Active(anon): 9 kB - Inactive(anon): 10 kB - Active(file): 11 kB - Inactive(file): 12 kB - Unevictable: 13 kB - Mlocked: 14 kB - SwapTotal: 15 kB - SwapFree: 16 kB - Dirty: 17 kB - Writeback: 18 kB - AnonPages: 19 kB - Mapped: 20 kB - Shmem: 21 kB - Slab: 22 kB - SReclaimable: 23 kB - SUnreclaim: 24 kB - KernelStack: 25 kB - PageTables: 26 kB - NFS_Unstable: 27 kB - Bounce: 28 kB - WritebackTmp: 29 kB - CommitLimit: 30 kB - Committed_AS: 31 kB - VmallocTotal: 32 kB - VmallocUsed: 33 kB - VmallocChunk: 34 kB - HardwareCorrupted: 35 kB - AnonHugePages: 36 kB - ShmemHugePages: 37 kB - ShmemPmdMapped: 38 kB - CmaTotal: 39 kB - CmaFree: 40 kB - HugePages_Total: 41 kB - HugePages_Free: 42 kB - HugePages_Rsvd: 43 kB - HugePages_Surp: 44 kB - Hugepagesize: 45 kB - DirectMap46k: 46 kB - DirectMap47M: 47 kB - DirectMap48G: 48 kB - """).encode()) - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, create=True, side_effect=open_mock) as m: - mem = psutil.virtual_memory() - assert m.called - self.assertEqual(mem.total, 100 * 1024) - self.assertEqual(mem.free, 2 * 1024) - self.assertEqual(mem.buffers, 4 * 1024) - # cached mem also includes reclaimable memory - self.assertEqual(mem.cached, (5 + 23) * 1024) - self.assertEqual(mem.shared, 21 * 1024) - self.assertEqual(mem.active, 7 * 1024) - self.assertEqual(mem.inactive, 8 * 1024) - self.assertEqual(mem.slab, 22 * 1024) - self.assertEqual(mem.available, 3 * 1024) - - -# ===================================================================== -# --- system swap memory -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemSwapMemory(unittest.TestCase): - - @staticmethod - def meminfo_has_swap_info(): - """Return True if /proc/meminfo provides swap metrics.""" - with open("/proc/meminfo") as f: - data = f.read() - return 'SwapTotal:' in data and 'SwapFree:' in data - - def test_total(self): - free_value = free_swap().total - psutil_value = psutil.swap_memory().total - return self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_used(self): - free_value = free_swap().used - psutil_value = psutil.swap_memory().used - return self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_free(self): - free_value = free_swap().free - psutil_value = psutil.swap_memory().free - return self.assertAlmostEqual( - free_value, psutil_value, delta=MEMORY_TOLERANCE) - - def test_missing_sin_sout(self): - with mock.patch('psutil._common.open', create=True) as m: - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter("always") - ret = psutil.swap_memory() - assert m.called - self.assertEqual(len(ws), 1) - w = ws[0] - assert w.filename.endswith('psutil/_pslinux.py') - self.assertIn( - "'sin' and 'sout' swap memory stats couldn't " - "be determined", str(w.message)) - self.assertEqual(ret.sin, 0) - self.assertEqual(ret.sout, 0) - - def test_no_vmstat_mocked(self): - # see https://github.com/giampaolo/psutil/issues/722 - with mock_open_exception( - "/proc/vmstat", - IOError(errno.ENOENT, 'no such file or directory')) as m: - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter("always") - ret = psutil.swap_memory() - assert m.called - self.assertEqual(len(ws), 1) - w = ws[0] - assert w.filename.endswith('psutil/_pslinux.py') - self.assertIn( - "'sin' and 'sout' swap memory stats couldn't " - "be determined and were set to 0", - str(w.message)) - self.assertEqual(ret.sin, 0) - self.assertEqual(ret.sout, 0) - - def test_meminfo_against_sysinfo(self): - # Make sure the content of /proc/meminfo about swap memory - # matches sysinfo() syscall, see: - # https://github.com/giampaolo/psutil/issues/1015 - if not self.meminfo_has_swap_info(): - return unittest.skip("/proc/meminfo has no swap metrics") - with mock.patch('psutil._pslinux.cext.linux_sysinfo') as m: - swap = psutil.swap_memory() - assert not m.called - import psutil._psutil_linux as cext - _, _, _, _, total, free, unit_multiplier = cext.linux_sysinfo() - total *= unit_multiplier - free *= unit_multiplier - self.assertEqual(swap.total, total) - self.assertAlmostEqual(swap.free, free, delta=MEMORY_TOLERANCE) - - def test_emulate_meminfo_has_no_metrics(self): - # Emulate a case where /proc/meminfo provides no swap metrics - # in which case sysinfo() syscall is supposed to be used - # as a fallback. - with mock_open_content("/proc/meminfo", b"") as m: - psutil.swap_memory() - assert m.called - - -# ===================================================================== -# --- system CPU -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemCPUTimes(unittest.TestCase): - - @unittest.skipIf(TRAVIS, "unknown failure on travis") - def test_fields(self): - fields = psutil.cpu_times()._fields - kernel_ver = re.findall(r'\d+\.\d+\.\d+', os.uname()[2])[0] - kernel_ver_info = tuple(map(int, kernel_ver.split('.'))) - if kernel_ver_info >= (2, 6, 11): - self.assertIn('steal', fields) - else: - self.assertNotIn('steal', fields) - if kernel_ver_info >= (2, 6, 24): - self.assertIn('guest', fields) - else: - self.assertNotIn('guest', fields) - if kernel_ver_info >= (3, 2, 0): - self.assertIn('guest_nice', fields) - else: - self.assertNotIn('guest_nice', fields) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemCPUCountLogical(unittest.TestCase): - - @unittest.skipIf(not os.path.exists("/sys/devices/system/cpu/online"), - "/sys/devices/system/cpu/online does not exist") - def test_against_sysdev_cpu_online(self): - with open("/sys/devices/system/cpu/online") as f: - value = f.read().strip() - if "-" in str(value): - value = int(value.split('-')[1]) + 1 - self.assertEqual(psutil.cpu_count(), value) - - @unittest.skipIf(not os.path.exists("/sys/devices/system/cpu"), - "/sys/devices/system/cpu does not exist") - def test_against_sysdev_cpu_num(self): - ls = os.listdir("/sys/devices/system/cpu") - count = len([x for x in ls if re.search(r"cpu\d+$", x) is not None]) - self.assertEqual(psutil.cpu_count(), count) - - @unittest.skipIf(not which("nproc"), "nproc utility not available") - def test_against_nproc(self): - num = int(sh("nproc --all")) - self.assertEqual(psutil.cpu_count(logical=True), num) - - @unittest.skipIf(not which("lscpu"), "lscpu utility not available") - def test_against_lscpu(self): - out = sh("lscpu -p") - num = len([x for x in out.split('\n') if not x.startswith('#')]) - self.assertEqual(psutil.cpu_count(logical=True), num) - - def test_emulate_fallbacks(self): - import psutil._pslinux - original = psutil._pslinux.cpu_count_logical() - # Here we want to mock os.sysconf("SC_NPROCESSORS_ONLN") in - # order to cause the parsing of /proc/cpuinfo and /proc/stat. - with mock.patch( - 'psutil._pslinux.os.sysconf', side_effect=ValueError) as m: - self.assertEqual(psutil._pslinux.cpu_count_logical(), original) - assert m.called - - # Let's have open() return emtpy data and make sure None is - # returned ('cause we mimick os.cpu_count()). - with mock.patch('psutil._common.open', create=True) as m: - self.assertIsNone(psutil._pslinux.cpu_count_logical()) - self.assertEqual(m.call_count, 2) - # /proc/stat should be the last one - self.assertEqual(m.call_args[0][0], '/proc/stat') - - # Let's push this a bit further and make sure /proc/cpuinfo - # parsing works as expected. - with open('/proc/cpuinfo', 'rb') as f: - cpuinfo_data = f.read() - fake_file = io.BytesIO(cpuinfo_data) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(psutil._pslinux.cpu_count_logical(), original) - - # Finally, let's make /proc/cpuinfo return meaningless data; - # this way we'll fall back on relying on /proc/stat - with mock_open_content('/proc/cpuinfo', b"") as m: - self.assertEqual(psutil._pslinux.cpu_count_logical(), original) - m.called - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemCPUCountPhysical(unittest.TestCase): - - @unittest.skipIf(not which("lscpu"), "lscpu utility not available") - def test_against_lscpu(self): - out = sh("lscpu -p") - core_ids = set() - for line in out.split('\n'): - if not line.startswith('#'): - fields = line.split(',') - core_ids.add(fields[1]) - self.assertEqual(psutil.cpu_count(logical=False), len(core_ids)) - - def test_emulate_none(self): - with mock.patch('glob.glob', return_value=[]) as m1: - with mock.patch('psutil._common.open', create=True) as m2: - self.assertIsNone(psutil._pslinux.cpu_count_physical()) - assert m1.called - assert m2.called - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemCPUFrequency(unittest.TestCase): - - @unittest.skipIf(TRAVIS, "fails on Travis") - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_emulate_use_second_file(self): - # https://github.com/giampaolo/psutil/issues/981 - def path_exists_mock(path): - if path.startswith("/sys/devices/system/cpu/cpufreq/policy"): - return False - else: - return orig_exists(path) - - orig_exists = os.path.exists - with mock.patch("os.path.exists", side_effect=path_exists_mock, - create=True): - assert psutil.cpu_freq() - - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_emulate_use_cpuinfo(self): - # Emulate a case where /sys/devices/system/cpu/cpufreq* does not - # exist and /proc/cpuinfo is used instead. - def path_exists_mock(path): - if path.startswith('/sys/devices/system/cpu/'): - return False - else: - if path == "/proc/cpuinfo": - flags.append(None) - return os_path_exists(path) - - flags = [] - os_path_exists = os.path.exists - try: - with mock.patch("os.path.exists", side_effect=path_exists_mock): - reload_module(psutil._pslinux) - ret = psutil.cpu_freq() - assert ret - assert flags - self.assertEqual(ret.max, 0.0) - self.assertEqual(ret.min, 0.0) - for freq in psutil.cpu_freq(percpu=True): - self.assertEqual(ret.max, 0.0) - self.assertEqual(ret.min, 0.0) - finally: - reload_module(psutil._pslinux) - reload_module(psutil) - - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_emulate_data(self): - def open_mock(name, *args, **kwargs): - if (name.endswith('/scaling_cur_freq') and - name.startswith("/sys/devices/system/cpu/cpufreq/policy")): - return io.BytesIO(b"500000") - elif (name.endswith('/scaling_min_freq') and - name.startswith("/sys/devices/system/cpu/cpufreq/policy")): - return io.BytesIO(b"600000") - elif (name.endswith('/scaling_max_freq') and - name.startswith("/sys/devices/system/cpu/cpufreq/policy")): - return io.BytesIO(b"700000") - elif name == '/proc/cpuinfo': - return io.BytesIO(b"cpu MHz : 500") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - with mock.patch( - 'os.path.exists', return_value=True): - freq = psutil.cpu_freq() - self.assertEqual(freq.current, 500.0) - # when /proc/cpuinfo is used min and max frequencies are not - # available and are set to 0. - if freq.min != 0.0: - self.assertEqual(freq.min, 600.0) - if freq.max != 0.0: - self.assertEqual(freq.max, 700.0) - - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_emulate_multi_cpu(self): - def open_mock(name, *args, **kwargs): - n = name - if (n.endswith('/scaling_cur_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy0")): - return io.BytesIO(b"100000") - elif (n.endswith('/scaling_min_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy0")): - return io.BytesIO(b"200000") - elif (n.endswith('/scaling_max_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy0")): - return io.BytesIO(b"300000") - elif (n.endswith('/scaling_cur_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy1")): - return io.BytesIO(b"400000") - elif (n.endswith('/scaling_min_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy1")): - return io.BytesIO(b"500000") - elif (n.endswith('/scaling_max_freq') and - n.startswith("/sys/devices/system/cpu/cpufreq/policy1")): - return io.BytesIO(b"600000") - elif name == '/proc/cpuinfo': - return io.BytesIO(b"cpu MHz : 100\n" - b"cpu MHz : 400") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - with mock.patch('os.path.exists', return_value=True): - with mock.patch('psutil._pslinux.cpu_count_logical', - return_value=2): - freq = psutil.cpu_freq(percpu=True) - self.assertEqual(freq[0].current, 100.0) - if freq[0].min != 0.0: - self.assertEqual(freq[0].min, 200.0) - if freq[0].max != 0.0: - self.assertEqual(freq[0].max, 300.0) - self.assertEqual(freq[1].current, 400.0) - if freq[1].min != 0.0: - self.assertEqual(freq[1].min, 500.0) - if freq[1].max != 0.0: - self.assertEqual(freq[1].max, 600.0) - - @unittest.skipIf(TRAVIS, "fails on Travis") - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_emulate_no_scaling_cur_freq_file(self): - # See: https://github.com/giampaolo/psutil/issues/1071 - def open_mock(name, *args, **kwargs): - if name.endswith('/scaling_cur_freq'): - raise IOError(errno.ENOENT, "") - elif name.endswith('/cpuinfo_cur_freq'): - return io.BytesIO(b"200000") - elif name == '/proc/cpuinfo': - return io.BytesIO(b"cpu MHz : 200") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - with mock.patch('os.path.exists', return_value=True): - with mock.patch('psutil._pslinux.cpu_count_logical', - return_value=1): - freq = psutil.cpu_freq() - self.assertEqual(freq.current, 200) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemCPUStats(unittest.TestCase): - - @unittest.skipIf(TRAVIS, "fails on Travis") - def test_ctx_switches(self): - vmstat_value = vmstat("context switches") - psutil_value = psutil.cpu_stats().ctx_switches - self.assertAlmostEqual(vmstat_value, psutil_value, delta=500) - - @unittest.skipIf(TRAVIS, "fails on Travis") - def test_interrupts(self): - vmstat_value = vmstat("interrupts") - psutil_value = psutil.cpu_stats().interrupts - self.assertAlmostEqual(vmstat_value, psutil_value, delta=500) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestLoadAvg(unittest.TestCase): - - @unittest.skipIf(not HAS_GETLOADAVG, "not supported") - def test_getloadavg(self): - psutil_value = psutil.getloadavg() - with open("/proc/loadavg", "r") as f: - proc_value = f.read().split() - - self.assertAlmostEqual(float(proc_value[0]), psutil_value[0], delta=1) - self.assertAlmostEqual(float(proc_value[1]), psutil_value[1], delta=1) - self.assertAlmostEqual(float(proc_value[2]), psutil_value[2], delta=1) - - -# ===================================================================== -# --- system network -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemNetIfAddrs(unittest.TestCase): - - def test_ips(self): - for name, addrs in psutil.net_if_addrs().items(): - for addr in addrs: - if addr.family == psutil.AF_LINK: - self.assertEqual(addr.address, get_mac_address(name)) - elif addr.family == socket.AF_INET: - self.assertEqual(addr.address, get_ipv4_address(name)) - # TODO: test for AF_INET6 family - - # XXX - not reliable when having virtual NICs installed by Docker. - # @unittest.skipIf(not which('ip'), "'ip' utility not available") - # @unittest.skipIf(TRAVIS, "skipped on Travis") - # def test_net_if_names(self): - # out = sh("ip addr").strip() - # nics = [x for x in psutil.net_if_addrs().keys() if ':' not in x] - # found = 0 - # for line in out.split('\n'): - # line = line.strip() - # if re.search(r"^\d+:", line): - # found += 1 - # name = line.split(':')[1].strip() - # self.assertIn(name, nics) - # self.assertEqual(len(nics), found, msg="%s\n---\n%s" % ( - # pprint.pformat(nics), out)) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemNetIfStats(unittest.TestCase): - - def test_against_ifconfig(self): - for name, stats in psutil.net_if_stats().items(): - try: - out = sh("ifconfig %s" % name) - except RuntimeError: - pass - else: - # Not always reliable. - # self.assertEqual(stats.isup, 'RUNNING' in out, msg=out) - self.assertEqual(stats.mtu, - int(re.findall(r'(?i)MTU[: ](\d+)', out)[0])) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemNetIOCounters(unittest.TestCase): - - @retry_on_failure() - def test_against_ifconfig(self): - def ifconfig(nic): - ret = {} - out = sh("ifconfig %s" % name) - ret['packets_recv'] = int( - re.findall(r'RX packets[: ](\d+)', out)[0]) - ret['packets_sent'] = int( - re.findall(r'TX packets[: ](\d+)', out)[0]) - ret['errin'] = int(re.findall(r'errors[: ](\d+)', out)[0]) - ret['errout'] = int(re.findall(r'errors[: ](\d+)', out)[1]) - ret['dropin'] = int(re.findall(r'dropped[: ](\d+)', out)[0]) - ret['dropout'] = int(re.findall(r'dropped[: ](\d+)', out)[1]) - ret['bytes_recv'] = int( - re.findall(r'RX (?:packets \d+ +)?bytes[: ](\d+)', out)[0]) - ret['bytes_sent'] = int( - re.findall(r'TX (?:packets \d+ +)?bytes[: ](\d+)', out)[0]) - return ret - - nio = psutil.net_io_counters(pernic=True, nowrap=False) - for name, stats in nio.items(): - try: - ifconfig_ret = ifconfig(name) - except RuntimeError: - continue - self.assertAlmostEqual( - stats.bytes_recv, ifconfig_ret['bytes_recv'], delta=1024 * 5) - self.assertAlmostEqual( - stats.bytes_sent, ifconfig_ret['bytes_sent'], delta=1024 * 5) - self.assertAlmostEqual( - stats.packets_recv, ifconfig_ret['packets_recv'], delta=1024) - self.assertAlmostEqual( - stats.packets_sent, ifconfig_ret['packets_sent'], delta=1024) - self.assertAlmostEqual( - stats.errin, ifconfig_ret['errin'], delta=10) - self.assertAlmostEqual( - stats.errout, ifconfig_ret['errout'], delta=10) - self.assertAlmostEqual( - stats.dropin, ifconfig_ret['dropin'], delta=10) - self.assertAlmostEqual( - stats.dropout, ifconfig_ret['dropout'], delta=10) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemNetConnections(unittest.TestCase): - - @mock.patch('psutil._pslinux.socket.inet_ntop', side_effect=ValueError) - @mock.patch('psutil._pslinux.supports_ipv6', return_value=False) - def test_emulate_ipv6_unsupported(self, supports_ipv6, inet_ntop): - # see: https://github.com/giampaolo/psutil/issues/623 - try: - s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - self.addCleanup(s.close) - s.bind(("::1", 0)) - except socket.error: - pass - psutil.net_connections(kind='inet6') - - def test_emulate_unix(self): - with mock_open_content( - '/proc/net/unix', - textwrap.dedent("""\ - 0: 00000003 000 000 0001 03 462170 @/tmp/dbus-Qw2hMPIU3n - 0: 00000003 000 000 0001 03 35010 @/tmp/dbus-tB2X8h69BQ - 0: 00000003 000 000 0001 03 34424 @/tmp/dbus-cHy80Y8O - 000000000000000000000000000000000000000000000000000000 - """)) as m: - psutil.net_connections(kind='unix') - assert m.called - - -# ===================================================================== -# --- system disks -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemDiskPartitions(unittest.TestCase): - - @unittest.skipIf(not hasattr(os, 'statvfs'), "os.statvfs() not available") - @skip_on_not_implemented() - def test_against_df(self): - # test psutil.disk_usage() and psutil.disk_partitions() - # against "df -a" - def df(path): - out = sh('df -P -B 1 "%s"' % path).strip() - lines = out.split('\n') - lines.pop(0) - line = lines.pop(0) - dev, total, used, free = line.split()[:4] - if dev == 'none': - dev = '' - total, used, free = int(total), int(used), int(free) - return dev, total, used, free - - for part in psutil.disk_partitions(all=False): - usage = psutil.disk_usage(part.mountpoint) - dev, total, used, free = df(part.mountpoint) - self.assertEqual(usage.total, total) - # 10 MB tollerance - if abs(usage.free - free) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.free, free)) - if abs(usage.used - used) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.used, used)) - - def test_zfs_fs(self): - # Test that ZFS partitions are returned. - with open("/proc/filesystems", "r") as f: - data = f.read() - if 'zfs' in data: - for part in psutil.disk_partitions(): - if part.fstype == 'zfs': - break - else: - self.fail("couldn't find any ZFS partition") - else: - # No ZFS partitions on this system. Let's fake one. - fake_file = io.StringIO(u("nodev\tzfs\n")) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m1: - with mock.patch( - 'psutil._pslinux.cext.disk_partitions', - return_value=[('/dev/sdb3', '/', 'zfs', 'rw')]) as m2: - ret = psutil.disk_partitions() - assert m1.called - assert m2.called - assert ret - self.assertEqual(ret[0].fstype, 'zfs') - - def test_emulate_realpath_fail(self): - # See: https://github.com/giampaolo/psutil/issues/1307 - try: - with mock.patch('os.path.realpath', - return_value='/non/existent') as m: - with self.assertRaises(FileNotFoundError): - psutil.disk_partitions() - assert m.called - finally: - psutil.PROCFS_PATH = "/proc" - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSystemDiskIoCounters(unittest.TestCase): - - def test_emulate_kernel_2_4(self): - # Tests /proc/diskstats parsing format for 2.4 kernels, see: - # https://github.com/giampaolo/psutil/issues/767 - with mock_open_content( - '/proc/diskstats', - " 3 0 1 hda 2 3 4 5 6 7 8 9 10 11 12"): - with mock.patch('psutil._pslinux.is_storage_device', - return_value=True): - ret = psutil.disk_io_counters(nowrap=False) - self.assertEqual(ret.read_count, 1) - self.assertEqual(ret.read_merged_count, 2) - self.assertEqual(ret.read_bytes, 3 * SECTOR_SIZE) - self.assertEqual(ret.read_time, 4) - self.assertEqual(ret.write_count, 5) - self.assertEqual(ret.write_merged_count, 6) - self.assertEqual(ret.write_bytes, 7 * SECTOR_SIZE) - self.assertEqual(ret.write_time, 8) - self.assertEqual(ret.busy_time, 10) - - def test_emulate_kernel_2_6_full(self): - # Tests /proc/diskstats parsing format for 2.6 kernels, - # lines reporting all metrics: - # https://github.com/giampaolo/psutil/issues/767 - with mock_open_content( - '/proc/diskstats', - " 3 0 hda 1 2 3 4 5 6 7 8 9 10 11"): - with mock.patch('psutil._pslinux.is_storage_device', - return_value=True): - ret = psutil.disk_io_counters(nowrap=False) - self.assertEqual(ret.read_count, 1) - self.assertEqual(ret.read_merged_count, 2) - self.assertEqual(ret.read_bytes, 3 * SECTOR_SIZE) - self.assertEqual(ret.read_time, 4) - self.assertEqual(ret.write_count, 5) - self.assertEqual(ret.write_merged_count, 6) - self.assertEqual(ret.write_bytes, 7 * SECTOR_SIZE) - self.assertEqual(ret.write_time, 8) - self.assertEqual(ret.busy_time, 10) - - def test_emulate_kernel_2_6_limited(self): - # Tests /proc/diskstats parsing format for 2.6 kernels, - # where one line of /proc/partitions return a limited - # amount of metrics when it bumps into a partition - # (instead of a disk). See: - # https://github.com/giampaolo/psutil/issues/767 - with mock_open_content( - '/proc/diskstats', - " 3 1 hda 1 2 3 4"): - with mock.patch('psutil._pslinux.is_storage_device', - return_value=True): - ret = psutil.disk_io_counters(nowrap=False) - self.assertEqual(ret.read_count, 1) - self.assertEqual(ret.read_bytes, 2 * SECTOR_SIZE) - self.assertEqual(ret.write_count, 3) - self.assertEqual(ret.write_bytes, 4 * SECTOR_SIZE) - - self.assertEqual(ret.read_merged_count, 0) - self.assertEqual(ret.read_time, 0) - self.assertEqual(ret.write_merged_count, 0) - self.assertEqual(ret.write_time, 0) - self.assertEqual(ret.busy_time, 0) - - def test_emulate_include_partitions(self): - # Make sure that when perdisk=True disk partitions are returned, - # see: - # https://github.com/giampaolo/psutil/pull/1313#issuecomment-408626842 - with mock_open_content( - '/proc/diskstats', - textwrap.dedent("""\ - 3 0 nvme0n1 1 2 3 4 5 6 7 8 9 10 11 - 3 0 nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11 - """)): - with mock.patch('psutil._pslinux.is_storage_device', - return_value=False): - ret = psutil.disk_io_counters(perdisk=True, nowrap=False) - self.assertEqual(len(ret), 2) - self.assertEqual(ret['nvme0n1'].read_count, 1) - self.assertEqual(ret['nvme0n1p1'].read_count, 1) - self.assertEqual(ret['nvme0n1'].write_count, 5) - self.assertEqual(ret['nvme0n1p1'].write_count, 5) - - def test_emulate_exclude_partitions(self): - # Make sure that when perdisk=False partitions (e.g. 'sda1', - # 'nvme0n1p1') are skipped and not included in the total count. - # https://github.com/giampaolo/psutil/pull/1313#issuecomment-408626842 - with mock_open_content( - '/proc/diskstats', - textwrap.dedent("""\ - 3 0 nvme0n1 1 2 3 4 5 6 7 8 9 10 11 - 3 0 nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11 - """)): - with mock.patch('psutil._pslinux.is_storage_device', - return_value=False): - ret = psutil.disk_io_counters(perdisk=False, nowrap=False) - self.assertIsNone(ret) - - # - def is_storage_device(name): - return name == 'nvme0n1' - - with mock_open_content( - '/proc/diskstats', - textwrap.dedent("""\ - 3 0 nvme0n1 1 2 3 4 5 6 7 8 9 10 11 - 3 0 nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11 - """)): - with mock.patch('psutil._pslinux.is_storage_device', - create=True, side_effect=is_storage_device): - ret = psutil.disk_io_counters(perdisk=False, nowrap=False) - self.assertEqual(ret.read_count, 1) - self.assertEqual(ret.write_count, 5) - - def test_emulate_use_sysfs(self): - def exists(path): - if path == '/proc/diskstats': - return False - return True - - wprocfs = psutil.disk_io_counters(perdisk=True) - with mock.patch('psutil._pslinux.os.path.exists', - create=True, side_effect=exists): - wsysfs = psutil.disk_io_counters(perdisk=True) - self.assertEqual(len(wprocfs), len(wsysfs)) - - def test_emulate_not_impl(self): - def exists(path): - return False - - with mock.patch('psutil._pslinux.os.path.exists', - create=True, side_effect=exists): - self.assertRaises(NotImplementedError, psutil.disk_io_counters) - - -# ===================================================================== -# --- misc -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestMisc(unittest.TestCase): - - def test_boot_time(self): - vmstat_value = vmstat('boot time') - psutil_value = psutil.boot_time() - self.assertEqual(int(vmstat_value), int(psutil_value)) - - def test_no_procfs_on_import(self): - my_procfs = tempfile.mkdtemp() - - with open(os.path.join(my_procfs, 'stat'), 'w') as f: - f.write('cpu 0 0 0 0 0 0 0 0 0 0\n') - f.write('cpu0 0 0 0 0 0 0 0 0 0 0\n') - f.write('cpu1 0 0 0 0 0 0 0 0 0 0\n') - - try: - orig_open = open - - def open_mock(name, *args, **kwargs): - if name.startswith('/proc'): - raise IOError(errno.ENOENT, 'rejecting access for test') - return orig_open(name, *args, **kwargs) - - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - reload_module(psutil) - - self.assertRaises(IOError, psutil.cpu_times) - self.assertRaises(IOError, psutil.cpu_times, percpu=True) - self.assertRaises(IOError, psutil.cpu_percent) - self.assertRaises(IOError, psutil.cpu_percent, percpu=True) - self.assertRaises(IOError, psutil.cpu_times_percent) - self.assertRaises( - IOError, psutil.cpu_times_percent, percpu=True) - - psutil.PROCFS_PATH = my_procfs - - self.assertEqual(psutil.cpu_percent(), 0) - self.assertEqual(sum(psutil.cpu_times_percent()), 0) - - # since we don't know the number of CPUs at import time, - # we awkwardly say there are none until the second call - per_cpu_percent = psutil.cpu_percent(percpu=True) - self.assertEqual(sum(per_cpu_percent), 0) - - # ditto awkward length - per_cpu_times_percent = psutil.cpu_times_percent(percpu=True) - self.assertEqual(sum(map(sum, per_cpu_times_percent)), 0) - - # much user, very busy - with open(os.path.join(my_procfs, 'stat'), 'w') as f: - f.write('cpu 1 0 0 0 0 0 0 0 0 0\n') - f.write('cpu0 1 0 0 0 0 0 0 0 0 0\n') - f.write('cpu1 1 0 0 0 0 0 0 0 0 0\n') - - self.assertNotEqual(psutil.cpu_percent(), 0) - self.assertNotEqual( - sum(psutil.cpu_percent(percpu=True)), 0) - self.assertNotEqual(sum(psutil.cpu_times_percent()), 0) - self.assertNotEqual( - sum(map(sum, psutil.cpu_times_percent(percpu=True))), 0) - finally: - shutil.rmtree(my_procfs) - reload_module(psutil) - - self.assertEqual(psutil.PROCFS_PATH, '/proc') - - def test_cpu_steal_decrease(self): - # Test cumulative cpu stats decrease. We should ignore this. - # See issue #1210. - with mock_open_content( - "/proc/stat", - textwrap.dedent("""\ - cpu 0 0 0 0 0 0 0 1 0 0 - cpu0 0 0 0 0 0 0 0 1 0 0 - cpu1 0 0 0 0 0 0 0 1 0 0 - """).encode()) as m: - # first call to "percent" functions should read the new stat file - # and compare to the "real" file read at import time - so the - # values are meaningless - psutil.cpu_percent() - assert m.called - psutil.cpu_percent(percpu=True) - psutil.cpu_times_percent() - psutil.cpu_times_percent(percpu=True) - - with mock_open_content( - "/proc/stat", - textwrap.dedent("""\ - cpu 1 0 0 0 0 0 0 0 0 0 - cpu0 1 0 0 0 0 0 0 0 0 0 - cpu1 1 0 0 0 0 0 0 0 0 0 - """).encode()) as m: - # Increase "user" while steal goes "backwards" to zero. - cpu_percent = psutil.cpu_percent() - assert m.called - cpu_percent_percpu = psutil.cpu_percent(percpu=True) - cpu_times_percent = psutil.cpu_times_percent() - cpu_times_percent_percpu = psutil.cpu_times_percent(percpu=True) - self.assertNotEqual(cpu_percent, 0) - self.assertNotEqual(sum(cpu_percent_percpu), 0) - self.assertNotEqual(sum(cpu_times_percent), 0) - self.assertNotEqual(sum(cpu_times_percent), 100.0) - self.assertNotEqual(sum(map(sum, cpu_times_percent_percpu)), 0) - self.assertNotEqual(sum(map(sum, cpu_times_percent_percpu)), 100.0) - self.assertEqual(cpu_times_percent.steal, 0) - self.assertNotEqual(cpu_times_percent.user, 0) - - def test_boot_time_mocked(self): - with mock.patch('psutil._common.open', create=True) as m: - self.assertRaises( - RuntimeError, - psutil._pslinux.boot_time) - assert m.called - - def test_users_mocked(self): - # Make sure ':0' and ':0.0' (returned by C ext) are converted - # to 'localhost'. - with mock.patch('psutil._pslinux.cext.users', - return_value=[('giampaolo', 'pts/2', ':0', - 1436573184.0, True, 2)]) as m: - self.assertEqual(psutil.users()[0].host, 'localhost') - assert m.called - with mock.patch('psutil._pslinux.cext.users', - return_value=[('giampaolo', 'pts/2', ':0.0', - 1436573184.0, True, 2)]) as m: - self.assertEqual(psutil.users()[0].host, 'localhost') - assert m.called - # ...otherwise it should be returned as-is - with mock.patch('psutil._pslinux.cext.users', - return_value=[('giampaolo', 'pts/2', 'foo', - 1436573184.0, True, 2)]) as m: - self.assertEqual(psutil.users()[0].host, 'foo') - assert m.called - - def test_procfs_path(self): - tdir = tempfile.mkdtemp() - try: - psutil.PROCFS_PATH = tdir - self.assertRaises(IOError, psutil.virtual_memory) - self.assertRaises(IOError, psutil.cpu_times) - self.assertRaises(IOError, psutil.cpu_times, percpu=True) - self.assertRaises(IOError, psutil.boot_time) - # self.assertRaises(IOError, psutil.pids) - self.assertRaises(IOError, psutil.net_connections) - self.assertRaises(IOError, psutil.net_io_counters) - self.assertRaises(IOError, psutil.net_if_stats) - # self.assertRaises(IOError, psutil.disk_io_counters) - self.assertRaises(IOError, psutil.disk_partitions) - self.assertRaises(psutil.NoSuchProcess, psutil.Process) - finally: - psutil.PROCFS_PATH = "/proc" - os.rmdir(tdir) - - def test_issue_687(self): - # In case of thread ID: - # - pid_exists() is supposed to return False - # - Process(tid) is supposed to work - # - pids() should not return the TID - # See: https://github.com/giampaolo/psutil/issues/687 - t = ThreadTask() - t.start() - try: - p = psutil.Process() - tid = p.threads()[1].id - assert not psutil.pid_exists(tid), tid - pt = psutil.Process(tid) - pt.as_dict() - self.assertNotIn(tid, psutil.pids()) - finally: - t.stop() - - def test_pid_exists_no_proc_status(self): - # Internally pid_exists relies on /proc/{pid}/status. - # Emulate a case where this file is empty in which case - # psutil is supposed to fall back on using pids(). - with mock_open_content("/proc/%s/status", "") as m: - assert psutil.pid_exists(os.getpid()) - assert m.called - - -# ===================================================================== -# --- sensors -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -@unittest.skipIf(not HAS_BATTERY, "no battery") -class TestSensorsBattery(unittest.TestCase): - - @unittest.skipIf(not which("acpi"), "acpi utility not available") - def test_percent(self): - out = sh("acpi -b") - acpi_value = int(out.split(",")[1].strip().replace('%', '')) - psutil_value = psutil.sensors_battery().percent - self.assertAlmostEqual(acpi_value, psutil_value, delta=1) - - @unittest.skipIf(not which("acpi"), "acpi utility not available") - def test_power_plugged(self): - out = sh("acpi -b") - if 'unknown' in out.lower(): - return unittest.skip("acpi output not reliable") - if 'discharging at zero rate' in out: - plugged = True - else: - plugged = "Charging" in out.split('\n')[0] - self.assertEqual(psutil.sensors_battery().power_plugged, plugged) - - def test_emulate_power_plugged(self): - # Pretend the AC power cable is connected. - def open_mock(name, *args, **kwargs): - if name.endswith("AC0/online") or name.endswith("AC/online"): - return io.BytesIO(b"1") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - self.assertEqual(psutil.sensors_battery().power_plugged, True) - self.assertEqual( - psutil.sensors_battery().secsleft, psutil.POWER_TIME_UNLIMITED) - assert m.called - - def test_emulate_power_plugged_2(self): - # Same as above but pretend /AC0/online does not exist in which - # case code relies on /status file. - def open_mock(name, *args, **kwargs): - if name.endswith("AC0/online") or name.endswith("AC/online"): - raise IOError(errno.ENOENT, "") - elif name.endswith("/status"): - return io.StringIO(u("charging")) - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - self.assertEqual(psutil.sensors_battery().power_plugged, True) - assert m.called - - def test_emulate_power_not_plugged(self): - # Pretend the AC power cable is not connected. - def open_mock(name, *args, **kwargs): - if name.endswith("AC0/online") or name.endswith("AC/online"): - return io.BytesIO(b"0") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - self.assertEqual(psutil.sensors_battery().power_plugged, False) - assert m.called - - def test_emulate_power_not_plugged_2(self): - # Same as above but pretend /AC0/online does not exist in which - # case code relies on /status file. - def open_mock(name, *args, **kwargs): - if name.endswith("AC0/online") or name.endswith("AC/online"): - raise IOError(errno.ENOENT, "") - elif name.endswith("/status"): - return io.StringIO(u("discharging")) - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - self.assertEqual(psutil.sensors_battery().power_plugged, False) - assert m.called - - def test_emulate_power_undetermined(self): - # Pretend we can't know whether the AC power cable not - # connected (assert fallback to False). - def open_mock(name, *args, **kwargs): - if name.startswith("/sys/class/power_supply/AC0/online") or \ - name.startswith("/sys/class/power_supply/AC/online"): - raise IOError(errno.ENOENT, "") - elif name.startswith("/sys/class/power_supply/BAT0/status"): - return io.BytesIO(b"???") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - self.assertIsNone(psutil.sensors_battery().power_plugged) - assert m.called - - def test_emulate_no_base_files(self): - # Emulate a case where base metrics files are not present, - # in which case we're supposed to get None. - with mock_open_exception( - "/sys/class/power_supply/BAT0/energy_now", - IOError(errno.ENOENT, "")): - with mock_open_exception( - "/sys/class/power_supply/BAT0/charge_now", - IOError(errno.ENOENT, "")): - self.assertIsNone(psutil.sensors_battery()) - - def test_emulate_energy_full_0(self): - # Emulate a case where energy_full files returns 0. - with mock_open_content( - "/sys/class/power_supply/BAT0/energy_full", b"0") as m: - self.assertEqual(psutil.sensors_battery().percent, 0) - assert m.called - - def test_emulate_energy_full_not_avail(self): - # Emulate a case where energy_full file does not exist. - # Expected fallback on /capacity. - with mock_open_exception( - "/sys/class/power_supply/BAT0/energy_full", - IOError(errno.ENOENT, "")): - with mock_open_exception( - "/sys/class/power_supply/BAT0/charge_full", - IOError(errno.ENOENT, "")): - with mock_open_content( - "/sys/class/power_supply/BAT0/capacity", b"88"): - self.assertEqual(psutil.sensors_battery().percent, 88) - - def test_emulate_no_power(self): - # Emulate a case where /AC0/online file nor /BAT0/status exist. - with mock_open_exception( - "/sys/class/power_supply/AC/online", - IOError(errno.ENOENT, "")): - with mock_open_exception( - "/sys/class/power_supply/AC0/online", - IOError(errno.ENOENT, "")): - with mock_open_exception( - "/sys/class/power_supply/BAT0/status", - IOError(errno.ENOENT, "")): - self.assertIsNone(psutil.sensors_battery().power_plugged) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSensorsTemperatures(unittest.TestCase): - - def test_emulate_class_hwmon(self): - def open_mock(name, *args, **kwargs): - if name.endswith('/name'): - return io.StringIO(u("name")) - elif name.endswith('/temp1_label'): - return io.StringIO(u("label")) - elif name.endswith('/temp1_input'): - return io.BytesIO(b"30000") - elif name.endswith('/temp1_max'): - return io.BytesIO(b"40000") - elif name.endswith('/temp1_crit'): - return io.BytesIO(b"50000") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - # Test case with /sys/class/hwmon - with mock.patch('glob.glob', - return_value=['/sys/class/hwmon/hwmon0/temp1']): - temp = psutil.sensors_temperatures()['name'][0] - self.assertEqual(temp.label, 'label') - self.assertEqual(temp.current, 30.0) - self.assertEqual(temp.high, 40.0) - self.assertEqual(temp.critical, 50.0) - - def test_emulate_class_thermal(self): - def open_mock(name, *args, **kwargs): - if name.endswith('0_temp'): - return io.BytesIO(b"50000") - elif name.endswith('temp'): - return io.BytesIO(b"30000") - elif name.endswith('0_type'): - return io.StringIO(u("critical")) - elif name.endswith('type'): - return io.StringIO(u("name")) - else: - return orig_open(name, *args, **kwargs) - - def glob_mock(path): - if path == '/sys/class/hwmon/hwmon*/temp*_*': - return [] - elif path == '/sys/class/hwmon/hwmon*/device/temp*_*': - return [] - elif path == '/sys/class/thermal/thermal_zone*': - return ['/sys/class/thermal/thermal_zone0'] - elif path == '/sys/class/thermal/thermal_zone0/trip_point*': - return ['/sys/class/thermal/thermal_zone1/trip_point_0_type', - '/sys/class/thermal/thermal_zone1/trip_point_0_temp'] - return [] - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - with mock.patch('glob.glob', create=True, side_effect=glob_mock): - temp = psutil.sensors_temperatures()['name'][0] - self.assertEqual(temp.label, '') - self.assertEqual(temp.current, 30.0) - self.assertEqual(temp.high, 50.0) - self.assertEqual(temp.critical, 50.0) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestSensorsFans(unittest.TestCase): - - def test_emulate_data(self): - def open_mock(name, *args, **kwargs): - if name.endswith('/name'): - return io.StringIO(u("name")) - elif name.endswith('/fan1_label'): - return io.StringIO(u("label")) - elif name.endswith('/fan1_input'): - return io.StringIO(u("2000")) - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock): - with mock.patch('glob.glob', - return_value=['/sys/class/hwmon/hwmon2/fan1']): - fan = psutil.sensors_fans()['name'][0] - self.assertEqual(fan.label, 'label') - self.assertEqual(fan.current, 2000) - - -# ===================================================================== -# --- test process -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestProcess(unittest.TestCase): - - def setUp(self): - safe_rmpath(TESTFN) - - tearDown = setUp - - def test_memory_full_info(self): - src = textwrap.dedent(""" - import time - with open("%s", "w") as f: - time.sleep(10) - """ % TESTFN) - sproc = pyrun(src) - self.addCleanup(reap_children) - call_until(lambda: os.listdir('.'), "'%s' not in ret" % TESTFN) - p = psutil.Process(sproc.pid) - time.sleep(.1) - mem = p.memory_full_info() - maps = p.memory_maps(grouped=False) - self.assertAlmostEqual( - mem.uss, sum([x.private_dirty + x.private_clean for x in maps]), - delta=4096) - self.assertAlmostEqual( - mem.pss, sum([x.pss for x in maps]), delta=4096) - self.assertAlmostEqual( - mem.swap, sum([x.swap for x in maps]), delta=4096) - - def test_memory_full_info_mocked(self): - # See: https://github.com/giampaolo/psutil/issues/1222 - with mock_open_content( - "/proc/%s/smaps" % os.getpid(), - textwrap.dedent("""\ - fffff0 r-xp 00000000 00:00 0 [vsyscall] - Size: 1 kB - Rss: 2 kB - Pss: 3 kB - Shared_Clean: 4 kB - Shared_Dirty: 5 kB - Private_Clean: 6 kB - Private_Dirty: 7 kB - Referenced: 8 kB - Anonymous: 9 kB - LazyFree: 10 kB - AnonHugePages: 11 kB - ShmemPmdMapped: 12 kB - Shared_Hugetlb: 13 kB - Private_Hugetlb: 14 kB - Swap: 15 kB - SwapPss: 16 kB - KernelPageSize: 17 kB - MMUPageSize: 18 kB - Locked: 19 kB - VmFlags: rd ex - """).encode()) as m: - p = psutil.Process() - mem = p.memory_full_info() - assert m.called - self.assertEqual(mem.uss, (6 + 7 + 14) * 1024) - self.assertEqual(mem.pss, 3 * 1024) - self.assertEqual(mem.swap, 15 * 1024) - - # On PYPY file descriptors are not closed fast enough. - @unittest.skipIf(PYPY, "unreliable on PYPY") - def test_open_files_mode(self): - def get_test_file(): - p = psutil.Process() - giveup_at = time.time() + 2 - while True: - for file in p.open_files(): - if file.path == os.path.abspath(TESTFN): - return file - elif time.time() > giveup_at: - break - raise RuntimeError("timeout looking for test file") - - # - with open(TESTFN, "w"): - self.assertEqual(get_test_file().mode, "w") - with open(TESTFN, "r"): - self.assertEqual(get_test_file().mode, "r") - with open(TESTFN, "a"): - self.assertEqual(get_test_file().mode, "a") - # - with open(TESTFN, "r+"): - self.assertEqual(get_test_file().mode, "r+") - with open(TESTFN, "w+"): - self.assertEqual(get_test_file().mode, "r+") - with open(TESTFN, "a+"): - self.assertEqual(get_test_file().mode, "a+") - # note: "x" bit is not supported - if PY3: - safe_rmpath(TESTFN) - with open(TESTFN, "x"): - self.assertEqual(get_test_file().mode, "w") - safe_rmpath(TESTFN) - with open(TESTFN, "x+"): - self.assertEqual(get_test_file().mode, "r+") - - def test_open_files_file_gone(self): - # simulates a file which gets deleted during open_files() - # execution - p = psutil.Process() - files = p.open_files() - with tempfile.NamedTemporaryFile(): - # give the kernel some time to see the new file - call_until(p.open_files, "len(ret) != %i" % len(files)) - with mock.patch('psutil._pslinux.os.readlink', - side_effect=OSError(errno.ENOENT, "")) as m: - files = p.open_files() - assert not files - assert m.called - # also simulate the case where os.readlink() returns EINVAL - # in which case psutil is supposed to 'continue' - with mock.patch('psutil._pslinux.os.readlink', - side_effect=OSError(errno.EINVAL, "")) as m: - self.assertEqual(p.open_files(), []) - assert m.called - - def test_open_files_fd_gone(self): - # Simulate a case where /proc/{pid}/fdinfo/{fd} disappears - # while iterating through fds. - # https://travis-ci.org/giampaolo/psutil/jobs/225694530 - p = psutil.Process() - files = p.open_files() - with tempfile.NamedTemporaryFile(): - # give the kernel some time to see the new file - call_until(p.open_files, "len(ret) != %i" % len(files)) - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, - side_effect=IOError(errno.ENOENT, "")) as m: - files = p.open_files() - assert not files - assert m.called - - # --- mocked tests - - def test_terminal_mocked(self): - with mock.patch('psutil._pslinux._psposix.get_terminal_map', - return_value={}) as m: - self.assertIsNone(psutil._pslinux.Process(os.getpid()).terminal()) - assert m.called - - # TODO: re-enable this test. - # def test_num_ctx_switches_mocked(self): - # with mock.patch('psutil._common.open', create=True) as m: - # self.assertRaises( - # NotImplementedError, - # psutil._pslinux.Process(os.getpid()).num_ctx_switches) - # assert m.called - - def test_cmdline_mocked(self): - # see: https://github.com/giampaolo/psutil/issues/639 - p = psutil.Process() - fake_file = io.StringIO(u('foo\x00bar\x00')) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(p.cmdline(), ['foo', 'bar']) - assert m.called - fake_file = io.StringIO(u('foo\x00bar\x00\x00')) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(p.cmdline(), ['foo', 'bar', '']) - assert m.called - - def test_cmdline_spaces_mocked(self): - # see: https://github.com/giampaolo/psutil/issues/1179 - p = psutil.Process() - fake_file = io.StringIO(u('foo bar ')) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(p.cmdline(), ['foo', 'bar']) - assert m.called - fake_file = io.StringIO(u('foo bar ')) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(p.cmdline(), ['foo', 'bar', '']) - assert m.called - - def test_cmdline_mixed_separators(self): - # https://github.com/giampaolo/psutil/issues/ - # 1179#issuecomment-552984549 - p = psutil.Process() - fake_file = io.StringIO(u('foo\x20bar\x00')) - with mock.patch('psutil._common.open', - return_value=fake_file, create=True) as m: - self.assertEqual(p.cmdline(), ['foo', 'bar']) - assert m.called - - def test_readlink_path_deleted_mocked(self): - with mock.patch('psutil._pslinux.os.readlink', - return_value='/home/foo (deleted)'): - self.assertEqual(psutil.Process().exe(), "/home/foo") - self.assertEqual(psutil.Process().cwd(), "/home/foo") - - def test_threads_mocked(self): - # Test the case where os.listdir() returns a file (thread) - # which no longer exists by the time we open() it (race - # condition). threads() is supposed to ignore that instead - # of raising NSP. - def open_mock(name, *args, **kwargs): - if name.startswith('/proc/%s/task' % os.getpid()): - raise IOError(errno.ENOENT, "") - else: - return orig_open(name, *args, **kwargs) - - orig_open = open - patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: - ret = psutil.Process().threads() - assert m.called - self.assertEqual(ret, []) - - # ...but if it bumps into something != ENOENT we want an - # exception. - def open_mock(name, *args, **kwargs): - if name.startswith('/proc/%s/task' % os.getpid()): - raise IOError(errno.EPERM, "") - else: - return orig_open(name, *args, **kwargs) - - with mock.patch(patch_point, side_effect=open_mock): - self.assertRaises(psutil.AccessDenied, psutil.Process().threads) - - def test_exe_mocked(self): - with mock.patch('psutil._pslinux.readlink', - side_effect=OSError(errno.ENOENT, "")) as m1: - with mock.patch('psutil.Process.cmdline', - side_effect=psutil.AccessDenied(0, "")) as m2: - # No such file error; might be raised also if /proc/pid/exe - # path actually exists for system processes with low pids - # (about 0-20). In this case psutil is supposed to return - # an empty string. - ret = psutil.Process().exe() - assert m1.called - assert m2.called - self.assertEqual(ret, "") - - # ...but if /proc/pid no longer exist we're supposed to treat - # it as an alias for zombie process - with mock.patch('psutil._pslinux.os.path.lexists', - return_value=False): - self.assertRaises( - psutil.ZombieProcess, psutil.Process().exe) - - def test_issue_1014(self): - # Emulates a case where smaps file does not exist. In this case - # wrap_exception decorator should not raise NoSuchProcess. - with mock_open_exception( - '/proc/%s/smaps' % os.getpid(), - IOError(errno.ENOENT, "")) as m: - p = psutil.Process() - with self.assertRaises(FileNotFoundError): - p.memory_maps() - assert m.called - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_zombie(self): - # Emulate a case where rlimit() raises ENOSYS, which may - # happen in case of zombie process: - # https://travis-ci.org/giampaolo/psutil/jobs/51368273 - with mock.patch("psutil._pslinux.cext.linux_prlimit", - side_effect=OSError(errno.ENOSYS, "")) as m: - p = psutil.Process() - p.name() - with self.assertRaises(psutil.ZombieProcess) as exc: - p.rlimit(psutil.RLIMIT_NOFILE) - assert m.called - self.assertEqual(exc.exception.pid, p.pid) - self.assertEqual(exc.exception.name, p.name()) - - def test_cwd_zombie(self): - with mock.patch("psutil._pslinux.os.readlink", - side_effect=OSError(errno.ENOENT, "")) as m: - p = psutil.Process() - p.name() - with self.assertRaises(psutil.ZombieProcess) as exc: - p.cwd() - assert m.called - self.assertEqual(exc.exception.pid, p.pid) - self.assertEqual(exc.exception.name, p.name()) - - def test_stat_file_parsing(self): - from psutil._pslinux import CLOCK_TICKS - - args = [ - "0", # pid - "(cat)", # name - "Z", # status - "1", # ppid - "0", # pgrp - "0", # session - "0", # tty - "0", # tpgid - "0", # flags - "0", # minflt - "0", # cminflt - "0", # majflt - "0", # cmajflt - "2", # utime - "3", # stime - "4", # cutime - "5", # cstime - "0", # priority - "0", # nice - "0", # num_threads - "0", # itrealvalue - "6", # starttime - "0", # vsize - "0", # rss - "0", # rsslim - "0", # startcode - "0", # endcode - "0", # startstack - "0", # kstkesp - "0", # kstkeip - "0", # signal - "0", # blocked - "0", # sigignore - "0", # sigcatch - "0", # wchan - "0", # nswap - "0", # cnswap - "0", # exit_signal - "6", # processor - "0", # rt priority - "0", # policy - "7", # delayacct_blkio_ticks - ] - content = " ".join(args).encode() - with mock_open_content('/proc/%s/stat' % os.getpid(), content): - p = psutil.Process() - self.assertEqual(p.name(), 'cat') - self.assertEqual(p.status(), psutil.STATUS_ZOMBIE) - self.assertEqual(p.ppid(), 1) - self.assertEqual( - p.create_time(), 6 / CLOCK_TICKS + psutil.boot_time()) - cpu = p.cpu_times() - self.assertEqual(cpu.user, 2 / CLOCK_TICKS) - self.assertEqual(cpu.system, 3 / CLOCK_TICKS) - self.assertEqual(cpu.children_user, 4 / CLOCK_TICKS) - self.assertEqual(cpu.children_system, 5 / CLOCK_TICKS) - self.assertEqual(cpu.iowait, 7 / CLOCK_TICKS) - self.assertEqual(p.cpu_num(), 6) - - def test_status_file_parsing(self): - with mock_open_content( - '/proc/%s/status' % os.getpid(), - textwrap.dedent("""\ - Uid:\t1000\t1001\t1002\t1003 - Gid:\t1004\t1005\t1006\t1007 - Threads:\t66 - Cpus_allowed:\tf - Cpus_allowed_list:\t0-7 - voluntary_ctxt_switches:\t12 - nonvoluntary_ctxt_switches:\t13""").encode()): - p = psutil.Process() - self.assertEqual(p.num_ctx_switches().voluntary, 12) - self.assertEqual(p.num_ctx_switches().involuntary, 13) - self.assertEqual(p.num_threads(), 66) - uids = p.uids() - self.assertEqual(uids.real, 1000) - self.assertEqual(uids.effective, 1001) - self.assertEqual(uids.saved, 1002) - gids = p.gids() - self.assertEqual(gids.real, 1004) - self.assertEqual(gids.effective, 1005) - self.assertEqual(gids.saved, 1006) - self.assertEqual(p._proc._get_eligible_cpus(), list(range(0, 8))) - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestProcessAgainstStatus(unittest.TestCase): - """/proc/pid/stat and /proc/pid/status have many values in common. - Whenever possible, psutil uses /proc/pid/stat (it's faster). - For all those cases we check that the value found in - /proc/pid/stat (by psutil) matches the one found in - /proc/pid/status. - """ - - @classmethod - def setUpClass(cls): - cls.proc = psutil.Process() - - def read_status_file(self, linestart): - with psutil._psplatform.open_text( - '/proc/%s/status' % self.proc.pid) as f: - for line in f: - line = line.strip() - if line.startswith(linestart): - value = line.partition('\t')[2] - try: - return int(value) - except ValueError: - return value - raise ValueError("can't find %r" % linestart) - - def test_name(self): - value = self.read_status_file("Name:") - self.assertEqual(self.proc.name(), value) - - def test_status(self): - value = self.read_status_file("State:") - value = value[value.find('(') + 1:value.rfind(')')] - value = value.replace(' ', '-') - self.assertEqual(self.proc.status(), value) - - def test_ppid(self): - value = self.read_status_file("PPid:") - self.assertEqual(self.proc.ppid(), value) - - def test_num_threads(self): - value = self.read_status_file("Threads:") - self.assertEqual(self.proc.num_threads(), value) - - def test_uids(self): - value = self.read_status_file("Uid:") - value = tuple(map(int, value.split()[1:4])) - self.assertEqual(self.proc.uids(), value) - - def test_gids(self): - value = self.read_status_file("Gid:") - value = tuple(map(int, value.split()[1:4])) - self.assertEqual(self.proc.gids(), value) - - @retry_on_failure() - def test_num_ctx_switches(self): - value = self.read_status_file("voluntary_ctxt_switches:") - self.assertEqual(self.proc.num_ctx_switches().voluntary, value) - value = self.read_status_file("nonvoluntary_ctxt_switches:") - self.assertEqual(self.proc.num_ctx_switches().involuntary, value) - - def test_cpu_affinity(self): - value = self.read_status_file("Cpus_allowed_list:") - if '-' in str(value): - min_, max_ = map(int, value.split('-')) - self.assertEqual( - self.proc.cpu_affinity(), list(range(min_, max_ + 1))) - - def test_cpu_affinity_eligible_cpus(self): - value = self.read_status_file("Cpus_allowed_list:") - with mock.patch("psutil._pslinux.per_cpu_times") as m: - self.proc._proc._get_eligible_cpus() - if '-' in str(value): - assert not m.called - else: - assert m.called - - -# ===================================================================== -# --- test utils -# ===================================================================== - - -@unittest.skipIf(not LINUX, "LINUX only") -class TestUtils(unittest.TestCase): - - def test_readlink(self): - with mock.patch("os.readlink", return_value="foo (deleted)") as m: - self.assertEqual(psutil._psplatform.readlink("bar"), "foo") - assert m.called - - def test_cat(self): - fname = os.path.abspath(TESTFN) - with open(fname, "wt") as f: - f.write("foo ") - self.assertEqual(psutil._psplatform.cat(TESTFN, binary=False), "foo") - self.assertEqual(psutil._psplatform.cat(TESTFN, binary=True), b"foo") - self.assertEqual( - psutil._psplatform.cat(TESTFN + '??', fallback="bar"), "bar") - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_memory_leaks.py b/third_party/python/psutil/psutil/tests/test_memory_leaks.py deleted file mode 100755 index f9cad70fd33e..000000000000 --- a/third_party/python/psutil/psutil/tests/test_memory_leaks.py +++ /dev/null @@ -1,600 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Tests for detecting function memory leaks (typically the ones -implemented in C). It does so by calling a function many times and -checking whether process memory usage keeps increasing between -calls or over time. -Note that this may produce false positives (especially on Windows -for some reason). -PyPy appears to be completely unstable for this framework, probably -because of how its JIT handles memory, so tests are skipped. -""" - -from __future__ import print_function -import functools -import gc -import os -import sys -import threading -import time - -import psutil -import psutil._common -from psutil import FREEBSD -from psutil import LINUX -from psutil import MACOS -from psutil import OPENBSD -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -from psutil._common import bytes2human -from psutil._compat import ProcessLookupError -from psutil._compat import xrange -from psutil.tests import CIRRUS -from psutil.tests import create_sockets -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_CPU_AFFINITY -from psutil.tests import HAS_CPU_FREQ -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 -from psutil.tests import HAS_SENSORS_BATTERY -from psutil.tests import HAS_SENSORS_FANS -from psutil.tests import HAS_SENSORS_TEMPERATURES -from psutil.tests import PYPY -from psutil.tests import reap_children -from psutil.tests import safe_rmpath -from psutil.tests import skip_on_access_denied -from psutil.tests import TESTFN -from psutil.tests import TRAVIS -from psutil.tests import unittest - - -# configurable opts -LOOPS = 1000 -MEMORY_TOLERANCE = 4096 -RETRY_FOR = 3 -SKIP_PYTHON_IMPL = True - -cext = psutil._psplatform.cext -thisproc = psutil.Process() - - -# =================================================================== -# utils -# =================================================================== - - -def skip_if_linux(): - return unittest.skipIf(LINUX and SKIP_PYTHON_IMPL, - "worthless on LINUX (pure python)") - - -@unittest.skipIf(PYPY, "unreliable on PYPY") -class TestMemLeak(unittest.TestCase): - """Base framework class which calls a function many times and - produces a failure if process memory usage keeps increasing - between calls or over time. - """ - tolerance = MEMORY_TOLERANCE - loops = LOOPS - retry_for = RETRY_FOR - - def setUp(self): - gc.collect() - - def execute(self, fun, *args, **kwargs): - """Test a callable.""" - def call_many_times(): - for x in xrange(loops): - self._call(fun, *args, **kwargs) - del x - gc.collect() - - tolerance = kwargs.pop('tolerance_', None) or self.tolerance - loops = kwargs.pop('loops_', None) or self.loops - retry_for = kwargs.pop('retry_for_', None) or self.retry_for - - # warm up - for x in range(10): - self._call(fun, *args, **kwargs) - self.assertEqual(gc.garbage, []) - self.assertEqual(threading.active_count(), 1) - self.assertEqual(thisproc.children(), []) - - # Get 2 distinct memory samples, before and after having - # called fun repeadetly. - # step 1 - call_many_times() - mem1 = self._get_mem() - # step 2 - call_many_times() - mem2 = self._get_mem() - - diff1 = mem2 - mem1 - if diff1 > tolerance: - # This doesn't necessarily mean we have a leak yet. - # At this point we assume that after having called the - # function so many times the memory usage is stabilized - # and if there are no leaks it should not increase - # anymore. - # Let's keep calling fun for 3 more seconds and fail if - # we notice any difference. - ncalls = 0 - stop_at = time.time() + retry_for - while time.time() <= stop_at: - self._call(fun, *args, **kwargs) - ncalls += 1 - - del stop_at - gc.collect() - mem3 = self._get_mem() - diff2 = mem3 - mem2 - - if mem3 > mem2: - # failure - extra_proc_mem = bytes2human(diff1 + diff2) - print("exta proc mem: %s" % extra_proc_mem, file=sys.stderr) - msg = "+%s after %s calls, +%s after another %s calls, " - msg += "+%s extra proc mem" - msg = msg % ( - bytes2human(diff1), loops, bytes2human(diff2), ncalls, - extra_proc_mem) - self.fail(msg) - - def execute_w_exc(self, exc, fun, *args, **kwargs): - """Convenience function which tests a callable raising - an exception. - """ - def call(): - self.assertRaises(exc, fun, *args, **kwargs) - - self.execute(call) - - @staticmethod - def _get_mem(): - # By using USS memory it seems it's less likely to bump - # into false positives. - if LINUX or WINDOWS or MACOS: - return thisproc.memory_full_info().uss - else: - return thisproc.memory_info().rss - - @staticmethod - def _call(fun, *args, **kwargs): - fun(*args, **kwargs) - - -# =================================================================== -# Process class -# =================================================================== - - -class TestProcessObjectLeaks(TestMemLeak): - """Test leaks of Process class methods.""" - - proc = thisproc - - def test_coverage(self): - skip = set(( - "pid", "as_dict", "children", "cpu_affinity", "cpu_percent", - "ionice", "is_running", "kill", "memory_info_ex", "memory_percent", - "nice", "oneshot", "parent", "parents", "rlimit", "send_signal", - "suspend", "terminate", "wait")) - for name in dir(psutil.Process): - if name.startswith('_'): - continue - if name in skip: - continue - self.assertTrue(hasattr(self, "test_" + name), msg=name) - - @skip_if_linux() - def test_name(self): - self.execute(self.proc.name) - - @skip_if_linux() - def test_cmdline(self): - self.execute(self.proc.cmdline) - - @skip_if_linux() - def test_exe(self): - self.execute(self.proc.exe) - - @skip_if_linux() - def test_ppid(self): - self.execute(self.proc.ppid) - - @unittest.skipIf(not POSIX, "POSIX only") - @skip_if_linux() - def test_uids(self): - self.execute(self.proc.uids) - - @unittest.skipIf(not POSIX, "POSIX only") - @skip_if_linux() - def test_gids(self): - self.execute(self.proc.gids) - - @skip_if_linux() - def test_status(self): - self.execute(self.proc.status) - - def test_nice_get(self): - self.execute(self.proc.nice) - - def test_nice_set(self): - niceness = thisproc.nice() - self.execute(self.proc.nice, niceness) - - @unittest.skipIf(not HAS_IONICE, "not supported") - def test_ionice_get(self): - self.execute(self.proc.ionice) - - @unittest.skipIf(not HAS_IONICE, "not supported") - def test_ionice_set(self): - if WINDOWS: - value = thisproc.ionice() - self.execute(self.proc.ionice, value) - else: - self.execute(self.proc.ionice, psutil.IOPRIO_CLASS_NONE) - fun = functools.partial(cext.proc_ioprio_set, os.getpid(), -1, 0) - self.execute_w_exc(OSError, fun) - - @unittest.skipIf(not HAS_PROC_IO_COUNTERS, "not supported") - @skip_if_linux() - def test_io_counters(self): - self.execute(self.proc.io_counters) - - @unittest.skipIf(POSIX, "worthless on POSIX") - def test_username(self): - self.execute(self.proc.username) - - @skip_if_linux() - def test_create_time(self): - self.execute(self.proc.create_time) - - @skip_if_linux() - @skip_on_access_denied(only_if=OPENBSD) - def test_num_threads(self): - self.execute(self.proc.num_threads) - - @unittest.skipIf(not WINDOWS, "WINDOWS only") - def test_num_handles(self): - self.execute(self.proc.num_handles) - - @unittest.skipIf(not POSIX, "POSIX only") - @skip_if_linux() - def test_num_fds(self): - self.execute(self.proc.num_fds) - - @skip_if_linux() - def test_num_ctx_switches(self): - self.execute(self.proc.num_ctx_switches) - - @skip_if_linux() - @skip_on_access_denied(only_if=OPENBSD) - def test_threads(self): - self.execute(self.proc.threads) - - @skip_if_linux() - def test_cpu_times(self): - self.execute(self.proc.cpu_times) - - @skip_if_linux() - @unittest.skipIf(not HAS_PROC_CPU_NUM, "not supported") - def test_cpu_num(self): - self.execute(self.proc.cpu_num) - - @skip_if_linux() - def test_memory_info(self): - self.execute(self.proc.memory_info) - - @skip_if_linux() - def test_memory_full_info(self): - self.execute(self.proc.memory_full_info) - - @unittest.skipIf(not POSIX, "POSIX only") - @skip_if_linux() - def test_terminal(self): - self.execute(self.proc.terminal) - - @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, - "worthless on POSIX (pure python)") - def test_resume(self): - self.execute(self.proc.resume) - - @skip_if_linux() - def test_cwd(self): - self.execute(self.proc.cwd) - - @unittest.skipIf(not HAS_CPU_AFFINITY, "not supported") - def test_cpu_affinity_get(self): - self.execute(self.proc.cpu_affinity) - - @unittest.skipIf(not HAS_CPU_AFFINITY, "not supported") - def test_cpu_affinity_set(self): - affinity = thisproc.cpu_affinity() - self.execute(self.proc.cpu_affinity, affinity) - if not TRAVIS: - self.execute_w_exc(ValueError, self.proc.cpu_affinity, [-1]) - - @skip_if_linux() - def test_open_files(self): - safe_rmpath(TESTFN) # needed after UNIX socket test has run - with open(TESTFN, 'w'): - self.execute(self.proc.open_files) - - @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") - @skip_if_linux() - def test_memory_maps(self): - self.execute(self.proc.memory_maps) - - @unittest.skipIf(not LINUX, "LINUX only") - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_get(self): - self.execute(self.proc.rlimit, psutil.RLIMIT_NOFILE) - - @unittest.skipIf(not LINUX, "LINUX only") - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_set(self): - limit = thisproc.rlimit(psutil.RLIMIT_NOFILE) - self.execute(self.proc.rlimit, psutil.RLIMIT_NOFILE, limit) - self.execute_w_exc(OSError, self.proc.rlimit, -1) - - @skip_if_linux() - # Windows implementation is based on a single system-wide - # function (tested later). - @unittest.skipIf(WINDOWS, "worthless on WINDOWS") - def test_connections(self): - # TODO: UNIX sockets are temporarily implemented by parsing - # 'pfiles' cmd output; we don't want that part of the code to - # be executed. - with create_sockets(): - kind = 'inet' if SUNOS else 'all' - self.execute(self.proc.connections, kind) - - @unittest.skipIf(not HAS_ENVIRON, "not supported") - def test_environ(self): - self.execute(self.proc.environ) - - @unittest.skipIf(not WINDOWS, "WINDOWS only") - def test_proc_info(self): - self.execute(cext.proc_info, os.getpid()) - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestProcessDualImplementation(TestMemLeak): - - def test_cmdline_peb_true(self): - self.execute(cext.proc_cmdline, os.getpid(), use_peb=True) - - def test_cmdline_peb_false(self): - self.execute(cext.proc_cmdline, os.getpid(), use_peb=False) - - -class TestTerminatedProcessLeaks(TestProcessObjectLeaks): - """Repeat the tests above looking for leaks occurring when dealing - with terminated processes raising NoSuchProcess exception. - The C functions are still invoked but will follow different code - paths. We'll check those code paths. - """ - - @classmethod - def setUpClass(cls): - super(TestTerminatedProcessLeaks, cls).setUpClass() - p = get_test_subprocess() - cls.proc = psutil.Process(p.pid) - cls.proc.kill() - cls.proc.wait() - - @classmethod - def tearDownClass(cls): - super(TestTerminatedProcessLeaks, cls).tearDownClass() - reap_children() - - def _call(self, fun, *args, **kwargs): - try: - fun(*args, **kwargs) - except psutil.NoSuchProcess: - pass - - if WINDOWS: - - def test_kill(self): - self.execute(self.proc.kill) - - def test_terminate(self): - self.execute(self.proc.terminate) - - def test_suspend(self): - self.execute(self.proc.suspend) - - def test_resume(self): - self.execute(self.proc.resume) - - def test_wait(self): - self.execute(self.proc.wait) - - def test_proc_info(self): - # test dual implementation - def call(): - try: - return cext.proc_info(self.proc.pid) - except ProcessLookupError: - pass - - self.execute(call) - - -# =================================================================== -# system APIs -# =================================================================== - - -class TestModuleFunctionsLeaks(TestMemLeak): - """Test leaks of psutil module functions.""" - - def test_coverage(self): - skip = set(( - "version_info", "__version__", "process_iter", "wait_procs", - "cpu_percent", "cpu_times_percent", "cpu_count")) - for name in psutil.__all__: - if not name.islower(): - continue - if name in skip: - continue - self.assertTrue(hasattr(self, "test_" + name), msg=name) - - # --- cpu - - @skip_if_linux() - def test_cpu_count_logical(self): - self.execute(psutil.cpu_count, logical=True) - - @skip_if_linux() - def test_cpu_count_physical(self): - self.execute(psutil.cpu_count, logical=False) - - @skip_if_linux() - def test_cpu_times(self): - self.execute(psutil.cpu_times) - - @skip_if_linux() - def test_per_cpu_times(self): - self.execute(psutil.cpu_times, percpu=True) - - @skip_if_linux() - def test_cpu_stats(self): - self.execute(psutil.cpu_stats) - - @skip_if_linux() - @unittest.skipIf(not HAS_CPU_FREQ, "not supported") - def test_cpu_freq(self): - self.execute(psutil.cpu_freq) - - @unittest.skipIf(not WINDOWS, "WINDOWS only") - def test_getloadavg(self): - self.execute(psutil.getloadavg) - - # --- mem - - def test_virtual_memory(self): - self.execute(psutil.virtual_memory) - - # TODO: remove this skip when this gets fixed - @unittest.skipIf(SUNOS, "worthless on SUNOS (uses a subprocess)") - def test_swap_memory(self): - self.execute(psutil.swap_memory) - - @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, - "worthless on POSIX (pure python)") - def test_pid_exists(self): - self.execute(psutil.pid_exists, os.getpid()) - - # --- disk - - @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, - "worthless on POSIX (pure python)") - def test_disk_usage(self): - self.execute(psutil.disk_usage, '.') - - def test_disk_partitions(self): - self.execute(psutil.disk_partitions) - - @unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'), - '/proc/diskstats not available on this Linux version') - @skip_if_linux() - def test_disk_io_counters(self): - self.execute(psutil.disk_io_counters, nowrap=False) - - # --- proc - - @skip_if_linux() - def test_pids(self): - self.execute(psutil.pids) - - # --- net - - @unittest.skipIf(TRAVIS and MACOS, "false positive on TRAVIS + MACOS") - @unittest.skipIf(CIRRUS and FREEBSD, "false positive on CIRRUS + FREEBSD") - @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) - - @skip_if_linux() - @unittest.skipIf(MACOS and os.getuid() != 0, "need root access") - def test_net_connections(self): - with create_sockets(): - self.execute(psutil.net_connections) - - def test_net_if_addrs(self): - # Note: verified that on Windows this was a false positive. - self.execute(psutil.net_if_addrs, - tolerance_=80 * 1024 if WINDOWS else None) - - @unittest.skipIf(TRAVIS, "EPERM on travis") - def test_net_if_stats(self): - self.execute(psutil.net_if_stats) - - # --- sensors - - @skip_if_linux() - @unittest.skipIf(not HAS_SENSORS_BATTERY, "not supported") - def test_sensors_battery(self): - self.execute(psutil.sensors_battery) - - @skip_if_linux() - @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") - def test_sensors_temperatures(self): - self.execute(psutil.sensors_temperatures) - - @skip_if_linux() - @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") - def test_sensors_fans(self): - self.execute(psutil.sensors_fans) - - # --- others - - @skip_if_linux() - def test_boot_time(self): - self.execute(psutil.boot_time) - - @unittest.skipIf(WINDOWS, "XXX produces a false positive on Windows") - def test_users(self): - self.execute(psutil.users) - - if WINDOWS: - - # --- win services - - def test_win_service_iter(self): - self.execute(cext.winservice_enumerate) - - def test_win_service_get(self): - pass - - def test_win_service_get_config(self): - name = next(psutil.win_service_iter()).name() - self.execute(cext.winservice_query_config, name) - - def test_win_service_get_status(self): - name = next(psutil.win_service_iter()).name() - self.execute(cext.winservice_query_status, name) - - def test_win_service_get_description(self): - name = next(psutil.win_service_iter()).name() - self.execute(cext.winservice_query_descr, name) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_misc.py b/third_party/python/psutil/psutil/tests/test_misc.py deleted file mode 100755 index c20cd9413b6a..000000000000 --- a/third_party/python/psutil/psutil/tests/test_misc.py +++ /dev/null @@ -1,1065 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# 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. - -""" -Miscellaneous tests. -""" - -import ast -import collections -import contextlib -import errno -import json -import os -import pickle -import socket -import stat - -from psutil import FREEBSD -from psutil import LINUX -from psutil import NETBSD -from psutil import POSIX -from psutil import WINDOWS -from psutil._common import memoize -from psutil._common import memoize_when_activated -from psutil._common import supports_ipv6 -from psutil._common import wrap_numbers -from psutil._common import open_text -from psutil._common import open_binary -from psutil._compat import PY3 -from psutil.tests import APPVEYOR -from psutil.tests import bind_socket -from psutil.tests import bind_unix_socket -from psutil.tests import call_until -from psutil.tests import chdir -from psutil.tests import CI_TESTING -from psutil.tests import create_proc_children_pair -from psutil.tests import create_sockets -from psutil.tests import create_zombie_proc -from psutil.tests import DEVNULL -from psutil.tests import get_free_port -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_BATTERY -from psutil.tests import HAS_CONNECTIONS_UNIX -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 -from psutil.tests import import_module_by_path -from psutil.tests import is_namedtuple -from psutil.tests import mock -from psutil.tests import PYTHON_EXE -from psutil.tests import reap_children -from psutil.tests import reload_module -from psutil.tests import retry -from psutil.tests import ROOT_DIR -from psutil.tests import safe_mkdir -from psutil.tests import safe_rmpath -from psutil.tests import SCRIPTS_DIR -from psutil.tests import sh -from psutil.tests import tcp_socketpair -from psutil.tests import TESTFN -from psutil.tests import TOX -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import unix_socket_path -from psutil.tests import unix_socketpair -from psutil.tests import wait_for_file -from psutil.tests import wait_for_pid -import psutil -import psutil.tests - - -# =================================================================== -# --- Misc / generic tests. -# =================================================================== - - -class TestMisc(unittest.TestCase): - - def test_process__repr__(self, func=repr): - p = psutil.Process() - r = func(p) - self.assertIn("psutil.Process", r) - self.assertIn("pid=%s" % p.pid, r) - self.assertIn("name=", r) - self.assertIn(p.name(), r) - with mock.patch.object(psutil.Process, "name", - side_effect=psutil.ZombieProcess(os.getpid())): - p = psutil.Process() - r = func(p) - self.assertIn("pid=%s" % p.pid, r) - self.assertIn("zombie", r) - self.assertNotIn("name=", r) - with mock.patch.object(psutil.Process, "name", - side_effect=psutil.NoSuchProcess(os.getpid())): - p = psutil.Process() - r = func(p) - self.assertIn("pid=%s" % p.pid, r) - self.assertIn("terminated", r) - self.assertNotIn("name=", r) - with mock.patch.object(psutil.Process, "name", - side_effect=psutil.AccessDenied(os.getpid())): - p = psutil.Process() - r = func(p) - self.assertIn("pid=%s" % p.pid, r) - self.assertNotIn("name=", r) - - def test_process__str__(self): - self.test_process__repr__(func=str) - - def test_no_such_process__repr__(self, func=repr): - self.assertEqual( - repr(psutil.NoSuchProcess(321)), - "psutil.NoSuchProcess process no longer exists (pid=321)") - self.assertEqual( - repr(psutil.NoSuchProcess(321, name='foo')), - "psutil.NoSuchProcess process no longer exists (pid=321, " - "name='foo')") - self.assertEqual( - repr(psutil.NoSuchProcess(321, msg='foo')), - "psutil.NoSuchProcess foo") - - def test_zombie_process__repr__(self, func=repr): - self.assertEqual( - repr(psutil.ZombieProcess(321)), - "psutil.ZombieProcess process still exists but it's a zombie " - "(pid=321)") - self.assertEqual( - repr(psutil.ZombieProcess(321, name='foo')), - "psutil.ZombieProcess process still exists but it's a zombie " - "(pid=321, name='foo')") - self.assertEqual( - repr(psutil.ZombieProcess(321, name='foo', ppid=1)), - "psutil.ZombieProcess process still exists but it's a zombie " - "(pid=321, name='foo', ppid=1)") - self.assertEqual( - repr(psutil.ZombieProcess(321, msg='foo')), - "psutil.ZombieProcess foo") - - def test_access_denied__repr__(self, func=repr): - self.assertEqual( - repr(psutil.AccessDenied(321)), - "psutil.AccessDenied (pid=321)") - self.assertEqual( - repr(psutil.AccessDenied(321, name='foo')), - "psutil.AccessDenied (pid=321, name='foo')") - self.assertEqual( - repr(psutil.AccessDenied(321, msg='foo')), - "psutil.AccessDenied foo") - - def test_timeout_expired__repr__(self, func=repr): - self.assertEqual( - repr(psutil.TimeoutExpired(321)), - "psutil.TimeoutExpired timeout after 321 seconds") - self.assertEqual( - repr(psutil.TimeoutExpired(321, pid=111)), - "psutil.TimeoutExpired timeout after 321 seconds (pid=111)") - self.assertEqual( - repr(psutil.TimeoutExpired(321, pid=111, name='foo')), - "psutil.TimeoutExpired timeout after 321 seconds " - "(pid=111, name='foo')") - - def test_process__eq__(self): - p1 = psutil.Process() - p2 = psutil.Process() - self.assertEqual(p1, p2) - p2._ident = (0, 0) - self.assertNotEqual(p1, p2) - self.assertNotEqual(p1, 'foo') - - def test_process__hash__(self): - s = set([psutil.Process(), psutil.Process()]) - self.assertEqual(len(s), 1) - - def test__all__(self): - dir_psutil = dir(psutil) - for name in dir_psutil: - if name in ('callable', 'error', 'namedtuple', 'tests', - 'long', 'test', 'NUM_CPUS', 'BOOT_TIME', - 'TOTAL_PHYMEM', 'PermissionError', - 'ProcessLookupError'): - continue - if not name.startswith('_'): - try: - __import__(name) - except ImportError: - if name not in psutil.__all__: - fun = getattr(psutil, name) - if fun is None: - continue - if (fun.__doc__ is not None and - 'deprecated' not in fun.__doc__.lower()): - self.fail('%r not in psutil.__all__' % name) - - # Import 'star' will break if __all__ is inconsistent, see: - # https://github.com/giampaolo/psutil/issues/656 - # Can't do `from psutil import *` as it won't work on python 3 - # so we simply iterate over __all__. - for name in psutil.__all__: - self.assertIn(name, dir_psutil) - - def test_version(self): - self.assertEqual('.'.join([str(x) for x in psutil.version_info]), - psutil.__version__) - - def test_process_as_dict_no_new_names(self): - # See https://github.com/giampaolo/psutil/issues/813 - p = psutil.Process() - p.foo = '1' - self.assertNotIn('foo', p.as_dict()) - - def test_memoize(self): - @memoize - def foo(*args, **kwargs): - "foo docstring" - calls.append(None) - return (args, kwargs) - - calls = [] - # no args - for x in range(2): - ret = foo() - expected = ((), {}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 1) - # with args - for x in range(2): - ret = foo(1) - expected = ((1, ), {}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 2) - # with args + kwargs - for x in range(2): - ret = foo(1, bar=2) - expected = ((1, ), {'bar': 2}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 3) - # clear cache - foo.cache_clear() - ret = foo() - expected = ((), {}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 4) - # docstring - self.assertEqual(foo.__doc__, "foo docstring") - - def test_memoize_when_activated(self): - class Foo: - - @memoize_when_activated - def foo(self): - calls.append(None) - - f = Foo() - calls = [] - f.foo() - f.foo() - self.assertEqual(len(calls), 2) - - # activate - calls = [] - f.foo.cache_activate(f) - f.foo() - f.foo() - self.assertEqual(len(calls), 1) - - # deactivate - calls = [] - f.foo.cache_deactivate(f) - f.foo() - f.foo() - self.assertEqual(len(calls), 2) - - def test_parse_environ_block(self): - from psutil._common import parse_environ_block - - def k(s): - return s.upper() if WINDOWS else s - - self.assertEqual(parse_environ_block("a=1\0"), - {k("a"): "1"}) - self.assertEqual(parse_environ_block("a=1\0b=2\0\0"), - {k("a"): "1", k("b"): "2"}) - self.assertEqual(parse_environ_block("a=1\0b=\0\0"), - {k("a"): "1", k("b"): ""}) - # ignore everything after \0\0 - self.assertEqual(parse_environ_block("a=1\0b=2\0\0c=3\0"), - {k("a"): "1", k("b"): "2"}) - # ignore everything that is not an assignment - self.assertEqual(parse_environ_block("xxx\0a=1\0"), {k("a"): "1"}) - self.assertEqual(parse_environ_block("a=1\0=b=2\0"), {k("a"): "1"}) - # do not fail if the block is incomplete - self.assertEqual(parse_environ_block("a=1\0b=2"), {k("a"): "1"}) - - def test_supports_ipv6(self): - self.addCleanup(supports_ipv6.cache_clear) - if supports_ipv6(): - with mock.patch('psutil._common.socket') as s: - s.has_ipv6 = False - supports_ipv6.cache_clear() - assert not supports_ipv6() - - supports_ipv6.cache_clear() - with mock.patch('psutil._common.socket.socket', - side_effect=socket.error) as s: - assert not supports_ipv6() - assert s.called - - supports_ipv6.cache_clear() - with mock.patch('psutil._common.socket.socket', - side_effect=socket.gaierror) as s: - assert not supports_ipv6() - supports_ipv6.cache_clear() - assert s.called - - supports_ipv6.cache_clear() - with mock.patch('psutil._common.socket.socket.bind', - side_effect=socket.gaierror) as s: - assert not supports_ipv6() - supports_ipv6.cache_clear() - assert s.called - else: - with self.assertRaises(Exception): - sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) - sock.bind(("::1", 0)) - - def test_isfile_strict(self): - from psutil._common import isfile_strict - this_file = os.path.abspath(__file__) - assert isfile_strict(this_file) - assert not isfile_strict(os.path.dirname(this_file)) - with mock.patch('psutil._common.os.stat', - side_effect=OSError(errno.EPERM, "foo")): - self.assertRaises(OSError, isfile_strict, this_file) - with mock.patch('psutil._common.os.stat', - side_effect=OSError(errno.EACCES, "foo")): - self.assertRaises(OSError, isfile_strict, this_file) - with mock.patch('psutil._common.os.stat', - side_effect=OSError(errno.EINVAL, "foo")): - assert not isfile_strict(this_file) - with mock.patch('psutil._common.stat.S_ISREG', return_value=False): - assert not isfile_strict(this_file) - - def test_serialization(self): - def check(ret): - if json is not None: - json.loads(json.dumps(ret)) - a = pickle.dumps(ret) - b = pickle.loads(a) - self.assertEqual(ret, b) - - check(psutil.Process().as_dict()) - check(psutil.virtual_memory()) - check(psutil.swap_memory()) - check(psutil.cpu_times()) - check(psutil.cpu_times_percent(interval=0)) - check(psutil.net_io_counters()) - if LINUX and not os.path.exists('/proc/diskstats'): - pass - else: - if not APPVEYOR: - check(psutil.disk_io_counters()) - check(psutil.disk_partitions()) - check(psutil.disk_usage(os.getcwd())) - check(psutil.users()) - - def test_setup_script(self): - setup_py = os.path.join(ROOT_DIR, 'setup.py') - if TRAVIS and not os.path.exists(setup_py): - return self.skipTest("can't find setup.py") - module = import_module_by_path(setup_py) - self.assertRaises(SystemExit, module.setup) - self.assertEqual(module.get_version(), psutil.__version__) - - def test_ad_on_process_creation(self): - # We are supposed to be able to instantiate Process also in case - # of zombie processes or access denied. - with mock.patch.object(psutil.Process, 'create_time', - side_effect=psutil.AccessDenied) as meth: - psutil.Process() - assert meth.called - with mock.patch.object(psutil.Process, 'create_time', - side_effect=psutil.ZombieProcess(1)) as meth: - psutil.Process() - assert meth.called - with mock.patch.object(psutil.Process, 'create_time', - side_effect=ValueError) as meth: - with self.assertRaises(ValueError): - psutil.Process() - assert meth.called - - def test_sanity_version_check(self): - # see: https://github.com/giampaolo/psutil/issues/564 - with mock.patch( - "psutil._psplatform.cext.version", return_value="0.0.0"): - with self.assertRaises(ImportError) as cm: - reload_module(psutil) - self.assertIn("version conflict", str(cm.exception).lower()) - - -# =================================================================== -# --- Tests for wrap_numbers() function. -# =================================================================== - - -nt = collections.namedtuple('foo', 'a b c') - - -class TestWrapNumbers(unittest.TestCase): - - def setUp(self): - wrap_numbers.cache_clear() - - tearDown = setUp - - def test_first_call(self): - input = {'disk1': nt(5, 5, 5)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - - def test_input_hasnt_changed(self): - input = {'disk1': nt(5, 5, 5)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - - def test_increase_but_no_wrap(self): - input = {'disk1': nt(5, 5, 5)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - input = {'disk1': nt(10, 15, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - input = {'disk1': nt(20, 25, 30)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - input = {'disk1': nt(20, 25, 30)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - - def test_wrap(self): - # let's say 100 is the threshold - input = {'disk1': nt(100, 100, 100)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - # first wrap restarts from 10 - input = {'disk1': nt(100, 100, 10)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(100, 100, 110)}) - # then it remains the same - input = {'disk1': nt(100, 100, 10)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(100, 100, 110)}) - # then it goes up - input = {'disk1': nt(100, 100, 90)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(100, 100, 190)}) - # then it wraps again - input = {'disk1': nt(100, 100, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(100, 100, 210)}) - # and remains the same - input = {'disk1': nt(100, 100, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(100, 100, 210)}) - # now wrap another num - input = {'disk1': nt(50, 100, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(150, 100, 210)}) - # and again - input = {'disk1': nt(40, 100, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(190, 100, 210)}) - # keep it the same - input = {'disk1': nt(40, 100, 20)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(190, 100, 210)}) - - def test_changing_keys(self): - # Emulate a case where the second call to disk_io() - # (or whatever) provides a new disk, then the new disk - # disappears on the third call. - input = {'disk1': nt(5, 5, 5)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - input = {'disk1': nt(5, 5, 5), - 'disk2': nt(7, 7, 7)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - input = {'disk1': nt(8, 8, 8)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - - def test_changing_keys_w_wrap(self): - input = {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 100)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - # disk 2 wraps - input = {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 10)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 110)}) - # disk 2 disappears - input = {'disk1': nt(50, 50, 50)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - - # then it appears again; the old wrap is supposed to be - # gone. - input = {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 100)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - # remains the same - input = {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 100)} - self.assertEqual(wrap_numbers(input, 'disk_io'), input) - # and then wraps again - input = {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 10)} - self.assertEqual(wrap_numbers(input, 'disk_io'), - {'disk1': nt(50, 50, 50), - 'disk2': nt(100, 100, 110)}) - - def test_real_data(self): - d = {'nvme0n1': (300, 508, 640, 1571, 5970, 1987, 2049, 451751, 47048), - 'nvme0n1p1': (1171, 2, 5600256, 1024, 516, 0, 0, 0, 8), - 'nvme0n1p2': (54, 54, 2396160, 5165056, 4, 24, 30, 1207, 28), - 'nvme0n1p3': (2389, 4539, 5154, 150, 4828, 1844, 2019, 398, 348)} - self.assertEqual(wrap_numbers(d, 'disk_io'), d) - self.assertEqual(wrap_numbers(d, 'disk_io'), d) - # decrease this ↓ - d = {'nvme0n1': (100, 508, 640, 1571, 5970, 1987, 2049, 451751, 47048), - 'nvme0n1p1': (1171, 2, 5600256, 1024, 516, 0, 0, 0, 8), - 'nvme0n1p2': (54, 54, 2396160, 5165056, 4, 24, 30, 1207, 28), - 'nvme0n1p3': (2389, 4539, 5154, 150, 4828, 1844, 2019, 398, 348)} - out = wrap_numbers(d, 'disk_io') - self.assertEqual(out['nvme0n1'][0], 400) - - # --- cache tests - - def test_cache_first_call(self): - input = {'disk1': nt(5, 5, 5)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - self.assertEqual(cache[1], {'disk_io': {}}) - self.assertEqual(cache[2], {'disk_io': {}}) - - def test_cache_call_twice(self): - input = {'disk1': nt(5, 5, 5)} - wrap_numbers(input, 'disk_io') - input = {'disk1': nt(10, 10, 10)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - self.assertEqual( - cache[1], - {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 0}}) - self.assertEqual(cache[2], {'disk_io': {}}) - - def test_cache_wrap(self): - # let's say 100 is the threshold - input = {'disk1': nt(100, 100, 100)} - wrap_numbers(input, 'disk_io') - - # first wrap restarts from 10 - input = {'disk1': nt(100, 100, 10)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - self.assertEqual( - cache[1], - {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 100}}) - self.assertEqual(cache[2], {'disk_io': {'disk1': set([('disk1', 2)])}}) - - def assert_(): - cache = wrap_numbers.cache_info() - self.assertEqual( - cache[1], - {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, - ('disk1', 2): 100}}) - self.assertEqual(cache[2], - {'disk_io': {'disk1': set([('disk1', 2)])}}) - - # then it remains the same - input = {'disk1': nt(100, 100, 10)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - assert_() - - # then it goes up - input = {'disk1': nt(100, 100, 90)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - assert_() - - # then it wraps again - input = {'disk1': nt(100, 100, 20)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - self.assertEqual( - cache[1], - {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 190}}) - self.assertEqual(cache[2], {'disk_io': {'disk1': set([('disk1', 2)])}}) - - def test_cache_changing_keys(self): - input = {'disk1': nt(5, 5, 5)} - wrap_numbers(input, 'disk_io') - input = {'disk1': nt(5, 5, 5), - 'disk2': nt(7, 7, 7)} - wrap_numbers(input, 'disk_io') - cache = wrap_numbers.cache_info() - self.assertEqual(cache[0], {'disk_io': input}) - self.assertEqual( - cache[1], - {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 0}}) - self.assertEqual(cache[2], {'disk_io': {}}) - - def test_cache_clear(self): - input = {'disk1': nt(5, 5, 5)} - wrap_numbers(input, 'disk_io') - wrap_numbers(input, 'disk_io') - wrap_numbers.cache_clear('disk_io') - self.assertEqual(wrap_numbers.cache_info(), ({}, {}, {})) - wrap_numbers.cache_clear('disk_io') - wrap_numbers.cache_clear('?!?') - - @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() - for cache in caches: - self.assertIn('psutil.disk_io_counters', cache) - self.assertIn('psutil.net_io_counters', cache) - - psutil.disk_io_counters.cache_clear() - caches = wrap_numbers.cache_info() - for cache in caches: - self.assertIn('psutil.net_io_counters', cache) - self.assertNotIn('psutil.disk_io_counters', cache) - - psutil.net_io_counters.cache_clear() - caches = wrap_numbers.cache_info() - self.assertEqual(caches, ({}, {}, {})) - - -# =================================================================== -# --- Example script tests -# =================================================================== - - -@unittest.skipIf(TOX, "can't test on TOX") -# See: https://travis-ci.org/giampaolo/psutil/jobs/295224806 -@unittest.skipIf(TRAVIS and not os.path.exists(SCRIPTS_DIR), - "can't locate scripts directory") -class TestScripts(unittest.TestCase): - """Tests for scripts in the "scripts" directory.""" - - @staticmethod - def assert_stdout(exe, *args, **kwargs): - exe = '%s' % os.path.join(SCRIPTS_DIR, exe) - cmd = [PYTHON_EXE, exe] - for arg in args: - cmd.append(arg) - try: - out = sh(cmd, **kwargs).strip() - except RuntimeError as err: - if 'AccessDenied' in str(err): - return str(err) - else: - raise - assert out, out - return out - - @staticmethod - def assert_syntax(exe, args=None): - exe = os.path.join(SCRIPTS_DIR, exe) - if PY3: - f = open(exe, 'rt', encoding='utf8') - else: - f = open(exe, 'rt') - with f: - src = f.read() - ast.parse(src) - - def test_coverage(self): - # make sure all example scripts have a test method defined - meths = dir(self) - for name in os.listdir(SCRIPTS_DIR): - if name.endswith('.py'): - if 'test_' + os.path.splitext(name)[0] not in meths: - # self.assert_stdout(name) - self.fail('no test defined for %r script' - % os.path.join(SCRIPTS_DIR, name)) - - @unittest.skipIf(not POSIX, "POSIX only") - def test_executable(self): - for name in os.listdir(SCRIPTS_DIR): - if name.endswith('.py'): - path = os.path.join(SCRIPTS_DIR, name) - if not stat.S_IXUSR & os.stat(path)[stat.ST_MODE]: - self.fail('%r is not executable' % path) - - def test_disk_usage(self): - self.assert_stdout('disk_usage.py') - - def test_free(self): - self.assert_stdout('free.py') - - def test_meminfo(self): - self.assert_stdout('meminfo.py') - - def test_procinfo(self): - self.assert_stdout('procinfo.py', str(os.getpid())) - - @unittest.skipIf(CI_TESTING and not psutil.users(), "no users") - def test_who(self): - self.assert_stdout('who.py') - - def test_ps(self): - self.assert_stdout('ps.py') - - def test_pstree(self): - self.assert_stdout('pstree.py') - - def test_netstat(self): - self.assert_stdout('netstat.py') - - # permission denied on travis - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - def test_ifconfig(self): - self.assert_stdout('ifconfig.py') - - @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") - def test_pmap(self): - self.assert_stdout('pmap.py', str(os.getpid())) - - def test_procsmem(self): - if 'uss' not in psutil.Process().memory_full_info()._fields: - raise self.skipTest("not supported") - self.assert_stdout('procsmem.py', stderr=DEVNULL) - - def test_killall(self): - self.assert_syntax('killall.py') - - def test_nettop(self): - self.assert_syntax('nettop.py') - - def test_top(self): - self.assert_syntax('top.py') - - def test_iotop(self): - self.assert_syntax('iotop.py') - - def test_pidof(self): - output = self.assert_stdout('pidof.py', psutil.Process().name()) - self.assertIn(str(os.getpid()), output) - - @unittest.skipIf(not WINDOWS, "WINDOWS only") - def test_winservices(self): - self.assert_stdout('winservices.py') - - def test_cpu_distribution(self): - self.assert_syntax('cpu_distribution.py') - - @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - def test_temperatures(self): - if not psutil.sensors_temperatures(): - self.skipTest("no temperatures") - self.assert_stdout('temperatures.py') - - @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") - def test_fans(self): - if not psutil.sensors_fans(): - self.skipTest("no fans") - self.assert_stdout('fans.py') - - @unittest.skipIf(not HAS_SENSORS_BATTERY, "not supported") - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_battery(self): - self.assert_stdout('battery.py') - - def test_sensors(self): - self.assert_stdout('sensors.py') - - -# =================================================================== -# --- Unit tests for test utilities. -# =================================================================== - - -class TestRetryDecorator(unittest.TestCase): - - @mock.patch('time.sleep') - def test_retry_success(self, sleep): - # Fail 3 times out of 5; make sure the decorated fun returns. - - @retry(retries=5, interval=1, logfun=None) - def foo(): - while queue: - queue.pop() - 1 / 0 - return 1 - - queue = list(range(3)) - self.assertEqual(foo(), 1) - self.assertEqual(sleep.call_count, 3) - - @mock.patch('time.sleep') - def test_retry_failure(self, sleep): - # Fail 6 times out of 5; th function is supposed to raise exc. - - @retry(retries=5, interval=1, logfun=None) - def foo(): - while queue: - queue.pop() - 1 / 0 - return 1 - - queue = list(range(6)) - self.assertRaises(ZeroDivisionError, foo) - self.assertEqual(sleep.call_count, 5) - - @mock.patch('time.sleep') - def test_exception_arg(self, sleep): - @retry(exception=ValueError, interval=1) - def foo(): - raise TypeError - - self.assertRaises(TypeError, foo) - self.assertEqual(sleep.call_count, 0) - - @mock.patch('time.sleep') - def test_no_interval_arg(self, sleep): - # if interval is not specified sleep is not supposed to be called - - @retry(retries=5, interval=None, logfun=None) - def foo(): - 1 / 0 - - self.assertRaises(ZeroDivisionError, foo) - self.assertEqual(sleep.call_count, 0) - - @mock.patch('time.sleep') - def test_retries_arg(self, sleep): - - @retry(retries=5, interval=1, logfun=None) - def foo(): - 1 / 0 - - self.assertRaises(ZeroDivisionError, foo) - self.assertEqual(sleep.call_count, 5) - - @mock.patch('time.sleep') - def test_retries_and_timeout_args(self, sleep): - self.assertRaises(ValueError, retry, retries=5, timeout=1) - - -class TestSyncTestUtils(unittest.TestCase): - - def tearDown(self): - safe_rmpath(TESTFN) - - def test_wait_for_pid(self): - wait_for_pid(os.getpid()) - nopid = max(psutil.pids()) + 99999 - with mock.patch('psutil.tests.retry.__iter__', return_value=iter([0])): - self.assertRaises(psutil.NoSuchProcess, wait_for_pid, nopid) - - def test_wait_for_file(self): - with open(TESTFN, 'w') as f: - f.write('foo') - wait_for_file(TESTFN) - assert not os.path.exists(TESTFN) - - def test_wait_for_file_empty(self): - with open(TESTFN, 'w'): - pass - wait_for_file(TESTFN, empty=True) - assert not os.path.exists(TESTFN) - - def test_wait_for_file_no_file(self): - with mock.patch('psutil.tests.retry.__iter__', return_value=iter([0])): - self.assertRaises(IOError, wait_for_file, TESTFN) - - def test_wait_for_file_no_delete(self): - with open(TESTFN, 'w') as f: - f.write('foo') - wait_for_file(TESTFN, delete=False) - assert os.path.exists(TESTFN) - - def test_call_until(self): - ret = call_until(lambda: 1, "ret == 1") - self.assertEqual(ret, 1) - - -class TestFSTestUtils(unittest.TestCase): - - def setUp(self): - safe_rmpath(TESTFN) - - tearDown = setUp - - def test_open_text(self): - with open_text(__file__) as f: - self.assertEqual(f.mode, 'rt') - - def test_open_binary(self): - with open_binary(__file__) as f: - self.assertEqual(f.mode, 'rb') - - def test_safe_mkdir(self): - safe_mkdir(TESTFN) - assert os.path.isdir(TESTFN) - safe_mkdir(TESTFN) - assert os.path.isdir(TESTFN) - - def test_safe_rmpath(self): - # test file is removed - open(TESTFN, 'w').close() - safe_rmpath(TESTFN) - assert not os.path.exists(TESTFN) - # test no exception if path does not exist - safe_rmpath(TESTFN) - # test dir is removed - os.mkdir(TESTFN) - safe_rmpath(TESTFN) - assert not os.path.exists(TESTFN) - # test other exceptions are raised - with mock.patch('psutil.tests.os.stat', - side_effect=OSError(errno.EINVAL, "")) as m: - with self.assertRaises(OSError): - safe_rmpath(TESTFN) - assert m.called - - def test_chdir(self): - base = os.getcwd() - os.mkdir(TESTFN) - with chdir(TESTFN): - self.assertEqual(os.getcwd(), os.path.join(base, TESTFN)) - self.assertEqual(os.getcwd(), base) - - -class TestProcessUtils(unittest.TestCase): - - def test_reap_children(self): - subp = get_test_subprocess() - p = psutil.Process(subp.pid) - assert p.is_running() - reap_children() - assert not p.is_running() - assert not psutil.tests._pids_started - assert not psutil.tests._subprocesses_started - - def test_create_proc_children_pair(self): - p1, p2 = create_proc_children_pair() - self.assertNotEqual(p1.pid, p2.pid) - assert p1.is_running() - assert p2.is_running() - children = psutil.Process().children(recursive=True) - self.assertEqual(len(children), 2) - self.assertIn(p1, children) - self.assertIn(p2, children) - self.assertEqual(p1.ppid(), os.getpid()) - self.assertEqual(p2.ppid(), p1.pid) - - # make sure both of them are cleaned up - reap_children() - assert not p1.is_running() - assert not p2.is_running() - assert not psutil.tests._pids_started - assert not psutil.tests._subprocesses_started - - @unittest.skipIf(not POSIX, "POSIX only") - def test_create_zombie_proc(self): - zpid = create_zombie_proc() - self.addCleanup(reap_children, recursive=True) - p = psutil.Process(zpid) - self.assertEqual(p.status(), psutil.STATUS_ZOMBIE) - - -class TestNetUtils(unittest.TestCase): - - def bind_socket(self): - port = get_free_port() - with contextlib.closing(bind_socket(addr=('', port))) as s: - self.assertEqual(s.getsockname()[1], port) - - @unittest.skipIf(not POSIX, "POSIX only") - def test_bind_unix_socket(self): - with unix_socket_path() as name: - sock = bind_unix_socket(name) - with contextlib.closing(sock): - self.assertEqual(sock.family, socket.AF_UNIX) - self.assertEqual(sock.type, socket.SOCK_STREAM) - self.assertEqual(sock.getsockname(), name) - assert os.path.exists(name) - assert stat.S_ISSOCK(os.stat(name).st_mode) - # UDP - with unix_socket_path() as name: - sock = bind_unix_socket(name, type=socket.SOCK_DGRAM) - with contextlib.closing(sock): - self.assertEqual(sock.type, socket.SOCK_DGRAM) - - def tcp_tcp_socketpair(self): - addr = ("127.0.0.1", get_free_port()) - server, client = tcp_socketpair(socket.AF_INET, addr=addr) - with contextlib.closing(server): - with contextlib.closing(client): - # Ensure they are connected and the positions are - # correct. - self.assertEqual(server.getsockname(), addr) - self.assertEqual(client.getpeername(), addr) - self.assertNotEqual(client.getsockname(), addr) - - @unittest.skipIf(not POSIX, "POSIX only") - @unittest.skipIf(NETBSD or FREEBSD, - "/var/run/log UNIX socket opened by default") - def test_unix_socketpair(self): - p = psutil.Process() - num_fds = p.num_fds() - assert not p.connections(kind='unix') - with unix_socket_path() as name: - server, client = unix_socketpair(name) - try: - assert os.path.exists(name) - assert stat.S_ISSOCK(os.stat(name).st_mode) - self.assertEqual(p.num_fds() - num_fds, 2) - self.assertEqual(len(p.connections(kind='unix')), 2) - self.assertEqual(server.getsockname(), name) - self.assertEqual(client.getpeername(), name) - finally: - client.close() - server.close() - - def test_create_sockets(self): - with create_sockets() as socks: - fams = collections.defaultdict(int) - types = collections.defaultdict(int) - for s in socks: - fams[s.family] += 1 - # work around http://bugs.python.org/issue30204 - types[s.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)] += 1 - self.assertGreaterEqual(fams[socket.AF_INET], 2) - if supports_ipv6(): - self.assertGreaterEqual(fams[socket.AF_INET6], 2) - if POSIX and HAS_CONNECTIONS_UNIX: - self.assertGreaterEqual(fams[socket.AF_UNIX], 2) - self.assertGreaterEqual(types[socket.SOCK_STREAM], 2) - self.assertGreaterEqual(types[socket.SOCK_DGRAM], 2) - - -class TestOtherUtils(unittest.TestCase): - - def test_is_namedtuple(self): - assert is_namedtuple(collections.namedtuple('foo', 'a b c')(1, 2, 3)) - assert not is_namedtuple(tuple()) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_osx.py b/third_party/python/psutil/psutil/tests/test_osx.py deleted file mode 100755 index e4e77f93537e..000000000000 --- a/third_party/python/psutil/psutil/tests/test_osx.py +++ /dev/null @@ -1,294 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""MACOS specific tests.""" - -import os -import re -import time - -import psutil -from psutil import MACOS -from psutil.tests import create_zombie_proc -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_BATTERY -from psutil.tests import MEMORY_TOLERANCE -from psutil.tests import reap_children -from psutil.tests import retry_on_failure -from psutil.tests import sh -from psutil.tests import unittest - - -PAGESIZE = os.sysconf("SC_PAGE_SIZE") if MACOS else None - - -def sysctl(cmdline): - """Expects a sysctl command with an argument and parse the result - returning only the value of interest. - """ - out = sh(cmdline) - result = out.split()[1] - try: - return int(result) - except ValueError: - return result - - -def vm_stat(field): - """Wrapper around 'vm_stat' cmdline utility.""" - out = sh('vm_stat') - for line in out.split('\n'): - if field in line: - break - else: - raise ValueError("line not found") - return int(re.search(r'\d+', line).group(0)) * PAGESIZE - - -# http://code.activestate.com/recipes/578019/ -def human2bytes(s): - SYMBOLS = { - 'customary': ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'), - } - init = s - num = "" - while s and s[0:1].isdigit() or s[0:1] == '.': - num += s[0] - s = s[1:] - num = float(num) - letter = s.strip() - for name, sset in SYMBOLS.items(): - if letter in sset: - break - else: - if letter == 'k': - sset = SYMBOLS['customary'] - letter = letter.upper() - else: - raise ValueError("can't interpret %r" % init) - prefix = {sset[0]: 1} - for i, s in enumerate(sset[1:]): - prefix[s] = 1 << (i + 1) * 10 - return int(num * prefix[letter]) - - -@unittest.skipIf(not MACOS, "MACOS only") -class TestProcess(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_process_create_time(self): - output = sh("ps -o lstart -p %s" % self.pid) - start_ps = output.replace('STARTED', '').strip() - hhmmss = start_ps.split(' ')[-2] - year = start_ps.split(' ')[-1] - start_psutil = psutil.Process(self.pid).create_time() - self.assertEqual( - hhmmss, - time.strftime("%H:%M:%S", time.localtime(start_psutil))) - self.assertEqual( - year, - time.strftime("%Y", time.localtime(start_psutil))) - - -@unittest.skipIf(not MACOS, "MACOS only") -class TestZombieProcessAPIs(unittest.TestCase): - - @classmethod - def setUpClass(cls): - zpid = create_zombie_proc() - cls.p = psutil.Process(zpid) - - @classmethod - def tearDownClass(cls): - reap_children(recursive=True) - - def test_pidtask_info(self): - self.assertEqual(self.p.status(), psutil.STATUS_ZOMBIE) - self.p.ppid() - self.p.uids() - self.p.gids() - self.p.terminal() - self.p.create_time() - - def test_exe(self): - self.assertRaises(psutil.ZombieProcess, self.p.exe) - - def test_cmdline(self): - self.assertRaises(psutil.ZombieProcess, self.p.cmdline) - - def test_environ(self): - self.assertRaises(psutil.ZombieProcess, self.p.environ) - - def test_cwd(self): - self.assertRaises(psutil.ZombieProcess, self.p.cwd) - - def test_memory_full_info(self): - self.assertRaises(psutil.ZombieProcess, self.p.memory_full_info) - - def test_cpu_times(self): - self.assertRaises(psutil.ZombieProcess, self.p.cpu_times) - - def test_num_ctx_switches(self): - self.assertRaises(psutil.ZombieProcess, self.p.num_ctx_switches) - - def test_num_threads(self): - self.assertRaises(psutil.ZombieProcess, self.p.num_threads) - - def test_open_files(self): - self.assertRaises(psutil.ZombieProcess, self.p.open_files) - - def test_connections(self): - self.assertRaises(psutil.ZombieProcess, self.p.connections) - - def test_num_fds(self): - self.assertRaises(psutil.ZombieProcess, self.p.num_fds) - - def test_threads(self): - self.assertRaises((psutil.ZombieProcess, psutil.AccessDenied), - self.p.threads) - - -@unittest.skipIf(not MACOS, "MACOS only") -class TestSystemAPIs(unittest.TestCase): - - # --- disk - - def test_disks(self): - # test psutil.disk_usage() and psutil.disk_partitions() - # against "df -a" - def df(path): - out = sh('df -k "%s"' % path).strip() - lines = out.split('\n') - lines.pop(0) - line = lines.pop(0) - dev, total, used, free = line.split()[:4] - if dev == 'none': - dev = '' - total = int(total) * 1024 - used = int(used) * 1024 - free = int(free) * 1024 - return dev, total, used, free - - for part in psutil.disk_partitions(all=False): - usage = psutil.disk_usage(part.mountpoint) - dev, total, used, free = df(part.mountpoint) - self.assertEqual(part.device, dev) - self.assertEqual(usage.total, total) - # 10 MB tollerance - if abs(usage.free - free) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % usage.free, free) - if abs(usage.used - used) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % usage.used, used) - - # --- cpu - - def test_cpu_count_logical(self): - num = sysctl("sysctl hw.logicalcpu") - self.assertEqual(num, psutil.cpu_count(logical=True)) - - def test_cpu_count_physical(self): - num = sysctl("sysctl hw.physicalcpu") - self.assertEqual(num, psutil.cpu_count(logical=False)) - - def test_cpu_freq(self): - freq = psutil.cpu_freq() - self.assertEqual( - freq.current * 1000 * 1000, sysctl("sysctl hw.cpufrequency")) - self.assertEqual( - freq.min * 1000 * 1000, sysctl("sysctl hw.cpufrequency_min")) - self.assertEqual( - freq.max * 1000 * 1000, sysctl("sysctl hw.cpufrequency_max")) - - # --- virtual mem - - def test_vmem_total(self): - sysctl_hwphymem = sysctl('sysctl hw.memsize') - self.assertEqual(sysctl_hwphymem, psutil.virtual_memory().total) - - @retry_on_failure() - def test_vmem_free(self): - vmstat_val = vm_stat("free") - psutil_val = psutil.virtual_memory().free - self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_active(self): - vmstat_val = vm_stat("active") - psutil_val = psutil.virtual_memory().active - self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_inactive(self): - vmstat_val = vm_stat("inactive") - psutil_val = psutil.virtual_memory().inactive - self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) - - @retry_on_failure() - def test_vmem_wired(self): - vmstat_val = vm_stat("wired") - psutil_val = psutil.virtual_memory().wired - self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) - - # --- swap mem - - @retry_on_failure() - def test_swapmem_sin(self): - vmstat_val = vm_stat("Pageins") - psutil_val = psutil.swap_memory().sin - self.assertEqual(psutil_val, vmstat_val) - - @retry_on_failure() - def test_swapmem_sout(self): - vmstat_val = vm_stat("Pageout") - psutil_val = psutil.swap_memory().sout - self.assertEqual(psutil_val, vmstat_val) - - # Not very reliable. - # def test_swapmem_total(self): - # out = sh('sysctl vm.swapusage') - # out = out.replace('vm.swapusage: ', '') - # total, used, free = re.findall('\d+.\d+\w', out) - # psutil_smem = psutil.swap_memory() - # self.assertEqual(psutil_smem.total, human2bytes(total)) - # self.assertEqual(psutil_smem.used, human2bytes(used)) - # self.assertEqual(psutil_smem.free, human2bytes(free)) - - # --- network - - def test_net_if_stats(self): - for name, stats in psutil.net_if_stats().items(): - try: - out = sh("ifconfig %s" % name) - except RuntimeError: - pass - else: - self.assertEqual(stats.isup, 'RUNNING' in out, msg=out) - self.assertEqual(stats.mtu, - int(re.findall(r'mtu (\d+)', out)[0])) - - # --- sensors_battery - - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_sensors_battery(self): - out = sh("pmset -g batt") - percent = re.search(r"(\d+)%", out).group(1) - drawing_from = re.search("Now drawing from '([^']+)'", out).group(1) - power_plugged = drawing_from == "AC Power" - psutil_result = psutil.sensors_battery() - self.assertEqual(psutil_result.power_plugged, power_plugged) - self.assertEqual(psutil_result.percent, int(percent)) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_posix.py b/third_party/python/psutil/psutil/tests/test_posix.py deleted file mode 100755 index a96b310ffe7f..000000000000 --- a/third_party/python/psutil/psutil/tests/test_posix.py +++ /dev/null @@ -1,453 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# 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. - -"""POSIX specific tests.""" - -import datetime -import errno -import os -import re -import subprocess -import time - -import psutil -from psutil import AIX -from psutil import BSD -from psutil import LINUX -from psutil import MACOS -from psutil import OPENBSD -from psutil import POSIX -from psutil import SUNOS -from psutil.tests import CI_TESTING -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 -from psutil.tests import retry_on_failure -from psutil.tests import sh -from psutil.tests import skip_on_access_denied -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import wait_for_pid -from psutil.tests import which - - -def ps(fmt, pid=None): - """ - Wrapper for calling the ps command with a little bit of cross-platform - support for a narrow range of features. - """ - - cmd = ['ps'] - - if LINUX: - cmd.append('--no-headers') - - if pid is not None: - cmd.extend(['-p', str(pid)]) - else: - if SUNOS or AIX: - cmd.append('-A') - else: - cmd.append('ax') - - if SUNOS: - fmt_map = set(('command', 'comm', 'start', 'stime')) - fmt = fmt_map.get(fmt, fmt) - - cmd.extend(['-o', fmt]) - - output = sh(cmd) - - if LINUX: - output = output.splitlines() - else: - output = output.splitlines()[1:] - - all_output = [] - for line in output: - line = line.strip() - - try: - line = int(line) - except ValueError: - pass - - all_output.append(line) - - if pid is None: - return all_output - else: - return all_output[0] - -# ps "-o" field names differ wildly between platforms. -# "comm" means "only executable name" but is not available on BSD platforms. -# "args" means "command with all its arguments", and is also not available -# on BSD platforms. -# "command" is like "args" on most platforms, but like "comm" on AIX, -# and not available on SUNOS. -# so for the executable name we can use "comm" on Solaris and split "command" -# on other platforms. -# to get the cmdline (with args) we have to use "args" on AIX and -# Solaris, and can use "command" on all others. - - -def ps_name(pid): - field = "command" - if SUNOS: - field = "comm" - return ps(field, pid).split()[0] - - -def ps_args(pid): - field = "command" - if AIX or SUNOS: - field = "args" - return ps(field, pid) - - -def ps_rss(pid): - field = "rss" - if AIX: - field = "rssize" - return ps(field, pid) - - -def ps_vsz(pid): - field = "vsz" - if AIX: - field = "vsize" - return ps(field, pid) - - -@unittest.skipIf(not POSIX, "POSIX only") -class TestProcess(unittest.TestCase): - """Compare psutil results against 'ps' command line utility (mainly).""" - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess([PYTHON_EXE, "-E", "-O"], - stdin=subprocess.PIPE).pid - wait_for_pid(cls.pid) - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_ppid(self): - ppid_ps = ps('ppid', self.pid) - ppid_psutil = psutil.Process(self.pid).ppid() - self.assertEqual(ppid_ps, ppid_psutil) - - def test_uid(self): - uid_ps = ps('uid', self.pid) - uid_psutil = psutil.Process(self.pid).uids().real - self.assertEqual(uid_ps, uid_psutil) - - def test_gid(self): - gid_ps = ps('rgid', self.pid) - gid_psutil = psutil.Process(self.pid).gids().real - self.assertEqual(gid_ps, gid_psutil) - - def test_username(self): - username_ps = ps('user', self.pid) - username_psutil = psutil.Process(self.pid).username() - self.assertEqual(username_ps, username_psutil) - - def test_username_no_resolution(self): - # Emulate a case where the system can't resolve the uid to - # a username in which case psutil is supposed to return - # the stringified uid. - p = psutil.Process() - with mock.patch("psutil.pwd.getpwuid", side_effect=KeyError) as fun: - self.assertEqual(p.username(), str(p.uids().real)) - assert fun.called - - @skip_on_access_denied() - @retry_on_failure() - def test_rss_memory(self): - # give python interpreter some time to properly initialize - # so that the results are the same - time.sleep(0.1) - rss_ps = ps_rss(self.pid) - rss_psutil = psutil.Process(self.pid).memory_info()[0] / 1024 - self.assertEqual(rss_ps, rss_psutil) - - @skip_on_access_denied() - @retry_on_failure() - def test_vsz_memory(self): - # give python interpreter some time to properly initialize - # so that the results are the same - time.sleep(0.1) - vsz_ps = ps_vsz(self.pid) - vsz_psutil = psutil.Process(self.pid).memory_info()[1] / 1024 - self.assertEqual(vsz_ps, vsz_psutil) - - def test_name(self): - name_ps = ps_name(self.pid) - # remove path if there is any, from the command - name_ps = os.path.basename(name_ps).lower() - name_psutil = psutil.Process(self.pid).name().lower() - # ...because of how we calculate PYTHON_EXE; on MACOS this may - # be "pythonX.Y". - name_ps = re.sub(r"\d.\d", "", name_ps) - name_psutil = re.sub(r"\d.\d", "", name_psutil) - # ...may also be "python.X" - name_ps = re.sub(r"\d", "", name_ps) - name_psutil = re.sub(r"\d", "", name_psutil) - self.assertEqual(name_ps, name_psutil) - - def test_name_long(self): - # On UNIX the kernel truncates the name to the first 15 - # characters. In such a case psutil tries to determine the - # full name from the cmdline. - name = "long-program-name" - cmdline = ["long-program-name-extended", "foo", "bar"] - with mock.patch("psutil._psplatform.Process.name", - return_value=name): - with mock.patch("psutil._psplatform.Process.cmdline", - return_value=cmdline): - p = psutil.Process() - self.assertEqual(p.name(), "long-program-name-extended") - - def test_name_long_cmdline_ad_exc(self): - # Same as above but emulates a case where cmdline() raises - # AccessDenied in which case psutil is supposed to return - # the truncated name instead of crashing. - name = "long-program-name" - with mock.patch("psutil._psplatform.Process.name", - return_value=name): - with mock.patch("psutil._psplatform.Process.cmdline", - side_effect=psutil.AccessDenied(0, "")): - p = psutil.Process() - self.assertEqual(p.name(), "long-program-name") - - def test_name_long_cmdline_nsp_exc(self): - # Same as above but emulates a case where cmdline() raises NSP - # which is supposed to propagate. - name = "long-program-name" - with mock.patch("psutil._psplatform.Process.name", - return_value=name): - with mock.patch("psutil._psplatform.Process.cmdline", - side_effect=psutil.NoSuchProcess(0, "")): - p = psutil.Process() - self.assertRaises(psutil.NoSuchProcess, p.name) - - @unittest.skipIf(MACOS or BSD, 'ps -o start not available') - def test_create_time(self): - time_ps = ps('start', self.pid) - time_psutil = psutil.Process(self.pid).create_time() - time_psutil_tstamp = datetime.datetime.fromtimestamp( - time_psutil).strftime("%H:%M:%S") - # sometimes ps shows the time rounded up instead of down, so we check - # for both possible values - round_time_psutil = round(time_psutil) - round_time_psutil_tstamp = datetime.datetime.fromtimestamp( - round_time_psutil).strftime("%H:%M:%S") - self.assertIn(time_ps, [time_psutil_tstamp, round_time_psutil_tstamp]) - - def test_exe(self): - ps_pathname = ps_name(self.pid) - psutil_pathname = psutil.Process(self.pid).exe() - try: - self.assertEqual(ps_pathname, psutil_pathname) - except AssertionError: - # certain platforms such as BSD are more accurate returning: - # "/usr/local/bin/python2.7" - # ...instead of: - # "/usr/local/bin/python" - # We do not want to consider this difference in accuracy - # an error. - adjusted_ps_pathname = ps_pathname[:len(ps_pathname)] - self.assertEqual(ps_pathname, adjusted_ps_pathname) - - def test_cmdline(self): - ps_cmdline = ps_args(self.pid) - psutil_cmdline = " ".join(psutil.Process(self.pid).cmdline()) - self.assertEqual(ps_cmdline, psutil_cmdline) - - # On SUNOS "ps" reads niceness /proc/pid/psinfo which returns an - # incorrect value (20); the real deal is getpriority(2) which - # returns 0; psutil relies on it, see: - # https://github.com/giampaolo/psutil/issues/1082 - # AIX has the same issue - @unittest.skipIf(SUNOS, "not reliable on SUNOS") - @unittest.skipIf(AIX, "not reliable on AIX") - def test_nice(self): - ps_nice = ps('nice', self.pid) - psutil_nice = psutil.Process().nice() - self.assertEqual(ps_nice, psutil_nice) - - def test_num_fds(self): - # Note: this fails from time to time; I'm keen on thinking - # it doesn't mean something is broken - def call(p, attr): - args = () - attr = getattr(p, name, None) - if attr is not None and callable(attr): - if name == 'rlimit': - args = (psutil.RLIMIT_NOFILE,) - attr(*args) - else: - attr - - p = psutil.Process(os.getpid()) - failures = [] - ignored_names = ['terminate', 'kill', 'suspend', 'resume', 'nice', - 'send_signal', 'wait', 'children', 'as_dict', - 'memory_info_ex', 'parent', 'parents'] - if LINUX and get_kernel_version() < (2, 6, 36): - ignored_names.append('rlimit') - if LINUX and get_kernel_version() < (2, 6, 23): - ignored_names.append('num_ctx_switches') - for name in dir(psutil.Process): - if (name.startswith('_') or name in ignored_names): - continue - else: - try: - num1 = p.num_fds() - for x in range(2): - call(p, name) - num2 = p.num_fds() - except psutil.AccessDenied: - pass - else: - if abs(num2 - num1) > 1: - fail = "failure while processing Process.%s method " \ - "(before=%s, after=%s)" % (name, num1, num2) - failures.append(fail) - if failures: - self.fail('\n' + '\n'.join(failures)) - - -@unittest.skipIf(not POSIX, "POSIX only") -class TestSystemAPIs(unittest.TestCase): - """Test some system APIs.""" - - @retry_on_failure() - def test_pids(self): - # Note: this test might fail if the OS is starting/killing - # other processes in the meantime - pids_ps = sorted(ps("pid")) - pids_psutil = psutil.pids() - - # on MACOS and OPENBSD ps doesn't show pid 0 - if MACOS or OPENBSD and 0 not in pids_ps: - pids_ps.insert(0, 0) - - # There will often be one more process in pids_ps for ps itself - if len(pids_ps) - len(pids_psutil) > 1: - difference = [x for x in pids_psutil if x not in pids_ps] + \ - [x for x in pids_ps if x not in pids_psutil] - self.fail("difference: " + str(difference)) - - # for some reason ifconfig -a does not report all interfaces - # returned by psutil - @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(): - for line in output.split(): - if line.startswith(nic): - break - else: - self.fail( - "couldn't find %s nic in 'ifconfig -a' output\n%s" % ( - nic, output)) - - @unittest.skipIf(CI_TESTING and not psutil.users(), "unreliable on CI") - @retry_on_failure() - def test_users(self): - out = sh("who") - lines = out.split('\n') - if not lines: - raise self.skipTest("no users on this system") - users = [x.split()[0] for x in lines] - terminals = [x.split()[1] for x in lines] - self.assertEqual(len(users), len(psutil.users())) - for u in psutil.users(): - self.assertIn(u.name, users) - self.assertIn(u.terminal, terminals) - - def test_pid_exists_let_raise(self): - # According to "man 2 kill" possible error values for kill - # are (EINVAL, EPERM, ESRCH). Test that any other errno - # results in an exception. - with mock.patch("psutil._psposix.os.kill", - side_effect=OSError(errno.EBADF, "")) as m: - self.assertRaises(OSError, psutil._psposix.pid_exists, os.getpid()) - assert m.called - - def test_os_waitpid_let_raise(self): - # os.waitpid() is supposed to catch EINTR and ECHILD only. - # Test that any other errno results in an exception. - with mock.patch("psutil._psposix.os.waitpid", - side_effect=OSError(errno.EBADF, "")) as m: - self.assertRaises(OSError, psutil._psposix.wait_pid, os.getpid()) - assert m.called - - def test_os_waitpid_eintr(self): - # os.waitpid() is supposed to "retry" on EINTR. - with mock.patch("psutil._psposix.os.waitpid", - side_effect=OSError(errno.EINTR, "")) as m: - self.assertRaises( - psutil._psposix.TimeoutExpired, - psutil._psposix.wait_pid, os.getpid(), timeout=0.01) - assert m.called - - def test_os_waitpid_bad_ret_status(self): - # Simulate os.waitpid() returning a bad status. - with mock.patch("psutil._psposix.os.waitpid", - return_value=(1, -1)) as m: - self.assertRaises(ValueError, - psutil._psposix.wait_pid, os.getpid()) - assert m.called - - # AIX can return '-' in df output instead of numbers, e.g. for /proc - @unittest.skipIf(AIX, "unreliable on AIX") - def test_disk_usage(self): - def df(device): - out = sh("df -k %s" % device).strip() - line = out.split('\n')[1] - fields = line.split() - total = int(fields[1]) * 1024 - used = int(fields[2]) * 1024 - free = int(fields[3]) * 1024 - percent = float(fields[4].replace('%', '')) - return (total, used, free, percent) - - tolerance = 4 * 1024 * 1024 # 4MB - for part in psutil.disk_partitions(all=False): - usage = psutil.disk_usage(part.mountpoint) - try: - total, used, free, percent = df(part.device) - except RuntimeError as err: - # see: - # https://travis-ci.org/giampaolo/psutil/jobs/138338464 - # https://travis-ci.org/giampaolo/psutil/jobs/138343361 - err = str(err).lower() - if "no such file or directory" in err or \ - "raw devices not supported" in err or \ - "permission denied" in err: - continue - else: - raise - else: - self.assertAlmostEqual(usage.total, total, delta=tolerance) - self.assertAlmostEqual(usage.used, used, delta=tolerance) - self.assertAlmostEqual(usage.free, free, delta=tolerance) - self.assertAlmostEqual(usage.percent, percent, delta=1) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_process.py b/third_party/python/psutil/psutil/tests/test_process.py deleted file mode 100755 index 987bdf38bb69..000000000000 --- a/third_party/python/psutil/psutil/tests/test_process.py +++ /dev/null @@ -1,1643 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Tests for psutil.Process class.""" - -import collections -import errno -import getpass -import itertools -import os -import signal -import socket -import subprocess -import sys -import tempfile -import textwrap -import time -import types - -import psutil - -from psutil import AIX -from psutil import BSD -from psutil import LINUX -from psutil import MACOS -from psutil import NETBSD -from psutil import OPENBSD -from psutil import OSX -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -from psutil._common import open_text -from psutil._compat import long -from psutil._compat import PY3 -from psutil.tests import APPVEYOR -from psutil.tests import call_until -from psutil.tests import CIRRUS -from psutil.tests import copyload_shared_lib -from psutil.tests import create_exe -from psutil.tests import create_proc_children_pair -from psutil.tests import create_zombie_proc -from psutil.tests import enum -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_CPU_AFFINITY -from psutil.tests import HAS_ENVIRON -from psutil.tests import HAS_IONICE -from psutil.tests import HAS_MEMORY_MAPS -from psutil.tests import HAS_PROC_CPU_NUM -from psutil.tests import HAS_PROC_IO_COUNTERS -from psutil.tests import HAS_RLIMIT -from psutil.tests import HAS_THREADS -from psutil.tests import mock -from psutil.tests import PYPY -from psutil.tests import PYTHON_EXE -from psutil.tests import reap_children -from psutil.tests import retry_on_failure -from psutil.tests import safe_rmpath -from psutil.tests import sh -from psutil.tests import skip_on_access_denied -from psutil.tests import skip_on_not_implemented -from psutil.tests import TESTFILE_PREFIX -from psutil.tests import TESTFN -from psutil.tests import ThreadTask -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import wait_for_pid - - -# =================================================================== -# --- psutil.Process class tests -# =================================================================== - -class TestProcess(unittest.TestCase): - """Tests for psutil.Process class.""" - - def setUp(self): - safe_rmpath(TESTFN) - - def tearDown(self): - reap_children() - - def test_pid(self): - p = psutil.Process() - self.assertEqual(p.pid, os.getpid()) - sproc = get_test_subprocess() - self.assertEqual(psutil.Process(sproc.pid).pid, sproc.pid) - with self.assertRaises(AttributeError): - p.pid = 33 - - def test_kill(self): - sproc = get_test_subprocess() - test_pid = sproc.pid - p = psutil.Process(test_pid) - p.kill() - sig = p.wait() - self.assertFalse(psutil.pid_exists(test_pid)) - if POSIX: - self.assertEqual(sig, -signal.SIGKILL) - - def test_terminate(self): - sproc = get_test_subprocess() - test_pid = sproc.pid - p = psutil.Process(test_pid) - p.terminate() - sig = p.wait() - self.assertFalse(psutil.pid_exists(test_pid)) - if POSIX: - self.assertEqual(sig, -signal.SIGTERM) - - def test_send_signal(self): - sig = signal.SIGKILL if POSIX else signal.SIGTERM - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.send_signal(sig) - exit_sig = p.wait() - self.assertFalse(psutil.pid_exists(p.pid)) - if POSIX: - self.assertEqual(exit_sig, -sig) - # - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.send_signal(sig) - with mock.patch('psutil.os.kill', - side_effect=OSError(errno.ESRCH, "")): - with self.assertRaises(psutil.NoSuchProcess): - p.send_signal(sig) - # - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.send_signal(sig) - with mock.patch('psutil.os.kill', - side_effect=OSError(errno.EPERM, "")): - with self.assertRaises(psutil.AccessDenied): - psutil.Process().send_signal(sig) - # Sending a signal to process with PID 0 is not allowed as - # it would affect every process in the process group of - # the calling process (os.getpid()) instead of PID 0"). - if 0 in psutil.pids(): - p = psutil.Process(0) - self.assertRaises(ValueError, p.send_signal, signal.SIGTERM) - - def test_wait(self): - # check exit code signal - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.kill() - code = p.wait() - if POSIX: - self.assertEqual(code, -signal.SIGKILL) - else: - self.assertEqual(code, signal.SIGTERM) - self.assertFalse(p.is_running()) - - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.terminate() - code = p.wait() - if POSIX: - self.assertEqual(code, -signal.SIGTERM) - else: - self.assertEqual(code, signal.SIGTERM) - self.assertFalse(p.is_running()) - - # check sys.exit() code - code = "import time, sys; time.sleep(0.01); sys.exit(5);" - sproc = get_test_subprocess([PYTHON_EXE, "-c", code]) - p = psutil.Process(sproc.pid) - self.assertEqual(p.wait(), 5) - self.assertFalse(p.is_running()) - - # Test wait() issued twice. - # It is not supposed to raise NSP when the process is gone. - # On UNIX this should return None, on Windows it should keep - # returning the exit code. - sproc = get_test_subprocess([PYTHON_EXE, "-c", code]) - p = psutil.Process(sproc.pid) - self.assertEqual(p.wait(), 5) - self.assertIn(p.wait(), (5, None)) - - # test timeout - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.name() - self.assertRaises(psutil.TimeoutExpired, p.wait, 0.01) - - # timeout < 0 not allowed - self.assertRaises(ValueError, p.wait, -1) - - def test_wait_non_children(self): - # Test wait() against a process which is not our direct - # child. - p1, p2 = create_proc_children_pair() - self.assertRaises(psutil.TimeoutExpired, p1.wait, 0.01) - self.assertRaises(psutil.TimeoutExpired, p2.wait, 0.01) - # We also terminate the direct child otherwise the - # grandchild will hang until the parent is gone. - p1.terminate() - p2.terminate() - ret1 = p1.wait() - ret2 = p2.wait() - if POSIX: - self.assertEqual(ret1, -signal.SIGTERM) - # For processes which are not our children we're supposed - # to get None. - self.assertEqual(ret2, None) - else: - self.assertEqual(ret1, signal.SIGTERM) - self.assertEqual(ret1, signal.SIGTERM) - - def test_wait_timeout_0(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - self.assertRaises(psutil.TimeoutExpired, p.wait, 0) - p.kill() - stop_at = time.time() + 2 - while True: - try: - code = p.wait(0) - except psutil.TimeoutExpired: - if time.time() >= stop_at: - raise - else: - break - if POSIX: - self.assertEqual(code, -signal.SIGKILL) - else: - self.assertEqual(code, signal.SIGTERM) - self.assertFalse(p.is_running()) - - def test_cpu_percent(self): - p = psutil.Process() - p.cpu_percent(interval=0.001) - p.cpu_percent(interval=0.001) - for x in range(100): - percent = p.cpu_percent(interval=None) - self.assertIsInstance(percent, float) - self.assertGreaterEqual(percent, 0.0) - with self.assertRaises(ValueError): - p.cpu_percent(interval=-1) - - def test_cpu_percent_numcpus_none(self): - # See: https://github.com/giampaolo/psutil/issues/1087 - with mock.patch('psutil.cpu_count', return_value=None) as m: - psutil.Process().cpu_percent() - assert m.called - - def test_cpu_times(self): - times = psutil.Process().cpu_times() - assert (times.user > 0.0) or (times.system > 0.0), times - assert (times.children_user >= 0.0), times - assert (times.children_system >= 0.0), times - if LINUX: - assert times.iowait >= 0.0, times - # make sure returned values can be pretty printed with strftime - for name in times._fields: - time.strftime("%H:%M:%S", time.localtime(getattr(times, name))) - - def test_cpu_times_2(self): - user_time, kernel_time = psutil.Process().cpu_times()[:2] - utime, ktime = os.times()[:2] - - # Use os.times()[:2] as base values to compare our results - # using a tolerance of +/- 0.1 seconds. - # It will fail if the difference between the values is > 0.1s. - if (max([user_time, utime]) - min([user_time, utime])) > 0.1: - self.fail("expected: %s, found: %s" % (utime, user_time)) - - if (max([kernel_time, ktime]) - min([kernel_time, ktime])) > 0.1: - self.fail("expected: %s, found: %s" % (ktime, kernel_time)) - - @unittest.skipIf(not HAS_PROC_CPU_NUM, "not supported") - def test_cpu_num(self): - p = psutil.Process() - num = p.cpu_num() - self.assertGreaterEqual(num, 0) - if psutil.cpu_count() == 1: - self.assertEqual(num, 0) - self.assertIn(p.cpu_num(), range(psutil.cpu_count())) - - def test_create_time(self): - sproc = get_test_subprocess() - now = time.time() - p = psutil.Process(sproc.pid) - create_time = p.create_time() - - # Use time.time() as base value to compare our result using a - # tolerance of +/- 1 second. - # It will fail if the difference between the values is > 2s. - difference = abs(create_time - now) - if difference > 2: - self.fail("expected: %s, found: %s, difference: %s" - % (now, create_time, difference)) - - # make sure returned value can be pretty printed with strftime - time.strftime("%Y %m %d %H:%M:%S", time.localtime(p.create_time())) - - @unittest.skipIf(not POSIX, 'POSIX only') - @unittest.skipIf(TRAVIS or CIRRUS, 'not reliable on TRAVIS/CIRRUS') - def test_terminal(self): - terminal = psutil.Process().terminal() - if sys.stdin.isatty() or sys.stdout.isatty(): - tty = os.path.realpath(sh('tty')) - self.assertEqual(terminal, tty) - else: - self.assertIsNone(terminal) - - @unittest.skipIf(not HAS_PROC_IO_COUNTERS, 'not supported') - @skip_on_not_implemented(only_if=LINUX) - def test_io_counters(self): - p = psutil.Process() - # test reads - io1 = p.io_counters() - with open(PYTHON_EXE, 'rb') as f: - f.read() - io2 = p.io_counters() - if not BSD and not AIX: - self.assertGreater(io2.read_count, io1.read_count) - self.assertEqual(io2.write_count, io1.write_count) - if LINUX: - self.assertGreater(io2.read_chars, io1.read_chars) - self.assertEqual(io2.write_chars, io1.write_chars) - else: - self.assertGreaterEqual(io2.read_bytes, io1.read_bytes) - self.assertGreaterEqual(io2.write_bytes, io1.write_bytes) - - # test writes - io1 = p.io_counters() - with tempfile.TemporaryFile(prefix=TESTFILE_PREFIX) as f: - if PY3: - f.write(bytes("x" * 1000000, 'ascii')) - else: - f.write("x" * 1000000) - io2 = p.io_counters() - self.assertGreaterEqual(io2.write_count, io1.write_count) - self.assertGreaterEqual(io2.write_bytes, io1.write_bytes) - self.assertGreaterEqual(io2.read_count, io1.read_count) - self.assertGreaterEqual(io2.read_bytes, io1.read_bytes) - if LINUX: - self.assertGreater(io2.write_chars, io1.write_chars) - self.assertGreaterEqual(io2.read_chars, io1.read_chars) - - # sanity check - for i in range(len(io2)): - if BSD and i >= 2: - # On BSD read_bytes and write_bytes are always set to -1. - continue - self.assertGreaterEqual(io2[i], 0) - self.assertGreaterEqual(io2[i], 0) - - @unittest.skipIf(not HAS_IONICE, "not supported") - @unittest.skipIf(not LINUX, "linux only") - def test_ionice_linux(self): - p = psutil.Process() - self.assertEqual(p.ionice()[0], psutil.IOPRIO_CLASS_NONE) - self.assertEqual(psutil.IOPRIO_CLASS_NONE, 0) - self.assertEqual(psutil.IOPRIO_CLASS_RT, 1) # high - self.assertEqual(psutil.IOPRIO_CLASS_BE, 2) # normal - self.assertEqual(psutil.IOPRIO_CLASS_IDLE, 3) # low - try: - # low - p.ionice(psutil.IOPRIO_CLASS_IDLE) - self.assertEqual(tuple(p.ionice()), (psutil.IOPRIO_CLASS_IDLE, 0)) - with self.assertRaises(ValueError): # accepts no value - p.ionice(psutil.IOPRIO_CLASS_IDLE, value=7) - # normal - p.ionice(psutil.IOPRIO_CLASS_BE) - self.assertEqual(tuple(p.ionice()), (psutil.IOPRIO_CLASS_BE, 0)) - p.ionice(psutil.IOPRIO_CLASS_BE, value=7) - self.assertEqual(tuple(p.ionice()), (psutil.IOPRIO_CLASS_BE, 7)) - with self.assertRaises(ValueError): - p.ionice(psutil.IOPRIO_CLASS_BE, value=8) - # high - if os.getuid() == 0: # root - p.ionice(psutil.IOPRIO_CLASS_RT) - self.assertEqual(tuple(p.ionice()), - (psutil.IOPRIO_CLASS_RT, 0)) - p.ionice(psutil.IOPRIO_CLASS_RT, value=7) - self.assertEqual(tuple(p.ionice()), - (psutil.IOPRIO_CLASS_RT, 7)) - with self.assertRaises(ValueError): - p.ionice(psutil.IOPRIO_CLASS_IDLE, value=8) - # errs - self.assertRaisesRegex( - ValueError, "ioclass accepts no value", - p.ionice, psutil.IOPRIO_CLASS_NONE, 1) - self.assertRaisesRegex( - ValueError, "ioclass accepts no value", - p.ionice, psutil.IOPRIO_CLASS_IDLE, 1) - self.assertRaisesRegex( - ValueError, "'ioclass' argument must be specified", - p.ionice, value=1) - finally: - p.ionice(psutil.IOPRIO_CLASS_BE) - - @unittest.skipIf(not HAS_IONICE, "not supported") - @unittest.skipIf(not WINDOWS, 'not supported on this win version') - def test_ionice_win(self): - p = psutil.Process() - self.assertEqual(p.ionice(), psutil.IOPRIO_NORMAL) - try: - # base - p.ionice(psutil.IOPRIO_VERYLOW) - self.assertEqual(p.ionice(), psutil.IOPRIO_VERYLOW) - p.ionice(psutil.IOPRIO_LOW) - self.assertEqual(p.ionice(), psutil.IOPRIO_LOW) - try: - p.ionice(psutil.IOPRIO_HIGH) - except psutil.AccessDenied: - pass - else: - self.assertEqual(p.ionice(), psutil.IOPRIO_HIGH) - # errs - self.assertRaisesRegex( - TypeError, "value argument not accepted on Windows", - p.ionice, psutil.IOPRIO_NORMAL, value=1) - self.assertRaisesRegex( - ValueError, "is not a valid priority", - p.ionice, psutil.IOPRIO_HIGH + 1) - finally: - p.ionice(psutil.IOPRIO_NORMAL) - self.assertEqual(p.ionice(), psutil.IOPRIO_NORMAL) - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_get(self): - import resource - p = psutil.Process(os.getpid()) - names = [x for x in dir(psutil) if x.startswith('RLIMIT')] - assert names, names - for name in names: - value = getattr(psutil, name) - self.assertGreaterEqual(value, 0) - if name in dir(resource): - self.assertEqual(value, getattr(resource, name)) - # XXX - On PyPy RLIMIT_INFINITY returned by - # resource.getrlimit() is reported as a very big long - # number instead of -1. It looks like a bug with PyPy. - if PYPY: - continue - self.assertEqual(p.rlimit(value), resource.getrlimit(value)) - else: - ret = p.rlimit(value) - self.assertEqual(len(ret), 2) - self.assertGreaterEqual(ret[0], -1) - self.assertGreaterEqual(ret[1], -1) - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_set(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) - self.assertEqual(p.rlimit(psutil.RLIMIT_NOFILE), (5, 5)) - # If pid is 0 prlimit() applies to the calling process and - # we don't want that. - with self.assertRaises(ValueError): - psutil._psplatform.Process(0).rlimit(0) - with self.assertRaises(ValueError): - p.rlimit(psutil.RLIMIT_NOFILE, (5, 5, 5)) - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit(self): - p = psutil.Process() - soft, hard = p.rlimit(psutil.RLIMIT_FSIZE) - try: - p.rlimit(psutil.RLIMIT_FSIZE, (1024, hard)) - with open(TESTFN, "wb") as f: - f.write(b"X" * 1024) - # write() or flush() doesn't always cause the exception - # but close() will. - with self.assertRaises(IOError) as exc: - with open(TESTFN, "wb") as f: - f.write(b"X" * 1025) - self.assertEqual(exc.exception.errno if PY3 else exc.exception[0], - errno.EFBIG) - finally: - p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard)) - self.assertEqual(p.rlimit(psutil.RLIMIT_FSIZE), (soft, hard)) - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_infinity(self): - # First set a limit, then re-set it by specifying INFINITY - # and assume we overridden the previous limit. - p = psutil.Process() - soft, hard = p.rlimit(psutil.RLIMIT_FSIZE) - try: - p.rlimit(psutil.RLIMIT_FSIZE, (1024, hard)) - p.rlimit(psutil.RLIMIT_FSIZE, (psutil.RLIM_INFINITY, hard)) - with open(TESTFN, "wb") as f: - f.write(b"X" * 2048) - finally: - p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard)) - self.assertEqual(p.rlimit(psutil.RLIMIT_FSIZE), (soft, hard)) - - @unittest.skipIf(not HAS_RLIMIT, "not supported") - def test_rlimit_infinity_value(self): - # RLIMIT_FSIZE should be RLIM_INFINITY, which will be a really - # big number on a platform with large file support. On these - # platforms we need to test that the get/setrlimit functions - # properly convert the number to a C long long and that the - # conversion doesn't raise an error. - p = psutil.Process() - soft, hard = p.rlimit(psutil.RLIMIT_FSIZE) - self.assertEqual(psutil.RLIM_INFINITY, hard) - p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard)) - - def test_num_threads(self): - # on certain platforms such as Linux we might test for exact - # thread number, since we always have with 1 thread per process, - # but this does not apply across all platforms (MACOS, Windows) - p = psutil.Process() - if OPENBSD: - try: - step1 = p.num_threads() - except psutil.AccessDenied: - raise unittest.SkipTest("on OpenBSD this requires root access") - else: - step1 = p.num_threads() - - with ThreadTask(): - step2 = p.num_threads() - self.assertEqual(step2, step1 + 1) - - @unittest.skipIf(not WINDOWS, 'WINDOWS only') - def test_num_handles(self): - # a better test is done later into test/_windows.py - p = psutil.Process() - self.assertGreater(p.num_handles(), 0) - - @unittest.skipIf(not HAS_THREADS, 'not supported') - def test_threads(self): - p = psutil.Process() - if OPENBSD: - try: - step1 = p.threads() - except psutil.AccessDenied: - raise unittest.SkipTest("on OpenBSD this requires root access") - else: - step1 = p.threads() - - with ThreadTask(): - step2 = p.threads() - self.assertEqual(len(step2), len(step1) + 1) - athread = step2[0] - # test named tuple - self.assertEqual(athread.id, athread[0]) - self.assertEqual(athread.user_time, athread[1]) - self.assertEqual(athread.system_time, athread[2]) - - @retry_on_failure() - @skip_on_access_denied(only_if=MACOS) - @unittest.skipIf(not HAS_THREADS, 'not supported') - def test_threads_2(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - if OPENBSD: - try: - p.threads() - except psutil.AccessDenied: - raise unittest.SkipTest( - "on OpenBSD this requires root access") - self.assertAlmostEqual( - p.cpu_times().user, - sum([x.user_time for x in p.threads()]), delta=0.1) - self.assertAlmostEqual( - p.cpu_times().system, - sum([x.system_time for x in p.threads()]), delta=0.1) - - def test_memory_info(self): - p = psutil.Process() - - # step 1 - get a base value to compare our results - rss1, vms1 = p.memory_info()[:2] - percent1 = p.memory_percent() - self.assertGreater(rss1, 0) - self.assertGreater(vms1, 0) - - # step 2 - allocate some memory - memarr = [None] * 1500000 - - rss2, vms2 = p.memory_info()[:2] - percent2 = p.memory_percent() - - # step 3 - make sure that the memory usage bumped up - self.assertGreater(rss2, rss1) - self.assertGreaterEqual(vms2, vms1) # vms might be equal - self.assertGreater(percent2, percent1) - del memarr - - if WINDOWS: - mem = p.memory_info() - self.assertEqual(mem.rss, mem.wset) - self.assertEqual(mem.vms, mem.pagefile) - - mem = p.memory_info() - for name in mem._fields: - self.assertGreaterEqual(getattr(mem, name), 0) - - def test_memory_full_info(self): - total = psutil.virtual_memory().total - mem = psutil.Process().memory_full_info() - for name in mem._fields: - value = getattr(mem, name) - self.assertGreaterEqual(value, 0, msg=(name, value)) - if name == 'vms' and OSX or LINUX: - continue - self.assertLessEqual(value, total, msg=(name, value, total)) - if LINUX or WINDOWS or MACOS: - self.assertGreaterEqual(mem.uss, 0) - if LINUX: - self.assertGreaterEqual(mem.pss, 0) - self.assertGreaterEqual(mem.swap, 0) - - @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") - def test_memory_maps(self): - p = psutil.Process() - maps = p.memory_maps() - paths = [x for x in maps] - self.assertEqual(len(paths), len(set(paths))) - ext_maps = p.memory_maps(grouped=False) - - for nt in maps: - if not nt.path.startswith('['): - assert os.path.isabs(nt.path), nt.path - if POSIX: - try: - assert os.path.exists(nt.path) or \ - os.path.islink(nt.path), nt.path - except AssertionError: - if not LINUX: - raise - else: - # https://github.com/giampaolo/psutil/issues/759 - with open_text('/proc/self/smaps') as f: - data = f.read() - if "%s (deleted)" % nt.path not in data: - raise - else: - # XXX - On Windows we have this strange behavior with - # 64 bit dlls: they are visible via explorer but cannot - # be accessed via os.stat() (wtf?). - if '64' not in os.path.basename(nt.path): - assert os.path.exists(nt.path), nt.path - for nt in ext_maps: - for fname in nt._fields: - value = getattr(nt, fname) - if fname == 'path': - continue - elif fname in ('addr', 'perms'): - assert value, value - else: - self.assertIsInstance(value, (int, long)) - assert value >= 0, value - - @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") - def test_memory_maps_lists_lib(self): - # Make sure a newly loaded shared lib is listed. - with copyload_shared_lib() as path: - def normpath(p): - return os.path.realpath(os.path.normcase(p)) - libpaths = [normpath(x.path) - for x in psutil.Process().memory_maps()] - self.assertIn(normpath(path), libpaths) - - def test_memory_percent(self): - p = psutil.Process() - p.memory_percent() - self.assertRaises(ValueError, p.memory_percent, memtype="?!?") - if LINUX or MACOS or WINDOWS: - p.memory_percent(memtype='uss') - - def test_is_running(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - assert p.is_running() - assert p.is_running() - p.kill() - p.wait() - assert not p.is_running() - assert not p.is_running() - - def test_exe(self): - sproc = get_test_subprocess() - exe = psutil.Process(sproc.pid).exe() - try: - self.assertEqual(exe, PYTHON_EXE) - except AssertionError: - if WINDOWS and len(exe) == len(PYTHON_EXE): - # on Windows we don't care about case sensitivity - normcase = os.path.normcase - self.assertEqual(normcase(exe), normcase(PYTHON_EXE)) - else: - # certain platforms such as BSD are more accurate returning: - # "/usr/local/bin/python2.7" - # ...instead of: - # "/usr/local/bin/python" - # We do not want to consider this difference in accuracy - # an error. - ver = "%s.%s" % (sys.version_info[0], sys.version_info[1]) - try: - self.assertEqual(exe.replace(ver, ''), - PYTHON_EXE.replace(ver, '')) - except AssertionError: - # Tipically MACOS. Really not sure what to do here. - pass - - out = sh([exe, "-c", "import os; print('hey')"]) - self.assertEqual(out, 'hey') - - def test_cmdline(self): - cmdline = [PYTHON_EXE, "-c", "import time; time.sleep(60)"] - sproc = get_test_subprocess(cmdline) - try: - self.assertEqual(' '.join(psutil.Process(sproc.pid).cmdline()), - ' '.join(cmdline)) - except AssertionError: - # XXX - most of the times the underlying sysctl() call on Net - # and Open BSD returns a truncated string. - # Also /proc/pid/cmdline behaves the same so it looks - # like this is a kernel bug. - # XXX - AIX truncates long arguments in /proc/pid/cmdline - if NETBSD or OPENBSD or AIX: - self.assertEqual( - psutil.Process(sproc.pid).cmdline()[0], PYTHON_EXE) - else: - raise - - @unittest.skipIf(PYPY, "broken on PYPY") - def test_long_cmdline(self): - create_exe(TESTFN) - self.addCleanup(safe_rmpath, TESTFN) - cmdline = [TESTFN] + (["0123456789"] * 20) - sproc = get_test_subprocess(cmdline) - p = psutil.Process(sproc.pid) - self.assertEqual(p.cmdline(), cmdline) - - def test_name(self): - sproc = get_test_subprocess(PYTHON_EXE) - name = psutil.Process(sproc.pid).name().lower() - pyexe = os.path.basename(os.path.realpath(sys.executable)).lower() - assert pyexe.startswith(name), (pyexe, name) - - @unittest.skipIf(PYPY, "unreliable on PYPY") - def test_long_name(self): - long_name = TESTFN + ("0123456789" * 2) - create_exe(long_name) - self.addCleanup(safe_rmpath, long_name) - sproc = get_test_subprocess(long_name) - p = psutil.Process(sproc.pid) - self.assertEqual(p.name(), os.path.basename(long_name)) - - # XXX - @unittest.skipIf(SUNOS, "broken on SUNOS") - @unittest.skipIf(AIX, "broken on AIX") - @unittest.skipIf(PYPY, "broken on PYPY") - def test_prog_w_funky_name(self): - # Test that name(), exe() and cmdline() correctly handle programs - # with funky chars such as spaces and ")", see: - # https://github.com/giampaolo/psutil/issues/628 - - def rm(): - # Try to limit occasional failures on Appveyor: - # https://ci.appveyor.com/project/giampaolo/psutil/build/1350/ - # job/lbo3bkju55le850n - try: - safe_rmpath(funky_path) - except OSError: - pass - - funky_path = TESTFN + 'foo bar )' - create_exe(funky_path) - self.addCleanup(rm) - cmdline = [funky_path, "-c", - "import time; [time.sleep(0.01) for x in range(3000)];" - "arg1", "arg2", "", "arg3", ""] - sproc = get_test_subprocess(cmdline) - p = psutil.Process(sproc.pid) - # ...in order to try to prevent occasional failures on travis - if TRAVIS: - wait_for_pid(p.pid) - self.assertEqual(p.cmdline(), cmdline) - self.assertEqual(p.name(), os.path.basename(funky_path)) - self.assertEqual(os.path.normcase(p.exe()), - os.path.normcase(funky_path)) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_uids(self): - p = psutil.Process() - real, effective, saved = p.uids() - # os.getuid() refers to "real" uid - self.assertEqual(real, os.getuid()) - # os.geteuid() refers to "effective" uid - self.assertEqual(effective, os.geteuid()) - # No such thing as os.getsuid() ("saved" uid), but starting - # from python 2.7 we have os.getresuid() which returns all - # of them. - if hasattr(os, "getresuid"): - self.assertEqual(os.getresuid(), p.uids()) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_gids(self): - p = psutil.Process() - real, effective, saved = p.gids() - # os.getuid() refers to "real" uid - self.assertEqual(real, os.getgid()) - # os.geteuid() refers to "effective" uid - self.assertEqual(effective, os.getegid()) - # No such thing as os.getsgid() ("saved" gid), but starting - # from python 2.7 we have os.getresgid() which returns all - # of them. - if hasattr(os, "getresuid"): - self.assertEqual(os.getresgid(), p.gids()) - - def test_nice(self): - p = psutil.Process() - self.assertRaises(TypeError, p.nice, "str") - if WINDOWS: - try: - init = p.nice() - if sys.version_info > (3, 4): - self.assertIsInstance(init, enum.IntEnum) - else: - self.assertIsInstance(init, int) - self.assertEqual(init, psutil.NORMAL_PRIORITY_CLASS) - p.nice(psutil.HIGH_PRIORITY_CLASS) - self.assertEqual(p.nice(), psutil.HIGH_PRIORITY_CLASS) - p.nice(psutil.NORMAL_PRIORITY_CLASS) - self.assertEqual(p.nice(), psutil.NORMAL_PRIORITY_CLASS) - finally: - p.nice(psutil.NORMAL_PRIORITY_CLASS) - else: - first_nice = p.nice() - try: - if hasattr(os, "getpriority"): - self.assertEqual( - os.getpriority(os.PRIO_PROCESS, os.getpid()), p.nice()) - p.nice(1) - self.assertEqual(p.nice(), 1) - if hasattr(os, "getpriority"): - self.assertEqual( - os.getpriority(os.PRIO_PROCESS, os.getpid()), p.nice()) - # XXX - going back to previous nice value raises - # AccessDenied on MACOS - if not MACOS: - p.nice(0) - self.assertEqual(p.nice(), 0) - except psutil.AccessDenied: - pass - finally: - try: - p.nice(first_nice) - except psutil.AccessDenied: - pass - - def test_status(self): - p = psutil.Process() - self.assertEqual(p.status(), psutil.STATUS_RUNNING) - - def test_username(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - username = p.username() - if WINDOWS: - domain, username = username.split('\\') - self.assertEqual(username, getpass.getuser()) - if 'USERDOMAIN' in os.environ: - self.assertEqual(domain, os.environ['USERDOMAIN']) - else: - self.assertEqual(username, getpass.getuser()) - - def test_cwd(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - self.assertEqual(p.cwd(), os.getcwd()) - - def test_cwd_2(self): - cmd = [PYTHON_EXE, "-c", - "import os, time; os.chdir('..'); time.sleep(60)"] - sproc = get_test_subprocess(cmd) - p = psutil.Process(sproc.pid) - call_until(p.cwd, "ret == os.path.dirname(os.getcwd())") - - @unittest.skipIf(not HAS_CPU_AFFINITY, 'not supported') - def test_cpu_affinity(self): - p = psutil.Process() - initial = p.cpu_affinity() - assert initial, initial - self.addCleanup(p.cpu_affinity, initial) - - if hasattr(os, "sched_getaffinity"): - self.assertEqual(initial, list(os.sched_getaffinity(p.pid))) - self.assertEqual(len(initial), len(set(initial))) - - all_cpus = list(range(len(psutil.cpu_percent(percpu=True)))) - # Work around travis failure: - # https://travis-ci.org/giampaolo/psutil/builds/284173194 - for n in all_cpus if not TRAVIS else initial: - p.cpu_affinity([n]) - self.assertEqual(p.cpu_affinity(), [n]) - if hasattr(os, "sched_getaffinity"): - self.assertEqual(p.cpu_affinity(), - list(os.sched_getaffinity(p.pid))) - # also test num_cpu() - if hasattr(p, "num_cpu"): - self.assertEqual(p.cpu_affinity()[0], p.num_cpu()) - - # [] is an alias for "all eligible CPUs"; on Linux this may - # not be equal to all available CPUs, see: - # https://github.com/giampaolo/psutil/issues/956 - p.cpu_affinity([]) - if LINUX: - self.assertEqual(p.cpu_affinity(), p._proc._get_eligible_cpus()) - else: - self.assertEqual(p.cpu_affinity(), all_cpus) - if hasattr(os, "sched_getaffinity"): - self.assertEqual(p.cpu_affinity(), - list(os.sched_getaffinity(p.pid))) - # - self.assertRaises(TypeError, p.cpu_affinity, 1) - p.cpu_affinity(initial) - # it should work with all iterables, not only lists - if not TRAVIS: - p.cpu_affinity(set(all_cpus)) - p.cpu_affinity(tuple(all_cpus)) - - @unittest.skipIf(not HAS_CPU_AFFINITY, 'not supported') - def test_cpu_affinity_errs(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - invalid_cpu = [len(psutil.cpu_times(percpu=True)) + 10] - self.assertRaises(ValueError, p.cpu_affinity, invalid_cpu) - self.assertRaises(ValueError, p.cpu_affinity, range(10000, 11000)) - self.assertRaises(TypeError, p.cpu_affinity, [0, "1"]) - self.assertRaises(ValueError, p.cpu_affinity, [0, -1]) - - @unittest.skipIf(not HAS_CPU_AFFINITY, 'not supported') - def test_cpu_affinity_all_combinations(self): - p = psutil.Process() - initial = p.cpu_affinity() - assert initial, initial - self.addCleanup(p.cpu_affinity, initial) - - # All possible CPU set combinations. - if len(initial) > 12: - initial = initial[:12] # ...otherwise it will take forever - combos = [] - for l in range(0, len(initial) + 1): - for subset in itertools.combinations(initial, l): - if subset: - combos.append(list(subset)) - - for combo in combos: - p.cpu_affinity(combo) - self.assertEqual(p.cpu_affinity(), combo) - - # TODO: #595 - @unittest.skipIf(BSD, "broken on BSD") - # can't find any process file on Appveyor - @unittest.skipIf(APPVEYOR, "unreliable on APPVEYOR") - def test_open_files(self): - # current process - p = psutil.Process() - files = p.open_files() - self.assertFalse(TESTFN in files) - with open(TESTFN, 'wb') as f: - f.write(b'x' * 1024) - f.flush() - # give the kernel some time to see the new file - files = call_until(p.open_files, "len(ret) != %i" % len(files)) - filenames = [os.path.normcase(x.path) for x in files] - self.assertIn(os.path.normcase(TESTFN), filenames) - if LINUX: - for file in files: - if file.path == TESTFN: - self.assertEqual(file.position, 1024) - for file in files: - assert os.path.isfile(file.path), file - - # another process - cmdline = "import time; f = open(r'%s', 'r'); time.sleep(60);" % TESTFN - sproc = get_test_subprocess([PYTHON_EXE, "-c", cmdline]) - p = psutil.Process(sproc.pid) - - for x in range(100): - filenames = [os.path.normcase(x.path) for x in p.open_files()] - if TESTFN in filenames: - break - time.sleep(.01) - else: - self.assertIn(os.path.normcase(TESTFN), filenames) - for file in filenames: - assert os.path.isfile(file), file - - # TODO: #595 - @unittest.skipIf(BSD, "broken on BSD") - # can't find any process file on Appveyor - @unittest.skipIf(APPVEYOR, "unreliable on APPVEYOR") - def test_open_files_2(self): - # test fd and path fields - normcase = os.path.normcase - with open(TESTFN, 'w') as fileobj: - p = psutil.Process() - for file in p.open_files(): - if normcase(file.path) == normcase(fileobj.name) or \ - file.fd == fileobj.fileno(): - break - else: - self.fail("no file found; files=%s" % repr(p.open_files())) - self.assertEqual(normcase(file.path), normcase(fileobj.name)) - if WINDOWS: - self.assertEqual(file.fd, -1) - else: - self.assertEqual(file.fd, fileobj.fileno()) - # test positions - ntuple = p.open_files()[0] - self.assertEqual(ntuple[0], ntuple.path) - self.assertEqual(ntuple[1], ntuple.fd) - # test file is gone - self.assertNotIn(fileobj.name, p.open_files()) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_num_fds(self): - p = psutil.Process() - start = p.num_fds() - file = open(TESTFN, 'w') - self.addCleanup(file.close) - self.assertEqual(p.num_fds(), start + 1) - sock = socket.socket() - self.addCleanup(sock.close) - self.assertEqual(p.num_fds(), start + 2) - file.close() - sock.close() - self.assertEqual(p.num_fds(), start) - - @skip_on_not_implemented(only_if=LINUX) - @unittest.skipIf(OPENBSD or NETBSD, "not reliable on OPENBSD & NETBSD") - def test_num_ctx_switches(self): - p = psutil.Process() - before = sum(p.num_ctx_switches()) - for x in range(500000): - after = sum(p.num_ctx_switches()) - if after > before: - return - self.fail("num ctx switches still the same after 50.000 iterations") - - def test_ppid(self): - if hasattr(os, 'getppid'): - self.assertEqual(psutil.Process().ppid(), os.getppid()) - this_parent = os.getpid() - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - self.assertEqual(p.ppid(), this_parent) - # no other process is supposed to have us as parent - reap_children(recursive=True) - if APPVEYOR: - # Occasional failures, see: - # https://ci.appveyor.com/project/giampaolo/psutil/build/ - # job/0hs623nenj7w4m33 - return - for p in psutil.process_iter(): - if p.pid == sproc.pid: - continue - # XXX: sometimes this fails on Windows; not sure why. - self.assertNotEqual(p.ppid(), this_parent, msg=p) - - def test_parent(self): - this_parent = os.getpid() - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - self.assertEqual(p.parent().pid, this_parent) - - lowest_pid = psutil.pids()[0] - self.assertIsNone(psutil.Process(lowest_pid).parent()) - - def test_parent_multi(self): - p1, p2 = create_proc_children_pair() - self.assertEqual(p2.parent(), p1) - self.assertEqual(p1.parent(), psutil.Process()) - - def test_parent_disappeared(self): - # Emulate a case where the parent process disappeared. - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - with mock.patch("psutil.Process", - side_effect=psutil.NoSuchProcess(0, 'foo')): - self.assertIsNone(p.parent()) - - @retry_on_failure() - def test_parents(self): - assert psutil.Process().parents() - p1, p2 = create_proc_children_pair() - self.assertEqual(p1.parents()[0], psutil.Process()) - self.assertEqual(p2.parents()[0], p1) - self.assertEqual(p2.parents()[1], psutil.Process()) - - def test_children(self): - reap_children(recursive=True) - p = psutil.Process() - self.assertEqual(p.children(), []) - self.assertEqual(p.children(recursive=True), []) - # On Windows we set the flag to 0 in order to cancel out the - # CREATE_NO_WINDOW flag (enabled by default) which creates - # an extra "conhost.exe" child. - sproc = get_test_subprocess(creationflags=0) - children1 = p.children() - children2 = p.children(recursive=True) - for children in (children1, children2): - self.assertEqual(len(children), 1) - self.assertEqual(children[0].pid, sproc.pid) - self.assertEqual(children[0].ppid(), os.getpid()) - - def test_children_recursive(self): - # Test children() against two sub processes, p1 and p2, where - # p1 (our child) spawned p2 (our grandchild). - p1, p2 = create_proc_children_pair() - p = psutil.Process() - self.assertEqual(p.children(), [p1]) - self.assertEqual(p.children(recursive=True), [p1, p2]) - # If the intermediate process is gone there's no way for - # children() to recursively find it. - p1.terminate() - p1.wait() - self.assertEqual(p.children(recursive=True), []) - - def test_children_duplicates(self): - # find the process which has the highest number of children - table = collections.defaultdict(int) - for p in psutil.process_iter(): - try: - table[p.ppid()] += 1 - except psutil.Error: - pass - # this is the one, now let's make sure there are no duplicates - pid = sorted(table.items(), key=lambda x: x[1])[-1][0] - p = psutil.Process(pid) - try: - c = p.children(recursive=True) - except psutil.AccessDenied: # windows - pass - else: - self.assertEqual(len(c), len(set(c))) - - def test_parents_and_children(self): - p1, p2 = create_proc_children_pair() - me = psutil.Process() - # forward - children = me.children(recursive=True) - self.assertEqual(len(children), 2) - self.assertEqual(children[0], p1) - self.assertEqual(children[1], p2) - # backward - parents = p2.parents() - self.assertEqual(parents[0], p1) - self.assertEqual(parents[1], me) - - def test_suspend_resume(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.suspend() - for x in range(100): - if p.status() == psutil.STATUS_STOPPED: - break - time.sleep(0.01) - p.resume() - self.assertNotEqual(p.status(), psutil.STATUS_STOPPED) - - def test_invalid_pid(self): - self.assertRaises(TypeError, psutil.Process, "1") - self.assertRaises(ValueError, psutil.Process, -1) - - def test_as_dict(self): - p = psutil.Process() - d = p.as_dict(attrs=['exe', 'name']) - self.assertEqual(sorted(d.keys()), ['exe', 'name']) - - p = psutil.Process(min(psutil.pids())) - d = p.as_dict(attrs=['connections'], ad_value='foo') - if not isinstance(d['connections'], list): - self.assertEqual(d['connections'], 'foo') - - # Test ad_value is set on AccessDenied. - with mock.patch('psutil.Process.nice', create=True, - side_effect=psutil.AccessDenied): - self.assertEqual( - p.as_dict(attrs=["nice"], ad_value=1), {"nice": 1}) - - # Test that NoSuchProcess bubbles up. - with mock.patch('psutil.Process.nice', create=True, - side_effect=psutil.NoSuchProcess(p.pid, "name")): - self.assertRaises( - psutil.NoSuchProcess, p.as_dict, attrs=["nice"]) - - # Test that ZombieProcess is swallowed. - with mock.patch('psutil.Process.nice', create=True, - side_effect=psutil.ZombieProcess(p.pid, "name")): - self.assertEqual( - p.as_dict(attrs=["nice"], ad_value="foo"), {"nice": "foo"}) - - # By default APIs raising NotImplementedError are - # supposed to be skipped. - with mock.patch('psutil.Process.nice', create=True, - side_effect=NotImplementedError): - d = p.as_dict() - self.assertNotIn('nice', list(d.keys())) - # ...unless the user explicitly asked for some attr. - with self.assertRaises(NotImplementedError): - p.as_dict(attrs=["nice"]) - - # errors - with self.assertRaises(TypeError): - p.as_dict('name') - with self.assertRaises(ValueError): - p.as_dict(['foo']) - with self.assertRaises(ValueError): - p.as_dict(['foo', 'bar']) - - def test_oneshot(self): - with mock.patch("psutil._psplatform.Process.cpu_times") as m: - p = psutil.Process() - with p.oneshot(): - p.cpu_times() - p.cpu_times() - self.assertEqual(m.call_count, 1) - - with mock.patch("psutil._psplatform.Process.cpu_times") as m: - p.cpu_times() - p.cpu_times() - self.assertEqual(m.call_count, 2) - - def test_oneshot_twice(self): - # Test the case where the ctx manager is __enter__ed twice. - # The second __enter__ is supposed to resut in a NOOP. - with mock.patch("psutil._psplatform.Process.cpu_times") as m1: - with mock.patch("psutil._psplatform.Process.oneshot_enter") as m2: - p = psutil.Process() - with p.oneshot(): - p.cpu_times() - p.cpu_times() - with p.oneshot(): - p.cpu_times() - p.cpu_times() - self.assertEqual(m1.call_count, 1) - self.assertEqual(m2.call_count, 1) - - with mock.patch("psutil._psplatform.Process.cpu_times") as m: - p.cpu_times() - p.cpu_times() - self.assertEqual(m.call_count, 2) - - def test_oneshot_cache(self): - # Make sure oneshot() cache is nonglobal. Instead it's - # supposed to be bound to the Process instance, see: - # https://github.com/giampaolo/psutil/issues/1373 - p1, p2 = create_proc_children_pair() - p1_ppid = p1.ppid() - p2_ppid = p2.ppid() - self.assertNotEqual(p1_ppid, p2_ppid) - with p1.oneshot(): - self.assertEqual(p1.ppid(), p1_ppid) - self.assertEqual(p2.ppid(), p2_ppid) - with p2.oneshot(): - self.assertEqual(p1.ppid(), p1_ppid) - self.assertEqual(p2.ppid(), p2_ppid) - - def test_halfway_terminated_process(self): - # Test that NoSuchProcess exception gets raised in case the - # process dies after we create the Process object. - # Example: - # >>> proc = Process(1234) - # >>> time.sleep(2) # time-consuming task, process dies in meantime - # >>> proc.name() - # Refers to Issue #15 - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.terminate() - p.wait() - if WINDOWS: - call_until(psutil.pids, "%s not in ret" % p.pid) - assert not p.is_running() - - if WINDOWS: - with self.assertRaises(psutil.NoSuchProcess): - p.send_signal(signal.CTRL_C_EVENT) - with self.assertRaises(psutil.NoSuchProcess): - p.send_signal(signal.CTRL_BREAK_EVENT) - - excluded_names = ['pid', 'is_running', 'wait', 'create_time', - 'oneshot', 'memory_info_ex'] - if LINUX and not HAS_RLIMIT: - excluded_names.append('rlimit') - for name in dir(p): - if (name.startswith('_') or - name in excluded_names): - continue - try: - meth = getattr(p, name) - # get/set methods - if name == 'nice': - if POSIX: - ret = meth(1) - else: - ret = meth(psutil.NORMAL_PRIORITY_CLASS) - elif name == 'ionice': - ret = meth() - ret = meth(2) - elif name == 'rlimit': - ret = meth(psutil.RLIMIT_NOFILE) - ret = meth(psutil.RLIMIT_NOFILE, (5, 5)) - elif name == 'cpu_affinity': - ret = meth() - ret = meth([0]) - elif name == 'send_signal': - ret = meth(signal.SIGTERM) - else: - ret = meth() - except psutil.ZombieProcess: - self.fail("ZombieProcess for %r was not supposed to happen" % - name) - except psutil.NoSuchProcess: - pass - except psutil.AccessDenied: - if OPENBSD and name in ('threads', 'num_threads'): - pass - else: - raise - except NotImplementedError: - pass - else: - # NtQuerySystemInformation succeeds if process is gone. - if WINDOWS and name in ('exe', 'name'): - normcase = os.path.normcase - if name == 'exe': - self.assertEqual(normcase(ret), normcase(PYTHON_EXE)) - else: - self.assertEqual( - normcase(ret), - normcase(os.path.basename(PYTHON_EXE))) - continue - self.fail( - "NoSuchProcess exception not raised for %r, retval=%s" % ( - name, ret)) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_zombie_process(self): - def succeed_or_zombie_p_exc(fun, *args, **kwargs): - try: - return fun(*args, **kwargs) - except (psutil.ZombieProcess, psutil.AccessDenied): - pass - - zpid = create_zombie_proc() - self.addCleanup(reap_children, recursive=True) - # A zombie process should always be instantiable - zproc = psutil.Process(zpid) - # ...and at least its status always be querable - self.assertEqual(zproc.status(), psutil.STATUS_ZOMBIE) - # ...and it should be considered 'running' - self.assertTrue(zproc.is_running()) - # ...and as_dict() shouldn't crash - zproc.as_dict() - # if cmdline succeeds it should be an empty list - ret = succeed_or_zombie_p_exc(zproc.suspend) - if ret is not None: - self.assertEqual(ret, []) - - if hasattr(zproc, "rlimit"): - succeed_or_zombie_p_exc(zproc.rlimit, psutil.RLIMIT_NOFILE) - succeed_or_zombie_p_exc(zproc.rlimit, psutil.RLIMIT_NOFILE, - (5, 5)) - # set methods - succeed_or_zombie_p_exc(zproc.parent) - if hasattr(zproc, 'cpu_affinity'): - try: - succeed_or_zombie_p_exc(zproc.cpu_affinity, [0]) - except ValueError as err: - if TRAVIS and LINUX and "not eligible" in str(err): - # https://travis-ci.org/giampaolo/psutil/jobs/279890461 - pass - else: - raise - - succeed_or_zombie_p_exc(zproc.nice, 0) - if hasattr(zproc, 'ionice'): - if LINUX: - succeed_or_zombie_p_exc(zproc.ionice, 2, 0) - else: - succeed_or_zombie_p_exc(zproc.ionice, 0) # Windows - if hasattr(zproc, 'rlimit'): - succeed_or_zombie_p_exc(zproc.rlimit, - psutil.RLIMIT_NOFILE, (5, 5)) - succeed_or_zombie_p_exc(zproc.suspend) - succeed_or_zombie_p_exc(zproc.resume) - succeed_or_zombie_p_exc(zproc.terminate) - succeed_or_zombie_p_exc(zproc.kill) - - # ...its parent should 'see' it - # edit: not true on BSD and MACOS - # descendants = [x.pid for x in psutil.Process().children( - # recursive=True)] - # self.assertIn(zpid, descendants) - # XXX should we also assume ppid be usable? Note: this - # would be an important use case as the only way to get - # rid of a zombie is to kill its parent. - # self.assertEqual(zpid.ppid(), os.getpid()) - # ...and all other APIs should be able to deal with it - self.assertTrue(psutil.pid_exists(zpid)) - if not TRAVIS and MACOS: - # For some reason this started failing all of the sudden. - # Maybe they upgraded MACOS version? - # https://travis-ci.org/giampaolo/psutil/jobs/310896404 - self.assertIn(zpid, psutil.pids()) - self.assertIn(zpid, [x.pid for x in psutil.process_iter()]) - psutil._pmap = {} - self.assertIn(zpid, [x.pid for x in psutil.process_iter()]) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_zombie_process_is_running_w_exc(self): - # Emulate a case where internally is_running() raises - # ZombieProcess. - p = psutil.Process() - with mock.patch("psutil.Process", - side_effect=psutil.ZombieProcess(0)) as m: - assert p.is_running() - assert m.called - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_zombie_process_status_w_exc(self): - # Emulate a case where internally status() raises - # ZombieProcess. - p = psutil.Process() - with mock.patch("psutil._psplatform.Process.status", - side_effect=psutil.ZombieProcess(0)) as m: - self.assertEqual(p.status(), psutil.STATUS_ZOMBIE) - assert m.called - - def test_pid_0(self): - # Process(0) is supposed to work on all platforms except Linux - if 0 not in psutil.pids(): - self.assertRaises(psutil.NoSuchProcess, psutil.Process, 0) - return - - # test all methods - p = psutil.Process(0) - for name in psutil._as_dict_attrnames: - if name == 'pid': - continue - meth = getattr(p, name) - try: - ret = meth() - except psutil.AccessDenied: - pass - else: - if name in ("uids", "gids"): - self.assertEqual(ret.real, 0) - elif name == "username": - if POSIX: - self.assertEqual(p.username(), 'root') - elif WINDOWS: - self.assertEqual(p.username(), 'NT AUTHORITY\\SYSTEM') - elif name == "name": - assert name, name - - if hasattr(p, 'rlimit'): - try: - p.rlimit(psutil.RLIMIT_FSIZE) - except psutil.AccessDenied: - pass - - p.as_dict() - - if not OPENBSD: - self.assertIn(0, psutil.pids()) - self.assertTrue(psutil.pid_exists(0)) - - @unittest.skipIf(not HAS_ENVIRON, "not supported") - def test_environ(self): - def clean_dict(d): - # Most of these are problematic on Travis. - d.pop("PSUTIL_TESTING", None) - d.pop("PLAT", None) - d.pop("HOME", None) - if MACOS: - d.pop("__CF_USER_TEXT_ENCODING", None) - d.pop("VERSIONER_PYTHON_PREFER_32_BIT", None) - d.pop("VERSIONER_PYTHON_VERSION", None) - return dict( - [(k.replace("\r", "").replace("\n", ""), - v.replace("\r", "").replace("\n", "")) - for k, v in d.items()]) - - self.maxDiff = None - p = psutil.Process() - d1 = clean_dict(p.environ()) - d2 = clean_dict(os.environ.copy()) - self.assertEqual(d1, d2) - - @unittest.skipIf(not HAS_ENVIRON, "not supported") - @unittest.skipIf(not POSIX, "POSIX only") - def test_weird_environ(self): - # environment variables can contain values without an equals sign - code = textwrap.dedent(""" - #include - #include - char * const argv[] = {"cat", 0}; - char * const envp[] = {"A=1", "X", "C=3", 0}; - int main(void) { - /* Close stderr on exec so parent can wait for the execve to - * finish. */ - if (fcntl(2, F_SETFD, FD_CLOEXEC) != 0) - return 0; - return execve("/bin/cat", argv, envp); - } - """) - path = TESTFN - create_exe(path, c_code=code) - self.addCleanup(safe_rmpath, path) - sproc = get_test_subprocess([path], - stdin=subprocess.PIPE, - stderr=subprocess.PIPE) - p = psutil.Process(sproc.pid) - wait_for_pid(p.pid) - self.assertTrue(p.is_running()) - # Wait for process to exec or exit. - self.assertEqual(sproc.stderr.read(), b"") - self.assertEqual(p.environ(), {"A": "1", "C": "3"}) - sproc.communicate() - self.assertEqual(sproc.returncode, 0) - - -# =================================================================== -# --- Limited user tests -# =================================================================== - - -if POSIX and os.getuid() == 0: - class LimitedUserTestCase(TestProcess): - """Repeat the previous tests by using a limited user. - Executed only on UNIX and only if the user who run the test script - is root. - """ - # the uid/gid the test suite runs under - if hasattr(os, 'getuid'): - PROCESS_UID = os.getuid() - PROCESS_GID = os.getgid() - - def __init__(self, *args, **kwargs): - TestProcess.__init__(self, *args, **kwargs) - # re-define all existent test methods in order to - # ignore AccessDenied exceptions - for attr in [x for x in dir(self) if x.startswith('test')]: - meth = getattr(self, attr) - - def test_(self): - try: - meth() - except psutil.AccessDenied: - pass - setattr(self, attr, types.MethodType(test_, self)) - - def setUp(self): - safe_rmpath(TESTFN) - TestProcess.setUp(self) - os.setegid(1000) - os.seteuid(1000) - - def tearDown(self): - os.setegid(self.PROCESS_UID) - os.seteuid(self.PROCESS_GID) - TestProcess.tearDown(self) - - def test_nice(self): - try: - psutil.Process().nice(-1) - except psutil.AccessDenied: - pass - else: - self.fail("exception not raised") - - def test_zombie_process(self): - # causes problems if test test suite is run as root - pass - - -# =================================================================== -# --- psutil.Popen tests -# =================================================================== - - -class TestPopen(unittest.TestCase): - """Tests for psutil.Popen class.""" - - def tearDown(self): - reap_children() - - def test_misc(self): - # XXX this test causes a ResourceWarning on Python 3 because - # psutil.__subproc instance doesn't get propertly freed. - # Not sure what to do though. - cmd = [PYTHON_EXE, "-c", "import time; time.sleep(60);"] - with psutil.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) as proc: - proc.name() - proc.cpu_times() - proc.stdin - self.assertTrue(dir(proc)) - self.assertRaises(AttributeError, getattr, proc, 'foo') - proc.terminate() - - def test_ctx_manager(self): - with psutil.Popen([PYTHON_EXE, "-V"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - stdin=subprocess.PIPE) as proc: - proc.communicate() - assert proc.stdout.closed - assert proc.stderr.closed - assert proc.stdin.closed - self.assertEqual(proc.returncode, 0) - - def test_kill_terminate(self): - # subprocess.Popen()'s terminate(), kill() and send_signal() do - # not raise exception after the process is gone. psutil.Popen - # diverges from that. - cmd = [PYTHON_EXE, "-c", "import time; time.sleep(60);"] - with psutil.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) as proc: - proc.terminate() - proc.wait() - self.assertRaises(psutil.NoSuchProcess, proc.terminate) - self.assertRaises(psutil.NoSuchProcess, proc.kill) - self.assertRaises(psutil.NoSuchProcess, proc.send_signal, - signal.SIGTERM) - if WINDOWS and sys.version_info >= (2, 7): - self.assertRaises(psutil.NoSuchProcess, proc.send_signal, - signal.CTRL_C_EVENT) - self.assertRaises(psutil.NoSuchProcess, proc.send_signal, - signal.CTRL_BREAK_EVENT) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_sunos.py b/third_party/python/psutil/psutil/tests/test_sunos.py deleted file mode 100755 index e3beb625bf53..000000000000 --- a/third_party/python/psutil/psutil/tests/test_sunos.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Sun OS specific tests.""" - -import os - -import psutil -from psutil import SUNOS -from psutil.tests import sh -from psutil.tests import unittest - - -@unittest.skipIf(not SUNOS, "SUNOS only") -class SunOSSpecificTestCase(unittest.TestCase): - - def test_swap_memory(self): - out = sh('env PATH=/usr/sbin:/sbin:%s swap -l' % os.environ['PATH']) - lines = out.strip().split('\n')[1:] - if not lines: - raise ValueError('no swap device(s) configured') - total = free = 0 - for line in lines: - line = line.split() - t, f = line[-2:] - total += int(int(t) * 512) - free += int(int(f) * 512) - used = total - free - - psutil_swap = psutil.swap_memory() - self.assertEqual(psutil_swap.total, total) - self.assertEqual(psutil_swap.used, used) - self.assertEqual(psutil_swap.free, free) - - def test_cpu_count(self): - out = sh("/usr/sbin/psrinfo") - self.assertEqual(psutil.cpu_count(), len(out.split('\n'))) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_system.py b/third_party/python/psutil/psutil/tests/test_system.py deleted file mode 100755 index 3834209fcb36..000000000000 --- a/third_party/python/psutil/psutil/tests/test_system.py +++ /dev/null @@ -1,904 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Tests for system APIS.""" - -import contextlib -import datetime -import errno -import os -import pprint -import shutil -import signal -import socket -import sys -import tempfile -import time - -import psutil -from psutil import AIX -from psutil import BSD -from psutil import FREEBSD -from psutil import LINUX -from psutil import MACOS -from psutil import NETBSD -from psutil import OPENBSD -from psutil import POSIX -from psutil import SUNOS -from psutil import WINDOWS -from psutil._compat import FileNotFoundError -from psutil._compat import long -from psutil.tests import ASCII_FS -from psutil.tests import check_net_address -from psutil.tests import CI_TESTING -from psutil.tests import DEVNULL -from psutil.tests import enum -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_GETLOADAVG -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 -from psutil.tests import mock -from psutil.tests import PYPY -from psutil.tests import reap_children -from psutil.tests import retry_on_failure -from psutil.tests import safe_rmpath -from psutil.tests import TESTFN -from psutil.tests import TESTFN_UNICODE -from psutil.tests import TRAVIS -from psutil.tests import unittest - - -# =================================================================== -# --- System-related API tests -# =================================================================== - - -class TestProcessAPIs(unittest.TestCase): - - def setUp(self): - safe_rmpath(TESTFN) - - def tearDown(self): - reap_children() - - def test_process_iter(self): - self.assertIn(os.getpid(), [x.pid for x in psutil.process_iter()]) - sproc = get_test_subprocess() - self.assertIn(sproc.pid, [x.pid for x in psutil.process_iter()]) - p = psutil.Process(sproc.pid) - p.kill() - p.wait() - self.assertNotIn(sproc.pid, [x.pid for x in psutil.process_iter()]) - - with mock.patch('psutil.Process', - side_effect=psutil.NoSuchProcess(os.getpid())): - self.assertEqual(list(psutil.process_iter()), []) - with mock.patch('psutil.Process', - side_effect=psutil.AccessDenied(os.getpid())): - with self.assertRaises(psutil.AccessDenied): - list(psutil.process_iter()) - - def test_prcess_iter_w_attrs(self): - for p in psutil.process_iter(attrs=['pid']): - self.assertEqual(list(p.info.keys()), ['pid']) - with self.assertRaises(ValueError): - list(psutil.process_iter(attrs=['foo'])) - with mock.patch("psutil._psplatform.Process.cpu_times", - side_effect=psutil.AccessDenied(0, "")) as m: - for p in psutil.process_iter(attrs=["pid", "cpu_times"]): - self.assertIsNone(p.info['cpu_times']) - self.assertGreaterEqual(p.info['pid'], 0) - assert m.called - with mock.patch("psutil._psplatform.Process.cpu_times", - side_effect=psutil.AccessDenied(0, "")) as m: - flag = object() - for p in psutil.process_iter( - attrs=["pid", "cpu_times"], ad_value=flag): - self.assertIs(p.info['cpu_times'], flag) - self.assertGreaterEqual(p.info['pid'], 0) - assert m.called - - @unittest.skipIf(PYPY and WINDOWS, - "get_test_subprocess() unreliable on PYPY + WINDOWS") - def test_wait_procs(self): - def callback(p): - pids.append(p.pid) - - pids = [] - sproc1 = get_test_subprocess() - sproc2 = get_test_subprocess() - sproc3 = get_test_subprocess() - procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)] - self.assertRaises(ValueError, psutil.wait_procs, procs, timeout=-1) - self.assertRaises(TypeError, psutil.wait_procs, procs, callback=1) - t = time.time() - gone, alive = psutil.wait_procs(procs, timeout=0.01, callback=callback) - - self.assertLess(time.time() - t, 0.5) - self.assertEqual(gone, []) - self.assertEqual(len(alive), 3) - self.assertEqual(pids, []) - for p in alive: - self.assertFalse(hasattr(p, 'returncode')) - - @retry_on_failure(30) - def test(procs, callback): - gone, alive = psutil.wait_procs(procs, timeout=0.03, - callback=callback) - self.assertEqual(len(gone), 1) - self.assertEqual(len(alive), 2) - return gone, alive - - sproc3.terminate() - gone, alive = test(procs, callback) - self.assertIn(sproc3.pid, [x.pid for x in gone]) - if POSIX: - self.assertEqual(gone.pop().returncode, -signal.SIGTERM) - else: - self.assertEqual(gone.pop().returncode, 1) - self.assertEqual(pids, [sproc3.pid]) - for p in alive: - self.assertFalse(hasattr(p, 'returncode')) - - @retry_on_failure(30) - def test(procs, callback): - gone, alive = psutil.wait_procs(procs, timeout=0.03, - callback=callback) - self.assertEqual(len(gone), 3) - self.assertEqual(len(alive), 0) - return gone, alive - - sproc1.terminate() - sproc2.terminate() - gone, alive = test(procs, callback) - self.assertEqual(set(pids), set([sproc1.pid, sproc2.pid, sproc3.pid])) - for p in gone: - self.assertTrue(hasattr(p, 'returncode')) - - @unittest.skipIf(PYPY and WINDOWS, - "get_test_subprocess() unreliable on PYPY + WINDOWS") - def test_wait_procs_no_timeout(self): - sproc1 = get_test_subprocess() - sproc2 = get_test_subprocess() - sproc3 = get_test_subprocess() - procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)] - for p in procs: - p.terminate() - gone, alive = psutil.wait_procs(procs) - - def test_pid_exists(self): - sproc = get_test_subprocess() - self.assertTrue(psutil.pid_exists(sproc.pid)) - p = psutil.Process(sproc.pid) - p.kill() - p.wait() - self.assertFalse(psutil.pid_exists(sproc.pid)) - self.assertFalse(psutil.pid_exists(-1)) - self.assertEqual(psutil.pid_exists(0), 0 in psutil.pids()) - - def test_pid_exists_2(self): - reap_children() - pids = psutil.pids() - for pid in pids: - try: - assert psutil.pid_exists(pid) - except AssertionError: - # in case the process disappeared in meantime fail only - # if it is no longer in psutil.pids() - time.sleep(.1) - if pid in psutil.pids(): - self.fail(pid) - pids = range(max(pids) + 5000, max(pids) + 6000) - for pid in pids: - self.assertFalse(psutil.pid_exists(pid), msg=pid) - - def test_pids(self): - pidslist = psutil.pids() - procslist = [x.pid for x in psutil.process_iter()] - # make sure every pid is unique - self.assertEqual(sorted(set(pidslist)), pidslist) - self.assertEqual(pidslist, procslist) - - -class TestMiscAPIs(unittest.TestCase): - - def test_boot_time(self): - bt = psutil.boot_time() - self.assertIsInstance(bt, float) - self.assertGreater(bt, 0) - self.assertLess(bt, time.time()) - - @unittest.skipIf(CI_TESTING and not psutil.users(), "unreliable on CI") - def test_users(self): - users = psutil.users() - self.assertNotEqual(users, []) - for user in users: - assert user.name, user - self.assertIsInstance(user.name, str) - self.assertIsInstance(user.terminal, (str, type(None))) - if user.host is not None: - self.assertIsInstance(user.host, (str, type(None))) - user.terminal - user.host - assert user.started > 0.0, user - datetime.datetime.fromtimestamp(user.started) - if WINDOWS or OPENBSD: - self.assertIsNone(user.pid) - else: - psutil.Process(user.pid) - - @unittest.skipIf(not POSIX, 'POSIX only') - def test_PAGESIZE(self): - # pagesize is used internally to perform different calculations - # and it's determined by using SC_PAGE_SIZE; make sure - # getpagesize() returns the same value. - import resource - self.assertEqual(os.sysconf("SC_PAGE_SIZE"), resource.getpagesize()) - - def test_test(self): - # test for psutil.test() function - stdout = sys.stdout - sys.stdout = DEVNULL - try: - psutil.test() - finally: - sys.stdout = stdout - - def test_os_constants(self): - names = ["POSIX", "WINDOWS", "LINUX", "MACOS", "FREEBSD", "OPENBSD", - "NETBSD", "BSD", "SUNOS"] - for name in names: - self.assertIsInstance(getattr(psutil, name), bool, msg=name) - - if os.name == 'posix': - assert psutil.POSIX - assert not psutil.WINDOWS - names.remove("POSIX") - if "linux" in sys.platform.lower(): - assert psutil.LINUX - names.remove("LINUX") - elif "bsd" in sys.platform.lower(): - assert psutil.BSD - self.assertEqual([psutil.FREEBSD, psutil.OPENBSD, - psutil.NETBSD].count(True), 1) - names.remove("BSD") - names.remove("FREEBSD") - names.remove("OPENBSD") - names.remove("NETBSD") - elif "sunos" in sys.platform.lower() or \ - "solaris" in sys.platform.lower(): - assert psutil.SUNOS - names.remove("SUNOS") - elif "darwin" in sys.platform.lower(): - assert psutil.MACOS - names.remove("MACOS") - else: - assert psutil.WINDOWS - assert not psutil.POSIX - names.remove("WINDOWS") - - # assert all other constants are set to False - for name in names: - self.assertIs(getattr(psutil, name), False, msg=name) - - -class TestMemoryAPIs(unittest.TestCase): - - def test_virtual_memory(self): - mem = psutil.virtual_memory() - assert mem.total > 0, mem - assert mem.available > 0, mem - assert 0 <= mem.percent <= 100, mem - assert mem.used > 0, mem - assert mem.free >= 0, mem - for name in mem._fields: - value = getattr(mem, name) - if name != 'percent': - self.assertIsInstance(value, (int, long)) - if name != 'total': - if not value >= 0: - self.fail("%r < 0 (%s)" % (name, value)) - if value > mem.total: - self.fail("%r > total (total=%s, %s=%s)" - % (name, mem.total, name, value)) - - def test_swap_memory(self): - mem = psutil.swap_memory() - self.assertEqual( - mem._fields, ('total', 'used', 'free', 'percent', 'sin', 'sout')) - - assert mem.total >= 0, mem - assert mem.used >= 0, mem - if mem.total > 0: - # likely a system with no swap partition - assert mem.free > 0, mem - else: - assert mem.free == 0, mem - assert 0 <= mem.percent <= 100, mem - assert mem.sin >= 0, mem - assert mem.sout >= 0, mem - - -class TestCpuAPIs(unittest.TestCase): - - def test_cpu_count_logical(self): - logical = psutil.cpu_count() - self.assertIsNotNone(logical) - self.assertEqual(logical, len(psutil.cpu_times(percpu=True))) - self.assertGreaterEqual(logical, 1) - # - if os.path.exists("/proc/cpuinfo"): - with open("/proc/cpuinfo") as fd: - cpuinfo_data = fd.read() - if "physical id" not in cpuinfo_data: - raise unittest.SkipTest("cpuinfo doesn't include physical id") - - def test_cpu_count_physical(self): - logical = psutil.cpu_count() - physical = psutil.cpu_count(logical=False) - if physical is None: - raise self.skipTest("physical cpu_count() is None") - if WINDOWS and sys.getwindowsversion()[:2] <= (6, 1): # <= Vista - self.assertIsNone(physical) - else: - self.assertGreaterEqual(physical, 1) - self.assertGreaterEqual(logical, physical) - - def test_cpu_count_none(self): - # https://github.com/giampaolo/psutil/issues/1085 - for val in (-1, 0, None): - with mock.patch('psutil._psplatform.cpu_count_logical', - return_value=val) as m: - self.assertIsNone(psutil.cpu_count()) - assert m.called - with mock.patch('psutil._psplatform.cpu_count_physical', - return_value=val) as m: - self.assertIsNone(psutil.cpu_count(logical=False)) - assert m.called - - def test_cpu_times(self): - # Check type, value >= 0, str(). - total = 0 - times = psutil.cpu_times() - sum(times) - for cp_time in times: - self.assertIsInstance(cp_time, float) - self.assertGreaterEqual(cp_time, 0.0) - total += cp_time - self.assertEqual(total, sum(times)) - str(times) - # CPU times are always supposed to increase over time - # or at least remain the same and that's because time - # cannot go backwards. - # Surprisingly sometimes this might not be the case (at - # least on Windows and Linux), see: - # https://github.com/giampaolo/psutil/issues/392 - # https://github.com/giampaolo/psutil/issues/645 - # if not WINDOWS: - # last = psutil.cpu_times() - # for x in range(100): - # new = psutil.cpu_times() - # for field in new._fields: - # new_t = getattr(new, field) - # last_t = getattr(last, field) - # self.assertGreaterEqual(new_t, last_t, - # msg="%s %s" % (new_t, last_t)) - # last = new - - def test_cpu_times_time_increases(self): - # Make sure time increases between calls. - t1 = sum(psutil.cpu_times()) - stop_at = time.time() + 1 - while time.time() < stop_at: - t2 = sum(psutil.cpu_times()) - if t2 > t1: - return - self.fail("time remained the same") - - def test_per_cpu_times(self): - # Check type, value >= 0, str(). - for times in psutil.cpu_times(percpu=True): - total = 0 - sum(times) - for cp_time in times: - self.assertIsInstance(cp_time, float) - self.assertGreaterEqual(cp_time, 0.0) - total += cp_time - self.assertEqual(total, sum(times)) - str(times) - self.assertEqual(len(psutil.cpu_times(percpu=True)[0]), - len(psutil.cpu_times(percpu=False))) - - # Note: in theory CPU times are always supposed to increase over - # time or remain the same but never go backwards. In practice - # sometimes this is not the case. - # This issue seemd to be afflict Windows: - # https://github.com/giampaolo/psutil/issues/392 - # ...but it turns out also Linux (rarely) behaves the same. - # last = psutil.cpu_times(percpu=True) - # for x in range(100): - # new = psutil.cpu_times(percpu=True) - # for index in range(len(new)): - # newcpu = new[index] - # lastcpu = last[index] - # for field in newcpu._fields: - # new_t = getattr(newcpu, field) - # last_t = getattr(lastcpu, field) - # self.assertGreaterEqual( - # new_t, last_t, msg="%s %s" % (lastcpu, newcpu)) - # last = new - - def test_per_cpu_times_2(self): - # Simulate some work load then make sure time have increased - # between calls. - tot1 = psutil.cpu_times(percpu=True) - giveup_at = time.time() + 1 - while True: - if time.time() >= giveup_at: - return self.fail("timeout") - tot2 = psutil.cpu_times(percpu=True) - for t1, t2 in zip(tot1, tot2): - t1, t2 = psutil._cpu_busy_time(t1), psutil._cpu_busy_time(t2) - difference = t2 - t1 - if difference >= 0.05: - return - - def test_cpu_times_comparison(self): - # Make sure the sum of all per cpu times is almost equal to - # base "one cpu" times. - base = psutil.cpu_times() - per_cpu = psutil.cpu_times(percpu=True) - summed_values = base._make([sum(num) for num in zip(*per_cpu)]) - for field in base._fields: - self.assertAlmostEqual( - getattr(base, field), getattr(summed_values, field), delta=1) - - def _test_cpu_percent(self, percent, last_ret, new_ret): - try: - self.assertIsInstance(percent, float) - self.assertGreaterEqual(percent, 0.0) - self.assertIsNot(percent, -0.0) - self.assertLessEqual(percent, 100.0 * psutil.cpu_count()) - except AssertionError as err: - raise AssertionError("\n%s\nlast=%s\nnew=%s" % ( - err, pprint.pformat(last_ret), pprint.pformat(new_ret))) - - def test_cpu_percent(self): - last = psutil.cpu_percent(interval=0.001) - for x in range(100): - new = psutil.cpu_percent(interval=None) - self._test_cpu_percent(new, last, new) - last = new - with self.assertRaises(ValueError): - psutil.cpu_percent(interval=-1) - - def test_per_cpu_percent(self): - last = psutil.cpu_percent(interval=0.001, percpu=True) - self.assertEqual(len(last), psutil.cpu_count()) - for x in range(100): - new = psutil.cpu_percent(interval=None, percpu=True) - for percent in new: - self._test_cpu_percent(percent, last, new) - last = new - with self.assertRaises(ValueError): - psutil.cpu_percent(interval=-1, percpu=True) - - def test_cpu_times_percent(self): - last = psutil.cpu_times_percent(interval=0.001) - for x in range(100): - new = psutil.cpu_times_percent(interval=None) - for percent in new: - self._test_cpu_percent(percent, last, new) - self._test_cpu_percent(sum(new), last, new) - last = new - - def test_per_cpu_times_percent(self): - last = psutil.cpu_times_percent(interval=0.001, percpu=True) - self.assertEqual(len(last), psutil.cpu_count()) - for x in range(100): - new = psutil.cpu_times_percent(interval=None, percpu=True) - for cpu in new: - for percent in cpu: - self._test_cpu_percent(percent, last, new) - self._test_cpu_percent(sum(cpu), last, new) - last = new - - def test_per_cpu_times_percent_negative(self): - # see: https://github.com/giampaolo/psutil/issues/645 - psutil.cpu_times_percent(percpu=True) - zero_times = [x._make([0 for x in range(len(x._fields))]) - for x in psutil.cpu_times(percpu=True)] - with mock.patch('psutil.cpu_times', return_value=zero_times): - for cpu in psutil.cpu_times_percent(percpu=True): - for percent in cpu: - self._test_cpu_percent(percent, None, None) - - def test_cpu_stats(self): - # Tested more extensively in per-platform test modules. - infos = psutil.cpu_stats() - self.assertEqual( - infos._fields, - ('ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls')) - for name in infos._fields: - value = getattr(infos, name) - self.assertGreaterEqual(value, 0) - # on AIX, ctx_switches is always 0 - if not AIX and name in ('ctx_switches', 'interrupts'): - self.assertGreater(value, 0) - - @unittest.skipIf(not HAS_CPU_FREQ, "not suported") - def test_cpu_freq(self): - def check_ls(ls): - for nt in ls: - self.assertEqual(nt._fields, ('current', 'min', 'max')) - if nt.max != 0.0: - self.assertLessEqual(nt.current, nt.max) - for name in nt._fields: - value = getattr(nt, name) - self.assertIsInstance(value, (int, long, float)) - self.assertGreaterEqual(value, 0) - - ls = psutil.cpu_freq(percpu=True) - if TRAVIS and not ls: - raise self.skipTest("skipped on Travis") - if FREEBSD and not ls: - raise self.skipTest("returns empty list on FreeBSD") - - assert ls, ls - check_ls([psutil.cpu_freq(percpu=False)]) - - if LINUX: - self.assertEqual(len(ls), psutil.cpu_count()) - - @unittest.skipIf(not HAS_GETLOADAVG, "not supported") - def test_getloadavg(self): - loadavg = psutil.getloadavg() - assert len(loadavg) == 3 - - for load in loadavg: - self.assertIsInstance(load, float) - self.assertGreaterEqual(load, 0.0) - - -class TestDiskAPIs(unittest.TestCase): - - def test_disk_usage(self): - usage = psutil.disk_usage(os.getcwd()) - self.assertEqual(usage._fields, ('total', 'used', 'free', 'percent')) - - assert usage.total > 0, usage - assert usage.used > 0, usage - assert usage.free > 0, usage - assert usage.total > usage.used, usage - assert usage.total > usage.free, usage - assert 0 <= usage.percent <= 100, usage.percent - if hasattr(shutil, 'disk_usage'): - # py >= 3.3, see: http://bugs.python.org/issue12442 - shutil_usage = shutil.disk_usage(os.getcwd()) - tolerance = 5 * 1024 * 1024 # 5MB - self.assertEqual(usage.total, shutil_usage.total) - self.assertAlmostEqual(usage.free, shutil_usage.free, - delta=tolerance) - self.assertAlmostEqual(usage.used, shutil_usage.used, - delta=tolerance) - - # if path does not exist OSError ENOENT is expected across - # all platforms - fname = tempfile.mktemp() - with self.assertRaises(FileNotFoundError): - psutil.disk_usage(fname) - - def test_disk_usage_unicode(self): - # See: https://github.com/giampaolo/psutil/issues/416 - if ASCII_FS: - with self.assertRaises(UnicodeEncodeError): - psutil.disk_usage(TESTFN_UNICODE) - - def test_disk_usage_bytes(self): - psutil.disk_usage(b'.') - - def test_disk_partitions(self): - # all = False - ls = psutil.disk_partitions(all=False) - # on travis we get: - # self.assertEqual(p.cpu_affinity(), [n]) - # AssertionError: Lists differ: [0, 1, 2, 3, 4, 5, 6, 7,... != [0] - self.assertTrue(ls, msg=ls) - for disk in ls: - self.assertIsInstance(disk.device, str) - self.assertIsInstance(disk.mountpoint, str) - self.assertIsInstance(disk.fstype, str) - self.assertIsInstance(disk.opts, str) - if WINDOWS and 'cdrom' in disk.opts: - continue - if not POSIX: - assert os.path.exists(disk.device), disk - else: - # we cannot make any assumption about this, see: - # http://goo.gl/p9c43 - disk.device - # on modern systems mount points can also be files - assert os.path.exists(disk.mountpoint), disk - assert disk.fstype, disk - - # all = True - ls = psutil.disk_partitions(all=True) - self.assertTrue(ls, msg=ls) - for disk in psutil.disk_partitions(all=True): - if not WINDOWS and disk.mountpoint: - try: - os.stat(disk.mountpoint) - except OSError as err: - if TRAVIS and MACOS and err.errno == errno.EIO: - continue - # http://mail.python.org/pipermail/python-dev/ - # 2012-June/120787.html - if err.errno not in (errno.EPERM, errno.EACCES): - raise - else: - assert os.path.exists(disk.mountpoint), disk - self.assertIsInstance(disk.fstype, str) - self.assertIsInstance(disk.opts, str) - - def find_mount_point(path): - path = os.path.abspath(path) - while not os.path.ismount(path): - path = os.path.dirname(path) - return path.lower() - - mount = find_mount_point(__file__) - mounts = [x.mountpoint.lower() for x in - psutil.disk_partitions(all=True) if x.mountpoint] - self.assertIn(mount, mounts) - psutil.disk_usage(mount) - - @unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'), - '/proc/diskstats not available on this linux version') - @unittest.skipIf(CI_TESTING and not psutil.disk_io_counters(), - "unreliable on CI") # no visible disks - def test_disk_io_counters(self): - def check_ntuple(nt): - self.assertEqual(nt[0], nt.read_count) - self.assertEqual(nt[1], nt.write_count) - self.assertEqual(nt[2], nt.read_bytes) - self.assertEqual(nt[3], nt.write_bytes) - if not (OPENBSD or NETBSD): - self.assertEqual(nt[4], nt.read_time) - self.assertEqual(nt[5], nt.write_time) - if LINUX: - self.assertEqual(nt[6], nt.read_merged_count) - self.assertEqual(nt[7], nt.write_merged_count) - self.assertEqual(nt[8], nt.busy_time) - elif FREEBSD: - self.assertEqual(nt[6], nt.busy_time) - for name in nt._fields: - assert getattr(nt, name) >= 0, nt - - ret = psutil.disk_io_counters(perdisk=False) - assert ret is not None, "no disks on this system?" - check_ntuple(ret) - ret = psutil.disk_io_counters(perdisk=True) - # make sure there are no duplicates - self.assertEqual(len(ret), len(set(ret))) - for key in ret: - assert key, key - check_ntuple(ret[key]) - - def test_disk_io_counters_no_disks(self): - # Emulate a case where no disks are installed, see: - # https://github.com/giampaolo/psutil/issues/1062 - with mock.patch('psutil._psplatform.disk_io_counters', - return_value={}) as m: - self.assertIsNone(psutil.disk_io_counters(perdisk=False)) - self.assertEqual(psutil.disk_io_counters(perdisk=True), {}) - assert m.called - - -class TestNetAPIs(unittest.TestCase): - - @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) - self.assertEqual(nt[1], nt.bytes_recv) - self.assertEqual(nt[2], nt.packets_sent) - self.assertEqual(nt[3], nt.packets_recv) - self.assertEqual(nt[4], nt.errin) - self.assertEqual(nt[5], nt.errout) - self.assertEqual(nt[6], nt.dropin) - self.assertEqual(nt[7], nt.dropout) - assert nt.bytes_sent >= 0, nt - assert nt.bytes_recv >= 0, nt - assert nt.packets_sent >= 0, nt - assert nt.packets_recv >= 0, nt - assert nt.errin >= 0, nt - assert nt.errout >= 0, nt - assert nt.dropin >= 0, nt - assert nt.dropout >= 0, nt - - ret = psutil.net_io_counters(pernic=False) - check_ntuple(ret) - ret = psutil.net_io_counters(pernic=True) - self.assertNotEqual(ret, []) - for key in ret: - self.assertTrue(key) - 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 - with mock.patch('psutil._psplatform.net_io_counters', - return_value={}) as m: - self.assertIsNone(psutil.net_io_counters(pernic=False)) - self.assertEqual(psutil.net_io_counters(pernic=True), {}) - assert m.called - - def test_net_if_addrs(self): - nics = psutil.net_if_addrs() - assert nics, nics - - nic_stats = psutil.net_if_stats() - - # Not reliable on all platforms (net_if_addrs() reports more - # interfaces). - # self.assertEqual(sorted(nics.keys()), - # sorted(psutil.net_io_counters(pernic=True).keys())) - - families = set([socket.AF_INET, socket.AF_INET6, psutil.AF_LINK]) - for nic, addrs in nics.items(): - self.assertIsInstance(nic, str) - self.assertEqual(len(set(addrs)), len(addrs)) - for addr in addrs: - self.assertIsInstance(addr.family, int) - self.assertIsInstance(addr.address, str) - self.assertIsInstance(addr.netmask, (str, type(None))) - self.assertIsInstance(addr.broadcast, (str, type(None))) - self.assertIn(addr.family, families) - if sys.version_info >= (3, 4): - self.assertIsInstance(addr.family, enum.IntEnum) - if nic_stats[nic].isup: - # Do not test binding to addresses of interfaces - # that are down - if addr.family == socket.AF_INET: - s = socket.socket(addr.family) - with contextlib.closing(s): - s.bind((addr.address, 0)) - elif addr.family == socket.AF_INET6: - info = socket.getaddrinfo( - addr.address, 0, socket.AF_INET6, - socket.SOCK_STREAM, 0, socket.AI_PASSIVE)[0] - af, socktype, proto, canonname, sa = info - s = socket.socket(af, socktype, proto) - with contextlib.closing(s): - s.bind(sa) - for ip in (addr.address, addr.netmask, addr.broadcast, - addr.ptp): - if ip is not None: - # TODO: skip AF_INET6 for now because I get: - # AddressValueError: Only hex digits permitted in - # u'c6f3%lxcbr0' in u'fe80::c8e0:fff:fe54:c6f3%lxcbr0' - if addr.family != socket.AF_INET6: - check_net_address(ip, addr.family) - # broadcast and ptp addresses are mutually exclusive - if addr.broadcast: - self.assertIsNone(addr.ptp) - elif addr.ptp: - self.assertIsNone(addr.broadcast) - - if BSD or MACOS or SUNOS: - if hasattr(socket, "AF_LINK"): - self.assertEqual(psutil.AF_LINK, socket.AF_LINK) - elif LINUX: - self.assertEqual(psutil.AF_LINK, socket.AF_PACKET) - elif WINDOWS: - self.assertEqual(psutil.AF_LINK, -1) - - def test_net_if_addrs_mac_null_bytes(self): - # Simulate that the underlying C function returns an incomplete - # MAC address. psutil is supposed to fill it with null bytes. - # https://github.com/giampaolo/psutil/issues/786 - if POSIX: - ret = [('em1', psutil.AF_LINK, '06:3d:29', None, None, None)] - else: - ret = [('em1', -1, '06-3d-29', None, None, None)] - with mock.patch('psutil._psplatform.net_if_addrs', - return_value=ret) as m: - addr = psutil.net_if_addrs()['em1'][0] - assert m.called - if POSIX: - self.assertEqual(addr.address, '06:3d:29:00:00:00') - else: - self.assertEqual(addr.address, '06-3d-29-00-00-00') - - @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") # raises EPERM - def test_net_if_stats(self): - nics = psutil.net_if_stats() - assert nics, nics - all_duplexes = (psutil.NIC_DUPLEX_FULL, - psutil.NIC_DUPLEX_HALF, - psutil.NIC_DUPLEX_UNKNOWN) - for name, stats in nics.items(): - self.assertIsInstance(name, str) - isup, duplex, speed, mtu = stats - self.assertIsInstance(isup, bool) - self.assertIn(duplex, all_duplexes) - self.assertIn(duplex, all_duplexes) - self.assertGreaterEqual(speed, 0) - self.assertGreaterEqual(mtu, 0) - - @unittest.skipIf(not (LINUX or BSD or MACOS), - "LINUX or BSD or MACOS specific") - def test_net_if_stats_enodev(self): - # See: https://github.com/giampaolo/psutil/issues/1279 - with mock.patch('psutil._psutil_posix.net_if_mtu', - side_effect=OSError(errno.ENODEV, "")) as m: - ret = psutil.net_if_stats() - self.assertEqual(ret, {}) - assert m.called - - -class TestSensorsAPIs(unittest.TestCase): - - @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") - def test_sensors_temperatures(self): - temps = psutil.sensors_temperatures() - for name, entries in temps.items(): - self.assertIsInstance(name, str) - for entry in entries: - self.assertIsInstance(entry.label, str) - if entry.current is not None: - self.assertGreaterEqual(entry.current, 0) - if entry.high is not None: - self.assertGreaterEqual(entry.high, 0) - if entry.critical is not None: - self.assertGreaterEqual(entry.critical, 0) - - @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") - def test_sensors_temperatures_fahreneit(self): - d = {'coretemp': [('label', 50.0, 60.0, 70.0)]} - with mock.patch("psutil._psplatform.sensors_temperatures", - return_value=d) as m: - temps = psutil.sensors_temperatures( - fahrenheit=True)['coretemp'][0] - assert m.called - self.assertEqual(temps.current, 122.0) - self.assertEqual(temps.high, 140.0) - self.assertEqual(temps.critical, 158.0) - - @unittest.skipIf(not HAS_SENSORS_BATTERY, "not supported") - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_sensors_battery(self): - ret = psutil.sensors_battery() - self.assertGreaterEqual(ret.percent, 0) - self.assertLessEqual(ret.percent, 100) - if ret.secsleft not in (psutil.POWER_TIME_UNKNOWN, - psutil.POWER_TIME_UNLIMITED): - self.assertGreaterEqual(ret.secsleft, 0) - else: - if ret.secsleft == psutil.POWER_TIME_UNLIMITED: - self.assertTrue(ret.power_plugged) - self.assertIsInstance(ret.power_plugged, bool) - - @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") - def test_sensors_fans(self): - fans = psutil.sensors_fans() - for name, entries in fans.items(): - self.assertIsInstance(name, str) - for entry in entries: - self.assertIsInstance(entry.label, str) - self.assertIsInstance(entry.current, (int, long)) - self.assertGreaterEqual(entry.current, 0) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_unicode.py b/third_party/python/psutil/psutil/tests/test_unicode.py deleted file mode 100755 index ac2d4f69e0aa..000000000000 --- a/third_party/python/psutil/psutil/tests/test_unicode.py +++ /dev/null @@ -1,372 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# 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. - -""" -Notes about unicode handling in psutil -====================================== - -Starting from version 5.3.0 psutil adds unicode support, see: -https://github.com/giampaolo/psutil/issues/1040 -The notes below apply to *any* API returning a string such as -process exe(), cwd() or username(): - -* all strings are encoded by using the OS filesystem encoding - (sys.getfilesystemencoding()) which varies depending on the platform - (e.g. "UTF-8" on macOS, "mbcs" on Win) -* no API call is supposed to crash with UnicodeDecodeError -* instead, in case of badly encoded data returned by the OS, the - following error handlers are used to replace the corrupted characters in - the string: - * Python 3: sys.getfilesystemencodeerrors() (PY 3.6+) or - "surrogatescape" on POSIX and "replace" on Windows - * Python 2: "replace" -* on Python 2 all APIs return bytes (str type), never unicode -* on Python 2, you can go back to unicode by doing: - - >>> unicode(p.exe(), sys.getdefaultencoding(), errors="replace") - -For a detailed explanation of how psutil handles unicode see #1040. - -Tests -===== - -List of APIs returning or dealing with a string: -('not tested' means they are not tested to deal with non-ASCII strings): - -* Process.cmdline() -* Process.connections('unix') -* Process.cwd() -* Process.environ() -* Process.exe() -* Process.memory_maps() -* Process.name() -* Process.open_files() -* Process.username() (not tested) - -* disk_io_counters() (not tested) -* disk_partitions() (not tested) -* disk_usage(str) -* net_connections('unix') -* net_if_addrs() (not tested) -* net_if_stats() (not tested) -* net_io_counters() (not tested) -* sensors_fans() (not tested) -* sensors_temperatures() (not tested) -* users() (not tested) - -* WindowsService.binpath() (not tested) -* WindowsService.description() (not tested) -* WindowsService.display_name() (not tested) -* WindowsService.name() (not tested) -* WindowsService.status() (not tested) -* WindowsService.username() (not tested) - -In here we create a unicode path with a funky non-ASCII name and (where -possible) make psutil return it back (e.g. on name(), exe(), open_files(), -etc.) and make sure that: - -* psutil never crashes with UnicodeDecodeError -* the returned path matches -""" - -import os -import traceback -import warnings -from contextlib import closing - -from psutil import BSD -from psutil import MACOS -from psutil import OPENBSD -from psutil import POSIX -from psutil import WINDOWS -from psutil._compat import PY3 -from psutil._compat import u -from psutil.tests import APPVEYOR -from psutil.tests import CIRRUS -from psutil.tests import ASCII_FS -from psutil.tests import bind_unix_socket -from psutil.tests import chdir -from psutil.tests import copyload_shared_lib -from psutil.tests import create_exe -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_CONNECTIONS_UNIX -from psutil.tests import HAS_ENVIRON -from psutil.tests import HAS_MEMORY_MAPS -from psutil.tests import PYPY -from psutil.tests import reap_children -from psutil.tests import safe_mkdir -from psutil.tests import safe_rmpath as _safe_rmpath -from psutil.tests import skip_on_access_denied -from psutil.tests import TESTFILE_PREFIX -from psutil.tests import TESTFN -from psutil.tests import TESTFN_UNICODE -from psutil.tests import TRAVIS -from psutil.tests import unittest -from psutil.tests import unix_socket_path -import psutil - - -def safe_rmpath(path): - if APPVEYOR: - # TODO - this is quite random and I'm not sure why it happens, - # nor I can reproduce it locally: - # https://ci.appveyor.com/project/giampaolo/psutil/build/job/ - # jiq2cgd6stsbtn60 - # safe_rmpath() happens after reap_children() so this is weird - # Perhaps wait_procs() on Windows is broken? Maybe because - # of STILL_ACTIVE? - # https://github.com/giampaolo/psutil/blob/ - # 68c7a70728a31d8b8b58f4be6c4c0baa2f449eda/psutil/arch/ - # windows/process_info.c#L146 - try: - return _safe_rmpath(path) - except WindowsError: - traceback.print_exc() - else: - return _safe_rmpath(path) - - -def subprocess_supports_unicode(name): - """Return True if both the fs and the subprocess module can - deal with a unicode file name. - """ - if PY3: - return True - try: - safe_rmpath(name) - create_exe(name) - get_test_subprocess(cmd=[name]) - except UnicodeEncodeError: - return False - else: - return True - finally: - reap_children() - - -# An invalid unicode string. -if PY3: - INVALID_NAME = (TESTFN.encode('utf8') + b"f\xc0\x80").decode( - 'utf8', 'surrogateescape') -else: - INVALID_NAME = TESTFN + "f\xc0\x80" - - -# =================================================================== -# FS APIs -# =================================================================== - - -class _BaseFSAPIsTests(object): - funky_name = None - - @classmethod - def setUpClass(cls): - safe_rmpath(cls.funky_name) - create_exe(cls.funky_name) - - @classmethod - def tearDownClass(cls): - reap_children() - safe_rmpath(cls.funky_name) - - def tearDown(self): - reap_children() - - def expect_exact_path_match(self): - raise NotImplementedError("must be implemented in subclass") - - def test_proc_exe(self): - subp = get_test_subprocess(cmd=[self.funky_name]) - p = psutil.Process(subp.pid) - exe = p.exe() - self.assertIsInstance(exe, str) - if self.expect_exact_path_match(): - self.assertEqual(os.path.normcase(exe), - os.path.normcase(self.funky_name)) - - def test_proc_name(self): - subp = get_test_subprocess(cmd=[self.funky_name]) - name = psutil.Process(subp.pid).name() - self.assertIsInstance(name, str) - if self.expect_exact_path_match(): - self.assertEqual(name, os.path.basename(self.funky_name)) - - def test_proc_cmdline(self): - subp = get_test_subprocess(cmd=[self.funky_name]) - p = psutil.Process(subp.pid) - cmdline = p.cmdline() - for part in cmdline: - self.assertIsInstance(part, str) - if self.expect_exact_path_match(): - self.assertEqual(cmdline, [self.funky_name]) - - def test_proc_cwd(self): - dname = self.funky_name + "2" - self.addCleanup(safe_rmpath, dname) - safe_mkdir(dname) - with chdir(dname): - p = psutil.Process() - cwd = p.cwd() - self.assertIsInstance(p.cwd(), str) - if self.expect_exact_path_match(): - self.assertEqual(cwd, dname) - - @unittest.skipIf(PYPY and WINDOWS, "fails on PYPY + WINDOWS") - def test_proc_open_files(self): - p = psutil.Process() - start = set(p.open_files()) - with open(self.funky_name, 'rb'): - new = set(p.open_files()) - path = (new - start).pop().path - self.assertIsInstance(path, str) - if BSD and not path: - # XXX - see https://github.com/giampaolo/psutil/issues/595 - return self.skipTest("open_files on BSD is broken") - if self.expect_exact_path_match(): - self.assertEqual(os.path.normcase(path), - os.path.normcase(self.funky_name)) - - @unittest.skipIf(not POSIX, "POSIX only") - def test_proc_connections(self): - suffix = os.path.basename(self.funky_name) - with unix_socket_path(suffix=suffix) as name: - try: - sock = bind_unix_socket(name) - except UnicodeEncodeError: - if PY3: - raise - else: - raise unittest.SkipTest("not supported") - with closing(sock): - conn = psutil.Process().connections('unix')[0] - self.assertIsInstance(conn.laddr, str) - # AF_UNIX addr not set on OpenBSD - if not OPENBSD and not CIRRUS: # XXX - self.assertEqual(conn.laddr, name) - - @unittest.skipIf(not POSIX, "POSIX only") - @unittest.skipIf(not HAS_CONNECTIONS_UNIX, "can't list UNIX sockets") - @skip_on_access_denied() - def test_net_connections(self): - def find_sock(cons): - for conn in cons: - if os.path.basename(conn.laddr).startswith(TESTFILE_PREFIX): - return conn - raise ValueError("connection not found") - - suffix = os.path.basename(self.funky_name) - with unix_socket_path(suffix=suffix) as name: - try: - sock = bind_unix_socket(name) - except UnicodeEncodeError: - if PY3: - raise - else: - raise unittest.SkipTest("not supported") - with closing(sock): - cons = psutil.net_connections(kind='unix') - # AF_UNIX addr not set on OpenBSD - if not OPENBSD: - conn = find_sock(cons) - self.assertIsInstance(conn.laddr, str) - self.assertEqual(conn.laddr, name) - - def test_disk_usage(self): - dname = self.funky_name + "2" - self.addCleanup(safe_rmpath, dname) - safe_mkdir(dname) - psutil.disk_usage(dname) - - @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") - @unittest.skipIf(not PY3, "ctypes does not support unicode on PY2") - @unittest.skipIf(PYPY and WINDOWS, - "copyload_shared_lib() unsupported on PYPY + WINDOWS") - def test_memory_maps(self): - # XXX: on Python 2, using ctypes.CDLL with a unicode path - # opens a message box which blocks the test run. - with copyload_shared_lib(dst_prefix=self.funky_name) as funky_path: - def normpath(p): - return os.path.realpath(os.path.normcase(p)) - libpaths = [normpath(x.path) - for x in psutil.Process().memory_maps()] - # ...just to have a clearer msg in case of failure - libpaths = [x for x in libpaths if TESTFILE_PREFIX in x] - self.assertIn(normpath(funky_path), libpaths) - for path in libpaths: - self.assertIsInstance(path, str) - - -# https://travis-ci.org/giampaolo/psutil/jobs/440073249 -@unittest.skipIf(PYPY and TRAVIS, "unreliable on PYPY + TRAVIS") -@unittest.skipIf(MACOS and TRAVIS, "unreliable on TRAVIS") # TODO -@unittest.skipIf(ASCII_FS, "ASCII fs") -@unittest.skipIf(not subprocess_supports_unicode(TESTFN_UNICODE), - "subprocess can't deal with unicode") -class TestFSAPIs(_BaseFSAPIsTests, unittest.TestCase): - """Test FS APIs with a funky, valid, UTF8 path name.""" - funky_name = TESTFN_UNICODE - - @classmethod - def expect_exact_path_match(cls): - # Do not expect psutil to correctly handle unicode paths on - # Python 2 if os.listdir() is not able either. - here = '.' if isinstance(cls.funky_name, str) else u('.') - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - return cls.funky_name in os.listdir(here) - - -@unittest.skipIf(PYPY and TRAVIS, "unreliable on PYPY + TRAVIS") -@unittest.skipIf(MACOS and TRAVIS, "unreliable on TRAVIS") # TODO -@unittest.skipIf(PYPY, "unreliable on PYPY") -@unittest.skipIf(not subprocess_supports_unicode(INVALID_NAME), - "subprocess can't deal with invalid unicode") -class TestFSAPIsWithInvalidPath(_BaseFSAPIsTests, unittest.TestCase): - """Test FS APIs with a funky, invalid path name.""" - funky_name = INVALID_NAME - - @classmethod - def expect_exact_path_match(cls): - # Invalid unicode names are supposed to work on Python 2. - return True - - -# =================================================================== -# Non fs APIs -# =================================================================== - - -class TestNonFSAPIS(unittest.TestCase): - """Unicode tests for non fs-related APIs.""" - - def tearDown(self): - reap_children() - - @unittest.skipIf(not HAS_ENVIRON, "not supported") - @unittest.skipIf(PYPY and WINDOWS, "segfaults on PYPY + WINDOWS") - def test_proc_environ(self): - # Note: differently from others, this test does not deal - # with fs paths. On Python 2 subprocess module is broken as - # it's not able to handle with non-ASCII env vars, so - # we use "è", which is part of the extended ASCII table - # (unicode point <= 255). - env = os.environ.copy() - funky_str = TESTFN_UNICODE if PY3 else 'è' - env['FUNNY_ARG'] = funky_str - sproc = get_test_subprocess(env=env) - p = psutil.Process(sproc.pid) - env = p.environ() - for k, v in env.items(): - self.assertIsInstance(k, str) - self.assertIsInstance(v, str) - self.assertEqual(env['FUNNY_ARG'], funky_str) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/psutil/tests/test_windows.py b/third_party/python/psutil/psutil/tests/test_windows.py deleted file mode 100755 index f68885d0ca3d..000000000000 --- a/third_party/python/psutil/psutil/tests/test_windows.py +++ /dev/null @@ -1,870 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: UTF-8 -* - -# 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. - -"""Windows specific tests.""" - -import datetime -import errno -import glob -import os -import platform -import re -import signal -import subprocess -import sys -import time -import warnings - -import psutil -from psutil import WINDOWS -from psutil._compat import FileNotFoundError -from psutil.tests import APPVEYOR -from psutil.tests import get_test_subprocess -from psutil.tests import HAS_BATTERY -from psutil.tests import mock -from psutil.tests import PY3 -from psutil.tests import PYPY -from psutil.tests import reap_children -from psutil.tests import retry_on_failure -from psutil.tests import sh -from psutil.tests import unittest - - -if WINDOWS and not PYPY: - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - import win32api # requires "pip install pypiwin32" - import win32con - import win32process - import wmi # requires "pip install wmi" / "make setup-dev-env" - - -cext = psutil._psplatform.cext - -# are we a 64 bit process -IS_64_BIT = sys.maxsize > 2**32 - - -def wrap_exceptions(fun): - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except OSError as err: - from psutil._pswindows import ACCESS_DENIED_SET - if err.errno in ACCESS_DENIED_SET: - raise psutil.AccessDenied(None, None) - if err.errno == errno.ESRCH: - raise psutil.NoSuchProcess(None, None) - raise - return wrapper - - -@unittest.skipIf(PYPY, "pywin32 not available on PYPY") # skip whole module -class TestCase(unittest.TestCase): - pass - - -# =================================================================== -# System APIs -# =================================================================== - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestCpuAPIs(TestCase): - - @unittest.skipIf('NUMBER_OF_PROCESSORS' not in os.environ, - 'NUMBER_OF_PROCESSORS env var is not available') - def test_cpu_count_vs_NUMBER_OF_PROCESSORS(self): - # Will likely fail on many-cores systems: - # https://stackoverflow.com/questions/31209256 - num_cpus = int(os.environ['NUMBER_OF_PROCESSORS']) - self.assertEqual(num_cpus, psutil.cpu_count()) - - def test_cpu_count_vs_GetSystemInfo(self): - # Will likely fail on many-cores systems: - # https://stackoverflow.com/questions/31209256 - sys_value = win32api.GetSystemInfo()[5] - psutil_value = psutil.cpu_count() - self.assertEqual(sys_value, psutil_value) - - def test_cpu_count_logical_vs_wmi(self): - w = wmi.WMI() - proc = w.Win32_Processor()[0] - self.assertEqual(psutil.cpu_count(), proc.NumberOfLogicalProcessors) - - def test_cpu_count_phys_vs_wmi(self): - w = wmi.WMI() - proc = w.Win32_Processor()[0] - self.assertEqual(psutil.cpu_count(logical=False), proc.NumberOfCores) - - def test_cpu_count_vs_cpu_times(self): - self.assertEqual(psutil.cpu_count(), - len(psutil.cpu_times(percpu=True))) - - def test_cpu_freq(self): - w = wmi.WMI() - proc = w.Win32_Processor()[0] - self.assertEqual(proc.CurrentClockSpeed, psutil.cpu_freq().current) - self.assertEqual(proc.MaxClockSpeed, psutil.cpu_freq().max) - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestSystemAPIs(TestCase): - - def test_nic_names(self): - out = sh('ipconfig /all') - nics = psutil.net_io_counters(pernic=True).keys() - for nic in nics: - if "pseudo-interface" in nic.replace(' ', '-').lower(): - continue - if nic not in out: - self.fail( - "%r nic wasn't found in 'ipconfig /all' output" % nic) - - def test_total_phymem(self): - w = wmi.WMI().Win32_ComputerSystem()[0] - self.assertEqual(int(w.TotalPhysicalMemory), - psutil.virtual_memory().total) - - # @unittest.skipIf(wmi is None, "wmi module is not installed") - # def test__UPTIME(self): - # # _UPTIME constant is not public but it is used internally - # # as value to return for pid 0 creation time. - # # WMI behaves the same. - # w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - # p = psutil.Process(0) - # wmic_create = str(w.CreationDate.split('.')[0]) - # psutil_create = time.strftime("%Y%m%d%H%M%S", - # time.localtime(p.create_time())) - - # Note: this test is not very reliable - @unittest.skipIf(APPVEYOR, "test not relieable on appveyor") - @retry_on_failure() - def test_pids(self): - # Note: this test might fail if the OS is starting/killing - # other processes in the meantime - w = wmi.WMI().Win32_Process() - wmi_pids = set([x.ProcessId for x in w]) - psutil_pids = set(psutil.pids()) - self.assertEqual(wmi_pids, psutil_pids) - - @retry_on_failure() - def test_disks(self): - ps_parts = psutil.disk_partitions(all=True) - wmi_parts = wmi.WMI().Win32_LogicalDisk() - for ps_part in ps_parts: - for wmi_part in wmi_parts: - if ps_part.device.replace('\\', '') == wmi_part.DeviceID: - if not ps_part.mountpoint: - # this is usually a CD-ROM with no disk inserted - break - if 'cdrom' in ps_part.opts: - break - try: - usage = psutil.disk_usage(ps_part.mountpoint) - except FileNotFoundError: - # usually this is the floppy - break - self.assertEqual(usage.total, int(wmi_part.Size)) - wmi_free = int(wmi_part.FreeSpace) - self.assertEqual(usage.free, wmi_free) - # 10 MB tollerance - if abs(usage.free - wmi_free) > 10 * 1024 * 1024: - self.fail("psutil=%s, wmi=%s" % ( - usage.free, wmi_free)) - break - else: - self.fail("can't find partition %s" % repr(ps_part)) - - def test_disk_usage(self): - for disk in psutil.disk_partitions(): - if 'cdrom' in disk.opts: - continue - sys_value = win32api.GetDiskFreeSpaceEx(disk.mountpoint) - psutil_value = psutil.disk_usage(disk.mountpoint) - self.assertAlmostEqual(sys_value[0], psutil_value.free, - delta=1024 * 1024) - self.assertAlmostEqual(sys_value[1], psutil_value.total, - delta=1024 * 1024) - self.assertEqual(psutil_value.used, - psutil_value.total - psutil_value.free) - - def test_disk_partitions(self): - sys_value = [ - x + '\\' for x in win32api.GetLogicalDriveStrings().split("\\\x00") - if x and not x.startswith('A:')] - psutil_value = [x.mountpoint for x in psutil.disk_partitions(all=True)] - self.assertEqual(sys_value, psutil_value) - - def test_net_if_stats(self): - ps_names = set(cext.net_if_stats()) - wmi_adapters = wmi.WMI().Win32_NetworkAdapter() - wmi_names = set() - for wmi_adapter in wmi_adapters: - wmi_names.add(wmi_adapter.Name) - wmi_names.add(wmi_adapter.NetConnectionID) - self.assertTrue(ps_names & wmi_names, - "no common entries in %s, %s" % (ps_names, wmi_names)) - - def test_boot_time(self): - wmi_os = wmi.WMI().Win32_OperatingSystem() - wmi_btime_str = wmi_os[0].LastBootUpTime.split('.')[0] - wmi_btime_dt = datetime.datetime.strptime( - wmi_btime_str, "%Y%m%d%H%M%S") - psutil_dt = datetime.datetime.fromtimestamp(psutil.boot_time()) - diff = abs((wmi_btime_dt - psutil_dt).total_seconds()) - self.assertLessEqual(diff, 3) - - def test_boot_time_fluctuation(self): - # https://github.com/giampaolo/psutil/issues/1007 - with mock.patch('psutil._pswindows.cext.boot_time', return_value=5): - self.assertEqual(psutil.boot_time(), 5) - with mock.patch('psutil._pswindows.cext.boot_time', return_value=4): - self.assertEqual(psutil.boot_time(), 5) - with mock.patch('psutil._pswindows.cext.boot_time', return_value=6): - self.assertEqual(psutil.boot_time(), 5) - with mock.patch('psutil._pswindows.cext.boot_time', return_value=333): - self.assertEqual(psutil.boot_time(), 333) - - -# =================================================================== -# sensors_battery() -# =================================================================== - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestSensorsBattery(TestCase): - - def test_has_battery(self): - if win32api.GetPwrCapabilities()['SystemBatteriesPresent']: - self.assertIsNotNone(psutil.sensors_battery()) - else: - self.assertIsNone(psutil.sensors_battery()) - - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_percent(self): - w = wmi.WMI() - battery_wmi = w.query('select * from Win32_Battery')[0] - battery_psutil = psutil.sensors_battery() - self.assertAlmostEqual( - battery_psutil.percent, battery_wmi.EstimatedChargeRemaining, - delta=1) - - @unittest.skipIf(not HAS_BATTERY, "no battery") - def test_power_plugged(self): - w = wmi.WMI() - battery_wmi = w.query('select * from Win32_Battery')[0] - battery_psutil = psutil.sensors_battery() - # Status codes: - # https://msdn.microsoft.com/en-us/library/aa394074(v=vs.85).aspx - self.assertEqual(battery_psutil.power_plugged, - battery_wmi.BatteryStatus == 2) - - def test_emulate_no_battery(self): - with mock.patch("psutil._pswindows.cext.sensors_battery", - return_value=(0, 128, 0, 0)) as m: - self.assertIsNone(psutil.sensors_battery()) - assert m.called - - def test_emulate_power_connected(self): - with mock.patch("psutil._pswindows.cext.sensors_battery", - return_value=(1, 0, 0, 0)) as m: - self.assertEqual(psutil.sensors_battery().secsleft, - psutil.POWER_TIME_UNLIMITED) - assert m.called - - def test_emulate_power_charging(self): - with mock.patch("psutil._pswindows.cext.sensors_battery", - return_value=(0, 8, 0, 0)) as m: - self.assertEqual(psutil.sensors_battery().secsleft, - psutil.POWER_TIME_UNLIMITED) - assert m.called - - def test_emulate_secs_left_unknown(self): - with mock.patch("psutil._pswindows.cext.sensors_battery", - return_value=(0, 0, 0, -1)) as m: - self.assertEqual(psutil.sensors_battery().secsleft, - psutil.POWER_TIME_UNKNOWN) - assert m.called - - -# =================================================================== -# Process APIs -# =================================================================== - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestProcess(TestCase): - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_issue_24(self): - p = psutil.Process(0) - self.assertRaises(psutil.AccessDenied, p.kill) - - def test_special_pid(self): - p = psutil.Process(4) - self.assertEqual(p.name(), 'System') - # use __str__ to access all common Process properties to check - # that nothing strange happens - str(p) - p.username() - self.assertTrue(p.create_time() >= 0.0) - try: - rss, vms = p.memory_info()[:2] - except psutil.AccessDenied: - # expected on Windows Vista and Windows 7 - if not platform.uname()[1] in ('vista', 'win-7', 'win7'): - raise - else: - self.assertTrue(rss > 0) - - def test_send_signal(self): - p = psutil.Process(self.pid) - self.assertRaises(ValueError, p.send_signal, signal.SIGINT) - - def test_num_handles_increment(self): - p = psutil.Process(os.getpid()) - before = p.num_handles() - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, os.getpid()) - after = p.num_handles() - self.assertEqual(after, before + 1) - win32api.CloseHandle(handle) - self.assertEqual(p.num_handles(), before) - - def test_handles_leak(self): - # Call all Process methods and make sure no handles are left - # open. This is here mainly to make sure functions using - # OpenProcess() always call CloseHandle(). - def call(p, attr): - attr = getattr(p, name, None) - if attr is not None and callable(attr): - attr() - else: - attr - - p = psutil.Process(self.pid) - failures = [] - for name in dir(psutil.Process): - if name.startswith('_') \ - or name in ('terminate', 'kill', 'suspend', 'resume', - 'nice', 'send_signal', 'wait', 'children', - 'as_dict', 'memory_info_ex'): - continue - else: - try: - call(p, name) - num1 = p.num_handles() - call(p, name) - num2 = p.num_handles() - except (psutil.NoSuchProcess, psutil.AccessDenied): - pass - else: - if num2 > num1: - fail = \ - "failure while processing Process.%s method " \ - "(before=%s, after=%s)" % (name, num1, num2) - failures.append(fail) - if failures: - self.fail('\n' + '\n'.join(failures)) - - @unittest.skipIf(not sys.version_info >= (2, 7), - "CTRL_* signals not supported") - def test_ctrl_signals(self): - p = psutil.Process(get_test_subprocess().pid) - p.send_signal(signal.CTRL_C_EVENT) - p.send_signal(signal.CTRL_BREAK_EVENT) - p.kill() - p.wait() - self.assertRaises(psutil.NoSuchProcess, - p.send_signal, signal.CTRL_C_EVENT) - self.assertRaises(psutil.NoSuchProcess, - p.send_signal, signal.CTRL_BREAK_EVENT) - - def test_username(self): - self.assertEqual(psutil.Process().username(), - win32api.GetUserNameEx(win32con.NameSamCompatible)) - - def test_cmdline(self): - sys_value = re.sub(' +', ' ', win32api.GetCommandLine()).strip() - psutil_value = ' '.join(psutil.Process().cmdline()) - self.assertEqual(sys_value, psutil_value) - - # XXX - occasional failures - - # def test_cpu_times(self): - # handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - # win32con.FALSE, os.getpid()) - # self.addCleanup(win32api.CloseHandle, handle) - # sys_value = win32process.GetProcessTimes(handle) - # psutil_value = psutil.Process().cpu_times() - # self.assertAlmostEqual( - # psutil_value.user, sys_value['UserTime'] / 10000000.0, - # delta=0.2) - # self.assertAlmostEqual( - # psutil_value.user, sys_value['KernelTime'] / 10000000.0, - # delta=0.2) - - def test_nice(self): - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, os.getpid()) - self.addCleanup(win32api.CloseHandle, handle) - sys_value = win32process.GetPriorityClass(handle) - psutil_value = psutil.Process().nice() - self.assertEqual(psutil_value, sys_value) - - def test_memory_info(self): - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, self.pid) - self.addCleanup(win32api.CloseHandle, handle) - sys_value = win32process.GetProcessMemoryInfo(handle) - psutil_value = psutil.Process(self.pid).memory_info() - self.assertEqual( - sys_value['PeakWorkingSetSize'], psutil_value.peak_wset) - self.assertEqual( - sys_value['WorkingSetSize'], psutil_value.wset) - self.assertEqual( - sys_value['QuotaPeakPagedPoolUsage'], psutil_value.peak_paged_pool) - self.assertEqual( - sys_value['QuotaPagedPoolUsage'], psutil_value.paged_pool) - self.assertEqual( - sys_value['QuotaPeakNonPagedPoolUsage'], - psutil_value.peak_nonpaged_pool) - self.assertEqual( - sys_value['QuotaNonPagedPoolUsage'], psutil_value.nonpaged_pool) - self.assertEqual( - sys_value['PagefileUsage'], psutil_value.pagefile) - self.assertEqual( - sys_value['PeakPagefileUsage'], psutil_value.peak_pagefile) - - self.assertEqual(psutil_value.rss, psutil_value.wset) - self.assertEqual(psutil_value.vms, psutil_value.pagefile) - - def test_wait(self): - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, self.pid) - self.addCleanup(win32api.CloseHandle, handle) - p = psutil.Process(self.pid) - p.terminate() - psutil_value = p.wait() - sys_value = win32process.GetExitCodeProcess(handle) - self.assertEqual(psutil_value, sys_value) - - def test_cpu_affinity(self): - def from_bitmask(x): - return [i for i in range(64) if (1 << i) & x] - - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, self.pid) - self.addCleanup(win32api.CloseHandle, handle) - sys_value = from_bitmask( - win32process.GetProcessAffinityMask(handle)[0]) - psutil_value = psutil.Process(self.pid).cpu_affinity() - self.assertEqual(psutil_value, sys_value) - - def test_io_counters(self): - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, os.getpid()) - self.addCleanup(win32api.CloseHandle, handle) - sys_value = win32process.GetProcessIoCounters(handle) - psutil_value = psutil.Process().io_counters() - self.assertEqual( - psutil_value.read_count, sys_value['ReadOperationCount']) - self.assertEqual( - psutil_value.write_count, sys_value['WriteOperationCount']) - self.assertEqual( - psutil_value.read_bytes, sys_value['ReadTransferCount']) - self.assertEqual( - psutil_value.write_bytes, sys_value['WriteTransferCount']) - self.assertEqual( - psutil_value.other_count, sys_value['OtherOperationCount']) - self.assertEqual( - psutil_value.other_bytes, sys_value['OtherTransferCount']) - - def test_num_handles(self): - import ctypes - import ctypes.wintypes - PROCESS_QUERY_INFORMATION = 0x400 - handle = ctypes.windll.kernel32.OpenProcess( - PROCESS_QUERY_INFORMATION, 0, self.pid) - self.addCleanup(ctypes.windll.kernel32.CloseHandle, handle) - - hndcnt = ctypes.wintypes.DWORD() - ctypes.windll.kernel32.GetProcessHandleCount( - handle, ctypes.byref(hndcnt)) - sys_value = hndcnt.value - psutil_value = psutil.Process(self.pid).num_handles() - self.assertEqual(psutil_value, sys_value) - - def test_error_partial_copy(self): - # https://github.com/giampaolo/psutil/issues/875 - exc = WindowsError() - exc.winerror = 299 - with mock.patch("psutil._psplatform.cext.proc_cwd", side_effect=exc): - with mock.patch("time.sleep") as m: - p = psutil.Process() - self.assertRaises(psutil.AccessDenied, p.cwd) - self.assertGreaterEqual(m.call_count, 5) - - def test_exe(self): - # NtQuerySystemInformation succeeds if process is gone. Make sure - # it raises NSP for a non existent pid. - pid = psutil.pids()[-1] + 99999 - proc = psutil._psplatform.Process(pid) - self.assertRaises(psutil.NoSuchProcess, proc.exe) - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestProcessWMI(TestCase): - """Compare Process API results with WMI.""" - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_name(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - self.assertEqual(p.name(), w.Caption) - - def test_exe(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - # Note: wmi reports the exe as a lower case string. - # Being Windows paths case-insensitive we ignore that. - self.assertEqual(p.exe().lower(), w.ExecutablePath.lower()) - - def test_cmdline(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - self.assertEqual(' '.join(p.cmdline()), - w.CommandLine.replace('"', '')) - - def test_username(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - domain, _, username = w.GetOwner() - username = "%s\\%s" % (domain, username) - self.assertEqual(p.username(), username) - - def test_memory_rss(self): - time.sleep(0.1) - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - rss = p.memory_info().rss - self.assertEqual(rss, int(w.WorkingSetSize)) - - def test_memory_vms(self): - time.sleep(0.1) - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - vms = p.memory_info().vms - # http://msdn.microsoft.com/en-us/library/aa394372(VS.85).aspx - # ...claims that PageFileUsage is represented in Kilo - # bytes but funnily enough on certain platforms bytes are - # returned instead. - wmi_usage = int(w.PageFileUsage) - if (vms != wmi_usage) and (vms != wmi_usage * 1024): - self.fail("wmi=%s, psutil=%s" % (wmi_usage, vms)) - - def test_create_time(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - wmic_create = str(w.CreationDate.split('.')[0]) - psutil_create = time.strftime("%Y%m%d%H%M%S", - time.localtime(p.create_time())) - self.assertEqual(wmic_create, psutil_create) - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestDualProcessImplementation(TestCase): - """ - Certain APIs on Windows have 2 internal implementations, one - based on documented Windows APIs, another one based - NtQuerySystemInformation() which gets called as fallback in - case the first fails because of limited permission error. - Here we test that the two methods return the exact same value, - see: - https://github.com/giampaolo/psutil/issues/304 - """ - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_memory_info(self): - mem_1 = psutil.Process(self.pid).memory_info() - with mock.patch("psutil._psplatform.cext.proc_memory_info", - side_effect=OSError(errno.EPERM, "msg")) as fun: - mem_2 = psutil.Process(self.pid).memory_info() - self.assertEqual(len(mem_1), len(mem_2)) - for i in range(len(mem_1)): - self.assertGreaterEqual(mem_1[i], 0) - self.assertGreaterEqual(mem_2[i], 0) - self.assertAlmostEqual(mem_1[i], mem_2[i], delta=512) - assert fun.called - - def test_create_time(self): - ctime = psutil.Process(self.pid).create_time() - with mock.patch("psutil._psplatform.cext.proc_times", - side_effect=OSError(errno.EPERM, "msg")) as fun: - self.assertEqual(psutil.Process(self.pid).create_time(), ctime) - assert fun.called - - def test_cpu_times(self): - cpu_times_1 = psutil.Process(self.pid).cpu_times() - with mock.patch("psutil._psplatform.cext.proc_times", - side_effect=OSError(errno.EPERM, "msg")) as fun: - cpu_times_2 = psutil.Process(self.pid).cpu_times() - assert fun.called - self.assertAlmostEqual( - cpu_times_1.user, cpu_times_2.user, delta=0.01) - self.assertAlmostEqual( - cpu_times_1.system, cpu_times_2.system, delta=0.01) - - def test_io_counters(self): - io_counters_1 = psutil.Process(self.pid).io_counters() - with mock.patch("psutil._psplatform.cext.proc_io_counters", - side_effect=OSError(errno.EPERM, "msg")) as fun: - io_counters_2 = psutil.Process(self.pid).io_counters() - for i in range(len(io_counters_1)): - self.assertAlmostEqual( - io_counters_1[i], io_counters_2[i], delta=5) - assert fun.called - - def test_num_handles(self): - num_handles = psutil.Process(self.pid).num_handles() - with mock.patch("psutil._psplatform.cext.proc_num_handles", - side_effect=OSError(errno.EPERM, "msg")) as fun: - self.assertEqual(psutil.Process(self.pid).num_handles(), - num_handles) - assert fun.called - - def test_cmdline(self): - from psutil._pswindows import convert_oserror - for pid in psutil.pids(): - try: - a = cext.proc_cmdline(pid, use_peb=True) - b = cext.proc_cmdline(pid, use_peb=False) - except OSError as err: - err = convert_oserror(err) - if not isinstance(err, (psutil.AccessDenied, - psutil.NoSuchProcess)): - raise - else: - self.assertEqual(a, b) - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class RemoteProcessTestCase(TestCase): - """Certain functions require calling ReadProcessMemory. - This trivially works when called on the current process. - Check that this works on other processes, especially when they - have a different bitness. - """ - - @staticmethod - def find_other_interpreter(): - # find a python interpreter that is of the opposite bitness from us - code = "import sys; sys.stdout.write(str(sys.maxsize > 2**32))" - - # XXX: a different and probably more stable approach might be to access - # the registry but accessing 64 bit paths from a 32 bit process - for filename in glob.glob(r"C:\Python*\python.exe"): - proc = subprocess.Popen(args=[filename, "-c", code], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - output, _ = proc.communicate() - if output == str(not IS_64_BIT): - return filename - - @classmethod - def setUpClass(cls): - other_python = cls.find_other_interpreter() - - if other_python is None: - raise unittest.SkipTest( - "could not find interpreter with opposite bitness") - - if IS_64_BIT: - cls.python64 = sys.executable - cls.python32 = other_python - else: - cls.python64 = other_python - cls.python32 = sys.executable - - test_args = ["-c", "import sys; sys.stdin.read()"] - - def setUp(self): - env = os.environ.copy() - env["THINK_OF_A_NUMBER"] = str(os.getpid()) - self.proc32 = get_test_subprocess([self.python32] + self.test_args, - env=env, - stdin=subprocess.PIPE) - self.proc64 = get_test_subprocess([self.python64] + self.test_args, - env=env, - stdin=subprocess.PIPE) - - def tearDown(self): - self.proc32.communicate() - self.proc64.communicate() - reap_children() - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_cmdline_32(self): - p = psutil.Process(self.proc32.pid) - self.assertEqual(len(p.cmdline()), 3) - self.assertEqual(p.cmdline()[1:], self.test_args) - - def test_cmdline_64(self): - p = psutil.Process(self.proc64.pid) - self.assertEqual(len(p.cmdline()), 3) - self.assertEqual(p.cmdline()[1:], self.test_args) - - def test_cwd_32(self): - p = psutil.Process(self.proc32.pid) - self.assertEqual(p.cwd(), os.getcwd()) - - def test_cwd_64(self): - p = psutil.Process(self.proc64.pid) - self.assertEqual(p.cwd(), os.getcwd()) - - def test_environ_32(self): - p = psutil.Process(self.proc32.pid) - e = p.environ() - self.assertIn("THINK_OF_A_NUMBER", e) - self.assertEquals(e["THINK_OF_A_NUMBER"], str(os.getpid())) - - def test_environ_64(self): - p = psutil.Process(self.proc64.pid) - try: - p.environ() - except psutil.AccessDenied: - pass - - -# =================================================================== -# Windows services -# =================================================================== - - -@unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestServices(TestCase): - - def test_win_service_iter(self): - valid_statuses = set([ - "running", - "paused", - "start", - "pause", - "continue", - "stop", - "stopped", - ]) - valid_start_types = set([ - "automatic", - "manual", - "disabled", - ]) - valid_statuses = set([ - "running", - "paused", - "start_pending", - "pause_pending", - "continue_pending", - "stop_pending", - "stopped" - ]) - for serv in psutil.win_service_iter(): - data = serv.as_dict() - self.assertIsInstance(data['name'], str) - self.assertNotEqual(data['name'].strip(), "") - self.assertIsInstance(data['display_name'], str) - self.assertIsInstance(data['username'], str) - self.assertIn(data['status'], valid_statuses) - if data['pid'] is not None: - psutil.Process(data['pid']) - self.assertIsInstance(data['binpath'], str) - self.assertIsInstance(data['username'], str) - self.assertIsInstance(data['start_type'], str) - self.assertIn(data['start_type'], valid_start_types) - self.assertIn(data['status'], valid_statuses) - self.assertIsInstance(data['description'], str) - pid = serv.pid() - if pid is not None: - p = psutil.Process(pid) - self.assertTrue(p.is_running()) - # win_service_get - s = psutil.win_service_get(serv.name()) - # test __eq__ - self.assertEqual(serv, s) - - def test_win_service_get(self): - ERROR_SERVICE_DOES_NOT_EXIST = \ - psutil._psplatform.cext.ERROR_SERVICE_DOES_NOT_EXIST - ERROR_ACCESS_DENIED = psutil._psplatform.cext.ERROR_ACCESS_DENIED - - name = next(psutil.win_service_iter()).name() - with self.assertRaises(psutil.NoSuchProcess) as cm: - psutil.win_service_get(name + '???') - self.assertEqual(cm.exception.name, name + '???') - - # test NoSuchProcess - service = psutil.win_service_get(name) - if PY3: - args = (0, "msg", 0, ERROR_SERVICE_DOES_NOT_EXIST) - else: - args = (ERROR_SERVICE_DOES_NOT_EXIST, "msg") - exc = WindowsError(*args) - with mock.patch("psutil._psplatform.cext.winservice_query_status", - side_effect=exc): - self.assertRaises(psutil.NoSuchProcess, service.status) - with mock.patch("psutil._psplatform.cext.winservice_query_config", - side_effect=exc): - self.assertRaises(psutil.NoSuchProcess, service.username) - - # test AccessDenied - if PY3: - args = (0, "msg", 0, ERROR_ACCESS_DENIED) - else: - args = (ERROR_ACCESS_DENIED, "msg") - exc = WindowsError(*args) - with mock.patch("psutil._psplatform.cext.winservice_query_status", - side_effect=exc): - self.assertRaises(psutil.AccessDenied, service.status) - with mock.patch("psutil._psplatform.cext.winservice_query_config", - side_effect=exc): - self.assertRaises(psutil.AccessDenied, service.username) - - # test __str__ and __repr__ - self.assertIn(service.name(), str(service)) - self.assertIn(service.display_name(), str(service)) - self.assertIn(service.name(), repr(service)) - self.assertIn(service.display_name(), repr(service)) - - -if __name__ == '__main__': - from psutil.tests.runner import run - run(__file__) diff --git a/third_party/python/psutil/scripts/battery.py b/third_party/python/psutil/scripts/battery.py deleted file mode 100755 index 0da2b9588900..000000000000 --- a/third_party/python/psutil/scripts/battery.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Show battery information. - -$ python scripts/battery.py -charge: 74% -left: 2:11:31 -status: discharging -plugged in: no -""" - -from __future__ import print_function -import sys - -import psutil - - -def secs2hours(secs): - mm, ss = divmod(secs, 60) - hh, mm = divmod(mm, 60) - return "%d:%02d:%02d" % (hh, mm, ss) - - -def main(): - if not hasattr(psutil, "sensors_battery"): - return sys.exit("platform not supported") - batt = psutil.sensors_battery() - if batt is None: - return sys.exit("no battery is installed") - - print("charge: %s%%" % round(batt.percent, 2)) - if batt.power_plugged: - print("status: %s" % ( - "charging" if batt.percent < 100 else "fully charged")) - print("plugged in: yes") - else: - print("left: %s" % secs2hours(batt.secsleft)) - print("status: %s" % "discharging") - print("plugged in: no") - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/cpu_distribution.py b/third_party/python/psutil/scripts/cpu_distribution.py deleted file mode 100755 index 08997797c3d0..000000000000 --- a/third_party/python/psutil/scripts/cpu_distribution.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Shows CPU workload split across different CPUs. - -$ python scripts/cpu_workload.py -CPU 0 CPU 1 CPU 2 CPU 3 CPU 4 CPU 5 CPU 6 CPU 7 -19.8 20.6 18.2 15.8 6.9 17.3 5.0 20.4 -gvfsd pytho kwork chrom unity kwork kwork kwork -chrom chrom indic ibus- whoop nfsd (sd-p gvfsd -ibus- cat at-sp chrom Modem nfsd4 light upsta -ibus- iprt- ibus- nacl_ cfg80 kwork nfsd bluet -chrom irqba gpg-a chrom ext4- biose nfsd dio/n -chrom acpid bamfd nvidi kwork scsi_ sshd rpc.m -upsta rsysl dbus- nfsd biose scsi_ ext4- polki -rtkit avahi upowe Netwo scsi_ biose UVM T irq/9 -light rpcbi snapd cron ipv6_ biose kwork dbus- -agett kvm-i avahi kwork biose biose scsi_ syste -nfsd syste rpc.i biose biose kbloc kthro UVM g -nfsd kwork kwork biose vmsta kwork crypt kaudi -nfsd scsi_ charg biose md ksoft kwork kwork -memca biose ksmd ecryp ksoft watch migra nvme -therm biose kcomp kswap migra cpuhp watch biose -syste biose kdevt khuge watch cpuhp biose -led_w devfr kwork write cpuhp biose -rpcio oom_r ksoft kwork syste biose -kwork kwork watch migra acpi_ -biose ksoft cpuhp watch watch -biose migra cpuhp kinte -biose watch rcu_s netns -biose cpuhp kthre kwork -cpuhp ksoft -watch migra -rcu_b cpuhp -kwork -""" - -from __future__ import print_function -import collections -import os -import sys -import time - -import psutil -from psutil._compat import get_terminal_size - - -if not hasattr(psutil.Process, "cpu_num"): - sys.exit("platform not supported") - - -def clean_screen(): - if psutil.POSIX: - os.system('clear') - else: - os.system('cls') - - -def main(): - num_cpus = psutil.cpu_count() - if num_cpus > 8: - num_cpus = 8 # try to fit into screen - cpus_hidden = True - else: - cpus_hidden = False - - while True: - # header - clean_screen() - cpus_percent = psutil.cpu_percent(percpu=True) - for i in range(num_cpus): - print("CPU %-6i" % i, end="") - if cpus_hidden: - print(" (+ hidden)", end="") - - print() - for _ in range(num_cpus): - print("%-10s" % cpus_percent.pop(0), end="") - print() - - # processes - procs = collections.defaultdict(list) - for p in psutil.process_iter(['name', 'cpu_num']): - procs[p.info['cpu_num']].append(p.info['name'][:5]) - - curr_line = 3 - while True: - for num in range(num_cpus): - try: - pname = procs[num].pop() - except IndexError: - pname = "" - print("%-10s" % pname[:10], end="") - print() - curr_line += 1 - if curr_line >= get_terminal_size()[1]: - break - - time.sleep(1) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/disk_usage.py b/third_party/python/psutil/scripts/disk_usage.py deleted file mode 100755 index 901dbf8c226c..000000000000 --- a/third_party/python/psutil/scripts/disk_usage.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -List all mounted disk partitions a-la "df -h" command. - -$ python scripts/disk_usage.py -Device Total Used Free Use % Type Mount -/dev/sdb3 18.9G 14.7G 3.3G 77% ext4 / -/dev/sda6 345.9G 83.8G 244.5G 24% ext4 /home -/dev/sda1 296.0M 43.1M 252.9M 14% vfat /boot/efi -/dev/sda2 600.0M 312.4M 287.6M 52% fuseblk /media/Recovery -""" - -import sys -import os -import psutil -from psutil._common import bytes2human - - -def main(): - templ = "%-17s %8s %8s %8s %5s%% %9s %s" - print(templ % ("Device", "Total", "Used", "Free", "Use ", "Type", - "Mount")) - for part in psutil.disk_partitions(all=False): - if os.name == 'nt': - if 'cdrom' in part.opts or part.fstype == '': - # skip cd-rom drives with no disk in it; they may raise - # ENOENT, pop-up a Windows GUI error for a non-ready - # partition or just hang. - continue - usage = psutil.disk_usage(part.mountpoint) - print(templ % ( - part.device, - bytes2human(usage.total), - bytes2human(usage.used), - bytes2human(usage.free), - int(usage.percent), - part.fstype, - part.mountpoint)) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/third_party/python/psutil/scripts/fans.py b/third_party/python/psutil/scripts/fans.py deleted file mode 100755 index 179af6312c6f..000000000000 --- a/third_party/python/psutil/scripts/fans.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Show fans information. - -$ python fans.py -asus - cpu_fan 3200 RPM -""" - -from __future__ import print_function -import sys - -import psutil - - -def main(): - if not hasattr(psutil, "sensors_fans"): - return sys.exit("platform not supported") - fans = psutil.sensors_fans() - if not fans: - print("no fans detected") - return - for name, entries in fans.items(): - print(name) - for entry in entries: - print(" %-20s %s RPM" % (entry.label or name, entry.current)) - print() - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/free.py b/third_party/python/psutil/scripts/free.py deleted file mode 100755 index 000323c5ddcf..000000000000 --- a/third_party/python/psutil/scripts/free.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -A clone of 'free' cmdline utility. - -$ python scripts/free.py - total used free shared buffers cache -Mem: 10125520 8625996 1499524 0 349500 3307836 -Swap: 0 0 0 -""" - -import psutil - - -def main(): - virt = psutil.virtual_memory() - swap = psutil.swap_memory() - templ = "%-7s %10s %10s %10s %10s %10s %10s" - print(templ % ('', 'total', 'used', 'free', 'shared', 'buffers', 'cache')) - print(templ % ( - 'Mem:', - int(virt.total / 1024), - int(virt.used / 1024), - int(virt.free / 1024), - int(getattr(virt, 'shared', 0) / 1024), - int(getattr(virt, 'buffers', 0) / 1024), - int(getattr(virt, 'cached', 0) / 1024))) - print(templ % ( - 'Swap:', int(swap.total / 1024), - int(swap.used / 1024), - int(swap.free / 1024), - '', - '', - '')) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/ifconfig.py b/third_party/python/psutil/scripts/ifconfig.py deleted file mode 100755 index cfd02f0dafa3..000000000000 --- a/third_party/python/psutil/scripts/ifconfig.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -A clone of 'ifconfig' on UNIX. - -$ python scripts/ifconfig.py -lo: - stats : speed=0MB, duplex=?, mtu=65536, up=yes - incoming : bytes=1.95M, pkts=22158, errs=0, drops=0 - outgoing : bytes=1.95M, pkts=22158, errs=0, drops=0 - IPv4 address : 127.0.0.1 - netmask : 255.0.0.0 - IPv6 address : ::1 - netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff - MAC address : 00:00:00:00:00:00 - -docker0: - stats : speed=0MB, duplex=?, mtu=1500, up=yes - incoming : bytes=3.48M, pkts=65470, errs=0, drops=0 - outgoing : bytes=164.06M, pkts=112993, errs=0, drops=0 - IPv4 address : 172.17.0.1 - broadcast : 172.17.0.1 - netmask : 255.255.0.0 - IPv6 address : fe80::42:27ff:fe5e:799e%docker0 - netmask : ffff:ffff:ffff:ffff:: - MAC address : 02:42:27:5e:79:9e - broadcast : ff:ff:ff:ff:ff:ff - -wlp3s0: - stats : speed=0MB, duplex=?, mtu=1500, up=yes - incoming : bytes=7.04G, pkts=5637208, errs=0, drops=0 - outgoing : bytes=372.01M, pkts=3200026, errs=0, drops=0 - IPv4 address : 10.0.0.2 - broadcast : 10.255.255.255 - netmask : 255.0.0.0 - IPv6 address : fe80::ecb3:1584:5d17:937%wlp3s0 - netmask : ffff:ffff:ffff:ffff:: - MAC address : 48:45:20:59:a4:0c - broadcast : ff:ff:ff:ff:ff:ff -""" - -from __future__ import print_function -import socket - -import psutil -from psutil._common import bytes2human - - -af_map = { - socket.AF_INET: 'IPv4', - socket.AF_INET6: 'IPv6', - psutil.AF_LINK: 'MAC', -} - -duplex_map = { - psutil.NIC_DUPLEX_FULL: "full", - psutil.NIC_DUPLEX_HALF: "half", - psutil.NIC_DUPLEX_UNKNOWN: "?", -} - - -def main(): - stats = psutil.net_if_stats() - io_counters = psutil.net_io_counters(pernic=True) - for nic, addrs in psutil.net_if_addrs().items(): - print("%s:" % (nic)) - if nic in stats: - st = stats[nic] - print(" stats : ", end='') - print("speed=%sMB, duplex=%s, mtu=%s, up=%s" % ( - st.speed, duplex_map[st.duplex], st.mtu, - "yes" if st.isup else "no")) - if nic in io_counters: - io = io_counters[nic] - print(" incoming : ", end='') - print("bytes=%s, pkts=%s, errs=%s, drops=%s" % ( - bytes2human(io.bytes_recv), io.packets_recv, io.errin, - io.dropin)) - print(" outgoing : ", end='') - print("bytes=%s, pkts=%s, errs=%s, drops=%s" % ( - bytes2human(io.bytes_sent), io.packets_sent, io.errout, - io.dropout)) - for addr in addrs: - print(" %-4s" % af_map.get(addr.family, addr.family), end="") - print(" address : %s" % addr.address) - if addr.broadcast: - print(" broadcast : %s" % addr.broadcast) - if addr.netmask: - print(" netmask : %s" % addr.netmask) - if addr.ptp: - print(" p2p : %s" % addr.ptp) - print("") - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/internal/.git-pre-commit b/third_party/python/psutil/scripts/internal/.git-pre-commit deleted file mode 100755 index e60092538d3d..000000000000 --- a/third_party/python/psutil/scripts/internal/.git-pre-commit +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -This gets executed on 'git commit' and rejects the commit in case the -submitted code does not pass validation. Validation is run only against -the *.py files which were modified in the commit. Checks: - -- assert no space at EOLs -- assert not pdb.set_trace in code -- assert no bare except clause ("except:") in code -- assert "flake8" returns no warnings - -Install this with "make install-git-hooks". -""" - -from __future__ import print_function -import os -import subprocess -import sys - - -def term_supports_colors(): - try: - import curses - assert sys.stderr.isatty() - curses.setupterm() - assert curses.tigetnum("colors") > 0 - except Exception: - return False - else: - return True - - -def hilite(s, ok=True, bold=False): - """Return an highlighted version of 'string'.""" - if not term_supports_colors(): - return s - attr = [] - if ok is None: # no color - pass - elif ok: # green - attr.append('32') - else: # red - attr.append('31') - if bold: - attr.append('1') - return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), s) - - -def exit(msg): - msg = hilite(msg, ok=False) - print(msg, file=sys.stderr) - sys.exit(1) - - -def sh(cmd): - """run cmd in a subprocess and return its output. - raises RuntimeError on error. - """ - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, universal_newlines=True) - stdout, stderr = p.communicate() - if p.returncode != 0: - raise RuntimeError(stderr) - if stderr: - print(stderr, file=sys.stderr) - if stdout.endswith('\n'): - stdout = stdout[:-1] - return stdout - - -def main(): - out = sh("git diff --cached --name-only") - py_files = [x for x in out.split('\n') if x.endswith('.py') and - os.path.exists(x)] - c_files = [x for x in out.split('\n') if x.endswith(('.c', '.h')) and - os.path.exists(x)] - - lineno = 0 - kw = {'encoding': 'utf8'} if sys.version_info[0] == 3 else {} - for path in py_files: - with open(path, 'rt', **kw) as f: - for line in f: - lineno += 1 - # space at end of line - if line.endswith(' '): - print("%s:%s %r" % (path, lineno, line)) - return exit( - "commit aborted: space at end of line") - line = line.rstrip() - # pdb - if "pdb.set_trace" in line: - print("%s:%s %s" % (path, lineno, line)) - return exit( - "commit aborted: you forgot a pdb in your python code") - # bare except clause - if "except:" in line and not line.endswith("# NOQA"): - print("%s:%s %s" % (path, lineno, line)) - return exit("commit aborted: bare except clause") - - # Python linter - if py_files: - try: - import flake8 # NOQA - except ImportError: - return exit("commit aborted: flake8 is not installed; " - "run 'make setup-dev-env'") - - # XXX: we should escape spaces and possibly other amenities here - ret = subprocess.call( - "%s -m flake8 %s" % (sys.executable, " ".join(py_files)), - shell=True) - if ret != 0: - return exit("commit aborted: python code is not flake8 compliant") - - # C linter - if c_files: - # XXX: we should escape spaces and possibly other amenities here - cmd = "%s scripts/internal/clinter.py %s" % ( - sys.executable, " ".join(c_files)) - print(cmd) - ret = subprocess.call(cmd, shell=True) - if ret != 0: - return exit("commit aborted: C code didn't pass style check") - - -main() diff --git a/third_party/python/psutil/scripts/internal/README b/third_party/python/psutil/scripts/internal/README deleted file mode 100644 index 69a4c386f29a..000000000000 --- a/third_party/python/psutil/scripts/internal/README +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains scripts which are meant to be used internally -(benchmarks, CI automation, etc.). diff --git a/third_party/python/psutil/scripts/internal/bench_oneshot.py b/third_party/python/psutil/scripts/internal/bench_oneshot.py deleted file mode 100755 index 436bdd6b0187..000000000000 --- a/third_party/python/psutil/scripts/internal/bench_oneshot.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -A simple micro benchmark script which prints the speedup when using -Process.oneshot() ctx manager. -See: https://github.com/giampaolo/psutil/issues/799 -""" - -from __future__ import print_function, division -import sys -import timeit -import textwrap - -import psutil - - -ITERATIONS = 1000 - -# The list of Process methods which gets collected in one shot and -# as such get advantage of the speedup. -names = [ - 'cpu_times', - 'cpu_percent', - 'memory_info', - 'memory_percent', - 'ppid', - 'parent', -] - -if psutil.POSIX: - names.append('uids') - names.append('username') - -if psutil.LINUX: - names += [ - # 'memory_full_info', - # 'memory_maps', - 'cpu_num', - 'cpu_times', - 'gids', - 'name', - 'num_ctx_switches', - 'num_threads', - 'ppid', - 'status', - 'terminal', - 'uids', - ] -elif psutil.BSD: - names = [ - 'cpu_times', - 'gids', - 'io_counters', - 'memory_full_info', - 'memory_info', - 'name', - 'num_ctx_switches', - 'ppid', - 'status', - 'terminal', - 'uids', - ] - if psutil.FREEBSD: - names.append('cpu_num') -elif psutil.SUNOS: - names += [ - 'cmdline', - 'gids', - 'memory_full_info', - 'memory_info', - 'name', - 'num_threads', - 'ppid', - 'status', - 'terminal', - 'uids', - ] -elif psutil.MACOS: - names += [ - 'cpu_times', - 'create_time', - 'gids', - 'memory_info', - 'name', - 'num_ctx_switches', - 'num_threads', - 'ppid', - 'terminal', - 'uids', - ] -elif psutil.WINDOWS: - names += [ - 'num_ctx_switches', - 'num_threads', - # dual implementation, called in case of AccessDenied - 'num_handles', - 'cpu_times', - 'create_time', - 'num_threads', - 'io_counters', - 'memory_info', - ] - -names = sorted(set(names)) - -setup = textwrap.dedent(""" - from __main__ import names - import psutil - - def call_normal(funs): - for fun in funs: - fun() - - def call_oneshot(funs): - with p.oneshot(): - for fun in funs: - fun() - - p = psutil.Process() - funs = [getattr(p, n) for n in names] - """) - - -def main(): - print("%s methods involved on platform %r (%s iterations, psutil %s):" % ( - len(names), sys.platform, ITERATIONS, psutil.__version__)) - for name in sorted(names): - print(" " + name) - - # "normal" run - elapsed1 = timeit.timeit( - "call_normal(funs)", setup=setup, number=ITERATIONS) - print("normal: %.3f secs" % elapsed1) - - # "one shot" run - elapsed2 = timeit.timeit( - "call_oneshot(funs)", setup=setup, number=ITERATIONS) - print("onshot: %.3f secs" % elapsed2) - - # done - if elapsed2 < elapsed1: - print("speedup: +%.2fx" % (elapsed1 / elapsed2)) - elif elapsed2 > elapsed1: - print("slowdown: -%.2fx" % (elapsed2 / elapsed1)) - else: - print("same speed") - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/internal/bench_oneshot_2.py b/third_party/python/psutil/scripts/internal/bench_oneshot_2.py deleted file mode 100755 index 3867391b4036..000000000000 --- a/third_party/python/psutil/scripts/internal/bench_oneshot_2.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Same as bench_oneshot.py but uses perf module instead, which is -supposed to be more precise. -""" - -import sys - -import pyperf # requires "pip install pyperf" - -import psutil -from bench_oneshot import names - - -p = psutil.Process() -funs = [getattr(p, n) for n in names] - - -def call_normal(): - for fun in funs: - fun() - - -def call_oneshot(): - with p.oneshot(): - for fun in funs: - fun() - - -def add_cmdline_args(cmd, args): - cmd.append(args.benchmark) - - -def main(): - runner = pyperf.Runner() - - args = runner.parse_args() - if not args.worker: - print("%s methods involved on platform %r (psutil %s):" % ( - len(names), sys.platform, psutil.__version__)) - for name in sorted(names): - print(" " + name) - - runner.bench_func("normal", call_normal) - runner.bench_func("oneshot", call_oneshot) - - -main() diff --git a/third_party/python/psutil/scripts/internal/check_broken_links.py b/third_party/python/psutil/scripts/internal/check_broken_links.py deleted file mode 100755 index 1a0761161329..000000000000 --- a/third_party/python/psutil/scripts/internal/check_broken_links.py +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2009, Giampaolo Rodola', Himanshu Shekhar. -# All rights reserved. Use of this source code is governed by a -# BSD-style license that can be found in the LICENSE file. - -""" -Checks for broken links in file names specified as command line -parameters. - -There are a ton of a solutions available for validating URLs in string -using regex, but less for searching, of which very few are accurate. -This snippet is intended to just do the required work, and avoid -complexities. Django Validator has pretty good regex for validation, -but we have to find urls instead of validating them (REFERENCES [7]). -There's always room for improvement. - -Method: -* Match URLs using regex (REFERENCES [1]]) -* Some URLs need to be fixed, as they have < (or) > due to inefficient - regex. -* Remove duplicates (because regex is not 100% efficient as of now). -* Check validity of URL, using HEAD request. (HEAD to save bandwidth) - Uses requests module for others are painful to use. REFERENCES[9] - Handles redirects, http, https, ftp as well. - -REFERENCES: -Using [1] with some modificatons for including ftp -[1] http://stackoverflow.com/a/6883094/5163807 -[2] http://stackoverflow.com/a/31952097/5163807 -[3] http://daringfireball.net/2010/07/improved_regex_for_matching_urls -[4] https://mathiasbynens.be/demo/url-regex -[5] https://github.com/django/django/blob/master/django/core/validators.py -[6] https://data.iana.org/TLD/tlds-alpha-by-domain.txt -[7] https://codereview.stackexchange.com/questions/19663/http-url-validating -[8] https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD -[9] http://docs.python-requests.org/ - -Author: Himanshu Shekhar (2017) -""" - -from __future__ import print_function - -import concurrent.futures -import functools -import os -import re -import sys -import traceback - -import requests - - -HERE = os.path.abspath(os.path.dirname(__file__)) -REGEX = re.compile( - r'(?:http|ftp|https)?://' - r'(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+') -REQUEST_TIMEOUT = 15 -# There are some status codes sent by websites on HEAD request. -# Like 503 by Microsoft, and 401 by Apple -# They need to be sent GET request -RETRY_STATUSES = [503, 401, 403] - - -def memoize(fun): - """A memoize decorator.""" - @functools.wraps(fun) - def wrapper(*args, **kwargs): - key = (args, frozenset(sorted(kwargs.items()))) - try: - return cache[key] - except KeyError: - ret = cache[key] = fun(*args, **kwargs) - return ret - - cache = {} - return wrapper - - -def sanitize_url(url): - url = url.rstrip(',') - url = url.rstrip('.') - url = url.lstrip('(') - url = url.rstrip(')') - url = url.lstrip('[') - url = url.rstrip(']') - url = url.lstrip('<') - url = url.rstrip('>') - return url - - -def find_urls(s): - matches = REGEX.findall(s) or [] - return list(set([sanitize_url(x) for x in matches])) - - -def parse_rst(fname): - """Look for links in a .rst file.""" - with open(fname) as f: - text = f.read() - urls = find_urls(text) - # HISTORY file has a lot of dead links. - if fname == 'HISTORY.rst' and urls: - urls = [ - x for x in urls if - not x.startswith('https://github.com/giampaolo/psutil/issues')] - return urls - - -def parse_py(fname): - """Look for links in a .py file.""" - with open(fname) as f: - lines = f.readlines() - urls = set() - for i, line in enumerate(lines): - for url in find_urls(line): - # comment block - if line.lstrip().startswith('# '): - subidx = i + 1 - while True: - nextline = lines[subidx].strip() - if re.match('^# .+', nextline): - url += nextline[1:].strip() - else: - break - subidx += 1 - urls.add(url) - return list(urls) - - -def parse_c(fname): - """Look for links in a .py file.""" - with open(fname) as f: - lines = f.readlines() - urls = set() - for i, line in enumerate(lines): - for url in find_urls(line): - # comment block // - if line.lstrip().startswith('// '): - subidx = i + 1 - while True: - nextline = lines[subidx].strip() - if re.match('^// .+', nextline): - url += nextline[2:].strip() - else: - break - subidx += 1 - # comment block /* - elif line.lstrip().startswith('* '): - subidx = i + 1 - while True: - nextline = lines[subidx].strip() - if re.match(r'^\* .+', nextline): - url += nextline[1:].strip() - else: - break - subidx += 1 - urls.add(url) - return list(urls) - - -def parse_generic(fname): - with open(fname, 'rt', errors='ignore') as f: - text = f.read() - return find_urls(text) - - -def get_urls(fname): - """Extracts all URLs in fname and return them as a list.""" - if fname.endswith('.rst'): - return parse_rst(fname) - elif fname.endswith('.py'): - return parse_py(fname) - elif fname.endswith('.c') or fname.endswith('.h'): - return parse_c(fname) - else: - with open(fname, 'rt', errors='ignore') as f: - if f.readline().strip().startswith('#!/usr/bin/env python3'): - return parse_py(fname) - return parse_generic(fname) - - -@memoize -def validate_url(url): - """Validate the URL by attempting an HTTP connection. - Makes an HTTP-HEAD request for each URL. - """ - try: - res = requests.head(url, timeout=REQUEST_TIMEOUT) - # some websites deny 503, like Microsoft - # and some send 401, like Apple, observations - if (not res.ok) and (res.status_code in RETRY_STATUSES): - res = requests.get(url, timeout=REQUEST_TIMEOUT) - return res.ok - except requests.exceptions.RequestException: - return False - - -def parallel_validator(urls): - """validates all urls in parallel - urls: tuple(filename, url) - """ - fails = [] # list of tuples (filename, url) - current = 0 - total = len(urls) - with concurrent.futures.ThreadPoolExecutor() as executor: - fut_to_url = {executor.submit(validate_url, url[1]): url - for url in urls} - for fut in concurrent.futures.as_completed(fut_to_url): - current += 1 - sys.stdout.write("\r%s / %s" % (current, total)) - sys.stdout.flush() - fname, url = fut_to_url[fut] - try: - ok = fut.result() - except Exception: - fails.append((fname, url)) - print() - print("warn: error while validating %s" % url, file=sys.stderr) - traceback.print_exc() - else: - if not ok: - fails.append((fname, url)) - - print() - return fails - - -def main(): - files = sys.argv[1:] - if not files: - print("usage: %s " % sys.argv[0], file=sys.stderr) - return sys.exit(1) - - all_urls = [] - for fname in files: - urls = get_urls(fname) - if urls: - print("%4s %s" % (len(urls), fname)) - for url in urls: - all_urls.append((fname, url)) - - fails = parallel_validator(all_urls) - if not fails: - print("all links are valid; cheers!") - else: - for fail in fails: - fname, url = fail - print("%-30s: %s " % (fname, url)) - print('-' * 20) - print("total: %s fails!" % len(fails)) - sys.exit(1) - - -if __name__ == '__main__': - try: - main() - except (KeyboardInterrupt, SystemExit): - os._exit(0) diff --git a/third_party/python/psutil/scripts/internal/clinter.py b/third_party/python/psutil/scripts/internal/clinter.py deleted file mode 100755 index 1d4ba9b14bf6..000000000000 --- a/third_party/python/psutil/scripts/internal/clinter.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""A super simple linter to check C syntax.""" - -from __future__ import print_function -import argparse -import sys - - -warned = False - - -def warn(path, line, lineno, msg): - global warned - warned = True - print("%s:%s: %s" % (path, lineno, msg), file=sys.stderr) - - -def check_line(path, line, idx, lines): - s = line - lineno = idx + 1 - eof = lineno == len(lines) - if s.endswith(' \n'): - warn(path, line, lineno, "extra space at EOL") - elif '\t' in line: - warn(path, line, lineno, "line has a tab") - elif s.endswith('\r\n'): - warn(path, line, lineno, "Windows line ending") - # end of global block, e.g. "}newfunction...": - elif s == "}\n": - if not eof: - nextline = lines[idx + 1] - # "#" is a pre-processor line - if nextline != '\n' and \ - nextline.strip()[0] != '#' and \ - nextline.strip()[:2] != '*/': - warn(path, line, lineno, "expected 1 blank line") - - sls = s.lstrip() - if sls.startswith('//') and sls[2] != ' ' and line.strip() != '//': - warn(path, line, lineno, "no space after // comment") - - # e.g. "if(..." after keywords - keywords = ("if", "else", "while", "do", "enum", "for") - for kw in keywords: - if sls.startswith(kw + '('): - warn(path, line, lineno, "missing space between %r and '('" % kw) - # eof - if eof: - if not line.endswith('\n'): - warn(path, line, lineno, "no blank line at EOF") - - -def process(path): - with open(path, 'rt') as f: - lines = f.readlines() - for idx, line in enumerate(lines): - check_line(path, line, idx, lines) - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('paths', nargs='+', help='path(s) to a file(s)') - args = parser.parse_args() - for path in args.paths: - process(path) - if warned: - sys.exit(1) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/internal/fix_flake8.py b/third_party/python/psutil/scripts/internal/fix_flake8.py deleted file mode 100755 index 7cde608bbadd..000000000000 --- a/third_party/python/psutil/scripts/internal/fix_flake8.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Fix some flake8 errors by rewriting files for which flake8 emitted -an error/warning. Usage (from the root dir): - - $ python3 -m flake8 --exit-zero | python3 scripts/fix_flake8.py -""" - -import sys -import tempfile -import shutil -from collections import defaultdict -from collections import namedtuple -from pprint import pprint as pp # NOQA - - -ntentry = namedtuple('ntentry', 'msg, issue, lineno, pos, descr') - - -# ===================================================================== -# utils -# ===================================================================== - - -def enter_pdb(): - from pdb import set_trace as st # trick GIT commit hook - sys.stdin = open('/dev/tty') - st() - - -def read_lines(fname): - with open(fname, 'rt') as f: - return f.readlines() - - -def read_line(fname, lineno): - with open(fname, 'rt') as f: - for i, line in enumerate(f, 1): - if i == lineno: - return line - raise ValueError("lineno too big") - - -def write_file(fname, newlines): - with tempfile.NamedTemporaryFile('wt', delete=False) as f: - for line in newlines: - f.write(line) - shutil.move(f.name, fname) - - -# ===================================================================== -# handlers -# ===================================================================== - - -def handle_f401(fname, lineno): - """ This is 'module imported but not used' - Able to handle this case: - import os - - ...but not this: - from os import listdir - """ - line = read_line(fname, lineno).strip() - if line.startswith('import '): - return True - else: - mods = line.partition(' import ')[2] # everything after import - return ',' not in mods - - -# ===================================================================== -# converters -# ===================================================================== - - -def remove_lines(fname, entries): - """Check if we should remove lines, then do it. - Return the numner of lines removed. - """ - to_remove = [] - for entry in entries: - msg, issue, lineno, pos, descr = entry - # 'module imported but not used' - if issue == 'F401' and handle_f401(fname, lineno): - to_remove.append(lineno) - # 'blank line(s) at end of file' - elif issue == 'W391': - lines = read_lines(fname) - i = len(lines) - 1 - while lines[i] == '\n': - to_remove.append(i + 1) - i -= 1 - # 'too many blank lines' - elif issue == 'E303': - howmany = descr.replace('(', '').replace(')', '') - howmany = int(howmany[-1]) - for x in range(lineno - howmany, lineno): - to_remove.append(x) - - if to_remove: - newlines = [] - for i, line in enumerate(read_lines(fname), 1): - if i not in to_remove: - newlines.append(line) - print("removing line(s) from %s" % fname) - write_file(fname, newlines) - - return len(to_remove) - - -def add_lines(fname, entries): - """Check if we should remove lines, then do it. - Return the numner of lines removed. - """ - EXPECTED_BLANK_LINES = ( - 'E302', # 'expected 2 blank limes, found 1' - 'E305') # ìexpected 2 blank lines after class or fun definition' - to_add = {} - for entry in entries: - msg, issue, lineno, pos, descr = entry - if issue in EXPECTED_BLANK_LINES: - howmany = 2 if descr.endswith('0') else 1 - to_add[lineno] = howmany - - if to_add: - newlines = [] - for i, line in enumerate(read_lines(fname), 1): - if i in to_add: - newlines.append('\n' * to_add[i]) - newlines.append(line) - print("adding line(s) to %s" % fname) - write_file(fname, newlines) - - return len(to_add) - - -# ===================================================================== -# main -# ===================================================================== - - -def build_table(): - table = defaultdict(list) - for line in sys.stdin: - line = line.strip() - if not line: - break - fields = line.split(':') - fname, lineno, pos = fields[:3] - issue = fields[3].split()[0] - descr = fields[3].strip().partition(' ')[2] - lineno, pos = int(lineno), int(pos) - table[fname].append(ntentry(line, issue, lineno, pos, descr)) - return table - - -def main(): - table = build_table() - - # remove lines (unused imports) - removed = 0 - for fname, entries in table.items(): - removed += remove_lines(fname, entries) - if removed: - print("%s lines were removed from some file(s); please re-run" % - removed) - return - - # add lines (missing \n between functions/classes) - added = 0 - for fname, entries in table.items(): - added += add_lines(fname, entries) - if added: - print("%s lines were added from some file(s); please re-run" % - added) - return - - -main() diff --git a/third_party/python/psutil/scripts/internal/generate_manifest.py b/third_party/python/psutil/scripts/internal/generate_manifest.py deleted file mode 100755 index c0be6d99d978..000000000000 --- a/third_party/python/psutil/scripts/internal/generate_manifest.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Generate MANIFEST.in file. -""" - -import os -import subprocess - - -SKIP_EXTS = ('.png', '.jpg', '.jpeg') -SKIP_FILES = ('.travis.yml', 'appveyor.yml') -SKIP_PREFIXES = ('.ci/', '.github/') - - -def sh(cmd): - return subprocess.check_output( - cmd, shell=True, universal_newlines=True).strip() - - -def main(): - files = sh("git ls-files").split('\n') - for file in files: - if file.startswith(SKIP_PREFIXES) or \ - os.path.splitext(file)[1].lower() in SKIP_EXTS or \ - file in SKIP_FILES: - continue - print("include " + file) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/internal/print_access_denied.py b/third_party/python/psutil/scripts/internal/print_access_denied.py deleted file mode 100755 index 81d192f0c754..000000000000 --- a/third_party/python/psutil/scripts/internal/print_access_denied.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Helper script iterates over all processes and . -It prints how many AccessDenied exceptions are raised in total and -for what Process method. - -$ make print-access-denied -API AD Percent Outcome -memory_info 0 0.0% SUCCESS -uids 0 0.0% SUCCESS -cmdline 0 0.0% SUCCESS -create_time 0 0.0% SUCCESS -status 0 0.0% SUCCESS -num_ctx_switches 0 0.0% SUCCESS -username 0 0.0% SUCCESS -ionice 0 0.0% SUCCESS -memory_percent 0 0.0% SUCCESS -gids 0 0.0% SUCCESS -cpu_times 0 0.0% SUCCESS -nice 0 0.0% SUCCESS -pid 0 0.0% SUCCESS -cpu_percent 0 0.0% SUCCESS -num_threads 0 0.0% SUCCESS -cpu_num 0 0.0% SUCCESS -ppid 0 0.0% SUCCESS -terminal 0 0.0% SUCCESS -name 0 0.0% SUCCESS -threads 0 0.0% SUCCESS -cpu_affinity 0 0.0% SUCCESS -memory_maps 71 21.3% ACCESS DENIED -memory_full_info 71 21.3% ACCESS DENIED -exe 174 52.1% ACCESS DENIED -environ 238 71.3% ACCESS DENIED -num_fds 238 71.3% ACCESS DENIED -io_counters 238 71.3% ACCESS DENIED -cwd 238 71.3% ACCESS DENIED -connections 238 71.3% ACCESS DENIED -open_files 238 71.3% ACCESS DENIED --------------------------------------------------- -Totals: access-denied=1744, calls=10020, processes=334 -""" - -from __future__ import print_function, division -from collections import defaultdict -import time - -import psutil -from psutil._common import print_color - - -def main(): - # collect - tot_procs = 0 - tot_ads = 0 - tot_calls = 0 - signaler = object() - d = defaultdict(int) - start = time.time() - for p in psutil.process_iter(attrs=[], ad_value=signaler): - tot_procs += 1 - for methname, value in p.info.items(): - tot_calls += 1 - if value is signaler: - tot_ads += 1 - d[methname] += 1 - else: - d[methname] += 0 - elapsed = time.time() - start - - # print - templ = "%-20s %-5s %-9s %s" - s = templ % ("API", "AD", "Percent", "Outcome") - print_color(s, color=None, bold=True) - for methname, ads in sorted(d.items(), key=lambda x: (x[1], x[0])): - perc = (ads / tot_procs) * 100 - outcome = "SUCCESS" if not ads else "ACCESS DENIED" - s = templ % (methname, ads, "%6.1f%%" % perc, outcome) - print_color(s, "red" if ads else None) - tot_perc = round((tot_ads / tot_calls) * 100, 1) - print("-" * 50) - print("Totals: access-denied=%s (%s%%), calls=%s, processes=%s, " - "elapsed=%ss" % (tot_ads, tot_perc, tot_calls, tot_procs, - round(elapsed, 2))) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/internal/print_announce.py b/third_party/python/psutil/scripts/internal/print_announce.py deleted file mode 100755 index 9569c3674d8c..000000000000 --- a/third_party/python/psutil/scripts/internal/print_announce.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Prints release announce based on HISTORY.rst file content. -""" - -import os -import re - -from psutil import __version__ as PRJ_VERSION - - -HERE = os.path.abspath(os.path.dirname(__file__)) -HISTORY = os.path.abspath(os.path.join(HERE, '../../HISTORY.rst')) - -PRJ_NAME = 'psutil' -PRJ_URL_HOME = 'https://github.com/giampaolo/psutil' -PRJ_URL_DOC = 'http://psutil.readthedocs.io' -PRJ_URL_DOWNLOAD = 'https://pypi.org/project/psutil/#files' -PRJ_URL_WHATSNEW = \ - 'https://github.com/giampaolo/psutil/blob/master/HISTORY.rst' - -template = """\ -Hello all, -I'm glad to announce the release of {prj_name} {prj_version}: -{prj_urlhome} - -About -===== - -psutil (process and system utilities) is a cross-platform library for \ -retrieving information on running processes and system utilization (CPU, \ -memory, disks, network) in Python. It is useful mainly for system \ -monitoring, profiling and limiting process resources and management of \ -running processes. It implements many functionalities offered by command \ -line tools such as: ps, top, lsof, netstat, ifconfig, who, df, kill, free, \ -nice, ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. It \ -currently supports Linux, Windows, macOS, Sun Solaris, FreeBSD, OpenBSD, \ -NetBSD and AIX, both 32-bit and 64-bit architectures. Supported Python \ -versions are 2.6, 2.7 and 3.4+. PyPy is also known to work. - -What's new -========== - -{changes} - -Links -===== - -- Home page: {prj_urlhome} -- Download: {prj_urldownload} -- Documentation: {prj_urldoc} -- What's new: {prj_urlwhatsnew} - --- - -Giampaolo - http://grodola.blogspot.com -""" - - -def get_changes(): - """Get the most recent changes for this release by parsing - HISTORY.rst file. - """ - with open(HISTORY) as f: - lines = f.readlines() - - block = [] - - # eliminate the part preceding the first block - for i, line in enumerate(lines): - line = lines.pop(0) - if line.startswith('===='): - break - lines.pop(0) - - for i, line in enumerate(lines): - line = lines.pop(0) - line = line.rstrip() - if re.match(r"^- \d+_: ", line): - num, _, rest = line.partition(': ') - num = ''.join([x for x in num if x.isdigit()]) - line = "- #%s: %s" % (num, rest) - - if line.startswith('===='): - break - block.append(line) - - # eliminate bottom empty lines - block.pop(-1) - while not block[-1]: - block.pop(-1) - - return "\n".join(block) - - -def main(): - changes = get_changes() - print(template.format( - prj_name=PRJ_NAME, - prj_version=PRJ_VERSION, - prj_urlhome=PRJ_URL_HOME, - prj_urldownload=PRJ_URL_DOWNLOAD, - prj_urldoc=PRJ_URL_DOC, - prj_urlwhatsnew=PRJ_URL_WHATSNEW, - changes=changes, - )) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/internal/print_api_speed.py b/third_party/python/psutil/scripts/internal/print_api_speed.py deleted file mode 100755 index e39a1baa7b96..000000000000 --- a/third_party/python/psutil/scripts/internal/print_api_speed.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Benchmark all API calls. - -$ make print_api_speed -SYSTEM APIS SECONDS ----------------------------------- -cpu_count 0.000014 -disk_usage 0.000027 -cpu_times 0.000037 -cpu_percent 0.000045 -... - -PROCESS APIS SECONDS ----------------------------------- -create_time 0.000001 -nice 0.000005 -cwd 0.000011 -cpu_affinity 0.000011 -ionice 0.000013 -... -""" - -from __future__ import print_function, division -from timeit import default_timer as timer -import inspect -import os - -import psutil -from psutil._common import print_color - - -timings = [] -templ = "%-25s %s" - - -def print_timings(): - timings.sort(key=lambda x: x[1]) - i = 0 - while timings[:]: - title, elapsed = timings.pop(0) - s = templ % (title, "%f" % elapsed) - if i > len(timings) - 5: - print_color(s, color="red") - else: - print(s) - - -def timecall(title, fun, *args, **kw): - t = timer() - fun(*args, **kw) - elapsed = timer() - t - timings.append((title, elapsed)) - - -def main(): - # --- system - - public_apis = [] - ignore = ['wait_procs', 'process_iter', 'win_service_get', - 'win_service_iter'] - if psutil.MACOS: - ignore.append('net_connections') # raises AD - for name in psutil.__all__: - obj = getattr(psutil, name, None) - if inspect.isfunction(obj): - if name not in ignore: - public_apis.append(name) - - print_color(templ % ("SYSTEM APIS", "SECONDS"), color=None, bold=True) - print("-" * 34) - for name in public_apis: - fun = getattr(psutil, name) - args = () - if name == 'pid_exists': - args = (os.getpid(), ) - elif name == 'disk_usage': - args = (os.getcwd(), ) - timecall(name, fun, *args) - timecall('cpu_count (cores)', psutil.cpu_count, logical=False) - timecall('process_iter (all)', lambda: list(psutil.process_iter())) - print_timings() - - # --- process - print("") - print_color(templ % ("PROCESS APIS", "SECONDS"), color=None, bold=True) - print("-" * 34) - ignore = ['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait', - 'as_dict', 'parent', 'parents', 'memory_info_ex', 'oneshot', - 'pid', 'rlimit'] - if psutil.MACOS: - ignore.append('memory_maps') # XXX - p = psutil.Process() - for name in sorted(dir(p)): - if not name.startswith('_') and name not in ignore: - fun = getattr(p, name) - timecall(name, fun) - print_timings() - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/internal/print_timeline.py b/third_party/python/psutil/scripts/internal/print_timeline.py deleted file mode 100755 index 64608b26ba59..000000000000 --- a/third_party/python/psutil/scripts/internal/print_timeline.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Prints releases' timeline in RST format. -""" - -import subprocess - - -entry = """\ -- {date}: - `{ver} `__ - - `what's new `__ - - `diff `__""" # NOQA - - -def sh(cmd): - return subprocess.check_output( - cmd, shell=True, universal_newlines=True).strip() - - -def get_tag_date(tag): - out = sh(r"git log -1 --format=%ai {}".format(tag)) - return out.split(' ')[0] - - -def main(): - releases = [] - out = sh("git tag") - for line in out.split('\n'): - tag = line.split(' ')[0] - ver = tag.replace('release-', '') - nodotver = ver.replace('.', '') - date = get_tag_date(tag) - releases.append((tag, ver, nodotver, date)) - releases.sort(reverse=True) - - for i, rel in enumerate(releases): - tag, ver, nodotver, date = rel - try: - prevtag = releases[i + 1][0] - except IndexError: - # get first commit - prevtag = sh("git rev-list --max-parents=0 HEAD") - print(entry.format(**locals())) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/internal/purge_installation.py b/third_party/python/psutil/scripts/internal/purge_installation.py deleted file mode 100755 index 50c00463cf39..000000000000 --- a/third_party/python/psutil/scripts/internal/purge_installation.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Purge psutil installation by removing psutil-related files and -directories found in site-packages directories. This is needed mainly -because sometimes "import psutil" imports a leftover installation -from site-packages directory instead of the main working directory. -""" - -import os -import shutil -import site - - -PKGNAME = "psutil" - - -def rmpath(path): - if os.path.isdir(path): - print("rmdir " + path) - shutil.rmtree(path) - else: - print("rm " + path) - os.remove(path) - - -def main(): - locations = [site.getusersitepackages()] - locations.extend(site.getsitepackages()) - for root in locations: - if os.path.isdir(root): - for name in os.listdir(root): - if PKGNAME in name: - abspath = os.path.join(root, name) - rmpath(abspath) - - -main() diff --git a/third_party/python/psutil/scripts/internal/win_download_wheels.py b/third_party/python/psutil/scripts/internal/win_download_wheels.py deleted file mode 100755 index 3720dd96c07b..000000000000 --- a/third_party/python/psutil/scripts/internal/win_download_wheels.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Script which downloads exe and wheel files hosted on AppVeyor: -https://ci.appveyor.com/project/giampaolo/psutil -Readapted from the original recipe of Ibarra Corretge' -: -http://code.saghul.net/index.php/2015/09/09/ -""" - -from __future__ import print_function -import argparse -import concurrent.futures -import errno -import os -import requests -import shutil -import sys - -from psutil import __version__ as PSUTIL_VERSION -from psutil._common import bytes2human -from psutil._common import print_color - - -BASE_URL = 'https://ci.appveyor.com/api' -PY_VERSIONS = ['2.7', '3.5', '3.6', '3.7', '3.8'] -TIMEOUT = 30 -COLORS = True - - -def safe_makedirs(path): - try: - os.makedirs(path) - except OSError as err: - if err.errno == errno.EEXIST: - if not os.path.isdir(path): - raise - else: - raise - - -def safe_rmtree(path): - def onerror(fun, path, excinfo): - exc = excinfo[1] - if exc.errno != errno.ENOENT: - raise - - shutil.rmtree(path, onerror=onerror) - - -def download_file(url): - local_fname = url.split('/')[-1] - local_fname = os.path.join('dist', local_fname) - safe_makedirs('dist') - r = requests.get(url, stream=True, timeout=TIMEOUT) - tot_bytes = 0 - with open(local_fname, 'wb') as f: - for chunk in r.iter_content(chunk_size=16384): - if chunk: # filter out keep-alive new chunks - f.write(chunk) - tot_bytes += len(chunk) - return local_fname - - -def get_file_urls(options): - with requests.Session() as session: - data = session.get( - BASE_URL + '/projects/' + options.user + '/' + options.project, - timeout=TIMEOUT) - data = data.json() - - urls = [] - for job in (job['jobId'] for job in data['build']['jobs']): - job_url = BASE_URL + '/buildjobs/' + job + '/artifacts' - data = session.get(job_url, timeout=TIMEOUT) - data = data.json() - for item in data: - file_url = job_url + '/' + item['fileName'] - urls.append(file_url) - if not urls: - print_color("no artifacts found", 'ret') - sys.exit(1) - else: - for url in sorted(urls, key=lambda x: os.path.basename(x)): - yield url - - -def rename_27_wheels(): - # See: https://github.com/giampaolo/psutil/issues/810 - src = 'dist/psutil-%s-cp27-cp27m-win32.whl' % PSUTIL_VERSION - dst = 'dist/psutil-%s-cp27-none-win32.whl' % PSUTIL_VERSION - print("rename: %s\n %s" % (src, dst)) - os.rename(src, dst) - src = 'dist/psutil-%s-cp27-cp27m-win_amd64.whl' % PSUTIL_VERSION - dst = 'dist/psutil-%s-cp27-none-win_amd64.whl' % PSUTIL_VERSION - print("rename: %s\n %s" % (src, dst)) - os.rename(src, dst) - - -def run(options): - safe_rmtree('dist') - urls = get_file_urls(options) - completed = 0 - exc = None - with concurrent.futures.ThreadPoolExecutor() as e: - fut_to_url = {e.submit(download_file, url): url for url in urls} - for fut in concurrent.futures.as_completed(fut_to_url): - url = fut_to_url[fut] - try: - local_fname = fut.result() - except Exception: - print_color("error while downloading %s" % (url), 'red') - raise - else: - completed += 1 - print("downloaded %-45s %s" % ( - local_fname, bytes2human(os.path.getsize(local_fname)))) - # 2 wheels (32 and 64 bit) per supported python version - expected = len(PY_VERSIONS) * 2 - if expected != completed: - return exit("expected %s files, got %s" % (expected, completed)) - if exc: - return exit() - rename_27_wheels() - - -def main(): - parser = argparse.ArgumentParser( - description='AppVeyor artifact downloader') - parser.add_argument('--user', required=True) - parser.add_argument('--project', required=True) - args = parser.parse_args() - run(args) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/internal/winmake.py b/third_party/python/psutil/scripts/internal/winmake.py deleted file mode 100755 index 4d3fa3184bc1..000000000000 --- a/third_party/python/psutil/scripts/internal/winmake.py +++ /dev/null @@ -1,608 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - - -"""Shortcuts for various tasks, emulating UNIX "make" on Windows. -This is supposed to be invoked by "make.bat" and not used directly. -This was originally written as a bat file but they suck so much -that they should be deemed illegal! -""" - -from __future__ import print_function -import argparse -import atexit -import ctypes -import errno -import fnmatch -import os -import shutil -import site -import ssl -import subprocess -import sys -import tempfile - - -APPVEYOR = bool(os.environ.get('APPVEYOR')) -if APPVEYOR: - PYTHON = sys.executable -else: - PYTHON = os.getenv('PYTHON', sys.executable) -TEST_SCRIPT = 'psutil\\tests\\runner.py' -GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py" -PY3 = sys.version_info[0] == 3 -HERE = os.path.abspath(os.path.dirname(__file__)) -ROOT_DIR = os.path.realpath(os.path.join(HERE, "..", "..")) -PYPY = '__pypy__' in sys.builtin_module_names -DEPS = [ - "coverage", - "flake8", - "nose", - "pdbpp", - "pip", - "pyperf", - "pyreadline", - "setuptools", - "wheel", - "wmi", - "requests" -] -if sys.version_info[:2] <= (2, 6): - DEPS.append('unittest2') -if sys.version_info[:2] <= (2, 7): - DEPS.append('mock') -if sys.version_info[:2] <= (3, 2): - DEPS.append('ipaddress') -if PYPY: - pass -elif sys.version_info[:2] <= (3, 4): - DEPS.append("pypiwin32==219") -else: - DEPS.append("pypiwin32") - -_cmds = {} -if PY3: - basestring = str - -GREEN = 2 -LIGHTBLUE = 3 -YELLOW = 6 -RED = 4 -DEFAULT_COLOR = 7 - - -# =================================================================== -# utils -# =================================================================== - - -def safe_print(text, file=sys.stdout, flush=False): - """Prints a (unicode) string to the console, encoded depending on - the stdout/file encoding (eg. cp437 on Windows). This is to avoid - encoding errors in case of funky path names. - Works with Python 2 and 3. - """ - if not isinstance(text, basestring): - return print(text, file=file) - try: - file.write(text) - except UnicodeEncodeError: - bytes_string = text.encode(file.encoding, 'backslashreplace') - if hasattr(file, 'buffer'): - file.buffer.write(bytes_string) - else: - text = bytes_string.decode(file.encoding, 'strict') - file.write(text) - file.write("\n") - - -def stderr_handle(): - GetStdHandle = ctypes.windll.Kernel32.GetStdHandle - STD_ERROR_HANDLE_ID = ctypes.c_ulong(0xfffffff4) - GetStdHandle.restype = ctypes.c_ulong - handle = GetStdHandle(STD_ERROR_HANDLE_ID) - atexit.register(ctypes.windll.Kernel32.CloseHandle, handle) - return handle - - -def win_colorprint(s, color=LIGHTBLUE): - color += 8 # bold - handle = stderr_handle() - SetConsoleTextAttribute = ctypes.windll.Kernel32.SetConsoleTextAttribute - SetConsoleTextAttribute(handle, color) - try: - print(s) - finally: - SetConsoleTextAttribute(handle, DEFAULT_COLOR) - - -def sh(cmd, nolog=False): - if not nolog: - safe_print("cmd: " + cmd) - p = subprocess.Popen(cmd, shell=True, env=os.environ, cwd=os.getcwd()) - p.communicate() - if p.returncode != 0: - sys.exit(p.returncode) - - -def rm(pattern, directory=False): - """Recursively remove a file or dir by pattern.""" - def safe_remove(path): - try: - os.remove(path) - except OSError as err: - if err.errno != errno.ENOENT: - raise - else: - safe_print("rm %s" % path) - - def safe_rmtree(path): - def onerror(fun, path, excinfo): - exc = excinfo[1] - if exc.errno != errno.ENOENT: - raise - - existed = os.path.isdir(path) - shutil.rmtree(path, onerror=onerror) - if existed: - safe_print("rmdir -f %s" % path) - - if "*" not in pattern: - if directory: - safe_rmtree(pattern) - else: - safe_remove(pattern) - return - - for root, subdirs, subfiles in os.walk('.'): - root = os.path.normpath(root) - if root.startswith('.git/'): - continue - found = fnmatch.filter(subdirs if directory else subfiles, pattern) - for name in found: - path = os.path.join(root, name) - if directory: - safe_print("rmdir -f %s" % path) - safe_rmtree(path) - else: - safe_print("rm %s" % path) - safe_remove(path) - - -def safe_remove(path): - try: - os.remove(path) - except OSError as err: - if err.errno != errno.ENOENT: - raise - else: - safe_print("rm %s" % path) - - -def safe_rmtree(path): - def onerror(fun, path, excinfo): - exc = excinfo[1] - if exc.errno != errno.ENOENT: - raise - - existed = os.path.isdir(path) - shutil.rmtree(path, onerror=onerror) - if existed: - safe_print("rmdir -f %s" % path) - - -def recursive_rm(*patterns): - """Recursively remove a file or matching a list of patterns.""" - for root, subdirs, subfiles in os.walk(u'.'): - root = os.path.normpath(root) - if root.startswith('.git/'): - continue - for file in subfiles: - for pattern in patterns: - if fnmatch.fnmatch(file, pattern): - safe_remove(os.path.join(root, file)) - for dir in subdirs: - for pattern in patterns: - if fnmatch.fnmatch(dir, pattern): - safe_rmtree(os.path.join(root, dir)) - - -def test_setup(): - os.environ['PYTHONWARNINGS'] = 'all' - os.environ['PSUTIL_TESTING'] = '1' - os.environ['PSUTIL_DEBUG'] = '1' - - -# =================================================================== -# commands -# =================================================================== - - -def build(): - """Build / compile""" - # Make sure setuptools is installed (needed for 'develop' / - # edit mode). - sh('%s -c "import setuptools"' % PYTHON) - - # Print coloured warnings in real time. - cmd = [PYTHON, "setup.py", "build"] - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - try: - for line in iter(p.stdout.readline, b''): - if PY3: - line = line.decode() - line = line.strip() - if 'warning' in line: - win_colorprint(line, YELLOW) - elif 'error' in line: - win_colorprint(line, RED) - else: - print(line) - # retcode = p.poll() - p.communicate() - if p.returncode: - win_colorprint("failure", RED) - sys.exit(p.returncode) - finally: - p.terminate() - p.wait() - - # Copies compiled *.pyd files in ./psutil directory in order to - # allow "import psutil" when using the interactive interpreter - # from within this directory. - sh("%s setup.py build_ext -i" % PYTHON) - # Make sure it actually worked. - sh('%s -c "import psutil"' % PYTHON) - win_colorprint("build + import successful", GREEN) - - -def wheel(): - """Create wheel file.""" - build() - sh("%s setup.py bdist_wheel" % PYTHON) - - -def upload_wheels(): - """Upload wheel files on PyPI.""" - build() - sh("%s -m twine upload dist/*.whl" % PYTHON) - - -def install_pip(): - """Install pip""" - try: - sh('%s -c "import pip"' % PYTHON) - except SystemExit: - if PY3: - from urllib.request import urlopen - else: - from urllib2 import urlopen - - if hasattr(ssl, '_create_unverified_context'): - ctx = ssl._create_unverified_context() - else: - ctx = None - kw = dict(context=ctx) if ctx else {} - safe_print("downloading %s" % GET_PIP_URL) - req = urlopen(GET_PIP_URL, **kw) - data = req.read() - - tfile = os.path.join(tempfile.gettempdir(), 'get-pip.py') - with open(tfile, 'wb') as f: - f.write(data) - - try: - sh('%s %s --user' % (PYTHON, tfile)) - finally: - os.remove(tfile) - - -def install(): - """Install in develop / edit mode""" - build() - sh("%s setup.py develop" % PYTHON) - - -def uninstall(): - """Uninstall psutil""" - # Uninstalling psutil on Windows seems to be tricky. - # On "import psutil" tests may import a psutil version living in - # C:\PythonXY\Lib\site-packages which is not what we want, so - # we try both "pip uninstall psutil" and manually remove stuff - # from site-packages. - clean() - install_pip() - here = os.getcwd() - try: - os.chdir('C:\\') - while True: - try: - import psutil # NOQA - except ImportError: - break - else: - sh("%s -m pip uninstall -y psutil" % PYTHON) - finally: - os.chdir(here) - - for dir in site.getsitepackages(): - for name in os.listdir(dir): - if name.startswith('psutil'): - rm(os.path.join(dir, name)) - elif name == 'easy-install.pth': - # easy_install can add a line (installation path) into - # easy-install.pth; that line alters sys.path. - path = os.path.join(dir, name) - with open(path, 'rt') as f: - lines = f.readlines() - hasit = False - for line in lines: - if 'psutil' in line: - hasit = True - break - if hasit: - with open(path, 'wt') as f: - for line in lines: - if 'psutil' not in line: - f.write(line) - else: - print("removed line %r from %r" % (line, path)) - - -def clean(): - """Deletes dev files""" - recursive_rm( - "$testfn*", - "*.bak", - "*.core", - "*.egg-info", - "*.orig", - "*.pyc", - "*.pyd", - "*.pyo", - "*.rej", - "*.so", - "*.~", - "*__pycache__", - ".coverage", - ".failed-tests.txt", - ".tox", - ) - safe_rmtree("build") - safe_rmtree(".coverage") - safe_rmtree("dist") - safe_rmtree("docs/_build") - safe_rmtree("htmlcov") - safe_rmtree("tmp") - - -def setup_dev_env(): - """Install useful deps""" - install_pip() - install_git_hooks() - sh("%s -m pip install -U %s" % (PYTHON, " ".join(DEPS))) - - -def lint(): - """Run flake8 against all py files""" - py_files = subprocess.check_output("git ls-files") - if PY3: - py_files = py_files.decode() - py_files = [x for x in py_files.split() if x.endswith('.py')] - py_files = ' '.join(py_files) - sh("%s -m flake8 %s" % (PYTHON, py_files), nolog=True) - - -def test(script=TEST_SCRIPT): - """Run tests""" - install() - test_setup() - cmdline = "%s %s" % (PYTHON, script) - safe_print(cmdline) - sh(cmdline) - - -def coverage(): - """Run coverage tests.""" - # Note: coverage options are controlled by .coveragerc file - install() - test_setup() - sh("%s -m coverage run %s" % (PYTHON, TEST_SCRIPT)) - sh("%s -m coverage report" % PYTHON) - sh("%s -m coverage html" % PYTHON) - sh("%s -m webbrowser -t htmlcov/index.html" % PYTHON) - - -def test_process(): - """Run process tests""" - install() - test_setup() - sh("%s psutil\\tests\\test_process.py" % PYTHON) - - -def test_system(): - """Run system tests""" - install() - test_setup() - sh("%s psutil\\tests\\test_system.py" % PYTHON) - - -def test_platform(): - """Run windows only tests""" - install() - test_setup() - sh("%s psutil\\tests\\test_windows.py" % PYTHON) - - -def test_misc(): - """Run misc tests""" - install() - test_setup() - sh("%s psutil\\tests\\test_misc.py" % PYTHON) - - -def test_unicode(): - """Run unicode tests""" - install() - test_setup() - sh("%s psutil\\tests\\test_unicode.py" % PYTHON) - - -def test_connections(): - """Run connections tests""" - install() - test_setup() - sh("%s psutil\\tests\\test_connections.py" % PYTHON) - - -def test_contracts(): - """Run contracts tests""" - install() - test_setup() - sh("%s psutil\\tests\\test_contracts.py" % PYTHON) - - -def test_by_name(name): - """Run test by name""" - install() - test_setup() - sh("%s -m unittest -v %s" % (PYTHON, name)) - - -def test_failed(): - """Re-run tests which failed on last run.""" - install() - test_setup() - sh('%s -c "import psutil.tests.runner as r; r.run(last_failed=True)"' % ( - PYTHON)) - - -def test_memleaks(): - """Run memory leaks tests""" - install() - test_setup() - sh("%s psutil\\tests\\test_memory_leaks.py" % PYTHON) - - -def install_git_hooks(): - """Install GIT pre-commit hook.""" - if os.path.isdir('.git'): - src = os.path.join(ROOT_DIR, "scripts", "internal", ".git-pre-commit") - dst = os.path.realpath( - os.path.join(ROOT_DIR, ".git", "hooks", "pre-commit")) - with open(src, "rt") as s: - with open(dst, "wt") as d: - d.write(s.read()) - - -def bench_oneshot(): - """Benchmarks for oneshot() ctx manager (see #799).""" - sh("%s -Wa scripts\\internal\\bench_oneshot.py" % PYTHON) - - -def bench_oneshot_2(): - """Same as above but using perf module (supposed to be more precise).""" - sh("%s -Wa scripts\\internal\\bench_oneshot_2.py" % PYTHON) - - -def print_access_denied(): - """Print AD exceptions raised by all Process methods.""" - install() - test_setup() - sh("%s -Wa scripts\\internal\\print_access_denied.py" % PYTHON) - - -def print_api_speed(): - """Benchmark all API calls.""" - install() - test_setup() - sh("%s -Wa scripts\\internal\\print_api_speed.py" % PYTHON) - - -def get_python(path): - if not path: - return sys.executable - if os.path.isabs(path): - return path - # try to look for a python installation given a shortcut name - path = path.replace('.', '') - vers = ('26', '27', '36', '37', '38', - '26-64', '27-64', '36-64', '37-64', '38-64' - '26-32', '27-32', '36-32', '37-32', '38-32') - for v in vers: - pypath = r'C:\\python%s\python.exe' % v - if path in pypath and os.path.isfile(pypath): - return pypath - - -def main(): - global PYTHON - parser = argparse.ArgumentParser() - # option shared by all commands - parser.add_argument( - '-p', '--python', - help="use python executable path") - sp = parser.add_subparsers(dest='command', title='targets') - sp.add_parser('bench-oneshot', help="benchmarks for oneshot()") - sp.add_parser('bench-oneshot_2', help="benchmarks for oneshot() (perf)") - sp.add_parser('build', help="build") - sp.add_parser('clean', help="deletes dev files") - sp.add_parser('coverage', help="run coverage tests.") - sp.add_parser('help', help="print this help") - sp.add_parser('install', help="build + install in develop/edit mode") - sp.add_parser('install-git-hooks', help="install GIT pre-commit hook") - sp.add_parser('install-pip', help="install pip") - sp.add_parser('lint', help="run flake8 against all py files") - sp.add_parser('print-access-denied', help="print AD exceptions") - sp.add_parser('print-api-speed', help="benchmark all API calls") - sp.add_parser('setup-dev-env', help="install deps") - test = sp.add_parser('test', help="[ARG] run tests") - test_by_name = sp.add_parser('test-by-name', help=" run test by name") - sp.add_parser('test-connections', help="run connections tests") - sp.add_parser('test-contracts', help="run contracts tests") - sp.add_parser('test-failed', help="re-run tests which failed on last run") - sp.add_parser('test-memleaks', help="run memory leaks tests") - sp.add_parser('test-misc', help="run misc tests") - sp.add_parser('test-platform', help="run windows only tests") - sp.add_parser('test-process', help="run process tests") - sp.add_parser('test-system', help="run system tests") - sp.add_parser('test-unicode', help="run unicode tests") - sp.add_parser('uninstall', help="uninstall psutil") - sp.add_parser('upload-wheels', help="upload wheel files on PyPI") - sp.add_parser('wheel', help="create wheel file") - - for p in (test, test_by_name): - p.add_argument('arg', type=str, nargs='?', default="", help="arg") - args = parser.parse_args() - - # set python exe - PYTHON = get_python(args.python) - if not PYTHON: - return sys.exit( - "can't find any python installation matching %r" % args.python) - os.putenv('PYTHON', PYTHON) - win_colorprint("using " + PYTHON) - - if not args.command or args.command == 'help': - parser.print_help(sys.stderr) - sys.exit(1) - - fname = args.command.replace('-', '_') - fun = getattr(sys.modules[__name__], fname) # err if fun not defined - funargs = [] - # mandatory args - if args.command in ('test-by-name', 'test-script'): - if not args.arg: - sys.exit('command needs an argument') - funargs = [args.arg] - # optional args - if args.command == 'test' and args.arg: - funargs = [args.arg] - fun(*funargs) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/iotop.py b/third_party/python/psutil/scripts/iotop.py deleted file mode 100755 index c3afd0715162..000000000000 --- a/third_party/python/psutil/scripts/iotop.py +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -A clone of iotop (http://guichaz.free.fr/iotop/) showing real time -disk I/O statistics. - -It works on Linux only (FreeBSD and macOS are missing support for IO -counters). -It doesn't work on Windows as curses module is required. - -Example output: - -$ python scripts/iotop.py -Total DISK READ: 0.00 B/s | Total DISK WRITE: 472.00 K/s -PID USER DISK READ DISK WRITE COMMAND -13155 giampao 0.00 B/s 428.00 K/s /usr/bin/google-chrome-beta -3260 giampao 0.00 B/s 0.00 B/s bash -3779 giampao 0.00 B/s 0.00 B/s gnome-session --session=ubuntu -3830 giampao 0.00 B/s 0.00 B/s /usr/bin/dbus-launch -3831 giampao 0.00 B/s 0.00 B/s //bin/dbus-daemon --fork --print-pid 5 -3841 giampao 0.00 B/s 0.00 B/s /usr/lib/at-spi-bus-launcher -3845 giampao 0.00 B/s 0.00 B/s /bin/dbus-daemon -3848 giampao 0.00 B/s 0.00 B/s /usr/lib/at-spi2-core/at-spi2-registryd -3862 giampao 0.00 B/s 0.00 B/s /usr/lib/gnome-settings-daemon - -Author: Giampaolo Rodola' -""" - -import atexit -import time -import sys -try: - import curses -except ImportError: - sys.exit('platform not supported') - -import psutil -from psutil._common import bytes2human - - -def tear_down(): - win.keypad(0) - curses.nocbreak() - curses.echo() - curses.endwin() - - -win = curses.initscr() -atexit.register(tear_down) -curses.endwin() -lineno = 0 - - -def print_line(line, highlight=False): - """A thin wrapper around curses's addstr().""" - global lineno - try: - if highlight: - line += " " * (win.getmaxyx()[1] - len(line)) - win.addstr(lineno, 0, line, curses.A_REVERSE) - else: - win.addstr(lineno, 0, line, 0) - except curses.error: - lineno = 0 - win.refresh() - raise - else: - lineno += 1 - - -def poll(interval): - """Calculate IO usage by comparing IO statics before and - after the interval. - Return a tuple including all currently running processes - sorted by IO activity and total disks I/O activity. - """ - # first get a list of all processes and disk io counters - procs = [p for p in psutil.process_iter()] - for p in procs[:]: - try: - p._before = p.io_counters() - except psutil.Error: - procs.remove(p) - continue - disks_before = psutil.disk_io_counters() - - # sleep some time - time.sleep(interval) - - # then retrieve the same info again - for p in procs[:]: - with p.oneshot(): - try: - p._after = p.io_counters() - p._cmdline = ' '.join(p.cmdline()) - if not p._cmdline: - p._cmdline = p.name() - p._username = p.username() - except (psutil.NoSuchProcess, psutil.ZombieProcess): - procs.remove(p) - disks_after = psutil.disk_io_counters() - - # finally calculate results by comparing data before and - # after the interval - for p in procs: - p._read_per_sec = p._after.read_bytes - p._before.read_bytes - p._write_per_sec = p._after.write_bytes - p._before.write_bytes - p._total = p._read_per_sec + p._write_per_sec - - disks_read_per_sec = disks_after.read_bytes - disks_before.read_bytes - disks_write_per_sec = disks_after.write_bytes - disks_before.write_bytes - - # sort processes by total disk IO so that the more intensive - # ones get listed first - processes = sorted(procs, key=lambda p: p._total, reverse=True) - - return (processes, disks_read_per_sec, disks_write_per_sec) - - -def refresh_window(procs, disks_read, disks_write): - """Print results on screen by using curses.""" - curses.endwin() - templ = "%-5s %-7s %11s %11s %s" - win.erase() - - disks_tot = "Total DISK READ: %s | Total DISK WRITE: %s" \ - % (bytes2human(disks_read), bytes2human(disks_write)) - print_line(disks_tot) - - header = templ % ("PID", "USER", "DISK READ", "DISK WRITE", "COMMAND") - print_line(header, highlight=True) - - for p in procs: - line = templ % ( - p.pid, - p._username[:7], - bytes2human(p._read_per_sec), - bytes2human(p._write_per_sec), - p._cmdline) - try: - print_line(line) - except curses.error: - break - win.refresh() - - -def main(): - try: - interval = 0 - while True: - args = poll(interval) - refresh_window(*args) - interval = 1 - except (KeyboardInterrupt, SystemExit): - pass - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/killall.py b/third_party/python/psutil/scripts/killall.py deleted file mode 100755 index 7bbcd75a88d3..000000000000 --- a/third_party/python/psutil/scripts/killall.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Kill a process by name. -""" - -import os -import sys -import psutil - - -def main(): - if len(sys.argv) != 2: - sys.exit('usage: %s name' % __file__) - else: - NAME = sys.argv[1] - - killed = [] - for proc in psutil.process_iter(): - if proc.name() == NAME and proc.pid != os.getpid(): - proc.kill() - killed.append(proc.pid) - if not killed: - sys.exit('%s: no process found' % NAME) - else: - sys.exit(0) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/meminfo.py b/third_party/python/psutil/scripts/meminfo.py deleted file mode 100755 index 550fcd0128f5..000000000000 --- a/third_party/python/psutil/scripts/meminfo.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Print system memory information. - -$ python scripts/meminfo.py -MEMORY ------- -Total : 9.7G -Available : 4.9G -Percent : 49.0 -Used : 8.2G -Free : 1.4G -Active : 5.6G -Inactive : 2.1G -Buffers : 341.2M -Cached : 3.2G - -SWAP ----- -Total : 0B -Used : 0B -Free : 0B -Percent : 0.0 -Sin : 0B -Sout : 0B -""" - -import psutil -from psutil._common import bytes2human - - -def pprint_ntuple(nt): - for name in nt._fields: - value = getattr(nt, name) - if name != 'percent': - value = bytes2human(value) - print('%-10s : %7s' % (name.capitalize(), value)) - - -def main(): - print('MEMORY\n------') - pprint_ntuple(psutil.virtual_memory()) - print('\nSWAP\n----') - pprint_ntuple(psutil.swap_memory()) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/netstat.py b/third_party/python/psutil/scripts/netstat.py deleted file mode 100755 index fe3bfe402c53..000000000000 --- a/third_party/python/psutil/scripts/netstat.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -A clone of 'netstat -antp' on Linux. - -$ python scripts/netstat.py -Proto Local address Remote address Status PID Program name -tcp 127.0.0.1:48256 127.0.0.1:45884 ESTABLISHED 13646 chrome -tcp 127.0.0.1:47073 127.0.0.1:45884 ESTABLISHED 13646 chrome -tcp 127.0.0.1:47072 127.0.0.1:45884 ESTABLISHED 13646 chrome -tcp 127.0.0.1:45884 - LISTEN 13651 GoogleTalkPlugi -tcp 127.0.0.1:60948 - LISTEN 13651 GoogleTalkPlugi -tcp 172.17.42.1:49102 127.0.0.1:19305 CLOSE_WAIT 13651 GoogleTalkPlugi -tcp 172.17.42.1:55797 127.0.0.1:443 CLOSE_WAIT 13651 GoogleTalkPlugi -... -""" - -import socket -from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM - -import psutil - - -AD = "-" -AF_INET6 = getattr(socket, 'AF_INET6', object()) -proto_map = { - (AF_INET, SOCK_STREAM): 'tcp', - (AF_INET6, SOCK_STREAM): 'tcp6', - (AF_INET, SOCK_DGRAM): 'udp', - (AF_INET6, SOCK_DGRAM): 'udp6', -} - - -def main(): - templ = "%-5s %-30s %-30s %-13s %-6s %s" - print(templ % ( - "Proto", "Local address", "Remote address", "Status", "PID", - "Program name")) - proc_names = {} - for p in psutil.process_iter(['pid', 'name']): - proc_names[p.info['pid']] = p.info['name'] - for c in psutil.net_connections(kind='inet'): - laddr = "%s:%s" % (c.laddr) - raddr = "" - if c.raddr: - raddr = "%s:%s" % (c.raddr) - print(templ % ( - proto_map[(c.family, c.type)], - laddr, - raddr or AD, - c.status, - c.pid or AD, - proc_names.get(c.pid, '?')[:15], - )) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/nettop.py b/third_party/python/psutil/scripts/nettop.py deleted file mode 100755 index ce647c9dd391..000000000000 --- a/third_party/python/psutil/scripts/nettop.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env python3 -# -# $Id: iotop.py 1160 2011-10-14 18:50:36Z g.rodola@gmail.com $ -# -# 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. - -""" -Shows real-time network statistics. - -Author: Giampaolo Rodola' - -$ python scripts/nettop.py ------------------------------------------------------------ -total bytes: sent: 1.49 G received: 4.82 G -total packets: sent: 7338724 received: 8082712 - -wlan0 TOTAL PER-SEC ------------------------------------------------------------ -bytes-sent 1.29 G 0.00 B/s -bytes-recv 3.48 G 0.00 B/s -pkts-sent 7221782 0 -pkts-recv 6753724 0 - -eth1 TOTAL PER-SEC ------------------------------------------------------------ -bytes-sent 131.77 M 0.00 B/s -bytes-recv 1.28 G 0.00 B/s -pkts-sent 0 0 -pkts-recv 1214470 0 -""" - -import atexit -import time -import sys -try: - import curses -except ImportError: - sys.exit('platform not supported') - -import psutil -from psutil._common import bytes2human - - -def tear_down(): - win.keypad(0) - curses.nocbreak() - curses.echo() - curses.endwin() - - -win = curses.initscr() -atexit.register(tear_down) -curses.endwin() -lineno = 0 - - -def print_line(line, highlight=False): - """A thin wrapper around curses's addstr().""" - global lineno - try: - if highlight: - line += " " * (win.getmaxyx()[1] - len(line)) - win.addstr(lineno, 0, line, curses.A_REVERSE) - else: - win.addstr(lineno, 0, line, 0) - except curses.error: - lineno = 0 - win.refresh() - raise - else: - lineno += 1 - - -def poll(interval): - """Retrieve raw stats within an interval window.""" - tot_before = psutil.net_io_counters() - pnic_before = psutil.net_io_counters(pernic=True) - # sleep some time - time.sleep(interval) - tot_after = psutil.net_io_counters() - pnic_after = psutil.net_io_counters(pernic=True) - return (tot_before, tot_after, pnic_before, pnic_after) - - -def refresh_window(tot_before, tot_after, pnic_before, pnic_after): - """Print stats on screen.""" - global lineno - - # totals - print_line("total bytes: sent: %-10s received: %s" % ( - bytes2human(tot_after.bytes_sent), - bytes2human(tot_after.bytes_recv)) - ) - print_line("total packets: sent: %-10s received: %s" % ( - tot_after.packets_sent, tot_after.packets_recv)) - - # per-network interface details: let's sort network interfaces so - # that the ones which generated more traffic are shown first - print_line("") - nic_names = list(pnic_after.keys()) - nic_names.sort(key=lambda x: sum(pnic_after[x]), reverse=True) - for name in nic_names: - stats_before = pnic_before[name] - stats_after = pnic_after[name] - templ = "%-15s %15s %15s" - print_line(templ % (name, "TOTAL", "PER-SEC"), highlight=True) - print_line(templ % ( - "bytes-sent", - bytes2human(stats_after.bytes_sent), - bytes2human( - stats_after.bytes_sent - stats_before.bytes_sent) + '/s', - )) - print_line(templ % ( - "bytes-recv", - bytes2human(stats_after.bytes_recv), - bytes2human( - stats_after.bytes_recv - stats_before.bytes_recv) + '/s', - )) - print_line(templ % ( - "pkts-sent", - stats_after.packets_sent, - stats_after.packets_sent - stats_before.packets_sent, - )) - print_line(templ % ( - "pkts-recv", - stats_after.packets_recv, - stats_after.packets_recv - stats_before.packets_recv, - )) - print_line("") - win.refresh() - lineno = 0 - - -def main(): - try: - interval = 0 - while True: - args = poll(interval) - refresh_window(*args) - interval = 1 - except (KeyboardInterrupt, SystemExit): - pass - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/pidof.py b/third_party/python/psutil/scripts/pidof.py deleted file mode 100755 index ee18aae4c5b5..000000000000 --- a/third_party/python/psutil/scripts/pidof.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) 2009, Giampaolo Rodola', karthikrev. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - - -""" -A clone of 'pidof' cmdline utility. -$ pidof python -1140 1138 1136 1134 1133 1129 1127 1125 1121 1120 1119 -""" - -from __future__ import print_function -import psutil -import sys - - -def pidof(pgname): - pids = [] - for proc in psutil.process_iter(['name', 'cmdline']): - # search for matches in the process name and cmdline - if proc.info['name'] == pgname or \ - proc.info['cmdline'] and proc.info['cmdline'][0] == pgname: - pids.append(str(proc.pid)) - return pids - - -def main(): - if len(sys.argv) != 2: - sys.exit('usage: %s pgname' % __file__) - else: - pgname = sys.argv[1] - pids = pidof(pgname) - if pids: - print(" ".join(pids)) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/pmap.py b/third_party/python/psutil/scripts/pmap.py deleted file mode 100755 index 5f7246a159bf..000000000000 --- a/third_party/python/psutil/scripts/pmap.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -A clone of 'pmap' utility on Linux, 'vmmap' on macOS and 'procstat -v' on BSD. -Report memory map of a process. - -$ python scripts/pmap.py 32402 -Address RSS Mode Mapping -0000000000400000 1200K r-xp /usr/bin/python2.7 -0000000000838000 4K r--p /usr/bin/python2.7 -0000000000839000 304K rw-p /usr/bin/python2.7 -00000000008ae000 68K rw-p [anon] -000000000275e000 5396K rw-p [heap] -00002b29bb1e0000 124K r-xp /lib/x86_64-linux-gnu/ld-2.17.so -00002b29bb203000 8K rw-p [anon] -00002b29bb220000 528K rw-p [anon] -00002b29bb2d8000 768K rw-p [anon] -00002b29bb402000 4K r--p /lib/x86_64-linux-gnu/ld-2.17.so -00002b29bb403000 8K rw-p /lib/x86_64-linux-gnu/ld-2.17.so -00002b29bb405000 60K r-xp /lib/x86_64-linux-gnu/libpthread-2.17.so -00002b29bb41d000 0K ---p /lib/x86_64-linux-gnu/libpthread-2.17.so -00007fff94be6000 48K rw-p [stack] -00007fff94dd1000 4K r-xp [vdso] -ffffffffff600000 0K r-xp [vsyscall] -... -""" - -import sys - -import psutil -from psutil._common import bytes2human -from psutil._compat import get_terminal_size - - -def safe_print(s): - s = s[:get_terminal_size()[0]] - try: - print(s) - except UnicodeEncodeError: - print(s.encode('ascii', 'ignore').decode()) - - -def main(): - if len(sys.argv) != 2: - sys.exit('usage: pmap ') - p = psutil.Process(int(sys.argv[1])) - templ = "%-20s %10s %-7s %s" - print(templ % ("Address", "RSS", "Mode", "Mapping")) - total_rss = 0 - for m in p.memory_maps(grouped=False): - total_rss += m.rss - safe_print(templ % ( - m.addr.split('-')[0].zfill(16), - bytes2human(m.rss), - m.perms, - m.path)) - print("-" * 31) - print(templ % ("Total", bytes2human(total_rss), '', '')) - safe_print("PID = %s, name = %s" % (p.pid, p.name())) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/procinfo.py b/third_party/python/psutil/scripts/procinfo.py deleted file mode 100755 index 01974513f035..000000000000 --- a/third_party/python/psutil/scripts/procinfo.py +++ /dev/null @@ -1,328 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Print detailed information about a process. -Author: Giampaolo Rodola' - -$ python scripts/procinfo.py -pid 4600 -name chrome -parent 4554 (bash) -exe /opt/google/chrome/chrome -cwd /home/giampaolo -cmdline /opt/google/chrome/chrome -started 2016-09-19 11:12 -cpu-tspent 27:27.68 -cpu-times user=8914.32, system=3530.59, - children_user=1.46, children_system=1.31 -cpu-affinity [0, 1, 2, 3, 4, 5, 6, 7] -memory rss=520.5M, vms=1.9G, shared=132.6M, text=95.0M, lib=0B, - data=816.5M, dirty=0B -memory % 3.26 -user giampaolo -uids real=1000, effective=1000, saved=1000 -uids real=1000, effective=1000, saved=1000 -terminal /dev/pts/2 -status sleeping -nice 0 -ionice class=IOPriority.IOPRIO_CLASS_NONE, value=0 -num-threads 47 -num-fds 379 -I/O read_count=96.6M, write_count=80.7M, - read_bytes=293.2M, write_bytes=24.5G -ctx-switches voluntary=30426463, involuntary=460108 -children PID NAME - 4605 cat - 4606 cat - 4609 chrome - 4669 chrome -open-files PATH - /opt/google/chrome/icudtl.dat - /opt/google/chrome/snapshot_blob.bin - /opt/google/chrome/natives_blob.bin - /opt/google/chrome/chrome_100_percent.pak - [...] -connections PROTO LOCAL ADDR REMOTE ADDR STATUS - UDP 10.0.0.3:3693 *:* NONE - TCP 10.0.0.3:55102 172.217.22.14:443 ESTABLISHED - UDP 10.0.0.3:35172 *:* NONE - TCP 10.0.0.3:32922 172.217.16.163:443 ESTABLISHED - UDP :::5353 *:* NONE - UDP 10.0.0.3:59925 *:* NONE -threads TID USER SYSTEM - 11795 0.7 1.35 - 11796 0.68 1.37 - 15887 0.74 0.03 - 19055 0.77 0.01 - [...] - total=47 -res-limits RLIMIT SOFT HARD - virtualmem infinity infinity - coredumpsize 0 infinity - cputime infinity infinity - datasize infinity infinity - filesize infinity infinity - locks infinity infinity - memlock 65536 65536 - msgqueue 819200 819200 - nice 0 0 - openfiles 8192 65536 - maxprocesses 63304 63304 - rss infinity infinity - realtimeprio 0 0 - rtimesched infinity infinity - sigspending 63304 63304 - stack 8388608 infinity -mem-maps RSS PATH - 381.4M [anon] - 62.8M /opt/google/chrome/chrome - 15.8M /home/giampaolo/.config/google-chrome/Default/History - 6.6M /home/giampaolo/.config/google-chrome/Default/Favicons - [...] -""" - -import argparse -import datetime -import socket -import sys - -import psutil -from psutil._common import bytes2human - - -ACCESS_DENIED = '' -NON_VERBOSE_ITERATIONS = 4 -RLIMITS_MAP = { - "RLIMIT_AS": "virtualmem", - "RLIMIT_CORE": "coredumpsize", - "RLIMIT_CPU": "cputime", - "RLIMIT_DATA": "datasize", - "RLIMIT_FSIZE": "filesize", - "RLIMIT_LOCKS": "locks", - "RLIMIT_MEMLOCK": "memlock", - "RLIMIT_MSGQUEUE": "msgqueue", - "RLIMIT_NICE": "nice", - "RLIMIT_NOFILE": "openfiles", - "RLIMIT_NPROC": "maxprocesses", - "RLIMIT_RSS": "rss", - "RLIMIT_RTPRIO": "realtimeprio", - "RLIMIT_RTTIME": "rtimesched", - "RLIMIT_SIGPENDING": "sigspending", - "RLIMIT_STACK": "stack", -} - - -def print_(a, b): - if sys.stdout.isatty() and psutil.POSIX: - fmt = '\x1b[1;32m%-13s\x1b[0m %s' % (a, b) - else: - fmt = '%-11s %s' % (a, b) - print(fmt) - - -def str_ntuple(nt, convert_bytes=False): - if nt == ACCESS_DENIED: - return "" - if not convert_bytes: - return ", ".join(["%s=%s" % (x, getattr(nt, x)) for x in nt._fields]) - else: - return ", ".join(["%s=%s" % (x, bytes2human(getattr(nt, x))) - for x in nt._fields]) - - -def run(pid, verbose=False): - try: - proc = psutil.Process(pid) - pinfo = proc.as_dict(ad_value=ACCESS_DENIED) - except psutil.NoSuchProcess as err: - sys.exit(str(err)) - - # collect other proc info - with proc.oneshot(): - try: - parent = proc.parent() - if parent: - parent = '(%s)' % parent.name() - else: - parent = '' - except psutil.Error: - parent = '' - try: - pinfo['children'] = proc.children() - except psutil.Error: - pinfo['children'] = [] - if pinfo['create_time']: - started = datetime.datetime.fromtimestamp( - pinfo['create_time']).strftime('%Y-%m-%d %H:%M') - else: - started = ACCESS_DENIED - - # here we go - print_('pid', pinfo['pid']) - print_('name', pinfo['name']) - print_('parent', '%s %s' % (pinfo['ppid'], parent)) - print_('exe', pinfo['exe']) - print_('cwd', pinfo['cwd']) - print_('cmdline', ' '.join(pinfo['cmdline'])) - print_('started', started) - - cpu_tot_time = datetime.timedelta(seconds=sum(pinfo['cpu_times'])) - cpu_tot_time = "%s:%s.%s" % ( - cpu_tot_time.seconds // 60 % 60, - str((cpu_tot_time.seconds % 60)).zfill(2), - str(cpu_tot_time.microseconds)[:2]) - print_('cpu-tspent', cpu_tot_time) - print_('cpu-times', str_ntuple(pinfo['cpu_times'])) - if hasattr(proc, "cpu_affinity"): - print_("cpu-affinity", pinfo["cpu_affinity"]) - if hasattr(proc, "cpu_num"): - print_("cpu-num", pinfo["cpu_num"]) - - print_('memory', str_ntuple(pinfo['memory_info'], convert_bytes=True)) - print_('memory %', round(pinfo['memory_percent'], 2)) - print_('user', pinfo['username']) - if psutil.POSIX: - print_('uids', str_ntuple(pinfo['uids'])) - if psutil.POSIX: - print_('uids', str_ntuple(pinfo['uids'])) - if psutil.POSIX: - print_('terminal', pinfo['terminal'] or '') - - print_('status', pinfo['status']) - print_('nice', pinfo['nice']) - if hasattr(proc, "ionice"): - try: - ionice = proc.ionice() - except psutil.Error: - pass - else: - if psutil.WINDOWS: - print_("ionice", ionice) - else: - print_("ionice", "class=%s, value=%s" % ( - str(ionice.ioclass), ionice.value)) - - print_('num-threads', pinfo['num_threads']) - if psutil.POSIX: - print_('num-fds', pinfo['num_fds']) - if psutil.WINDOWS: - print_('num-handles', pinfo['num_handles']) - - if 'io_counters' in pinfo: - print_('I/O', str_ntuple(pinfo['io_counters'], convert_bytes=True)) - if 'num_ctx_switches' in pinfo: - print_("ctx-switches", str_ntuple(pinfo['num_ctx_switches'])) - if pinfo['children']: - template = "%-6s %s" - print_("children", template % ("PID", "NAME")) - for child in pinfo['children']: - try: - print_('', template % (child.pid, child.name())) - except psutil.AccessDenied: - print_('', template % (child.pid, "")) - except psutil.NoSuchProcess: - pass - - if pinfo['open_files']: - print_('open-files', 'PATH') - for i, file in enumerate(pinfo['open_files']): - if not verbose and i >= NON_VERBOSE_ITERATIONS: - print_("", "[...]") - break - print_('', file.path) - else: - print_('open-files', '') - - if pinfo['connections']: - template = '%-5s %-25s %-25s %s' - print_('connections', - template % ('PROTO', 'LOCAL ADDR', 'REMOTE ADDR', 'STATUS')) - for conn in pinfo['connections']: - if conn.type == socket.SOCK_STREAM: - type = 'TCP' - elif conn.type == socket.SOCK_DGRAM: - type = 'UDP' - else: - type = 'UNIX' - lip, lport = conn.laddr - if not conn.raddr: - rip, rport = '*', '*' - else: - rip, rport = conn.raddr - print_('', template % ( - type, - "%s:%s" % (lip, lport), - "%s:%s" % (rip, rport), - conn.status)) - else: - print_('connections', '') - - if pinfo['threads'] and len(pinfo['threads']) > 1: - template = "%-5s %12s %12s" - print_('threads', template % ("TID", "USER", "SYSTEM")) - for i, thread in enumerate(pinfo['threads']): - if not verbose and i >= NON_VERBOSE_ITERATIONS: - print_("", "[...]") - break - print_('', template % thread) - print_('', "total=%s" % len(pinfo['threads'])) - else: - print_('threads', '') - - if hasattr(proc, "rlimit"): - res_names = [x for x in dir(psutil) if x.startswith("RLIMIT")] - resources = [] - for res_name in res_names: - try: - soft, hard = proc.rlimit(getattr(psutil, res_name)) - except psutil.AccessDenied: - pass - else: - resources.append((res_name, soft, hard)) - if resources: - template = "%-12s %15s %15s" - print_("res-limits", template % ("RLIMIT", "SOFT", "HARD")) - for res_name, soft, hard in resources: - if soft == psutil.RLIM_INFINITY: - soft = "infinity" - if hard == psutil.RLIM_INFINITY: - hard = "infinity" - print_('', template % ( - RLIMITS_MAP.get(res_name, res_name), soft, hard)) - - if hasattr(proc, "environ") and pinfo['environ']: - template = "%-25s %s" - print_("environ", template % ("NAME", "VALUE")) - for i, k in enumerate(sorted(pinfo['environ'])): - if not verbose and i >= NON_VERBOSE_ITERATIONS: - print_("", "[...]") - break - print_("", template % (k, pinfo['environ'][k])) - - if pinfo.get('memory_maps', None): - template = "%-8s %s" - print_("mem-maps", template % ("RSS", "PATH")) - maps = sorted(pinfo['memory_maps'], key=lambda x: x.rss, reverse=True) - for i, region in enumerate(maps): - if not verbose and i >= NON_VERBOSE_ITERATIONS: - print_("", "[...]") - break - print_("", template % (bytes2human(region.rss), region.path)) - - -def main(argv=None): - parser = argparse.ArgumentParser( - description="print information about a process") - parser.add_argument("pid", type=int, help="process pid") - parser.add_argument('--verbose', '-v', action='store_true', - help="print more info") - args = parser.parse_args() - run(args.pid, args.verbose) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/third_party/python/psutil/scripts/procsmem.py b/third_party/python/psutil/scripts/procsmem.py deleted file mode 100755 index 259d79d42f2b..000000000000 --- a/third_party/python/psutil/scripts/procsmem.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Show detailed memory usage about all (querable) processes. - -Processes are sorted by their "USS" (Unique Set Size) memory, which is -probably the most representative metric for determining how much memory -is actually being used by a process. - -This is similar to "smem" cmdline utility on Linux: -https://www.selenic.com/smem/ - -Author: Giampaolo Rodola' - -~/svn/psutil$ ./scripts/procsmem.py -PID User Cmdline USS PSS Swap RSS -============================================================================== -... -3986 giampao /usr/bin/python3 /usr/bin/indi 15.3M 16.6M 0B 25.6M -3906 giampao /usr/lib/ibus/ibus-ui-gtk3 17.6M 18.1M 0B 26.7M -3991 giampao python /usr/bin/hp-systray -x 19.0M 23.3M 0B 40.7M -3830 giampao /usr/bin/ibus-daemon --daemoni 19.0M 19.0M 0B 21.4M -20529 giampao /opt/sublime_text/plugin_host 19.9M 20.1M 0B 22.0M -3990 giampao nautilus -n 20.6M 29.9M 0B 50.2M -3898 giampao /usr/lib/unity/unity-panel-ser 27.1M 27.9M 0B 37.7M -4176 giampao /usr/lib/evolution/evolution-c 35.7M 36.2M 0B 41.5M -20712 giampao /usr/bin/python -B /home/giamp 45.6M 45.9M 0B 49.4M -3880 giampao /usr/lib/x86_64-linux-gnu/hud/ 51.6M 52.7M 0B 61.3M -20513 giampao /opt/sublime_text/sublime_text 65.8M 73.0M 0B 87.9M -3976 giampao compiz 115.0M 117.0M 0B 130.9M -32486 giampao skype 145.1M 147.5M 0B 149.6M -""" - -from __future__ import print_function -import sys - -import psutil - - -if not (psutil.LINUX or psutil.MACOS or psutil.WINDOWS): - sys.exit("platform not supported") - - -def convert_bytes(n): - symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') - prefix = {} - for i, s in enumerate(symbols): - prefix[s] = 1 << (i + 1) * 10 - for s in reversed(symbols): - if n >= prefix[s]: - value = float(n) / prefix[s] - return '%.1f%s' % (value, s) - return "%sB" % n - - -def main(): - ad_pids = [] - procs = [] - for p in psutil.process_iter(): - with p.oneshot(): - try: - mem = p.memory_full_info() - info = p.as_dict(["cmdline", "username"]) - except psutil.AccessDenied: - ad_pids.append(p.pid) - except psutil.NoSuchProcess: - pass - else: - p._uss = mem.uss - p._rss = mem.rss - if not p._uss: - continue - p._pss = getattr(mem, "pss", "") - p._swap = getattr(mem, "swap", "") - p._info = info - procs.append(p) - - procs.sort(key=lambda p: p._uss) - templ = "%-7s %-7s %-30s %7s %7s %7s %7s" - print(templ % ("PID", "User", "Cmdline", "USS", "PSS", "Swap", "RSS")) - print("=" * 78) - for p in procs[:86]: - line = templ % ( - p.pid, - p._info["username"][:7] if p._info["username"] else "", - " ".join(p._info["cmdline"])[:30], - convert_bytes(p._uss), - convert_bytes(p._pss) if p._pss != "" else "", - convert_bytes(p._swap) if p._swap != "" else "", - convert_bytes(p._rss), - ) - print(line) - if ad_pids: - print("warning: access denied for %s pids" % (len(ad_pids)), - file=sys.stderr) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/third_party/python/psutil/scripts/ps.py b/third_party/python/psutil/scripts/ps.py deleted file mode 100755 index 540c032a7f4c..000000000000 --- a/third_party/python/psutil/scripts/ps.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -A clone of 'ps aux'. - -$ python scripts/ps.py -USER PID %MEM VSZ RSS NICE STATUS START TIME CMDLINE -root 1 0.0 220.9M 6.5M sleep Mar27 09:10 /lib/systemd -root 2 0.0 0.0B 0.0B sleep Mar27 00:00 kthreadd -root 4 0.0 0.0B 0.0B -20 idle Mar27 00:00 kworker/0:0H -root 6 0.0 0.0B 0.0B -20 idle Mar27 00:00 mm_percpu_wq -root 7 0.0 0.0B 0.0B sleep Mar27 00:06 ksoftirqd/0 -root 8 0.0 0.0B 0.0B idle Mar27 03:32 rcu_sched -root 9 0.0 0.0B 0.0B idle Mar27 00:00 rcu_bh -root 10 0.0 0.0B 0.0B sleep Mar27 00:00 migration/0 -root 11 0.0 0.0B 0.0B sleep Mar27 00:00 watchdog/0 -root 12 0.0 0.0B 0.0B sleep Mar27 00:00 cpuhp/0 -root 13 0.0 0.0B 0.0B sleep Mar27 00:00 cpuhp/1 -root 14 0.0 0.0B 0.0B sleep Mar27 00:01 watchdog/1 -root 15 0.0 0.0B 0.0B sleep Mar27 00:00 migration/1 -[...] -giampaolo 19704 1.5 1.9G 235.6M sleep 17:39 01:11 firefox -root 20414 0.0 0.0B 0.0B idle Apr04 00:00 kworker/4:2 -giampaolo 20952 0.0 10.7M 100.0K sleep Mar28 00:00 sh -c /usr -giampaolo 20953 0.0 269.0M 528.0K sleep Mar28 00:00 /usr/lib/ -giampaolo 22150 3.3 2.4G 525.5M sleep Apr02 49:09 /usr/lib/ -root 22338 0.0 0.0B 0.0B idle 02:04 00:00 kworker/1:2 -giampaolo 24123 0.0 35.0M 7.0M sleep 02:12 00:02 bash -""" - -import datetime -import time - -import psutil -from psutil._common import bytes2human -from psutil._compat import get_terminal_size - - -def main(): - today_day = datetime.date.today() - templ = "%-10s %5s %5s %7s %7s %5s %6s %6s %6s %s" - attrs = ['pid', 'memory_percent', 'name', 'cmdline', 'cpu_times', - 'create_time', 'memory_info', 'status', 'nice', 'username'] - print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "NICE", - "STATUS", "START", "TIME", "CMDLINE")) - for p in psutil.process_iter(attrs, ad_value=None): - if p.info['create_time']: - ctime = datetime.datetime.fromtimestamp(p.info['create_time']) - if ctime.date() == today_day: - ctime = ctime.strftime("%H:%M") - else: - ctime = ctime.strftime("%b%d") - else: - ctime = '' - if p.info['cpu_times']: - cputime = time.strftime("%M:%S", - time.localtime(sum(p.info['cpu_times']))) - else: - cputime = '' - - user = p.info['username'] - if not user and psutil.POSIX: - try: - user = p.uids()[0] - except psutil.Error: - pass - if user and psutil.WINDOWS and '\\' in user: - user = user.split('\\')[1] - if not user: - user = '' - user = user[:9] - vms = bytes2human(p.info['memory_info'].vms) if \ - p.info['memory_info'] is not None else '' - rss = bytes2human(p.info['memory_info'].rss) if \ - p.info['memory_info'] is not None else '' - memp = round(p.info['memory_percent'], 1) if \ - p.info['memory_percent'] is not None else '' - nice = int(p.info['nice']) if p.info['nice'] else '' - if p.info['cmdline']: - cmdline = ' '.join(p.info['cmdline']) - else: - cmdline = p.info['name'] - status = p.info['status'][:5] if p.info['status'] else '' - - line = templ % ( - user, - p.info['pid'], - memp, - vms, - rss, - nice, - status, - ctime, - cputime, - cmdline) - print(line[:get_terminal_size()[0]]) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/pstree.py b/third_party/python/psutil/scripts/pstree.py deleted file mode 100755 index 0005e4a18161..000000000000 --- a/third_party/python/psutil/scripts/pstree.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -Similar to 'ps aux --forest' on Linux, prints the process list -as a tree structure. - -$ python scripts/pstree.py -0 ? -|- 1 init -| |- 289 cgmanager -| |- 616 upstart-socket-bridge -| |- 628 rpcbind -| |- 892 upstart-file-bridge -| |- 907 dbus-daemon -| |- 978 avahi-daemon -| | `_ 979 avahi-daemon -| |- 987 NetworkManager -| | |- 2242 dnsmasq -| | `_ 10699 dhclient -| |- 993 polkitd -| |- 1061 getty -| |- 1066 su -| | `_ 1190 salt-minion... -... -""" - -from __future__ import print_function -import collections -import sys - -import psutil - - -def print_tree(parent, tree, indent=''): - try: - name = psutil.Process(parent).name() - except psutil.Error: - name = "?" - print(parent, name) - if parent not in tree: - return - children = tree[parent][:-1] - for child in children: - sys.stdout.write(indent + "|- ") - print_tree(child, tree, indent + "| ") - child = tree[parent][-1] - sys.stdout.write(indent + "`_ ") - print_tree(child, tree, indent + " ") - - -def main(): - # construct a dict where 'values' are all the processes - # having 'key' as their parent - tree = collections.defaultdict(list) - for p in psutil.process_iter(): - try: - tree[p.ppid()].append(p.pid) - except (psutil.NoSuchProcess, psutil.ZombieProcess): - pass - # on systems supporting PID 0, PID 0's parent is usually 0 - if 0 in tree and 0 in tree[0]: - tree[0].remove(0) - print_tree(min(tree), tree) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/sensors.py b/third_party/python/psutil/scripts/sensors.py deleted file mode 100755 index 726af3d2c55d..000000000000 --- a/third_party/python/psutil/scripts/sensors.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# 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. - -""" -A clone of 'sensors' utility on Linux printing hardware temperatures, -fans speed and battery info. - -$ python scripts/sensors.py -asus - Temperatures: - asus 57.0°C (high=None°C, critical=None°C) - Fans: - cpu_fan 3500 RPM -acpitz - Temperatures: - acpitz 57.0°C (high=108.0°C, critical=108.0°C) -coretemp - Temperatures: - Physical id 0 61.0°C (high=87.0°C, critical=105.0°C) - Core 0 61.0°C (high=87.0°C, critical=105.0°C) - Core 1 59.0°C (high=87.0°C, critical=105.0°C) -Battery: - charge: 84.95% - status: charging - plugged in: yes -""" - -from __future__ import print_function - -import psutil - - -def secs2hours(secs): - mm, ss = divmod(secs, 60) - hh, mm = divmod(mm, 60) - return "%d:%02d:%02d" % (hh, mm, ss) - - -def main(): - if hasattr(psutil, "sensors_temperatures"): - temps = psutil.sensors_temperatures() - else: - temps = {} - if hasattr(psutil, "sensors_fans"): - fans = psutil.sensors_fans() - else: - fans = {} - if hasattr(psutil, "sensors_battery"): - battery = psutil.sensors_battery() - else: - battery = None - - if not any((temps, fans, battery)): - print("can't read any temperature, fans or battery info") - return - - names = set(list(temps.keys()) + list(fans.keys())) - for name in names: - print(name) - # Temperatures. - if name in temps: - print(" Temperatures:") - for entry in temps[name]: - print(" %-20s %s°C (high=%s°C, critical=%s°C)" % ( - entry.label or name, entry.current, entry.high, - entry.critical)) - # Fans. - if name in fans: - print(" Fans:") - for entry in fans[name]: - print(" %-20s %s RPM" % ( - entry.label or name, entry.current)) - - # Battery. - if battery: - print("Battery:") - print(" charge: %s%%" % round(battery.percent, 2)) - if battery.power_plugged: - print(" status: %s" % ( - "charging" if battery.percent < 100 else "fully charged")) - print(" plugged in: yes") - else: - print(" left: %s" % secs2hours(battery.secsleft)) - print(" status: %s" % "discharging") - print(" plugged in: no") - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/temperatures.py b/third_party/python/psutil/scripts/temperatures.py deleted file mode 100755 index e83df44036f6..000000000000 --- a/third_party/python/psutil/scripts/temperatures.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# 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. - -""" -A clone of 'sensors' utility on Linux printing hardware temperatures. - -$ python scripts/sensors.py -asus - asus 47.0 °C (high = None °C, critical = None °C) - -acpitz - acpitz 47.0 °C (high = 103.0 °C, critical = 103.0 °C) - -coretemp - Physical id 0 54.0 °C (high = 100.0 °C, critical = 100.0 °C) - Core 0 47.0 °C (high = 100.0 °C, critical = 100.0 °C) - Core 1 48.0 °C (high = 100.0 °C, critical = 100.0 °C) - Core 2 47.0 °C (high = 100.0 °C, critical = 100.0 °C) - Core 3 54.0 °C (high = 100.0 °C, critical = 100.0 °C) -""" - -from __future__ import print_function -import sys - -import psutil - - -def main(): - if not hasattr(psutil, "sensors_temperatures"): - sys.exit("platform not supported") - temps = psutil.sensors_temperatures() - if not temps: - sys.exit("can't read any temperature") - for name, entries in temps.items(): - print(name) - for entry in entries: - print(" %-20s %s °C (high = %s °C, critical = %s °C)" % ( - entry.label or name, entry.current, entry.high, - entry.critical)) - print() - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/top.py b/third_party/python/psutil/scripts/top.py deleted file mode 100755 index 0b17471d55fd..000000000000 --- a/third_party/python/psutil/scripts/top.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -A clone of top / htop. - -Author: Giampaolo Rodola' - -$ python scripts/top.py - CPU0 [|||| ] 10.9% - CPU1 [||||| ] 13.1% - CPU2 [||||| ] 12.8% - CPU3 [|||| ] 11.5% - Mem [||||||||||||||||||||||||||||| ] 73.0% 11017M / 15936M - Swap [ ] 1.3% 276M / 20467M - Processes: 347 (sleeping=273, running=1, idle=73) - Load average: 1.10 1.28 1.34 Uptime: 8 days, 21:15:40 - -PID USER NI VIRT RES CPU% MEM% TIME+ NAME -5368 giampaol 0 7.2G 4.3G 41.8 27.7 56:34.18 VirtualBox -24976 giampaol 0 2.1G 487.2M 18.7 3.1 22:05.16 Web Content -22731 giampaol 0 3.2G 596.2M 11.6 3.7 35:04.90 firefox -1202 root 0 807.4M 288.5M 10.6 1.8 12:22.12 Xorg -22811 giampaol 0 2.8G 741.8M 9.0 4.7 2:26.61 Web Content -2590 giampaol 0 2.3G 579.4M 5.5 3.6 28:02.70 compiz -22990 giampaol 0 3.0G 1.2G 4.2 7.6 4:30.32 Web Content -18412 giampaol 0 90.1M 14.5M 3.5 0.1 0:00.26 python3 -26971 netdata 0 20.8M 3.9M 2.9 0.0 3:17.14 apps.plugin -2421 giampaol 0 3.3G 36.9M 2.3 0.2 57:14.21 pulseaudio -... -""" - -import atexit -import datetime -import sys -import time -try: - import curses -except ImportError: - sys.exit('platform not supported') - -import psutil -from psutil._common import bytes2human - - -# --- curses stuff - -def tear_down(): - win.keypad(0) - curses.nocbreak() - curses.echo() - curses.endwin() - - -win = curses.initscr() -atexit.register(tear_down) -curses.endwin() -lineno = 0 - - -def print_line(line, highlight=False): - """A thin wrapper around curses's addstr().""" - global lineno - try: - if highlight: - line += " " * (win.getmaxyx()[1] - len(line)) - win.addstr(lineno, 0, line, curses.A_REVERSE) - else: - win.addstr(lineno, 0, line, 0) - except curses.error: - lineno = 0 - win.refresh() - raise - else: - lineno += 1 - -# --- /curses stuff - - -def poll(interval): - # sleep some time - time.sleep(interval) - procs = [] - procs_status = {} - for p in psutil.process_iter(): - try: - p.dict = p.as_dict(['username', 'nice', 'memory_info', - 'memory_percent', 'cpu_percent', - 'cpu_times', 'name', 'status']) - try: - procs_status[p.dict['status']] += 1 - except KeyError: - procs_status[p.dict['status']] = 1 - except psutil.NoSuchProcess: - pass - else: - procs.append(p) - - # return processes sorted by CPU percent usage - processes = sorted(procs, key=lambda p: p.dict['cpu_percent'], - reverse=True) - return (processes, procs_status) - - -def print_header(procs_status, num_procs): - """Print system-related info, above the process list.""" - - def get_dashes(perc): - dashes = "|" * int((float(perc) / 10 * 4)) - empty_dashes = " " * (40 - len(dashes)) - return dashes, empty_dashes - - # cpu usage - percs = psutil.cpu_percent(interval=0, percpu=True) - for cpu_num, perc in enumerate(percs): - dashes, empty_dashes = get_dashes(perc) - print_line(" CPU%-2s [%s%s] %5s%%" % (cpu_num, dashes, empty_dashes, - perc)) - mem = psutil.virtual_memory() - dashes, empty_dashes = get_dashes(mem.percent) - line = " Mem [%s%s] %5s%% %6s / %s" % ( - dashes, empty_dashes, - mem.percent, - str(int(mem.used / 1024 / 1024)) + "M", - str(int(mem.total / 1024 / 1024)) + "M" - ) - print_line(line) - - # swap usage - swap = psutil.swap_memory() - dashes, empty_dashes = get_dashes(swap.percent) - line = " Swap [%s%s] %5s%% %6s / %s" % ( - dashes, empty_dashes, - swap.percent, - str(int(swap.used / 1024 / 1024)) + "M", - str(int(swap.total / 1024 / 1024)) + "M" - ) - print_line(line) - - # processes number and status - st = [] - for x, y in procs_status.items(): - if y: - st.append("%s=%s" % (x, y)) - st.sort(key=lambda x: x[:3] in ('run', 'sle'), reverse=1) - print_line(" Processes: %s (%s)" % (num_procs, ', '.join(st))) - # load average, uptime - uptime = datetime.datetime.now() - \ - datetime.datetime.fromtimestamp(psutil.boot_time()) - av1, av2, av3 = psutil.getloadavg() - line = " Load average: %.2f %.2f %.2f Uptime: %s" \ - % (av1, av2, av3, str(uptime).split('.')[0]) - print_line(line) - - -def refresh_window(procs, procs_status): - """Print results on screen by using curses.""" - curses.endwin() - templ = "%-6s %-8s %4s %6s %6s %5s %5s %9s %2s" - win.erase() - header = templ % ("PID", "USER", "NI", "VIRT", "RES", "CPU%", "MEM%", - "TIME+", "NAME") - print_header(procs_status, len(procs)) - print_line("") - print_line(header, highlight=True) - for p in procs: - # TIME+ column shows process CPU cumulative time and it - # is expressed as: "mm:ss.ms" - if p.dict['cpu_times'] is not None: - ctime = datetime.timedelta(seconds=sum(p.dict['cpu_times'])) - ctime = "%s:%s.%s" % (ctime.seconds // 60 % 60, - str((ctime.seconds % 60)).zfill(2), - str(ctime.microseconds)[:2]) - else: - ctime = '' - if p.dict['memory_percent'] is not None: - p.dict['memory_percent'] = round(p.dict['memory_percent'], 1) - else: - p.dict['memory_percent'] = '' - if p.dict['cpu_percent'] is None: - p.dict['cpu_percent'] = '' - if p.dict['username']: - username = p.dict['username'][:8] - else: - username = "" - line = templ % (p.pid, - username, - p.dict['nice'], - bytes2human(getattr(p.dict['memory_info'], 'vms', 0)), - bytes2human(getattr(p.dict['memory_info'], 'rss', 0)), - p.dict['cpu_percent'], - p.dict['memory_percent'], - ctime, - p.dict['name'] or '', - ) - try: - print_line(line) - except curses.error: - break - win.refresh() - - -def main(): - try: - interval = 0 - while True: - args = poll(interval) - refresh_window(*args) - interval = 1 - except (KeyboardInterrupt, SystemExit): - pass - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/who.py b/third_party/python/psutil/scripts/who.py deleted file mode 100755 index c2299eb09efd..000000000000 --- a/third_party/python/psutil/scripts/who.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -""" -A clone of 'who' command; print information about users who are -currently logged in. - -$ python scripts/who.py -giampaolo console 2017-03-25 22:24 loginwindow -giampaolo ttys000 2017-03-25 23:28 (10.0.2.2) sshd -""" - -from datetime import datetime - -import psutil - - -def main(): - users = psutil.users() - for user in users: - proc_name = psutil.Process(user.pid).name() if user.pid else "" - print("%-12s %-10s %-10s %-14s %s" % ( - user.name, - user.terminal or '-', - datetime.fromtimestamp(user.started).strftime("%Y-%m-%d %H:%M"), - "(%s)" % user.host if user.host else "", - proc_name - )) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/scripts/winservices.py b/third_party/python/psutil/scripts/winservices.py deleted file mode 100755 index 8792f752e4ac..000000000000 --- a/third_party/python/psutil/scripts/winservices.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -r""" -List all Windows services installed. - -$ python scripts/winservices.py -AeLookupSvc (Application Experience) -status: stopped, start: manual, username: localSystem, pid: None -binpath: C:\Windows\system32\svchost.exe -k netsvcs - -ALG (Application Layer Gateway Service) -status: stopped, start: manual, username: NT AUTHORITY\LocalService, pid: None -binpath: C:\Windows\System32\alg.exe - -APNMCP (Ask Update Service) -status: running, start: automatic, username: LocalSystem, pid: 1108 -binpath: "C:\Program Files (x86)\AskPartnerNetwork\Toolbar\apnmcp.exe" - -AppIDSvc (Application Identity) -status: stopped, start: manual, username: NT Authority\LocalService, pid: None -binpath: C:\Windows\system32\svchost.exe -k LocalServiceAndNoImpersonation - -Appinfo (Application Information) -status: stopped, start: manual, username: LocalSystem, pid: None -binpath: C:\Windows\system32\svchost.exe -k netsvcs -... -""" - - -import os -import sys - -import psutil - - -if os.name != 'nt': - sys.exit("platform not supported (Windows only)") - - -def main(): - for service in psutil.win_service_iter(): - info = service.as_dict() - print("%r (%r)" % (info['name'], info['display_name'])) - print("status: %s, start: %s, username: %s, pid: %s" % ( - info['status'], info['start_type'], info['username'], info['pid'])) - print("binpath: %s" % info['binpath']) - print("") - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/third_party/python/psutil/setup.cfg b/third_party/python/psutil/setup.cfg deleted file mode 100644 index 8bfd5a12f85b..000000000000 --- a/third_party/python/psutil/setup.cfg +++ /dev/null @@ -1,4 +0,0 @@ -[egg_info] -tag_build = -tag_date = 0 - diff --git a/third_party/python/psutil/setup.py b/third_party/python/psutil/setup.py deleted file mode 100755 index 2402a143c4bd..000000000000 --- a/third_party/python/psutil/setup.py +++ /dev/null @@ -1,426 +0,0 @@ -#!/usr/bin/env python3 - -# 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. - -"""Cross-platform lib for process and system monitoring in Python.""" - -from __future__ import print_function -import contextlib -import io -import os -import platform -import re -import shutil -import struct -import sys -import tempfile -import warnings - -with warnings.catch_warnings(): - warnings.simplefilter("ignore") - try: - import setuptools - from setuptools import setup, Extension - except ImportError: - setuptools = None - from distutils.core import setup, Extension - -HERE = os.path.abspath(os.path.dirname(__file__)) - -# ...so we can import _common.py and _compat.py -sys.path.insert(0, os.path.join(HERE, "psutil")) - -from _common import AIX # NOQA -from _common import BSD # NOQA -from _common import FREEBSD # NOQA -from _common import hilite # NOQA -from _common import LINUX # NOQA -from _common import MACOS # NOQA -from _common import NETBSD # NOQA -from _common import OPENBSD # NOQA -from _common import POSIX # NOQA -from _common import SUNOS # NOQA -from _common import WINDOWS # NOQA -from _compat import PY3 # NOQA -from _compat import which # NOQA - - -macros = [] -if POSIX: - macros.append(("PSUTIL_POSIX", 1)) -if BSD: - macros.append(("PSUTIL_BSD", 1)) - -# Needed to determine _Py_PARSE_PID in case it's missing (Python 2, PyPy). -# Taken from Lib/test/test_fcntl.py. -# XXX: not bullet proof as the (long long) case is missing. -if struct.calcsize('l') <= 8: - macros.append(('PSUTIL_SIZEOF_PID_T', '4')) # int -else: - macros.append(('PSUTIL_SIZEOF_PID_T', '8')) # long - - -sources = ['psutil/_psutil_common.c'] -if POSIX: - sources.append('psutil/_psutil_posix.c') - - -extras_require = {} -if sys.version_info[:2] <= (3, 3): - extras_require.update(dict(enum='enum34')) - - -def get_version(): - INIT = os.path.join(HERE, 'psutil/__init__.py') - with open(INIT, 'r') as f: - for line in f: - if line.startswith('__version__'): - ret = eval(line.strip().split(' = ')[1]) - assert ret.count('.') == 2, ret - for num in ret.split('.'): - assert num.isdigit(), ret - return ret - raise ValueError("couldn't find version string") - - -VERSION = get_version() -macros.append(('PSUTIL_VERSION', int(VERSION.replace('.', '')))) - - -def get_description(): - README = os.path.join(HERE, 'README.rst') - with open(README, 'r') as f: - return f.read() - - -@contextlib.contextmanager -def silenced_output(stream_name): - class DummyFile(io.BytesIO): - # see: https://github.com/giampaolo/psutil/issues/678 - errors = "ignore" - - def write(self, s): - pass - - orig = getattr(sys, stream_name) - try: - setattr(sys, stream_name, DummyFile()) - yield - finally: - setattr(sys, stream_name, orig) - - -def missdeps(msg): - s = hilite("C compiler or Python headers are not installed ", ok=False) - s += hilite("on this system. Try to run:\n", ok=False) - s += hilite(msg, ok=False, bold=True) - print(s, file=sys.stderr) - - -if WINDOWS: - def get_winver(): - maj, min = sys.getwindowsversion()[0:2] - return '0x0%s' % ((maj * 100) + min) - - if sys.getwindowsversion()[0] < 6: - msg = "this Windows version is too old (< Windows Vista); " - msg += "psutil 3.4.2 is the latest version which supports Windows " - msg += "2000, XP and 2003 server" - raise RuntimeError(msg) - - macros.append(("PSUTIL_WINDOWS", 1)) - macros.extend([ - # be nice to mingw, see: - # http://www.mingw.org/wiki/Use_more_recent_defined_functions - ('_WIN32_WINNT', get_winver()), - ('_AVAIL_WINVER_', get_winver()), - ('_CRT_SECURE_NO_WARNINGS', None), - # see: https://github.com/giampaolo/psutil/issues/348 - ('PSAPI_VERSION', 1), - ]) - - ext = Extension( - 'psutil._psutil_windows', - sources=sources + [ - 'psutil/_psutil_windows.c', - 'psutil/arch/windows/process_utils.c', - 'psutil/arch/windows/process_info.c', - 'psutil/arch/windows/process_handles.c', - 'psutil/arch/windows/disk.c', - 'psutil/arch/windows/net.c', - 'psutil/arch/windows/cpu.c', - 'psutil/arch/windows/security.c', - 'psutil/arch/windows/services.c', - 'psutil/arch/windows/socks.c', - 'psutil/arch/windows/wmi.c', - ], - define_macros=macros, - libraries=[ - "psapi", "kernel32", "advapi32", "shell32", "netapi32", - "wtsapi32", "ws2_32", "PowrProf", "pdh", - ], - # extra_compile_args=["/W 4"], - # extra_link_args=["/DEBUG"] - ) - -elif MACOS: - macros.append(("PSUTIL_OSX", 1)) - ext = Extension( - 'psutil._psutil_osx', - sources=sources + [ - 'psutil/_psutil_osx.c', - 'psutil/arch/osx/process_info.c', - ], - define_macros=macros, - extra_link_args=[ - '-framework', 'CoreFoundation', '-framework', 'IOKit' - ]) - -elif FREEBSD: - macros.append(("PSUTIL_FREEBSD", 1)) - ext = Extension( - 'psutil._psutil_bsd', - sources=sources + [ - 'psutil/_psutil_bsd.c', - 'psutil/arch/freebsd/specific.c', - 'psutil/arch/freebsd/sys_socks.c', - 'psutil/arch/freebsd/proc_socks.c', - ], - define_macros=macros, - libraries=["devstat"]) - -elif OPENBSD: - macros.append(("PSUTIL_OPENBSD", 1)) - ext = Extension( - 'psutil._psutil_bsd', - sources=sources + [ - 'psutil/_psutil_bsd.c', - 'psutil/arch/openbsd/specific.c', - ], - define_macros=macros, - libraries=["kvm"]) - -elif NETBSD: - macros.append(("PSUTIL_NETBSD", 1)) - ext = Extension( - 'psutil._psutil_bsd', - sources=sources + [ - 'psutil/_psutil_bsd.c', - 'psutil/arch/netbsd/specific.c', - 'psutil/arch/netbsd/socks.c', - ], - define_macros=macros, - libraries=["kvm"]) - -elif LINUX: - def get_ethtool_macro(): - # see: https://github.com/giampaolo/psutil/issues/659 - from distutils.unixccompiler import UnixCCompiler - from distutils.errors import CompileError - - with tempfile.NamedTemporaryFile( - suffix='.c', delete=False, mode="wt") as f: - f.write("#include ") - - output_dir = tempfile.mkdtemp() - try: - compiler = UnixCCompiler() - # https://github.com/giampaolo/psutil/pull/1568 - if os.getenv('CC'): - compiler.set_executable('compiler_so', os.getenv('CC')) - with silenced_output('stderr'): - with silenced_output('stdout'): - compiler.compile([f.name], output_dir=output_dir) - except CompileError: - return ("PSUTIL_ETHTOOL_MISSING_TYPES", 1) - else: - return None - finally: - os.remove(f.name) - shutil.rmtree(output_dir) - - macros.append(("PSUTIL_LINUX", 1)) - ETHTOOL_MACRO = get_ethtool_macro() - if ETHTOOL_MACRO is not None: - macros.append(ETHTOOL_MACRO) - ext = Extension( - 'psutil._psutil_linux', - sources=sources + ['psutil/_psutil_linux.c'], - define_macros=macros) - -elif SUNOS: - macros.append(("PSUTIL_SUNOS", 1)) - ext = Extension( - 'psutil._psutil_sunos', - sources=sources + [ - 'psutil/_psutil_sunos.c', - 'psutil/arch/solaris/v10/ifaddrs.c', - 'psutil/arch/solaris/environ.c' - ], - define_macros=macros, - libraries=['kstat', 'nsl', 'socket']) - -elif AIX: - macros.append(("PSUTIL_AIX", 1)) - ext = Extension( - 'psutil._psutil_aix', - sources=sources + [ - 'psutil/_psutil_aix.c', - 'psutil/arch/aix/net_connections.c', - 'psutil/arch/aix/common.c', - 'psutil/arch/aix/ifaddrs.c'], - libraries=['perfstat'], - define_macros=macros) - -else: - sys.exit('platform %s is not supported' % sys.platform) - - -if POSIX: - posix_extension = Extension( - 'psutil._psutil_posix', - define_macros=macros, - sources=sources) - if SUNOS: - def get_sunos_update(): - # See https://serverfault.com/q/524883 - # for an explanation of Solaris /etc/release - with open('/etc/release') as f: - update = re.search(r'(?<=s10s_u)[0-9]{1,2}', f.readline()) - if update is None: - return 0 - else: - return int(update.group(0)) - - posix_extension.libraries.append('socket') - if platform.release() == '5.10': - # Detect Solaris 5.10, update >= 4, see: - # https://github.com/giampaolo/psutil/pull/1638 - if get_sunos_update() >= 4: - # MIB compliancy starts with SunOS 5.10 Update 4: - posix_extension.define_macros.append(('NEW_MIB_COMPLIANT', 1)) - posix_extension.sources.append('psutil/arch/solaris/v10/ifaddrs.c') - posix_extension.define_macros.append(('PSUTIL_SUNOS10', 1)) - else: - # Other releases are by default considered to be new mib compliant. - posix_extension.define_macros.append(('NEW_MIB_COMPLIANT', 1)) - elif AIX: - posix_extension.sources.append('psutil/arch/aix/ifaddrs.c') - - extensions = [ext, posix_extension] -else: - extensions = [ext] - - -def main(): - kwargs = dict( - name='psutil', - version=VERSION, - description=__doc__ .replace('\n', ' ').strip() if __doc__ else '', - long_description=get_description(), - keywords=[ - 'ps', 'top', 'kill', 'free', 'lsof', 'netstat', 'nice', 'tty', - 'ionice', 'uptime', 'taskmgr', 'process', 'df', 'iotop', 'iostat', - 'ifconfig', 'taskset', 'who', 'pidof', 'pmap', 'smem', 'pstree', - 'monitoring', 'ulimit', 'prlimit', 'smem', 'performance', - 'metrics', 'agent', 'observability', - ], - author='Giampaolo Rodola', - author_email='g.rodola@gmail.com', - url='https://github.com/giampaolo/psutil', - platforms='Platform Independent', - license='BSD', - packages=['psutil', 'psutil.tests'], - ext_modules=extensions, - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Environment :: Console', - 'Environment :: Win32 (MS Windows)', - 'Intended Audience :: Developers', - 'Intended Audience :: Information Technology', - 'Intended Audience :: System Administrators', - 'License :: OSI Approved :: BSD License', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows :: Windows 10', - 'Operating System :: Microsoft :: Windows :: Windows 7', - 'Operating System :: Microsoft :: Windows :: Windows 8', - 'Operating System :: Microsoft :: Windows :: Windows 8.1', - 'Operating System :: Microsoft :: Windows :: Windows Server 2003', - 'Operating System :: Microsoft :: Windows :: Windows Server 2008', - 'Operating System :: Microsoft :: Windows :: Windows Vista', - 'Operating System :: Microsoft', - 'Operating System :: OS Independent', - 'Operating System :: POSIX :: AIX', - 'Operating System :: POSIX :: BSD :: FreeBSD', - 'Operating System :: POSIX :: BSD :: NetBSD', - 'Operating System :: POSIX :: BSD :: OpenBSD', - 'Operating System :: POSIX :: BSD', - 'Operating System :: POSIX :: Linux', - 'Operating System :: POSIX :: SunOS/Solaris', - 'Operating System :: POSIX', - 'Programming Language :: C', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: Implementation :: CPython', - 'Programming Language :: Python :: Implementation :: PyPy', - 'Programming Language :: Python', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Topic :: Software Development :: Libraries', - 'Topic :: System :: Benchmark', - 'Topic :: System :: Hardware :: Hardware Drivers', - 'Topic :: System :: Hardware', - 'Topic :: System :: Monitoring', - 'Topic :: System :: Networking :: Monitoring :: Hardware Watchdog', - 'Topic :: System :: Networking :: Monitoring', - 'Topic :: System :: Networking', - 'Topic :: System :: Operating System', - 'Topic :: System :: Systems Administration', - 'Topic :: Utilities', - ], - ) - if setuptools is not None: - kwargs.update( - python_requires=">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", - extras_require=extras_require, - zip_safe=False, - ) - success = False - try: - setup(**kwargs) - success = True - finally: - if not success and POSIX and not which('gcc'): - py3 = "3" if PY3 else "" - if LINUX: - if which('dpkg'): - missdeps("sudo apt-get install gcc python%s-dev" % py3) - elif which('rpm'): - missdeps("sudo yum install gcc python%s-devel" % py3) - elif MACOS: - print(hilite("XCode (https://developer.apple.com/xcode/) " - "is not installed"), ok=False, file=sys.stderr) - elif FREEBSD: - missdeps("pkg install gcc python%s" % py3) - elif OPENBSD: - missdeps("pkg_add -v gcc python%s" % py3) - elif NETBSD: - missdeps("pkgin install gcc python%s" % py3) - elif SUNOS: - missdeps("sudo ln -s /usr/bin/gcc /usr/local/bin/cc && " - "pkg install gcc") - elif not success and WINDOWS: - if PY3: - ur = "http://www.visualstudio.com/en-au/news/vs2015-preview-vs" - else: - ur = "http://www.microsoft.com/en-us/download/" - ur += "details.aspx?id=44266" - s = "VisualStudio is not installed; get it from %s" % ur - print(hilite(s, ok=False), file=sys.stderr) - - -if __name__ == '__main__': - main() diff --git a/third_party/python/psutil/tox.ini b/third_party/python/psutil/tox.ini deleted file mode 100644 index b148642ba82c..000000000000 --- a/third_party/python/psutil/tox.ini +++ /dev/null @@ -1,28 +0,0 @@ -# Tox (http://tox.testrun.org/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. -# To use it run "pip install tox" and then run "tox" from this -# directory. - -[tox] -envlist = py26, py27, py34, py35, py36, py37, py38, lint - -[testenv] -deps = - py26: ipaddress - py26: mock==1.0.1 - py26: unittest2 - py27: ipaddress - py27: mock - -setenv = - TOX = 1 - -commands = python psutil/tests/runner.py - -usedevelop = True - -[testenv:lint] -deps = flake8 -commands = flake8 -skip_install = True diff --git a/third_party/python/requirements.in b/third_party/python/requirements.in index 36b16ed10c98..b719dc12c2c5 100644 --- a/third_party/python/requirements.in +++ b/third_party/python/requirements.in @@ -34,7 +34,6 @@ pathlib2==2.3.2 pathspec==0.8 pip-tools==5.3.1 ply==3.10 -psutil==5.7.0 pyasn1==0.4.8 pyflakes==2.2.0 pytest==3.6.2 diff --git a/third_party/python/requirements.txt b/third_party/python/requirements.txt index 9ed7a79dd090..88213dcef494 100644 --- a/third_party/python/requirements.txt +++ b/third_party/python/requirements.txt @@ -169,19 +169,6 @@ pluggy==0.6.0 \ ply==3.10 \ --hash=sha256:96e94af7dd7031d8d6dd6e2a8e0de593b511c211a86e28a9c9621c275ac8bacb \ # via -r requirements-mach-vendor-python.in -psutil==5.7.0 \ - --hash=sha256:1413f4158eb50e110777c4f15d7c759521703bd6beb58926f1d562da40180058 \ - --hash=sha256:298af2f14b635c3c7118fd9183843f4e73e681bb6f01e12284d4d70d48a60953 \ - --hash=sha256:60b86f327c198561f101a92be1995f9ae0399736b6eced8f24af41ec64fb88d4 \ - --hash=sha256:685ec16ca14d079455892f25bd124df26ff9137664af445563c1bd36629b5e0e \ - --hash=sha256:73f35ab66c6c7a9ce82ba44b1e9b1050be2a80cd4dcc3352cc108656b115c74f \ - --hash=sha256:75e22717d4dbc7ca529ec5063000b2b294fc9a367f9c9ede1f65846c7955fd38 \ - --hash=sha256:a02f4ac50d4a23253b68233b07e7cdb567bd025b982d5cf0ee78296990c22d9e \ - --hash=sha256:d008ddc00c6906ec80040d26dc2d3e3962109e40ad07fd8a12d0284ce5e0e4f8 \ - --hash=sha256:d84029b190c8a66a946e28b4d3934d2ca1528ec94764b180f7d6ea57b0e75e26 \ - --hash=sha256:e2d0c5b07c6fe5a87fa27b7855017edb0d52ee73b71e6ee368fae268605cc3f5 \ - --hash=sha256:f344ca230dd8e8d5eee16827596f1c22ec0876127c28e800d7ae20ed44c4b310 \ - # via -r requirements-mach-vendor-python.in py==1.5.4 \ --hash=sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7 \ --hash=sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e \