summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL.rst2
-rw-r--r--Makefile14
-rw-r--r--docs/conf.py26
-rw-r--r--docs/index.rst2
-rwxr-xr-xexamples/disk_usage.py7
-rwxr-xr-xexamples/free.py7
-rwxr-xr-xexamples/meminfo.py7
-rwxr-xr-xexamples/netstat.py5
-rwxr-xr-xexamples/pmap.py11
-rwxr-xr-xexamples/process_detail.py4
-rw-r--r--examples/ps.py26
-rwxr-xr-xexamples/who.py3
-rw-r--r--make.bat3
-rw-r--r--psutil/__init__.py53
-rw-r--r--psutil/_common.py14
-rw-r--r--psutil/_compat.py246
-rw-r--r--psutil/_psbsd.py8
-rw-r--r--psutil/_pslinux.py365
-rw-r--r--psutil/_psosx.py9
-rw-r--r--psutil/_psposix.py9
-rw-r--r--psutil/_pssunos.py24
-rw-r--r--psutil/_psutil_linux.c6
-rw-r--r--psutil/_pswindows.py28
-rw-r--r--setup.py12
-rw-r--r--test/_windows.py6
-rw-r--r--test/test_memory_leaks.py5
-rw-r--r--test/test_psutil.py222
27 files changed, 342 insertions, 782 deletions
diff --git a/INSTALL.rst b/INSTALL.rst
index 93ce4691..bb30a06b 100644
--- a/INSTALL.rst
+++ b/INSTALL.rst
@@ -56,8 +56,6 @@ Compiling on Windows using Visual Studio
To use Visual Studio to compile psutil you must have the same version of
Visual Studio used to compile your installation of Python which is::
- Python 2.4: VS 2003
- Python 2.5: VS 2003
Python 2.6: VS 2008
Python 2.7: VS 2008
Python 3.3+: VS 2010
diff --git a/Makefile b/Makefile
index 9b794953..542cc251 100644
--- a/Makefile
+++ b/Makefile
@@ -27,20 +27,10 @@ build: clean
$(PYTHON) setup.py build
install: build
- if test $(PYTHON) = python2.4; then \
- $(PYTHON) setup.py install; \
- elif test $(PYTHON) = python2.5; then \
- $(PYTHON) setup.py install; \
- else \
- $(PYTHON) setup.py install --user; \
- fi
+ $(PYTHON) setup.py install --user; \
uninstall:
- if test $(PYTHON) = python2.4; then \
- pip-2.4 uninstall -y -v psutil; \
- else \
- cd ..; $(PYTHON) -m pip uninstall -y -v psutil; \
- fi
+ cd ..; $(PYTHON) -m pip uninstall -y -v psutil; \
test: install
$(PYTHON) $(TSCRIPT)
diff --git a/docs/conf.py b/docs/conf.py
index 9ec91df7..9fa163b6 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -14,29 +14,17 @@
import datetime
import os
-import sys
-if sys.version_info >= (3, ):
- def u(s):
- return s
-else:
- def u(s):
- if not isinstance(s, unicode): # NOQA
- s = unicode(s, "unicode_escape") # NOQA
- return s
-
-
-PROJECT_NAME = u("psutil")
-AUTHOR = u("Giampaolo Rodola'")
+PROJECT_NAME = "psutil"
+AUTHOR = "Giampaolo Rodola'"
THIS_YEAR = str(datetime.datetime.now().year)
HERE = os.path.abspath(os.path.dirname(__file__))
def get_version():
INIT = os.path.abspath(os.path.join(HERE, '../psutil/__init__.py'))
- f = open(INIT, 'r')
- try:
+ with open(INIT, 'r') as f:
for line in f:
if line.startswith('__version__'):
ret = eval(line.strip().split(' = ')[1])
@@ -46,8 +34,6 @@ def get_version():
return ret
else:
raise ValueError("couldn't find version string")
- finally:
- f.close()
VERSION = get_version()
@@ -77,7 +63,7 @@ master_doc = 'index'
# General information about the project.
project = PROJECT_NAME
-copyright = u('2009-%s, %s' % (THIS_YEAR, AUTHOR))
+copyright = '2009-%s, %s' % (THIS_YEAR, AUTHOR)
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -223,7 +209,7 @@ htmlhelp_basename = '%s-doc' % PROJECT_NAME
# [howto/manual]).
latex_documents = [
('index', '%s.tex' % PROJECT_NAME,
- u('%s documentation') % PROJECT_NAME, AUTHOR),
+ '%s documentation' % PROJECT_NAME, AUTHOR),
]
# The name of an image file (relative to this directory) to place at
@@ -255,7 +241,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
- ('index', PROJECT_NAME, u('%s documentation') % PROJECT_NAME, [AUTHOR], 1)
+ ('index', PROJECT_NAME, '%s documentation' % PROJECT_NAME, [AUTHOR], 1)
]
# If true, show URL addresses after external links.
diff --git a/docs/index.rst b/docs/index.rst
index e053b935..5e0914cb 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -38,7 +38,7 @@ From project's home page:
ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap*.
It currently supports **Linux, Windows, OSX, FreeBSD** and **Sun Solaris**,
both **32-bit** and **64-bit** architectures, with Python versions from
- **2.4** to **3.4**.
+ **2.6** to **3.4**.
`Pypy <http://pypy.org/>`__ is also known to work.
The psutil documentation you're reading is distributed as a single HTML page.
diff --git a/examples/disk_usage.py b/examples/disk_usage.py
index 787cb0f5..d8600a8c 100755
--- a/examples/disk_usage.py
+++ b/examples/disk_usage.py
@@ -18,7 +18,6 @@ Device Total Used Free Use % Type Mount
import sys
import os
import psutil
-from psutil._compat import print_
def bytes2human(n):
@@ -40,8 +39,8 @@ def bytes2human(n):
def main():
templ = "%-17s %8s %8s %8s %5s%% %9s %s"
- print_(templ % ("Device", "Total", "Used", "Free", "Use ", "Type",
- "Mount"))
+ 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 == '':
@@ -50,7 +49,7 @@ def main():
# partition or just hang.
continue
usage = psutil.disk_usage(part.mountpoint)
- print_(templ % (
+ print(templ % (
part.device,
bytes2human(usage.total),
bytes2human(usage.used),
diff --git a/examples/free.py b/examples/free.py
index 95e11fb6..913ca58a 100755
--- a/examples/free.py
+++ b/examples/free.py
@@ -14,15 +14,14 @@ Swap: 0 0 0
"""
import psutil
-from psutil._compat import print_
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 % (
+ print(templ % ('', 'total', 'used', 'free', 'shared', 'buffers', 'cache'))
+ print(templ % (
'Mem:',
int(virt.total / 1024),
int(virt.used / 1024),
@@ -30,7 +29,7 @@ def main():
int(getattr(virt, 'shared', 0) / 1024),
int(getattr(virt, 'buffers', 0) / 1024),
int(getattr(virt, 'cached', 0) / 1024)))
- print_(templ % (
+ print(templ % (
'Swap:', int(swap.total / 1024),
int(swap.used / 1024),
int(swap.free / 1024),
diff --git a/examples/meminfo.py b/examples/meminfo.py
index 671f907c..c463a3de 100755
--- a/examples/meminfo.py
+++ b/examples/meminfo.py
@@ -31,7 +31,6 @@ Sout : 0B
"""
import psutil
-from psutil._compat import print_
def bytes2human(n):
@@ -56,13 +55,13 @@ def pprint_ntuple(nt):
value = getattr(nt, name)
if name != 'percent':
value = bytes2human(value)
- print_('%-10s : %7s' % (name.capitalize(), value))
+ print('%-10s : %7s' % (name.capitalize(), value))
def main():
- print_('MEMORY\n------')
+ print('MEMORY\n------')
pprint_ntuple(psutil.virtual_memory())
- print_('\nSWAP\n----')
+ print('\nSWAP\n----')
pprint_ntuple(psutil.swap_memory())
if __name__ == '__main__':
diff --git a/examples/netstat.py b/examples/netstat.py
index 70bc2317..884622e9 100755
--- a/examples/netstat.py
+++ b/examples/netstat.py
@@ -23,7 +23,6 @@ import socket
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
import psutil
-from psutil._compat import print_
AD = "-"
@@ -38,7 +37,7 @@ proto_map = {
def main():
templ = "%-5s %-30s %-30s %-13s %-6s %s"
- print_(templ % (
+ print(templ % (
"Proto", "Local address", "Remote address", "Status", "PID",
"Program name"))
proc_names = {}
@@ -52,7 +51,7 @@ def main():
raddr = ""
if c.raddr:
raddr = "%s:%s" % (c.raddr)
- print_(templ % (
+ print(templ % (
proto_map[(c.family, c.type)],
laddr,
raddr or AD,
diff --git a/examples/pmap.py b/examples/pmap.py
index 1936c0b2..7593777a 100755
--- a/examples/pmap.py
+++ b/examples/pmap.py
@@ -33,26 +33,25 @@ ffffffffff600000 0K r-xp [vsyscall]
import sys
import psutil
-from psutil._compat import print_
def main():
if len(sys.argv) != 2:
sys.exit('usage: pmap <pid>')
p = psutil.Process(int(sys.argv[1]))
- print_("pid=%s, name=%s" % (p.pid, p.name()))
+ print("pid=%s, name=%s" % (p.pid, p.name()))
templ = "%-16s %10s %-7s %s"
- print_(templ % ("Address", "RSS", "Mode", "Mapping"))
+ print(templ % ("Address", "RSS", "Mode", "Mapping"))
total_rss = 0
for m in p.memory_maps(grouped=False):
total_rss += m.rss
- print_(templ % (
+ print(templ % (
m.addr.split('-')[0].zfill(16),
str(m.rss / 1024) + 'K',
m.perms,
m.path))
- print_("-" * 33)
- print_(templ % ("Total", str(total_rss / 1024) + 'K', '', ''))
+ print("-" * 33)
+ print(templ % ("Total", str(total_rss / 1024) + 'K', '', ''))
if __name__ == '__main__':
main()
diff --git a/examples/process_detail.py b/examples/process_detail.py
index a0787286..a55fc959 100755
--- a/examples/process_detail.py
+++ b/examples/process_detail.py
@@ -68,8 +68,8 @@ def run(pid):
try:
p = psutil.Process(pid)
pinfo = p.as_dict(ad_value=ACCESS_DENIED)
- except psutil.NoSuchProcess:
- sys.exit(str(sys.exc_info()[1]))
+ except psutil.NoSuchProcess as err:
+ sys.exit(str(err))
try:
parent = p.parent()
diff --git a/examples/ps.py b/examples/ps.py
index 2ead7470..2b67bd18 100644
--- a/examples/ps.py
+++ b/examples/ps.py
@@ -16,7 +16,6 @@ import os
import time
import psutil
-from psutil._compat import print_
def main():
@@ -27,8 +26,8 @@ def main():
if os.name == 'posix':
attrs.append('uids')
attrs.append('terminal')
- print_(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
- "START", "TIME", "COMMAND"))
+ print(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
+ "START", "TIME", "COMMAND"))
for p in psutil.process_iter():
try:
pinfo = p.as_dict(attrs, ad_value='')
@@ -65,16 +64,17 @@ def main():
int(pinfo['memory_info'].rss / 1024) or '?'
memp = pinfo['memory_percent'] and \
round(pinfo['memory_percent'], 1) or '?'
- print_(templ % (user[:10],
- pinfo['pid'],
- pinfo['cpu_percent'],
- memp,
- vms,
- rss,
- pinfo.get('terminal', '') or '?',
- ctime,
- cputime,
- pinfo['name'].strip() or '?'))
+ print(templ % (
+ user[:10],
+ pinfo['pid'],
+ pinfo['cpu_percent'],
+ memp,
+ vms,
+ rss,
+ pinfo.get('terminal', '') or '?',
+ ctime,
+ cputime,
+ pinfo['name'].strip() or '?'))
if __name__ == '__main__':
diff --git a/examples/who.py b/examples/who.py
index 8ffbc818..b382bebf 100755
--- a/examples/who.py
+++ b/examples/who.py
@@ -18,13 +18,12 @@ giampaolo pts/9 2014-02-27 01:32 (:0)
from datetime import datetime
import psutil
-from psutil._compat import print_
def main():
users = psutil.users()
for user in users:
- print_("%-15s %-15s %s (%s)" % (
+ print("%-15s %-15s %s (%s)" % (
user.name,
user.terminal or '-',
datetime.fromtimestamp(user.started).strftime("%Y-%m-%d %H:%M"),
diff --git a/make.bat b/make.bat
index 72ace94c..24e5c7e3 100644
--- a/make.bat
+++ b/make.bat
@@ -7,7 +7,6 @@ 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 - mingw32 for Python 2.4 and 2.5
rem - Visual studio 2008 for Python 2.6, 2.7, 3.2
rem - Visual studio 2010 for Python 3.3+
rem ...therefore it might not work on your Windows installation.
@@ -17,8 +16,6 @@ rem To compile for a specific Python version run:
rem
rem set PYTHON=C:\Python24\python.exe & make.bat build
rem
-rem If you compile by using mingw on Python 2.4 and 2.5 you need to patch
-rem distutils first: http://stackoverflow.com/questions/13592192
rem ==========================================================================
if "%PYTHON%" == "" (
diff --git a/psutil/__init__.py b/psutil/__init__.py
index 8cb55187..f1f89e8f 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -38,22 +38,23 @@ __all__ = [
"users", "boot_time", # others
]
-import sys
+import collections
+import errno
+import functools
import os
-import time
import signal
-import warnings
-import errno
import subprocess
+import sys
+import time
+import warnings
try:
import pwd
except ImportError:
pwd = None
from psutil._common import memoize
-from psutil._compat import property, callable, long, defaultdict
-from psutil._compat import (wraps as _wraps,
- PY3 as _PY3)
+from psutil._compat import callable, long
+from psutil._compat import PY3 as _PY3
from psutil._common import (deprecated_method as _deprecated_method,
deprecated as _deprecated,
sdiskio as _nt_sys_diskio,
@@ -251,7 +252,7 @@ def _assert_pid_not_reused(fun):
"""Decorator which raises NoSuchProcess in case a process is no
longer running or its PID has been reused.
"""
- @_wraps(fun)
+ @functools.wraps(fun)
def wrapper(self, *args, **kwargs):
if not self.is_running():
raise NoSuchProcess(self.pid, self._name)
@@ -531,8 +532,7 @@ class Process(object):
if self._exe is None:
try:
exe = self._proc.exe()
- except AccessDenied:
- err = sys.exc_info()[1]
+ except AccessDenied as err:
return guess_it(fallback=err)
else:
if not exe:
@@ -767,7 +767,7 @@ class Process(object):
else:
# construct a dict where 'values' are all the processes
# having 'key' as their parent
- table = defaultdict(list)
+ table = collections.defaultdict(list)
if ppid_map is None:
for p in process_iter():
try:
@@ -966,8 +966,7 @@ class Process(object):
def _send_signal(self, sig):
try:
os.kill(self.pid, sig)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno == errno.ESRCH:
self._gone = True
raise NoSuchProcess(self.pid, self._name)
@@ -1888,7 +1887,6 @@ def test():
output.
"""
import datetime
- from psutil._compat import print_
today_day = datetime.date.today()
templ = "%-10s %5s %4s %4s %7s %7s %-13s %5s %7s %s"
@@ -1897,8 +1895,8 @@ def test():
if _POSIX:
attrs.append('uids')
attrs.append('terminal')
- print_(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
- "START", "TIME", "COMMAND"))
+ print(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
+ "START", "TIME", "COMMAND"))
for p in process_iter():
try:
pinfo = p.as_dict(attrs, ad_value='')
@@ -1935,16 +1933,17 @@ def test():
int(pinfo['memory_info'].rss / 1024) or '?'
memp = pinfo['memory_percent'] and \
round(pinfo['memory_percent'], 1) or '?'
- print_(templ % (user[:10],
- pinfo['pid'],
- pinfo['cpu_percent'],
- memp,
- vms,
- rss,
- pinfo.get('terminal', '') or '?',
- ctime,
- cputime,
- pinfo['name'].strip() or '?'))
+ print(templ % (
+ user[:10],
+ pinfo['pid'],
+ pinfo['cpu_percent'],
+ memp,
+ vms,
+ rss,
+ pinfo.get('terminal', '') or '?',
+ ctime,
+ cputime,
+ pinfo['name'].strip() or '?'))
def _replace_module():
@@ -1984,7 +1983,7 @@ def _replace_module():
_replace_module()
-del property, memoize, division, _replace_module
+del memoize, division, _replace_module
if sys.version_info < (3, 0):
del num
diff --git a/psutil/_common.py b/psutil/_common.py
index 9db5ad37..92d0fd0c 100644
--- a/psutil/_common.py
+++ b/psutil/_common.py
@@ -8,20 +8,19 @@
from __future__ import division
import errno
+import functools
import os
import socket
import stat
-import sys
import warnings
try:
import threading
except ImportError:
import dummy_threading as threading
+from collections import namedtuple
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
-from psutil._compat import namedtuple, wraps
-
# --- constants
AF_INET6 = getattr(socket, 'AF_INET6', None)
@@ -82,7 +81,7 @@ def memoize(fun):
>>> foo.cache_clear()
>>>
"""
- @wraps(fun)
+ @functools.wraps(fun)
def wrapper(*args, **kwargs):
key = (args, frozenset(sorted(kwargs.items())))
lock.acquire()
@@ -119,7 +118,7 @@ def deprecated(replacement=None):
if fun.__doc__ is None:
fun.__doc__ = msg
- @wraps(fun)
+ @functools.wraps(fun)
def inner(*args, **kwargs):
warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
return fun(*args, **kwargs)
@@ -138,7 +137,7 @@ def deprecated_method(replacement):
if fun.__doc__ is None:
fun.__doc__ = msg
- @wraps(fun)
+ @functools.wraps(fun)
def inner(self, *args, **kwargs):
warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
return getattr(self, replacement)(*args, **kwargs)
@@ -153,8 +152,7 @@ def isfile_strict(path):
"""
try:
st = os.stat(path)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno in (errno.EPERM, errno.EACCES):
raise
return False
diff --git a/psutil/_compat.py b/psutil/_compat.py
index ad3bccee..84fd9ca8 100644
--- a/psutil/_compat.py
+++ b/psutil/_compat.py
@@ -6,9 +6,10 @@
"""Module which provides compatibility with older Python versions."""
-__all__ = ["PY3", "int", "long", "xrange", "exec_", "callable", "namedtuple",
- "property", "wraps", "defaultdict", "update_wrapper", "lru_cache"]
+__all__ = ["PY3", "int", "long", "xrange", "exec_", "callable", "lru_cache"]
+import collections
+import functools
import sys
try:
import __builtin__
@@ -24,13 +25,6 @@ if PY3:
unicode = str
basestring = str
exec_ = getattr(__builtin__, "exec")
- print_ = getattr(__builtin__, "print")
-
- def u(s):
- return s
-
- def b(s):
- return s.encode("latin-1")
else:
int = int
long = long
@@ -38,15 +32,9 @@ else:
unicode = unicode
basestring = basestring
- def u(s):
- return unicode(s, "unicode_escape")
-
- def b(s):
- return s
-
def exec_(code, globs=None, locs=None):
if globs is None:
- frame = _sys._getframe(1)
+ frame = sys._getframe(1)
globs = frame.f_globals
if locs is None:
locs = frame.f_locals
@@ -55,10 +43,6 @@ else:
locs = globs
exec("""exec code in globs, locs""")
- def print_(s):
- sys.stdout.write(s + '\n')
- sys.stdout.flush()
-
# removed in 3.0, reintroduced in 3.2
try:
@@ -70,222 +54,6 @@ except NameError:
# --- stdlib additions
-# py 2.6 collections.namedtuple
-# Taken from: http://code.activestate.com/recipes/500261/
-# Credits: Raymond Hettinger
-try:
- from collections import namedtuple
-except ImportError:
- from operator import itemgetter as _itemgetter
- from keyword import iskeyword as _iskeyword
- import sys as _sys
-
- def namedtuple(typename, field_names, verbose=False, rename=False):
- """A collections.namedtuple implementation, see:
- http://docs.python.org/library/collections.html#namedtuple
- """
- if isinstance(field_names, basestring):
- field_names = field_names.replace(',', ' ').split()
- field_names = tuple(map(str, field_names))
- if rename:
- names = list(field_names)
- seen = set()
- for i, name in enumerate(names):
- if ((not min(c.isalnum() or c == '_' for c in name)
- or _iskeyword(name)
- or not name or name[0].isdigit()
- or name.startswith('_')
- or name in seen)):
- names[i] = '_%d' % i
- seen.add(name)
- field_names = tuple(names)
- for name in (typename,) + field_names:
- if not min(c.isalnum() or c == '_' for c in name):
- raise ValueError('Type names and field names can only contain '
- 'alphanumeric characters and underscores: %r'
- % name)
- if _iskeyword(name):
- raise ValueError('Type names and field names cannot be a '
- 'keyword: %r' % name)
- if name[0].isdigit():
- raise ValueError('Type names and field names cannot start '
- 'with a number: %r' % name)
- seen_names = set()
- for name in field_names:
- if name.startswith('_') and not rename:
- raise ValueError(
- 'Field names cannot start with an underscore: %r' % name)
- if name in seen_names:
- raise ValueError('Encountered duplicate field name: %r' % name)
- seen_names.add(name)
-
- numfields = len(field_names)
- argtxt = repr(field_names).replace("'", "")[1:-1]
- reprtxt = ', '.join('%s=%%r' % name for name in field_names)
- template = '''class %(typename)s(tuple):
- '%(typename)s(%(argtxt)s)' \n
- __slots__ = () \n
- _fields = %(field_names)r \n
- def __new__(_cls, %(argtxt)s):
- return _tuple.__new__(_cls, (%(argtxt)s)) \n
- @classmethod
- def _make(cls, iterable, new=tuple.__new__, len=len):
- 'Make a new %(typename)s object from a sequence or iterable'
- result = new(cls, iterable)
- if len(result) != %(numfields)d:
- raise TypeError(
- 'Expected %(numfields)d arguments, got %%d' %% len(result))
- return result \n
- def __repr__(self):
- return '%(typename)s(%(reprtxt)s)' %% self \n
- def _asdict(self):
- 'Return a new dict which maps field names to their values'
- return dict(zip(self._fields, self)) \n
- def _replace(_self, **kwds):
- result = _self._make(map(kwds.pop, %(field_names)r, _self))
- if kwds:
- raise ValueError(
- 'Got unexpected field names: %%r' %% kwds.keys())
- return result \n
- def __getnewargs__(self):
- return tuple(self) \n\n''' % locals()
- for i, name in enumerate(field_names):
- template += ' %s = _property(_itemgetter(%d))\n' % (name, i)
- if verbose:
- sys.stdout.write(template + '\n')
- sys.stdout.flush()
-
- namespace = dict(
- _itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
- _property=property, _tuple=tuple)
- try:
- exec_(template, namespace)
- except SyntaxError:
- e = sys.exc_info()[1]
- raise SyntaxError(e.message + ':\n' + template)
- result = namespace[typename]
- try:
- result.__module__ = _sys._getframe(
- 1).f_globals.get('__name__', '__main__')
- except (AttributeError, ValueError):
- pass
-
- return result
-
-
-# hack to support property getter/setter/deleter on python < 2.6
-# http://docs.python.org/library/functions.html?highlight=property#property
-if hasattr(property, 'setter'):
- property = property
-else:
- class property(__builtin__.property):
- __metaclass__ = type
-
- def __init__(self, fget, *args, **kwargs):
- super(property, self).__init__(fget, *args, **kwargs)
- self.__doc__ = fget.__doc__
-
- def getter(self, method):
- return property(method, self.fset, self.fdel)
-
- def setter(self, method):
- return property(self.fget, method, self.fdel)
-
- def deleter(self, method):
- return property(self.fget, self.fset, method)
-
-
-# py 2.5 collections.defauldict
-# Taken from:
-# http://code.activestate.com/recipes/523034-emulate-collectionsdefaultdict/
-# Credits: Jason Kirtland
-try:
- from collections import defaultdict
-except ImportError:
- class defaultdict(dict):
- """Dict subclass that calls a factory function to supply
- missing values:
- http://docs.python.org/library/collections.html#collections.defaultdict
- """
-
- def __init__(self, default_factory=None, *a, **kw):
- if ((default_factory is not None and
- not hasattr(default_factory, '__call__'))):
- raise TypeError('first argument must be callable')
- dict.__init__(self, *a, **kw)
- self.default_factory = default_factory
-
- def __getitem__(self, key):
- try:
- return dict.__getitem__(self, key)
- except KeyError:
- return self.__missing__(key)
-
- def __missing__(self, key):
- if self.default_factory is None:
- raise KeyError(key)
- self[key] = value = self.default_factory()
- return value
-
- def __reduce__(self):
- if self.default_factory is None:
- args = tuple()
- else:
- args = self.default_factory,
- return type(self), args, None, None, self.items()
-
- def copy(self):
- return self.__copy__()
-
- def __copy__(self):
- return type(self)(self.default_factory, self)
-
- def __deepcopy__(self, memo):
- import copy
- return type(self)(self.default_factory,
- copy.deepcopy(self.items()))
-
- def __repr__(self):
- return 'defaultdict(%s, %s)' % (self.default_factory,
- dict.__repr__(self))
-
-
-# py 2.5 functools.wraps
-try:
- from functools import wraps
-except ImportError:
- def wraps(original):
- def inner(fn):
- for attribute in ['__module__', '__name__', '__doc__']:
- setattr(fn, attribute, getattr(original, attribute))
- for attribute in ['__dict__']:
- if hasattr(fn, attribute):
- getattr(fn, attribute).update(getattr(original, attribute))
- else:
- setattr(fn, attribute,
- getattr(original, attribute).copy())
- return fn
- return inner
-
-
-# py 2.5 functools.update_wrapper
-try:
- from functools import update_wrapper
-except ImportError:
- WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
- WRAPPER_UPDATES = ('__dict__',)
-
- def update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS,
- updated=WRAPPER_UPDATES):
- """Update a wrapper function to look like the wrapped function, see:
- http://docs.python.org/library/functools.html#functools.update_wrapper
- """
- for attr in assigned:
- setattr(wrapper, attr, getattr(wrapped, attr))
- for attr in updated:
- getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
- return wrapper
-
# py 3.2 functools.lru_cache
# Taken from: http://code.activestate.com/recipes/578078
@@ -298,8 +66,8 @@ except ImportError:
except ImportError:
from dummy_threading import RLock
- _CacheInfo = namedtuple("CacheInfo",
- ["hits", "misses", "maxsize", "currsize"])
+ _CacheInfo = collections.namedtuple(
+ "CacheInfo", ["hits", "misses", "maxsize", "currsize"])
class _HashedSeq(list):
__slots__ = 'hashvalue'
@@ -430,6 +198,6 @@ except ImportError:
wrapper.__wrapped__ = user_function
wrapper.cache_info = cache_info
wrapper.cache_clear = cache_clear
- return update_wrapper(wrapper, user_function)
+ return functools.update_wrapper(wrapper, user_function)
return decorating_function
diff --git a/psutil/_psbsd.py b/psutil/_psbsd.py
index 9dcdfc21..8560df4c 100644
--- a/psutil/_psbsd.py
+++ b/psutil/_psbsd.py
@@ -7,13 +7,14 @@
"""FreeBSD platform implementation."""
import errno
+import functools
import os
import sys
+from collections import namedtuple
from psutil import _common
from psutil import _psposix
from psutil._common import conn_tmap, usage_percent
-from psutil._compat import namedtuple, wraps
import _psutil_bsd as cext
import _psutil_posix
@@ -206,15 +207,14 @@ def wrap_exceptions(fun):
"""Decorator which translates bare OSError exceptions into
NoSuchProcess and AccessDenied.
"""
- @wraps(fun)
+ @functools.wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
- except OSError:
+ except OSError as err:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
raise
- err = sys.exc_info()[1]
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
index 2abd59c3..2bedac6f 100644
--- a/psutil/_pslinux.py
+++ b/psutil/_pslinux.py
@@ -10,17 +10,19 @@ from __future__ import division
import base64
import errno
+import functools
import os
import re
import socket
import struct
import sys
import warnings
+from collections import namedtuple, defaultdict
from psutil import _common
from psutil import _psposix
from psutil._common import (isfile_strict, usage_percent, deprecated)
-from psutil._compat import PY3, namedtuple, wraps, b, defaultdict
+from psutil._compat import PY3
import _psutil_linux as cext
import _psutil_posix
@@ -102,11 +104,8 @@ def _get_cputimes_fields():
(user, nice, system, idle, iowait, irq, softirq, [steal, [guest,
[guest_nice]]])
"""
- f = open('/proc/stat', 'rb')
- try:
+ with open('/proc/stat', 'rb') as f:
values = f.readline().split()[1:]
- finally:
- f.close()
fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq']
vlen = len(values)
if vlen >= 8:
@@ -143,15 +142,13 @@ pmmap_ext = namedtuple(
def virtual_memory():
total, free, buffers, shared, _, _ = cext.linux_sysinfo()
cached = active = inactive = None
- f = open('/proc/meminfo', 'rb')
- CACHED, ACTIVE, INACTIVE = b("Cached:"), b("Active:"), b("Inactive:")
- try:
+ with open('/proc/meminfo', 'rb') as f:
for line in f:
- if line.startswith(CACHED):
+ if line.startswith(b"Cached:"):
cached = int(line.split()[1]) * 1024
- elif line.startswith(ACTIVE):
+ elif line.startswith(b"Active:"):
active = int(line.split()[1]) * 1024
- elif line.startswith(INACTIVE):
+ elif line.startswith(b"Inactive:"):
inactive = int(line.split()[1]) * 1024
if (cached is not None
and active is not None
@@ -164,8 +161,6 @@ def virtual_memory():
"be determined and were set to 0"
warnings.warn(msg, RuntimeWarning)
cached = active = inactive = 0
- finally:
- f.close()
avail = free + buffers + cached
used = total - free
percent = usage_percent((total - avail), total, _round=1)
@@ -178,16 +173,14 @@ def swap_memory():
used = total - free
percent = usage_percent(used, total, _round=1)
# get pgin/pgouts
- f = open("/proc/vmstat", "rb")
- SIN, SOUT = b('pswpin'), b('pswpout')
- sin = sout = None
- try:
+ with open("/proc/vmstat", "rb") as f:
+ sin = sout = None
for line in f:
# values are expressed in 4 kilo bytes, we want bytes instead
- if line.startswith(SIN):
- sin = int(line.split(b(' '))[1]) * 4 * 1024
- elif line.startswith(SOUT):
- sout = int(line.split(b(' '))[1]) * 4 * 1024
+ 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:
@@ -197,8 +190,6 @@ def swap_memory():
"be determined and were set to 0"
warnings.warn(msg, RuntimeWarning)
sin = sout = 0
- finally:
- f.close()
return _common.sswap(total, used, free, percent, sin, sout)
@@ -221,11 +212,8 @@ def cpu_times():
[guest_nice]]])
Last 3 fields may not be available on all Linux kernel versions.
"""
- f = open('/proc/stat', 'rb')
- try:
+ with open('/proc/stat', 'rb') as f:
values = f.readline().split()
- finally:
- f.close()
fields = values[1:len(scputimes._fields) + 1]
fields = [float(x) / CLOCK_TICKS for x in fields]
return scputimes(*fields)
@@ -236,21 +224,17 @@ def per_cpu_times():
for every CPU available on the system.
"""
cpus = []
- f = open('/proc/stat', 'rb')
- try:
+ with open('/proc/stat', 'rb') as f:
# get rid of the first line which refers to system wide CPU stats
f.readline()
- CPU = b('cpu')
for line in f:
- if line.startswith(CPU):
+ 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
- finally:
- f.close()
def cpu_count_logical():
@@ -260,30 +244,21 @@ def cpu_count_logical():
except ValueError:
# as a second fallback we try to parse /proc/cpuinfo
num = 0
- f = open('/proc/cpuinfo', 'rb')
- try:
- lines = f.readlines()
- finally:
- f.close()
- PROCESSOR = b('processor')
- for line in lines:
- if line.lower().startswith(PROCESSOR):
- num += 1
+ with open('/proc/cpuinfo', 'rb') 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:
- f = open('/proc/stat', 'rt')
- try:
- lines = f.readlines()
- finally:
- f.close()
search = re.compile('cpu\d')
- for line in lines:
- line = line.split(' ')[0]
- if search.match(line):
- num += 1
+ with open('/proc/stat', 'rt') as f:
+ for line in f:
+ line = line.split(' ')[0]
+ if search.match(line):
+ num += 1
if num == 0:
# mimic os.cpu_count()
@@ -293,16 +268,11 @@ def cpu_count_logical():
def cpu_count_physical():
"""Return the number of physical CPUs in the system."""
- f = open('/proc/cpuinfo', 'rb')
- try:
- lines = f.readlines()
- finally:
- f.close()
- found = set()
- PHYSICAL_ID = b('physical id')
- for line in lines:
- if line.lower().startswith(PHYSICAL_ID):
- found.add(line.strip())
+ with open('/proc/cpuinfo', 'rb') as f:
+ found = set()
+ for line in f:
+ if line.lower().startswith(b'physical id'):
+ found.add(line.strip())
if found:
return len(found)
else:
@@ -332,24 +302,20 @@ def users():
def boot_time():
"""Return the system boot time expressed in seconds since the epoch."""
global BOOT_TIME
- f = open('/proc/stat', 'rb')
- try:
- BTIME = b('btime')
+ with open('/proc/stat', 'rb') as f:
for line in f:
- if line.startswith(BTIME):
+ if line.startswith(b'btime'):
ret = float(line.strip().split()[1])
BOOT_TIME = ret
return ret
raise RuntimeError("line 'btime' not found")
- finally:
- f.close()
# --- processes
def pids():
"""Returns a list of PIDs currently running on the system."""
- return [int(x) for x in os.listdir(b('/proc')) if x.isdigit()]
+ return [int(x) for x in os.listdir(b'/proc') if x.isdigit()]
def pid_exists(pid):
@@ -411,7 +377,7 @@ class Connections:
for pid in pids():
try:
inodes.update(self.get_proc_inodes(pid))
- except OSError:
+ except OSError as err:
# 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
@@ -419,7 +385,6 @@ class Connections:
# 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.
- err = sys.exc_info()[1]
if err.errno not in (
errno.ENOENT, errno.ESRCH, errno.EPERM, errno.EACCES):
raise
@@ -477,59 +442,57 @@ class Connections:
if file.endswith('6') and not os.path.exists(file):
# IPv6 not supported
return
- f = open(file, 'rt')
- f.readline() # skip the first line
- for line in f:
- _, laddr, raddr, status, _, _, _, _, _, inode = \
- line.split()[:10]
- 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 type_ != 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]
+ with open(file, 'rt') as f:
+ f.readline() # skip the first line
+ for line in f:
+ _, laddr, raddr, status, _, _, _, _, _, inode = \
+ line.split()[:10]
+ 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 type_ != socket.AF_UNIX:
+ raise ValueError("ambiguos inode with multiple "
+ "PIDs references")
+ pid, fd = inodes[inode][0]
else:
- status = _common.CONN_NONE
- laddr = self.decode_address(laddr, family)
- raddr = self.decode_address(raddr, family)
- yield (fd, family, type_, laddr, raddr, status, pid)
- f.close()
+ 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
+ laddr = self.decode_address(laddr, family)
+ raddr = self.decode_address(raddr, family)
+ yield (fd, family, type_, laddr, raddr, status, pid)
def process_unix(self, file, family, inodes, filter_pid=None):
"""Parse /proc/net/unix files."""
- f = open(file, 'rt')
- f.readline() # skip the first line
- for line in f:
- tokens = line.split()
- _, _, _, _, type_, _, inode = tokens[0:7]
- 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
+ with open(file, 'rt') as f:
+ f.readline() # skip the first line
+ for line in f:
+ tokens = line.split()
+ _, _, _, _, type_, _, inode = tokens[0:7]
+ if inode in inodes:
+ # With UNIX sockets we can have a single inode
+ # referencing many file descriptors.
+ pairs = inodes[inode]
else:
- if len(tokens) == 8:
- path = tokens[-1]
+ pairs = [(None, -1)]
+ for pid, fd in pairs:
+ if filter_pid is not None and filter_pid != pid:
+ continue
else:
- path = ""
- type_ = int(type_)
- raddr = None
- status = _common.CONN_NONE
- yield (fd, family, type_, path, raddr, status, pid)
- f.close()
+ if len(tokens) == 8:
+ path = tokens[-1]
+ else:
+ path = ""
+ type_ = int(type_)
+ raddr = None
+ status = _common.CONN_NONE
+ yield (fd, family, type_, path, raddr, status, pid)
def retrieve(self, kind, pid=None):
if kind not in self.tmap:
@@ -573,12 +536,8 @@ def net_io_counters():
"""Return network I/O statistics for every network interface
installed on the system as a dict of raw tuples.
"""
- f = open("/proc/net/dev", "rt")
- try:
+ with open("/proc/net/dev", "rt") as f:
lines = f.readlines()
- finally:
- f.close()
-
retdict = {}
for line in lines[2:]:
colon = line.rfind(':')
@@ -611,11 +570,8 @@ def disk_io_counters():
# determine partitions we want to look for
partitions = []
- f = open("/proc/partitions", "rt")
- try:
+ with open("/proc/partitions", "rt") as f:
lines = f.readlines()[2:]
- finally:
- f.close()
for line in reversed(lines):
_, _, _, name = line.split()
if name[-1].isdigit():
@@ -631,11 +587,8 @@ def disk_io_counters():
partitions.append(name)
#
retdict = {}
- f = open("/proc/diskstats", "rt")
- try:
+ with open("/proc/diskstats", "rt") as f:
lines = f.readlines()
- finally:
- f.close()
for line in lines:
# http://www.mjmwired.net/kernel/Documentation/iostats.txt
fields = line.split()
@@ -660,13 +613,10 @@ def disk_io_counters():
def disk_partitions(all=False):
"""Return mounted disk partitions as a list of nameduples"""
phydevs = []
- f = open("/proc/filesystems", "r")
- try:
+ with open("/proc/filesystems", "r") as f:
for line in f:
if not line.startswith("nodev"):
phydevs.append(line.strip())
- finally:
- f.close()
retlist = []
partitions = cext.disk_partitions()
@@ -691,18 +641,17 @@ def wrap_exceptions(fun):
"""Decorator which translates bare OSError and IOError exceptions
into NoSuchProcess and AccessDenied.
"""
- @wraps(fun)
+ @functools.wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
- except EnvironmentError:
+ except EnvironmentError as err:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
raise
# 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.
- err = sys.exc_info()[1]
if err.errno in (errno.ENOENT, errno.ESRCH):
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
@@ -727,18 +676,14 @@ class Process(object):
f = open(fname, "rt", encoding=DEFAULT_ENCODING)
else:
f = open(fname, "rt")
- try:
- name = f.read().split(' ')[1].replace('(', '').replace(')', '')
- finally:
- f.close()
- # XXX - gets changed later and probably needs refactoring
- return name
+ with f:
+ # XXX - gets changed later and probably needs refactoring
+ return f.read().split(' ')[1].replace('(', '').replace(')', '')
def exe(self):
try:
exe = os.readlink("/proc/%s/exe" % self.pid)
- except (OSError, IOError):
- err = sys.exc_info()[1]
+ except (OSError, IOError) as err:
if err.errno in (errno.ENOENT, errno.ESRCH):
# no such file error; might be raised also if the
# path actually exists for system processes with
@@ -769,20 +714,15 @@ class Process(object):
f = open(fname, "rt", encoding=DEFAULT_ENCODING)
else:
f = open(fname, "rt")
- try:
+ with f:
# return the args as a list
return [x for x in f.read().split('\x00') if x]
- finally:
- f.close()
@wrap_exceptions
def terminal(self):
tmap = _psposix._get_terminal_map()
- f = open("/proc/%s/stat" % self.pid, 'rb')
- try:
- tty_nr = int(f.read().split(b(' '))[6])
- finally:
- f.close()
+ with open("/proc/%s/stat" % self.pid, 'rb') as f:
+ tty_nr = int(f.read().split(b' ')[6])
try:
return tmap[tty_nr]
except KeyError:
@@ -792,27 +732,22 @@ class Process(object):
@wrap_exceptions
def io_counters(self):
fname = "/proc/%s/io" % self.pid
- f = open(fname, 'rb')
- SYSCR, SYSCW = b("syscr"), b("syscw")
- READ_BYTES, WRITE_BYTES = b("read_bytes"), b("write_bytes")
- try:
+ with open(fname, 'rb') as f:
rcount = wcount = rbytes = wbytes = None
for line in f:
- if rcount is None and line.startswith(SYSCR):
+ if rcount is None and line.startswith(b"syscr"):
rcount = int(line.split()[1])
- elif wcount is None and line.startswith(SYSCW):
+ elif wcount is None and line.startswith(b"syscw"):
wcount = int(line.split()[1])
- elif rbytes is None and line.startswith(READ_BYTES):
+ elif rbytes is None and line.startswith(b"read_bytes"):
rbytes = int(line.split()[1])
- elif wbytes is None and line.startswith(WRITE_BYTES):
+ elif wbytes is None and line.startswith(b"write_bytes"):
wbytes = int(line.split()[1])
for x in (rcount, wcount, rbytes, wbytes):
if x is None:
raise NotImplementedError(
"couldn't read all necessary info from %r" % fname)
return _common.pio(rcount, wcount, rbytes, wbytes)
- finally:
- f.close()
else:
def io_counters(self):
raise NotImplementedError("couldn't find /proc/%s/io (kernel "
@@ -820,14 +755,11 @@ class Process(object):
@wrap_exceptions
def cpu_times(self):
- f = open("/proc/%s/stat" % self.pid, 'rb')
- try:
+ with open("/proc/%s/stat" % self.pid, 'rb') as f:
st = f.read().strip()
- finally:
- f.close()
# ignore the first two values ("pid (exe)")
- st = st[st.find(b(')')) + 2:]
- values = st.split(b(' '))
+ st = st[st.find(b')') + 2:]
+ values = st.split(b' ')
utime = float(values[11]) / CLOCK_TICKS
stime = float(values[12]) / CLOCK_TICKS
return _common.pcputimes(utime, stime)
@@ -844,14 +776,11 @@ class Process(object):
@wrap_exceptions
def create_time(self):
- f = open("/proc/%s/stat" % self.pid, 'rb')
- try:
+ with open("/proc/%s/stat" % self.pid, 'rb') as f:
st = f.read().strip()
- finally:
- f.close()
# ignore the first two values ("pid (exe)")
- st = st[st.rfind(b(')')) + 2:]
- values = st.split(b(' '))
+ st = st[st.rfind(b')') + 2:]
+ values = st.split(b' ')
# 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
@@ -862,13 +791,10 @@ class Process(object):
@wrap_exceptions
def memory_info(self):
- f = open("/proc/%s/statm" % self.pid, 'rb')
- try:
+ with open("/proc/%s/statm" % self.pid, 'rb') as f:
vms, rss = f.readline().split()[:2]
return _common.pmem(int(rss) * PAGESIZE,
int(vms) * PAGESIZE)
- finally:
- f.close()
@wrap_exceptions
def memory_info_ex(self):
@@ -883,12 +809,9 @@ class Process(object):
# | data | data + stack | drs | DATA |
# | dirty | dirty pages (unused in Linux 2.6) | dt | |
# ============================================================
- f = open("/proc/%s/statm" % self.pid, "rb")
- try:
+ with open("/proc/%s/statm" % self.pid, "rb") as f:
vms, rss, shared, text, lib, data, dirty = \
[int(x) * PAGESIZE for x in f.readline().split()[:7]]
- finally:
- f.close()
return pextmem(rss, vms, shared, text, lib, data, dirty)
if os.path.exists('/proc/%s/smaps' % os.getpid()):
@@ -947,13 +870,12 @@ class Process(object):
data.get('Anonymous:', 0),
data.get('Swap:', 0))
f.close()
- except EnvironmentError:
+ except EnvironmentError as err:
# XXX - Can't use wrap_exceptions decorator as we're
# returning a generator; this probably needs some
# refactoring in order to avoid this code duplication.
if f is not None:
f.close()
- err = sys.exc_info()[1]
if err.errno in (errno.ENOENT, errno.ESRCH):
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
@@ -983,14 +905,11 @@ class Process(object):
@wrap_exceptions
def num_ctx_switches(self):
vol = unvol = None
- f = open("/proc/%s/status" % self.pid, "rb")
- VOLUNTARY = b("voluntary_ctxt_switches")
- NON_VOLUNTARY = b("nonvoluntary_ctxt_switches")
- try:
+ with open("/proc/%s/status" % self.pid, "rb") as f:
for line in f:
- if line.startswith(VOLUNTARY):
+ if line.startswith(b"voluntary_ctxt_switches"):
vol = int(line.split()[1])
- elif line.startswith(NON_VOLUNTARY):
+ elif line.startswith(b"nonvoluntary_ctxt_switches"):
unvol = int(line.split()[1])
if vol is not None and unvol is not None:
return _common.pctxsw(vol, unvol)
@@ -998,20 +917,14 @@ class Process(object):
"'voluntary_ctxt_switches' and 'nonvoluntary_ctxt_switches'"
"fields were not found in /proc/%s/status; the kernel is "
"probably older than 2.6.23" % self.pid)
- finally:
- f.close()
@wrap_exceptions
def num_threads(self):
- f = open("/proc/%s/status" % self.pid, "rb")
- try:
- THREADS = b("Threads:")
+ with open("/proc/%s/status" % self.pid, "rb") as f:
for line in f:
- if line.startswith(THREADS):
+ if line.startswith(b"Threads:"):
return int(line.split()[1])
raise NotImplementedError("line not found")
- finally:
- f.close()
@wrap_exceptions
def threads(self):
@@ -1022,21 +935,18 @@ class Process(object):
for thread_id in thread_ids:
try:
f = open("/proc/%s/task/%s/stat" % (self.pid, thread_id), 'rb')
- except EnvironmentError:
- err = sys.exc_info()[1]
+ except EnvironmentError as err:
if err.errno == errno.ENOENT:
# no such file or directory; it means thread
# disappeared on us
hit_enoent = True
continue
raise
- try:
+ with f:
st = f.read().strip()
- finally:
- f.close()
# ignore the first two values ("pid (exe)")
- st = st[st.find(b(')')) + 2:]
- values = st.split(b(' '))
+ 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)
@@ -1048,12 +958,9 @@ class Process(object):
@wrap_exceptions
def nice_get(self):
- # f = open('/proc/%s/stat' % self.pid, 'r')
- # try:
+ # with open('/proc/%s/stat' % self.pid, 'r') as f:
# data = f.read()
# return int(data.split()[18])
- # finally:
- # f.close()
# Use C implementation
return _psutil_posix.getpriority(self.pid)
@@ -1070,8 +977,7 @@ class Process(object):
def cpu_affinity_set(self, cpus):
try:
cext.proc_cpu_affinity_set(self.pid, cpus)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno == errno.EINVAL:
allcpus = tuple(range(len(per_cpu_times())))
for cpu in cpus:
@@ -1131,19 +1037,15 @@ class Process(object):
@wrap_exceptions
def status(self):
- f = open("/proc/%s/status" % self.pid, 'rb')
- try:
- STATE = b("State:")
+ with open("/proc/%s/status" % self.pid, 'rb') as f:
for line in f:
- if line.startswith(STATE):
+ if line.startswith(b"State:"):
letter = line.split()[1]
if PY3:
letter = letter.decode()
# XXX is '?' legit? (we're not supposed to return
# it anyway)
return PROC_STATUSES.get(letter, '?')
- finally:
- f.close()
@wrap_exceptions
def open_files(self):
@@ -1155,9 +1057,8 @@ class Process(object):
if os.path.islink(file):
try:
file = os.readlink(file)
- except OSError:
+ except OSError as err:
# ENOENT == file which is gone in the meantime
- err = sys.exc_info()[1]
if err.errno in (errno.ENOENT, errno.ESRCH):
hit_enoent = True
continue
@@ -1188,39 +1089,27 @@ class Process(object):
@wrap_exceptions
def ppid(self):
- f = open("/proc/%s/status" % self.pid, 'rb')
- try:
- PPID = b("PPid:")
+ with open("/proc/%s/status" % self.pid, 'rb') as f:
for line in f:
- if line.startswith(PPID):
+ if line.startswith(b"PPid:"):
# PPid: nnnn
return int(line.split()[1])
raise NotImplementedError("line not found")
- finally:
- f.close()
@wrap_exceptions
def uids(self):
- f = open("/proc/%s/status" % self.pid, 'rb')
- try:
- UID = b('Uid:')
+ with open("/proc/%s/status" % self.pid, 'rb') as f:
for line in f:
- if line.startswith(UID):
+ if line.startswith(b'Uid:'):
_, real, effective, saved, fs = line.split()
return _common.puids(int(real), int(effective), int(saved))
raise NotImplementedError("line not found")
- finally:
- f.close()
@wrap_exceptions
def gids(self):
- f = open("/proc/%s/status" % self.pid, 'rb')
- try:
- GID = b('Gid:')
+ with open("/proc/%s/status" % self.pid, 'rb') as f:
for line in f:
- if line.startswith(GID):
+ if line.startswith(b'Gid:'):
_, real, effective, saved, fs = line.split()
return _common.pgids(int(real), int(effective), int(saved))
raise NotImplementedError("line not found")
- finally:
- f.close()
diff --git a/psutil/_psosx.py b/psutil/_psosx.py
index 8953867d..c40ef1d7 100644
--- a/psutil/_psosx.py
+++ b/psutil/_psosx.py
@@ -7,13 +7,13 @@
"""OSX platform implementation."""
import errno
+import functools
import os
-import sys
+from collections import namedtuple
from psutil import _common
from psutil import _psposix
from psutil._common import conn_tmap, usage_percent, isfile_strict
-from psutil._compat import namedtuple, wraps
import _psutil_osx as cext
import _psutil_posix
@@ -176,15 +176,14 @@ def wrap_exceptions(fun):
"""Decorator which translates bare OSError exceptions into
NoSuchProcess and AccessDenied.
"""
- @wraps(fun)
+ @functools.wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
- except OSError:
+ except OSError as err:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
raise
- err = sys.exc_info()[1]
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
diff --git a/psutil/_psposix.py b/psutil/_psposix.py
index 81076043..280cdeeb 100644
--- a/psutil/_psposix.py
+++ b/psutil/_psposix.py
@@ -31,8 +31,7 @@ def pid_exists(pid):
return True
try:
os.kill(pid, 0)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno == errno.ESRCH:
# ESRCH == No such process
return False
@@ -78,8 +77,7 @@ def wait_pid(pid, timeout=None):
while 1:
try:
retpid, status = waitcall()
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno == errno.EINTR:
delay = check_timeout(delay)
continue
@@ -150,8 +148,7 @@ def _get_terminal_map():
assert name not in ret
try:
ret[os.stat(name).st_rdev] = name
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno != errno.ENOENT:
raise
return ret
diff --git a/psutil/_pssunos.py b/psutil/_pssunos.py
index 2fc1ec45..7b5385ef 100644
--- a/psutil/_pssunos.py
+++ b/psutil/_pssunos.py
@@ -11,11 +11,12 @@ import os
import socket
import subprocess
import sys
+from collections import namedtuple
from psutil import _common
from psutil import _psposix
from psutil._common import usage_percent, isfile_strict
-from psutil._compat import namedtuple, PY3
+from psutil._compat import PY3
import _psutil_posix
import _psutil_sunos as cext
@@ -232,14 +233,13 @@ def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
- except EnvironmentError:
+ except EnvironmentError as err:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
raise
# 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.
- err = sys.exc_info()[1]
if err.errno in (errno.ENOENT, errno.ESRCH):
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
@@ -293,8 +293,7 @@ class Process(object):
# fine.
try:
return _psutil_posix.getpriority(self.pid)
- except EnvironmentError:
- err = sys.exc_info()[1]
+ except EnvironmentError as err:
if err.errno in (errno.ENOENT, errno.ESRCH):
if pid_exists(self.pid):
raise AccessDenied(self.pid, self._name)
@@ -338,8 +337,7 @@ class Process(object):
for x in (0, 1, 2, 255):
try:
return os.readlink('/proc/%d/path/%d' % (self.pid, x))
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno == errno.ENOENT:
hit_enoent = True
continue
@@ -356,8 +354,7 @@ class Process(object):
# Reference: http://goo.gl/55XgO
try:
return os.readlink("/proc/%s/path/cwd" % self.pid)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno == errno.ENOENT:
os.stat("/proc/%s" % self.pid)
return None
@@ -388,9 +385,8 @@ class Process(object):
try:
utime, stime = cext.query_process_thread(
self.pid, tid)
- except EnvironmentError:
+ except EnvironmentError as err:
# ENOENT == thread gone in meantime
- err = sys.exc_info()[1]
if err.errno == errno.ENOENT:
hit_enoent = True
continue
@@ -413,9 +409,8 @@ class Process(object):
if os.path.islink(path):
try:
file = os.readlink(path)
- except OSError:
+ except OSError as err:
# ENOENT == file which is gone in the meantime
- err = sys.exc_info()[1]
if err.errno == errno.ENOENT:
hit_enoent = True
continue
@@ -495,8 +490,7 @@ class Process(object):
if not name.startswith('['):
try:
name = os.readlink('/proc/%s/path/%s' % (self.pid, name))
- except OSError:
- err = sys.exc_info()[1]
+ 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).
diff --git a/psutil/_psutil_linux.c b/psutil/_psutil_linux.c
index 4602178e..164b9973 100644
--- a/psutil/_psutil_linux.c
+++ b/psutil/_psutil_linux.c
@@ -373,10 +373,8 @@ psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args)
}
if (!PySequence_Check(py_cpu_set)) {
- // does not work on Python 2.4
- // PyErr_Format(PyExc_TypeError, "sequence argument expected, got %s",
- // Py_TYPE(py_cpu_set)->tp_name);
- PyErr_Format(PyExc_TypeError, "sequence argument expected");
+ PyErr_Format(PyExc_TypeError, "sequence argument expected, got %s",
+ Py_TYPE(py_cpu_set)->tp_name);
goto error;
}
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index b540bdac..6068446b 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -7,12 +7,13 @@
"""Windows platform implementation."""
import errno
+import functools
import os
-import sys
+from collections import namedtuple
from psutil import _common
from psutil._common import conn_tmap, usage_percent, isfile_strict
-from psutil._compat import PY3, xrange, wraps, lru_cache, namedtuple
+from psutil._compat import PY3, xrange, lru_cache
import _psutil_windows as cext
# process priority constants, import from __init__.py:
@@ -200,15 +201,14 @@ def wrap_exceptions(fun):
"""Decorator which translates bare OSError and WindowsError
exceptions into NoSuchProcess and AccessDenied.
"""
- @wraps(fun)
+ @functools.wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
- except OSError:
+ except OSError as err:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
raise
- err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
raise AccessDenied(self.pid, self._name)
if err.errno == errno.ESRCH:
@@ -265,8 +265,7 @@ class Process(object):
def _get_raw_meminfo(self):
try:
return cext.proc_memory_info(self.pid)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno in ACCESS_DENIED_SET:
return cext.proc_memory_info_2(self.pid)
raise
@@ -287,10 +286,9 @@ class Process(object):
def memory_maps(self):
try:
raw = cext.proc_memory_maps(self.pid)
- except OSError:
+ except OSError as err:
# XXX - can't use wrap_exceptions decorator as we're
# returning a generator; probably needs refactoring.
- err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
raise AccessDenied(self.pid, self._name)
if err.errno == errno.ESRCH:
@@ -334,8 +332,7 @@ class Process(object):
return boot_time()
try:
return cext.proc_create_time(self.pid)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno in ACCESS_DENIED_SET:
return cext.proc_create_time_2(self.pid)
raise
@@ -357,8 +354,7 @@ class Process(object):
def cpu_times(self):
try:
ret = cext.proc_cpu_times(self.pid)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno in ACCESS_DENIED_SET:
ret = cext.proc_cpu_times_2(self.pid)
else:
@@ -431,8 +427,7 @@ class Process(object):
def io_counters(self):
try:
ret = cext.proc_io_counters(self.pid)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno in ACCESS_DENIED_SET:
ret = cext.proc_io_counters_2(self.pid)
else:
@@ -478,8 +473,7 @@ class Process(object):
def num_handles(self):
try:
return cext.proc_num_handles(self.pid)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno in ACCESS_DENIED_SET:
return cext.proc_num_handles_2(self.pid)
raise
diff --git a/setup.py b/setup.py
index 277ef75b..28142398 100644
--- a/setup.py
+++ b/setup.py
@@ -22,8 +22,7 @@ HERE = os.path.abspath(os.path.dirname(__file__))
def get_version():
INIT = os.path.join(HERE, 'psutil/__init__.py')
- f = open(INIT, 'r')
- try:
+ with open(INIT, 'r') as f:
for line in f:
if line.startswith('__version__'):
ret = eval(line.strip().split(' = ')[1])
@@ -33,17 +32,12 @@ def get_version():
return ret
else:
raise ValueError("couldn't find version string")
- finally:
- f.close()
def get_description():
README = os.path.join(HERE, 'README.rst')
- f = open(README, 'r')
- try:
+ with open(README, 'r') as f:
return f.read()
- finally:
- f.close()
# POSIX
@@ -166,8 +160,6 @@ def main():
'Operating System :: POSIX',
'Programming Language :: C',
'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.4',
- 'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
diff --git a/test/_windows.py b/test/_windows.py
index e1b27cc0..5f61bd20 100644
--- a/test/_windows.py
+++ b/test/_windows.py
@@ -37,8 +37,7 @@ def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno in ACCESS_DENIED_SET:
raise psutil.AccessDenied(None, None)
if err.errno == errno.ESRCH:
@@ -215,8 +214,7 @@ class WindowsSpecificTestCase(unittest.TestCase):
break
try:
usage = psutil.disk_usage(ps_part.mountpoint)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno == errno.ENOENT:
# usually this is the floppy
break
diff --git a/test/test_memory_leaks.py b/test/test_memory_leaks.py
index c33d37f0..a8f6fc68 100644
--- a/test/test_memory_leaks.py
+++ b/test/test_memory_leaks.py
@@ -227,11 +227,8 @@ class TestProcessObjectLeaks(Base):
@skip_if_linux()
def test_open_files(self):
safe_remove(TESTFN) # needed after UNIX socket test has run
- f = open(TESTFN, 'w')
- try:
+ with open(TESTFN, 'w'):
self.execute('open_files')
- finally:
- f.close()
# OSX implementation is unbelievably slow
@unittest.skipIf(OSX, "OSX implementation is too slow")
diff --git a/test/test_psutil.py b/test/test_psutil.py
index 40bfac4b..3cf70ce9 100644
--- a/test/test_psutil.py
+++ b/test/test_psutil.py
@@ -16,8 +16,10 @@ https://pypi.python.org/pypi/unittest2
from __future__ import division
import atexit
+import collections
import datetime
import errno
+import functools
import os
import pickle
import re
@@ -51,7 +53,7 @@ else:
import unittest
import psutil
-from psutil._compat import PY3, callable, long, wraps, unicode
+from psutil._compat import PY3, callable, long, unicode
# ===================================================================
@@ -161,16 +163,16 @@ def pyrun(src):
# >= 2.6 only
fd, path = tempfile.mkstemp(prefix=TESTFILE_PREFIX)
_testfiles.append(path)
- f = open(path, 'wb')
- try:
- f.write(src)
- f.flush()
- subp = get_test_subprocess([PYTHON, f.name], stdout=None, stderr=None)
- wait_for_pid(subp.pid)
- return subp
- finally:
- os.close(fd)
- f.close()
+ with open(path, 'wb') as f:
+ try:
+ f.write(src)
+ f.flush()
+ subp = get_test_subprocess([PYTHON, f.name], stdout=None,
+ stderr=None)
+ wait_for_pid(subp.pid)
+ return subp
+ finally:
+ os.close(fd)
def warn(msg):
@@ -323,8 +325,7 @@ def check_connection(conn):
s = socket.socket(conn.family, conn.type)
try:
s.bind((conn.laddr[0], 0))
- except socket.error:
- err = sys.exc_info()[1]
+ except socket.error as err:
if err.errno != errno.EADDRNOTAVAIL:
raise
s.close()
@@ -339,15 +340,12 @@ def check_connection(conn):
try:
try:
dupsock = socket.fromfd(conn.fd, conn.family, conn.type)
- except (socket.error, OSError):
- err = sys.exc_info()[1]
+ except (socket.error, OSError) as err:
if err.args[0] != errno.EBADF:
raise
else:
- # python >= 2.5
- if hasattr(dupsock, "family"):
- assert dupsock.family == conn.family
- assert dupsock.type == conn.type
+ assert dupsock.family == conn.family
+ assert dupsock.type == conn.type
finally:
if dupsock is not None:
dupsock.close()
@@ -357,8 +355,7 @@ def safe_remove(file):
"Convenience function for removing temporary test files"
try:
os.remove(file)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno != errno.ENOENT:
# file is being used by another process
if WINDOWS and isinstance(err, WindowsError) and err.errno == 13:
@@ -370,8 +367,7 @@ def safe_rmdir(dir):
"Convenience function for removing temporary test directories"
try:
os.rmdir(dir)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.errno != errno.ENOENT:
raise
@@ -394,7 +390,7 @@ def retry_before_failing(ntimes=None):
actually failing.
"""
def decorator(fun):
- @wraps(fun)
+ @functools.wraps(fun)
def wrapper(*args, **kwargs):
for x in range(ntimes or NO_RETRIES):
try:
@@ -409,7 +405,7 @@ def retry_before_failing(ntimes=None):
def skip_on_access_denied(only_if=None):
"""Decorator to Ignore AccessDenied exceptions."""
def decorator(fun):
- @wraps(fun)
+ @functools.wraps(fun)
def wrapper(*args, **kwargs):
try:
return fun(*args, **kwargs)
@@ -428,7 +424,7 @@ def skip_on_access_denied(only_if=None):
def skip_on_not_implemented(only_if=None):
"""Decorator to Ignore NotImplementedError exceptions."""
def decorator(fun):
- @wraps(fun)
+ @functools.wraps(fun)
def wrapper(*args, **kwargs):
try:
return fun(*args, **kwargs)
@@ -513,12 +509,6 @@ class ThreadTask(threading.Thread):
self.join()
-# python 2.4
-if not hasattr(subprocess.Popen, 'terminate'):
- subprocess.Popen.terminate = \
- lambda self: psutil.Process(self.pid).terminate()
-
-
# ===================================================================
# --- System-related API tests
# ===================================================================
@@ -921,8 +911,7 @@ class TestSystemAPIs(unittest.TestCase):
fname = tempfile.mktemp()
try:
psutil.disk_usage(fname)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
if err.args[0] != errno.ENOENT:
raise
else:
@@ -976,10 +965,9 @@ class TestSystemAPIs(unittest.TestCase):
if not WINDOWS:
try:
os.stat(disk.mountpoint)
- except OSError:
+ except OSError as err:
# http://mail.python.org/pipermail/python-dev/
# 2012-June/120787.html
- err = sys.exc_info()[1]
if err.errno not in (errno.EPERM, errno.EACCES):
raise
else:
@@ -1296,9 +1284,8 @@ class TestProcess(unittest.TestCase):
p = psutil.Process()
# test reads
io1 = p.io_counters()
- f = open(PYTHON, 'rb')
- f.read()
- f.close()
+ with open(PYTHON, 'rb') as f:
+ f.read()
io2 = p.io_counters()
if not BSD:
assert io2.read_count > io1.read_count, (io1, io2)
@@ -1662,11 +1649,10 @@ class TestProcess(unittest.TestCase):
p = psutil.Process()
files = p.open_files()
self.assertFalse(TESTFN in files)
- f = open(TESTFN, 'w')
- call_until(p.open_files, "len(ret) != %i" % len(files))
- filenames = [x.path for x in p.open_files()]
- self.assertIn(TESTFN, filenames)
- f.close()
+ with open(TESTFN, 'w'):
+ call_until(p.open_files, "len(ret) != %i" % len(files))
+ filenames = [x.path for x in p.open_files()]
+ self.assertIn(TESTFN, filenames)
for file in filenames:
assert os.path.isfile(file), file
@@ -1687,25 +1673,24 @@ class TestProcess(unittest.TestCase):
def test_open_files2(self):
# test fd and path fields
- fileobj = open(TESTFN, 'w')
- p = psutil.Process()
- for path, fd in p.open_files():
- if path == fileobj.name or fd == fileobj.fileno():
- break
- else:
- self.fail("no file found; files=%s" % repr(p.open_files()))
- self.assertEqual(path, fileobj.name)
- if WINDOWS:
- self.assertEqual(fd, -1)
- else:
- self.assertEqual(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
- fileobj.close()
- self.assertTrue(fileobj.name not in p.open_files())
+ with open(TESTFN, 'w') as fileobj:
+ p = psutil.Process()
+ for path, fd in p.open_files():
+ if path == fileobj.name or fd == fileobj.fileno():
+ break
+ else:
+ self.fail("no file found; files=%s" % repr(p.open_files()))
+ self.assertEqual(path, fileobj.name)
+ if WINDOWS:
+ self.assertEqual(fd, -1)
+ else:
+ self.assertEqual(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.assertTrue(fileobj.name not in p.open_files())
def compare_proc_sys_cons(self, pid, proc_cons):
from psutil._common import pconn
@@ -1973,8 +1958,7 @@ class TestProcess(unittest.TestCase):
def test_children_duplicates(self):
# find the process which has the highest number of children
- from psutil._compat import defaultdict
- table = defaultdict(int)
+ table = collections.defaultdict(int)
for p in psutil.process_iter():
try:
table[p.ppid()] += 1
@@ -2241,8 +2225,7 @@ class TestFetchAllProcesses(unittest.TestCase):
msg = "%r was skipped because not implemented" % (
self.__class__.__name__ + '.test_' + name)
warn(msg)
- except (psutil.NoSuchProcess, psutil.AccessDenied):
- err = sys.exc_info()[1]
+ except (psutil.NoSuchProcess, psutil.AccessDenied) as err:
self.assertEqual(err.pid, p.pid)
if err.name:
# make sure exception's name attr is set
@@ -2255,8 +2238,7 @@ class TestFetchAllProcesses(unittest.TestCase):
assert ret, ret
meth = getattr(self, name)
meth(ret)
- except Exception:
- err = sys.exc_info()[1]
+ except Exception as err:
s = '\n' + '=' * 70 + '\n'
s += "FAIL: test_%s (proc=%s" % (name, p)
if ret != default:
@@ -2394,8 +2376,7 @@ class TestFetchAllProcesses(unittest.TestCase):
assert os.path.isabs(ret), ret
try:
st = os.stat(ret)
- except OSError:
- err = sys.exc_info()[1]
+ except OSError as err:
# directory has been removed in mean time
if err.errno != errno.ENOENT:
raise
@@ -2460,58 +2441,53 @@ class TestFetchAllProcesses(unittest.TestCase):
# --- Limited user tests
# ===================================================================
-if hasattr(os, 'getuid') 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
- 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_remove(TESTFN)
- os.setegid(1000)
- os.seteuid(1000)
- TestProcess.setUp(self)
+@unittest.skipUnless(hasattr(os, 'getuid') and os.getuid() == 0,
+ "super user privileges are required")
+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
+ 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 tearDown(self):
- os.setegid(self.PROCESS_UID)
- os.seteuid(self.PROCESS_GID)
- TestProcess.tearDown(self)
+ def setUp(self):
+ safe_remove(TESTFN)
+ os.setegid(1000)
+ os.seteuid(1000)
+ TestProcess.setUp(self)
- def test_nice(self):
- try:
- psutil.Process().nice(-1)
- except psutil.AccessDenied:
- pass
- else:
- self.fail("exception not raised")
+ def tearDown(self):
+ os.setegid(self.PROCESS_UID)
+ os.seteuid(self.PROCESS_GID)
+ TestProcess.tearDown(self)
- def test_zombie_process(self):
- # causes problems if test test suite is run as root
+ def test_nice(self):
+ try:
+ psutil.Process().nice(-1)
+ except psutil.AccessDenied:
pass
-else:
+ else:
+ self.fail("exception not raised")
- class LimitedUserTestCase(unittest.TestCase):
- def test_it(self):
- unittest.skip("super user privileges are required")
+ def test_zombie_process(self):
+ # causes problems if test test suite is run as root
+ pass
# ===================================================================
@@ -2550,7 +2526,7 @@ class TestMisc(unittest.TestCase):
def test__all__(self):
for name in dir(psutil):
- if name in ('callable', 'defaultdict', 'error', 'namedtuple',
+ if name in ('callable', 'error', 'namedtuple',
'long', 'test', 'NUM_CPUS', 'BOOT_TIME',
'TOTAL_PHYMEM'):
continue
@@ -2639,8 +2615,7 @@ class TestExampleScripts(unittest.TestCase):
exe = exe + ' ' + args
try:
out = sh(sys.executable + ' ' + exe).strip()
- except RuntimeError:
- err = sys.exc_info()[1]
+ except RuntimeError as err:
if 'AccessDenied' in str(err):
return str(err)
else:
@@ -2650,11 +2625,8 @@ class TestExampleScripts(unittest.TestCase):
def assert_syntax(self, exe, args=None):
exe = os.path.join(EXAMPLES_DIR, exe)
- f = open(exe, 'r')
- try:
+ with open(exe, 'r') as f:
src = f.read()
- finally:
- f.close()
ast.parse(src)
def test_check_presence(self):